1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
# Copyright 2002, 2003 Ben Escoto
#
# This file is part of rdiff-backup.
#
# rdiff-backup is free software; you can redistribute it and/or modify
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# rdiff-backup is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with rdiff-backup; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""This module deal with users and groups
On each connection we may need to map unames and gnames to uids and
gids, and possibly vice-versa. So maintain a separate dictionary for
this.
On the destination connection only, if necessary have a separate
dictionary of mappings, which specify how to map users/groups on one
connection to the users/groups on the other.
"""
import grp, pwd
import log, Globals
# This should be set to the user UserMap class object if using
# user-defined user mapping, and a Map class object otherwise.
UserMap = None
# This should be set to the group UserMap class object if using
# user-defined group mapping, and a Map class object otherwise.
GroupMap = None
uid2uname_dict = {}; gid2gname_dict = {}
def uid2uname(uid):
"""Given uid, return uname or None if cannot find"""
try: return uid2uname_dict[uid]
except KeyError:
try: uname = pwd.getpwuid(uid)[0]
except KeyError: uname = None
uid2uname_dict[uid] = uname
return uname
def gid2gname(gid):
"""Given gid, return group name or None if cannot find"""
try: return gid2gname_dict[gid]
except KeyError:
try: gname = grp.getgrgid(gid)[0]
except KeyError: gname = None
gid2gname_dict[gid] = gname
return gname
def uname2uid(uname):
"""Given uname, return uid or None if cannot find"""
try: uname = pwd.getpwnam(uname)[2]
except KeyError: return None
def gname2gid(gname):
"""Given gname, return gid or None if cannot find"""
try: gname = grp.getgrnam(gname)[2]
except KeyError: return None
class Map:
"""Used for mapping names and id on source side to dest side"""
def __init__(self, name2id_func):
"""Map initializer, set dictionaries"""
self.name2id_dict = {}
self.name2id_func = name2id_func
def get_id(self, id, name = None):
"""Return mapped id from id and, if available, name"""
if not name: return self.get_id_from_id(id)
try: return self.name2id_dict[name]
except KeyError:
out_id = self.find_id(id, name)
self.name2id_dict[name] = out_id
return out_id
def get_id_from_name(self, name):
"""Return mapped id from name only, or None if cannot"""
try: return self.name2id_dict[name]
except KeyError:
out_id = self.find_id_from_name(name)
self.name2id_dict[name] = out_id
return out_id
def get_id_from_id(self, id): return id
def find_id(self, id, name):
"""Find the proper id to use with given id and name"""
try: return self.name2id_func(name)
except KeyError: return id
def find_id_from_name(self, name):
"""Look up proper id to use with name, or None"""
try: return self.name2id_func(name)
except KeyError: return None
class DefinedMap(Map):
"""Map names and ids on source side to appropriate ids on dest side
Like map, but initialize with user-defined mapping string, which
supersedes Map.
"""
def __init__(self, name2id_func, mapping_string):
"""Initialize object with given mapping string
The mapping_string should consist of a number of lines, each which
should have the form "source_id_or_name:dest_id_or_name". Do user
mapping unless user is false, then do group.
"""
Map.__init__(self, name2id_func)
self.name_mapping_dict = {}; self.id_mapping_dict = {}
for line in mapping_string.split('\n'):
line = line.strip()
if not line: continue
comps = line.split(':')
if not len(comps) == 2:
log.Log.FatalError("Error parsing mapping file, bad line: "
+ line)
old, new = comps
try: self.id_mapping_dict[int(old)] = self.init_get_new_id(new)
except ValueError:
self.name_mapping_dict[old] = self.init_get_new_id(new)
def init_get_new_id(self, id_or_name):
"""Return id of id_or_name, failing if cannot. Used in __init__"""
try: return int(id_or_name)
except ValueError:
try: id = self.name2id_func(id_or_name)
except KeyError:
log.Log.FatalError("Cannot get id for user or group name"
+ id_or_name)
return id
def get_id_from_id(self, id): return self.id_mapping_dict.get(id, id)
def find_id(self, id, name):
"""Find proper id to use when source file has give id and name"""
try: return self.name_mapping_dict[name]
except KeyError:
try: return self.id_mapping_dict[id]
except KeyError: return Map.find_id(self, id, name)
def find_id_from_name(self, name):
"""Find id to map name to, or None if we can't"""
try: return self.name_mapping_dict[name]
except KeyError: return Map.find_id_from_name(name)
def init_user_mapping(mapping_string = None):
"""Initialize user mapping with given mapping string or None"""
global UserMap
name2id_func = lambda name: pwd.getpwnam(name)[2]
if mapping_string: UserMap = DefinedMap(name2id_func, mapping_string)
else: UserMap = Map(name2id_func)
def init_group_mapping(mapping_string = None):
"""Initialize the group mapping dictionary with given mapping string"""
global GroupMap
name2id_func = lambda name: grp.getgrnam(name)[2]
if mapping_string: GroupMap = DefinedMap(name2id_func, mapping_string)
else: GroupMap = Map(name2id_func)
def map_rpath(rp):
"""Return (uid, gid) of mapped ownership of given rpath"""
old_uid, old_gid = rp.getuidgid()
new_uid = UserMap.get_id(old_uid, rp.getuname())
new_gid = GroupMap.get_id(old_gid, rp.getgname())
return (new_uid, new_gid)
|