# 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 class Map: """Used for mapping names and id on source side to dest side""" def __init__(self, name2id_func): """Map initializer, set dictionaries""" assert Globals.isdest, "Should run on destination connection" 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_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 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 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): """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)