diff options
-rw-r--r-- | Makefile-tests.am | 1 | ||||
-rw-r--r-- | doc/ostree-sections.txt | 1 | ||||
-rw-r--r-- | src/libostree/ostree-cmdprivate.c | 2 | ||||
-rw-r--r-- | src/libostree/ostree-repo-pull.c | 28 | ||||
-rw-r--r-- | src/libostree/ostree-repo.c | 52 | ||||
-rw-r--r-- | src/libostree/ostree-repo.h | 10 | ||||
-rw-r--r-- | src/libotutil/ot-fs-utils.c | 18 | ||||
-rw-r--r-- | src/libotutil/ot-fs-utils.h | 4 | ||||
-rw-r--r-- | src/ostree/ot-builtin-fsck.c | 20 | ||||
-rw-r--r-- | tests/test-oldstyle-partial.sh | 37 |
10 files changed, 153 insertions, 20 deletions
diff --git a/Makefile-tests.am b/Makefile-tests.am index bf584240..7350032f 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -48,6 +48,7 @@ testfiles = test-basic \ test-admin-locking \ test-repo-checkout-subpath \ test-reset-nonlinear \ + test-oldstyle-partial \ test-setuid \ test-delta \ test-xattrs \ diff --git a/doc/ostree-sections.txt b/doc/ostree-sections.txt index 9e2ef6c3..b75efc97 100644 --- a/doc/ostree-sections.txt +++ b/doc/ostree-sections.txt @@ -255,6 +255,7 @@ ostree_repo_write_content_finish ostree_repo_resolve_rev ostree_repo_list_refs ostree_repo_load_variant +ostree_repo_load_commit ostree_repo_load_variant_if_exists ostree_repo_load_file ostree_repo_load_object_stream diff --git a/src/libostree/ostree-cmdprivate.c b/src/libostree/ostree-cmdprivate.c index ea122434..99834937 100644 --- a/src/libostree/ostree-cmdprivate.c +++ b/src/libostree/ostree-cmdprivate.c @@ -21,6 +21,8 @@ #include "config.h" #include "ostree-cmdprivate.h" +#include "ostree-repo-private.h" +#include "ostree-core-private.h" #include "ostree-sysroot.h" #include "ostree-bootloader-grub2.h" diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 97c044f8..db91d1ec 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1126,10 +1126,12 @@ scan_one_metadata_object_c (OtPullData *pull_data, /* For commits, check whether we only had a partial fetch */ if (!do_scan && objtype == OSTREE_OBJECT_TYPE_COMMIT) { - g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (tmp_checksum); - struct stat stbuf; + OstreeRepoCommitState commitstate; - if (fstatat (pull_data->repo->repo_dir_fd, commitpartial_path, &stbuf, 0) == 0) + if (!ostree_repo_load_commit (pull_data->repo, tmp_checksum, NULL, &commitstate, error)) + goto out; + + if (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) { do_scan = TRUE; pull_data->commitpartial_exists = TRUE; @@ -2178,14 +2180,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, const char *checksum = value; g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum); - if (unlinkat (pull_data->repo->repo_dir_fd, commitpartial_path, 0) != 0) - { - if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - goto out; - } - } + if (!ot_ensure_unlinked_at (pull_data->repo->repo_dir_fd, commitpartial_path, 0)) + goto out; } g_hash_table_iter_init (&hash_iter, commits_to_fetch); while (g_hash_table_iter_next (&hash_iter, &key, &value)) @@ -2193,14 +2189,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, const char *commit = value; g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (commit); - if (unlinkat (pull_data->repo->repo_dir_fd, commitpartial_path, 0) != 0) - { - if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - goto out; - } - } + if (!ot_ensure_unlinked_at (pull_data->repo->repo_dir_fd, commitpartial_path, 0)) + goto out; } } diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 5499dc11..106298a4 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2652,6 +2652,58 @@ ostree_repo_load_variant (OstreeRepo *self, } /** + * ostree_repo_load_commit: + * @self: Repo + * @checksum: Commit checksum + * @out_commit: (out) (allow-none): Commit + * @out_state: (out) (allow-none): Commit state + * @error: Error + * + * A version of ostree_repo_load_variant() specialized to commits, + * capable of returning extended state information. Currently + * the only extended state is %OSTREE_REPO_COMMIT_STATE_PARTIAL, which + * means that only a sub-path of the commit is available. + */ +gboolean +ostree_repo_load_commit (OstreeRepo *self, + const char *checksum, + GVariant **out_variant, + OstreeRepoCommitState *out_state, + GError **error) +{ + gboolean ret = FALSE; + + if (out_variant) + { + if (!load_metadata_internal (self, OSTREE_OBJECT_TYPE_COMMIT, checksum, TRUE, + out_variant, NULL, NULL, NULL, error)) + goto out; + } + + if (out_state) + { + g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum); + struct stat stbuf; + + *out_state = 0; + + if (fstatat (self->repo_dir_fd, commitpartial_path, &stbuf, 0) == 0) + { + *out_state |= OSTREE_REPO_COMMIT_STATE_PARTIAL; + } + else if (errno != ENOENT) + { + glnx_set_error_from_errno (error); + goto out; + } + } + + ret = TRUE; + out: + return ret; +} + +/** * ostree_repo_list_objects: * @self: Repo * @flags: Flags controlling enumeration diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index e6614dfa..c882356a 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -280,6 +280,16 @@ gboolean ostree_repo_load_variant_if_exists (OstreeRepo *self, GVariant **out_variant, GError **error); +typedef enum { + OSTREE_REPO_COMMIT_STATE_PARTIAL = (1 << 0), +} OstreeRepoCommitState; + +gboolean ostree_repo_load_commit (OstreeRepo *self, + const char *checksum, + GVariant **out_commit, + OstreeRepoCommitState *out_state, + GError **error); + gboolean ostree_repo_load_file (OstreeRepo *self, const char *checksum, GInputStream **out_input, diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 040636bd..b0f41a64 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -22,6 +22,7 @@ #include "ot-fs-utils.h" #include "libgsystem.h" +#include "libglnx.h" #include <sys/xattr.h> #include <gio/gunixinputstream.h> @@ -188,3 +189,20 @@ ot_openat_read_stream (int dfd, out: return ret; } + +gboolean +ot_ensure_unlinked_at (int dfd, + const char *path, + GError **error) +{ + if (unlinkat (dfd, path, 0) != 0) + { + if (G_UNLIKELY (errno != ENOENT)) + { + glnx_set_error_from_errno (error); + return FALSE; + } + } + return TRUE; +} + diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index 0113da46..10686be6 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -57,4 +57,8 @@ gboolean ot_openat_read_stream (int dfd, GCancellable *cancellable, GError **error); +gboolean ot_ensure_unlinked_at (int dfd, + const char *path, + GError **error); + G_END_DECLS diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index ae1dcce4..8f340439 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -25,6 +25,7 @@ #include "ot-main.h" #include "ot-builtins.h" #include "ostree.h" +#include "ostree-cmdprivate.h" #include "otutil.h" static gboolean opt_quiet; @@ -242,6 +243,7 @@ ostree_builtin_fsck (int argc, char **argv, GCancellable *cancellable, GError ** GHashTableIter hash_iter; gpointer key, value; gboolean found_corruption = FALSE; + guint n_partial = 0; gs_unref_hashtable GHashTable *objects = NULL; gs_unref_hashtable GHashTable *commits = NULL; @@ -267,11 +269,22 @@ ostree_builtin_fsck (int argc, char **argv, GCancellable *cancellable, GError ** GVariant *serialized_key = key; const char *checksum; OstreeObjectType objtype; + OstreeRepoCommitState commitstate = 0; ostree_object_name_deserialize (serialized_key, &checksum, &objtype); if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - g_hash_table_insert (commits, g_variant_ref (serialized_key), serialized_key); + { + if (!ostree_repo_load_commit (repo, checksum, NULL, &commitstate, error)) + goto out; + + if (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) + { + n_partial++; + } + else + g_hash_table_insert (commits, g_variant_ref (serialized_key), serialized_key); + } } g_clear_pointer (&objects, (GDestroyNotify) g_hash_table_unref); @@ -284,6 +297,11 @@ ostree_builtin_fsck (int argc, char **argv, GCancellable *cancellable, GError ** cancellable, error)) goto out; + if (n_partial > 0) + { + g_print ("%u partial commits not verified\n", n_partial); + } + if (found_corruption) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, diff --git a/tests/test-oldstyle-partial.sh b/tests/test-oldstyle-partial.sh new file mode 100644 index 00000000..84460e97 --- /dev/null +++ b/tests/test-oldstyle-partial.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Copyright (C) 2015 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -e + +. $(dirname $0)/libtest.sh + +setup_fake_remote_repo1 "archive-z2" + +echo '1..1' + +cd ${test_tmpdir} +rm repo -rf +mkdir repo +${CMD_PREFIX} ostree --repo=repo init +${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo + +ostree --repo=repo pull origin main --subpath /baz +ostree fsck --repo=repo >fsck.out +assert_file_has_content fsck.out 'Verifying content integrity of 0 commit objects' +assert_file_has_content fsck.out '1 partial commits not verified' |