]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix for issue #623.
authorTim Kientzle <kientzle@acm.org>
Sun, 21 Feb 2016 20:34:57 +0000 (12:34 -0800)
committerTim Kientzle <kientzle@acm.org>
Sun, 21 Feb 2016 20:34:57 +0000 (12:34 -0800)
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.

libarchive/archive_write_set_format_pax.c

index 687f8e48a9b790c9b9944fb698440c2974a927cb..6f7fe7839001deef476142456cafda2927d08443 100644 (file)
@@ -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);