X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Flist.c;h=59374ff8cbaf6fdb4943511f49e20ea0abdf01b5;hb=31d9c7e2a4344d8f884c93dd4fb467894de69e99;hp=1c75808a461662289e87dbf5fa2058a95b9fc738;hpb=a52396de9bde77671ac389183de918bb86ac785b;p=chaz%2Ftar diff --git a/src/list.c b/src/list.c index 1c75808..59374ff 100644 --- a/src/list.c +++ b/src/list.c @@ -1,7 +1,7 @@ /* List a tar archive, with support routines for reading a tar archive. - Copyright 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, - 2001 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, + 2001, 2003 Free Software Foundation, Inc. Written by John Gilmore, on 1985-08-26. @@ -32,9 +32,13 @@ 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)); +static uintmax_t from_header (const char *, size_t, const char *, + uintmax_t, uintmax_t); /* Base 64 digits; see Internet RFC 2045 Table 1. */ static char const base_64_digits[64] = @@ -61,7 +65,7 @@ base64_init (void) /* Main loop for reading an archive. */ void -read_and (void (*do_something) ()) +read_and (void (*do_something) (void)) { enum read_header status = HEADER_STILL_UNREAD; enum read_header prev_status; @@ -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: @@ -99,7 +103,7 @@ read_and (void (*do_something) ()) case GNUTYPE_MULTIVOL: case GNUTYPE_NAMES: break; - + case DIRTYPE: if (show_omitted_dirs_option) WARN ((0, 0, _("%s: Omitting"), @@ -176,7 +180,7 @@ list_archive (void) { if (verbose_option > 1) decode_header (current_header, ¤t_stat, ¤t_format, 0); - print_header (); + print_header (-1); } if (incremental_option && current_header->header.typeflag == GNUTYPE_DUMPDIR) @@ -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 *header_copy; char *bp; union block *data_block; size_t size, written; - static char *next_long_name, *next_long_link; + union block *next_long_name = 0; + union block *next_long_link = 0; + size_t next_long_name_blocks; + size_t next_long_link_blocks; while (1) { @@ -318,19 +328,38 @@ 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 (); + } + + header_copy = xmalloc (size + 1); + + if (header->header.typeflag == GNUTYPE_LONGNAME) + { + if (next_long_name) + free (next_long_name); + next_long_name = header_copy; + next_long_name_blocks = size / BLOCKSIZE; + } + else + { + if (next_long_link) + free (next_long_link); + next_long_link = header_copy; + 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); - - for (; size > 0; size -= written) + *header_copy = *header; + bp = header_copy->buffer + BLOCKSIZE; + + for (size -= BLOCKSIZE; size > 0; size -= written) { data_block = find_next_block (); if (! data_block) @@ -348,6 +377,8 @@ read_header (void) (data_block->buffer + written - 1)); } + *bp = '\0'; + /* Loop! */ } @@ -357,8 +388,16 @@ 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 (recent_long_name) + free (recent_long_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 +418,30 @@ read_header (void) memcpy (np, h->name, sizeof h->name); np[sizeof h->name] = '\0'; name = namebuf; + recent_long_name = 0; + recent_long_name_blocks = 0; } assign_string (¤t_file_name, name); - if (next_long_name) + current_trailing_slash = strip_trailing_slashes (current_file_name); + + if (recent_long_link) + free (recent_long_link); + + 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 = 0; + 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; } @@ -745,7 +787,7 @@ off_from_header (const char *p, size_t s) size_t size_from_header (const char *p, size_t s) { - return from_header (p, s, "size_t", (uintmax_t) 0, + return from_header (p, s, "size_t", (uintmax_t) 0, (uintmax_t) TYPE_MAXIMUM (size_t)); } @@ -811,8 +853,8 @@ tartime (time_t t) struct tm *tm = localtime (&t); if (tm) { - sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d", + tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return buffer; } @@ -857,7 +899,7 @@ static int ugswidth = UGSWIDTH; /* maximum width encountered so far */ #endif void -print_header (void) +print_header (off_t block_ordinal) { char modes[11]; char const *time_stamp; @@ -872,8 +914,12 @@ print_header (void) if (block_number_option) { char buf[UINTMAX_STRSIZE_BOUND]; + if (block_ordinal < 0) + block_ordinal = current_block_ordinal (); + block_ordinal -= recent_long_name_blocks; + block_ordinal -= recent_long_link_blocks; fprintf (stdlis, _("block %s: "), - STRINGIFY_BIGINT (current_block_ordinal (), buf)); + STRINGIFY_BIGINT (block_ordinal, buf)); } if (verbose_option <= 1) @@ -902,17 +948,20 @@ print_header (void) case GNUTYPE_LONGNAME: case GNUTYPE_LONGLINK: + modes[0] = 'L'; ERROR ((0, 0, _("Visible longname error"))); break; case GNUTYPE_SPARSE: case REGTYPE: case AREGTYPE: - case LNKTYPE: modes[0] = '-'; if (current_file_name[strlen (current_file_name) - 1] == '/') modes[0] = 'd'; break; + case LNKTYPE: + modes[0] = 'h'; + break; case GNUTYPE_DUMPDIR: modes[0] = 'd'; break; @@ -1055,6 +1104,14 @@ print_header (void) putc ('\n', stdlis); break; + case GNUTYPE_LONGLINK: + fprintf (stdlis, _("--Long Link--\n")); + break; + + case GNUTYPE_LONGNAME: + fprintf (stdlis, _("--Long Name--\n")); + break; + case GNUTYPE_VOLHDR: fprintf (stdlis, _("--Volume Header--\n")); break;