Selaa lähdekoodia

Merge pull request #7235 from ThomasWaldmann/macos-resourcefork-mtime-1.2

extract: fix mtime when ResourceFork xattr is set (macOS specific)
TW 2 vuotta sitten
vanhempi
sitoutus
32b5f44bbb
2 muutettua tiedostoa jossa 33 lisäystä ja 9 poistoa
  1. 9 8
      src/borg/archive.py
  2. 24 1
      src/borg/testsuite/archiver.py

+ 9 - 8
src/borg/archive.py

@@ -913,6 +913,15 @@ Utilization of max. archive size: {csize_max:.0%}
                 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:
+                # 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.get('xattrs', {}), follow_symlinks=False)
+                if warning:
+                    set_ec(EXIT_WARNING)
+            # set timestamps rather late
             mtime = item.mtime
             if 'atime' in item:
                 atime = item.atime
@@ -939,14 +948,6 @@ Utilization of max. archive size: {csize_max:.0%}
             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:
-                # 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.get('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:

+ 24 - 1
src/borg/testsuite/archiver.py

@@ -56,7 +56,7 @@ from ..repository import Repository
 from . import has_lchflags, llfuse
 from . import BaseTestCase, changedir, environment_variable, no_selinux
 from . import are_symlinks_supported, are_hardlinks_supported, are_fifos_supported, is_utime_fully_supported, is_birthtime_fully_supported
-from .platform import fakeroot_detected
+from .platform import fakeroot_detected, is_darwin
 from .upgrader import make_attic_repo
 from . import key
 
@@ -1424,6 +1424,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('init', self.repository_location, '-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('create', self.repository_location + '::test', 'input')
+        with changedir('output'):
+            self.cmd('extract', self.repository_location + '::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_path_normalization(self):
         self.cmd('init', '--encryption=repokey', self.repository_location)
         self.create_regular_file('dir1/dir2/file', size=1024 * 80)