Skip to content

Commit

Permalink
Merge pull request #79 from cgwalters/wip/preserve-passwd
Browse files Browse the repository at this point in the history
compose: Support "preserve-passwd" option (enabled by default)
  • Loading branch information
cgwalters committed Dec 24, 2014
2 parents fc1a4b0 + f9e9c06 commit 526958a
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 0 deletions.
7 changes: 7 additions & 0 deletions doc/treefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ Treefile

Note this does not alter the RPM database, so `rpm -V` will complain.

* `preserve-passwd`: boolean, optional: Defaults to `true`. If enabled,
copy the `/etc/passwd` (and `/usr/lib/passwd`) files from the previous commit
if they exist. This helps ensure consistent uid/gid allocations across
builds. However, it does mean that removed users will exist in the `passwd`
database forever. It also does not help clients switch between unrelated
trees.

* `check-passwd`: Object, optional: Checks to run against the new passwd file
before accepting the tree. All the entries specified should exist (unless
ignored) and have the same values or the compose will fail. There are four
Expand Down
17 changes: 17 additions & 0 deletions src/rpmostree-compose-builtin-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,23 @@ rpmostree_compose_builtin_tree (int argc,
self->serialized_treefile = g_bytes_new_take (treefile_buf, len);
}

{
gboolean generate_from_previous = TRUE;

if (!_rpmostree_jsonutil_object_get_optional_boolean_member (treefile,
"preserve-passwd",
&generate_from_previous,
error))
goto out;

if (generate_from_previous)
{
if (!rpmostree_generate_passwd_from_previous (repo, yumroot, ref,
cancellable, error))
goto out;
}
}

if (!yuminstall (self, treefile, yumroot,
(char**)packages->pdata,
cancellable, error))
Expand Down
25 changes: 25 additions & 0 deletions src/rpmostree-json-parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,31 @@ _rpmostree_jsonutil_object_require_int_member (JsonObject *object,
return TRUE;
}

gboolean
_rpmostree_jsonutil_object_get_optional_boolean_member (JsonObject *object,
const char *member_name,
gboolean *out_value,
GError **error)
{
gboolean ret = FALSE;
JsonNode *node = json_object_get_member (object, member_name);

if (node != NULL)
{
if (json_node_get_value_type (node) != G_TYPE_BOOLEAN)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Member '%s' is not a boolean", member_name);
goto out;
}
*out_value = json_node_get_boolean (node);
}

ret = TRUE;
out:
return ret;
}

const char *
_rpmostree_jsonutil_array_require_string_element (JsonArray *array,
guint i,
Expand Down
6 changes: 6 additions & 0 deletions src/rpmostree-json-parsing.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ _rpmostree_jsonutil_object_require_int_member (JsonObject *object,
gint64 *out_val,
GError **error);

gboolean
_rpmostree_jsonutil_object_get_optional_boolean_member (JsonObject *object,
const char *member_name,
gboolean *out_value,
GError **error);

const char *
_rpmostree_jsonutil_array_require_string_element (JsonArray *array,
guint i,
Expand Down
103 changes: 103 additions & 0 deletions src/rpmostree-passwd-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,106 @@ rpmostree_check_groups (OstreeRepo *repo,
return rpmostree_check_passwd_groups (TRUE, repo, yumroot, treefile_dirpath,
treedata, cancellable, error);
}

static gboolean
concat_passwd_file (GFile *yumroot,
GFile *previous_commit,
const char *filename,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_free char *etc_subpath = g_strconcat ("etc/", filename, NULL);
gs_free char *usrlib_subpath = g_strconcat ("usr/lib/", filename, NULL);
gs_unref_object GFile *yumroot_etc = g_file_resolve_relative_path (yumroot, "etc");
gs_unref_object GFile *yumroot_dest = g_file_resolve_relative_path (yumroot, etc_subpath);
gs_unref_object GFile *orig_etc_content = g_file_resolve_relative_path (previous_commit, etc_subpath);
gs_unref_object GFile *orig_usrlib_content = g_file_resolve_relative_path (previous_commit, usrlib_subpath);
gs_unref_object GFileOutputStream *out = NULL;
gboolean have_etc, have_usr;

if (!gs_file_ensure_directory (yumroot_etc, TRUE, cancellable, error))
goto out;

have_etc = g_file_query_exists (orig_etc_content, NULL);
have_usr = g_file_query_exists (orig_usrlib_content, NULL);

if (!(have_etc || have_usr))
{
ret = TRUE;
goto out;
}

out = g_file_replace (yumroot_dest, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
cancellable, error);
if (!out)
goto out;

if (have_etc)
{
gs_unref_object GInputStream *src =
(GInputStream*)g_file_read (orig_etc_content, cancellable, error);
if (g_output_stream_splice ((GOutputStream*)out, src,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
cancellable, error ) < 0)
goto out;
}

if (have_usr)
{
gs_unref_object GInputStream *src =
(GInputStream*)g_file_read (orig_usrlib_content, cancellable, error);
if (g_output_stream_splice ((GOutputStream*)out, src,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
cancellable, error ) < 0)
goto out;
}

if (!g_output_stream_flush ((GOutputStream*)out, cancellable, error))
goto out;

ret = TRUE;
out:
return ret;
}


gboolean
rpmostree_generate_passwd_from_previous (OstreeRepo *repo,
GFile *yumroot,
const char *ref,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GError *temp_error = NULL;
gs_unref_object GFile *previous_root = NULL;
gs_unref_object GFile *yumroot_etc_group = g_file_resolve_relative_path (yumroot, "etc/group");
gs_unref_object GFile *out = NULL;

if (!ostree_repo_read_commit (repo, ref, &previous_root, NULL, NULL, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_clear_error (&temp_error);
ret = TRUE;
}
else
{
g_propagate_error (error, temp_error);
}
goto out;
}

if (!concat_passwd_file (yumroot, previous_root, "passwd",
cancellable, error))
goto out;

if (!concat_passwd_file (yumroot, previous_root, "group",
cancellable, error))
goto out;

ret = TRUE;
out:
return ret;
}
7 changes: 7 additions & 0 deletions src/rpmostree-passwd-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,10 @@ rpmostree_check_groups (OstreeRepo *repo,
JsonObject *treedata,
GCancellable *cancellable,
GError **error);

gboolean
rpmostree_generate_passwd_from_previous (OstreeRepo *repo,
GFile *yumroot,
const char *ref,
GCancellable *cancellable,
GError **error);

0 comments on commit 526958a

Please sign in to comment.