--- pym/portage/repository/config.py | 13 +++++++--- pym/portage/sync/controller.py | 52 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py index 678cc68..f45684b 100644 --- a/pym/portage/repository/config.py +++ b/pym/portage/repository/config.py @@ -85,7 +85,7 @@ class RepoConfig(object): 'main_repo', 'manifest_hashes', 'masters', 'missing_repo_name', 'name', 'portage1_profiles', 'portage1_profiles_compat', 'priority', 'profile_formats', 'sign_commit', 'sign_manifest', 'sync_cvs_repo', - 'sync_type', 'sync_umask', 'sync_uri', 'thin_manifest', + 'sync_type', 'sync_umask', 'sync_uri', 'sync_user', 'thin_manifest', 'update_changelog', 'user_location', '_eapis_banned', '_eapis_deprecated', '_masters_orig') @@ -165,6 +165,11 @@ class RepoConfig(object): sync_uri = sync_uri.strip() self.sync_uri = sync_uri or None + sync_user = repo_opts.get('sync-user') + if sync_user is not None: + sync_user = sync_user.strip() + self.sync_user = sync_user or None + auto_sync = repo_opts.get('auto-sync') if auto_sync is not None: auto_sync = auto_sync.strip().lower() @@ -385,6 +390,8 @@ class RepoConfig(object): repo_msg.append(indent + "sync-umask: " + self.sync_umask) if self.sync_uri: repo_msg.append(indent + "sync-uri: " + self.sync_uri) + if self.sync_user: + repo_msg.append(indent + "sync-user: " + self.sync_user) if self.masters: repo_msg.append(indent + "masters: " + " ".join(master.name for master in self.masters)) if self.priority is not None: @@ -472,7 +479,7 @@ class RepoConfigLoader(object): # repos.conf is allowed to override. for k in ('aliases', 'auto_sync', 'eclass_overrides', 'force', 'masters', 'priority', 'sync_cvs_repo', - 'sync_type', 'sync_umask', 'sync_uri', + 'sync_type', 'sync_umask', 'sync_uri', 'sync_user', ): v = getattr(repos_conf_opts, k, None) if v is not None: @@ -923,7 +930,7 @@ class RepoConfigLoader(object): def config_string(self): str_or_int_keys = ("auto_sync", "format", "location", "main_repo", "priority", "sync_cvs_repo", - "sync_type", "sync_umask", "sync_uri") + "sync_type", "sync_umask", "sync_uri", 'sync_user') str_tuple_keys = ("aliases", "eclass_overrides", "force") repo_config_tuple_keys = ("masters",) keys = str_or_int_keys + str_tuple_keys + repo_config_tuple_keys diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py index 0e5efb6..3104524 100644 --- a/pym/portage/sync/controller.py +++ b/pym/portage/sync/controller.py @@ -6,6 +6,7 @@ from __future__ import print_function import sys import logging +import grp import pwd import portage @@ -193,7 +194,56 @@ class SyncManager(object): self.usersync_uid = None spawn_kwargs = {} spawn_kwargs["env"] = self.settings.environ() - if ('usersync' in self.settings.features and + if repo.sync_user is not None: + def get_sync_user_data(sync_user): + spl = sync_user.split(':', 1) + if not spl[0]: + writemsg("!!! Invalid sync-user = %s\n" % sync_user, + noiselevel=-1) + return () + + user = spl[0] + try: + try: + # maybe it's a uid? + uid = int(user) + except ValueError: + pw = pwd.getpwnam(user) + else: + pw = pwd.getpwuid(uid) + except KeyError: + writemsg("!!! User '%s' invalid or does not exist\n" + % user, noiselevel=-1) + return () + + if len(spl) > 1: + group = spl[1] + try: + try: + # maybe it's a gid? + gid = int(group) + except ValueError: + gp = grp.getgrnam(group) + else: + pw = grp.getgrgid(gid) + except KeyError: + writemsg("!!! Group '%s' invalid or does not exist\n" + % group, noiselevel=-1) + return () + + gr = gp.gr_gid + else: + gr = pw.pw_gid + + return (pw.pw_uid, gr, pw.pw_dir) + + # user or user:group + (uid, gid, home) = get_sync_user_data(repo.sync_user) + spawn_kwargs["uid"] = uid + spawn_kwargs["gid"] = gid + spawn_kwargs["groups"] = [gid] + spawn_kwargs["env"]["HOME"] = home + elif ('usersync' in self.settings.features and portage.data.secpass >= 2 and (st.st_uid != os.getuid() and st.st_mode & 0o700 or st.st_gid != os.getgid() and st.st_mode & 0o070)): -- 2.2.0