Line data Source code
1 : #ifndef HEADER_fd_src_archive_fd_tar_h 2 : #define HEADER_fd_src_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 Solana snapshots. */ 7 : 8 : #include "../fd_util_base.h" 9 : 10 : /* File Format ********************************************************/ 11 : 12 : /* fd_tar_meta_t is the ustar/OLDGNU version of the TAR header. */ 13 : 14 : struct __attribute__((packed)) fd_tar_meta { 15 0 : # define FD_TAR_NAME_SZ (100) 16 : /* 0x000 */ char name [ FD_TAR_NAME_SZ ]; 17 : /* 0x064 */ char mode [ 8 ]; 18 : /* 0x06c */ char uid [ 8 ]; 19 : /* 0x074 */ char gid [ 8 ]; 20 : /* 0x07c */ char size [ 12 ]; 21 : /* 0x088 */ char mtime [ 12 ]; 22 : /* 0x094 */ char chksum [ 8 ]; 23 : /* 0x09c */ char typeflag; 24 : /* 0x09d */ char linkname[ 100 ]; 25 : /* 0x101 */ char magic [ 6 ]; 26 : /* 0x107 */ char version [ 2 ]; 27 : /* 0x109 */ char uname [ 32 ]; 28 : /* 0x129 */ char gname [ 32 ]; 29 : /* 0x149 */ char devmajor[ 8 ]; 30 : /* 0x151 */ char devminor[ 8 ]; 31 : /* 0x159 */ char prefix [ 155 ]; 32 : /* 0x1f4 */ char padding [ 12 ]; 33 : }; 34 : 35 : typedef struct fd_tar_meta fd_tar_meta_t; 36 : 37 : /* FD_TAR_MAGIC is the only value of fd_tar_meta::magic supported by 38 : fd_tar. */ 39 : 40 : #define FD_TAR_MAGIC "ustar" 41 : 42 : /* Known file types */ 43 : 44 54 : #define FD_TAR_TYPE_NULL ('\0') /* implies FD_TAR_TYPE_REGULAR */ 45 108 : #define FD_TAR_TYPE_REGULAR ('0') 46 : #define FD_TAR_TYPE_HARD_LINK ('1') 47 : #define FD_TAR_TYPE_SYM_LINK ('2') 48 : #define FD_TAR_TYPE_CHAR_DEV ('3') 49 : #define FD_TAR_TYPE_BLOCK_DEV ('4') 50 : #define FD_TAR_TYPE_DIR ('5') 51 : #define FD_TAR_TYPE_FIFO ('6') 52 : 53 : FD_PROTOTYPES_BEGIN 54 : 55 : /* fd_tar_meta_is_reg returns 1 if the file type is 'regular', and 0 56 : otherwise. */ 57 : 58 : FD_FN_PURE static inline int 59 54 : fd_tar_meta_is_reg( fd_tar_meta_t const * meta ) { 60 54 : return ( meta->typeflag == FD_TAR_TYPE_NULL ) 61 54 : | ( meta->typeflag == FD_TAR_TYPE_REGULAR ); 62 54 : } 63 : 64 : /* fd_tar_meta_get_size parses the size field of the TAR header. 65 : Returns ULONG_MAX if parsing failed. */ 66 : 67 : FD_FN_PURE ulong 68 : fd_tar_meta_get_size( fd_tar_meta_t const * meta ); 69 : 70 : /* fd_tar_set_octal is a helper function to write 12-byte octal fields */ 71 : 72 : int 73 : fd_tar_set_octal( char buf[ static 12 ], 74 : ulong val ); 75 : 76 : /* fd_tar_meta_set_size sets the size field. Returns 1 on success, 0 77 : if sz is too large to be represented in TAR header. */ 78 : 79 : static inline int 80 : fd_tar_meta_set_size( fd_tar_meta_t * meta, 81 0 : ulong sz ) { 82 0 : return fd_tar_set_octal( meta->size, sz ); 83 0 : } 84 : 85 : /* fd_tar_meta_set_mtime sets the modification time field. Returns 1 86 : on success, 0 if time cannot be represented in TAR header. */ 87 : 88 : static inline int 89 : fd_tar_meta_set_mtime( fd_tar_meta_t * meta, 90 0 : ulong mtime ) { 91 0 : return fd_tar_set_octal( meta->mtime, mtime ); 92 0 : } 93 : 94 : FD_PROTOTYPES_END 95 : 96 : /* Streaming reader ***************************************************/ 97 : 98 : typedef struct fd_tar_reader fd_tar_reader_t; 99 : 100 : /* fd_tar_file_fn_t is called by fd_tar when a new file was encountered. 101 : cb_arg is the callback context value. meta is the file header 102 : (lifetime until return). sz is the expected file size that follows 103 : (via read callbacks). The actual read size might differ in case of 104 : errors (e.g. unexpected EOF). Returns 0 on success and non-zero if 105 : tar reader should stop. */ 106 : 107 : typedef int 108 : (* fd_tar_file_fn_t)( void * cb_arg, 109 : fd_tar_meta_t const * meta, 110 : ulong sz ); 111 : 112 : /* fd_tar_read_cb_t is called by fd_tar when a new chunk of data has 113 : been read. Each read callback is associated with the last file 114 : callback. Read callbacks are issued in order such that concatenating 115 : all buffers results in the correct file content. Returns 0 on 116 : success and non-zero if tar reader should stop. 117 : 118 : cb_arg is the callback context value. buf points to the first byte 119 : of the chunk. bufsz is the byte count. The lifetime of buf is until 120 : the callback returns. */ 121 : 122 : typedef int 123 : (* fd_tar_read_fn_t)( void * cb_arg, 124 : void const * buf, 125 : ulong bufsz ); 126 : 127 : /* fd_tar_read_vtable_t is the virtual function table of the 128 : fd_tar_reader_t consumer object. */ 129 : 130 : struct fd_tar_read_vtable { 131 : fd_tar_file_fn_t file; 132 : fd_tar_read_fn_t read; 133 : }; 134 : 135 : typedef struct fd_tar_read_vtable fd_tar_read_vtable_t; 136 : 137 : /* fd_tar_reader_t is a streaming TAR reader using a callback API for 138 : delivering data. To use, feed it the chunks of the TAR stream via 139 : fd_tar_read. There is no restriction on the size and alignment of 140 : these chunks, other than that the chunks are supplied in order and 141 : gapless. The resulting callback sequence is (1x file, Nx read, 1x 142 : file, Nx read ...). As in: Each new file encountered creates a file 143 : callback and a variable number of read callbacks. */ 144 : 145 : struct fd_tar_reader { 146 : 147 : /* Buffered file header. Required because a file header might be 148 : split across multiple fd_tar_read calls. */ 149 : union { 150 : uchar buf[ sizeof(fd_tar_meta_t) ]; 151 : fd_tar_meta_t header; 152 : }; 153 : 154 : ulong pos; /* Number of bytes consumed */ 155 : ulong buf_ctr; /* Write cursor in file header */ 156 : ulong file_sz; /* Number of file bytes left */ 157 : 158 : /* Callback parameters */ 159 : fd_tar_read_vtable_t cb_vt; 160 : void * cb_arg; 161 : 162 : }; 163 : 164 : FD_PROTOTYPES_BEGIN 165 : 166 : /* fd_tar_reader_{align,footprint} return parameters for the memory 167 : region backing a fd_tar_reader_t. */ 168 : 169 : FD_FN_CONST static inline ulong 170 0 : fd_tar_reader_align( void ) { 171 0 : return alignof(fd_tar_reader_t); 172 0 : } 173 : 174 : FD_FN_CONST static inline ulong 175 0 : fd_tar_reader_footprint( void ) { 176 0 : return sizeof(fd_tar_reader_t); 177 0 : } 178 : 179 : /* fd_tar_reader_new creates a new TAR reader. mem is the memory region 180 : that will hold the fd_tar_reader_t (matches above align/ footprint 181 : requirements). cb_vt contains the callback function pointers of 182 : the recipient. cb_vt pointer is borrowed until this function 183 : returns. cb_arg is the callback context value (usually a pointer to 184 : the recipient object). Returns a qualified handle to the reader 185 : object in mem on success. On failure, returns NULL and writes reason 186 : to warning log. Reasons for failure include invalid memory region or 187 : NULL callback. */ 188 : 189 : fd_tar_reader_t * 190 : fd_tar_reader_new( void * mem, 191 : fd_tar_read_vtable_t const * cb_vt, 192 : void * cb_arg ); 193 : 194 : /* fd_tar_reader_delete destroys a .tar reader and frees any allocated 195 : resources. Returns the underlying memory region back to the caller. */ 196 : 197 : void * 198 : fd_tar_reader_delete( fd_tar_reader_t * reader ); 199 : 200 : /* fd_tar_read processes a chunk of the TAR stream. Issues callbacks 201 : when file headers or content are read. reader is an fd_tar_reader_t 202 : pointer. data points to the first byte of the data chunk. data_sz 203 : is the byte count. data_sz==0UL is a no-op. Returns 0 on success. 204 : Returns -1 on end-of-file. On failure, returns positive errno 205 : compatible error code. In case of error, caller should delete reader 206 : and must not issue any more fd_tar_read calls. Suitable as a 207 : fd_decompress_cb_t callback. */ 208 : 209 : int 210 : fd_tar_read( void * reader, 211 : uchar const * data, 212 : ulong data_sz ); 213 : 214 : FD_PROTOTYPES_END 215 : 216 : #endif /* HEADER_fd_src_archive_fd_tar_h */