Skip to content

Commit

Permalink
Fix for issue #623.
Browse files Browse the repository at this point in the history
Apparently, people have come to expect that the following
is sufficient to get bit-for-bit identical output from tar:
   * Same filenames
   * Same contents
   * Same uid, gid
   * Same mtime (forced via "touch -t <timestamp>")
   * Sorting entries

Bsdtar's "restricted pax" format violated this by including
ctime, atime, and birthtime (which are not updated by
'touch -t).  So we should only emit those additional time
values in the full pax format.

People who are really serious about generating bit-for-bit
identical archives should really build their own command-line
interface: You can still use libarchive to build the output,
but your custom CLI could sort the entries and strip everything
except a bare minimum of basic metadata.
  • Loading branch information
kientzle committed Feb 21, 2016
1 parent 37649d2 commit 3477e4e
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions libarchive/archive_write_set_format_pax.c
Expand Up @@ -1036,22 +1036,12 @@ archive_write_pax_header(struct archive_write *a,
need_extension = 1;

/*
* The following items are handled differently in "pax
* restricted" format. In particular, in "pax restricted"
* format they won't be added unless need_extension is
* already set (we're already generating an extended header, so
* may as well include these).
* Libarchive used to include these in extended headers for
* restricted pax format, but that confused people who
* expected ustar-like time semantics. So now we only include
* them in full pax format.
*/
if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
need_extension) {

if (archive_entry_mtime(entry_main) < 0 ||
archive_entry_mtime(entry_main) >= 0x7fffffff ||
archive_entry_mtime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "mtime",
archive_entry_mtime(entry_main),
archive_entry_mtime_nsec(entry_main));

if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED) {
if (archive_entry_ctime(entry_main) != 0 ||
archive_entry_ctime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "ctime",
Expand All @@ -1072,6 +1062,23 @@ archive_write_pax_header(struct archive_write *a,
"LIBARCHIVE.creationtime",
archive_entry_birthtime(entry_main),
archive_entry_birthtime_nsec(entry_main));
}

/*
* The following items are handled differently in "pax
* restricted" format. In particular, in "pax restricted"
* format they won't be added unless need_extension is
* already set (we're already generating an extended header, so
* may as well include these).
*/
if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
need_extension) {
if (archive_entry_mtime(entry_main) < 0 ||
archive_entry_mtime(entry_main) >= 0x7fffffff ||
archive_entry_mtime_nsec(entry_main) != 0)
add_pax_attr_time(&(pax->pax_header), "mtime",
archive_entry_mtime(entry_main),
archive_entry_mtime_nsec(entry_main));

/* I use a star-compatible file flag attribute. */
p = archive_entry_fflags_text(entry_main);
Expand Down

0 comments on commit 3477e4e

Please sign in to comment.