Incorporate broder's comments.
[invirt/packages/python-afs.git] / afs / acl.py
1 import _acl
2 from _acl import READ, WRITE, INSERT, LOOKUP, DELETE, LOCK, ADMINISTER, \
3     USR0, USR1, USR2, USR3, USR4, USR5, USR6, USR7
4 from _acl import getCallerAccess
5
6 _canonical = {
7     "read":     "rl",
8     "write":    "rwlidwk",
9     "all":      "rwlidwka",
10     "mail":     "lik",
11     "none":     "",
12 }
13
14 _charBitAssoc = [
15     ('r', READ),
16     ('w', WRITE),
17     ('i', INSERT),
18     ('l', LOOKUP),
19     ('d', DELETE),
20     ('k', LOCK),
21     ('a', ADMINISTER),
22     ('A', USR0),
23     ('B', USR1),
24     ('C', USR2),
25     ('D', USR3),
26     ('E', USR4),
27     ('F', USR5),
28     ('G', USR6),
29     ('H', USR7),
30 ]
31
32 _char2bit = dict(_charBitAssoc)
33
34
35 def crights(s):
36     """Canonicalizes string rights to bitmask"""
37     if s in _canonical: s = _canonical[s]
38     return _parseRights(s)
39
40 class ACL(object):
41     def __init__(self, pos, neg):
42         """
43         ``pos``
44             Dictionary of usernames to positive ACL bitmasks
45         ``neg``
46             Dictionary of usernames to negative ACL bitmasks
47         """
48         self.pos = pos
49         self.neg = neg
50     @staticmethod
51     def retrieve(dir,follow=1):
52         """Retrieve the ACL for an AFS directory"""
53         pos, neg = _parseAcl(_acl.getAcl(dir, follow))
54         return ACL(pos, neg)
55
56 def showRights(r):
57     """Takes a bitmask and returns a rwlidka string"""
58     s = ""
59     for char,mask in _charBitAssoc:
60         if r & mask == mask: s += char
61     return s
62
63 def _parseRights(s):
64     """Parses a rwlid... rights tring to bitmask"""
65     r = 0
66     try:
67         for c in s:
68             r = r | _char2bit[c]
69     except KeyError:
70         raise ValueError
71     return r
72
73 def _parseAcl(inp):
74     lines = inp.split("\n")
75     npos = int(lines[0].split(" ")[0])
76     pos = {}
77     neg = {}
78     for l in lines[2:]:
79         if l == "": continue
80         name, acl = l.split()
81         if npos:
82             npos -= 1
83             pos[name] = int(acl)
84         else:
85             # negative acl
86             neg[name] = int(acl)
87     return (pos, neg)
88