diff --git a/src/buffer.c b/src/buffer.c
index 613a7e84..ed753034 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,7 +1,8 @@
/* Buffer management for tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+ Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
@@ -1167,7 +1168,7 @@ read_header0 (struct tar_stat_info *info)
enum read_header rc;
tar_stat_init (info);
- rc = read_header_primitive (false, info);
+ rc = read_header (¤t_header, info, false);
if (rc == HEADER_SUCCESS)
{
set_next_block_after (current_header);
@@ -1312,20 +1313,17 @@ try_new_volume ()
}
-/* Check the LABEL block against the volume label, seen as a globbing
+/* Check LABEL against the volume label, seen as a globbing
pattern. Return true if the pattern matches. In case of failure,
retry matching a volume sequence number before giving up in
multi-volume mode. */
static bool
-check_label_pattern (union block *label)
+check_label_pattern (const char *label)
{
char *string;
bool result;
- if (! memchr (label->header.name, '\0', sizeof label->header.name))
- return false;
-
- if (fnmatch (volume_label_option, label->header.name, 0) == 0)
+ if (fnmatch (volume_label_option, label, 0) == 0)
return true;
if (!multi_volume_option)
@@ -1335,7 +1333,7 @@ check_label_pattern (union block *label)
+ sizeof VOLUME_LABEL_APPEND + 1);
strcpy (string, volume_label_option);
strcat (string, VOLUME_LABEL_APPEND);
- result = fnmatch (string, label->header.name, 0) == 0;
+ result = fnmatch (string, label, 0) == 0;
free (string);
return result;
}
@@ -1345,14 +1343,43 @@ check_label_pattern (union block *label)
static void
match_volume_label (void)
{
- union block *label = find_next_block ();
-
- if (!label)
+ if (!volume_label)
+ {
+ union block *label = find_next_block ();
+
+ if (!label)
+ FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
+ quote (volume_label_option)));
+ if (label->header.typeflag == GNUTYPE_VOLHDR)
+ {
+ if (memchr (label->header.name, '\0', sizeof label->header.name))
+ assign_string (&volume_label, label->header.name);
+ else
+ {
+ volume_label = xmalloc (sizeof (label->header.name) + 1);
+ memcpy (volume_label, label->header.name,
+ sizeof (label->header.name));
+ volume_label[sizeof (label->header.name)] = 0;
+ }
+ }
+ else if (label->header.typeflag == XGLTYPE)
+ {
+ struct tar_stat_info st;
+ tar_stat_init (&st);
+ xheader_read (&st.xhdr, label,
+ OFF_FROM_HEADER (label->header.size));
+ xheader_decode (&st);
+ tar_stat_destroy (&st);
+ }
+ }
+
+ if (!volume_label)
FATAL_ERROR ((0, 0, _("Archive not labeled to match %s"),
quote (volume_label_option)));
- if (!check_label_pattern (label))
+
+ if (!check_label_pattern (volume_label))
FATAL_ERROR ((0, 0, _("Volume %s does not match %s"),
- quote_n (0, label->header.name),
+ quote_n (0, volume_label),
quote_n (1, volume_label_option)));
}
diff --git a/src/common.h b/src/common.h
index 360fb861..2af403c1 100644
--- a/src/common.h
+++ b/src/common.h
@@ -1,7 +1,8 @@
/* Common declarations for the tar program.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+ Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -396,6 +397,7 @@ extern enum access_mode access_mode;
extern FILE *stdlis;
extern bool write_archive_to_stdout;
extern char *volume_label;
+extern size_t volume_label_count;
extern char *continued_file_name;
extern uintmax_t continued_file_size;
extern uintmax_t continued_file_offset;
@@ -577,11 +579,12 @@ uintmax_t uintmax_from_header (const char *buf, size_t size);
void list_archive (void);
void print_for_mkdir (char *dirname, int length, mode_t mode);
-void print_header (struct tar_stat_info *st, off_t block_ordinal);
+void print_header (struct tar_stat_info *st, union block *blk,
+ off_t block_ordinal);
void read_and (void (*do_something) (void));
-enum read_header read_header_primitive (bool raw_extended_headers,
- struct tar_stat_info *info);
-enum read_header read_header (bool raw_extended_headers);
+enum read_header read_header (union block **return_block,
+ struct tar_stat_info *info,
+ bool raw_extended_headers);
enum read_header tar_checksum (union block *header, bool silent);
void skip_file (off_t size);
void skip_member (void);
diff --git a/src/compare.c b/src/compare.c
index cb1f3a8b..9385d409 100644
--- a/src/compare.c
+++ b/src/compare.c
@@ -1,7 +1,7 @@
/* Diff files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1987-04-30.
@@ -460,7 +460,7 @@ diff_archive (void)
{
if (now_verifying)
fprintf (stdlis, _("Verify "));
- print_header (¤t_stat_info, -1);
+ print_header (¤t_stat_info, current_header, -1);
}
switch (current_header->header.typeflag)
@@ -578,7 +578,8 @@ verify_volume (void)
flush_read ();
while (1)
{
- enum read_header status = read_header (false);
+ enum read_header status = read_header (¤t_header,
+ ¤t_stat_info, false);
if (status == HEADER_FAILURE)
{
@@ -588,7 +589,8 @@ verify_volume (void)
{
counter++;
set_next_block_after (current_header);
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info,
+ false);
}
while (status == HEADER_FAILURE);
@@ -606,7 +608,7 @@ verify_volume (void)
{
char buf[UINTMAX_STRSIZE_BOUND];
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info, false);
if (status == HEADER_ZERO_BLOCK)
break;
WARNOPT (WARN_ALONE_ZERO_BLOCK,
diff --git a/src/create.c b/src/create.c
index 8c66d9bc..748f2747 100644
--- a/src/create.c
+++ b/src/create.c
@@ -1,7 +1,7 @@
/* Create a tar archive.
Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-25.
@@ -996,11 +996,11 @@ finish_header (struct tar_stat_info *st,
&& header->header.typeflag != XHDTYPE
&& header->header.typeflag != XGLTYPE)
{
- /* These globals are parameters to print_header, sigh. */
+ /* FIXME: These globals are parameters to print_header, sigh. */
current_header = header;
current_format = archive_format;
- print_header (st, block_ordinal);
+ print_header (st, current_header, block_ordinal);
}
header = write_extended (false, st, header);
diff --git a/src/delete.c b/src/delete.c
index a67993cb..8f729ba2 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -1,7 +1,7 @@
/* Delete entries from a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 2000, 2001, 2003, 2004,
- 2005, 2006 Free Software Foundation, Inc.
+ 2005, 2006, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -165,7 +165,9 @@ delete_archive_members (void)
do
{
- enum read_header status = read_header (true);
+ enum read_header status = read_header (¤t_header,
+ ¤t_stat_info,
+ true);
switch (status)
{
@@ -260,7 +262,7 @@ delete_archive_members (void)
if (current_block == record_end)
flush_archive ();
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info, false);
xheader_decode (¤t_stat_info);
diff --git a/src/extract.c b/src/extract.c
index 5f12cf9a..32a883f6 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -1,7 +1,7 @@
/* Extract files from a tar archive.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-11-19.
@@ -1092,8 +1092,6 @@ extract_fifo (char *file_name, int typeflag)
static int
extract_volhdr (char *file_name, int typeflag)
{
- if (verbose_option)
- fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name));
skip_member ();
return 0;
}
@@ -1259,7 +1257,7 @@ extract_archive (void)
/* Print the block from current_header and current_stat. */
if (verbose_option)
- print_header (¤t_stat_info, -1);
+ print_header (¤t_stat_info, current_header, -1);
/* Restore stats for all non-ancestor directories, unless
it is an incremental archive.
diff --git a/src/list.c b/src/list.c
index bba430ad..3394e90d 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 (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2003, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc.
Written by John Gilmore, on 1985-08-26.
@@ -33,6 +33,7 @@ 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 */
+union block *recent_global_header; /* Recent global header block */
static uintmax_t from_header (const char *, size_t, const char *,
uintmax_t, uintmax_t, bool, bool);
@@ -77,7 +78,7 @@ read_and (void (*do_something) (void))
prev_status = status;
tar_stat_destroy (¤t_stat_info);
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info, false);
switch (status)
{
case HEADER_STILL_UNREAD:
@@ -138,7 +139,7 @@ read_and (void (*do_something) (void))
{
char buf[UINTMAX_STRSIZE_BOUND];
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info, false);
if (status == HEADER_ZERO_BLOCK)
break;
WARNOPT (WARN_ALONE_ZERO_BLOCK,
@@ -205,11 +206,12 @@ void
list_archive (void)
{
off_t block_ordinal = current_block_ordinal ();
- /* Print the header block. */
+ /* Print the header block. */
+
decode_header (current_header, ¤t_stat_info, ¤t_format, 0);
if (verbose_option)
- print_header (¤t_stat_info, block_ordinal);
+ print_header (¤t_stat_info, current_header, block_ordinal);
if (incremental_option)
{
@@ -293,7 +295,8 @@ tar_checksum (union block *header, bool silent)
the header which this routine reads. */
enum read_header
-read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
+read_header (union block **return_block, struct tar_stat_info *info,
+ bool raw_extended_headers)
{
union block *header;
union block *header_copy;
@@ -310,7 +313,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
enum read_header status;
header = find_next_block ();
- current_header = header;
+ *return_block = header;
if (!header)
return HEADER_END_OF_FILE;
@@ -392,6 +395,11 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else if (header->header.typeflag == XGLTYPE)
{
struct xheader xhdr;
+
+ if (!recent_global_header)
+ recent_global_header = xmalloc (sizeof *recent_global_header);
+ memcpy (recent_global_header, header,
+ sizeof *recent_global_header);
memset (&xhdr, 0, sizeof xhdr);
xheader_read (&xhdr, header,
OFF_FROM_HEADER (header->header.size));
@@ -405,7 +413,7 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
else
{
char const *name;
- struct posix_header const *h = ¤t_header->header;
+ struct posix_header const *h = &header->header;
char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
if (recent_long_name)
@@ -464,12 +472,6 @@ read_header_primitive (bool raw_extended_headers, struct tar_stat_info *info)
}
}
-enum read_header
-read_header (bool raw_extended_headers)
-{
- return read_header_primitive (raw_extended_headers, ¤t_stat_info);
-}
-
static char *
decode_xform (char *file_name, void *data)
{
@@ -1019,9 +1021,6 @@ tartime (struct timespec t, bool full_time)
they shouldn't. Unix tar is pretty random here anyway. */
-/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
- HEAD_STANDARD, which must be set up in advance. Not very clean.. */
-
/* Width of "user/group size", with initial value chosen
heuristically. This grows as needed, though this may cause some
stairstepping in the output. Make it too small and the output will
@@ -1034,8 +1033,11 @@ static int ugswidth = 19;
USGWIDTH, some stairstepping may occur. */
static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;
-void
-print_header (struct tar_stat_info *st, off_t block_ordinal)
+static bool volume_label_printed = false;
+
+static void
+simple_print_header (struct tar_stat_info *st, union block *blk,
+ off_t block_ordinal)
{
char modes[11];
char const *time_stamp;
@@ -1051,7 +1053,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
int pad;
int sizelen;
- if (test_label_option && current_header->header.typeflag != GNUTYPE_VOLHDR)
+ if (test_label_option && blk->header.typeflag != GNUTYPE_VOLHDR)
return;
if (show_transformed_names_option)
@@ -1080,9 +1082,10 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* File type and modes. */
modes[0] = '?';
- switch (current_header->header.typeflag)
+ switch (blk->header.typeflag)
{
case GNUTYPE_VOLHDR:
+ volume_label_printed = true;
modes[0] = 'V';
break;
@@ -1150,8 +1153,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
uid_t if that fails. This method can list positive user
ids that are too large to fit in a uid_t. */
- uintmax_t u = from_header (current_header->header.uid,
- sizeof current_header->header.uid, 0,
+ uintmax_t u = from_header (blk->header.uid,
+ sizeof blk->header.uid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
false, false);
@@ -1160,7 +1163,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
else
{
sprintf (uform, "%ld",
- (long) UID_FROM_HEADER (current_header->header.uid));
+ (long) UID_FROM_HEADER (blk->header.uid));
user = uform;
}
}
@@ -1175,8 +1178,8 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
/* Try parsing it as an unsigned integer first, and as a
gid_t if that fails. This method can list positive group
ids that are too large to fit in a gid_t. */
- uintmax_t g = from_header (current_header->header.gid,
- sizeof current_header->header.gid, 0,
+ uintmax_t g = from_header (blk->header.gid,
+ sizeof blk->header.gid, 0,
(uintmax_t) 0,
(uintmax_t) TYPE_MAXIMUM (uintmax_t),
false, false);
@@ -1185,14 +1188,14 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
else
{
sprintf (gform, "%ld",
- (long) GID_FROM_HEADER (current_header->header.gid));
+ (long) GID_FROM_HEADER (blk->header.gid));
group = gform;
}
}
/* Format the file size or major/minor device numbers. */
- switch (current_header->header.typeflag)
+ switch (blk->header.typeflag)
{
case CHRTYPE:
case BLKTYPE:
@@ -1222,7 +1225,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
fprintf (stdlis, " %s", quotearg (temp_name));
- switch (current_header->header.typeflag)
+ switch (blk->header.typeflag)
{
case SYMTYPE:
fprintf (stdlis, " -> %s\n", quotearg (st->link_name));
@@ -1235,7 +1238,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
default:
{
char type_string[2];
- type_string[0] = current_header->header.typeflag;
+ type_string[0] = blk->header.typeflag;
type_string[1] = '\0';
fprintf (stdlis, _(" unknown file type %s\n"),
quote (type_string));
@@ -1269,7 +1272,7 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
case GNUTYPE_MULTIVOL:
strcpy (size,
STRINGIFY_BIGINT
- (UINTMAX_FROM_HEADER (current_header->oldgnu_header.offset),
+ (UINTMAX_FROM_HEADER (blk->oldgnu_header.offset),
uintbuf));
fprintf (stdlis, _("--Continued at byte %s--\n"), size);
break;
@@ -1278,6 +1281,34 @@ print_header (struct tar_stat_info *st, off_t block_ordinal)
fflush (stdlis);
}
+
+void
+print_header (struct tar_stat_info *st, union block *blk,
+ off_t block_ordinal)
+{
+ if (current_format == POSIX_FORMAT && !volume_label_printed && volume_label)
+ {
+ struct tar_stat_info vstat;
+ union block vblk;
+ enum archive_format dummy;
+
+ volume_label_printed = true;
+
+ memset (&vblk, 0, sizeof (vblk));
+ vblk.header.typeflag = GNUTYPE_VOLHDR;
+ if (recent_global_header)
+ memcpy (vblk.header.mtime, recent_global_header->header.mtime,
+ sizeof vblk.header.mtime);
+ tar_stat_init (&vstat);
+ assign_string (&vstat.file_name, ".");
+ decode_header (&vblk, &vstat, &dummy, 0);
+ assign_string (&vstat.file_name, volume_label);
+ simple_print_header (&vstat, &vblk, block_ordinal);
+ tar_stat_destroy (&vstat);
+ }
+ simple_print_header (st, blk, block_ordinal);
+}
+
/* Print a similar line when we make a directory automatically. */
void
print_for_mkdir (char *dirname, int length, mode_t mode)
diff --git a/src/update.c b/src/update.c
index 0f5dadf7..468c6458 100644
--- a/src/update.c
+++ b/src/update.c
@@ -1,7 +1,7 @@
/* Update a tar archive.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003,
- 2004, 2005, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2007, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -114,7 +114,8 @@ update_archive (void)
while (!found_end)
{
- enum read_header status = read_header (false);
+ enum read_header status = read_header (¤t_header,
+ ¤t_stat_info, false);
switch (status)
{
diff --git a/src/xheader.c b/src/xheader.c
index 5eabdfb4..724837f6 100644
--- a/src/xheader.c
+++ b/src/xheader.c
@@ -1,6 +1,7 @@
/* POSIX extended headers for tar.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software
+ Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -440,30 +441,37 @@ xheader_write (char type, char *name, time_t t, struct xheader *xhdr)
void
xheader_write_global (struct xheader *xhdr)
{
- char *name;
- struct keyword_list *kp;
+ if (keyword_global_override_list)
+ {
+ struct keyword_list *kp;
- if (!keyword_global_override_list)
- return;
-
- xheader_init (xhdr);
- for (kp = keyword_global_override_list; kp; kp = kp->next)
- code_string (kp->value, kp->pattern, xhdr);
- xheader_finish (xhdr);
- xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), xhdr);
- free (name);
+ xheader_init (xhdr);
+ for (kp = keyword_global_override_list; kp; kp = kp->next)
+ code_string (kp->value, kp->pattern, xhdr);
+ }
+ if (xhdr->stk)
+ {
+ char *name;
+
+ xheader_finish (xhdr);
+ xheader_write (XGLTYPE, name = xheader_ghdr_name (), time (NULL), xhdr);
+ free (name);
+ }
}
/* General Interface */
+#define XHDR_PROTECTED 0x01
+#define XHDR_GLOBAL 0x02
+
struct xhdr_tab
{
char const *keyword;
void (*coder) (struct tar_stat_info const *, char const *,
struct xheader *, void const *data);
void (*decoder) (struct tar_stat_info *, char const *, char const *, size_t);
- bool protect;
+ int flags;
};
/* This declaration must be extern, because ISO C99 section 6.9.2
@@ -491,7 +499,7 @@ xheader_protected_pattern_p (const char *pattern)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
- if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
+ if ((p->flags & XHDR_PROTECTED) && fnmatch (pattern, p->keyword, 0) == 0)
return true;
return false;
}
@@ -502,7 +510,7 @@ xheader_protected_keyword_p (const char *keyword)
struct xhdr_tab const *p;
for (p = xhdr_tab; p->keyword; p++)
- if (p->protect && strcmp (p->keyword, keyword) == 0)
+ if ((p->flags & XHDR_PROTECTED) && strcmp (p->keyword, keyword) == 0)
return true;
return false;
}
@@ -633,7 +641,11 @@ decg (void *data, char const *keyword, char const *value,
size_t size __attribute__((unused)))
{
struct keyword_list **kwl = data;
- xheader_list_append (kwl, keyword, value);
+ struct xhdr_tab const *tab = locate_handler (keyword);
+ if (tab && (tab->flags & XHDR_GLOBAL))
+ tab->decoder (data, keyword, value, size);
+ else
+ xheader_list_append (kwl, keyword, value);
}
void
@@ -695,6 +707,9 @@ xheader_read (struct xheader *xhdr, union block *p, size_t size)
if (len > BLOCKSIZE)
len = BLOCKSIZE;
+ if (!p)
+ FATAL_ERROR ((0, 0, _("Unexpected EOF in archive")));
+
memcpy (&xhdr->buffer[j], p->buffer, len);
set_next_block_after (p);
@@ -1491,51 +1506,53 @@ sparse_minor_decoder (struct tar_stat_info *st,
}
struct xhdr_tab const xhdr_tab[] = {
- { "atime", atime_coder, atime_decoder, false },
- { "comment", dummy_coder, dummy_decoder, false },
- { "charset", dummy_coder, dummy_decoder, false },
- { "ctime", ctime_coder, ctime_decoder, false },
- { "gid", gid_coder, gid_decoder, false },
- { "gname", gname_coder, gname_decoder, false },
- { "linkpath", linkpath_coder, linkpath_decoder, false },
- { "mtime", mtime_coder, mtime_decoder, false },
- { "path", path_coder, path_decoder, false },
- { "size", size_coder, size_decoder, false },
- { "uid", uid_coder, uid_decoder, false },
- { "uname", uname_coder, uname_decoder, false },
+ { "atime", atime_coder, atime_decoder, 0 },
+ { "comment", dummy_coder, dummy_decoder, 0 },
+ { "charset", dummy_coder, dummy_decoder, 0 },
+ { "ctime", ctime_coder, ctime_decoder, 0 },
+ { "gid", gid_coder, gid_decoder, 0 },
+ { "gname", gname_coder, gname_decoder, 0 },
+ { "linkpath", linkpath_coder, linkpath_decoder, 0 },
+ { "mtime", mtime_coder, mtime_decoder, 0 },
+ { "path", path_coder, path_decoder, 0 },
+ { "size", size_coder, size_decoder, 0 },
+ { "uid", uid_coder, uid_decoder, 0 },
+ { "uname", uname_coder, uname_decoder, 0 },
/* Sparse file handling */
{ "GNU.sparse.name", path_coder, path_decoder,
- true },
+ XHDR_PROTECTED },
{ "GNU.sparse.major", sparse_major_coder, sparse_major_decoder,
- true },
+ XHDR_PROTECTED },
{ "GNU.sparse.minor", sparse_minor_coder, sparse_minor_decoder,
- true },
+ XHDR_PROTECTED },
{ "GNU.sparse.realsize", sparse_size_coder, sparse_size_decoder,
- true },
+ XHDR_PROTECTED },
{ "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
- true },
+ XHDR_PROTECTED },
/* tar 1.14 - 1.15.90 keywords. */
- { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
+ { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder,
+ XHDR_PROTECTED },
/* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
headers, and each of them was meaningful. It confilcted with POSIX specs,
which requires that "when extended header records conflict, the last one
given in the header shall take precedence." */
{ "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
- true },
+ XHDR_PROTECTED },
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
- true },
+ XHDR_PROTECTED },
/* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
{ "GNU.sparse.map", NULL /* Unused, see pax_dump_header() */,
- sparse_map_decoder, false },
+ sparse_map_decoder, 0 },
{ "GNU.dumpdir", dumpdir_coder, dumpdir_decoder,
- true },
+ XHDR_PROTECTED },
/* Keeps the tape/volume label. May be present only in the global headers.
Equivalent to GNUTYPE_VOLHDR. */
- { "GNU.volume.label", volume_label_coder, volume_label_decoder, true },
+ { "GNU.volume.label", volume_label_coder, volume_label_decoder,
+ XHDR_PROTECTED | XHDR_GLOBAL },
/* These may be present in a first global header of the archive.
They provide the same functionality as GNUTYPE_MULTIVOL header.
@@ -1544,9 +1561,11 @@ struct xhdr_tab const xhdr_tab[] = {
GNU.volume.offset keeps the offset of the start of this volume,
otherwise kept in oldgnu_header.offset. */
{ "GNU.volume.filename", volume_label_coder, volume_filename_decoder,
- true },
- { "GNU.volume.size", volume_size_coder, volume_size_decoder, true },
- { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, true },
+ XHDR_PROTECTED | XHDR_GLOBAL },
+ { "GNU.volume.size", volume_size_coder, volume_size_decoder,
+ XHDR_PROTECTED | XHDR_GLOBAL },
+ { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
+ XHDR_PROTECTED | XHDR_GLOBAL },
- { NULL, NULL, NULL, false }
+ { NULL, NULL, NULL, 0 }
};
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 006a6941..1b3b2c1b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -87,6 +87,8 @@ TESTSUITE_AT = \
incr06.at\
indexfile.at\
ignfail.at\
+ label01.at\
+ label02.at\
link01.at\
link02.at\
link03.at\
diff --git a/tests/label01.at b/tests/label01.at
new file mode 100644
index 00000000..933682b8
--- /dev/null
+++ b/tests/label01.at
@@ -0,0 +1,35 @@
+# Process this file with autom4te to create testsuite. -*- Autotest -*-
+
+# Test suite for GNU tar.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+AT_SETUP([single-volume label])
+AT_KEYWORDS([label label01])
+
+AT_TAR_CHECK([
+genfile --file foo
+genfile --file bar
+tar -cf archive --label=Test foo bar
+tar tf archive
+],
+[0],
+[Test
+foo
+bar
+],
+[],[],[],[gnu,oldgnu,posix])
+
+AT_CLEANUP
diff --git a/tests/label02.at b/tests/label02.at
new file mode 100644
index 00000000..3aa5ce71
--- /dev/null
+++ b/tests/label02.at
@@ -0,0 +1,38 @@
+# Process this file with autom4te to create testsuite. -*- Autotest -*-
+
+# Test suite for GNU tar.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+AT_SETUP([multi-volume label])
+AT_KEYWORDS([label label02 multi-label multivolume multiv])
+
+AT_TAR_CHECK([
+exec <&-
+genfile --length 0 --file foo
+genfile --length 12288 --file bar
+genfile --length 12288 --file baz
+tar --label=Test -cM -L10 -f 1.tar -f 2.tar -f 3.tar -f 4.tar foo bar baz
+tar -Mt -f 1.tar -f 2.tar -f 3.tar -f 4.tar
+],
+[0],
+[Test Volume 1
+foo
+bar
+baz
+],
+[],[],[],[gnu,oldgnu,posix])
+
+AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index b67d016b..6dbd6b3b 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -146,6 +146,9 @@ m4_include([extrac06.at])
m4_include([extrac07.at])
m4_include([extrac08.at])
+m4_include([label01.at])
+m4_include([label02.at])
+
m4_include([backup01.at])
m4_include([gzip.at])