summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2017-11-20 13:16:35 +0000
committerAtomic Bot <atomic-devel@projectatomic.io>2017-12-14 14:18:44 +0000
commitfb7692bd448ef0a395485a79a050193e50e417ac (patch)
treef030cfe21a36eb9b4c782a1afc05e1351b2904c9
parent38152d71aa0fc1167313723ec190b65421324472 (diff)
downloadostree-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/ostree1
-rw-r--r--man/ostree-fsck.xml11
-rw-r--r--src/ostree/ot-builtin-fsck.c73
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;