2014-05-03 13:10:11 +00:00
|
|
|
import os
|
2014-05-03 21:22:55 +00:00
|
|
|
from attic.helpers import user2uid, group2gid
|
|
|
|
|
2014-08-01 13:50:18 +00:00
|
|
|
API_VERSION = 2
|
2014-05-03 13:10:11 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2014-05-03 21:22:55 +00:00
|
|
|
def _remove_numeric_id_if_possible(acl):
|
|
|
|
"""Replace the user/group field with the local uid/gid if possible
|
|
|
|
"""
|
|
|
|
entries = []
|
|
|
|
for entry in acl.decode('ascii').split('\n'):
|
|
|
|
if entry:
|
|
|
|
fields = entry.split(':')
|
|
|
|
if fields[0] == 'user':
|
|
|
|
if user2uid(fields[2]) is not None:
|
|
|
|
fields[1] = fields[3] = ''
|
|
|
|
elif fields[0] == 'group':
|
|
|
|
if group2gid(fields[2]) is not None:
|
|
|
|
fields[1] = fields[3] = ''
|
|
|
|
entries.append(':'.join(fields))
|
|
|
|
return ('\n'.join(entries)).encode('ascii')
|
|
|
|
|
|
|
|
|
|
|
|
def _remove_non_numeric_identifier(acl):
|
|
|
|
"""Remove user and group names from the acl
|
|
|
|
"""
|
|
|
|
entries = []
|
|
|
|
for entry in acl.split(b'\n'):
|
|
|
|
if entry:
|
|
|
|
fields = entry.split(b':')
|
|
|
|
if fields[0] in (b'user', b'group'):
|
|
|
|
fields[2] = b''
|
|
|
|
entries.append(b':'.join(fields))
|
|
|
|
else:
|
|
|
|
entries.append(entry)
|
|
|
|
return b'\n'.join(entries)
|
|
|
|
|
|
|
|
|
2014-08-01 13:50:18 +00:00
|
|
|
def acl_get(path, item, st, numeric_owner=False):
|
2014-05-03 13:10:11 +00:00
|
|
|
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
|
2014-05-03 21:22:55 +00:00
|
|
|
if numeric_owner:
|
|
|
|
item[b'acl_extended'] = _remove_non_numeric_identifier(text)
|
|
|
|
else:
|
|
|
|
item[b'acl_extended'] = text
|
2014-05-03 13:10:11 +00:00
|
|
|
finally:
|
|
|
|
acl_free(text)
|
|
|
|
acl_free(acl)
|
|
|
|
|
|
|
|
|
|
|
|
def acl_set(path, item, numeric_owner=False):
|
|
|
|
cdef acl_t acl = NULL
|
|
|
|
try:
|
|
|
|
try:
|
2014-05-03 21:22:55 +00:00
|
|
|
if numeric_owner:
|
|
|
|
acl = acl_from_text(item[b'acl_extended'])
|
|
|
|
else:
|
|
|
|
acl = acl_from_text(<bytes>_remove_numeric_id_if_possible(item[b'acl_extended']))
|
2014-05-03 13:10:11 +00:00
|
|
|
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)
|
|
|
|
|