From: Paul Eggert Date: Sat, 22 Sep 2001 00:47:09 +0000 (+0000) Subject: (recent_long_name, recent_long_link, recent_long_name_blocks, X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=85f651c8c69c45c2df5ea6d9bd8efb3b6c28584f;p=chaz%2Ftar (recent_long_name, recent_long_link, recent_long_name_blocks, recent_long_link_blocks): New vars. (read_and): Pass 0 to read_header. (read_header): New arg RAW_EXTENDED_HEADERS. Store away extended headers into new vars. Null-terminate incoming symbolic links. --- diff --git a/src/list.c b/src/list.c index 1c75808..8169a79 100644 --- a/src/list.c +++ b/src/list.c @@ -32,6 +32,10 @@ union block *current_header; /* points to current archive header */ struct stat current_stat; /* stat struct corresponding */ enum archive_format current_format; /* recognized format */ +union block *recent_long_name; /* recent long name header and contents */ +union block *recent_long_link; /* likewise, for long link */ +size_t recent_long_name_blocks; /* number of blocks in recent_long_name */ +size_t recent_long_link_blocks; /* likewise, for long link */ static uintmax_t from_header PARAMS ((const char *, size_t, const char *, uintmax_t, uintmax_t)); @@ -73,7 +77,7 @@ read_and (void (*do_something) ()) while (1) { prev_status = status; - status = read_header (); + status = read_header (0); switch (status) { case HEADER_STILL_UNREAD: @@ -239,6 +243,9 @@ list_archive (void) Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a block full of zeros (EOF marker). + If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the + GNU long name and link headers into later headers. + You must always set_next_block_after(current_header) to skip past the header which this routine reads. */ @@ -252,7 +259,7 @@ list_archive (void) computes two checksums -- signed and unsigned. */ enum read_header -read_header (void) +read_header (bool raw_extended_headers) { size_t i; int unsigned_sum; /* the POSIX one :-) */ @@ -261,11 +268,14 @@ read_header (void) uintmax_t parsed_sum; char *p; union block *header; - char **longp; + union block **longp; char *bp; union block *data_block; size_t size, written; - static char *next_long_name, *next_long_link; + static union block *next_long_name; + static union block *next_long_link; + static size_t next_long_name_blocks; + static size_t next_long_link_blocks; while (1) { @@ -318,19 +328,35 @@ read_header (void) if (header->header.typeflag == GNUTYPE_LONGNAME || header->header.typeflag == GNUTYPE_LONGLINK) { - longp = ((header->header.typeflag == GNUTYPE_LONGNAME) - ? &next_long_name - : &next_long_link); + if (raw_extended_headers) + return HEADER_SUCCESS_EXTENDED; + else + { + size_t name_size = current_stat.st_size; + size = name_size - name_size % BLOCKSIZE + 2 * BLOCKSIZE; + if (name_size != current_stat.st_size || size < name_size) + xalloc_die (); + } + + if (header->header.typeflag == GNUTYPE_LONGNAME) + { + longp = &next_long_name; + next_long_name_blocks = size / BLOCKSIZE; + } + else + { + longp = &next_long_link; + next_long_link_blocks = size / BLOCKSIZE; + } set_next_block_after (header); if (*longp) free (*longp); - size = current_stat.st_size; - if (size != current_stat.st_size) - xalloc_die (); - bp = *longp = xmalloc (size); + *longp = xmalloc (size); + **longp = *header; + bp = (*longp)->buffer + BLOCKSIZE; - for (; size > 0; size -= written) + for (size -= BLOCKSIZE; size > 0; size -= written) { data_block = find_next_block (); if (! data_block) @@ -348,6 +374,8 @@ read_header (void) (data_block->buffer + written - 1)); } + *bp = '\0'; + /* Loop! */ } @@ -357,8 +385,13 @@ read_header (void) struct posix_header const *h = ¤t_header->header; char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1]; - name = next_long_name; - if (! name) + if (next_long_name) + { + name = next_long_name->buffer + BLOCKSIZE; + recent_long_name = next_long_name; + recent_long_name_blocks = next_long_name_blocks; + } + else { /* Accept file names as specified by POSIX.1-1996 section 10.1.1. */ @@ -379,27 +412,24 @@ read_header (void) memcpy (np, h->name, sizeof h->name); np[sizeof h->name] = '\0'; name = namebuf; + recent_long_name_blocks = 0; } assign_string (¤t_file_name, name); - if (next_long_name) + + if (next_long_link) { - free (next_long_name); - next_long_name = 0; + name = next_long_link->buffer + BLOCKSIZE; + recent_long_link = next_long_link; + recent_long_link_blocks = next_long_link_blocks; } - - name = next_long_link; - if (! name) + else { memcpy (namebuf, h->linkname, sizeof h->linkname); namebuf[sizeof h->linkname] = '\0'; name = namebuf; + recent_long_link_blocks = 0; } assign_string (¤t_link_name, name); - if (next_long_link) - { - free (next_long_link); - next_long_link = 0; - } return HEADER_SUCCESS; }