summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2001-09-22 00:47:09 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2001-09-22 00:47:09 +0000
commit85f651c8c69c45c2df5ea6d9bd8efb3b6c28584f (patch)
treebd112edd28c4abbccd8613d17f6098b225b4634e
parent6c9e824ce52554abd04bf4c7f8e20485ccbe2dc4 (diff)
downloadtar-85f651c8c69c45c2df5ea6d9bd8efb3b6c28584f.tar.gz
(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.
-rw-r--r--src/list.c80
1 files changed, 55 insertions, 25 deletions
diff --git a/src/list.c b/src/list.c
index 1c75808a..8169a796 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 = &current_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 (&current_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 (&current_link_name, name);
- if (next_long_link)
- {
- free (next_long_link);
- next_long_link = 0;
- }
return HEADER_SUCCESS;
}