From c095e2ef6189040390a6285faa4ea7e05952164f Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 29 Dec 2022 23:28:15 +0100 Subject: [PATCH 1/2] macOS: test correct timestamp extraction if ResourceFork xattr is present, see #7234 --- src/borg/testsuite/archiver.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py index e4f293be0..22cf71754 100644 --- a/src/borg/testsuite/archiver.py +++ b/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) From b96781b9ddcb6e5531c3fdb1ff6c2c5ace1db425 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 29 Dec 2022 23:53:10 +0100 Subject: [PATCH 2/2] macOS: fix mtime timestamp extraction if ResourceFork xattr is present, fixes #7234 setting the timestamps after xattrs helps for correct mtime, but atime is still broken in this case. --- src/borg/archive.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index f1da994de..44b92c04c 100644 --- a/src/borg/archive.py +++ b/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: