[systemd-devel] [PATCH 1/3] sysusers: allow separate alternate roots for configs and modifications
Ivan Shapovalov
intelfx100 at gmail.com
Wed Feb 25 15:46:23 PST 2015
This is useful, for example, to create system accounts on an initramfs
using the host's configuration.
---
src/sysusers/sysusers.c | 97 +++++++++++++++++++++++++++++++++----------------
1 file changed, 66 insertions(+), 31 deletions(-)
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 0b5668a..9d39bd4 100644
--- a/src/sysusers/sysusers.c
+++ b/src/sysusers/sysusers.c
@@ -64,7 +64,7 @@ typedef struct Item {
bool todo_group:1;
} Item;
-static char *arg_root = NULL;
+static char *arg_root_config = NULL, *arg_root_dest = NULL;
static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysusers");
@@ -79,7 +79,7 @@ static uid_t search_uid = UID_INVALID;
static UidRange *uid_range = NULL;
static unsigned n_uid_range = 0;
-#define fix_root(x) (arg_root ? strjoina(arg_root, x) : x)
+#define fix_root_dest(x) (arg_root_dest ? strjoina(arg_root_dest, x) : x)
static int load_user_database(void) {
_cleanup_fclose_ FILE *f = NULL;
@@ -87,7 +87,7 @@ static int load_user_database(void) {
struct passwd *pw;
int r;
- passwd_path = fix_root("/etc/passwd");
+ passwd_path = fix_root_dest("/etc/passwd");
f = fopen(passwd_path, "re");
if (!f)
return errno == ENOENT ? 0 : -errno;
@@ -139,7 +139,7 @@ static int load_group_database(void) {
struct group *gr;
int r;
- group_path = fix_root("/etc/group");
+ group_path = fix_root_dest("/etc/group");
f = fopen(group_path, "re");
if (!f)
return errno == ENOENT ? 0 : -errno;
@@ -368,7 +368,7 @@ static int write_files(void) {
_cleanup_fclose_ FILE *original = NULL;
/* First we update the actual group list file */
- group_path = fix_root("/etc/group");
+ group_path = fix_root_dest("/etc/group");
r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp);
if (r < 0)
goto finish;
@@ -447,7 +447,7 @@ static int write_files(void) {
}
/* OK, now also update the shadow file for the group list */
- gshadow_path = fix_root("/etc/gshadow");
+ gshadow_path = fix_root_dest("/etc/gshadow");
r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp);
if (r < 0)
goto finish;
@@ -513,7 +513,7 @@ static int write_files(void) {
long lstchg;
/* First we update the user database itself */
- passwd_path = fix_root("/etc/passwd");
+ passwd_path = fix_root_dest("/etc/passwd");
r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
if (r < 0)
goto finish;
@@ -598,7 +598,7 @@ static int write_files(void) {
}
/* The we update the shadow database */
- shadow_path = fix_root("/etc/shadow");
+ shadow_path = fix_root_dest("/etc/shadow");
r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
if (r < 0)
goto finish;
@@ -772,7 +772,7 @@ static int uid_is_ok(uid_t uid, const char *name) {
return 0;
/* Let's also check via NSS, to avoid UID clashes over LDAP and such, just in case */
- if (!arg_root) {
+ if (!arg_root_dest) {
errno = 0;
p = getpwuid(uid);
if (p)
@@ -792,10 +792,10 @@ static int uid_is_ok(uid_t uid, const char *name) {
return 1;
}
-static int root_stat(const char *p, struct stat *st) {
+static int root_dest_stat(const char *p, struct stat *st) {
const char *fix;
- fix = fix_root(p);
+ fix = fix_root_dest(p);
if (stat(fix, st) < 0)
return -errno;
@@ -811,7 +811,7 @@ static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
assert(i);
/* First, try to get the gid directly */
- if (_gid && i->gid_path && root_stat(i->gid_path, &st) >= 0) {
+ if (_gid && i->gid_path && root_dest_stat(i->gid_path, &st) >= 0) {
gid = st.st_gid;
found_gid = true;
}
@@ -819,7 +819,7 @@ static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
/* Then, try to get the uid directly */
if ((_uid || (_gid && !found_gid))
&& i->uid_path
- && root_stat(i->uid_path, &st) >= 0) {
+ && root_dest_stat(i->uid_path, &st) >= 0) {
uid = st.st_uid;
found_uid = true;
@@ -837,7 +837,7 @@ static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
if (found_gid) {
uid = (uid_t) gid;
found_uid = true;
- } else if (root_stat(i->gid_path, &st) >= 0) {
+ } else if (root_dest_stat(i->gid_path, &st) >= 0) {
uid = (uid_t) st.st_gid;
found_uid = true;
}
@@ -875,7 +875,7 @@ static int add_user(Item *i) {
return 0;
}
- if (!arg_root) {
+ if (!arg_root_dest) {
struct passwd *p;
struct spwd *sp;
@@ -999,7 +999,7 @@ static int gid_is_ok(gid_t gid) {
if (hashmap_contains(database_uid, UID_TO_PTR(gid)))
return 0;
- if (!arg_root) {
+ if (!arg_root_dest) {
errno = 0;
g = getgrgid(gid);
if (g)
@@ -1034,7 +1034,7 @@ static int add_group(Item *i) {
}
/* Also check NSS */
- if (!arg_root) {
+ if (!arg_root_dest) {
struct group *g;
errno = 0;
@@ -1691,7 +1691,7 @@ static int read_config_file(const char *fn, bool ignore_enoent) {
if (streq(fn, "-"))
f = stdin;
else {
- r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf);
+ r = search_and_fopen_nulstr(fn, "re", arg_root_config, conf_file_dirs, &rf);
if (r < 0) {
if (ignore_enoent && r == -ENOENT)
return 0;
@@ -1752,25 +1752,46 @@ static void help(void) {
"Creates system user accounts.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
- " --root=PATH Operate on an alternate filesystem root\n"
+ " --root=PATH Operate on an alternate filesystem root (equivalent to a combination of --dest-root and --config-root)\n"
+ " --dest-root=PATH Create user accounts on an alternate filesystem root\n"
+ " --config-root=PATH Search for the configuration files on an alternate filesystem root\n"
, program_invocation_short_name);
}
+static int set_arg_root(char **arg_root, const char *option)
+{
+ assert(arg_root);
+ assert(option);
+
+ free(*arg_root);
+ *arg_root = path_make_absolute_cwd(option);
+ if(!*arg_root)
+ return log_oom();
+
+ path_kill_slashes(*arg_root);
+
+ return 0;
+}
+
static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_ROOT,
+ ARG_ROOT_CONFIG,
+ ARG_ROOT_DEST
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, ARG_VERSION },
+ { "root", required_argument, NULL, ARG_ROOT },
+ { "dest-root", required_argument, NULL, ARG_ROOT_DEST },
+ { "config-root", required_argument, NULL, ARG_ROOT_CONFIG },
{}
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
@@ -1789,12 +1810,25 @@ static int parse_argv(int argc, char *argv[]) {
return 0;
case ARG_ROOT:
- free(arg_root);
- arg_root = path_make_absolute_cwd(optarg);
- if (!arg_root)
- return log_oom();
+ r = set_arg_root(&arg_root_config, optarg);
+ if (r < 0)
+ return r;
- path_kill_slashes(arg_root);
+ r = set_arg_root(&arg_root_dest, optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_ROOT_CONFIG:
+ r = set_arg_root(&arg_root_config, optarg);
+ if (r < 0)
+ return r;
+ break;
+
+ case ARG_ROOT_DEST:
+ r = set_arg_root(&arg_root_dest, optarg);
+ if (r < 0)
+ return r;
break;
case '?':
@@ -1843,7 +1877,7 @@ int main(int argc, char *argv[]) {
_cleanup_strv_free_ char **files = NULL;
char **f;
- r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
+ r = conf_files_list_nulstr(&files, ".conf", arg_root_config, conf_file_dirs);
if (r < 0) {
log_error_errno(r, "Failed to enumerate sysusers.d files: %m");
goto finish;
@@ -1869,7 +1903,7 @@ int main(int argc, char *argv[]) {
if (r < 0)
goto finish;
- lock = take_password_lock(arg_root);
+ lock = take_password_lock(arg_root_dest);
if (lock < 0) {
log_error_errno(lock, "Failed to take lock: %m");
goto finish;
@@ -1918,7 +1952,8 @@ finish:
free_database(database_user, database_uid);
free_database(database_group, database_gid);
- free(arg_root);
+ free(arg_root_config);
+ free(arg_root_dest);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
--
2.3.0
More information about the systemd-devel
mailing list