Line data Source code
1 : #ifndef HEADER_fd_src_util_archive_fd_tar_h 2 : #define HEADER_fd_src_util_archive_fd_tar_h 3 : 4 : /* fd_tar implements the ustar and old-GNU versions of the TAR file 5 : format. This is not a general-purpose TAR implementation. It is 6 : currently only intended for loading and writing Solana snapshots. */ 7 : 8 : #include "../bits/fd_bits.h" 9 : 10 : /* File Format ********************************************************/ 11 : 12 : /* The high level format of a tar archive/ball is a set of 512 byte blocks. 13 : Each file will be described a tar header (fd_tar_meta_t) and will be 14 : followed by the raw bytes of the file. The last block that is used for 15 : the file will be padded to fit into a tar block. When the archive is 16 : completed, it will be trailed by two EOF blocks which are populated with 17 : zero bytes. */ 18 : 19 : /* fd_tar_meta_t is the ustar/OLDGNU version of the TAR header. */ 20 : 21 : #define FD_TAR_BLOCK_SZ (512UL) 22 : 23 : struct __attribute__((packed)) fd_tar_meta { 24 : # define FD_TAR_NAME_SZ (100) 25 : /* 0x000 */ char name [ FD_TAR_NAME_SZ ]; 26 : /* 0x064 */ char mode [ 8 ]; 27 : /* 0x06c */ char uid [ 8 ]; 28 : /* 0x074 */ char gid [ 8 ]; 29 : /* 0x07c */ char size [ 12 ]; 30 : /* 0x088 */ char mtime [ 12 ]; 31 : /* 0x094 */ char chksum [ 8 ]; 32 : /* 0x09c */ char typeflag; 33 : /* 0x09d */ char linkname[ 100 ]; 34 : /* 0x101 */ char magic [ 6 ]; 35 : /* 0x107 */ char version [ 2 ]; 36 : /* 0x109 */ char uname [ 32 ]; 37 : /* 0x129 */ char gname [ 32 ]; 38 : /* 0x149 */ char devmajor[ 8 ]; 39 : /* 0x151 */ char devminor[ 8 ]; 40 : /* 0x159 */ char prefix [ 155 ]; 41 : /* 0x1f4 */ char padding [ 12 ]; 42 : }; 43 : 44 : typedef struct fd_tar_meta fd_tar_meta_t; 45 : 46 : /* FD_TAR_MAGIC is the only value of fd_tar_meta::magic supported by 47 : fd_tar. */ 48 : 49 0 : #define FD_TAR_MAGIC "ustar" 50 : 51 : /* Known file types */ 52 : 53 0 : #define FD_TAR_TYPE_NULL ('\0') /* implies FD_TAR_TYPE_REGULAR */ 54 0 : #define FD_TAR_TYPE_REGULAR ('0') 55 : #define FD_TAR_TYPE_HARD_LINK ('1') 56 : #define FD_TAR_TYPE_SYM_LINK ('2') 57 : #define FD_TAR_TYPE_CHAR_DEV ('3') 58 : #define FD_TAR_TYPE_BLOCK_DEV ('4') 59 : #define FD_TAR_TYPE_DIR ('5') 60 : #define FD_TAR_TYPE_FIFO ('6') 61 : 62 : FD_PROTOTYPES_BEGIN 63 : 64 : /* fd_tar_meta_is_reg returns 1 if the file type is 'regular', and 0 65 : otherwise. */ 66 : 67 : FD_FN_PURE static inline int 68 0 : fd_tar_meta_is_reg( fd_tar_meta_t const * meta ) { 69 0 : return ( meta->typeflag == FD_TAR_TYPE_NULL ) 70 0 : | ( meta->typeflag == FD_TAR_TYPE_REGULAR ); 71 0 : } 72 : 73 : /* fd_tar_meta_get_size parses the size field of the TAR header. 74 : Returns ULONG_MAX if parsing failed. */ 75 : 76 : FD_FN_PURE FD_FN_UNUSED static ulong 77 3 : fd_tar_meta_get_size( fd_tar_meta_t const * meta ) { 78 3 : char const * buf = meta->size; 79 3 : if( ((uchar)buf[0]) & 0x80U ) { 80 : /* OLDGNU tar files may use a binary size encoding */ 81 3 : return fd_ulong_bswap( FD_LOAD( ulong, buf+4 ) ); 82 3 : } 83 : 84 0 : ulong ret = 0UL; 85 0 : for( char const * p=buf; p<buf+12; p++ ) { 86 0 : if( *p == '\0' ) break; 87 0 : ret = (ret << 3) + (ulong)(*p - '0'); 88 0 : } 89 : 90 0 : return ret; 91 3 : } 92 : 93 : /* fd_tar_set_octal is a helper function to write 12-byte octal fields */ 94 : 95 : int 96 : fd_tar_set_octal( char buf[ static 12 ], 97 : ulong val ); 98 : 99 : /* fd_tar_meta_set_size sets the size field. Returns 1 on success, 0 100 : if sz is too large to be represented in TAR header. Set size using the 101 : OLDGNU size extension to allow for unlimited file sizes. The first byte 102 : must be 0x80 followed by 0s and then the size in binary. */ 103 : 104 : static inline int 105 : fd_tar_meta_set_size( fd_tar_meta_t * meta, 106 0 : ulong sz ) { 107 0 : meta->size[ 0 ] = (char)0x80; 108 0 : FD_STORE( ulong, meta->size + 4UL, fd_ulong_bswap( sz ) ); 109 0 : return 1; 110 0 : } 111 : 112 : /* fd_tar_meta_set_mtime sets the modification time field. Returns 1 113 : on success, 0 if time cannot be represented in TAR header. */ 114 : 115 : static inline int 116 : fd_tar_meta_set_mtime( fd_tar_meta_t * meta, 117 0 : ulong mtime ) { 118 0 : return fd_tar_set_octal( meta->mtime, mtime ); 119 0 : } 120 : 121 : FD_PROTOTYPES_END 122 : 123 : #endif /* HEADER_fd_src_util_archive_fd_tar_h */