]> arthur.barton.de Git - bup.git/blob - lib/bup/pwdgrp.py
pwdgrp: check for bytes with isinstance everywhere
[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 isinstance(name, bytes)
18         assert isinstance(passwd, bytes)
19         assert isinstance(gecos, bytes)
20         assert isinstance(dir, bytes)
21         assert isinstance(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     assert isinstance(name, bytes)
41     return _passwd_from_py(pwd.getpwnam(name.decode('iso-8859-1') if py_maj > 2
42                                         else name))
43
44
45 class Group:
46     """Drop in replacement for grp's structure with bytes instead of strings."""
47     __slots__ = 'gr_name', 'gr_passwd', 'gr_gid', 'gr_mem'
48     def __init__(self, name, passwd, gid, mem):
49         assert isinstance(name, bytes)
50         assert isinstance(passwd, bytes)
51         for m in mem:
52             assert isinstance(m, bytes)
53         self.gr_name, self.gr_passwd, self.gr_gid, self.gr_mem = \
54             name, passwd, gid, mem
55
56 def _group_from_py(py):
57     if py_maj < 3:
58         return py
59     return Group(py.gr_name.encode('iso-8859-1'),
60                  py.gr_passwd.encode('iso-8859-1'),
61                  py.gr_gid,
62                  tuple(x.encode('iso-8859-1') for x in py.gr_mem))
63
64 def getgrgid(uid):
65     return _group_from_py(grp.getgrgid(uid))
66
67 def getgrnam(name):
68     assert isinstance(name, bytes)
69     return _group_from_py(grp.getgrnam(name.decode('iso-8859-1') if py_maj > 2
70                                        else name))
71
72
73 _uid_to_pwd_cache = {}
74 _name_to_pwd_cache = {}
75
76 def pwd_from_uid(uid):
77     """Return password database entry for uid (may be a cached value).
78     Return None if no entry is found.
79     """
80     global _uid_to_pwd_cache, _name_to_pwd_cache
81     entry, cached = cache_key_value(getpwuid, uid, _uid_to_pwd_cache)
82     if entry and not cached:
83         _name_to_pwd_cache[entry.pw_name] = entry
84     return entry
85
86 def pwd_from_name(name):
87     """Return password database entry for name (may be a cached value).
88     Return None if no entry is found.
89     """
90     assert isinstance(name, bytes)
91     global _uid_to_pwd_cache, _name_to_pwd_cache
92     entry, cached = cache_key_value(getpwnam, name, _name_to_pwd_cache)
93     if entry and not cached:
94         _uid_to_pwd_cache[entry.pw_uid] = entry
95     return entry
96
97
98 _gid_to_grp_cache = {}
99 _name_to_grp_cache = {}
100
101 def grp_from_gid(gid):
102     """Return password database entry for gid (may be a cached value).
103     Return None if no entry is found.
104     """
105     global _gid_to_grp_cache, _name_to_grp_cache
106     entry, cached = cache_key_value(getgrgid, gid, _gid_to_grp_cache)
107     if entry and not cached:
108         _name_to_grp_cache[entry.gr_name] = entry
109     return entry
110
111
112 def grp_from_name(name):
113     """Return password database entry for name (may be a cached value).
114     Return None if no entry is found.
115     """
116     assert isinstance(name, bytes)
117     global _gid_to_grp_cache, _name_to_grp_cache
118     entry, cached = cache_key_value(getgrnam, name, _name_to_grp_cache)
119     if entry and not cached:
120         _gid_to_grp_cache[entry.gr_gid] = entry
121     return entry
122
123
124 _username = None
125 def username():
126     """Get the user's login name."""
127     global _username
128     if not _username:
129         uid = os.getuid()
130         _username = pwd_from_uid(uid).pw_name or b'user%d' % uid
131     return _username
132
133
134 _userfullname = None
135 def userfullname():
136     """Get the user's full name."""
137     global _userfullname
138     if not _userfullname:
139         uid = os.getuid()
140         entry = pwd_from_uid(uid)
141         if entry:
142             _userfullname = entry.pw_gecos.split(b',')[0] or entry.pw_name
143         if not _userfullname:
144             _userfullname = b'user%d' % uid
145     return _userfullname