Refine the heuristic used to determine whether or not to obey

the size field for a hardlink entry.  Specifically, ensure that
we do obey the size field for archives that we know are pax interchange
format archives, as required by POSIX.

Also, clarify the comment explaining why this is necessary and explain
the (very unusual) conditions under which it might fail.
This commit is contained in:
Tim Kientzle 2004-05-19 06:35:47 +00:00
parent ab203c2d8c
commit 44c46f7978

View File

@ -593,21 +593,32 @@ header_common(struct archive *a, struct tar *tar, struct archive_entry *entry,
*/
if (st->st_size > 0)
st->st_mode |= S_IFREG;
/*
* A tricky point: Traditionally, tar programs have
* A tricky point: Traditionally, tar readers have
* ignored the size field when reading hardlink
* entries. As a result, some programs write non-zero
* sizes, even though the body is empty and expect the
* reader to ignore that. POSIX.1-2001 broke this by
* permitting hardlink entries to store valid bodies
* in pax interchange format. Since there is no hard
* and fast way to distinguish pax interchange from
* 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.
* 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.
*/
if (st->st_size > 0 && archive_read_format_tar_bid(a) > 50)
if (st->st_size > 0 &&
a->archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
archive_read_format_tar_bid(a) > 50)
st->st_size = 0;
break;
case '2': /* Symlink */