blob: 3769b0eb28b02be8300f5475b1bd4834a5531df3 [file] [log] [blame]
Christopher Wiley5ccc8292015-05-28 10:01:22 -07001# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""This script installs users and groups into sysroots."""
6
7from __future__ import print_function
8
9import os
10
11from chromite.lib import accounts_lib
12from chromite.lib import commandline
13from chromite.lib import cros_build_lib
14from chromite.lib import osutils
15from chromite.lib import sysroot_lib
16from chromite.lib import user_db
17
18
19ACCOUNT_DB_FILENAME = 'accounts.json'
20
21ACTION_GET_ENTRY = 'get_entry'
22ACTION_INSTALL_USER = 'install_user'
23ACTION_INSTALL_GROUP = 'install_group'
24
25USER_DB = 'passwd'
26GROUP_DB = 'group'
27
28
29def GetOptions(argv):
30 """Returns the parsed command line arguments in |argv|."""
31 parser = commandline.ArgumentParser(description=__doc__)
32 command_parsers = parser.add_subparsers(dest='action')
33
34 get_ent_parser = command_parsers.add_parser(
35 ACTION_GET_ENTRY, help='Get an entry from an account database.')
36 get_ent_parser.add_argument(
37 '--nolock', action='store_true', default=False,
38 help='Skip locking the database before reading it.')
39 get_ent_parser.add_argument('sysroot', type='path',
40 help='Path to sysroot containing the database')
41 get_ent_parser.add_argument('database', choices=(USER_DB, GROUP_DB),
42 help='Name of database to get')
43 get_ent_parser.add_argument('name', type=str, help='Name of account to get')
44
45 user_parser = command_parsers.add_parser(
46 ACTION_INSTALL_USER, help='Install a user to a sysroot')
47 user_parser.add_argument('name', type=str,
48 help='Name of user to install')
49 user_parser.add_argument('--uid', type=int,
50 help='UID of the user')
51 user_parser.add_argument('--shell', type='path',
52 help='Shell of user')
53 user_parser.add_argument('--home', type='path',
54 help='Home directory of user')
55 user_parser.add_argument('--primary_group', type=str,
56 help='Name of primary group for user')
57
58 group_parser = command_parsers.add_parser(
59 ACTION_INSTALL_GROUP, help='Install a group to a sysroot')
60 group_parser.add_argument('name', type=str,
61 help='Name of group to install.')
62 group_parser.add_argument('--gid', type=int, help='GID of the group')
63
64 # Both group and user parsers need to understand the target sysroot.
65 for sub_parser in (user_parser, group_parser):
66 sub_parser.add_argument(
67 'sysroot', type='path', help='The sysroot to install the user into')
68
69 options = parser.parse_args(argv)
70 options.Freeze()
71 return options
72
73
74def main(argv):
75 cros_build_lib.AssertInsideChroot()
76 options = GetOptions(argv)
77
78 if options.action == ACTION_GET_ENTRY:
79 db = user_db.UserDB(options.sysroot)
80 if options.database == USER_DB:
81 print(db.GetUserEntry(options.name, skip_lock=options.nolock))
82 else:
83 print(db.GetGroupEntry(options.name, skip_lock=options.nolock))
84 return 0
85
86 overlays = sysroot_lib.Sysroot(options.sysroot).GetStandardField(
87 sysroot_lib.STANDARD_FIELD_PORTDIR_OVERLAY).split()
88
89 # TODO(wiley) This process could be optimized to avoid reparsing these
90 # overlay databases each time.
91 account_db = accounts_lib.AccountDatabase()
92 for overlay_path in overlays:
93 database_path = os.path.join(overlay_path, ACCOUNT_DB_FILENAME)
94 if os.path.exists(database_path):
95 account_db.AddAccountsFromDatabase(database_path)
96
97 installed_users = user_db.UserDB(options.sysroot)
98
99 if options.action == ACTION_INSTALL_USER:
100 account_db.InstallUser(options.name, installed_users,
101 uid=options.uid, shell=options.shell,
102 homedir=options.home,
103 primary_group=options.primary_group)
104
105 homedir = account_db.users[options.name].home
106 homedir_path = os.path.join(options.sysroot, homedir)
107
108 if homedir != '/dev/null' and not os.path.exists(homedir_path):
109 osutils.SafeMakedirs(homedir_path, sudo=True)
110 uid = account_db.users[options.name].uid
111 cros_build_lib.SudoRunCommand(
112 ['chown', '%d:%d' % (uid, uid), homedir_path], print_cmd=False)
113
114 elif options.action == ACTION_INSTALL_GROUP:
115 account_db.InstallGroup(options.name, installed_users, gid=options.gid)
116 else:
117 cros_build_lib.Die('Unsupported account type: %s' % options.account_type)