diff options
author | Philip Withnall <withnall@endlessm.com> | 2017-11-20 13:16:35 +0000 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-12-14 14:18:44 +0000 |
commit | fb7692bd448ef0a395485a79a050193e50e417ac (patch) | |
tree | f030cfe21a36eb9b4c782a1afc05e1351b2904c9 | |
parent | 38152d71aa0fc1167313723ec190b65421324472 (diff) | |
download | ostree-fb7692bd448ef0a395485a79a050193e50e417ac.tar.gz |
ostree/fsck: Add --verify-back-refs option
This new option verifies that the refs listed in the ref-bindings for
each commit all point to that commit (i.e. there aren’t multiple commits
listing the same ref in their ref-bindings, and there aren’t any commits
with non-empty ref-bindings which aren’t pointed at by a ref).
This is useful when generating a new repository from scratch, but not
useful when adding new commits to an existing repository (since the old
commits will still, correctly, have ref-bindings from when the refs
pointed at them). That’s why it has to be enabled explicitly using
--verify-back-refs, rather than being on by default.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Closes: #1347
Approved by: cgwalters
-rw-r--r-- | bash/ostree | 1 | ||||
-rw-r--r-- | man/ostree-fsck.xml | 11 | ||||
-rw-r--r-- | src/ostree/ot-builtin-fsck.c | 73 |
3 files changed, 85 insertions, 0 deletions
diff --git a/bash/ostree b/bash/ostree index c132a43f..2a67d1aa 100644 --- a/bash/ostree +++ b/bash/ostree @@ -963,6 +963,7 @@ _ostree_fsck() { --add-tombstones --delete --quiet -q + --verify-back-refs " local options_with_args=" diff --git a/man/ostree-fsck.xml b/man/ostree-fsck.xml index 2cae92cf..f634933b 100644 --- a/man/ostree-fsck.xml +++ b/man/ostree-fsck.xml @@ -85,6 +85,17 @@ Boston, MA 02111-1307, USA. Add tombstone commit for referenced but missing commits. </para></listitem> </varlistentry> + + <varlistentry> + <term><option>--verify-back-refs</option></term> + <listitem><para> + Verify that all the refs listed in a commit’s ref-bindings + point to that commit. This cannot be used in repositories + where the target of refs is changed over time as new commits + are added, but can be used in repositories which are + regenerated from scratch for each commit. + </para></listitem> + </varlistentry> </variablelist> </refsect1> diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index 6cd9b457..3505f7b3 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -30,6 +30,7 @@ static gboolean opt_quiet; static gboolean opt_delete; static gboolean opt_add_tombstones; +static gboolean opt_verify_back_refs; /* ATTENTION: * Please remember to update the bash-completion script (bash/ostree) and @@ -40,6 +41,7 @@ static GOptionEntry options[] = { { "add-tombstones", 0, 0, G_OPTION_ARG_NONE, &opt_add_tombstones, "Add tombstones for missing commits", NULL }, { "quiet", 'q', 0, G_OPTION_ARG_NONE, &opt_quiet, "Only print error messages", NULL }, { "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Remove corrupted objects", NULL }, + { "verify-back-refs", 0, 0, G_OPTION_ARG_NONE, &opt_verify_back_refs, "Verify back-references", NULL }, { NULL } }; @@ -253,6 +255,77 @@ ostree_builtin_fsck (int argc, char **argv, OstreeCommandInvocation *invocation, if (!ostree_repo_load_commit (repo, checksum, &commit, &commitstate, error)) return FALSE; + /* If requested, check that all the refs listed in the ref-bindings + * for this commit resolve back to this commit. */ + if (opt_verify_back_refs) + { + g_autoptr(GVariant) metadata = g_variant_get_child_value (commit, 0); + + const char *collection_id = NULL; +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + if (!g_variant_lookup (metadata, + OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, + "&s", + &collection_id)) + collection_id = NULL; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + + g_autofree const char **refs = NULL; + if (g_variant_lookup (metadata, + OSTREE_COMMIT_META_KEY_REF_BINDING, + "^a&s", + &refs)) + { + for (const char **iter = refs; *iter != NULL; ++iter) + { + g_autofree char *checksum_for_ref = NULL; + +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + if (collection_id != NULL) + { + const OstreeCollectionRef collection_ref = { (char *) collection_id, (char *) *iter }; + if (!ostree_repo_resolve_collection_ref (repo, &collection_ref, + TRUE, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &checksum_for_ref, + cancellable, + error)) + return FALSE; + } + else +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + { + if (!ostree_repo_resolve_rev (repo, *iter, TRUE, + &checksum_for_ref, error)) + return FALSE; + } + + if (checksum_for_ref == NULL) + { + if (collection_id != NULL) + return glnx_throw (error, + "Collection–ref (%s, %s) in bindings for commit %s does not exist", + collection_id, *iter, checksum); + else + return glnx_throw (error, + "Ref ‘%s’ in bindings for commit %s does not exist", + *iter, checksum); + } + else if (g_strcmp0 (checksum_for_ref, checksum) != 0) + { + if (collection_id != NULL) + return glnx_throw (error, + "Collection–ref (%s, %s) in bindings for commit %s does not resolve to that commit", + collection_id, *iter, checksum); + else + return glnx_throw (error, + "Ref ‘%s’ in bindings for commit %s does not resolve to that commit", + *iter, checksum); + } + } + } + } + if (opt_add_tombstones) { GError *local_error = NULL; |