util.py 4.23 KB
Newer Older
Anders Blomdell's avatar
Anders Blomdell committed
1
2
3
4
import grp
import os
import pwd
import re
Anders Blomdell's avatar
Anders Blomdell committed
5
from mio.log import log, NORMAL, VERBOSE
Anders Blomdell's avatar
Anders Blomdell committed
6
from mio.node import *
Anders Blomdell's avatar
Anders Blomdell committed
7

Anders Blomdell's avatar
Anders Blomdell committed
8
9
10
11
12
13
try:
    # Python 2
    from __builtin__ import unicode
except ModuleNotFoundError:
    # Python 3
    from builtins import str as unicode
Anders Blomdell's avatar
Anders Blomdell committed
14
15
16
def mode_mask(s):
    result = 0
    for c in s:
Anders Blomdell's avatar
Anders Blomdell committed
17
18
19
20
        if   c == 'u': result |= 0o4700
        elif c == 'g': result |= 0o2070
        elif c == 'o': result |= 0o1007
        elif c == 'a': result |= 0o7777
Anders Blomdell's avatar
Anders Blomdell committed
21
22
23
24
25
26
        else: raise Exception("Illegal mode group %c" % c)
    return result

def mode_bits(s):
    result = 0
    for c in s:
Anders Blomdell's avatar
Anders Blomdell committed
27
28
29
30
31
        if   c == 'r': result |= 0o0444
        elif c == 'w': result |= 0o0222
        elif c == 'x': result |= 0o0111
        elif c == 's': result |= 0o6000
        elif c == 't': result |= 0o1000
Anders Blomdell's avatar
Anders Blomdell committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
        else: raise Exception("Illegal mode bits %c" % c)
    return result

def mode_combine(mode):
    result = 0
    mode = list(mode)
    mode.reverse()
    for m in mode:
        if m.__class__ == int:
            result = m
        elif m.__class__ == str or m.__class__ == unicode:
            for s in m.split(','):
                num = re.match("^[0-7]+$", s)
                sym = re.match('([ugoa]+)([-+=])([rwxst]+)', s)
                if num:
                    # Numeric mode
                    result = int(s, 8)
                elif sym:
                    # Symbolic mode
                    changed = mode_mask(sym.group(1)) & mode_bits(sym.group(3))
                    if   sym.group(2) == '-': result &= ~changed
                    elif sym.group(2) == '=': result = changed
                    elif sym.group(2) == '+': result |= changed
                    else: raise Exception("Illegal mode action %s" %
                                          sym.group(2))
                else:
                    raise Exception("Unparseable mode '%s' in '%s'" %
                                    (s, m))
    return result

def filemode(file):
    mode = file.mode[0::1]
Anders Blomdell's avatar
Anders Blomdell committed
64
    mode.append(0o600)
Anders Blomdell's avatar
Anders Blomdell committed
65
66
67
68
69
    return mode_combine(mode)

def dirmode(dir):
    mode = [ dir.mode[0] ]
    mode.extend(dir.dirmode[1::1])
Anders Blomdell's avatar
Anders Blomdell committed
70
    mode.append(0o700)
Anders Blomdell's avatar
Anders Blomdell committed
71
72
    return mode_combine(mode)

Anders Blomdell's avatar
Anders Blomdell committed
73
def uid(owner):
Anders Blomdell's avatar
Anders Blomdell committed
74
75
76
77
78
79
80
81
82
83
84
85
    class deferred_uid:
        def __int__(self):
            if owner == None:
                return os.getuid()
            elif owner.isdigit():
                return int(owner)
            else:
                try:
                    return pwd.getpwnam(owner)[2]
                except KeyError:
                    raise KeyError("user '%s' not found" % owner)

86
        def __eq__(self, other):
Anders Blomdell's avatar
Anders Blomdell committed
87
            try:
88
                return int(self) == other
Anders Blomdell's avatar
Anders Blomdell committed
89
90
            except KeyError:
                log(NORMAL, "Deferring uid lookup for '%s'" % owner)
91
                return False
Anders Blomdell's avatar
Anders Blomdell committed
92
93

    return deferred_uid()
Anders Blomdell's avatar
Anders Blomdell committed
94

Anders Blomdell's avatar
Anders Blomdell committed
95
def gid(group):
Anders Blomdell's avatar
Anders Blomdell committed
96
97
98
99
100
101
102
103
104
105
106
107
    class deferred_gid:
        def __int__(self):
            if group == None:
                return os.getgid()
            elif group.isdigit():
                return int(group)
            else:
                try:
                    return grp.getgrnam(group)[2]
                except KeyError:
                    raise KeyError("group '%s' not found" % group)
        
108
        def __eq__(self, other):
Anders Blomdell's avatar
Anders Blomdell committed
109
            try:
110
                return int(self) == other
Anders Blomdell's avatar
Anders Blomdell committed
111
112
            except KeyError:
                log(NORMAL, "Deferring gid lookup for '%s'" % group)
113
                return False
Anders Blomdell's avatar
Anders Blomdell committed
114
115
            
    return deferred_gid()
Anders Blomdell's avatar
Anders Blomdell committed
116
117
118
119
120
121
122

def owner(decl):
    return decl.owner[0:]

def group(decl):
    return decl.group[0:]

Anders Blomdell's avatar
Anders Blomdell committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
def exclusion_closure(exclude, target):
    if not target._exclude_:
        return exclude
    else:
        result = list(exclude) # Create exclusion closure
        for e in target._exclude_:
            for (key, value) in e._attribute.items():
                if key == 'dependency':
                    result.append(group_node(value))
                elif key == 'file':
                    result.append(file_node(value))
                elif key == 'dir':
                    result.append(dir_node(value))
                elif key == 'rpm':
                    result.append(rpm_node(value))
                elif key == 'symlink':
                    result.append(symlink_node(value))
                else:
                    raise BadExclude(e, key)
        return result