Line data Source code
1 : #define _GNU_SOURCE 2 : #include "fd_snap_pool.h" 3 : 4 : #include <dirent.h> 5 : #include <errno.h> 6 : #include <fcntl.h> 7 : #include <sys/stat.h> 8 : #include <sys/syscall.h> 9 : #include <unistd.h> 10 : 11 : void 12 : fd_snap_pool_recover( int snapshots_fd, 13 : char const * snapshots_path, 14 : fd_backup_inode_t * pool, 15 0 : uint pool_max ) { 16 0 : FD_TEST( pool_max && pool_max<=FD_SNAP_MAX ); 17 : 18 0 : struct stat pool_st[ FD_SNAP_MAX ]; 19 0 : int found [ FD_SNAP_MAX ] = {0}; 20 0 : for( uint i=0U; i<pool_max; i++ ) { 21 0 : if( FD_UNLIKELY( -1==fstat( FD_SNAP_FD( i ), &pool_st[ i ] ) ) ) 22 0 : FD_LOG_ERR(( "fstat(snapshot pool fd %d) failed (%i-%s), was the snapshot pool initialized on boot?", 23 0 : FD_SNAP_FD( i ), errno, fd_io_strerror( errno ) )); 24 0 : } 25 : 26 0 : if( FD_UNLIKELY( lseek( snapshots_fd, 0L, SEEK_SET ) ) ) 27 0 : FD_LOG_ERR(( "lseek(%s) failed (%i-%s)", snapshots_path, errno, fd_io_strerror( errno ) )); 28 0 : for(;;) { 29 0 : uchar buf[ 4096UL ] __attribute__((aligned(alignof(struct dirent)))); 30 0 : long dents_sz = syscall( SYS_getdents64, snapshots_fd, buf, sizeof(buf) ); 31 0 : if( FD_UNLIKELY( dents_sz<0L ) ) 32 0 : FD_LOG_ERR(( "getdents64(%s) failed (%i-%s)", snapshots_path, errno, fd_io_strerror( errno ) )); 33 0 : if( FD_UNLIKELY( !dents_sz ) ) break; 34 : 35 0 : ulong off = 0UL; 36 0 : while( off<(ulong)dents_sz ) { 37 0 : struct dirent const * entry = (struct dirent const *)(buf+off); 38 0 : FD_TEST( entry->d_reclen && off+(ulong)entry->d_reclen<=(ulong)dents_sz ); 39 0 : off += entry->d_reclen; 40 0 : if( FD_LIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue; 41 : 42 0 : struct stat st; 43 0 : if( FD_UNLIKELY( -1==fstatat( snapshots_fd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW ) ) ) continue; 44 : 45 0 : for( uint i=0U; i<pool_max; i++ ) { 46 0 : if( FD_LIKELY( found[ i ] ) ) continue; 47 0 : if( FD_LIKELY( st.st_dev!=pool_st[ i ].st_dev || st.st_ino!=pool_st[ i ].st_ino ) ) continue; 48 : 49 0 : if( FD_UNLIKELY( strlen( entry->d_name )>=sizeof(pool[ i ].name) ) ) 50 0 : FD_LOG_ERR(( "snapshot pool file name `%s` too long", entry->d_name )); 51 0 : fd_cstr_ncpy( pool[ i ].name, entry->d_name, sizeof(pool[ i ].name) ); 52 : 53 0 : int is_zstd; 54 0 : uchar decoded_hash[ FD_HASH_FOOTPRINT ]; 55 0 : if( FD_UNLIKELY( -1==fd_ssarchive_parse_filename( entry->d_name, &pool[ i ].full_slot, &pool[ i ].incr_slot, decoded_hash, &is_zstd ) ) ) { 56 0 : pool[ i ].full_slot = ULONG_MAX; 57 0 : pool[ i ].incr_slot = ULONG_MAX; 58 0 : } 59 0 : found[ i ] = 1; 60 0 : break; 61 0 : } 62 0 : } 63 0 : } 64 : 65 0 : for( uint i=0U; i<pool_max; i++ ) { 66 0 : if( FD_UNLIKELY( !found[ i ] ) ) 67 0 : FD_LOG_ERR(( "snapshot pool fd %d has no directory entry in `%s`", FD_SNAP_FD( i ), snapshots_path )); 68 0 : } 69 0 : }