diff --git a/src/borg/platform/freebsd.pyx b/src/borg/platform/freebsd.pyx index 0976f019d..1a7871235 100644 --- a/src/borg/platform/freebsd.pyx +++ b/src/borg/platform/freebsd.pyx @@ -51,43 +51,57 @@ cdef extern from "unistd.h": def listxattr(path, *, follow_symlinks=False): + ns, prefix = EXTATTR_NAMESPACE_USER, b'user.' + def func(path, buf, size): if isinstance(path, int): - return c_extattr_list_fd(path, EXTATTR_NAMESPACE_USER, buf, size) + return c_extattr_list_fd(path, ns, buf, size) else: if follow_symlinks: - return c_extattr_list_file(path, EXTATTR_NAMESPACE_USER, buf, size) + return c_extattr_list_file(path, ns, buf, size) else: - return c_extattr_list_link(path, EXTATTR_NAMESPACE_USER, buf, size) + return c_extattr_list_link(path, ns, buf, size) n, buf = _listxattr_inner(func, path) - return [name for name in split_lstring(buf[:n]) if name] + return [prefix + name for name in split_lstring(buf[:n]) if name] def getxattr(path, name, *, follow_symlinks=False): + ns, prefix = EXTATTR_NAMESPACE_USER, b'user.' + def func(path, name, buf, size): if isinstance(path, int): - return c_extattr_get_fd(path, EXTATTR_NAMESPACE_USER, name, buf, size) + return c_extattr_get_fd(path, ns, name, buf, size) else: if follow_symlinks: - return c_extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, buf, size) + return c_extattr_get_file(path, ns, name, buf, size) else: - return c_extattr_get_link(path, EXTATTR_NAMESPACE_USER, name, buf, size) + return c_extattr_get_link(path, ns, name, buf, size) + # strip namespace if there, but ignore if not there. + # older borg / attic versions did not prefix the namespace to the names. + if name.startswith(prefix): + name = name[len(prefix):] n, buf = _getxattr_inner(func, path, name) return bytes(buf[:n]) def setxattr(path, name, value, *, follow_symlinks=False): + ns, prefix = EXTATTR_NAMESPACE_USER, b'user.' + def func(path, name, value, size): if isinstance(path, int): - return c_extattr_set_fd(path, EXTATTR_NAMESPACE_USER, name, value, size) + return c_extattr_set_fd(path, ns, name, value, size) else: if follow_symlinks: - return c_extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, value, size) + return c_extattr_set_file(path, ns, name, value, size) else: - return c_extattr_set_link(path, EXTATTR_NAMESPACE_USER, name, value, size) + return c_extattr_set_link(path, ns, name, value, size) + # strip namespace if there, but ignore if not there. + # older borg / attic versions did not prefix the namespace to the names. + if name.startswith(prefix): + name = name[len(prefix):] _setxattr_inner(func, path, name, value) diff --git a/src/borg/testsuite/xattr.py b/src/borg/testsuite/xattr.py index 44d1d12db..17cd5421b 100644 --- a/src/borg/testsuite/xattr.py +++ b/src/borg/testsuite/xattr.py @@ -56,13 +56,13 @@ class XattrTestCase(BaseTestCase): tmp_fn = os.fsencode(self.tmpfile.name) # make it work even with ext4, which imposes rather low limits buffer.resize(size=64, init=True) - # xattr raw key list will be size 9 * (10 + 1), which is > 64 - keys = [b'user.attr%d' % i for i in range(9)] + # xattr raw key list will be > 64 + keys = [b'user.attr%d' % i for i in range(20)] for key in keys: setxattr(tmp_fn, key, b'x') got_keys = listxattr(tmp_fn) self.assert_equal_se(got_keys, keys) - self.assert_equal(len(buffer), 128) + self.assert_true(len(buffer) > 64) def test_getxattr_buffer_growth(self): tmp_fn = os.fsencode(self.tmpfile.name)