From: Sergey Poznyakoff Date: Mon, 17 Nov 2003 15:20:46 +0000 (+0000) Subject: Support for star sparse format X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Ftar;a=commitdiff_plain;h=8d6e47cc7fcfb6781b82ba60b8eb823c7fdc7013 Support for star sparse format --- diff --git a/src/sparse.c b/src/sparse.c index 4f936dc..39be72d 100644 --- a/src/sparse.c +++ b/src/sparse.c @@ -215,11 +215,12 @@ sparse_scan_file (struct tar_sparse_file *file) } static struct tar_sparse_optab oldgnu_optab; +static struct tar_sparse_optab star_optab; static bool sparse_select_optab (struct tar_sparse_file *file) { - switch (archive_format) + switch (current_format == DEFAULT_FORMAT ? archive_format : current_format) { case V7_FORMAT: case USTAR_FORMAT: @@ -231,12 +232,15 @@ sparse_select_optab (struct tar_sparse_file *file) break; case POSIX_FORMAT: - case STAR_FORMAT: - /* FIXME: Add methods */ + /* FIXME: Add method */ return false; - default: + case STAR_FORMAT: + file->optab = &star_optab; break; + + default: + return false; } return true; } @@ -640,3 +644,72 @@ static struct tar_sparse_optab oldgnu_optab = { sparse_dump_region, sparse_extract_region, }; + + +/* Star */ + +/* Convert STAR format sparse data to internal representation + FIXME: Clubbers current_header! */ +static bool +star_get_sparse_info (struct tar_sparse_file *file) +{ + size_t i; + union block *h = current_header; + int ext_p; + static enum oldgnu_add_status rc; + + /* FIXME: note this! st_size was initialized from the header + which actually contains archived size. The following fixes it */ + file->stat_info->archive_file_size = file->stat_info->stat.st_size; + file->stat_info->stat.st_size = + OFF_FROM_HEADER (current_header->star_in_header.realsize); + + file->stat_info->sparse_map_size = 0; + + if (h->star_in_header.prefix[0] == '\0' + && h->star_in_header.sp[0].offset[10] != '\0') + { + /* Old star format */ + for (i = 0; i < SPARSES_IN_STAR_HEADER; i++) + { + rc = oldgnu_add_sparse (file, &h->star_in_header.sp[i]); + if (rc != add_ok) + break; + } + ext_p = h->star_in_header.isextended; + } + else + ext_p = 1; + + for (; rc == add_ok && ext_p; ext_p = h->star_ext_header.isextended) + { + h = find_next_block (); + if (!h) + { + ERROR ((0, 0, _("Unexpected EOF in archive"))); + return false; + } + set_next_block_after (h); + for (i = 0; i < SPARSES_IN_STAR_EXT_HEADER && rc == add_ok; i++) + rc = oldgnu_add_sparse (file, &h->star_ext_header.sp[i]); + } + + if (rc == add_fail) + { + ERROR ((0, 0, _("%s: invalid sparse archive member"), + file->stat_info->orig_file_name)); + return false; + } + return true; +} + + +static struct tar_sparse_optab star_optab = { + NULL, /* No init function */ + NULL, /* No done function */ + NULL, + star_get_sparse_info, + NULL, /* No scan_block function */ + NULL, /* No dump region function */ + sparse_extract_region, +}; diff --git a/src/tar.h b/src/tar.h index c2a2004..449a938 100644 --- a/src/tar.h +++ b/src/tar.h @@ -42,29 +42,6 @@ struct posix_header /* 500 */ }; -struct star_header -{ /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - char typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[131]; /* 345 */ - char atime[12]; /* 476 */ - char ctime[12]; /* 488 */ - /* 500 */ -}; - #define TMAGIC "ustar" /* ustar and a null */ #define TMAGLEN 6 #define TVERSION "00" /* 00 and no null */ @@ -212,6 +189,57 @@ struct oldgnu_header /* This file is a tape/volume header. Ignore it on extraction. */ #define GNUTYPE_VOLHDR 'V' + +/* Jörg Schilling star header */ + +struct star_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[131]; /* 345 */ + char atime[12]; /* 476 */ + char ctime[12]; /* 488 */ + /* 500 */ +}; + +#define SPARSES_IN_STAR_HEADER 4 +#define SPARSES_IN_STAR_EXT_HEADER 21 + +struct star_in_header { + char fill[345]; /* 0 Everything that is before t_prefix */ + char prefix[1]; /* 345 t_name prefix */ + char fill2; /* 346 */ + char fill3[8]; /* 347 */ + char isextended; /* 355 */ + struct sparse sp[SPARSES_IN_STAR_HEADER]; /* 356 */ + char realsize[12]; /* 452 Actual size of the file */ + char offset[12]; /* 464 Offset of multivolume contents */ + char atime[12]; /* 476 */ + char ctime[12]; /* 488 */ + char mfill[8]; /* 500 */ + char xmagic[4]; /* 508 "tar" */ +}; + +struct star_ext_header { + struct sparse sp[SPARSES_IN_STAR_EXT_HEADER]; + char isextended; +}; + + + /* tar Header Block, overall structure. */ /* tar files are made in basic blocks of this size. */ @@ -267,6 +295,8 @@ union block struct star_header star_header; struct oldgnu_header oldgnu_header; struct sparse_header sparse_header; + struct star_in_header star_in_header; + struct star_ext_header star_ext_header; }; /* End of Format description. */