Hi, On 19/09/2010 03:08, Samuel Thibault wrote: > Samuel Thibault, le Sun 19 Sep 2010 03:00:31 +0200, a écrit : >> I have pushed debian packagings for gopherfs, netio, and tarfs to >> pkg-hurd, and uploaded them to debian-ports.
> I forgot to say: unfortunately, it seems gopherfs and tarfs don't work > atm. Here is a patch that fixes tarfs. It's mostly updating the code taken from mc (tweaked a little bit to remove mc-specific parts and to integrate with tarfs). With this patch, it seems to be working fine (read/write and with bzip2/gzip files). diff -Nurp orig/tarfs-0.0.20100918/tar.c tarfs-0.0.20100918/tar.c --- orig/tarfs-0.0.20100918/tar.c 2010-09-19 02:39:04.000000000 +0200 +++ tarfs-0.0.20100918/tar.c 2010-09-20 22:07:32.000000000 +0200 @@ -1,5 +1,6 @@ /* GNU tar files parsing. - Copyright (C) 1995 The Free Software Foundation + Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007 Free Software Foundation, Inc. Written by: 1995 Jakub Jelinek Rewritten by: 1998 Pavel Machek @@ -39,7 +40,7 @@ #include "debug.h" /* A hook which is called each time a header has been parsed. */ -int (*tar_header_hook) (tar_record_t *, off_t) = NULL; +int (*tar_header_hook) (tar_record_t *, struct archive *) = NULL; #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) @@ -48,141 +49,102 @@ int (*tar_header_hook) (tar_record_t *, # define isspace(c) ( (c) == ' ' ) #endif +/* Taken from glibc. */ +char * +strconcat (const char *string1, ...) +{ + size_t l; + va_list args; + char *s; + char *concat; + char *ptr; + + if (!string1) + return NULL; + + l = 1 + strlen (string1); + va_start (args, string1); + s = va_arg (args, char *); + while (s) + { + l += strlen (s); + s = va_arg (args, char *); + } + va_end (args); + + concat = malloc (l); + ptr = concat; + + ptr = stpcpy (ptr, string1); + va_start (args, string1); + s = va_arg (args, char *); + while (s) + { + ptr = stpcpy (ptr, s); + s = va_arg (args, char *); + } + va_end (args); + + return concat; +} + /* * Quick and dirty octal conversion. * * Result is -1 if the field is invalid (all blank, or nonoctal). */ -static long -from_oct (int digs, char *where) +static long tar_from_oct (int digs, char *where) { - register long value; + register long value; - while (isspace (*where)) - { /* Skip spaces */ - where++; - if (--digs <= 0) - return -1; /* All blank field */ + while (isspace ((unsigned char) *where)) { /* Skip spaces */ + where++; + if (--digs <= 0) + return -1; /* All blank field */ } - value = 0; - while (digs > 0 && isodigit (*where)) - { /* Scan till nonoctal */ - value = (value << 3) | (*where++ - '0'); - --digs; + value = 0; + while (digs > 0 && isodigit (*where)) { /* Scan till nonoctal */ + value = (value << 3) | (*where++ - '0'); + --digs; } - if (digs > 0 && *where && !isspace (*where)) - return -1; /* Ended on non-space/nul */ + if (digs > 0 && *where && !isspace ((unsigned char) *where)) + return -1; /* Ended on non-space/nul */ - return value; + return value; } -/* As we open one archive at a time, it is safe to have this static */ -static store_offset_t current_tar_position = 0; - -static tar_record_t rec_buf; - -static tar_record_t * -get_next_record (struct store *tar_file) +static union record * +tar_get_next_record (struct archive *archive) { - error_t err; - size_t n; - void *buf; - - debug (("Reading at offset %lli", current_tar_position)); - buf = rec_buf.charptr; - err = store_read (tar_file, current_tar_position, RECORDSIZE, &buf, &n); - - if (err) - error (1, err, "Read error (offset=%lli)", current_tar_position); - assert (n <= RECORDSIZE); + error_t err; + void *buf = NULL; + size_t n = 0; + + err = store_read (archive->tar_file, archive->current_tar_position, RECORDSIZE, &buf, &n); + if (err) + error (1, err, "Read error (offset=%lli)", archive->current_tar_position); + if (n != RECORDSIZE) + return NULL; /* An error has occurred */ + + if (buf != archive->rec_buf.charptr) + { + memcpy (archive->rec_buf.charptr, buf, n); + munmap (buf, n); + } - if (buf != rec_buf.charptr) - { - memcpy (rec_buf.charptr, buf, n); - munmap (buf, n); - } - - if (n != RECORDSIZE) - return NULL; /* An error has occurred */ + archive->current_tar_position += RECORDSIZE; - current_tar_position += n; - - return &rec_buf; + return &(archive->rec_buf); } -static void -skip_n_records (struct store *tar_file, int n) +static void tar_skip_n_records (struct archive *archive, int n) { - current_tar_position += n * RECORDSIZE; -} - -void -tar_header2stat (io_statbuf_t *st, tar_record_t *header) -{ - st->st_mode = from_oct (8, header->header.mode); - - /* Adjust st->st_mode because there are tar-files with - * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't - * know about the other modes but I think I cause no new - * problem when I adjust them, too. -- Norbert. - */ - if (header->header.linkflag == LF_DIR) - { - st->st_mode |= S_IFDIR; - } - else if (header->header.linkflag == LF_SYMLINK) - { - st->st_mode |= S_IFLNK; - } - else if (header->header.linkflag == LF_CHR) - { - st->st_mode |= S_IFCHR; - } - else if (header->header.linkflag == LF_BLK) - { - st->st_mode |= S_IFBLK; - } - else if (header->header.linkflag == LF_FIFO) - { - st->st_mode |= S_IFIFO; - } - else - st->st_mode |= S_IFREG; - - st->st_rdev = 0; - if (!strcmp (header->header.magic, TMAGIC)) - { - st->st_uid = *header->header.uname ? finduid (header->header.uname) : - from_oct (8, header->header.uid); - st->st_gid = *header->header.gname ? findgid (header->header.gname) : - from_oct (8, header->header.gid); - switch (header->header.linkflag) - { - case LF_BLK: - case LF_CHR: - st->st_rdev = (from_oct (8, header->header.devmajor) << 8) | - from_oct (8, header->header.devminor); - } - } - else - { /* Old Unix tar */ - st->st_uid = from_oct (8, header->header.uid); - st->st_gid = from_oct (8, header->header.gid); - } - //st->st_size = hstat.st_size; - st->st_size = from_oct (1 + 12, header->header.size); - if (st->st_size > 0) - st->st_blocks = ((st->st_size - 1) / 512) + 1; - else - st->st_blocks = 0; - st->st_mtime = from_oct (1 + 12, header->header.mtime); - st->st_atime = from_oct (1 + 12, header->header.atime); - st->st_ctime = from_oct (1 + 12, header->header.ctime); + (void) archive; + archive->current_tar_position += n * RECORDSIZE; } - typedef enum { STATUS_BADCHECKSUM, @@ -197,153 +159,282 @@ ReadStatus; * */ static ReadStatus -read_header (struct store *tar_file) +tar_read_header (struct archive *archive, size_t *h_size) { - register int i; - register long sum, signed_sum, recsum; - register char *p; - register tar_record_t *header; - char *data; - int size, written; - static char *next_lonname = NULL, *next_lonlink = NULL; - char *current_file_name, *current_link_name; - struct stat hstat; /* Stat struct corresponding */ - char arch_name[NAMSIZ + 1]; - char arch_linkname[NAMSIZ + 1]; - - memcpy (arch_name, header->header.arch_name, NAMSIZ); - arch_name [NAMSIZ] = '\0'; - memcpy (arch_linkname, header->header.arch_linkname, NAMSIZ); - arch_linkname [NAMSIZ] = '\0'; - - -recurse: - - header = get_next_record (tar_file); - if (NULL == header) - return STATUS_EOF; - - recsum = from_oct (8, header->header.chksum); - - sum = 0; - signed_sum = 0; - p = header->charptr; - for (i = sizeof (*header); --i >= 0;) - { - /* - * We can't use unsigned char here because of old compilers, - * e.g. V7. - */ - signed_sum += *p; - sum += 0xFF & *p++; - } - - /* Adjust checksum to count the "chksum" field as blanks. */ - for (i = sizeof (header->header.chksum); --i >= 0;) - { - sum -= 0xFF & header->header.chksum[i]; - signed_sum -= (char) header->header.chksum[i]; + register int i; + register long sum, signed_sum, recsum; + register char *p; + register union record *header; + static char *next_long_name = NULL, *next_long_link = NULL; + + recurse: + + header = tar_get_next_record (archive); + if (NULL == header) + return STATUS_EOF; + + recsum = tar_from_oct (8, header->header.chksum); + + sum = 0; + signed_sum = 0; + p = header->charptr; + for (i = sizeof (*header); --i >= 0;) { + /* + * We can't use unsigned char here because of old compilers, + * e.g. V7. + */ + signed_sum += *p; + sum += 0xFF & *p++; + } + + /* Adjust checksum to count the "chksum" field as blanks. */ + for (i = sizeof (header->header.chksum); --i >= 0;) { + sum -= 0xFF & header->header.chksum[i]; + signed_sum -= (char) header->header.chksum[i]; + } + sum += ' ' * sizeof header->header.chksum; + signed_sum += ' ' * sizeof header->header.chksum; + + /* + * This is a zeroed record...whole record is 0's except + * for the 8 blanks we faked for the checksum field. + */ + if (sum == 8 * ' ') + return STATUS_EOFMARK; + + if (sum != recsum && signed_sum != recsum) + return STATUS_BADCHECKSUM; + + /* + * Try to determine the archive format. + */ + if (archive->type == TAR_UNKNOWN) { + if (!strcmp (header->header.magic, TMAGIC)) { + if (header->header.linkflag == LF_GLOBAL_EXTHDR) + archive->type = TAR_POSIX; + else + archive->type = TAR_USTAR; + } else if (!strcmp (header->header.magic, OLDGNU_MAGIC)) { + archive->type = TAR_GNU; + } } - sum += ' ' * sizeof header->header.chksum; - signed_sum += ' ' * sizeof header->header.chksum; - /* - * This is a zeroed record...whole record is 0's except - * for the 8 blanks we faked for the checksum field. - */ - if (sum == 8 * ' ') - return STATUS_EOFMARK; - - if (sum != recsum && signed_sum != recsum) - return STATUS_BADCHECKSUM; - - /* - * linkflag on BSDI tar (pax) always '\000' - */ - - if (header->header.linkflag == '\000' && - strlen (arch_name) && - arch_name[strlen (arch_name) - 1] == '/') - header->header.linkflag = LF_DIR; + /* + * linkflag on BSDI tar (pax) always '\000' + */ + if (header->header.linkflag == '\000') { + if (header->header.arch_name[NAMSIZ - 1] != '\0') + i = NAMSIZ; + else + i = strlen (header->header.arch_name); + + if (i && header->header.arch_name[i - 1] == '/') + header->header.linkflag = LF_DIR; + } + + /* + * Good record. Decode file size and return. + */ + if (header->header.linkflag == LF_LINK + || header->header.linkflag == LF_DIR) + *h_size = 0; /* Links 0 size on tape */ + else + *h_size = tar_from_oct (1 + 12, header->header.size); + + /* + * Skip over directory snapshot info records that + * are stored in incremental tar archives. + */ + if (header->header.linkflag == LF_DUMPDIR) { + if (archive->type == TAR_UNKNOWN) + archive->type = TAR_GNU; + return STATUS_SUCCESS; + } + + /* + * Skip over pax extended header and global extended + * header records. + */ + if (header->header.linkflag == LF_EXTHDR || + header->header.linkflag == LF_GLOBAL_EXTHDR) { + if (archive->type == TAR_UNKNOWN) + archive->type = TAR_POSIX; + return STATUS_SUCCESS; + } + + if (header->header.linkflag == LF_LONGNAME + || header->header.linkflag == LF_LONGLINK) { + char **longp; + char *bp, *data; + int size, written; + + if (archive->type == TAR_UNKNOWN) + archive->type = TAR_GNU; + + longp = ((header->header.linkflag == LF_LONGNAME) + ? &next_long_name : &next_long_link); + + free (*longp); + bp = *longp = malloc (*h_size + 1); + + for (size = *h_size; size > 0; size -= written) { + data = tar_get_next_record (archive)->charptr; + if (data == NULL) { + free (*longp); + *longp = NULL; + error (0, 0, "Unexpected EOF on archive file"); + return STATUS_BADCHECKSUM; + } + written = RECORDSIZE; + if (written > size) + written = size; - /* - * Good record. Decode file size and return. - */ - if (header->header.linkflag == LF_LINK || header->header.linkflag == LF_DIR) - hstat.st_size = 0; /* Links 0 size on tape */ - else - hstat.st_size = from_oct (1 + 12, header->header.size); + memcpy (bp, data, written); + bp += written; + } - if (header->header.linkflag == LF_LONGNAME - || header->header.linkflag == LF_LONGLINK) - { - for (size = hstat.st_size; size > 0; size -= written) - { - data = get_next_record (tar_file)->charptr; - if (data == NULL) - { - error (0, 0, "Unexpected EOF on archive file"); - return STATUS_BADCHECKSUM; + *bp = 0; + goto recurse; + } else { + long data_position; + char *q; + int len; + char *current_file_name, *current_link_name; + + current_link_name = + (next_long_link ? next_long_link : + strndup (header->header.arch_linkname, NAMSIZ)); + len = strlen (current_link_name); + if (len > 1 && current_link_name[len - 1] == '/') + current_link_name[len - 1] = 0; + + current_file_name = NULL; + switch (archive->type) { + case TAR_USTAR: + case TAR_POSIX: + /* The ustar archive format supports pathnames of upto 256 + * characters in length. This is achieved by concatenating + * the contents of the `prefix' and `arch_name' fields like + * this: + * + * prefix + path_separator + arch_name + * + * If the `prefix' field contains an empty string i.e. its + * first characters is '\0' the prefix field is ignored. + */ + if (header->header.unused.prefix[0] != '\0') { + char *temp_name, *temp_prefix; + + temp_name = strndup (header->header.arch_name, NAMSIZ); + temp_prefix = strndup (header->header.unused.prefix, + PREFIX_SIZE); + current_file_name = strconcat (temp_prefix, "/", + temp_name, (char *) NULL); + free (temp_name); + free (temp_prefix); } - written = RECORDSIZE; - if (written > size) - written = size; - } - goto recurse; - } - else - { - long data_position; - char *p, *q; - int len; - int isdir = 0; - - current_file_name = (next_lonname - ? next_lonname - : strdup (arch_name)); - len = strlen (current_file_name); - if (current_file_name[len - 1] == '/') - { - current_file_name[len - 1] = 0; - isdir = 1; + break; + case TAR_GNU: + if (next_long_name != NULL) + current_file_name = next_long_name; + break; + default: + break; } + if (current_file_name == NULL) + current_file_name = strndup (header->header.arch_name, NAMSIZ); - current_link_name = (next_lonlink - ? next_lonlink - : strdup (arch_linkname)); - len = strlen (current_link_name); - if (len && current_link_name[len - 1] == '/') - current_link_name[len - 1] = 0; - - next_lonlink = next_lonname = NULL; - - data_position = current_tar_position; - - p = strrchr (current_file_name, '/'); - if (p == NULL) - { - p = current_file_name; - q = current_file_name + strlen (current_file_name); /* "" */ - } - else - { - *(p++) = 0; - q = current_file_name; + len = strlen (current_file_name); + + data_position = archive->current_tar_position; + + p = strrchr (current_file_name, '/'); + if (p == NULL) { + p = current_file_name; + q = current_file_name + len; /* "" */ + } else { + *(p++) = 0; + q = current_file_name; } - if (tar_header_hook) - tar_header_hook (header, current_tar_position); + if (tar_header_hook) + tar_header_hook (header, archive); + + free (current_file_name); + + /* done:*/ + next_long_link = next_long_name = NULL; + + if (archive->type == TAR_GNU && + header->header.unused.oldgnu.isextended) { + while (tar_get_next_record (archive)->ext_hdr. + isextended); + } + return STATUS_SUCCESS; + } +} - free (current_file_name); +void +tar_fill_stat (struct archive *archive, struct stat *st, tar_record_t *header) +{ + st->st_mode = tar_from_oct (8, header->header.mode); -/* done: */ - if (header->header.isextended) - { - while (get_next_record (tar_file)->ext_hdr.isextended); + /* Adjust st->st_mode because there are tar-files with + * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't + * know about the other modes but I think I cause no new + * problem when I adjust them, too. -- Norbert. + */ + if (header->header.linkflag == LF_DIR) { + st->st_mode |= S_IFDIR; + } else if (header->header.linkflag == LF_SYMLINK) { + st->st_mode |= S_IFLNK; + } else if (header->header.linkflag == LF_CHR) { + st->st_mode |= S_IFCHR; + } else if (header->header.linkflag == LF_BLK) { + st->st_mode |= S_IFBLK; + } else if (header->header.linkflag == LF_FIFO) { + st->st_mode |= S_IFIFO; + } else + st->st_mode |= S_IFREG; + + st->st_rdev = 0; + switch (archive->type) { + case TAR_USTAR: + case TAR_POSIX: + case TAR_GNU: + st->st_uid = + *header->header.uname ? finduid (header->header. + uname) : tar_from_oct (8, + header-> + header. + uid); + st->st_gid = + *header->header.gname ? findgid (header->header. + gname) : tar_from_oct (8, + header-> + header. + gid); + switch (header->header.linkflag) { + case LF_BLK: + case LF_CHR: + st->st_rdev = + (tar_from_oct (8, header->header.devmajor) << 8) | + tar_from_oct (8, header->header.devminor); } - skip_n_records (tar_file, (hstat.st_size + RECORDSIZE - 1) / RECORDSIZE); - return STATUS_SUCCESS; + default: + st->st_uid = tar_from_oct (8, header->header.uid); + st->st_gid = tar_from_oct (8, header->header.gid); + } + st->st_size = tar_from_oct (1 + 12, header->header.size); + st->st_mtime = tar_from_oct (1 + 12, header->header.mtime); + st->st_atime = 0; + st->st_ctime = 0; + if (archive->type == TAR_GNU) { + st->st_atime = tar_from_oct (1 + 12, + header->header.unused.oldgnu.atime); + st->st_ctime = tar_from_oct (1 + 12, + header->header.unused.oldgnu.ctime); } } @@ -354,77 +445,65 @@ recurse: int tar_open_archive (struct store *tar_file) { - ReadStatus status = STATUS_EOFMARK; /* Initial status at start of archive */ - ReadStatus prev_status = STATUS_SUCCESS; + /* Initial status at start of archive */ + ReadStatus status = STATUS_EOFMARK; + ReadStatus prev_status; + + struct archive archive; + archive.tar_file = tar_file; + archive.current_tar_position = 0; + archive.type = TAR_UNKNOWN; - current_tar_position = 0; - - for (;;) - { - prev_status = status; - status = read_header (tar_file); + for (;;) { + size_t h_size; + prev_status = status; + status = tar_read_header (&archive, &h_size); - switch (status) - { + switch (status) { case STATUS_SUCCESS: - continue; - - /* - * Invalid header: - * - * If the previous header was good, tell them - * that we are skipping bad ones. - */ + tar_skip_n_records (&archive, + (h_size + RECORDSIZE - + 1) / RECORDSIZE); + continue; + + /* + * Invalid header: + * + * If the previous header was good, tell them + * that we are skipping bad ones. + */ case STATUS_BADCHECKSUM: - switch (prev_status) - { + switch (prev_status) { - /* Error on first record */ + /* Error on first record */ case STATUS_EOFMARK: - return -1; - /* FALL THRU */ + /* FALL THRU */ - /* Error after header rec */ + /* Error after header rec */ case STATUS_SUCCESS: - prev_status = status; - { - /* FIXME: Bad hack */ - size_t size; - tar_record_t *hdr; - current_tar_position -= RECORDSIZE; - error (0, 0, "Skipping to next header (offset=%lli)", - current_tar_position); - hdr = get_next_record (tar_file); - size = from_oct (8, hdr->header.size); - size = size % RECORDSIZE - ? size / RECORDSIZE - : (size / RECORDSIZE) + RECORDSIZE; - current_tar_position += size; - } - - /* Error after error */ + /* Error after error */ case STATUS_BADCHECKSUM: - error (1, 0, "Bad checksum (offset=%lli)", current_tar_position); - return -1; + return -1; case STATUS_EOF: - return 0; + return 0; } - /* Record of zeroes */ + /* Record of zeroes */ case STATUS_EOFMARK: - status = prev_status; /* If error after 0's */ - /* FALL THRU */ + status = prev_status; /* If error after 0's */ + /* FALL THRU */ case STATUS_EOF: /* End of archive */ - break; + break; } - break; + break; }; - return 0; + + return 0; } @@ -497,7 +576,7 @@ tar_make_header (tar_record_t *header, i else header->header.linkflag = LF_NORMAL; - strncpy (header->header.magic, TMAGIC, TMAGLEN); + strncpy (header->header.magic, TMAGIC, strlen(TMAGIC)); uid_to_uname (st->st_uid, header->header.uname); gid_to_gname (st->st_gid, header->header.gname); diff -Nurp orig/tarfs-0.0.20100918/tar.h tarfs-0.0.20100918/tar.h --- orig/tarfs-0.0.20100918/tar.h 2010-09-19 02:39:04.000000000 +0200 +++ tarfs-0.0.20100918/tar.h 2010-09-20 18:58:12.000000000 +0200 @@ -33,6 +33,14 @@ #include <sys/mknod.h> #endif +enum { + TAR_UNKNOWN = 0, + TAR_V7, + TAR_USTAR, + TAR_POSIX, + TAR_GNU +}; + /* * Header block on tape. * @@ -43,6 +51,7 @@ */ #define RECORDSIZE 512 #define NAMSIZ 100 +#define PREFIX_SIZE 155 #define TUNMLEN 32 #define TGNMLEN 32 #define SPARSE_EXT_HDR 21 @@ -75,20 +84,27 @@ union record { char gname[TGNMLEN]; char devmajor[8]; char devminor[8]; - /* these following fields were added by JF for gnu */ - /* and are NOT standard */ - char atime[12]; - char ctime[12]; - char offset[12]; - char longnames[4]; -#ifdef NEEDPAD - char pad; -#endif - struct sparse sp[SPARSE_IN_HDR]; - char isextended; - char realsize[12]; /* true size of the sparse file */ - /* char ending_blanks[12];*//* number of nulls at the - end of the file, if any */ + /* The following bytes of the tar header record were originally unused. + + Archives following the ustar specification use almost all of those + bytes to support pathnames of 256 characters in length. + + GNU tar archives use the "unused" space to support incremental + archives and sparse files. */ + union unused { + char prefix[PREFIX_SIZE]; + /* GNU extensions to the ustar (POSIX.1-1988) archive format. */ + struct oldgnu { + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char pad; + struct sparse sp[SPARSE_IN_HDR]; + char isextended; + char realsize[12]; /* true size of the sparse file */ + } oldgnu; + } unused; } header; struct extended_header { struct sparse sp[21]; @@ -100,10 +116,8 @@ union record { #define CHKBLANKS " " /* 8 blanks, no null */ /* The magic field is filled with this if uname and gname are valid. */ -#define TMAGIC "ustar " /* 7 chars and a null */ -#define TMAGLEN 6 -#define TVERSION "00" /* 00 and no null */ -#define TVERSLEN 2 +#define TMAGIC "ustar" /* ustar and a null */ +#define OLDGNU_MAGIC "ustar " /* 7 chars and a null */ /* The linkflag defines the type of file */ #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compat */ @@ -115,6 +129,8 @@ union record { #define LF_DIR '5' /* Directory */ #define LF_FIFO '6' /* FIFO special file */ #define LF_CONTIG '7' /* Contiguous file */ +#define LF_EXTHDR 'x' /* pax Extended Header */ +#define LF_GLOBAL_EXTHDR 'g' /* pax Global Extended Header */ /* Further link types may be defined later. */ /* Note that the standards committee allows only capital A through @@ -137,8 +153,6 @@ union record { #define LF_VOLHDR 'V' /* This file is a tape/volume header */ /* Ignore it on extraction */ -#define LF_TRANS 'T' /* GNU/Hurd passive translator */ - /* * Exit codes from the "tar" program */ @@ -151,6 +165,8 @@ union record { Tape volume doesn't match the one specified on the command line */ +#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) + /* * We default to Unix Standard format rather than 4.2BSD tar format. * The code can actually produce all three: @@ -171,8 +187,15 @@ union record { typedef union record tar_record_t; +struct archive { + struct store *tar_file; + int type; + store_offset_t current_tar_position; + tar_record_t rec_buf; +}; + extern int tar_open_archive (struct store *tar_file); -extern void tar_header2stat (io_statbuf_t *st, tar_record_t *header); +extern void tar_fill_stat (struct archive *archive, io_statbuf_t *st, tar_record_t *header); /* Create a tar header based on ST and NAME where NAME is a path. If NAME is a hard link (resp. symlink), HARDLINK (resp. diff -Nurp orig/tarfs-0.0.20100918/tarfs.c tarfs-0.0.20100918/tarfs.c --- orig/tarfs-0.0.20100918/tarfs.c 2010-09-19 02:39:04.000000000 +0200 +++ tarfs-0.0.20100918/tarfs.c 2010-09-20 22:13:28.000000000 +0200 @@ -80,7 +80,7 @@ static struct store *tar_file; static struct mutex tar_file_lock; /* Archive parsing hook (see tar.c) */ -extern int (* tar_header_hook) (tar_record_t *, off_t); +extern int (* tar_header_hook) (tar_record_t *, struct archive *); /* List of tar items for this file */ static struct tar_list tar_list; @@ -325,7 +325,7 @@ error_t tarfs_create_node (struct node * It simply creates the node corresponding to the header. OFFSET denotes the offset of the header in the archive. */ int -tarfs_add_header (tar_record_t *hdr, off_t offset) +tarfs_add_header (tar_record_t *hdr, struct archive *archive) { error_t err; static struct tar_item *last_item = NULL; @@ -412,7 +412,7 @@ tarfs_add_header (tar_record_t *hdr, off /* Add the tar item into the list. */ err = tar_make_item (&NODE_INFO(new)->tar, new, - 0, offset); + 0, archive->current_tar_position); assert_perror (err); } } @@ -431,7 +431,7 @@ tarfs_add_header (tar_record_t *hdr, off if (new) { NEW_NODE_INFO (new); - tar_header2stat (&new->nn_stat, hdr); + tar_fill_stat (archive, &new->nn_stat, hdr); /* Create a cache for the new node. */ err = cache_create (new); @@ -440,7 +440,7 @@ tarfs_add_header (tar_record_t *hdr, off /* Add the tar item into the list. */ err = tar_make_item (&NODE_INFO(new)->tar, new, - new->nn_stat.st_size, offset); + new->nn_stat.st_size, archive->current_tar_position); assert_perror (err); } } HTH, -- Manuel Menal
signature.asc
Description: OpenPGP digital signature