]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Thanks to Xavier for pointing out that the security.capability xattr
authorTim Kientzle <kientzle@gmail.com>
Sun, 8 Nov 2009 07:06:02 +0000 (02:06 -0500)
committerTim Kientzle <kientzle@gmail.com>
Sun, 8 Nov 2009 07:06:02 +0000 (02:06 -0500)
on Linux must be restored last.  Let's try moving xattr restore to
after file data and see if that works any better; we may end up having
to do a full xattr restore both before and after the file data.

This also changes the behavior of xattr restore failures; they now
cause warnings when the entry is finished (which can be as late as
archive_write_close()) rather than when the header is written.

SVN-Revision: 1590

libarchive/archive_write_disk.c
libarchive/test/test_extattr_freebsd.c

index 7722196579ae48ac9100788595363412bd3a050a..b824cc9e7da930c742b03e86cc437d3f9df65c61 100644 (file)
@@ -442,15 +442,14 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
        ret = restore_entry(a);
 
        /*
-        * On the GNU tar mailing list, some people working with new
-        * Linux filesystems observed that system xattrs used as
-        * layout hints need to be restored before the file contents
-        * are written, so this can't be done at file close.
+        * TODO: There are rumours that some extended attributes must
+        * be restored before file data is written.  If this is true,
+        * then we either need to write all extended attributes both
+        * before and after restoring the data, or find some rule for
+        * determining which must go first and which last.  Due to the
+        * many ways people are using xattrs, this may prove to be an
+        * intractable problem.
         */
-       if (a->todo & TODO_XATTR) {
-               int r2 = set_xattrs(a);
-               if (r2 < ret) ret = r2;
-       }
 
 #ifdef HAVE_FCHDIR
        /* If we changed directory above, restore it here. */
@@ -754,6 +753,17 @@ _archive_write_finish_entry(struct archive *_a)
                int r2 = set_acls(a);
                if (r2 < ret) ret = r2;
        }
+
+       /*
+        * Security-related extended attributes (such as
+        * security.capability on Linux) have to be restored last,
+        * since they're implicitly removed by other file changes.
+        */
+       if (a->todo & TODO_XATTR) {
+               int r2 = set_xattrs(a);
+               if (r2 < ret) ret = r2;
+       }
+
        /*
         * Some flags prevent file modification; they must be restored after
         * file contents are written.
index 8b8cc7e6eac2c6a4637f501fa4cc2a08f79d088b..de3ae2a586d18cb2f4029d0f8d1dd1ada17a089b 100644 (file)
@@ -114,17 +114,15 @@ DEFINE_TEST(test_extattr_freebsd)
        archive_entry_set_size(ae, 0);
        archive_entry_set_mode(ae, 0);
        archive_entry_xattr_add_entry(ae, "user.bar", "123456", 6);
-       if (extattr_privilege_bug)
-               /* If the bug is here, write_header will return warning. */
-               assertEqualIntA(a, ARCHIVE_WARN,
-                   archive_write_header(a, ae));
-       else
-               assertEqualIntA(a, ARCHIVE_OK,
-                   archive_write_header(a, ae));
+       assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
        archive_entry_free(ae);
 
        /* Close the archive. */
-       assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
+       if (extattr_privilege_bug)
+               /* If the bug is here, write_close will return warning. */
+               assertEqualIntA(a, ARCHIVE_WARN, archive_write_close(a));
+       else
+               assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
        assertEqualInt(ARCHIVE_OK, archive_write_finish(a));
 
        /* Verify the data on disk. */