* src/buffer.c (match_volume_label): Call set_volume_label.
(check_label_pattern): Get label string
as argument.
(match_volume_label): Handle volume labels stored in
global PAX headers.
* src/common.c (print_header,read_header): Change signature.
(read_header_primitive): Remove prototype.
* src/list.c (recent_global_header): New static.
(list_archive): Always print volume labels.
(read_header_primitive): Remove.
(read_header): Change the signature (all callers updated)
Save the recent global header.
(volume_label_printed): New static.
(simple_print_header): New function (ex-print_header).
(print_header): Change the signature (all callers updated).
For POSIX formats, print first volume header (if set).
* src/xheader.c (xheader_write_global): Write the data
accumulated in xhdr->stk even if keyword_global_override_list
is empty.
(xheader_read): On unexpected EOF, report error instead of
coredumping.
(XHDR_PROTECTED, XHDR_GLOBAL): New defines.
(struct xhdr_tab): Remove `protected' with `flags'. All uses updated.
(decg): If XHDR_GLOBAL bit is set, call the keyword's decode
method instead of adding it to `kwl'.
* src/compare.c: Update calls to read_header.
* src/create.c: Likewise.
* src/delete.c: Likewise.
* src/update.c: Likewise.
* src/extract.c: Likewise.
(extract_volhdr): Do not print "Reading <label>" statement, because
it is inconsistent: it is not printed if the volume begins with a
member continued from the previous volume.
* tests/label01.at: New testcase.
* tests/label02.at: New testcase.
* tests/Makefile.am, tests/testsuite.at: Add new testcases.
/* 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.
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);
}
\f
-/* 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)
+ 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;
}
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)));
}
/* 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
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;
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 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.
{
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)
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)
{
{
counter++;
set_next_block_after (current_header);
- status = read_header (false);
+ status = read_header (¤t_header, ¤t_stat_info,
+ false);
}
while (status == HEADER_FAILURE);
{
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,
/* 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.
&& 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);
/* 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
do
{
- enum read_header status = read_header (true);
+ enum read_header status = read_header (¤t_header,
+ ¤t_stat_info,
+ true);
switch (status)
{
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);
/* 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.
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;
}
/* 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.
/* 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.
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);
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:
{
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,
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)
{
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;
enum read_header status;
header = find_next_block ();
- current_header = header;
+ *return_block = header;
if (!header)
return HEADER_END_OF_FILE;
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));
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)
}
}
-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)
{
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
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;
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)
/* 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;
/* 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);
else
{
sprintf (uform, "%ld",
- (long) UID_FROM_HEADER (current_header->header.uid));
+ (long) UID_FROM_HEADER (blk->header.uid));
user = uform;
}
}
/* 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);
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:
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));
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));
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;
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)
/* 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
while (!found_end)
{
- enum read_header status = read_header (false);
+ enum read_header status = read_header (¤t_header,
+ ¤t_stat_info, false);
switch (status)
{
/* 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
void
xheader_write_global (struct xheader *xhdr)
{
- char *name;
- struct keyword_list *kp;
-
- if (!keyword_global_override_list)
- return;
+ if (keyword_global_override_list)
+ {
+ struct keyword_list *kp;
- 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);
+ }
}
\f
/* 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
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;
}
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;
}
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
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);
}
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.
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 }
};
incr06.at\
indexfile.at\
ignfail.at\
+ label01.at\
+ label02.at\
link01.at\
link02.at\
link03.at\
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+
+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
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+
+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
m4_include([extrac07.at])
m4_include([extrac08.at])
+m4_include([label01.at])
+m4_include([label02.at])
+
m4_include([backup01.at])
m4_include([gzip.at])