summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2008-01-31 07:41:45 +0000
committerkientzle <kientzle@FreeBSD.org>2008-01-31 07:41:45 +0000
commit512df3b205d7ab93a9a868315d0eafb9347cad28 (patch)
tree4b3908978d72efd82e7e7724533a0848936f23d6 /lib
parent54c503ac15e94c6380c1761dc00a214d1393d9b2 (diff)
downloadFreeBSD-src-512df3b205d7ab93a9a868315d0eafb9347cad28.zip
FreeBSD-src-512df3b205d7ab93a9a868315d0eafb9347cad28.tar.gz
Tighten up the heuristic that decides whether or not we should
obey or ignore the size field on a hardlink entry. In particular, if we're reading a non-POSIX archive, we should always ignore the size field. This should fix both the audio/xmcd port and the math/unixstat port. Thanks to: Pav Lucistnik for pointing these two ports out to me. MFC after: 7 days
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c
index cda113b..9cfe0e7 100644
--- a/lib/libarchive/archive_read_support_format_tar.c
+++ b/lib/libarchive/archive_read_support_format_tar.c
@@ -943,30 +943,46 @@ header_common(struct archive_read *a, struct tar *tar,
* A tricky point: Traditionally, tar readers have
* ignored the size field when reading hardlink
* entries, and some writers put non-zero sizes even
- * though the body is empty. POSIX.1-2001 broke with
- * this tradition by permitting hardlink entries to
- * store valid bodies in pax interchange format, but
- * not in ustar format. Since there is no hard and
- * fast way to distinguish pax interchange from
- * earlier archives (the 'x' and 'g' entries are
- * optional, after all), we need a heuristic. Here, I
- * use the bid function to test whether or not there's
- * a valid header following. Of course, if we know
- * this is pax interchange format, then we must obey
- * the size.
- *
- * This heuristic will only fail for a pax interchange
- * archive that is storing hardlink bodies, no pax
- * extended attribute entries have yet occurred, and
- * we encounter a hardlink entry for a file that is
- * itself an uncompressed tar archive.
+ * though the body is empty. POSIX blessed this
+ * convention in the 1988 standard, but broke with
+ * this tradition in 2001 by permitting hardlink
+ * entries to store valid bodies in pax interchange
+ * format, but not in ustar format. Since there is no
+ * hard and fast way to distinguish pax interchange
+ * from earlier archives (the 'x' and 'g' entries are
+ * optional, after all), we need a heuristic.
*/
- if (archive_entry_size(entry) > 0 &&
- a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
- archive_read_format_tar_bid(a) > 50) {
+ if (archive_entry_size(entry) == 0) {
+ /* If the size is already zero, we're done. */
+ } else if (a->archive.archive_format
+ == ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) {
+ /* Definitely pax extended; must obey hardlink size. */
+ } else if (a->archive.archive_format == ARCHIVE_FORMAT_TAR
+ || a->archive.archive_format == ARCHIVE_FORMAT_TAR_GNUTAR)
+ {
+ /* Old-style or GNU tar: we must ignore the size. */
+ archive_entry_set_size(entry, 0);
+ tar->entry_bytes_remaining = 0;
+ } else if (archive_read_format_tar_bid(a) > 50) {
+ /*
+ * We don't know if it's pax: If the bid
+ * function sees a valid ustar header
+ * immediately following, then let's ignore
+ * the hardlink size.
+ */
archive_entry_set_size(entry, 0);
tar->entry_bytes_remaining = 0;
}
+ /*
+ * TODO: There are still two cases I'd like to handle:
+ * = a ustar non-pax archive with a hardlink entry at
+ * end-of-archive. (Look for block of nulls following?)
+ * = a pax archive that has not seen any pax headers
+ * and has an entry which is a hardlink entry storing
+ * a body containing an uncompressed tar archive.
+ * The first is worth addressing; I don't see any reliable
+ * way to deal with the second possibility.
+ */
break;
case '2': /* Symlink */
archive_entry_set_filetype(entry, AE_IFLNK);
OpenPOWER on IntegriCloud