From 4ebcd57fec0a6e79a40dc18991839afa7ba482bc Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 8 Jul 2016 13:51:36 -0700 Subject: [PATCH 01/76] repo: Fix annotation for ostree_repo_add_gpg_signature_summary GI needs to know this is a NULL terminated array of gchar or you'll segfault using it from a binding. Closes: #387 Approved by: cgwalters --- 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 99dbb581..89d976b2 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4219,7 +4219,7 @@ ostree_repo_sign_delta (OstreeRepo *self, /** * ostree_repo_add_gpg_signature_summary: * @self: Self - * @key_id: NULL-terminated array of GPG keys. + * @key_id: (array zero-terminated=1) (element-type utf8): NULL-terminated array of GPG keys. * @homedir: (allow-none): GPG home directory, or %NULL * @cancellable: A #GCancellable * @error: a #GError From 35b4131bd7cc8164c70cf79d3f8ae566902b43a0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 8 Jul 2016 10:54:11 -0400 Subject: [PATCH 02/76] tests: Fix karg tests on ostree-booted system https://github.com/ostreedev/ostree/pull/372 caused these tests to start failing when the host system is managed using ostree - since the tests *do* replace the `ostree=` kernel argument. Closes: #384 Approved by: cgwalters --- tests/test-admin-deploy-karg.sh | 7 ++++++- tests/test-admin-instutil-set-kargs.sh | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/test-admin-deploy-karg.sh b/tests/test-admin-deploy-karg.sh index 1165b428..b7305f4c 100755 --- a/tests/test-admin-deploy-karg.sh +++ b/tests/test-admin-deploy-karg.sh @@ -44,7 +44,12 @@ echo "ok deploy with --karg, but same config" ${CMD_PREFIX} ostree admin deploy --karg-proc-cmdline --os=testos testos:testos/buildmaster/x86_64-runtime for arg in $(cat /proc/cmdline); do - assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg" + case "$arg" in + ostree=*) # Skip ostree arg that gets stripped out + ;; + *) assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg" + ;; + esac done echo "ok deploy --karg-proc-cmdline" diff --git a/tests/test-admin-instutil-set-kargs.sh b/tests/test-admin-instutil-set-kargs.sh index d2abec2e..40f4b746 100755 --- a/tests/test-admin-instutil-set-kargs.sh +++ b/tests/test-admin-instutil-set-kargs.sh @@ -55,6 +55,11 @@ echo "ok instutil set-kargs --append" ${CMD_PREFIX} ostree admin instutil set-kargs --import-proc-cmdline for arg in $(cat /proc/cmdline); do - assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg" + case "$arg" in + ostree=*) # Skip ostree arg that gets stripped out + ;; + *) assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf "options.*$arg" + ;; + esac done echo "ok instutil set-kargs --import-proc-cmdline" From 87c9e227cb84b8c720a41bc228beeb1b6f9b09c4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 11 Jul 2016 15:18:34 -0400 Subject: [PATCH 03/76] Revert "tests/libtest.sh: Print non-matching file on failure" This reverts commit 71301d18244a3a26a6ba6fd3934633ef94811a15. I was confused by the fact that the non-matching content was empty and forgot we already did print it. Reported-by: smcv Closes: #390 Approved by: jlebon --- tests/libtest.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index e93b9510..2d064299 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -138,7 +138,6 @@ assert_file_has_content () { if ! grep -q -e "$2" "$1"; then sed -e 's/^/# /' < "$1" >&2 echo 1>&2 "File '$1' doesn't match regexp '$2'" - cat $1 exit 1 fi } From f45eca948c98c57965dd9cf703f46f2ae405e349 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 12 Jul 2016 09:43:32 -0400 Subject: [PATCH 04/76] repo: Ensure we set mode for bare-user files before xattrs When trying to switch ostree to `O_TMPFILE`, I hit the fact that by default it uses mode `000`. It still works to write to the open fd of course, but it *doesn't* work to set xattrs because that code path for some reason in the kernel checks the mode bits. This only broke for bare-user repos where we tried to set the xattr before calling `fchmod()`, so just invert those two operations. Closes: #391 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 662ee21e..fcfe487a 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -240,15 +240,13 @@ commit_loose_object_trusted (OstreeRepo *self, if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE_USER) { - if (!write_file_metadata_to_xattr (fd, uid, gid, mode, xattrs, error)) - goto out; - if (!object_is_symlink) { /* We need to apply at least some mode bits, because the repo file was created with mode 644, and we need e.g. exec bits to be right when we do a user-mode checkout. To make this work we apply all user bits and the read bits for - group/other */ + group/other. Furthermore, setting user xattrs requires write access, so + this makes sure it's at least writable by us. (O_TMPFILE uses mode 0 by default) */ do res = fchmod (fd, mode | 0744); while (G_UNLIKELY (res == -1 && errno == EINTR)); @@ -258,6 +256,9 @@ commit_loose_object_trusted (OstreeRepo *self, goto out; } } + + if (!write_file_metadata_to_xattr (fd, uid, gid, mode, xattrs, error)) + goto out; } if (objtype == OSTREE_OBJECT_TYPE_FILE && (self->mode == OSTREE_REPO_MODE_BARE || From efa1fa65341ac934b2fb78f9b9bc3ce61b38d655 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 13 Jul 2016 11:46:16 -0400 Subject: [PATCH 05/76] builtins/commit: Switch to using ostree_repo_write_dfd_to_mtree() Where we're referencing local files. It's what ostree_repo_write_directory_to_mtree() is doing internally anyways, and I consider the `GFile*` based APIs to be generally deprecated for the most part. Closes: #394 Approved by: giuseppe --- src/ostree/ot-builtin-commit.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index ec3ca960..fa829817 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -455,12 +455,8 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError if (argc <= 1 && (opt_trees == NULL || opt_trees[0] == NULL)) { - char *current_dir = g_get_current_dir (); - object_to_commit = g_file_new_for_path (current_dir); - g_free (current_dir); - - if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier, - cancellable, error)) + if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, modifier, + cancellable, error)) goto out; } else if (opt_trees != NULL) @@ -487,9 +483,8 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError g_clear_object (&object_to_commit); if (strcmp (tree_type, "dir") == 0) { - object_to_commit = g_file_new_for_path (tree); - if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier, - cancellable, error)) + if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, tree, mtree, modifier, + cancellable, error)) goto out; } else if (strcmp (tree_type, "tar") == 0) @@ -520,9 +515,8 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError else { g_assert (argc > 1); - object_to_commit = g_file_new_for_path (argv[1]); - if (!ostree_repo_write_directory_to_mtree (repo, object_to_commit, mtree, modifier, - cancellable, error)) + if (!ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, argv[1], mtree, modifier, + cancellable, error)) goto out; } From 307f4b2957d0416604b1b0f9e74d72fd695c7137 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 14 Jul 2016 13:42:32 +0200 Subject: [PATCH 06/76] Makefile-tests.am: make check uses the built binaries The tests suite was failing locally as it was using the installed version of rofiles-fuse, instead of the built one. Create the needed symlinks in tests/ as we are already doing for the "ostree" binary. ostree-prepare-root and ostree-remount added for completeness. Signed-off-by: Giuseppe Scrivano Closes: #395 Approved by: cgwalters --- Makefile-tests.am | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Makefile-tests.am b/Makefile-tests.am index e274c5e6..0b6b64e9 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -33,7 +33,8 @@ TESTS_ENVIRONMENT += OT_TESTS_DEBUG=1 \ PATH=$$(cd $(top_builddir)/tests && pwd):$${PATH} \ $(NULL) -uninstalled_test_data = tests/ostree-symlink-stamp +uninstalled_test_data = tests/ostree-symlink-stamp tests/ostree-prepare-root-symlink-stamp \ + tests/ostree-remount-symlink-stamp tests/rofiles-fuse-symlink-stamp dist_uninstalled_test_scripts = tests/test-symbols.sh @@ -238,12 +239,19 @@ EXTRA_DIST += \ tests/libreaddir-rand.so: Makefile $(AM_V_GEN) ln -fns ../.libs/libreaddir-rand.so tests ALL_LOCAL_RULES += tests/libreaddir-rand.so -CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp tests/ostree +CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp \ + tests/ostree-prepare-root-symlink-stamp tests/ostree-remount-symlink-stamp \ + tests/rofiles-fuse-symlink-stamp tests/ostree -tests/ostree-symlink-stamp: Makefile +tests/%-symlink-stamp: Makefile @set -e; \ - real_bin=`cd $(top_builddir) && ./libtool --mode=execute echo ostree`; \ - ln -sf "$${real_bin}" tests/ostree; \ + lt_bin=`cd $(top_builddir) && ./libtool --mode=execute echo $*`; \ + if test "$${lt_bin}" = "$*"; then \ + real_bin=$(abs_top_builddir)/$*; \ + else \ + real_bin="$${lt_bin}"; \ + fi; \ + ln -sf "$${real_bin}" tests/$*; \ touch $@ # Unfortunately the glib test data APIs don't actually handle From 203c0c88dbbdaecef9056641f4629f28133d0e7c Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Thu, 14 Jul 2016 16:10:55 -0400 Subject: [PATCH 07/76] README: Fix broken link Closes: #397 Approved by: cgwalters --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index caa8503d..369a8925 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ However, in order to build from a git clone, you must update the submodules. If you're packaging OSTree and want a tarball, I recommend using a "recursive git archive" script. There are several available online; -[this code](https://git.gnome.org/browse/ostree/tree/packaging/Makefile.dist-packaging#n11) +[this code](https://github.com/ostreedev/ostree/blob/master/packaging/Makefile.dist-packaging#L11) in OSTree is an example. Once you have a git clone or recursive archive, building is the From 2e97e721230c52a5e980f1567a988a5c355289c0 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 14 Jul 2016 12:45:39 -0700 Subject: [PATCH 08/76] lib: Fix version script node ordering The order of the VERSION nodes is such that the new node name goes first and the one it depends on goes after the commands. See https://sourceware.org/binutils/docs/ld/VERSION.html. Closes: #398 Approved by: cgwalters --- src/libostree/libostree.sym | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 702968a9..f26be3f0 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -352,8 +352,8 @@ global: */ /* UNCOMMENT WHEN ADDING THE FIRST NEW SYMBOL FOR 2016.8 -LIBOSTREE_2016.7 { +LIBOSTREE_2016.8 { global: insert_symbol_here; -} LIBOSTREE_2016.8; +} LIBOSTREE_2016.7; */ From db974b0596a881f545c62de11fc95b68c4890f75 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 14 Jul 2016 09:09:12 -0700 Subject: [PATCH 09/76] core: Add allocating b64 checksum functions The checksum_b64_inplace variants can't be used in bindings. Provide versions that allocate and return the output rather than working on a passed in buffer. These can then be used in GI bindings to get the ostree modified base64 encodings. Closes: #398 Approved by: cgwalters --- apidoc/ostree-sections.txt | 2 ++ src/libostree/libostree.sym | 5 ++--- src/libostree/ostree-core.c | 31 +++++++++++++++++++++++++++++++ src/libostree/ostree-core.h | 4 ++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index cc77f15a..8b6337f7 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -99,6 +99,8 @@ ostree_checksum_inplace_from_bytes ostree_checksum_inplace_to_bytes ostree_checksum_bytes_peek ostree_checksum_bytes_peek_validate +ostree_checksum_b64_from_bytes +ostree_checksum_b64_to_bytes ostree_checksum_b64_inplace_from_bytes ostree_checksum_b64_inplace_to_bytes ostree_cmp_checksum_bytes diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index f26be3f0..04e36453 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -351,9 +351,8 @@ global: * NOTE NOTE NOTE */ -/* UNCOMMENT WHEN ADDING THE FIRST NEW SYMBOL FOR 2016.8 LIBOSTREE_2016.8 { global: - insert_symbol_here; + ostree_checksum_b64_to_bytes; + ostree_checksum_b64_from_bytes; } LIBOSTREE_2016.7; -*/ diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 32f0fd44..bf4d62a8 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1272,6 +1272,20 @@ ostree_checksum_to_bytes_v (const char *checksum) return ot_gvariant_new_bytearray ((guchar*)result, OSTREE_SHA256_DIGEST_LEN); } +/** + * ostree_checksum_b64_to_bytes: + * @checksum: An ASCII checksum + * + * Returns: (transfer full) (array fixed-size=32): Binary version of @checksum. + */ +guchar * +ostree_checksum_b64_to_bytes (const char *checksum) +{ + guchar *ret = g_malloc (32); + ostree_checksum_b64_inplace_to_bytes (checksum, ret); + return ret; +} + /** * ostree_checksum_inplace_from_bytes: (skip) * @csum: (array fixed-size=32): An binary checksum of length 32 @@ -1363,6 +1377,23 @@ ostree_checksum_from_bytes_v (GVariant *csum_v) return ostree_checksum_from_bytes (ostree_checksum_bytes_peek (csum_v)); } +/** + * ostree_checksum_b64_from_bytes: + * @csum: (array fixed-size=32): An binary checksum of length 32 + * + * Returns: (transfer full): Modified base64 encoding of @csum + * + * The "modified" term refers to the fact that instead of '/', the '_' + * character is used. + */ +char * +ostree_checksum_b64_from_bytes (const guchar *csum) +{ + char *ret = g_malloc (44); + ostree_checksum_b64_inplace_from_bytes (csum, ret); + return ret; +} + /** * ostree_checksum_bytes_peek: * @bytes: #GVariant of type ay diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index 415369d5..d1f76cf1 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -192,6 +192,8 @@ guchar *ostree_checksum_to_bytes (const char *checksum); _OSTREE_PUBLIC GVariant *ostree_checksum_to_bytes_v (const char *checksum); _OSTREE_PUBLIC +guchar *ostree_checksum_b64_to_bytes (const char *checksum); +_OSTREE_PUBLIC void ostree_checksum_b64_inplace_to_bytes (const char *checksum, guint8 *buf); @@ -199,6 +201,8 @@ _OSTREE_PUBLIC char * ostree_checksum_from_bytes (const guchar *csum); _OSTREE_PUBLIC char * ostree_checksum_from_bytes_v (GVariant *csum_v); +_OSTREE_PUBLIC +char * ostree_checksum_b64_from_bytes (const guchar *csum); _OSTREE_PUBLIC void ostree_checksum_inplace_from_bytes (const guchar *csum, From 29451a39994ba54c2d41887b84342af9e3632b19 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 15 Jul 2016 11:17:43 -0400 Subject: [PATCH 10/76] build: Make symlink depend on source Closes: https://github.com/ostreedev/ostree/issues/389 Closes: #400 Approved by: smcv --- Makefile-tests.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile-tests.am b/Makefile-tests.am index 0b6b64e9..63d11ec8 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -243,8 +243,8 @@ CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp \ tests/ostree-prepare-root-symlink-stamp tests/ostree-remount-symlink-stamp \ tests/rofiles-fuse-symlink-stamp tests/ostree -tests/%-symlink-stamp: Makefile - @set -e; \ +tests/%-symlink-stamp: % Makefile + $(AM_V_GEN) set -e; \ lt_bin=`cd $(top_builddir) && ./libtool --mode=execute echo $*`; \ if test "$${lt_bin}" = "$*"; then \ real_bin=$(abs_top_builddir)/$*; \ From d49d42b983483f990460f64af59b7d6b9266f058 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 19 Jul 2016 10:24:18 -0400 Subject: [PATCH 11/76] docs/formats: Elaborate a bit on delta from NULL usage See discussion on ostree-list. Closes: #402 Approved by: gatispaeglis --- docs/manual/formats.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/manual/formats.md b/docs/manual/formats.md index 87d0005f..e3fe00e1 100644 --- a/docs/manual/formats.md +++ b/docs/manual/formats.md @@ -79,7 +79,10 @@ concept of a "static delta". These deltas are targeted to be a delta between two specific commit objects, including "bsdiff" and "rsync-style" deltas within a content object. Static deltas also support `from NULL`, where the client can -more efficiently download a commit object from scratch. +more efficiently download a commit object from scratch - this is +mostly useful when using OSTree for containers, rather than OS images. +For OS images, one tends to download an installer ISO or qcow2 image +which is a single file that contains the tree data already. Effectively, we're spending server-side storage (and one-time compute cost), and gaining efficiency in client network bandwidth. From f3cbe86117d8e68e4dc02c597da59588be31f7e2 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 22 Jul 2016 09:34:32 -0400 Subject: [PATCH 12/76] libglnx: bump to latest OSTree can sometimes print very long lines which lead to many empty spaces getting printed if the output overflowed the line due to a bug in libglnx. Reported-by: Gatis Paeglis Closes: #406 Approved by: cgwalters --- libglnx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libglnx b/libglnx index a6d08657..c072ef1e 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit a6d08657aa868a0d5c7b5dd494e16f65415a148f +Subproject commit c072ef1ebab052bdecb0d9a52c14813728f83859 From a6aeacede6de0dd8bb8b9fae3350973fadca6073 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 8 Jul 2016 11:26:45 -0400 Subject: [PATCH 13/76] repo: Fix leak with ostree_repo_commit_traverse_iter_init_commit() I noticed this using `OT_TEST_VALGRIND=1` on `test-basic.sh`. Closes: #385 Approved by: jlebon --- src/libostree/ostree-repo-traverse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libostree/ostree-repo-traverse.c b/src/libostree/ostree-repo-traverse.c index 4cc05e2e..516f39f5 100644 --- a/src/libostree/ostree-repo-traverse.c +++ b/src/libostree/ostree-repo-traverse.c @@ -264,6 +264,7 @@ ostree_repo_commit_traverse_iter_clear (OstreeRepoCommitTraverseIter *iter) { struct _OstreeRepoRealCommitTraverseIter *real = (struct _OstreeRepoRealCommitTraverseIter*)iter; + g_clear_object (&real->repo); g_clear_pointer (&real->commit, g_variant_unref); g_clear_pointer (&real->current_dir, g_variant_unref); } From bac1fa18390da157e8b9aa9014b4e901af8d7fce Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 22 Jul 2016 16:58:26 -0400 Subject: [PATCH 14/76] pull: Don't execute static deltas when mirroring We don't presently support this, since the static delta code assumes it can just `mmap()` file objects. We could at some point implement this, but for now just skip executing deltas when doing `archive -> archive` mirroring. I noticed this when trying to mirror a repo in Jenkins in [CAHC](https://wiki.centos.org/SpecialInterestGroup/Atomic/Devel). Closes: #408 Approved by: giuseppe --- src/libostree/ostree-repo-pull.c | 3 ++- tests/pull-test.sh | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 82bf66f6..0d342d3f 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -2705,7 +2705,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, &from_revision, error)) goto out; - if (!disable_static_deltas && (from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0)) + if (!disable_static_deltas && !pull_data->is_mirror && + (from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0)) { if (!request_static_delta_superblock_sync (pull_data, from_revision, to_revision, &delta_superblock, cancellable, error)) diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 8e8a6934..b050e111 100755 --- 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..11" +echo "1..12" # Try both syntaxes repo_init @@ -57,6 +57,17 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo fsck $OSTREE show main >/dev/null echo "ok pull mirror" +cd ${test_tmpdir} +rm checkout-origin-main -rf +$OSTREE --repo=ostree-srv/gnomerepo checkout main checkout-origin-main +echo moomoo > checkout-origin-main/baz/cow +${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b main -s "" --tree=dir=checkout-origin-main +${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo static-delta generate main +${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo fsck +${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror origin main +${CMD_PREFIX} ostree --repo=mirrorrepo fsck +echo "ok pull mirror (should not apply deltas)" + cd ${test_tmpdir} mkdir mirrorrepo-local ${CMD_PREFIX} ostree --repo=mirrorrepo-local init --mode=archive-z2 From 7f335a843797ac0c103be6883832886a1a02a399 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 14:54:07 -0400 Subject: [PATCH 15/76] trivial-httpd: Fix leak of option context Right now our valgrind runs also end up valgrinding the `trivial-httpd` code, so while it doesn't matter, let's fix this leak anyways. We need to avoid calling `_exit()` since that won't run the cleanup functions. Closes: #410 Approved by: giuseppe --- src/ostree/ot-builtin-trivial-httpd.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ostree/ot-builtin-trivial-httpd.c b/src/ostree/ot-builtin-trivial-httpd.c index 5b942cd5..30c593c2 100644 --- a/src/ostree/ot-builtin-trivial-httpd.c +++ b/src/ostree/ot-builtin-trivial-httpd.c @@ -386,7 +386,7 @@ gboolean ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; - GOptionContext *context; + g_autoptr(GOptionContext) context = NULL; const char *dirpath; OtTrivialHttpd appstruct = { 0, }; OtTrivialHttpd *app = &appstruct; @@ -501,8 +501,8 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable, } else if (pid > 0) { - /* Parent */ - _exit (0); + ret = TRUE; + goto out; } /* Child, continue */ /* Daemonising: close stdout/stderr so $() et al work on us */ @@ -559,7 +559,5 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable, out: g_clear_object (&app->root); g_clear_object (&app->log); - if (context) - g_option_context_free (context); return ret; } From d13cf37b3f19982e2089fb6cea17824acb9a8828 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 14:59:33 -0400 Subject: [PATCH 16/76] glib.supp: Suppress some dynamic type registrations too These mirror the static ones, and we need the dynamic versions for glib-networking -> gnutls stuff. Closes: #410 Approved by: giuseppe --- tests/glib.supp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/glib.supp b/tests/glib.supp index 33449070..8129c3e2 100644 --- a/tests/glib.supp +++ b/tests/glib.supp @@ -15,6 +15,12 @@ ... fun:g_type_register_static } +{ + g_type_register_dynamic + Memcheck:Leak + ... + fun:g_type_register_dynamic +} { g_type_register_fundamental Memcheck:Leak @@ -49,6 +55,12 @@ ... fun:g_type_add_interface_static } +{ + g_type_add_interface_dynamic + Memcheck:Leak + ... + fun:g_type_add_interface_dynamic +} { g_param_spec_internal Memcheck:Leak From 35008ead771a7b84128a0fb275af3ca9367a3571 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:00:02 -0400 Subject: [PATCH 17/76] pull-local: Explicitly unref variant rather than relying on floating This shows up as a leak in valgrind; the callee isn't sinking. In general through the power of cleanup attributes we can do explicit cleanup rather than relying on floating refs. Closes: #410 Approved by: giuseppe --- src/ostree/ot-builtin-pull-local.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index 7fb6f03a..b6f649f6 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -132,6 +132,7 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr } { GVariantBuilder builder; + g_autoptr(GVariant) opts = NULL; g_auto(GLnxConsoleRef) console = { 0, }; glnx_console_lock (&console); @@ -157,8 +158,9 @@ 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); + opts = g_variant_ref_sink (g_variant_builder_end (&builder)); if (!ostree_repo_pull_with_options (repo, src_repo_uri, - g_variant_builder_end (&builder), + opts, progress, cancellable, error)) goto out; From 544365f834eecc4138001be02bbc10064a537685 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:10:55 -0400 Subject: [PATCH 18/76] glib.supp: Suppress worker context -> thread bits The worker context isn't cleaned up now. Closes: #410 Approved by: giuseppe --- tests/glib.supp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/glib.supp b/tests/glib.supp index 8129c3e2..f76596a0 100644 --- a/tests/glib.supp +++ b/tests/glib.supp @@ -545,3 +545,10 @@ ... fun:glib_worker_main } +{ + glib_worker_2 + Memcheck:Leak + ... + fun:g_thread_new + fun:g_get_worker_context +} From ba21023d6cd28dca6377b8bf425fc5fa489f5fe7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:11:17 -0400 Subject: [PATCH 19/76] fetcher: Explicitly join thread if it's not self This fixes a valgrind leak; see [this StackOverflow thread](http://stackoverflow.com/questions/17642433/why-pthread-causes-a-memory-leak). Closes: #410 Approved by: giuseppe --- src/libostree/ostree-fetcher.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-fetcher.c b/src/libostree/ostree-fetcher.c index 865c7b76..bde6ed9a 100644 --- a/src/libostree/ostree-fetcher.c +++ b/src/libostree/ostree-fetcher.c @@ -540,7 +540,14 @@ _ostree_fetcher_finalize (GObject *object) /* Terminate the session thread. */ g_main_loop_quit (self->thread_closure->main_loop); - g_clear_pointer (&self->session_thread, g_thread_unref); + if (self->session_thread) + { + /* We need to explicitly synchronize to clean up TLS */ + if (self->session_thread != g_thread_self ()) + g_thread_join (self->session_thread); + else + g_clear_pointer (&self->session_thread, g_thread_unref); + } g_clear_pointer (&self->thread_closure, thread_closure_unref); G_OBJECT_CLASS (_ostree_fetcher_parent_class)->finalize (object); From 402020b4ca5853a8d85d2a051036d36f316db233 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:26:11 -0400 Subject: [PATCH 20/76] glib.supp: Suppress g_task -> thread leaks There are variants of this, but right now because `GTask` has its own pool which isn't necessarily cleaned up on exit, we need to suppress all of this. Closes: #410 Approved by: giuseppe --- tests/glib.supp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/glib.supp b/tests/glib.supp index f76596a0..7ac6ed87 100644 --- a/tests/glib.supp +++ b/tests/glib.supp @@ -400,6 +400,14 @@ fun:g_thread_pool_push fun:g_task_start_task_thread } +{ + g_task_to_pool + Memcheck:Leak + ... + fun:g_thread_pool_start_thread + ... + fun:g_task_run_in_thread +} { g_get_language_names Memcheck:Leak From 707ef9309747dc8a429c42443d8c2c1adade18ed Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:40:22 -0400 Subject: [PATCH 21/76] sysroot: Fix a leak in deployment dirpath API This one is pretty obvious in retrospect. Closes: #410 Approved by: giuseppe --- src/libostree/ostree-sysroot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 7cc4c9f5..2a55c6b1 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1003,7 +1003,8 @@ GFile * ostree_sysroot_get_deployment_directory (OstreeSysroot *self, OstreeDeployment *deployment) { - return g_file_resolve_relative_path (self->path, ostree_sysroot_get_deployment_dirpath (self, deployment)); + g_autofree char *dirpath = ostree_sysroot_get_deployment_dirpath (self, deployment); + return g_file_resolve_relative_path (self->path, dirpath); } /** From 27559c58a980dabebabd93d7c522537b664e161d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:40:49 -0400 Subject: [PATCH 22/76] deploy: Fix leaks in parsing /etc/os-release This one is a bit subtle; we're generating a hash that contains pointers to the strings we parsed, so we need to carefully track ownership. Closes: #410 Approved by: giuseppe --- src/libostree/ostree-sysroot-deploy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index cc1a1faa..246a3412 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1244,13 +1244,13 @@ static GHashTable * parse_os_release (const char *contents, const char *split) { - char **lines = g_strsplit (contents, split, -1); + g_autofree char **lines = g_strsplit (contents, split, -1); char **iter; GHashTable *ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (iter = lines; *iter; iter++) { - char *line = *iter; + g_autofree char *line = *iter; char *eq; const char *quotedval; char *val; @@ -1268,7 +1268,7 @@ parse_os_release (const char *contents, if (!val) continue; - g_hash_table_insert (ret, line, val); + g_hash_table_insert (ret, g_steal_pointer (&line), val); } return ret; From a38f2f41b2e7fa357227178f936f6e7475d54f80 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 24 Jul 2016 15:45:02 -0400 Subject: [PATCH 23/76] lib: Fix leak in bootconfig parser Pretty simple. Closes: #410 Approved by: giuseppe --- src/libostree/ostree-bootconfig-parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-bootconfig-parser.c b/src/libostree/ostree-bootconfig-parser.c index 661e759d..6ca4df1d 100644 --- a/src/libostree/ostree-bootconfig-parser.c +++ b/src/libostree/ostree-bootconfig-parser.c @@ -244,7 +244,7 @@ static void ostree_bootconfig_parser_init (OstreeBootconfigParser *self) { self->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - self->lines = g_ptr_array_new (); + self->lines = g_ptr_array_new_with_free_func (g_variant_unref); } void From fc25fa16e1c1195de1a36a17ffcff7eaf5bccd1c Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 28 Jul 2016 09:57:48 -0400 Subject: [PATCH 24/76] lib: Fix compiler warning from previous patch I had this in a `fixup!` I thought. Closes: #414 Approved by: giuseppe --- src/libostree/ostree-bootconfig-parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-bootconfig-parser.c b/src/libostree/ostree-bootconfig-parser.c index 6ca4df1d..f7728e42 100644 --- a/src/libostree/ostree-bootconfig-parser.c +++ b/src/libostree/ostree-bootconfig-parser.c @@ -244,7 +244,7 @@ static void ostree_bootconfig_parser_init (OstreeBootconfigParser *self) { self->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - self->lines = g_ptr_array_new_with_free_func (g_variant_unref); + self->lines = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref); } void From fb0bf27d100943311204c343d458f1fa9c3e6d65 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 28 Jul 2016 21:06:38 -0400 Subject: [PATCH 25/76] tests/delta-crosscheck: Add missing --from Otherwise we generate a static delta from the *previous* and get confused. To make doubly sure, add `--require-static-deltas` to pull. Closes: #416 Approved by: jlebon --- manual-tests/static-delta-generate-crosscheck.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manual-tests/static-delta-generate-crosscheck.sh b/manual-tests/static-delta-generate-crosscheck.sh index fbcbe677..831e0b62 100755 --- a/manual-tests/static-delta-generate-crosscheck.sh +++ b/manual-tests/static-delta-generate-crosscheck.sh @@ -45,10 +45,10 @@ validate_delta_options() { mkdir testrepo ostree --repo=testrepo init --mode=bare-user ostree --repo=testrepo remote add --set=gpg-verify=false local file://${repo} - ostree --repo=${repo} static-delta generate $@ ${from} ${to} - ostree --repo=testrepo pull local ${branch}@${from} + ostree --repo=${repo} static-delta generate $@ --from=${from} --to=${to} + ostree --repo=testrepo pull --require-static-deltas local ${branch}@${from} assert_streq $(ostree --repo=testrepo rev-parse ${branch}) ${from} - ostree --repo=testrepo pull local ${branch} + ostree --repo=testrepo pull --require-static-deltas local ${branch} assert_streq $(ostree --repo=testrepo rev-parse ${branch}) ${to} ostree --repo=testrepo fsck rm testrepo -rf From 6ffcb24d227eae5a479caf45adb8037eceb6ae33 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 11 Jul 2016 09:29:18 -0400 Subject: [PATCH 26/76] deltas: Handle untrusted checksums faster and more robustly When reworking the ostree core [to use O_TMPFILE](https://github.com/ostreedev/ostree/pull/369), I hit an issue in the way the untrusted delta codepath ends up trying to re-open the file to checksum it. That's not possible with `O_TMPFILE` since the fd (which we opened `O_WRONLY`) is the only accessible reference to the content. Fix this by changing the delta processing code to update a checksum as we're doing writes, which is also faster, and ends up simplifying the code as well. What would be an even larger simplification here is if we e.g. used a separate thread calling `write_object()` or something like that; the main issue I see there is somehow bridging the fact that function wants a `GInputStream*` but the delta code is generating stream of writes. Closes: #392 Approved by: jlebon --- src/libostree/ostree-core-private.h | 4 + src/libostree/ostree-core.c | 10 +- src/libostree/ostree-repo-commit.c | 111 +---------- src/libostree/ostree-repo-private.h | 16 +- .../ostree-repo-static-delta-processing.c | 180 ++++++++++-------- 5 files changed, 126 insertions(+), 195 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index b49e5e47..cb4d953d 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -63,6 +63,10 @@ G_BEGIN_DECLS */ #define _OSTREE_ZLIB_FILE_HEADER_GVARIANT_FORMAT G_VARIANT_TYPE ("(tuuuusa(ayay))") + +GVariant *_ostree_file_header_new (GFileInfo *file_info, + GVariant *xattrs); + GVariant *_ostree_zlib_file_header_new (GFileInfo *file_info, GVariant *xattrs); diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index bf4d62a8..6e3c4e2e 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -203,9 +203,9 @@ ostree_validate_rev (const char *rev, return ret; } -static GVariant * -file_header_new (GFileInfo *file_info, - GVariant *xattrs) +GVariant * +_ostree_file_header_new (GFileInfo *file_info, + GVariant *xattrs) { guint32 uid; guint32 gid; @@ -518,7 +518,7 @@ ostree_raw_file_to_content_stream (GInputStream *input, g_autoptr(GVariant) file_header = NULL; guint64 header_size; - file_header = file_header_new (file_info, xattrs); + file_header = _ostree_file_header_new (file_info, xattrs); if (!header_and_input_to_stream (file_header, input, out_input, @@ -772,7 +772,7 @@ ostree_checksum_file_from_input (GFileInfo *file_info, { g_autoptr(GVariant) file_header = NULL; - file_header = file_header_new (file_info, xattrs); + file_header = _ostree_file_header_new (file_info, xattrs); if (!write_file_header_update_checksum (NULL, file_header, checksum, cancellable, error)) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index fcfe487a..0f9a4fb7 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -446,109 +446,14 @@ fallocate_stream (GFileDescriptorBased *stream, } gboolean -_ostree_repo_open_untrusted_content_bare (OstreeRepo *self, - const char *expected_checksum, - guint64 content_len, - OstreeRepoContentBareCommit *out_state, - GOutputStream **out_stream, - gboolean *out_have_object, - GCancellable *cancellable, - GError **error) -{ - /* The trusted codepath is fine here */ - return _ostree_repo_open_trusted_content_bare (self, - expected_checksum, - content_len, - out_state, - out_stream, - out_have_object, - cancellable, - error); -} - -gboolean -_ostree_repo_commit_untrusted_content_bare (OstreeRepo *self, - const char *expected_checksum, - OstreeRepoContentBareCommit *state, - guint32 uid, - guint32 gid, - guint32 mode, - GVariant *xattrs, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - - if (state->fd != -1) - { - GMappedFile *mapped; - g_autoptr(GBytes) bytes = NULL; - g_autoptr(GInputStream) raw_in = NULL; - g_autoptr(GInputStream) in = NULL; - g_autoptr(GFileInfo) file_info = NULL; - g_autofree guchar *actual_csum = NULL; - g_autofree char *actual_checksum = NULL; - int fd; - - fd = openat (self->tmp_dir_fd, state->temp_filename, O_RDONLY); - if (fd == -1) - { - glnx_set_error_from_errno (error); - goto out; - } - - mapped = g_mapped_file_new_from_fd (fd, FALSE, error); - - close (fd); - if (mapped == NULL) - goto out; - - bytes = g_mapped_file_get_bytes (mapped); - g_mapped_file_unref (mapped); - - raw_in = g_memory_input_stream_new_from_bytes (bytes); - - file_info = _ostree_header_gfile_info_new (mode, uid, gid); - - if (!ostree_raw_file_to_content_stream (raw_in, file_info, xattrs, &in, NULL, cancellable, error)) - goto out; - - if (!ot_gio_checksum_stream (in, &actual_csum, cancellable, error)) - goto out; - - actual_checksum = ostree_checksum_from_bytes (actual_csum); - - if (strcmp (actual_checksum, expected_checksum) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Corrupted object %s (actual checksum is %s)", - expected_checksum, actual_checksum); - goto out; - } - - if (!commit_loose_object_trusted (self, expected_checksum, OSTREE_OBJECT_TYPE_FILE, - state->temp_filename, - FALSE, uid, gid, mode, - xattrs, state->fd, - cancellable, error)) - goto out; - } - - ret = TRUE; - out: - g_free (state->temp_filename); - return ret; -} - -gboolean -_ostree_repo_open_trusted_content_bare (OstreeRepo *self, - const char *checksum, - guint64 content_len, - OstreeRepoContentBareCommit *out_state, - GOutputStream **out_stream, - gboolean *out_have_object, - GCancellable *cancellable, - GError **error) +_ostree_repo_open_content_bare (OstreeRepo *self, + const char *checksum, + guint64 content_len, + OstreeRepoContentBareCommit *out_state, + GOutputStream **out_stream, + gboolean *out_have_object, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; g_autofree char *temp_filename = NULL; diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 52dbfdd5..d6996377 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -265,14 +265,14 @@ typedef struct { } OstreeRepoContentBareCommit; gboolean -_ostree_repo_open_trusted_content_bare (OstreeRepo *self, - const char *checksum, - guint64 content_len, - OstreeRepoContentBareCommit *out_state, - GOutputStream **out_stream, - gboolean *out_have_object, - GCancellable *cancellable, - GError **error); +_ostree_repo_open_content_bare (OstreeRepo *self, + const char *checksum, + guint64 content_len, + OstreeRepoContentBareCommit *out_state, + GOutputStream **out_stream, + gboolean *out_have_object, + GCancellable *cancellable, + GError **error); gboolean _ostree_repo_commit_trusted_content_bare (OstreeRepo *self, diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c index 871ab7bd..ea1aad17 100644 --- a/src/libostree/ostree-repo-static-delta-processing.c +++ b/src/libostree/ostree-repo-static-delta-processing.c @@ -60,6 +60,7 @@ typedef struct { OstreeRepoContentBareCommit barecommitstate; guint64 content_size; GOutputStream *content_out; + GChecksum *content_checksum; char checksum[OSTREE_SHA256_STRING_LEN+1]; char *read_source_object; int read_source_fd; @@ -386,6 +387,29 @@ validate_ofs (StaticDeltaExecutionState *state, return TRUE; } +static gboolean +content_out_write (OstreeRepo *repo, + StaticDeltaExecutionState *state, + const guint8* buf, + gsize len, + GCancellable *cancellable, + GError **error) +{ + gsize bytes_written; + + if (state->content_checksum) + g_checksum_update (state->content_checksum, buf, len); + + /* Ignore bytes_written since we discard partial content */ + if (!g_output_stream_write_all (state->content_out, + buf, len, + &bytes_written, + cancellable, error)) + return FALSE; + + return TRUE; +} + static gboolean do_content_open_generic (OstreeRepo *repo, StaticDeltaExecutionState *state, @@ -451,7 +475,6 @@ dispatch_bspatch (OstreeRepo *repo, g_autofree guchar *buf = NULL; struct bspatch_stream stream; struct bzpatch_opaque_s opaque; - gsize bytes_written; if (!read_varuint64 (state, &offset, error)) goto out; @@ -484,14 +507,9 @@ dispatch_bspatch (OstreeRepo *repo, &stream) < 0) goto out; - if (!g_output_stream_write_all (state->content_out, - buf, - state->content_size, - &bytes_written, - cancellable, error)) + if (!content_out_write (repo, state, buf, state->content_size, + cancellable, error)) goto out; - - g_assert (bytes_written == state->content_size); } ret = TRUE; @@ -499,6 +517,35 @@ dispatch_bspatch (OstreeRepo *repo, return ret; } +/* When processing untrusted static deltas, we need to checksum the + * file content, which includes a header. Compare with what + * ostree_checksum_file_from_input() is doing too. + */ +static gboolean +handle_untrusted_content_checksum (OstreeRepo *repo, + StaticDeltaExecutionState *state, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GVariant) header = NULL; + g_autoptr(GFileInfo) finfo = NULL; + gsize bytes_written; + + if (state->trusted) + return TRUE; + + finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid); + header = _ostree_file_header_new (finfo, state->xattrs); + + state->content_checksum = g_checksum_new (G_CHECKSUM_SHA256); + + if (!_ostree_write_variant_with_size (NULL, header, 0, &bytes_written, state->content_checksum, + cancellable, error)) + return FALSE; + + return TRUE; +} + static gboolean dispatch_open_splice_and_close (OstreeRepo *repo, StaticDeltaExecutionState *state, @@ -557,7 +604,6 @@ dispatch_open_splice_and_close (OstreeRepo *repo, { guint64 content_offset; guint64 objlen; - gsize bytes_written; g_autoptr(GInputStream) object_input = NULL; g_autoptr(GInputStream) memin = NULL; @@ -582,34 +628,23 @@ dispatch_open_splice_and_close (OstreeRepo *repo, (repo->mode == OSTREE_REPO_MODE_BARE || repo->mode == OSTREE_REPO_MODE_BARE_USER)) { - if (state->trusted) - { - if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum, - state->content_size, - &state->barecommitstate, - &state->content_out, - &state->have_obj, - cancellable, error)) - goto out; - } - else - { - if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum, - state->content_size, - &state->barecommitstate, - &state->content_out, - &state->have_obj, - cancellable, error)) - goto out; - } + if (!_ostree_repo_open_content_bare (repo, state->checksum, + state->content_size, + &state->barecommitstate, + &state->content_out, + &state->have_obj, + cancellable, error)) + goto out; if (!state->have_obj) { - if (!g_output_stream_write_all (state->content_out, - state->payload_data + content_offset, - state->content_size, - &bytes_written, - cancellable, error)) + if (!handle_untrusted_content_checksum (repo, state, cancellable, error)) + goto out; + + if (!content_out_write (repo, state, + state->payload_data + content_offset, + state->content_size, + cancellable, error)) goto out; } } @@ -705,27 +740,17 @@ dispatch_open (OstreeRepo *repo, ret = TRUE; goto out; } + + if (!_ostree_repo_open_content_bare (repo, state->checksum, + state->content_size, + &state->barecommitstate, + &state->content_out, + &state->have_obj, + cancellable, error)) + goto out; - if (state->trusted) - { - if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum, - state->content_size, - &state->barecommitstate, - &state->content_out, - &state->have_obj, - cancellable, error)) - goto out; - } - else - { - if (!_ostree_repo_open_untrusted_content_bare (repo, state->checksum, - state->content_size, - &state->barecommitstate, - &state->content_out, - &state->have_obj, - cancellable, error)) - goto out; - } + if (!handle_untrusted_content_checksum (repo, state, cancellable, error)) + goto out; ret = TRUE; out: @@ -743,7 +768,6 @@ dispatch_write (OstreeRepo *repo, gboolean ret = FALSE; guint64 content_size; guint64 content_offset; - gsize bytes_written; if (!read_varuint64 (state, &content_size, error)) goto out; @@ -785,11 +809,8 @@ dispatch_write (OstreeRepo *repo, goto out; } - if (!g_output_stream_write_all (state->content_out, - buf, - bytes_read, - &bytes_written, - cancellable, error)) + if (!content_out_write (repo, state, (guint8*)buf, bytes_read, + cancellable, error)) goto out; content_size -= bytes_read; @@ -800,11 +821,8 @@ dispatch_write (OstreeRepo *repo, if (!validate_ofs (state, content_offset, content_size, error)) goto out; - if (!g_output_stream_write_all (state->content_out, - state->payload_data + content_offset, - content_size, - &bytes_written, - cancellable, error)) + if (!content_out_write (repo, state, state->payload_data + content_offset, content_size, + cancellable, error)) goto out; } } @@ -898,22 +916,26 @@ dispatch_close (OstreeRepo *repo, if (!g_output_stream_flush (state->content_out, cancellable, error)) goto out; - if (state->trusted) + if (state->content_checksum) { - if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate, - state->uid, state->gid, state->mode, - state->xattrs, - cancellable, error)) - goto out; - } - else - { - if (!_ostree_repo_commit_untrusted_content_bare (repo, state->checksum, &state->barecommitstate, - state->uid, state->gid, state->mode, - state->xattrs, - cancellable, error)) - goto out; + const char *actual_checksum = g_checksum_get_string (state->content_checksum); + + g_assert (!state->trusted); + + if (strcmp (actual_checksum, state->checksum) != 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Corrupted object %s (actual checksum is %s)", + state->checksum, actual_checksum); + goto out; + } } + + if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate, + state->uid, state->gid, state->mode, + state->xattrs, + cancellable, error)) + goto out; } if (!dispatch_unset_read_source (repo, state, cancellable, error)) From e9f08d45f75d07e7d7f1114588ca2199273811d5 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 29 Jul 2016 10:57:44 -0400 Subject: [PATCH 27/76] static-delta: fix command contexts Closes: #418 Approved by: cgwalters --- src/ostree/ot-builtin-static-delta.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ostree/ot-builtin-static-delta.c b/src/ostree/ot-builtin-static-delta.c index 90702c5a..a1c220bb 100644 --- a/src/ostree/ot-builtin-static-delta.c +++ b/src/ostree/ot-builtin-static-delta.c @@ -212,7 +212,7 @@ ot_static_delta_builtin_generate (int argc, char **argv, GCancellable *cancellab GOptionContext *context; glnx_unref_object OstreeRepo *repo = NULL; - context = g_option_context_new ("Generate static delta files"); + context = g_option_context_new ("GENERATE [TO] - Generate static delta files"); if (!ostree_option_context_parse (context, generate_options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) goto out; @@ -360,7 +360,7 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, GCancellable *canc GOptionContext *context; glnx_unref_object OstreeRepo *repo = NULL; - context = g_option_context_new ("DELTA - Apply static delta file"); + context = g_option_context_new ("APPLY-OFFLINE - Apply static delta file"); if (!ostree_option_context_parse (context, apply_offline_options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) goto out; From 1db0c8dcd642e7803a6d90b502664107ce11ec55 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 29 Jul 2016 12:31:42 -0400 Subject: [PATCH 28/76] static-delta: remove unused struct Closes: #418 Approved by: cgwalters --- src/libostree/ostree-repo-static-delta-processing.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c index ea1aad17..f78b7ab7 100644 --- a/src/libostree/ostree-repo-static-delta-processing.c +++ b/src/libostree/ostree-repo-static-delta-processing.c @@ -87,11 +87,6 @@ typedef gboolean (*DispatchOpFunc) (OstreeRepo *repo, GCancellable *cancellable, GError **error); -typedef struct { - const char *name; - DispatchOpFunc func; -} OstreeStaticDeltaOperation; - #define OPPROTO(name) \ static gboolean dispatch_##name (OstreeRepo *repo, \ StaticDeltaExecutionState *state, \ From 6d310db1e79d34dd9f34dfddfb2448bbe0e04bb8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 26 Jun 2016 21:59:12 -0400 Subject: [PATCH 29/76] libglnx porting: Migrate to new tempfile code In general this is even cleaner now, though it was better after I extracted a helper function for the "write tempfile with contents" bits that were shared between metadata and regular file codepaths. Closes: #369 Approved by: jlebon --- Makefile.am | 2 +- autogen.sh | 3 + configure.ac | 1 + src/libostree/ostree-repo-checkout.c | 61 ++++++----- src/libostree/ostree-repo-commit.c | 150 +++++++++++++++++---------- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo-pull.c | 2 +- 7 files changed, 138 insertions(+), 82 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0d2fd6b3..495a5930 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ include Makefile-decls.am shortened_sysconfdir = $$(echo "$(sysconfdir)" | sed -e 's|^$(prefix)||' -e 's|^/||') -ACLOCAL_AMFLAGS = -I buildutil ${ACLOCAL_FLAGS} +ACLOCAL_AMFLAGS = -I buildutil -I libglnx ${ACLOCAL_FLAGS} AM_CPPFLAGS += -DDATADIR='"$(datadir)"' -DLIBEXECDIR='"$(libexecdir)"' \ -DLOCALEDIR=\"$(datadir)/locale\" -DSYSCONFDIR=\"$(sysconfdir)\" \ -DSHORTENED_SYSCONFDIR=\"$(shortened_sysconfdir)\" \ diff --git a/autogen.sh b/autogen.sh index 581f3dee..0f32089a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -36,6 +36,9 @@ fi sed -e 's,$(libglnx_srcpath),libglnx,g' < libglnx/Makefile-libglnx.am >libglnx/Makefile-libglnx.am.inc sed -e 's,$(libbsdiff_srcpath),bsdiff,g' < bsdiff/Makefile-bsdiff.am >bsdiff/Makefile-bsdiff.am.inc +# FIXME - figure out how to get aclocal to find this by default +ln -sf ../libglnx/libglnx.m4 buildutil/libglnx.m4 + autoreconf --force --install --verbose test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac index 70b3b019..d4dac2a1 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,7 @@ OSTREE_FEATURES="" AC_SUBST([OSTREE_FEATURES]) GLIB_TESTS +LIBGLNX_CONFIGURE AC_CHECK_HEADER([sys/xattr.h],,[AC_MSG_ERROR([You must have sys/xattr.h from glibc])]) diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 0094aefd..265270b1 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -45,7 +45,7 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, gboolean ret = FALSE; g_autofree char *temp_filename = NULL; g_autoptr(GOutputStream) temp_out = NULL; - int fd; + glnx_fd_close int fd = -1; int res; guint32 file_mode; @@ -53,10 +53,11 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, file_mode = g_file_info_get_attribute_uint32 (src_info, "unix::mode"); file_mode &= ~(S_ISUID|S_ISGID); - if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, file_mode, - &temp_filename, &temp_out, - cancellable, error)) + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY | O_CLOEXEC, + &fd, &temp_filename, + error)) goto out; + temp_out = g_unix_output_stream_new (fd, FALSE); if (g_output_stream_splice (temp_out, content, 0, cancellable, error) < 0) goto out; @@ -64,8 +65,6 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, if (!g_output_stream_flush (temp_out, cancellable, error)) goto out; - fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)temp_out); - if (!self->disable_fsync) { do @@ -81,23 +80,22 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, if (!g_output_stream_close (temp_out, cancellable, error)) goto out; + if (fchmod (fd, file_mode) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + if (!_ostree_repo_ensure_loose_objdir_at (self->uncompressed_objects_dir_fd, loose_path, cancellable, error)) goto out; - if (G_UNLIKELY (renameat (self->tmp_dir_fd, temp_filename, - self->uncompressed_objects_dir_fd, loose_path) == -1)) - { - if (errno != EEXIST) - { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Storing file '%s': ", temp_filename); - goto out; - } - else - (void) unlinkat (self->tmp_dir_fd, temp_filename, 0); - } + if (!glnx_link_tmpfile_at (self->tmp_dir_fd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, + fd, temp_filename, + self->uncompressed_objects_dir_fd, loose_path, + error)) + goto out; ret = TRUE; out: @@ -292,9 +290,16 @@ checkout_file_unioning_from_input_at (OstreeRepo *repo, xattrs, cancellable, error)) goto out; } + if (G_UNLIKELY (renameat (destination_dfd, temp_filename, + destination_dfd, destination_name) == -1)) + { + glnx_set_error_from_errno (error); + goto out; + } } else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { + glnx_fd_close int temp_fd = -1; g_autoptr(GOutputStream) temp_out = NULL; guint32 file_mode; @@ -303,25 +308,25 @@ checkout_file_unioning_from_input_at (OstreeRepo *repo, if (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER) file_mode &= ~(S_ISUID|S_ISGID); - if (!gs_file_open_in_tmpdir_at (destination_dfd, file_mode, - &temp_filename, &temp_out, - cancellable, error)) + if (!glnx_open_tmpfile_linkable_at (destination_dfd, ".", O_WRONLY | O_CLOEXEC, + &temp_fd, &temp_filename, + error)) goto out; + temp_out = g_unix_output_stream_new (temp_fd, FALSE); if (!write_regular_file_content (repo, options, temp_out, file_info, xattrs, input, cancellable, error)) goto out; + + if (!glnx_link_tmpfile_at (destination_dfd, GLNX_LINK_TMPFILE_REPLACE, + temp_fd, temp_filename, destination_dfd, + destination_name, + error)) + goto out; } else g_assert_not_reached (); - if (G_UNLIKELY (renameat (destination_dfd, temp_filename, - destination_dfd, destination_name) == -1)) - { - glnx_set_error_from_errno (error); - goto out; - } - ret = TRUE; out: return ret; diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 0f9a4fb7..bf2677be 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "otutil.h" #include "ostree-core-private.h" @@ -114,6 +115,7 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, const char *checksum, OstreeObjectType objtype, int temp_dfd, + int fd, const char *temp_filename, GCancellable *cancellable, GError **error) @@ -133,17 +135,26 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, cancellable, error)) goto out; - if (G_UNLIKELY (renameat (temp_dfd, temp_filename, - dest_dfd, tmpbuf) == -1)) + if (fd != -1) { - if (errno != EEXIST) + if (!glnx_link_tmpfile_at (temp_dfd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, + fd, temp_filename, dest_dfd, tmpbuf, error)) + goto out; + } + else + { + if (G_UNLIKELY (renameat (temp_dfd, temp_filename, + dest_dfd, tmpbuf) == -1)) { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Storing file '%s': ", temp_filename); - goto out; + if (errno != EEXIST) + { + glnx_set_error_from_errno (error); + g_prefix_error (error, "Storing file '%s': ", temp_filename); + goto out; + } + else + (void) unlinkat (temp_dfd, temp_filename, 0); } - else - (void) unlinkat (temp_dfd, temp_filename, 0); } ret = TRUE; @@ -173,10 +184,18 @@ commit_loose_object_trusted (OstreeRepo *self, if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->target_owner_uid != -1) { - if (G_UNLIKELY (fchownat (self->tmp_dir_fd, temp_filename, - self->target_owner_uid, - self->target_owner_gid, - AT_SYMLINK_NOFOLLOW) == -1)) + if (fd != -1) + { + if (fchown (fd, self->target_owner_uid, self->target_owner_gid) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + } + else if (G_UNLIKELY (fchownat (self->tmp_dir_fd, temp_filename, + self->target_owner_uid, + self->target_owner_gid, + AT_SYMLINK_NOFOLLOW) == -1)) { glnx_set_error_from_errno (error); goto out; @@ -293,7 +312,7 @@ commit_loose_object_trusted (OstreeRepo *self, } if (!_ostree_repo_commit_loose_final (self, checksum, objtype, - self->tmp_dir_fd, temp_filename, + self->tmp_dir_fd, fd, temp_filename, cancellable, error)) goto out; @@ -466,9 +485,13 @@ _ostree_repo_open_content_bare (OstreeRepo *self, if (!have_obj) { - if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, 0644, &temp_filename, &ret_stream, - cancellable, error)) + int fd; + + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, + &fd, &temp_filename, error)) goto out; + + ret_stream = g_unix_output_stream_new (fd, TRUE); if (!fallocate_stream ((GFileDescriptorBased*)ret_stream, content_len, cancellable, error)) @@ -518,6 +541,42 @@ _ostree_repo_commit_trusted_content_bare (OstreeRepo *self, return ret; } +static gboolean +create_regular_tmpfile_linkable_with_content (OstreeRepo *self, + guint64 length, + GInputStream *input, + int *out_fd, + char **out_path, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GOutputStream) temp_out = NULL; + glnx_fd_close int temp_fd = -1; + g_autofree char *temp_filename = NULL; + + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, + &temp_fd, &temp_filename, + error)) + return FALSE; + temp_out = g_unix_output_stream_new (temp_fd, FALSE); + + if (!fallocate_stream ((GFileDescriptorBased*)temp_out, length, + cancellable, error)) + return FALSE; + + if (g_output_stream_splice (temp_out, input, 0, + cancellable, error) < 0) + return FALSE; + if (fchmod (temp_fd, 0644) < 0) + { + glnx_set_error_from_errno (error); + return FALSE; + } + *out_fd = temp_fd; temp_fd = -1; + *out_path = g_steal_pointer (&temp_filename); + return TRUE; +} + static gboolean write_object (OstreeRepo *self, OstreeObjectType objtype, @@ -539,11 +598,11 @@ write_object (OstreeRepo *self, g_autoptr(GInputStream) file_input = NULL; g_autoptr(GFileInfo) file_info = NULL; g_autoptr(GVariant) xattrs = NULL; - g_autoptr(GOutputStream) temp_out = NULL; gboolean have_obj; GChecksum *checksum = NULL; gboolean temp_file_is_regular; gboolean temp_file_is_symlink; + glnx_fd_close int temp_fd = -1; gboolean object_is_symlink = FALSE; gssize unpacked_size = 0; gboolean indexable = FALSE; @@ -623,16 +682,9 @@ write_object (OstreeRepo *self, { guint64 size = g_file_info_get_size (file_info); - if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, 0644, &temp_filename, &temp_out, - cancellable, error)) - goto out; - - if (!fallocate_stream ((GFileDescriptorBased*)temp_out, size, - cancellable, error)) - goto out; - - if (g_output_stream_splice (temp_out, file_input, 0, - cancellable, error) < 0) + if (!create_regular_tmpfile_linkable_with_content (self, size, file_input, + &temp_fd, &temp_filename, + cancellable, error)) goto out; } else if (repo_mode == OSTREE_REPO_MODE_BARE && temp_file_is_symlink) @@ -648,15 +700,17 @@ write_object (OstreeRepo *self, g_autoptr(GVariant) file_meta = NULL; g_autoptr(GConverter) zlib_compressor = NULL; g_autoptr(GOutputStream) compressed_out_stream = NULL; + g_autoptr(GOutputStream) temp_out = NULL; if (self->generate_sizes) indexable = TRUE; - if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, 0644, - &temp_filename, &temp_out, - cancellable, error)) + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_WRONLY|O_CLOEXEC, + &temp_fd, &temp_filename, + error)) goto out; temp_file_is_regular = TRUE; + temp_out = g_unix_output_stream_new (temp_fd, FALSE); file_meta = _ostree_zlib_file_header_new (file_info, xattrs); @@ -676,33 +730,29 @@ write_object (OstreeRepo *self, if (unpacked_size < 0) goto out; } + + if (!g_output_stream_flush (temp_out, cancellable, error)) + goto out; + + if (fchmod (temp_fd, 0644) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } } else g_assert_not_reached (); } else { - if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, 0644, &temp_filename, &temp_out, - cancellable, error)) - goto out; - - if (!fallocate_stream ((GFileDescriptorBased*)temp_out, file_object_length, - cancellable, error)) - goto out; - - if (g_output_stream_splice (temp_out, checksum_input ? (GInputStream*)checksum_input : input, - 0, - cancellable, error) < 0) + if (!create_regular_tmpfile_linkable_with_content (self, file_object_length, + checksum_input ? (GInputStream*)checksum_input : input, + &temp_fd, &temp_filename, + cancellable, error)) goto out; temp_file_is_regular = TRUE; } - if (temp_out) - { - if (!g_output_stream_flush (temp_out, cancellable, error)) - goto out; - } - if (!checksum) actual_checksum = expected_checksum; else @@ -724,7 +774,7 @@ write_object (OstreeRepo *self, { struct stat stbuf; - if (fstatat (self->tmp_dir_fd, temp_filename, &stbuf, AT_SYMLINK_NOFOLLOW) == -1) + if (fstat (temp_fd, &stbuf) == -1) { glnx_set_error_from_errno (error); goto out; @@ -742,7 +792,6 @@ write_object (OstreeRepo *self, if (do_commit) { guint32 uid, gid, mode; - int fd = -1; if (file_info) { @@ -752,15 +801,12 @@ write_object (OstreeRepo *self, } else uid = gid = mode = 0; - - if (temp_out) - fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)temp_out); if (!commit_loose_object_trusted (self, actual_checksum, objtype, temp_filename, object_is_symlink, uid, gid, mode, - xattrs, fd, + xattrs, temp_fd, cancellable, error)) goto out; diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index d6996377..917a9dae 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -255,6 +255,7 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, const char *checksum, OstreeObjectType objtype, int temp_dfd, + int fd, const char *temp_filename, GCancellable *cancellable, GError **error); diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 0d342d3f..7d9f61b0 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -726,7 +726,7 @@ content_fetch_on_complete (GObject *object, if (!have_object) { if (!_ostree_repo_commit_loose_final (pull_data->repo, checksum, OSTREE_OBJECT_TYPE_FILE, - _ostree_fetcher_get_dfd (fetcher), temp_path, + _ostree_fetcher_get_dfd (fetcher), -1, temp_path, cancellable, error)) goto out; } From 30963766c7b22779210464c47cc4d0c0c171debf Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 27 Jul 2016 10:38:36 +0200 Subject: [PATCH 30/76] libostree: new function ostree_repo_checkout_at Provide a gobject introspection safe version for `ostree_repo_checkout_tree_at'. Signed-off-by: Giuseppe Scrivano Closes: #417 Approved by: cgwalters --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree.sym | 1 + src/libostree/ostree-repo-checkout.c | 70 ++++++++++++++++++++++------ src/libostree/ostree-repo.h | 50 +++++++++++++++++--- 4 files changed, 102 insertions(+), 20 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 8b6337f7..37c7e11e 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -344,6 +344,7 @@ OstreeRepoCheckoutMode OstreeRepoCheckoutOverwriteMode ostree_repo_checkout_tree ostree_repo_checkout_tree_at +ostree_repo_checkout_at ostree_repo_checkout_gc ostree_repo_read_commit OstreeRepoListObjectsFlags diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 04e36453..3d05ac0e 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -355,4 +355,5 @@ LIBOSTREE_2016.8 { global: ostree_checksum_b64_to_bytes; ostree_checksum_b64_from_bytes; + ostree_repo_checkout_at; } LIBOSTREE_2016.7; diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 265270b1..1010d239 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -104,14 +104,14 @@ checkout_object_for_uncompressed_cache (OstreeRepo *self, static gboolean fsync_is_enabled (OstreeRepo *self, - OstreeRepoCheckoutOptions *options) + OstreeRepoCheckoutAtOptions *options) { return !(self->disable_fsync || options->disable_fsync); } static gboolean write_regular_file_content (OstreeRepo *self, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, GOutputStream *output, GFileInfo *file_info, GVariant *xattrs, @@ -181,7 +181,7 @@ write_regular_file_content (OstreeRepo *self, static gboolean checkout_file_from_input_at (OstreeRepo *self, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, GFileInfo *file_info, GVariant *xattrs, GInputStream *input, @@ -264,7 +264,7 @@ checkout_file_from_input_at (OstreeRepo *self, */ static gboolean checkout_file_unioning_from_input_at (OstreeRepo *repo, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, GFileInfo *file_info, GVariant *xattrs, GInputStream *input, @@ -334,7 +334,7 @@ checkout_file_unioning_from_input_at (OstreeRepo *repo, static gboolean checkout_file_hardlink (OstreeRepo *self, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, const char *loose_path, int destination_dfd, const char *destination_name, @@ -391,7 +391,7 @@ checkout_file_hardlink (OstreeRepo *self, static gboolean checkout_one_file_at (OstreeRepo *repo, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, GFile *source, GFileInfo *source_info, int destination_dfd, @@ -627,7 +627,7 @@ checkout_one_file_at (OstreeRepo *repo, */ static gboolean checkout_tree_at (OstreeRepo *self, - OstreeRepoCheckoutOptions *options, + OstreeRepoCheckoutAtOptions *options, int destination_parent_fd, const char *destination_name, OstreeRepoFile *source, @@ -813,7 +813,7 @@ ostree_repo_checkout_tree (OstreeRepo *self, GCancellable *cancellable, GError **error) { - OstreeRepoCheckoutOptions options = { 0, }; + OstreeRepoCheckoutAtOptions options = { 0, }; options.mode = mode; options.overwrite_mode = overwrite_mode; @@ -827,7 +827,7 @@ ostree_repo_checkout_tree (OstreeRepo *self, } /** - * ostree_repo_checkout_tree_at: + * ostree_repo_checkout_tree_at: (skip) * @self: Repo * @options: (allow-none): Options * @destination_dfd: Directory FD for destination @@ -837,7 +837,7 @@ ostree_repo_checkout_tree (OstreeRepo *self, * @error: Error * * Similar to ostree_repo_checkout_tree(), but uses directory-relative - * paths for the destination, uses a new `OstreeRepoCheckoutOptions`, + * paths for the destination, uses a new `OstreeRepoCheckoutAtOptions`, * and takes a commit checksum and optional subpath pair, rather than * requiring use of `GFile` APIs for the caller. * @@ -846,19 +846,63 @@ ostree_repo_checkout_tree (OstreeRepo *self, * cache. */ gboolean -ostree_repo_checkout_tree_at (OstreeRepo *self, +ostree_repo_checkout_tree_at (OstreeRepo *self, OstreeRepoCheckoutOptions *options, int destination_dfd, const char *destination_path, const char *commit, GCancellable *cancellable, GError **error) +{ + OstreeRepoCheckoutAtOptions new_opts = {0, }; + new_opts.mode = options->mode; + new_opts.overwrite_mode = options->overwrite_mode; + new_opts.enable_uncompressed_cache = options->enable_uncompressed_cache; + new_opts.disable_fsync = options->disable_fsync; + new_opts.process_whiteouts = options->process_whiteouts; + new_opts.no_copy_fallback = options->no_copy_fallback; + new_opts.subpath = options->subpath; + new_opts.devino_to_csum_cache = options->devino_to_csum_cache; + return ostree_repo_checkout_at (self, &new_opts, destination_dfd, + destination_path, commit, cancellable, error); +} + +/** + * ostree_repo_checkout_at: + * @self: Repo + * @options: (allow-none): Options + * @destination_dfd: Directory FD for destination + * @destination_path: Directory for destination + * @commit: Checksum for commit + * @cancellable: Cancellable + * @error: Error + * + * Similar to ostree_repo_checkout_tree(), but uses directory-relative + * paths for the destination, uses a new `OstreeRepoCheckoutAtOptions`, + * and takes a commit checksum and optional subpath pair, rather than + * requiring use of `GFile` APIs for the caller. + * + * It also replaces ostree_repo_checkout_at() which was not safe to + * use with GObject introspection. + * + * Note in addition that unlike ostree_repo_checkout_tree(), the + * default is not to use the repository-internal uncompressed objects + * cache. + */ +gboolean +ostree_repo_checkout_at (OstreeRepo *self, + OstreeRepoCheckoutAtOptions *options, + int destination_dfd, + const char *destination_path, + const char *commit, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; g_autoptr(GFile) commit_root = NULL; g_autoptr(GFile) target_dir = NULL; g_autoptr(GFileInfo) target_info = NULL; - OstreeRepoCheckoutOptions default_options = { 0, }; + OstreeRepoCheckoutAtOptions default_options = { 0, }; if (!options) { @@ -920,7 +964,7 @@ devino_equal (gconstpointer a, * ostree_repo_write_directory_to_mtree() using a (normally modified) * directory. In order for OSTree to optimally detect just the new * files, use this function and fill in the `devino_to_csum_cache` - * member of `OstreeRepoCheckoutOptions`, then call + * member of `OstreeRepoCheckoutAtOptions`, then call * ostree_repo_commit_set_devino_cache(). * * Returns: (transfer full): Newly allocated cache diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 872f9b81..28766a24 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -624,13 +624,14 @@ typedef struct { } OstreeRepoImportArchiveOptions; _OSTREE_PUBLIC -gboolean ostree_repo_import_archive_to_mtree (OstreeRepo *self, +gboolean ostree_repo_import_archive_to_mtree (OstreeRepo *self, OstreeRepoImportArchiveOptions *opts, - void *archive, /* Really struct archive * */ - OstreeMutableTree *mtree, - OstreeRepoCommitModifier *modifier, - GCancellable *cancellable, - GError **error); + void *archive, /* Really struct archive * */ + OstreeMutableTree *mtree, + OstreeRepoCommitModifier *modifier, + GCancellable *cancellable, + GError **error); + /** * OstreeRepoExportArchiveOptions: * @@ -735,7 +736,7 @@ ostree_repo_checkout_tree (OstreeRepo *self, GError **error); /** - * OstreeRepoCheckoutOptions: + * OstreeRepoCheckoutOptions: (skip) * * An extensible options structure controlling checkout. Ensure that * you have entirely zeroed the structure, then set just the desired @@ -761,6 +762,32 @@ typedef struct { gpointer unused_ptrs[7]; } OstreeRepoCheckoutOptions; +/** + * OstreeRepoCheckoutAtOptions: + * + * An extensible options structure controlling checkout. Ensure that + * you have entirely zeroed the structure, then set just the desired + * options. This is used by ostree_repo_checkout_at() which + * supercedes previous separate enumeration usage in + * ostree_repo_checkout_tree() and ostree_repo_checkout_tree_at(). + */ +typedef struct { + OstreeRepoCheckoutMode mode; + OstreeRepoCheckoutOverwriteMode overwrite_mode; + + gboolean enable_uncompressed_cache; + gboolean disable_fsync; + gboolean process_whiteouts; + gboolean no_copy_fallback; + + const char *subpath; + + OstreeRepoDevInoCache *devino_to_csum_cache; + + int unused_ints[6]; + gpointer unused_ptrs[7]; +} OstreeRepoCheckoutAtOptions; + _OSTREE_PUBLIC GType ostree_repo_devino_cache_get_type (void); _OSTREE_PUBLIC @@ -779,6 +806,15 @@ gboolean ostree_repo_checkout_tree_at (OstreeRepo *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_checkout_at (OstreeRepo *self, + OstreeRepoCheckoutAtOptions *options, + int destination_dfd, + const char *destination_path, + const char *commit, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC gboolean ostree_repo_checkout_gc (OstreeRepo *self, GCancellable *cancellable, From 88676932406ea3bc35abc4dc84ac7efecd493d6a Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 27 Jul 2016 11:11:13 +0200 Subject: [PATCH 31/76] libostree: mark ostree_repo_checkout_tree_at as deprecated and move its definition to a separate file. Signed-off-by: Giuseppe Scrivano Closes: #417 Approved by: cgwalters --- Makefile-libostree-defines.am | 1 + Makefile-libostree.am | 3 +- src/libostree/ostree-repo-checkout.c | 2 + src/libostree/ostree-repo-deprecated.h | 69 ++++++++++++++++++++++++++ src/libostree/ostree-repo.h | 41 ++------------- 5 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 src/libostree/ostree-repo-deprecated.h diff --git a/Makefile-libostree-defines.am b/Makefile-libostree-defines.am index 2d478bb6..e3ec3950 100644 --- a/Makefile-libostree-defines.am +++ b/Makefile-libostree-defines.am @@ -35,4 +35,5 @@ libostree_public_headers = \ src/libostree/ostree-sysroot-upgrader.h \ src/libostree/ostree-deployment.h \ src/libostree/ostree-bootconfig-parser.h \ + src/libostree/ostree-repo-deprecated.h \ $(NULL) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index efddd37d..0be60a18 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -205,7 +205,8 @@ gpgreadmedir = $(pkgdatadir)/trusted.gpg.d EXTRA_DIST += src/libostree/README-gpg src/libostree/bupsplit.h \ src/libostree/ostree-enumtypes.h.template \ src/libostree/ostree-enumtypes.c.template \ - src/libostree/ostree-deployment-private.h + src/libostree/ostree-deployment-private.h \ + src/libostree/ostree-repo-deprecated.h install-mkdir-remotes-d-hook: mkdir -p $(DESTDIR)$(sysconfdir)/ostree/remotes.d diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 1010d239..4e0f0a23 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -844,6 +844,8 @@ ostree_repo_checkout_tree (OstreeRepo *self, * Note in addition that unlike ostree_repo_checkout_tree(), the * default is not to use the repository-internal uncompressed objects * cache. + * + * This function is deprecated. Use ostree_repo_checkout_at() instead. */ gboolean ostree_repo_checkout_tree_at (OstreeRepo *self, diff --git a/src/libostree/ostree-repo-deprecated.h b/src/libostree/ostree-repo-deprecated.h new file mode 100644 index 00000000..bb4b09d7 --- /dev/null +++ b/src/libostree/ostree-repo-deprecated.h @@ -0,0 +1,69 @@ +/* -*- 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 + * 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. + */ + +#pragma once + +#include "ostree-core.h" +#include "ostree-types.h" + +#ifndef G_GNUC_DEPRECATED_FOR +# define G_GNUC_DEPRECATED_FOR(x) +#endif + +G_BEGIN_DECLS + +/** + * OstreeRepoCheckoutOptions: (skip) + * + * An extensible options structure controlling checkout. Ensure that + * you have entirely zeroed the structure, then set just the desired + * options. This is used by ostree_repo_checkout_tree_at() which + * supercedes previous separate enumeration usage in + * ostree_repo_checkout_tree(). + */ +typedef struct { + OstreeRepoCheckoutMode mode; + OstreeRepoCheckoutOverwriteMode overwrite_mode; + + guint enable_uncompressed_cache : 1; + guint disable_fsync : 1; + guint process_whiteouts : 1; + guint no_copy_fallback : 1; + guint reserved : 28; + + const char *subpath; + + OstreeRepoDevInoCache *devino_to_csum_cache; + + guint unused_uints[6]; + gpointer unused_ptrs[7]; +} OstreeRepoCheckoutOptions; + +_OSTREE_PUBLIC +gboolean ostree_repo_checkout_tree_at (OstreeRepo *self, + OstreeRepoCheckoutOptions *options, + int destination_dfd, + const char *destination_path, + const char *commit, + GCancellable *cancellable, + GError **error) +G_GNUC_DEPRECATED_FOR(ostree_repo_checkout_at); + +G_END_DECLS diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 28766a24..04f467d2 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -735,33 +735,6 @@ ostree_repo_checkout_tree (OstreeRepo *self, GCancellable *cancellable, GError **error); -/** - * OstreeRepoCheckoutOptions: (skip) - * - * An extensible options structure controlling checkout. Ensure that - * you have entirely zeroed the structure, then set just the desired - * options. This is used by ostree_repo_checkout_tree_at() which - * supercedes previous separate enumeration usage in - * ostree_repo_checkout_tree(). - */ -typedef struct { - OstreeRepoCheckoutMode mode; - OstreeRepoCheckoutOverwriteMode overwrite_mode; - - guint enable_uncompressed_cache : 1; - guint disable_fsync : 1; - guint process_whiteouts : 1; - guint no_copy_fallback : 1; - guint reserved : 28; - - const char *subpath; - - OstreeRepoDevInoCache *devino_to_csum_cache; - - guint unused_uints[6]; - gpointer unused_ptrs[7]; -} OstreeRepoCheckoutOptions; - /** * OstreeRepoCheckoutAtOptions: * @@ -797,15 +770,6 @@ OstreeRepoDevInoCache * ostree_repo_devino_cache_ref (OstreeRepoDevInoCache *cac _OSTREE_PUBLIC void ostree_repo_devino_cache_unref (OstreeRepoDevInoCache *cache); -_OSTREE_PUBLIC -gboolean ostree_repo_checkout_tree_at (OstreeRepo *self, - OstreeRepoCheckoutOptions *options, - int destination_dfd, - const char *destination_path, - const char *commit, - GCancellable *cancellable, - GError **error); - _OSTREE_PUBLIC gboolean ostree_repo_checkout_at (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options, @@ -1123,3 +1087,8 @@ gboolean ostree_repo_regenerate_summary (OstreeRepo *self, G_END_DECLS + + +/* Include here as the functions defined before should not depend on anything which + is defined in -deprecated.h. */ +#include "ostree-repo-deprecated.h" From 0bac88e13209001b478fe771749441526095cb0a Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 29 Jul 2016 16:03:11 +0200 Subject: [PATCH 32/76] libostree: skip introspection for two functions These two functions are not safe for gobject introspection, so annotate them to be skipped: 1) ostree_repo_import_archive_to_mtree 2) ostree_repo_export_tree_to_archive Signed-off-by: Giuseppe Scrivano Closes: #417 Approved by: cgwalters --- src/libostree/ostree-repo-libarchive.c | 4 ++-- src/libostree/ostree-repo.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index cfecd6d9..d05b34ea 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -804,7 +804,7 @@ deferred_hardlinks_list_free (void *data) #endif /* HAVE_LIBARCHIVE */ /** - * ostree_repo_import_archive_to_mtree: + * ostree_repo_import_archive_to_mtree: (skip) * @self: An #OstreeRepo * @opts: Options structure, ensure this is zeroed, then set specific variables * @archive: Really this is "struct archive*" @@ -1171,7 +1171,7 @@ write_directory_to_libarchive_recurse (OstreeRepo *self, #endif /** - * ostree_repo_export_tree_to_archive: + * ostree_repo_export_tree_to_archive: (skip) * @self: An #OstreeRepo * @opts: Options controlling conversion * @root: An #OstreeRepoFile for the base directory diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 04f467d2..0b99c9dd 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -606,7 +606,7 @@ gboolean ostree_repo_write_archive_to_mtree (OstreeRepo * GError **error); /** - * OstreeRepoImportArchiveOptions: + * OstreeRepoImportArchiveOptions: (skip) * * An extensible options structure controlling archive import. Ensure that * you have entirely zeroed the structure, then set just the desired @@ -633,7 +633,7 @@ gboolean ostree_repo_import_archive_to_mtree (OstreeRepo GError **error); /** - * OstreeRepoExportArchiveOptions: + * OstreeRepoExportArchiveOptions: (skip) * * An extensible options structure controlling archive creation. Ensure that * you have entirely zeroed the structure, then set just the desired From edecae06ab65f139cddbb701cb37b672715bb176 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 27 Jul 2016 11:34:22 +0200 Subject: [PATCH 33/76] libostree, ostree: fix usage of ostree_repo_checkout_tree_at it was deprecated, use ostree_repo_checkout_at. Signed-off-by: Giuseppe Scrivano Closes: #417 Approved by: cgwalters --- src/libostree/ostree-sysroot-deploy.c | 8 ++++---- src/ostree/ot-builtin-checkout.c | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 246a3412..e8c61ad5 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -546,7 +546,7 @@ checkout_deployment_tree (OstreeSysroot *sysroot, GError **error) { gboolean ret = FALSE; - OstreeRepoCheckoutOptions checkout_opts = { 0, }; + OstreeRepoCheckoutAtOptions checkout_opts = { 0, }; const char *csum = ostree_deployment_get_csum (deployment); g_autofree char *checkout_target_name = NULL; g_autofree char *osdeploy_path = NULL; @@ -571,9 +571,9 @@ checkout_deployment_tree (OstreeSysroot *sysroot, if (!glnx_shutil_rm_rf_at (osdeploy_dfd, checkout_target_name, cancellable, error)) goto out; - if (!ostree_repo_checkout_tree_at (repo, &checkout_opts, osdeploy_dfd, - checkout_target_name, csum, - cancellable, error)) + if (!ostree_repo_checkout_at (repo, &checkout_opts, osdeploy_dfd, + checkout_target_name, csum, + cancellable, error)) goto out; if (!glnx_opendirat (osdeploy_dfd, checkout_target_name, TRUE, &ret_fd, error)) diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index c6fdf1fc..21e568b2 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -84,12 +84,12 @@ process_one_checkout (OstreeRepo *repo, /* This strange code structure is to preserve testing * coverage of both `ostree_repo_checkout_tree` and - * `ostree_repo_checkout_tree_at` until such time as we have a more + * `ostree_repo_checkout_at` until such time as we have a more * convenient infrastructure for testing C APIs with data. */ if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks) { - OstreeRepoCheckoutOptions options = { 0, }; + OstreeRepoCheckoutAtOptions options = { 0, }; if (opt_user_mode) options.mode = OSTREE_REPO_CHECKOUT_MODE_USER; @@ -101,10 +101,10 @@ process_one_checkout (OstreeRepo *repo, options.subpath = subpath; options.no_copy_fallback = opt_require_hardlinks; - if (!ostree_repo_checkout_tree_at (repo, &options, - AT_FDCWD, destination, - resolved_commit, - cancellable, error)) + if (!ostree_repo_checkout_at (repo, &options, + AT_FDCWD, destination, + resolved_commit, + cancellable, error)) goto out; } else From 512090785e039e560f5e0df9b1e1db004298eeb6 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sat, 30 Jul 2016 10:14:17 -0500 Subject: [PATCH 34/76] deltas: Allow processing of empty delta parts If a static delta is generated between 2 commits with the same content, then the delta will contain 1 part with no checksums. While useless, this is a valid delta that shouldn't raise an assertion. If the delta part has no checksums, then there are no objects to recreate and the processing can be skipped. Closes: #420 Approved by: cgwalters --- src/libostree/ostree-repo-static-delta-core.c | 3 +-- src/libostree/ostree-repo-static-delta-processing.c | 8 +++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index 68c45055..46fa5f86 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -42,8 +42,7 @@ _ostree_static_delta_parse_checksum_array (GVariant *array, n_checksums = n / OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN; - if (G_UNLIKELY(n == 0 || - n > (G_MAXUINT32/OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) || + if (G_UNLIKELY(n > (G_MAXUINT32/OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) || (n_checksums * OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN) != n)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c index f78b7ab7..304d7b4a 100644 --- a/src/libostree/ostree-repo-static-delta-processing.c +++ b/src/libostree/ostree-repo-static-delta-processing.c @@ -210,8 +210,14 @@ _ostree_static_delta_part_execute (OstreeRepo *repo, error)) goto out; + /* Skip processing for empty delta part */ + if (state->n_checksums == 0) + { + ret = TRUE; + goto out; + } + state->checksums = checksums_data; - g_assert (state->n_checksums > 0); g_variant_get (part, "(@a(uuu)@aa(ayay)@ay@ay)", &mode_dict, From a312d8fd8c3d6b57e17354ae6b14227729c45ab3 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sat, 30 Jul 2016 09:00:04 -0700 Subject: [PATCH 35/76] tests: Add test for delta with empty parts Closes: #420 Approved by: cgwalters --- tests/test-delta.sh | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/test-delta.sh b/tests/test-delta.sh index bd735c4a..1a8f8139 100755 --- a/tests/test-delta.sh +++ b/tests/test-delta.sh @@ -26,7 +26,7 @@ skip_without_user_xattrs bindatafiles="bash true ostree" morebindatafiles="false ls" -echo '1..8' +echo '1..10' mkdir repo ${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 @@ -208,3 +208,26 @@ ${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}-${newrev}$ ${CMD_PREFIX} ostree --repo=repo static-delta list | grep ^${origrev}$ && exit 1 echo 'ok delete' + +# Make another commit with no changes to create a delta with no parts +${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files +samerev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test) +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${newrev} --to=${samerev} +${CMD_PREFIX} ostree --repo=repo static-delta show ${newrev}-${samerev} > show-empty.txt +nparts_empty=$(grep '^Number of parts:' show-empty.txt) +part0_meta_empty=$(grep '^PartMeta0:' show-empty.txt) +totalsize_empty=$(grep '^Total Uncompressed Size:' show-empty.txt) +assert_streq "${nparts_empty}" "Number of parts: 1" +assert_str_match "${part0_meta_empty}" "nobjects=0" +assert_streq "${totalsize_empty}" "Total Uncompressed Size: 0 (0 bytes)" + +echo 'ok generate + show empty delta part' + +rm -rf repo2 +mkdir repo2 && ${CMD_PREFIX} ostree --repo=repo2 init --mode=archive-z2 +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${newrev} +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${samerev} +${CMD_PREFIX} ostree --repo=repo2 fsck +${CMD_PREFIX} ostree --repo=repo2 ls ${samerev} >/dev/null + +echo 'ok pull empty delta part' From 5334758ba7309438686c779e4ff943a5f84b6868 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 1 Aug 2016 10:43:49 -0400 Subject: [PATCH 36/76] repo: Make ostree_repo_create() nonfatal on existing repos In general we want to support "idempotentcy" or "state synchronization" across interruption. If a repo is only partially created due to a crash or whatever, it's hard for a user to know that. Let's just make `ostree_repo_create()` idempotent. Since all we're doing is a set of `mkdirat()` invocations, it's quite simple. This also involved porting to fd-relative, which IMO makes the code a lot clearer. Closes: #422 Approved by: 14rcole --- src/libostree/ostree-repo.c | 110 +++++++++++++++++------------------- tests/basic-test.sh | 8 ++- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 89d976b2..c48c139e 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1842,8 +1842,15 @@ ostree_repo_mode_from_string (const char *mode, * @cancellable: Cancellable * @error: Error * - * Create the underlying structure on disk for the - * repository. + * Create the underlying structure on disk for the repository, and call + * ostree_repo_open() on the result, preparing it for use. + + * Since version 2016.8, this function will succeed on an existing + * repository, and finish creating any necessary files in a partially + * created repository. However, this function cannot change the mode + * of an existing repository, and will silently ignore an attempt to + * do so. + * */ gboolean ostree_repo_create (OstreeRepo *self, @@ -1851,76 +1858,65 @@ ostree_repo_create (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GString *config_data = NULL; - g_autoptr(GFile) child = NULL; - g_autoptr(GFile) grandchild = NULL; - const char *mode_str; + const char *repopath = gs_file_get_path_cached (self->repodir); + glnx_fd_close int dfd = -1; + struct stat stbuf; + const char *state_dirs[] = { "objects", "tmp", "extensions", "state", + "refs", "refs/heads", "refs/remotes" }; - if (!ostree_repo_mode_to_string (mode, &mode_str, error)) - goto out; - - if (mkdir (gs_file_get_path_cached (self->repodir), 0755) != 0) + if (mkdir (repopath, 0755) != 0) { - if (errno != EEXIST) + if (G_UNLIKELY (errno != EEXIST)) { glnx_set_error_from_errno (error); - goto out; + return FALSE; } } - config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); - g_string_append_printf (config_data, "mode=%s\n", mode_str); + if (!glnx_opendirat (AT_FDCWD, repopath, TRUE, &dfd, error)) + return FALSE; - if (!g_file_replace_contents (self->config_file, - config_data->str, - config_data->len, - NULL, FALSE, 0, NULL, - cancellable, error)) - goto out; + if (fstatat (dfd, "config", &stbuf, 0) < 0) + { + if (errno == ENOENT) + { + const char *mode_str; + g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); - if (!g_file_make_directory (self->objects_dir, cancellable, error)) - goto out; + if (!ostree_repo_mode_to_string (mode, &mode_str, error)) + return FALSE; - if (!g_file_make_directory (self->tmp_dir, cancellable, error)) - goto out; + g_string_append_printf (config_data, "mode=%s\n", mode_str); - { - g_autoptr(GFile) extensions_dir = - g_file_resolve_relative_path (self->repodir, "extensions"); - if (!g_file_make_directory (extensions_dir, cancellable, error)) - goto out; - } + if (!glnx_file_replace_contents_at (dfd, "config", + (guint8*)config_data->str, config_data->len, + 0, cancellable, error)) + return FALSE; + } + else + { + glnx_set_error_from_errno (error); + return FALSE; + } + } - g_clear_object (&child); - child = g_file_get_child (self->repodir, "refs"); - if (!g_file_make_directory (child, cancellable, error)) - goto out; - - g_clear_object (&grandchild); - grandchild = g_file_get_child (child, "heads"); - if (!g_file_make_directory (grandchild, cancellable, error)) - goto out; - - g_clear_object (&grandchild); - grandchild = g_file_get_child (child, "remotes"); - if (!g_file_make_directory (grandchild, cancellable, error)) - goto out; - - g_clear_object (&child); - child = g_file_get_child (self->repodir, "state"); - if (!g_file_make_directory (child, cancellable, error)) - goto out; + for (guint i = 0; i < G_N_ELEMENTS (state_dirs); i++) + { + const char *elt = state_dirs[i]; + if (mkdirat (dfd, elt, 0755) == -1) + { + if (G_UNLIKELY (errno != EEXIST)) + { + glnx_set_error_from_errno (error); + return FALSE; + } + } + } if (!ostree_repo_open (self, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - - out: - if (config_data) - g_string_free (config_data, TRUE); - return ret; + return TRUE; } static gboolean diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 003df893..d4c9aaf2 100755 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..57" +echo "1..58" $OSTREE checkout test2 checkout-test2 echo "ok checkout" @@ -41,6 +41,12 @@ echo "ok shortened checksum" (cd repo && ${CMD_PREFIX} ostree rev-parse test2) echo "ok repo-in-cwd" +rm test-repo -rf +$OSTREE --repo=test-repo init --mode=bare-user +$OSTREE --repo=test-repo init --mode=bare-user +rm test-repo -rf +echo "ok repo-init on existing repo" + cd checkout-test2 assert_has_file firstfile assert_has_file baz/cow From 6f172378498d42f942828cca44e9efc9fa936c45 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 31 Jul 2016 21:03:16 -0400 Subject: [PATCH 37/76] deploy: Replace a use of gs_file_enumerator with compat wrapper More libglnx/glib porting. Closes: #423 Approved by: giuseppe --- src/libostree/ostree-sysroot-deploy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index e8c61ad5..779c7dc1 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -662,8 +662,8 @@ relabel_recursively (OstreeSysroot *sysroot, GFile *child; GFileType ftype; - if (!gs_file_enumerator_iterate (direnum, &file_info, &child, - cancellable, error)) + if (!g_file_enumerator_iterate (direnum, &file_info, &child, + cancellable, error)) goto out; if (file_info == NULL) break; From 421c902125d0e2ce6ac2a6dd941e19c23eca5eda Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 31 Jul 2016 20:58:32 -0400 Subject: [PATCH 38/76] repo: Port sign_data() to libglnx tmpfile APIs Part of dropping libgsystem. Closes: #423 Approved by: giuseppe --- src/libostree/ostree-repo.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index c48c139e..44646b0f 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -25,6 +25,7 @@ #include #include +#include #include #include "libglnx.h" #include "otutil.h" @@ -3986,7 +3987,8 @@ sign_data (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - g_autoptr(GFile) tmp_signature_file = NULL; + glnx_fd_close int tmp_fd = -1; + g_autofree char *tmp_path = NULL; g_autoptr(GOutputStream) tmp_signature_output = NULL; gpgme_ctx_t context = NULL; g_autoptr(GBytes) ret_signature = NULL; @@ -3995,12 +3997,12 @@ sign_data (OstreeRepo *self, gpgme_key_t key = NULL; gpgme_data_t commit_buffer = NULL; gpgme_data_t signature_buffer = NULL; - GMappedFile *signature_file = NULL; + g_autoptr(GMappedFile) signature_file = NULL; - if (!gs_file_open_in_tmpdir (self->tmp_dir, 0644, - &tmp_signature_file, &tmp_signature_output, - cancellable, error)) + if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_RDWR | O_CLOEXEC, + &tmp_fd, &tmp_path, error)) goto out; + tmp_signature_output = g_unix_output_stream_new (tmp_fd, FALSE); if ((err = gpgme_new (&context)) != GPG_ERR_NO_ERROR) { @@ -4079,7 +4081,7 @@ sign_data (OstreeRepo *self, if (!g_output_stream_close (tmp_signature_output, cancellable, error)) goto out; - signature_file = g_mapped_file_new (gs_file_get_path_cached (tmp_signature_file), FALSE, error); + signature_file = g_mapped_file_new_from_fd (tmp_fd, FALSE, error); if (!signature_file) goto out; ret_signature = g_mapped_file_get_bytes (signature_file); @@ -4096,8 +4098,6 @@ out: gpgme_key_release (key); if (context) gpgme_release (context); - if (signature_file) - g_mapped_file_unref (signature_file); return ret; } From 24671f7d253b08265a8aaaa9c06c0fe517eb20ff Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 31 Jul 2016 20:50:07 -0400 Subject: [PATCH 39/76] repo: Port to g_autoptr() rather than old style cleanup macros This notably kills a few libgsystem uses here. Closes: #423 Approved by: giuseppe --- src/libostree/ostree-repo.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 44646b0f..675e1cac 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -101,9 +101,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (OstreeRepo, ostree_repo, G_TYPE_OBJECT) -GS_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, local_keyfile_unref, g_key_file_unref) -#define local_cleanup_keyfile __attribute__ ((cleanup(local_keyfile_unref))) - #define SYSCONF_REMOTES SHORTENED_SYSCONFDIR "/ostree/remotes.d" typedef struct { @@ -189,8 +186,7 @@ ost_remote_unref (OstreeRemote *remote) } } -GS_DEFINE_CLEANUP_FUNCTION0(OstreeRemote*, local_remote_unref, ost_remote_unref) -#define local_cleanup_remote __attribute__ ((cleanup(local_remote_unref))) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeRemote, ost_remote_unref) static OstreeRemote * ost_repo_get_remote (OstreeRepo *self, @@ -221,7 +217,7 @@ ost_repo_get_remote_inherited (OstreeRepo *self, const char *name, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; g_autoptr(GError) temp_error = NULL; remote = ost_repo_get_remote (self, name, &temp_error); @@ -301,7 +297,7 @@ ostree_repo_get_remote_option (OstreeRepo *self, char **out_value, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; gboolean ret = FALSE; g_autoptr(GError) temp_error = NULL; g_autofree char *value = NULL; @@ -377,7 +373,7 @@ ostree_repo_get_remote_list_option (OstreeRepo *self, char ***out_value, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; gboolean ret = FALSE; g_autoptr(GError) temp_error = NULL; g_auto(GStrv) value = NULL; @@ -452,7 +448,7 @@ ostree_repo_get_remote_boolean_option (OstreeRepo *self, gboolean *out_value, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; g_autoptr(GError) temp_error = NULL; gboolean ret = FALSE; gboolean value = FALSE; @@ -967,7 +963,7 @@ impl_repo_remote_add (OstreeRepo *self, GCancellable *cancellable, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; gboolean different_sysroot = FALSE; gboolean ret = FALSE; @@ -1070,7 +1066,7 @@ impl_repo_remote_add (OstreeRepo *self, } else { - local_cleanup_keyfile GKeyFile *config = NULL; + g_autoptr(GKeyFile) config = NULL; config = ostree_repo_copy_config (self); ot_keyfile_copy_group (remote->options, config, remote->group); @@ -1125,7 +1121,7 @@ impl_repo_remote_delete (OstreeRepo *self, GCancellable *cancellable, GError **error) { - local_cleanup_remote OstreeRemote *remote = NULL; + g_autoptr(OstreeRemote) remote = NULL; gboolean ret = FALSE; g_return_val_if_fail (name != NULL, FALSE); @@ -1163,7 +1159,7 @@ impl_repo_remote_delete (OstreeRepo *self, } else { - local_cleanup_keyfile GKeyFile *config = NULL; + g_autoptr(GKeyFile) config = NULL; config = ostree_repo_copy_config (self); @@ -2018,7 +2014,7 @@ append_one_remote_config (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - local_cleanup_keyfile GKeyFile *remotedata = g_key_file_new (); + g_autoptr(GKeyFile) remotedata = g_key_file_new (); if (!g_key_file_load_from_file (remotedata, gs_file_get_path_cached (path), 0, error)) From 94e50ca5aa19b5a2a8590b317c57412d8862ca9d Mon Sep 17 00:00:00 2001 From: William Manley Date: Wed, 27 Jul 2016 16:40:05 +0100 Subject: [PATCH 40/76] tests: Add basic tests for ostree-prepare-root These tests use unshare and mount to prepare a fake initrd/early boot directory structure so we can then test ostree-prepare-root. Things that are tested: * Running in an initrd environment * Running without initrd * /var and /sysroot being mounted correctly * /usr being mounted read-only Things not tested (yet): * Running as init - this could be accomplished by unsharing the pid namespace too. * mounting/unmounting `/proc` if `/proc/cmdline` isn't available * Persistent overlayfs for `/usr` * Probably other things The tests are basic but can be extended in the future as we do more work on `ostree-prepare-root`. These tests must be run as root as they require the ability to `mount` and to `unshare` the mount namespace. Perhaps in the future we can use user namespaces for this test once they are more widely available. Closes: #403 Approved by: cgwalters --- Makefile-tests.am | 1 + tests/libtest.sh | 33 ++++++--------- tests/test-switchroot.sh | 87 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 21 deletions(-) create mode 100755 tests/test-switchroot.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 63d11ec8..4316f2ee 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -87,6 +87,7 @@ dist_test_scripts = \ tests/test-prune.sh \ tests/test-refs.sh \ tests/test-demo-buildsystem.sh \ + tests/test-switchroot.sh \ $(NULL) if BUILDOPT_FUSE diff --git a/tests/libtest.sh b/tests/libtest.sh index 2d064299..958f6769 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -399,34 +399,25 @@ os_repository_new_commit () cd ${test_tmpdir} } +skip() { + echo "1..0 # SKIP" "$@" + exit 0 +} + skip_without_user_xattrs () { touch test-xattrs - if ! setfattr -n user.testvalue -v somevalue test-xattrs; then - echo "1..0 # SKIP this test requires xattr support" - exit 0 - fi + setfattr -n user.testvalue -v somevalue test-xattrs || \ + skip "this test requires xattr support" } skip_without_fuse () { - if ! fusermount --version >/dev/null 2>&1; then - echo "1..0 # SKIP no fusermount" - exit 0 - fi + fusermount --version >/dev/null 2>&1 || skip "no fusermount" - if ! capsh --print | grep -q 'Bounding set.*[^a-z]cap_sys_admin'; then - echo "1..0 # SKIP No cap_sys_admin in bounding set, can't use FUSE" - exit 0 - fi + capsh --print | grep -q 'Bounding set.*[^a-z]cap_sys_admin' || \ + skip "No cap_sys_admin in bounding set, can't use FUSE" - if ! [ -w /dev/fuse ]; then - echo "1..0 # SKIP no write access to /dev/fuse" - exit 0 - fi - - if ! [ -e /etc/mtab ]; then - echo "1..0 # SKIP no /etc/mtab" - exit 0 - fi + [ -w /dev/fuse ] || skip "no write access to /dev/fuse" + [ -e /etc/mtab ] || skip "no /etc/mtab" } libtest_cleanup_gpg () { diff --git a/tests/test-switchroot.sh b/tests/test-switchroot.sh new file mode 100755 index 00000000..e039f5b7 --- /dev/null +++ b/tests/test-switchroot.sh @@ -0,0 +1,87 @@ +#!/bin/bash -ex + +this_script="${BASH_SOURCE:-$(readlink -f "$0")}" + +setup_bootfs() { + mkdir -p "$1/proc" "$1/bin" + echo "quiet ostree=/ostree/boot.0 ro" >"$1/proc/cmdline" + touch "$1/this_is_bootfs" + cp "$(dirname "$this_script")/../src/switchroot/ostree-prepare-root" "$1/bin" +} + +setup_rootfs() { + mkdir -p "$1/ostree/deploy/linux/deploy/1334/sysroot" \ + "$1/ostree/deploy/linux/deploy/1334/var" \ + "$1/ostree/deploy/linux/deploy/1334/usr" \ + "$1/ostree/deploy/linux/var" \ + "$1/bin" + ln -s "deploy/linux/deploy/1334" "$1/ostree/boot.0" + ln -s . "$1/sysroot" + touch "$1/ostree/deploy/linux/deploy/1334/this_is_ostree_root" \ + "$1/ostree/deploy/linux/var/this_is_ostree_var" \ + "$1/ostree/deploy/linux/deploy/1334/usr/this_is_ostree_usr" \ + "$1/this_is_real_root" + cp /bin/busybox "$1/bin" + busybox --list | xargs -n1 -I '{}' ln -s busybox "$1/bin/{}" + cp -r "$1/bin" "$1/ostree/deploy/linux/deploy/1334/" +} + +enter_fs() { + cd "$1" + mkdir testroot + pivot_root . testroot + export PATH=$PATH:/sysroot/bin + cd / + umount -l testroot + rmdir testroot +} + +find_in_env() { + tmpdir="$(mktemp -dt ostree-test-switchroot.XXXXXX)" + unshare -m <<-EOF + set -e + . "$this_script" + "$1" "$tmpdir" + enter_fs "$tmpdir" + ostree-prepare-root /sysroot + find / + touch /usr/usr_writable 2>/null \ + && echo "/usr is writable" \ + || echo "/usr is not writable" + touch /sysroot/usr/sysroot_usr_writable 2>/null \ + && echo "/sysroot/usr is writable" \ + || echo "/sysroot/usr is not writable" + EOF + rm -rf "$tmpdir" +} + +setup_initrd_env() { + mount -t tmpfs tmpfs "$1" + setup_bootfs "$1" + mkdir "$1/sysroot" + mount -t tmpfs tmpfs "$1/sysroot" + setup_rootfs "$1/sysroot" +} + +test_that_prepare_root_sets_sysroot_up_correctly_with_initrd() { + find_in_env setup_initrd_env >files + + grep -qx "/this_is_bootfs" files + grep -qx "/sysroot/this_is_ostree_root" files + grep -qx "/sysroot/sysroot/this_is_real_root" files + grep -qx "/sysroot/var/this_is_ostree_var" files + grep -qx "/sysroot/usr/this_is_ostree_usr" files + + grep -qx "/sysroot/usr is not writable" files + echo "ok ostree-prepare-root sets sysroot up correctly with initrd" +} + +# This script sources itself so we only want to run tests if we're the parent: +if [ "${BASH_SOURCE[0]}" = "${0}" ]; then + . $(dirname $0)/libtest.sh + unshare -m true || \ + skip "this test needs to set up mount namespaces, rerun as root" + + echo "1..1" + test_that_prepare_root_sets_sysroot_up_correctly_with_initrd +fi From 1364e6e30d3b579de8b410c219d305ec5c7c21ef Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 18 Jul 2016 14:42:40 +0100 Subject: [PATCH 41/76] ostree-prepare-root: Refactor code to resolve deploy_path I'll reuse this for a new ostree-init. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 61 ++++++++++++++++------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 375867b1..df3e3219 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -108,25 +108,12 @@ touch_run_ostree (void) (void) close (fd); } -int -main(int argc, char *argv[]) +static char* +resolve_deploy_path (const char * root_mountpoint) { - const char *root_mountpoint = NULL; - char *ostree_target = NULL; - char *deploy_path = NULL; - char srcpath[PATH_MAX]; char destpath[PATH_MAX]; - char newroot[PATH_MAX]; struct stat stbuf; - int orig_cwd_dfd; - - if (argc < 2) - { - fprintf (stderr, "usage: ostree-prepare-root SYSROOT\n"); - exit (EXIT_FAILURE); - } - - root_mountpoint = argv[1]; + char *ostree_target, *deploy_path; ostree_target = parse_ostree_cmdline (); if (!ostree_target) @@ -135,16 +122,6 @@ main(int argc, char *argv[]) exit (EXIT_FAILURE); } - /* Create a temporary target for our mounts in the initramfs; this will - * be moved to the new system root below. - */ - snprintf (newroot, sizeof(newroot), "%s.tmp", root_mountpoint); - if (mkdir (newroot, 0755) < 0) - { - perrorv ("Couldn't create temporary sysroot '%s': ", newroot); - exit (EXIT_FAILURE); - } - snprintf (destpath, sizeof(destpath), "%s/%s", root_mountpoint, ostree_target); printf ("Examining %s\n", destpath); if (lstat (destpath, &stbuf) < 0) @@ -164,6 +141,38 @@ main(int argc, char *argv[]) exit (EXIT_FAILURE); } printf ("Resolved OSTree target to: %s\n", deploy_path); + return deploy_path; +} + +int +main(int argc, char *argv[]) +{ + const char *root_mountpoint = NULL; + char *deploy_path = NULL; + char srcpath[PATH_MAX]; + char destpath[PATH_MAX]; + char newroot[PATH_MAX]; + struct stat stbuf; + int orig_cwd_dfd; + + if (argc < 2) + { + fprintf (stderr, "usage: ostree-prepare-root SYSROOT\n"); + exit (EXIT_FAILURE); + } + + root_mountpoint = argv[1]; + deploy_path = resolve_deploy_path (root_mountpoint); + + /* Create a temporary target for our mounts in the initramfs; this will + * be moved to the new system root below. + */ + snprintf (newroot, sizeof(newroot), "%s.tmp", root_mountpoint); + if (mkdir (newroot, 0755) < 0) + { + perrorv ("Couldn't create temporary sysroot '%s': ", newroot); + exit (EXIT_FAILURE); + } /* Work-around for a kernel bug: for some reason the kernel * refuses switching root if any file systems are mounted From c9551dc2310c86afebb33b3e58d5a04a3ea18a1d Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 18 Jul 2016 17:03:11 +0100 Subject: [PATCH 42/76] ostree-prepare-root as init: exec init from deployment if run as PID1 This supports running ostree on embedded platforms without an initrd. Specificially I'm trying to do bringup on an NVidia Tegra based Jetson TK1 dev board. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index df3e3219..a233007e 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -156,12 +156,10 @@ main(int argc, char *argv[]) int orig_cwd_dfd; if (argc < 2) - { - fprintf (stderr, "usage: ostree-prepare-root SYSROOT\n"); - exit (EXIT_FAILURE); - } + root_mountpoint = "/"; + else + root_mountpoint = argv[1]; - root_mountpoint = argv[1]; deploy_path = resolve_deploy_path (root_mountpoint); /* Create a temporary target for our mounts in the initramfs; this will @@ -303,6 +301,15 @@ main(int argc, char *argv[]) perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint); exit (EXIT_FAILURE); } - - exit (EXIT_SUCCESS); + + if (getpid() == 1) + { + execl ("/sbin/init", "/sbin/init", NULL); + perrorv ("failed to exec init inside ostree"); + exit (EXIT_FAILURE); + } + else + { + exit (EXIT_SUCCESS); + } } From a0a4052365288d32c682baa7b6477645130c265e Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 18 Jul 2016 17:44:19 +0100 Subject: [PATCH 43/76] ostree-prepare-root: Cope with /proc not being mounted When trying to read kernel command-line. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 50 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index a233007e..77a084ad 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -45,21 +45,20 @@ #include "ostree-mount-util.h" static char * -parse_ostree_cmdline (void) +read_proc_cmdline (void) { FILE *f = fopen("/proc/cmdline", "r"); char *cmdline = NULL; - const char *iter; - char *ret = NULL; size_t len; if (!f) - return NULL; + goto out; + /* Note that /proc/cmdline will not end in a newline, so getline * will fail unelss we provide a length. */ if (getline (&cmdline, &len, f) < 0) - return NULL; + goto out; /* ... but the length will be the size of the malloc buffer, not * strlen(). Fix that. */ @@ -67,6 +66,47 @@ parse_ostree_cmdline (void) if (cmdline[len-1] == '\n') cmdline[len-1] = '\0'; +out: + if (f) + fclose (f); + return cmdline; +} + +static char * +parse_ostree_cmdline (void) +{ + char *cmdline = NULL; + const char *iter; + char *ret = NULL; + int tmp_errno; + + cmdline = read_proc_cmdline (); + if (!cmdline) + { + // Mount proc + if (mount ("proc", "/proc", "proc", 0, NULL) < 0) + { + perrorv ("failed to mount proc on /proc: "); + exit (EXIT_FAILURE); + } + + cmdline = read_proc_cmdline (); + tmp_errno = errno; + + /* Leave the filesystem in the state that we found it: */ + if (umount ("/proc")) + { + perrorv ("failed to umount proc from /proc: "); + exit (EXIT_FAILURE); + } + + errno = tmp_errno; + if (!cmdline) + { + perrorv ("failed to read /proc/cmdline: "); + exit (EXIT_FAILURE); + } + } iter = cmdline; while (iter != NULL) From 47e7afab272721fdfa046aa22ee5260ce64d5541 Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 18 Jul 2016 18:02:12 +0100 Subject: [PATCH 44/76] ostree-prepare-root: Refactor: Create /sysroot.tmp much later Typically we have our ready made-up up root at `/sysroot/ostree/deploy/.../` (`deploy_path`) and the real rootfs at `/sysroot` (`root_mountpoint`). We want to end up with our made-up root at `/sysroot/` and the real rootfs under `/sysroot/sysroot` as systemd will be responsible for moving `/sysroot` to `/`. We need to do this in 3 moves to avoid trying to move `/sysroot` under itself: 1. `/sysroot/ostree/deploy/...` -> `/sysroot.tmp` 2. `/sysroot` -> `/sysroot.tmp/sysroot` 3. `/sysroot.tmp` -> `/sysroot` This is a refactoring to group all these operations together so I can implement an alternative in terms of `pivot_root`. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 61 ++++++++++++++++------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 77a084ad..114bd672 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -191,7 +191,6 @@ main(int argc, char *argv[]) char *deploy_path = NULL; char srcpath[PATH_MAX]; char destpath[PATH_MAX]; - char newroot[PATH_MAX]; struct stat stbuf; int orig_cwd_dfd; @@ -202,16 +201,6 @@ main(int argc, char *argv[]) deploy_path = resolve_deploy_path (root_mountpoint); - /* Create a temporary target for our mounts in the initramfs; this will - * be moved to the new system root below. - */ - snprintf (newroot, sizeof(newroot), "%s.tmp", root_mountpoint); - if (mkdir (newroot, 0755) < 0) - { - perrorv ("Couldn't create temporary sysroot '%s': ", newroot); - exit (EXIT_FAILURE); - } - /* Work-around for a kernel bug: for some reason the kernel * refuses switching root if any file systems are mounted * MS_SHARED. Hence remount them MS_PRIVATE here as a @@ -225,7 +214,7 @@ main(int argc, char *argv[]) } /* Make deploy_path a bind mount, so we can move it later */ - if (mount (deploy_path, newroot, NULL, MS_BIND, NULL) < 0) + if (mount (deploy_path, deploy_path, NULL, MS_BIND, NULL) < 0) { perrorv ("failed to initial bind mount %s", deploy_path); exit (EXIT_FAILURE); @@ -233,7 +222,7 @@ main(int argc, char *argv[]) /* Link to the deployment's /var */ snprintf (srcpath, sizeof(srcpath), "%s/../../var", deploy_path); - snprintf (destpath, sizeof(destpath), "%s/var", newroot); + snprintf (destpath, sizeof(destpath), "%s/var", deploy_path); if (mount (srcpath, destpath, NULL, MS_MGC_VAL|MS_BIND, NULL) < 0) { perrorv ("failed to bind mount %s to %s", srcpath, destpath); @@ -245,7 +234,7 @@ main(int argc, char *argv[]) snprintf (srcpath, sizeof(srcpath), "%s/boot/loader", root_mountpoint); if (lstat (srcpath, &stbuf) == 0 && S_ISLNK (stbuf.st_mode)) { - snprintf (destpath, sizeof(destpath), "%s/boot", newroot); + snprintf (destpath, sizeof(destpath), "%s/boot", deploy_path); if (lstat (destpath, &stbuf) == 0 && S_ISDIR (stbuf.st_mode)) { snprintf (srcpath, sizeof(srcpath), "%s/boot", root_mountpoint); @@ -257,7 +246,7 @@ main(int argc, char *argv[]) } } - /* Here we do a dance to chdir to the newroot so that we can have + /* Here we do a dance to chdir to the deploy_path so that we can have * the potential overlayfs mount points not look ugly. However...I * think we could do this a lot earlier and make all of the mounts * here just be relative. @@ -269,9 +258,9 @@ main(int argc, char *argv[]) exit (EXIT_FAILURE); } - if (chdir (newroot) < 0) + if (chdir (deploy_path) < 0) { - perrorv ("failed to chdir to newroot"); + perrorv ("failed to chdir to deploy_path"); exit (EXIT_FAILURE); } @@ -324,19 +313,39 @@ main(int argc, char *argv[]) touch_run_ostree (); - /* Move physical root to $deployment/sysroot */ - snprintf (destpath, sizeof(destpath), "%s/sysroot", newroot); - if (mount (root_mountpoint, destpath, NULL, MS_MOVE, NULL) < 0) + /* In this instance typically we have our ready made-up up root at + * /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at + * /sysroot (root_mountpoint). We want to end up with our made-up root at + * /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be + * responsible for moving /sysroot to /. + * + * We need to do this in 3 moves to avoid trying to move /sysroot under + * itself: + * + * 1. /sysroot/ostree/deploy/... -> /sysroot.tmp + * 2. /sysroot -> /sysroot.tmp/sysroot + * 3. /sysroot.tmp -> /sysroot + */ + if (mkdir ("/sysroot.tmp", 0755) < 0) { - perrorv ("Failed to MS_MOVE %s to '%s'", root_mountpoint, destpath); + perrorv ("couldn't create temporary sysroot /sysroot.tmp: "); exit (EXIT_FAILURE); } - /* Now that we've set up all the bind mounts in /sysroot.tmp which - * points to the deployment, move it /sysroot. From there, - * systemd's initrd-switch-root.target will take over. - */ - if (mount (newroot, root_mountpoint, NULL, MS_MOVE, NULL) < 0) + if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE, NULL) < 0) + { + perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path); + exit (EXIT_FAILURE); + } + + if (mount (root_mountpoint, "/sysroot.tmp/sysroot", NULL, MS_MOVE, NULL) < 0) + { + perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp/sysroot'", + root_mountpoint); + exit (EXIT_FAILURE); + } + + if (mount ("/sysroot.tmp", root_mountpoint, NULL, MS_MOVE, NULL) < 0) { perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint); exit (EXIT_FAILURE); From 83c0fdc3520fb8e3494fe915b86d8125c53509ae Mon Sep 17 00:00:00 2001 From: William Manley Date: Mon, 18 Jul 2016 18:09:10 +0100 Subject: [PATCH 45/76] Refactor ostree-prepare-root: Perform chdir to deploy directory earlier ...for simplicity. This way we don't need to keep concatenating deploy_path to everything. We can just refer relative to the current working directory. We need to do this after bind-mounting it over itself otherwise our cwd is still on the non-bind-mounted filesystem below. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 58 +++++++++------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 114bd672..980e69fc 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -190,9 +190,7 @@ main(int argc, char *argv[]) const char *root_mountpoint = NULL; char *deploy_path = NULL; char srcpath[PATH_MAX]; - char destpath[PATH_MAX]; struct stat stbuf; - int orig_cwd_dfd; if (argc < 2) root_mountpoint = "/"; @@ -220,12 +218,19 @@ main(int argc, char *argv[]) exit (EXIT_FAILURE); } - /* Link to the deployment's /var */ - snprintf (srcpath, sizeof(srcpath), "%s/../../var", deploy_path); - snprintf (destpath, sizeof(destpath), "%s/var", deploy_path); - if (mount (srcpath, destpath, NULL, MS_MGC_VAL|MS_BIND, NULL) < 0) + /* chdir to our new root. We need to do this after bind-mounting it over + * itself otherwise our cwd is still on the non-bind-mounted filesystem + * below. */ + if (chdir (deploy_path) < 0) { - perrorv ("failed to bind mount %s to %s", srcpath, destpath); + perrorv ("failed to chdir to deploy_path"); + exit (EXIT_FAILURE); + } + + /* Link to the deployment's /var */ + if (mount ("../../var", "var", NULL, MS_MGC_VAL|MS_BIND, NULL) < 0) + { + perrorv ("failed to bind mount ../../var to var"); exit (EXIT_FAILURE); } @@ -234,36 +239,17 @@ main(int argc, char *argv[]) snprintf (srcpath, sizeof(srcpath), "%s/boot/loader", root_mountpoint); if (lstat (srcpath, &stbuf) == 0 && S_ISLNK (stbuf.st_mode)) { - snprintf (destpath, sizeof(destpath), "%s/boot", deploy_path); - if (lstat (destpath, &stbuf) == 0 && S_ISDIR (stbuf.st_mode)) + if (lstat ("boot", &stbuf) == 0 && S_ISDIR (stbuf.st_mode)) { snprintf (srcpath, sizeof(srcpath), "%s/boot", root_mountpoint); - if (mount (srcpath, destpath, NULL, MS_BIND, NULL) < 0) + if (mount (srcpath, "boot", NULL, MS_BIND, NULL) < 0) { - perrorv ("failed to bind mount %s to %s", srcpath, destpath); + perrorv ("failed to bind mount %s to boot", srcpath); exit (EXIT_FAILURE); } } } - /* Here we do a dance to chdir to the deploy_path so that we can have - * the potential overlayfs mount points not look ugly. However...I - * think we could do this a lot earlier and make all of the mounts - * here just be relative. - */ - orig_cwd_dfd = openat (AT_FDCWD, ".", O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); - if (orig_cwd_dfd < 0) - { - perrorv ("failed to open ."); - exit (EXIT_FAILURE); - } - - if (chdir (deploy_path) < 0) - { - perrorv ("failed to chdir to deploy_path"); - exit (EXIT_FAILURE); - } - /* Do we have a persistent overlayfs for /usr? If so, mount it now. */ if (lstat (".usr-ovl-work", &stbuf) == 0) { @@ -304,13 +290,6 @@ main(int argc, char *argv[]) } } - if (fchdir (orig_cwd_dfd) < 0) - { - perrorv ("failed to chdir to orig root"); - exit (EXIT_FAILURE); - } - (void) close (orig_cwd_dfd); - touch_run_ostree (); /* In this instance typically we have our ready made-up up root at @@ -338,14 +317,13 @@ main(int argc, char *argv[]) exit (EXIT_FAILURE); } - if (mount (root_mountpoint, "/sysroot.tmp/sysroot", NULL, MS_MOVE, NULL) < 0) + if (mount (root_mountpoint, "sysroot", NULL, MS_MOVE, NULL) < 0) { - perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp/sysroot'", - root_mountpoint); + perrorv ("failed to MS_MOVE '%s' to 'sysroot'", root_mountpoint); exit (EXIT_FAILURE); } - if (mount ("/sysroot.tmp", root_mountpoint, NULL, MS_MOVE, NULL) < 0) + if (mount (".", root_mountpoint, NULL, MS_MOVE, NULL) < 0) { perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint); exit (EXIT_FAILURE); From 485a374b2175a9a7dcb64889eb0acc10cb8bf3e4 Mon Sep 17 00:00:00 2001 From: William Manley Date: Tue, 19 Jul 2016 19:48:23 +0100 Subject: [PATCH 46/76] ostree-prepare-root: Use pivot_root if real sysroot is already mounted at / This allows ostree-prepare-root outside of the initramfs context where the real rootfs is already mounted at /. We can't use `mount --move` in this case because we would be trying to move / into a subdirectory of itself. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 85 ++++++++++++++++++---------- tests/test-switchroot.sh | 22 ++++++- 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 980e69fc..0d5ba35e 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -184,6 +185,12 @@ resolve_deploy_path (const char * root_mountpoint) return deploy_path; } +static int +pivot_root(const char * new_root, const char * put_old) +{ + return syscall(__NR_pivot_root, new_root, put_old); +} + int main(int argc, char *argv[]) { @@ -197,6 +204,7 @@ main(int argc, char *argv[]) else root_mountpoint = argv[1]; + root_mountpoint = realpath (root_mountpoint, NULL); deploy_path = resolve_deploy_path (root_mountpoint); /* Work-around for a kernel bug: for some reason the kernel @@ -292,41 +300,58 @@ main(int argc, char *argv[]) touch_run_ostree (); - /* In this instance typically we have our ready made-up up root at - * /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at - * /sysroot (root_mountpoint). We want to end up with our made-up root at - * /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be - * responsible for moving /sysroot to /. - * - * We need to do this in 3 moves to avoid trying to move /sysroot under - * itself: - * - * 1. /sysroot/ostree/deploy/... -> /sysroot.tmp - * 2. /sysroot -> /sysroot.tmp/sysroot - * 3. /sysroot.tmp -> /sysroot - */ - if (mkdir ("/sysroot.tmp", 0755) < 0) + if (strcmp(root_mountpoint, "/") == 0) { - perrorv ("couldn't create temporary sysroot /sysroot.tmp: "); - exit (EXIT_FAILURE); + /* pivot_root rotates two mount points around. In this instance . (the + * deploy location) becomes / and the existing / becomes /sysroot. We + * have to use pivot_root rather than mount --move in this instance + * because our deploy location is mounted as a subdirectory of the real + * sysroot, so moving sysroot would also move the deploy location. In + * reality attempting mount --move would fail with EBUSY. */ + if (pivot_root (".", "sysroot") < 0) + { + perrorv ("failed to pivot_root to deployment"); + exit (EXIT_FAILURE); + } } - - if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE, NULL) < 0) + else { - perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path); - exit (EXIT_FAILURE); - } + /* In this instance typically we have our ready made-up up root at + * /sysroot/ostree/deploy/.../ (deploy_path) and the real rootfs at + * /sysroot (root_mountpoint). We want to end up with our made-up root at + * /sysroot/ and the real rootfs under /sysroot/sysroot as systemd will be + * responsible for moving /sysroot to /. + * + * We need to do this in 3 moves to avoid trying to move /sysroot under + * itself: + * + * 1. /sysroot/ostree/deploy/... -> /sysroot.tmp + * 2. /sysroot -> /sysroot.tmp/sysroot + * 3. /sysroot.tmp -> /sysroot + */ + if (mkdir ("/sysroot.tmp", 0755) < 0) + { + perrorv ("couldn't create temporary sysroot /sysroot.tmp: "); + exit (EXIT_FAILURE); + } - if (mount (root_mountpoint, "sysroot", NULL, MS_MOVE, NULL) < 0) - { - perrorv ("failed to MS_MOVE '%s' to 'sysroot'", root_mountpoint); - exit (EXIT_FAILURE); - } + if (mount (deploy_path, "/sysroot.tmp", NULL, MS_MOVE, NULL) < 0) + { + perrorv ("failed to MS_MOVE '%s' to '/sysroot.tmp'", deploy_path); + exit (EXIT_FAILURE); + } - if (mount (".", root_mountpoint, NULL, MS_MOVE, NULL) < 0) - { - perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint); - exit (EXIT_FAILURE); + if (mount (root_mountpoint, "sysroot", NULL, MS_MOVE, NULL) < 0) + { + perrorv ("failed to MS_MOVE '%s' to 'sysroot'", root_mountpoint); + exit (EXIT_FAILURE); + } + + if (mount (".", root_mountpoint, NULL, MS_MOVE, NULL) < 0) + { + perrorv ("failed to MS_MOVE %s to %s", deploy_path, root_mountpoint); + exit (EXIT_FAILURE); + } } if (getpid() == 1) diff --git a/tests/test-switchroot.sh b/tests/test-switchroot.sh index e039f5b7..03e82808 100755 --- a/tests/test-switchroot.sh +++ b/tests/test-switchroot.sh @@ -76,12 +76,32 @@ test_that_prepare_root_sets_sysroot_up_correctly_with_initrd() { echo "ok ostree-prepare-root sets sysroot up correctly with initrd" } +setup_no_initrd_env() { + mount --bind "$1" "$1" + setup_rootfs "$1" + setup_bootfs "$1" +} + +test_that_prepare_root_sets_root_up_correctly_with_no_initrd() { + find_in_env setup_no_initrd_env >files + + grep -qx "/this_is_ostree_root" files + grep -qx "/sysroot/this_is_bootfs" files + grep -qx "/sysroot/this_is_real_root" files + grep -qx "/var/this_is_ostree_var" files + grep -qx "/usr/this_is_ostree_usr" files + + grep -qx "/usr is not writable" files + echo "ok ostree-prepare-root sets root up correctly with no initrd" +} + # This script sources itself so we only want to run tests if we're the parent: if [ "${BASH_SOURCE[0]}" = "${0}" ]; then . $(dirname $0)/libtest.sh unshare -m true || \ skip "this test needs to set up mount namespaces, rerun as root" - echo "1..1" + echo "1..2" test_that_prepare_root_sets_sysroot_up_correctly_with_initrd + test_that_prepare_root_sets_root_up_correctly_with_no_initrd fi From 6356edaaba5e9443e9034d74550237f4f7c6991d Mon Sep 17 00:00:00 2001 From: William Manley Date: Tue, 26 Jul 2016 17:53:53 +0100 Subject: [PATCH 47/76] ostree-prepare-root: Make error message capitalisation consistent There seemed to be more lower case first letters so I've standardised on that. Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 0d5ba35e..f469a1b9 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -215,7 +215,7 @@ main(int argc, char *argv[]) * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ if (mount (NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0) { - perrorv ("Failed to make \"/\" private mount: %m"); + perrorv ("failed to make \"/\" private mount: %m"); exit (EXIT_FAILURE); } @@ -272,7 +272,7 @@ main(int argc, char *argv[]) { if (mount (".", ".", NULL, MS_REMOUNT | MS_SILENT, NULL) < 0) { - perrorv ("Failed to remount rootfs writable (for overlayfs)"); + perrorv ("failed to remount rootfs writable (for overlayfs)"); exit (EXIT_FAILURE); } } From 78f99d4780dfe8a11e782465dc758d3c37513206 Mon Sep 17 00:00:00 2001 From: William Manley Date: Tue, 26 Jul 2016 18:05:25 +0100 Subject: [PATCH 48/76] ostree-prepare-root: Fix typo in error message Closes: #403 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index f469a1b9..895b2e51 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -222,7 +222,7 @@ main(int argc, char *argv[]) /* Make deploy_path a bind mount, so we can move it later */ if (mount (deploy_path, deploy_path, NULL, MS_BIND, NULL) < 0) { - perrorv ("failed to initial bind mount %s", deploy_path); + perrorv ("failed to make initial bind mount %s", deploy_path); exit (EXIT_FAILURE); } From 52acb9d8e365672ce23b521209fd10a21879ad6d Mon Sep 17 00:00:00 2001 From: William Manley Date: Sun, 31 Jul 2016 22:19:13 +0100 Subject: [PATCH 49/76] ostree-prepare-root: Add test that overlayfs over /usr works. Closes: #403 Approved by: cgwalters --- tests/test-switchroot.sh | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test-switchroot.sh b/tests/test-switchroot.sh index 03e82808..17085140 100755 --- a/tests/test-switchroot.sh +++ b/tests/test-switchroot.sh @@ -26,6 +26,11 @@ setup_rootfs() { cp -r "$1/bin" "$1/ostree/deploy/linux/deploy/1334/" } +setup_overlay() { + mkdir -p "$1/ostree/deploy/linux/deploy/1334/.usr-ovl-work" \ + "$1/ostree/deploy/linux/deploy/1334/.usr-ovl-upper" +} + enter_fs() { cd "$1" mkdir testroot @@ -52,6 +57,7 @@ find_in_env() { && echo "/sysroot/usr is writable" \ || echo "/sysroot/usr is not writable" EOF + (cd $tmpdir && find) >permanent_files rm -rf "$tmpdir" } @@ -95,13 +101,28 @@ test_that_prepare_root_sets_root_up_correctly_with_no_initrd() { echo "ok ostree-prepare-root sets root up correctly with no initrd" } +setup_no_initrd_with_overlay() { + setup_no_initrd_env "$1" + setup_overlay "$1" +} + +test_that_prepare_root_provides_overlay_over_usr_if__usr_ovl_work_exists() { + find_in_env setup_no_initrd_with_overlay >files + + grep -qx "/usr is writable" files + grep -qx "./ostree/deploy/linux/deploy/1334/.usr-ovl-upper/usr_writable" permanent_files + ! grep -qx "./ostree/deploy/linux/deploy/1334/usr/usr_writable" permanent_files || exit 1 + echo "ok ostree-prepare-root sets root up correctly with writable usr overlay" +} + # This script sources itself so we only want to run tests if we're the parent: if [ "${BASH_SOURCE[0]}" = "${0}" ]; then . $(dirname $0)/libtest.sh unshare -m true || \ skip "this test needs to set up mount namespaces, rerun as root" - echo "1..2" + echo "1..3" test_that_prepare_root_sets_sysroot_up_correctly_with_initrd test_that_prepare_root_sets_root_up_correctly_with_no_initrd + test_that_prepare_root_provides_overlay_over_usr_if__usr_ovl_work_exists fi From c671c1dd3e48927a7c545ade4dec80d7dff5beda Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 31 Jul 2016 21:33:15 -0400 Subject: [PATCH 50/76] lib: Port away from gs_file_rename() In one case, we already had relative fds and hence this was nicer. Unfortunately the other areas got uglier. More fd-relative porting to do later. Closes: #424 Approved by: giuseppe --- src/libostree/ostree-bootloader-grub2.c | 8 +++++--- src/libostree/ostree-sysroot-deploy.c | 17 +++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index 6aa551ae..30edb7a5 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -408,9 +408,11 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, */ if (!ot_gfile_ensure_unlinked (self->config_path_efi, cancellable, error)) goto out; - if (!gs_file_rename (new_config_path, self->config_path_efi, - cancellable, error)) - goto out; + if (rename (gs_file_get_path_cached (new_config_path), gs_file_get_path_cached (self->config_path_efi)) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } } ret = TRUE; diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 779c7dc1..d4feb7ed 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -795,9 +795,12 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, cancellable, error)) goto out; - if (!gs_file_rename (deployment_var_labeled_tmp, deployment_var_labeled, - cancellable, error)) - goto out; + if (rename (gs_file_get_path_cached (deployment_var_labeled_tmp), + gs_file_get_path_cached (deployment_var_labeled)) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } } ret = TRUE; @@ -861,9 +864,11 @@ merge_configuration (OstreeSysroot *sysroot, else if (etc_exists) { /* Compatibility hack */ - if (!gs_file_rename (deployment_etc_path, deployment_usretc_path, - cancellable, error)) - goto out; + if (renameat (deployment_dfd, "etc", deployment_dfd, "usr/etc") < 0) + { + glnx_set_error_from_errno (error); + goto out; + } usretc_exists = TRUE; etc_exists = FALSE; } From a843d16de22343bc55f0f584a77b5f5587e4ea23 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 31 Jul 2016 21:31:45 -0400 Subject: [PATCH 51/76] grub2: Port away from gs_file_sync_data() Inlining this is uglier, but this code kind of sucks anyways =( We're going to need to do some fd-relative porting in here at some point. Closes: #424 Approved by: giuseppe --- src/libostree/ostree-bootloader-grub2.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index 30edb7a5..b2c68ac9 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -389,8 +389,18 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, goto out; /* Now let's fdatasync() for the new file */ - if (!gs_file_sync_data (new_config_path, cancellable, error)) - goto out; + { glnx_fd_close int new_config_fd = open (gs_file_get_path_cached (new_config_path), O_RDONLY | O_CLOEXEC); + if (new_config_fd < 0) + { + glnx_set_prefix_error_from_errno (error, "Opening %s", gs_file_get_path_cached (new_config_path)); + goto out; + } + if (fdatasync (new_config_fd) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + } if (self->is_efi) { From f66906c40179ae9fe047be5412fe368f29a98290 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 2 Aug 2016 14:49:42 -0400 Subject: [PATCH 52/76] deltas: Port compilation to libglnx/fd-relative This was the last use of libgsystem tmpfile APIs. The change here is a bit uglier than it needs to be because we support creating the delta in place as well as in the repo, so we needed to abstract over locations. Closes: #424 Approved by: giuseppe --- .../ostree-repo-static-delta-compilation.c | 106 ++++++++++++------ 1 file changed, 74 insertions(+), 32 deletions(-) diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index 4e4e7f9c..a6bc3206 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -1258,19 +1258,19 @@ ostree_repo_static_delta_generate (OstreeRepo *self, guint64 total_compressed_size = 0; guint64 total_uncompressed_size = 0; g_autoptr(GVariantBuilder) part_headers = NULL; - g_autoptr(GPtrArray) part_tempfiles = NULL; + g_autoptr(GArray) part_temp_fds = NULL; + g_autoptr(GPtrArray) part_temp_paths = NULL; g_autoptr(GVariant) delta_descriptor = NULL; g_autoptr(GVariant) to_commit = NULL; const char *opt_filename; - g_autofree char *descriptor_relpath = NULL; - g_autoptr(GFile) descriptor_path = NULL; - g_autoptr(GFile) descriptor_dir = NULL; + g_autofree char *descriptor_name = NULL; + glnx_fd_close int descriptor_dfd = -1; g_autoptr(GVariant) tmp_metadata = NULL; g_autoptr(GVariant) fallback_headers = NULL; g_autoptr(GVariant) detached = NULL; gboolean inline_parts; - guint endianness = G_BYTE_ORDER; - g_autoptr(GFile) tmp_dir = NULL; + guint endianness = G_BYTE_ORDER; + glnx_fd_close int tmp_dfd = NULL; builder.parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref); builder.fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref); @@ -1355,16 +1355,24 @@ ostree_repo_static_delta_generate (OstreeRepo *self, if (opt_filename) { - g_autoptr(GFile) f = g_file_new_for_path (opt_filename); - tmp_dir = g_file_get_parent (f); + g_autofree char *dnbuf = g_strdup (opt_filename); + const char *dn = dirname (dnbuf); + if (!glnx_opendirat (AT_FDCWD, dn, TRUE, &tmp_dfd, error)) + goto out; } else { - tmp_dir = g_object_ref (self->tmp_dir); + tmp_dfd = fcntl (self->tmp_dir_fd, F_DUPFD_CLOEXEC); + if (tmp_dfd < 0) + { + glnx_set_error_from_errno (error); + goto out; + } } part_headers = g_variant_builder_new (G_VARIANT_TYPE ("a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT)); - part_tempfiles = g_ptr_array_new_with_free_func (g_object_unref); + part_temp_paths = g_ptr_array_new_with_free_func (g_free); + part_temp_fds = g_array_new (FALSE, TRUE, sizeof(int)); for (i = 0; i < builder.parts->len; i++) { OstreeStaticDeltaPartBuilder *part_builder = builder.parts->pdata[i]; @@ -1374,7 +1382,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autoptr(GChecksum) checksum = NULL; g_autoptr(GBytes) objtype_checksum_array = NULL; g_autoptr(GBytes) checksum_bytes = NULL; - g_autoptr(GFile) part_tempfile = NULL; g_autoptr(GOutputStream) part_temp_outstream = NULL; g_autoptr(GInputStream) part_in = NULL; g_autoptr(GInputStream) part_payload_in = NULL; @@ -1436,10 +1443,21 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autofree char *part_relpath = _ostree_get_relative_static_delta_part_path (from, to, i); g_variant_builder_add (&metadata_builder, "{sv}", part_relpath, delta_part); } - else if (!gs_file_open_in_tmpdir (tmp_dir, 0644, - &part_tempfile, &part_temp_outstream, - cancellable, error)) - goto out; + else + { + char *part_tempfile; + int part_temp_fd; + + if (!glnx_open_tmpfile_linkable_at (tmp_dfd, ".", O_WRONLY | O_CLOEXEC, + &part_temp_fd, &part_tempfile, error)) + goto out; + + /* Transfer tempfile ownership to arrays */ + g_array_append_val (part_temp_fds, part_temp_fd); + g_ptr_array_add (part_temp_paths, g_steal_pointer (&part_tempfile)); + part_temp_outstream = g_unix_output_stream_new (part_temp_fd, FALSE); + } + part_in = ot_variant_read (delta_part); if (!ot_gio_splice_get_checksum (part_temp_outstream, part_in, &part_checksum, @@ -1456,9 +1474,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self, ot_gvariant_new_ay_bytes (objtype_checksum_array)); g_variant_builder_add_value (part_headers, g_variant_ref (delta_part_header)); - if (part_tempfile) - g_ptr_array_add (part_tempfiles, g_object_ref (part_tempfile)); - + total_compressed_size += g_variant_get_size (delta_part); total_uncompressed_size += part_builder->uncompressed_size; @@ -1473,27 +1489,43 @@ ostree_repo_static_delta_generate (OstreeRepo *self, if (opt_filename) { - descriptor_path = g_file_new_for_path (opt_filename); + g_autofree char *dnbuf = g_strdup (opt_filename); + const char *dn = dirname (dnbuf); + descriptor_name = g_strdup (opt_filename); + + if (!glnx_opendirat (AT_FDCWD, dn, TRUE, &descriptor_dfd, error)) + goto out; } else { - descriptor_relpath = _ostree_get_relative_static_delta_superblock_path (from, to); - descriptor_path = g_file_resolve_relative_path (self->repodir, descriptor_relpath); + g_autofree char *descriptor_relpath = _ostree_get_relative_static_delta_superblock_path (from, to); + g_autofree char *dnbuf = g_strdup (descriptor_relpath); + const char *dn = dirname (dnbuf); + + if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, dn, 0755, cancellable, error)) + goto out; + if (!glnx_opendirat (self->repo_dir_fd, dn, TRUE, &descriptor_dfd, error)) + goto out; + + descriptor_name = g_strdup (basename (descriptor_relpath)); } - descriptor_dir = g_file_get_parent (descriptor_path); - - if (!glnx_shutil_mkdir_p_at (AT_FDCWD, gs_file_get_path_cached (descriptor_dir), 0755, - cancellable, error)) - goto out; - - for (i = 0; i < part_tempfiles->len; i++) + for (i = 0; i < part_temp_paths->len; i++) { - GFile *tempfile = part_tempfiles->pdata[i]; g_autofree char *partstr = g_strdup_printf ("%u", i); - g_autoptr(GFile) part_path = g_file_resolve_relative_path (descriptor_dir, partstr); + /* Take ownership of the path/fd here */ + g_autofree char *path = g_steal_pointer (&part_temp_paths->pdata[i]); + glnx_fd_close int fd = g_array_index (part_temp_fds, int, i); + g_array_index (part_temp_fds, int, i) = -1; - if (!gs_file_rename (tempfile, part_path, cancellable, error)) + if (fchmod (fd, 0644) < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + if (!glnx_link_tmpfile_at (tmp_dfd, GLNX_LINK_TMPFILE_REPLACE, fd, path, + descriptor_dfd, partstr, error)) goto out; } @@ -1544,11 +1576,21 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_printerr ("bsdiff=%u objects\n", builder.n_bsdiff); } - if (!ot_util_variant_save (descriptor_path, delta_descriptor, cancellable, error)) + if (!glnx_file_replace_contents_at (descriptor_dfd, descriptor_name, + g_variant_get_data (delta_descriptor), + g_variant_get_size (delta_descriptor), + 0, cancellable, error)) goto out; ret = TRUE; out: + for (i = 0; i < part_temp_fds->len; i++) + { + int fd = g_array_index (part_temp_fds, int, i); + if (fd == -1) + continue; + (void) close (fd); + } g_clear_pointer (&builder.parts, g_ptr_array_unref); g_clear_pointer (&builder.fallback_objects, g_ptr_array_unref); return ret; From 18d826e3a53e8ab6bf8575bbcb1138f4ff6a3029 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 3 Aug 2016 10:55:35 -0400 Subject: [PATCH 53/76] repo: Flip the fsync default to off for new checkout API Since we're adding a new API, we have the opportunity to fix the defaults. We expect clients to do a `syncfs()` or equivalent on their own now, since it's way more efficient. Flip the checkout fsync default to off. Closes: #425 Approved by: giuseppe --- src/libostree/ostree-repo-checkout.c | 4 ++-- src/libostree/ostree-repo.h | 4 ++-- src/libostree/ostree-sysroot-deploy.c | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 4e0f0a23..bf18c9e4 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -106,7 +106,7 @@ static gboolean fsync_is_enabled (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options) { - return !(self->disable_fsync || options->disable_fsync); + return options->enable_fsync || !self->disable_fsync; } static gboolean @@ -860,7 +860,7 @@ ostree_repo_checkout_tree_at (OstreeRepo *self, new_opts.mode = options->mode; new_opts.overwrite_mode = options->overwrite_mode; new_opts.enable_uncompressed_cache = options->enable_uncompressed_cache; - new_opts.disable_fsync = options->disable_fsync; + new_opts.enable_fsync = !options->disable_fsync; new_opts.process_whiteouts = options->process_whiteouts; new_opts.no_copy_fallback = options->no_copy_fallback; new_opts.subpath = options->subpath; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 0b99c9dd..f1ba22f1 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -748,8 +748,8 @@ typedef struct { OstreeRepoCheckoutMode mode; OstreeRepoCheckoutOverwriteMode overwrite_mode; - gboolean enable_uncompressed_cache; - gboolean disable_fsync; + gboolean enable_uncompressed_cache; /* Deprecated */ + gboolean enable_fsync; /* Deprecated */ gboolean process_whiteouts; gboolean no_copy_fallback; diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d4feb7ed..7b8173b6 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -554,11 +554,6 @@ checkout_deployment_tree (OstreeSysroot *sysroot, glnx_fd_close int osdeploy_dfd = -1; int ret_fd; - /* We end up using syncfs for the entire filesystem, so turn off - * OstreeRepo level fsync. - */ - checkout_opts.disable_fsync = TRUE; - osdeploy_path = g_strconcat ("ostree/deploy/", ostree_deployment_get_osname (deployment), "/deploy", NULL); checkout_target_name = g_strdup_printf ("%s.%d", csum, ostree_deployment_get_deployserial (deployment)); From 593effe2fb0e096937f46a4d0930b1fcc9f811cd Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 07:22:41 -0400 Subject: [PATCH 54/76] lib: Add padding booleans to OstreeRepoCheckoutAtOptions Since this is a new API, and adding booleans is the most likely thing we'll do, let's stick some explicit padding for them in here now. We could use the `unused_ints[]` but it'd be out of order, and this will more clearly remind people about the padding. The efficiency hit versus bitfields is annoying, but oh well, not a real world problem. Closes: #427 Approved by: giuseppe --- src/libostree/ostree-repo.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index f1ba22f1..ff1e712d 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -752,6 +752,7 @@ typedef struct { gboolean enable_fsync; /* Deprecated */ gboolean process_whiteouts; gboolean no_copy_fallback; + gboolean unused_bools[7]; const char *subpath; From 1ce633f1589cdd095e9cf1b03db77feeb8238d56 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 3 Aug 2016 13:16:30 -0400 Subject: [PATCH 55/76] Update libglnx for O_TMPFILE build time option See: https://github.com/ostreedev/ostree/issues/421 Closes: #426 Approved by: gatispaeglis --- configure.ac | 1 + libglnx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d4dac2a1..609968fa 100644 --- a/configure.ac +++ b/configure.ac @@ -320,6 +320,7 @@ echo " libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive static deltas: yes (always enabled now) + O_TMPFILE: $enable_otmpfile man pages (xsltproc): $enable_man api docs (gtk-doc): $enable_gtk_doc gjs-based tests: $have_gjs diff --git a/libglnx b/libglnx index c072ef1e..c2ba4d87 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit c072ef1ebab052bdecb0d9a52c14813728f83859 +Subproject commit c2ba4d879956436c1349acb0aeafd6f885276c67 From 30aa1ec668cd49412ee39d8f163cd1ac45cc0694 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 13:29:13 -0400 Subject: [PATCH 56/76] lib: Use libglnx file replace API more consistently We have a better API now, drop use of the internal helper, which also depended on libgsystem. This required bumping libglnx to pull in a fix. Closes: #429 Approved by: giuseppe --- libglnx | 2 +- src/libostree/ostree-repo-pull.c | 24 +++++--- src/libotutil/ot-gio-utils.c | 94 ++------------------------------ 3 files changed, 23 insertions(+), 97 deletions(-) diff --git a/libglnx b/libglnx index c2ba4d87..5ac0d702 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit c2ba4d879956436c1349acb0aeafd6f885276c67 +Subproject commit 5ac0d702d70b00887f9329e47f4d5653e994531a diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 7d9f61b0..712f17dc 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -2791,16 +2791,24 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (pull_data->is_mirror && pull_data->summary_data) { - if (!ot_file_replace_contents_at (pull_data->repo->repo_dir_fd, "summary", - pull_data->summary_data, !pull_data->repo->disable_fsync, - cancellable, error)) + GLnxFileReplaceFlags replaceflag = + pull_data->repo->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : 0; + gsize len; + const guint8 *buf = g_bytes_get_data (pull_data->summary_data, &len); + + if (!glnx_file_replace_contents_at (pull_data->repo->repo_dir_fd, "summary", + buf, len, replaceflag, + cancellable, error)) goto out; - if (pull_data->summary_data_sig && - !ot_file_replace_contents_at (pull_data->repo->repo_dir_fd, "summary.sig", - pull_data->summary_data_sig, !pull_data->repo->disable_fsync, - cancellable, error)) - goto out; + if (pull_data->summary_data_sig) + { + buf = g_bytes_get_data (pull_data->summary_data_sig, &len); + if (!glnx_file_replace_contents_at (pull_data->repo->repo_dir_fd, "summary.sig", + buf, len, replaceflag, + cancellable, error)) + goto out; + } } if (!ostree_repo_commit_transaction (pull_data->repo, NULL, cancellable, error)) diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index 4ff2feda..a7fe74cf 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -275,76 +275,6 @@ ot_gfile_load_contents_utf8_allow_noent (GFile *path, return ret; } -/** - * ot_file_replace_contents_at: - * - * Like g_file_replace_contents(), except using a fd-relative - * directory, and optionally enforces use of fdatasync(). - */ -gboolean -ot_file_replace_contents_at (int dfd, - const char *path, - GBytes *contents, - gboolean datasync, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - int fd; - g_autofree char *tmpname = NULL; - g_autoptr(GOutputStream) stream = NULL; - g_autoptr(GInputStream) instream = NULL; - - if (!gs_file_open_in_tmpdir_at (dfd, 0644, - &tmpname, &stream, - cancellable, error)) - goto out; - - g_assert (G_IS_FILE_DESCRIPTOR_BASED (stream)); - fd = g_file_descriptor_based_get_fd (G_FILE_DESCRIPTOR_BASED (stream)); - - instream = g_memory_input_stream_new_from_bytes (contents); - - if (g_bytes_get_size (contents) > 0) - { - int r = posix_fallocate (fd, 0, g_bytes_get_size (contents)); - if (r != 0) - { - /* posix_fallocate is a weird deviation from errno standards */ - errno = r; - glnx_set_error_from_errno (error); - goto out; - } - } - - if (g_output_stream_splice (stream, instream, 0, - cancellable, error) < 0) - goto out; - - if (datasync && fdatasync (fd) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } - - if (!g_output_stream_close (stream, cancellable, error)) - goto out; - - if (renameat (dfd, tmpname, dfd, path) == -1) - { - glnx_set_error_from_errno (error); - goto out; - } - - g_clear_pointer (&tmpname, g_free); - - ret = TRUE; - out: - if (tmpname) - (void) unlinkat (dfd, tmpname, 0); - return ret; -} - /** * ot_gfile_replace_contents_fsync: * @@ -356,25 +286,13 @@ ot_gfile_replace_contents_fsync (GFile *path, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - glnx_fd_close int parent_dfd = -1; - const char *target_basename = glnx_basename (gs_file_get_path_cached (path)); - g_autoptr(GFile) parent = NULL; + gsize len; + const guint8*buf = g_bytes_get_data (contents, &len); - parent = g_file_get_parent (path); - - if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (parent), TRUE, - &parent_dfd, error)) - goto out; - - if (!ot_file_replace_contents_at (parent_dfd, target_basename, - contents, TRUE, - cancellable, error)) - goto out; - - ret = TRUE; - out: - return ret; + return glnx_file_replace_contents_at (AT_FDCWD, gs_file_get_path_cached (path), + buf, len, + GLNX_FILE_REPLACE_DATASYNC_NEW, + cancellable, error); } /** From cfd402e5f7a445824027d3f68b7687a41dbceba6 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 16:35:49 -0400 Subject: [PATCH 57/76] lib: Fix a compiler warning introduced from earlier patch I think we'd end up closing stdin...yuck. Need to investigate having this be fatal, but CentOS 7 `gcc-4.8.5` doesn't understand `-Werror=int-conversion`. Closes: #430 Approved by: giuseppe --- src/libostree/ostree-repo-static-delta-compilation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index a6bc3206..8b388094 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -1270,7 +1270,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autoptr(GVariant) detached = NULL; gboolean inline_parts; guint endianness = G_BYTE_ORDER; - glnx_fd_close int tmp_dfd = NULL; + glnx_fd_close int tmp_dfd = -1; builder.parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref); builder.fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref); From 308c75e281134dbec0ba205d7727dc02de11f403 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 21:30:56 -0400 Subject: [PATCH 58/76] repo: Port metadata writing code to fd-relative It was the last thing referencing `self->objects_dir`. Closes: #432 Approved by: giuseppe --- src/libostree/ostree-repo-commit.c | 63 +++++++++--------------------- 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index bf2677be..decb7d30 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2005,15 +2005,6 @@ ostree_repo_write_commit_with_time (OstreeRepo *self, return ret; } -GFile * -_ostree_repo_get_commit_metadata_loose_path (OstreeRepo *self, - const char *checksum) -{ - char buf[_OSTREE_LOOSE_PATH_MAX]; - _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); - return g_file_resolve_relative_path (self->objects_dir, buf); -} - /** * ostree_repo_read_commit_detached_metadata: * @self: Repo @@ -2034,11 +2025,12 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - g_autoptr(GFile) metadata_path = - _ostree_repo_get_commit_metadata_loose_path (self, checksum); + char buf[_OSTREE_LOOSE_PATH_MAX]; g_autoptr(GVariant) ret_metadata = NULL; + + _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); - if (!ot_util_variant_map_at (AT_FDCWD, gs_file_get_path_cached (metadata_path), + if (!ot_util_variant_map_at (self->objects_dir_fd, buf, G_VARIANT_TYPE ("a{sv}"), OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) { @@ -2071,53 +2063,36 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GFile) metadata_path = - _ostree_repo_get_commit_metadata_loose_path (self, checksum); + char pathbuf[_OSTREE_LOOSE_PATH_MAX]; g_autoptr(GVariant) normalized = NULL; gsize normalized_size = 0; + const guint8 *data; + + _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, checksum, cancellable, error)) - goto out; + return FALSE; if (metadata != NULL) { normalized = g_variant_get_normal_form (metadata); normalized_size = g_variant_get_size (normalized); + data = g_variant_get_data (normalized); } - if (normalized_size > 0) + if (data == NULL) + data = (guint8*)""; + + if (!glnx_file_replace_contents_at (self->objects_dir_fd, pathbuf, + data, normalized_size, + 0, cancellable, error)) { - if (!g_file_replace_contents (metadata_path, - g_variant_get_data (normalized), - g_variant_get_size (normalized), - NULL, FALSE, 0, NULL, - cancellable, error)) - { - g_prefix_error (error, "Unable to write detached metadata: "); - goto out; - } - } - else - { - g_autoptr(GFileOutputStream) output_stream = NULL; - - /* Don't write to the stream, leave the file empty. */ - output_stream = g_file_replace (metadata_path, - NULL, FALSE, - G_FILE_CREATE_NONE, - cancellable, error); - if (output_stream == NULL) - { - g_prefix_error (error, "Unable to write detached metadata: "); - goto out; - } + g_prefix_error (error, "Unable to write detached metadata: "); + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } static GVariant * From 18a576c3907d5f42c7cee79600731be3ef32b808 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 21:31:39 -0400 Subject: [PATCH 59/76] lib: Drop GFiles for self->{objects_dir,state_dir} Everything that used to reference these is now fd-relative. Closes: #432 Approved by: giuseppe --- src/libostree/ostree-repo-private.h | 2 -- src/libostree/ostree-repo.c | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 917a9dae..e20e7455 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -73,8 +73,6 @@ struct OstreeRepo { int tmp_dir_fd; int cache_dir_fd; char *cache_dir; - GFile *objects_dir; - GFile *state_dir; int objects_dir_fd; GFile *deltas_dir; GFile *uncompressed_objects_dir; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 675e1cac..e9966b5f 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -520,11 +520,9 @@ ostree_repo_finalize (GObject *object) (void) close (self->tmp_dir_fd); if (self->cache_dir_fd) (void) close (self->cache_dir_fd); - g_clear_object (&self->objects_dir); if (self->objects_dir_fd != -1) (void) close (self->objects_dir_fd); g_clear_object (&self->deltas_dir); - g_clear_object (&self->state_dir); g_clear_object (&self->uncompressed_objects_dir); if (self->uncompressed_objects_dir_fd != -1) (void) close (self->uncompressed_objects_dir_fd); @@ -613,10 +611,8 @@ ostree_repo_constructed (GObject *object) self->tmp_dir = g_file_resolve_relative_path (self->repodir, "tmp"); - self->objects_dir = g_file_get_child (self->repodir, "objects"); self->deltas_dir = g_file_get_child (self->repodir, "deltas"); self->uncompressed_objects_dir = g_file_get_child (self->repodir, "uncompressed-objects-cache"); - self->state_dir = g_file_get_child (self->repodir, "state"); self->config_file = g_file_get_child (self->repodir, "config"); /* Ensure the "sysroot-path" property is set. */ From d55655b096507c9e5698836661d1fa8a52e2c3c7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 21:49:05 -0400 Subject: [PATCH 60/76] repo: Drop internal GFile config_file The remote parsing code still uses GFiles but this is a start. Closes: #432 Approved by: giuseppe --- src/libostree/ostree-repo.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index e9966b5f..27b16fe2 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -526,7 +526,6 @@ ostree_repo_finalize (GObject *object) g_clear_object (&self->uncompressed_objects_dir); if (self->uncompressed_objects_dir_fd != -1) (void) close (self->uncompressed_objects_dir_fd); - g_clear_object (&self->config_file); g_clear_object (&self->sysroot_dir); g_free (self->remotes_config_dir); @@ -613,7 +612,6 @@ ostree_repo_constructed (GObject *object) self->deltas_dir = g_file_get_child (self->repodir, "deltas"); self->uncompressed_objects_dir = g_file_get_child (self->repodir, "uncompressed-objects-cache"); - self->config_file = g_file_get_child (self->repodir, "config"); /* Ensure the "sysroot-path" property is set. */ if (self->sysroot_dir == NULL) @@ -905,8 +903,9 @@ ostree_repo_write_config (OstreeRepo *self, g_return_val_if_fail (self->inited, FALSE); data = g_key_file_to_data (new_config, &len, error); - if (!g_file_replace_contents (self->config_file, data, len, NULL, FALSE, 0, NULL, - NULL, error)) + if (!glnx_file_replace_contents_at (self->repo_dir_fd, "config", + (guint8*)data, len, 0, + NULL, error)) goto out; g_key_file_free (self->config); @@ -983,17 +982,9 @@ impl_repo_remote_add (OstreeRepo *self, } else if (remote != NULL) { - GFile *file; - - if (remote->file != NULL) - file = remote->file; - else - file = self->config_file; - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Remote configuration for \"%s\" already exists: %s", - name, gs_file_get_path_cached (file)); - + name, remote->file ? gs_file_get_path_cached (remote->file) : "(in config)"); goto out; } @@ -2159,11 +2150,20 @@ ostree_repo_open (OstreeRepo *self, } self->config = g_key_file_new (); - if (!g_key_file_load_from_file (self->config, gs_file_get_path_cached (self->config_file), 0, error)) - { - g_prefix_error (error, "Couldn't parse config file: "); + + { g_autofree char *contents = NULL; + gsize len; + + contents = glnx_file_get_contents_utf8_at (self->repo_dir_fd, "config", &len, + NULL, error); + if (!contents) goto out; - } + if (!g_key_file_load_from_data (self->config, contents, len, 0, error)) + { + g_prefix_error (error, "Couldn't parse config file: "); + goto out; + } + } if (!add_remotes_from_keyfile (self, self->config, NULL, error)) goto out; From 64e4525793602c29b626c707230143c92ffa6c66 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 5 Aug 2016 14:38:34 +0100 Subject: [PATCH 61/76] Update libglnx: Add missing files to libglnx distribution This fixes distcheck. Signed-off-by: Simon McVittie Closes: #436 Approved by: cgwalters --- libglnx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libglnx b/libglnx index 5ac0d702..871617d5 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 5ac0d702d70b00887f9329e47f4d5653e994531a +Subproject commit 871617d51984604e28483d959e37fd6ce4524b0e From 0de51bfc45cf06e83b2d796219f890e5f297cde0 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 5 Aug 2016 20:41:05 +0100 Subject: [PATCH 62/76] Skip tests that use whiteouts under Docker/aufs ostree's naming convention for whiteouts is similar to what is done in aufs, which means we can't compose the trees to test this feature under Docker with the aufs storage driver, as used on travis-ci. Signed-off-by: Simon McVittie Closes: #437 Approved by: cgwalters --- tests/basic-test.sh | 61 ++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/tests/basic-test.sh b/tests/basic-test.sh index d4c9aaf2..c4828d90 100755 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -452,38 +452,41 @@ echo "ok test error pre commit/bootid" # Whiteouts cd ${test_tmpdir} mkdir -p overlay/baz/ -touch overlay/baz/.wh.cow -touch overlay/.wh.deeper -touch overlay/anewfile -mkdir overlay/anewdir/ -touch overlay/anewdir/blah -$OSTREE --repo=repo commit -b overlay -s 'overlay' --tree=dir=overlay -rm overlay -rf +if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then + touch overlay/anewfile + mkdir overlay/anewdir/ + touch overlay/anewdir/blah + $OSTREE --repo=repo commit -b overlay -s 'overlay' --tree=dir=overlay + rm overlay -rf -for branch in test2 overlay; do - $OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co -done -for f in .wh.deeper baz/cow baz/.wh.cow; do - assert_not_has_file overlay-co/${f} -done -assert_not_has_dir overlay-co/deeper -assert_has_file overlay-co/anewdir/blah -assert_has_file overlay-co/anewfile + for branch in test2 overlay; do + $OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co + done + for f in .wh.deeper baz/cow baz/.wh.cow; do + assert_not_has_file overlay-co/${f} + done + assert_not_has_dir overlay-co/deeper + assert_has_file overlay-co/anewdir/blah + assert_has_file overlay-co/anewfile -echo "ok whiteouts enabled" + echo "ok whiteouts enabled" -# Now double check whiteouts are not processed without --whiteouts -rm overlay-co -rf -for branch in test2 overlay; do - $OSTREE --repo=repo checkout --union ${branch} overlay-co -done -for f in .wh.deeper baz/cow baz/.wh.cow; do - assert_has_file overlay-co/${f} -done -assert_not_has_dir overlay-co/deeper -assert_has_file overlay-co/anewdir/blah -assert_has_file overlay-co/anewfile -echo "ok whiteouts disabled" + # Now double check whiteouts are not processed without --whiteouts + rm overlay-co -rf + for branch in test2 overlay; do + $OSTREE --repo=repo checkout --union ${branch} overlay-co + done + for f in .wh.deeper baz/cow baz/.wh.cow; do + assert_has_file overlay-co/${f} + done + assert_not_has_dir overlay-co/deeper + assert_has_file overlay-co/anewdir/blah + assert_has_file overlay-co/anewfile + echo "ok whiteouts disabled" +else + echo "ok # SKIP whiteouts do not work, are you using aufs?" + echo "ok # SKIP whiteouts do not work, are you using aufs?" +fi cd ${test_tmpdir} rm -rf test2-checkout From 704c7e57fabc5744de222cc7d0c1d910ef003901 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 5 Aug 2016 16:30:13 -0400 Subject: [PATCH 63/76] .travis.yml: Delete, we aren't using it right now @smcv will re-add a new version. Closes: #439 Approved by: smcv --- .travis.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 69ea10fd..00000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -# We're just using a "stubbed out" Travis right now so we can -# use Homu to auto-squash -# etc. -# -# In the future we'll hook up better tests. -language: c -dist: trusty -addons: - apt: - packages: - - automake - - autotools-dev -script: - - env NOCONFIGURE=1 ./autogen.sh - -notifications: - # This is Colin's personal Homu instance. We will - # also work on productizing this in Project Atomic. - webhooks: http://escher.verbum.org:54856/travis - email: false - -branches: - only: - - auto From 46e118ee8404b6dbad3ab99166ce18678fe24d20 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 5 Aug 2016 22:12:55 +0100 Subject: [PATCH 64/76] travis: run the test suite on various distributions .travis.yml is obviously still Travis-specific, but tests/ci-* are designed to be shareable with other CI environments if there is interest in doing so. At the moment I'm only testing on Debian and Ubuntu. In principle we could try a non-Debian-derived Docker container such as Fedora or CentOS inside travis-ci's Ubuntu environment, similar to what I'm doing for Debian, but I don't know the correct setup commands to use there. Closes: #438 Approved by: cgwalters --- .travis.yml | 13 +++++ tests/ci-Dockerfile.in | 10 ++++ tests/ci-build.sh | 67 ++++++++++++++++++++++++++ tests/ci-install.sh | 105 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 .travis.yml create mode 100644 tests/ci-Dockerfile.in create mode 100755 tests/ci-build.sh create mode 100755 tests/ci-install.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..8b57f413 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: c +dist: trusty +sudo: required + +env: + - ci_distro=ubuntu ci_suite=trusty + - ci_docker=debian:jessie ci_distro=debian ci_suite=jessie + - ci_docker=debian:unstable ci_distro=debian ci_suite=unstable + - ci_docker=ubuntu:xenial ci_distro=ubuntu ci_suite=xenial + +script: + - tests/ci-install.sh + - ci_parallel=2 ci_sudo=yes tests/ci-build.sh diff --git a/tests/ci-Dockerfile.in b/tests/ci-Dockerfile.in new file mode 100644 index 00000000..0b56b431 --- /dev/null +++ b/tests/ci-Dockerfile.in @@ -0,0 +1,10 @@ +FROM @ci_docker@ +ENV container docker + +ADD tests/ci-install.sh /ci-install.sh +RUN ci_suite="@ci_suite@" ci_distro="@ci_distro@" ci_in_docker=yes /ci-install.sh + +ADD . /home/user/ostree +RUN chown -R user:user /home/user/ostree +WORKDIR /home/user/ostree +USER user diff --git a/tests/ci-build.sh b/tests/ci-build.sh new file mode 100755 index 00000000..4aaa47af --- /dev/null +++ b/tests/ci-build.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +set -euo pipefail +set -x + +NULL= +: "${ci_docker:=}" +: "${ci_parallel:=1}" +: "${ci_sudo:=no}" +: "${ci_test:=yes}" +: "${ci_test_fatal:=yes}" + +if [ -n "$ci_docker" ]; then + exec docker run \ + --env=ci_docker="" \ + --env=ci_parallel="${ci_parallel}" \ + --env=ci_sudo=yes \ + --env=ci_test="${ci_test}" \ + --env=ci_test_fatal="${ci_test_fatal}" \ + --privileged \ + ostree-ci \ + tests/ci-build.sh +fi + +NOCONFIGURE=1 ./autogen.sh + +srcdir="$(pwd)" +mkdir ci-build +cd ci-build + +make="make -j${ci_parallel} V=1 VERBOSE=1" + +../configure \ + --enable-always-build-tests \ + --enable-installed-tests \ + "$@" + +${make} + +maybe_fail_tests () { + if [ "$ci_test_fatal" = yes ]; then + exit 1 + fi +} + +[ "$ci_test" = no ] || ${make} check || maybe_fail_tests +# TODO: if ostree aims to support distcheck, run that too + +${make} install DESTDIR=$(pwd)/DESTDIR + +( cd DESTDIR && find . ) + +if [ -n "$ci_sudo" ] && [ -n "$ci_test" ]; then + sudo ${make} install + env \ + LD_LIBRARY_PATH=/usr/local/lib \ + GI_TYPELIB_PATH=/usr/local/lib/girepository-1.0 \ + ${make} installcheck || \ + maybe_fail_tests + env \ + LD_LIBRARY_PATH=/usr/local/lib \ + GI_TYPELIB_PATH=/usr/local/lib/girepository-1.0 \ + gnome-desktop-testing-runner -d /usr/local/share ostree/ || \ + maybe_fail_tests +fi + +# vim:set sw=4 sts=4 et: diff --git a/tests/ci-install.sh b/tests/ci-install.sh new file mode 100755 index 00000000..ecd03b58 --- /dev/null +++ b/tests/ci-install.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +set -euo pipefail +set -x + +NULL= +: "${ci_docker:=}" +: "${ci_in_docker:=}" +: "${ci_suite:=jessie}" + +if [ $(id -u) = 0 ]; then + sudo= +else + sudo=sudo +fi + +if [ -n "$ci_docker" ]; then + sed \ + -e "s/@ci_distro@/${ci_distro}/" \ + -e "s/@ci_docker@/${ci_docker}/" \ + -e "s/@ci_suite@/${ci_suite}/" \ + < tests/ci-Dockerfile.in > Dockerfile + exec docker build -t ostree-ci . +fi + +case "$ci_distro" in + (debian) + # Docker images use httpredir.debian.org but it seems to be + # unreliable; use a CDN instead + sed -i -e 's/httpredir\.debian\.org/deb.debian.org/g' /etc/apt/sources.list + ;; +esac + +case "$ci_suite" in + (jessie) + # Add alexl's Debian 8 backport repository to get libgsystem + # TODO: remove this when libgsystem is no longer needed + $sudo apt-get -y update + $sudo apt-get -y install apt-transport-https wget + wget -O - https://sdk.gnome.org/apt/debian/conf/alexl.gpg.key | $sudo apt-key add - + echo "deb [arch=amd64] https://sdk.gnome.org/apt/debian/ jessie main" | $sudo tee /etc/apt/sources.list.d/flatpak.list + ;; + + (trusty|xenial) + # Add alexl's Flatpak PPA, again to get libgsystem + # TODO: remove this when libgsystem is no longer needed + $sudo apt-get -y update + $sudo apt-get -y install software-properties-common + $sudo add-apt-repository --yes ppa:alexlarsson/flatpak + ;; +esac + +case "$ci_distro" in + (debian|ubuntu) + # TODO: fetch this list from the Debian packaging git repository? + $sudo apt-get -y update + $sudo apt-get -y install \ + attr \ + bison \ + cpio \ + debhelper \ + dh-autoreconf \ + dh-systemd \ + docbook-xml \ + docbook-xsl \ + e2fslibs-dev \ + elfutils \ + fuse \ + gjs \ + gnome-desktop-testing \ + gobject-introspection \ + gtk-doc-tools \ + libarchive-dev \ + libattr1-dev \ + libcap-dev \ + libfuse-dev \ + libgirepository1.0-dev \ + libglib2.0-dev \ + libgpgme11-dev \ + libgsystem-dev \ + liblzma-dev \ + libmount-dev \ + libselinux1-dev \ + libsoup2.4-dev \ + procps \ + zlib1g-dev \ + ${NULL} + + if [ -n "$ci_in_docker" ]; then + # Add the user that we will use to do the build inside the + # Docker container, and let them use sudo + adduser --disabled-password user /etc/sudoers.d/nopasswd + chmod 0440 /etc/sudoers.d/nopasswd + fi + ;; + + (*) + echo "Don't know how to set up ${ci_distro}" >&2 + exit 1 + ;; +esac + +# vim:set sw=4 sts=4 et: From 6b089304bf3cd916d32e5a5d47366183ff1d9a3e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 5 Aug 2016 07:08:14 -0400 Subject: [PATCH 65/76] repo: Drop more internally unused GFile members I forgot to actually remove `config_file` in the previous commit, the txn lock hasn't been used in a long time, and for the uncompressed cache, everything uses the fd already. Closes: #433 Approved by: giuseppe --- src/libostree/ostree-repo-private.h | 3 --- src/libostree/ostree-repo.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index e20e7455..92d8a084 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -75,13 +75,10 @@ struct OstreeRepo { char *cache_dir; int objects_dir_fd; GFile *deltas_dir; - GFile *uncompressed_objects_dir; int uncompressed_objects_dir_fd; - GFile *config_file; GFile *sysroot_dir; char *remotes_config_dir; - GFile *transaction_lock_path; GHashTable *txn_refs; GMutex txn_stats_lock; OstreeRepoTransactionStats txn_stats; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 27b16fe2..62415f06 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -523,14 +523,11 @@ ostree_repo_finalize (GObject *object) if (self->objects_dir_fd != -1) (void) close (self->objects_dir_fd); g_clear_object (&self->deltas_dir); - g_clear_object (&self->uncompressed_objects_dir); if (self->uncompressed_objects_dir_fd != -1) (void) close (self->uncompressed_objects_dir_fd); g_clear_object (&self->sysroot_dir); g_free (self->remotes_config_dir); - g_clear_object (&self->transaction_lock_path); - if (self->loose_object_devino_hash) g_hash_table_destroy (self->loose_object_devino_hash); if (self->updated_uncompressed_dirs) @@ -611,7 +608,6 @@ ostree_repo_constructed (GObject *object) self->tmp_dir = g_file_resolve_relative_path (self->repodir, "tmp"); self->deltas_dir = g_file_get_child (self->repodir, "deltas"); - self->uncompressed_objects_dir = g_file_get_child (self->repodir, "uncompressed-objects-cache"); /* Ensure the "sysroot-path" property is set. */ if (self->sysroot_dir == NULL) From 76d6afa707add8c5409edbfd939460b632980972 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 16:47:46 -0400 Subject: [PATCH 66/76] build: Import attributes.m4, detect CFLAGS at build time I want to add `-Werror=int-conversion`, but it's only available in newer GCC versions. So let's start autodetecting available compiler flags. Closes: #431 Approved by: giuseppe --- buildutil/attributes.m4 | 292 ++++++++++++++++++++++++++++++++++++++++ configure.ac | 25 ++-- 2 files changed, 307 insertions(+), 10 deletions(-) create mode 100644 buildutil/attributes.m4 diff --git a/buildutil/attributes.m4 b/buildutil/attributes.m4 new file mode 100644 index 00000000..51ac88be --- /dev/null +++ b/buildutil/attributes.m4 @@ -0,0 +1,292 @@ +dnl Macros to check the presence of generic (non-typed) symbols. +dnl Copyright (c) 2006-2008 Diego Pettenò +dnl Copyright (c) 2006-2008 xine project +dnl Copyright (c) 2012 Lucas De Marchi +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +dnl 02110-1301, USA. +dnl +dnl As a special exception, the copyright owners of the +dnl macro gives unlimited permission to copy, distribute and modify the +dnl configure scripts that are the output of Autoconf when processing the +dnl Macro. You need not follow the terms of the GNU General Public +dnl License when using or distributing such scripts, even though portions +dnl of the text of the Macro appear in them. The GNU General Public +dnl License (GPL) does govern all other use of the material that +dnl constitutes the Autoconf Macro. +dnl +dnl This special exception to the GPL applies to versions of the +dnl Autoconf Macro released by this project. When you make and +dnl distribute a modified version of the Autoconf Macro, you may extend +dnl this special exception to the GPL to apply to your modified version as +dnl well. + +dnl Check if FLAG in ENV-VAR is supported by compiler and append it +dnl to WHERE-TO-APPEND variable. Note that we invert -Wno-* checks to +dnl -W* as gcc cannot test for negated warnings. If a C snippet is passed, +dnl use it, otherwise use a simple main() definition that just returns 0. +dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG], [C-SNIPPET]) + +AC_DEFUN([CC_CHECK_FLAG_APPEND], [ + AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2], + AS_TR_SH([cc_cv_$2_$3]), + [eval "AS_TR_SH([cc_save_$2])='${$2}'" + eval "AS_TR_SH([$2])='${cc_save_$2} -Werror `echo "$3" | sed 's/^-Wno-/-W/'`'" + AC_LINK_IFELSE([AC_LANG_SOURCE(ifelse([$4], [], + [int main(void) { return 0; } ], + [$4]))], + [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"], + [eval "AS_TR_SH([cc_cv_$2_$3])='no'"]) + eval "AS_TR_SH([$2])='$cc_save_$2'"]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes], + [eval "$1='${$1} $3'"]) +]) + +dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2], [C-SNIPPET]) +AC_DEFUN([CC_CHECK_FLAGS_APPEND], [ + for flag in [$3]; do + CC_CHECK_FLAG_APPEND([$1], [$2], $flag, [$4]) + done +]) + +dnl Check if the flag is supported by linker (cacheable) +dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) + +AC_DEFUN([CC_CHECK_LDFLAGS], [ + AC_CACHE_CHECK([if $CC supports $1 flag], + AS_TR_SH([cc_cv_ldflags_$1]), + [ac_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $1" + AC_LINK_IFELSE([int main() { return 1; }], + [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_ldflags_$1])="]) + LDFLAGS="$ac_save_LDFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes], + [$2], [$3]) +]) + +dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for +dnl the current linker to avoid undefined references in a shared object. +AC_DEFUN([CC_NOUNDEFINED], [ + dnl We check $host for which systems to enable this for. + AC_REQUIRE([AC_CANONICAL_HOST]) + + case $host in + dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads + dnl are requested, as different implementations are present; to avoid problems + dnl use -Wl,-z,defs only for those platform not behaving this way. + *-freebsd* | *-openbsd*) ;; + *) + dnl First of all check for the --no-undefined variant of GNU ld. This allows + dnl for a much more readable command line, so that people can understand what + dnl it does without going to look for what the heck -z defs does. + for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do + CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"]) + break + done + ;; + esac + + AC_SUBST([LDFLAGS_NOUNDEFINED]) +]) + +dnl Check for a -Werror flag or equivalent. -Werror is the GCC +dnl and ICC flag that tells the compiler to treat all the warnings +dnl as fatal. We usually need this option to make sure that some +dnl constructs (like attributes) are not simply ignored. +dnl +dnl Other compilers don't support -Werror per se, but they support +dnl an equivalent flag: +dnl - Sun Studio compiler supports -errwarn=%all +AC_DEFUN([CC_CHECK_WERROR], [ + AC_CACHE_CHECK( + [for $CC way to treat warnings as errors], + [cc_cv_werror], + [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror], + [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])]) + ]) +]) + +AC_DEFUN([CC_CHECK_ATTRIBUTE], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))], + AS_TR_SH([cc_cv_attribute_$1]), + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])], + [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"], + [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes], + [AC_DEFINE( + AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1, + [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))] + ) + $4], + [$5]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [ + CC_CHECK_ATTRIBUTE( + [constructor],, + [void __attribute__((constructor)) ctor() { int a; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT], [ + CC_CHECK_ATTRIBUTE( + [format], [format(printf, n, n)], + [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [ + CC_CHECK_ATTRIBUTE( + [format_arg], [format_arg(printf)], + [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [ + CC_CHECK_ATTRIBUTE( + [visibility_$1], [visibility("$1")], + [void __attribute__((visibility("$1"))) $1_function() { }], + [$2], [$3]) +]) + +AC_DEFUN([CC_ATTRIBUTE_NONNULL], [ + CC_CHECK_ATTRIBUTE( + [nonnull], [nonnull()], + [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_UNUSED], [ + CC_CHECK_ATTRIBUTE( + [unused], , + [void some_function(void *foo, __attribute__((unused)) void *bar);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [ + CC_CHECK_ATTRIBUTE( + [sentinel], , + [void some_function(void *foo, ...) __attribute__((sentinel));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [ + CC_CHECK_ATTRIBUTE( + [deprecated], , + [void some_function(void *foo, ...) __attribute__((deprecated));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIAS], [ + CC_CHECK_ATTRIBUTE( + [alias], [weak, alias], + [void other_function(void *foo) { } + void some_function(void *foo) __attribute__((weak, alias("other_function")));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_MALLOC], [ + CC_CHECK_ATTRIBUTE( + [malloc], , + [void * __attribute__((malloc)) my_alloc(int n);], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_PACKED], [ + CC_CHECK_ATTRIBUTE( + [packed], , + [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));], + [$1], [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_CONST], [ + CC_CHECK_ATTRIBUTE( + [const], , + [int __attribute__((const)) twopow(int n) { return 1 << n; } ], + [$1], [$2]) +]) + +AC_DEFUN([CC_FLAG_VISIBILITY], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if $CC supports -fvisibility=hidden], + [cc_cv_flag_visibility], + [cc_flag_visibility_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden], + cc_cv_flag_visibility='yes', + cc_cv_flag_visibility='no') + CFLAGS="$cc_flag_visibility_save_CFLAGS"]) + + AS_IF([test "x$cc_cv_flag_visibility" = "xyes"], + [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1, + [Define this if the compiler supports the -fvisibility flag]) + $1], + [$2]) +]) + +AC_DEFUN([CC_FUNC_EXPECT], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([if compiler has __builtin_expect function], + [cc_cv_func_expect], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [int some_function() { + int a = 3; + return (int)__builtin_expect(a, 3); + }])], + [cc_cv_func_expect=yes], + [cc_cv_func_expect=no]) + CFLAGS="$ac_save_CFLAGS" + ]) + + AS_IF([test "x$cc_cv_func_expect" = "xyes"], + [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1, + [Define this if the compiler supports __builtin_expect() function]) + $1], + [$2]) +]) + +AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ + AC_REQUIRE([CC_CHECK_WERROR]) + AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported], + [cc_cv_attribute_aligned], + [ac_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $cc_cv_werror" + for cc_attribute_align_try in 64 32 16 8 4 2; do + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + int main() { + static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0; + return c; + }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break]) + done + CFLAGS="$ac_save_CFLAGS" + ]) + + if test "x$cc_cv_attribute_aligned" != "x"; then + AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], + [Define the highest alignment supported]) + fi +]) diff --git a/configure.ac b/configure.ac index 609968fa..18ab7b04 100644 --- a/configure.ac +++ b/configure.ac @@ -15,16 +15,21 @@ AC_PROG_CC AM_PROG_CC_C_O AC_PROG_YACC -changequote(,)dnl -if test "x$GCC" = "xyes"; then - WARN_CFLAGS="-Wall -Wempty-body -Wstrict-prototypes -Werror=missing-prototypes \ - -Werror=implicit-function-declaration \ - -Werror=pointer-arith -Werror=init-self -Werror=format=2 \ - -Werror=format-security \ - -Werror=missing-include-dirs -Werror=aggregate-return \ - -Werror=declaration-after-statement" -fi -changequote([,])dnl +CC_CHECK_FLAGS_APPEND([WARN_CFLAGS], [CFLAGS], [\ + -pipe \ + -Wall \ + -Werror=empty-body \ + -Werror=strict-prototypes \ + -Werror=missing-prototypes \ + -Werror=implicit-function-declaration \ + "-Werror=format=2 -Werror=format-security -Werror=format-nonliteral" \ + -Werror=pointer-arith -Werror=init-self \ + -Werror=missing-declarations \ + -Werror=return-type \ + -Werror=overflow \ + -Werror=missing-include-dirs -Werror=aggregate-return \ + -Werror=declaration-after-statement \ +]) AC_SUBST(WARN_CFLAGS) # Initialize libtool From e7b3cf9850374df232d2cf264dcfcfdca97d80a9 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 16:58:07 -0400 Subject: [PATCH 67/76] build: Make -Werror=int-conversion fatal This should hopefully avoid me accidentally passing NULL for an `int` file descriptor in the future. Closes: #431 Approved by: giuseppe --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 18ab7b04..4831bcc4 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,7 @@ CC_CHECK_FLAGS_APPEND([WARN_CFLAGS], [CFLAGS], [\ -Werror=missing-declarations \ -Werror=return-type \ -Werror=overflow \ + -Werror=int-conversion \ -Werror=missing-include-dirs -Werror=aggregate-return \ -Werror=declaration-after-statement \ ]) From 8dab17f6dbc7934af416e833c2c1ab29b7a928af Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 8 Aug 2016 06:34:50 -0400 Subject: [PATCH 68/76] repo: Fix an uninitialized variable Closes: #431 Approved by: giuseppe --- src/libostree/ostree-repo-commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index decb7d30..9a938ddc 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2066,7 +2066,7 @@ ostree_repo_write_commit_detached_metadata (OstreeRepo *self, char pathbuf[_OSTREE_LOOSE_PATH_MAX]; g_autoptr(GVariant) normalized = NULL; gsize normalized_size = 0; - const guint8 *data; + const guint8 *data = NULL; _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); From 686d0352e1217af633058b2476a36d7cf6ae81dc Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 3 Aug 2016 21:24:09 -0400 Subject: [PATCH 69/76] deploy: Port file copying code to GLnxDirFdIterator It handles ownership of the `DIR*` for us more cleanly, and is just a better API. This is in preparation for further changes to this code to do SELinux labeling while copying. Closes: #428 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 58 ++++++++++----------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 7b8173b6..d9f6ab94 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -171,76 +171,60 @@ copy_dir_recurse (int src_parent_dfd, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - glnx_fd_close int src_dfd = -1; + g_auto(GLnxDirFdIterator) src_dfd_iter = { 0, }; glnx_fd_close int dest_dfd = -1; - DIR *srcd = NULL; struct dirent *dent; - if (!ot_gopendirat (src_parent_dfd, name, TRUE, &src_dfd, error)) - goto out; + if (!glnx_dirfd_iterator_init_at (src_parent_dfd, name, TRUE, &src_dfd_iter, error)) + return FALSE; /* Create with mode 0700, we'll fchmod/fchown later */ if (mkdirat (dest_parent_dfd, name, 0700) != 0) { glnx_set_error_from_errno (error); - goto out; + return FALSE; } - if (!ot_gopendirat (dest_parent_dfd, name, TRUE, &dest_dfd, error)) - goto out; + if (!glnx_opendirat (dest_parent_dfd, name, TRUE, &dest_dfd, error)) + return FALSE; - if (!dirfd_copy_attributes_and_xattrs (src_parent_dfd, name, src_dfd, dest_dfd, + if (!dirfd_copy_attributes_and_xattrs (src_parent_dfd, name, src_dfd_iter.fd, dest_dfd, cancellable, error)) - goto out; + return FALSE; - srcd = fdopendir (src_dfd); - if (!srcd) + while (TRUE) { - glnx_set_error_from_errno (error); - goto out; - } - - while ((dent = readdir (srcd)) != NULL) - { - const char *name = dent->d_name; struct stat child_stbuf; - if (strcmp (name, ".") == 0 || - strcmp (name, "..") == 0) - continue; + if (!glnx_dirfd_iterator_next_dent (&src_dfd_iter, &dent, cancellable, error)) + return FALSE; + if (dent == NULL) + break; - if (fstatat (src_dfd, name, &child_stbuf, + if (fstatat (src_dfd_iter.fd, dent->d_name, &child_stbuf, AT_SYMLINK_NOFOLLOW) != 0) { glnx_set_error_from_errno (error); - goto out; + return FALSE; } if (S_ISDIR (child_stbuf.st_mode)) { - if (!copy_dir_recurse (src_dfd, dest_dfd, name, + if (!copy_dir_recurse (src_dfd_iter.fd, dest_dfd, dent->d_name, cancellable, error)) - goto out; + return FALSE; } else { - if (!glnx_file_copy_at (src_dfd, name, &child_stbuf, dest_dfd, name, + if (!glnx_file_copy_at (src_dfd_iter.fd, dent->d_name, &child_stbuf, + dest_dfd, dent->d_name, GLNX_FILE_COPY_OVERWRITE, cancellable, error)) - goto out; + return FALSE; } } - ret = TRUE; - out: - if (srcd) - { - (void) closedir (srcd); - /* Note the srcd owns src_dfd */ - src_dfd = -1; - } - return ret; + return TRUE; } static gboolean From d238683332e1aa7d18551d293d4c941a3d010545 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 4 Aug 2016 09:37:26 -0400 Subject: [PATCH 70/76] deploy: Use internal recursive copy rather than libgsystem Since we already had a "recursive copy" implementation here, let's reuse it rather than the libgsystem `gs_shutil_cp_a()`. Part of the libglnx porting. Closes: #428 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d9f6ab94..a05ca30d 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -854,10 +854,15 @@ merge_configuration (OstreeSysroot *sysroot, if (usretc_exists) { + glnx_fd_close int deployment_usr_dfd = -1; + + if (!glnx_opendirat (deployment_dfd, "usr", TRUE, &deployment_usr_dfd, error)) + goto out; + /* TODO - set out labels as we copy files */ g_assert (!etc_exists); - if (!gs_shutil_cp_a (deployment_usretc_path, deployment_etc_path, - cancellable, error)) + if (!copy_dir_recurse (deployment_usr_dfd, deployment_dfd, "etc", + cancellable, error)) goto out; /* Here, we initialize SELinux policy from the /usr/etc inside From 056cc0543f2a965fbcb66952b9c9d295fdd2e865 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 8 Aug 2016 20:19:54 -0400 Subject: [PATCH 71/76] build: Update .gitignore The patch to add more symlink bits also needed CLEANFILES updates. Closes: #446 Approved by: jlebon --- Makefile-tests.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile-tests.am b/Makefile-tests.am index 4316f2ee..80f60add 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -243,6 +243,7 @@ ALL_LOCAL_RULES += tests/libreaddir-rand.so CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp \ tests/ostree-prepare-root-symlink-stamp tests/ostree-remount-symlink-stamp \ tests/rofiles-fuse-symlink-stamp tests/ostree +CLEANFILES += tests/ostree-prepare-root tests/ostree-remount tests/rofiles-fuse tests/%-symlink-stamp: % Makefile $(AM_V_GEN) set -e; \ From fd9536bb19dc70f14a9fe0f622f52aa80d36b85b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 8 Aug 2016 15:41:09 -0400 Subject: [PATCH 72/76] prune: Retain the tip of each ref even with date pruning I hit an error with [CAHC](https://wiki.centos.org/SpecialInterestGroup/Atomic/Devel) where we were doing time-based pruning. `ostree summary -u` started failing, and it took me a bit to realize it was because we were pruning even the tip of old branches, which I was not at all expecting, and I don't think users will too. Perhaps in the future we could add some sort of --prune-ref-tips or something if people wanted it, but I doubt it. Closes: #445 Approved by: jlebon --- src/ostree/ot-builtin-prune.c | 20 ++++++++++++++++++++ tests/test-prune.sh | 16 +++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c index 0b843c98..393ba379 100644 --- a/src/ostree/ot-builtin-prune.c +++ b/src/ostree/ot-builtin-prune.c @@ -84,6 +84,8 @@ delete_commit (OstreeRepo *repo, const char *commit_to_delete, GCancellable *can static gboolean prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCancellable *cancellable, GError **error) { + g_autoptr(GHashTable) refs = NULL; + g_autoptr(GHashTable) ref_heads = g_hash_table_new (g_str_hash, g_str_equal); g_autoptr(GHashTable) objects = NULL; GHashTableIter hash_iter; gpointer key, value; @@ -100,6 +102,21 @@ prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCance if (!ot_enable_tombstone_commits (repo, error)) goto out; + if (!ostree_repo_list_refs (repo, NULL, &refs, cancellable, error)) + goto out; + + /* We used to prune the HEAD of a given ref by default, but that's + * broken for a few reasons. One is that people may use branches as + * tags. Second is that if we do it, we should be deleting the ref + * too, otherwise e.g. `summary -u` breaks trying to load it, etc. + */ + g_hash_table_iter_init (&hash_iter, refs); + while (g_hash_table_iter_next (&hash_iter, &key, &value)) + { + /* Value is lifecycle bound to refs */ + g_hash_table_add (ref_heads, (char*)value); + } + if (!ostree_repo_list_objects (repo, OSTREE_REPO_LIST_OBJECTS_ALL, &objects, cancellable, error)) goto out; @@ -119,6 +136,9 @@ prune_commits_keep_younger_than_date (OstreeRepo *repo, const char *date, GCance if (objtype != OSTREE_OBJECT_TYPE_COMMIT) continue; + if (g_hash_table_contains (ref_heads, checksum)) + continue; + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, checksum, &commit, error)) goto out; diff --git a/tests/test-prune.sh b/tests/test-prune.sh index d32edbc0..5134d560 100755 --- a/tests/test-prune.sh +++ b/tests/test-prune.sh @@ -87,25 +87,31 @@ assert_file_has_content tombstonecommitcount "^1$" ${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$" -${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="2010-10-29 12:43:29 +0000" ${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$" ${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 "^1$" +assert_file_has_content commitcount "^2$" ${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_file_has_content commitcount "^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 "^3$" +assert_file_has_content commitcount "^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 "^1$" +assert_file_has_content commitcount "^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) +$OSTREE ls ${oldcommit_rev} +${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" +$OSTREE ls ${oldcommit_rev} ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin test ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="November 05 1955" From a29bb0ab6b3d495e0c3d09384712290acf36ee5d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 22 Jun 2016 20:12:31 -0400 Subject: [PATCH 73/76] Final excision of libgsystem dependency Lots and lots of preparation led to this moment - when nothing apparent changes for users! Woo! But seriously, having the extra dependency is a minor annoyance, and in the big picture I think the libgsystem idea was wrong - we need to land things in GLib, and use git submodules for API-unstable or Linux-specific sharing. For a lot of OSTree, the libgsystem `GFile*` orientation was also wrong, we really want fd-relative. Closes: #444 Approved by: jlebon --- configure.ac | 2 +- libglnx | 2 +- packaging/ostree.spec.in | 1 - src/libotutil/ot-fs-utils.c | 1 - src/libotutil/ot-gio-utils.c | 36 ++++++++++++++++++++++++++++++++++ src/libotutil/ot-gio-utils.h | 10 ++++++++++ src/libotutil/otutil.h | 2 -- src/ostree/ot-editor.c | 2 +- tests/ci-install.sh | 20 ------------------- tests/test-checksum.c | 1 - tests/test-gpg-verify-result.c | 2 +- 11 files changed, 50 insertions(+), 29 deletions(-) diff --git a/configure.ac b/configure.ac index 4831bcc4..558a590f 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AM_PATH_GLIB_2_0 dnl When bumping the gio-unix-2.0 dependency (or glib-2.0 in general), dnl remember to bump GLIB_VERSION_MIN_REQUIRED and dnl GLIB_VERSION_MAX_ALLOWED in Makefile.am -GIO_DEPENDENCY="gio-unix-2.0 >= 2.40.0 libgsystem >= 2015.1" +GIO_DEPENDENCY="gio-unix-2.0 >= 2.40.0" PKG_CHECK_MODULES(OT_DEP_GIO_UNIX, $GIO_DEPENDENCY) dnl 5.1.0 is an arbitrary version here diff --git a/libglnx b/libglnx index 871617d5..4ae5e3be 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 871617d51984604e28483d959e37fd6ce4524b0e +Subproject commit 4ae5e3beaaa674abfabf7404ab6fafcc4ec547db diff --git a/packaging/ostree.spec.in b/packaging/ostree.spec.in index 2f07f0a8..eff0f353 100644 --- a/packaging/ostree.spec.in +++ b/packaging/ostree.spec.in @@ -15,7 +15,6 @@ BuildRequires: gtk-doc # Core requirements BuildRequires: pkgconfig(gio-unix-2.0) BuildRequires: pkgconfig(libsoup-2.4) -BuildRequires: pkgconfig(libgsystem) BuildRequires: pkgconfig(e2p) # Extras BuildRequires: pkgconfig(libarchive) diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 46a0405b..4575effe 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -21,7 +21,6 @@ #include "config.h" #include "ot-fs-utils.h" -#include "libgsystem.h" #include "libglnx.h" #include #include diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index a7fe74cf..683fa48e 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -463,3 +463,39 @@ ot_file_enumerator_iterate (GFileEnumerator *direnum, } #endif + +G_LOCK_DEFINE_STATIC (pathname_cache); + +/** + * ot_file_get_path_cached: + * + * Like g_file_get_path(), but returns a constant copy so callers + * don't need to free the result. + */ +const char * +ot_file_get_path_cached (GFile *file) +{ + const char *path; + static GQuark _file_path_quark = 0; + + if (G_UNLIKELY (_file_path_quark) == 0) + _file_path_quark = g_quark_from_static_string ("gsystem-file-path"); + + G_LOCK (pathname_cache); + + path = g_object_get_qdata ((GObject*)file, _file_path_quark); + if (!path) + { + path = g_file_get_path (file); + if (path == NULL) + { + G_UNLOCK (pathname_cache); + return NULL; + } + g_object_set_qdata_full ((GObject*)file, _file_path_quark, (char*)path, (GDestroyNotify)g_free); + } + + G_UNLOCK (pathname_cache); + + return path; +} diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h index 030acac6..0d3c45d2 100644 --- a/src/libotutil/ot-gio-utils.h +++ b/src/libotutil/ot-gio-utils.h @@ -115,4 +115,14 @@ ot_file_enumerator_iterate (GFileEnumerator *direnum, #endif #define g_file_enumerator_iterate ot_file_enumerator_iterate +const char * +ot_file_get_path_cached (GFile *file); + +static inline +const char * +gs_file_get_path_cached (GFile *file) +{ + return ot_file_get_path_cached (file); +} + G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index 6790d8ff..ec516f65 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -23,9 +23,7 @@ #pragma once #include -#include #include /* Yeah...let's just do that here. */ -#include #include #define ot_gobject_refz(o) (o ? g_object_ref (o) : o) diff --git a/src/ostree/ot-editor.c b/src/ostree/ot-editor.c index 66c6e7be..bb0dd3c2 100644 --- a/src/ostree/ot-editor.c +++ b/src/ostree/ot-editor.c @@ -23,8 +23,8 @@ #include "config.h" #include "libglnx.h" +#include "otutil.h" #include "ot-editor.h" -#include "libgsystem.h" #include #include diff --git a/tests/ci-install.sh b/tests/ci-install.sh index ecd03b58..4aff39e9 100755 --- a/tests/ci-install.sh +++ b/tests/ci-install.sh @@ -31,25 +31,6 @@ case "$ci_distro" in ;; esac -case "$ci_suite" in - (jessie) - # Add alexl's Debian 8 backport repository to get libgsystem - # TODO: remove this when libgsystem is no longer needed - $sudo apt-get -y update - $sudo apt-get -y install apt-transport-https wget - wget -O - https://sdk.gnome.org/apt/debian/conf/alexl.gpg.key | $sudo apt-key add - - echo "deb [arch=amd64] https://sdk.gnome.org/apt/debian/ jessie main" | $sudo tee /etc/apt/sources.list.d/flatpak.list - ;; - - (trusty|xenial) - # Add alexl's Flatpak PPA, again to get libgsystem - # TODO: remove this when libgsystem is no longer needed - $sudo apt-get -y update - $sudo apt-get -y install software-properties-common - $sudo add-apt-repository --yes ppa:alexlarsson/flatpak - ;; -esac - case "$ci_distro" in (debian|ubuntu) # TODO: fetch this list from the Debian packaging git repository? @@ -77,7 +58,6 @@ case "$ci_distro" in libgirepository1.0-dev \ libglib2.0-dev \ libgpgme11-dev \ - libgsystem-dev \ liblzma-dev \ libmount-dev \ libselinux1-dev \ diff --git a/tests/test-checksum.c b/tests/test-checksum.c index e7fd7be4..9537804d 100644 --- a/tests/test-checksum.c +++ b/tests/test-checksum.c @@ -21,7 +21,6 @@ #include "config.h" #include "libglnx.h" -#include "libgsystem.h" #include #include #include diff --git a/tests/test-gpg-verify-result.c b/tests/test-gpg-verify-result.c index e2cb48a7..d2c1ff66 100644 --- a/tests/test-gpg-verify-result.c +++ b/tests/test-gpg-verify-result.c @@ -20,8 +20,8 @@ #include "config.h" -#include #include +#include "libglnx.h" #include "ostree-gpg-verify-result-private.h" From 519292114fd2294f9a09b4674010a8c98bb89b5c Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 9 Aug 2016 12:51:30 -0400 Subject: [PATCH 74/76] travis: Disable email notifications I'm getting spammed. We'll see the results in the status. Closes: #450 Approved by: jlebon --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8b57f413..8594ff78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,6 @@ env: script: - tests/ci-install.sh - ci_parallel=2 ci_sudo=yes tests/ci-build.sh + +notifications: + email: false From 56a922280fbf2012f2b790691450a7e4fdc9e1c8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 9 Aug 2016 13:52:43 -0400 Subject: [PATCH 75/76] tests: Port sysroot.js away from libgsystem My case-sensitive `git grep` didn't find this one originally, but the Travis+Debian setup was configured to run it. Closes: #451 Approved by: jlebon --- tests/test-sysroot.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/test-sysroot.js b/tests/test-sysroot.js index 7c31659d..7e8fcf7a 100644 --- a/tests/test-sysroot.js +++ b/tests/test-sysroot.js @@ -19,8 +19,6 @@ const GLib = imports.gi.GLib; const Gio = imports.gi.Gio; - -const GSystem = imports.gi.GSystem; const OSTree = imports.gi.OSTree; function assertEquals(a, b) { @@ -36,12 +34,8 @@ function assertNotEquals(a, b) { function libtestExec(shellCode) { let testdatadir = GLib.getenv("G_TEST_SRCDIR"); let libtestPath = GLib.build_filenamev([testdatadir, 'libtest.sh']) - let proc = GSystem.Subprocess.new_simple_argv(['bash', '-c', - 'set -xeuo pipefail; . ' + GLib.shell_quote(libtestPath) + '; ' + shellCode], - GSystem.SubprocessStreamDisposition.INHERIT, - GSystem.SubprocessStreamDisposition.INHERIT, - null); - proc.wait_sync_check(null); + let proc = Gio.Subprocess.new(['bash', '-c', 'set -xeuo pipefail; . ' + GLib.shell_quote(libtestPath) + '; ' + shellCode], 0); + proc.wait_check(null); } libtestExec('setup_os_repository archive-z2 syslinux'); From 73eabca5e853385df0cd81dd0f685904f9a20c3d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 9 Aug 2016 13:58:02 -0400 Subject: [PATCH 76/76] Release 2016.8 It's time for a new release, there's enough queued and it's been ~a month. Closes: #452 Approved by: jlebon --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 558a590f..aa4a42bd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.63]) -AC_INIT([ostree], [2016.7], [walters@verbum.org]) +AC_INIT([ostree], [2016.8], [walters@verbum.org]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux])