Manual pages: mcmcdiffmceditmcview

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     char offset[12];    //   0
  98     char numbytes[12];  //  12
  99                         //  24
 100 };
 101 
 102 /* Extension header for sparse files, used immediately after the GNU extra
 103    header, and used only if all sparse information cannot fit into that
 104    extra header.  There might even be many such extension headers, one after
 105    the other, until all sparse information has been recorded.  */
 106 struct sparse_header
 107 {  // byte offset
 108     struct sparse sp[SPARSES_IN_SPARSE_HEADER];
 109     //   0
 110     char isextended;  // 504
 111                       // 505
 112 };
 113 
 114 /* The old GNU format header conflicts with POSIX format in such a way that
 115    POSIX archives may fool old GNU tar's, and POSIX tar's might well be
 116    fooled by old GNU tar archives.  An old GNU format header uses the space
 117    used by the prefix field in a POSIX header, and cumulates information
 118    normally found in a GNU extra header.  With an old GNU tar header, we
 119    never see any POSIX header nor GNU extra header.  Supplementary sparse
 120    headers are allowed, however.  */
 121 struct oldgnu_header
 122 {                           // byte offset
 123     char unused_pad1[345];  //   0
 124     char atime[12];         // 345 Incr. archive: atime of the file
 125     char ctime[12];         // 357 Incr. archive: ctime of the file
 126     char offset[12];        // 369 Multivolume archive: the offset of start of this volume
 127     char longnames[4];      // 381 Not used
 128     char unused_pad2;       // 385
 129     struct sparse sp[SPARSES_IN_OLDGNU_HEADER];
 130     // 386
 131     char isextended;    // 482 Sparse file: Extension sparse header follows
 132     char realsize[12];  // 483 Sparse file: Real size
 133                         // 495
 134 };
 135 
 136 /* J@"org Schilling star header */
 137 struct star_header
 138 {                        // byte offset
 139     char name[100];      //   0
 140     char mode[8];        // 100
 141     char uid[8];         // 108
 142     char gid[8];         // 116
 143     char size[12];       // 124
 144     char mtime[12];      // 136
 145     char chksum[8];      // 148
 146     char typeflag;       // 156
 147     char linkname[100];  // 157
 148     char magic[6];       // 257
 149     char version[2];     // 263
 150     char uname[32];      // 265
 151     char gname[32];      // 297
 152     char devmajor[8];    // 329
 153     char devminor[8];    // 337
 154     char prefix[131];    // 345
 155     char atime[12];      // 476
 156     char ctime[12];      // 488
 157                          // 500
 158 };
 159 
 160 struct star_in_header
 161 {
 162     char fill[345];                            //   0  Everything that is before t_prefix
 163     char prefix[1];                            // 345  t_name prefix
 164     char fill2;                                // 346
 165     char fill3[8];                             // 347
 166     char isextended;                           // 355
 167     struct sparse sp[SPARSES_IN_STAR_HEADER];  // 356
 168     char realsize[12];                         // 452  Actual size of the file
 169     char offset[12];                           // 464  Offset of multivolume contents
 170     char atime[12];                            // 476
 171     char ctime[12];                            // 488
 172     char mfill[8];                             // 500
 173     char xmagic[4];                            // 508  "tar"
 174 };
 175 
 176 struct star_ext_header
 177 {
 178     struct sparse sp[SPARSES_IN_STAR_EXT_HEADER];
 179     char isextended;
 180 };
 181 
 182 /* tar Header Block, overall structure */
 183 union block
 184 {
 185     char buffer[BLOCKSIZE];
 186     struct posix_header header;
 187     struct star_header star_header;
 188     struct oldgnu_header oldgnu_header;
 189     struct sparse_header sparse_header;
 190     struct star_in_header star_in_header;
 191     struct star_ext_header star_ext_header;
 192 };
 193 
 194 /* Information about a sparse file */
 195 struct sp_array
 196 {
 197     off_t offset;       // chunk offset in file
 198     off_t numbytes;     // length of chunk
 199     off_t arch_offset;  // chunk offset in archive
 200 };
 201 
 202 enum dump_status
 203 {
 204     dump_status_ok,
 205     dump_status_short,
 206     dump_status_fail,
 207     dump_status_not_implemented
 208 };
 209 
 210 enum archive_format
 211 {
 212     TAR_UNKNOWN = 0,  // format to be decided later
 213     TAR_V7,           // old V7 tar format
 214     TAR_OLDGNU,       // GNU format as per before tar 1.12
 215     TAR_USTAR,        // POSIX.1-1988 (ustar) format
 216     TAR_POSIX,        // POSIX.1-2001 format
 217     TAR_STAR,         // star format defined in 1994
 218     TAR_GNU           // almost same as OLDGNU_FORMAT
 219 };
 220 
 221 typedef struct
 222 {
 223     struct vfs_s_super base;  // base class
 224 
 225     int fd;
 226     struct stat st;
 227     enum archive_format type;   // type of the archive
 228     union block *record_start;  // start of record of archive
 229 } tar_super_t;
 230 
 231 struct xheader
 232 {
 233     size_t size;
 234     char *buffer;
 235 };
 236 
 237 struct tar_stat_info
 238 {
 239     char *orig_file_name;  // name of file read from the archive header
 240     char *file_name;       // name of file for the current archive entry after being normalized
 241     char *link_name;       // name of link for the current archive entry
 242 #if 0
 243     char *uname;                // user name of owner
 244     char *gname;                // group name of owner
 245 #endif
 246     struct stat stat;  // regular filesystem stat
 247 
 248     /* stat() doesn't always have access, data modification, and status
 249        change times in a convenient form, so store them separately.  */
 250     struct timespec atime;
 251     struct timespec mtime;
 252     struct timespec ctime;
 253 
 254     off_t archive_file_size;  // size of file as stored in the archive, equals stat.st_size for
 255                               // non-sparse files
 256     gboolean is_sparse;       // is the file sparse
 257 
 258     // For sparse files
 259     intmax_t sparse_major;
 260     intmax_t sparse_minor;
 261     GArray *sparse_map;  // array of struct sp_array
 262 
 263     off_t real_size;         // real size of sparse file
 264     gboolean real_size_set;  // TRUE when GNU.sparse.realsize is set in archived file
 265 
 266     gboolean
 267         sparse_name_done;  // TRUE if 'GNU.sparse.name' header was processed pax header parsing.
 268                            // Following 'path'  header (lower priority) will be ignored.
 269 
 270     // Extended headers
 271     struct xheader xhdr;
 272 
 273     // For dumpdirs
 274     gboolean is_dumpdir;  // is the member a dumpdir?
 275     gboolean skipped;     // the member contents is already read (for GNUTYPE_DUMPDIR)
 276     char *dumpdir;        // contents of the dump directory
 277 };
 278 
 279 /*** global variables defined in .c file *********************************************************/
 280 
 281 extern const idx_t blocking_factor;
 282 extern const idx_t record_size;
 283 
 284 extern union block *record_end;     // last+1 block of archive record
 285 extern union block *current_block;  // current block of archive
 286 extern off_t record_start_block;    // block ordinal at record_start
 287 
 288 extern union block *current_header;
 289 
 290 /* Have we hit EOF yet?  */
 291 extern gboolean hit_eof;
 292 
 293 extern struct tar_stat_info current_stat_info;
 294 
 295 /*** declarations of public functions ************************************************************/
 296 
 297 /* tar-internal.c */
 298 gboolean is_octal_digit (char c);
 299 void tar_assign_string (char **string, char *value);
 300 void tar_assign_string_dup (char **string, const char *value);
 301 void tar_assign_string_dup_n (char **string, const char *value, size_t n);
 302 intmax_t stoint (const char *arg, char **arglim, gboolean *overflow, intmax_t minval,
 303                  uintmax_t maxval);
 304 intmax_t tar_from_header (const char *where0, size_t digs, char const *type, intmax_t minval,
 305                           uintmax_t maxval, gboolean octal_only);
 306 off_t off_from_header (const char *p, size_t s);
 307 union block *tar_find_next_block (tar_super_t *archive);
 308 gboolean tar_set_next_block_after (union block *block);
 309 off_t tar_current_block_ordinal (const tar_super_t *archive);
 310 gboolean tar_skip_file (tar_super_t *archive, off_t size);
 311 
 312 /* tar-sparse.c */
 313 gboolean tar_sparse_member_p (tar_super_t *archive, struct tar_stat_info *st);
 314 gboolean tar_sparse_fixup_header (tar_super_t *archive, struct tar_stat_info *st);
 315 enum dump_status tar_sparse_skip_file (tar_super_t *archive, struct tar_stat_info *st);
 316 
 317 /* tar-xheader.c */
 318 gboolean tar_xheader_decode (struct tar_stat_info *st);
 319 gboolean tar_xheader_read (tar_super_t *archive, struct xheader *xhdr, union block *header,
 320                            off_t size);
 321 gboolean tar_xheader_decode_global (struct xheader *xhdr);
 322 void tar_xheader_destroy (struct xheader *xhdr);
 323 
 324 /*** inline functions ****************************************************************************/
 325 
 326 /**
 327  * Represent @n using a signed integer I such that (uintmax_t) I == @n.
 328    With a good optimizing compiler, this is equivalent to (intmax_t) i
 329    and requires zero machine instructions.  */
 330 #if !(UINTMAX_MAX / 2 <= INTMAX_MAX)
 331 #error "tar_represent_uintmax() returns intmax_t to represent uintmax_t"
 332 #endif
 333 static inline intmax_t
 334 tar_represent_uintmax (uintmax_t n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 335 {
 336     intmax_t nd;
 337 
 338     if (n <= INTMAX_MAX)
 339         return n;
 340 
 341     // Avoid signed integer overflow on picky platforms.
 342     nd = n - INTMAX_MIN;
 343     return nd + INTMAX_MIN;
 344 }
 345 
 346 #endif

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