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 408 : #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 2154 : int * is_zstd ) {
34 2154 : char name[ PATH_MAX ];
35 2154 : fd_cstr_ncpy( name, _name, sizeof(name) );
36 :
37 2154 : char * ptr = name;
38 2154 : int is_incremental;
39 2154 : if( !strncmp( ptr, "incremental-snapshot-", 21UL ) ) {
40 153 : is_incremental = 1;
41 153 : ptr += 21UL;
42 2001 : } else if( !strncmp( ptr, "snapshot-", 9UL ) ) {
43 1986 : is_incremental = 0;
44 1986 : ptr += 9UL;
45 1986 : } else {
46 15 : return -1;
47 15 : }
48 :
49 2139 : char * next = strchr( ptr, '-' );
50 2139 : if( FD_UNLIKELY( !next ) ) return -1;
51 2136 : *next = '\0';
52 2136 : char * endptr;
53 2136 : if( FD_UNLIKELY( *ptr<'0' || *ptr>'9' ) ) return -1;
54 2124 : *full_slot = strtoul( ptr, &endptr, 10 );
55 2124 : if( FD_UNLIKELY( *endptr!='\0' || endptr==ptr || *full_slot==ULONG_MAX ) ) return -1;
56 :
57 2124 : if( is_incremental ) {
58 150 : ptr = next + 1;
59 150 : next = strchr( ptr, '-' );
60 150 : if( FD_UNLIKELY( !next ) ) return -1;
61 147 : *next = '\0';
62 147 : if( FD_UNLIKELY( *ptr<'0' || *ptr>'9' ) ) return -1;
63 141 : *incremental_slot = strtoul( ptr, &endptr, 10 );
64 141 : if( FD_UNLIKELY( *endptr!='\0' || endptr==ptr || *incremental_slot==ULONG_MAX ) ) return -1;
65 1974 : } else {
66 1974 : *incremental_slot = ULONG_MAX;
67 1974 : }
68 :
69 2115 : ptr = next + 1;
70 2115 : next = strchr( ptr, '.' );
71 2115 : if( FD_UNLIKELY( !next ) ) return -1;
72 2112 : *next = '\0';
73 2112 : ulong sz = (ulong)(next - ptr);
74 2112 : if( FD_UNLIKELY( sz>FD_BASE58_ENCODED_32_LEN ) ) return -1;
75 2112 : uchar * result = fd_base58_decode_32( ptr, hash );
76 2112 : if( FD_UNLIKELY( result!=hash ) ) return -1;
77 :
78 2109 : ptr = next + 1;
79 :
80 2109 : if( FD_LIKELY( 0==strcmp( ptr, "tar.zst" ) ) ) *is_zstd = 1;
81 39 : else if ( FD_LIKELY( 0==strcmp( ptr, "tar" ) ) ) *is_zstd = 0;
82 3 : else return -1;
83 :
84 2106 : return 0;
85 2109 : }
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 */
|