From 3477e4e33fb83a721ba274e49df9c2c92e4c953d Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sun, 21 Feb 2016 12:34:57 -0800 Subject: [PATCH] Fix for issue #623. 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 ") * 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. --- libarchive/archive_write_set_format_pax.c | 37 ++++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/libarchive/archive_write_set_format_pax.c b/libarchive/archive_write_set_format_pax.c index 687f8e48a..6f7fe7839 100644 --- a/libarchive/archive_write_set_format_pax.c +++ b/libarchive/archive_write_set_format_pax.c @@ -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", @@ -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); -- 2.47.2