root/src/vfs/tar/tar-internal.h

/* [previous][next][first][last][top][bottom][index][help]  */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. tar_represent_uintmax

   1 
   2 #ifndef MC__VFS_TAR_INTERNAL_H
   3 #define MC__VFS_TAR_INTERNAL_H
   4 
   5 #include <inttypes.h>  // (u)intmax_t
   6 #include <limits.h>    // CHAR_BIT, INT_MAX, etc
   7 #include <sys/stat.h>
   8 #include <sys/types.h>
   9 
  10 #ifdef HAVE_STDCKDINT_H
  11 #    include <stdckdint.h>
  12 #else
  13 #    include "lib/stdckdint.h"
  14 #endif
  15 #include "lib/intprops.h"
  16 #include "lib/idx.h"
  17 #include "lib/vfs/xdirentry.h"  // vfs_s_super
  18 
  19 /*** typedefs(not structures) and defined constants **********************************************/
  20 
  21 /* tar files are made in basic blocks of this size.  */
  22 #define BLOCKSIZE        512
  23 
  24 #define DEFAULT_BLOCKING 20
  25 
  26 /* Sparse files are not supported in POSIX ustar format.  For sparse files
  27    with a POSIX header, a GNU extra header is provided which holds overall
  28    sparse information and a few sparse descriptors.  When an old GNU header
  29    replaces both the POSIX header and the GNU extra header, it holds some
  30    sparse descriptors too.  Whether POSIX or not, if more sparse descriptors
  31    are still needed, they are put into as many successive sparse headers as
  32    necessary.  The following constants tell how many sparse descriptors fit
  33    in each kind of header able to hold them.  */
  34 
  35 #define SPARSES_IN_EXTRA_HEADER    16
  36 #define SPARSES_IN_OLDGNU_HEADER   4
  37 #define SPARSES_IN_SPARSE_HEADER   21
  38 
  39 #define SPARSES_IN_STAR_HEADER     4
  40 #define SPARSES_IN_STAR_EXT_HEADER 21
  41 
  42 /* *BEWARE* *BEWARE* *BEWARE* that the following information is still
  43    boiling, and may change.  Even if the OLDGNU format description should be
  44    accurate, the so-called GNU format is not yet fully decided.  It is
  45    surely meant to use only extensions allowed by POSIX, but the sketch
  46    below repeats some ugliness from the OLDGNU format, which should rather
  47    go away.  Sparse files should be saved in such a way that they do *not*
  48    require two passes at archive creation time.  Huge files get some POSIX
  49    fields to overflow, alternate solutions have to be sought for this.  */
  50 
  51 /* This is a dir entry that contains the names of files that were in the
  52    dir at the time the dump was made.  */
  53 #define GNUTYPE_DUMPDIR 'D'
  54 
  55 /* Identifies the *next* file on the tape as having a long linkname.  */
  56 #define GNUTYPE_LONGLINK 'K'
  57 
  58 /* Identifies the *next* file on the tape as having a long name.  */
  59 #define GNUTYPE_LONGNAME 'L'
  60 
  61 /* Solaris extended header */
  62 #define SOLARIS_XHDTYPE        'X'
  63 
  64 #define GNUTYPE_SPARSE         'S'
  65 
  66 #define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
  67 
  68 /*** enums ***************************************************************************************/
  69 
  70 /*** structures declarations (and typedefs of structures)*****************************************/
  71 
  72 /* POSIX header */
  73 struct posix_header
  74 {                        // byte offset
  75     char name[100];      //   0
  76     char mode[8];        // 100
  77     char uid[8];         // 108
  78     char gid[8];         // 116
  79     char size[12];       // 124
  80     char mtime[12];      // 136
  81     char chksum[8];      // 148
  82     char typeflag;       // 156
  83     char linkname[100];  // 157
  84     char magic[6];       // 257
  85     char version[2];     // 263
  86     char uname[32];      // 265
  87     char gname[32];      // 297
  88     char devmajor[8];    // 329
  89     char devminor[8];    // 337
  90     char prefix[155];    // 345
  91                          // 500
  92 };
  93 
  94 /* Descriptor for a single file hole */
  95 struct sparse
  96 {  // byte offset
  97     // cppcheck-suppress unusedStructMember
  98     char offset[12];  //   0
  99     // cppcheck-suppress unusedStructMember
 100     char numbytes[12];  //  12
 101                         //  24
 102 };
 103 
 104 /* Extension header for sparse files, used immediately after the GNU extra
 105    header, and used only if all sparse information cannot fit into that
 106    extra header.  There might even be many such extension headers, one after
 107    the other, until all sparse information has been recorded.  */
 108 struct sparse_header
 109 {  // byte offset
 110     struct sparse sp[SPARSES_IN_SPARSE_HEADER];
 111     //   0
 112     char isextended;  // 504
 113                       // 505
 114 };
 115 
 116 /* The old GNU format header conflicts with POSIX format in such a way that
 117    POSIX archives may fool old GNU tar's, and POSIX tar's might well be
 118    fooled by old GNU tar archives.  An old GNU format header uses the space
 119    used by the prefix field in a POSIX header, and cumulates information
 120    normally found in a GNU extra header.  With an old GNU tar header, we
 121    never see any POSIX header nor GNU extra header.  Supplementary sparse
 122    headers are allowed, however.  */
 123 struct oldgnu_header
 124 {                           // byte offset
 125     char unused_pad1[345];  //   0
 126     char atime[12];         // 345 Incr. archive: atime of the file
 127     char ctime[12];         // 357 Incr. archive: ctime of the file
 128     char offset[12];        // 369 Multivolume archive: the offset of start of this volume
 129     char longnames[4];      // 381 Not used
 130     char unused_pad2;       // 385
 131     struct sparse sp[SPARSES_IN_OLDGNU_HEADER];
 132     // 386
 133     char isextended;    // 482 Sparse file: Extension sparse header follows
 134     char realsize[12];  // 483 Sparse file: Real size
 135                         // 495
 136 };
 137 
 138 /* J@"org Schilling star header */
 139 struct star_header
 140 {                        // byte offset
 141     char name[100];      //   0
 142     char mode[8];        // 100
 143     char uid[8];         // 108
 144     char gid[8];         // 116
 145     char size[12];       // 124
 146     char mtime[12];      // 136
 147     char chksum[8];      // 148
 148     char typeflag;       // 156
 149     char linkname[100];  // 157
 150     char magic[6];       // 257
 151     char version[2];     // 263
 152     char uname[32];      // 265
 153     char gname[32];      // 297
 154     char devmajor[8];    // 329
 155     char devminor[8];    // 337
 156     char prefix[131];    // 345
 157     char atime[12];      // 476
 158     char ctime[12];      // 488
 159                          // 500
 160 };
 161 
 162 struct star_in_header
 163 {
 164     char fill[345];                            //   0  Everything that is before t_prefix
 165     char prefix[1];                            // 345  t_name prefix
 166     char fill2;                                // 346
 167     char fill3[8];                             // 347
 168     char isextended;                           // 355
 169     struct sparse sp[SPARSES_IN_STAR_HEADER];  // 356
 170     char realsize[12];                         // 452  Actual size of the file
 171     char offset[12];                           // 464  Offset of multivolume contents
 172     char atime[12];                            // 476
 173     char ctime[12];                            // 488
 174     char mfill[8];                             // 500
 175     char xmagic[4];                            // 508  "tar"
 176 };
 177 
 178 struct star_ext_header
 179 {
 180     struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
 181     char isextended;
 182 };
 183 
 184 /* tar Header Block, overall structure */
 185 union block
 186 {
 187     char buffer[BLOCKSIZE];
 188     struct posix_header header;
 189     struct star_header star_header;
 190     struct oldgnu_header oldgnu_header;
 191     struct sparse_header sparse_header;
 192     struct star_in_header star_in_header;
 193     struct star_ext_header star_ext_header;
 194 };
 195 
 196 /* Information about a sparse file */
 197 struct sp_array
 198 {
 199     off_t offset;       // chunk offset in file
 200     off_t numbytes;     // length of chunk
 201     off_t arch_offset;  // chunk offset in archive
 202 };
 203 
 204 enum dump_status
 205 {
 206     dump_status_ok,
 207     dump_status_short,
 208     dump_status_fail,
 209     dump_status_not_implemented
 210 };
 211 
 212 enum archive_format
 213 {
 214     TAR_UNKNOWN = 0,  // format to be decided later
 215     TAR_V7,           // old V7 tar format
 216     TAR_OLDGNU,       // GNU format as per before tar 1.12
 217     TAR_USTAR,        // POSIX.1-1988 (ustar) format
 218     TAR_POSIX,        // POSIX.1-2001 format
 219     TAR_STAR,         // star format defined in 1994
 220     TAR_GNU           // almost same as OLDGNU_FORMAT
 221 };
 222 
 223 typedef struct
 224 {
 225     struct vfs_s_super base;  // base class
 226 
 227     int fd;
 228     struct stat st;
 229     enum archive_format type;   // type of the archive
 230     union block *record_start;  // start of record of archive
 231 } tar_super_t;
 232 
 233 struct xheader
 234 {
 235     size_t size;
 236     char *buffer;
 237 };
 238 
 239 struct tar_stat_info
 240 {
 241     char *orig_file_name;  // name of file read from the archive header
 242     char *file_name;       // name of file for the current archive entry after being normalized
 243     char *link_name;       // name of link for the current archive entry
 244 #if 0
 245     char *uname;                // user name of owner
 246     char *gname;                // group name of owner
 247 #endif
 248     struct stat stat;  // regular filesystem stat
 249 
 250     /* stat() doesn't always have access, data modification, and status
 251        change times in a convenient form, so store them separately.  */
 252     struct timespec atime;
 253     struct timespec mtime;
 254     struct timespec ctime;
 255 
 256     off_t archive_file_size;  // size of file as stored in the archive, equals stat.st_size for
 257                               // non-sparse files
 258     gboolean is_sparse;       // is the file sparse
 259 
 260     // For sparse files
 261     intmax_t sparse_major;
 262     intmax_t sparse_minor;
 263     GArray *sparse_map;  // array of struct sp_array
 264 
 265     off_t real_size;         // real size of sparse file
 266     gboolean real_size_set;  // TRUE when GNU.sparse.realsize is set in archived file
 267 
 268     gboolean
 269         sparse_name_done;  // TRUE if 'GNU.sparse.name' header was processed pax header parsing.
 270                            // Following 'path'  header (lower priority) will be ignored.
 271 
 272     // Extended headers
 273     struct xheader xhdr;
 274 
 275     // For dumpdirs
 276     gboolean is_dumpdir;  // is the member a dumpdir?
 277     gboolean skipped;     // the member contents is already read (for GNUTYPE_DUMPDIR)
 278     char *dumpdir;        // contents of the dump directory
 279 };
 280 
 281 /*** global variables defined in .c file *********************************************************/
 282 
 283 extern const idx_t blocking_factor;
 284 extern const idx_t record_size;
 285 
 286 extern union block *record_end;     // last+1 block of archive record
 287 extern union block *current_block;  // current block of archive
 288 extern off_t record_start_block;    // block ordinal at record_start
 289 
 290 extern union block *current_header;
 291 
 292 /* Have we hit EOF yet?  */
 293 extern gboolean hit_eof;
 294 
 295 extern struct tar_stat_info current_stat_info;
 296 
 297 /*** declarations of public functions ************************************************************/
 298 
 299 /* tar-internal.c */
 300 gboolean is_octal_digit (char c);
 301 void tar_assign_string (char **string, char *value);
 302 void tar_assign_string_dup (char **string, const char *value);
 303 void tar_assign_string_dup_n (char **string, const char *value, size_t n);
 304 intmax_t stoint (const char *arg, char **arglim, gboolean *overflow, intmax_t minval,
 305                  uintmax_t maxval);
 306 intmax_t tar_from_header (const char *where0, size_t digs, char const *type, intmax_t minval,
 307                           uintmax_t maxval, gboolean octal_only);
 308 off_t off_from_header (const char *p, size_t s);
 309 union block *tar_find_next_block (tar_super_t *archive);
 310 gboolean tar_set_next_block_after (union block *block);
 311 off_t tar_current_block_ordinal (const tar_super_t *archive);
 312 gboolean tar_skip_file (tar_super_t *archive, off_t size);
 313 
 314 /* tar-sparse.c */
 315 gboolean tar_sparse_member_p (tar_super_t *archive, struct tar_stat_info *st);
 316 gboolean tar_sparse_fixup_header (tar_super_t *archive, struct tar_stat_info *st);
 317 enum dump_status tar_sparse_skip_file (tar_super_t *archive, struct tar_stat_info *st);
 318 
 319 /* tar-xheader.c */
 320 gboolean tar_xheader_decode (struct tar_stat_info *st);
 321 gboolean tar_xheader_read (tar_super_t *archive, struct xheader *xhdr, union block *header,
 322                            off_t size);
 323 gboolean tar_xheader_decode_global (struct xheader *xhdr);
 324 void tar_xheader_destroy (struct xheader *xhdr);
 325 
 326 /*** inline functions ****************************************************************************/
 327 
 328 /**
 329  * Represent @n using a signed integer I such that (uintmax_t) I == @n.
 330    With a good optimizing compiler, this is equivalent to (intmax_t) i
 331    and requires zero machine instructions.  */
 332 #if !(UINTMAX_MAX / 2 <= INTMAX_MAX)
 333 #    error "tar_represent_uintmax() returns intmax_t to represent uintmax_t"
 334 #endif
 335 static inline intmax_t
 336 tar_represent_uintmax (uintmax_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 337 {
 338     intmax_t nd;
 339 
 340     if (n <= INTMAX_MAX)
 341         return n;
 342 
 343     // Avoid signed integer overflow on picky platforms.
 344     nd = n - INTMAX_MIN;
 345     return nd + INTMAX_MIN;
 346 }
 347 
 348 #endif

/* [previous][next][first][last][top][bottom][index][help]  */