Line data Source code
1 : #include "fd_ssarchive.h"
2 :
3 : #include "../../../util/log/fd_log.h"
4 :
5 : #include <errno.h>
6 : #include <dirent.h>
7 : #include <stdlib.h>
8 :
9 : int
10 : fd_ssarchive_parse_filename( char * _name,
11 : ulong * full_slot,
12 : ulong * incremental_slot,
13 0 : uchar hash[ static FD_HASH_FOOTPRINT ] ) {
14 0 : char name[ PATH_MAX ] = {0};
15 0 : strncpy( name, _name, PATH_MAX-1 );
16 :
17 0 : char * ptr = name;
18 0 : int is_incremental;
19 0 : if( !strncmp( ptr, "incremental-snapshot-", 21UL ) ) {
20 0 : is_incremental = 1;
21 0 : ptr += 21UL;
22 0 : } else if( !strncmp( ptr, "snapshot-", 9UL ) ) {
23 0 : is_incremental = 0;
24 0 : ptr += 9UL;
25 0 : } else {
26 0 : return -1;
27 0 : }
28 :
29 0 : char * next = strchr( ptr, '-' );
30 0 : if( FD_UNLIKELY( !next ) ) return -1;
31 :
32 0 : *next = '\0';
33 0 : char * endptr;
34 0 : ulong slot = strtoul( ptr, &endptr, 10 );
35 0 : if( FD_UNLIKELY( *endptr!='\0' || slot==ULONG_MAX ) ) return -1;
36 :
37 0 : *full_slot = slot;
38 :
39 0 : if( is_incremental ) {
40 0 : ptr = next + 1;
41 0 : next = strchr( ptr, '-' );
42 0 : if( FD_UNLIKELY( !next ) ) return -1;
43 :
44 0 : *next = '\0';
45 0 : slot = strtoul( ptr, &endptr, 10 );
46 0 : if( FD_UNLIKELY( *endptr!='\0' || slot==ULONG_MAX ) ) return -1;
47 :
48 0 : *incremental_slot = slot;
49 0 : } else {
50 0 : *incremental_slot = ULONG_MAX;
51 0 : }
52 :
53 0 : ptr = next + 1;
54 0 : next = strchr( ptr, '.' );
55 0 : if( FD_UNLIKELY( !next ) ) return -1;
56 :
57 0 : ulong sz = (ulong)(next - ptr);
58 :
59 0 : if( FD_UNLIKELY( sz>FD_BASE58_ENCODED_32_LEN ) ) return -1;
60 :
61 0 : char encoded_hash[ FD_BASE58_ENCODED_32_SZ ];
62 0 : fd_memcpy( encoded_hash, ptr, sz );
63 0 : encoded_hash[ sz ] = '\0';
64 0 : uchar * result = fd_base58_decode_32( encoded_hash, hash );
65 :
66 0 : if( FD_UNLIKELY( !result ) ) return -1;
67 :
68 0 : if( FD_UNLIKELY( strncmp( next, ".tar.zst", 8UL ) ) ) return -1;
69 0 : return 0;
70 0 : }
71 :
72 : int
73 : fd_ssarchive_latest_pair( char const * directory,
74 : int incremental_snapshot,
75 : ulong * full_slot,
76 : ulong * incremental_slot,
77 : char full_path[ static PATH_MAX ],
78 0 : char incremental_path[ static PATH_MAX ] ) {
79 0 : *full_slot = ULONG_MAX;
80 0 : *incremental_slot = ULONG_MAX;
81 :
82 0 : DIR * dir = opendir( directory );
83 0 : if( FD_UNLIKELY( !dir ) ) {
84 0 : if( FD_LIKELY( errno==ENOENT ) ) return -1;
85 0 : FD_LOG_ERR(( "opendir() failed `%s` (%i-%s)", directory, errno, fd_io_strerror( errno ) ));
86 0 : }
87 :
88 0 : struct dirent * entry;
89 :
90 0 : errno = 0;
91 0 : while(( entry = readdir( dir ) )) {
92 0 : if( FD_LIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue;
93 :
94 0 : ulong entry_full_slot, entry_incremental_slot;
95 0 : uchar decoded_hash[ FD_HASH_FOOTPRINT ];
96 0 : if( FD_UNLIKELY( -1==fd_ssarchive_parse_filename( entry->d_name, &entry_full_slot, &entry_incremental_slot, decoded_hash ) ) ) {
97 0 : FD_LOG_INFO(( "unrecognized snapshot file `%s/%s` in snapshots directory", directory, entry->d_name ));
98 0 : continue;
99 0 : }
100 :
101 0 : if( FD_LIKELY( entry_incremental_slot==ULONG_MAX && (entry_full_slot>*full_slot || *full_slot==ULONG_MAX) ) ) {
102 0 : *full_slot = entry_full_slot;
103 0 : if( FD_UNLIKELY( !fd_cstr_printf_check( full_path, PATH_MAX, NULL, "%s/%s", directory, entry->d_name ) ) ) {
104 0 : FD_LOG_ERR(( "snapshot path too long `%s/%s`", directory, entry->d_name ));
105 0 : }
106 0 : }
107 0 : }
108 :
109 0 : if( FD_UNLIKELY( -1==closedir( dir ) ) ) FD_LOG_ERR(( "closedir() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
110 0 : if( FD_UNLIKELY( errno && errno!=ENOENT ) ) FD_LOG_ERR(( "readdir() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
111 :
112 0 : if( FD_UNLIKELY( *full_slot==ULONG_MAX ) ) return -1;
113 0 : if( FD_UNLIKELY( !incremental_snapshot ) ) return 0;
114 :
115 0 : dir = opendir( directory );
116 0 : if( FD_UNLIKELY( !dir ) ) {
117 0 : if( FD_LIKELY( errno==ENOENT ) ) return 0;
118 0 : FD_LOG_ERR(( "opendir() failed `%s` (%i-%s)", directory, errno, fd_io_strerror( errno ) ));
119 0 : }
120 :
121 0 : errno = 0;
122 0 : while(( entry = readdir( dir ) )) {
123 0 : if( FD_LIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue;
124 :
125 0 : ulong entry_full_slot, entry_incremental_slot;
126 0 : uchar decoded_hash[ FD_HASH_FOOTPRINT ];
127 0 : if( FD_UNLIKELY( -1==fd_ssarchive_parse_filename( entry->d_name, &entry_full_slot, &entry_incremental_slot, decoded_hash ) ) ) continue;
128 :
129 0 : if( FD_UNLIKELY( entry_incremental_slot==ULONG_MAX || *full_slot!=entry_full_slot ) ) continue;
130 :
131 0 : if( FD_LIKELY( *incremental_slot==ULONG_MAX || entry_incremental_slot>*incremental_slot ) ) {
132 0 : *incremental_slot = entry_incremental_slot;
133 0 : if( FD_UNLIKELY( !fd_cstr_printf_check( incremental_path, PATH_MAX, NULL, "%s/%s", directory, entry->d_name ) ) ) {
134 0 : FD_LOG_ERR(( "snapshot path too long `%s/%s`", directory, entry->d_name ));
135 0 : }
136 0 : }
137 0 : }
138 :
139 0 : if( FD_UNLIKELY( -1==closedir( dir ) ) ) FD_LOG_ERR(( "closedir() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
140 0 : if( FD_UNLIKELY( errno && errno!=ENOENT ) ) FD_LOG_ERR(( "readdir() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
141 0 : return 0;
142 0 : }
|