Merge branch 'acl'
[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 readRights(s):
36     """Canonicalizes string rights to bitmask"""
37     if s in _canonical: s = _canonical[s]
38     return _parseRights(s)
39
40 def showRights(r):
41     """Takes a bitmask and returns a rwlidka string"""
42     s = ""
43     for char,mask in _charBitAssoc:
44         if r & mask == mask: s += char
45     return s
46
47 def _parseRights(s):
48     """Parses a rwlid... rights tring to bitmask"""
49     r = 0
50     try:
51         for c in s:
52             r = r | _char2bit[c]
53     except KeyError:
54         raise ValueError
55     return r
56
57 def _parseAcl(inp):
58     lines = inp.split("\n")
59     npos = int(lines[0].split(" ")[0])
60     pos = {}
61     neg = {}
62     for l in lines[2:]:
63         if l == "": continue
64         name, acl = l.split()
65         if npos:
66             npos -= 1
67             pos[name] = int(acl)
68         else:
69             # negative acl
70             neg[name] = int(acl)
71     return (pos, neg)
72
73 class ACL(object):
74     def __init__(self, pos, neg):
75         """
76         ``pos``
77             Dictionary of usernames to positive ACL bitmasks
78         ``neg``
79             Dictionary of usernames to negative ACL bitmasks
80         """
81         self.pos = pos
82         self.neg = neg
83     @staticmethod
84     def retrieve(dir, follow=1):
85         """Retrieve the ACL for an AFS directory"""
86         pos, neg = _parseAcl(_acl.getAcl(dir, follow))
87         return ACL(pos, neg)
88