From 73fa43abc71df6a9c77c4cb009418714fb6d8ca5 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 14 Sep 2017 18:53:57 +0000 Subject: [PATCH 01/78] build-sys: Post-release version bump Closes: #1175 Approved by: cgwalters --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 2461f4d0..27e1a83d 100644 --- a/configure.ac +++ b/configure.ac @@ -4,10 +4,10 @@ dnl update libostree-released.sym from libostree-devel.sym, and update the check dnl in test-symbols.sh, and also set is_release_build=yes below. Then make dnl another post-release commit to bump the version, and set is_release_build=no. m4_define([year_version], [2017]) -m4_define([release_version], [11]) +m4_define([release_version], [12]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=yes +is_release_build=no AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) From 74996202544883ae2dc49407f44b05a09f5bc311 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 12 Sep 2017 16:58:58 -0400 Subject: [PATCH 02/78] lib/repo: Port gpg signing function to new code style We already had all of the autocleanups ready for this. Closes: #1164 Approved by: jlebon --- src/libostree/ostree-repo.c | 90 +++++++++++-------------------------- 1 file changed, 27 insertions(+), 63 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 0a7cf3e3..08403599 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4191,88 +4191,52 @@ sign_data (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_auto(GLnxTmpfile) tmpf = { 0, }; - g_autoptr(GOutputStream) tmp_signature_output = NULL; - gpgme_ctx_t context = NULL; - g_autoptr(GBytes) ret_signature = NULL; - gpgme_error_t err; - gpgme_key_t key = NULL; - gpgme_data_t commit_buffer = NULL; - gpgme_data_t signature_buffer = NULL; - g_autoptr(GMappedFile) signature_file = NULL; - if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) - goto out; - tmp_signature_output = g_unix_output_stream_new (tmpf.fd, FALSE); + return FALSE; + g_autoptr(GOutputStream) tmp_signature_output = g_unix_output_stream_new (tmpf.fd, FALSE); - context = ot_gpgme_new_ctx (homedir, error); + g_auto(gpgme_ctx_t) context = ot_gpgme_new_ctx (homedir, error); if (!context) - goto out; + return FALSE; /* Get the secret keys with the given key id */ - err = gpgme_get_key (context, key_id, &key, 1); + g_auto(gpgme_key_t) key = NULL; + gpgme_error_t err = gpgme_get_key (context, key_id, &key, 1); if (gpgme_err_code (err) == GPG_ERR_EOF) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No gpg key found with ID %s (homedir: %s)", key_id, - homedir ? homedir : ""); - goto out; - } + return glnx_throw (error, "No gpg key found with ID %s (homedir: %s)", key_id, + homedir ? homedir : ""); else if (err != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Unable to lookup key ID %s", key_id); - goto out; - } + return ot_gpgme_throw (err, error, "Unable to lookup key ID %s", key_id); /* Add the key to the context as a signer */ if ((err = gpgme_signers_add (context, key)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Error signing commit"); - goto out; - } + return ot_gpgme_throw (err, error, "Error signing commit"); - { - gsize len; - const char *buf = g_bytes_get_data (input_data, &len); - if ((err = gpgme_data_new_from_mem (&commit_buffer, buf, len, FALSE)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Failed to create buffer from commit file"); - goto out; - } - } - - signature_buffer = ot_gpgme_data_output (tmp_signature_output); + /* Get a gpg buffer from the commit */ + g_auto(gpgme_data_t) commit_buffer = NULL; + gsize len; + const char *buf = g_bytes_get_data (input_data, &len); + if ((err = gpgme_data_new_from_mem (&commit_buffer, buf, len, FALSE)) != GPG_ERR_NO_ERROR) + return ot_gpgme_throw (err, error, "Failed to create buffer from commit file"); + /* Sign it */ + g_auto(gpgme_data_t) signature_buffer = ot_gpgme_data_output (tmp_signature_output); if ((err = gpgme_op_sign (context, commit_buffer, signature_buffer, GPGME_SIG_MODE_DETACH)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Failure signing commit file"); - goto out; - } - + return ot_gpgme_throw (err, error, "Failure signing commit file"); if (!g_output_stream_close (tmp_signature_output, cancellable, error)) - goto out; - - signature_file = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); + return FALSE; + + /* Return a mmap() reference */ + g_autoptr(GMappedFile) signature_file = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); if (!signature_file) - goto out; - ret_signature = g_mapped_file_get_bytes (signature_file); - - ret = TRUE; + return FALSE; + if (out_signature) - *out_signature = g_steal_pointer (&ret_signature); -out: - if (commit_buffer) - gpgme_data_release (commit_buffer); - if (signature_buffer) - gpgme_data_release (signature_buffer); - if (key) - gpgme_key_release (key); - if (context) - gpgme_release (context); - return ret; + *out_signature = g_mapped_file_get_bytes (signature_file); + return TRUE; } /** From c32f234e9a63396725e98792dc2c4373504b44ac Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 13 Sep 2017 16:22:18 -0400 Subject: [PATCH 03/78] lib/checkout: Do UNION_FILES via atomic renameat() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I was looking at fixing an `rpm-ostree livefs` bug where we need to replace `/usr/lib/passwd`. It's obviously bad if that temporarily disappears 😉. My plan is to do a subpath checkout of just `/usr/lib/{passwd,group}`. Make this atomic (i.e. file always exists) by changing the logic to create a temporary link in repo/tmp, then rename() it into place. A bonus here is we kill one of the very few (only?) non-error-cleanup i.e. "non-linear" `goto`s in the ostree codebase. Closes: #1171 Approved by: jlebon --- src/libostree/ostree-repo-checkout.c | 76 +++++++++++++++++++++------- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 868cd186..7e36e689 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -338,6 +338,41 @@ typedef enum { HARDLINK_RESULT_LINKED } HardlinkResult; +/* Used for OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES. In + * order to atomically replace a target, we add a new link + * in self->tmp_dir_fd, with a name placed into the mutable + * buffer @tmpname. + */ +static gboolean +hardlink_add_tmp_name (OstreeRepo *self, + int srcfd, + const char *loose_path, + char *tmpname, + GCancellable *cancellable, + GError **error) +{ + const int max_attempts = 128; + guint i; + + for (i = 0; i < max_attempts; i++) + { + glnx_gen_temp_name (tmpname); + if (linkat (srcfd, loose_path, self->tmp_dir_fd, tmpname, 0) < 0) + { + if (errno == EEXIST) + continue; + else + return glnx_throw_errno_prefix (error, "linkat"); + } + else + break; + } + if (i == max_attempts) + return glnx_throw (error, "Exhausted attempts to make temporary hardlink"); + + return TRUE; +} + static gboolean checkout_file_hardlink (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options, @@ -353,7 +388,6 @@ checkout_file_hardlink (OstreeRepo *self, int srcfd = _ostree_repo_mode_is_bare (self->mode) ? self->objects_dir_fd : self->uncompressed_objects_dir_fd; - again: if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) == 0) ret_result = HARDLINK_RESULT_LINKED; else if (!options->no_copy_fallback && (errno == EMLINK || errno == EXDEV || errno == EPERM)) @@ -380,27 +414,20 @@ checkout_file_hardlink (OstreeRepo *self, ret_result = HARDLINK_RESULT_SKIP_EXISTED; break; case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES: - { - /* Idiocy, from man rename(2) - * - * "If oldpath and newpath are existing hard links referring to - * the same file, then rename() does nothing, and returns a - * success status." - * - * So we can't make this atomic. - */ - (void) unlinkat (destination_dfd, destination_name, 0); - goto again; - } case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL: { - /* In this mode, we error out on EEXIST *unless* the files are already - * hardlinked, which is what rpm-ostree wants for package layering. - * https://github.com/projectatomic/rpm-ostree/issues/982 + /* In both union-files and union-identical, see if the src/target are + * already hardlinked. If they are, we're done. * + * If not, for union-identical we error out, which is what + * rpm-ostree wants for package layering. + * https://github.com/projectatomic/rpm-ostree/issues/982 * This should be similar to the librpm version: * https://github.com/rpm-software-management/rpm/blob/e3cd2bc85e0578f158d14e6f9624eb955c32543b/lib/rpmfi.c#L921 * in rpmfilesCompare(). + * + * For union-files, we make a temporary link, then rename() it + * into place. */ struct stat src_stbuf; if (!glnx_fstatat (srcfd, loose_path, &src_stbuf, @@ -413,10 +440,25 @@ checkout_file_hardlink (OstreeRepo *self, const gboolean is_identical = (src_stbuf.st_dev == dest_stbuf.st_dev && src_stbuf.st_ino == dest_stbuf.st_ino); + if (is_identical) ret_result = HARDLINK_RESULT_SKIP_EXISTED; + else if (options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) + { + char *tmpname = strdupa ("checkout-union-XXXXXX"); + /* Make a link with a temp name */ + if (!hardlink_add_tmp_name (self, srcfd, loose_path, tmpname, cancellable, error)) + return FALSE; + /* Rename it into place */ + if (!glnx_renameat (self->tmp_dir_fd, tmpname, destination_dfd, destination_name, error)) + return FALSE; + ret_result = HARDLINK_RESULT_LINKED; + } else - return glnx_throw_errno_prefix (error, "Hardlinking %s to %s", loose_path, destination_name); + { + g_assert_cmpint (options->overwrite_mode, ==, OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL); + return glnx_throw_errno_prefix (error, "Hardlinking %s to %s", loose_path, destination_name); + } break; } } From 0488b4870e80ef575d8b0edf6f2a9e5ad54bf4df Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 14 Sep 2017 15:10:54 -0400 Subject: [PATCH 04/78] lib/pull: Drop partial fetch code from libsoup backend Doing this in prep for libglnx tmpdir porting, but I think we should also do this because the partial fetch code IMO was never fully baked; among other things it was never integrated into the scheme we came up with for "boot id sync" that we use for complete/staged objects. There's a lot of complexity here that while we have some coverage for, I think we need to refocus on the core functionality. The libcurl backend doesn't have an equivalent to this today. In particular for small objects, this is simply overly complex. The downside is clearly for large objects like FAH's 61MB initramfs; not being able to resume fetches of those is unfortunate. In practice though, I think most people should be using deltas, and we need to make sure deltas work for large objects anyways. Further ultimately the peer-to-peer work should help a lot for people with truly unreliable connections. Closes: #1176 Approved by: jlebon --- src/libostree/ostree-fetcher-curl.c | 5 +- src/libostree/ostree-fetcher-soup.c | 184 ++++++++-------------------- src/libostree/ostree-fetcher-util.h | 10 ++ src/libostree/ostree-repo-commit.c | 7 -- src/libostree/ostree-repo-private.h | 1 - src/libostree/ostree-repo.c | 3 +- 6 files changed, 65 insertions(+), 145 deletions(-) diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index 57118f9c..e3fd1a12 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -379,14 +379,13 @@ check_multi_info (OstreeFetcher *fetcher) g_autoptr(GError) local_error = NULL; GError **error = &local_error; - /* TODO - share file naming with soup, and fix it */ g_autofree char *tmpfile_path = - g_compute_checksum_for_string (G_CHECKSUM_SHA256, - eff_url, strlen (eff_url)); + ostree_fetcher_generate_url_tmpname (eff_url); if (!ensure_tmpfile (req, error)) { g_task_return_error (task, g_steal_pointer (&local_error)); } + /* This should match the libsoup chmod */ else if (fchmod (req->tmpf.fd, 0644) < 0) { glnx_set_error_from_errno (error); diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index e8185591..c9eaef7a 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -55,10 +55,7 @@ typedef struct { volatile gint running; GError *initialization_error; /* Any failure to load the db */ - int tmpdir_dfd; char *remote_name; - char *tmpdir_name; - GLnxLockFile tmpdir_lock; int base_tmpdir_dfd; GVariant *extra_headers; @@ -94,7 +91,7 @@ typedef struct { gboolean is_membuf; OstreeFetcherRequestFlags flags; GInputStream *request_body; - char *out_tmpfile; + GLnxTmpfile tmpf; GOutputStream *out_stream; guint64 max_size; @@ -155,17 +152,6 @@ thread_closure_unref (ThreadClosure *thread_closure) g_clear_pointer (&thread_closure->extra_headers, (GDestroyNotify)g_variant_unref); - if (thread_closure->tmpdir_dfd != -1) - close (thread_closure->tmpdir_dfd); - - /* Note: We don't remove the tmpdir here, because that would cause - us to not reuse it on resume. This happens because we use two - fetchers for each pull, so finalizing the first one would remove - all the files to be resumed from the previous second one */ - - g_free (thread_closure->tmpdir_name); - glnx_release_lock_file (&thread_closure->tmpdir_lock); - g_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref); g_mutex_clear (&thread_closure->output_stream_set_lock); @@ -210,7 +196,7 @@ pending_uri_unref (OstreeFetcherPendingURI *pending) g_free (pending->filename); g_clear_object (&pending->request); g_clear_object (&pending->request_body); - g_free (pending->out_tmpfile); + glnx_tmpfile_clear (&pending->tmpf); g_clear_object (&pending->out_stream); g_free (pending); } @@ -477,59 +463,7 @@ session_thread_request_uri (ThreadClosure *thread_closure, } else { - g_autofree char *uristring - = soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); - g_autofree char *tmpfile = NULL; - struct stat stbuf; - gboolean exists; - - /* The tmp directory is lazily created for each fetcher instance, - * since it may require superuser permissions and some instances - * only need _ostree_fetcher_request_uri_to_membuf() which keeps - * everything in memory buffers. */ - if (thread_closure->tmpdir_name == NULL) - { - if (!_ostree_repo_allocate_tmpdir (thread_closure->base_tmpdir_dfd, - OSTREE_REPO_TMPDIR_FETCHER, - &thread_closure->tmpdir_name, - &thread_closure->tmpdir_dfd, - &thread_closure->tmpdir_lock, - NULL, - cancellable, - &local_error)) - { - g_task_return_error (task, local_error); - return; - } - } - - tmpfile = g_compute_checksum_for_string (G_CHECKSUM_SHA256, uristring, strlen (uristring)); - - if (fstatat (thread_closure->tmpdir_dfd, tmpfile, &stbuf, AT_SYMLINK_NOFOLLOW) == 0) - exists = TRUE; - else - { - if (errno == ENOENT) - exists = FALSE; - else - { - glnx_set_error_from_errno (&local_error); - g_task_return_error (task, local_error); - return; - } - } - - if (SOUP_IS_REQUEST_HTTP (pending->request)) - { - glnx_unref_object SoupMessage *msg = NULL; - msg = soup_request_http_get_message ((SoupRequestHTTP*) pending->request); - if (exists && stbuf.st_size > 0) - soup_message_headers_set_range (msg->request_headers, stbuf.st_size, -1); - } - pending->out_tmpfile = tmpfile; - tmpfile = NULL; /* Transfer ownership */ - - start_pending_request (thread_closure, task); + start_pending_request (thread_closure, task); } } @@ -658,7 +592,6 @@ _ostree_fetcher_constructed (GObject *object) { OstreeFetcher *self = OSTREE_FETCHER (object); g_autoptr(GMainContext) main_context = NULL; - GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; const char *http_proxy; main_context = g_main_context_new (); @@ -668,8 +601,6 @@ _ostree_fetcher_constructed (GObject *object) self->thread_closure->main_context = g_main_context_ref (main_context); self->thread_closure->running = 1; self->thread_closure->transfer_gzip = (self->config_flags & OSTREE_FETCHER_FLAGS_TRANSFER_GZIP) != 0; - self->thread_closure->tmpdir_dfd = -1; - self->thread_closure->tmpdir_lock = empty_lockfile; self->thread_closure->outstanding = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)pending_uri_unref); self->thread_closure->output_stream_set = g_hash_table_new_full (NULL, NULL, @@ -749,7 +680,7 @@ _ostree_fetcher_new (int tmpdir_dfd, int _ostree_fetcher_get_dfd (OstreeFetcher *fetcher) { - return fetcher->thread_closure->tmpdir_dfd; + return fetcher->thread_closure->base_tmpdir_dfd; } void @@ -874,13 +805,8 @@ finish_stream (OstreeFetcherPendingURI *pending, if (!pending->is_membuf) { - if (fstatat (pending->thread_closure->tmpdir_dfd, - pending->out_tmpfile, - &stbuf, AT_SYMLINK_NOFOLLOW) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + if (!glnx_fstat (pending->tmpf.fd, &stbuf, error)) + goto out; } pending->state = OSTREE_FETCHER_STATE_COMPLETE; @@ -973,11 +899,39 @@ on_stream_read (GObject *object, pending = g_task_get_task_data (task); cancellable = g_task_get_cancellable (task); + /* Only open the output stream on demand to ensure we use as + * few file descriptors as possible. + */ + if (!pending->out_stream) + { + if (!pending->is_membuf) + { + if (!glnx_open_tmpfile_linkable_at (pending->thread_closure->base_tmpdir_dfd, ".", + O_WRONLY | O_CLOEXEC, &pending->tmpf, &local_error)) + goto out; + /* This should match the libcurl chmod */ + if (!glnx_fchmod (pending->tmpf.fd, 0644, &local_error)) + goto out; + pending->out_stream = g_unix_output_stream_new (pending->tmpf.fd, FALSE); + } + else + { + pending->out_stream = g_memory_output_stream_new_resizable (); + } + + g_mutex_lock (&pending->thread_closure->output_stream_set_lock); + g_hash_table_add (pending->thread_closure->output_stream_set, + g_object_ref (pending->out_stream)); + g_mutex_unlock (&pending->thread_closure->output_stream_set_lock); + } + + /* Get a GBytes buffer */ bytes = g_input_stream_read_bytes_finish ((GInputStream*)object, result, &local_error); if (!bytes) goto out; - bytes_read = g_bytes_get_size (bytes); + + /* Was this the end of the stream? */ if (bytes_read == 0) { if (!finish_stream (pending, cancellable, &local_error)) @@ -990,14 +944,24 @@ on_stream_read (GObject *object, } else { - g_task_return_pointer (task, - g_strdup (pending->out_tmpfile), - (GDestroyNotify) g_free); + g_autofree char *uristring = + soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); + g_autofree char *tmpfile_path = + ostree_fetcher_generate_url_tmpname (uristring); + if (!glnx_link_tmpfile_at (&pending->tmpf, GLNX_LINK_TMPFILE_REPLACE, + pending->thread_closure->base_tmpdir_dfd, tmpfile_path, + &local_error)) + g_task_return_error (task, g_steal_pointer (&local_error)); + else + g_task_return_pointer (task, + g_steal_pointer (&tmpfile_path), + (GDestroyNotify) g_free); } remove_pending (pending); } else { + /* Verify max size */ if (pending->max_size > 0) { if (bytes_read > pending->max_size || @@ -1011,7 +975,7 @@ on_stream_read (GObject *object, goto out; } } - + pending->current_size += bytes_read; /* We do this instead of _write_bytes_async() as that's not @@ -1063,19 +1027,7 @@ on_request_sent (GObject *object, if (SOUP_IS_REQUEST_HTTP (object)) { msg = soup_request_http_get_message ((SoupRequestHTTP*) object); - if (!pending->is_membuf && - msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) - { - // We already have the whole file, so just use it. - pending->state = OSTREE_FETCHER_STATE_COMPLETE; - (void) g_input_stream_close (pending->request_body, NULL, NULL); - g_task_return_pointer (task, - g_strdup (pending->out_tmpfile), - (GDestroyNotify) g_free); - remove_pending (pending); - goto out; - } - else if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { /* is there another mirror we can try? */ if (pending->mirrorlist_idx + 1 < pending->mirrorlist->len) @@ -1091,8 +1043,8 @@ on_request_sent (GObject *object, } else { - g_autofree char *uristring - = soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); + g_autofree char *uristring = + soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); GIOErrorEnum code; switch (msg->status_code) @@ -1143,38 +1095,6 @@ on_request_sent (GObject *object, pending->content_length = soup_request_get_content_length (pending->request); - if (!pending->is_membuf) - { - int oflags = O_CREAT | O_WRONLY | O_CLOEXEC; - int fd; - - /* If we got partial content, we can append; if the server - * ignored our range request, we need to truncate. - */ - if (msg && msg->status_code == SOUP_STATUS_PARTIAL_CONTENT) - oflags |= O_APPEND; - else - oflags |= O_TRUNC; - - fd = openat (pending->thread_closure->tmpdir_dfd, - pending->out_tmpfile, oflags, 0666); - if (fd == -1) - { - glnx_set_error_from_errno (&local_error); - goto out; - } - pending->out_stream = g_unix_output_stream_new (fd, TRUE); - } - else - { - pending->out_stream = g_memory_output_stream_new_resizable (); - } - - g_mutex_lock (&pending->thread_closure->output_stream_set_lock); - g_hash_table_add (pending->thread_closure->output_stream_set, - g_object_ref (pending->out_stream)); - g_mutex_unlock (&pending->thread_closure->output_stream_set_lock); - g_input_stream_read_bytes_async (pending->request_body, 8192, G_PRIORITY_DEFAULT, cancellable, diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h index c099a872..67b8f2f3 100644 --- a/src/libostree/ostree-fetcher-util.h +++ b/src/libostree/ostree-fetcher-util.h @@ -26,6 +26,16 @@ G_BEGIN_DECLS +/* FIXME - delete this and replace by having fetchers simply + * return O_TMPFILE fds, not file paths. + */ +static inline char * +ostree_fetcher_generate_url_tmpname (const char *url) +{ + return g_compute_checksum_for_string (G_CHECKSUM_SHA256, + url, strlen (url)); +} + gboolean _ostree_fetcher_mirrored_request_to_membuf (OstreeFetcher *fetcher, GPtrArray *mirrorlist, const char *filename, diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 5d28dca8..f15e05d2 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1284,13 +1284,6 @@ cleanup_tmpdir (OstreeRepo *self, if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error)) return glnx_prefix_error (error, "Removing %s", dent->d_name); } - /* FIXME - move OSTREE_REPO_TMPDIR_FETCHER underneath the - * staging/boot-id scheme as well, since all of the "did it get - * fsync'd" concerns apply to that as well. Then we can skip - * this special case. - */ - else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_FETCHER)) - continue; else { /* Now we do time-based cleanup. Ignore it if it's somehow diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 865cb120..5d2beaeb 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -205,7 +205,6 @@ _ostree_repo_memory_cache_ref_destroy (OstreeRepoMemoryCacheRef *state); G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeRepoMemoryCacheRef, _ostree_repo_memory_cache_ref_destroy) #define OSTREE_REPO_TMPDIR_STAGING "staging-" -#define OSTREE_REPO_TMPDIR_FETCHER "fetcher-" gboolean _ostree_repo_allocate_tmpdir (int tmpdir_dfd, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 08403599..18c7577c 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -5061,8 +5061,7 @@ ostree_repo_regenerate_summary (OstreeRepo *self, gboolean _ostree_repo_is_locked_tmpdir (const char *filename) { - return g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_STAGING) || - g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_FETCHER); + return g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_STAGING); } gboolean From 1b430a776486d68be2d16a0ec53ad5512c604988 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 15 Sep 2017 15:32:55 +0100 Subject: [PATCH 05/78] tests: Fix JavaScript tests with gjs 1.50.0 In recent gjs, you can't declare a variable with "let" multiple times. Signed-off-by: Simon McVittie Closes: #1178 Approved by: cgwalters --- tests/corrupt-repo-ref.js | 1 - tests/test-sysroot.js | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/corrupt-repo-ref.js b/tests/corrupt-repo-ref.js index c5f28062..bcde86b0 100755 --- a/tests/corrupt-repo-ref.js +++ b/tests/corrupt-repo-ref.js @@ -47,7 +47,6 @@ function listObjectChecksumsRecurse(dir, allObjects) { e.close(null); } -let [,commit] = repo.resolve_rev(refToCorrupt, false); let [,root,commit] = repo.read_commit(refToCorrupt, null); let allObjects = {}; allObjects[commit + '.commit'] = true; diff --git a/tests/test-sysroot.js b/tests/test-sysroot.js index 40397fe9..e7250a8c 100755 --- a/tests/test-sysroot.js +++ b/tests/test-sysroot.js @@ -97,9 +97,9 @@ assertEquals(deploymentPath.query_exists(null), false); //// Ok, redeploy, then add a new revision upstream and pull it -let [,deployment] = sysroot.deploy_tree('testos', rev, origin, - mergeDeployment, null, - null); +[,deployment] = sysroot.deploy_tree('testos', rev, origin, + mergeDeployment, null, + null); newDeployments = deployments; deployments = null; newDeployments.unshift(deployment); From 2f22e5b3599a216f557c9c63eab5494ccd9e2a06 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 15 Sep 2017 16:05:48 +0100 Subject: [PATCH 06/78] test-help.sh: Skip trivial-httpd if enabled Because it runs a binary in ${libexecdir}, it will only work if libostree was already installed, which makes the build-time test fail. It also doesn't produce the output we expect: its usage mechanism mentions "ostree-trivial-httpd", not "ostree trivial-httpd". Signed-off-by: Simon McVittie Closes: #1177 Approved by: jlebon --- tests/test-help.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test-help.sh b/tests/test-help.sh index 75fe0c11..ad74aaf9 100755 --- a/tests/test-help.sh +++ b/tests/test-help.sh @@ -75,7 +75,16 @@ test_recursive() { assert_file_empty out for subcmd in $builtins; do - test_recursive "$cmd $subcmd" + case "$subcmd" in + (trivial-httpd) + # Skip trivial-httpd if enabled, it doesn't work + # uninstalled (and also doesn't produce the output + # we expect). + ;; + (*) + test_recursive "$cmd $subcmd" + ;; + esac done fi } From b39a61b493de06b1cfe4a794993886345de7c8d9 Mon Sep 17 00:00:00 2001 From: yceh <31328757+yceh@users.noreply.github.com> Date: Mon, 18 Sep 2017 13:10:52 +0000 Subject: [PATCH 07/78] bin/commit: Fix build failure when libarchive is not used A `"}"` at line 641 is missing when `HAVE_LIBARCHIVE` is not defined (even though probably few will use ostree without libarchive). Closes: #1181 Approved by: jlebon --- src/ostree/ot-builtin-commit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 3b9e3630..eb5e99b0 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -631,12 +631,12 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError if (!ostree_repo_import_archive_to_mtree (repo, &opts, archive, mtree, modifier, cancellable, error)) goto out; - } #else - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "This version of ostree is not compiled with libarchive support"); - return FALSE; + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "This version of ostree is not compiled with libarchive support"); + goto out; #endif + } } else if (strcmp (tree_type, "ref") == 0) { From d0b0578cc1dcef5ab5c410f5e84a05e79fff0ecc Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 12 Sep 2017 09:40:58 -0400 Subject: [PATCH 08/78] Update libglnx Update libglnx, which is mostly port the repo stagedir code to the new tmpdir API. This turned out to require some libglnx changes to support de-allocating the tmpdir ref while still maintaining the on-disk dir. Update submodule: libglnx Closes: #1172 Approved by: jlebon --- libglnx | 2 +- src/libostree/ostree-repo-commit.c | 39 +++++----------- src/libostree/ostree-repo-private.h | 6 +-- src/libostree/ostree-repo.c | 71 +++++++++++++---------------- tests/test-repo-finder-config.c | 20 +++----- tests/test-repo-finder-mount.c | 22 ++++----- 6 files changed, 62 insertions(+), 98 deletions(-) diff --git a/libglnx b/libglnx index e226ccf6..e5856ca2 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit e226ccf6913d1d852fde1e150a99fab508f85c34 +Subproject commit e5856ca2939dca0589a836e3108dd3f9759e28fa diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index f15e05d2..ed13b3bf 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -140,7 +140,7 @@ _ostree_repo_commit_tmpf_final (OstreeRepo *self, int dest_dfd; if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; @@ -173,7 +173,7 @@ _ostree_repo_commit_path_final (OstreeRepo *self, int dest_dfd; if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; @@ -1114,8 +1114,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self, gboolean ret_transaction_resume = FALSE; if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd, self->stagedir_prefix, - &self->commit_stagedir_name, - &self->commit_stagedir_fd, + &self->commit_stagedir, &self->commit_stagedir_lock, &ret_transaction_resume, cancellable, error)) @@ -1134,7 +1133,7 @@ rename_pending_loose_objects (OstreeRepo *self, GLNX_AUTO_PREFIX_ERROR ("rename pending", error); g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - if (!glnx_dirfd_iterator_init_at (self->commit_stagedir_fd, ".", FALSE, &dfd_iter, error)) + if (!glnx_dirfd_iterator_init_at (self->commit_stagedir.fd, ".", FALSE, &dfd_iter, error)) return FALSE; /* Iterate over the outer checksum dir */ @@ -1212,8 +1211,7 @@ rename_pending_loose_objects (OstreeRepo *self, if (fsync (self->objects_dir_fd) == -1) return glnx_throw_errno_prefix (error, "fsync"); - if (!glnx_shutil_rm_rf_at (self->tmp_dir_fd, self->commit_stagedir_name, - cancellable, error)) + if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error)) return FALSE; return TRUE; @@ -1549,15 +1547,8 @@ ostree_repo_commit_transaction (OstreeRepo *self, return FALSE; g_clear_pointer (&self->txn_collection_refs, g_hash_table_destroy); - if (self->commit_stagedir_fd != -1) - { - (void) close (self->commit_stagedir_fd); - self->commit_stagedir_fd = -1; - - glnx_release_lock_file (&self->commit_stagedir_lock); - } - - g_clear_pointer (&self->commit_stagedir_name, g_free); + glnx_tmpdir_unset (&self->commit_stagedir); + glnx_release_lock_file (&self->commit_stagedir_lock); self->in_transaction = FALSE; @@ -1588,14 +1579,8 @@ ostree_repo_abort_transaction (OstreeRepo *self, g_clear_pointer (&self->txn_refs, g_hash_table_destroy); g_clear_pointer (&self->txn_collection_refs, g_hash_table_destroy); - if (self->commit_stagedir_fd != -1) - { - (void) close (self->commit_stagedir_fd); - self->commit_stagedir_fd = -1; - - glnx_release_lock_file (&self->commit_stagedir_lock); - } - g_clear_pointer (&self->commit_stagedir_name, g_free); + glnx_tmpdir_unset (&self->commit_stagedir); + glnx_release_lock_file (&self->commit_stagedir_lock); self->in_transaction = FALSE; @@ -2181,8 +2166,8 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); g_autoptr(GVariant) ret_metadata = NULL; - if (self->commit_stagedir_fd != -1 && - !ot_util_variant_map_at (self->commit_stagedir_fd, buf, + if (self->commit_stagedir.initialized && + !ot_util_variant_map_at (self->commit_stagedir.fd, buf, G_VARIANT_TYPE ("a{sv}"), OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) return glnx_prefix_error (error, "Unable to read existing detached metadata"); @@ -2229,7 +2214,7 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self, int dest_dfd; if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 5d2beaeb..dc785690 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -92,8 +92,7 @@ struct OstreeRepo { GObject parent; char *stagedir_prefix; - int commit_stagedir_fd; - char *commit_stagedir_name; + GLnxTmpDir commit_stagedir; GLnxLockFile commit_stagedir_lock; /* A cached fd-relative version, distinct from the case where we may have a @@ -209,8 +208,7 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeRepoMemoryCacheRef, _ostree_repo_memory_c gboolean _ostree_repo_allocate_tmpdir (int tmpdir_dfd, const char *tmpdir_prefix, - char **tmpdir_name_out, - int *tmpdir_fd_out, + GLnxTmpDir *tmpdir_out, GLnxLockFile *file_lock_out, gboolean * reusing_dir_out, GCancellable *cancellable, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 18c7577c..2aa8291d 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -487,9 +487,7 @@ ostree_repo_finalize (GObject *object) g_clear_object (&self->repodir); if (self->repo_dir_fd != -1) (void) close (self->repo_dir_fd); - if (self->commit_stagedir_fd != -1) - (void) close (self->commit_stagedir_fd); - g_free (self->commit_stagedir_name); + glnx_tmpdir_unset (&self->commit_stagedir); glnx_release_lock_file (&self->commit_stagedir_lock); if (self->tmp_dir_fd != -1) (void) close (self->tmp_dir_fd); @@ -687,7 +685,6 @@ ostree_repo_init (OstreeRepo *self) self->repo_dir_fd = -1; self->cache_dir_fd = -1; self->tmp_dir_fd = -1; - self->commit_stagedir_fd = -1; self->objects_dir_fd = -1; self->uncompressed_objects_dir_fd = -1; self->commit_stagedir_lock = empty_lockfile; @@ -2793,9 +2790,9 @@ load_metadata_internal (OstreeRepo *self, error)) return FALSE; - if (fd < 0 && self->commit_stagedir_fd != -1) + if (fd < 0 && self->commit_stagedir.initialized) { - if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd, + if (!ot_openat_ignore_enoent (self->commit_stagedir.fd, loose_path_buf, &fd, error)) return FALSE; } @@ -2906,9 +2903,9 @@ repo_load_file_archive (OstreeRepo *self, error)) return FALSE; - if (fd < 0 && self->commit_stagedir_fd != -1) + if (fd < 0 && self->commit_stagedir.initialized) { - if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd, + if (!ot_openat_ignore_enoent (self->commit_stagedir.fd, loose_path_buf, &fd, error)) return FALSE; } @@ -2967,9 +2964,9 @@ _ostree_repo_load_file_bare (OstreeRepo *self, int objdir_fd = self->objects_dir_fd; int res; if ((res = TEMP_FAILURE_RETRY (fstatat (objdir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW))) < 0 - && errno == ENOENT && self->commit_stagedir_fd != -1) + && errno == ENOENT && self->commit_stagedir.initialized) { - objdir_fd = self->commit_stagedir_fd; + objdir_fd = self->commit_stagedir.fd; res = TEMP_FAILURE_RETRY (fstatat (objdir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW)); } if (res < 0 && errno != ENOENT) @@ -3214,7 +3211,9 @@ _ostree_repo_has_loose_object (OstreeRepo *self, gboolean found = FALSE; /* It's easier to share code if we make this an array */ - const int dfd_searches[] = { self->commit_stagedir_fd, self->objects_dir_fd }; + int dfd_searches[] = { -1, self->objects_dir_fd }; + if (self->commit_stagedir.initialized) + dfd_searches[0] = self->commit_stagedir.fd; for (guint i = 0; i < G_N_ELEMENTS (dfd_searches); i++) { int dfd = dfd_searches[i]; @@ -3654,8 +3653,8 @@ ostree_repo_query_object_storage_size (OstreeRepo *self, struct stat stbuf; res = TEMP_FAILURE_RETRY (fstatat (self->objects_dir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); - if (res < 0 && errno == ENOENT && self->commit_stagedir_fd != -1) - res = TEMP_FAILURE_RETRY (fstatat (self->commit_stagedir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); + if (res < 0 && errno == ENOENT && self->commit_stagedir.initialized) + res = TEMP_FAILURE_RETRY (fstatat (self->commit_stagedir.fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); if (res < 0) return glnx_throw_errno_prefix (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype)); @@ -5104,8 +5103,7 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd, gboolean _ostree_repo_allocate_tmpdir (int tmpdir_dfd, const char *tmpdir_prefix, - char **tmpdir_name_out, - int *tmpdir_fd_out, + GLnxTmpDir *tmpdir_out, GLnxLockFile *file_lock_out, gboolean *reusing_dir_out, GCancellable *cancellable, @@ -5120,9 +5118,8 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, gboolean reusing_dir = FALSE; gboolean did_lock = FALSE; - g_autofree char *tmpdir_name = NULL; - glnx_fd_close int tmpdir_fd = -1; - while (tmpdir_name == NULL) + g_auto(GLnxTmpDir) ret_tmpdir = { 0, }; + while (!ret_tmpdir.initialized) { struct dirent *dent; glnx_fd_close int existing_tmpdir_fd = -1; @@ -5142,8 +5139,9 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, dent->d_type != DT_DIR) continue; + glnx_fd_close int target_dfd = -1; if (!glnx_opendirat (dfd_iter.fd, dent->d_name, FALSE, - &existing_tmpdir_fd, &local_error)) + &target_dfd, &local_error)) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) continue; @@ -5166,24 +5164,22 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, /* Touch the reused directory so that we don't accidentally * remove it due to being old when cleaning up the tmpdir. */ - (void)futimens (existing_tmpdir_fd, NULL); + (void)futimens (target_dfd, NULL); /* We found an existing tmpdir which we managed to lock */ - tmpdir_name = g_strdup (dent->d_name); - tmpdir_fd = glnx_steal_fd (&existing_tmpdir_fd); - reusing_dir = TRUE; + ret_tmpdir.src_dfd = tmpdir_dfd; + ret_tmpdir.fd = glnx_steal_fd (&target_dfd); + ret_tmpdir.path = g_strdup (dent->d_name); + ret_tmpdir.initialized = TRUE; } - while (tmpdir_name == NULL) + while (!ret_tmpdir.initialized) { + g_auto(GLnxTmpDir) new_tmpdir = { 0, }; /* No existing tmpdir found, create a new */ - g_autofree char *tmpdir_name_template = g_strconcat (tmpdir_prefix, "XXXXXX", NULL); - if (!glnx_mkdtempat (tmpdir_dfd, tmpdir_name_template, 0777, error)) - return FALSE; - - glnx_fd_close int new_tmpdir_fd = -1; - if (!glnx_opendirat (tmpdir_dfd, tmpdir_name_template, FALSE, - &new_tmpdir_fd, error)) + const char *tmpdir_name_template = glnx_strjoina (tmpdir_prefix, "XXXXXX"); + if (!glnx_mkdtempat (tmpdir_dfd, tmpdir_name_template, 0755, + &new_tmpdir, error)) return FALSE; /* Note, at this point we can race with another process that picks up this @@ -5195,16 +5191,13 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, if (!did_lock) continue; - tmpdir_name = g_steal_pointer (&tmpdir_name_template); - tmpdir_fd = glnx_steal_fd (&new_tmpdir_fd); + ret_tmpdir = new_tmpdir; /* Transfer ownership */ + new_tmpdir.initialized = FALSE; } - if (tmpdir_name_out) - *tmpdir_name_out = g_steal_pointer (&tmpdir_name); - if (tmpdir_fd_out) - *tmpdir_fd_out = glnx_steal_fd (&tmpdir_fd); - if (reusing_dir_out) - *reusing_dir_out = reusing_dir; + *tmpdir_out = ret_tmpdir; /* Transfer ownership */ + ret_tmpdir.initialized = FALSE; + *reusing_dir_out = reusing_dir; return TRUE; } diff --git a/tests/test-repo-finder-config.c b/tests/test-repo-finder-config.c index ba7191ec..eeae0b60 100644 --- a/tests/test-repo-finder-config.c +++ b/tests/test-repo-finder-config.c @@ -39,7 +39,7 @@ typedef struct { OstreeRepo *parent_repo; /* owned */ - int working_dfd; /* owned */ + GLnxTmpDir tmpdir; /* owned */ GFile *working_dir; /* owned */ } Fixture; @@ -47,20 +47,17 @@ static void setup (Fixture *fixture, gconstpointer test_data) { - g_autofree gchar *tmp_name = NULL; g_autoptr(GError) error = NULL; - tmp_name = g_strdup ("test-repo-finder-config-XXXXXX"); - glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error); + (void)glnx_mkdtemp ("test-repo-finder-config-XXXXXX", 0700, &fixture->tmpdir, &error); g_assert_no_error (error); - g_test_message ("Using temporary directory: %s", tmp_name); + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); - glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, "repo", 0700, NULL, &error); g_assert_no_error (error); - g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ()); - fixture->working_dir = g_file_get_child (tmp_dir, tmp_name); + fixture->working_dir = g_file_new_for_path (fixture->tmpdir.path); fixture->parent_repo = ot_test_setup_repo (NULL, &error); g_assert_no_error (error); @@ -73,10 +70,7 @@ teardown (Fixture *fixture, g_autoptr(GError) error = NULL; /* Recursively remove the temporary directory. */ - glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL); - - close (fixture->working_dfd); - fixture->working_dfd = -1; + (void)glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); /* The repo also needs its source files to be removed. This is the inverse * of setup_test_repository() in libtest.sh. */ @@ -177,7 +171,7 @@ assert_create_remote (Fixture *fixture, g_autoptr(GError) error = NULL; const gchar *repo_name = (collection_id != NULL) ? collection_id : "no-collection"; - glnx_shutil_mkdir_p_at (fixture->working_dfd, repo_name, 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, repo_name, 0700, NULL, &error); g_assert_no_error (error); g_autoptr(GFile) repo_path = g_file_get_child (fixture->working_dir, repo_name); diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index f51fb3bb..8376e51e 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -40,30 +40,27 @@ typedef struct { OstreeRepo *parent_repo; - int working_dfd; /* owned */ - GFile *working_dir; /* owned */ + GLnxTmpDir tmpdir; /* owned */ + GFile *working_dir; /* Points at tmpdir */ } Fixture; static void setup (Fixture *fixture, gconstpointer test_data) { - g_autofree gchar *tmp_name = NULL; g_autoptr(GError) error = NULL; - tmp_name = g_strdup ("test-repo-finder-mount-XXXXXX"); - glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error); + (void)glnx_mkdtemp ("test-repo-finder-mount-XXXXXX", 0700, &fixture->tmpdir, &error); g_assert_no_error (error); - g_test_message ("Using temporary directory: %s", tmp_name); + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); - glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, "repo", 0700, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); - g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ()); - fixture->working_dir = g_file_get_child (tmp_dir, tmp_name); + fixture->working_dir = g_file_new_for_path (fixture->tmpdir.path); fixture->parent_repo = ot_test_setup_repo (NULL, &error); g_assert_no_error (error); @@ -76,10 +73,7 @@ teardown (Fixture *fixture, g_autoptr(GError) error = NULL; /* Recursively remove the temporary directory. */ - glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL); - - close (fixture->working_dfd); - fixture->working_dfd = -1; + (void)glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); /* The repo also needs its source files to be removed. This is the inverse * of setup_test_repository() in libtest.sh. */ @@ -167,7 +161,7 @@ assert_create_repos_dir (Fixture *fixture, g_autoptr(GError) error = NULL; g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos", NULL); - glnx_shutil_mkdir_p_at_open (fixture->working_dfd, path, 0700, &repos_dfd, NULL, &error); + glnx_shutil_mkdir_p_at_open (fixture->tmpdir.fd, path, 0700, &repos_dfd, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); From 58e4abe4bcd8c4ca4c6e1a321f6f3f441e756a0c Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 1 Sep 2017 16:24:31 -0400 Subject: [PATCH 09/78] tests/prune: Factor out a helper for counting commits in the repo We had lots of duplicates; prep for adding more tests. Closes: #1127 Approved by: jlebon --- tests/test-prune.sh | 48 +++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/tests/test-prune.sh b/tests/test-prune.sh index afcfbb52..e41c0fbc 100755 --- a/tests/test-prune.sh +++ b/tests/test-prune.sh @@ -44,16 +44,20 @@ done ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin test +assert_repo_has_n_commits() { + repo=$1 + count=$2 + assert_streq "$(find ${repo}/objects -name '*.commit' | wc -l)" "${count}" +} + ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=2 -v -find repo | grep \.commit$ | wc -l > commitcount -assert_file_has_content commitcount "^3$" +assert_repo_has_n_commits repo 3 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_file_has_content tombstonecommitcount "^0$" $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=1 -v -find repo | grep \.commit$ | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_file_has_content tombstonecommitcount "^0$" @@ -70,8 +74,7 @@ find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_file_has_content tombstonecommitcount "^0$" ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^1$" +assert_repo_has_n_commits repo 1 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_not_file_has_content tombstonecommitcount "^0$" $OSTREE fsck @@ -88,28 +91,22 @@ assert_file_has_content tombstonecommitcount "^1$" $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^1$" +assert_repo_has_n_commits repo 1 ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="2005-10-29 12:43:29 +0000" ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="2010-10-29 12:43:29 +0000" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^3$" +assert_repo_has_n_commits repo 3 ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="2015-10-29 12:43:29 +0000" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="October 25 1985" ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="October 21 2015" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^4$" +assert_repo_has_n_commits repo 4 ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 ${CMD_PREFIX} ostree --repo=repo commit --branch=oldcommit tree --timestamp="2005-10-29 12:43:29 +0000" oldcommit_rev=$($OSTREE --repo=repo rev-parse oldcommit) @@ -200,8 +197,7 @@ for x in $(seq 3); do ${CMD_PREFIX} ostree --repo=datetest-snapshot-repo commit --branch=stable -m test -s "new stable build $x" tree ${CMD_PREFIX} ostree --repo=datetest-snapshot-repo commit --branch=dev -m test -s "new dev build $x" tree done -find datetest-snapshot-repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^16$" +assert_repo_has_n_commits datetest-snapshot-repo 16 # Snapshot the above reinitialize_datesnap_repo() { @@ -219,18 +215,15 @@ if ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" --ret fi assert_file_has_content err.txt 'Invalid depth BACON' ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" --retain-branch-depth=stable=-1 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^11$" +assert_repo_has_n_commits repo 11 # Double check our backup is unchanged -find datetest-snapshot-repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^16$" +assert_repo_has_n_commits datetest-snapshot-repo 16 $OSTREE fsck # Again but this time only retain 6 (5+1) commits on stable. This should drop # out 8 - 6 = 2 commits (so the 11 above minus 2 = 9) ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" --retain-branch-depth=stable=5 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^9$" +assert_repo_has_n_commits repo 9 $OSTREE fsck echo "ok retain branch depth and keep-younger-than" @@ -238,8 +231,7 @@ echo "ok retain branch depth and keep-younger-than" # so 8 stable + 1 dev = 9 reinitialize_datesnap_repo ${CMD_PREFIX} ostree --repo=repo prune --depth=0 --retain-branch-depth=stable=-1 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^9$" +assert_repo_has_n_commits repo 9 $OSTREE fsck echo "ok retain branch depth (alone)" From ab200495a86d8ff6ef309cf1e89b93275cb96793 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 1 Sep 2017 15:55:17 -0400 Subject: [PATCH 10/78] bin/prune: Add --only-branch In 5c940987e768523ef1411b65bcaad09fba6befef / #646 we added `--retain-branch-depth`; this adds a symmetric `--only-branch` for the case where a repo owner just wants to prune a specific branch. The implementation here is pretty straightforward; we just walk all refs and inject the equivalent of `--retain-branch-depth=$ref=-1` if they're *not* in `--only-branch`. Closes: https://github.com/ostreedev/ostree/issues/1115 Closes: #1127 Approved by: jlebon --- src/ostree/ot-builtin-prune.c | 45 ++++++++++++++++++++++++++++- tests/test-prune.sh | 53 ++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c index 2f66334e..6120e0a9 100644 --- a/src/ostree/ot-builtin-prune.c +++ b/src/ostree/ot-builtin-prune.c @@ -35,6 +35,7 @@ static gboolean opt_refs_only; static char *opt_delete_commit; static char *opt_keep_younger_than; static char **opt_retain_branch_depth; +static char **opt_only_branches; /* ATTENTION: * Please remember to update the bash-completion script (bash/ostree) and @@ -49,6 +50,7 @@ static GOptionEntry options[] = { { "keep-younger-than", 0, 0, G_OPTION_ARG_STRING, &opt_keep_younger_than, "Prune all commits older than the specified date", "DATE" }, { "static-deltas-only", 0, 0, G_OPTION_ARG_NONE, &opt_static_deltas_only, "Change the behavior of delete-commit and keep-younger-than to prune only static deltas" }, { "retain-branch-depth", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_retain_branch_depth, "Additionally retain BRANCH=DEPTH commits", "BRANCH=DEPTH" }, + { "only-branch", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_only_branches, "Only prune BRANCH (may be specified multiple times)", "BRANCH" }, { NULL } }; @@ -185,7 +187,7 @@ ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError * gint n_objects_total; gint n_objects_pruned; guint64 objsize_total; - if (!(opt_retain_branch_depth || opt_keep_younger_than)) + if (!(opt_retain_branch_depth || opt_keep_younger_than || opt_only_branches)) { if (!ostree_repo_prune (repo, pruneflags, opt_depth, &n_objects_total, &n_objects_pruned, &objsize_total, @@ -210,6 +212,7 @@ ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError * return glnx_throw (error, "Could not parse '%s'", opt_keep_younger_than); } + /* Process --retain-branch-depth */ for (char **iter = opt_retain_branch_depth; iter && *iter; iter++) { /* bd should look like BRANCH=DEPTH where DEPTH is an int */ @@ -239,6 +242,45 @@ ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError * cancellable, error)) return FALSE; + /* Process --only-branch. Note this combines with --retain-branch-depth; one + * could do e.g.: + * * --only-branch exampleos/x86_64/foo + * * --only-branch exampleos/x86_64/bar + * * --retain-branch-depth exampleos/x86_64/foo=0 + * * --depth 5 + * to prune exampleos/x86_64/foo to just the latest commit, and + * exampleos/x86_64/bar to a depth of 5. + */ + if (opt_only_branches) + { + /* Turn --only-branch into a set */ + g_autoptr(GHashTable) only_branches_set = g_hash_table_new (g_str_hash, g_str_equal); + for (char **iter = opt_only_branches; iter && *iter; iter++) + { + const char *ref = *iter; + /* Ensure the specified branch exists */ + if (!ostree_repo_resolve_rev (repo, ref, FALSE, NULL, error)) + return FALSE; + g_hash_table_add (only_branches_set, (char*)ref); + } + + /* Iterate over all refs, add equivalent of --retain-branch-depth=$ref=-1 + * if the ref isn't in --only-branch set and there wasn't already a + * --retain-branch-depth specified for it. + */ + GLNX_HASH_TABLE_FOREACH (all_refs, const char *, ref) + { + if (!g_hash_table_contains (only_branches_set, ref) && + !g_hash_table_contains (retain_branch_depth, ref)) + { + g_hash_table_insert (retain_branch_depth, g_strdup (ref), GINT_TO_POINTER ((int)-1)); + } + } + } + + /* Traverse each ref, and gather all objects pointed to by it up to a + * specific depth (if configured). + */ g_hash_table_iter_init (&hash_iter, all_refs); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { @@ -275,6 +317,7 @@ ostree_builtin_prune (int argc, char **argv, GCancellable *cancellable, GError * return FALSE; } + /* We've gathered the reachable set; start the prune ✀ */ { OstreeRepoPruneOptions opts = { pruneflags, reachable }; if (!ostree_repo_prune_from_reachable (repo, &opts, &n_objects_total, diff --git a/tests/test-prune.sh b/tests/test-prune.sh index e41c0fbc..07548822 100755 --- a/tests/test-prune.sh +++ b/tests/test-prune.sh @@ -25,7 +25,7 @@ skip_without_user_xattrs setup_fake_remote_repo1 "archive" -echo '1..5' +echo '1..12' cd ${test_tmpdir} mkdir repo @@ -235,3 +235,54 @@ assert_repo_has_n_commits repo 9 $OSTREE fsck echo "ok retain branch depth (alone)" + +# Test --only-branch with --depth=0; this should be exactly identical to the +# above with a result of 9. +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=0 +assert_repo_has_n_commits repo 9 +$OSTREE fsck +echo "ok --only-branch --depth=0" + +# Test --only-branch with --depth=1; should just add 1 to the above, for 10. +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=1 +assert_repo_has_n_commits repo 10 +echo "ok --only-branch --depth=1" + +# Test --only-branch with all branches +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=0 +assert_repo_has_n_commits repo 2 +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=1 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch (all) --depth=1" + +# Test --only-branch and --retain-branch-depth overlap +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=0 \ + --retain-branch-depth=stable=2 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch and --retain-branch-depth overlap" + +# Test --only-branch and --retain-branch-depth together +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=0 --retain-branch-depth=stable=2 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch and --retain-branch-depth together" + +# Test --only-branch with --keep-younger-than; this should be identical to the test +# above for --retain-branch-depth=stable=-1 +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=stable --keep-younger-than="1 week ago" +assert_repo_has_n_commits repo 11 +echo "ok --only-branch --keep-younger-than" + +# Test --only-branch with a nonexistent ref +reinitialize_datesnap_repo +if ${CMD_PREFIX} ostree --repo=repo prune --only-branch=BACON 2>err.txt; then + fatal "we pruned BACON?" +fi +assert_file_has_content err.txt "Refspec.*BACON.*not found" +echo "ok --only-branch=BACON" From 1036cc808470a8d17b83f5896c000fa76c8f43d0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Sep 2017 09:46:17 -0400 Subject: [PATCH 11/78] ci: Use distro-sync instead of upgrade This should help ensure that if installing `glibc-devel` downgrades `glibc` we'll run through our hackround for . Closes: #1190 Approved by: jlebon --- ci/libbuild.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ci/libbuild.sh b/ci/libbuild.sh index 0e024063..2b600dc7 100644 --- a/ci/libbuild.sh +++ b/ci/libbuild.sh @@ -2,12 +2,13 @@ pkg_upgrade() { # https://bugzilla.redhat.com/show_bug.cgi?id=1483553 - if ! yum -y upgrade 2>err.txt; then - ecode=$? - if grep -q -F -e "BDB1539 Build signature doesn't match environment" err.txt; then - rpm --rebuilddb - yum -y upgrade - else + ecode=0 + yum -y distro-sync 2>err.txt || ecode=$? + if test ${ecode} '!=' 0 && grep -q -F -e "BDB1539 Build signature doesn't match environment" err.txt; then + rpm --rebuilddb + yum -y distro-sync + else + if test ${ecode} '!=' 0; then cat err.txt exit ${ecode} fi From 981eb6c2267f076bbb278f634fda83aa9dfac2a9 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 15 Sep 2017 15:26:22 +0100 Subject: [PATCH 12/78] lib/repo: Add ostree_repo_equal() for comparing repos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will compare their root directory inodes to see if they are the same repository on disk. A convenience method for the users of the public API who can’t access OstreeRepo.inode. Signed-off-by: Philip Withnall Closes: #1179 Approved by: cgwalters --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree-devel.sym | 2 ++ src/libostree/ostree-repo.c | 25 +++++++++++++++++++++++++ src/libostree/ostree-repo.h | 4 ++++ 4 files changed, 32 insertions(+) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 5f061c00..547e1509 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -287,6 +287,7 @@ ostree_repo_get_path ostree_repo_get_mode ostree_repo_get_config ostree_repo_get_dfd +ostree_repo_equal ostree_repo_copy_config ostree_repo_remote_add ostree_repo_remote_delete diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 07f918a1..a416b7c1 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -19,6 +19,8 @@ /* Add new symbols here. Release commits should copy this section into -released.sym. */ LIBOSTREE_2017.12 { +global: + ostree_repo_equal; } LIBOSTREE_2017.11; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 2aa8291d..e6d8a747 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2612,6 +2612,31 @@ ostree_repo_get_dfd (OstreeRepo *self) return self->repo_dir_fd; } +/** + * ostree_repo_equal: + * @a: an #OstreeRepo + * @b: an #OstreeRepo + * + * Check whether two opened repositories are the same on disk: if their root + * directories are the same inode. If @a or @b are not open yet (due to + * ostree_repo_open() not being called on them yet), %FALSE will be returned. + * + * Returns: %TRUE if @a and @b are the same repository on disk, %FALSE otherwise + * Since: 2017.12 + */ +gboolean +ostree_repo_equal (OstreeRepo *a, + OstreeRepo *b) +{ + g_return_val_if_fail (OSTREE_IS_REPO (a), FALSE); + g_return_val_if_fail (OSTREE_IS_REPO (b), FALSE); + + if (a->repo_dir_fd < 0 || b->repo_dir_fd < 0) + return FALSE; + + return (a->device == b->device && a->inode == b->inode); +} + OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self) { diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 227fe597..682d4964 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -123,6 +123,10 @@ GFile * ostree_repo_get_path (OstreeRepo *self); _OSTREE_PUBLIC int ostree_repo_get_dfd (OstreeRepo *self); +_OSTREE_PUBLIC +gboolean ostree_repo_equal (OstreeRepo *a, + OstreeRepo *b); + _OSTREE_PUBLIC OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self); From 15247641d9e4bf6190954da806c8c08136d06f29 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 15 Sep 2017 15:59:32 +0100 Subject: [PATCH 13/78] lib/repo-finder-mount: Change the schema for finding repos on volumes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See issue #1174 for the rationale behind this. In summary: • It required two lists of collection–refs to be maintained: one in the repository, and one pointing to the repository. • It didn’t automatically work for live USBs of OSs based on OSTree (where there’s always a repository at /ostree/repo). • It was unnecessarily complex. The new scheme allows a list of repositories to be searched, but without needing a layer of indirection through their collection–refs. It adds /ostree/repo and /.ostree/repo as well-known repository locations which are always checked on a mounted volume (if they exist). Update the unit tests accordingly. Signed-off-by: Philip Withnall https://github.com/ostreedev/ostree/issues/1174 Closes: #1179 Approved by: cgwalters --- src/libostree/ostree-repo-finder-mount.c | 384 +++++++++++++++-------- tests/test-repo-finder-mount.c | 193 ++++++++---- 2 files changed, 388 insertions(+), 189 deletions(-) diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index b7b15bf0..31bb8bfc 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -46,19 +46,20 @@ * #OstreeRepoFinderMount is an implementation of #OstreeRepoFinder which looks * refs up in well-known locations on any mounted removable volumes. * - * For an #OstreeCollectionRef, (`C`, `R`), it checks whether `.ostree/repos/C/R` - * exists and is an OSTree repository on each mounted removable volume. Collection - * IDs and ref names are not escaped when building the path, so if either - * contains `/` in its name, the repository will be checked for in a - * subdirectory of `.ostree/repos`. Non-removable volumes are ignored. + * For each mounted removable volume, the directory `.ostree/repos.d` will be + * enumerated, and all OSTree repositories below it will be searched, in lexical + * order, for the requested #OstreeCollectionRefs. The names of the directories + * below `.ostree/repos.d` are irrelevant, apart from their lexical ordering. + * The directory `ostree/repo` will be searched after the others, if it exists. + * Non-removable volumes are ignored. * * For each repository which is found, a result will be returned for the * intersection of the refs being searched for, and the refs in `refs/heads` and * `refs/mirrors` in the repository on the removable volume. * - * Symlinks are followed when resolving the refs, so a volume might contain a - * single OSTree at some arbitrary path, with a number of refs linking to it - * from `.ostree/repos`. Any symlink which points outside the volume’s file + * Symlinks are followed when listing the repositories, so a volume might + * contain a single OSTree at some arbitrary path, with a symlink from + * `.ostree/repos.d`. Any symlink which points outside the volume’s file * system will be ignored. Repositories are deduplicated in the results. * * The volume monitor used to find mounted volumes can be overridden by setting @@ -166,6 +167,137 @@ results_compare_cb (gconstpointer a, return ostree_repo_finder_result_compare (result_a, result_b); } +typedef struct +{ + char *ordering_name; /* (owned) */ + OstreeRepo *repo; /* (owned) */ + GHashTable *refs; /* (owned) (element-type OstreeCollectionRef utf8) */ +} RepoAndRefs; + +static void +repo_and_refs_clear (RepoAndRefs *data) +{ + g_hash_table_unref (data->refs); + g_object_unref (data->repo); + g_free (data->ordering_name); +} + +static gint +repo_and_refs_compare (gconstpointer a, + gconstpointer b) +{ + const RepoAndRefs *_a = a; + const RepoAndRefs *_b = b; + + return strcmp (_a->ordering_name, _b->ordering_name); +} + +/* Check whether the repo at @dfd/@path is within the given mount, is not equal + * to the @parent_repo, and can be opened. If so, return it as @out_repo and + * all its collection–refs as @out_refs, to be added into the results. */ +static gboolean +scan_repo (int dfd, + const char *path, + const char *mount_name, + const struct stat *mount_root_stbuf, + OstreeRepo *parent_repo, + OstreeRepo **out_repo, + GHashTable **out_refs, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + + g_autoptr(OstreeRepo) repo = ostree_repo_open_at (dfd, path, cancellable, &local_error); + if (repo == NULL) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it could not be opened: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + int repo_dfd = ostree_repo_get_dfd (repo); + struct stat stbuf; + + if (!glnx_fstat (repo_dfd, &stbuf, &local_error)) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as querying its info failed: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* Check the resolved repository path is below the mount point. Do not + * allow ref symlinks to point somewhere outside of the mounted volume. */ + if (stbuf.st_dev != mount_root_stbuf->st_dev) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it’s on a different file system from the mount", + path, mount_name); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* Exclude repositories which resolve to @parent_repo. */ + if (stbuf.st_dev == parent_repo->device && + stbuf.st_ino == parent_repo->inode) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it is the same as the one we are resolving", + path, mount_name); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* List the repo’s refs and return them. */ + g_autoptr(GHashTable) repo_refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + + if (!ostree_repo_list_collection_refs (repo, NULL, &repo_refs, + OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES, + cancellable, &local_error)) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as its refs could not be listed: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + if (out_repo != NULL) + *out_repo = g_steal_pointer (&repo); + if (out_refs != NULL) + *out_refs = g_steal_pointer (&repo_refs); + + return TRUE; +} + +static void +scan_and_add_repo (int dfd, + const char *path, + gboolean sortable, + const char *mount_name, + const struct stat *mount_root_stbuf, + OstreeRepo *parent_repo, + GArray *inout_repos_refs, + GCancellable *cancellable) +{ + g_autoptr(GHashTable) repo_refs = NULL; + g_autoptr(OstreeRepo) repo = NULL; + + if (scan_repo (dfd, path, + mount_name, mount_root_stbuf, + parent_repo, &repo, &repo_refs, cancellable, NULL)) + { + RepoAndRefs val = { + sortable ? g_strdup (path) : NULL, + g_steal_pointer (&repo), + g_steal_pointer (&repo_refs) + }; + g_array_append_val (inout_repos_refs, val); + + g_debug ("%s: Adding repo ‘%s’ (%ssortable)", + G_STRFUNC, path, sortable ? "" : "not "); + } +} + static void ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finder, const OstreeCollectionRef * const *refs, @@ -214,7 +346,6 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde continue; } - /* Check if it contains a .ostree/repos directory. */ mount_root = g_mount_get_root (mount); mount_root_path = g_file_get_path (mount_root); @@ -225,18 +356,6 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde continue; } - if (!glnx_opendirat (mount_root_dfd, ".ostree/repos", TRUE, &repos_dfd, &local_error)) - { - if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - g_debug ("Ignoring mount ‘%s’ as ‘%s/.ostree/repos’ directory doesn’t exist.", - mount_name, mount_root_path); - else - g_debug ("Ignoring mount ‘%s’ as ‘%s/.ostree/repos’ directory can’t be opened: %s", - mount_name, mount_root_path, local_error->message); - - continue; - } - /* stat() the mount root so we can later check whether the resolved * repositories for individual refs are on the same device (to avoid the * symlinks for them pointing outside the mount root). */ @@ -247,6 +366,64 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde continue; } + /* Check if it contains a .ostree/repos.d directory. If not, move on and + * try the other well-known subdirectories. */ + if (!glnx_opendirat (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_dfd, NULL)) + repos_dfd = -1; + + /* List all the repositories in the repos.d directory. */ + /* (element-type GHashTable (element-type OstreeCollectionRef utf8)) */ + g_autoptr(GArray) repos_refs = g_array_new (FALSE, TRUE, sizeof (RepoAndRefs)); + g_array_set_clear_func (repos_refs, (GDestroyNotify) repo_and_refs_clear); + + GLnxDirFdIterator repos_iter; + + if (repos_dfd >= 0 && + !glnx_dirfd_iterator_init_at (repos_dfd, ".", TRUE, &repos_iter, &local_error)) + { + g_debug ("Error iterating over ‘%s/.ostree/repos.d’ directory in mount ‘%s’: %s", + mount_root_path, mount_name, local_error->message); + g_clear_error (&local_error); + /* don’t skip this mount as there’s still the ostree/repo directory to try */ + } + else if (repos_dfd >= 0) + { + while (TRUE) + { + struct dirent *repo_dent; + + if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, &local_error)) + { + g_debug ("Error iterating over ‘%s/.ostree/repos.d’ directory in mount ‘%s’: %s", + mount_root_path, mount_name, local_error->message); + g_clear_error (&local_error); + /* don’t skip this mount as there’s still the ostree/repo directory to try */ + break; + } + + if (repo_dent == NULL) + break; + + /* Grab the set of collection–refs from the repo if we can open it. */ + scan_and_add_repo (repos_dfd, repo_dent->d_name, TRUE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); + } + } + + /* Sort the repos lexically. */ + g_array_sort (repos_refs, repo_and_refs_compare); + + /* Also check the .ostree/repo and ostree/repo directories in the mount, + * as well-known special cases. Add them after sorting, so they’re always + * last. */ + scan_and_add_repo (mount_root_dfd, ".ostree/repo", FALSE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); + scan_and_add_repo (mount_root_dfd, "ostree/repo", FALSE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); + /* Check whether a subdirectory exists for any of the @refs we’re looking * for. If so, and it’s a symbolic link, dereference it so multiple links * to the same repository (containing multiple refs) are coalesced. @@ -256,122 +433,67 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde for (i = 0; refs[i] != NULL; i++) { - struct stat stbuf; - g_autofree gchar *collection_and_ref = NULL; + const OstreeCollectionRef *ref = refs[i]; g_autofree gchar *resolved_repo_uri = NULL; g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; - collection_and_ref = g_build_filename (refs[i]->collection_id, refs[i]->ref_name, NULL); - - if (!glnx_fstatat (repos_dfd, collection_and_ref, &stbuf, AT_NO_AUTOMOUNT, &local_error)) + for (gsize j = 0; j < repos_refs->len; j++) { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as querying info of ‘%s’ failed: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, collection_and_ref, local_error->message); - g_clear_error (&local_error); - continue; + const RepoAndRefs *repo_and_refs = &g_array_index (repos_refs, RepoAndRefs, j); + OstreeRepo *repo = repo_and_refs->repo; + GHashTable *repo_refs = repo_and_refs->refs; + g_autofree char *repo_path = g_file_get_path (ostree_repo_get_path (repo)); + + const gchar *checksum = g_hash_table_lookup (repo_refs, ref); + + if (checksum == NULL) + { + g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ as it doesn’t contain the ref.", + repo_path, ref->collection_id, ref->ref_name, mount_name); + g_clear_error (&local_error); + continue; + } + + /* Finally, look up the GPG keyring for this ref. */ + keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, + cancellable, &local_error); + + if (keyring == NULL) + { + g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", + repo_path, ref->collection_id, ref->ref_name, mount_name, local_error->message); + g_clear_error (&local_error); + continue; + } + + /* There is a valid repo at (or pointed to by) + * $mount_root/.ostree/repos.d/$something. + * Add it to the results, keyed by the canonicalised repository URI + * to deduplicate the results. */ + g_autofree char *canonical_repo_path = realpath (repo_path, NULL); + resolved_repo_uri = g_strconcat ("file://", canonical_repo_path, NULL); + g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’.", + ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, keyring); + + resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring); + + supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); + + if (supported_ref_to_checksum == NULL) + { + supported_ref_to_checksum = g_hash_table_new_full (ostree_collection_ref_hash, + ostree_collection_ref_equal, + NULL, g_free); + g_hash_table_insert (repo_to_refs, g_steal_pointer (&resolved_repo), supported_ref_to_checksum /* transfer */); + } + + g_hash_table_insert (supported_ref_to_checksum, (gpointer) ref, g_strdup (checksum)); + + /* We’ve found a result for this collection–ref. No point in checking + * the other repos on the mount, since pulling in parallel from them won’t help. */ + break; } - - if ((stbuf.st_mode & S_IFMT) != S_IFDIR) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as ‘%s’ is of type %u, not a directory.", - refs[i]->collection_id, refs[i]->ref_name, mount_name, collection_and_ref, (stbuf.st_mode & S_IFMT)); - g_clear_error (&local_error); - continue; - } - - /* Check the resolved repository path is below the mount point. Do not - * allow ref symlinks to point somewhere outside of the mounted - * volume. */ - if (stbuf.st_dev != mount_root_stbuf.st_dev) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as it’s on a different file system from the mount.", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; - } - - /* Exclude repositories which resolve to @parent_repo. */ - if (stbuf.st_dev == parent_repo->device && - stbuf.st_ino == parent_repo->inode) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as it is the same as the one we are resolving", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; - } - - /* Grab the given ref and a checksum for it from the repo, if it appears to be a valid repo */ - g_autoptr(OstreeRepo) repo = ostree_repo_open_at (repos_dfd, collection_and_ref, - cancellable, &local_error); - if (!repo) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its repository could not be opened: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - g_autoptr(GHashTable) repo_refs = NULL; /* (element-type OstreeCollectionRef utf8) */ - - if (!ostree_repo_list_collection_refs (repo, refs[i]->collection_id, &repo_refs, - OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES, - cancellable, &local_error)) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its refs could not be listed: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - const gchar *checksum = g_hash_table_lookup (repo_refs, refs[i]); - - if (checksum == NULL) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its repository doesn’t contain the ref.", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; - } - - /* Finally, look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, refs[i]->collection_id, - cancellable, &local_error); - - if (keyring == NULL) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - /* There is a valid repo at (or pointed to by) - * $mount_root/.ostree/repos/$refs[i]->collection_id/$refs[i]->ref_name. - * Add it to the results, keyed by the canonicalised repository URI - * to deduplicate the results. */ - - g_autofree char *repo_abspath = g_build_filename (mount_root_path, ".ostree/repos", - collection_and_ref, NULL); - /* FIXME - why are we using realpath here? */ - g_autofree char *canonical_repo_dir_path = realpath (repo_abspath, NULL); - resolved_repo_uri = g_strconcat ("file://", canonical_repo_dir_path, NULL); - g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’.", - refs[i]->collection_id, refs[i]->ref_name, mount_name, resolved_repo_uri, keyring); - - resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring); - - supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); - - if (supported_ref_to_checksum == NULL) - { - supported_ref_to_checksum = g_hash_table_new_full (ostree_collection_ref_hash, - ostree_collection_ref_equal, - NULL, g_free); - g_hash_table_insert (repo_to_refs, g_steal_pointer (&resolved_repo), supported_ref_to_checksum /* transfer */); - } - - g_hash_table_insert (supported_ref_to_checksum, (gpointer) refs[i], g_strdup (checksum)); } /* Aggregate the results. */ diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index 8376e51e..2ab08001 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -70,8 +70,6 @@ static void teardown (Fixture *fixture, gconstpointer test_data) { - g_autoptr(GError) error = NULL; - /* Recursively remove the temporary directory. */ (void)glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); @@ -150,7 +148,7 @@ test_repo_finder_mount_no_mounts (Fixture *fixture, g_main_context_pop_thread_default (context); } -/* Create a .ostree/repos directory under the given @mount_root, or abort. */ +/* Create a .ostree/repos.d directory under the given @mount_root, or abort. */ static gboolean assert_create_repos_dir (Fixture *fixture, const gchar *mount_root_name, @@ -160,7 +158,7 @@ assert_create_repos_dir (Fixture *fixture, glnx_fd_close int repos_dfd = -1; g_autoptr(GError) error = NULL; - g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos", NULL); + g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos.d", NULL); glnx_shutil_mkdir_p_at_open (fixture->tmpdir.fd, path, 0700, &repos_dfd, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); @@ -227,22 +225,22 @@ assert_create_remote_va (Fixture *fixture, } static OstreeRepo * -assert_create_repo_dir (Fixture *fixture, - int repos_dfd, - GMount *repos_mount, - const OstreeCollectionRef *ref, - gchar **out_uri, +assert_create_repo_dir (Fixture *fixture, + int repos_dfd, + GMount *repos_mount, + const char *repo_name, + gchar **out_uri, ...) G_GNUC_NULL_TERMINATED; -/* Create a @ref directory under the given @repos_dfd, or abort. Create a new - * repository in it with the refs given in @..., as per assert_create_remote_va(). - * Return the URI of the repository. */ +/* Create a @repo_name directory under the given @repos_dfd, or abort. Create a + * new repository in it with the refs given in @..., as per + * assert_create_remote_va(). Return the URI of the repository. */ static OstreeRepo * -assert_create_repo_dir (Fixture *fixture, - int repos_dfd, - GMount *repos_mount, - const OstreeCollectionRef *ref, - gchar **out_uri, +assert_create_repo_dir (Fixture *fixture, + int repos_dfd, + GMount *repos_mount, + const char *repo_name, + gchar **out_uri, ...) { glnx_fd_close int ref_dfd = -1; @@ -250,15 +248,14 @@ assert_create_repo_dir (Fixture *fixture, g_autoptr(GError) error = NULL; va_list args; - g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL); - glnx_shutil_mkdir_p_at_open (repos_dfd, path, 0700, &ref_dfd, NULL, &error); + glnx_shutil_mkdir_p_at_open (repos_dfd, repo_name, 0700, &ref_dfd, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); g_autoptr(GFile) mount_root = g_mount_get_root (repos_mount); - g_autoptr(GFile) repos_dir = g_file_get_child (mount_root, ".ostree/repos"); - g_autoptr(GFile) repo_dir = g_file_get_child (repos_dir, path); + g_autoptr(GFile) repos_dir = g_file_get_child (mount_root, ".ostree/repos.d"); + g_autoptr(GFile) repo_dir = g_file_get_child (repos_dir, repo_name); va_start (args, out_uri); repo = assert_create_remote_va (fixture, repo_dir, args); @@ -269,38 +266,19 @@ assert_create_repo_dir (Fixture *fixture, return g_steal_pointer (&repo); } -/* Create a @ref symlink under the given @repos_dfd, pointing to - * @symlink_target, or abort. */ -static int -assert_create_repo_symlink (int repos_dfd, - const OstreeCollectionRef *ref, - const gchar *symlink_target_path) +/* Create a @repo_name symlink under the given @repos_dfd, pointing to + * @symlink_target_path, or abort. */ +static void +assert_create_repo_symlink (int repos_dfd, + const char *repo_name, + const char *symlink_target_path) { - glnx_fd_close int symlink_target_dfd = -1; - g_autoptr(GError) error = NULL; - - /* The @ref_parent_dir is not necessarily @collection_dir, since @ref may - * contain slashes. */ - g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL); - g_autofree gchar *path_parent = g_path_get_dirname (path); - - glnx_shutil_mkdir_p_at (repos_dfd, path_parent, 0700, NULL, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) - g_clear_error (&error); - g_assert_no_error (error); - - if (TEMP_FAILURE_RETRY (symlinkat (symlink_target_path, repos_dfd, path)) != 0) + if (TEMP_FAILURE_RETRY (symlinkat (symlink_target_path, repos_dfd, repo_name)) != 0) { g_autoptr(GError) error = NULL; glnx_throw_errno_prefix (&error, "symlinkat"); g_assert_no_error (error); } - - /* Return a dir FD for the symlink target. */ - glnx_opendirat (repos_dfd, path, TRUE, &symlink_target_dfd, &error); - g_assert_no_error (error); - - return glnx_steal_fd (&symlink_target_dfd); } /* Add configuration for a remote named @remote_name, at @remote_uri, with a @@ -350,7 +328,7 @@ test_repo_finder_mount_mixed_mounts (Fixture *fixture, g_autofree gchar *repo2_repo_a_uri = NULL; g_autofree gchar *repo1_ref0_checksum = NULL, *repo1_ref1_checksum = NULL, *repo1_ref2_checksum = NULL; g_autofree gchar *repo2_ref0_checksum = NULL, *repo2_ref1_checksum = NULL, *repo2_ref2_checksum = NULL; - g_autofree gchar *repo1_ref5_checksum = NULL; + g_autofree gchar *repo1_ref5_checksum = NULL, *repo2_ref3_checksum = NULL; gsize i; const OstreeCollectionRef ref0 = { "org.example.Collection1", "exampleos/x86_64/ref0" }; const OstreeCollectionRef ref1 = { "org.example.Collection1", "exampleos/x86_64/ref1" }; @@ -373,27 +351,26 @@ test_repo_finder_mount_mixed_mounts (Fixture *fixture, assert_create_repos_dir (fixture, "no-repos-mount", &no_repos_repos, &no_repos_mount); assert_create_repos_dir (fixture, "repo1-mount", &repo1_repos, &repo1_mount); - repo1_repo_a = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[0], &repo1_repo_a_uri, + repo1_repo_a = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, "repo1-repo-a", &repo1_repo_a_uri, refs[0], &repo1_ref0_checksum, refs[2], &repo1_ref2_checksum, refs[5], &repo1_ref5_checksum, NULL); - repo1_repo_b = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[1], &repo1_repo_b_uri, + repo1_repo_b = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, "repo1-repo-b", &repo1_repo_b_uri, refs[1], &repo1_ref1_checksum, NULL); - assert_create_repo_symlink (repo1_repos, refs[2], "ref0"); /* repo1_repo_a */ - assert_create_repo_symlink (repo1_repos, refs[5], "../../../org.example.Collection1/exampleos/x86_64/ref0"); /* repo1_repo_a */ + assert_create_repo_symlink (repo1_repos, "repo1-repo-a-alias", "repo1-repo-a"); assert_create_repos_dir (fixture, "repo2-mount", &repo2_repos, &repo2_mount); - repo2_repo_a = assert_create_repo_dir (fixture, repo2_repos, repo2_mount, refs[0], &repo2_repo_a_uri, + repo2_repo_a = assert_create_repo_dir (fixture, repo2_repos, repo2_mount, "repo2-repo-a", &repo2_repo_a_uri, refs[0], &repo2_ref0_checksum, refs[1], &repo2_ref1_checksum, refs[2], &repo2_ref2_checksum, - refs[3], NULL, + refs[3], &repo2_ref3_checksum, NULL); - assert_create_repo_symlink (repo2_repos, refs[1], "ref0"); /* repo2_repo_a */ - assert_create_repo_symlink (repo2_repos, refs[2], "ref1"); /* repo2_repo_b */ - assert_create_repo_symlink (repo2_repos, refs[3], "/"); + assert_create_repo_symlink (repo2_repos, "repo2-repo-a-alias", "repo2-repo-a"); + assert_create_repo_symlink (repo2_repos, "dangling-symlink", "repo2-repo-b"); + assert_create_repo_symlink (repo2_repos, "root", "/"); mounts = g_list_prepend (mounts, non_removable_mount); mounts = g_list_prepend (mounts, no_repos_mount); @@ -456,10 +433,108 @@ test_repo_finder_mount_mixed_mounts (Fixture *fixture, else if (g_strcmp0 (uri, repo2_repo_a_uri) == 0 && g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0) { - g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 3); + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 4); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[0]), ==, repo2_ref0_checksum); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[1]), ==, repo2_ref1_checksum); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[2]), ==, repo2_ref2_checksum); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[3]), ==, repo2_ref3_checksum); + } + else + { + g_test_message ("Unknown result ‘%s’ with keyring ‘%s’.", + result->remote->name, result->remote->keyring); + g_assert_not_reached (); + } + } + + g_main_context_pop_thread_default (context); +} + +/* Test resolving the refs against a mock volume which contains two repositories + * in the default repository paths ostree/repo and .ostree/repo, to check that + * those paths are read */ +static void +test_repo_finder_mount_well_known (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(OstreeRepoFinderMount) finder = NULL; + g_autoptr(GVolumeMonitor) monitor = NULL; + g_autoptr(GMainContext) context = NULL; + g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */ + g_autoptr(GError) error = NULL; + g_autoptr(GList) mounts = NULL; /* (element-type OstreeMockMount) */ + g_autoptr(GMount) mount = NULL; + glnx_fd_close int repos = -1; + g_autoptr(OstreeRepo) repo_a = NULL, repo_b = NULL; + g_autofree gchar *repo_a_uri = NULL, *repo_b_uri = NULL; + g_autofree gchar *ref_a_checksum = NULL, *ref_b_checksum = NULL; + gsize i; + const OstreeCollectionRef ref_a = { "org.example.Collection1", "refA" }; + const OstreeCollectionRef ref_b = { "org.example.Collection2", "refB" }; + const OstreeCollectionRef * const refs[] = { &ref_a, &ref_b, NULL }; + + context = g_main_context_new (); + g_main_context_push_thread_default (context); + + /* Build the various mock drives/volumes/mounts, and some repositories with + * refs within them. We use "/" under the assumption that it’s on a separate + * file system from /tmp, so it’s an example of a symlink pointing outside + * its mount point. */ + assert_create_repos_dir (fixture, "mount", &repos, &mount); + repo_a = assert_create_repo_dir (fixture, repos, mount, "../../ostree/repo", &repo_a_uri, + &ref_a, &ref_a_checksum, + NULL); + repo_b = assert_create_repo_dir (fixture, repos, mount, "../../.ostree/repo", &repo_b_uri, + &ref_b, &ref_b_checksum, + NULL); + assert_create_repo_symlink (repos, "repo-a-alias", "../../ostree/repo"); + + mounts = g_list_prepend (mounts, mount); + + monitor = ostree_mock_volume_monitor_new (mounts, NULL); + finder = ostree_repo_finder_mount_new (monitor); + + assert_create_remote_config (fixture->parent_repo, "remote1", "https://nope1", "org.example.Collection1"); + assert_create_remote_config (fixture->parent_repo, "remote2", "https://nope2", "org.example.Collection2"); + + /* Resolve the refs. */ + ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs, + fixture->parent_repo, + NULL, result_cb, &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), + result, &error); + g_assert_no_error (error); + g_assert_nonnull (results); + g_assert_cmpuint (results->len, ==, 2); + + /* Check that the results are correct: the valid results canonicalised and + * deduplicated. */ + for (i = 0; i < results->len; i++) + { + g_autofree gchar *uri = NULL; + const gchar *keyring; + const OstreeRepoFinderResult *result = g_ptr_array_index (results, i); + + uri = g_key_file_get_string (result->remote->options, result->remote->group, "url", &error); + g_assert_no_error (error); + keyring = result->remote->keyring; + + if (g_strcmp0 (uri, repo_a_uri) == 0 && + g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0) + { + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, &ref_a), ==, ref_a_checksum); + } + else if (g_strcmp0 (uri, repo_b_uri) == 0 && + g_strcmp0 (keyring, "remote2.trustedkeys.gpg") == 0) + { + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, &ref_b), ==, ref_b_checksum); } else { @@ -482,6 +557,8 @@ int main (int argc, char **argv) test_repo_finder_mount_no_mounts, teardown); g_test_add ("/repo-finder-mount/mixed-mounts", Fixture, NULL, setup, test_repo_finder_mount_mixed_mounts, teardown); + g_test_add ("/repo-finder-mount/well-known", Fixture, NULL, setup, + test_repo_finder_mount_well_known, teardown); return g_test_run(); } From c62b36046bc28cb05f20a2e925c58f02e6dcc129 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 15 Sep 2017 16:03:36 +0100 Subject: [PATCH 14/78] lib/repo: Drop outdated FIXME comment from ostree-repo.h This was some incomplete planning from while the find_remotes() API was being designed; now totally outdated. Signed-off-by: Philip Withnall Closes: #1179 Approved by: cgwalters --- src/libostree/ostree-repo.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 682d4964..a2a46d4b 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1156,33 +1156,6 @@ ostree_repo_pull_one_dir (OstreeRepo *self, GCancellable *cancellable, GError **error); - - -#if 0 -FIXME -Called with: remote_name, refs, override-commit-ids -or: URL, refs, override-commit-ids -=> we only need refs; could use the remote_name or URL as additional results - -Summary file is downloaded first, so this would result in multiple downloads of -the summary, but we don’t care because of caching. - -Big problem preventing this from being the overall API: presenting the download -sizes in the gnome-software UI before the user chooses to download. - -_OSTREE_PUBLIC -gboolean ostree_repo_find_remotes_squashed (OstreeRepo *self, - const gchar * const *refs, -> options - GVariant *options, - OstreeRepoFinder **finders, -> options - GMainContext *context, -> nope - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -#endif - - - _OSTREE_PUBLIC gboolean ostree_repo_pull_with_options (OstreeRepo *self, const char *remote_name_or_baseurl, From 13c3898cc2ecc4d89b5756a2db78d709dd9e9f45 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 15 Sep 2017 16:29:22 -0400 Subject: [PATCH 15/78] tree-wide: Some glnx_fstatat_allow_noent() porting The new API is definitely nicer. Closes: #1180 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 10 +++--- src/libostree/ostree-repo-refs.c | 13 +++----- src/libostree/ostree-repo.c | 45 ++++++++++++------------- src/libostree/ostree-sysroot-deploy.c | 48 ++++++++++++--------------- src/libostree/ostree-sysroot.c | 13 +++----- src/libotutil/ot-fs-utils.c | 21 ------------ src/libotutil/ot-fs-utils.h | 5 --- 7 files changed, 55 insertions(+), 100 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index ed13b3bf..e226d500 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1249,12 +1249,10 @@ cleanup_tmpdir (OstreeRepo *self, if (strcmp (dent->d_name, "cache") == 0) continue; - if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) < 0) - { - if (errno == ENOENT) /* Did another cleanup win? */ - continue; - return glnx_throw_errno_prefix (error, "fstatat(%s)", dent->d_name); - } + if (!glnx_fstatat_allow_noent (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT) /* Did another cleanup win? */ + continue; /* First, if it's a directory which needs locking, but it's * busy, skip it. diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index b9b00896..78ac9121 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -545,12 +545,10 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(GHashTable) ret_all_refs = NULL; g_autofree char *remote = NULL; g_autofree char *ref_prefix = NULL; - ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - + g_autoptr(GHashTable) ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (refspec_prefix) { struct stat stbuf; @@ -571,12 +569,9 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, path = glnx_strjoina (prefix_path, ref_prefix); } - if (fstatat (self->repo_dir_fd, path, &stbuf, 0) < 0) - { - if (errno != ENOENT) - return glnx_throw_errno (error); - } - else + if (!glnx_fstatat_allow_noent (self->repo_dir_fd, path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { if (S_ISDIR (stbuf.st_mode)) { diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e6d8a747..f779db85 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1806,7 +1806,9 @@ repo_create_at_internal (int dfd, /* Early return if we have an existing repo */ { g_autofree char *objects_path = g_build_filename (path, "objects", NULL); - if (fstatat (dfd, objects_path, &stbuf, 0) == 0) + if (!glnx_fstatat_allow_noent (dfd, objects_path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { glnx_fd_close int repo_dfd = -1; if (!glnx_opendirat (dfd, path, TRUE, &repo_dfd, error)) @@ -1816,8 +1818,6 @@ repo_create_at_internal (int dfd, *out_dfd = glnx_steal_fd (&repo_dfd); return TRUE; } - else if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstatat"); } if (mkdirat (dfd, path, 0755) != 0) @@ -1830,32 +1830,29 @@ repo_create_at_internal (int dfd, if (!glnx_opendirat (dfd, path, TRUE, &repo_dfd, error)) return FALSE; - if (fstatat (repo_dfd, "config", &stbuf, 0) < 0) + if (!glnx_fstatat_allow_noent (repo_dfd, "config", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno == ENOENT) - { - const char *mode_str = NULL; - g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); + const char *mode_str = NULL; + g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); - if (!ostree_repo_mode_to_string (mode, &mode_str, error)) - return FALSE; - g_assert (mode_str); + if (!ostree_repo_mode_to_string (mode, &mode_str, error)) + return FALSE; + g_assert (mode_str); - g_string_append_printf (config_data, "mode=%s\n", mode_str); + g_string_append_printf (config_data, "mode=%s\n", mode_str); - const char *collection_id = NULL; - if (options) - g_variant_lookup (options, "collection-id", "&s", &collection_id); - if (collection_id != NULL) - g_string_append_printf (config_data, "collection-id=%s\n", collection_id); + const char *collection_id = NULL; + if (options) + g_variant_lookup (options, "collection-id", "&s", &collection_id); + if (collection_id != NULL) + g_string_append_printf (config_data, "collection-id=%s\n", collection_id); - if (!glnx_file_replace_contents_at (repo_dfd, "config", - (guint8*)config_data->str, config_data->len, - 0, cancellable, error)) - return FALSE; - } - else - return glnx_throw_errno_prefix (error, "fstatat"); + if (!glnx_file_replace_contents_at (repo_dfd, "config", + (guint8*)config_data->str, config_data->len, + 0, cancellable, error)) + return FALSE; } for (guint i = 0; i < G_N_ELEMENTS (state_dirs); i++) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 62ebd6b6..911c2854 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -689,12 +689,10 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, * when doing a deployment. */ const char selabeled[] = "var/.ostree-selabeled"; - gboolean deployment_var_labeled; - - if (!ot_query_exists_at (os_deploy_dfd, selabeled, &deployment_var_labeled, error)) + struct stat stbuf; + if (!glnx_fstatat_allow_noent (os_deploy_dfd, selabeled, &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - - if (!deployment_var_labeled) + if (errno == ENOENT) { { g_autofree char *msg = g_strdup_printf ("Relabeling /var (no stamp file '%s' found)", selabeled); @@ -764,12 +762,13 @@ merge_configuration (OstreeSysroot *sysroot, } } - gboolean etc_exists = FALSE; - if (!ot_query_exists_at (deployment_dfd, "etc", &etc_exists, error)) + struct stat stbuf; + if (!glnx_fstatat_allow_noent (deployment_dfd, "etc", &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - gboolean usretc_exists = FALSE; - if (!ot_query_exists_at (deployment_dfd, "usr/etc", &usretc_exists, error)) + gboolean etc_exists = (errno == 0); + if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/etc", &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; + gboolean usretc_exists = (errno == 0); if (etc_exists && usretc_exists) return glnx_throw (error, "Tree contains both /etc and /usr/etc"); @@ -1568,10 +1567,10 @@ install_deployment_kernel (OstreeSysroot *sysroot, * it doesn't exist already. */ struct stat stbuf; - if (fstatat (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->kernel_namever); if (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->kernel_srcpath, bootcsum_dfd, kernel_layout->kernel_namever, @@ -1586,10 +1585,10 @@ install_deployment_kernel (OstreeSysroot *sysroot, if (kernel_layout->initramfs_srcpath) { g_assert (kernel_layout->initramfs_namever); - if (fstatat (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->initramfs_namever); if (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->initramfs_srcpath, bootcsum_dfd, kernel_layout->initramfs_namever, sysroot->debug_flags, @@ -1599,19 +1598,14 @@ install_deployment_kernel (OstreeSysroot *sysroot, } g_autofree char *contents = NULL; - if (fstatat (deployment_dfd, "usr/lib/os-release", &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/lib/os-release", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - { - return glnx_throw_errno (error); - } - else - { - contents = glnx_file_get_contents_utf8_at (deployment_dfd, "etc/os-release", NULL, - cancellable, error); - if (!contents) - return glnx_prefix_error (error, "Reading /etc/os-release"); - } + contents = glnx_file_get_contents_utf8_at (deployment_dfd, "etc/os-release", NULL, + cancellable, error); + if (!contents) + return glnx_prefix_error (error, "Reading /etc/os-release"); } else { diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 18475d35..ee9b4818 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -541,12 +541,9 @@ parse_origin (OstreeSysroot *self, g_autoptr(GKeyFile) ret_origin = g_key_file_new (); struct stat stbuf; - if (fstatat (deployment_dfd, origin_path, &stbuf, 0) != 0) - { - if (errno != ENOENT) - return glnx_throw_errno (error); - } - else + if (!glnx_fstatat_allow_noent (deployment_dfd, origin_path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { g_autofree char *origin_contents = glnx_file_get_contents_utf8_at (deployment_dfd, origin_path, @@ -808,8 +805,8 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self, return FALSE; struct stat stbuf; - if (fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0) < 0) - return glnx_throw_errno_prefix (error, "fstatat"); + if (!glnx_fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0, error)) + return FALSE; if (out_changed) { diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 9100b85b..00b3c34f 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -104,27 +104,6 @@ ot_ensure_unlinked_at (int dfd, return TRUE; } -gboolean -ot_query_exists_at (int dfd, const char *path, - gboolean *out_exists, - GError **error) -{ - struct stat stbuf; - gboolean ret_exists; - - if (fstatat (dfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstatat(%s)", path); - ret_exists = FALSE; - } - else - ret_exists = TRUE; - - *out_exists = ret_exists; - return TRUE; -} - gboolean ot_openat_ignore_enoent (int dfd, const char *path, diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index e25522db..7f73762b 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -66,11 +66,6 @@ gboolean ot_openat_read_stream (int dfd, GCancellable *cancellable, GError **error); - -gboolean ot_query_exists_at (int dfd, const char *path, - gboolean *out_exists, - GError **error); - gboolean ot_ensure_unlinked_at (int dfd, const char *path, GError **error); From 223c940b46a4bb335665df7436566b73cdf0effd Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 19 Sep 2017 14:41:18 +0100 Subject: [PATCH 16/78] tests: Explicitly unset LANGUAGE after setting LC_ALL As a GNU extension, LANGUAGE takes precedence over LC_ALL for gettext(3) whenever the locale is not C, causing tests that grep for specific English strings to fail when run in non-English locales. The upstream glibc proposal for C.UTF-8 would give C.UTF-8 the same special case as C here, but the implementation in Debian does not currently have this, so we have to unset LANGUAGE too. Signed-off-by: Simon McVittie Closes: #1188 Approved by: jlebon --- tests/libtest-core.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/libtest-core.sh b/tests/libtest-core.sh index d0b7d372..ce0e4bb1 100644 --- a/tests/libtest-core.sh +++ b/tests/libtest-core.sh @@ -40,6 +40,8 @@ if locale -a | grep C.UTF-8 >/dev/null; then else export LC_ALL=C fi +# A GNU extension, used whenever LC_ALL is not C +unset LANGUAGE # This should really be the default IMO export G_DEBUG=fatal-warnings From 3e564116b26992fa68f82abb3da08f7572151554 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Sep 2017 15:46:03 -0400 Subject: [PATCH 17/78] lib/repo: Minor cleanup to object import function We have a lot of layers of abstraction here; let's fold in the `trusted` conditional into the call, since that's all the public API we're using does anyways. Prep for a future patch around object copying during imports. Closes: #1187 Approved by: jlebon --- src/libostree/ostree-repo.c | 45 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index f779db85..440d2bf9 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3598,23 +3598,12 @@ ostree_repo_import_object_from_with_trust (OstreeRepo *self, &variant, error)) return FALSE; - if (trusted) - { - if (!ostree_repo_write_metadata_trusted (self, objtype, - checksum, variant, - cancellable, error)) - return FALSE; - } - else - { - g_autofree guchar *real_csum = NULL; - - if (!ostree_repo_write_metadata (self, objtype, - checksum, variant, - &real_csum, - cancellable, error)) - return FALSE; - } + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_metadata (self, objtype, + checksum, variant, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; } else { @@ -3627,22 +3616,12 @@ ostree_repo_import_object_from_with_trust (OstreeRepo *self, cancellable, error)) return FALSE; - if (trusted) - { - if (!ostree_repo_write_content_trusted (self, checksum, - object_stream, length, - cancellable, error)) - return FALSE; - } - else - { - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_content (self, checksum, - object_stream, length, - &real_csum, - cancellable, error)) - return FALSE; - } + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_content (self, checksum, + object_stream, length, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; } return TRUE; From 5c4f26bd65b492e795ac8f9a5081fba4e60a3d42 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Sep 2017 12:08:48 -0400 Subject: [PATCH 18/78] lib/pull: Wait for pending ops to complete on error I saw in a stack trace that the main thread was calling `exit()` even while worker threads were alive and doing sha256/write/fsync etc. for objects. The stack trace was a SEGV as the main thread was calling into library `atexit()` handlers and we were a liblz4 destructor: ``` #0 0x00007f2db790f8d4 _fini (liblz4.so.1) #1 0x00007f2dbbae1c68 __run_exit_handlers (libc.so.6) ``` (Why that library has a destructor I don't know offhand, can't find it in the source in a quick look) Anyways, global library destructors and worker threads continuing simply don't mix. Let's wait for our outstanding operations before we exit. This is also a good idea for projects using libostree as a shared library, as we don't want worker threads outliving operations. Our existing pull corruption tests exercise coverage here. I added a new `caught-error` status boolean to the progress API, and use it the commandline to tell the user that we're waiting for outstanding ops. Closes: #1185 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 37 ++++++++++++++++++++++++++------ src/libostree/ostree-repo.c | 7 +++++- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 92aeb5bc..91fa7a96 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -218,6 +218,7 @@ static gboolean scan_one_metadata_object_c (OtPullData *pull_dat const OstreeCollectionRef *ref, GCancellable *cancellable, GError **error); +static void scan_object_queue_data_free (ScanObjectQueueData *scan_data); static gboolean update_progress (gpointer user_data) @@ -258,6 +259,7 @@ update_progress (gpointer user_data) "fetched", "u", fetched, "requested", "u", requested, "scanning", "u", g_queue_is_empty (&pull_data->scan_object_queue) ? 0 : 1, + "caught-error", "b", pull_data->caught_error, "scanned-metadata", "u", n_scanned_metadata, "bytes-transferred", "t", bytes_transferred, "start-time", "t", start_time, @@ -309,9 +311,6 @@ pull_termination_condition (OtPullData *pull_data) /* we only enter the main loop when we're fetching objects */ g_assert (pull_data->phase == OSTREE_PULL_PHASE_FETCHING_OBJECTS); - if (pull_data->caught_error) - return TRUE; - if (pull_data->dry_run) return pull_data->dry_run_emitted_progress; @@ -321,6 +320,10 @@ pull_termination_condition (OtPullData *pull_data) return current_idle; } +/* Most async operations finish by calling this function; it will consume + * @errorp if set, update statistics, and initiate processing of any further + * requests as appropriate. + */ static void check_outstanding_requests_handle_error (OtPullData *pull_data, GError **errorp) @@ -340,6 +343,18 @@ check_outstanding_requests_handle_error (OtPullData *pull_data, g_clear_error (errorp); } } + + /* If we're in error state, we wait for any pending operations to complete, + * but ensure that all no further operations are queued. + */ + if (pull_data->caught_error) + { + g_queue_foreach (&pull_data->scan_object_queue, (GFunc) scan_object_queue_data_free, NULL); + g_queue_clear (&pull_data->scan_object_queue); + g_hash_table_remove_all (pull_data->pending_fetch_metadata); + g_hash_table_remove_all (pull_data->pending_fetch_deltaparts); + g_hash_table_remove_all (pull_data->pending_fetch_content); + } else { GHashTableIter hiter; @@ -424,6 +439,15 @@ fetcher_queue_is_full (OtPullData *pull_data) return fetch_full || deltas_full || writes_full; } +static void +scan_object_queue_data_free (ScanObjectQueueData *scan_data) +{ + g_free (scan_data->path); + if (scan_data->requested_ref != NULL) + ostree_collection_ref_free (scan_data->requested_ref); + g_free (scan_data); +} + static gboolean idle_worker (gpointer user_data) { @@ -447,11 +471,8 @@ idle_worker (gpointer user_data) pull_data->cancellable, &error); check_outstanding_requests_handle_error (pull_data, &error); + scan_object_queue_data_free (scan_data); - g_free (scan_data->path); - if (scan_data->requested_ref != NULL) - ostree_collection_ref_free (scan_data->requested_ref); - g_free (scan_data); return G_SOURCE_CONTINUE; } @@ -4245,6 +4266,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_clear_pointer (&pull_data->pending_fetch_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->pending_fetch_metadata, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->pending_fetch_deltaparts, (GDestroyNotify) g_hash_table_unref); + g_queue_foreach (&pull_data->scan_object_queue, (GFunc) scan_object_queue_data_free, NULL); + g_queue_clear (&pull_data->scan_object_queue); g_clear_pointer (&pull_data->idle_src, (GDestroyNotify) g_source_destroy); g_clear_pointer (&pull_data->dirs, (GDestroyNotify) g_ptr_array_unref); g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 440d2bf9..0056d805 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4023,7 +4023,7 @@ ostree_repo_pull_default_console_progress_changed (OstreeAsyncProgress *progress gpointer user_data) { g_autofree char *status = NULL; - gboolean scanning; + gboolean caught_error, scanning; guint outstanding_fetches; guint outstanding_metadata_fetches; guint outstanding_writes; @@ -4039,6 +4039,7 @@ ostree_repo_pull_default_console_progress_changed (OstreeAsyncProgress *progress "outstanding-fetches", "u", &outstanding_fetches, "outstanding-metadata-fetches", "u", &outstanding_metadata_fetches, "outstanding-writes", "u", &outstanding_writes, + "caught-error", "b", &caught_error, "scanning", "u", &scanning, "scanned-metadata", "u", &n_scanned_metadata, "fetched-delta-parts", "u", &fetched_delta_parts, @@ -4052,6 +4053,10 @@ ostree_repo_pull_default_console_progress_changed (OstreeAsyncProgress *progress { g_string_append (buf, status); } + else if (caught_error) + { + g_string_append_printf (buf, "Caught error, waiting for outstanding tasks"); + } else if (outstanding_fetches) { guint64 bytes_transferred, start_time, total_delta_part_size; From db10bf464fcf28e3c21724353ffd6168c9f77aae Mon Sep 17 00:00:00 2001 From: Anton Gerasimov Date: Mon, 18 Sep 2017 16:29:27 +0200 Subject: [PATCH 19/78] Add support for pkcs11 URIs in TLS client key/certificate Closes: #1183 Approved by: cgwalters --- src/libostree/ostree-fetcher-curl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index e3fd1a12..c22141ec 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -747,6 +747,24 @@ initiate_next_curl_request (FetcherRequest *req, if (self->tls_client_cert_path) { + /* Support for pkcs11: + * https://github.com/ostreedev/ostree/pull/1183 + * This will be used by https://github.com/advancedtelematic/aktualizr + * at least to fetch certificates. No test coverage at the moment + * though. See https://gitlab.com/gnutls/gnutls/tree/master/tests/pkcs11 + * and https://github.com/opendnssec/SoftHSMv2 and + * https://github.com/p11-glue/p11-kit/tree/master/p11-kit for + * possible ideas there. + */ + if (g_str_has_prefix (self->tls_client_key_path, "pkcs11:")) + { + curl_easy_setopt (req->easy, CURLOPT_SSLENGINE, "pkcs11"); + curl_easy_setopt (req->easy, CURLOPT_SSLENGINE_DEFAULT, 1L); + curl_easy_setopt (req->easy, CURLOPT_SSLKEYTYPE, "ENG"); + } + if (g_str_has_prefix (self->tls_client_cert_path, "pkcs11:")) + curl_easy_setopt (req->easy, CURLOPT_SSLCERTTYPE, "ENG"); + curl_easy_setopt (req->easy, CURLOPT_SSLCERT, self->tls_client_cert_path); curl_easy_setopt (req->easy, CURLOPT_SSLKEY, self->tls_client_key_path); } From e3c3ec5dd91492e82c79223052443d038c60f41c Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 19 Sep 2017 18:37:58 +0100 Subject: [PATCH 20/78] tests: Reset umask to 022 while creating test repository In test-basic-root.sh we make assertions about the permissions of files like baz/cow, which were created without an explicit chmod. We can't do that unless we control the permissions. For some reason the "debomatic" autobuilder used to do some Debian archive rebuilds does the entire build including build-time tests as uid 0 with umask 002, which broke those assertions. This seems a weird thing to do, and I've opened a bug, but it also seems reasonable to fix this test. This also lets us remove a couple of existing workarounds for the same issue. Bug-Debian: https://bugs.debian.org/876138 Signed-off-by: Simon McVittie Closes: #1192 Approved by: cgwalters --- tests/libtest.sh | 3 +++ tests/test-basic-user.sh | 8 ++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index 73e88891..1ae04a74 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -150,6 +150,8 @@ setup_test_repository () { export OSTREE="${CMD_PREFIX} ostree ${ot_repo}" cd ${test_tmpdir} + local oldumask="$(umask)" + umask 022 mkdir files cd files ot_files=`pwd` @@ -172,6 +174,7 @@ setup_test_repository () { ln -s nonexistent baz/alink mkdir baz/another/ echo x > baz/another/y + umask "${oldumask}" cd ${test_tmpdir}/files $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Test Commit 2" -m "Commit body second" diff --git a/tests/test-basic-user.sh b/tests/test-basic-user.sh index 94866550..291806c8 100755 --- a/tests/test-basic-user.sh +++ b/tests/test-basic-user.sh @@ -34,11 +34,7 @@ setup_test_repository "bare-user" cd ${test_tmpdir} objpath_nonexec=$(ostree_file_path_to_object_path repo test2 baz/cow) -# Sigh, umask -touch testfile -default_mode=$(stat -c '%a' testfile) -rm testfile -assert_file_has_mode ${objpath_nonexec} ${default_mode} +assert_file_has_mode ${objpath_nonexec} 644 objpath_ro=$(ostree_file_path_to_object_path repo test2 baz/cowro) assert_file_has_mode ${objpath_ro} 600 objpath_exec=$(ostree_file_path_to_object_path repo test2 baz/deeper/ohyeahx) @@ -48,7 +44,7 @@ echo "ok bare-user committed modes" rm test2-checkout -rf $OSTREE checkout -U -H test2 test2-checkout cd test2-checkout -assert_file_has_mode baz/cow ${default_mode} +assert_file_has_mode baz/cow 644 assert_file_has_mode baz/cowro 600 assert_file_has_mode baz/deeper/ohyeahx 755 echo "ok bare-user checkout modes" From 74cf3594eed955847b7a16a7e8a775ba69a47617 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Tue, 19 Sep 2017 16:34:11 -0700 Subject: [PATCH 21/78] lib/pull: Clarify use of unsigned summary support Update the comments and remove an unneeded variable to make it clear that the find_remotes_async() / pull_from_remotes_async() functions use the unsigned summary support. This is a follow-up of commit 8c148eb7e "lib/repo-finder: Emit gpg-verify-summary=false in dynamic remote config". Closes: #1195 Approved by: pwithnall --- src/libostree/ostree-repo-pull.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 91fa7a96..5c36e081 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -4544,7 +4544,7 @@ static void find_remotes_cb (GObject *obj, * will typically be all available finders using their default options (but * this is not guaranteed). * - * GPG verification of the summary and all commits will be used unconditionally. + * GPG verification of commits will be used unconditionally. * * This will use the thread-default #GMainContext, but will not iterate it. * @@ -4843,7 +4843,7 @@ find_remotes_cb (GObject *obj, for (i = 0; i < results->len; i++) { OstreeRepoFinderResult *result = g_ptr_array_index (results, i); - g_autoptr(GBytes) summary_bytes = NULL, summary_sig_bytes = NULL; + g_autoptr(GBytes) summary_bytes = NULL; g_autoptr(GVariant) summary_v = NULL; guint64 summary_last_modified; g_autoptr(GVariant) summary_refs = NULL; @@ -4860,13 +4860,12 @@ find_remotes_cb (GObject *obj, g_debug ("%s: Fetching summary for remote ‘%s’ with keyring ‘%s’.", G_STRFUNC, result->remote->name, result->remote->keyring); - /* Download the summary and signature, and validate the signature. This - * will load from the cache if possible. */ + /* Download the summary. This will load from the cache if possible. */ ostree_repo_remote_fetch_summary_with_options (self, result->remote->name, NULL, /* no options */ &summary_bytes, - &summary_sig_bytes, + NULL, cancellable, &error); @@ -5274,7 +5273,7 @@ copy_option (GVariantDict *master_options, * immediately. The results of any successfully completed downloads at that * point will remain cached in the local repository. * - * GPG verification of the summary and all commits will be used unconditionally. + * GPG verification of commits will be used unconditionally. * * The following @options are currently defined: * From 7a8511e0ca9c4e2441077ad0f2872c35a199eebe Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Sep 2017 13:58:54 -0400 Subject: [PATCH 22/78] tests/libtest: Factor out user xattr detection Make the equivalent of a `GOnce` or Rust `lazy_static!` detecting this and share it between the two callers. Prep for a future similar patch for strace fault injection. Closes: #1186 Approved by: jlebon --- tests/libtest.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index 1ae04a74..5017abea 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -515,9 +515,21 @@ os_repository_new_commit () } # Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi +_have_user_xattrs='' +have_user_xattrs() { + if test "${_have_user_xattrs}" = ''; then + touch test-xattrs + if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then + _have_user_xattrs=yes + else + _have_user_xattrs=no + fi + rm -f test-xattrs + fi + test ${_have_user_xattrs} = yes +} skip_one_without_user_xattrs () { - touch test-xattrs - if ! setfattr -n user.testvalue -v somevalue test-xattrs; then + if ! have_user_xattrs; then echo "ok # SKIP - this test requires xattr support" return 0 else @@ -526,9 +538,9 @@ skip_one_without_user_xattrs () { } skip_without_user_xattrs () { - touch test-xattrs - setfattr -n user.testvalue -v somevalue test-xattrs || \ + if ! have_user_xattrs; then skip "this test requires xattr support" + fi } skip_without_fuse () { From 75150fe04a5dd830de87abfde99ce66ab9feb5a7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Sep 2017 14:29:16 -0400 Subject: [PATCH 23/78] lib/repo: Don't syncfs or fsync() dirs if fsync opt is disabled There are use cases for not syncing at all; think build cache repos, etc. Let's be consistent here and make sure if fsync is disabled we do no sync at all. I chose this opportunity to add tests using the shiny new strace fault injection. I can forsee using this for a lot more things, so I made the support for detecting things generic. Related: https://github.com/ostreedev/ostree/issues/1184 Closes: #1186 Approved by: jlebon --- ci/build.sh | 2 +- src/libostree/ostree-repo-commit.c | 16 ++++++++++------ tests/basic-test.sh | 16 +++++++++++++--- tests/libtest.sh | 23 +++++++++++++++++++++++ 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 26e2ff37..33ef9503 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -10,7 +10,7 @@ pkg_upgrade pkg_install_builddeps ostree # Until this propagates farther pkg_install 'pkgconfig(libcurl)' 'pkgconfig(openssl)' -pkg_install sudo which attr fuse \ +pkg_install sudo which attr fuse strace \ libubsan libasan libtsan PyYAML redhat-rpm-config \ elfutils if test -n "${CI_PKGS:-}"; then diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index e226d500..04349ed0 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1187,7 +1187,7 @@ rename_pending_loose_objects (OstreeRepo *self, renamed_some_object = TRUE; } - if (renamed_some_object) + if (renamed_some_object && !self->disable_fsync) { /* Ensure that in the case of a power cut all the directory metadata that we want has reached the disk. In particular, we want this before we @@ -1208,8 +1208,11 @@ rename_pending_loose_objects (OstreeRepo *self, } /* In case we created any loose object subdirs, make sure they are on disk */ - if (fsync (self->objects_dir_fd) == -1) - return glnx_throw_errno_prefix (error, "fsync"); + if (!self->disable_fsync) + { + if (fsync (self->objects_dir_fd) == -1) + return glnx_throw_errno_prefix (error, "fsync"); + } if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error)) return FALSE; @@ -1517,10 +1520,11 @@ ostree_repo_commit_transaction (OstreeRepo *self, if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_PRE_COMMIT) > 0) return glnx_throw (error, "OSTREE_REPO_TEST_ERROR_PRE_COMMIT specified"); - /* FIXME: Added since valgrind in el7 doesn't know about - * `syncfs`...we should delete this later. + /* FIXME: Added OSTREE_SUPPRESS_SYNCFS since valgrind in el7 doesn't know + * about `syncfs`...we should delete this later. */ - if (g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL) + if (!self->disable_fsync && + g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL) { if (syncfs (self->tmp_dir_fd) < 0) return glnx_throw_errno_prefix (error, "syncfs"); diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 5058af1d..218bc31c 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..$((72 + ${extra_basic_tests:-0}))" +echo "1..$((73 + ${extra_basic_tests:-0}))" $CMD_PREFIX ostree --version > version.yaml python -c 'import yaml; yaml.safe_load(open("version.yaml"))' @@ -809,8 +809,18 @@ cd ${test_tmpdir} rm -rf test2-checkout mkdir -p test2-checkout cd test2-checkout -touch should-not-be-fsynced -$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Unfsynced commit" --fsync=false +echo 'should not be fsynced' > should-not-be-fsynced +if ! skip_one_without_strace_fault_injection; then + # Test that --fsync=false doesn't fsync + fsync_inject_error_ostree="strace -o /dev/null -f -e inject=syncfs,fsync,sync:error=EPERM ostree" + ${fsync_inject_error_ostree} --repo=${test_tmpdir}/repo commit ${COMMIT_ARGS} -b test2-no-fsync --fsync=false + # And test that we get EPERM if we inject an error + if ${fsync_inject_error_ostree} --repo=${test_tmpdir}/repo commit ${COMMIT_ARGS} -b test2-no-fsync 2>err.txt; then + fatal "fsync error injection failed" + fi + assert_file_has_content err.txt 'sync.*Operation not permitted' + echo "ok fsync disabled" +fi # Run this test only as non-root user. When run as root, the chmod # won't have any effect. diff --git a/tests/libtest.sh b/tests/libtest.sh index 5017abea..2b30e654 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -543,6 +543,29 @@ skip_without_user_xattrs () { fi } +# https://brokenpi.pe/tools/strace-fault-injection +_have_strace_fault_injection='' +have_strace_fault_injection() { + if test "${_have_strace_fault_injection}" = ''; then + if strace -P ${test_srcdir}/libtest-core.sh -e inject=read:retval=0 cat ${test_srcdir}/libtest-core.sh >out.txt && + test '!' -s out.txt; then + _have_strace_fault_injection=yes + else + _have_strace_fault_injection=no + fi + rm -f out.txt + fi + test ${_have_strace_fault_injection} = yes +} + +skip_one_without_strace_fault_injection() { + if ! have_strace_fault_injection; then + echo "ok # SKIP this test requires strace fault injection" + return 0 + fi + return 1 +} + skip_without_fuse () { fusermount --version >/dev/null 2>&1 || skip "no fusermount" From 3767ac4ad83d0d0c720d68603f65bfd9a0ebb006 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 11:00:09 -0400 Subject: [PATCH 24/78] lib/repo: Move alloca() outside of loop Just noticed this while looking at the code for a different issue. Closes: #1201 Approved by: jlebon --- src/libostree/ostree-repo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 0056d805..e04a1b6a 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -5179,11 +5179,11 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, ret_tmpdir.initialized = TRUE; } + const char *tmpdir_name_template = glnx_strjoina (tmpdir_prefix, "XXXXXX"); while (!ret_tmpdir.initialized) { g_auto(GLnxTmpDir) new_tmpdir = { 0, }; /* No existing tmpdir found, create a new */ - const char *tmpdir_name_template = glnx_strjoina (tmpdir_prefix, "XXXXXX"); if (!glnx_mkdtempat (tmpdir_dfd, tmpdir_name_template, 0755, &new_tmpdir, error)) return FALSE; From f639f8f4c0ea8992203848c4e5f1c841c14f58f1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 11:00:47 -0400 Subject: [PATCH 25/78] lib/checkout: Squash a gcc maybe-uninitialized warning gcc doesn't know that our enum cases must be exhaustive. Closes: #1201 Approved by: jlebon --- src/libostree/ostree-repo-checkout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 7e36e689..de239eeb 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -303,11 +303,11 @@ create_file_copy_from_input_at (OstreeRepo *repo, return FALSE; /* The add/union/none behaviors map directly to GLnxLinkTmpfileReplaceMode */ - GLnxLinkTmpfileReplaceMode replace_mode; + GLnxLinkTmpfileReplaceMode replace_mode = GLNX_LINK_TMPFILE_NOREPLACE; switch (options->overwrite_mode) { case OSTREE_REPO_CHECKOUT_OVERWRITE_NONE: - replace_mode = GLNX_LINK_TMPFILE_NOREPLACE; + /* Handled above */ break; case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES: replace_mode = GLNX_LINK_TMPFILE_REPLACE; From 3f8f878fa38d9b515544be08ed5df4127dc1bc12 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 11:01:29 -0400 Subject: [PATCH 26/78] tree-wide: Squash a few warnings when building with no features Noticed these since I had a local configured build with no features for testing the PAPR context for it. Closes: #1201 Approved by: jlebon --- src/ostree/ot-builtin-commit.c | 2 ++ src/ostree/ot-builtin-export.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index eb5e99b0..1665765f 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -224,6 +224,7 @@ commit_filter (OstreeRepo *self, return OSTREE_REPO_COMMIT_FILTER_ALLOW; } +#ifdef HAVE_LIBARCHIVE typedef struct { GRegex *regex; const char *replacement; @@ -245,6 +246,7 @@ handle_translate_pathname (OstreeRepo *repo, g_assert (ret); return ret; } +#endif static gboolean commit_editor (OstreeRepo *repo, diff --git a/src/ostree/ot-builtin-export.c b/src/ostree/ot-builtin-export.c index aa79824e..b68cbb6d 100644 --- a/src/ostree/ot-builtin-export.c +++ b/src/ostree/ot-builtin-export.c @@ -68,15 +68,15 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; gboolean ret = FALSE; - const char *rev; g_autoptr(GFile) root = NULL; g_autoptr(GFile) subtree = NULL; g_autofree char *commit = NULL; g_autoptr(GVariant) commit_data = NULL; #ifdef HAVE_LIBARCHIVE + const char *rev; g_autoptr(OtAutoArchiveWrite) a = NULL; -#endif OstreeRepoExportArchiveOptions opts = { 0, }; +#endif context = g_option_context_new ("COMMIT - Stream COMMIT to stdout in tar format"); From d4c7093e370843c57eab2f89f0c39ef449e6b32e Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 20 Sep 2017 18:38:16 +0000 Subject: [PATCH 27/78] rofiles-fuse: also pass mode for O_RDONLY In the `O_RDONLY` case, we were calling `openat` without a mode argument. However, it's perfectly legal (albeit unusual) to do `open(O_RDONLY|O_CREAT)`. One such application that makes use of this is `flock(1)`. This was actually caught by `_FORTIFY_SOURCE=2`, and once we run `rofiles-fuse` with `-f`, the message is clear: ``` *** invalid openat64 call: O_CREAT or O_TMPFILE without mode ***: rofiles-fuse terminated ======= Backtrace: ========= /lib64/libc.so.6(+0x7c8dc)[0x7f36d9f188dc] /lib64/libc.so.6(__fortify_fail+0x37)[0x7f36d9fbfaa7] /lib64/libc.so.6(+0x10019a)[0x7f36d9f9c19a] rofiles-fuse[0x401768] ... ``` Without `_FORTIFY_SOURCE`, the file gets created, but its mode is completely random. I ran into this while investigating https://github.com/projectatomic/rpm-ostree/pull/1003. Closes: #1200 Approved by: cgwalters --- src/rofiles-fuse/main.c | 2 +- tests/test-rofiles-fuse.sh | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rofiles-fuse/main.c b/src/rofiles-fuse/main.c index 6deaa6d0..f2b1b650 100644 --- a/src/rofiles-fuse/main.c +++ b/src/rofiles-fuse/main.c @@ -313,7 +313,7 @@ do_open (const char *path, mode_t mode, struct fuse_file_info *finfo) if ((finfo->flags & O_ACCMODE) == O_RDONLY) { /* Read */ - fd = openat (basefd, path, finfo->flags); + fd = openat (basefd, path, finfo->flags, mode); if (fd == -1) return -errno; } diff --git a/tests/test-rofiles-fuse.sh b/tests/test-rofiles-fuse.sh index d329d765..6222929e 100755 --- a/tests/test-rofiles-fuse.sh +++ b/tests/test-rofiles-fuse.sh @@ -26,7 +26,7 @@ skip_without_user_xattrs setup_test_repository "bare" -echo "1..7" +echo "1..8" cd ${test_tmpdir} mkdir mnt @@ -114,3 +114,6 @@ fi assert_file_has_content err.txt "Unable to do hardlink checkout across devices" echo "ok checkout copy fallback" + +# check that O_RDONLY|O_CREAT is handled correctly; used by flock(1) at least +flock mnt/nonexistent-file echo "ok create file in ro mode" From 160864d557c02badc7e27a66484ffdf8a13b8341 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 18 Sep 2017 15:46:03 -0400 Subject: [PATCH 28/78] lib: Move bareuseronly verification into commit/core Conceptually `ostree-repo-pull.c` should be be written using just public APIs; we theoretically support building without HTTP for people who just want to use the object store portion and do their own fetching. We have some nontrivial behaviors in the pull layer though; one of those is the "bareuseronly" verification. Make a new internal API that accepts flags, move it into `commit.c`. This is prep for further work in changing object import to support reflinks. Closes: #1193 Approved by: jlebon --- src/libostree/ostree-core-private.h | 13 ++ src/libostree/ostree-core.c | 23 +++ src/libostree/ostree-repo-commit.c | 249 +++++++++++++++++++++++++++- src/libostree/ostree-repo-private.h | 15 ++ src/libostree/ostree-repo-pull.c | 90 ++-------- src/libostree/ostree-repo.c | 208 +---------------------- tests/basic-test.sh | 2 +- tests/pull-test.sh | 2 +- tests/test-basic-user-only.sh | 2 +- 9 files changed, 316 insertions(+), 288 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index 5a2835d5..e81537a6 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -134,6 +134,19 @@ static inline char * _ostree_get_commitpartial_path (const char *checksum) return g_strconcat ("state/", checksum, ".commitpartial", NULL); } +gboolean +_ostree_validate_bareuseronly_mode (guint32 mode, + const char *checksum, + GError **error); +static inline gboolean +_ostree_validate_bareuseronly_mode_finfo (GFileInfo *finfo, + const char *checksum, + GError **error) +{ + const guint32 content_mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode"); + return _ostree_validate_bareuseronly_mode (content_mode, checksum, error); +} + gboolean _ostree_parse_delta_name (const char *delta_name, char **out_from, diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 7d34278a..e64cee4c 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1998,6 +1998,29 @@ ostree_validate_structureof_dirtree (GVariant *dirtree, return TRUE; } +/* This bit mirrors similar code in commit_loose_regfile_object() for the + * bare-user-only mode. It's opt-in though for all pulls. + */ +gboolean +_ostree_validate_bareuseronly_mode (guint32 content_mode, + const char *checksum, + GError **error) +{ + if (S_ISREG (content_mode)) + { + const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775); + if (invalid_modebits > 0) + return glnx_throw (error, "Content object %s: invalid mode 0%04o with bits 0%04o", + checksum, content_mode, invalid_modebits); + } + else if (S_ISLNK (content_mode)) + ; /* Nothing */ + else + g_assert_not_reached (); + + return TRUE; +} + static gboolean validate_stat_mode_perms (guint32 mode, GError **error) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 04349ed0..6d770dea 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -262,10 +262,8 @@ commit_loose_regfile_object (OstreeRepo *self, } else if (self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY) { - guint32 invalid_modebits = (mode & ~S_IFMT) & ~0775; - if (invalid_modebits > 0) - return glnx_throw (error, "Invalid mode 0%04o with bits 0%04o in bare-user-only repository", - mode, invalid_modebits); + if (!_ostree_validate_bareuseronly_mode (mode, checksum, error)) + return FALSE; if (!glnx_fchmod (tmpf->fd, mode, error)) return FALSE; @@ -3171,6 +3169,249 @@ G_DEFINE_BOXED_TYPE(OstreeRepoCommitModifier, ostree_repo_commit_modifier, ostree_repo_commit_modifier_ref, ostree_repo_commit_modifier_unref); +/* Special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 + * see below for any more comments. + */ +static gboolean +import_is_bareuser_only_conversion (OstreeRepo *src_repo, + OstreeRepo *dest_repo, + OstreeObjectType objtype) +{ + return src_repo->mode == OSTREE_REPO_MODE_BARE_USER + && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY + && objtype == OSTREE_OBJECT_TYPE_FILE; +} + +/* Returns TRUE if we can potentially just call link() to copy an object. */ +static gboolean +import_via_hardlink_is_possible (OstreeRepo *src_repo, + OstreeRepo *dest_repo, + OstreeObjectType objtype) +{ + /* We need the ability to make hardlinks */ + if (src_repo->owner_uid != dest_repo->owner_uid) + return FALSE; + /* Equal modes are always compatible */ + if (src_repo->mode == dest_repo->mode) + return TRUE; + /* Metadata is identical between all modes */ + if (OSTREE_OBJECT_TYPE_IS_META (objtype)) + return TRUE; + /* And now a special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 + */ + if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype)) + return TRUE; + return FALSE; +} + +/* Copy the detached metadata for commit @checksum from @source repo + * to @self. + */ +static gboolean +copy_detached_metadata (OstreeRepo *self, + OstreeRepo *source, + const char *checksum, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GVariant) detached_meta = NULL; + if (!ostree_repo_read_commit_detached_metadata (source, + checksum, &detached_meta, + cancellable, error)) + return FALSE; + + if (detached_meta) + { + if (!ostree_repo_write_commit_detached_metadata (self, + checksum, detached_meta, + cancellable, error)) + return FALSE; + } + + return TRUE; +} + +/* Try to import an object by just calling linkat(); returns + * a value in @out_was_supported if we were able to do it or not. + */ +static gboolean +import_one_object_link (OstreeRepo *self, + OstreeRepo *source, + const char *checksum, + OstreeObjectType objtype, + gboolean *out_was_supported, + GCancellable *cancellable, + GError **error) +{ + const char *errprefix = glnx_strjoina ("Importing ", checksum, ".", + ostree_object_type_to_string (objtype)); + GLNX_AUTO_PREFIX_ERROR (errprefix, error); + char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; + _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode); + + /* Hardlinking between bare-user → bare-user-only is only possible for regular + * files, *not* symlinks, which in bare-user are stored as regular files. At + * this point we need to parse the file to see the difference. + */ + if (import_is_bareuser_only_conversion (source, self, objtype)) + { + struct stat stbuf; + + if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf, + NULL, NULL, cancellable, error)) + return FALSE; + + if (S_ISREG (stbuf.st_mode)) + { + /* This is OK, we'll drop through and try a hardlink */ + } + else if (S_ISLNK (stbuf.st_mode)) + { + /* NOTE early return */ + *out_was_supported = FALSE; + return TRUE; + } + else + g_assert_not_reached (); + } + + if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error)) + return FALSE; + + *out_was_supported = TRUE; + if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0) + { + if (errno == EEXIST) + return TRUE; + else if (errno == EMLINK || errno == EXDEV || errno == EPERM) + { + /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the + * optimization of hardlinking instead of copying. + */ + *out_was_supported = FALSE; + return TRUE; + } + else + return glnx_throw_errno_prefix (error, "linkat"); + } + + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + { + if (!copy_detached_metadata (self, source, checksum, cancellable, error)) + return FALSE; + } + + return TRUE; +} + +/* A version of ostree_repo_import_object_from_with_trust() + * with flags; may make this public API later. + */ +gboolean +_ostree_repo_import_object (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + OstreeRepoImportFlags flags, + GCancellable *cancellable, + GError **error) +{ + const gboolean trusted = (flags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0; + /* Implements OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES which was designed for flatpak */ + const gboolean verify_bareuseronly = (flags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; + + /* If we need to do bareuseronly verification, let's dispense with that + * first so we don't complicate the rest of the code below. + */ + if (verify_bareuseronly && !OSTREE_OBJECT_TYPE_IS_META (objtype)) + { + g_autoptr(GFileInfo) src_finfo = NULL; + if (!ostree_repo_load_file (source, checksum, + NULL, &src_finfo, NULL, + cancellable, error)) + return FALSE; + + if (!_ostree_validate_bareuseronly_mode_finfo (src_finfo, checksum, error)) + return FALSE; + } + + /* We try to import via hardlink. If the remote is explicitly not trusted + * (i.e.) their checksums may be incorrect, we skip that. Also, we require the + * repository modes to match, as well as the owner uid (since we need to be + * able to make hardlinks). + */ + if (trusted && import_via_hardlink_is_possible (source, self, objtype)) + { + gboolean hardlink_was_supported = FALSE; + + if (!import_one_object_link (self, source, checksum, objtype, + &hardlink_was_supported, + cancellable, error)) + return FALSE; + + /* If we hardlinked, we're done! */ + if (hardlink_was_supported) + return TRUE; + } + + /* The copy path */ + + /* First, do we have the object already? */ + gboolean has_object; + if (!ostree_repo_has_object (self, objtype, checksum, &has_object, + cancellable, error)) + return FALSE; + /* If we have it, we're done */ + if (has_object) + return TRUE; + + if (OSTREE_OBJECT_TYPE_IS_META (objtype)) + { + /* Metadata object */ + g_autoptr(GVariant) variant = NULL; + + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + { + /* FIXME - cleanup detached metadata if copy below fails */ + if (!copy_detached_metadata (self, source, checksum, cancellable, error)) + return FALSE; + } + + if (!ostree_repo_load_variant (source, objtype, checksum, + &variant, error)) + return FALSE; + + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_metadata (self, objtype, + checksum, variant, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; + } + else + { + /* Content object */ + guint64 length; + g_autoptr(GInputStream) object_stream = NULL; + + if (!ostree_repo_load_object_stream (source, objtype, checksum, + &object_stream, &length, + cancellable, error)) + return FALSE; + + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_content (self, checksum, + object_stream, length, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; + } + + return TRUE; +} + static OstreeRepoTransactionStats * ostree_repo_transaction_stats_copy (OstreeRepoTransactionStats *stats) { diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index dc785690..f5eb140e 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -343,6 +343,21 @@ _ostree_repo_verify_commit_internal (OstreeRepo *self, GCancellable *cancellable, GError **error); +typedef enum { + _OSTREE_REPO_IMPORT_FLAGS_NONE, + _OSTREE_REPO_IMPORT_FLAGS_TRUSTED, + _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY, +} OstreeRepoImportFlags; + +gboolean +_ostree_repo_import_object (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + OstreeRepoImportFlags flags, + GCancellable *cancellable, + GError **error); + gboolean _ostree_repo_commit_tmpf_final (OstreeRepo *self, const char *checksum, diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 5c36e081..d8d2e34b 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -623,33 +623,6 @@ pull_matches_subdir (OtPullData *pull_data, return FALSE; } -/* This bit mirrors similar code in commit_loose_content_object() for the - * bare-user-only mode. It's opt-in though for all pulls. - */ -static gboolean -validate_bareuseronly_mode (OtPullData *pull_data, - const char *checksum, - guint32 content_mode, - GError **error) -{ - if (!pull_data->is_bareuseronly_files) - return TRUE; - - if (S_ISREG (content_mode)) - { - const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775); - if (invalid_modebits > 0) - return glnx_throw (error, "object %s.file: invalid mode 0%04o with bits 0%04o", - checksum, content_mode, invalid_modebits); - } - else if (S_ISLNK (content_mode)) - ; /* Nothing */ - else - g_assert_not_reached (); - - return TRUE; -} - /* Synchronously import a single content object; this is used async for content, * or synchronously for metadata. @src_repo is either * pull_data->remote_repo_local or one of pull_data->localcache_repos. @@ -664,51 +637,14 @@ import_one_local_content_object_sync (OtPullData *pull_data, GCancellable *cancellable, GError **error) { - const gboolean trusted = !pull_data->is_untrusted; - if (trusted && !pull_data->is_bareuseronly_files) - { - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, src_repo, - OSTREE_OBJECT_TYPE_FILE, checksum, - trusted, - cancellable, error)) - return FALSE; - } - else - { - /* In this case we either need to validate the checksum - * or the file mode. - */ - g_autoptr(GInputStream) content_input = NULL; - g_autoptr(GFileInfo) content_finfo = NULL; - g_autoptr(GVariant) content_xattrs = NULL; - - if (!ostree_repo_load_file (src_repo, checksum, - &content_input, &content_finfo, &content_xattrs, - cancellable, error)) - return FALSE; - - if (!validate_bareuseronly_mode (pull_data, checksum, - g_file_info_get_attribute_uint32 (content_finfo, "unix::mode"), - error)) - return FALSE; - - /* Now that we've potentially validated it, convert to object stream */ - guint64 length; - g_autoptr(GInputStream) object_stream = NULL; - if (!ostree_raw_file_to_content_stream (content_input, content_finfo, - content_xattrs, &object_stream, - &length, cancellable, error)) - return FALSE; - - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_content (pull_data->repo, checksum, - object_stream, length, - &real_csum, - cancellable, error)) - return FALSE; - } - - return TRUE; + OstreeRepoImportFlags flags = _OSTREE_REPO_IMPORT_FLAGS_NONE; + if (!pull_data->is_untrusted) + flags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; + if (pull_data->is_bareuseronly_files) + flags |= _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY; + return _ostree_repo_import_object (pull_data->repo, src_repo, + OSTREE_OBJECT_TYPE_FILE, checksum, + flags, cancellable, error); } typedef struct { @@ -1129,11 +1065,11 @@ content_fetch_on_complete (GObject *object, */ ot_cleanup_unlinkat (&tmp_unlinker); - if (!validate_bareuseronly_mode (pull_data, - checksum, - g_file_info_get_attribute_uint32 (file_info, "unix::mode"), - error)) - goto out; + if (pull_data->is_bareuseronly_files) + { + if (!_ostree_validate_bareuseronly_mode_finfo (file_info, checksum, error)) + goto out; + } if (!ostree_raw_file_to_content_stream (file_in, file_info, xattrs, &object_input, &length, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e04a1b6a..5c3c2987 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3367,114 +3367,6 @@ ostree_repo_delete_object (OstreeRepo *self, return TRUE; } -static gboolean -copy_detached_metadata (OstreeRepo *self, - OstreeRepo *source, - const char *checksum, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GVariant) detached_meta = NULL; - if (!ostree_repo_read_commit_detached_metadata (source, - checksum, &detached_meta, - cancellable, error)) - return FALSE; - - if (detached_meta) - { - if (!ostree_repo_write_commit_detached_metadata (self, - checksum, detached_meta, - cancellable, error)) - return FALSE; - } - - return TRUE; -} - -/* Special case between bare-user and bare-user-only, - * mostly for https://github.com/flatpak/flatpak/issues/845 - * see below for any more comments. - */ -static gboolean -import_is_bareuser_only_conversion (OstreeRepo *src_repo, - OstreeRepo *dest_repo, - OstreeObjectType objtype) -{ - return src_repo->mode == OSTREE_REPO_MODE_BARE_USER - && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY - && objtype == OSTREE_OBJECT_TYPE_FILE; -} - -static gboolean -import_one_object_link (OstreeRepo *self, - OstreeRepo *source, - const char *checksum, - OstreeObjectType objtype, - gboolean *out_was_supported, - GCancellable *cancellable, - GError **error) -{ - const char *errprefix = glnx_strjoina ("Importing ", checksum, ".", - ostree_object_type_to_string (objtype)); - GLNX_AUTO_PREFIX_ERROR (errprefix, error); - char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode); - - /* Hardlinking between bare-user → bare-user-only is only possible for regular - * files, *not* symlinks, which in bare-user are stored as regular files. At - * this point we need to parse the file to see the difference. - */ - if (import_is_bareuser_only_conversion (source, self, objtype)) - { - struct stat stbuf; - - if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf, - NULL, NULL, cancellable, error)) - return FALSE; - - if (S_ISREG (stbuf.st_mode)) - { - /* This is OK, we'll drop through and try a hardlink */ - } - else if (S_ISLNK (stbuf.st_mode)) - { - /* NOTE early return */ - *out_was_supported = FALSE; - return TRUE; - } - else - g_assert_not_reached (); - } - - if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error)) - return FALSE; - - *out_was_supported = TRUE; - if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0) - { - if (errno == EEXIST) - return TRUE; - else if (errno == EMLINK || errno == EXDEV || errno == EPERM) - { - /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the - * optimization of hardlinking instead of copying. - */ - *out_was_supported = FALSE; - return TRUE; - } - else - return glnx_throw_errno_prefix (error, "linkat"); - } - - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - if (!copy_detached_metadata (self, source, checksum, cancellable, error)) - return FALSE; - } - - return TRUE; -} - /** * ostree_repo_import_object_from: * @self: Destination repo @@ -3504,28 +3396,6 @@ ostree_repo_import_object_from (OstreeRepo *self, checksum, TRUE, cancellable, error); } -static gboolean -import_via_hardlink_is_possible (OstreeRepo *src_repo, - OstreeRepo *dest_repo, - OstreeObjectType objtype) -{ - /* We need the ability to make hardlinks */ - if (src_repo->owner_uid != dest_repo->owner_uid) - return FALSE; - /* Equal modes are always compatible */ - if (src_repo->mode == dest_repo->mode) - return TRUE; - /* Metadata is identical between all modes */ - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) - return TRUE; - /* And now a special case between bare-user and bare-user-only, - * mostly for https://github.com/flatpak/flatpak/issues/845 - */ - if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype)) - return TRUE; - return FALSE; -} - /** * ostree_repo_import_object_from_with_trust: * @self: Destination repo @@ -3552,82 +3422,12 @@ ostree_repo_import_object_from_with_trust (OstreeRepo *self, GCancellable *cancellable, GError **error) { - /* We try to import via hardlink. If the remote is explicitly not trusted - * (i.e.) their checksums may be incorrect, we skip that. Also, we require the - * repository modes to match, as well as the owner uid (since we need to be - * able to make hardlinks). - */ - if (trusted && import_via_hardlink_is_possible (source, self, objtype)) - { - gboolean hardlink_was_supported = FALSE; - - if (!import_one_object_link (self, source, checksum, objtype, - &hardlink_was_supported, - cancellable, error)) - return FALSE; - - /* If we hardlinked, we're done! */ - if (hardlink_was_supported) - return TRUE; - } - - /* The copy path */ - - /* First, do we have the object already? */ - gboolean has_object; - if (!ostree_repo_has_object (self, objtype, checksum, &has_object, - cancellable, error)) - return FALSE; - /* If we have it, we're done */ - if (has_object) - return TRUE; - - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) - { - /* Metadata object */ - g_autoptr(GVariant) variant = NULL; - - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - /* FIXME - cleanup detached metadata if copy below fails */ - if (!copy_detached_metadata (self, source, checksum, cancellable, error)) - return FALSE; - } - - if (!ostree_repo_load_variant (source, objtype, checksum, - &variant, error)) - return FALSE; - - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_metadata (self, objtype, - checksum, variant, - trusted ? NULL : &real_csum, - cancellable, error)) - return FALSE; - } - else - { - /* Content object */ - guint64 length; - g_autoptr(GInputStream) object_stream = NULL; - - if (!ostree_repo_load_object_stream (source, objtype, checksum, - &object_stream, &length, - cancellable, error)) - return FALSE; - - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_content (self, checksum, - object_stream, length, - trusted ? NULL : &real_csum, - cancellable, error)) - return FALSE; - } - - return TRUE; + /* This just wraps a currently internal API, may make it public later */ + OstreeRepoImportFlags flags = trusted ? _OSTREE_REPO_IMPORT_FLAGS_TRUSTED : 0; + return _ostree_repo_import_object (self, source, objtype, checksum, + flags, cancellable, error); } - /** * ostree_repo_query_object_storage_size: * @self: Repo diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 218bc31c..742b1ada 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -314,7 +314,7 @@ $CMD_PREFIX ostree --repo=repo-input commit -b content-with-suid --statoverride= if $CMD_PREFIX ostree pull-local --repo=repo --bareuseronly-files repo-input content-with-suid 2>err.txt; then assert_not_reached "copying suid file with --bareuseronly-files worked?" fi -assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*' +assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*' echo "ok pull-local (bareuseronly files)" if ! skip_one_without_user_xattrs; then diff --git a/tests/pull-test.sh b/tests/pull-test.sh index f44c2ced..3780d1ad 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -127,7 +127,7 @@ for flag in "" "--mirror"; do if ${CMD_PREFIX} ostree --repo=mirrorrepo pull ${flag} --bareuseronly-files origin content-with-suid 2>err.txt; then assert_not_reached "pulled unsafe bareuseronly" fi - assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*' + assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*' done echo "ok pull (bareuseronly, unsafe)" diff --git a/tests/test-basic-user-only.sh b/tests/test-basic-user-only.sh index ce69e49e..19262b7b 100755 --- a/tests/test-basic-user-only.sh +++ b/tests/test-basic-user-only.sh @@ -45,7 +45,7 @@ $CMD_PREFIX ostree --repo=repo-input commit -b content-with-suid --statoverride= if $CMD_PREFIX ostree pull-local --repo=repo repo-input 2>err.txt; then assert_not_reached "copying suid file into bare-user worked?" fi -assert_file_has_content err.txt "Invalid mode.*with bits 040.*in bare-user-only" +assert_file_has_content err.txt "Content object.*invalid mode.*with bits 040.*" echo "ok failed to commit suid" cd ${test_tmpdir} From d75316c9072d9e10602eae4d4fe248d451fec533 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Sep 2017 15:07:30 -0400 Subject: [PATCH 29/78] lib/commit: Don't try to call linkat() for import on distinct devices While opening a repo we've recorded the device/inode for a while; use it to avoid calling `linkat()` during object import if we know it's going to fail. Closes: #1193 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 6d770dea..e8bb2395 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -3189,8 +3189,9 @@ import_via_hardlink_is_possible (OstreeRepo *src_repo, OstreeRepo *dest_repo, OstreeObjectType objtype) { - /* We need the ability to make hardlinks */ - if (src_repo->owner_uid != dest_repo->owner_uid) + /* hardlinks require the owner to match and to be on the same device */ + if (!(src_repo->owner_uid == dest_repo->owner_uid && + src_repo->device == dest_repo->device)) return FALSE; /* Equal modes are always compatible */ if (src_repo->mode == dest_repo->mode) From e689b8b4a563764d72b2985f170a6d7283f87cb0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Sep 2017 15:19:05 -0400 Subject: [PATCH 30/78] ci: Add an "all options disabled" context We keep occasionally regressing this so let's start covering it now. I'm intentionally not running the tests since that would likely entail a lot more conditionalizing pain. Closes: #1194 Approved by: jlebon --- .papr.yml | 14 ++++++++++++++ ci/build.sh | 16 ++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.papr.yml b/.papr.yml index 56ff4dae..4ae345e6 100644 --- a/.papr.yml +++ b/.papr.yml @@ -74,6 +74,20 @@ tests: --- +inherit: true + +context: f26-minimal +env: + CONFIGOPTS: '--without-curl --without-soup --disable-gtk-doc --disable-man + --disable-rust --without-libarchive --without-selinux --without-smack + --without-openssl --without-avahi --without-libmount --disable-rofiles-fuse + --disable-experimental-api' + +tests: + - ci/build.sh + +--- + inherit: true required: true diff --git a/ci/build.sh b/ci/build.sh index 33ef9503..572ae197 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -21,15 +21,19 @@ pkg_install_if_os fedora gjs gnome-desktop-testing parallel coccinelle clang # always fail on warnings; https://github.com/ostreedev/ostree/pull/971 export CFLAGS="-Werror ${CFLAGS:-}" -DETECTED_CONFIGOPTS= -if test -x /usr/bin/gnome-desktop-testing-runner; then - DETECTED_CONFIGOPTS="${DETECTED_CONFIGOPTS} --enable-installed-tests=exclusive" -fi # Default libcurl on by default in fedora unless libsoup is enabled if sh -c '. /etc/os-release; test "${ID}" = fedora'; then case "${CONFIGOPTS:-}" in - *--with-soup*) ;; + *--with-soup*|*--without-curl*) ;; *) CONFIGOPTS="${CONFIGOPTS:-} --with-curl" esac fi -build --enable-gtk-doc ${DETECTED_CONFIGOPTS} ${CONFIGOPTS:-} +case "${CONFIGOPTS:-}" in + *--with-curl*|--with-soup*) + if test -x /usr/bin/gnome-desktop-testing-runner; then + CONFIGOPTS="${CONFIGOPTS} --enable-installed-tests=exclusive" + fi + ;; +esac + +build --enable-gtk-doc ${CONFIGOPTS:-} From ae075d23e3d2069f48fcfca0207ca8f46a923d29 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 14:50:54 -0400 Subject: [PATCH 31/78] lib/repo: Use correct name for tmpdir lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Such an evil bug 🙈. I was just reading an strace trying to figure out what was going on, and noticed we had the `XXXXXX` in the lockfile name. It was only after that I realized that that this might *be* the cause of the skopeo issue. This is another case where we definitely need more test coverage of things that actually use the API multiple times in process; might look at dusting off the work for the rpm-ostree test. Closes: https://github.com/ostreedev/ostree/issues/1196 Closes: #1204 Approved by: jlebon --- src/libostree/ostree-repo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 5c3c2987..b1d88e48 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4990,7 +4990,7 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd, /* Note, at this point we can race with another process that picks up this * new directory. If that happens we need to retry, making a new directory. */ - if (!_ostree_repo_try_lock_tmpdir (tmpdir_dfd, tmpdir_name_template, + if (!_ostree_repo_try_lock_tmpdir (new_tmpdir.src_dfd, new_tmpdir.path, file_lock_out, &did_lock, error)) return FALSE; From 64b23fd0891277a26b23c15a7f75fc65f0145ae2 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 21 Sep 2017 20:22:09 +0100 Subject: [PATCH 32/78] lib/repo: Add ostree_repo_hash() and tests Add a hash function for OstreeRepo instances, which relies on the repo being open, and hence being able to hash the device and inode of its root directory. Add unit tests for this and ostree_repo_equal(). Signed-off-by: Philip Withnall https://github.com/ostreedev/ostree/issues/1191 Closes: #1205 Approved by: cgwalters --- Makefile-tests.am | 5 +- apidoc/ostree-sections.txt | 1 + src/libostree/libostree-devel.sym | 1 + src/libostree/ostree-repo.c | 30 ++++++ src/libostree/ostree-repo.h | 2 + tests/.gitignore | 1 + tests/test-repo.c | 168 ++++++++++++++++++++++++++++++ 7 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 tests/test-repo.c diff --git a/Makefile-tests.am b/Makefile-tests.am index 6a52faeb..c2186707 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -212,7 +212,7 @@ endif _installed_or_uninstalled_test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \ tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \ tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \ - tests/test-basic-c tests/test-sysroot-c tests/test-pull-c + tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo if ENABLE_EXPERIMENTAL_API test_programs += \ @@ -282,6 +282,9 @@ tests_test_sysroot_c_LDADD = $(TESTS_LDADD) tests_test_pull_c_CFLAGS = $(TESTS_CFLAGS) tests_test_pull_c_LDADD = $(TESTS_LDADD) +tests_test_repo_CFLAGS = $(TESTS_CFLAGS) +tests_test_repo_LDADD = $(TESTS_LDADD) + tests_test_ot_unix_utils_CFLAGS = $(TESTS_CFLAGS) tests_test_ot_unix_utils_LDADD = $(TESTS_LDADD) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 547e1509..e5ce157c 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -287,6 +287,7 @@ ostree_repo_get_path ostree_repo_get_mode ostree_repo_get_config ostree_repo_get_dfd +ostree_repo_hash ostree_repo_equal ostree_repo_copy_config ostree_repo_remote_add diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index a416b7c1..1462a647 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -21,6 +21,7 @@ LIBOSTREE_2017.12 { global: ostree_repo_equal; + ostree_repo_hash; } LIBOSTREE_2017.11; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index b1d88e48..7554bc44 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2609,6 +2609,36 @@ ostree_repo_get_dfd (OstreeRepo *self) return self->repo_dir_fd; } +/** + * ostree_repo_hash: + * @self: an #OstreeRepo + * + * Calculate a hash value for the given open repository, suitable for use when + * putting it into a hash table. It is an error to call this on an #OstreeRepo + * which is not yet open, as a persistent hash value cannot be calculated until + * the repository is open and the inode of its root directory has been loaded. + * + * This function does no I/O. + * + * Returns: hash value for the #OstreeRepo + * Since: 2017.12 + */ +guint +ostree_repo_hash (OstreeRepo *self) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), 0); + + /* We cannot hash non-open repositories, since their hash value would change + * once they’re opened, resulting in false lookup misses and the inability to + * remove them from a hash table. */ + g_assert (self->repo_dir_fd >= 0); + + /* device and inode numbers are distributed fairly uniformly, so we can’t + * do much better than just combining them. No need to rehash to even out + * the distribution. */ + return (self->device ^ self->inode); +} + /** * ostree_repo_equal: * @a: an #OstreeRepo diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index a2a46d4b..a22c1ade 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -123,6 +123,8 @@ GFile * ostree_repo_get_path (OstreeRepo *self); _OSTREE_PUBLIC int ostree_repo_get_dfd (OstreeRepo *self); +_OSTREE_PUBLIC +guint ostree_repo_hash (OstreeRepo *self); _OSTREE_PUBLIC gboolean ostree_repo_equal (OstreeRepo *a, OstreeRepo *b); diff --git a/tests/.gitignore b/tests/.gitignore index 9bec67a3..e56a8393 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -15,6 +15,7 @@ test-mutable-tree test-ot-opt-utils test-ot-tool-util test-ot-unix-utils +test-repo test-repo-finder-avahi test-repo-finder-config test-repo-finder-mount diff --git a/tests/test-repo.c b/tests/test-repo.c new file mode 100644 index 00000000..217ca23c --- /dev/null +++ b/tests/test-repo.c @@ -0,0 +1,168 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright © 2017 Endless Mobile, 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "ostree-autocleanups.h" +#include "ostree-types.h" + +/* Test fixture. Creates a temporary directory. */ +typedef struct +{ + GLnxTmpDir tmpdir; /* (owned) */ +} Fixture; + +static void +setup (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + + (void) glnx_mkdtemp ("test-repo-XXXXXX", 0700, &fixture->tmpdir, &error); + g_assert_no_error (error); + + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); +} + +static void +teardown (Fixture *fixture, + gconstpointer test_data) +{ + /* Recursively remove the temporary directory. */ + (void) glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); +} + +/* Test that the hash values for two #OstreeRepo instances pointing at the same + * repository are equal. We can’t test anything else, since hash collisions are + * always a possibility. */ +static void +test_repo_hash (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, ".", + OSTREE_REPO_MODE_ARCHIVE_Z2, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo2 = ostree_repo_open_at (fixture->tmpdir.fd, ".", + NULL, &error); + g_assert_no_error (error); + + g_assert_cmpuint (ostree_repo_hash (repo1), ==, ostree_repo_hash (repo2)); +} + +/* Test that trying to hash a closed repo results in an assertion failure. */ +static void +test_repo_hash_closed (Fixture *fixture, + gconstpointer test_data) +{ + if (g_test_subprocess ()) + { + g_autoptr(GFile) repo_path = g_file_new_for_path (fixture->tmpdir.path); + g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); + + ostree_repo_hash (repo); + + return; + } + + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*ERROR*ostree_repo_hash: assertion failed:*"); +} + +/* Test that various repositories test equal (or not) with each other. */ +static void +test_repo_equal (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + + /* Create a few separate repos and some #OstreeRepo objects for them. */ + glnx_ensure_dir (fixture->tmpdir.fd, "repo1", 0755, &error); + g_assert_no_error (error); + glnx_ensure_dir (fixture->tmpdir.fd, "repo2", 0755, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, "repo1", + OSTREE_REPO_MODE_ARCHIVE_Z2, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo1_alias = ostree_repo_open_at (fixture->tmpdir.fd, "repo1", + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo2 = ostree_repo_create_at (fixture->tmpdir.fd, "repo2", + OSTREE_REPO_MODE_ARCHIVE_Z2, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(GFile) closed_repo_path = g_file_new_for_path (fixture->tmpdir.path); + g_autoptr(OstreeRepo) closed_repo = ostree_repo_new (closed_repo_path); + + /* Test various equalities. */ + g_assert_true (ostree_repo_equal (repo1, repo1)); + g_assert_true (ostree_repo_equal (repo1_alias, repo1_alias)); + g_assert_true (ostree_repo_equal (repo1, repo1_alias)); + g_assert_true (ostree_repo_equal (repo1_alias, repo1)); + g_assert_true (ostree_repo_equal (repo2, repo2)); + g_assert_false (ostree_repo_equal (repo1, repo2)); + g_assert_false (ostree_repo_equal (repo1_alias, repo2)); + g_assert_false (ostree_repo_equal (repo2, repo1)); + g_assert_false (ostree_repo_equal (repo2, repo1_alias)); + g_assert_false (ostree_repo_equal (repo1, closed_repo)); + g_assert_false (ostree_repo_equal (repo1_alias, closed_repo)); + g_assert_false (ostree_repo_equal (closed_repo, repo1)); + g_assert_false (ostree_repo_equal (closed_repo, repo1_alias)); + g_assert_false (ostree_repo_equal (repo2, closed_repo)); + g_assert_false (ostree_repo_equal (closed_repo, repo2)); + g_assert_false (ostree_repo_equal (closed_repo, closed_repo)); +} + +int +main (int argc, + char **argv) +{ + setlocale (LC_ALL, ""); + g_test_init (&argc, &argv, NULL); + + g_test_add ("/repo/hash", Fixture, NULL, setup, + test_repo_hash, teardown); + g_test_add ("/repo/hash/closed", Fixture, NULL, setup, + test_repo_hash_closed, teardown); + g_test_add ("/repo/equal", Fixture, NULL, setup, + test_repo_equal, teardown); + + return g_test_run (); +} From 6e4146a35424537b95785bc71b1e19832a1588d6 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 15:26:06 -0400 Subject: [PATCH 33/78] tree-wide: Remove Emacs modelines We added a `.dir-locals.el` in commit: 9a77017d87b74c5e2895cdd64ad098018929403f There's no need to have it per-file, with that people might think to add other editors, which is the wrong direction. Closes: #1206 Approved by: jlebon --- src/libostree/ostree-async-progress.c | 3 +-- src/libostree/ostree-async-progress.h | 3 +-- src/libostree/ostree-autocleanups.h | 3 +-- src/libostree/ostree-bloom-private.h | 3 +-- src/libostree/ostree-bloom.c | 3 +-- src/libostree/ostree-bootconfig-parser.c | 3 +-- src/libostree/ostree-bootconfig-parser.h | 3 +-- src/libostree/ostree-bootloader-grub2.c | 3 +-- src/libostree/ostree-bootloader-grub2.h | 3 +-- src/libostree/ostree-bootloader-syslinux.c | 3 +-- src/libostree/ostree-bootloader-syslinux.h | 3 +-- src/libostree/ostree-bootloader-uboot.c | 3 +-- src/libostree/ostree-bootloader-uboot.h | 3 +-- src/libostree/ostree-bootloader.c | 3 +-- src/libostree/ostree-bootloader.h | 3 +-- src/libostree/ostree-chain-input-stream.c | 3 +-- src/libostree/ostree-chain-input-stream.h | 3 +-- src/libostree/ostree-checksum-input-stream.c | 3 +-- src/libostree/ostree-checksum-input-stream.h | 3 +-- src/libostree/ostree-cmdprivate.c | 3 +-- src/libostree/ostree-cmdprivate.h | 3 +-- src/libostree/ostree-core-private.h | 3 +-- src/libostree/ostree-core.c | 3 +-- src/libostree/ostree-core.h | 3 +-- src/libostree/ostree-deployment-private.h | 3 +-- src/libostree/ostree-deployment.c | 3 +-- src/libostree/ostree-deployment.h | 3 +-- src/libostree/ostree-diff.c | 3 +-- src/libostree/ostree-diff.h | 3 +-- src/libostree/ostree-fetcher-curl.c | 3 +-- src/libostree/ostree-fetcher-soup.c | 3 +-- src/libostree/ostree-fetcher-uri.c | 3 +-- src/libostree/ostree-fetcher-util.c | 3 +-- src/libostree/ostree-fetcher-util.h | 3 +-- src/libostree/ostree-fetcher.h | 3 +-- src/libostree/ostree-gpg-verifier.c | 3 +-- src/libostree/ostree-gpg-verifier.h | 3 +-- src/libostree/ostree-gpg-verify-result-private.h | 3 +-- src/libostree/ostree-gpg-verify-result.c | 3 +-- src/libostree/ostree-gpg-verify-result.h | 3 +-- src/libostree/ostree-impl-system-generator.c | 3 +-- src/libostree/ostree-kernel-args.c | 3 +-- src/libostree/ostree-kernel-args.h | 3 +-- src/libostree/ostree-libarchive-input-stream.c | 3 +-- src/libostree/ostree-libarchive-input-stream.h | 3 +-- src/libostree/ostree-libarchive-private.h | 3 +-- src/libostree/ostree-linuxfsutil.c | 3 +-- src/libostree/ostree-linuxfsutil.h | 3 +-- src/libostree/ostree-lzma-common.c | 3 +-- src/libostree/ostree-lzma-common.h | 3 +-- src/libostree/ostree-lzma-compressor.c | 3 +-- src/libostree/ostree-lzma-compressor.h | 3 +-- src/libostree/ostree-lzma-decompressor.c | 3 +-- src/libostree/ostree-lzma-decompressor.h | 3 +-- src/libostree/ostree-metalink.c | 3 +-- src/libostree/ostree-metalink.h | 3 +-- src/libostree/ostree-mutable-tree.c | 3 +-- src/libostree/ostree-mutable-tree.h | 3 +-- src/libostree/ostree-ref.c | 3 +-- src/libostree/ostree-ref.h | 3 +-- src/libostree/ostree-remote-private.h | 3 +-- src/libostree/ostree-remote.c | 3 +-- src/libostree/ostree-remote.h | 3 +-- src/libostree/ostree-repo-checkout.c | 3 +-- src/libostree/ostree-repo-commit.c | 3 +-- src/libostree/ostree-repo-deprecated.h | 3 +-- src/libostree/ostree-repo-file-enumerator.c | 3 +-- src/libostree/ostree-repo-file-enumerator.h | 3 +-- src/libostree/ostree-repo-file.c | 3 +-- src/libostree/ostree-repo-file.h | 3 +-- src/libostree/ostree-repo-finder-avahi-parser.c | 3 +-- src/libostree/ostree-repo-finder-avahi-private.h | 3 +-- src/libostree/ostree-repo-finder-avahi.c | 3 +-- src/libostree/ostree-repo-finder-avahi.h | 3 +-- src/libostree/ostree-repo-finder-config.c | 3 +-- src/libostree/ostree-repo-finder-config.h | 3 +-- src/libostree/ostree-repo-finder-mount.c | 3 +-- src/libostree/ostree-repo-finder-mount.h | 3 +-- src/libostree/ostree-repo-finder.c | 3 +-- src/libostree/ostree-repo-finder.h | 3 +-- src/libostree/ostree-repo-libarchive.c | 3 +-- src/libostree/ostree-repo-private.h | 3 +-- src/libostree/ostree-repo-prune.c | 3 +-- src/libostree/ostree-repo-pull.c | 3 +-- src/libostree/ostree-repo-refs.c | 3 +-- src/libostree/ostree-repo-static-delta-compilation-analysis.c | 3 +-- src/libostree/ostree-repo-static-delta-compilation.c | 3 +-- src/libostree/ostree-repo-static-delta-core.c | 3 +-- src/libostree/ostree-repo-static-delta-private.h | 3 +-- src/libostree/ostree-repo-static-delta-processing.c | 3 +-- src/libostree/ostree-repo-traverse.c | 3 +-- src/libostree/ostree-repo.c | 3 +-- src/libostree/ostree-repo.h | 3 +-- src/libostree/ostree-rollsum.c | 3 +-- src/libostree/ostree-rollsum.h | 3 +-- src/libostree/ostree-sepolicy-private.h | 3 +-- src/libostree/ostree-sepolicy.c | 3 +-- src/libostree/ostree-sepolicy.h | 3 +-- src/libostree/ostree-sysroot-cleanup.c | 3 +-- src/libostree/ostree-sysroot-deploy.c | 3 +-- src/libostree/ostree-sysroot-private.h | 3 +-- src/libostree/ostree-sysroot-upgrader.c | 3 +-- src/libostree/ostree-sysroot-upgrader.h | 3 +-- src/libostree/ostree-sysroot.c | 3 +-- src/libostree/ostree-sysroot.h | 3 +-- src/libostree/ostree-tls-cert-interaction.c | 3 +-- src/libostree/ostree-tls-cert-interaction.h | 3 +-- src/libostree/ostree-types.h | 3 +-- src/libostree/ostree-varint.c | 3 +-- src/libostree/ostree-varint.h | 3 +-- src/libostree/ostree-version.h.in | 3 +-- src/libostree/ostree.h | 3 +-- src/libotutil/ot-checksum-instream.c | 3 +-- src/libotutil/ot-checksum-instream.h | 3 +-- src/libotutil/ot-checksum-utils.c | 3 +-- src/libotutil/ot-checksum-utils.h | 3 +-- src/libotutil/ot-fs-utils.c | 3 +-- src/libotutil/ot-fs-utils.h | 3 +-- src/libotutil/ot-gio-utils.c | 3 +-- src/libotutil/ot-gio-utils.h | 3 +-- src/libotutil/ot-gpg-utils.c | 3 +-- src/libotutil/ot-gpg-utils.h | 3 +-- src/libotutil/ot-keyfile-utils.c | 3 +-- src/libotutil/ot-keyfile-utils.h | 3 +-- src/libotutil/ot-opt-utils.c | 3 +-- src/libotutil/ot-opt-utils.h | 3 +-- src/libotutil/ot-tool-util.c | 3 +-- src/libotutil/ot-tool-util.h | 3 +-- src/libotutil/ot-unix-utils.c | 3 +-- src/libotutil/ot-unix-utils.h | 3 +-- src/libotutil/ot-variant-utils.c | 3 +-- src/libotutil/ot-variant-utils.h | 3 +-- src/libotutil/otutil.c | 3 +-- src/libotutil/otutil.h | 3 +-- src/ostree/main.c | 3 +-- src/ostree/ostree-trivial-httpd.c | 3 +-- src/ostree/ot-admin-builtin-cleanup.c | 3 +-- src/ostree/ot-admin-builtin-deploy.c | 3 +-- src/ostree/ot-admin-builtin-diff.c | 3 +-- src/ostree/ot-admin-builtin-init-fs.c | 3 +-- src/ostree/ot-admin-builtin-instutil.c | 3 +-- src/ostree/ot-admin-builtin-os-init.c | 3 +-- src/ostree/ot-admin-builtin-set-origin.c | 3 +-- src/ostree/ot-admin-builtin-status.c | 3 +-- src/ostree/ot-admin-builtin-switch.c | 3 +-- src/ostree/ot-admin-builtin-undeploy.c | 3 +-- src/ostree/ot-admin-builtin-unlock.c | 3 +-- src/ostree/ot-admin-builtin-upgrade.c | 3 +-- src/ostree/ot-admin-builtins.h | 3 +-- src/ostree/ot-admin-functions.c | 3 +-- src/ostree/ot-admin-functions.h | 3 +-- src/ostree/ot-admin-instutil-builtin-grub2-generate.c | 3 +-- src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c | 3 +-- src/ostree/ot-admin-instutil-builtin-set-kargs.c | 3 +-- src/ostree/ot-admin-instutil-builtins.h | 3 +-- src/ostree/ot-builtin-admin.c | 3 +-- src/ostree/ot-builtin-cat.c | 3 +-- src/ostree/ot-builtin-checkout.c | 3 +-- src/ostree/ot-builtin-checksum.c | 3 +-- src/ostree/ot-builtin-commit.c | 3 +-- src/ostree/ot-builtin-config.c | 3 +-- src/ostree/ot-builtin-diff.c | 3 +-- src/ostree/ot-builtin-export.c | 3 +-- src/ostree/ot-builtin-find-remotes.c | 3 +-- src/ostree/ot-builtin-fsck.c | 3 +-- src/ostree/ot-builtin-gpg-sign.c | 3 +-- src/ostree/ot-builtin-init.c | 3 +-- src/ostree/ot-builtin-log.c | 3 +-- src/ostree/ot-builtin-ls.c | 3 +-- src/ostree/ot-builtin-prune.c | 3 +-- src/ostree/ot-builtin-pull-local.c | 3 +-- src/ostree/ot-builtin-pull.c | 3 +-- src/ostree/ot-builtin-refs.c | 3 +-- src/ostree/ot-builtin-remote.c | 3 +-- src/ostree/ot-builtin-reset.c | 3 +-- src/ostree/ot-builtin-rev-parse.c | 3 +-- src/ostree/ot-builtin-show.c | 3 +-- src/ostree/ot-builtin-static-delta.c | 3 +-- src/ostree/ot-builtin-summary.c | 3 +-- src/ostree/ot-builtin-trivial-httpd.c | 3 +-- src/ostree/ot-builtins.h | 3 +-- src/ostree/ot-dump.c | 3 +-- src/ostree/ot-dump.h | 3 +-- src/ostree/ot-editor.c | 3 +-- src/ostree/ot-editor.h | 3 +-- src/ostree/ot-main.c | 3 +-- src/ostree/ot-main.h | 3 +-- src/ostree/ot-remote-builtin-add-cookie.c | 3 +-- src/ostree/ot-remote-builtin-add.c | 3 +-- src/ostree/ot-remote-builtin-delete-cookie.c | 3 +-- src/ostree/ot-remote-builtin-delete.c | 3 +-- src/ostree/ot-remote-builtin-gpg-import.c | 3 +-- src/ostree/ot-remote-builtin-list-cookies.c | 3 +-- src/ostree/ot-remote-builtin-list.c | 3 +-- src/ostree/ot-remote-builtin-refs.c | 3 +-- src/ostree/ot-remote-builtin-show-url.c | 3 +-- src/ostree/ot-remote-builtin-summary.c | 3 +-- src/ostree/ot-remote-builtins.h | 3 +-- src/ostree/ot-remote-cookie-util.c | 3 +-- src/ostree/ot-remote-cookie-util.h | 3 +-- src/rofiles-fuse/main.c | 3 +-- src/switchroot/ostree-mount-util.h | 3 +-- src/switchroot/ostree-remount.c | 3 +-- src/switchroot/ostree-system-generator.c | 3 +-- tests/libostreetest.c | 3 +-- tests/libostreetest.h | 3 +-- tests/readdir-rand.c | 3 +-- tests/test-basic-c.c | 3 +-- tests/test-bloom.c | 3 +-- tests/test-bsdiff.c | 3 +-- tests/test-checksum.c | 3 +-- tests/test-gpg-verify-result.c | 3 +-- tests/test-keyfile-utils.c | 3 +-- tests/test-libarchive-import.c | 3 +-- tests/test-lzma.c | 3 +-- tests/test-mock-gio.c | 3 +-- tests/test-mock-gio.h | 3 +-- tests/test-mutable-tree.c | 3 +-- tests/test-ot-opt-utils.c | 3 +-- tests/test-ot-tool-util.c | 3 +-- tests/test-ot-unix-utils.c | 3 +-- tests/test-pull-c.c | 3 +-- tests/test-repo-finder-avahi.c | 3 +-- tests/test-repo-finder-config.c | 3 +-- tests/test-repo-finder-mount.c | 3 +-- tests/test-rollsum-cli.c | 3 +-- tests/test-rollsum.c | 3 +-- tests/test-sysroot-c.c | 3 +-- tests/test-varint.c | 3 +-- 229 files changed, 229 insertions(+), 458 deletions(-) diff --git a/src/libostree/ostree-async-progress.c b/src/libostree/ostree-async-progress.c index b879559e..a595e576 100644 --- a/src/libostree/ostree-async-progress.c +++ b/src/libostree/ostree-async-progress.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-async-progress.h b/src/libostree/ostree-async-progress.h index 55ac591c..ba46ecc1 100644 --- a/src/libostree/ostree-async-progress.h +++ b/src/libostree/ostree-async-progress.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-autocleanups.h b/src/libostree/ostree-autocleanups.h index b375413c..7228c0b2 100644 --- a/src/libostree/ostree-autocleanups.h +++ b/src/libostree/ostree-autocleanups.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-bloom-private.h b/src/libostree/ostree-bloom-private.h index 47f828b3..5be3cb43 100644 --- a/src/libostree/ostree-bloom-private.h +++ b/src/libostree/ostree-bloom-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-bloom.c b/src/libostree/ostree-bloom.c index 7677b3ba..6b42d97a 100644 --- a/src/libostree/ostree-bloom.c +++ b/src/libostree/ostree-bloom.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-bootconfig-parser.c b/src/libostree/ostree-bootconfig-parser.c index 9de0e56b..25da6657 100644 --- a/src/libostree/ostree-bootconfig-parser.c +++ b/src/libostree/ostree-bootconfig-parser.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootconfig-parser.h b/src/libostree/ostree-bootconfig-parser.h index cd524601..aec07535 100644 --- a/src/libostree/ostree-bootconfig-parser.h +++ b/src/libostree/ostree-bootconfig-parser.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index d917281c..1366dc95 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader-grub2.h b/src/libostree/ostree-bootloader-grub2.h index 8936aaa1..7aaa1698 100644 --- a/src/libostree/ostree-bootloader-grub2.h +++ b/src/libostree/ostree-bootloader-grub2.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader-syslinux.c b/src/libostree/ostree-bootloader-syslinux.c index 16f287b9..157cb51f 100644 --- a/src/libostree/ostree-bootloader-syslinux.c +++ b/src/libostree/ostree-bootloader-syslinux.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader-syslinux.h b/src/libostree/ostree-bootloader-syslinux.h index a20b0d0a..df4a9391 100644 --- a/src/libostree/ostree-bootloader-syslinux.h +++ b/src/libostree/ostree-bootloader-syslinux.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c index ce5d516c..5a51aae6 100644 --- a/src/libostree/ostree-bootloader-uboot.c +++ b/src/libostree/ostree-bootloader-uboot.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Collabora Ltd * * Based on ot-bootloader-syslinux.c by Colin Walters diff --git a/src/libostree/ostree-bootloader-uboot.h b/src/libostree/ostree-bootloader-uboot.h index da811897..89d7b47a 100644 --- a/src/libostree/ostree-bootloader-uboot.h +++ b/src/libostree/ostree-bootloader-uboot.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Collabora Ltd * * Based on ot-bootloader-syslinux.h by Colin Walters diff --git a/src/libostree/ostree-bootloader.c b/src/libostree/ostree-bootloader.c index c883fdb9..87823f7e 100644 --- a/src/libostree/ostree-bootloader.c +++ b/src/libostree/ostree-bootloader.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-bootloader.h b/src/libostree/ostree-bootloader.h index de46422d..a4793b08 100644 --- a/src/libostree/ostree-bootloader.h +++ b/src/libostree/ostree-bootloader.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-chain-input-stream.c b/src/libostree/ostree-chain-input-stream.c index 6a8459d3..27ca0781 100644 --- a/src/libostree/ostree-chain-input-stream.c +++ b/src/libostree/ostree-chain-input-stream.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-chain-input-stream.h b/src/libostree/ostree-chain-input-stream.h index dee38952..0db6505b 100644 --- a/src/libostree/ostree-chain-input-stream.h +++ b/src/libostree/ostree-chain-input-stream.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-checksum-input-stream.c b/src/libostree/ostree-checksum-input-stream.c index c0d65939..89a2d352 100644 --- a/src/libostree/ostree-checksum-input-stream.c +++ b/src/libostree/ostree-checksum-input-stream.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-checksum-input-stream.h b/src/libostree/ostree-checksum-input-stream.h index cb5b240c..26c2ea43 100644 --- a/src/libostree/ostree-checksum-input-stream.h +++ b/src/libostree/ostree-checksum-input-stream.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-cmdprivate.c b/src/libostree/ostree-cmdprivate.c index bade7431..3e60b125 100644 --- a/src/libostree/ostree-cmdprivate.c +++ b/src/libostree/ostree-cmdprivate.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-cmdprivate.h b/src/libostree/ostree-cmdprivate.h index 63c427cd..f636ab15 100644 --- a/src/libostree/ostree-cmdprivate.h +++ b/src/libostree/ostree-cmdprivate.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index e81537a6..783eacd3 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index e64cee4c..13dc6130 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index 92b56bb7..5124814c 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-deployment-private.h b/src/libostree/ostree-deployment-private.h index 01fdf1bf..114e2f63 100644 --- a/src/libostree/ostree-deployment-private.h +++ b/src/libostree/ostree-deployment-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 78afe18c..6431aa96 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-deployment.h b/src/libostree/ostree-deployment.h index bde0cf37..b4368f46 100644 --- a/src/libostree/ostree-deployment.h +++ b/src/libostree/ostree-deployment.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index f21b0302..064b873c 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-diff.h b/src/libostree/ostree-diff.h index b33bd63a..6e324e2a 100644 --- a/src/libostree/ostree-diff.h +++ b/src/libostree/ostree-diff.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index c22141ec..7aaabb78 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index c9eaef7a..90986c66 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher-uri.c b/src/libostree/ostree-fetcher-uri.c index 7ef42eca..aac18006 100644 --- a/src/libostree/ostree-fetcher-uri.c +++ b/src/libostree/ostree-fetcher-uri.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher-util.c b/src/libostree/ostree-fetcher-util.c index 7a6d94cc..a8134134 100644 --- a/src/libostree/ostree-fetcher-util.c +++ b/src/libostree/ostree-fetcher-util.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h index 67b8f2f3..5f1dd36d 100644 --- a/src/libostree/ostree-fetcher-util.h +++ b/src/libostree/ostree-fetcher-util.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-fetcher.h b/src/libostree/ostree-fetcher.h index 2dbace78..8cdd1e11 100644 --- a/src/libostree/ostree-fetcher.h +++ b/src/libostree/ostree-fetcher.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-gpg-verifier.c b/src/libostree/ostree-gpg-verifier.c index 9b731489..660a5b7c 100644 --- a/src/libostree/ostree-gpg-verifier.c +++ b/src/libostree/ostree-gpg-verifier.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Sjoerd Simons * diff --git a/src/libostree/ostree-gpg-verifier.h b/src/libostree/ostree-gpg-verifier.h index 7d5a7594..d0f02dbd 100644 --- a/src/libostree/ostree-gpg-verifier.h +++ b/src/libostree/ostree-gpg-verifier.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Sjoerd Simons * diff --git a/src/libostree/ostree-gpg-verify-result-private.h b/src/libostree/ostree-gpg-verify-result-private.h index 510728e3..3a8c1e2a 100644 --- a/src/libostree/ostree-gpg-verify-result-private.h +++ b/src/libostree/ostree-gpg-verify-result-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index 5be6b2e1..ddec0fac 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-gpg-verify-result.h b/src/libostree/ostree-gpg-verify-result.h index 3064ed8e..eccbe06d 100644 --- a/src/libostree/ostree-gpg-verify-result.h +++ b/src/libostree/ostree-gpg-verify-result.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-impl-system-generator.c b/src/libostree/ostree-impl-system-generator.c index ed2bb97c..cc05562b 100644 --- a/src/libostree/ostree-impl-system-generator.c +++ b/src/libostree/ostree-impl-system-generator.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-kernel-args.c b/src/libostree/ostree-kernel-args.c index 22b5caa7..a92a1f82 100644 --- a/src/libostree/ostree-kernel-args.c +++ b/src/libostree/ostree-kernel-args.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-kernel-args.h b/src/libostree/ostree-kernel-args.h index ceaa1ca7..4fff6df9 100644 --- a/src/libostree/ostree-kernel-args.h +++ b/src/libostree/ostree-kernel-args.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree-libarchive-input-stream.c b/src/libostree/ostree-libarchive-input-stream.c index a987e403..ea1b5fcf 100644 --- a/src/libostree/ostree-libarchive-input-stream.c +++ b/src/libostree/ostree-libarchive-input-stream.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-libarchive-input-stream.h b/src/libostree/ostree-libarchive-input-stream.h index 7f88693e..3daec85b 100644 --- a/src/libostree/ostree-libarchive-input-stream.h +++ b/src/libostree/ostree-libarchive-input-stream.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-libarchive-private.h b/src/libostree/ostree-libarchive-private.h index 2797fbac..6a4b0de2 100644 --- a/src/libostree/ostree-libarchive-private.h +++ b/src/libostree/ostree-libarchive-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-linuxfsutil.c b/src/libostree/ostree-linuxfsutil.c index 9785ac57..52c1b5be 100644 --- a/src/libostree/ostree-linuxfsutil.c +++ b/src/libostree/ostree-linuxfsutil.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-linuxfsutil.h b/src/libostree/ostree-linuxfsutil.h index 84122a70..febb3504 100644 --- a/src/libostree/ostree-linuxfsutil.h +++ b/src/libostree/ostree-linuxfsutil.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-common.c b/src/libostree/ostree-lzma-common.c index 61f3a2a4..c4438599 100644 --- a/src/libostree/ostree-lzma-common.c +++ b/src/libostree/ostree-lzma-common.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-common.h b/src/libostree/ostree-lzma-common.h index 17c8a64d..09eb2154 100644 --- a/src/libostree/ostree-lzma-common.h +++ b/src/libostree/ostree-lzma-common.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-compressor.c b/src/libostree/ostree-lzma-compressor.c index 8d9dcbc9..383037a8 100644 --- a/src/libostree/ostree-lzma-compressor.c +++ b/src/libostree/ostree-lzma-compressor.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-compressor.h b/src/libostree/ostree-lzma-compressor.h index ceb0fc57..b44d260f 100644 --- a/src/libostree/ostree-lzma-compressor.h +++ b/src/libostree/ostree-lzma-compressor.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-decompressor.c b/src/libostree/ostree-lzma-decompressor.c index 6376e389..cdbb946d 100644 --- a/src/libostree/ostree-lzma-decompressor.c +++ b/src/libostree/ostree-lzma-decompressor.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-lzma-decompressor.h b/src/libostree/ostree-lzma-decompressor.h index 0916c829..479dfd4b 100644 --- a/src/libostree/ostree-lzma-decompressor.h +++ b/src/libostree/ostree-lzma-decompressor.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-metalink.c b/src/libostree/ostree-metalink.c index 0b1b14fb..a1286185 100644 --- a/src/libostree/ostree-metalink.c +++ b/src/libostree/ostree-metalink.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-metalink.h b/src/libostree/ostree-metalink.h index 60a24204..4c2ae011 100644 --- a/src/libostree/ostree-metalink.h +++ b/src/libostree/ostree-metalink.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c index 5e933acc..05ec81f3 100644 --- a/src/libostree/ostree-mutable-tree.c +++ b/src/libostree/ostree-mutable-tree.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-mutable-tree.h b/src/libostree/ostree-mutable-tree.h index 1b642c42..d6c7b553 100644 --- a/src/libostree/ostree-mutable-tree.h +++ b/src/libostree/ostree-mutable-tree.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-ref.c b/src/libostree/ostree-ref.c index 8c84946c..bad86d9e 100644 --- a/src/libostree/ostree-ref.c +++ b/src/libostree/ostree-ref.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-ref.h b/src/libostree/ostree-ref.h index b23af171..3cf63ed4 100644 --- a/src/libostree/ostree-ref.h +++ b/src/libostree/ostree-ref.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-remote-private.h b/src/libostree/ostree-remote-private.h index 856cdaa6..b7e9eb3b 100644 --- a/src/libostree/ostree-remote-private.h +++ b/src/libostree/ostree-remote-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. diff --git a/src/libostree/ostree-remote.c b/src/libostree/ostree-remote.c index 1932b22f..cac7838c 100644 --- a/src/libostree/ostree-remote.c +++ b/src/libostree/ostree-remote.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. diff --git a/src/libostree/ostree-remote.h b/src/libostree/ostree-remote.h index df76f67e..23ee21bc 100644 --- a/src/libostree/ostree-remote.h +++ b/src/libostree/ostree-remote.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index de239eeb..fd1153ac 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index e8bb2395..a85da1c3 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-deprecated.h b/src/libostree/ostree-repo-deprecated.h index bb4b09d7..8729f7b9 100644 --- a/src/libostree/ostree-repo-deprecated.h +++ b/src/libostree/ostree-repo-deprecated.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-file-enumerator.c b/src/libostree/ostree-repo-file-enumerator.c index 7f25ec6d..83ed190f 100644 --- a/src/libostree/ostree-repo-file-enumerator.c +++ b/src/libostree/ostree-repo-file-enumerator.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-file-enumerator.h b/src/libostree/ostree-repo-file-enumerator.h index e4f95b10..d1ee449e 100644 --- a/src/libostree/ostree-repo-file-enumerator.h +++ b/src/libostree/ostree-repo-file-enumerator.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c index fcc435a8..7d6ac01e 100644 --- a/src/libostree/ostree-repo-file.c +++ b/src/libostree/ostree-repo-file.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-file.h b/src/libostree/ostree-repo-file.h index 6f9b79fe..658a0c3b 100644 --- a/src/libostree/ostree-repo-file.h +++ b/src/libostree/ostree-repo-file.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-avahi-parser.c b/src/libostree/ostree-repo-finder-avahi-parser.c index 805f5dff..e1ba3a03 100644 --- a/src/libostree/ostree-repo-finder-avahi-parser.c +++ b/src/libostree/ostree-repo-finder-avahi-parser.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2016 Kinvolk GmbH * Copyright © 2017 Endless Mobile, Inc. * diff --git a/src/libostree/ostree-repo-finder-avahi-private.h b/src/libostree/ostree-repo-finder-avahi-private.h index 6429cd7f..c7612adb 100644 --- a/src/libostree/ostree-repo-finder-avahi-private.h +++ b/src/libostree/ostree-repo-finder-avahi-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-avahi.c b/src/libostree/ostree-repo-finder-avahi.c index 5ded9636..4de74c6e 100644 --- a/src/libostree/ostree-repo-finder-avahi.c +++ b/src/libostree/ostree-repo-finder-avahi.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2016 Kinvolk GmbH * Copyright © 2017 Endless Mobile, Inc. * diff --git a/src/libostree/ostree-repo-finder-avahi.h b/src/libostree/ostree-repo-finder-avahi.h index 98d37723..dd0e478d 100644 --- a/src/libostree/ostree-repo-finder-avahi.h +++ b/src/libostree/ostree-repo-finder-avahi.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-config.c b/src/libostree/ostree-repo-finder-config.c index ada8479e..e3d32299 100644 --- a/src/libostree/ostree-repo-finder-config.c +++ b/src/libostree/ostree-repo-finder-config.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-config.h b/src/libostree/ostree-repo-finder-config.h index 28e6fc84..5d7d800f 100644 --- a/src/libostree/ostree-repo-finder-config.h +++ b/src/libostree/ostree-repo-finder-config.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index 31bb8bfc..9aa33834 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder-mount.h b/src/libostree/ostree-repo-finder-mount.h index d844dd44..31db1221 100644 --- a/src/libostree/ostree-repo-finder-mount.h +++ b/src/libostree/ostree-repo-finder-mount.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder.c b/src/libostree/ostree-repo-finder.c index 1ddb2c62..576a690c 100644 --- a/src/libostree/ostree-repo-finder.c +++ b/src/libostree/ostree-repo-finder.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-finder.h b/src/libostree/ostree-repo-finder.h index 6b0ce8ca..8434c8a8 100644 --- a/src/libostree/ostree-repo-finder.h +++ b/src/libostree/ostree-repo-finder.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index b34e4871..414981df 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index f5eb140e..7d50a5b7 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-prune.c b/src/libostree/ostree-repo-prune.c index 6ea899bc..88c52abf 100644 --- a/src/libostree/ostree-repo-prune.c +++ b/src/libostree/ostree-repo-prune.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index d8d2e34b..a32f6741 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2012,2013 Colin Walters * Copyright © 2017 Endless Mobile, Inc. * diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index 78ac9121..c6acc00b 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-static-delta-compilation-analysis.c b/src/libostree/ostree-repo-static-delta-compilation-analysis.c index 2b9b006f..f3e69af9 100644 --- a/src/libostree/ostree-repo-static-delta-compilation-analysis.c +++ b/src/libostree/ostree-repo-static-delta-compilation-analysis.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index 851f3fcb..759a75a4 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index b8a2c590..85952b6a 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-static-delta-private.h b/src/libostree/ostree-repo-static-delta-private.h index 6121c482..30d336b4 100644 --- a/src/libostree/ostree-repo-static-delta-private.h +++ b/src/libostree/ostree-repo-static-delta-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c index 2e75ea28..844de2c6 100644 --- a/src/libostree/ostree-repo-static-delta-processing.c +++ b/src/libostree/ostree-repo-static-delta-processing.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo-traverse.c b/src/libostree/ostree-repo-traverse.c index d125f01a..0d9ddbd9 100644 --- a/src/libostree/ostree-repo-traverse.c +++ b/src/libostree/ostree-repo-traverse.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 7554bc44..e2e91621 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2015 Red Hat, Inc. * diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index a22c1ade..1ba71c12 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-rollsum.c b/src/libostree/ostree-rollsum.c index 7e9190ce..beb9562f 100644 --- a/src/libostree/ostree-rollsum.c +++ b/src/libostree/ostree-rollsum.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-rollsum.h b/src/libostree/ostree-rollsum.h index ed832c6d..0cf5b0df 100644 --- a/src/libostree/ostree-rollsum.h +++ b/src/libostree/ostree-rollsum.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sepolicy-private.h b/src/libostree/ostree-sepolicy-private.h index def8ab74..ef8d574b 100644 --- a/src/libostree/ostree-sepolicy-private.h +++ b/src/libostree/ostree-sepolicy-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index 64670092..ab045970 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sepolicy.h b/src/libostree/ostree-sepolicy.h index 1c1a5786..39f142cf 100644 --- a/src/libostree/ostree-sepolicy.h +++ b/src/libostree/ostree-sepolicy.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index da239c78..a01334e3 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 911c2854..a89711f9 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 8c4de9e0..e362a025 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot-upgrader.c b/src/libostree/ostree-sysroot-upgrader.c index f028fa7c..eb75106e 100644 --- a/src/libostree/ostree-sysroot-upgrader.c +++ b/src/libostree/ostree-sysroot-upgrader.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot-upgrader.h b/src/libostree/ostree-sysroot-upgrader.h index 83c4ad32..4f3c0bfa 100644 --- a/src/libostree/ostree-sysroot-upgrader.h +++ b/src/libostree/ostree-sysroot-upgrader.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index ee9b4818..c7054571 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index f2573d6b..7446e379 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-tls-cert-interaction.c b/src/libostree/ostree-tls-cert-interaction.c index 7e60f9de..239f1ccc 100644 --- a/src/libostree/ostree-tls-cert-interaction.c +++ b/src/libostree/ostree-tls-cert-interaction.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-tls-cert-interaction.h b/src/libostree/ostree-tls-cert-interaction.h index 09a8ad0d..df4457b0 100644 --- a/src/libostree/ostree-tls-cert-interaction.h +++ b/src/libostree/ostree-tls-cert-interaction.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-types.h b/src/libostree/ostree-types.h index 61ac4283..7e07b04a 100644 --- a/src/libostree/ostree-types.h +++ b/src/libostree/ostree-types.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-varint.c b/src/libostree/ostree-varint.c index 3f1c7ead..4175999d 100644 --- a/src/libostree/ostree-varint.c +++ b/src/libostree/ostree-varint.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-varint.h b/src/libostree/ostree-varint.h index 0f0f06de..a7f6cd47 100644 --- a/src/libostree/ostree-varint.h +++ b/src/libostree/ostree-varint.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libostree/ostree-version.h.in b/src/libostree/ostree-version.h.in index 3f4d0fb7..8edb9116 100644 --- a/src/libostree/ostree-version.h.in +++ b/src/libostree/ostree-version.h.in @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Georges Basile Stavracas Neto * * This program is free software: you can redistribute it and/or modify diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h index 0f727384..bd748e68 100644 --- a/src/libostree/ostree.h +++ b/src/libostree/ostree.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c index 686554df..6838c774 100644 --- a/src/libotutil/ot-checksum-instream.c +++ b/src/libotutil/ot-checksum-instream.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-checksum-instream.h b/src/libotutil/ot-checksum-instream.h index 78a5d44e..6525aa91 100644 --- a/src/libotutil/ot-checksum-instream.h +++ b/src/libotutil/ot-checksum-instream.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c index eb0185bd..bd787a3f 100644 --- a/src/libotutil/ot-checksum-utils.c +++ b/src/libotutil/ot-checksum-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h index fdf7b09b..a0e72dbc 100644 --- a/src/libotutil/ot-checksum-utils.h +++ b/src/libotutil/ot-checksum-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 00b3c34f..253de5b3 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index 7f73762b..98fcd6a2 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index af2abb63..8dbaa840 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h index a69b744d..e72bae95 100644 --- a/src/libotutil/ot-gio-utils.h +++ b/src/libotutil/ot-gio-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-gpg-utils.c b/src/libotutil/ot-gpg-utils.c index f8a13269..981ac72f 100644 --- a/src/libotutil/ot-gpg-utils.c +++ b/src/libotutil/ot-gpg-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-gpg-utils.h b/src/libotutil/ot-gpg-utils.h index bd2810f8..fc5dcbce 100644 --- a/src/libotutil/ot-gpg-utils.h +++ b/src/libotutil/ot-gpg-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-keyfile-utils.c b/src/libotutil/ot-keyfile-utils.c index 6087a962..7c3b1d8a 100644 --- a/src/libotutil/ot-keyfile-utils.c +++ b/src/libotutil/ot-keyfile-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-keyfile-utils.h b/src/libotutil/ot-keyfile-utils.h index a5600a3e..b19b69e3 100644 --- a/src/libotutil/ot-keyfile-utils.h +++ b/src/libotutil/ot-keyfile-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-opt-utils.c b/src/libotutil/ot-opt-utils.c index 750e5b66..9e6eba0b 100644 --- a/src/libotutil/ot-opt-utils.c +++ b/src/libotutil/ot-opt-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-opt-utils.h b/src/libotutil/ot-opt-utils.h index ab2e0767..b6a5e956 100644 --- a/src/libotutil/ot-opt-utils.h +++ b/src/libotutil/ot-opt-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-tool-util.c b/src/libotutil/ot-tool-util.c index 0743c528..9e4b5dd3 100644 --- a/src/libotutil/ot-tool-util.c +++ b/src/libotutil/ot-tool-util.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-tool-util.h b/src/libotutil/ot-tool-util.h index 7d318173..6b7ab00a 100644 --- a/src/libotutil/ot-tool-util.h +++ b/src/libotutil/ot-tool-util.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-unix-utils.c b/src/libotutil/ot-unix-utils.c index 54547dd9..d6c5ee6d 100644 --- a/src/libotutil/ot-unix-utils.c +++ b/src/libotutil/ot-unix-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-unix-utils.h b/src/libotutil/ot-unix-utils.h index 817e6fd3..f59ab7ea 100644 --- a/src/libotutil/ot-unix-utils.h +++ b/src/libotutil/ot-unix-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-variant-utils.c b/src/libotutil/ot-variant-utils.c index c8c049fb..d1981c8b 100644 --- a/src/libotutil/ot-variant-utils.c +++ b/src/libotutil/ot-variant-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/ot-variant-utils.h b/src/libotutil/ot-variant-utils.h index 4f2131ee..135ae5d0 100644 --- a/src/libotutil/ot-variant-utils.h +++ b/src/libotutil/ot-variant-utils.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/otutil.c b/src/libotutil/otutil.c index ebed1a5e..26aed9b0 100644 --- a/src/libotutil/otutil.c +++ b/src/libotutil/otutil.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index 0647515c..d6fc603d 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/main.c b/src/ostree/main.c index 113edc66..9d8d2a4b 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ostree-trivial-httpd.c b/src/ostree/ostree-trivial-httpd.c index f3fd0c6c..e173fc38 100644 --- a/src/ostree/ostree-trivial-httpd.c +++ b/src/ostree/ostree-trivial-httpd.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-cleanup.c b/src/ostree/ot-admin-builtin-cleanup.c index a3b0a880..954f8d8a 100644 --- a/src/ostree/ot-admin-builtin-cleanup.c +++ b/src/ostree/ot-admin-builtin-cleanup.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index e46ad025..10ac57de 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-diff.c b/src/ostree/ot-admin-builtin-diff.c index 99672866..6afe4fae 100644 --- a/src/ostree/ot-admin-builtin-diff.c +++ b/src/ostree/ot-admin-builtin-diff.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-init-fs.c b/src/ostree/ot-admin-builtin-init-fs.c index a92d67dc..c5a9781f 100644 --- a/src/ostree/ot-admin-builtin-init-fs.c +++ b/src/ostree/ot-admin-builtin-init-fs.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-instutil.c b/src/ostree/ot-admin-builtin-instutil.c index 0770b1b2..91c4c114 100644 --- a/src/ostree/ot-admin-builtin-instutil.c +++ b/src/ostree/ot-admin-builtin-instutil.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-os-init.c b/src/ostree/ot-admin-builtin-os-init.c index 0abb8e39..b325ab32 100644 --- a/src/ostree/ot-admin-builtin-os-init.c +++ b/src/ostree/ot-admin-builtin-os-init.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-set-origin.c b/src/ostree/ot-admin-builtin-set-origin.c index e6020cbe..0332d882 100644 --- a/src/ostree/ot-admin-builtin-set-origin.c +++ b/src/ostree/ot-admin-builtin-set-origin.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-status.c b/src/ostree/ot-admin-builtin-status.c index 56107974..f076c592 100644 --- a/src/ostree/ot-admin-builtin-status.c +++ b/src/ostree/ot-admin-builtin-status.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-switch.c b/src/ostree/ot-admin-builtin-switch.c index 48fb2726..56e731b2 100644 --- a/src/ostree/ot-admin-builtin-switch.c +++ b/src/ostree/ot-admin-builtin-switch.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-undeploy.c b/src/ostree/ot-admin-builtin-undeploy.c index d16c927e..6ca8e3a3 100644 --- a/src/ostree/ot-admin-builtin-undeploy.c +++ b/src/ostree/ot-admin-builtin-undeploy.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-unlock.c b/src/ostree/ot-admin-builtin-unlock.c index 36d99edb..1b6d9203 100644 --- a/src/ostree/ot-admin-builtin-unlock.c +++ b/src/ostree/ot-admin-builtin-unlock.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c index 8944904b..dfda4d5f 100644 --- a/src/ostree/ot-admin-builtin-upgrade.c +++ b/src/ostree/ot-admin-builtin-upgrade.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h index f9425119..75cd1448 100644 --- a/src/ostree/ot-admin-builtins.h +++ b/src/ostree/ot-admin-builtins.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-functions.c b/src/ostree/ot-admin-functions.c index 6a99db04..bd71873c 100644 --- a/src/ostree/ot-admin-functions.c +++ b/src/ostree/ot-admin-functions.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-functions.h b/src/ostree/ot-admin-functions.h index 8c0cf8ee..73157bf3 100644 --- a/src/ostree/ot-admin-functions.h +++ b/src/ostree/ot-admin-functions.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-admin-instutil-builtin-grub2-generate.c b/src/ostree/ot-admin-instutil-builtin-grub2-generate.c index 8ff0dc47..64d2ae2a 100644 --- a/src/ostree/ot-admin-instutil-builtin-grub2-generate.c +++ b/src/ostree/ot-admin-instutil-builtin-grub2-generate.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c b/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c index cbca7db3..135bcf42 100644 --- a/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c +++ b/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/ostree/ot-admin-instutil-builtin-set-kargs.c b/src/ostree/ot-admin-instutil-builtin-set-kargs.c index 7a98feb7..f8db6c6b 100644 --- a/src/ostree/ot-admin-instutil-builtin-set-kargs.c +++ b/src/ostree/ot-admin-instutil-builtin-set-kargs.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff --git a/src/ostree/ot-admin-instutil-builtins.h b/src/ostree/ot-admin-instutil-builtins.h index b11336ac..748a7938 100644 --- a/src/ostree/ot-admin-instutil-builtins.h +++ b/src/ostree/ot-admin-instutil-builtins.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index ce0b2ffa..85db78ec 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-cat.c b/src/ostree/ot-builtin-cat.c index 9aedeb4e..6f2c466c 100644 --- a/src/ostree/ot-builtin-cat.c +++ b/src/ostree/ot-builtin-cat.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index 170d24e9..e774713e 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-checksum.c b/src/ostree/ot-builtin-checksum.c index 8c44de9e..5ca6eed3 100644 --- a/src/ostree/ot-builtin-checksum.c +++ b/src/ostree/ot-builtin-checksum.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 1665765f..c1d88b3b 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index 782fee85..6813305c 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index e00a20fd..465e2506 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-export.c b/src/ostree/ot-builtin-export.c index b68cbb6d..7967bf6c 100644 --- a/src/ostree/ot-builtin-export.c +++ b/src/ostree/ot-builtin-export.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-find-remotes.c b/src/ostree/ot-builtin-find-remotes.c index 10c310b2..daeea38b 100644 --- a/src/ostree/ot-builtin-find-remotes.c +++ b/src/ostree/ot-builtin-find-remotes.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index ed357eca..28320985 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-gpg-sign.c b/src/ostree/ot-builtin-gpg-sign.c index 8969fe86..451d0f46 100644 --- a/src/ostree/ot-builtin-gpg-sign.c +++ b/src/ostree/ot-builtin-gpg-sign.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-init.c b/src/ostree/ot-builtin-init.c index c77f6972..7b72620a 100644 --- a/src/ostree/ot-builtin-init.c +++ b/src/ostree/ot-builtin-init.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-log.c b/src/ostree/ot-builtin-log.c index 626793bc..5fda4ee7 100644 --- a/src/ostree/ot-builtin-log.c +++ b/src/ostree/ot-builtin-log.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-ls.c b/src/ostree/ot-builtin-ls.c index 9cd82eb1..ba22d3c3 100644 --- a/src/ostree/ot-builtin-ls.c +++ b/src/ostree/ot-builtin-ls.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c index 6120e0a9..f5ab5960 100644 --- a/src/ostree/ot-builtin-prune.c +++ b/src/ostree/ot-builtin-prune.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index 34115a01..d80c5a25 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index 119e6656..47f9d8be 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-refs.c b/src/ostree/ot-builtin-refs.c index 3742f050..1b4ead7d 100644 --- a/src/ostree/ot-builtin-refs.c +++ b/src/ostree/ot-builtin-refs.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-remote.c b/src/ostree/ot-builtin-remote.c index 9d290d09..c9b3be35 100644 --- a/src/ostree/ot-builtin-remote.c +++ b/src/ostree/ot-builtin-remote.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-reset.c b/src/ostree/ot-builtin-reset.c index 744d297c..ae1da7cb 100644 --- a/src/ostree/ot-builtin-reset.c +++ b/src/ostree/ot-builtin-reset.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-rev-parse.c b/src/ostree/ot-builtin-rev-parse.c index c339a9cf..060bcdc9 100644 --- a/src/ostree/ot-builtin-rev-parse.c +++ b/src/ostree/ot-builtin-rev-parse.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index 30375600..f197d7c3 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-static-delta.c b/src/ostree/ot-builtin-static-delta.c index c64dbbf5..c5d22dad 100644 --- a/src/ostree/ot-builtin-static-delta.c +++ b/src/ostree/ot-builtin-static-delta.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index c983a83e..aacd9bae 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtin-trivial-httpd.c b/src/ostree/ot-builtin-trivial-httpd.c index 206970c5..972cf1ad 100644 --- a/src/ostree/ot-builtin-trivial-httpd.c +++ b/src/ostree/ot-builtin-trivial-httpd.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h index 9c648458..96a5929e 100644 --- a/src/ostree/ot-builtins.h +++ b/src/ostree/ot-builtins.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-dump.c b/src/ostree/ot-dump.c index 83eb307f..7f7f8b6b 100644 --- a/src/ostree/ot-dump.c +++ b/src/ostree/ot-dump.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Stef Walter * diff --git a/src/ostree/ot-dump.h b/src/ostree/ot-dump.h index 547981e8..010449c3 100644 --- a/src/ostree/ot-dump.h +++ b/src/ostree/ot-dump.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-editor.c b/src/ostree/ot-editor.c index bb0dd3c2..a23633a6 100644 --- a/src/ostree/ot-editor.c +++ b/src/ostree/ot-editor.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-editor.h b/src/ostree/ot-editor.h index 81b6361e..e24d9279 100644 --- a/src/ostree/ot-editor.h +++ b/src/ostree/ot-editor.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index a6ddfe74..1f7e9382 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-main.h b/src/ostree/ot-main.h index ddf52959..11fc287e 100644 --- a/src/ostree/ot-main.h +++ b/src/ostree/ot-main.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-add-cookie.c b/src/ostree/ot-remote-builtin-add-cookie.c index 4edecaf9..764d2fc3 100644 --- a/src/ostree/ot-remote-builtin-add-cookie.c +++ b/src/ostree/ot-remote-builtin-add-cookie.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index efa9431f..f0990795 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-delete-cookie.c b/src/ostree/ot-remote-builtin-delete-cookie.c index 0838e7bf..ecb2451b 100644 --- a/src/ostree/ot-remote-builtin-delete-cookie.c +++ b/src/ostree/ot-remote-builtin-delete-cookie.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff --git a/src/ostree/ot-remote-builtin-delete.c b/src/ostree/ot-remote-builtin-delete.c index f10d793a..d7ad6bb5 100644 --- a/src/ostree/ot-remote-builtin-delete.c +++ b/src/ostree/ot-remote-builtin-delete.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-gpg-import.c b/src/ostree/ot-remote-builtin-gpg-import.c index 78a57fdf..6edcf321 100644 --- a/src/ostree/ot-remote-builtin-gpg-import.c +++ b/src/ostree/ot-remote-builtin-gpg-import.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-list-cookies.c b/src/ostree/ot-remote-builtin-list-cookies.c index 3a83eef4..99d76346 100644 --- a/src/ostree/ot-remote-builtin-list-cookies.c +++ b/src/ostree/ot-remote-builtin-list-cookies.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff --git a/src/ostree/ot-remote-builtin-list.c b/src/ostree/ot-remote-builtin-list.c index 772e212f..fea5e420 100644 --- a/src/ostree/ot-remote-builtin-list.c +++ b/src/ostree/ot-remote-builtin-list.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-refs.c b/src/ostree/ot-remote-builtin-refs.c index 66c6bea0..bffc1985 100644 --- a/src/ostree/ot-remote-builtin-refs.c +++ b/src/ostree/ot-remote-builtin-refs.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-show-url.c b/src/ostree/ot-remote-builtin-show-url.c index 16215c62..7ce0572e 100644 --- a/src/ostree/ot-remote-builtin-show-url.c +++ b/src/ostree/ot-remote-builtin-show-url.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtin-summary.c b/src/ostree/ot-remote-builtin-summary.c index ca9173ea..30aedc2d 100644 --- a/src/ostree/ot-remote-builtin-summary.c +++ b/src/ostree/ot-remote-builtin-summary.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-builtins.h b/src/ostree/ot-remote-builtins.h index aa2a7b6c..c61fcc07 100644 --- a/src/ostree/ot-remote-builtins.h +++ b/src/ostree/ot-remote-builtins.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/src/ostree/ot-remote-cookie-util.c b/src/ostree/ot-remote-cookie-util.c index 914af5af..6f7b4c2b 100644 --- a/src/ostree/ot-remote-cookie-util.c +++ b/src/ostree/ot-remote-cookie-util.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff --git a/src/ostree/ot-remote-cookie-util.h b/src/ostree/ot-remote-cookie-util.h index 1bcc0e87..c0659cf8 100644 --- a/src/ostree/ot-remote-cookie-util.h +++ b/src/ostree/ot-remote-cookie-util.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/rofiles-fuse/main.c b/src/rofiles-fuse/main.c index f2b1b650..b80c916d 100644 --- a/src/rofiles-fuse/main.c +++ b/src/rofiles-fuse/main.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015,2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/switchroot/ostree-mount-util.h b/src/switchroot/ostree-mount-util.h index 1e7253d2..0c37e6d1 100644 --- a/src/switchroot/ostree-mount-util.h +++ b/src/switchroot/ostree-mount-util.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/switchroot/ostree-remount.c b/src/switchroot/ostree-remount.c index a6d14d08..fe6b6f44 100644 --- a/src/switchroot/ostree-remount.c +++ b/src/switchroot/ostree-remount.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/src/switchroot/ostree-system-generator.c b/src/switchroot/ostree-system-generator.c index e7205b5a..5665d715 100644 --- a/src/switchroot/ostree-system-generator.c +++ b/src/switchroot/ostree-system-generator.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/tests/libostreetest.c b/tests/libostreetest.c index f1a01e68..6186a73a 100644 --- a/tests/libostreetest.c +++ b/tests/libostreetest.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/libostreetest.h b/tests/libostreetest.h index f777545e..d5512d55 100644 --- a/tests/libostreetest.h +++ b/tests/libostreetest.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/tests/readdir-rand.c b/tests/readdir-rand.c index 10bf8677..69047faa 100644 --- a/tests/readdir-rand.c +++ b/tests/readdir-rand.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters . * * This library is free software; you can redistribute it and/or diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c index d8800763..27b9744a 100644 --- a/tests/test-basic-c.c +++ b/tests/test-basic-c.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-bloom.c b/tests/test-bloom.c index 2e89456e..33cf4f35 100644 --- a/tests/test-bloom.c +++ b/tests/test-bloom.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-bsdiff.c b/tests/test-bsdiff.c index 0bf500da..de55aac2 100644 --- a/tests/test-bsdiff.c +++ b/tests/test-bsdiff.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-checksum.c b/tests/test-checksum.c index 7d2a0cea..af8efb2e 100644 --- a/tests/test-checksum.c +++ b/tests/test-checksum.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-gpg-verify-result.c b/tests/test-gpg-verify-result.c index 6d11fac6..d95aa2f8 100644 --- a/tests/test-gpg-verify-result.c +++ b/tests/test-gpg-verify-result.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-keyfile-utils.c b/tests/test-keyfile-utils.c index 376b0e82..bc9a7331 100644 --- a/tests/test-keyfile-utils.c +++ b/tests/test-keyfile-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-libarchive-import.c b/tests/test-libarchive-import.c index 77c2dd30..5559da34 100644 --- a/tests/test-libarchive-import.c +++ b/tests/test-libarchive-import.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-lzma.c b/tests/test-lzma.c index 559e9ad4..b8f5edbc 100644 --- a/tests/test-lzma.c +++ b/tests/test-lzma.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-mock-gio.c b/tests/test-mock-gio.c index f6d4f2a8..a5aa023f 100644 --- a/tests/test-mock-gio.c +++ b/tests/test-mock-gio.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-mock-gio.h b/tests/test-mock-gio.h index 9f544759..d4c62e8d 100644 --- a/tests/test-mock-gio.h +++ b/tests/test-mock-gio.h @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-mutable-tree.c b/tests/test-mutable-tree.c index f878f116..43ef9fbd 100644 --- a/tests/test-mutable-tree.c +++ b/tests/test-mutable-tree.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-ot-opt-utils.c b/tests/test-ot-opt-utils.c index 77ecdf30..267d4093 100644 --- a/tests/test-ot-opt-utils.c +++ b/tests/test-ot-opt-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-ot-tool-util.c b/tests/test-ot-tool-util.c index 13030fe4..e2b2497d 100644 --- a/tests/test-ot-tool-util.c +++ b/tests/test-ot-tool-util.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-ot-unix-utils.c b/tests/test-ot-unix-utils.c index 5eeab1d1..2e48b0e3 100644 --- a/tests/test-ot-unix-utils.c +++ b/tests/test-ot-unix-utils.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-pull-c.c b/tests/test-pull-c.c index 2b0cef6d..4541ed90 100644 --- a/tests/test-pull-c.c +++ b/tests/test-pull-c.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-repo-finder-avahi.c b/tests/test-repo-finder-avahi.c index b2fddf70..7788f67f 100644 --- a/tests/test-repo-finder-avahi.c +++ b/tests/test-repo-finder-avahi.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-repo-finder-config.c b/tests/test-repo-finder-config.c index eeae0b60..c4a763e6 100644 --- a/tests/test-repo-finder-config.c +++ b/tests/test-repo-finder-config.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index 2ab08001..7c5f9e9b 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-rollsum-cli.c b/tests/test-rollsum-cli.c index 256c79fe..20947ead 100644 --- a/tests/test-rollsum-cli.c +++ b/tests/test-rollsum-cli.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff --git a/tests/test-rollsum.c b/tests/test-rollsum.c index a6c1bebd..1164b266 100644 --- a/tests/test-rollsum.c +++ b/tests/test-rollsum.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-sysroot-c.c b/tests/test-sysroot-c.c index 9c07faf4..7cf30d1f 100644 --- a/tests/test-sysroot-c.c +++ b/tests/test-sysroot-c.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff --git a/tests/test-varint.c b/tests/test-varint.c index 062c47ef..311348df 100644 --- a/tests/test-varint.c +++ b/tests/test-varint.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or From 335f914d48064fe4e3abbbb3bf8b3e8605f262f9 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 20 Sep 2017 17:06:41 +0000 Subject: [PATCH 34/78] tests: allow specifying tmpdir Allow developers to override the default /var/tmp dir, which e.g. might be on overlayfs and thus produces reduced coverage. Closes: #1207 Approved by: cgwalters --- buildutil/tap-test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildutil/tap-test b/buildutil/tap-test index ac729d8d..e35f2a4a 100755 --- a/buildutil/tap-test +++ b/buildutil/tap-test @@ -8,7 +8,8 @@ srcd=$(cd $(dirname $1) && pwd) bn=$(basename $1) -tempdir=$(mktemp -d /var/tmp/tap-test.XXXXXX) +TEST_TMPDIR=${TEST_TMPDIR:-/var/tmp} +tempdir=$(mktemp -d $TEST_TMPDIR/tap-test.XXXXXX) touch ${tempdir}/.testtmp function cleanup () { if test -f ${tempdir}/.testtmp; then From 95bfe6b8627d7184cc12db1772d537c575904583 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 20 Sep 2017 17:07:54 +0000 Subject: [PATCH 35/78] tests/libtest: check that we have setfattr We use `setfattr` to determine whether the filesystem we're on supports xattrs, but we need to check that `setfattr` itself is available. We just make it a hard requirement but only if trying to run tests that ask about xattr support. Closes: #1207 Approved by: cgwalters --- tests/libtest.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/libtest.sh b/tests/libtest.sh index 2b30e654..9bfc199f 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -517,6 +517,9 @@ os_repository_new_commit () # Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi _have_user_xattrs='' have_user_xattrs() { + if ! which setfattr 2>/dev/null; then + fatal "no setfattr available to determine xattr support" + fi if test "${_have_user_xattrs}" = ''; then touch test-xattrs if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then From a0588c310225195818ebd4689eee5c4ad2103406 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 21 Sep 2017 19:46:17 +0000 Subject: [PATCH 36/78] Add a .vimrc and .editorconfig The `.vimrc` requires the `exrc` option to be turned on, and `.editorconfig` requires https://github.com/editorconfig/editorconfig-vim apparently. Closes: #1208 Approved by: cgwalters --- .editorconfig | 5 +++++ .vimrc | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .editorconfig create mode 100644 .vimrc diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..89742b69 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*.[ch]] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +indent_brace_style = gnu diff --git a/.vimrc b/.vimrc new file mode 100644 index 00000000..142c417a --- /dev/null +++ b/.vimrc @@ -0,0 +1,12 @@ +set expandtab +set tabstop=8 +set softtabstop=2 +set shiftwidth=2 + +" Let's try to not go longer than 92 +set textwidth=92 +autocmd BufNewFile,BufRead *.c,*.h set textwidth=92 + +" This is the same as the default minus 0{, which is really annoying otherwise +" with our coding style. +set cinkeys=0},0),:,0#,!^F,o,O,e From 1797aff6a86770621d3ea9e0f725ad96754876b5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 15:44:24 -0400 Subject: [PATCH 37/78] lib/core: Add static assertions for OstreeRepoMode enum values Prep for adding an alias. Closes: #1209 Approved by: jlebon --- src/libostree/ostree-core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 13dc6130..c81aa39c 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -32,6 +32,12 @@ #include "ostree-chain-input-stream.h" #include "otutil.h" +/* Generic ABI checks */ +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE == 0); +G_STATIC_ASSERT(OSTREE_REPO_MODE_ARCHIVE_Z2 == 1); +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER == 2); +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER_ONLY == 3); + #define ALIGN_VALUE(this, boundary) \ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1))) From ee5ecf33a55fb22ef121d76721dea0297d712c8f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 21 Sep 2017 15:48:46 -0400 Subject: [PATCH 38/78] lib: Define an alias OSTREE_REPO_MODE_ARCHIVE For the old `OSTREE_REPO_MODE_ARCHIVE_Z2`. Use it mostly tree wide except for the repo finder tests (to avoid conflicting with some outstanding PRs). Just noted another user coming in some of those tests and wanted to do a cleanup. Closes: #1209 Approved by: jlebon --- src/libostree/ostree-core.c | 3 ++- src/libostree/ostree-core.h | 6 ++++-- src/libostree/ostree-repo-checkout.c | 4 ++-- src/libostree/ostree-repo-commit.c | 10 +++++----- src/libostree/ostree-repo-pull.c | 8 ++++---- src/libostree/ostree-repo.c | 11 ++++++----- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index c81aa39c..5a4b58f4 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -35,6 +35,7 @@ /* Generic ABI checks */ G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE == 0); G_STATIC_ASSERT(OSTREE_REPO_MODE_ARCHIVE_Z2 == 1); +G_STATIC_ASSERT(OSTREE_REPO_MODE_ARCHIVE == OSTREE_REPO_MODE_ARCHIVE_Z2); G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER == 2); G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER_ONLY == 3); @@ -1530,7 +1531,7 @@ _ostree_loose_path (char *buf, buf++; snprintf (buf, _OSTREE_LOOSE_PATH_MAX - 2, "/%s.%s%s", checksum + 2, ostree_object_type_to_string (objtype), - (!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE_Z2) ? "z" : ""); + (!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE) ? "z" : ""); } /** diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index 5124814c..aae86d54 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -180,7 +180,8 @@ typedef enum { /** * OstreeRepoMode: * @OSTREE_REPO_MODE_BARE: Files are stored as themselves; checkouts are hardlinks; can only be written as root - * @OSTREE_REPO_MODE_ARCHIVE_Z2: Files are compressed, should be owned by non-root. Can be served via HTTP + * @OSTREE_REPO_MODE_ARCHIVE: Files are compressed, should be owned by non-root. Can be served via HTTP. Since: 2017.12 + * @OSTREE_REPO_MODE_ARCHIVE_Z2: Legacy alias for `OSTREE_REPO_MODE_ARCHIVE` * @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. Hardlinks work only in user checkouts. * @OSTREE_REPO_MODE_BARE_USER_ONLY: Same as BARE_USER, but all metadata is not stored, so it can only be used for user checkouts. Does not need xattrs. * @@ -189,7 +190,8 @@ typedef enum { */ typedef enum { OSTREE_REPO_MODE_BARE, - OSTREE_REPO_MODE_ARCHIVE_Z2, + OSTREE_REPO_MODE_ARCHIVE, + OSTREE_REPO_MODE_ARCHIVE_Z2 = OSTREE_REPO_MODE_ARCHIVE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY, } OstreeRepoMode; diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index fd1153ac..a3dd6887 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -536,7 +536,7 @@ checkout_one_file_at (OstreeRepo *repo, (repo_is_usermode && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER); gboolean current_can_cache = (options->enable_uncompressed_cache && current_repo->enable_uncompressed_cache); - gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER && current_can_cache); @@ -608,7 +608,7 @@ checkout_one_file_at (OstreeRepo *repo, && !is_whiteout && !is_symlink && need_copy - && repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + && repo->mode == OSTREE_REPO_MODE_ARCHIVE && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER) { HardlinkResult hardlink_res = HARDLINK_RESULT_NOT_SUPPORTED; diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index a85da1c3..2268c0ff 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -215,7 +215,7 @@ commit_loose_regfile_object (OstreeRepo *self, /* We may be writing as root to a non-root-owned repository; if so, * automatically inherit the non-root ownership. */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + if (self->mode == OSTREE_REPO_MODE_ARCHIVE && self->target_owner_uid != -1) { if (fchown (tmpf->fd, self->target_owner_uid, self->target_owner_gid) < 0) @@ -603,7 +603,7 @@ write_content_object (OstreeRepo *self, cancellable, error)) return FALSE; } - else if (repo_mode != OSTREE_REPO_MODE_ARCHIVE_Z2) + else if (repo_mode != OSTREE_REPO_MODE_ARCHIVE) { if (!create_regular_tmpfile_linkable_with_content (self, size, file_input, &tmpf, cancellable, error)) @@ -616,7 +616,7 @@ write_content_object (OstreeRepo *self, g_autoptr(GOutputStream) compressed_out_stream = NULL; g_autoptr(GOutputStream) temp_out = NULL; - g_assert (repo_mode == OSTREE_REPO_MODE_ARCHIVE_Z2); + g_assert (repo_mode == OSTREE_REPO_MODE_ARCHIVE); if (self->generate_sizes) indexable = TRUE; @@ -932,7 +932,7 @@ scan_one_loose_devino (OstreeRepo *self, gboolean skip; switch (self->mode) { - case OSTREE_REPO_MODE_ARCHIVE_Z2: + case OSTREE_REPO_MODE_ARCHIVE: case OSTREE_REPO_MODE_BARE: case OSTREE_REPO_MODE_BARE_USER: case OSTREE_REPO_MODE_BARE_USER_ONLY: @@ -981,7 +981,7 @@ scan_loose_devino (OstreeRepo *self, return FALSE; } - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) { if (!scan_one_loose_devino (self, self->uncompressed_objects_dir_fd, devino_cache, cancellable, error)) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index a32f6741..d8048e75 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1029,7 +1029,7 @@ content_fetch_on_complete (GObject *object, * the content rather than paying the cost of exploding it, checksumming, and * re-gzip. */ - if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE && !pull_data->is_bareuseronly_files) { gboolean have_object; @@ -3529,7 +3529,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, &pull_data->has_tombstone_commits, error)) goto out; - if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE_Z2) + if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't pull from archives with mode \"%s\"", @@ -3550,7 +3550,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, } /* We can't use static deltas if pulling into an archive repo. */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) { if (pull_data->require_static_deltas) { @@ -4894,7 +4894,7 @@ find_remotes_cb (GObject *obj, if (commit_metadata->timestamp != 0) continue; - _ostree_loose_path (buf, commit_metadata->checksum, OSTREE_OBJECT_TYPE_COMMIT, OSTREE_REPO_MODE_ARCHIVE_Z2); + _ostree_loose_path (buf, commit_metadata->checksum, OSTREE_OBJECT_TYPE_COMMIT, OSTREE_REPO_MODE_ARCHIVE); commit_filename = g_build_filename ("objects", buf, NULL); /* For each of the remotes whose summary files contain this ref, try diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e2e91621..82c01e05 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1749,7 +1749,8 @@ ostree_repo_mode_to_string (OstreeRepoMode mode, case OSTREE_REPO_MODE_BARE_USER_ONLY: ret_mode = "bare-user-only"; break; - case OSTREE_REPO_MODE_ARCHIVE_Z2: + case OSTREE_REPO_MODE_ARCHIVE: + /* Legacy alias */ ret_mode ="archive-z2"; break; default: @@ -1775,7 +1776,7 @@ ostree_repo_mode_from_string (const char *mode, ret_mode = OSTREE_REPO_MODE_BARE_USER_ONLY; else if (strcmp (mode, "archive-z2") == 0 || strcmp (mode, "archive") == 0) - ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z2; + ret_mode = OSTREE_REPO_MODE_ARCHIVE; else return glnx_throw (error, "Invalid mode '%s' in repository configuration", mode); @@ -2473,7 +2474,7 @@ ostree_repo_open (OstreeRepo *self, return FALSE; /* TODO - delete this */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->enable_uncompressed_cache) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE && self->enable_uncompressed_cache) { if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, "uncompressed-objects-cache", 0755, cancellable, error)) @@ -2724,7 +2725,7 @@ list_loose_objects_at (OstreeRepo *self, continue; OstreeObjectType objtype; - if ((self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + if ((self->mode == OSTREE_REPO_MODE_ARCHIVE && strcmp (dot, ".filez") == 0) || ((_ostree_repo_mode_is_bare (self->mode)) && strcmp (dot, ".file") == 0)) @@ -3150,7 +3151,7 @@ ostree_repo_load_file (OstreeRepo *self, GCancellable *cancellable, GError **error) { - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) return repo_load_file_archive (self, checksum, out_input, out_file_info, out_xattrs, cancellable, error); else From f91acf522631025ce036cc574b166939b95540dd Mon Sep 17 00:00:00 2001 From: Jussi Laako Date: Tue, 13 Jun 2017 16:56:21 +0300 Subject: [PATCH 39/78] Add --with-crypto=gnutls Introduce support for GnuTLS for computing cryptograpic hashes, similar to the OpenSSL backend. A reason to do this is some distributors want to avoid GPLv3, and GPG pulls that in. A possible extension of using GnuTLS would be replacing the GPG signing with `PKCS#7` signatures and `X.509` keys. We also support `--with-crypto=openssl`, which has the same effect as `--with-openssl`, and continues to be supported. Changes by Colin Walters : - Drop libgcrypt option for now - Unify buildsystem on --with-crypto Link: https://mail.gnome.org/archives/ostree-list/2017-June/msg00002.html Signed-off-by: Jussi Laako Closes: #1189 Approved by: cgwalters --- .papr.yml | 14 +++++++ Makefile-libostree.am | 4 +- configure.ac | 35 ++++++++++++++--- src/libotutil/ot-checksum-instream.c | 58 +++++++++++++++++++++++----- 4 files changed, 95 insertions(+), 16 deletions(-) diff --git a/.papr.yml b/.papr.yml index 4ae345e6..03489142 100644 --- a/.papr.yml +++ b/.papr.yml @@ -63,6 +63,20 @@ tests: --- +context: f26-gnutls +inherit: true +container: + image: registry.fedoraproject.org/fedora:26 +env: + CONFIGOPTS: '--with-crypto=gnutls' + CI_PKGS: pkgconfig(gnutls) + +tests: + - ci/build.sh + - make check TESTS=tests/test-basic.sh + +--- + inherit: true context: f26-experimental-api diff --git a/Makefile-libostree.am b/Makefile-libostree.am index c83569ff..ebbe8437 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -193,11 +193,11 @@ EXTRA_DIST += \ $(NULL) libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ - $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_OPENSSL_CFLAGS) \ + $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ - $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_OPENSSL_LIBS) + $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) libostree_1_la_LIBADD += $(bupsplitpath) EXTRA_libostree_1_la_DEPENDENCIES = $(symbol_files) diff --git a/configure.ac b/configure.ac index 27e1a83d..2a248bc5 100644 --- a/configure.ac +++ b/configure.ac @@ -329,15 +329,29 @@ AS_IF([ test x$with_smack = xyes], [ ]) AM_CONDITIONAL(USE_SMACK, test $with_smack != no) +dnl crypto +AC_ARG_WITH(crypto, +AS_HELP_STRING([--with-crypto], [Choose library for checksums, one of glib, openssl, gnutls (default: glib)]), +:, with_crypto=glib) + +AS_IF([test $with_crypto = glib], + [], + [test $with_crypto = openssl], + [with_openssl=yes], + [test $with_crypto = gnutls], + [], + [AC_MSG_ERROR([Invalid --with-crypto $with_crypto])] + ) + dnl begin openssl (really just libcrypto right now) +dnl Note this option is now deprecated in favor of --with-crypto=openssl OPENSSL_DEPENDENCY="libcrypto >= 1.0.1" AC_ARG_WITH(openssl, -AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]), -:, with_openssl=no) - +AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]),with_openssl=$withval,with_openssl=no) AS_IF([ test x$with_openssl != xno ], [ - PKG_CHECK_MODULES(OT_DEP_OPENSSL, $OPENSSL_DEPENDENCY) + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $OPENSSL_DEPENDENCY) AC_DEFINE([HAVE_OPENSSL], 1, [Define if we have openssl]) + with_crypto=openssl with_openssl=yes ], [ with_openssl=no @@ -346,6 +360,17 @@ if test x$with_openssl != xno; then OSTREE_FEATURES="$OSTREE_FEATURES openssl"; AM_CONDITIONAL(USE_OPENSSL, test $with_openssl != no) dnl end openssl +dnl begin gnutls; in contrast to openssl this one only +dnl supports --with-crypto=gnutls +GNUTLS_DEPENDENCY="gnutls >= 3.5.0" +AS_IF([ test $with_crypto = gnutls ], [ + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $GNUTLS_DEPENDENCY) + AC_DEFINE([HAVE_GNUTLS], 1, [Define if we have gnutls]) + OSTREE_FEATURES="$OSTREE_FEATURES gnutls" +]) +AM_CONDITIONAL(USE_GNUTLS, test $with_crypto = gnutls) +dnl end gnutls + dnl Avahi dependency for finding repos AVAHI_DEPENDENCY="avahi-client >= 0.6.31 avahi-glib >= 0.6.31" @@ -536,7 +561,7 @@ echo " HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux - OpenSSL libcrypto (checksums): $with_openssl + cryptographic checksums: $with_crypto systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c index 6838c774..368a337d 100644 --- a/src/libotutil/ot-checksum-instream.c +++ b/src/libotutil/ot-checksum-instream.c @@ -22,15 +22,21 @@ #include "ot-checksum-instream.h" #include "ot-checksum-utils.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) #include +#elif defined(HAVE_GNUTLS) +#include +#include #endif G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM) struct _OtChecksumInstreamPrivate { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX *checksum; +#elif defined(HAVE_GNUTLS) + gnutls_digest_algorithm_t checksum_type; + gnutls_hash_hd_t checksum; #else GChecksumType checksum_type; GChecksum *checksum; @@ -48,8 +54,10 @@ ot_checksum_instream_finalize (GObject *object) { OtChecksumInstream *self = (OtChecksumInstream*)object; -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX_destroy (self->priv->checksum); +#elif defined(HAVE_GNUTLS) + gnutls_hash_deinit (self->priv->checksum, NULL); #else g_checksum_free (self->priv->checksum); #endif @@ -75,7 +83,7 @@ ot_checksum_instream_init (OtChecksumInstream *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate); } -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) static const EVP_MD * gchecksum_type_to_openssl (GChecksumType checksum_type) { @@ -88,6 +96,18 @@ gchecksum_type_to_openssl (GChecksumType checksum_type) g_assert_not_reached (); } } +#elif defined(HAVE_GNUTLS) +static gnutls_digest_algorithm_t +gchecksum_type_to_gnutls (GChecksumType checksum_type) +{ + switch (checksum_type) + { + case G_CHECKSUM_SHA256: + return GNUTLS_DIG_SHA256; + default: + g_assert_not_reached (); + } +} #endif OtChecksumInstream * @@ -105,10 +125,13 @@ ot_checksum_instream_new (GInputStream *base, /* For now */ g_assert (checksum_type == G_CHECKSUM_SHA256); -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) stream->priv->checksum = EVP_MD_CTX_create (); g_assert (stream->priv->checksum); g_assert (EVP_DigestInit_ex (stream->priv->checksum, gchecksum_type_to_openssl (checksum_type), NULL)); +#elif defined(HAVE_GNUTLS) + stream->priv->checksum_type = gchecksum_type_to_gnutls (checksum_type); + g_assert (!gnutls_hash_init (&stream->priv->checksum, stream->priv->checksum_type)); #else stream->priv->checksum = g_checksum_new (checksum_type); stream->priv->checksum_type = checksum_type; @@ -135,8 +158,10 @@ ot_checksum_instream_read (GInputStream *stream, error); if (res > 0) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res)); +#elif defined(HAVE_GNUTLS) + g_assert (!gnutls_hash (self->priv->checksum, buffer, res)); #else g_checksum_update (self->priv->checksum, buffer, res); #endif @@ -150,11 +175,15 @@ ot_checksum_instream_get_digest (OtChecksumInstream *stream, guint8 *buffer, gsize *digest_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len); if (digest_len) *digest_len = len; +#elif defined(HAVE_GNUTLS) + gnutls_hash_output (stream->priv->checksum, buffer); + if (digest_len) + *digest_len = gnutls_hash_get_len (stream->priv->checksum_type); #else g_checksum_get_digest (stream->priv->checksum, buffer, digest_len); #endif @@ -164,10 +193,14 @@ guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream, gsize *ret_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) guint len; guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE); g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len)); +#elif defined(HAVE_GNUTLS) + guint len = gnutls_hash_get_len (stream->priv->checksum_type); + guchar *ret = g_malloc0 (len); + gnutls_hash_output (stream->priv->checksum, ret); #else gsize len = g_checksum_type_get_length (stream->priv->checksum_type); guchar *ret = g_malloc (len); @@ -181,13 +214,20 @@ ot_checksum_instream_dup_digest (OtChecksumInstream *stream, char * ot_checksum_instream_get_string (OtChecksumInstream *stream) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; guint8 csum[EVP_MAX_MD_SIZE]; g_assert (EVP_DigestFinal_ex (stream->priv->checksum, csum, &len)); char *buf = g_malloc (len * 2 + 1); ot_bin2hex (buf, (guint8*)csum, len); return buf; +#elif defined(HAVE_GNUTLS) + gsize len; + guint8 *csum = ot_checksum_instream_dup_digest(stream, &len); + char *buf = g_malloc0 (len * 2 + 1); + ot_bin2hex (buf, csum, len); + g_free (csum); + return buf; #else return g_strdup (g_checksum_get_string (stream->priv->checksum)); #endif From cd70aaac11c68888f56c753f8d1fda8a7895c75f Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 25 Sep 2017 18:32:07 +0100 Subject: [PATCH 40/78] lib/repo-finder-mount: Add var/lib/flatpak as a well-known directory Add this as an additional well-known directory which is checked on mounted removable drives to see if it contains OSTree repos we can pull refs from. Signed-off-by: Philip Withnall https://github.com/ostreedev/ostree/issues/1210 Closes: #1213 Approved by: cgwalters --- src/libostree/ostree-repo-finder-mount.c | 25 ++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index 9aa33834..5784b986 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -49,7 +49,8 @@ * enumerated, and all OSTree repositories below it will be searched, in lexical * order, for the requested #OstreeCollectionRefs. The names of the directories * below `.ostree/repos.d` are irrelevant, apart from their lexical ordering. - * The directory `ostree/repo` will be searched after the others, if it exists. + * The directories `.ostree/repo`, `ostree/repo` and `var/lib/flatpak` + * will be searched after the others, if they exist. * Non-removable volumes are ignored. * * For each repository which is found, a result will be returned for the @@ -413,15 +414,19 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde /* Sort the repos lexically. */ g_array_sort (repos_refs, repo_and_refs_compare); - /* Also check the .ostree/repo and ostree/repo directories in the mount, - * as well-known special cases. Add them after sorting, so they’re always - * last. */ - scan_and_add_repo (mount_root_dfd, ".ostree/repo", FALSE, - mount_name, &mount_root_stbuf, - parent_repo, repos_refs, cancellable); - scan_and_add_repo (mount_root_dfd, "ostree/repo", FALSE, - mount_name, &mount_root_stbuf, - parent_repo, repos_refs, cancellable); + /* Also check the well-known special-case directories in the mount. + * Add them after sorting, so they’re always last. */ + const gchar * const well_known_repos[] = + { + ".ostree/repo", + "ostree/repo", + "var/lib/flatpak", + }; + + for (i = 0; i < G_N_ELEMENTS (well_known_repos); i++) + scan_and_add_repo (mount_root_dfd, well_known_repos[i], FALSE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); /* Check whether a subdirectory exists for any of the @refs we’re looking * for. If so, and it’s a symbolic link, dereference it so multiple links From 3a08f7159d897533edda433ef2d98be93f02d6e0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 25 Sep 2017 20:39:53 -0400 Subject: [PATCH 41/78] lib/commit: Some misc porting to decl-after-stmnt Just happened to have this file open. Closes: #1214 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 76 ++++++++++-------------------- 1 file changed, 24 insertions(+), 52 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 2268c0ff..4f99f2dc 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2070,22 +2070,10 @@ ostree_repo_write_commit (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GDateTime *now = NULL; - - now = g_date_time_new_now_utc (); - ret = ostree_repo_write_commit_with_time (self, - parent, - subject, - body, - metadata, - root, - g_date_time_to_unix (now), - out_commit, - cancellable, - error); - g_date_time_unref (now); - return ret; + g_autoptr(GDateTime) now = g_date_time_new_now_utc (); + return ostree_repo_write_commit_with_time (self, parent, subject, body, + metadata, root, g_date_time_to_unix (now), + out_commit, cancellable, error); } /** @@ -2206,23 +2194,19 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self, GCancellable *cancellable, GError **error) { - char pathbuf[_OSTREE_LOOSE_PATH_MAX]; - g_autoptr(GVariant) normalized = NULL; - gsize normalized_size = 0; - const guint8 *data = NULL; int dest_dfd; - if (self->in_transaction) dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; - _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); - if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, checksum, cancellable, error)) return FALSE; + g_autoptr(GVariant) normalized = NULL; + gsize normalized_size = 0; + const guint8 *data = NULL; if (metadata != NULL) { normalized = g_variant_get_normal_form (metadata); @@ -2233,6 +2217,8 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self, if (data == NULL) data = (guint8*)""; + char pathbuf[_OSTREE_LOOSE_PATH_MAX]; + _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); if (!glnx_file_replace_contents_at (dest_dfd, pathbuf, data, normalized_size, 0, cancellable, error)) @@ -2250,14 +2236,11 @@ create_tree_variant_from_hashes (GHashTable *file_checksums, GHashTable *dir_metadata_checksums) { GVariantBuilder files_builder; - GVariantBuilder dirs_builder; - GSList *sorted_filenames = NULL; - GSList *iter; - GVariant *serialized_tree; - g_variant_builder_init (&files_builder, G_VARIANT_TYPE ("a(say)")); + GVariantBuilder dirs_builder; g_variant_builder_init (&dirs_builder, G_VARIANT_TYPE ("a(sayay)")); + GSList *sorted_filenames = NULL; GLNX_HASH_TABLE_FOREACH (file_checksums, const char*, name) { /* Should have been validated earlier, but be paranoid */ @@ -2265,10 +2248,8 @@ create_tree_variant_from_hashes (GHashTable *file_checksums, sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); } - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - - for (iter = sorted_filenames; iter; iter = iter->next) + for (GSList *iter = sorted_filenames; iter; iter = iter->next) { const char *name = iter->data; const char *value; @@ -2277,25 +2258,20 @@ create_tree_variant_from_hashes (GHashTable *file_checksums, g_variant_builder_add (&files_builder, "(s@ay)", name, ostree_checksum_to_bytes_v (value)); } - g_slist_free (sorted_filenames); sorted_filenames = NULL; + GLNX_HASH_TABLE_FOREACH (dir_metadata_checksums, const char*, name) sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - for (iter = sorted_filenames; iter; iter = iter->next) + for (GSList *iter = sorted_filenames; iter; iter = iter->next) { const char *name = iter->data; - const char *content_checksum; - const char *meta_checksum; + const char *content_checksum = g_hash_table_lookup (dir_contents_checksums, name); + const char *meta_checksum = g_hash_table_lookup (dir_metadata_checksums, name); - content_checksum = g_hash_table_lookup (dir_contents_checksums, name); - meta_checksum = g_hash_table_lookup (dir_metadata_checksums, name); - - g_variant_builder_add (&dirs_builder, "(s@ay@ay)", - name, + g_variant_builder_add (&dirs_builder, "(s@ay@ay)", name, ostree_checksum_to_bytes_v (content_checksum), ostree_checksum_to_bytes_v (meta_checksum)); } @@ -2303,12 +2279,11 @@ create_tree_variant_from_hashes (GHashTable *file_checksums, g_slist_free (sorted_filenames); sorted_filenames = NULL; - serialized_tree = g_variant_new ("(@a(say)@a(sayay))", - g_variant_builder_end (&files_builder), - g_variant_builder_end (&dirs_builder)); - g_variant_ref_sink (serialized_tree); - - return serialized_tree; + GVariant *serialized_tree = + g_variant_new ("(@a(say)@a(sayay))", + g_variant_builder_end (&files_builder), + g_variant_builder_end (&dirs_builder)); + return g_variant_ref_sink (serialized_tree); } /* If any filtering is set up, perform it, and return modified file info in @@ -2369,16 +2344,13 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self, static char * ptrarray_path_join (GPtrArray *path) { - GString *path_buf; - - path_buf = g_string_new (""); + GString *path_buf = g_string_new (""); if (path->len == 0) g_string_append_c (path_buf, '/'); else { - guint i; - for (i = 0; i < path->len; i++) + for (guint i = 0; i < path->len; i++) { const char *elt = path->pdata[i]; From 8a7a35970928331a028ccddd04590ac300dbd26e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Sep 2017 23:09:11 -0400 Subject: [PATCH 42/78] lib/commit: Add a copy fastpath for imports This fixes up the last of the embarassing bits I saw from the stack trace in: https://github.com/ostreedev/ostree/issues/1184 We had a hardlink fast path, but that doesn't apply across devices, which occurs in two notable cases: - Installer ISO with local repo - Tools like pungi that copy the repo to a local snapshot Obviously there are a lot of subtleties here around things like the bare-user-only conversions as well as exactly what data we copy. I think to get better test coverage we may want to add `pull-local --no-hardlink` or so. Closes: #1197 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 248 ++++++++++++++++++++--------- tests/installed/itest-pull.sh | 14 ++ 2 files changed, 190 insertions(+), 72 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 4f99f2dc..d0f3fa99 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -3156,19 +3156,15 @@ import_is_bareuser_only_conversion (OstreeRepo *src_repo, /* Returns TRUE if we can potentially just call link() to copy an object. */ static gboolean -import_via_hardlink_is_possible (OstreeRepo *src_repo, - OstreeRepo *dest_repo, - OstreeObjectType objtype) +import_via_reflink_is_possible (OstreeRepo *src_repo, + OstreeRepo *dest_repo, + OstreeObjectType objtype) { - /* hardlinks require the owner to match and to be on the same device */ - if (!(src_repo->owner_uid == dest_repo->owner_uid && - src_repo->device == dest_repo->device)) - return FALSE; - /* Equal modes are always compatible */ - if (src_repo->mode == dest_repo->mode) - return TRUE; - /* Metadata is identical between all modes */ - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) + /* Equal modes are always compatible, and metadata + * is identical between all modes. + */ + if (src_repo->mode == dest_repo->mode || + OSTREE_OBJECT_TYPE_IS_META (objtype)) return TRUE; /* And now a special case between bare-user and bare-user-only, * mostly for https://github.com/flatpak/flatpak/issues/845 @@ -3205,76 +3201,155 @@ copy_detached_metadata (OstreeRepo *self, return TRUE; } -/* Try to import an object by just calling linkat(); returns - * a value in @out_was_supported if we were able to do it or not. +/* Try to import an object via reflink or just linkat(); returns a value in + * @out_was_supported if we were able to do it or not. In this path + * we're not verifying the checksum. */ static gboolean -import_one_object_link (OstreeRepo *self, - OstreeRepo *source, - const char *checksum, - OstreeObjectType objtype, - gboolean *out_was_supported, - GCancellable *cancellable, - GError **error) +import_one_object_direct (OstreeRepo *dest_repo, + OstreeRepo *src_repo, + const char *checksum, + OstreeObjectType objtype, + gboolean *out_was_supported, + GCancellable *cancellable, + GError **error) { const char *errprefix = glnx_strjoina ("Importing ", checksum, ".", ostree_object_type_to_string (objtype)); GLNX_AUTO_PREFIX_ERROR (errprefix, error); char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode); + _ostree_loose_path (loose_path_buf, checksum, objtype, dest_repo->mode); - /* Hardlinking between bare-user → bare-user-only is only possible for regular - * files, *not* symlinks, which in bare-user are stored as regular files. At - * this point we need to parse the file to see the difference. + if (!import_via_reflink_is_possible (src_repo, dest_repo, objtype)) + { + /* If we can't reflink, nothing to do here */ + *out_was_supported = FALSE; + return TRUE; + } + + /* hardlinks require the owner to match and to be on the same device */ + const gboolean can_hardlink = + src_repo->owner_uid == dest_repo->owner_uid && + src_repo->device == dest_repo->device; + + /* Find our target dfd */ + int dest_dfd; + if (dest_repo->commit_stagedir.initialized) + dest_dfd = dest_repo->commit_stagedir.fd; + else + dest_dfd = dest_repo->objects_dir_fd; + + if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, loose_path_buf, cancellable, error)) + return FALSE; + + gboolean did_hardlink = FALSE; + if (can_hardlink) + { + if (linkat (src_repo->objects_dir_fd, loose_path_buf, dest_dfd, loose_path_buf, 0) != 0) + { + if (errno == EEXIST) + return TRUE; + else if (errno == EMLINK || errno == EXDEV || errno == EPERM) + { + /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do + * the optimization of hardlinking instead of copying. Fall + * through below. + */ + } + else + return glnx_throw_errno_prefix (error, "linkat"); + } + else + did_hardlink = TRUE; + } + + /* If we weren't able to hardlink, fall back to a copy (which might be + * reflinked). */ - if (import_is_bareuser_only_conversion (source, self, objtype)) + if (!did_hardlink) { struct stat stbuf; - if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf, - NULL, NULL, cancellable, error)) + if (!glnx_fstatat (src_repo->objects_dir_fd, loose_path_buf, + &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - if (S_ISREG (stbuf.st_mode)) + /* Let's punt for symlinks right now, it's more complicated */ + if (!S_ISREG (stbuf.st_mode)) { - /* This is OK, we'll drop through and try a hardlink */ - } - else if (S_ISLNK (stbuf.st_mode)) - { - /* NOTE early return */ *out_was_supported = FALSE; return TRUE; } - else - g_assert_not_reached (); - } - if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error)) - return FALSE; + /* This is yet another variation of glnx_file_copy_at() + * that basically just optionally does chown(). Perhaps + * in the future we should add flags for those things? + */ + glnx_fd_close int src_fd = -1; + if (!glnx_openat_rdonly (src_repo->objects_dir_fd, loose_path_buf, + FALSE, &src_fd, error)) + return FALSE; - *out_was_supported = TRUE; - if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0) - { - if (errno == EEXIST) - return TRUE; - else if (errno == EMLINK || errno == EXDEV || errno == EPERM) + /* Open a tmpfile for dest */ + g_auto(GLnxTmpfile) tmp_dest = { 0, }; + if (!glnx_open_tmpfile_linkable_at (dest_dfd, ".", O_WRONLY | O_CLOEXEC, + &tmp_dest, error)) + return FALSE; + + if (glnx_regfile_copy_bytes (src_fd, tmp_dest.fd, (off_t) -1) < 0) + return glnx_throw_errno_prefix (error, "regfile copy"); + + /* Only chown for true bare repos */ + if (dest_repo->mode == OSTREE_REPO_MODE_BARE) { - /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the - * optimization of hardlinking instead of copying. - */ - *out_was_supported = FALSE; - return TRUE; + if (fchown (tmp_dest.fd, stbuf.st_uid, stbuf.st_gid) != 0) + return glnx_throw_errno_prefix (error, "fchown"); } - else - return glnx_throw_errno_prefix (error, "linkat"); + + /* Don't want to copy xattrs for archive repos, nor for + * bare-user-only. + */ + const gboolean src_is_bare_or_bare_user = + G_IN_SET (src_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER); + if (src_is_bare_or_bare_user) + { + g_autoptr(GVariant) xattrs = NULL; + + if (!glnx_fd_get_all_xattrs (src_fd, &xattrs, + cancellable, error)) + return FALSE; + + if (!glnx_fd_set_all_xattrs (tmp_dest.fd, xattrs, + cancellable, error)) + return FALSE; + } + + if (fchmod (tmp_dest.fd, stbuf.st_mode & ~S_IFMT) != 0) + return glnx_throw_errno_prefix (error, "fchmod"); + + /* For archive repos, we just let the timestamps be object creation. + * Otherwise, copy the ostree timestamp value. + */ + if (_ostree_repo_mode_is_bare (dest_repo->mode)) + { + struct timespec ts[2]; + ts[0] = stbuf.st_atim; + ts[1] = stbuf.st_mtim; + (void) futimens (tmp_dest.fd, ts); + } + + if (!_ostree_repo_commit_tmpf_final (dest_repo, checksum, objtype, + &tmp_dest, cancellable, error)) + return FALSE; } if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { - if (!copy_detached_metadata (self, source, checksum, cancellable, error)) + if (!copy_detached_metadata (dest_repo, src_repo, checksum, cancellable, error)) return FALSE; } + *out_was_supported = TRUE; return TRUE; } @@ -3293,11 +3368,18 @@ _ostree_repo_import_object (OstreeRepo *self, const gboolean trusted = (flags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0; /* Implements OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES which was designed for flatpak */ const gboolean verify_bareuseronly = (flags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; - - /* If we need to do bareuseronly verification, let's dispense with that - * first so we don't complicate the rest of the code below. + /* A special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 */ - if (verify_bareuseronly && !OSTREE_OBJECT_TYPE_IS_META (objtype)) + const gboolean is_bareuseronly_conversion = + import_is_bareuser_only_conversion (source, self, objtype); + gboolean try_direct = trusted; + + /* If we need to do bareuseronly verification, or we're potentially doing a + * bareuseronly conversion, let's verify those first so we don't complicate + * the rest of the code below. + */ + if ((verify_bareuseronly || is_bareuseronly_conversion) && !OSTREE_OBJECT_TYPE_IS_META (objtype)) { g_autoptr(GFileInfo) src_finfo = NULL; if (!ostree_repo_load_file (source, checksum, @@ -3305,30 +3387,52 @@ _ostree_repo_import_object (OstreeRepo *self, cancellable, error)) return FALSE; - if (!_ostree_validate_bareuseronly_mode_finfo (src_finfo, checksum, error)) - return FALSE; + if (verify_bareuseronly) + { + if (!_ostree_validate_bareuseronly_mode_finfo (src_finfo, checksum, error)) + return FALSE; + } + + if (is_bareuseronly_conversion) + { + switch (g_file_info_get_file_type (src_finfo)) + { + case G_FILE_TYPE_REGULAR: + /* This is OK, we'll try a hardlink */ + break; + case G_FILE_TYPE_SYMBOLIC_LINK: + /* Symlinks in bare-user are regular files, we can't + * hardlink them to another repo mode. + */ + try_direct = FALSE; + break; + default: + g_assert_not_reached (); + break; + } + } } - /* We try to import via hardlink. If the remote is explicitly not trusted - * (i.e.) their checksums may be incorrect, we skip that. Also, we require the - * repository modes to match, as well as the owner uid (since we need to be - * able to make hardlinks). + /* We try to import via reflink/hardlink. If the remote is explicitly not trusted + * (i.e.) their checksums may be incorrect, we skip that. */ - if (trusted && import_via_hardlink_is_possible (source, self, objtype)) + if (try_direct) { - gboolean hardlink_was_supported = FALSE; - - if (!import_one_object_link (self, source, checksum, objtype, - &hardlink_was_supported, - cancellable, error)) + gboolean direct_was_supported = FALSE; + if (!import_one_object_direct (self, source, checksum, objtype, + &direct_was_supported, + cancellable, error)) return FALSE; - /* If we hardlinked, we're done! */ - if (hardlink_was_supported) + /* If direct import succeeded, we're done! */ + if (direct_was_supported) return TRUE; } - /* The copy path */ + /* The more expensive copy path; involves parsing the object. For + * example the input might be an archive repo and the destination bare, + * or vice versa. Or we may simply need to verify the checksum. + */ /* First, do we have the object already? */ gboolean has_object; diff --git a/tests/installed/itest-pull.sh b/tests/installed/itest-pull.sh index e3125f4c..65cb9449 100755 --- a/tests/installed/itest-pull.sh +++ b/tests/installed/itest-pull.sh @@ -25,3 +25,17 @@ run_tmp_webserver $(pwd)/repo ostree --repo=bare-repo init --mode=bare-user ostree --repo=bare-repo remote add origin --set=gpg-verify=false $(cat ${test_tmpdir}/httpd-address) ostree --repo=bare-repo pull --disable-static-deltas origin ${host_nonremoteref} + +rm bare-repo repo -rf + +# Try copying the host's repo across a mountpoint for direct +# imports. +cd ${test_tmpdir} +mkdir tmpfs mnt +mount --bind tmpfs mnt +cd mnt +ostree --repo=repo init --mode=bare +ostree --repo=repo pull-local /ostree/repo ${host_commit} +ostree --repo=repo fsck +cd .. +umount mnt From e5c86fad5c03a21b6972c3d1a458d89f74cbbf21 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 13 Sep 2017 16:05:47 +0000 Subject: [PATCH 43/78] lib/commit: add comments to explain dir commit path Add a few comments for each of the central functions used for committing data from a directory. Took me a bit to understand the relationship between those functions. Closes: #1216 Approved by: cgwalters --- src/libostree/ostree-repo-commit.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index d0f3fa99..fb927605 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2480,6 +2480,10 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error); +/* Given either a dir_enum or a dfd_iter, writes the directory entry to the mtree. For + * subdirs, we go back through either write_dfd_iter_to_mtree_internal (dfd_iter case) or + * write_directory_to_mtree_internal (dir_enum case) which will do the actual dirmeta + + * dirent iteration. */ static gboolean write_directory_content_to_mtree_internal (OstreeRepo *self, OstreeRepoFile *repo_dir, @@ -2632,6 +2636,8 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, return TRUE; } +/* Handles the dirmeta for the given GFile dir and then calls + * write_directory_content_to_mtree_internal() for each directory entry. */ static gboolean write_directory_to_mtree_internal (OstreeRepo *self, GFile *dir, @@ -2729,6 +2735,8 @@ write_directory_to_mtree_internal (OstreeRepo *self, return TRUE; } +/* Handles the dirmeta for the dir described by src_dfd_iter and then calls + * write_directory_content_to_mtree_internal() for each directory entry. */ static gboolean write_dfd_iter_to_mtree_internal (OstreeRepo *self, GLnxDirFdIterator *src_dfd_iter, From e44631ecc36c55b071c86dbf6a93928453853b0b Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 13 Sep 2017 16:17:17 +0000 Subject: [PATCH 44/78] lib/commit: fix using uninitialized var Noticed this while reading the code. The `child` var hasn't been initialized yet at the time we throw this error (and even then, it's only conditionally initialized). To be nice, let's just always calculate the child path and pass that along. Also do some minor style porting to decl near use. Closes: #1216 Approved by: cgwalters --- src/libostree/ostree-repo-commit.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index fb927605..df5c92cd 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2496,23 +2496,16 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(GFile) child = NULL; - g_autoptr(GFileInfo) modified_info = NULL; - g_autoptr(OstreeMutableTree) child_mtree = NULL; - g_autofree char *child_relpath = NULL; - const char *name; - GFileType file_type; - OstreeRepoCommitFilterResult filter_result; - g_assert (dir_enum != NULL || dfd_iter != NULL); - name = g_file_info_get_name (child_info); + const char *name = g_file_info_get_name (child_info); g_ptr_array_add (path, (char*)name); - if (modifier != NULL) - child_relpath = ptrarray_path_join (path); + g_autofree char *child_relpath = ptrarray_path_join (path); - filter_result = _ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info); + g_autoptr(GFileInfo) modified_info = NULL; + OstreeRepoCommitFilterResult filter_result = + _ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info); if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW) { @@ -2521,7 +2514,7 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, return TRUE; } - file_type = g_file_info_get_file_type (child_info); + GFileType file_type = g_file_info_get_file_type (child_info); switch (file_type) { case G_FILE_TYPE_DIRECTORY: @@ -2529,15 +2522,16 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, case G_FILE_TYPE_REGULAR: break; default: - return glnx_throw (error, "Unsupported file type: '%s'", - gs_file_get_path_cached (child)); + return glnx_throw (error, "Unsupported file type for file: '%s'", child_relpath); } + g_autoptr(GFile) child = NULL; if (dir_enum != NULL) child = g_file_enumerator_get_child (dir_enum, child_info); if (file_type == G_FILE_TYPE_DIRECTORY) { + g_autoptr(OstreeMutableTree) child_mtree = NULL; if (!ostree_mutable_tree_ensure_dir (mtree, name, &child_mtree, error)) return FALSE; From d0d27288da60aa01ac708ea59b2d3163cb0793c5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 13:07:53 -0400 Subject: [PATCH 45/78] bin/pull: Fix description of --untrusted It means *do* verify for local. Closes: #1212 Approved by: jlebon --- src/ostree/ot-builtin-pull-local.c | 2 +- src/ostree/ot-builtin-pull.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index d80c5a25..c3dc50c9 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -46,7 +46,7 @@ static int opt_depth = 0; static GOptionEntry options[] = { { "remote", 0, 0, G_OPTION_ARG_STRING, &opt_remote, "Add REMOTE to refspec", "REMOTE" }, { "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, - { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL }, { "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", NULL }, { "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL }, { "gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_gpg_verify, "GPG verify commits (must specify --remote)", NULL }, diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index 47f9d8be..a6fab0e3 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -56,7 +56,7 @@ static GOptionEntry options[] = { { "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL }, { "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror and fetches all refs if none provided", NULL }, { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only pull the provided subpath(s)", NULL }, - { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL }, { "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", NULL }, { "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL }, { "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" }, From 72ddd4f4198ead6237bcdb0f58d2d43e160e1cb2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 23 Sep 2017 09:44:49 -0400 Subject: [PATCH 46/78] lib/pull: Minor refactoring of metadata scanning function Make the "local repo" processing conditional the same as the "localcache" bits; this is really just a de-indent. Also add some comments. Prep for further work. Closes: #1212 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 33 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index d8048e75..bb34f2f6 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1749,35 +1749,36 @@ scan_one_metadata_object_c (OtPullData *pull_data, g_autofree char *tmp_checksum = ostree_checksum_from_bytes (csum); g_autoptr(GVariant) object = ostree_object_name_serialize (tmp_checksum, objtype); + /* It may happen that we've already looked at this object (think shared + * dirtree subtrees), if that's the case, we're done */ if (g_hash_table_lookup (pull_data->scanned_metadata, object)) return TRUE; gboolean is_requested = g_hash_table_lookup (pull_data->requested_metadata, object) != NULL; + /* Determine if we already have the object */ gboolean is_stored; if (!ostree_repo_has_object (pull_data->repo, objtype, tmp_checksum, &is_stored, cancellable, error)) return FALSE; - if (pull_data->remote_repo_local) + /* Are we pulling an object we don't have from a local repo? */ + if (!is_stored && pull_data->remote_repo_local) { - if (!is_stored) + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - /* mark as partial to ensure we scan the commit below */ - if (!write_commitpartial_for (pull_data, tmp_checksum, error)) - return FALSE; - } - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, - objtype, tmp_checksum, !pull_data->is_untrusted, - cancellable, error)) + /* mark as partial to ensure we scan the commit below */ + if (!write_commitpartial_for (pull_data, tmp_checksum, error)) return FALSE; - /* The import API will fetch both the commit and detached metadata, so - * add it to the hash to avoid re-fetching it below. - */ - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); } + if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, + objtype, tmp_checksum, !pull_data->is_untrusted, + cancellable, error)) + return FALSE; + /* The import API will fetch both the commit and detached metadata, so + * add it to the hash to avoid re-fetching it below. + */ + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); is_stored = TRUE; is_requested = TRUE; } From b6507a930e2604602f9911794c54dc7ba48832a3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 23 Sep 2017 09:59:53 -0400 Subject: [PATCH 47/78] lib/pull: Refactor to use OstreeRepoImportFlags internally Rather than carrying two booleans, just convert `OstreeRepoPullFlags` into `OstreeRepoImportFlags`. This allows us to drop an internal wrapper function and just directly call `_ostree_repo_import_object()`. This though reveals that our mirroring import path doesn't check the `OSTREE_REPO_PULL_FLAGS_UNTRUSTED` flag...it probably should. Prep for further work. Closes: #1212 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 80 +++++++++++++++----------------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index bb34f2f6..91cad430 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -142,8 +142,7 @@ typedef struct { gboolean is_mirror; gboolean is_commit_only; - gboolean is_untrusted; - gboolean is_bareuseronly_files; + OstreeRepoImportFlags importflags; GPtrArray *dirs; @@ -622,36 +621,15 @@ pull_matches_subdir (OtPullData *pull_data, return FALSE; } -/* Synchronously import a single content object; this is used async for content, - * or synchronously for metadata. @src_repo is either - * pull_data->remote_repo_local or one of pull_data->localcache_repos. - * - * One important special case here is handling the - * OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES flag. - */ -static gboolean -import_one_local_content_object_sync (OtPullData *pull_data, - OstreeRepo *src_repo, - const char *checksum, - GCancellable *cancellable, - GError **error) -{ - OstreeRepoImportFlags flags = _OSTREE_REPO_IMPORT_FLAGS_NONE; - if (!pull_data->is_untrusted) - flags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; - if (pull_data->is_bareuseronly_files) - flags |= _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY; - return _ostree_repo_import_object (pull_data->repo, src_repo, - OSTREE_OBJECT_TYPE_FILE, checksum, - flags, cancellable, error); -} - typedef struct { OtPullData *pull_data; OstreeRepo *src_repo; char checksum[OSTREE_SHA256_STRING_LEN+1]; } ImportLocalAsyncData; +/* Asynchronously import a single content object. @src_repo is either + * pull_data->remote_repo_local or one of pull_data->localcache_repos. + */ static void async_import_in_thread (GTask *task, gpointer source, @@ -659,12 +637,12 @@ async_import_in_thread (GTask *task, GCancellable *cancellable) { ImportLocalAsyncData *iataskdata = task_data; + OtPullData *pull_data = iataskdata->pull_data; g_autoptr(GError) local_error = NULL; - if (!import_one_local_content_object_sync (iataskdata->pull_data, - iataskdata->src_repo, - iataskdata->checksum, - cancellable, - &local_error)) + /* pull_data->importflags was set up in the pull option processing */ + if (!_ostree_repo_import_object (pull_data->repo, iataskdata->src_repo, + OSTREE_OBJECT_TYPE_FILE, iataskdata->checksum, + pull_data->importflags, cancellable, &local_error)) g_task_return_error (task, g_steal_pointer (&local_error)); else g_task_return_boolean (task, TRUE); @@ -1025,12 +1003,15 @@ content_fetch_on_complete (GObject *object, checksum_obj = ostree_object_to_string (checksum, objtype); g_debug ("fetch of %s complete", checksum_obj); + const gboolean verifying_bareuseronly = + (pull_data->importflags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; + /* If we're mirroring and writing into an archive repo, we can directly copy * the content rather than paying the cost of exploding it, checksumming, and * re-gzip. */ if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE - && !pull_data->is_bareuseronly_files) + && !verifying_bareuseronly) { gboolean have_object; if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, checksum, @@ -1064,7 +1045,7 @@ content_fetch_on_complete (GObject *object, */ ot_cleanup_unlinkat (&tmp_unlinker); - if (pull_data->is_bareuseronly_files) + if (verifying_bareuseronly) { if (!_ostree_validate_bareuseronly_mode_finfo (file_info, checksum, error)) goto out; @@ -1770,9 +1751,10 @@ scan_one_metadata_object_c (OtPullData *pull_data, if (!write_commitpartial_for (pull_data, tmp_checksum, error)) return FALSE; } - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, - objtype, tmp_checksum, !pull_data->is_untrusted, - cancellable, error)) + + if (!_ostree_repo_import_object (pull_data->repo, pull_data->remote_repo_local, + objtype, tmp_checksum, pull_data->importflags, + cancellable, error)) return FALSE; /* The import API will fetch both the commit and detached metadata, so * add it to the hash to avoid re-fetching it below. @@ -1801,10 +1783,9 @@ scan_one_metadata_object_c (OtPullData *pull_data, if (!write_commitpartial_for (pull_data, tmp_checksum, error)) return FALSE; } - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, refd_repo, - objtype, tmp_checksum, - !pull_data->is_untrusted, - cancellable, error)) + if (!_ostree_repo_import_object (pull_data->repo, refd_repo, + objtype, tmp_checksum, pull_data->importflags, + cancellable, error)) return FALSE; /* See comment above */ if (objtype == OSTREE_OBJECT_TYPE_COMMIT) @@ -3250,8 +3231,9 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->is_mirror = (flags & OSTREE_REPO_PULL_FLAGS_MIRROR) > 0; pull_data->is_commit_only = (flags & OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY) > 0; - pull_data->is_untrusted = (flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) > 0; - pull_data->is_bareuseronly_files = (flags & OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES) > 0; + /* See our processing of OSTREE_REPO_PULL_FLAGS_UNTRUSTED below */ + if ((flags & OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES) > 0) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY; pull_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; if (error) @@ -3540,6 +3522,9 @@ ostree_repo_pull_with_options (OstreeRepo *self, } } + /* Change some option defaults if we're actually pulling from a local + * (filesystem accessible) repo. + */ if (pull_data->remote_repo_local) { /* For local pulls, default to disabling static deltas so that the @@ -3548,6 +3533,17 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (!pull_data->require_static_deltas) pull_data->disable_static_deltas = TRUE; + /* Note the inversion here; PULL_FLAGS_UNTRUSTED is converted to + * IMPORT_FLAGS_TRUSTED only if it's unset (and just for local repos). + */ + if ((flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) == 0) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; + } + else + { + /* We don't add _IMPORT_FLAGS_TRUSTED for http repos; + * OSTREE_REPO_PULL_FLAGS_UNTRUSTED only matters for local repos. + */ } /* We can't use static deltas if pulling into an archive repo. */ From 25a7c4bd4e8aeaf68689fcd2ddc2f907f2f76f1f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 23 Sep 2017 10:23:47 -0400 Subject: [PATCH 48/78] lib/pull: Default checksum for archive mirror, add TRUSTED_HTTP flag I now think commit fab1e113db558cb7d6754e243919558df92d4864 was a mistake; because it breaks the mental model that at least I'd built up that "local repos don't have checksums verified, HTTP does". For example, a problem with this is (with that mental model in place) it's easy for people who set up mirrors like this to then do local pulls, and at that point we've done a deployment with no checksum verification. Further, since then we did PR #671 AKA commit 3d38f03 which is really most of the speed hit. So let's switch the default even for this case to doing checksum verification, and add `ostree pull --http-trusted`. People who are in situations where they know they want this can find it and turn it on. Closes: https://github.com/ostreedev/ostree/issues/1211 Closes: #1212 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 21 +++++++---- src/libostree/ostree-repo.h | 6 ++-- src/ostree/ot-builtin-pull.c | 10 +++++- tests/pull-test.sh | 61 ++++++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 91cad430..cd5fe520 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1006,12 +1006,15 @@ content_fetch_on_complete (GObject *object, const gboolean verifying_bareuseronly = (pull_data->importflags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; - /* If we're mirroring and writing into an archive repo, we can directly copy - * the content rather than paying the cost of exploding it, checksumming, and - * re-gzip. + /* If we're mirroring and writing into an archive repo, and both checksum and + * bareuseronly are turned off, we can directly copy the content rather than + * paying the cost of exploding it, checksumming, and re-gzip. */ - if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE - && !verifying_bareuseronly) + const gboolean mirroring_into_archive = + pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE; + const gboolean import_trusted = !verifying_bareuseronly && + (pull_data->importflags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0; + if (mirroring_into_archive && import_trusted) { gboolean have_object; if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, checksum, @@ -3541,9 +3544,13 @@ ostree_repo_pull_with_options (OstreeRepo *self, } else { - /* We don't add _IMPORT_FLAGS_TRUSTED for http repos; - * OSTREE_REPO_PULL_FLAGS_UNTRUSTED only matters for local repos. + /* For non-local repos, we require the TRUSTED_HTTP pull flag to map to + * the TRUSTED object import flag. In practice we don't do object imports + * for HTTP, but it's easiest to use one set of flags between HTTP and + * local imports. */ + if (flags & OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; } /* We can't use static deltas if pulling into an archive repo. */ diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 1ba71c12..51b44b3f 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1126,15 +1126,17 @@ gboolean ostree_repo_prune_from_reachable (OstreeRepo *self, * @OSTREE_REPO_PULL_FLAGS_NONE: No special options for pull * @OSTREE_REPO_PULL_FLAGS_MIRROR: Write out refs suitable for mirrors and fetch all refs if none requested * @OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY: Fetch only the commit metadata - * @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Don't trust local remote + * @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Do verify checksums of local (filesystem-accessible) repositories (defaults on for HTTP) * @OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES: Since 2017.7. Reject writes of content objects with modes outside of 0775. + * @OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP: Don't verify checksums of objects HTTP repositories (Since: 2017.12) */ typedef enum { OSTREE_REPO_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_MIRROR = (1 << 0), OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1), OSTREE_REPO_PULL_FLAGS_UNTRUSTED = (1 << 2), - OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES = (1 << 3) + OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES = (1 << 3), + OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP = (1 << 4), } OstreeRepoPullFlags; _OSTREE_PUBLIC diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index a6fab0e3..e67d5993 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -33,6 +33,7 @@ static gboolean opt_dry_run; static gboolean opt_disable_static_deltas; static gboolean opt_require_static_deltas; static gboolean opt_untrusted; +static gboolean opt_http_trusted; static gboolean opt_timestamp_check; static gboolean opt_bareuseronly_files; static char** opt_subpaths; @@ -57,6 +58,7 @@ static GOptionEntry options[] = { { "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror and fetches all refs if none provided", NULL }, { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only pull the provided subpath(s)", NULL }, { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "http-trusted", 0, 0, G_OPTION_ARG_NONE, &opt_http_trusted, "Do not verify checksums of HTTP sources (mostly useful when mirroring)", NULL }, { "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", NULL }, { "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL }, { "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" }, @@ -182,8 +184,14 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError ** if (opt_commit_only) pullflags |= OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY; + if (opt_http_trusted) + pullflags |= OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP; if (opt_untrusted) - pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; + { + pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; + /* If the user specifies both, assume they really mean untrusted */ + pullflags &= ~OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP; + } if (opt_bareuseronly_files) pullflags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES; diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 3780d1ad..573f8360 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -35,7 +35,7 @@ function verify_initial_contents() { assert_file_has_content baz/cow '^moo$' } -echo "1..29" +echo "1..30" # Try both syntaxes repo_init --no-gpg-verify @@ -137,6 +137,63 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo prune --refs-only ${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror --bareuseronly-files origin main echo "ok pull (bareuseronly mirror)" +# Corruption tests +cd ${test_tmpdir} +repo_init --no-gpg-verify +if ! is_bare_user_only_repo repo && ! skip_one_without_user_xattrs; then + if is_bare_user_only_repo repo; then + cacherepomode=bare-user-only + else + cacherepomode=bare-user + fi + rm cacherepo -rf + ostree_repo_init cacherepo --mode=${cacherepomode} + ${CMD_PREFIX} ostree --repo=cacherepo pull-local ostree-srv/gnomerepo main + rev=$(ostree --repo=cacherepo rev-parse main) + ${CMD_PREFIX} ostree --repo=cacherepo ls -R -C main > ls.txt + regfile_hash=$(grep -E -e '^-0' ls.txt | head -1 | awk '{ print $5 }') + ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false corruptrepo $(cat httpd-address)/ostree/corruptrepo + # Make this a loop so in the future we can add more object types like commit etc. + for object in ${regfile_hash}.file; do + checksum=$(echo ${object} | sed -e 's,\(.*\)\.[a-z]*$,\1,') + path=cacherepo/objects/${object:0:2}/${object:2} + # Preserve user.ostreemeta xattr + cp -a ${path}{,.new} + (dd if=${path} conv=swab) > ${path}.new + mv ${path}{.new,} + if ${CMD_PREFIX} ostree --repo=cacherepo fsck 2>err.txt; then + fatal "corrupt repo fsck?" + fi + assert_file_has_content err.txt "corrupted.*${checksum}" + rm ostree-srv/corruptrepo -rf + ostree_repo_init ostree-srv/corruptrepo --mode=archive + ${CMD_PREFIX} ostree --repo=ostree-srv/corruptrepo pull-local cacherepo main + # Pulling via HTTP into a non-archive should fail, even with + # --http-trusted. + if ${CMD_PREFIX} ostree --repo=repo pull --http-trusted corruptrepo main 2>err.txt; then + fatal "Pulled from corrupt repo?" + fi + assert_file_has_content err.txt "Corrupted.*${checksum}" + if ${CMD_PREFIX} ostree --repo=repo show corruptrepo:main >/dev/null; then + fatal "Pulled from corrupt repo?" + fi + ${CMD_PREFIX} ostree --repo=repo prune --refs-only + rm repo/tmp/* -rf + ostree_repo_init corruptmirrorrepo --mode=archive + # Pulling via http-trusted should not verify the checksum + ${CMD_PREFIX} ostree --repo=corruptmirrorrepo remote add --set=gpg-verify=false corruptrepo $(cat httpd-address)/ostree/corruptrepo + ${CMD_PREFIX} ostree --repo=corruptmirrorrepo pull --mirror --http-trusted corruptrepo main + # But it should fail to fsck + if ${CMD_PREFIX} ostree --repo=corruptmirrorrepo fsck 2>err.txt; then + fatal "corrupt mirror repo fsck?" + fi + done + + # And ensure the repo is reinitialized + repo_init --no-gpg-verify + echo "ok corruption" +fi + cd ${test_tmpdir} rm mirrorrepo/refs/remotes/* -rf ${CMD_PREFIX} ostree --repo=mirrorrepo prune --refs-only @@ -158,7 +215,7 @@ ostree_repo_init mirrorrepo-local --mode=archive ${CMD_PREFIX} ostree --repo=mirrorrepo-local remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo ${CMD_PREFIX} ostree --repo=mirrorrepo-local pull --mirror origin main ${CMD_PREFIX} ostree --repo=mirrorrepo-local fsck -$OSTREE show main >/dev/null +${CMD_PREFIX} ostree --repo=mirrorrepo show main >/dev/null echo "ok pull local mirror" cd ${test_tmpdir} From 5963d5a2a95b0aea7d306fc4ed5967b3e6ac4d83 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 12:41:07 -0400 Subject: [PATCH 49/78] tests,ci: Move "test-basic" (bare mode) to installed test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our CI uses default Docker, which has SELinux labeling but is rather evil in returning `EOPNOTSUPP` to any attempts to set `security.selinux`, even if to the same value. The previous fire 🔥 for this was: https://github.com/ostreedev/ostree/pull/759 The `bare` repo mode really only makes sense as uid 0, so our installed test framework is a good match for this. However, the unit tests *do* work in a privileged container even as non-root, and *also* should work on SELinux-disabled systems. So let's teach the test framework how to skip in those situations. I tested this both in a priv container (my default builder) and an unpriv container (like our CI). At the same time, start executing the `test-basic.sh` from an installed test, so we get better coverage than before. This is just the start - all of the sysroot tests really need the same treatment. Closes: #1217 Approved by: jlebon --- .papr.yml | 2 +- tests/basic-test.sh | 6 +----- tests/installed/fah-prep.sh | 2 ++ tests/installed/itest-bare-unit.sh | 25 +++++++++++++++++++++++++ tests/libtest.sh | 24 ++++++++++++++++++++++++ tests/test-basic-user-only.sh | 6 +++++- tests/test-basic.sh | 3 ++- 7 files changed, 60 insertions(+), 8 deletions(-) create mode 100755 tests/installed/itest-bare-unit.sh diff --git a/.papr.yml b/.papr.yml index 03489142..9a253431 100644 --- a/.papr.yml +++ b/.papr.yml @@ -153,7 +153,7 @@ tests: - make install DESTDIR=$(pwd)/insttree - yum -y install rsync - rsync -rl -e 'ssh -o User=root' . vmcheck:ostree/ - - ssh root@vmcheck './ostree/tests/installed/fah-prep.sh && ostree admin unlock && rsync -rlv ./ostree/insttree/usr/ /usr/ && ./ostree/tests/installed/run.sh' + - ssh root@vmcheck './ostree/tests/installed/fah-prep.sh && ./ostree/tests/installed/run.sh' --- diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 742b1ada..482f6979 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,11 +19,7 @@ set -euo pipefail -echo "1..$((73 + ${extra_basic_tests:-0}))" - -$CMD_PREFIX ostree --version > version.yaml -python -c 'import yaml; yaml.safe_load(open("version.yaml"))' -echo "ok yaml version" +echo "1..$((72 + ${extra_basic_tests:-0}))" CHECKOUT_U_ARG="" CHECKOUT_H_ARGS="-H" diff --git a/tests/installed/fah-prep.sh b/tests/installed/fah-prep.sh index 0db4d15e..865fa4f1 100755 --- a/tests/installed/fah-prep.sh +++ b/tests/installed/fah-prep.sh @@ -6,3 +6,5 @@ if lvm lvs atomicos/docker-pool &>/dev/null; then lvm lvremove -f atomicos/docker-pool fi lvm lvextend -r -l +100%FREE atomicos/root +ostree admin unlock +rsync -rlv ./ostree/insttree/usr/ /usr/ diff --git a/tests/installed/itest-bare-unit.sh b/tests/installed/itest-bare-unit.sh new file mode 100755 index 00000000..c763faf7 --- /dev/null +++ b/tests/installed/itest-bare-unit.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Run test-basic.sh as root. +# https://github.com/ostreedev/ostree/pull/1199 + +set -xeuo pipefail + +dn=$(dirname $0) +. ${dn}/libinsttest.sh + +# Use /var/tmp to hopefully use XFS + O_TMPFILE etc. +tempdir=$(mktemp -d /var/tmp/tap-test.XXXXXX) +touch ${tempdir}/.testtmp +function cleanup () { + if test -f ${tempdir}/.testtmp; then + rm "${tempdir}" -rf + fi +} +trap cleanup EXIT +cd ${tempdir} +# This sort of bypasses the installed-tests spec; +# fixing that would require installing g-d-t-r, though +# more ideally we architect things with a "control" container +# distinct from the host. +/usr/libexec/installed-tests/libostree/test-basic.sh diff --git a/tests/libtest.sh b/tests/libtest.sh index 9bfc199f..ed6cc43d 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -546,6 +546,30 @@ skip_without_user_xattrs () { fi } +# Skip unless SELinux is disabled, or we can relabel. +# Default Docker has security.selinux xattrs, but returns +# EOPNOTSUPP when trying to set them, even to the existing value. +# https://github.com/ostreedev/ostree/pull/759 +# https://github.com/ostreedev/ostree/pull/1217 +skip_without_no_selinux_or_relabel () { + cd ${test_tmpdir} + echo testlabel > testlabel.txt + selinux_xattr=security.selinux + if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then + label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,") + if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then + echo "SELinux enabled in $(pwd), and have privileges to relabel" + return 0 + else + sed -e 's/^/# /' < err.txt >&2 + skip "Found SELinux label, but unable to set (Unprivileged Docker?)" + fi + else + sed -e 's/^/# /' < err.txt >&2 + skip "Unable to retrieve SELinux label, assuming disabled" + fi +} + # https://brokenpi.pe/tools/strace-fault-injection _have_strace_fault_injection='' have_strace_fault_injection() { diff --git a/tests/test-basic-user-only.sh b/tests/test-basic-user-only.sh index 19262b7b..6a2ca25f 100755 --- a/tests/test-basic-user-only.sh +++ b/tests/test-basic-user-only.sh @@ -22,9 +22,13 @@ set -euo pipefail . $(dirname $0)/libtest.sh setup_test_repository "bare-user-only" -extra_basic_tests=4 +extra_basic_tests=5 . $(dirname $0)/basic-test.sh +$CMD_PREFIX ostree --version > version.yaml +python -c 'import yaml; yaml.safe_load(open("version.yaml"))' +echo "ok yaml version" + # Reset things so we don't inherit a lot of state from earlier tests cd ${test_tmpdir} rm repo files -rf diff --git a/tests/test-basic.sh b/tests/test-basic.sh index d1afe75f..eaccc2f0 100755 --- a/tests/test-basic.sh +++ b/tests/test-basic.sh @@ -21,6 +21,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -setup_test_repository "bare" +skip_without_no_selinux_or_relabel +setup_test_repository "bare" . $(dirname $0)/basic-test.sh From f923c2e1eaebe0c781f07d34ae1a03f94357bccd Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 18 Sep 2017 14:01:21 +0100 Subject: [PATCH 50/78] =?UTF-8?q?src/pull:=20Support=20local=20pulls=20for?= =?UTF-8?q?=20collection=E2=80=93refs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, collection–refs could only be pulled from a repository if it had a summary file (which listed them). There was no way to pull from a local repository which doesn’t have a summary file, and where the refs were stored as refs/remotes/$remote/$ref, with a config section linking that $remote to the queried collection ID. Fix that by explicitly supporting pull_data->remote_repo_local in fetch_ref_contents(). Signed-off-by: Philip Withnall Closes: #1182 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 57 ++++++++++++++++++++++++-------- tests/pull-test.sh | 2 +- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index cd5fe520..4e6031d6 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -834,24 +834,55 @@ fetch_ref_contents (OtPullData *pull_data, GCancellable *cancellable, GError **error) { - g_autofree char *filename = NULL; - - if (ref->collection_id == NULL || g_strcmp0 (ref->collection_id, main_collection_id) == 0) - filename = g_build_filename ("refs", "heads", ref->ref_name, NULL); - else - filename = g_build_filename ("refs", "mirrors", ref->collection_id, ref->ref_name, NULL); - g_autofree char *ret_contents = NULL; - if (!fetch_mirrored_uri_contents_utf8_sync (pull_data->fetcher, - pull_data->meta_mirrorlist, - filename, &ret_contents, - cancellable, error)) - return FALSE; + if (pull_data->remote_repo_local != NULL && ref->collection_id != NULL) + { +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + if (!ostree_repo_list_collection_refs (pull_data->remote_repo_local, + ref->collection_id, &refs, + OSTREE_REPO_LIST_REFS_EXT_NONE, + cancellable, error)) + return FALSE; + + ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + g_assert_not_reached (); +#endif /* !OSTREE_ENABLE_EXPERIMENTAL_API */ + } + else if (pull_data->remote_repo_local != NULL) + { + g_autoptr(GHashTable) refs = NULL; /* (element-type utf8 utf8) */ + if (!ostree_repo_list_refs (pull_data->remote_repo_local, NULL, + &refs, cancellable, error)) + return FALSE; + + ret_contents = g_strdup (g_hash_table_lookup (refs, ref->ref_name)); + } + else + { + g_autofree char *filename = NULL; + + if (ref->collection_id == NULL || g_strcmp0 (ref->collection_id, main_collection_id) == 0) + filename = g_build_filename ("refs", "heads", ref->ref_name, NULL); + else + filename = g_build_filename ("refs", "mirrors", ref->collection_id, ref->ref_name, NULL); + + if (!fetch_mirrored_uri_contents_utf8_sync (pull_data->fetcher, + pull_data->meta_mirrorlist, + filename, &ret_contents, + cancellable, error)) + return FALSE; + } + + /* Validate and return. */ g_strchomp (ret_contents); if (!ostree_validate_checksum_string (ret_contents, error)) - return glnx_prefix_error (error, "Fetching %s", filename); + return glnx_prefix_error (error, "Fetching checksum for ref (%s, %s)", + ref->collection_id ? ref->collection_id : "(empty)", + ref->ref_name); ot_transfer_out_value (out_contents, &ret_contents); return TRUE; diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 573f8360..49209839 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -508,5 +508,5 @@ rm ostree-srv/gnomerepo/summary if ${CMD_PREFIX} ostree --repo=repo pull origin main 2>err.txt; then fatal "pull of invalid ref succeeded" fi -assert_file_has_content_literal err.txt 'error: Fetching refs/heads/main: Invalid rev lots of html here lots of html here lots of html here lots of' +assert_file_has_content_literal err.txt 'error: Fetching checksum for ref ((empty), main): Invalid rev lots of html here lots of html here lots of html here lots of' echo "ok pull got HTML for a ref" From 9546e6795e8778f00d6df5dfbd3905754b3de05b Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 15 Sep 2017 16:05:12 +0100 Subject: [PATCH 51/78] create-usb: Add a create-usb command to complement OstreeRepoFinderMount This can be used to put OSTree repositories on USB sticks in a format recognised by OstreeRepoFinderMount. Signed-off-by: Philip Withnall Closes: #1182 Approved by: cgwalters --- Makefile-ostree.am | 5 +- Makefile-tests.am | 7 + src/ostree/main.c | 1 + src/ostree/ot-builtin-create-usb.c | 276 +++++++++++++++++++++++++++++ src/ostree/ot-builtins.h | 1 + tests/.gitignore | 1 + tests/libtest.sh | 6 + tests/repo-finder-mount.c | 126 +++++++++++++ tests/test-create-usb.sh | 110 ++++++++++++ 9 files changed, 532 insertions(+), 1 deletion(-) create mode 100644 src/ostree/ot-builtin-create-usb.c create mode 100644 tests/repo-finder-mount.c create mode 100755 tests/test-create-usb.sh diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 6414233f..04faa436 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -54,7 +54,10 @@ ostree_SOURCES = src/ostree/main.c \ $(NULL) if ENABLE_EXPERIMENTAL_API -ostree_SOURCES += src/ostree/ot-builtin-find-remotes.c +ostree_SOURCES += \ + src/ostree/ot-builtin-create-usb.c \ + src/ostree/ot-builtin-find-remotes.c \ + $(NULL) endif # Admin subcommand diff --git a/Makefile-tests.am b/Makefile-tests.am index c2186707..2ea112ec 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -115,6 +115,7 @@ _installed_or_uninstalled_test_scripts = \ $(NULL) experimental_test_scripts = \ + tests/test-create-usb.sh \ tests/test-find-remotes.sh \ tests/test-fsck-collections.sh \ tests/test-init-collections.sh \ @@ -124,9 +125,15 @@ experimental_test_scripts = \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh \ $(NULL) +test_extra_programs = $(NULL) + +tests_repo_finder_mount_SOURCES = tests/repo-finder-mount.c +tests_repo_finder_mount_CFLAGS = $(common_tests_cflags) +tests_repo_finder_mount_LDADD = $(common_tests_ldadd) libostreetest.la if ENABLE_EXPERIMENTAL_API _installed_or_uninstalled_test_scripts += $(experimental_test_scripts) +test_extra_programs += tests/repo-finder-mount else EXTRA_DIST += $(experimental_test_scripts) endif diff --git a/src/ostree/main.c b/src/ostree/main.c index 9d8d2a4b..e1ccf983 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -42,6 +42,7 @@ static OstreeCommand commands[] = { { "export", ostree_builtin_export }, #ifdef OSTREE_ENABLE_EXPERIMENTAL_API { "find-remotes", ostree_builtin_find_remotes }, + { "create-usb", ostree_builtin_create_usb }, #endif { "fsck", ostree_builtin_fsck }, { "gpg-sign", ostree_builtin_gpg_sign }, diff --git a/src/ostree/ot-builtin-create-usb.c b/src/ostree/ot-builtin-create-usb.c new file mode 100644 index 00000000..c77dbcba --- /dev/null +++ b/src/ostree/ot-builtin-create-usb.c @@ -0,0 +1,276 @@ +/* + * Copyright © 2017 Endless Mobile, 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include "ot-main.h" +#include "ot-builtins.h" +#include "ostree.h" +#include "otutil.h" + +#include "ostree-remote-private.h" + +static gboolean opt_disable_fsync = FALSE; +static char *opt_destination_repo = NULL; + +static GOptionEntry options[] = + { + { "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, + { "destination-repo", 0, 0, G_OPTION_ARG_FILENAME, &opt_destination_repo, "Use custom repository directory within the mount", NULL }, + { NULL } + }; + +/* TODO: Add a man page. */ +gboolean +ostree_builtin_create_usb (int argc, + char **argv, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(OstreeAsyncProgress) progress = NULL; + g_auto(GLnxConsoleRef) console = { 0, }; + + context = g_option_context_new ("MOUNT-PATH COLLECTION-ID REF [COLLECTION-ID REF...] - Copy the refs to a USB stick"); + + /* Parse options. */ + g_autoptr(OstreeRepo) src_repo = NULL; + + if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &src_repo, cancellable, error)) + return FALSE; + + if (argc < 2) + { + ot_util_usage_error (context, "A MOUNT-PATH must be specified", error); + return FALSE; + } + + if (argc < 4) + { + ot_util_usage_error (context, "At least one COLLECTION-ID REF pair must be specified", error); + return FALSE; + } + + if (argc % 2 == 1) + { + ot_util_usage_error (context, "Only complete COLLECTION-ID REF pairs may be specified", error); + return FALSE; + } + + /* Open the USB stick, which must exist. Allow automounting and following symlinks. */ + const char *mount_root_path = argv[1]; + struct stat mount_root_stbuf; + + glnx_fd_close int mount_root_dfd = -1; + if (!glnx_opendirat (AT_FDCWD, mount_root_path, TRUE, &mount_root_dfd, error)) + return FALSE; + if (!glnx_fstat (mount_root_dfd, &mount_root_stbuf, error)) + return FALSE; + + /* Read in the refs to add to the USB stick. */ + g_autoptr(GPtrArray) refs = g_ptr_array_new_full (argc, (GDestroyNotify) ostree_collection_ref_free); + + for (gsize i = 2; i < argc; i += 2) + { + if (!ostree_validate_collection_id (argv[i], error) || + !ostree_validate_rev (argv[i + 1], error)) + return FALSE; + + g_ptr_array_add (refs, ostree_collection_ref_new (argv[i], argv[i + 1])); + } + + /* Open the destination repository on the USB stick or create it if it doesn’t exist. + * Check it’s below @mount_root_path, and that it’s not the same as the source + * repository. + * + * If the destination file system supports xattrs (for example, ext4), we use + * a BARE_USER repository; if it doesn’t (for example, FAT), we use ARCHIVE. + * In either case, we want a lossless repository. */ + const char *dest_repo_path = (opt_destination_repo != NULL) ? opt_destination_repo : ".ostree/repo"; + + if (!glnx_shutil_mkdir_p_at (mount_root_dfd, dest_repo_path, 0755, cancellable, error)) + return FALSE; + + OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER; + + if (TEMP_FAILURE_RETRY (fgetxattr (mount_root_dfd, "user.test", NULL, 0)) < 0 && + errno == ENOTSUP) + mode = OSTREE_REPO_MODE_ARCHIVE; + + g_debug ("%s: Creating repository in mode %u", G_STRFUNC, mode); + + g_autoptr(OstreeRepo) dest_repo = ostree_repo_create_at (mount_root_dfd, dest_repo_path, + mode, NULL, cancellable, error); + + if (dest_repo == NULL) + return FALSE; + + struct stat dest_repo_stbuf; + + if (!glnx_fstat (ostree_repo_get_dfd (dest_repo), &dest_repo_stbuf, error)) + return FALSE; + + if (dest_repo_stbuf.st_dev != mount_root_stbuf.st_dev) + { + ot_util_usage_error (context, "--destination-repo must be a descendent of MOUNT-PATH", error); + return FALSE; + } + + if (ostree_repo_equal (src_repo, dest_repo)) + { + ot_util_usage_error (context, "--destination-repo must not be the source repository", error); + return FALSE; + } + + if (!ostree_ensure_repo_writable (dest_repo, error)) + return FALSE; + + if (opt_disable_fsync) + ostree_repo_set_disable_fsync (dest_repo, TRUE); + + /* Copy across all of the collection–refs to the destination repo. */ + GVariantBuilder refs_builder; + g_variant_builder_init (&refs_builder, G_VARIANT_TYPE ("a(sss)")); + + for (gsize i = 0; i < refs->len; i++) + { + const OstreeCollectionRef *ref = g_ptr_array_index (refs, i); + + g_variant_builder_add (&refs_builder, "(sss)", + ref->collection_id, ref->ref_name, ""); + } + + { + GVariantBuilder builder; + g_autoptr(GVariant) opts = NULL; + OstreeRepoPullFlags flags = OSTREE_REPO_PULL_FLAGS_MIRROR; + + glnx_console_lock (&console); + + if (console.is_tty) + progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + g_variant_builder_add (&builder, "{s@v}", "collection-refs", + g_variant_new_variant (g_variant_builder_end (&refs_builder))); + g_variant_builder_add (&builder, "{s@v}", "flags", + g_variant_new_variant (g_variant_new_int32 (flags))); + g_variant_builder_add (&builder, "{s@v}", "depth", + g_variant_new_variant (g_variant_new_int32 (0))); + opts = g_variant_ref_sink (g_variant_builder_end (&builder)); + + g_autofree char *src_repo_uri = g_file_get_uri (ostree_repo_get_path (src_repo)); + + if (!ostree_repo_pull_with_options (dest_repo, src_repo_uri, + opts, + progress, + cancellable, error)) + { + ostree_repo_abort_transaction (dest_repo, cancellable, NULL); + return FALSE; + } + + if (progress != NULL) + ostree_async_progress_finish (progress); + } + + /* Ensure a summary file is present to make it easier to look up commit checksums. */ + /* FIXME: It should be possible to work without this, but find_remotes_cb() in + * ostree-repo-pull.c currently assumes a summary file (signed or unsigned) is + * present. */ + struct stat stbuf; + if (!glnx_fstatat_allow_noent (ostree_repo_get_dfd (dest_repo), "summary", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT && + !ostree_repo_regenerate_summary (dest_repo, NULL, cancellable, error)) + return FALSE; + + /* Add the symlinks .ostree/repos.d/@symlink_name → @dest_repo_path, unless + * the @dest_repo_path is a well-known one like ostree/repo, in which case no + * symlink is necessary; #OstreeRepoFinderMount always looks there. */ + if (!g_str_equal (dest_repo_path, "ostree/repo") && + !g_str_equal (dest_repo_path, ".ostree/repo")) + { + if (!glnx_shutil_mkdir_p_at (mount_root_dfd, ".ostree/repos.d", 0755, cancellable, error)) + return FALSE; + + /* Find a unique name for the symlink. If a symlink already targets + * @dest_repo_path, use that and don’t create a new one. */ + GLnxDirFdIterator repos_iter; + gboolean need_symlink = TRUE; + + if (!glnx_dirfd_iterator_init_at (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_iter, error)) + return FALSE; + + while (TRUE) + { + struct dirent *repo_dent; + + if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, error)) + return FALSE; + + if (repo_dent == NULL) + break; + + /* Does the symlink already point to this repository? (Or is the + * repository itself present in repos.d?) We already guarantee that + * they’re on the same device. */ + if (repo_dent->d_ino == dest_repo_stbuf.st_ino) + { + need_symlink = FALSE; + break; + } + } + + /* If we need a symlink, find a unique name for it and create it. */ + if (need_symlink) + { + /* Relative to .ostree/repos.d. */ + g_autofree char *relative_dest_repo_path = g_build_filename ("..", "..", dest_repo_path, NULL); + guint i; + const guint max_attempts = 100; + + for (i = 0; i < max_attempts; i++) + { + g_autofree char *symlink_path = g_strdup_printf (".ostree/repos.d/%02u-generated", i); + + int ret = TEMP_FAILURE_RETRY (symlinkat (relative_dest_repo_path, mount_root_dfd, symlink_path)); + if (ret < 0 && errno != EEXIST) + return glnx_throw_errno_prefix (error, "symlinkat(%s → %s)", symlink_path, relative_dest_repo_path); + else if (ret >= 0) + break; + } + + if (i == max_attempts) + return glnx_throw (error, "Could not find an unused symlink name for the repository"); + } + } + + /* Report success to the user. */ + g_autofree char *src_repo_path = g_file_get_path (ostree_repo_get_path (src_repo)); + + g_print ("Copied %u/%u refs successfully from ‘%s’ to ‘%s’ repository in ‘%s’.\n", refs->len, refs->len, + src_repo_path, dest_repo_path, mount_root_path); + + return TRUE; +} diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h index 96a5929e..ccb47f60 100644 --- a/src/ostree/ot-builtins.h +++ b/src/ostree/ot-builtins.h @@ -39,6 +39,7 @@ BUILTINPROTO(diff); BUILTINPROTO(export); #ifdef OSTREE_ENABLE_EXPERIMENTAL_API BUILTINPROTO(find_remotes); +BUILTINPROTO(create_usb); #endif BUILTINPROTO(gpg_sign); BUILTINPROTO(init); diff --git a/tests/.gitignore b/tests/.gitignore index e56a8393..d5b49748 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ *.test *.trs ostree-http-server +repo-finder-mount run-apache tmpdir-lifecycle test-rollsum diff --git a/tests/libtest.sh b/tests/libtest.sh index ed6cc43d..7ebe4449 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -603,6 +603,12 @@ skip_without_fuse () { [ -e /etc/mtab ] || skip "no /etc/mtab" } +skip_without_experimental () { + if ! ostree --version | grep -q -e '- experimental'; then + skip "No experimental API is compiled in" + fi +} + has_gpgme () { ${CMD_PREFIX} ostree --version > version.txt assert_file_has_content version.txt '- gpgme' diff --git a/tests/repo-finder-mount.c b/tests/repo-finder-mount.c new file mode 100644 index 00000000..ccea1b2c --- /dev/null +++ b/tests/repo-finder-mount.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2017 Endless Mobile, 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "ostree-autocleanups.h" +#include "ostree-remote-private.h" +#include "ostree-repo-finder.h" +#include "ostree-repo-finder-mount.h" +#include "ostree-types.h" +#include "test-mock-gio.h" + +static void +result_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GAsyncResult **result_out = user_data; + *result_out = g_object_ref (result); +} + +static void +collection_ref_free0 (OstreeCollectionRef *ref) +{ + g_clear_pointer (&ref, (GDestroyNotify) ostree_collection_ref_free); +} + +int +main (int argc, char **argv) +{ + g_autoptr(GError) error = NULL; + + setlocale (LC_ALL, ""); + + if (argc < 5 || (argc % 2) != 1) + { + g_printerr ("Usage: %s REPO MOUNT-ROOT COLLECTION-ID REF-NAME [COLLECTION-ID REF-NAME …]\n", argv[0]); + return 1; + } + + g_autoptr(GMainContext) context = g_main_context_new (); + g_main_context_push_thread_default (context); + + g_autoptr(OstreeRepo) parent_repo = ostree_repo_open_at (AT_FDCWD, argv[1], NULL, &error); + g_assert_no_error (error); + + /* Set up a mock volume. */ + g_autoptr(GFile) mount_root = g_file_new_for_commandline_arg (argv[2]); + g_autoptr(GMount) mount = G_MOUNT (ostree_mock_mount_new ("mount", mount_root)); + + g_autoptr(GList) mounts = g_list_prepend (NULL, mount); + + g_autoptr(GVolumeMonitor) monitor = ostree_mock_volume_monitor_new (mounts, NULL); + g_autoptr(OstreeRepoFinderMount) finder = ostree_repo_finder_mount_new (monitor); + + /* Resolve the refs. */ + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func ((GDestroyNotify) collection_ref_free0); + + for (gsize i = 3; i < argc; i += 2) + { + const char *collection_id = argv[i]; + const char *ref_name = argv[i + 1]; + + g_ptr_array_add (refs, ostree_collection_ref_new (collection_id, ref_name)); + } + + g_ptr_array_add (refs, NULL); /* NULL terminator */ + + g_autoptr(GAsyncResult) result = NULL; + ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), + (const OstreeCollectionRef * const *) refs->pdata, + parent_repo, NULL, result_cb, &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + g_autoptr(GPtrArray) results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), + result, &error); + g_assert_no_error (error); + + /* Check that the results are correct: the invalid refs should have been + * ignored, and the valid results canonicalised and deduplicated. */ + for (gsize i = 0; i < results->len; i++) + { + const OstreeRepoFinderResult *result = g_ptr_array_index (results, i); + GHashTableIter iter; + OstreeCollectionRef *ref; + const gchar *checksum; + + g_hash_table_iter_init (&iter, result->ref_to_checksum); + + while (g_hash_table_iter_next (&iter, (gpointer *) &ref, (gpointer *) &checksum)) + g_print ("%" G_GSIZE_FORMAT " %s %s %s %s\n", + i, ostree_remote_get_name (result->remote), + ref->collection_id, ref->ref_name, + checksum); + } + + g_main_context_pop_thread_default (context); + + return 0; +} diff --git a/tests/test-create-usb.sh b/tests/test-create-usb.sh new file mode 100755 index 00000000..c1738b66 --- /dev/null +++ b/tests/test-create-usb.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# +# Copyright © 2017 Endless Mobile, 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. +# +# Authors: +# - Philip Withnall + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +echo "1..5" + +cd ${test_tmpdir} +mkdir repo +ostree_repo_init repo --collection-id org.example.Collection1 + +mkdir -p tree/root +touch tree/root/a + +# Add a few commits +seq 5 | while read i; do + echo a >> tree/root/a + ${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" tree +done + +${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" + +# Pull into a ‘local’ repository, to more accurately represent the situation of +# creating a USB stick from your local machine. +mkdir local-repo +${CMD_PREFIX} ostree --repo=local-repo init +${CMD_PREFIX} ostree --repo=local-repo remote add remote1 file://$(pwd)/repo --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" +${CMD_PREFIX} ostree --repo=local-repo pull remote1 test-1 test-2 test-3 test-4 test-5 + +# Simple test to put two refs onto a USB stick. +mkdir dest-mount1 +${CMD_PREFIX} ostree --repo=local-repo create-usb dest-mount1 org.example.Collection1 test-1 org.example.Collection1 test-2 + +assert_has_dir dest-mount1/.ostree/repo +${CMD_PREFIX} ostree --repo=dest-mount1/.ostree/repo refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" +assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_has_file dest-mount1/.ostree/repo/summary + +echo "ok 1 simple usb" + +# Test that the repository can be placed in another standard location on the USB stick. +for dest in ostree/repo .ostree/repo; do + rm -rf dest-mount2 + mkdir dest-mount2 + ${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo "$dest" dest-mount2 org.example.Collection1 test-1 + assert_has_dir "dest-mount2/$dest" + if [ -d dest-mount2/.ostree/repos.d ]; then + ls dest-mount2/.ostree/repos.d | wc -l > repo-links + assert_file_has_content repo-links "^0$" + fi +done + +echo "ok 2 usb in standard location" + +# Test that the repository can be placed in a non-standard location and gets a symlink to it. +mkdir dest-mount3 +${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest dest-mount3 org.example.Collection1 test-1 +assert_has_dir "dest-mount3/some-dest" +assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" +${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_has_file dest-mount3/.ostree/repos.d/00-generated/summary + +echo "ok 3 usb in non-standard location" + +# Test that adding an additional ref to an existing USB repository works. +${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest dest-mount3 org.example.Collection1 test-2 org.example.Collection1 test-3 +assert_has_dir "dest-mount3/some-dest" +assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" +${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_has_file dest-mount3/.ostree/repos.d/00-generated/summary + +echo "ok 4 adding ref to an existing usb" + +# Check that #OstreeRepoFinderMount works from a volume initialised uing create-usb. +mkdir finder-repo +ostree_repo_init finder-repo +${CMD_PREFIX} ostree --repo=finder-repo remote add remote1 file://$(pwd)/just-needed-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" + +${test_builddir}/repo-finder-mount finder-repo dest-mount1 org.example.Collection1 test-1 org.example.Collection1 test-2 &> out +assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-1 $(ostree --repo=repo show test-1)$" +assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-2 $(ostree --repo=repo show test-2)$" + +echo "ok 5 find from usb repo" From 149aec10997963c4447279bb7ca96a9925529d22 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 26 Sep 2017 15:15:57 +0100 Subject: [PATCH 52/78] lib/repo-refs: Add first version of ostree_repo_resolve_collection_ref() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a parallel for ostree_repo_resolve_rev_ext() which works on collection–refs. At the moment, the implementation is simple and uses ostree_repo_list_collection_refs(). In future, it could be rewritten to check the checksum directly rather than enumerating all potentially-relevant checksums. Signed-off-by: Philip Withnall Closes: #1182 Approved by: cgwalters --- apidoc/ostree-experimental-sections.txt | 1 + src/libostree/libostree-experimental.sym | 5 ++ src/libostree/ostree-repo-refs.c | 63 ++++++++++++++++++++++++ src/libostree/ostree-repo.h | 11 +++++ 4 files changed, 80 insertions(+) diff --git a/apidoc/ostree-experimental-sections.txt b/apidoc/ostree-experimental-sections.txt index 23412dda..c43d11e1 100644 --- a/apidoc/ostree-experimental-sections.txt +++ b/apidoc/ostree-experimental-sections.txt @@ -85,4 +85,5 @@ ostree_repo_list_collection_refs ostree_repo_remote_list_collection_refs ostree_repo_set_collection_ref_immediate ostree_repo_transaction_set_collection_ref +ostree_repo_resolve_collection_ref diff --git a/src/libostree/libostree-experimental.sym b/src/libostree/libostree-experimental.sym index f60d4e01..87f274da 100644 --- a/src/libostree/libostree-experimental.sym +++ b/src/libostree/libostree-experimental.sym @@ -77,3 +77,8 @@ global: ostree_repo_transaction_set_collection_ref; ostree_validate_collection_id; } LIBOSTREE_2017.7_EXPERIMENTAL; + +LIBOSTREE_2017.12_EXPERIMENTAL { +global: + ostree_repo_resolve_collection_ref; +} LIBOSTREE_2017.8_EXPERIMENTAL; diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index c6acc00b..86bdf999 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -468,6 +468,69 @@ ostree_repo_resolve_rev_ext (OstreeRepo *self, return _ostree_repo_resolve_rev_internal (self, refspec, allow_noent, FALSE, out_rev, error); } +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API +/** + * ostree_repo_resolve_collection_ref: + * @self: an #OstreeRepo + * @ref: a collection–ref to resolve + * @allow_noent: %TRUE to not throw an error if @ref doesn’t exist + * @flags: options controlling behaviour + * @out_rev: (out) (transfer full) (optional) (nullable): return location for + * the checksum corresponding to @ref, or %NULL if @allow_noent is %TRUE and + * the @ref could not be found + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: return location for a #GError, or %NULL + * + * Look up the checksum for the given collection–ref, returning it in @out_rev. + * This will search through the mirrors and remote refs. + * + * If @allow_noent is %TRUE and the given @ref cannot be found, %TRUE will be + * returned and @out_rev will be set to %NULL. If @allow_noent is %FALSE and + * the given @ref cannot be found, a %G_IO_ERROR_NOT_FOUND error will be + * returned. + * + * There are currently no @flags which affect the behaviour of this function. + * + * Returns: %TRUE on success, %FALSE on failure + * Since: 2017.12 + */ +gboolean +ostree_repo_resolve_collection_ref (OstreeRepo *self, + const OstreeCollectionRef *ref, + gboolean allow_noent, + OstreeRepoResolveRevExtFlags flags, + char **out_rev, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); + g_return_val_if_fail (ref != NULL, FALSE); + g_return_val_if_fail (ref->collection_id != NULL && ref->ref_name != NULL, FALSE); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs, + OSTREE_REPO_LIST_REFS_EXT_NONE, + cancellable, error)) + return FALSE; + + const char *ret_contents = g_hash_table_lookup (refs, ref); + + if (ret_contents == NULL && !allow_noent) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Collection–ref (%s, %s) not found", + ref->collection_id, ref->ref_name); + return FALSE; + } + + if (out_rev != NULL) + *out_rev = g_strdup (ret_contents); + return TRUE; +} +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + static gboolean enumerate_refs_recurse (OstreeRepo *repo, const char *remote, diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 51b44b3f..a2986e6d 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -471,6 +471,17 @@ gboolean ostree_repo_resolve_rev_ext (OstreeRepo *self, char **out_rev, GError **error); +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API +_OSTREE_PUBLIC +gboolean ostree_repo_resolve_collection_ref (OstreeRepo *self, + const OstreeCollectionRef *ref, + gboolean allow_noent, + OstreeRepoResolveRevExtFlags flags, + char **out_rev, + GCancellable *cancellable, + GError **error); +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + _OSTREE_PUBLIC gboolean ostree_repo_list_refs (OstreeRepo *self, const char *refspec_prefix, From 2f9f7222a411906a2e508e6aecf5a7ae30a4638c Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 26 Sep 2017 15:17:47 +0100 Subject: [PATCH 53/78] lib/repo-pull: Use resolve() instead of list() in fetch_ref_contents() This is more efficient in the non-collection case; in the collection case, the implementation of ostree_repo_resolve_collection_ref() needs to be rewritten to improve efficiency. Signed-off-by: Philip Withnall Closes: #1182 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 4e6031d6..4aff9e09 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -839,26 +839,22 @@ fetch_ref_contents (OtPullData *pull_data, if (pull_data->remote_repo_local != NULL && ref->collection_id != NULL) { #ifdef OSTREE_ENABLE_EXPERIMENTAL_API - g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ - if (!ostree_repo_list_collection_refs (pull_data->remote_repo_local, - ref->collection_id, &refs, - OSTREE_REPO_LIST_REFS_EXT_NONE, - cancellable, error)) + if (!ostree_repo_resolve_collection_ref (pull_data->remote_repo_local, + ref, TRUE /* ignore enoent */, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, cancellable, error)) return FALSE; - - ret_contents = g_strdup (g_hash_table_lookup (refs, ref)); #else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ g_assert_not_reached (); #endif /* !OSTREE_ENABLE_EXPERIMENTAL_API */ } else if (pull_data->remote_repo_local != NULL) { - g_autoptr(GHashTable) refs = NULL; /* (element-type utf8 utf8) */ - if (!ostree_repo_list_refs (pull_data->remote_repo_local, NULL, - &refs, cancellable, error)) + if (!ostree_repo_resolve_rev_ext (pull_data->remote_repo_local, + ref->ref_name, TRUE /* ignore enoent */, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, error)) return FALSE; - - ret_contents = g_strdup (g_hash_table_lookup (refs, ref->ref_name)); } else { @@ -877,9 +873,11 @@ fetch_ref_contents (OtPullData *pull_data, } /* Validate and return. */ - g_strchomp (ret_contents); + if (ret_contents != NULL) + g_strchomp (ret_contents); - if (!ostree_validate_checksum_string (ret_contents, error)) + if (ret_contents == NULL || + !ostree_validate_checksum_string (ret_contents, error)) return glnx_prefix_error (error, "Fetching checksum for ref (%s, %s)", ref->collection_id ? ref->collection_id : "(empty)", ref->ref_name); From c6f972406e1f3b939c11252d343bb3e91299f8b9 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 13:58:54 -0400 Subject: [PATCH 54/78] lib/pull: Add status for imported objects Followup for recent work in commits: - 8a7a35970928331a028ccddd04590ac300dbd26e - 1a9a473580e9066f5d4a969932d703b5b104b2b7 Keep track of how many objects we imported, and print that for `ostree pull-local` (also do this even if noninteractive, like we did for `pull`). In implementing this at first I used separate variables for import from repo vs import from localcache, but that broke some of the tests that checked those values. It's easier to just merge them; we know from looking at whether or not `remote_repo_local` is set whether or not we were doing a "HTTP pull with localcache" versus a true `pull-local` and can use that when rendering status. Closes: #1219 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 56 ++++++++++++++++++------------ src/ostree/ot-builtin-pull-local.c | 20 +++++++++-- tests/basic-test.sh | 3 +- tests/pull-test.sh | 2 +- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 4aff9e09..45e3eae5 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -132,9 +132,9 @@ typedef struct { guint n_fetched_deltapart_fallbacks; guint n_fetched_metadata; guint n_fetched_content; - /* Objects from pull --localcache-repo */ - guint n_fetched_localcache_metadata; - guint n_fetched_localcache_content; + /* Objects imported via hardlink/reflink/copying or --localcache-repo*/ + guint n_imported_metadata; + guint n_imported_content; gboolean timestamp_check; /* Verify commit timestamps */ int maxdepth; @@ -261,8 +261,11 @@ update_progress (gpointer user_data) "scanned-metadata", "u", n_scanned_metadata, "bytes-transferred", "t", bytes_transferred, "start-time", "t", start_time, - "metadata-fetched-localcache", "u", pull_data->n_fetched_localcache_metadata, - "content-fetched-localcache", "u", pull_data->n_fetched_localcache_content, + /* We use these status keys even though we now also + * use these values for filesystem-local pulls. + */ + "metadata-fetched-localcache", "u", pull_data->n_imported_metadata, + "content-fetched-localcache", "u", pull_data->n_imported_content, /* Deltas */ "fetched-delta-parts", "u", pull_data->n_fetched_deltaparts, @@ -696,6 +699,7 @@ on_local_object_imported (GObject *object, goto out; out: + pull_data->n_imported_content++; g_assert_cmpint (pull_data->n_outstanding_content_write_requests, >, 0); pull_data->n_outstanding_content_write_requests--; check_outstanding_requests_handle_error (pull_data, &local_error); @@ -778,7 +782,6 @@ scan_dirtree_object (OtPullData *pull_data, on_local_object_imported, pull_data); g_hash_table_add (pull_data->requested_content, g_steal_pointer (&file_checksum)); did_import_from_cache_repo = TRUE; - pull_data->n_fetched_localcache_content++; break; } } @@ -1793,6 +1796,7 @@ scan_one_metadata_object_c (OtPullData *pull_data, */ if (objtype == OSTREE_OBJECT_TYPE_COMMIT) g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); + pull_data->n_imported_metadata++; is_stored = TRUE; is_requested = TRUE; } @@ -1824,7 +1828,7 @@ scan_one_metadata_object_c (OtPullData *pull_data, g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); is_stored = TRUE; is_requested = TRUE; - pull_data->n_fetched_localcache_metadata++; + pull_data->n_imported_metadata++; break; } } @@ -4078,36 +4082,42 @@ ostree_repo_pull_with_options (OstreeRepo *self, end_time = g_get_monotonic_time (); bytes_transferred = _ostree_fetcher_bytes_transferred (pull_data->fetcher); - if (bytes_transferred > 0 && pull_data->progress) + if (pull_data->progress) { - guint shift; g_autoptr(GString) buf = g_string_new (""); /* Ensure the rest of the progress keys are set appropriately. */ update_progress (pull_data); - if (bytes_transferred < 1024) - shift = 1; - else - shift = 1024; - - if (pull_data->n_fetched_deltaparts > 0) + /* See if we did a local-only import */ + if (pull_data->remote_repo_local) + g_string_append_printf (buf, "%u metadata, %u content objects imported", + pull_data->n_imported_metadata, pull_data->n_imported_content); + else if (pull_data->n_fetched_deltaparts > 0) g_string_append_printf (buf, "%u delta parts, %u loose fetched", pull_data->n_fetched_deltaparts, pull_data->n_fetched_metadata + pull_data->n_fetched_content); else g_string_append_printf (buf, "%u metadata, %u content objects fetched", pull_data->n_fetched_metadata, pull_data->n_fetched_content); - if (pull_data->n_fetched_localcache_metadata || - pull_data->n_fetched_localcache_content) + if (!pull_data->remote_repo_local && + (pull_data->n_imported_metadata || pull_data->n_imported_content)) g_string_append_printf (buf, " (%u meta, %u content local)", - pull_data->n_fetched_localcache_metadata, - pull_data->n_fetched_localcache_content); + pull_data->n_imported_metadata, + pull_data->n_imported_content); - g_string_append_printf (buf, "; %" G_GUINT64_FORMAT " %s transferred in %u seconds", - (guint64)(bytes_transferred / shift), - shift == 1 ? "B" : "KiB", - (guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC)); + if (bytes_transferred > 0) + { + guint shift; + if (bytes_transferred < 1024) + shift = 1; + else + shift = 1024; + g_string_append_printf (buf, "; %" G_GUINT64_FORMAT " %s transferred in %u seconds", + (guint64)(bytes_transferred / shift), + shift == 1 ? "B" : "KiB", + (guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC)); + } ostree_async_progress_set_status (pull_data->progress, buf->str); } diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index c3dc50c9..8d4e8d60 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -55,6 +55,14 @@ static GOptionEntry options[] = { { NULL } }; +/* See canonical version of this in ot-builtin-pull.c */ +static void +noninteractive_console_progress_changed (OstreeAsyncProgress *progress, + gpointer user_data) +{ + /* We do nothing here - we just want the final status */ +} + gboolean ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GError **error) { @@ -170,6 +178,8 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr if (console.is_tty) progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); + else + progress = ostree_async_progress_new_and_connect (noninteractive_console_progress_changed, &console); opts = g_variant_ref_sink (g_variant_builder_end (&builder)); if (!ostree_repo_pull_with_options (repo, src_repo_uri, @@ -178,8 +188,14 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr cancellable, error)) goto out; - if (progress) - ostree_async_progress_finish (progress); + if (!console.is_tty) + { + g_assert (progress); + const char *status = ostree_async_progress_get_status (progress); + if (status) + g_print ("%s\n", status); + } + ostree_async_progress_finish (progress); } ret = TRUE; diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 482f6979..4df6a079 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -278,7 +278,8 @@ if ! skip_one_without_user_xattrs; then opposite_mode=archive fi ostree_repo_init repo2 --mode=$opposite_mode - ${CMD_PREFIX} ostree --repo=repo2 pull-local repo + ${CMD_PREFIX} ostree --repo=repo2 pull-local repo >out.txt + assert_file_has_content out.txt "[1-9][0-9]* metadata, [1-9][0-9]* content objects imported" test2_commitid=$(${CMD_PREFIX} ostree --repo=repo rev-parse test2) test2_commit_relpath=/objects/${test2_commitid:0:2}/${test2_commitid:2}.commit assert_files_hardlinked repo/${test2_commit_relpath} repo2/${test2_commit_relpath} diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 49209839..f2c45f93 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -42,7 +42,7 @@ repo_init --no-gpg-verify ${CMD_PREFIX} ostree --repo=repo pull origin main >out.txt assert_file_has_content out.txt "[1-9][0-9]* metadata, [1-9][0-9]* content objects fetched" ${CMD_PREFIX} ostree --repo=repo pull origin:main > out.txt -assert_not_file_has_content out.txt "content objects fetched" +assert_not_file_has_content out.txt "[1-9][0-9]* content objects fetched" ${CMD_PREFIX} ostree --repo=repo fsck echo "ok pull" From 030d2b1525a49c356210c18f57655afd9f474b4f Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 21 Sep 2017 16:01:44 +0100 Subject: [PATCH 55/78] lib/repo-pull: Fix a potential minor leak If override-remote-name is specified in the options to ostree_repo_pull_with_options(), but the remote_name_or_baseurl argument is also set to a remote name, the override-remote-name would be leaked. Note that this is currently an invalid configuration, so this leak is basically never hit. Signed-off-by: Philip Withnall Closes: #1202 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 45e3eae5..cad7f86e 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -3360,6 +3360,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, { g_autofree char *unconfigured_state = NULL; + g_free (pull_data->remote_name); pull_data->remote_name = g_strdup (remote_name_or_baseurl); /* Fetch GPG verification settings from remote if it wasn't already From 22c1fdfbd320379a09f4a670126bc28cdc383b87 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 21 Sep 2017 16:00:05 +0100 Subject: [PATCH 56/78] lib/repo: Change resolve_keyring_for_collection() to return a remote Instead of returning just the keyring filename, return the entire OstreeRemote, which has the keyring filename as one of its members. This will simplify some upcoming changes, and allows slightly improved debug logging. Signed-off-by: Philip Withnall Closes: #1202 Approved by: cgwalters --- src/libostree/ostree-repo-finder-avahi.c | 35 +++++++++++++----------- src/libostree/ostree-repo-finder-mount.c | 35 +++++++++++++----------- src/libostree/ostree-repo-pull.c | 11 ++++---- src/libostree/ostree-repo.h | 8 +++--- 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/libostree/ostree-repo-finder-avahi.c b/src/libostree/ostree-repo-finder-avahi.c index 4de74c6e..409fcae8 100644 --- a/src/libostree/ostree-repo-finder-avahi.c +++ b/src/libostree/ostree-repo-finder-avahi.c @@ -165,28 +165,28 @@ ostree_avahi_browser_event_to_string (AvahiBrowserEvent event) typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -196,7 +196,7 @@ uri_and_keyring_hash (gconstpointer key) { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -205,7 +205,8 @@ uri_and_keyring_equal (gconstpointer a, { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -213,7 +214,7 @@ static gchar * uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -770,14 +771,15 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService for (i = 0; i < possible_refs->len; i++) { const OstreeCollectionRef *ref = g_ptr_array_index (possible_refs, i); - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; + g_autoptr(OstreeRemote) keyring_remote = NULL; /* Look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, - cancellable, &error); + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &error); - if (keyring == NULL) + if (keyring_remote == NULL) { g_debug ("Ignoring ref (%s, %s) on host ‘%s’ due to missing keyring: %s", ref->collection_id, refs[i]->ref_name, service->address, @@ -788,10 +790,11 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService /* Add this repo to the results, keyed by the canonicalised repository URI * to deduplicate the results. */ - g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’.", - ref->collection_id, ref->ref_name, uri, keyring); + g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, uri, keyring_remote->keyring, + keyring_remote->name); - resolved_repo = uri_and_keyring_new (uri, keyring); + resolved_repo = uri_and_keyring_new (uri, keyring_remote); supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); @@ -821,7 +824,7 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService remote = ostree_remote_new (name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index 5784b986..7dcbab89 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -93,28 +93,28 @@ G_DEFINE_TYPE_WITH_CODE (OstreeRepoFinderMount, ostree_repo_finder_mount, G_TYPE typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -124,7 +124,7 @@ uri_and_keyring_hash (gconstpointer key) { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -133,7 +133,8 @@ uri_and_keyring_equal (gconstpointer a, { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -141,7 +142,7 @@ static gchar * uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -439,7 +440,6 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde { const OstreeCollectionRef *ref = refs[i]; g_autofree gchar *resolved_repo_uri = NULL; - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; for (gsize j = 0; j < repos_refs->len; j++) @@ -448,6 +448,7 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde OstreeRepo *repo = repo_and_refs->repo; GHashTable *repo_refs = repo_and_refs->refs; g_autofree char *repo_path = g_file_get_path (ostree_repo_get_path (repo)); + g_autoptr(OstreeRemote) keyring_remote = NULL; const gchar *checksum = g_hash_table_lookup (repo_refs, ref); @@ -460,10 +461,11 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde } /* Finally, look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, - cancellable, &local_error); + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &local_error); - if (keyring == NULL) + if (keyring_remote == NULL) { g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", repo_path, ref->collection_id, ref->ref_name, mount_name, local_error->message); @@ -477,10 +479,11 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde * to deduplicate the results. */ g_autofree char *canonical_repo_path = realpath (repo_path, NULL); resolved_repo_uri = g_strconcat ("file://", canonical_repo_path, NULL); - g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’.", - ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, keyring); + g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, + keyring_remote->keyring, keyring_remote->name); - resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring); + resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring_remote); supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); @@ -513,7 +516,7 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde remote = ostree_remote_new (name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index cad7f86e..4401d763 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -5498,7 +5498,7 @@ check_remote_matches_collection_id (OstreeRepo *repo, * Find the GPG keyring for the given @collection_id, using the local * configuration from the given #OstreeRepo. This will search the configured * remotes for ones whose `collection-id` key matches @collection_id, and will - * return the GPG keyring from the first matching remote. + * return the first matching remote. * * If multiple remotes match and have different keyrings, a debug message will * be emitted, and the first result will be returned. It is expected that the @@ -5506,10 +5506,11 @@ check_remote_matches_collection_id (OstreeRepo *repo, * * If no match can be found, a %G_IO_ERROR_NOT_FOUND error will be returned. * - * Returns: (transfer full): filename of the GPG keyring for @collection_id + * Returns: (transfer full): #OstreeRemote containing the GPG keyring for + * @collection_id * Since: 2017.8 */ -gchar * +OstreeRemote * ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, const gchar *collection_id, GCancellable *cancellable, @@ -5517,7 +5518,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, { gsize i; g_auto(GStrv) remotes = NULL; - const OstreeRemote *keyring_remote = NULL; + OstreeRemote *keyring_remote = NULL; g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); g_return_val_if_fail (ostree_validate_collection_id (collection_id, NULL), NULL); @@ -5567,7 +5568,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, } if (keyring_remote != NULL) - return g_strdup (keyring_remote->keyring); + return ostree_remote_ref (keyring_remote); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index a2986e6d..990573e7 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -1208,10 +1208,10 @@ gboolean ostree_repo_pull_from_remotes_finish (OstreeRepo *self, GError **error); _OSTREE_PUBLIC -gchar *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, - const gchar *collection_id, - GCancellable *cancellable, - GError **error); +OstreeRemote *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, + const gchar *collection_id, + GCancellable *cancellable, + GError **error); _OSTREE_PUBLIC gboolean ostree_repo_list_collection_refs (OstreeRepo *self, From 69e332a0c034b9d0e754372b3c9d653f492a97c7 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 21 Sep 2017 16:04:11 +0100 Subject: [PATCH 57/78] lib/remote: Store name of remote providing keyring for dynamic remotes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When pulling from a dynamic (peer to peer) remote, the remote’s name is set to a unique, generated string which doesn’t exist in repo/config. If doing a non-mirror pull, however, we don’t want to use this name in the refspecs for newly created or updated refs — we want to use the name of the remote which provided the keyring for the pull (this will be a remote from repo/config whose collection ID matches that being used for the peer to peer pull). Store both names in OstreeRemote. The name to use for refspecs is stored as refspec_name, and is typically NULL unless it differs from name. Signed-off-by: Philip Withnall Closes: #1202 Approved by: cgwalters --- src/libostree/ostree-remote-private.h | 9 ++++++++- src/libostree/ostree-remote.c | 13 +++++++++++-- src/libostree/ostree-repo-finder-avahi.c | 2 +- src/libostree/ostree-repo-finder-mount.c | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-remote-private.h b/src/libostree/ostree-remote-private.h index b7e9eb3b..ff7f885b 100644 --- a/src/libostree/ostree-remote-private.h +++ b/src/libostree/ostree-remote-private.h @@ -35,17 +35,24 @@ G_BEGIN_DECLS +/* @refspec_name is set if this is a dynamic remote. It’s the name of the static + * remote which this one inherits from, and is what should be used in refspecs + * for pulls from this remote. If it’s %NULL, @name should be used instead. */ struct OstreeRemote { volatile int ref_count; char *name; /* (not nullable) */ + char *refspec_name; /* (nullable) */ char *group; /* group name in options (not nullable) */ - char *keyring; /* keyring name (NAME.trustedkeys.gpg) (not nullable) */ + char *keyring; /* keyring name ($refspec_name.trustedkeys.gpg) (not nullable) */ GFile *file; /* NULL if remote defined in repo/config */ GKeyFile *options; }; G_GNUC_INTERNAL OstreeRemote *ostree_remote_new (const gchar *name); +G_GNUC_INTERNAL +OstreeRemote *ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name); G_GNUC_INTERNAL OstreeRemote *ostree_remote_new_from_keyfile (GKeyFile *keyfile, diff --git a/src/libostree/ostree-remote.c b/src/libostree/ostree-remote.c index cac7838c..605a7eb9 100644 --- a/src/libostree/ostree-remote.c +++ b/src/libostree/ostree-remote.c @@ -53,16 +53,25 @@ OstreeRemote * ostree_remote_new (const gchar *name) +{ + return ostree_remote_new_dynamic (name, NULL); +} + +OstreeRemote * +ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name) { OstreeRemote *remote; g_return_val_if_fail (name != NULL && *name != '\0', NULL); + g_return_val_if_fail (refspec_name == NULL || *refspec_name != '\0', NULL); remote = g_slice_new0 (OstreeRemote); remote->ref_count = 1; remote->name = g_strdup (name); - remote->group = g_strdup_printf ("remote \"%s\"", name); - remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", name); + remote->refspec_name = g_strdup (refspec_name); + remote->group = g_strdup_printf ("remote \"%s\"", (refspec_name != NULL) ? refspec_name : name); + remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", (refspec_name != NULL) ? refspec_name : name); remote->options = g_key_file_new (); return remote; diff --git a/src/libostree/ostree-repo-finder-avahi.c b/src/libostree/ostree-repo-finder-avahi.c index 409fcae8..a39d9533 100644 --- a/src/libostree/ostree-repo-finder-avahi.c +++ b/src/libostree/ostree-repo-finder-avahi.c @@ -821,7 +821,7 @@ ostree_avahi_service_build_repo_finder_result (OstreeAvahiService /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); remote->keyring = g_strdup (repo->keyring_remote->keyring); diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index 7dcbab89..c385e70c 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -513,7 +513,7 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); remote->keyring = g_strdup (repo->keyring_remote->keyring); From 9d8c1ec7dff18941b1cf2fac7328bffb25c63c1e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 21 Sep 2017 16:08:26 +0100 Subject: [PATCH 58/78] lib/repo-pull: Fix remote names in refspecs from non-mirror P2P pulls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Propagate the refspec_name from the OstreeRemote returned by an OstreeRepoFinder through to the set_ref() call. This changes ostree_repo_pull_with_options() to accept the previously-disallowed combination of passing override-remote-name in options and also setting a remote name in remote_name_or_baseurl. ostree_repo_pull_with_options() will continue to pull using the remote config named in remote_name_or_baseurl as before; but will now use the remote name from override-remote-name when it’s setting the refs at the end of the pull. This is consistent with the documentation for override-remote-name. Signed-off-by: Philip Withnall Closes: #1202 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 4401d763..b187175c 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -68,7 +68,8 @@ typedef struct { OstreeRepo *repo; int tmpdir_dfd; OstreeRepoPullFlags flags; - char *remote_name; + char *remote_name; + char *remote_refspec_name; OstreeRepoMode remote_mode; OstreeFetcher *fetcher; OstreeFetcherSecurityState fetcher_security_state; @@ -3226,7 +3227,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, flags = flags_i; (void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull); (void) g_variant_lookup (options, "subdirs", "^a&s", &dirs_to_pull); - (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name); + (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_refspec_name); opt_gpg_verify_set = g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify); opt_gpg_verify_summary_set = @@ -3242,6 +3243,9 @@ ostree_repo_pull_with_options (OstreeRepo *self, (void) g_variant_lookup (options, "update-frequency", "u", &update_frequency); (void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos); (void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check); + + if (pull_data->remote_refspec_name != NULL) + pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); } g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); @@ -4049,7 +4053,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, ostree_repo_transaction_set_collection_ref (pull_data->repo, ref, checksum); else - ostree_repo_transaction_set_ref (pull_data->repo, pull_data->remote_name, + ostree_repo_transaction_set_ref (pull_data->repo, + (pull_data->remote_refspec_name != NULL) ? pull_data->remote_refspec_name : pull_data->remote_name, ref->ref_name, checksum); } } @@ -5370,6 +5375,8 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self, g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", TRUE); g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE); g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE); + if (result->remote->refspec_name != NULL) + g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name); copy_option (&options_dict, &local_options_dict, "depth", G_VARIANT_TYPE ("i")); copy_option (&options_dict, &local_options_dict, "disable-static-deltas", G_VARIANT_TYPE ("b")); copy_option (&options_dict, &local_options_dict, "http-headers", G_VARIANT_TYPE ("a(ss)")); From b71a913e210e5ca853030b6c466fd52054e1217e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 14:05:08 -0400 Subject: [PATCH 59/78] ci: Record primary context results using g-d-t-r --log-directory So the output isn't all intermingled. I just pushed a commit to add `--log-directory`, so we need to build it from git master for now. Closes: #1218 Approved by: jlebon --- .papr.yml | 2 ++ ci/build-check.sh | 24 +++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.papr.yml b/.papr.yml index 9a253431..00512eda 100644 --- a/.papr.yml +++ b/.papr.yml @@ -25,9 +25,11 @@ tests: timeout: 30m +# Keep this in sync with build-check.sh artifacts: - test-suite.log - config.log + - gdtr-results --- context: c7-primary diff --git a/ci/build-check.sh b/ci/build-check.sh index 7df1f424..cb9dbb83 100755 --- a/ci/build-check.sh +++ b/ci/build-check.sh @@ -6,12 +6,26 @@ set -xeuo pipefail dn=$(dirname $0) . ${dn}/libbuild.sh ${dn}/build.sh +topdir=$(git rev-parse --show-toplevel) +resultsdir=$(mktemp -d) make check make syntax-check # TODO: do syntax-check under check +# See comment below +for x in test-suite.log config.log; do + mv ${x} ${resultsdir} +done # And now run the installed tests make install if test -x /usr/bin/gnome-desktop-testing-runner; then - gnome-desktop-testing-runner -p 0 ${INSTALLED_TESTS_PATTERN:-libostree/} + mkdir ${resultsdir}/gdtr-results + # Temporary hack + (git clone --depth=1 https://git.gnome.org/browse/gnome-desktop-testing + cd gnome-desktop-testing + env NOCONFIGURE=1 ./autogen.sh + ./configure --prefix=/usr --libdir=/usr/lib64 + make && rm -f /usr/bin/ginsttest-runner && make install) + # Use the new -L option + gnome-desktop-testing-runner -L ${resultsdir}/gdtr-results -p 0 ${INSTALLED_TESTS_PATTERN:-libostree/} fi if test -x /usr/bin/clang; then @@ -25,3 +39,11 @@ if test -x /usr/bin/clang; then export CC=clang build fi + +# Keep this in sync with papr.yml +# TODO; Split the main/clang builds into separate build dirs +for x in test-suite.log config.log gdtr-results; do + if test -e ${resultsdir}/${x}; then + mv ${resultsdir}/${x} ${topdir} + fi +done From d319e7598271ed07c04048f2e7bcf711622a7f7e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 27 Sep 2017 13:15:06 -0400 Subject: [PATCH 60/78] lib/diff: Add compile-time ABI check on 64 bit arches Like what was done for most of the `ostree-repo.h` values. Prep for adding a new option. Closes: #1223 Approved by: jlebon --- src/libostree/ostree-diff.c | 10 ++++++++++ src/libostree/ostree-diff.h | 1 + src/libostree/ostree-repo.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index 064b873c..0c6cb0e7 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -26,6 +26,16 @@ #include "ostree-repo-private.h" #include "otutil.h" +/* See ostree-repo.c for a bit more info about these ABI checks */ +#if __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 && __SIZEOF_INT__ == 4 +G_STATIC_ASSERT(sizeof(OstreeDiffDirsOptions) == + sizeof(int) * 2 + + sizeof(gpointer) + + sizeof(int) * (7+6) + + sizeof(int) + /* hole */ + sizeof(gpointer) * 7); +#endif + static gboolean get_file_checksum (OstreeDiffFlags flags, GFile *f, diff --git a/src/libostree/ostree-diff.h b/src/libostree/ostree-diff.h index 6e324e2a..64fd7f8b 100644 --- a/src/libostree/ostree-diff.h +++ b/src/libostree/ostree-diff.h @@ -85,6 +85,7 @@ typedef struct { gboolean unused_bools[7]; int unused_ints[6]; + /* 4 byte hole on 64 bit */ gpointer unused_ptrs[7]; } OstreeDiffDirsOptions; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 82c01e05..e02ea87a 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -48,6 +48,10 @@ /* ABI Size checks for ostree-repo.h, only for LP64 systems; * https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models + * + * To generate this data, I used `pahole` from gdb. More concretely, `gdb --args + * /usr/bin/ostree`, then `start`, (to ensure debuginfo was loaded), then e.g. + * `$ pahole OstreeRepoTransactionStats`. */ #if __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 && __SIZEOF_INT__ == 4 G_STATIC_ASSERT(sizeof(OstreeRepoTransactionStats) == sizeof(int) * 4 + 8 * 5); From 33141404150ec0166fb72e8f50c461194aec52f4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 20:51:24 -0400 Subject: [PATCH 61/78] tests/commit-sign: Update a bit to more modern style I was trying to debug this while working on another PR. Add `echo ok` lines and also use `assert_file_has_content` more directly; there's no reason to use an intermediate `grep` since if it fails it won't print the original file. Closes: #1220 Approved by: jlebon --- tests/test-commit-sign.sh | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/test-commit-sign.sh b/tests/test-commit-sign.sh index 755818c8..b0a88138 100755 --- a/tests/test-commit-sign.sh +++ b/tests/test-commit-sign.sh @@ -26,7 +26,7 @@ if ! has_gpgme; then exit 0 fi -echo "1..1" +echo "1..6" keyid="472CDAFA" oldpwd=`pwd` @@ -73,6 +73,7 @@ if env OSTREE_GPG_HOME=${test_tmpdir} ${CMD_PREFIX} ostree --repo=repo pull orig assert_not_reached "pull with no trusted GPG keys unexpectedly succeeded!" fi rm repo -rf +echo "ok pull no trusted GPG" # And a test case with valid signature cd ${test_tmpdir} @@ -80,9 +81,10 @@ mkdir repo ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main -${CMD_PREFIX} ostree --repo=repo show --gpg-verify-remote=origin main | grep -o 'Found [[:digit:]] signature' > show-verify-remote -assert_file_has_content show-verify-remote 'Found 1 signature' +${CMD_PREFIX} ostree --repo=repo show --gpg-verify-remote=origin main > show.txt +assert_file_has_content_literal show.txt 'Found 1 signature' rm repo -rf +echo "ok pull verify" # A test with corrupted detached signature cd ${test_tmpdir} @@ -96,6 +98,7 @@ if ${CMD_PREFIX} ostree --repo=repo pull origin main; then assert_not_reached "pull with corrupted signature unexpectedly succeeded!" fi rm repo -rf +echo "ok pull corrupted sig" # And now attempt to pull the same corrupted commit, but with GPG # verification off @@ -105,6 +108,7 @@ ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main rm repo -rf +echo "ok repull corrupted" # Add an unsigned commit to the repo, then pull, then sign the commit, # then pull again. Make sure we get the expected number of signatures @@ -117,23 +121,21 @@ mkdir repo ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main -if ${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature'; then - assert_not_reached -fi +${CMD_PREFIX} ostree --repo=repo show main > show.txt +assert_not_file_has_content show.txt 'Found.*signature' ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo gpg-sign --gpg-homedir=${test_tmpdir}/gpghome main $keyid ${CMD_PREFIX} ostree --repo=repo pull origin main -${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature' > show -assert_file_has_content show 'Found 1 signature' +${CMD_PREFIX} ostree --repo=repo show main > show.txt +assert_file_has_content_literal show.txt 'Found 1 signature' +echo "ok pull unsigned, then sign" # Delete the signature from the commit so the detached metadata is empty, # then pull and verify the signature is also deleted on the client side. ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo gpg-sign --gpg-homedir=${test_tmpdir}/gpghome --delete main $keyid ${CMD_PREFIX} ostree --repo=repo pull origin main -if ${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature'; then - assert_not_reached -fi +${CMD_PREFIX} ostree --repo=repo show main >show.txt +assert_not_file_has_content show.txt 'Found.*signature' +echo "ok pull sig deleted" rm -rf repo gnomerepo-files libtest_cleanup_gpg - -echo "ok" From 5b860fba05651b075e10e19b295a1d00ebb5b8e2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 26 Sep 2017 17:21:59 -0400 Subject: [PATCH 62/78] lib/pull: Don't request deltas for unchanged commits I noticed this while debugging why I was seeing "2 metadata objects" fetched for a different PR. I knew 1 was detached meta, but the other turned out to be this. There's no reason to request a delta if the ref is unchanged. Closes: #1220 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index b187175c..8a699ca0 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -3117,10 +3117,14 @@ initiate_request (OtPullData *pull_data, g_clear_pointer (&delta_from_revision, g_free); } - /* This is similar to the below, except we *might* use the previous - * commit, or we might do a scratch delta first. + /* If the current ref is the same, we don't do a delta request, just a + * scan. Otherise, use the previous commit if available, or a scratch + * delta. */ - initiate_delta_request (pull_data, delta_from_revision ?: NULL, to_revision, ref); + if (delta_from_revision && g_str_equal (delta_from_revision, to_revision)) + queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0, ref); + else + initiate_delta_request (pull_data, delta_from_revision ?: NULL, to_revision, ref); } else { From aa067aeafac1473b972fdc594e6efbd5247bb364 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 27 Sep 2017 15:54:32 -0400 Subject: [PATCH 63/78] tree-wide: Bump libglnx, port to new lockfile init In particular I'd like to get the copy fix in, since it might affect users for the keyring bits. Update submodule: libglnx Closes: #1225 Approved by: jlebon --- libglnx | 2 +- src/libostree/ostree-repo-commit.c | 2 +- src/libostree/ostree-repo.c | 2 -- src/libostree/ostree-sysroot.c | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libglnx b/libglnx index e5856ca2..e3015443 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit e5856ca2939dca0589a836e3108dd3f9759e28fa +Subproject commit e30154431d7eea6397e5502b175ba3b50330140f diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index df5c92cd..1b7d380c 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1234,7 +1234,7 @@ cleanup_tmpdir (OstreeRepo *self, guint64 delta; struct dirent *dent; struct stat stbuf; - g_auto(GLnxLockFile) lockfile = GLNX_LOCK_FILE_INIT; + g_auto(GLnxLockFile) lockfile = { 0, }; gboolean did_lock; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e02ea87a..1e336e90 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -662,7 +662,6 @@ static void ostree_repo_init (OstreeRepo *self) { static gsize gpgme_initialized; - GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; const GDebugKey test_error_keys[] = { { "pre-commit", OSTREE_REPO_TEST_ERROR_PRE_COMMIT }, }; @@ -690,7 +689,6 @@ ostree_repo_init (OstreeRepo *self) self->tmp_dir_fd = -1; self->objects_dir_fd = -1; self->uncompressed_objects_dir_fd = -1; - self->commit_stagedir_lock = empty_lockfile; self->sysroot_kind = OSTREE_REPO_SYSROOT_KIND_UNKNOWN; } diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index c7054571..fe61a12e 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -197,7 +197,6 @@ ostree_sysroot_init (OstreeSysroot *self) keys, G_N_ELEMENTS (keys)); self->sysroot_fd = -1; - self->lock = (GLnxLockFile)GLNX_LOCK_FILE_INIT; } /** From 15096ac49e3c387ba9050ba1d611e99375d4f98a Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 26 May 2017 10:52:26 -0400 Subject: [PATCH 64/78] tests: Add 404 tests for dirtree objects too I now believe the flatpak issue we were hitting was https://github.com/ostreedev/ostree/pull/1185 but let's add these tests anyways for more coverage. Closes: #888 Approved by: jlebon --- tests/pull-test.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/pull-test.sh b/tests/pull-test.sh index f2c45f93..7d4b57f9 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -35,7 +35,7 @@ function verify_initial_contents() { assert_file_has_content baz/cow '^moo$' } -echo "1..30" +echo "1..31" # Try both syntaxes repo_init --no-gpg-verify @@ -476,6 +476,16 @@ fi assert_file_has_content err.txt "GPG verification enabled, but no signatures found" echo "ok pull repo 404 (gpg)" +cd ${test_tmpdir} +find ostree-srv/gnomerepo/objects -name '*.dirtree' | while read f; do mv ${f}{,.orig}; done +repo_init --set=gpg-verify=false +if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main 2>err.txt; then + assert_not_reached "pull repo 404 succeeded?" +fi +assert_file_has_content err.txt "404" +find ostree-srv/gnomerepo/objects -name '*.dirtree.orig' | while read f; do mv ${f} $(dirname $f)/$(basename ${f} .orig); done +echo "ok pull repo 404 on dirtree object" + cd ${test_tmpdir} repo_init --set=gpg-verify=true ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit \ From df1d0a5fc65ded50f090376806329c85e9136dba Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 18 Sep 2017 15:43:41 +0100 Subject: [PATCH 65/78] tests: Add a manual integration test for OstreeRepoFinderMount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test an end-to-end flow of pulling refs from an online repository → local OS repository → create a USB stick of them → pull to a local OS repository on another machine. This is a manual test, as it requires a throwaway USB stick which the test can format as ext4 or vfat to test the flow works with both file systems. Run it as: MOUNT_INTEGRATION_DEV=/dev/sdb1 make check \ TESTS=tests/test-repo-finder-mount-integration.sh Signed-off-by: Philip Withnall Closes: #1203 Approved by: cgwalters --- Makefile-tests.am | 1 + tests/test-repo-finder-mount-integration.sh | 131 ++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100755 tests/test-repo-finder-mount-integration.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 2ea112ec..7cf2b19a 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -122,6 +122,7 @@ experimental_test_scripts = \ tests/test-prune-collections.sh \ tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ + tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh \ $(NULL) diff --git a/tests/test-repo-finder-mount-integration.sh b/tests/test-repo-finder-mount-integration.sh new file mode 100755 index 00000000..9ce34cb2 --- /dev/null +++ b/tests/test-repo-finder-mount-integration.sh @@ -0,0 +1,131 @@ +#!/bin/bash +# +# Copyright © 2017 Endless Mobile, 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. +# +# Authors: +# - Philip Withnall + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +SUDO="sudo --non-interactive" + +# Skip the test if a well-known USB stick is not available. +# To run the test, you must have a throwaway partition on a USB stick (doesn’t +# matter how it’s formatted, as the test will reformat it), and must set +# MOUNT_INTEGRATION_DEV to that partition. For example, +# MOUNT_INTEGRATION_DEV=/dev/sdb1. For safety, the test will be skipped if the +# partition is already mounted. +# +# FIXME: We could potentially automate this in future if there’s a way to trick +# GIO into treating an arbitrary partition (such as a loopback device of our +# creation) as removable. + +if ! [ -b "${MOUNT_INTEGRATION_DEV:-}" ]; then + skip "Test needs a disposable USB stick passed in as MOUNT_INTEGRATION_DEV" +fi + +# Sanity check that the given device is not already mounted, to try and avoid +# hosing the system. +if mount | grep -q "${MOUNT_INTEGRATION_DEV}"; then + skip "${MOUNT_INTEGRATION_DEV} must not be mounted already" +fi + +_mount_cleanup () { + ${SUDO} umount "${MOUNT_INTEGRATION_DEV}" || true +} + +case "${TEST_SKIP_CLEANUP:-}" in + no|"") + trap _mount_cleanup EXIT + ;; + err) + trap _mount_cleanup ERR + ;; +esac + +echo "1..3" + +cd ${test_tmpdir} +mkdir repo +ostree_repo_init repo --collection-id org.example.Collection1 + +mkdir -p tree/root +touch tree/root/a + +# Add a few commits +seq 5 | while read i; do + echo a >> tree/root/a + ${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" tree +done + +${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" +${CMD_PREFIX} ostree --repo=repo rev-parse test-1 > ref1-checksum + +# Pull into a ‘local’ repository, to more accurately represent the situation of +# creating a USB stick from your local machine. +mkdir local-repo +ostree_repo_init local-repo +${CMD_PREFIX} ostree --repo=local-repo remote add remote1 file://$(pwd)/repo --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" +${CMD_PREFIX} ostree --repo=local-repo pull remote1 test-1 test-2 test-3 test-4 test-5 + +for fs_type in ext4 vfat; do + # Prepare a USB stick containing some of the refs on the given file system. + if [ "$fs_type" = "ext4" ]; then + fs_options="-F -E root_owner=$(id -u):$(id -g)" + else + fs_options= + fi + ${SUDO} mkfs.$fs_type $fs_options "${MOUNT_INTEGRATION_DEV}" > /dev/null + usb_mount=$(udisksctl mount --block-device "${MOUNT_INTEGRATION_DEV}" --filesystem-type $fs_type | sed -n "s/^Mounted .* at \(.*\)\.$/\1/p") + + ${CMD_PREFIX} ostree --repo=local-repo create-usb "${usb_mount}" org.example.Collection1 test-1 org.example.Collection1 test-2 + + assert_has_dir "${usb_mount}"/.ostree/repo + ${CMD_PREFIX} ostree --repo="${usb_mount}"/.ostree/repo refs --collections > dest-refs + assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" + assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" + assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" + assert_has_file "${usb_mount}"/.ostree/repo/summary + + # Pull into a second local repository (theoretically, a separate computer). + mkdir peer-repo_$fs_type + ostree_repo_init peer-repo_$fs_type + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type remote add remote1 file://just-here-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes org.example.Collection1 test-1 > find-results + assert_not_file_has_content find-results "^No results.$" + assert_file_has_content find-results "^Result 0: file://${usb_mount}" + assert_file_has_content find-results "(org.example.Collection1, test-1) = $(cat ref1-checksum)$" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes --pull org.example.Collection1 test-1 > pull-results + assert_file_has_content pull-results "^Pulled 1/1 refs successfully.$" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type refs --collections > refs + assert_file_has_content refs "^(org.example.Collection1, test-1)$" + + ${SUDO} umount "${MOUNT_INTEGRATION_DEV}" + + echo "ok end-to-end USB on ${fs_type}" +done + +# Check the two repositories are identical. +diff -ur peer-repo_ext4 peer-repo_vfat + +echo "ok end-to-end USB repositories are identical" From 467fcff349cea0c9cfed83b43dd40c5c18db58c4 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 22 Sep 2017 12:08:01 +0100 Subject: [PATCH 66/78] tests: Update some tests to use OSTREE_REPO_MODE_ARCHIVE not ARCHIVE_Z2 The latter is deprecated now. Signed-off-by: Philip Withnall Closes: #1203 Approved by: cgwalters --- tests/test-repo-finder-config.c | 2 +- tests/test-repo-finder-mount.c | 2 +- tests/test-repo.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test-repo-finder-config.c b/tests/test-repo-finder-config.c index c4a763e6..b89aaee4 100644 --- a/tests/test-repo-finder-config.c +++ b/tests/test-repo-finder-config.c @@ -177,7 +177,7 @@ assert_create_remote (Fixture *fixture, g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); ostree_repo_set_collection_id (repo, collection_id, &error); g_assert_no_error (error); - ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error); + ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE, NULL, &error); g_assert_no_error (error); /* Set up the refs from @.... */ diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index 7c5f9e9b..10b253f7 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -182,7 +182,7 @@ assert_create_remote_va (Fixture *fixture, g_autoptr(GError) error = NULL; g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_dir); - ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error); + ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE, NULL, &error); g_assert_no_error (error); /* Set up the refs from @.... */ diff --git a/tests/test-repo.c b/tests/test-repo.c index 217ca23c..e327f602 100644 --- a/tests/test-repo.c +++ b/tests/test-repo.c @@ -67,7 +67,7 @@ test_repo_hash (Fixture *fixture, { g_autoptr(GError) error = NULL; g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, ".", - OSTREE_REPO_MODE_ARCHIVE_Z2, + OSTREE_REPO_MODE_ARCHIVE, NULL, NULL, &error); g_assert_no_error (error); @@ -113,7 +113,7 @@ test_repo_equal (Fixture *fixture, g_assert_no_error (error); g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, "repo1", - OSTREE_REPO_MODE_ARCHIVE_Z2, + OSTREE_REPO_MODE_ARCHIVE, NULL, NULL, &error); g_assert_no_error (error); @@ -123,7 +123,7 @@ test_repo_equal (Fixture *fixture, g_assert_no_error (error); g_autoptr(OstreeRepo) repo2 = ostree_repo_create_at (fixture->tmpdir.fd, "repo2", - OSTREE_REPO_MODE_ARCHIVE_Z2, + OSTREE_REPO_MODE_ARCHIVE, NULL, NULL, &error); g_assert_no_error (error); From 6c7302fcdd1d5292e0d2ba815ea7eb02b3d1e871 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 22 Sep 2017 12:49:30 +0100 Subject: [PATCH 67/78] tests/repo: Drop modeline from top of file As per commit 6e4146a3. Signed-off-by: Philip Withnall Closes: #1203 Approved by: cgwalters --- tests/test-repo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test-repo.c b/tests/test-repo.c index e327f602..dc87111b 100644 --- a/tests/test-repo.c +++ b/tests/test-repo.c @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or From a7f04a14b584b04389576d3f10fad79b40f466d8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 28 Sep 2017 15:41:02 -0400 Subject: [PATCH 68/78] libarchive: Fix assertion error if used with CANONICAL_PERMISSIONS I was trying to do a change for rpm-ostree to use `OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS` for container builds with `bare-user-only,` but hit an assertion here ultimtely because we weren't setting `standard::type`. Rather than hand-rolling `GFileInfo` creation, use the stat buffer conversion code which is more robust and used in multiple places already. Closes: #1227 Approved by: jlebon --- src/libostree/ostree-repo-libarchive.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index 414981df..64d8a503 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -871,10 +871,14 @@ ostree_repo_import_archive_to_mtree (OstreeRepo *self, if (opts->autocreate_parents && ostree_mutable_tree_get_metadata_checksum (mtree) == NULL) { - glnx_unref_object GFileInfo *fi = g_file_info_new (); - g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); - g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); - g_file_info_set_attribute_uint32 (fi, "unix::mode", DEFAULT_DIRMODE); + /* _ostree_stbuf_to_gfileinfo() only looks at these fields, + * but we use it to ensure it sets all of the relevant GFileInfo + * properties. + */ + struct stat stbuf = { .st_mode = DEFAULT_DIRMODE, + .st_uid = 0, + .st_gid = 0 }; + g_autoptr(GFileInfo) fi = _ostree_stbuf_to_gfileinfo (&stbuf); g_autoptr(GFileInfo) mfi = NULL; (void)_ostree_repo_commit_modifier_apply (self, modifier, "/", From e4a90caeb9d210344e537e2a9b8016dc0e01e15a Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 28 Sep 2017 18:56:17 +0000 Subject: [PATCH 69/78] tests/libtest.sh: always nuke repo and files This allows users to easily re-initialize the test repo. Closes: #1170 Approved by: cgwalters --- tests/libtest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/libtest.sh b/tests/libtest.sh index 7ebe4449..6993629d 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -141,6 +141,7 @@ setup_test_repository () { fi cd ${test_tmpdir} + rm -rf repo if test -n "${mode}"; then ostree_repo_init repo --mode=${mode} else @@ -152,6 +153,7 @@ setup_test_repository () { cd ${test_tmpdir} local oldumask="$(umask)" umask 022 + rm -rf files mkdir files cd files ot_files=`pwd` From 8fe45362578a43260876134d6547ebd0bb2485c3 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 28 Sep 2017 19:08:06 +0000 Subject: [PATCH 70/78] lib/commit: don't query devino cache for modified files We can't use the cache if the file we want to commit has been modified by the client through the file info or xattr modifiers. We would prematurely look into the cache in `write_dfd_iter_to_mtree_internal`, regardless of whether any filtering applied. We remove that path there, and make sure that we only use the cache if there were no modifications. We rename the `get_modified_xattrs` to `get_final_xattrs` to reflect the fact that the xattrs may not be modified. One tricky bit that took me some time was that we now need to store the st_dev & st_ino values in the GFileInfo because the cache lookup relies on it. I'm guessing we regressed on this at some point. This patch does slightly change the semantics of the xattr callback. Previously, returning NULL from the cb meant no xattrs at all. Now, it means to default to the on-disk state. We might want to consider putting that behind a flag instead. Though it seems like a more useful behaviour so that callers can only override the files they want to without losing original on-disk state (and if they don't want that, just return an empty GVariant). Closes: #1165 Closes: #1170 Approved by: cgwalters --- src/libostree/ostree-core-private.h | 1 + src/libostree/ostree-core.c | 40 +++++++++ src/libostree/ostree-repo-commit.c | 125 +++++++++++++++------------- tests/basic-test.sh | 20 ++++- tests/test-basic-c.c | 122 ++++++++++++++++++++++++++- 5 files changed, 246 insertions(+), 62 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index 783eacd3..0658a0cb 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -89,6 +89,7 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd, GError **error); GFileInfo * _ostree_stbuf_to_gfileinfo (const struct stat *stbuf); +gboolean _ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b); GFileInfo * _ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid); static inline void diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 5a4b58f4..08c28924 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1568,12 +1568,52 @@ _ostree_stbuf_to_gfileinfo (const struct stat *stbuf) g_file_info_set_attribute_uint32 (ret, "unix::uid", stbuf->st_uid); g_file_info_set_attribute_uint32 (ret, "unix::gid", stbuf->st_gid); g_file_info_set_attribute_uint32 (ret, "unix::mode", mode); + + /* those aren't stored by ostree, but used by the devino cache */ + g_file_info_set_attribute_uint32 (ret, "unix::device", stbuf->st_dev); + g_file_info_set_attribute_uint64 (ret, "unix::inode", stbuf->st_ino); + if (S_ISREG (mode)) g_file_info_set_attribute_uint64 (ret, "standard::size", stbuf->st_size); return ret; } +/** + * _ostree_gfileinfo_equal: + * @a: First file info + * @b: Second file info + * + * OSTree only cares about a subset of file attributes. This function + * checks whether two #GFileInfo objects are equal as far as OSTree is + * concerned. + * + * Returns: TRUE if the #GFileInfo objects are OSTree-equivalent. + */ +gboolean +_ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b) +{ + /* trivial case */ + if (a == b) + return TRUE; + +#define CHECK_ONE_ATTR(type, attr, a, b) \ + do { if (g_file_info_get_attribute_##type(a, attr) != \ + g_file_info_get_attribute_##type(b, attr)) \ + return FALSE; \ + } while (0) + + CHECK_ONE_ATTR (uint32, "unix::uid", a, b); + CHECK_ONE_ATTR (uint32, "unix::gid", a, b); + CHECK_ONE_ATTR (uint32, "unix::mode", a, b); + CHECK_ONE_ATTR (uint32, "standard::type", a, b); + CHECK_ONE_ATTR (uint64, "standard::size", a, b); + +#undef CHECK_ONE_ATTR + + return TRUE; +} + GFileInfo * _ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid) { diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 1b7d380c..c4484f44 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2363,58 +2363,68 @@ ptrarray_path_join (GPtrArray *path) } static gboolean -get_modified_xattrs (OstreeRepo *self, - OstreeRepoCommitModifier *modifier, - const char *relpath, - GFileInfo *file_info, - GFile *path, - int dfd, - const char *dfd_subpath, - GVariant **out_xattrs, - GCancellable *cancellable, - GError **error) +get_final_xattrs (OstreeRepo *self, + OstreeRepoCommitModifier *modifier, + const char *relpath, + GFileInfo *file_info, + GFile *path, + int dfd, + const char *dfd_subpath, + GVariant **out_xattrs, + gboolean *out_modified, + GCancellable *cancellable, + GError **error) { - g_autoptr(GVariant) ret_xattrs = NULL; + /* track whether the returned xattrs differ from the file on disk */ + gboolean modified = TRUE; + const gboolean skip_xattrs = (modifier && + modifier->flags & (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS | + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS)) > 0; - if (modifier && modifier->xattr_callback) - { - ret_xattrs = modifier->xattr_callback (self, relpath, file_info, - modifier->xattr_user_data); - } - else if (!(modifier && (modifier->flags & (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS | - OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS)) > 0) - && !self->disable_xattrs) + /* fetch on-disk xattrs if needed & not disabled */ + g_autoptr(GVariant) original_xattrs = NULL; + if (!skip_xattrs && !self->disable_xattrs) { if (path && OSTREE_IS_REPO_FILE (path)) { - if (!ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (path), - &ret_xattrs, - cancellable, - error)) + if (!ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (path), &original_xattrs, + cancellable, error)) return FALSE; } else if (path) { if (!glnx_dfd_name_get_all_xattrs (AT_FDCWD, gs_file_get_path_cached (path), - &ret_xattrs, cancellable, error)) + &original_xattrs, cancellable, error)) return FALSE; } else if (dfd_subpath == NULL) { g_assert (dfd != -1); - if (!glnx_fd_get_all_xattrs (dfd, &ret_xattrs, - cancellable, error)) + if (!glnx_fd_get_all_xattrs (dfd, &original_xattrs, cancellable, error)) return FALSE; } else { g_assert (dfd != -1); - if (!glnx_dfd_name_get_all_xattrs (dfd, dfd_subpath, &ret_xattrs, - cancellable, error)) + if (!glnx_dfd_name_get_all_xattrs (dfd, dfd_subpath, &original_xattrs, + cancellable, error)) return FALSE; } + + g_assert (original_xattrs); } + g_autoptr(GVariant) ret_xattrs = NULL; + if (modifier && modifier->xattr_callback) + { + ret_xattrs = modifier->xattr_callback (self, relpath, file_info, + modifier->xattr_user_data); + } + + /* if callback returned NULL or didn't exist, default to on-disk state */ + if (!ret_xattrs && original_xattrs) + ret_xattrs = g_variant_ref (original_xattrs); + if (modifier && modifier->sepolicy) { g_autofree char *label = NULL; @@ -2436,10 +2446,9 @@ get_modified_xattrs (OstreeRepo *self, { /* drop out any existing SELinux policy from the set, so we don't end up * counting it twice in the checksum */ - g_autoptr(GVariant) new_ret_xattrs = NULL; - new_ret_xattrs = _ostree_filter_selinux_xattr (ret_xattrs); + GVariant* new_ret_xattrs = _ostree_filter_selinux_xattr (ret_xattrs); g_variant_unref (ret_xattrs); - ret_xattrs = g_steal_pointer (&new_ret_xattrs); + ret_xattrs = new_ret_xattrs; } /* ret_xattrs may be NULL */ @@ -2458,8 +2467,13 @@ get_modified_xattrs (OstreeRepo *self, } } + if (original_xattrs && ret_xattrs && g_variant_equal (original_xattrs, ret_xattrs)) + modified = FALSE; + if (out_xattrs) *out_xattrs = g_steal_pointer (&ret_xattrs); + if (out_modified) + *out_modified = modified; return TRUE; } @@ -2506,6 +2520,7 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, g_autoptr(GFileInfo) modified_info = NULL; OstreeRepoCommitFilterResult filter_result = _ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info); + const gboolean child_info_was_modified = !_ostree_gfileinfo_equal (child_info, modified_info); if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW) { @@ -2567,16 +2582,26 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, else { guint64 file_obj_length; - const char *loose_checksum; g_autoptr(GInputStream) file_input = NULL; - g_autoptr(GVariant) xattrs = NULL; g_autoptr(GInputStream) file_object_input = NULL; g_autofree guchar *child_file_csum = NULL; g_autofree char *tmp_checksum = NULL; - loose_checksum = devino_cache_lookup (self, modifier, - g_file_info_get_attribute_uint32 (child_info, "unix::device"), - g_file_info_get_attribute_uint64 (child_info, "unix::inode")); + g_autoptr(GVariant) xattrs = NULL; + gboolean xattrs_were_modified; + if (!get_final_xattrs (self, modifier, child_relpath, child_info, child, + dfd_iter != NULL ? dfd_iter->fd : -1, name, &xattrs, + &xattrs_were_modified, cancellable, error)) + return FALSE; + + /* only check the devino cache if the file info & xattrs were not modified */ + const char *loose_checksum = NULL; + if (!child_info_was_modified && !xattrs_were_modified) + { + guint32 dev = g_file_info_get_attribute_uint32 (child_info, "unix::device"); + guint64 inode = g_file_info_get_attribute_uint64 (child_info, "unix::inode"); + loose_checksum = devino_cache_lookup (self, modifier, dev, inode); + } if (loose_checksum) { @@ -2602,12 +2627,6 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, } } - if (!get_modified_xattrs (self, modifier, - child_relpath, child_info, child, dfd_iter != NULL ? dfd_iter->fd : -1, name, - &xattrs, - cancellable, error)) - return FALSE; - if (!ostree_raw_file_to_content_stream (file_input, modified_info, xattrs, &file_object_input, &file_obj_length, @@ -2681,10 +2700,8 @@ write_directory_to_mtree_internal (OstreeRepo *self, if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) { - if (!get_modified_xattrs (self, modifier, relpath, child_info, - dir, -1, NULL, - &xattrs, - cancellable, error)) + if (!get_final_xattrs (self, modifier, relpath, child_info, dir, -1, NULL, + &xattrs, NULL, cancellable, error)) return FALSE; g_autofree guchar *child_file_csum = NULL; @@ -2768,10 +2785,8 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) { - if (!get_modified_xattrs (self, modifier, relpath, modified_info, - NULL, src_dfd_iter->fd, NULL, - &xattrs, - cancellable, error)) + if (!get_final_xattrs (self, modifier, relpath, modified_info, NULL, src_dfd_iter->fd, + NULL, &xattrs, NULL, cancellable, error)) return FALSE; if (!_ostree_repo_write_directory_meta (self, modified_info, xattrs, &child_file_csum, @@ -2801,16 +2816,6 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, if (!glnx_fstatat (src_dfd_iter->fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - const char *loose_checksum = devino_cache_lookup (self, modifier, stbuf.st_dev, stbuf.st_ino); - if (loose_checksum) - { - if (!ostree_mutable_tree_replace_file (mtree, dent->d_name, loose_checksum, - error)) - return FALSE; - - continue; - } - g_autoptr(GFileInfo) child_info = _ostree_stbuf_to_gfileinfo (&stbuf); g_file_info_set_name (child_info, dent->d_name); diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 4df6a079..a01f437a 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..$((72 + ${extra_basic_tests:-0}))" +echo "1..$((73 + ${extra_basic_tests:-0}))" CHECKOUT_U_ARG="" CHECKOUT_H_ARGS="-H" @@ -602,6 +602,24 @@ $OSTREE checkout test2 test2-checkout (cd test2-checkout && $OSTREE commit ${COMMIT_ARGS} --link-checkout-speedup -b test2 -s "tmp") echo "ok commit with link speedup" +cd ${test_tmpdir} +rm -rf test2-checkout +$OSTREE checkout test2 test2-checkout +# set cow to different perms, but re-set cowro to the same perms +cat > statoverride.txt < stats.txt +$OSTREE diff test2 test2-tmp > diff-test2 +assert_file_has_content diff-test2 'M */baz/cow$' +assert_not_file_has_content diff-test2 'M */baz/cowro$' +assert_not_file_has_content diff-test2 'baz/saucer' +# only /baz/cow is a cache miss +assert_file_has_content stats.txt '^Content Written: 1$' +echo "ok commit with link speedup and modifier" + cd ${test_tmpdir} $OSTREE ls test2 echo "ok ls with no argument" diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c index 27b9744a..163774f3 100644 --- a/tests/test-basic-c.c +++ b/tests/test-basic-c.c @@ -236,6 +236,125 @@ test_object_writes (gconstpointer data) } } +static GVariant* +xattr_cb (OstreeRepo *repo, + const char *path, + GFileInfo *file_info, + gpointer user_data) +{ + GVariant *xattr = user_data; + if (g_str_equal (path, "/baz/cow")) + return g_variant_ref (xattr); + return NULL; +} + +/* check that using a devino cache doesn't cause us to ignore xattr callbacks */ +static void +test_devino_cache_xattrs (void) +{ + g_autoptr(GError) error = NULL; + gboolean ret = FALSE; + + g_autoptr(GFile) repo_path = g_file_new_for_path ("repo"); + + /* re-initialize as bare */ + ret = ot_test_run_libtest ("setup_test_repository bare", &error); + g_assert_no_error (error); + g_assert (ret); + + gboolean on_overlay; + ret = ot_check_for_overlay (&on_overlay, &error); + g_assert_no_error (error); + g_assert (ret); + + if (on_overlay) + { + g_test_skip ("overlayfs detected"); + return; + } + + g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); + ret = ostree_repo_open (repo, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autofree char *csum = NULL; + ret = ostree_repo_resolve_rev (repo, "test2", FALSE, &csum, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(OstreeRepoDevInoCache) cache = ostree_repo_devino_cache_new (); + + OstreeRepoCheckoutAtOptions options = {0,}; + options.no_copy_fallback = TRUE; + options.devino_to_csum_cache = cache; + ret = ostree_repo_checkout_at (repo, &options, AT_FDCWD, "checkout", csum, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(OstreeMutableTree) mtree = ostree_mutable_tree_new (); + g_autoptr(OstreeRepoCommitModifier) modifier = + ostree_repo_commit_modifier_new (0, NULL, NULL, NULL); + ostree_repo_commit_modifier_set_devino_cache (modifier, cache); + + g_auto(GVariantBuilder) builder; + g_variant_builder_init (&builder, (GVariantType*)"a(ayay)"); + g_variant_builder_add (&builder, "(@ay@ay)", + g_variant_new_bytestring ("user.myattr"), + g_variant_new_bytestring ("data")); + g_autoptr(GVariant) orig_xattrs = g_variant_ref_sink (g_variant_builder_end (&builder)); + + ret = ostree_repo_prepare_transaction (repo, NULL, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + ostree_repo_commit_modifier_set_xattr_callback (modifier, xattr_cb, NULL, orig_xattrs); + ret = ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, "checkout", + mtree, modifier, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(GFile) root = NULL; + ret = ostree_repo_write_mtree (repo, mtree, &root, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* now check that the final xattr matches */ + g_autoptr(GFile) baz_child = g_file_get_child (root, "baz"); + g_autoptr(GFile) cow_child = g_file_get_child (baz_child, "cow"); + + g_autoptr(GVariant) xattrs = NULL; + ret = ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (cow_child), &xattrs, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + gboolean found_xattr = FALSE; + gsize n = g_variant_n_children (xattrs); + for (gsize i = 0; i < n; i++) + { + const guint8* name; + const guint8* value; + g_variant_get_child (xattrs, i, "(^&ay^&ay)", &name, &value); + + if (g_str_equal ((const char*)name, "user.myattr")) + { + g_assert_cmpstr ((const char*)value, ==, "data"); + found_xattr = TRUE; + break; + } + } + + g_assert (found_xattr); + + OstreeRepoTransactionStats stats; + ret = ostree_repo_commit_transaction (repo, &stats, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* we should only have had to checksum /baz/cow */ + g_assert_cmpint (stats.content_objects_written, ==, 1); +} + int main (int argc, char **argv) { g_autoptr(GError) error = NULL; @@ -243,13 +362,14 @@ int main (int argc, char **argv) g_test_init (&argc, &argv, NULL); - repo = ot_test_setup_repo (NULL, &error); + repo = ot_test_setup_repo (NULL, &error); if (!repo) goto out; g_test_add_data_func ("/repo-not-system", repo, test_repo_is_not_system); g_test_add_data_func ("/raw-file-to-archive-stream", repo, test_raw_file_to_archive_stream); g_test_add_data_func ("/objectwrites", repo, test_object_writes); + g_test_add_func ("/xattrs-devino-cache", test_devino_cache_xattrs); g_test_add_func ("/remotename", test_validate_remotename); return g_test_run(); From a06bd82cd4dc14b3c2949a421870b6d3067aba34 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Thu, 28 Sep 2017 18:57:33 +0000 Subject: [PATCH 71/78] tests: check for relabeling rather than overlay Instead of checking for overlayfs, let's explicitly check for our ability to relabel files since we now have a `libtest` function to do this. Also port that logic to `libostreetest`. Note that overlayfs *does* allow manipulating user xattrs. So ideally, we should break down `OSTREE_NO_XATTRS` further to distinguish between tests that use bare repos from other modes. We check the current directory instead of `/` so that developers can just point `TEST_TMPDIR` to a non-overlayfs mount point when hacking from a container. Closes: #1170 Approved by: cgwalters --- tests/libostreetest.c | 91 +++++++++++++++++++++++++++++++++++-------- tests/libostreetest.h | 6 +++ tests/libtest.sh | 78 +++++++++++++++++++++++-------------- tests/test-basic-c.c | 14 +++++-- 4 files changed, 140 insertions(+), 49 deletions(-) diff --git a/tests/libostreetest.c b/tests/libostreetest.c index 6186a73a..496ff740 100644 --- a/tests/libostreetest.c +++ b/tests/libostreetest.c @@ -72,6 +72,68 @@ ot_test_setup_repo (GCancellable *cancellable, return g_steal_pointer (&ret_repo); } +/* Determine whether we're able to relabel files. Needed for bare tests. */ +gboolean +ot_check_relabeling (gboolean *can_relabel, + GError **error) +{ + g_auto(GLnxTmpfile) tmpf = { 0, }; + if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) + return FALSE; + + g_autoptr(GError) local_error = NULL; + g_autoptr(GBytes) bytes = glnx_fgetxattr_bytes (tmpf.fd, "security.selinux", &local_error); + if (!bytes) + { + /* libglnx preserves errno */ + if (G_IN_SET (errno, ENOTSUP, ENODATA)) + { + *can_relabel = FALSE; + return TRUE; + } + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + gsize data_len; + const guint8 *data = g_bytes_get_data (bytes, &data_len); + if (fsetxattr (tmpf.fd, "security.selinux", data, data_len, 0) < 0) + { + if (errno == ENOTSUP) + { + *can_relabel = FALSE; + return TRUE; + } + return glnx_throw_errno_prefix (error, "fsetxattr"); + } + + *can_relabel = TRUE; + return TRUE; +} + +/* Determine whether the filesystem supports getting/setting user xattrs. */ +gboolean +ot_check_user_xattrs (gboolean *has_user_xattrs, + GError **error) +{ + g_auto(GLnxTmpfile) tmpf = { 0, }; + if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) + return FALSE; + + if (fsetxattr (tmpf.fd, "user.test", "novalue", strlen ("novalue"), 0) < 0) + { + if (errno == ENOTSUP) + { + *has_user_xattrs = FALSE; + return TRUE; + } + return glnx_throw_errno_prefix (error, "fsetxattr"); + } + + *has_user_xattrs = TRUE; + return TRUE; +} + OstreeSysroot * ot_test_setup_sysroot (GCancellable *cancellable, GError **error) @@ -79,22 +141,19 @@ ot_test_setup_sysroot (GCancellable *cancellable, if (!ot_test_run_libtest ("setup_os_repository \"archive\" \"syslinux\"", error)) return FALSE; - struct statfs stbuf; - { g_autoptr(GString) buf = g_string_new ("mutable-deployments"); - if (statfs ("/", &stbuf) < 0) - return glnx_null_throw_errno (error); - /* Keep this in sync with the overlayfs bits in libtest.sh */ -#ifndef OVERLAYFS_SUPER_MAGIC -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 -#endif - if (stbuf.f_type == OVERLAYFS_SUPER_MAGIC) - { - g_print ("libostreetest: detected overlayfs\n"); - g_string_append (buf, ",no-xattrs"); - } - /* Make sure deployments are mutable */ - g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE); - } + g_autoptr(GString) buf = g_string_new ("mutable-deployments"); + + gboolean can_relabel; + if (!ot_check_relabeling (&can_relabel, error)) + return FALSE; + if (!can_relabel) + { + g_print ("libostreetest: can't relabel, turning off xattrs\n"); + g_string_append (buf, ",no-xattrs"); + } + + /* Make sure deployments are mutable */ + g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE); g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot"); return ostree_sysroot_new (sysroot_path); diff --git a/tests/libostreetest.h b/tests/libostreetest.h index d5512d55..0273334a 100644 --- a/tests/libostreetest.h +++ b/tests/libostreetest.h @@ -31,6 +31,12 @@ gboolean ot_test_run_libtest (const char *cmd, GError **error); OstreeRepo *ot_test_setup_repo (GCancellable *cancellable, GError **error); +gboolean ot_check_relabeling (gboolean *can_relabel, + GError **error); + +gboolean ot_check_user_xattrs (gboolean *has_user_xattrs, + GError **error); + OstreeSysroot *ot_test_setup_sysroot (GCancellable *cancellable, GError **error); diff --git a/tests/libtest.sh b/tests/libtest.sh index 6993629d..a0c0e36f 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -70,16 +70,50 @@ chmod -R u+w "${test_tmpdir}" export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted -# See comment in ot-builtin-commit.c and https://github.com/ostreedev/ostree/issues/758 -# Also keep this in sync with the bits in libostreetest.c -echo evaluating for overlayfs... -case $(stat -f --printf '%T' /) in - overlayfs) - echo "overlayfs found; enabling OSTREE_NO_XATTRS" - export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs" - export OSTREE_NO_XATTRS=1 ;; - *) ;; -esac +assert_has_setfattr() { + if ! which setfattr 2>/dev/null; then + fatal "no setfattr available to determine xattr support" + fi +} + +_have_selinux_relabel='' +have_selinux_relabel() { + assert_has_setfattr + if test "${_have_selinux_relabel}" = ''; then + pushd ${test_tmpdir} + echo testlabel > testlabel.txt + selinux_xattr=security.selinux + if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then + label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,") + if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then + echo "SELinux enabled in $(pwd), and have privileges to relabel" + _have_selinux_relabel=yes + else + sed -e 's/^/# /' < err.txt >&2 + echo "Found SELinux label, but unable to set (Unprivileged Docker?)" + _have_selinux_relabel=no + fi + else + sed -e 's/^/# /' < err.txt >&2 + echo "Unable to retrieve SELinux label, assuming disabled" + _have_selinux_relabel=no + fi + popd + fi + test ${_have_selinux_relabel} = yes +} + +# just globally turn off xattrs if we can't manipulate security xattrs; this is +# the case for overlayfs -- really, we should only enforce this for tests that +# use bare repos; separate from other tests that should check for user xattrs +# support +# see https://github.com/ostreedev/ostree/issues/758 +# and https://github.com/ostreedev/ostree/pull/1217 +echo -n checking for xattrs... +if ! have_selinux_relabel; then + export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs" + export OSTREE_NO_XATTRS=1 +fi echo done if test -n "${OT_TESTS_DEBUG:-}"; then @@ -516,12 +550,9 @@ os_repository_new_commit () cd ${test_tmpdir} } -# Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi _have_user_xattrs='' have_user_xattrs() { - if ! which setfattr 2>/dev/null; then - fatal "no setfattr available to determine xattr support" - fi + assert_has_setfattr if test "${_have_user_xattrs}" = ''; then touch test-xattrs if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then @@ -533,6 +564,8 @@ have_user_xattrs() { fi test ${_have_user_xattrs} = yes } + +# Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi skip_one_without_user_xattrs () { if ! have_user_xattrs; then echo "ok # SKIP - this test requires xattr support" @@ -554,21 +587,8 @@ skip_without_user_xattrs () { # https://github.com/ostreedev/ostree/pull/759 # https://github.com/ostreedev/ostree/pull/1217 skip_without_no_selinux_or_relabel () { - cd ${test_tmpdir} - echo testlabel > testlabel.txt - selinux_xattr=security.selinux - if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then - label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,") - if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then - echo "SELinux enabled in $(pwd), and have privileges to relabel" - return 0 - else - sed -e 's/^/# /' < err.txt >&2 - skip "Found SELinux label, but unable to set (Unprivileged Docker?)" - fi - else - sed -e 's/^/# /' < err.txt >&2 - skip "Unable to retrieve SELinux label, assuming disabled" + if ! have_selinux_relabel; then + skip "this test requires xattr support" fi } diff --git a/tests/test-basic-c.c b/tests/test-basic-c.c index 163774f3..f7e85438 100644 --- a/tests/test-basic-c.c +++ b/tests/test-basic-c.c @@ -262,14 +262,20 @@ test_devino_cache_xattrs (void) g_assert_no_error (error); g_assert (ret); - gboolean on_overlay; - ret = ot_check_for_overlay (&on_overlay, &error); + gboolean can_relabel; + ret = ot_check_relabeling (&can_relabel, &error); g_assert_no_error (error); g_assert (ret); - if (on_overlay) + gboolean has_user_xattrs; + ret = ot_check_user_xattrs (&has_user_xattrs, &error); + g_assert_no_error (error); + g_assert (ret); + + /* we need both because we're bare and our tests target user xattrs */ + if (!can_relabel || !has_user_xattrs) { - g_test_skip ("overlayfs detected"); + g_test_skip ("this test requires full xattr support"); return; } From 4262a4b016ec1ca252dfb4b2fcc82a27f643ea63 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 29 Sep 2017 21:42:23 +0000 Subject: [PATCH 72/78] tests/installed: also run test-basic-c Since we now have a subtest there that needs full xattr support. Closes: #1170 Approved by: cgwalters --- tests/installed/itest-bare-unit.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/installed/itest-bare-unit.sh b/tests/installed/itest-bare-unit.sh index c763faf7..28ea4651 100755 --- a/tests/installed/itest-bare-unit.sh +++ b/tests/installed/itest-bare-unit.sh @@ -8,6 +8,12 @@ set -xeuo pipefail dn=$(dirname $0) . ${dn}/libinsttest.sh +# These tests sort of bypass the installed-tests spec; +# fixing that would require installing g-d-t-r, though +# more ideally we architect things with a "control" container +# distinct from the host. +export G_TEST_SRCDIR=$(realpath $dn/../..) + # Use /var/tmp to hopefully use XFS + O_TMPFILE etc. tempdir=$(mktemp -d /var/tmp/tap-test.XXXXXX) touch ${tempdir}/.testtmp @@ -18,8 +24,5 @@ function cleanup () { } trap cleanup EXIT cd ${tempdir} -# This sort of bypasses the installed-tests spec; -# fixing that would require installing g-d-t-r, though -# more ideally we architect things with a "control" container -# distinct from the host. /usr/libexec/installed-tests/libostree/test-basic.sh +/usr/libexec/installed-tests/libostree/test-basic-c From 1673601510da20b132bcc3fd17d6e0cc9bf837dd Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sun, 1 Oct 2017 00:12:25 +0100 Subject: [PATCH 73/78] lib/bloom: Fix bloom hashing on 32-bit architectures There was an implicit cast from guint64 to gsize (which is 32-bit on armhf, for example) before the modulus arithmetic which safely narrows the index. Fix that by using a guint64 intermediate variable and making the cast explicit. Signed-off-by: Philip Withnall Closes: #1231 Approved by: cgwalters --- src/libostree/ostree-bloom.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-bloom.c b/src/libostree/ostree-bloom.c index 6b42d97a..8defb176 100644 --- a/src/libostree/ostree-bloom.c +++ b/src/libostree/ostree-bloom.c @@ -273,11 +273,11 @@ ostree_bloom_maybe_contains (OstreeBloom *bloom, for (i = 0; i < bloom->k; i++) { - gsize idx; + guint64 idx; idx = bloom->hash_func (element, i); - if (!ostree_bloom_get_bit (bloom, idx % (bloom->n_bytes * 8))) + if (!ostree_bloom_get_bit (bloom, (gsize) (idx % (bloom->n_bytes * 8)))) return FALSE; /* definitely not in the set */ } @@ -337,8 +337,8 @@ ostree_bloom_add_element (OstreeBloom *bloom, for (i = 0; i < bloom->k; i++) { - gsize idx = bloom->hash_func (element, i); - ostree_bloom_set_bit (bloom, idx % (bloom->n_bytes * 8)); + guint64 idx = bloom->hash_func (element, i); + ostree_bloom_set_bit (bloom, (gsize) (idx % (bloom->n_bytes * 8))); } } From 1f666eb07dfc994e1459d4c07b54bc857b961f49 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Sun, 1 Oct 2017 00:13:17 +0100 Subject: [PATCH 74/78] lib/bloom: Fix a -Wconversion warning in OstreeBloom Compiling with -Wconversion warns on this line, as the conversion from guint64 to guint8 is implicit (but safe: there is no bug here, since the implicit cast is applied after the modulus arithmetic). Make the cast explicit to silence -Wconversion. Signed-off-by: Philip Withnall Closes: #1231 Approved by: cgwalters --- src/libostree/ostree-bloom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-bloom.c b/src/libostree/ostree-bloom.c index 8defb176..9bd2ad28 100644 --- a/src/libostree/ostree-bloom.c +++ b/src/libostree/ostree-bloom.c @@ -246,7 +246,7 @@ ostree_bloom_set_bit (OstreeBloom *bloom, { g_assert (bloom->is_mutable); g_assert (idx / 8 < bloom->n_bytes); - bloom->mutable_bytes[idx / 8] |= (1 << (idx % 8)); + bloom->mutable_bytes[idx / 8] |= (guint8) (1 << (idx % 8)); } /** From d1a5652bdd2c1ec55b29a36a67b5278fb7eec876 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 11 Sep 2017 15:35:48 +0100 Subject: [PATCH 75/78] man: Fix a copypasta error in ostree-summary.xml Signed-off-by: Philip Withnall Closes: #1158 Approved by: cgwalters --- man/ostree-summary.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/ostree-summary.xml b/man/ostree-summary.xml index 4e897592..dd72a6ea 100644 --- a/man/ostree-summary.xml +++ b/man/ostree-summary.xml @@ -90,7 +90,7 @@ Boston, MA 02111-1307, USA. =KEYID - GPG Key ID to sign the delta with. + GPG Key ID to sign the summary with. From 16aa4d728a5c92fc44d35d29c631708d1cc31eec Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 11 Sep 2017 14:42:07 +0100 Subject: [PATCH 76/78] ostree/summary: Eliminate redundant gotos from error handling path There is no error handling to do, so just return everywhere instead. Signed-off-by: Philip Withnall Closes: #1158 Approved by: cgwalters --- src/ostree/ot-builtin-summary.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index aacd9bae..9d04753d 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -83,7 +83,6 @@ build_additional_metadata (const char * const *args, gboolean ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; OstreeDumpFlags flags = OSTREE_DUMP_NONE; @@ -91,24 +90,24 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError context = g_option_context_new ("Manage summary metadata"); if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) - goto out; + return FALSE; if (opt_update) { g_autoptr(GVariant) additional_metadata = NULL; if (!ostree_ensure_repo_writable (repo, error)) - goto out; + return FALSE; if (opt_metadata != NULL) { additional_metadata = build_additional_metadata ((const char * const *) opt_metadata, error); if (additional_metadata == NULL) - goto out; + return FALSE; } if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error)) - goto out; + return FALSE; if (opt_key_ids) { @@ -117,7 +116,7 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError opt_gpg_homedir, cancellable, error)) - goto out; + return FALSE; } } else if (opt_view) @@ -129,7 +128,7 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError summary_data = ot_file_mapat_bytes (repo->repo_dir_fd, "summary", error); if (!summary_data) - goto out; + return FALSE; ot_dump_summary_bytes (summary_data, flags); } @@ -137,10 +136,8 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No option specified; use -u to update summary"); - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } From feeb3548f4e00fb60481f9105c68e4f2322ab92a Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 11 Sep 2017 14:42:52 +0100 Subject: [PATCH 77/78] ostree/summary: Generate an ostree-metadata ref when updating summary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the new way of publishing repository metadata, rather than as additional-metadata in the summary file. The use of an ostree-metadata ref means that the metadata from multiple upstream collections is not conflated when doing P2P mirroring of many repositories. The new ref is only generated if the repository has a collection ID set. The old summary file continues to be generated for backwards compatibility (and because it continues to be the canonical ref → checksum map for the repository). The new code is only used if configured with --enable-experimental-api. Includes unit tests. Signed-off-by: Philip Withnall Closes: #1158 Approved by: cgwalters --- man/ostree-summary.xml | 11 +++- src/ostree/ot-builtin-summary.c | 91 +++++++++++++++++++++++++++++++++ tests/test-summary-update.sh | 19 +++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/man/ostree-summary.xml b/man/ostree-summary.xml index dd72a6ea..815d2b5a 100644 --- a/man/ostree-summary.xml +++ b/man/ostree-summary.xml @@ -83,7 +83,16 @@ Boston, MA 02111-1307, USA. your organisation or repository using a dot prefix. The values must be in GVariant text format. For example, exampleos.end-of-life "@t 1445385600". - + + + + + diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index 9d04753d..abd1f86c 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -106,6 +106,97 @@ ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError return FALSE; } +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + const char *collection_id = ostree_repo_get_collection_id (repo); +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + const char *collection_id = NULL; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + + /* Write out a new metadata commit for the repository. */ + if (collection_id != NULL) + { +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + OstreeCollectionRef collection_ref = { (gchar *) collection_id, (gchar *) OSTREE_REPO_METADATA_REF }; + g_autofree char *old_ostree_metadata_checksum = NULL; + g_autofree gchar *new_ostree_metadata_checksum = NULL; + g_autoptr(OstreeMutableTree) mtree = NULL; + g_autoptr(OstreeRepoFile) repo_file = NULL; + g_autoptr(GVariantDict) new_summary_commit_dict = NULL; + g_autoptr(GVariant) new_summary_commit = NULL; + + if (!ostree_repo_resolve_rev (repo, OSTREE_REPO_METADATA_REF, + TRUE, &old_ostree_metadata_checksum, error)) + return FALSE; + + /* Add bindings to the metadata. */ + new_summary_commit_dict = g_variant_dict_new (additional_metadata); + g_variant_dict_insert (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, + "s", collection_ref.collection_id); + g_variant_dict_insert_value (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_REF_BINDING, + g_variant_new_strv ((const gchar * const *) &collection_ref.ref_name, 1)); + new_summary_commit = g_variant_dict_end (new_summary_commit_dict); + + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return FALSE; + + /* Set up an empty mtree. */ + mtree = ostree_mutable_tree_new (); + + glnx_unref_object GFileInfo *fi = g_file_info_new (); + g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::mode", (0755 | S_IFDIR)); + + g_autofree guchar *csum_raw = NULL; + g_autofree char *csum = NULL; + + g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (fi, NULL /* xattrs */); + + if (!ostree_repo_write_metadata (repo, OSTREE_OBJECT_TYPE_DIR_META, NULL, + dirmeta, &csum_raw, cancellable, error)) + return FALSE; + + csum = ostree_checksum_from_bytes (csum_raw); + ostree_mutable_tree_set_metadata_checksum (mtree, csum); + + if (!ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, error)) + return FALSE; + + if (!ostree_repo_write_commit (repo, old_ostree_metadata_checksum, + NULL /* subject */, NULL /* body */, + new_summary_commit, repo_file, &new_ostree_metadata_checksum, + NULL, error)) + return FALSE; + + if (opt_key_ids != NULL) + { + for (const char * const *iter = (const char * const *) opt_key_ids; + iter != NULL && *iter != NULL; iter++) + { + const char *key_id = *iter; + + if (!ostree_repo_sign_commit (repo, + new_ostree_metadata_checksum, + key_id, + opt_gpg_homedir, + cancellable, + error)) + return FALSE; + } + } + + ostree_repo_transaction_set_collection_ref (repo, &collection_ref, + new_ostree_metadata_checksum); + + if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) + return FALSE; +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + g_assert_not_reached (); + return FALSE; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + } + + /* Regenerate and sign the conventional summary file. */ if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error)) return FALSE; diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index 457debbe..60228114 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -91,4 +91,23 @@ ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata=map='@a{sv} {}' ${CMD_PREFIX} ostree --repo=repo summary --view > summary assert_file_has_content summary "^map: {}$" +# Check the ostree-metadata ref has also been created with the same content and appropriate bindings. +${CMD_PREFIX} ostree --repo=repo refs --collections > refs +assert_file_has_content refs "^(org.example.Collection1, ostree-metadata)$" + +${CMD_PREFIX} ostree --repo=repo show ostree-metadata --raw > metadata +assert_file_has_content metadata "'map': <@a{sv} {}>" +assert_file_has_content metadata "'ostree.ref-binding': <\['ostree-metadata'\]>" +assert_file_has_content metadata "'ostree.collection-binding': <'org.example.Collection1'>" + +# There should be 5 commits in the ostree-metadata branch, since we’ve updated the summary 5 times. +${CMD_PREFIX} ostree --repo=repo log ostree-metadata | grep 'commit ' | wc -l > commit-count +assert_file_has_content commit-count "^5$" + +# The ostree-metadata commits should not contain any files +${CMD_PREFIX} ostree --repo=repo ls ostree-metadata > files +assert_file_has_content files " /$" +cat files | wc -l > files-count +assert_file_has_content files-count "^1$" + echo "ok 2 update summary with collections" From 64f3257d8832edf6855052b5c8a3fc5250279499 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 2 Oct 2017 10:21:27 -0400 Subject: [PATCH 78/78] Release 2017.12 Closes: #1234 Approved by: jlebon --- configure.ac | 2 +- src/libostree/libostree-devel.sym | 8 ++------ src/libostree/libostree-released.sym | 6 ++++++ tests/test-symbols.sh | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 2a248bc5..e6980f7b 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ m4_define([year_version], [2017]) m4_define([release_version], [12]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=no +is_release_build=yes AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 1462a647..896d2b75 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -18,12 +18,8 @@ ***/ /* Add new symbols here. Release commits should copy this section into -released.sym. */ -LIBOSTREE_2017.12 { -global: - ostree_repo_equal; - ostree_repo_hash; -} LIBOSTREE_2017.11; - +LIBOSTREE_2017.13 { +} LIBOSTREE_2017.12; /* Stub section for the stable release *after* this development one; don't * edit this other than to update the last number. This is just a copy/paste diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 03cb952d..d1465290 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -430,6 +430,12 @@ LIBOSTREE_2017.10 { LIBOSTREE_2017.11 { } LIBOSTREE_2017.10; +LIBOSTREE_2017.12 { +global: + ostree_repo_equal; + ostree_repo_hash; +} LIBOSTREE_2017.11; + /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. */ diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index f54b64ee..c7b3124c 100755 --- a/tests/test-symbols.sh +++ b/tests/test-symbols.sh @@ -52,7 +52,7 @@ echo 'ok documented symbols' # ONLY update this checksum in release commits! cat > released-sha256.txt <