Line data Source code
1 : #ifndef HEADER_fd_src_discof_restore_utils_fd_ssarchive_h
2 : #define HEADER_fd_src_discof_restore_utils_fd_ssarchive_h
3 :
4 : #include "../../../flamenco/fd_flamenco_base.h"
5 :
6 : #include <stdlib.h>
7 :
8 : /* FD_SNAP_NAME_MAX is the max length of a snapshot filename (cstr)
9 : including NUL terminator. */
10 0 : #define FD_SNAP_NAME_MAX (128UL)
11 :
12 : /* FD_SSARCHIVE_MAX_ENTRIES is the number of snapshots of each class
13 : (full, incremental) that fd_ssarchive_latest_pair considers. If a
14 : directory holds more than this, only the newest
15 : FD_SSARCHIVE_MAX_ENTRIES of each class are considered. */
16 0 : #define FD_SSARCHIVE_MAX_ENTRIES (512UL)
17 :
18 : FD_PROTOTYPES_BEGIN
19 :
20 : /* Parses a snapshot filename into components.
21 :
22 : incremental-snapshot-344185432-344209085-45eJ5C91fEenPRFc8NiqaDXMCHcPFwRUTMH3k1zY6a1B.tar.zst
23 : snapshot-344185432-BSP9ztdFEjwvkBo2LhHA47g9Q3PDwja9x5fj7taFRKH5.tar.zst
24 : snapshot-369927872-AaswH3EY2QJtTL1rTGxKCKsJ6SAjAeAvNfJhgM9D4ytU.tar
25 :
26 : Returns -1 on failure and 0 on success. */
27 :
28 : static inline int
29 : fd_ssarchive_parse_filename( char const * _name,
30 : ulong * full_slot,
31 : ulong * incremental_slot,
32 : uchar hash[ static FD_HASH_FOOTPRINT ],
33 0 : int * is_zstd ) {
34 0 : char name[ PATH_MAX ];
35 0 : fd_cstr_ncpy( name, _name, sizeof(name) );
36 :
37 0 : char * ptr = name;
38 0 : int is_incremental;
39 0 : if( !strncmp( ptr, "incremental-snapshot-", 21UL ) ) {
40 0 : is_incremental = 1;
41 0 : ptr += 21UL;
42 0 : } else if( !strncmp( ptr, "snapshot-", 9UL ) ) {
43 0 : is_incremental = 0;
44 0 : ptr += 9UL;
45 0 : } else {
46 0 : return -1;
47 0 : }
48 :
49 0 : char * next = strchr( ptr, '-' );
50 0 : if( FD_UNLIKELY( !next ) ) return -1;
51 0 : *next = '\0';
52 0 : char * endptr;
53 0 : if( FD_UNLIKELY( *ptr<'0' || *ptr>'9' ) ) return -1;
54 0 : *full_slot = strtoul( ptr, &endptr, 10 );
55 0 : if( FD_UNLIKELY( *endptr!='\0' || endptr==ptr || *full_slot==ULONG_MAX ) ) return -1;
56 :
57 0 : if( is_incremental ) {
58 0 : ptr = next + 1;
59 0 : next = strchr( ptr, '-' );
60 0 : if( FD_UNLIKELY( !next ) ) return -1;
61 0 : *next = '\0';
62 0 : if( FD_UNLIKELY( *ptr<'0' || *ptr>'9' ) ) return -1;
63 0 : *incremental_slot = strtoul( ptr, &endptr, 10 );
64 0 : if( FD_UNLIKELY( *endptr!='\0' || endptr==ptr || *incremental_slot==ULONG_MAX ) ) return -1;
65 0 : } else {
66 0 : *incremental_slot = ULONG_MAX;
67 0 : }
68 :
69 0 : ptr = next + 1;
70 0 : next = strchr( ptr, '.' );
71 0 : if( FD_UNLIKELY( !next ) ) return -1;
72 0 : *next = '\0';
73 0 : ulong sz = (ulong)(next - ptr);
74 0 : if( FD_UNLIKELY( sz>FD_BASE58_ENCODED_32_LEN ) ) return -1;
75 0 : uchar * result = fd_base58_decode_32( ptr, hash );
76 0 : if( FD_UNLIKELY( result!=hash ) ) return -1;
77 :
78 0 : ptr = next + 1;
79 :
80 0 : if( FD_LIKELY( 0==strcmp( ptr, "tar.zst" ) ) ) *is_zstd = 1;
81 0 : else if ( FD_LIKELY( 0==strcmp( ptr, "tar" ) ) ) *is_zstd = 0;
82 0 : else return -1;
83 :
84 0 : return 0;
85 0 : }
86 :
87 : /* Given a directory on the filesystem, determine the most recent (full,
88 : incremental) slot pair, whether each snapshot is zstd compressed, the
89 : associated full and incremental hashes, and the snapshot paths. The
90 : incremental slot is set to ULONG_MAX if the highest pair is just a
91 : full snapshot alone, or if incremental_snapshot is 0 (only full
92 : snapshots are considered). In this case, incremental_path is left
93 : empty, *incremental_is_zstd is set to 0, and incremental_hash is
94 : zeroed.
95 :
96 : Returns -1 on failure, and 0 on success. */
97 :
98 : int
99 : fd_ssarchive_latest_pair( char const * directory,
100 : int incremental_snapshot,
101 : ulong * full_slot,
102 : ulong * incremental_slot,
103 : char full_path[ static PATH_MAX ],
104 : char incremental_path[ static PATH_MAX ],
105 : int * full_is_zstd,
106 : int * incremental_is_zstd,
107 : uchar full_hash[ static FD_HASH_FOOTPRINT ],
108 : uchar incremental_hash[ static FD_HASH_FOOTPRINT ] );
109 :
110 : /* fd_ssarchive_latest_best picks whichever reaches the higher slot:
111 : the newest full snapshot on its own, or the newest full+incremental
112 : pair. Incrementals are considered when incremental_snapshot is
113 : non-zero, or when the full alone does not reach target_slot; pass
114 : target_slot 0 for no target. It only gates that choice: selection
115 : always maximizes the reachable slot, so the full returned may be
116 : older than the newest on disk when its incremental reaches further.
117 :
118 : Out-params and the return value follow fd_ssarchive_latest_pair. */
119 :
120 : int
121 : fd_ssarchive_latest_best( char const * directory,
122 : int incremental_snapshot,
123 : ulong target_slot,
124 : ulong * full_slot,
125 : ulong * incremental_slot,
126 : char full_path[ static PATH_MAX ],
127 : char incremental_path[ static PATH_MAX ],
128 : int * full_is_zstd,
129 : int * incremental_is_zstd,
130 : uchar full_hash[ static FD_HASH_FOOTPRINT ],
131 : uchar incremental_hash[ static FD_HASH_FOOTPRINT ] );
132 :
133 : FD_PROTOTYPES_END
134 :
135 : #endif /* HEADER_fd_src_discof_restore_utils_fd_ssarchive_h */
|