]> arthur.barton.de Git - bup.git/blob - lib/bup/pwdgrp.py
Move pwd grp functions to pwdgrp module; require binary fields
[bup.git] / lib / bup / pwdgrp.py
1
2 from __future__ import absolute_import, print_function
3 import os, pwd, grp
4
5 from bup import compat  # to force the LC_CTYPE check
6 from bup.compat import py_maj
7 from bup.helpers import cache_key_value
8
9
10 # Using __slots__ makes these much smaller (even than a namedtuple)
11
12 class Passwd:
13     """Drop in replacement for pwd's structure with bytes instead of strings."""
14     __slots__ = ('pw_name', 'pw_passwd', 'pw_uid', 'pw_gid', 'pw_gecos',
15                  'pw_dir', 'pw_shell')
16     def __init__(self, name, passwd, uid, gid, gecos, dir, shell):
17         assert type(name) == bytes
18         assert type(passwd) == bytes
19         assert type(gecos) == bytes
20         assert type(dir) == bytes
21         assert type(shell) == bytes
22         (self.pw_name, self.pw_passwd, self.pw_uid, self.pw_gid,
23          self.pw_gecos, self.pw_dir, self.pw_shell) = \
24              name, passwd, uid, gid, gecos, dir, shell
25
26 def _passwd_from_py(py):
27     if py_maj < 3:
28         return py
29     return Passwd(py.pw_name.encode('iso-8859-1'),
30                   py.pw_passwd.encode("iso-8859-1"),
31                   py.pw_uid, py.pw_gid,
32                   py.pw_gecos.encode('iso-8859-1'),
33                   py.pw_dir.encode('iso-8859-1'),
34                   py.pw_shell.encode('iso-8859-1'))
35
36 def getpwuid(uid):
37     return _passwd_from_py(pwd.getpwuid(uid))
38
39 def getpwnam(name):
40     return _passwd_from_py(pwd.getpwnam(name))
41
42
43 class Group:
44     """Drop in replacement for grp's structure with bytes instead of strings."""
45     __slots__ = 'gr_name', 'gr_passwd', 'gr_gid', 'gr_mem'
46     def __init__(self, name, passwd, gid, mem):
47         assert type(name) == bytes
48         assert type(passwd) == bytes
49         for m in mem:
50             assert type(m) == bytes
51         self.gr_name, self.gr_passwd, self.gr_gid, self.gr_mem = \
52             name, passwd, gid, mem
53
54 def _group_from_py(py):
55     if py_maj < 3:
56         return py
57     return Group(py.gr_name.encode('iso-8859-1'),
58                  py.gr_passwd.encode('iso-8859-1'),
59                  py.gr_gid,
60                  tuple(x.encode('iso-8859-1') for x in py.gr_mem))
61
62 def getgrgid(uid):
63     return _group_from_py(pwd.getgrgid(uid))
64
65 def getgrnam(name):
66     return _group_from_py(pwd.getgrnam(name))
67
68
69 _uid_to_pwd_cache = {}
70 _name_to_pwd_cache = {}
71
72 def pwd_from_uid(uid):
73     """Return password database entry for uid (may be a cached value).
74     Return None if no entry is found.
75     """
76     global _uid_to_pwd_cache, _name_to_pwd_cache
77     entry, cached = cache_key_value(getpwuid, uid, _uid_to_pwd_cache)
78     if entry and not cached:
79         _name_to_pwd_cache[entry.pw_name] = entry
80     return entry
81
82 def pwd_from_name(name):
83     """Return password database entry for name (may be a cached value).
84     Return None if no entry is found.
85     """
86     assert type(name) == bytes
87     global _uid_to_pwd_cache, _name_to_pwd_cache
88     entry, cached = cache_key_value(getpwnam, name, _name_to_pwd_cache)
89     if entry and not cached:
90         _uid_to_pwd_cache[entry.pw_uid] = entry
91     return entry
92
93
94 _gid_to_grp_cache = {}
95 _name_to_grp_cache = {}
96
97 def grp_from_gid(gid):
98     """Return password database entry for gid (may be a cached value).
99     Return None if no entry is found.
100     """
101     global _gid_to_grp_cache, _name_to_grp_cache
102     entry, cached = cache_key_value(grp.getgrgid, gid, _gid_to_grp_cache)
103     if entry and not cached:
104         _name_to_grp_cache[entry.gr_name] = entry
105     return entry
106
107
108 def grp_from_name(name):
109     """Return password database entry for name (may be a cached value).
110     Return None if no entry is found.
111     """
112     assert type(name) == bytes
113     global _gid_to_grp_cache, _name_to_grp_cache
114     entry, cached = cache_key_value(grp.getgrnam, name, _name_to_grp_cache)
115     if entry and not cached:
116         _gid_to_grp_cache[entry.gr_gid] = entry
117     return entry
118
119
120 _username = None
121 def username():
122     """Get the user's login name."""
123     global _username
124     if not _username:
125         uid = os.getuid()
126         _username = pwd_from_uid(uid).pw_name or b'user%d' % uid
127     return _username
128
129
130 _userfullname = None
131 def userfullname():
132     """Get the user's full name."""
133     global _userfullname
134     if not _userfullname:
135         uid = os.getuid()
136         entry = pwd_from_uid(uid)
137         if entry:
138             _userfullname = entry.pw_gecos.split(b',')[0] or entry.pw_name
139         if not _userfullname:
140             _userfullname = b'user%d' % uid
141     return _userfullname