diff --git a/doc/treefile.md b/doc/treefile.md index 4c56b0a931..7ff64260ae 100644 --- a/doc/treefile.md +++ b/doc/treefile.md @@ -27,6 +27,10 @@ Treefile set; rpm-ostree will modify the `/etc/nsswitch.conf` in the target root to ensure that `/usr/lib/passwd` is used. + * `etc-group-members`: Array of strings, optional: Unix groups in this + list will be stored in `/etc/group` instead of `/usr/lib/group`. Use + this option for groups for which humans should be a member. + * `install-langs`: Array of strings, optional. This sets the RPM _install_langs macro. Set this to e.g. `["en_US", "fr_FR"]`. diff --git a/src/rpmostree-json-parsing.c b/src/rpmostree-json-parsing.c index 03f5de06fd..0911740b08 100644 --- a/src/rpmostree-json-parsing.c +++ b/src/rpmostree-json-parsing.c @@ -112,3 +112,20 @@ _rpmostree_jsonutil_append_string_array_to (JsonObject *object, return TRUE; } + +GHashTable * +_rpmostree_jsonutil_jsarray_strings_to_set (JsonArray *array) +{ + GHashTable *ret = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free); + guint i; + guint len = json_array_get_length (array); + + for (i = 0; i < len; i++) + { + const char *elt = json_array_get_string_element (array, i); + char *duped = g_strdup (elt); + g_hash_table_insert (ret, duped, duped); + } + + return ret; +} diff --git a/src/rpmostree-json-parsing.h b/src/rpmostree-json-parsing.h index 8f542eb19c..106132b4ba 100644 --- a/src/rpmostree-json-parsing.h +++ b/src/rpmostree-json-parsing.h @@ -46,4 +46,7 @@ _rpmostree_jsonutil_append_string_array_to (JsonObject *object, GCancellable *cancellable, GError **error); +GHashTable * +_rpmostree_jsonutil_jsarray_strings_to_set (JsonArray *array); + diff --git a/src/rpmostree-postprocess.c b/src/rpmostree-postprocess.c index 9f47fb416d..d7d9976ef6 100644 --- a/src/rpmostree-postprocess.c +++ b/src/rpmostree-postprocess.c @@ -596,6 +596,7 @@ typedef enum { static gboolean migrate_passwd_file_except_root (GFile *rootfs, MigrateKind kind, + GHashTable *preserve, GCancellable *cancellable, GError **error) { @@ -627,6 +628,8 @@ migrate_passwd_file_except_root (GFile *rootfs, struct group *gr = NULL; FILE *deststream; int r; + guint32 id; + const char *name; if (kind == MIGRATE_PASSWD) pw = fgetpwent (src_stream); @@ -645,11 +648,21 @@ migrate_passwd_file_except_root (GFile *rootfs, break; } - if ((pw && pw->pw_uid == 0) || - (gr && gr->gr_gid == 0)) - deststream = etcdest_stream; + deststream = usrdest_stream; + + if (pw) + { + id = pw->pw_uid; + name = pw->pw_name; + } else - deststream = usrdest_stream; + { + id = gr->gr_gid; + name = gr->gr_name; + } + + if (id == 0 || (preserve && g_hash_table_contains (preserve, name))) + deststream = etcdest_stream; if (pw) r = putpwent (pw, deststream); @@ -826,6 +839,7 @@ create_rootfs_from_yumroot_content (GFile *targetroot, gboolean ret = FALSE; gs_unref_object GFile *kernel_path = NULL; gs_unref_object GFile *initramfs_path = NULL; + gs_unref_hashtable GHashTable *preserve_groups_set = NULL; g_print ("Preparing kernel\n"); if (!do_kernel_prep (yumroot, cancellable, error)) @@ -836,10 +850,19 @@ create_rootfs_from_yumroot_content (GFile *targetroot, goto out; g_print ("Migrating /etc/passwd to /usr/lib/\n"); - if (!migrate_passwd_file_except_root (yumroot, MIGRATE_PASSWD, cancellable, error)) + if (!migrate_passwd_file_except_root (yumroot, MIGRATE_PASSWD, NULL, + cancellable, error)) goto out; + + if (json_object_has_member (treefile, "etc-group-members")) + { + JsonArray *etc_group_members = json_object_get_array_member (treefile, "etc-group-members"); + preserve_groups_set = _rpmostree_jsonutil_jsarray_strings_to_set (etc_group_members); + } + g_print ("Migrating /etc/group to /usr/lib/\n"); - if (!migrate_passwd_file_except_root (yumroot, MIGRATE_GROUP, cancellable, error)) + if (!migrate_passwd_file_except_root (yumroot, MIGRATE_GROUP, preserve_groups_set, + cancellable, error)) goto out; /* NSS configuration to look at the new files */