Browse Source

Merge pull request #7243 from ThomasWaldmann/macos-resourcefork-mtime-master

extract: fix mtime when ResourceFork xattr is set (macOS specific)
TW 2 years ago
parent
commit
daf890ebfa
2 changed files with 32 additions and 8 deletions
  1. 9 8
      src/borg/archive.py
  2. 23 0
      src/borg/testsuite/archiver/extract_cmd.py

+ 9 - 8
src/borg/archive.py

@@ -951,6 +951,15 @@ Duration: {0.duration}
                 except NotImplementedError:
                     if not symlink:
                         os.chmod(path, item.mode)
+            if not self.noacls:
+                acl_set(path, item, self.numeric_ids, fd=fd)
+            if not self.noxattrs and "xattrs" in item:
+                # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include
+                # the Linux capabilities in the "security.capability" attribute.
+                warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
+                if warning:
+                    set_ec(EXIT_WARNING)
+            # set timestamps rather late
             mtime = item.mtime
             atime = item.atime if "atime" in item else mtime
             if "birthtime" in item:
@@ -973,14 +982,6 @@ Duration: {0.duration}
             except OSError:
                 # some systems don't support calling utime on a symlink
                 pass
-            if not self.noacls:
-                acl_set(path, item, self.numeric_ids, fd=fd)
-            if not self.noxattrs and "xattrs" in item:
-                # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include
-                # the Linux capabilities in the "security.capability" attribute.
-                warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
-                if warning:
-                    set_ec(EXIT_WARNING)
             # bsdflags include the immutable flag and need to be set last:
             if not self.noflags and "bsdflags" in item:
                 try:

+ 23 - 0
src/borg/testsuite/archiver/extract_cmd.py

@@ -488,6 +488,29 @@ class ArchiverTestCase(ArchiverTestCaseBase):
                 assert "when setting extended attribute user.attribute" in out
             assert os.path.isfile(input_abspath)
 
+    @pytest.mark.skipif(not is_darwin, reason="only for macOS")
+    def test_extract_xattrs_resourcefork(self):
+        self.create_regular_file("file")
+        self.cmd(f"--repo={self.repository_location}", "rcreate", "-e" "none")
+        input_path = os.path.abspath("input/file")
+        xa_key, xa_value = b"com.apple.ResourceFork", b"whatshouldbehere"  # issue #7234
+        xattr.setxattr(input_path.encode(), xa_key, xa_value)
+        birthtime_expected = os.stat(input_path).st_birthtime
+        mtime_expected = os.stat(input_path).st_mtime_ns
+        # atime_expected = os.stat(input_path).st_atime_ns
+        self.cmd(f"--repo={self.repository_location}", "create", "test", "input")
+        with changedir("output"):
+            self.cmd(f"--repo={self.repository_location}", "extract", "test")
+            extracted_path = os.path.abspath("input/file")
+            birthtime_extracted = os.stat(extracted_path).st_birthtime
+            mtime_extracted = os.stat(extracted_path).st_mtime_ns
+            # atime_extracted = os.stat(extracted_path).st_atime_ns
+            xa_value_extracted = xattr.getxattr(extracted_path.encode(), xa_key)
+        assert xa_value_extracted == xa_value
+        assert birthtime_extracted == birthtime_expected
+        assert mtime_extracted == mtime_expected
+        # assert atime_extracted == atime_expected  # still broken, but not really important.
+
     def test_overwrite(self):
         self.create_regular_file("file1", size=1024 * 80)
         self.create_regular_file("dir2/file2", size=1024 * 80)