blob: 630d2f205b8357105d14ea40d33415f81d18909b [file] [log] [blame]
# Copyright 2015 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This script installs users and groups into sysroots."""
import os
from chromite.lib import accounts_lib
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import sysroot_lib
from chromite.lib import user_db
ACCOUNT_DB_FILENAME = "accounts.json"
ACTION_GET_ENTRY = "get_entry"
ACTION_INSTALL_USER = "install_user"
ACTION_INSTALL_GROUP = "install_group"
USER_DB = "passwd"
GROUP_DB = "group"
def GetOptions(argv):
"""Returns the parsed command line arguments in |argv|."""
parser = commandline.ArgumentParser(description=__doc__)
command_parsers = parser.add_subparsers(dest="action")
get_ent_parser = command_parsers.add_parser(
ACTION_GET_ENTRY, help="Get an entry from an account database."
)
get_ent_parser.add_argument(
"--nolock",
action="store_true",
default=False,
help="Skip locking the database before reading it.",
)
get_ent_parser.add_argument(
"sysroot", type="path", help="Path to sysroot containing the database"
)
get_ent_parser.add_argument(
"database", choices=(USER_DB, GROUP_DB), help="Name of database to get"
)
get_ent_parser.add_argument("name", type=str, help="Name of account to get")
user_parser = command_parsers.add_parser(
ACTION_INSTALL_USER, help="Install a user to a sysroot"
)
user_parser.add_argument("name", type=str, help="Name of user to install")
user_parser.add_argument("--uid", type=int, help="UID of the user")
user_parser.add_argument("--shell", type="path", help="Shell of user")
user_parser.add_argument(
"--home", type="path", help="Home directory of user"
)
user_parser.add_argument(
"--primary_group", type=str, help="Name of primary group for user"
)
group_parser = command_parsers.add_parser(
ACTION_INSTALL_GROUP, help="Install a group to a sysroot"
)
group_parser.add_argument(
"name", type=str, help="Name of group to install."
)
group_parser.add_argument("--gid", type=int, help="GID of the group")
# Both group and user parsers need to understand the target sysroot.
for sub_parser in (user_parser, group_parser):
sub_parser.add_argument(
"sysroot", type="path", help="The sysroot to install the user into"
)
options = parser.parse_args(argv)
options.Freeze()
return options
def main(argv):
cros_build_lib.AssertInsideChroot()
options = GetOptions(argv)
if options.action == ACTION_GET_ENTRY:
db = user_db.UserDB(options.sysroot)
if options.database == USER_DB:
print(db.GetUserEntry(options.name, skip_lock=options.nolock))
else:
print(db.GetGroupEntry(options.name, skip_lock=options.nolock))
return 0
overlays = (
sysroot_lib.Sysroot(options.sysroot)
.GetStandardField(sysroot_lib.STANDARD_FIELD_PORTDIR_OVERLAY)
.split()
)
# TODO(wiley) This process could be optimized to avoid reparsing these
# overlay databases each time.
account_db = accounts_lib.AccountDatabase()
for overlay_path in overlays:
database_path = os.path.join(overlay_path, ACCOUNT_DB_FILENAME)
if os.path.exists(database_path):
account_db.AddAccountsFromDatabase(database_path)
installed_users = user_db.UserDB(options.sysroot)
if options.action == ACTION_INSTALL_USER:
account_db.InstallUser(
options.name,
installed_users,
uid=options.uid,
shell=options.shell,
homedir=options.home,
primary_group=options.primary_group,
)
homedir = account_db.users[options.name].home
homedir_path = os.path.join(options.sysroot, homedir)
if homedir != "/dev/null" and not os.path.exists(homedir_path):
osutils.SafeMakedirs(homedir_path, sudo=True)
uid = account_db.users[options.name].uid
cros_build_lib.sudo_run(
["chown", "%d:%d" % (uid, uid), homedir_path], print_cmd=False
)
elif options.action == ACTION_INSTALL_GROUP:
account_db.InstallGroup(options.name, installed_users, gid=options.gid)
else:
cros_build_lib.Die(
"Unsupported account type: %s" % options.account_type
)