Implement the ability to set ACLs.
authorJonathan Reed <jdreed@infinite-loop.mit.edu>
Fri, 13 Nov 2009 21:57:40 +0000 (16:57 -0500)
committerJonathan Reed <jdreed@infinite-loop.mit.edu>
Fri, 13 Nov 2009 22:07:40 +0000 (17:07 -0500)
- 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 <jdreed@mit.edu>

afs/_acl.pyx
afs/acl.py
afs/afs.pxd
afs/afs.pyx

index ef65388..3f34685 100644 (file)
@@ -43,3 +43,6 @@ def getCallerAccess(char *dir, int follow=1):
     cdef vcxstat2 stat
     pioctl_read(dir, VIOC_GETVCXSTATUS2, <void*>&stat, sizeof(vcxstat2), follow)
     return stat.callerAccess
     cdef vcxstat2 stat
     pioctl_read(dir, VIOC_GETVCXSTATUS2, <void*>&stat, sizeof(vcxstat2), follow)
     return stat.callerAccess
+
+def setAcl(char* dir, char* acl, int follow=1):
+    pioctl_write(dir, VIOCSETAL, acl, follow)
index 713d5b8..1fb1dac 100644 (file)
@@ -70,6 +70,16 @@ def _parseAcl(inp):
             neg[name] = int(acl)
     return (pos, neg)
 
             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):
         """
 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)
         """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)
+        
index 02518e2..2b02338 100644 (file)
@@ -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)
     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)
 
 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
 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
 
 # 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
 
 
index 29a2442..4fe9e1c 100644 (file)
@@ -26,6 +26,20 @@ cdef extern int pioctl_read(char *dir, afs_int32 op, void *buffer, unsigned shor
     pyafs_error(code)
     return code
 
     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):
 # Error handling
 
 class AFSException(Exception):