Skip to content

Commit e79c02b

Browse files
fuse: we need the binary ACL representation
1 parent 154359c commit e79c02b

File tree

6 files changed

+42
-7
lines changed

6 files changed

+42
-7
lines changed

src/borg/fuse.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def async_wrapper(fn):
4444
from .helpers import msgpack
4545
from .helpers.lrucache import LRUCache
4646
from .item import Item
47-
from .platform import uid2user, gid2group
47+
from .platform import uid2user, gid2group, get_binary_acl
4848
from .platformflags import is_darwin
4949
from .repository import Repository
5050
from .remote import RemoteRepository
@@ -642,9 +642,9 @@ def getxattr(self, inode, name, ctx=None):
642642
item = self.get_item(inode)
643643
try:
644644
if name == b"system.posix_acl_access":
645-
return item["acl_access"]
645+
return get_binary_acl(item, "acl_access", self.numeric_ids)
646646
elif name == b"system.posix_acl_default":
647-
return item["acl_default"]
647+
return get_binary_acl(item, "acl_default", self.numeric_ids)
648648
else:
649649
return item.get("xattrs", {})[name] or b""
650650
except KeyError:

src/borg/platform/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
if is_linux: # pragma: linux only
1414
from .linux import API_VERSION as OS_API_VERSION
1515
from .linux import listxattr, getxattr, setxattr
16-
from .linux import acl_get, acl_set
16+
from .linux import acl_get, acl_set, get_binary_acl
1717
from .linux import set_flags, get_flags
1818
from .linux import SyncFile
1919
from .posix import process_alive, local_pid_alive
@@ -23,7 +23,7 @@
2323
elif is_freebsd: # pragma: freebsd only
2424
from .freebsd import API_VERSION as OS_API_VERSION
2525
from .freebsd import listxattr, getxattr, setxattr
26-
from .freebsd import acl_get, acl_set
26+
from .freebsd import acl_get, acl_set, get_binary_acl
2727
from .base import set_flags, get_flags
2828
from .base import SyncFile
2929
from .posix import process_alive, local_pid_alive
@@ -33,7 +33,7 @@
3333
elif is_darwin: # pragma: darwin only
3434
from .darwin import API_VERSION as OS_API_VERSION
3535
from .darwin import listxattr, getxattr, setxattr
36-
from .darwin import acl_get, acl_set
36+
from .darwin import acl_get, acl_set, get_binary_acl
3737
from .darwin import is_darwin_feature_64_bit_inode, _get_birthtime_ns
3838
from .base import set_flags, get_flags
3939
from .base import SyncFile
@@ -45,7 +45,7 @@
4545
# generic stuff for all other posix OSes
4646
OS_API_VERSION = API_VERSION
4747
from .base import listxattr, getxattr, setxattr
48-
from .base import acl_get, acl_set
48+
from .base import acl_get, acl_set, get_binary_acl
4949
from .base import set_flags, get_flags
5050
from .base import SyncFile
5151
from .posix import process_alive, local_pid_alive

src/borg/platform/base.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ def acl_set(path, item, numeric_ids=False, fd=None):
8181
"""
8282

8383

84+
def get_binary_acl(item, key, numeric_ids=False):
85+
"""
86+
Get binary ACL data for item and key (acl name).
87+
"""
88+
raise KeyError(key)
89+
90+
8491
try:
8592
from os import lchflags # type: ignore[attr-defined]
8693

src/borg/platform/darwin.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ from libc cimport errno
55
from posix.time cimport timespec
66

77
from .posix import user2uid, group2gid
8+
from .base import get_binary_acl # dummy
89
from ..helpers import safe_decode, safe_encode
910
from .xattr import _listxattr_inner, _getxattr_inner, _setxattr_inner, split_string0
1011

src/borg/platform/freebsd.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import stat
44
from libc cimport errno
55

66
from .posix import posix_acl_use_stored_uid_gid
7+
from .base import get_binary_acl # dummy
78
from ..helpers import safe_encode, safe_decode
89
from .xattr import _listxattr_inner, _getxattr_inner, _setxattr_inner, split_lstring
910

src/borg/platform/linux.pyx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from cpython.bytes cimport PyBytes_FromStringAndSize
2+
13
import os
24
import re
35
import stat
@@ -48,6 +50,7 @@ cdef extern from "sys/acl.h":
4850
int acl_set_fd(int fd, acl_t acl)
4951
acl_t acl_from_text(const char *buf)
5052
char *acl_to_text(acl_t acl, ssize_t *len)
53+
ssize_t acl_size(acl_t)
5154

5255
cdef extern from "acl/libacl.h":
5356
int acl_extended_file_nofollow(const char *path)
@@ -321,6 +324,29 @@ def acl_set(path, item, numeric_ids=False, fd=None):
321324
acl_free(default_acl)
322325

323326

327+
def get_binary_acl(item, key, numeric_ids=False):
328+
assert key in ("acl_access", "acl_default")
329+
cdef acl_t acl = NULL
330+
cdef ssize_t size
331+
332+
if numeric_ids:
333+
converter = posix_acl_use_stored_uid_gid
334+
else:
335+
converter = acl_use_local_uid_gid
336+
acl_text = item[key]
337+
try:
338+
acl = acl_from_text(<bytes>converter(acl_text))
339+
if acl == NULL:
340+
raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(item.path))
341+
size = acl_size(acl)
342+
if size < 0:
343+
raise OSError(errno.errno, "Failed to get ACL size")
344+
# Create a bytes object from the ACL data structure:
345+
return PyBytes_FromStringAndSize(<char *> acl, size)
346+
finally:
347+
acl_free(acl)
348+
349+
324350
cdef _sync_file_range(fd, offset, length, flags):
325351
assert offset & PAGE_MASK == 0, "offset %d not page-aligned" % offset
326352
assert length & PAGE_MASK == 0, "length %d not page-aligned" % length

0 commit comments

Comments
 (0)