|
@@ -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)
|
|
|
- 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
/* 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 }
|
|
|
};
|