mirror of https://github.com/borgbackup/borg.git
Experimental OS X ACL support (#66)
This commit is contained in:
parent
db0381e6f2
commit
47c6141aab
2
CHANGES
2
CHANGES
|
@ -9,7 +9,7 @@ Version 0.13
|
|||
(feature release, released on X)
|
||||
|
||||
- Reduced memory usage when backing up many small files (#69)
|
||||
- Experimental Linux and FreeBSD ACL support (#66)
|
||||
- Experimental Linux, OS X and FreeBSD ACL support (#66)
|
||||
- Added support for backup and restore of BSDFlags (OSX, FreeBSD) (#56)
|
||||
- Fix bug where xattrs on symlinks were not correctly restored
|
||||
- Added cachedir support. CACHEDIR.TAG compatible cache directories
|
||||
|
|
|
@ -6,6 +6,8 @@ if platform == 'Linux':
|
|||
from attic.platform_linux import acl_get, acl_set, API_VERSION
|
||||
elif platform == 'FreeBSD':
|
||||
from attic.platform_freebsd import acl_get, acl_set, API_VERSION
|
||||
elif platform == 'Darwin':
|
||||
from attic.platform_darwin import acl_get, acl_set, API_VERSION
|
||||
else:
|
||||
API_VERSION = 1
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import os
|
||||
API_VERSION = 1
|
||||
|
||||
cdef extern from "sys/acl.h":
|
||||
ctypedef struct _acl_t:
|
||||
pass
|
||||
ctypedef _acl_t *acl_t
|
||||
|
||||
int acl_free(void *obj)
|
||||
acl_t acl_get_link_np(const char *path, int type)
|
||||
acl_t acl_set_link_np(const char *path, int type, acl_t acl)
|
||||
acl_t acl_from_text(const char *buf)
|
||||
char *acl_to_text(acl_t acl, ssize_t *len_p)
|
||||
int ACL_TYPE_EXTENDED
|
||||
|
||||
|
||||
def acl_get(path, item, numeric_owner=False):
|
||||
cdef acl_t acl = NULL
|
||||
cdef char *text = NULL
|
||||
try:
|
||||
acl = acl_get_link_np(<bytes>os.fsencode(path), ACL_TYPE_EXTENDED)
|
||||
if acl == NULL:
|
||||
return
|
||||
text = acl_to_text(acl, NULL)
|
||||
if text == NULL:
|
||||
return
|
||||
item[b'acl_extended'] = text
|
||||
finally:
|
||||
acl_free(text)
|
||||
acl_free(acl)
|
||||
|
||||
|
||||
def acl_set(path, item, numeric_owner=False):
|
||||
cdef acl_t acl = NULL
|
||||
try:
|
||||
try:
|
||||
acl = acl_from_text(item[b'acl_extended'])
|
||||
except KeyError:
|
||||
return
|
||||
if acl == NULL:
|
||||
return
|
||||
if acl_set_link_np(<bytes>os.fsencode(path), ACL_TYPE_EXTENDED, acl):
|
||||
return
|
||||
finally:
|
||||
acl_free(acl)
|
||||
|
|
@ -71,3 +71,30 @@ class PlatformLinuxTestCase(AtticTestCase):
|
|||
self.assert_equal(self.get_acl(self.tmpdir)[b'acl_access'], ACCESS_ACL)
|
||||
self.assert_equal(self.get_acl(self.tmpdir)[b'acl_default'], DEFAULT_ACL)
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('darwin'), 'OS X only test')
|
||||
@unittest.skipIf(fakeroot_detected(), 'not compatible with fakeroot')
|
||||
class PlatformDarwinTestCase(AtticTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmpdir)
|
||||
|
||||
def get_acl(self, path, numeric_owner=False):
|
||||
item = {}
|
||||
acl_get(path, item, numeric_owner=numeric_owner)
|
||||
return item
|
||||
|
||||
def set_acl(self, path, acl, numeric_owner=False):
|
||||
item = {b'acl_extended': acl}
|
||||
acl_set(path, item, numeric_owner=numeric_owner)
|
||||
|
||||
def test_access_acl(self):
|
||||
file = tempfile.NamedTemporaryFile()
|
||||
self.assert_equal(self.get_acl(file.name), {})
|
||||
self.set_acl(file.name, b'!#acl 1\ngroup:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000014:staff:9999:allow:read\nuser:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n', numeric_owner=False)
|
||||
self.assert_in(b'group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000014:staff:20:allow:read', self.get_acl(file.name)[b'acl_extended'])
|
||||
self.assert_in(b'user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read', self.get_acl(file.name)[b'acl_extended'])
|
||||
|
||||
|
|
6
setup.py
6
setup.py
|
@ -25,6 +25,7 @@ crypto_source = 'attic/crypto.pyx'
|
|||
chunker_source = 'attic/chunker.pyx'
|
||||
hashindex_source = 'attic/hashindex.pyx'
|
||||
platform_linux_source = 'attic/platform_linux.pyx'
|
||||
platform_darwin_source = 'attic/platform_darwin.pyx'
|
||||
platform_freebsd_source = 'attic/platform_freebsd.pyx'
|
||||
|
||||
try:
|
||||
|
@ -39,7 +40,7 @@ try:
|
|||
versioneer.cmd_sdist.__init__(self, *args, **kwargs)
|
||||
|
||||
def make_distribution(self):
|
||||
self.filelist.extend(['attic/crypto.c', 'attic/chunker.c', 'attic/_chunker.c', 'attic/hashindex.c', 'attic/_hashindex.c', 'attic/platform_linux.c', 'attic/platform_freebsd.c'])
|
||||
self.filelist.extend(['attic/crypto.c', 'attic/chunker.c', 'attic/_chunker.c', 'attic/hashindex.c', 'attic/_hashindex.c', 'attic/platform_linux.c', 'attic/platform_freebsd.c', 'attic/platform_darwin.c'])
|
||||
super(Sdist, self).make_distribution()
|
||||
|
||||
except ImportError:
|
||||
|
@ -52,6 +53,7 @@ except ImportError:
|
|||
hashindex_source = hashindex_source.replace('.pyx', '.c')
|
||||
platform_linux_source = platform_linux_source.replace('.pyx', '.c')
|
||||
platform_freebsd_source = platform_freebsd_source.replace('.pyx', '.c')
|
||||
platform_darwin_source = platform_darwin_source.replace('.pyx', '.c')
|
||||
from distutils.command.build_ext import build_ext
|
||||
if not all(os.path.exists(path) for path in [crypto_source, chunker_source, hashindex_source, platform_linux_source, platform_freebsd_source]):
|
||||
raise ImportError('The GIT version of Attic needs Cython. Install Cython or use a released version')
|
||||
|
@ -91,6 +93,8 @@ if platform == 'Linux':
|
|||
ext_modules.append(Extension('attic.platform_linux', [platform_linux_source], libraries=['acl']))
|
||||
elif platform == 'FreeBSD':
|
||||
ext_modules.append(Extension('attic.platform_freebsd', [platform_freebsd_source]))
|
||||
elif platform == 'Darwin':
|
||||
ext_modules.append(Extension('attic.platform_darwin', [platform_darwin_source]))
|
||||
|
||||
setup(
|
||||
name='Attic',
|
||||
|
|
Loading…
Reference in New Issue