Fix listing of volume labels (in particular in PAX archives).
* 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.
This commit is contained in:
105
src/xheader.c
105
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 }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user