From: Jonathan Reed Date: Fri, 13 Nov 2009 21:57:40 +0000 (-0500) Subject: Implement the ability to set ACLs. X-Git-Tag: 0.1.0~14 X-Git-Url: http://xvm.mit.edu/gitweb/invirt/packages/python-afs.git/commitdiff_plain/137d9e9aa87890dbd343383f636652374dbd72db?hp=4d3e823390c355e15521d9792de840eefad63cf7 Implement the ability to set ACLs. - Added pioctl_write and setAcl to the Pyrex code - Added ACL.set to set an ACL to a given bitmask, ACL.apply to actually apply the ACL. ACLs set to 0 are pruned before applying. Signed-off-by: Jonathan Reed --- diff --git a/afs/_acl.pyx b/afs/_acl.pyx index ef65388..3f34685 100644 --- a/afs/_acl.pyx +++ b/afs/_acl.pyx @@ -43,3 +43,6 @@ def getCallerAccess(char *dir, int follow=1): cdef vcxstat2 stat pioctl_read(dir, VIOC_GETVCXSTATUS2, &stat, sizeof(vcxstat2), follow) return stat.callerAccess + +def setAcl(char* dir, char* acl, int follow=1): + pioctl_write(dir, VIOCSETAL, acl, follow) diff --git a/afs/acl.py b/afs/acl.py index 713d5b8..1fb1dac 100644 --- a/afs/acl.py +++ b/afs/acl.py @@ -70,6 +70,16 @@ def _parseAcl(inp): neg[name] = int(acl) return (pos, neg) +def _unparseAcl(pos, neg): + npos = len(pos) + nneg = len(neg) + acl = "%d\n%d\n" % (npos, nneg) + for p in pos.items(): + acl += "%s\t%d\n" % p + for n in neg.items(): + acl += "%s\t%d\n" % n + return acl + class ACL(object): def __init__(self, pos, neg): """ @@ -85,4 +95,27 @@ class ACL(object): """Retrieve the ACL for an AFS directory""" pos, neg = _parseAcl(_acl.getAcl(dir, follow)) return ACL(pos, neg) - + def apply(self, dir, follow=True): + """Apply the ACL to a directory""" + self._clean() + _acl.setAcl(dir, _unparseAcl(self.pos, self.neg), follow) + def _clean(self): + """Clean an ACL by removing any entries whose bitmask is 0""" + for n,a in self.pos.items(): + if a == 0: + del self.pos[n] + for n,a in self.neg.items(): + if a == 0: + del self.neg[n] + def set(self, user, bitmask, negative=False): + """Set the bitmask for a given user""" + if bitmask < 0 or bitmask > max(_char2bit.values()): + raise ValueError, "Invalid bitmask" + if negative: + self.neg[user] = bitmask + else: + self.pos[user] = bitmask + def remove(self, user, negative=False): + """Convenience function to removeSet the bitmask for a given user""" + self.set(user, 0, negative) + diff --git a/afs/afs.pxd b/afs/afs.pxd index 02518e2..2b02338 100644 --- a/afs/afs.pxd +++ b/afs/afs.pxd @@ -9,6 +9,7 @@ cdef extern from "string.h": char * strncpy(char *s1, char *s2, size_t n) void * memset(void *b, int c, size_t n) void * memcpy(void *s1, void *s2, size_t n) + size_t strlen(char *s) cdef extern from "stdlib.h": void * malloc(size_t size) @@ -157,9 +158,10 @@ cdef extern from "afs/vice.h": cdef import from "afs/venus.h": enum: # PIOCTLS to Venus that we use - VIOCGETAL, VIOC_GETVCXSTATUS2 + VIOCGETAL, VIOC_GETVCXSTATUS2, VIOCSETAL # pioctl doesn't actually have a header, so we have to define it here cdef extern int pioctl(char *, afs_int32, ViceIoctl *, afs_int32) cdef int pioctl_read(char *, afs_int32, void *, unsigned short, afs_int32) except -1 +cdef int pioctl_write(char *, afs_int32, char *, afs_int32) except -1 diff --git a/afs/afs.pyx b/afs/afs.pyx index 29a2442..4fe9e1c 100644 --- a/afs/afs.pyx +++ b/afs/afs.pyx @@ -26,6 +26,20 @@ cdef extern int pioctl_read(char *dir, afs_int32 op, void *buffer, unsigned shor pyafs_error(code) return code +cdef extern int pioctl_write(char *dir, afs_int32 op, char *buffer, afs_int32 follow) except -1: + cdef ViceIoctl blob + cdef afs_int32 code + blob.cin = buffer + blob.in_size = 1 + strlen(buffer) + blob.out_size = 0 + code = pioctl(dir, op, &blob, follow) + # This might work with the rest of OpenAFS, but I'm not convinced + # the rest of it is consistent + if code == -1: + raise OSError(errno, strerror(errno)) + pyafs_error(code) + return code + # Error handling class AFSException(Exception):