diff --git a/src/borg/platform/darwin.pyx b/src/borg/platform/darwin.pyx index 3a861aac6..bb7f8139b 100644 --- a/src/borg/platform/darwin.pyx +++ b/src/borg/platform/darwin.pyx @@ -1,6 +1,7 @@ import os from libc.stdint cimport uint32_t +from libc cimport errno from .posix import user2uid, group2gid from ..helpers import safe_decode, safe_encode @@ -121,7 +122,10 @@ def acl_get(path, item, st, numeric_ids=False, fd=None): else: acl = acl_get_link_np(path, ACL_TYPE_EXTENDED) if acl == NULL: - return + if errno.errno == errno.ENOENT: + # macOS weirdness: if a file has no ACLs, it sets errno to ENOENT. :-( + return + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) text = acl_to_text(acl, NULL) if text == NULL: return @@ -148,8 +152,10 @@ def acl_set(path, item, numeric_ids=False, fd=None): if isinstance(path, str): path = os.fsencode(path) if fd is not None: - acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) + if acl_set_fd_np(fd, acl, ACL_TYPE_EXTENDED) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) else: - acl_set_link_np(path, ACL_TYPE_EXTENDED, acl) + if acl_set_link_np(path, ACL_TYPE_EXTENDED, acl) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) finally: acl_free(acl) diff --git a/src/borg/platform/freebsd.pyx b/src/borg/platform/freebsd.pyx index 1c67de023..a2d431c11 100644 --- a/src/borg/platform/freebsd.pyx +++ b/src/borg/platform/freebsd.pyx @@ -4,11 +4,9 @@ from .posix import posix_acl_use_stored_uid_gid from ..helpers import safe_encode, safe_decode from .xattr import _listxattr_inner, _getxattr_inner, _setxattr_inner, split_lstring -API_VERSION = '1.4_01' +from libc cimport errno -cdef extern from "errno.h": - int errno - int EINVAL +API_VERSION = '1.4_01' cdef extern from "sys/extattr.h": ssize_t c_extattr_list_file "extattr_list_file" (const char *path, int attrnamespace, void *data, size_t nbytes) @@ -136,6 +134,8 @@ cdef _get_acl(p, type, item, attribute, flags, fd=None): item[attribute] = text acl_free(text) acl_free(acl) + else: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(p)) def acl_get(path, item, st, numeric_ids=False, fd=None): @@ -147,7 +147,7 @@ def acl_get(path, item, st, numeric_ids=False, fd=None): if isinstance(path, str): path = os.fsencode(path) ret = lpathconf(path, _PC_ACL_NFS4) - if ret < 0 and errno == EINVAL: + if ret < 0 and errno.errno == errno.EINVAL: return flags |= ACL_TEXT_NUMERIC_IDS if numeric_ids else 0 if ret > 0: @@ -167,11 +167,15 @@ cdef _set_acl(p, type, item, attribute, numeric_ids=False, fd=None): text = posix_acl_use_stored_uid_gid(text) acl = acl_from_text(text) if acl: - if fd is not None: - acl_set_fd_np(fd, acl, type) - else: - acl_set_link_np(p, type, acl) - acl_free(acl) + try: + if fd is not None: + if acl_set_fd_np(fd, acl, type) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(p)) + else: + if acl_set_link_np(p, type, acl) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(p)) + finally: + acl_free(acl) cdef _nfs4_use_stored_uid_gid(acl): diff --git a/src/borg/platform/linux.pyx b/src/borg/platform/linux.pyx index 189e2955d..955fdbad8 100644 --- a/src/borg/platform/linux.pyx +++ b/src/borg/platform/linux.pyx @@ -251,9 +251,13 @@ def acl_get(path, item, st, numeric_ids=False, fd=None): access_acl = acl_get_fd(fd) else: access_acl = acl_get_file(path, ACL_TYPE_ACCESS) + if access_acl == NULL: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) if stat.S_ISDIR(st.st_mode): # only directories can have a default ACL. there is no fd-based api to get it. default_acl = acl_get_file(path, ACL_TYPE_DEFAULT) + if default_acl == NULL: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) if access_acl: access_text = acl_to_text(access_acl, NULL) if access_text: @@ -289,9 +293,11 @@ def acl_set(path, item, numeric_ids=False, fd=None): access_acl = acl_from_text(converter(access_text)) if access_acl: if fd is not None: - acl_set_fd(fd, access_acl) + if acl_set_fd(fd, access_acl) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) else: - acl_set_file(path, ACL_TYPE_ACCESS, access_acl) + if acl_set_file(path, ACL_TYPE_ACCESS, access_acl) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) finally: acl_free(access_acl) default_text = item.get('acl_default') @@ -300,7 +306,8 @@ def acl_set(path, item, numeric_ids=False, fd=None): default_acl = acl_from_text(converter(default_text)) if default_acl: # only directories can get a default ACL. there is no fd-based api to set it. - acl_set_file(path, ACL_TYPE_DEFAULT, default_acl) + if acl_set_file(path, ACL_TYPE_DEFAULT, default_acl) == -1: + raise OSError(errno.errno, os.strerror(errno.errno), os.fsdecode(path)) finally: acl_free(default_acl)