diff --git a/Makefile-libostree.am b/Makefile-libostree.am index a180e86b..96b9249b 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -182,9 +182,9 @@ libostree_1_la_SOURCES += \ endif # USE_GPGME symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym -#if BUILDOPT_IS_DEVEL_BUILD -#symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym -#endif +if BUILDOPT_IS_DEVEL_BUILD +symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym +endif # http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html wl_versionscript_arg = -Wl,--version-script= EXTRA_DIST += \ diff --git a/Makefile-tests.am b/Makefile-tests.am index a4179377..3fbc94bf 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -105,6 +105,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-deploy-nomerge.sh \ tests/test-admin-deploy-none.sh \ tests/test-admin-deploy-bootid-gc.sh \ + tests/test-osupdate-dtb.sh \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ tests/test-admin-pull-deploy-commit.sh \ @@ -114,6 +115,8 @@ _installed_or_uninstalled_test_scripts = \ tests/test-reset-nonlinear.sh \ tests/test-oldstyle-partial.sh \ tests/test-delta.sh \ + tests/test-delta-sign.sh \ + tests/test-delta-ed25519.sh \ tests/test-xattrs.sh \ tests/test-auto-summary.sh \ tests/test-prune.sh \ diff --git a/Makefile.in b/Makefile.in index dd959d64..e90c2196 100644 --- a/Makefile.in +++ b/Makefile.in @@ -454,15 +454,16 @@ check_PROGRAMS = $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) @USE_GPGME_FALSE@ src/libostree/ostree-gpg-verify-result-dummy.c \ @USE_GPGME_FALSE@ $(NULL) +@BUILDOPT_IS_DEVEL_BUILD_TRUE@am__append_26 = $(top_srcdir)/src/libostree/libostree-devel.sym # Some change between rust-1.21.0-1.fc27 and rust-1.22.1-1.fc27.x86_64 -@ENABLE_RUST_TRUE@am__append_26 = -ldl -@USE_LIBARCHIVE_TRUE@am__append_27 = $(OT_DEP_LIBARCHIVE_CFLAGS) -@USE_LIBARCHIVE_TRUE@am__append_28 = $(OT_DEP_LIBARCHIVE_LIBS) -@USE_AVAHI_TRUE@am__append_29 = $(OT_DEP_AVAHI_CFLAGS) -@USE_AVAHI_TRUE@am__append_30 = $(OT_DEP_AVAHI_LIBS) -@BUILDOPT_SYSTEMD_TRUE@am__append_31 = $(LIBSYSTEMD_CFLAGS) -@BUILDOPT_SYSTEMD_TRUE@am__append_32 = $(LIBSYSTEMD_LIBS) -@USE_CURL_OR_SOUP_TRUE@am__append_33 = \ +@ENABLE_RUST_TRUE@am__append_27 = -ldl +@USE_LIBARCHIVE_TRUE@am__append_28 = $(OT_DEP_LIBARCHIVE_CFLAGS) +@USE_LIBARCHIVE_TRUE@am__append_29 = $(OT_DEP_LIBARCHIVE_LIBS) +@USE_AVAHI_TRUE@am__append_30 = $(OT_DEP_AVAHI_CFLAGS) +@USE_AVAHI_TRUE@am__append_31 = $(OT_DEP_AVAHI_LIBS) +@BUILDOPT_SYSTEMD_TRUE@am__append_32 = $(LIBSYSTEMD_CFLAGS) +@BUILDOPT_SYSTEMD_TRUE@am__append_33 = $(LIBSYSTEMD_LIBS) +@USE_CURL_OR_SOUP_TRUE@am__append_34 = \ @USE_CURL_OR_SOUP_TRUE@ src/libostree/ostree-fetcher.h \ @USE_CURL_OR_SOUP_TRUE@ src/libostree/ostree-fetcher-util.h \ @USE_CURL_OR_SOUP_TRUE@ src/libostree/ostree-fetcher-util.c \ @@ -471,45 +472,45 @@ check_PROGRAMS = $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) @USE_CURL_OR_SOUP_TRUE@ src/libostree/ostree-metalink.c \ @USE_CURL_OR_SOUP_TRUE@ $(NULL) -@USE_CURL_TRUE@am__append_34 = src/libostree/ostree-fetcher-curl.c \ +@USE_CURL_TRUE@am__append_35 = src/libostree/ostree-fetcher-curl.c \ @USE_CURL_TRUE@ src/libostree/ostree-soup-uri.h src/libostree/ostree-soup-uri.c \ @USE_CURL_TRUE@ src/libostree/ostree-soup-form.c \ @USE_CURL_TRUE@ $(NULL) -@USE_CURL_TRUE@am__append_35 = $(OT_DEP_CURL_CFLAGS) -@USE_CURL_TRUE@am__append_36 = $(OT_DEP_CURL_LIBS) -@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_37 = src/libostree/ostree-fetcher-soup.c -@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_38 = $(OT_INTERNAL_SOUP_CFLAGS) -@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_39 = $(OT_INTERNAL_SOUP_LIBS) -@USE_AVAHI_TRUE@@USE_CURL_FALSE@@USE_LIBSOUP_FALSE@am__append_40 = src/libostree/ostree-soup-uri.h \ +@USE_CURL_TRUE@am__append_36 = $(OT_DEP_CURL_CFLAGS) +@USE_CURL_TRUE@am__append_37 = $(OT_DEP_CURL_LIBS) +@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_38 = src/libostree/ostree-fetcher-soup.c +@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_39 = $(OT_INTERNAL_SOUP_CFLAGS) +@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_40 = $(OT_INTERNAL_SOUP_LIBS) +@USE_AVAHI_TRUE@@USE_CURL_FALSE@@USE_LIBSOUP_FALSE@am__append_41 = src/libostree/ostree-soup-uri.h \ @USE_AVAHI_TRUE@@USE_CURL_FALSE@@USE_LIBSOUP_FALSE@ src/libostree/ostree-soup-uri.c \ @USE_AVAHI_TRUE@@USE_CURL_FALSE@@USE_LIBSOUP_FALSE@ src/libostree/ostree-soup-form.c \ @USE_AVAHI_TRUE@@USE_CURL_FALSE@@USE_LIBSOUP_FALSE@ $(NULL) -@USE_LIBMOUNT_TRUE@am__append_41 = $(OT_DEP_LIBMOUNT_CFLAGS) -@USE_LIBMOUNT_TRUE@am__append_42 = $(OT_DEP_LIBMOUNT_LIBS) -@USE_SELINUX_TRUE@am__append_43 = $(OT_DEP_SELINUX_CFLAGS) -@USE_SELINUX_TRUE@am__append_44 = $(OT_DEP_SELINUX_LIBS) -@USE_LIBSODIUM_TRUE@am__append_45 = $(OT_DEP_LIBSODIUM_CFLAGS) -@USE_LIBSODIUM_TRUE@am__append_46 = $(OT_DEP_LIBSODIUM_LIBS) +@USE_LIBMOUNT_TRUE@am__append_42 = $(OT_DEP_LIBMOUNT_CFLAGS) +@USE_LIBMOUNT_TRUE@am__append_43 = $(OT_DEP_LIBMOUNT_LIBS) +@USE_SELINUX_TRUE@am__append_44 = $(OT_DEP_SELINUX_CFLAGS) +@USE_SELINUX_TRUE@am__append_45 = $(OT_DEP_SELINUX_LIBS) +@USE_LIBSODIUM_TRUE@am__append_46 = $(OT_DEP_LIBSODIUM_CFLAGS) +@USE_LIBSODIUM_TRUE@am__append_47 = $(OT_DEP_LIBSODIUM_LIBS) # When compiling this is set via config.h, but g-ir-scanner can't use that -@BUILDOPT_INTROSPECTION_TRUE@@ENABLE_EXPERIMENTAL_API_TRUE@am__append_47 = -DOSTREE_ENABLE_EXPERIMENTAL_API=1 -@BUILDOPT_INTROSPECTION_TRUE@am__append_48 = OSTree-1.0.gir +@BUILDOPT_INTROSPECTION_TRUE@@ENABLE_EXPERIMENTAL_API_TRUE@am__append_48 = -DOSTREE_ENABLE_EXPERIMENTAL_API=1 @BUILDOPT_INTROSPECTION_TRUE@am__append_49 = OSTree-1.0.gir -@BUILDOPT_INTROSPECTION_TRUE@am__append_50 = OSTree-1.0.typelib -@BUILDOPT_INTROSPECTION_TRUE@am__append_51 = $(gir_DATA) $(typelib_DATA) -@ENABLE_EXPERIMENTAL_API_TRUE@am__append_52 = \ +@BUILDOPT_INTROSPECTION_TRUE@am__append_50 = OSTree-1.0.gir +@BUILDOPT_INTROSPECTION_TRUE@am__append_51 = OSTree-1.0.typelib +@BUILDOPT_INTROSPECTION_TRUE@am__append_52 = $(gir_DATA) $(typelib_DATA) +@ENABLE_EXPERIMENTAL_API_TRUE@am__append_53 = \ @ENABLE_EXPERIMENTAL_API_TRUE@ $(NULL) -@USE_GPGME_TRUE@am__append_53 = \ +@USE_GPGME_TRUE@am__append_54 = \ @USE_GPGME_TRUE@ src/ostree/ot-builtin-gpg-sign.c \ @USE_GPGME_TRUE@ $(NULL) -@USE_GPGME_TRUE@am__append_54 = \ +@USE_GPGME_TRUE@am__append_55 = \ @USE_GPGME_TRUE@ src/ostree/ot-remote-builtin-gpg-import.c \ @USE_GPGME_TRUE@ $(NULL) -@USE_CURL_OR_SOUP_TRUE@am__append_55 = src/ostree/ot-remote-builtin-add-cookie.c \ +@USE_CURL_OR_SOUP_TRUE@am__append_56 = src/ostree/ot-remote-builtin-add-cookie.c \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ot-remote-builtin-delete-cookie.c \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ot-remote-builtin-list-cookies.c \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ot-remote-cookie-util.h \ @@ -517,20 +518,20 @@ check_PROGRAMS = $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) @USE_CURL_OR_SOUP_TRUE@ $(NULL) src/ostree/ot-builtin-pull.c # Eventually once we stop things from using this, we should support disabling this -@USE_LIBSOUP_TRUE@am__append_56 = src/ostree/ot-builtin-trivial-httpd.c -@USE_LIBSOUP_TRUE@am__append_57 = ostree-trivial-httpd +@USE_LIBSOUP_TRUE@am__append_57 = src/ostree/ot-builtin-trivial-httpd.c +@USE_LIBSOUP_TRUE@am__append_58 = ostree-trivial-httpd # This is necessary for the cookie jar bits -@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_58 = $(OT_INTERNAL_SOUP_CFLAGS) -@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_59 = $(OT_INTERNAL_SOUP_LIBS) -@USE_LIBARCHIVE_TRUE@am__append_60 = $(OT_DEP_LIBARCHIVE_CFLAGS) -@USE_LIBARCHIVE_TRUE@am__append_61 = $(OT_DEP_LIBARCHIVE_LIBS) -@USE_LIBSODIUM_TRUE@am__append_62 = $(OT_DEP_LIBSODIUM_CFLAGS) -@USE_LIBSODIUM_TRUE@am__append_63 = $(OT_DEP_LIBSODIUM_LIBS) -@BUILDOPT_SYSTEMD_TRUE@am__append_64 = ostree-remount +@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_59 = $(OT_INTERNAL_SOUP_CFLAGS) +@USE_CURL_FALSE@@USE_LIBSOUP_TRUE@am__append_60 = $(OT_INTERNAL_SOUP_LIBS) +@USE_LIBARCHIVE_TRUE@am__append_61 = $(OT_DEP_LIBARCHIVE_CFLAGS) +@USE_LIBARCHIVE_TRUE@am__append_62 = $(OT_DEP_LIBARCHIVE_LIBS) +@USE_LIBSODIUM_TRUE@am__append_63 = $(OT_DEP_LIBSODIUM_CFLAGS) +@USE_LIBSODIUM_TRUE@am__append_64 = $(OT_DEP_LIBSODIUM_LIBS) +@BUILDOPT_SYSTEMD_TRUE@am__append_65 = ostree-remount # It is built anyway as a side-effect of having the symlink in tests/, # and if we declare it here, it gets cleaned up properly -@BUILDOPT_SYSTEMD_FALSE@am__append_65 = ostree-remount +@BUILDOPT_SYSTEMD_FALSE@am__append_66 = ostree-remount # ostree-prepare-root can be used as init in a system without a populated /lib. # To support this use case we need to link statically as we will be unable to @@ -542,66 +543,66 @@ check_PROGRAMS = $(am__EXEEXT_12) $(am__EXEEXT_13) $(am__EXEEXT_14) # to get autotools to install this as an executable but without generating rules # to make it itself which we have specified manually. See # https://lists.gnu.org/archive/html/help-gnu-utils/2007-01/msg00007.html -@BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_66 = ostree-prepare-root -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_67 = ostree-prepare-root -@BUILDOPT_SYSTEMD_TRUE@am__append_68 = -DHAVE_SYSTEMD=1 +@BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_67 = ostree-prepare-root +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_68 = ostree-prepare-root +@BUILDOPT_SYSTEMD_TRUE@am__append_69 = -DHAVE_SYSTEMD=1 # This is the "new mode" of using a generator for /var; see # https://github.com/ostreedev/ostree/issues/855 -@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_69 = -DHAVE_SYSTEMD_AND_LIBMOUNT=1 @BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_70 = -DHAVE_SYSTEMD_AND_LIBMOUNT=1 +@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_71 = -DHAVE_SYSTEMD_AND_LIBMOUNT=1 @BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@systemdsystemgenerator_PROGRAMS = ostree-system-generator$(EXEEXT) -@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_71 = $(systemdsystemgenerator_PROGRAMS) +@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_72 = $(systemdsystemgenerator_PROGRAMS) # Allow the distcheck install under $prefix test to pass -@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_72 = --with-systemdsystemgeneratordir='$${libdir}/systemd/system-generators' -@BUILDOPT_FUSE_TRUE@am__append_73 = rofiles-fuse -@BUILDOPT_ASAN_TRUE@am__append_74 = OT_SKIP_READDIR_RAND=1 G_SLICE=always-malloc -@USE_GPGME_TRUE@am__append_75 = \ +@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_73 = --with-systemdsystemgeneratordir='$${libdir}/systemd/system-generators' +@BUILDOPT_FUSE_TRUE@am__append_74 = rofiles-fuse +@BUILDOPT_ASAN_TRUE@am__append_75 = OT_SKIP_READDIR_RAND=1 G_SLICE=always-malloc +@USE_GPGME_TRUE@am__append_76 = \ @USE_GPGME_TRUE@ tests/test-remote-gpg-import.sh \ @USE_GPGME_TRUE@ tests/test-gpg-signed-commit.sh \ @USE_GPGME_TRUE@ tests/test-admin-gpg.sh \ @USE_GPGME_TRUE@ $(NULL) -@ENABLE_EXPERIMENTAL_API_TRUE@am__append_76 = $(experimental_test_scripts) -@ENABLE_EXPERIMENTAL_API_FALSE@am__append_77 = $(experimental_test_scripts) -@BUILDOPT_FUSE_TRUE@am__append_78 = tests/test-rofiles-fuse.sh -@BUILDOPT_FUSE_TRUE@am__append_79 = tests/rofiles-fuse-symlink-stamp -@BUILDOPT_FUSE_FALSE@am__append_80 = tests/test-rofiles-fuse.sh -@USE_LIBSOUP_TRUE@am__append_81 = tests/test-remote-cookies.sh -@BUILDOPT_GJS_TRUE@am__append_82 = $(js_tests) $(js_installed_tests) -@BUILDOPT_GJS_FALSE@am__append_83 = $(js_tests) -@BUILDOPT_GJS_FALSE@am__append_84 = $(js_installed_tests) -@ENABLE_INSTALLED_TESTS_FALSE@am__append_85 = -rpath $(abs_builddir) -@USE_GPGME_TRUE@am__append_86 = \ +@ENABLE_EXPERIMENTAL_API_TRUE@am__append_77 = $(experimental_test_scripts) +@ENABLE_EXPERIMENTAL_API_FALSE@am__append_78 = $(experimental_test_scripts) +@BUILDOPT_FUSE_TRUE@am__append_79 = tests/test-rofiles-fuse.sh +@BUILDOPT_FUSE_TRUE@am__append_80 = tests/rofiles-fuse-symlink-stamp +@BUILDOPT_FUSE_FALSE@am__append_81 = tests/test-rofiles-fuse.sh +@USE_LIBSOUP_TRUE@am__append_82 = tests/test-remote-cookies.sh +@BUILDOPT_GJS_TRUE@am__append_83 = $(js_tests) $(js_installed_tests) +@BUILDOPT_GJS_FALSE@am__append_84 = $(js_tests) +@BUILDOPT_GJS_FALSE@am__append_85 = $(js_installed_tests) +@ENABLE_INSTALLED_TESTS_FALSE@am__append_86 = -rpath $(abs_builddir) +@USE_GPGME_TRUE@am__append_87 = \ @USE_GPGME_TRUE@ tests/test-gpg-verify-result \ @USE_GPGME_TRUE@ $(NULL) -@USE_AVAHI_TRUE@am__append_87 = tests/test-repo-finder-avahi -@USE_LIBARCHIVE_TRUE@am__append_88 = tests/test-libarchive-import -@USE_GPGME_TRUE@am__append_89 = \ +@USE_AVAHI_TRUE@am__append_88 = tests/test-repo-finder-avahi +@USE_LIBARCHIVE_TRUE@am__append_89 = tests/test-libarchive-import +@USE_GPGME_TRUE@am__append_90 = \ @USE_GPGME_TRUE@ tests/gpg-verify-data/README.md \ @USE_GPGME_TRUE@ $(NULL) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_90 = $(_installed_or_uninstalled_test_scripts) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_91 = $(_installed_or_uninstalled_test_programs) -@ENABLE_INSTALLED_TESTS_TRUE@am__append_92 = install-installed-tests-extra +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_91 = $(_installed_or_uninstalled_test_scripts) +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_92 = $(_installed_or_uninstalled_test_programs) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_93 = install-installed-tests-extra # Allow the distcheck install under $prefix test to pass -@BUILDOPT_SYSTEMD_TRUE@am__append_93 = --with-systemdsystemunitdir='$${libdir}/systemd/system' +@BUILDOPT_SYSTEMD_TRUE@am__append_94 = --with-systemdsystemunitdir='$${libdir}/systemd/system' # We're using the system grub2-mkconfig generator -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_94 = src/boot/grub2/grub2-15_ostree -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_95 = install-grub2-config-hook +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_95 = src/boot/grub2/grub2-15_ostree +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_96 = install-grub2-config-hook # We're using our internal generator -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_TRUE@am__append_96 = src/boot/grub2/ostree-grub-generator -@ENABLE_MAN_TRUE@@USE_LIBSOUP_TRUE@am__append_97 = ostree-trivial-httpd.1 +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_TRUE@am__append_97 = src/boot/grub2/ostree-grub-generator +@ENABLE_MAN_TRUE@@USE_LIBSOUP_TRUE@am__append_98 = ostree-trivial-httpd.1 # We still want to distribute the source, even if we are not building it -@ENABLE_MAN_TRUE@@USE_LIBSOUP_FALSE@am__append_98 = man/ostree-trivial-httpd.xml -@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_99 = rofiles-fuse.1 -@ENABLE_MAN_TRUE@@USE_GPGME_TRUE@am__append_100 = ostree-gpg-sign.1 -@ENABLE_MAN_TRUE@am__append_101 = $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) -@ENABLE_MAN_TRUE@am__append_102 = \ +@ENABLE_MAN_TRUE@@USE_LIBSOUP_FALSE@am__append_99 = man/ostree-trivial-httpd.xml +@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_100 = rofiles-fuse.1 +@ENABLE_MAN_TRUE@@USE_GPGME_TRUE@am__append_101 = ostree-gpg-sign.1 +@ENABLE_MAN_TRUE@am__append_102 = $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) +@ENABLE_MAN_TRUE@am__append_103 = \ @ENABLE_MAN_TRUE@ $(man1_MANS) \ @ENABLE_MAN_TRUE@ $(man5_MANS) \ @ENABLE_MAN_TRUE@ $(NULL) @@ -2055,13 +2056,15 @@ am__EXEEXT_25 = tests/test-basic.sh tests/test-basic-user.sh \ tests/test-admin-deploy-nomerge.sh \ tests/test-admin-deploy-none.sh \ tests/test-admin-deploy-bootid-gc.sh \ + tests/test-osupdate-dtb.sh \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ tests/test-admin-pull-deploy-commit.sh \ tests/test-admin-pull-deploy-split.sh \ tests/test-admin-locking.sh tests/test-admin-deploy-clean.sh \ tests/test-reset-nonlinear.sh tests/test-oldstyle-partial.sh \ - tests/test-delta.sh tests/test-xattrs.sh \ + tests/test-delta.sh tests/test-delta-sign.sh \ + tests/test-delta-ed25519.sh tests/test-xattrs.sh \ tests/test-auto-summary.sh tests/test-prune.sh \ tests/test-concurrency.py tests/test-refs.sh \ tests/test-demo-buildsystem.sh tests/test-switchroot.sh \ @@ -2078,8 +2081,8 @@ am__EXEEXT_25 = tests/test-basic.sh tests/test-basic-user.sh \ tests/test-signed-commit.sh tests/test-signed-pull.sh \ tests/test-pre-signed-pull.sh \ tests/test-signed-pull-summary.sh $(am__EXEEXT_2) \ - $(am__EXEEXT_20) $(am__EXEEXT_22) $(am__append_78) \ - $(am__append_81) $(am__EXEEXT_24) + $(am__EXEEXT_20) $(am__EXEEXT_22) $(am__append_79) \ + $(am__append_82) $(am__EXEEXT_24) @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__EXEEXT_26 = \ @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@ $(am__EXEEXT_25) am__EXEEXT_27 = $(am__EXEEXT_2) $(am__EXEEXT_26) @@ -2382,21 +2385,21 @@ AM_CFLAGS = -std=gnu99 -fno-strict-aliasing $(WARN_CFLAGS) # Allow the distcheck install under $prefix test to pass AM_DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-man \ - --disable-maintainer-mode $(NULL) $(am__append_72) \ - $(am__append_93) \ + --disable-maintainer-mode $(NULL) $(am__append_73) \ + $(am__append_94) \ BASH_COMPLETIONSDIR='$${datadir}/bash-completion/completions' SUBDIRS = . $(am__append_14) NULL = BUILT_SOURCES = $(nodist_libostree_1_la_SOURCES) MANPAGES = -CLEANFILES = $(am__append_13) $(BUILT_SOURCES) $(am__append_51) \ +CLEANFILES = $(am__append_13) $(BUILT_SOURCES) $(am__append_52) \ src/ostree/parse-datetime.c 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-prepare-root tests/ostree-remount \ - tests/rofiles-fuse $(am__append_102) + tests/rofiles-fuse $(am__append_103) EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ COPYING README.md $(am__append_15) libglnx/README.md \ libglnx/COPYING libglnx/libglnx.m4 $(NULL) \ @@ -2412,9 +2415,9 @@ EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ src/libostree/ostree-repo-deprecated.h \ src/libostree/ostree-version.h src/ostree/parse-datetime.y \ buildutil/tap-driver.sh buildutil/tap-test tests/glib.supp \ - tests/ostree.supp $(NULL) $(am__append_77) $(am__append_80) \ - $(am__append_83) tests/libtest.sh $(am__append_84) \ - $(am__append_89) tests/libostreetest.h tests/libtest.sh \ + tests/ostree.supp $(NULL) $(am__append_78) $(am__append_81) \ + $(am__append_84) tests/libtest.sh $(am__append_85) \ + $(am__append_90) tests/libostreetest.h tests/libtest.sh \ $(NULL) src/boot/dracut/module-setup.sh \ src/boot/dracut/ostree.conf src/boot/mkinitcpio/ostree \ src/boot/ostree-prepare-root.service \ @@ -2422,25 +2425,25 @@ EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ src/boot/ostree-remount.service \ src/boot/ostree-finalize-staged.service \ src/boot/grub2/grub2-15_ostree \ - src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_98) \ - $(am__append_101) + src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_99) \ + $(am__append_102) bin_SCRIPTS = lib_LTLIBRARIES = libostree-1.la -pkglibexec_SCRIPTS = $(am__append_94) +pkglibexec_SCRIPTS = $(am__append_95) noinst_LTLIBRARIES = $(am__append_1) libglnx.la libbsdiff.la \ libotutil.la $(am__append_18) libostreetest.la privlibdir = $(pkglibdir) privlib_LTLIBRARIES = pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = src/libostree/ostree-1.pc -INTROSPECTION_GIRS = $(am__append_48) +INTROSPECTION_GIRS = $(am__append_49) girdir = $(datadir)/gir-1.0 -gir_DATA = $(am__append_49) +gir_DATA = $(am__append_50) typelibdir = $(libdir)/girepository-1.0 -typelib_DATA = $(am__append_50) +typelib_DATA = $(am__append_51) gsettings_SCHEMAS = ostree_bootdir = $(prefix)/lib/ostree -ostree_boot_SCRIPTS = $(am__append_66) $(am__append_96) +ostree_boot_SCRIPTS = $(am__append_67) $(am__append_97) # We should probably consider flipping the default for DEBUG. Also, # include the builddir in $PATH so we find our just-built ostree @@ -2457,7 +2460,7 @@ AM_TESTS_ENVIRONMENT = G_TEST_SRCDIR="$(abs_srcdir)" \ pwd)$${LD_LIBRARY_PATH:+:$${LD_LIBRARY_PATH}} PATH=$$(cd \ $(top_builddir)/tests && pwd):$${PATH} \ OSTREE_FEATURES="$(OSTREE_FEATURES)" PYTHONUNBUFFERED=1 \ - $(NULL) $(am__append_74) + $(NULL) $(am__append_75) LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/buildutil/tap-driver.sh LOG_COMPILER = $(top_srcdir)/buildutil/tap-test installed_test_LTLIBRARIES = $(am__append_12) @@ -2497,8 +2500,8 @@ all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installe # This initializes some more variables # This is a special facility to chain together hooks easily -INSTALL_DATA_HOOKS = install-mkdir-remotes-d-hook $(am__append_92) \ - $(am__append_95) +INSTALL_DATA_HOOKS = install-mkdir-remotes-d-hook $(am__append_93) \ + $(am__append_96) ALL_LOCAL_RULES = tests/libreaddir-rand.so shortened_sysconfdir = $$(echo "$(sysconfdir)" | sed -e 's|^$(prefix)||' -e 's|^/||') OSTREE_GITREV = $(shell cd $(srcdir) && if command -v git >/dev/null 2>&1 && test -d .git; then git describe --abbrev=42 --tags --always HEAD; fi) @@ -2506,7 +2509,7 @@ ACLOCAL_AMFLAGS = -I buildutil -I libglnx ${ACLOCAL_FLAGS} # Generated by coreos-assembler build-fast and kola GITIGNOREFILES = aclocal.m4 build-aux/ buildutil/*.m4 config.h.in \ - gtk-doc.make fastbuild-*.qcow2 _kola_temp/ $(am__append_71) + gtk-doc.make fastbuild-*.qcow2 _kola_temp/ $(am__append_72) OT_INTERNAL_GIO_UNIX_CFLAGS = $(OT_DEP_GIO_UNIX_CFLAGS) OT_INTERNAL_GIO_UNIX_LIBS = $(OT_DEP_GIO_UNIX_LIBS) OT_INTERNAL_SOUP_CFLAGS = $(OT_DEP_SOUP_CFLAGS) @@ -2718,8 +2721,8 @@ libostree_1_la_SOURCES = src/libostree/ostree-async-progress.c \ src/libostree/ostree-kernel-args.c $(NULL) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_23) $(am__append_24) $(am__append_25) \ - $(am__append_33) $(am__append_34) $(am__append_37) \ - $(am__append_40) src/libostree/ostree-sign.c \ + $(am__append_34) $(am__append_35) $(am__append_38) \ + $(am__append_41) src/libostree/ostree-sign.c \ src/libostree/ostree-sign.h src/libostree/ostree-sign-dummy.c \ src/libostree/ostree-sign-dummy.h \ src/libostree/ostree-sign-ed25519.c \ @@ -2727,10 +2730,8 @@ libostree_1_la_SOURCES = src/libostree/ostree-async-progress.c \ libostree_experimental_headers = \ $(NULL) -symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym -#if BUILDOPT_IS_DEVEL_BUILD -#symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym -#endif +symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym \ + $(am__append_26) # http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html wl_versionscript_arg = -Wl,--version-script= libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff \ @@ -2740,17 +2741,17 @@ libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff \ $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) \ $(OT_DEP_CRYPTO_CFLAGS) -fvisibility=hidden \ '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) \ - extern' $(am__append_27) $(am__append_29) $(am__append_31) \ - $(am__append_35) $(am__append_38) $(am__append_41) \ - $(am__append_43) $(am__append_45) + extern' $(am__append_28) $(am__append_30) $(am__append_32) \ + $(am__append_36) $(am__append_39) $(am__append_42) \ + $(am__append_44) $(am__append_46) libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la \ $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) \ - $(am__append_26) $(bupsplitpath) $(am__append_28) \ - $(am__append_30) $(am__append_32) $(am__append_36) \ - $(am__append_39) $(am__append_42) $(am__append_44) \ - $(am__append_46) + $(am__append_27) $(bupsplitpath) $(am__append_29) \ + $(am__append_31) $(am__append_33) $(am__append_37) \ + $(am__append_40) $(am__append_43) $(am__append_45) \ + $(am__append_47) EXTRA_libostree_1_la_DEPENDENCIES = $(symbol_files) # XXX: work around clang being passed -fstack-clash-protection which it doesn't understand @@ -2760,7 +2761,7 @@ INTROSPECTION_SCANNER_ENV = CC=gcc @BUILDOPT_INTROSPECTION_TRUE@OSTree_1_0_gir_INCLUDES = Gio-2.0 @BUILDOPT_INTROSPECTION_TRUE@OSTree_1_0_gir_CFLAGS = \ @BUILDOPT_INTROSPECTION_TRUE@ $(libostree_1_la_CFLAGS) \ -@BUILDOPT_INTROSPECTION_TRUE@ $(am__append_47) +@BUILDOPT_INTROSPECTION_TRUE@ $(am__append_48) @BUILDOPT_INTROSPECTION_TRUE@OSTree_1_0_gir_LIBS = libostree-1.la @BUILDOPT_INTROSPECTION_TRUE@OSTree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=Ostree --symbol-prefix=ostree $(GI_SCANNERFLAGS) @BUILDOPT_INTROSPECTION_TRUE@OSTree_1_0_gir_FILES = $(libostreeinclude_HEADERS) $(filter-out %-private.h %/ostree-soup-uri.h $(libostree_experimental_headers),$(libostree_1_la_SOURCES)) @@ -2789,8 +2790,8 @@ ostree_SOURCES = src/ostree/main.c src/ostree/ot-builtin-admin.c \ src/ostree/ot-builtin-static-delta.c src/ostree/ot-main.h \ src/ostree/ot-main.c src/ostree/ot-dump.h src/ostree/ot-dump.c \ src/ostree/ot-editor.c src/ostree/ot-editor.h \ - src/ostree/parse-datetime.h $(NULL) $(am__append_52) \ - $(am__append_53) src/ostree/ot-admin-builtin-init-fs.c \ + src/ostree/parse-datetime.h $(NULL) $(am__append_53) \ + $(am__append_54) src/ostree/ot-admin-builtin-init-fs.c \ src/ostree/ot-admin-builtin-diff.c \ src/ostree/ot-admin-builtin-deploy.c \ src/ostree/ot-admin-builtin-finalize-staged.c \ @@ -2818,7 +2819,7 @@ ostree_SOURCES = src/ostree/main.c src/ostree/ot-builtin-admin.c \ src/ostree/ot-remote-builtin-show-url.c \ src/ostree/ot-remote-builtin-refs.c \ src/ostree/ot-remote-builtin-summary.c $(NULL) \ - $(am__append_54) $(am__append_55) $(am__append_56) + $(am__append_55) $(am__append_56) $(am__append_57) nodist_ostree_SOURCES = \ src/ostree/parse-datetime.c \ $(NULL) @@ -2830,11 +2831,11 @@ ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/sr ostree_bin_shared_ldadd = $(AM_LDFLAGS) libglnx.la libotutil.la libostree-1.la \ $(OT_INTERNAL_GIO_UNIX_LIBS) -ostree_CFLAGS = $(ostree_bin_shared_cflags) $(am__append_58) \ - $(am__append_60) $(am__append_62) +ostree_CFLAGS = $(ostree_bin_shared_cflags) $(am__append_59) \ + $(am__append_61) $(am__append_63) ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la \ - $(LIBSYSTEMD_LIBS) $(am__append_59) $(am__append_61) \ - $(am__append_63) + $(LIBSYSTEMD_LIBS) $(am__append_60) $(am__append_62) \ + $(am__append_64) @USE_LIBSOUP_TRUE@ostree_trivial_httpd_SOURCES = src/ostree/ostree-trivial-httpd.c @USE_LIBSOUP_TRUE@ostree_trivial_httpd_CFLAGS = $(ostree_bin_shared_cflags) $(OT_INTERNAL_SOUP_CFLAGS) @USE_LIBSOUP_TRUE@ostree_trivial_httpd_LDADD = $(ostree_bin_shared_ldadd) $(OT_INTERNAL_SOUP_LIBS) @@ -2843,8 +2844,8 @@ ostree_prepare_root_SOURCES = \ src/switchroot/ostree-prepare-root.c \ $(NULL) -ostree_prepare_root_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_68) \ - $(am__append_69) +ostree_prepare_root_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_69) \ + $(am__append_70) @BUILDOPT_USE_STATIC_COMPILER_FALSE@ostree_prepare_root_CFLAGS = $(AM_CFLAGS) -Isrc/switchroot ostree_remount_SOURCES = \ src/switchroot/ostree-mount-util.h \ @@ -2853,7 +2854,7 @@ ostree_remount_SOURCES = \ ostree_remount_CPPFLAGS = $(AM_CPPFLAGS) \ $(OT_INTERNAL_GIO_UNIX_CFLAGS) -Isrc/switchroot \ - -I$(srcdir)/libglnx $(am__append_70) + -I$(srcdir)/libglnx $(am__append_71) ostree_remount_LDADD = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) libglnx.la @BUILDOPT_SYSTEMD_TRUE@ostree_prepare_root_LDADD = $(AM_LDFLAGS) $(LIBSYSTEMD_LIBS) @BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@ostree_system_generator_SOURCES = src/switchroot/ostree-mount-util.h \ @@ -2870,7 +2871,7 @@ ostree_remount_LDADD = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) libglnx.la @BUILDOPT_FUSE_TRUE@rofiles_fuse_LDADD = libglnx.la $(BUILDOPT_FUSE_LIBS) $(OT_INTERNAL_GIO_UNIX_LIBS) libostree-1.la uninstalled_test_data = tests/ostree-symlink-stamp \ tests/ostree-prepare-root-symlink-stamp \ - tests/ostree-remount-symlink-stamp $(am__append_79) + tests/ostree-remount-symlink-stamp $(am__append_80) dist_uninstalled_test_scripts = tests/test-symbols.sh tests/coccinelle.sh # This logic implements ENABLE_INSTALLED_TESTS_EXCLUSIVE; see below. @@ -2878,10 +2879,10 @@ dist_uninstalled_test_scripts = tests/test-symbols.sh tests/coccinelle.sh # tests *only* run installed, to avoid having to run them twice in CI. # This overrides the glib-tap.mk emphasis on doing both, if we'd # used e.g. `dist_test_scripts`. -dist_test_scripts = $(NULL) $(am__append_90) +dist_test_scripts = $(NULL) $(am__append_91) test_programs = tests/test-bloom tests/test-repo-finder-config \ - tests/test-repo-finder-mount $(NULL) $(am__append_87) \ - $(am__append_91) + tests/test-repo-finder-mount $(NULL) $(am__append_88) \ + $(am__append_92) _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-basic-user.sh tests/test-basic-user-only.sh \ tests/test-basic-root.sh tests/test-pull-subpath.sh \ @@ -2912,13 +2913,15 @@ _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-admin-deploy-nomerge.sh \ tests/test-admin-deploy-none.sh \ tests/test-admin-deploy-bootid-gc.sh \ + tests/test-osupdate-dtb.sh \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ tests/test-admin-pull-deploy-commit.sh \ tests/test-admin-pull-deploy-split.sh \ tests/test-admin-locking.sh tests/test-admin-deploy-clean.sh \ tests/test-reset-nonlinear.sh tests/test-oldstyle-partial.sh \ - tests/test-delta.sh tests/test-xattrs.sh \ + tests/test-delta.sh tests/test-delta-sign.sh \ + tests/test-delta-ed25519.sh tests/test-xattrs.sh \ tests/test-auto-summary.sh tests/test-prune.sh \ tests/test-concurrency.py tests/test-refs.sh \ tests/test-demo-buildsystem.sh tests/test-switchroot.sh \ @@ -2934,9 +2937,9 @@ _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-pull-collections.sh tests/test-config.sh \ tests/test-signed-commit.sh tests/test-signed-pull.sh \ tests/test-pre-signed-pull.sh \ - tests/test-signed-pull-summary.sh $(NULL) $(am__append_75) \ - $(am__append_76) $(am__append_78) $(am__append_81) \ - $(am__append_82) + tests/test-signed-pull-summary.sh $(NULL) $(am__append_76) \ + $(am__append_77) $(am__append_79) $(am__append_82) \ + $(am__append_83) experimental_test_scripts = \ $(NULL) @@ -3015,7 +3018,7 @@ libreaddir_rand_la_LIBADD = \ $(NULL) libreaddir_rand_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version \ - $(am__append_85) + $(am__append_86) _installed_or_uninstalled_test_programs = tests/test-varint \ tests/test-ot-unix-utils tests/test-bsdiff \ tests/test-mutable-tree tests/test-keyfile-utils \ @@ -3023,7 +3026,7 @@ _installed_or_uninstalled_test_programs = tests/test-varint \ tests/test-checksum tests/test-lzma tests/test-rollsum \ tests/test-basic-c tests/test-sysroot-c tests/test-pull-c \ tests/test-repo tests/test-include-ostree-h tests/test-kargs \ - $(am__append_86) $(am__append_88) + $(am__append_87) $(am__append_89) common_tests_cflags = $(ostree_bin_shared_cflags) $(OT_INTERNAL_GIO_UNIX_CFLAGS) -I$(srcdir)/libglnx common_tests_ldadd = $(ostree_bin_shared_ldadd) $(OT_INTERNAL_GIO_UNIX_LIBS) libostreetest_la_SOURCES = tests/libostreetest.c tests/test-mock-gio.c tests/test-mock-gio.h @@ -3144,8 +3147,8 @@ tests_test_lzma_LDADD = $(TESTS_LDADD) $(OT_DEP_LZMA_LIBS) @ENABLE_MAN_TRUE@ ostree-pull.1 ostree-refs.1 ostree-remote.1 \ @ENABLE_MAN_TRUE@ ostree-reset.1 ostree-rev-parse.1 \ @ENABLE_MAN_TRUE@ ostree-show.1 ostree-sign.1 ostree-summary.1 \ -@ENABLE_MAN_TRUE@ ostree-static-delta.1 $(am__append_97) \ -@ENABLE_MAN_TRUE@ $(am__append_99) $(am__append_100) +@ENABLE_MAN_TRUE@ ostree-static-delta.1 $(am__append_98) \ +@ENABLE_MAN_TRUE@ $(am__append_100) $(am__append_101) @ENABLE_MAN_TRUE@man5_files = ostree.repo.5 ostree.repo-config.5 @ENABLE_MAN_TRUE@man1_MANS = $(addprefix man/,$(man1_files)) @ENABLE_MAN_TRUE@man5_MANS = $(addprefix man/,$(man5_files)) @@ -8360,6 +8363,13 @@ tests/test-admin-deploy-bootid-gc.sh.log: tests/test-admin-deploy-bootid-gc.sh --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-osupdate-dtb.sh.log: tests/test-osupdate-dtb.sh + @p='tests/test-osupdate-dtb.sh'; \ + b='tests/test-osupdate-dtb.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/test-admin-instutil-set-kargs.sh.log: tests/test-admin-instutil-set-kargs.sh @p='tests/test-admin-instutil-set-kargs.sh'; \ b='tests/test-admin-instutil-set-kargs.sh'; \ @@ -8423,6 +8433,20 @@ tests/test-delta.sh.log: tests/test-delta.sh --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-delta-sign.sh.log: tests/test-delta-sign.sh + @p='tests/test-delta-sign.sh'; \ + b='tests/test-delta-sign.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-delta-ed25519.sh.log: tests/test-delta-ed25519.sh + @p='tests/test-delta-ed25519.sh'; \ + b='tests/test-delta-ed25519.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/test-xattrs.sh.log: tests/test-xattrs.sh @p='tests/test-xattrs.sh'; \ b='tests/test-xattrs.sh'; \ diff --git a/README.md b/README.md index 1ef8e302..be6f6453 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,4 @@ -libostree ---------- - -New! See the docs online at [Read The Docs (OSTree)](https://ostree.readthedocs.org/en/latest/ ) - ------ +# libostree This project is now known as "libostree", though it is still appropriate to use the previous name: "OSTree" (or "ostree"). The focus is on projects which use @@ -36,8 +31,12 @@ version of projects like [flatpak](https://github.com/flatpak/flatpak) which use libostree for applications, rather than hosts. -Operating systems and distributions using OSTree ---------------------- +## Documentation + +For more information, see the [project documentation](docs/index.md) or the +[project documentation website](https://ostreedev.github.io/ostree). + +## Operating systems and distributions using OSTree [Endless OS](https://endlessos.com/) uses libostree for their host system as well as flatpak. See @@ -63,8 +62,7 @@ system for GNOME. [Liri OS](https://liri.io/download/silverblue/) has the option to install their distribution using ostree. -Distribution build tools ------------------------- +## Distribution build tools [meta-updater](https://github.com/advancedtelematic/meta-updater) is a layer available for [OpenEmbedded](http://www.openembedded.org/wiki/Main_Page) @@ -79,8 +77,7 @@ integration tool supports importing and exporting from libostree repos. Fedora [coreos-assembler](https://github.com/coreos/coreos-assembler) is the build tool used to generate Fedora CoreOS derivatives. -Projects linking to libostree ------------------------------ +## Projects linking to libostree [rpm-ostree](https://github.com/projectatomic/rpm-ostree) is used by the Fedora-derived operating systems listed above. It is a full hybrid @@ -98,8 +95,7 @@ use the "libostree host system" aspects (e.g. bootloader management), just the "git-like hardlink dedup". For example, flatpak supports a per-user OSTree repository. -Language bindings ----- +## Language bindings libostree is accessible via [GObject Introspection](https://gi.readthedocs.io/en/latest/); any language which has implemented the GI binding model should work. @@ -114,8 +110,7 @@ for statically compiled languages. Here's a list of such bindings: - [ostree-go](https://github.com/ostreedev/ostree-go/) - [ostree-rs](https://gitlab.com/fkrull/ostree-rs/) -Building --------- +## Building Releases are available as GPG signed git tags, and most recent versions support extended validation using @@ -139,19 +134,11 @@ make make install DESTDIR=/path/to/dest ``` -More documentation ------------------- - -New! See the docs online at [Read The Docs (OSTree)](https://ostree.readthedocs.org/en/latest/ ) - -Contributing ------------- +## Contributing See [Contributing](docs/CONTRIBUTING.md). - -Licensing -------- +## Licensing The licensing for the *code* of libostree can be canonically found in the individual files; and the overall status in the [COPYING](https://github.com/ostreedev/ostree/blob/master/COPYING) diff --git a/apidoc/html/ostree-OstreeRepo.html b/apidoc/html/ostree-OstreeRepo.html index c59f6826..efccacd3 100644 --- a/apidoc/html/ostree-OstreeRepo.html +++ b/apidoc/html/ostree-OstreeRepo.html @@ -914,11 +914,27 @@ gboolean +ostree_repo_static_delta_execute_offline_with_signature () + + + + +gboolean + + ostree_repo_static_delta_execute_offline () +gboolean + + +ostree_repo_static_delta_verify_signature () + + + + GHashTable * @@ -6472,6 +6488,8 @@ for input files

  • verbose: b: Print diagnostic messages. Default FALSE.

  • endianness: b: Deltas use host byte order by default; this option allows choosing (G_BIG_ENDIAN or G_LITTLE_ENDIAN)

  • filename: ay: Save delta superblock to this filename, and parts in the same directory. Default saves to repository.

  • +
  • sign-name: ay: Signature type to use.

  • +
  • sign-key-ids: as: Array of keys used to sign delta superblock.

  • Parameters

    @@ -6528,6 +6546,69 @@ for input files


    +

    ostree_repo_static_delta_execute_offline_with_signature ()

    +
    gboolean
    +ostree_repo_static_delta_execute_offline_with_signature
    +                               (OstreeRepo *self,
    +                                GFile *dir_or_file,
    +                                OstreeSign *sign,
    +                                gboolean skip_validation,
    +                                GCancellable *cancellable,
    +                                GError **error);
    +

    Given a directory representing an already-downloaded static delta +on disk, apply it, generating a new commit. +If sign is passed, the static delta signature is verified. +If sign-verify-deltas configuration option is set and static delta is signed, +signature verification will be mandatory before apply the static delta. +The directory must be named with the form "FROM-TO", where both are +checksums, and it must contain a file named "superblock", along with at least +one part.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    self

    Repo

     

    dir_or_file

    Path to a directory containing static delta data, or directly to the superblock

     

    sign

    Signature engine used to check superblock

     

    skip_validation

    If TRUE, assume data integrity

     

    cancellable

    Cancellable

     

    error

    Error

     
    +
    +

    Since: 2020.7

    +
    +
    +

    ostree_repo_static_delta_execute_offline ()

    gboolean
     ostree_repo_static_delta_execute_offline
    @@ -6580,6 +6661,61 @@ must contain a file named "superblock", along with at least one part.


    +

    ostree_repo_static_delta_verify_signature ()

    +
    gboolean
    +ostree_repo_static_delta_verify_signature
    +                               (OstreeRepo *self,
    +                                const char *delta_id,
    +                                OstreeSign *sign,
    +                                char **out_success_message,
    +                                GError **error);
    +

    Verify static delta file signature.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    self

    Repo

     

    delta_id

    delta path

     

    sign

    Signature engine used to check superblock

     

    out_success_message

    success message

     

    error

    Error

     
    +
    +
    +

    Returns

    +

    TRUE if the signature of static delta file is valid using the +signature engine provided, FALSE otherwise.

    +
    +

    Since: 2020.7

    +
    +
    +

    ostree_repo_traverse_new_reachable ()

    GHashTable *
     ostree_repo_traverse_new_reachable (void);
    diff --git a/apidoc/html/ostree-Root-partition-mount-point.html b/apidoc/html/ostree-Root-partition-mount-point.html index 42e09abe..91c0d6ba 100644 --- a/apidoc/html/ostree-Root-partition-mount-point.html +++ b/apidoc/html/ostree-Root-partition-mount-point.html @@ -348,11 +348,35 @@ gboolean +ostree_sysroot_stage_tree_with_options () + + + + +gboolean + + +ostree_sysroot_stage_overlay_initrd () + + + + +gboolean + + ostree_sysroot_deploy_tree () +gboolean + + +ostree_sysroot_deploy_tree_with_options () + + + + OstreeDeployment * @@ -1728,8 +1752,7 @@ ostree_sysroot_stage_tree (OstreeDeployment **out_new_deployment, GCancellable *cancellable, GError **error); -

    Like ostree_sysroot_deploy_tree(), but "finalization" only occurs at OS -shutdown time.

    +

    Older version of ostree_sysroot_stage_tree_with_options().

    Parameters

    @@ -1791,6 +1814,132 @@ shutdown time.


    +

    ostree_sysroot_stage_tree_with_options ()

    +
    gboolean
    +ostree_sysroot_stage_tree_with_options
    +                               (OstreeSysroot *self,
    +                                const char *osname,
    +                                const char *revision,
    +                                GKeyFile *origin,
    +                                OstreeDeployment *merge_deployment,
    +                                OstreeSysrootDeployTreeOpts *opts,
    +                                OstreeDeployment **out_new_deployment,
    +                                GCancellable *cancellable,
    +                                GError **error);
    +

    Like ostree_sysroot_deploy_tree(), but "finalization" only occurs at OS +shutdown time.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    self

    Sysroot

     

    osname

    osname to use for merge deployment.

    [allow-none]

    revision

    Checksum to add

     

    origin

    Origin to use for upgrades.

    [allow-none]

    merge_deployment

    Use this deployment for merge path.

    [allow-none]

    opts

    Options

     

    out_new_deployment

    The new deployment path.

    [out]

    cancellable

    Cancellable

     

    error

    Error

     
    +
    +

    Since: 2020.7

    +
    +
    +
    +

    ostree_sysroot_stage_overlay_initrd ()

    +
    gboolean
    +ostree_sysroot_stage_overlay_initrd (OstreeSysroot *self,
    +                                     int fd,
    +                                     char **out_checksum,
    +                                     GCancellable *cancellable,
    +                                     GError **error);
    +

    Stage an overlay initrd to be used in an upcoming deployment. Returns a checksum which +can be passed to ostree_sysroot_deploy_tree_with_options() or +ostree_sysroot_stage_tree_with_options() via the overlay_initrds array option.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    self

    Sysroot

     

    fd

    File descriptor to overlay initrd.

    [transfer none]

    out_checksum

    Overlay initrd checksum.

    [out][transfer full]

    cancellable

    Cancellable

     

    error

    Error

     
    +
    +

    Since: 2020.7

    +
    +
    +

    ostree_sysroot_deploy_tree ()

    gboolean
     ostree_sysroot_deploy_tree (OstreeSysroot *self,
    @@ -1802,12 +1951,7 @@ ostree_sysroot_deploy_tree (OstreeDeployment **out_new_deployment,
                                 GCancellable *cancellable,
                                 GError **error);
    -

    Check out deployment tree with revision revision -, performing a 3 -way merge with provided_merge_deployment - for configuration.

    -

    When booted into the sysroot, you should use the -ostree_sysroot_stage_tree() API instead.

    +

    Older version of ostree_sysroot_stage_tree_with_options().

    Parameters

    @@ -1865,6 +2009,86 @@ way merge with provided_merge_deployment
    +

    Since: 2018.5

    +
    +
    +
    +

    ostree_sysroot_deploy_tree_with_options ()

    +
    gboolean
    +ostree_sysroot_deploy_tree_with_options
    +                               (OstreeSysroot *self,
    +                                const char *osname,
    +                                const char *revision,
    +                                GKeyFile *origin,
    +                                OstreeDeployment *provided_merge_deployment,
    +                                OstreeSysrootDeployTreeOpts *opts,
    +                                OstreeDeployment **out_new_deployment,
    +                                GCancellable *cancellable,
    +                                GError **error);
    +

    Check out deployment tree with revision revision +, performing a 3 +way merge with provided_merge_deployment + for configuration.

    +

    When booted into the sysroot, you should use the +ostree_sysroot_stage_tree() API instead.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    self

    Sysroot

     

    osname

    osname to use for merge deployment.

    [allow-none]

    revision

    Checksum to add

     

    origin

    Origin to use for upgrades.

    [allow-none]

    provided_merge_deployment

    Use this deployment for merge path.

    [allow-none]

    opts

    Options.

    [allow-none]

    out_new_deployment

    The new deployment path.

    [out]

    cancellable

    Cancellable

     

    error

    Error

     
    +
    +

    Since: 2020.7


    diff --git a/apidoc/html/ostree-ostree-bootconfig-parser.html b/apidoc/html/ostree-ostree-bootconfig-parser.html index c9fdc372..b5b6a770 100644 --- a/apidoc/html/ostree-ostree-bootconfig-parser.html +++ b/apidoc/html/ostree-ostree-bootconfig-parser.html @@ -102,6 +102,22 @@ ostree_bootconfig_parser_get () + + +void + + +ostree_bootconfig_parser_set_overlay_initrds () + + + + +char ** + + +ostree_bootconfig_parser_get_overlay_initrds () + +
    @@ -246,6 +262,69 @@ ostree_bootconfig_parser_set (OstreeBootconfigParser *self, const char *key); +
    +
    +

    ostree_bootconfig_parser_set_overlay_initrds ()

    +
    void
    +ostree_bootconfig_parser_set_overlay_initrds
    +                               (OstreeBootconfigParser *self,
    +                                char **initrds);
    +

    These are rendered as additional initrd keys in the final bootloader configs. The +base initrd is part of the primary keys.

    +
    +

    Parameters

    +
    +++++ + + + + + + + + + + + + +

    self

    Parser

     

    initrds

    Array of overlay +initrds or NULL to unset.

    [array zero-terminated=1][transfer none][allow-none]
    +
    +

    Since: 2020.7

    +
    +
    +
    +

    ostree_bootconfig_parser_get_overlay_initrds ()

    +
    char **
    +ostree_bootconfig_parser_get_overlay_initrds
    +                               (OstreeBootconfigParser *self);
    +
    +

    Parameters

    +
    +++++ + + + + + +

    self

    Parser

     
    +
    +
    +

    Returns

    +

    Array of initrds or NULL +if none are set.

    +

    [array zero-terminated=1][transfer none][nullable]

    +
    +

    Since: 2020.7

    +

    Types and Values

    diff --git a/apidoc/html/ostree-ostree-deployment.html b/apidoc/html/ostree-ostree-deployment.html index bcac84d9..a206f46a 100644 --- a/apidoc/html/ostree-ostree-deployment.html +++ b/apidoc/html/ostree-ostree-deployment.html @@ -574,6 +574,8 @@ ostree_deployment_unlocked_state_to_string GKeyFile *origin; OstreeDeploymentUnlockedState unlocked; gboolean staged; + char **overlay_initrds; + char *overlay_initrds_id; } OstreeDeployment;
    @@ -635,6 +637,16 @@ ostree_deployment_unlocked_state_to_string

    TRUE iff this deployment is staged

      + +

    char **overlay_initrds;

    +

    Checksums of staged additional initrds for this deployment

    +  + + +

    char *overlay_initrds_id;

    +

    Unique ID generated from initrd checksums; used to compare deployments

    +  +
    diff --git a/apidoc/html/ostree.devhelp2 b/apidoc/html/ostree.devhelp2 index a1f6dc54..89cd25b0 100644 --- a/apidoc/html/ostree.devhelp2 +++ b/apidoc/html/ostree.devhelp2 @@ -199,7 +199,9 @@ + + @@ -305,7 +307,10 @@ - + + + + @@ -388,6 +393,8 @@ + + @@ -559,5 +566,7 @@ + + diff --git a/apidoc/html/reference.html b/apidoc/html/reference.html index 272075de..0bf7c27f 100644 --- a/apidoc/html/reference.html +++ b/apidoc/html/reference.html @@ -148,6 +148,10 @@
    +ostree_bootconfig_parser_get_overlay_initrds, function in ostree-bootconfig-parser +
    +
    +
    ostree_bootconfig_parser_new, function in ostree-bootconfig-parser
    @@ -164,6 +168,10 @@
    +ostree_bootconfig_parser_set_overlay_initrds, function in ostree-bootconfig-parser +
    +
    +
    ostree_bootconfig_parser_write, function in ostree-bootconfig-parser
    @@ -1462,10 +1470,18 @@ ostree_repo_set_collection_ref_immediate, function in ostree-misc-experimental
    +ostree_repo_static_delta_execute_offline_with_signature, function in OstreeRepo +
    +
    +
    ostree_repo_static_delta_generate, function in OstreeRepo
    +ostree_repo_static_delta_verify_signature, function in OstreeRepo +
    +
    +
    ostree_repo_transaction_set_collection_ref, function in ostree-misc-experimental
    @@ -1763,6 +1779,10 @@ ostree_repo_transaction_set_collection_ref, function in ostree-misc-experimental
    +ostree_sysroot_deploy_tree_with_options, function in Root partition mount point +
    +
    +
    ostree_sysroot_ensure_initialized, function in Root partition mount point
    @@ -1879,10 +1899,18 @@ ostree_repo_transaction_set_collection_ref, function in ostree-misc-experimental
    +ostree_sysroot_stage_overlay_initrd, function in Root partition mount point +
    +
    +
    ostree_sysroot_stage_tree, function in Root partition mount point
    +ostree_sysroot_stage_tree_with_options, function in Root partition mount point +
    +
    +
    ostree_sysroot_try_lock, function in Root partition mount point
    diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 979c8e93..c1d6b35e 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -37,6 +37,8 @@ ostree_bootconfig_parser_write ostree_bootconfig_parser_write_at ostree_bootconfig_parser_set ostree_bootconfig_parser_get +ostree_bootconfig_parser_set_overlay_initrds +ostree_bootconfig_parser_get_overlay_initrds OSTREE_BOOTCONFIG_PARSER OSTREE_IS_BOOTCONFIG_PARSER @@ -412,7 +414,9 @@ ostree_repo_list_commit_objects_starting_with ostree_repo_list_static_delta_names OstreeStaticDeltaGenerateOpt ostree_repo_static_delta_generate +ostree_repo_static_delta_execute_offline_with_signature ostree_repo_static_delta_execute_offline +ostree_repo_static_delta_verify_signature ostree_repo_traverse_new_reachable ostree_repo_traverse_new_parents ostree_repo_traverse_parents_get_commits @@ -543,7 +547,10 @@ ostree_sysroot_write_deployments ostree_sysroot_write_deployments_with_options ostree_sysroot_write_origin_file ostree_sysroot_stage_tree +ostree_sysroot_stage_tree_with_options +ostree_sysroot_stage_overlay_initrd ostree_sysroot_deploy_tree +ostree_sysroot_deploy_tree_with_options ostree_sysroot_get_merge_deployment ostree_sysroot_query_deployments_for ostree_sysroot_origin_new_from_refspec diff --git a/bash/ostree b/bash/ostree index 7256e40a..d00695ef 100644 --- a/bash/ostree +++ b/bash/ostree @@ -1532,6 +1532,9 @@ _ostree_static_delta_apply_offline() { " local options_with_args=" + --sign-type + --keys-file + --keys-dir --repo " @@ -1613,6 +1616,8 @@ _ostree_static_delta_generate() { --repo --set-endianness --to + --sign + --sign-type " local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" ) @@ -1630,6 +1635,9 @@ _ostree_static_delta_generate() { COMPREPLY=( $( compgen -W "l B" -- "$cur" ) ) return 0 ;; + $options_with_args_glob ) + return 0 + ;; esac case "$cur" in @@ -1704,6 +1712,40 @@ _ostree_static_delta_show() { return 0 } +_ostree_static_delta_verify() { + local boolean_options=" + $main_boolean_options + " + + local options_with_args=" + --sign-type + --keys-file + --keys-dir + --repo + " + + local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" ) + + case "$prev" in + --keys-file|--keys-dir|--repo) + __ostree_compreply_dirs_only + return 0 + ;; + $options_with_args_glob ) + return 0 + ;; + esac + + case "$cur" in + -*) + local all_options="$boolean_options $options_with_args" + __ostree_compreply_all_options + ;; + esac + + return 0 +} + _ostree_static_delta() { local subcommands=" apply-offline diff --git a/configure b/configure index d735da6c..6f5d091e 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libostree 2020.6. +# Generated by GNU Autoconf 2.69 for libostree 2020.7. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libostree' PACKAGE_TARNAME='libostree' -PACKAGE_VERSION='2020.6' -PACKAGE_STRING='libostree 2020.6' +PACKAGE_VERSION='2020.7' +PACKAGE_STRING='libostree 2020.7' PACKAGE_BUGREPORT='walters@verbum.org' PACKAGE_URL='' @@ -1561,7 +1561,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libostree 2020.6 to adapt to many kinds of systems. +\`configure' configures libostree 2020.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1631,7 +1631,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libostree 2020.6:";; + short | recursive ) echo "Configuration of libostree 2020.7:";; esac cat <<\_ACEOF @@ -1896,7 +1896,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libostree configure 2020.6 +libostree configure 2020.7 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2368,7 +2368,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libostree $as_me 2020.6, which was +It was created by libostree $as_me 2020.7, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3236,7 +3236,7 @@ fi # Define the identity of the package. PACKAGE='libostree' - VERSION='2020.6' + VERSION='2020.7' # Some tools Automake needs. @@ -5970,9 +5970,9 @@ test -n "$YACC" || YACC="yacc" YEAR_VERSION=2020 -RELEASE_VERSION=6 +RELEASE_VERSION=7 -PACKAGE_VERSION=2020.6 +PACKAGE_VERSION=2020.7 if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then : @@ -5983,6 +5983,7 @@ else for flag in \ -pipe \ -Wall \ + -Werror=shadow \ -Werror=empty-body \ -Werror=strict-prototypes \ -Werror=missing-prototypes \ @@ -19025,7 +19026,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libostree $as_me 2020.6, which was +This file was extended by libostree $as_me 2020.7, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19091,7 +19092,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libostree config.status 2020.6 +libostree config.status 2020.7 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 0c3c6fed..13f5bef8 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ dnl Seed the release notes with `git-shortlog-with-prs ..`. Th dnl `git-evtag` to create the tag and push it. Finally, create a GitHub release and attach dnl the tarball from `make dist`. m4_define([year_version], [2020]) -m4_define([release_version], [6]) +m4_define([release_version], [7]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) is_release_build=yes @@ -35,6 +35,7 @@ AS_IF([echo "$CFLAGS" | grep -q -E -e '-Werror($| )'], [], [ CC_CHECK_FLAGS_APPEND([WARN_CFLAGS], [CFLAGS], [\ -pipe \ -Wall \ + -Werror=shadow \ -Werror=empty-body \ -Werror=strict-prototypes \ -Werror=missing-prototypes \ diff --git a/libglnx/glnx-fdio.c b/libglnx/glnx-fdio.c index e537a9bc..422bc2dd 100644 --- a/libglnx/glnx-fdio.c +++ b/libglnx/glnx-fdio.c @@ -303,8 +303,8 @@ glnx_open_anonymous_tmpfile_full (int flags, } /* A variant of `glnx_open_tmpfile_linkable_at()` which doesn't support linking. - * Useful for true temporary storage. The fd will be allocated in /var/tmp to - * ensure maximum storage space. + * Useful for true temporary storage. The fd will be allocated in `$TMPDIR` if + * set or `/var/tmp` otherwise. * * If you need the file on a specific filesystem use glnx_open_anonymous_tmpfile_full() * which lets you pass a directory. @@ -314,7 +314,10 @@ glnx_open_anonymous_tmpfile (int flags, GLnxTmpfile *out_tmpf, GError **error) { - return glnx_open_anonymous_tmpfile_full (flags, "/var/tmp", out_tmpf, error); + return glnx_open_anonymous_tmpfile_full (flags, + getenv("TMPDIR") ?: "/var/tmp", + out_tmpf, + error); } /* Use this after calling glnx_open_tmpfile_linkable_at() to give diff --git a/libglnx/glnx-xattrs.c b/libglnx/glnx-xattrs.c index 79a14cd3..892d5343 100644 --- a/libglnx/glnx-xattrs.c +++ b/libglnx/glnx-xattrs.c @@ -283,7 +283,7 @@ set_all_xattrs_for_path (const char *path, const guint8* value_data = g_variant_get_fixed_array (value, &value_len, 1); if (lsetxattr (path, (char*)name, (char*)value_data, value_len, 0) < 0) - return glnx_throw_errno_prefix (error, "lsetxattr"); + return glnx_throw_errno_prefix (error, "lsetxattr(%s)", name); } return TRUE; @@ -351,7 +351,7 @@ glnx_fd_set_all_xattrs (int fd, const guint8* value_data = g_variant_get_fixed_array (value, &value_len, 1); if (TEMP_FAILURE_RETRY (fsetxattr (fd, (char*)name, (char*)value_data, value_len, 0)) < 0) - return glnx_throw_errno_prefix (error, "fsetxattr"); + return glnx_throw_errno_prefix (error, "Setting xattrs: fsetxattr(%s)", name); } return TRUE; @@ -378,11 +378,11 @@ glnx_lgetxattrat (int dfd, ssize_t bytes_read, real_size; if (TEMP_FAILURE_RETRY (bytes_read = lgetxattr (pathbuf, attribute, NULL, 0)) < 0) - return glnx_null_throw_errno_prefix (error, "lgetxattr"); + return glnx_null_throw_errno_prefix (error, "lgetxattr(%s)", attribute); g_autofree guint8 *buf = g_malloc (bytes_read); if (TEMP_FAILURE_RETRY (real_size = lgetxattr (pathbuf, attribute, buf, bytes_read)) < 0) - return glnx_null_throw_errno_prefix (error, "lgetxattr"); + return glnx_null_throw_errno_prefix (error, "lgetxattr(%s)", attribute); return g_bytes_new_take (g_steal_pointer (&buf), real_size); } @@ -403,11 +403,11 @@ glnx_fgetxattr_bytes (int fd, ssize_t bytes_read, real_size; if (TEMP_FAILURE_RETRY (bytes_read = fgetxattr (fd, attribute, NULL, 0)) < 0) - return glnx_null_throw_errno_prefix (error, "fgetxattr"); + return glnx_null_throw_errno_prefix (error, "fgetxattr(%s)", attribute); g_autofree guint8 *buf = g_malloc (bytes_read); if (TEMP_FAILURE_RETRY (real_size = fgetxattr (fd, attribute, buf, bytes_read)) < 0) - return glnx_null_throw_errno_prefix (error, "fgetxattr"); + return glnx_null_throw_errno_prefix (error, "fgetxattr(%s)", attribute); return g_bytes_new_take (g_steal_pointer (&buf), real_size); } @@ -437,7 +437,7 @@ glnx_lsetxattrat (int dfd, snprintf (pathbuf, sizeof (pathbuf), "/proc/self/fd/%d/%s", dfd, subpath); if (TEMP_FAILURE_RETRY (lsetxattr (subpath, attribute, value, len, flags)) < 0) - return glnx_throw_errno_prefix (error, "lsetxattr"); + return glnx_throw_errno_prefix (error, "lsetxattr(%s)", attribute); return TRUE; } diff --git a/man/ostree-checkout.xml b/man/ostree-checkout.xml index 3956e34f..dfa2ce16 100644 --- a/man/ostree-checkout.xml +++ b/man/ostree-checkout.xml @@ -163,7 +163,7 @@ Boston, MA 02111-1307, USA. - Do not hardlink zero-sized files. + This option does nothing; the functionality is now always on by default. diff --git a/man/ostree-static-delta.xml b/man/ostree-static-delta.xml index dfeef28b..440ada41 100644 --- a/man/ostree-static-delta.xml +++ b/man/ostree-static-delta.xml @@ -63,7 +63,10 @@ Boston, MA 02111-1307, USA. ostree static-delta generate --to=REV OPTIONS - ostree static-delta apply-offline PATH + ostree static-delta apply-offline OPTIONS PATH KEY-ID + + + ostree static-delta verify OPTIONS STATIC-DELTA KEY-ID @@ -113,6 +116,159 @@ Boston, MA 02111-1307, USA. + + =ENGINE + + + Use particular signature engine. Currently + available ed25519 and dummy + signature types. + + The default is ed25519. + + + + + ="KEY-ID" + + There KEY-ID is: + + + + + base64-encoded secret key for signing. + + + + + + + ASCII-string used as secret key. + + + + + + + + + + 'Apply-offline' Options + + + + + + + + + + + base64-encoded public key for verifying. + + + + + + + ASCII-string used as public key. + + + + + + + + =ENGINE + + + Use particular signature engine. Currently + available ed25519 and dummy + signature types. + + + + + + + Read key(s) from file filename. + + + + Valid for ed25519 signature type. + For ed25519 this file must contain base64-encoded + public key(s) per line for verifying. + + + + + + + Redefine the system path, where to search files and subdirectories with + well-known and revoked keys. + + + + + + + 'Verify' Options + + + + + + + + + + + base64-encoded public key for verifying. + + + + + + + ASCII-string used as public key. + + + + + + + + =ENGINE + + + Use particular signature engine. Currently + available ed25519 and dummy + signature types. + + The default is ed25519. + + + + + + + Read key(s) from file filename. + + + + Valid for ed25519 signature type. + For ed25519 this file must contain base64-encoded + public key(s) per line for verifying. + + + + + + + Redefine the system path, where to search files and subdirectories with + well-known and revoked keys. + + diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 21669c4a..2ed658c4 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -17,13 +17,6 @@ Boston, MA 02111-1307, USA. ***/ -LIBOSTREE_2020.5 { -global: - /* Add symbols here, and uncomment the bits in - * Makefile-libostree.am to enable this too. - */ -} LIBOSTREE_2020.4; - /* Stub section for the stable release *after* this development one; don't * edit this other than to update the year. This is just a copy/paste * source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 5c63f78f..c154d8c1 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -593,6 +593,9 @@ global: ostree_sysroot_set_mount_namespace_in_use; } LIBOSTREE_2019.6; +/* No new symbols in 2020.2 */ +/* No new symbols in 2020.3 */ + /* Add new symbols here. Release commits should copy this section into -released.sym. */ LIBOSTREE_2020.4 { global: @@ -615,7 +618,23 @@ global: ostree_sign_summary; } LIBOSTREE_2020.1; -/* No new symbols in 2020.2 */ +/* No new symbols in 2020.5 */ + +/* No new symbols in 2020.6 */ + +LIBOSTREE_2020.7 { +global: + /* Add symbols here, and uncomment the bits in + * Makefile-libostree.am to enable this too. + */ + ostree_repo_static_delta_execute_offline_with_signature; + ostree_repo_static_delta_verify_signature; + ostree_bootconfig_parser_get_overlay_initrds; + ostree_bootconfig_parser_set_overlay_initrds; + ostree_sysroot_deploy_tree_with_options; + ostree_sysroot_stage_tree_with_options; + ostree_sysroot_stage_overlay_initrd; +} LIBOSTREE_2020.4; /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. diff --git a/src/libostree/ostree-bootconfig-parser.c b/src/libostree/ostree-bootconfig-parser.c index 67f9fb58..a36a4118 100644 --- a/src/libostree/ostree-bootconfig-parser.c +++ b/src/libostree/ostree-bootconfig-parser.c @@ -30,6 +30,9 @@ struct _OstreeBootconfigParser const char *separators; GHashTable *options; + + /* Additional initrds; the primary initrd is in options. */ + char **overlay_initrds; }; typedef GObjectClass OstreeBootconfigParserClass; @@ -50,6 +53,8 @@ ostree_bootconfig_parser_clone (OstreeBootconfigParser *self) GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v) g_hash_table_replace (parser->options, g_strdup (k), g_strdup (v)); + parser->overlay_initrds = g_strdupv (self->overlay_initrds); + return parser; } @@ -76,6 +81,8 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self, if (!contents) return FALSE; + g_autoptr(GPtrArray) overlay_initrds = NULL; + g_auto(GStrv) lines = g_strsplit (contents, "\n", -1); for (char **iter = lines; *iter; iter++) { @@ -87,8 +94,19 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self, items = g_strsplit_set (line, self->separators, 2); if (g_strv_length (items) == 2 && items[0][0] != '\0') { - g_hash_table_insert (self->options, items[0], items[1]); - g_free (items); /* Transfer ownership */ + if (g_str_equal (items[0], "initrd") && + g_hash_table_contains (self->options, "initrd")) + { + if (!overlay_initrds) + overlay_initrds = g_ptr_array_new_with_free_func (g_free); + g_ptr_array_add (overlay_initrds, items[1]); + g_free (items[0]); + } + else + { + g_hash_table_insert (self->options, items[0], items[1]); + } + g_free (items); /* Free container; we stole the elements */ } else { @@ -97,6 +115,12 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self, } } + if (overlay_initrds) + { + g_ptr_array_add (overlay_initrds, NULL); + self->overlay_initrds = (char**)g_ptr_array_free (g_steal_pointer (&overlay_initrds), FALSE); + } + self->parsed = TRUE; return TRUE; @@ -127,6 +151,41 @@ ostree_bootconfig_parser_get (OstreeBootconfigParser *self, return g_hash_table_lookup (self->options, key); } +/** + * ostree_bootconfig_parser_set_overlay_initrds: + * @self: Parser + * @initrds: (array zero-terminated=1) (transfer none) (allow-none): Array of overlay + * initrds or %NULL to unset. + * + * These are rendered as additional `initrd` keys in the final bootloader configs. The + * base initrd is part of the primary keys. + * + * Since: 2020.7 + */ +void +ostree_bootconfig_parser_set_overlay_initrds (OstreeBootconfigParser *self, + char **initrds) +{ + g_assert (g_hash_table_contains (self->options, "initrd")); + g_strfreev (self->overlay_initrds); + self->overlay_initrds = g_strdupv (initrds); +} + +/** + * ostree_bootconfig_parser_get_overlay_initrds: + * @self: Parser + * + * Returns: (array zero-terminated=1) (transfer none) (nullable): Array of initrds or %NULL + * if none are set. + * + * Since: 2020.7 + */ +char** +ostree_bootconfig_parser_get_overlay_initrds (OstreeBootconfigParser *self) +{ + return self->overlay_initrds; +} + static void write_key (OstreeBootconfigParser *self, GString *buf, @@ -165,6 +224,15 @@ ostree_bootconfig_parser_write_at (OstreeBootconfigParser *self, } } + /* Write overlay initrds */ + if (self->overlay_initrds && (g_strv_length (self->overlay_initrds) > 0)) + { + /* we should've written the primary initrd already */ + g_assert (g_hash_table_contains (keys_written, "initrd")); + for (char **it = self->overlay_initrds; it && *it; it++) + write_key (self, buf, "initrd", *it); + } + /* Write unknown fields */ GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v) { @@ -197,6 +265,7 @@ ostree_bootconfig_parser_finalize (GObject *object) { OstreeBootconfigParser *self = OSTREE_BOOTCONFIG_PARSER (object); + g_strfreev (self->overlay_initrds); g_hash_table_unref (self->options); G_OBJECT_CLASS (ostree_bootconfig_parser_parent_class)->finalize (object); diff --git a/src/libostree/ostree-bootconfig-parser.h b/src/libostree/ostree-bootconfig-parser.h index aec07535..d03c931c 100644 --- a/src/libostree/ostree-bootconfig-parser.h +++ b/src/libostree/ostree-bootconfig-parser.h @@ -73,5 +73,11 @@ _OSTREE_PUBLIC const char *ostree_bootconfig_parser_get (OstreeBootconfigParser *self, const char *key); +_OSTREE_PUBLIC +void ostree_bootconfig_parser_set_overlay_initrds (OstreeBootconfigParser *self, + char **initrds); + +_OSTREE_PUBLIC +char** ostree_bootconfig_parser_get_overlay_initrds (OstreeBootconfigParser *self); G_END_DECLS diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 523f57c0..29528fa5 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -2675,7 +2675,7 @@ _ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata, _OSTREE_METADATA_GPGSIGS_NAME, g_variant_builder_end (signature_builder)); - return g_variant_dict_end (&metadata_dict); + return g_variant_ref_sink (g_variant_dict_end (&metadata_dict)); } #endif /* OSTREE_DISABLE_GPGME */ diff --git a/src/libostree/ostree-deployment-private.h b/src/libostree/ostree-deployment-private.h index ad77317d..b339ae26 100644 --- a/src/libostree/ostree-deployment-private.h +++ b/src/libostree/ostree-deployment-private.h @@ -37,6 +37,8 @@ G_BEGIN_DECLS * @origin: How to construct an upgraded version of this tree * @unlocked: The unlocked state * @staged: TRUE iff this deployment is staged + * @overlay_initrds: Checksums of staged additional initrds for this deployment + * @overlay_initrds_id: Unique ID generated from initrd checksums; used to compare deployments */ struct _OstreeDeployment { @@ -52,8 +54,15 @@ struct _OstreeDeployment GKeyFile *origin; OstreeDeploymentUnlockedState unlocked; gboolean staged; + char **overlay_initrds; + char *overlay_initrds_id; }; void _ostree_deployment_set_bootcsum (OstreeDeployment *self, const char *bootcsum); +void _ostree_deployment_set_overlay_initrds (OstreeDeployment *self, + char **overlay_initrds); + +char** _ostree_deployment_get_overlay_initrds (OstreeDeployment *self); + G_END_DECLS diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 70e1bc49..182bceea 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -158,6 +158,34 @@ _ostree_deployment_set_bootcsum (OstreeDeployment *self, self->bootcsum = g_strdup (bootcsum); } +void +_ostree_deployment_set_overlay_initrds (OstreeDeployment *self, + char **overlay_initrds) +{ + g_clear_pointer (&self->overlay_initrds, g_strfreev); + g_clear_pointer (&self->overlay_initrds_id, g_free); + + if (!overlay_initrds || g_strv_length (overlay_initrds) == 0) + return; + + /* Generate a unique ID representing this combination of overlay initrds. This is so that + * ostree_sysroot_write_deployments_with_options() can easily compare initrds when + * comparing deployments for whether a bootswap is necessary. We could be fancier here but + * meh... this works. */ + g_autoptr(GString) id = g_string_new (NULL); + for (char **it = overlay_initrds; it && *it; it++) + g_string_append (id, *it); + + self->overlay_initrds = g_strdupv (overlay_initrds); + self->overlay_initrds_id = g_string_free (g_steal_pointer (&id), FALSE); +} + +char** +_ostree_deployment_get_overlay_initrds (OstreeDeployment *self) +{ + return self->overlay_initrds; +} + /** * ostree_deployment_clone: * @self: Deployment @@ -175,6 +203,8 @@ ostree_deployment_clone (OstreeDeployment *self) new_bootconfig = ostree_bootconfig_parser_clone (self->bootconfig); ostree_deployment_set_bootconfig (ret, new_bootconfig); + _ostree_deployment_set_overlay_initrds (ret, self->overlay_initrds); + if (self->origin) { g_autoptr(GKeyFile) new_origin = NULL; @@ -238,6 +268,8 @@ ostree_deployment_finalize (GObject *object) g_free (self->bootcsum); g_clear_object (&self->bootconfig); g_clear_pointer (&self->origin, g_key_file_unref); + g_strfreev (self->overlay_initrds); + g_free (self->overlay_initrds_id); G_OBJECT_CLASS (ostree_deployment_parent_class)->finalize (object); } diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index fdf8a2ef..0ce3ff00 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -341,14 +341,14 @@ check_multi_info (OstreeFetcher *fetcher) if (req->idx + 1 == req->mirrorlist->len) { - g_autofree char *msg = g_strdup_printf ("Server returned HTTP %lu", response); + g_autofree char *response_msg = g_strdup_printf ("Server returned HTTP %lu", response); g_task_return_new_error (task, G_IO_ERROR, giocode, - "%s", msg); + "%s", response_msg); if (req->fetcher->remote_name && !((req->flags & OSTREE_FETCHER_REQUEST_OPTIONAL_CONTENT) > 0 && giocode == G_IO_ERROR_NOT_FOUND)) _ostree_fetcher_journal_failure (req->fetcher->remote_name, - eff_url, msg); + eff_url, response_msg); } else diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index dc36370f..00c6a773 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -613,9 +613,12 @@ checkout_one_file_at (OstreeRepo *repo, } const gboolean is_symlink = (g_file_info_get_file_type (source_info) == G_FILE_TYPE_SYMBOLIC_LINK); + const guint32 source_mode = g_file_info_get_attribute_uint32 (source_info, "unix::mode"); + const gboolean is_unreadable = (!is_symlink && (source_mode & S_IRUSR) == 0); const gboolean is_whiteout = (!is_symlink && options->process_whiteouts && g_str_has_prefix (destination_name, WHITEOUT_PREFIX)); const gboolean is_reg_zerosized = (!is_symlink && g_file_info_get_size (source_info) == 0); + const gboolean override_user_unreadable = (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER && is_unreadable); /* First, see if it's a Docker whiteout, * https://github.com/docker/docker/blob/1a714e76a2cb9008cd19609059e9988ff1660b78/pkg/archive/whiteouts.go @@ -634,8 +637,12 @@ checkout_one_file_at (OstreeRepo *repo, need_copy = FALSE; } - else if (options->force_copy_zerosized && is_reg_zerosized) + else if (is_reg_zerosized || override_user_unreadable) { + /* In https://github.com/ostreedev/ostree/commit/673cacd633f9d6b653cdea530657d3e780a41bbd we + * made this an option, but in order to avoid hitting EMLINK, we now force copy zerosized + * files unconditionally. + */ need_copy = TRUE; } else if (!options->force_copy) @@ -735,7 +742,7 @@ checkout_one_file_at (OstreeRepo *repo, if (can_cache && !is_whiteout && !is_symlink - && !is_reg_zerosized + && !(is_reg_zerosized || override_user_unreadable) && need_copy && repo->mode == OSTREE_REPO_MODE_ARCHIVE && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER) @@ -799,12 +806,21 @@ checkout_one_file_at (OstreeRepo *repo, * succeeded at hardlinking above. */ if (options->no_copy_fallback) - g_assert (is_bare_user_symlink || is_reg_zerosized); + g_assert (is_bare_user_symlink || is_reg_zerosized || override_user_unreadable); if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs, cancellable, error)) return FALSE; - if (!create_file_copy_from_input_at (repo, options, state, checksum, source_info, xattrs, input, + GFileInfo *copy_source_info = source_info; + g_autoptr(GFileInfo) modified_info = NULL; + if (override_user_unreadable) + { + modified_info = g_file_info_dup (source_info); + g_file_info_set_attribute_uint32 (modified_info, "unix::mode", (source_mode | S_IRUSR)); + copy_source_info = modified_info; + } + + if (!create_file_copy_from_input_at (repo, options, state, checksum, copy_source_info, xattrs, input, destination_dfd, destination_name, cancellable, error)) return glnx_prefix_error (error, "Copy checkout of %s to %s", checksum, destination_name); diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 20340257..690075e1 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -3943,11 +3943,9 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(GFileInfo) child_info = NULL; g_autoptr(GFileInfo) modified_info = NULL; g_autoptr(GVariant) xattrs = NULL; g_autofree guchar *child_file_csum = NULL; - g_autofree char *tmp_checksum = NULL; g_autofree char *relpath = NULL; OstreeRepoCommitFilterResult filter_result; struct stat dir_stbuf; @@ -3955,19 +3953,19 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, if (!glnx_fstat (src_dfd_iter->fd, &dir_stbuf, error)) return FALSE; - child_info = _ostree_stbuf_to_gfileinfo (&dir_stbuf); - - if (modifier != NULL) - { - relpath = ptrarray_path_join (path); - - filter_result = _ostree_repo_commit_modifier_apply (self, modifier, relpath, child_info, &modified_info); - } - else - { - filter_result = OSTREE_REPO_COMMIT_FILTER_ALLOW; - modified_info = g_object_ref (child_info); - } + { + g_autoptr(GFileInfo) child_info = _ostree_stbuf_to_gfileinfo (&dir_stbuf); + if (modifier != NULL) + { + relpath = ptrarray_path_join (path); + filter_result = _ostree_repo_commit_modifier_apply (self, modifier, relpath, child_info, &modified_info); + } + else + { + filter_result = OSTREE_REPO_COMMIT_FILTER_ALLOW; + modified_info = g_object_ref (child_info); + } + } if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) { @@ -3979,8 +3977,7 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, cancellable, error)) return FALSE; - g_free (tmp_checksum); - tmp_checksum = ostree_checksum_from_bytes (child_file_csum); + g_autofree char *tmp_checksum = ostree_checksum_from_bytes (child_file_csum); ostree_mutable_tree_set_metadata_checksum (mtree, tmp_checksum); } diff --git a/src/libostree/ostree-repo-finder-avahi-parser.c b/src/libostree/ostree-repo-finder-avahi-parser.c index afc9790c..1cf4a11d 100644 --- a/src/libostree/ostree-repo-finder-avahi-parser.c +++ b/src/libostree/ostree-repo-finder-avahi-parser.c @@ -91,14 +91,14 @@ parse_txt_record (const guint8 *txt, /* TODO: Docs. Return value is only valid as long as @txt is. Reference: RFC 6763, §6. */ GHashTable * -_ostree_txt_records_parse (AvahiStringList *txt) +_ostree_txt_records_parse (AvahiStringList *txt_list) { AvahiStringList *l; g_autoptr(GHashTable) out = NULL; out = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_bytes_unref); - for (l = txt; l != NULL; l = avahi_string_list_get_next (l)) + for (l = txt_list; l != NULL; l = avahi_string_list_get_next (l)) { const guint8 *txt; gsize txt_len; diff --git a/src/libostree/ostree-repo-finder-mount.c b/src/libostree/ostree-repo-finder-mount.c index c259f3e6..5c8ab1f3 100644 --- a/src/libostree/ostree-repo-finder-mount.c +++ b/src/libostree/ostree-repo-finder-mount.c @@ -336,7 +336,6 @@ ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finde g_autoptr(GHashTable) repo_to_refs = NULL; /* (element-type UriAndKeyring GHashTable) */ GHashTable *supported_ref_to_checksum; /* (element-type OstreeCollectionRef utf8) */ GHashTableIter iter; - UriAndKeyring *repo; g_autoptr(GError) local_error = NULL; mount_name = g_mount_get_name (mount); @@ -525,6 +524,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS /* Aggregate the results. */ g_hash_table_iter_init (&iter, repo_to_refs); + UriAndKeyring *repo; while (g_hash_table_iter_next (&iter, (gpointer *) &repo, (gpointer *) &supported_ref_to_checksum)) { g_autoptr(OstreeRemote) remote = NULL; diff --git a/src/libostree/ostree-repo-finder-override.c b/src/libostree/ostree-repo-finder-override.c index 32199546..d6fb5a9b 100644 --- a/src/libostree/ostree-repo-finder-override.c +++ b/src/libostree/ostree-repo-finder-override.c @@ -151,7 +151,6 @@ ostree_repo_finder_override_resolve_async (OstreeRepoFinder *fi GHashTable *supported_ref_to_checksum; /* (element-type OstreeCollectionRef utf8) */ GHashTableIter iter; const gchar *remote_uri; - OstreeRemote *remote; task = g_task_new (finder, cancellable, callback, user_data); g_task_set_source_tag (task, ostree_repo_finder_override_resolve_async); @@ -242,6 +241,7 @@ ostree_repo_finder_override_resolve_async (OstreeRepoFinder *fi /* Aggregate the results. */ g_hash_table_iter_init (&iter, repo_remote_to_refs); + OstreeRemote *remote; while (g_hash_table_iter_next (&iter, (gpointer *) &remote, (gpointer *) &supported_ref_to_checksum)) g_ptr_array_add (results, ostree_repo_finder_result_new (remote, finder, priority, supported_ref_to_checksum, NULL, 0)); diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index d55459f4..ef7252e8 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -1161,16 +1161,16 @@ write_directory_to_libarchive_recurse (OstreeRepo *self, { guint8 buf[8192]; g_autoptr(GInputStream) file_in = NULL; - g_autoptr(GFileInfo) file_info = NULL; + g_autoptr(GFileInfo) regular_file_info = NULL; const char *checksum; checksum = ostree_repo_file_get_checksum ((OstreeRepoFile*)path); - if (!ostree_repo_load_file (self, checksum, &file_in, &file_info, NULL, + if (!ostree_repo_load_file (self, checksum, &file_in, ®ular_file_info, NULL, cancellable, error)) goto out; - archive_entry_set_size (entry, g_file_info_get_size (file_info)); + archive_entry_set_size (entry, g_file_info_get_size (regular_file_info)); if (archive_write_header (a, entry) != ARCHIVE_OK) { diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 8c1f5071..a48feca4 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -55,6 +55,8 @@ G_BEGIN_DECLS #define OSTREE_SUMMARY_EXPIRES "ostree.summary.expires" #define OSTREE_SUMMARY_COLLECTION_ID "ostree.summary.collection-id" #define OSTREE_SUMMARY_COLLECTION_MAP "ostree.summary.collection-map" +#define OSTREE_SUMMARY_MODE "ostree.summary.mode" +#define OSTREE_SUMMARY_TOMBSTONE_COMMITS "ostree.summary.tombstone-commits" #define _OSTREE_PAYLOAD_LINK_PREFIX "../" #define _OSTREE_PAYLOAD_LINK_PREFIX_LEN (sizeof (_OSTREE_PAYLOAD_LINK_PREFIX) - 1) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index d817575b..58c80543 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1625,13 +1625,13 @@ scan_commit_object (OtPullData *pull_data, } if (pull_data->timestamp_check_from_rev) { - g_autoptr(GVariant) commit = NULL; + g_autoptr(GVariant) timestamp_commit = NULL; if (!ostree_repo_load_commit (pull_data->repo, pull_data->timestamp_check_from_rev, - &commit, NULL, error)) + ×tamp_commit, NULL, error)) return glnx_prefix_error (error, "Reading %s for timestamp-check-from-rev", pull_data->timestamp_check_from_rev); - guint64 ts = ostree_commit_get_timestamp (commit); + guint64 ts = ostree_commit_get_timestamp (timestamp_commit); if (!_ostree_compare_timestamps (pull_data->timestamp_check_from_rev, ts, checksum, new_ts, error)) return FALSE; } @@ -2001,6 +2001,8 @@ start_fetch (OtPullData *pull_data, is_meta ? meta_fetch_on_complete : content_fetch_on_complete, fetch); } +/* Deprecated: code should load options from the `summary` file rather than + * downloading the remote’s `config` file, to save on network round trips. */ static gboolean load_remote_repo_config (OtPullData *pull_data, GKeyFile **out_keyfile, @@ -2513,10 +2515,7 @@ on_superblock_fetched (GObject *src, const guchar *expected_summary_digest = g_hash_table_lookup (pull_data->summary_deltas_checksums, delta); guint8 actual_summary_digest[OSTREE_SHA256_DIGEST_LEN]; - g_auto(OtChecksum) hasher = { 0, }; - ot_checksum_init (&hasher); - ot_checksum_update_bytes (&hasher, delta_superblock_data); - ot_checksum_get_digest (&hasher, actual_summary_digest, sizeof (actual_summary_digest)); + ot_checksum_bytes (delta_superblock_data, actual_summary_digest); #ifndef OSTREE_DISABLE_GPGME /* At this point we've GPG verified the data, so in theory @@ -2626,54 +2625,180 @@ validate_variant_is_csum (GVariant *csum, return ostree_validate_structureof_csum_v (csum, error); } +static gboolean +_ostree_repo_verify_summary (OstreeRepo *self, + const char *name, + gboolean gpg_verify_summary, + GPtrArray *signapi_summary_verifiers, + GBytes *summary, + GBytes *signatures, + GCancellable *cancellable, + GError **error) +{ + if (gpg_verify_summary) + { + if (summary == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "GPG verification enabled, but no summary found (check that the configured URL in remote config is correct)"); + return FALSE; + } + + if (signatures == NULL) + { + g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_NO_SIGNATURE, + "GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)"); + return FALSE; + } + + /* Verify any summary signatures. */ + if (summary != NULL && signatures != NULL) + { + g_autoptr(OstreeGpgVerifyResult) result = NULL; + + result = ostree_repo_verify_summary (self, + name, + summary, + signatures, + cancellable, + error); + if (!ostree_gpg_verify_result_require_valid_signature (result, error)) + return FALSE; + } + } + + if (signapi_summary_verifiers) + { + if (summary == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Signature verification enabled, but no summary found (check that the configured URL in remote config is correct)"); + return FALSE; + } + + if (signatures == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Signature verification enabled, but no summary signatures found (use sign-verify-summary=false in remote config to disable)"); + return FALSE; + } + + /* Verify any summary signatures. */ + if (summary != NULL && signatures != NULL) + { + g_autoptr(GVariant) sig_variant = NULL; + + sig_variant = g_variant_new_from_bytes (OSTREE_SUMMARY_SIG_GVARIANT_FORMAT, + signatures, FALSE); + + if (!_sign_verify_for_remote (signapi_summary_verifiers, summary, sig_variant, NULL, error)) + return FALSE; + } + } + + return TRUE; +} + +static gboolean +_ostree_repo_load_cache_summary_file (OstreeRepo *self, + const char *filename, + const char *extension, + GBytes **out_data, + GCancellable *cancellable, + GError **error) +{ + const char *file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", filename, extension); + glnx_autofd int fd = -1; + g_autoptr(GBytes) data = NULL; + + *out_data = NULL; + + if (self->cache_dir_fd == -1) + return TRUE; + + fd = openat (self->cache_dir_fd, file, O_CLOEXEC | O_RDONLY); + if (fd < 0) + { + if (errno == ENOENT) + return TRUE; + return glnx_throw_errno_prefix (error, "openat(%s)", file); + } + + data = ot_fd_readall_or_mmap (fd, 0, error); + if (!data) + return FALSE; + + *out_data =g_steal_pointer (&data); + return TRUE; +} + /* Load the summary from the cache if the provided .sig file is the same as the cached version. */ static gboolean _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self, const char *remote, GBytes *summary_sig, - GBytes **summary, + GBytes **out_summary, GCancellable *cancellable, GError **error) { + g_autoptr(GBytes) old_sig_contents = NULL; + + *out_summary = NULL; + + if (!_ostree_repo_load_cache_summary_file (self, remote, ".sig", + &old_sig_contents, + cancellable, error)) + return FALSE; + + if (old_sig_contents != NULL && + g_bytes_compare (old_sig_contents, summary_sig) == 0) + { + g_autoptr(GBytes) summary_data = NULL; + + if (!_ostree_repo_load_cache_summary_file (self, remote, NULL, + &summary_data, + cancellable, error)) + return FALSE; + + if (summary_data == NULL) + { + /* Cached signature without cached summary, remove the signature */ + const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote, ".sig"); + (void) unlinkat (self->cache_dir_fd, summary_cache_sig_file, 0); + } + else + *out_summary = g_steal_pointer (&summary_data); + } + + return TRUE; +} + +static gboolean +_ostree_repo_save_cache_summary_file (OstreeRepo *self, + const char *filename, + const char *extension, + GBytes *data, + GCancellable *cancellable, + GError **error) +{ + const char *file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", filename, extension); + glnx_autofd int fd = -1; + if (self->cache_dir_fd == -1) return TRUE; - const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote, ".sig"); - glnx_autofd int prev_fd = -1; - if (!ot_openat_ignore_enoent (self->cache_dir_fd, summary_cache_sig_file, &prev_fd, error)) - return FALSE; - if (prev_fd < 0) - return TRUE; /* Note early return */ - - g_autoptr(GBytes) old_sig_contents = ot_fd_readall_or_mmap (prev_fd, 0, error); - if (!old_sig_contents) + if (!glnx_shutil_mkdir_p_at (self->cache_dir_fd, _OSTREE_SUMMARY_CACHE_DIR, DEFAULT_DIRECTORY_MODE, cancellable, error)) return FALSE; - if (g_bytes_compare (old_sig_contents, summary_sig) == 0) - { - const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote); - glnx_autofd int summary_fd = -1; - GBytes *summary_data; + if (!glnx_file_replace_contents_at (self->cache_dir_fd, + file, + g_bytes_get_data (data, NULL), + g_bytes_get_size (data), + self->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : GLNX_FILE_REPLACE_DATASYNC_NEW, + cancellable, error)) + return FALSE; - - summary_fd = openat (self->cache_dir_fd, summary_cache_file, O_CLOEXEC | O_RDONLY); - if (summary_fd < 0) - { - if (errno == ENOENT) - { - (void) unlinkat (self->cache_dir_fd, summary_cache_sig_file, 0); - return TRUE; /* Note early return */ - } - - return glnx_throw_errno_prefix (error, "openat(%s)", summary_cache_file); - } - - summary_data = glnx_fd_readall_bytes (summary_fd, cancellable, error); - if (!summary_data) - return FALSE; - *summary = summary_data; - } return TRUE; } @@ -2686,28 +2811,12 @@ _ostree_repo_cache_summary (OstreeRepo *self, GCancellable *cancellable, GError **error) { - if (self->cache_dir_fd == -1) - return TRUE; - - if (!glnx_shutil_mkdir_p_at (self->cache_dir_fd, _OSTREE_SUMMARY_CACHE_DIR, DEFAULT_DIRECTORY_MODE, cancellable, error)) + if (!_ostree_repo_save_cache_summary_file (self, remote, NULL, + summary, cancellable, error)) return FALSE; - const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote); - if (!glnx_file_replace_contents_at (self->cache_dir_fd, - summary_cache_file, - g_bytes_get_data (summary, NULL), - g_bytes_get_size (summary), - self->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : GLNX_FILE_REPLACE_DATASYNC_NEW, - cancellable, error)) - return FALSE; - - const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_DIR, "/", remote, ".sig"); - if (!glnx_file_replace_contents_at (self->cache_dir_fd, - summary_cache_sig_file, - g_bytes_get_data (summary_sig, NULL), - g_bytes_get_size (summary_sig), - self->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : GLNX_FILE_REPLACE_DATASYNC_NEW, - cancellable, error)) + if (!_ostree_repo_save_cache_summary_file (self, remote, ".sig", + summary_sig, cancellable, error)) return FALSE; return TRUE; @@ -2717,6 +2826,8 @@ static OstreeFetcher * _ostree_repo_remote_new_fetcher (OstreeRepo *self, const char *remote_name, gboolean gzip, + GVariant *extra_headers, + const char *append_user_agent, OstreeFetcherSecurityState *out_state, GError **error) { @@ -2830,6 +2941,12 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self, _ostree_fetcher_set_cookie_jar (fetcher, jar_path); } + if (extra_headers) + _ostree_fetcher_set_extra_headers (fetcher, extra_headers); + + if (append_user_agent) + _ostree_fetcher_set_extra_user_agent (fetcher, append_user_agent); + success = TRUE; out: @@ -2977,127 +3094,43 @@ fetch_mirrorlist (OstreeFetcher *fetcher, } static gboolean -repo_remote_fetch_summary (OstreeRepo *self, - const char *name, - const char *metalink_url_string, - GVariant *options, - GBytes **out_summary, - GBytes **out_signatures, - gboolean *out_from_cache, - GCancellable *cancellable, - GError **error) +compute_effective_mirrorlist (OstreeRepo *self, + const char *remote_name_or_baseurl, + const char *url_override, + OstreeFetcher *fetcher, + guint n_network_retries, + GPtrArray **out_mirrorlist, + GCancellable *cancellable, + GError **error) { - g_autoptr(OstreeFetcher) fetcher = NULL; - g_autoptr(GMainContext) mainctx = NULL; - gboolean ret = FALSE; - gboolean from_cache = FALSE; - const char *url_override = NULL; - g_autoptr(GVariant) extra_headers = NULL; - g_autoptr(GPtrArray) mirrorlist = NULL; - const char *append_user_agent = NULL; - guint n_network_retries = DEFAULT_N_NETWORK_RETRIES; + g_autofree char *baseurl = NULL; - if (options) + if (url_override != NULL) + baseurl = g_strdup (url_override); + else if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error)) + return FALSE; + + if (g_str_has_prefix (baseurl, "mirrorlist=")) { - (void) g_variant_lookup (options, "override-url", "&s", &url_override); - (void) g_variant_lookup (options, "http-headers", "@a(ss)", &extra_headers); - (void) g_variant_lookup (options, "append-user-agent", "&s", &append_user_agent); - (void) g_variant_lookup (options, "n-network-retries", "&u", &n_network_retries); + if (!fetch_mirrorlist (fetcher, + baseurl + strlen ("mirrorlist="), + n_network_retries, + out_mirrorlist, + cancellable, error)) + return FALSE; } - - mainctx = g_main_context_new (); - g_main_context_push_thread_default (mainctx); - - fetcher = _ostree_repo_remote_new_fetcher (self, name, TRUE, NULL, error); - if (fetcher == NULL) - goto out; - - if (extra_headers) - _ostree_fetcher_set_extra_headers (fetcher, extra_headers); - - if (append_user_agent) - _ostree_fetcher_set_extra_user_agent (fetcher, append_user_agent); - - { - g_autofree char *url_string = NULL; - if (metalink_url_string) - url_string = g_strdup (metalink_url_string); - else if (url_override) - url_string = g_strdup (url_override); - else if (!ostree_repo_remote_get_url (self, name, &url_string, error)) - goto out; - - if (metalink_url_string == NULL && - g_str_has_prefix (url_string, "mirrorlist=")) - { - if (!fetch_mirrorlist (fetcher, url_string + strlen ("mirrorlist="), - n_network_retries, &mirrorlist, cancellable, error)) - goto out; - } - else - { - g_autoptr(OstreeFetcherURI) uri = _ostree_fetcher_uri_parse (url_string, error); - - if (!uri) - goto out; - - mirrorlist = - g_ptr_array_new_with_free_func ((GDestroyNotify) _ostree_fetcher_uri_free); - g_ptr_array_add (mirrorlist, g_steal_pointer (&uri)); - } - } - - /* FIXME: Send the ETag from the cache with the request for summary.sig to - * avoid downloading summary.sig unnecessarily. This won’t normally provide - * any benefits (but won’t do any harm) since summary.sig is typically 500B - * in size. But if a repository has multiple keys, the signature file will - * grow and this optimisation may be useful. */ - if (!_ostree_preload_metadata_file (self, - fetcher, - mirrorlist, - "summary.sig", - metalink_url_string ? TRUE : FALSE, - n_network_retries, - out_signatures, - cancellable, - error)) - goto out; - - if (*out_signatures) - { - if (!_ostree_repo_load_cache_summary_if_same_sig (self, - name, - *out_signatures, - out_summary, - cancellable, - error)) - goto out; - } - - if (*out_summary) - from_cache = TRUE; else { - if (!_ostree_preload_metadata_file (self, - fetcher, - mirrorlist, - "summary", - metalink_url_string ? TRUE : FALSE, - n_network_retries, - out_summary, - cancellable, - error)) - goto out; + g_autoptr(OstreeFetcherURI) baseuri = _ostree_fetcher_uri_parse (baseurl, error); + + if (!baseuri) + return FALSE; + + *out_mirrorlist = + g_ptr_array_new_with_free_func ((GDestroyNotify) _ostree_fetcher_uri_free); + g_ptr_array_add (*out_mirrorlist, g_steal_pointer (&baseuri)); } - - ret = TRUE; - - out: - if (mainctx) - g_main_context_pop_thread_default (mainctx); - - *out_from_cache = from_cache; - return ret; + return TRUE; } /* Create the fetcher by unioning options from the remote config, plus @@ -3109,17 +3142,13 @@ reinitialize_fetcher (OtPullData *pull_data, const char *remote_name, { g_clear_object (&pull_data->fetcher); pull_data->fetcher = _ostree_repo_remote_new_fetcher (pull_data->repo, remote_name, FALSE, + pull_data->extra_headers, + pull_data->append_user_agent, &pull_data->fetcher_security_state, error); if (pull_data->fetcher == NULL) return FALSE; - if (pull_data->extra_headers) - _ostree_fetcher_set_extra_headers (pull_data->fetcher, pull_data->extra_headers); - - if (pull_data->append_user_agent) - _ostree_fetcher_set_extra_user_agent (pull_data->fetcher, pull_data->append_user_agent); - return TRUE; } @@ -3362,7 +3391,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, const char *url_override = NULL; gboolean inherit_transaction = FALSE; g_autoptr(GHashTable) updated_requested_refs_to_fetch = NULL; /* (element-type OstreeCollectionRef utf8) */ - int i; + gsize i; g_autofree char **opt_localcache_repos = NULL; g_autoptr(GVariantIter) ref_keyring_map_iter = NULL; g_autoptr(GVariant) summary_bytes_v = NULL; @@ -3631,33 +3660,13 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (!metalink_url_str) { - g_autofree char *baseurl = NULL; - - if (url_override != NULL) - baseurl = g_strdup (url_override); - else if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error)) + if (!compute_effective_mirrorlist (self, remote_name_or_baseurl, + url_override, + pull_data->fetcher, + pull_data->n_network_retries, + &pull_data->meta_mirrorlist, + cancellable, error)) goto out; - - if (g_str_has_prefix (baseurl, "mirrorlist=")) - { - if (!fetch_mirrorlist (pull_data->fetcher, - baseurl + strlen ("mirrorlist="), - pull_data->n_network_retries, - &pull_data->meta_mirrorlist, - cancellable, error)) - goto out; - } - else - { - g_autoptr(OstreeFetcherURI) baseuri = _ostree_fetcher_uri_parse (baseurl, error); - - if (!baseuri) - goto out; - - pull_data->meta_mirrorlist = - g_ptr_array_new_with_free_func ((GDestroyNotify) _ostree_fetcher_uri_free); - g_ptr_array_add (pull_data->meta_mirrorlist, g_steal_pointer (&baseuri)); - } } else { @@ -3716,27 +3725,13 @@ ostree_repo_pull_with_options (OstreeRepo *self, } else { - if (g_str_has_prefix (contenturl, "mirrorlist=")) - { - if (!fetch_mirrorlist (pull_data->fetcher, - contenturl + strlen ("mirrorlist="), - pull_data->n_network_retries, - &pull_data->content_mirrorlist, - cancellable, error)) - goto out; - } - else - { - g_autoptr(OstreeFetcherURI) contenturi = _ostree_fetcher_uri_parse (contenturl, error); - - if (!contenturi) - goto out; - - pull_data->content_mirrorlist = - g_ptr_array_new_with_free_func ((GDestroyNotify) _ostree_fetcher_uri_free); - g_ptr_array_add (pull_data->content_mirrorlist, - g_steal_pointer (&contenturi)); - } + if (!compute_effective_mirrorlist (self, remote_name_or_baseurl, + contenturl, + pull_data->fetcher, + pull_data->n_network_retries, + &pull_data->content_mirrorlist, + cancellable, error)) + goto out; } } @@ -3764,30 +3759,6 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (!ostree_repo_open (pull_data->remote_repo_local, cancellable, error)) goto out; } - else - { - if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error)) - goto out; - - if (!ot_keyfile_get_value_with_default (remote_config, "core", "mode", "bare", - &remote_mode_str, error)) - goto out; - - if (!ostree_repo_mode_from_string (remote_mode_str, &pull_data->remote_mode, error)) - goto out; - - if (!ot_keyfile_get_boolean_with_default (remote_config, "core", "tombstone-commits", FALSE, - &pull_data->has_tombstone_commits, error)) - goto out; - - if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't pull from archives with mode \"%s\"", - remote_mode_str); - goto out; - } - } } /* Change some option defaults if we're actually pulling from a local @@ -3856,11 +3827,13 @@ ostree_repo_pull_with_options (OstreeRepo *self, { g_autoptr(GBytes) bytes_sig = NULL; - gsize i, n; + gsize n; g_autoptr(GVariant) refs = NULL; g_autoptr(GVariant) deltas = NULL; g_autoptr(GVariant) additional_metadata = NULL; gboolean summary_from_cache = FALSE; + gboolean remote_mode_loaded = FALSE; + gboolean tombstone_commits = FALSE; if (summary_sig_bytes_v) { @@ -4174,6 +4147,46 @@ ostree_repo_pull_with_options (OstreeRepo *self, csum_data); } } + + if (pull_data->summary && + g_variant_lookup (additional_metadata, OSTREE_SUMMARY_MODE, "s", &remote_mode_str) && + g_variant_lookup (additional_metadata, OSTREE_SUMMARY_TOMBSTONE_COMMITS, "b", &tombstone_commits)) + { + if (!ostree_repo_mode_from_string (remote_mode_str, &pull_data->remote_mode, error)) + goto out; + pull_data->has_tombstone_commits = tombstone_commits; + remote_mode_loaded = TRUE; + } + else if (pull_data->remote_repo_local == NULL) + { + /* Fall-back path which loads the necessary config from the remote’s + * `config` file. Doing so is deprecated since it means an + * additional round trip to the remote for each pull. No need to do + * it for local pulls. */ + if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error)) + goto out; + + if (!ot_keyfile_get_value_with_default (remote_config, "core", "mode", "bare", + &remote_mode_str, error)) + goto out; + + if (!ostree_repo_mode_from_string (remote_mode_str, &pull_data->remote_mode, error)) + goto out; + + if (!ot_keyfile_get_boolean_with_default (remote_config, "core", "tombstone-commits", FALSE, + &pull_data->has_tombstone_commits, error)) + goto out; + + remote_mode_loaded = TRUE; + } + + if (remote_mode_loaded && pull_data->remote_repo_local == NULL && pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Can't pull from archives with mode \"%s\"", + remote_mode_str); + goto out; + } } if (pull_data->is_mirror && !refs_to_fetch && !opt_collection_refs_set && !configured_branches) @@ -5234,7 +5247,7 @@ find_remotes_process_refs (OstreeRepo *self, static void find_remotes_cb (GObject *obj, - GAsyncResult *result, + GAsyncResult *async_result, gpointer user_data) { OstreeRepo *self; @@ -5266,7 +5279,7 @@ find_remotes_cb (GObject *obj, /* progress = data->progress; */ /* Finish finding the remotes. */ - results = ostree_repo_finder_resolve_all_finish (result, &error); + results = ostree_repo_finder_resolve_all_finish (async_result, &error); if (results == NULL) { @@ -5359,8 +5372,8 @@ find_remotes_cb (GObject *obj, /* Check the metadata in the summary file, especially whether it contains * all the @refs we are interested in. */ - summary_v = g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, - summary_bytes, FALSE); + summary_v = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, + summary_bytes, FALSE)); /* Check the summary’s additional metadata and set up @commit_metadata * and @refs_and_remotes_table with the refs listed in the summary file, @@ -5471,7 +5484,7 @@ find_remotes_cb (GObject *obj, goto error; fetcher = _ostree_repo_remote_new_fetcher (self, result->remote->name, - TRUE, NULL, &error); + TRUE, NULL, NULL, NULL, &error); if (fetcher == NULL) goto error; @@ -6093,95 +6106,107 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, g_autoptr(GBytes) signatures = NULL; gboolean gpg_verify_summary; g_autoptr(GPtrArray) signapi_summary_verifiers = NULL; - gboolean ret = FALSE; - gboolean summary_is_from_cache; + gboolean summary_is_from_cache = FALSE; + g_autoptr(OstreeFetcher) fetcher = NULL; + g_autoptr(GMainContextPopDefault) mainctx = NULL; + const char *url_override = NULL; + g_autoptr(GVariant) extra_headers = NULL; + g_autoptr(GPtrArray) mirrorlist = NULL; + const char *append_user_agent = NULL; + guint n_network_retries = DEFAULT_N_NETWORK_RETRIES; g_return_val_if_fail (OSTREE_REPO (self), FALSE); g_return_val_if_fail (name != NULL, FALSE); if (!ostree_repo_get_remote_option (self, name, "metalink", NULL, &metalink_url_string, error)) - goto out; + return FALSE; - if (!repo_remote_fetch_summary (self, - name, - metalink_url_string, - options, - &summary, - &signatures, - &summary_is_from_cache, - cancellable, - error)) - goto out; + if (options) + { + (void) g_variant_lookup (options, "override-url", "&s", &url_override); + (void) g_variant_lookup (options, "http-headers", "@a(ss)", &extra_headers); + (void) g_variant_lookup (options, "append-user-agent", "&s", &append_user_agent); + (void) g_variant_lookup (options, "n-network-retries", "u", &n_network_retries); + } if (!ostree_repo_remote_get_gpg_verify_summary (self, name, &gpg_verify_summary, error)) - goto out; - - if (gpg_verify_summary) - { - if (summary == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "GPG verification enabled, but no summary found (check that the configured URL in remote config is correct)"); - goto out; - } - - if (signatures == NULL) - { - g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_NO_SIGNATURE, - "GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)"); - goto out; - } - - /* Verify any summary signatures. */ - if (summary != NULL && signatures != NULL) - { - g_autoptr(OstreeGpgVerifyResult) result = NULL; - - result = ostree_repo_verify_summary (self, - name, - summary, - signatures, - cancellable, - error); - if (!ostree_gpg_verify_result_require_valid_signature (result, error)) - goto out; - } - } + return FALSE; if (!_signapi_init_for_remote (self, name, NULL, &signapi_summary_verifiers, error)) - goto out; + return FALSE; - if (signapi_summary_verifiers) + mainctx = _ostree_main_context_new_default (); + + fetcher = _ostree_repo_remote_new_fetcher (self, name, TRUE, extra_headers, append_user_agent, NULL, error); + if (fetcher == NULL) + return FALSE; + + if (metalink_url_string) { - if (summary == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "Signature verification enabled, but no summary found (check that the configured URL in remote config is correct)"); - goto out; - } + g_autoptr(OstreeFetcherURI) uri = _ostree_fetcher_uri_parse (metalink_url_string, error); + if (!uri) + return FALSE; - if (signatures == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "Signature verification enabled, but no summary signatures found (use sign-verify-summary=false in remote config to disable)"); - goto out; - } - - /* Verify any summary signatures. */ - if (summary != NULL && signatures != NULL) - { - g_autoptr(GVariant) sig_variant = NULL; - - sig_variant = g_variant_new_from_bytes (OSTREE_SUMMARY_SIG_GVARIANT_FORMAT, - signatures, FALSE); - - if (!_sign_verify_for_remote (signapi_summary_verifiers, summary, sig_variant, NULL, error)) - goto out; - } + mirrorlist = + g_ptr_array_new_with_free_func ((GDestroyNotify) _ostree_fetcher_uri_free); + g_ptr_array_add (mirrorlist, g_steal_pointer (&uri)); } + else if (!compute_effective_mirrorlist (self, name, url_override, + fetcher, n_network_retries, + &mirrorlist, cancellable, error)) + return FALSE; + + /* FIXME: Send the ETag from the cache with the request for summary.sig to + * avoid downloading summary.sig unnecessarily. This won’t normally provide + * any benefits (but won’t do any harm) since summary.sig is typically 500B + * in size. But if a repository has multiple keys, the signature file will + * grow and this optimisation may be useful. */ + if (!_ostree_preload_metadata_file (self, + fetcher, + mirrorlist, + "summary.sig", + metalink_url_string ? TRUE : FALSE, + n_network_retries, + &signatures, + cancellable, + error)) + return FALSE; + + if (signatures) + { + if (!_ostree_repo_load_cache_summary_if_same_sig (self, + name, + signatures, + &summary, + cancellable, + error)) + return FALSE; + } + + if (summary) + summary_is_from_cache = TRUE; + else + { + if (!_ostree_preload_metadata_file (self, + fetcher, + mirrorlist, + "summary", + metalink_url_string ? TRUE : FALSE, + n_network_retries, + &summary, + cancellable, + error)) + return FALSE; + } + + if (!_ostree_repo_verify_summary (self, name, + gpg_verify_summary, signapi_summary_verifiers, + summary, signatures, + cancellable, error)) + return FALSE; if (!summary_is_from_cache && summary && signatures) { @@ -6199,7 +6224,7 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, else { g_propagate_error (error, g_steal_pointer (&temp_error)); - goto out; + return FALSE; } } } @@ -6210,10 +6235,7 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, if (out_signatures != NULL) *out_signatures = g_steal_pointer (&signatures); - ret = TRUE; - -out: - return ret; + return TRUE; } #else /* HAVE_LIBCURL_OR_LIBSOUP */ diff --git a/src/libostree/ostree-repo-static-delta-compilation.c b/src/libostree/ostree-repo-static-delta-compilation.c index 3e9a8e30..753f8aee 100644 --- a/src/libostree/ostree-repo-static-delta-compilation.c +++ b/src/libostree/ostree-repo-static-delta-compilation.c @@ -36,6 +36,8 @@ #include "libglnx.h" #include "ostree-varint.h" #include "bsdiff/bsdiff.h" +#include "ostree-autocleanups.h" +#include "ostree-sign.h" #define CONTENT_SIZE_SIMILARITY_THRESHOLD_PERCENT (30) @@ -1335,6 +1337,8 @@ get_fallback_headers (OstreeRepo *self, * - verbose: b: Print diagnostic messages. Default FALSE. * - endianness: b: Deltas use host byte order by default; this option allows choosing (G_BIG_ENDIAN or G_LITTLE_ENDIAN) * - filename: ay: Save delta superblock to this filename, and parts in the same directory. Default saves to repository. + * - sign-name: ay: Signature type to use. + * - sign-key-ids: as: Array of keys used to sign delta superblock. */ gboolean ostree_repo_static_delta_generate (OstreeRepo *self, @@ -1368,6 +1372,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_autoptr(GPtrArray) builder_fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref); g_auto(GLnxTmpfile) descriptor_tmpf = { 0, }; g_autoptr(OtVariantBuilder) descriptor_builder = NULL; + const char *opt_sign_name; + const char **opt_key_ids; if (!g_variant_lookup (params, "min-fallback-size", "u", &min_fallback_size)) min_fallback_size = 4; @@ -1407,6 +1413,12 @@ ostree_repo_static_delta_generate (OstreeRepo *self, if (!g_variant_lookup (params, "filename", "^&ay", &opt_filename)) opt_filename = NULL; + if (!g_variant_lookup (params, "sign-name", "^&ay", &opt_sign_name)) + opt_sign_name = NULL; + + if (!g_variant_lookup (params, "sign-key-ids", "^a&s", &opt_key_ids)) + opt_key_ids = NULL; + if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, to, &to_commit, error)) return FALSE; @@ -1442,7 +1454,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self, cancellable, error)) return FALSE; - if (!glnx_open_tmpfile_linkable_at (descriptor_dfd, ".", O_WRONLY | O_CLOEXEC, + if (!glnx_open_tmpfile_linkable_at (descriptor_dfd, ".", O_RDWR | O_CLOEXEC, &descriptor_tmpf, error)) return FALSE; @@ -1586,12 +1598,85 @@ ostree_repo_static_delta_generate (OstreeRepo *self, g_printerr ("bsdiff=%u objects\n", builder.n_bsdiff); } - if (fchmod (descriptor_tmpf.fd, 0644) < 0) - return glnx_throw_errno_prefix (error, "fchmod"); + if (opt_sign_name != NULL && opt_key_ids != NULL) + { + g_autoptr(GBytes) tmpdata = NULL; + g_autoptr(OstreeSign) sign = NULL; + const gchar *signature_key = NULL; + g_autoptr(GVariantBuilder) signature_builder = NULL; + g_auto(GLnxTmpfile) descriptor_sign_tmpf = { 0, }; + g_autoptr(OtVariantBuilder) descriptor_sign_builder = NULL; - if (!glnx_link_tmpfile_at (&descriptor_tmpf, GLNX_LINK_TMPFILE_REPLACE, - descriptor_dfd, descriptor_name, error)) - return FALSE; + lseek (descriptor_tmpf.fd, 0, SEEK_SET); + tmpdata = glnx_fd_readall_bytes (descriptor_tmpf.fd, cancellable, error); + if (!tmpdata) + return FALSE; + + sign = ostree_sign_get_by_name (opt_sign_name, error); + if (sign == NULL) + return FALSE; + + signature_key = ostree_sign_metadata_key (sign); + const gchar *signature_format = ostree_sign_metadata_format (sign); + + signature_builder = g_variant_builder_new (G_VARIANT_TYPE (signature_format)); + + for (const char **iter = opt_key_ids; iter && *iter; iter++) + { + const char *keyid = *iter; + g_autoptr(GVariant) secret_key = NULL; + g_autoptr(GBytes) signature_bytes = NULL; + + secret_key = g_variant_new_string (keyid); + if (!ostree_sign_set_sk (sign, secret_key, error)) + return FALSE; + + if (!ostree_sign_data (sign, tmpdata, &signature_bytes, + NULL, error)) + return FALSE; + + g_variant_builder_add (signature_builder, "@ay", ot_gvariant_new_ay_bytes (signature_bytes)); + } + + if (!glnx_open_tmpfile_linkable_at (descriptor_dfd, ".", O_WRONLY | O_CLOEXEC, + &descriptor_sign_tmpf, error)) + return FALSE; + + descriptor_sign_builder = ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SIGNED_FORMAT), + descriptor_sign_tmpf.fd); + + if (!ot_variant_builder_add (descriptor_sign_builder, error, "t", + GUINT64_TO_BE (OSTREE_STATIC_DELTA_SIGNED_MAGIC))) + return FALSE; + if (!ot_variant_builder_add (descriptor_sign_builder, error, "@ay", ot_gvariant_new_ay_bytes (tmpdata))) + return FALSE; + if (!ot_variant_builder_open (descriptor_sign_builder, G_VARIANT_TYPE ("a{sv}"), error)) + return FALSE; + if (!ot_variant_builder_add (descriptor_sign_builder, error, "{sv}", + signature_key, g_variant_builder_end(signature_builder))) + return FALSE; + if (!ot_variant_builder_close (descriptor_sign_builder, error)) + return FALSE; + + if (!ot_variant_builder_end (descriptor_sign_builder, error)) + return FALSE; + + if (fchmod (descriptor_sign_tmpf.fd, 0644) < 0) + return glnx_throw_errno_prefix (error, "fchmod"); + + if (!glnx_link_tmpfile_at (&descriptor_sign_tmpf, GLNX_LINK_TMPFILE_REPLACE, + descriptor_dfd, descriptor_name, error)) + return FALSE; + } + else + { + if (fchmod (descriptor_tmpf.fd, 0644) < 0) + return glnx_throw_errno_prefix (error, "fchmod"); + + if (!glnx_link_tmpfile_at (&descriptor_tmpf, GLNX_LINK_TMPFILE_REPLACE, + descriptor_dfd, descriptor_name, error)) + return FALSE; + } return TRUE; } diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c index ade4e9df..d83ec8c4 100644 --- a/src/libostree/ostree-repo-static-delta-core.c +++ b/src/libostree/ostree-repo-static-delta-core.c @@ -54,6 +54,28 @@ _ostree_static_delta_parse_checksum_array (GVariant *array, return TRUE; } +GVariant * +_ostree_repo_static_delta_superblock_digest (OstreeRepo *repo, + const char *from, + const char *to, + GCancellable *cancellable, + GError **error) +{ + g_autofree char *superblock = _ostree_get_relative_static_delta_superblock_path ((from && from[0]) ? from : NULL, to); + glnx_autofd int superblock_file_fd = -1; + guint8 digest[OSTREE_SHA256_DIGEST_LEN]; + + if (!glnx_openat_rdonly (repo->repo_dir_fd, superblock, TRUE, &superblock_file_fd, error)) + return NULL; + + g_autoptr(GBytes) superblock_content = ot_fd_readall_or_mmap (superblock_file_fd, 0, error); + if (!superblock_content) + return NULL; + + ot_checksum_bytes (superblock_content, digest); + + return ot_gvariant_new_bytearray (digest, sizeof (digest)); +} /** * ostree_repo_list_static_delta_names: @@ -109,7 +131,7 @@ ostree_repo_list_static_delta_names (OstreeRepo *self, return FALSE; if (sub_dent == NULL) break; - if (dent->d_type != DT_DIR) + if (sub_dent->d_type != DT_DIR) continue; const char *name1 = dent->d_name; @@ -188,27 +210,126 @@ _ostree_repo_static_delta_part_have_all_objects (OstreeRepo *repo, return TRUE; } +static gboolean +_ostree_repo_static_delta_is_signed (OstreeRepo *self, + int fd, + GPtrArray **out_value, + GError **error) +{ + g_autoptr(GVariant) delta = NULL; + g_autoptr(GVariant) delta_sign_magic = NULL; + g_autoptr(GVariant) delta_sign = NULL; + GVariantIter iter; + GVariant *item; + g_autoptr(GPtrArray) signatures = NULL; + gboolean ret = FALSE; + + if (out_value) + *out_value = NULL; + + if (!ot_variant_read_fd (fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT, TRUE, &delta, error)) + return FALSE; + + delta_sign_magic = g_variant_get_child_value (delta, 0); + if (delta_sign_magic == NULL) + return glnx_throw (error, "no signatures in static-delta"); + + if (GUINT64_FROM_BE (g_variant_get_uint64 (delta_sign_magic)) != OSTREE_STATIC_DELTA_SIGNED_MAGIC) + return glnx_throw (error, "no signatures in static-delta"); + + delta_sign = g_variant_get_child_value (delta, 2); + if (delta_sign == NULL) + return glnx_throw (error, "no signatures in static-delta"); + + if (out_value) + signatures = g_ptr_array_new_with_free_func (g_free); + + /* Check if there are signatures in the superblock */ + g_variant_iter_init (&iter, delta_sign); + while ((item = g_variant_iter_next_value (&iter))) + { + g_autoptr(GVariant) key_v = g_variant_get_child_value (item, 0); + const char *str = g_variant_get_string (key_v, NULL); + if (g_str_has_prefix (str, "ostree.sign.")) + { + ret = TRUE; + if (signatures) + g_ptr_array_add (signatures, g_strdup (str + strlen ("ostree.sign."))); + } + g_variant_unref (item); + } + + if (out_value && ret) + ot_transfer_out_value (out_value, &signatures); + + return ret; +} + +static gboolean +_ostree_repo_static_delta_verify_signature (OstreeRepo *self, + int fd, + OstreeSign *sign, + char **out_success_message, + GError **error) +{ + g_autoptr(GVariant) delta = NULL; + + if (!ot_variant_read_fd (fd, 0, + (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT, + TRUE, &delta, error)) + return FALSE; + + /* Check if there are signatures for signature engine */ + const gchar *signature_key = ostree_sign_metadata_key(sign); + GVariantType *signature_format = (GVariantType *) ostree_sign_metadata_format(sign); + g_autoptr(GVariant) delta_meta = g_variant_get_child_value (delta, 2); + if (delta_meta == NULL) + return glnx_throw (error, "no metadata in static-delta superblock"); + g_autoptr(GVariant) signatures = g_variant_lookup_value (delta_meta, + signature_key, + signature_format); + if (!signatures) + return glnx_throw (error, "no signature for '%s' in static-delta superblock", signature_key); + + /* Get static delta superblock */ + g_autoptr(GVariant) child = g_variant_get_child_value (delta, 1); + if (child == NULL) + return glnx_throw (error, "no metadata in static-delta superblock"); + g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes(child); + + return ostree_sign_data_verify (sign, signed_data, signatures, out_success_message, error); +} + /** - * ostree_repo_static_delta_execute_offline: + * ostree_repo_static_delta_execute_offline_with_signature: * @self: Repo * @dir_or_file: Path to a directory containing static delta data, or directly to the superblock + * @sign: Signature engine used to check superblock * @skip_validation: If %TRUE, assume data integrity * @cancellable: Cancellable * @error: Error * * Given a directory representing an already-downloaded static delta - * on disk, apply it, generating a new commit. The directory must be - * named with the form "FROM-TO", where both are checksums, and it - * must contain a file named "superblock", along with at least one part. + * on disk, apply it, generating a new commit. + * If sign is passed, the static delta signature is verified. + * If sign-verify-deltas configuration option is set and static delta is signed, + * signature verification will be mandatory before apply the static delta. + * The directory must be named with the form "FROM-TO", where both are + * checksums, and it must contain a file named "superblock", along with at least + * one part. + * + * Since: 2020.7 */ gboolean -ostree_repo_static_delta_execute_offline (OstreeRepo *self, - GFile *dir_or_file, - gboolean skip_validation, - GCancellable *cancellable, - GError **error) +ostree_repo_static_delta_execute_offline_with_signature (OstreeRepo *self, + GFile *dir_or_file, + OstreeSign *sign, + gboolean skip_validation, + GCancellable *cancellable, + GError **error) { g_autofree char *basename = NULL; + g_autoptr(GVariant) meta = NULL; const char *dir_or_file_path = gs_file_get_path_cached (dir_or_file); @@ -234,10 +355,44 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self, if (meta_fd < 0) return glnx_throw_errno_prefix (error, "openat(%s)", basename); - g_autoptr(GVariant) meta = NULL; - if (!ot_variant_read_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), - FALSE, &meta, error)) - return FALSE; + gboolean is_signed = _ostree_repo_static_delta_is_signed (self, meta_fd, NULL, NULL); + if (is_signed) + { + gboolean verify_deltas; + gboolean verified; + + if (!ot_keyfile_get_boolean_with_default (self->config, "core", "sign-verify-deltas", + FALSE, &verify_deltas, error)) + return FALSE; + + if (verify_deltas && !sign) + return glnx_throw (error, "Key is mandatory to check delta signature"); + + if (sign) + { + verified = _ostree_repo_static_delta_verify_signature (self, meta_fd, sign, NULL, error); + if (*error) + return FALSE; + if (!verified) + return glnx_throw (error, "Delta signature verification failed"); + } + + g_autoptr(GVariant) delta = NULL; + if (!ot_variant_read_fd (meta_fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT, + TRUE, &delta, error)) + return FALSE; + + g_autoptr(GVariant) child = g_variant_get_child_value (delta, 1); + g_autoptr(GBytes) bytes = g_variant_get_data_as_bytes (child); + meta = g_variant_new_from_bytes ((GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, + bytes, FALSE); + } + else + { + if (!ot_variant_read_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), + FALSE, &meta, error)) + return FALSE; + } /* Parsing OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */ @@ -280,9 +435,8 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self, if (!have_to_commit) { g_autofree char *detached_path = _ostree_get_relative_static_delta_path (from_checksum, to_checksum, "commitmeta"); - g_autoptr(GVariant) detached_data = NULL; - - detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}")); + g_autoptr(GVariant) detached_data = + g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}")); if (detached_data && !ostree_repo_write_commit_detached_metadata (self, to_checksum, detached_data, @@ -386,6 +540,32 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self, return TRUE; } +/** + * ostree_repo_static_delta_execute_offline: + * @self: Repo + * @dir_or_file: Path to a directory containing static delta data, or directly to the superblock + * @skip_validation: If %TRUE, assume data integrity + * @cancellable: Cancellable + * @error: Error + * + * Given a directory representing an already-downloaded static delta + * on disk, apply it, generating a new commit. The directory must be + * named with the form "FROM-TO", where both are checksums, and it + * must contain a file named "superblock", along with at least one part. + */ +gboolean +ostree_repo_static_delta_execute_offline (OstreeRepo *self, + GFile *dir_or_file, + gboolean skip_validation, + GCancellable *cancellable, + GError **error) +{ + return ostree_repo_static_delta_execute_offline_with_signature(self, dir_or_file, NULL, + skip_validation, + cancellable, + error); +} + gboolean _ostree_static_delta_part_open (GInputStream *part_in, GBytes *inline_part_bytes, @@ -726,6 +906,8 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, GError **error) { glnx_autofd int superblock_fd = -1; + g_autoptr(GVariant) delta = NULL; + g_autoptr(GVariant) delta_superblock = NULL; if (strchr (delta_id, '/')) { @@ -744,13 +926,28 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, return FALSE; } - g_autoptr(GVariant) delta_superblock = NULL; - if (!ot_variant_read_fd (superblock_fd, 0, - (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, - TRUE, &delta_superblock, error)) - return FALSE; + gboolean is_signed = _ostree_repo_static_delta_is_signed(self, superblock_fd, NULL, NULL); + if (is_signed) + { + if (!ot_variant_read_fd (superblock_fd, 0, (GVariantType*)OSTREE_STATIC_DELTA_SIGNED_FORMAT, + TRUE, &delta, error)) + return FALSE; + + g_autoptr(GVariant) child = g_variant_get_child_value (delta, 1); + g_autoptr(GBytes) bytes = g_variant_get_data_as_bytes(child); + delta_superblock = g_variant_new_from_bytes ((GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, + bytes, FALSE); + } + else + { + if (!ot_variant_read_fd (superblock_fd, 0, + (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT, + TRUE, &delta_superblock, error)) + return FALSE; + } g_print ("Delta: %s\n", delta_id); + g_print ("Signed: %s\n", is_signed ? "yes" : "no"); g_autoptr(GVariant) from_commit_v = NULL; g_variant_get_child (delta_superblock, 2, "@ay", &from_commit_v); g_autofree char *from_commit = NULL; @@ -873,3 +1070,51 @@ _ostree_repo_static_delta_dump (OstreeRepo *self, return TRUE; } + +/** + * ostree_repo_static_delta_verify_signature: + * @self: Repo + * @delta_id: delta path + * @sign: Signature engine used to check superblock + * @out_success_message: success message + * @error: Error + * + * Verify static delta file signature. + * + * Returns: TRUE if the signature of static delta file is valid using the + * signature engine provided, FALSE otherwise. + * + * Since: 2020.7 + */ +gboolean +ostree_repo_static_delta_verify_signature (OstreeRepo *self, + const char *delta_id, + OstreeSign *sign, + char **out_success_message, + GError **error) +{ + g_autoptr(GVariant) delta_meta = NULL; + glnx_autofd int delta_fd = -1; + + if (strchr (delta_id, '/')) + { + if (!glnx_openat_rdonly (AT_FDCWD, delta_id, TRUE, &delta_fd, error)) + return FALSE; + } + else + { + g_autofree char *from = NULL; + g_autofree char *to = NULL; + if (!_ostree_parse_delta_name (delta_id, &from, &to, error)) + return FALSE; + + g_autofree char *delta_path = _ostree_get_relative_static_delta_superblock_path (from, to); + if (!glnx_openat_rdonly (self->repo_dir_fd, delta_path, TRUE, &delta_fd, error)) + return FALSE; + } + + if (!_ostree_repo_static_delta_is_signed (self, delta_fd, NULL, error)) + return FALSE; + + return _ostree_repo_static_delta_verify_signature (self, delta_fd, sign, out_success_message, error); +} diff --git a/src/libostree/ostree-repo-static-delta-private.h b/src/libostree/ostree-repo-static-delta-private.h index 155acd52..5a2e6879 100644 --- a/src/libostree/ostree-repo-static-delta-private.h +++ b/src/libostree/ostree-repo-static-delta-private.h @@ -104,6 +104,25 @@ G_BEGIN_DECLS */ #define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")" +/** + * OSTREE_STATIC_DELTA_SIGNED_FORMAT + * + * magic: t magic number, 8 bytes for alignment + * superblock: ay delta supeblock variant + * signatures: a{sv} + * + * The signed static delta starts with the 'OSTSGNDT' magic number followed by + * the array of bytes containing the superblock used for the signature. + * + * Then, the signatures array contains the signatures of the superblock. A + * signature has the following form: + * type: signature key + * signature: variant depending on type used + */ +#define OSTREE_STATIC_DELTA_SIGNED_FORMAT "(taya{sv})" + +#define OSTREE_STATIC_DELTA_SIGNED_MAGIC 0x4F535453474E4454 /* OSTSGNDT */ + typedef enum { OSTREE_STATIC_DELTA_OPEN_FLAGS_NONE = 0, OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM = (1 << 0), @@ -190,6 +209,12 @@ _ostree_repo_static_delta_query_exists (OstreeRepo *repo, gboolean *out_exists, GCancellable *cancellable, GError **error); +GVariant * +_ostree_repo_static_delta_superblock_digest (OstreeRepo *repo, + const char *from, + const char *to, + GCancellable *cancellable, + GError **error); gboolean _ostree_repo_static_delta_dump (OstreeRepo *repo, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 95eb0efc..ba3e877f 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3782,14 +3782,14 @@ load_metadata_internal (OstreeRepo *self, g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (sha256); *out_state = 0; - glnx_autofd int fd = -1; - if (!ot_openat_ignore_enoent (self->repo_dir_fd, commitpartial_path, &fd, error)) + glnx_autofd int commitpartial_fd = -1; + if (!ot_openat_ignore_enoent (self->repo_dir_fd, commitpartial_path, &commitpartial_fd, error)) return FALSE; - if (fd != -1) + if (commitpartial_fd != -1) { *out_state |= OSTREE_REPO_COMMIT_STATE_PARTIAL; char reason; - if (read (fd, &reason, 1) == 1) + if (read (commitpartial_fd, &reason, 1) == 1) { if (reason == 'f') *out_state |= OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL; @@ -5793,25 +5793,18 @@ ostree_repo_regenerate_summary (OstreeRepo *self, { g_autofree char *from = NULL; g_autofree char *to = NULL; + GVariant *digest; + if (!_ostree_parse_delta_name (delta_names->pdata[i], &from, &to, error)) return FALSE; - g_autofree char *superblock = _ostree_get_relative_static_delta_superblock_path ((from && from[0]) ? from : NULL, to); - glnx_autofd int superblock_file_fd = -1; - - if (!glnx_openat_rdonly (self->repo_dir_fd, superblock, TRUE, &superblock_file_fd, error)) + digest = _ostree_repo_static_delta_superblock_digest (self, + (from && from[0]) ? from : NULL, + to, cancellable, error); + if (digest == NULL) return FALSE; - g_autoptr(GBytes) superblock_content = ot_fd_readall_or_mmap (superblock_file_fd, 0, error); - if (!superblock_content) - return FALSE; - g_auto(OtChecksum) hasher = { 0, }; - ot_checksum_init (&hasher); - ot_checksum_update_bytes (&hasher, superblock_content); - guint8 digest[OSTREE_SHA256_DIGEST_LEN]; - ot_checksum_get_digest (&hasher, digest, sizeof (digest)); - - g_variant_dict_insert_value (&deltas_builder, delta_names->pdata[i], ot_gvariant_new_bytearray (digest, sizeof (digest))); + g_variant_dict_insert_value (&deltas_builder, delta_names->pdata[i], digest); } if (delta_names->len > 0) @@ -5823,6 +5816,24 @@ ostree_repo_regenerate_summary (OstreeRepo *self, g_variant_new_uint64 (GUINT64_TO_BE (g_get_real_time () / G_USEC_PER_SEC))); } + { + g_autofree char *remote_mode_str = NULL; + if (!ot_keyfile_get_value_with_default (self->config, "core", "mode", "bare", + &remote_mode_str, error)) + return FALSE; + g_variant_dict_insert_value (&additional_metadata_builder, OSTREE_SUMMARY_MODE, + g_variant_new_string (remote_mode_str)); + } + + { + gboolean tombstone_commits = FALSE; + if (!ot_keyfile_get_boolean_with_default (self->config, "core", "tombstone-commits", FALSE, + &tombstone_commits, error)) + return FALSE; + g_variant_dict_insert_value (&additional_metadata_builder, OSTREE_SUMMARY_TOMBSTONE_COMMITS, + g_variant_new_boolean (tombstone_commits)); + } + /* Add refs which have a collection specified, which could be in refs/mirrors, * refs/heads, and/or refs/remotes. */ { @@ -5838,19 +5849,19 @@ ostree_repo_regenerate_summary (OstreeRepo *self, collection_map = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_unref); - const OstreeCollectionRef *ref; + const OstreeCollectionRef *c_ref; const char *checksum; - while (g_hash_table_iter_next (&iter, (gpointer *) &ref, (gpointer *) &checksum)) + while (g_hash_table_iter_next (&iter, (gpointer *) &c_ref, (gpointer *) &checksum)) { - GHashTable *ref_map = g_hash_table_lookup (collection_map, ref->collection_id); + GHashTable *ref_map = g_hash_table_lookup (collection_map, c_ref->collection_id); if (ref_map == NULL) { ref_map = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); - g_hash_table_insert (collection_map, ref->collection_id, ref_map); + g_hash_table_insert (collection_map, c_ref->collection_id, ref_map); } - g_hash_table_insert (ref_map, ref->ref_name, (gpointer) checksum); + g_hash_table_insert (ref_map, c_ref->ref_name, (gpointer) checksum); } g_autoptr(GVariantBuilder) collection_refs_builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sa(s(taya{sv}))}")); diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index e28af29c..d52fc9c3 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -32,6 +32,7 @@ #include "ostree-repo-finder.h" #include "ostree-sepolicy.h" #include "ostree-gpg-verify-result.h" +#include "ostree-sign.h" G_BEGIN_DECLS @@ -1067,6 +1068,14 @@ gboolean ostree_repo_static_delta_generate (OstreeRepo *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_static_delta_execute_offline_with_signature (OstreeRepo *self, + GFile *dir_or_file, + OstreeSign *sign, + gboolean skip_validation, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC gboolean ostree_repo_static_delta_execute_offline (OstreeRepo *self, GFile *dir_or_file, @@ -1074,6 +1083,13 @@ gboolean ostree_repo_static_delta_execute_offline (OstreeRepo GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_static_delta_verify_signature (OstreeRepo *self, + const char *delta_id, + OstreeSign *sign, + char **out_success_message, + GError **error); + _OSTREE_PUBLIC GHashTable *ostree_repo_traverse_new_reachable (void); diff --git a/src/libostree/ostree-sign.c b/src/libostree/ostree-sign.c index ee7e928d..eeef96dd 100644 --- a/src/libostree/ostree-sign.c +++ b/src/libostree/ostree-sign.c @@ -365,7 +365,7 @@ _sign_detached_metadata_append (OstreeSign *self, signature_key, g_variant_builder_end (signature_builder)); - return g_variant_dict_end (&metadata_dict); + return g_variant_ref_sink (g_variant_dict_end (&metadata_dict)); } /** diff --git a/src/libostree/ostree-soup-uri.c b/src/libostree/ostree-soup-uri.c index a3fa2acc..ba14e5c6 100644 --- a/src/libostree/ostree-soup-uri.c +++ b/src/libostree/ostree-soup-uri.c @@ -348,7 +348,7 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) { SoupURI *uri, fixed_base; const char *end, *hash, *colon, *at, *path, *question; - const char *p, *hostend; + const char *c, *hostend; gboolean remove_dot_segments = TRUE; int len; @@ -402,17 +402,17 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) } /* Find scheme */ - p = uri_string; - while (p < end && (g_ascii_isalpha (*p) || - (p > uri_string && (g_ascii_isdigit (*p) || - *p == '.' || - *p == '+' || - *p == '-')))) - p++; + c = uri_string; + while (c < end && (g_ascii_isalpha (*c) || + (c > uri_string && (g_ascii_isdigit (*c) || + *c == '.' || + *c == '+' || + *c == '-')))) + c++; - if (p > uri_string && *p == ':') { - uri->scheme = soup_uri_parse_scheme (uri_string, p - uri_string); - uri_string = p + 1; + if (c > uri_string && *c == ':') { + uri->scheme = soup_uri_parse_scheme (uri_string, c - uri_string); + uri_string = c + 1; } if (uri_string == end && !base && !uri->fragment) { diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index ffad4130..27122834 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -298,6 +298,8 @@ cleanup_old_deployments (OstreeSysroot *self, g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_autoptr(GHashTable) active_boot_checksums = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_autoptr(GHashTable) active_overlay_initrds = + g_hash_table_new (g_str_hash, g_str_equal); /* borrows from deployment's bootconfig */ for (guint i = 0; i < self->deployments->len; i++) { OstreeDeployment *deployment = self->deployments->pdata[i]; @@ -306,6 +308,11 @@ cleanup_old_deployments (OstreeSysroot *self, /* Transfer ownership */ g_hash_table_replace (active_deployment_dirs, deployment_path, deployment_path); g_hash_table_replace (active_boot_checksums, bootcsum, bootcsum); + + OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); + char **initrds = ostree_bootconfig_parser_get_overlay_initrds (bootconfig); + for (char **it = initrds; it && *it; it++) + g_hash_table_add (active_overlay_initrds, (char*)glnx_basename (*it)); } /* Find all deployment directories, both active and inactive */ @@ -349,6 +356,42 @@ cleanup_old_deployments (OstreeSysroot *self, return FALSE; } + /* Clean up overlay initrds */ + glnx_autofd int overlays_dfd = + glnx_opendirat_with_errno (self->sysroot_fd, _OSTREE_SYSROOT_INITRAMFS_OVERLAYS, FALSE); + if (overlays_dfd < 0) + { + if (errno != ENOENT) + return glnx_throw_errno_prefix (error, "open(initrd_overlays)"); + } + else + { + g_autoptr(GPtrArray) initrds_to_delete = g_ptr_array_new_with_free_func (g_free); + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; + if (!glnx_dirfd_iterator_init_at (overlays_dfd, ".", TRUE, &dfd_iter, error)) + return FALSE; + while (TRUE) + { + struct dirent *dent; + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) + return FALSE; + if (dent == NULL) + break; + + /* there shouldn't be other file types there, but let's be conservative */ + if (dent->d_type != DT_REG) + continue; + + if (!g_hash_table_lookup (active_overlay_initrds, dent->d_name)) + g_ptr_array_add (initrds_to_delete, g_strdup (dent->d_name)); + } + for (guint i = 0; i < initrds_to_delete->len; i++) + { + if (!ot_ensure_unlinked_at (overlays_dfd, initrds_to_delete->pdata[i], error)) + return FALSE; + } + } + return TRUE; } diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 0e02d1f2..7b7ba5e9 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -272,13 +272,13 @@ checksum_dir_recurse (int dfd, } else { - int fd; + glnx_autofd int fd = -1; if (!ot_openat_ignore_enoent (dfditer.fd, d_name, &fd, error)) return FALSE; if (fd != -1) { - g_autoptr(GInputStream) in = g_unix_input_stream_new (fd, FALSE); + g_autoptr(GInputStream) in = g_unix_input_stream_new (glnx_steal_fd (&fd), TRUE); if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error)) return FALSE; } @@ -313,7 +313,7 @@ copy_dir_recurse (int src_parent_dfd, if (!dirfd_copy_attributes_and_xattrs (src_parent_dfd, name, src_dfd_iter.fd, dest_dfd, flags, cancellable, error)) - return FALSE; + return glnx_prefix_error (error, "Copying attributes of %s", name); while (TRUE) { @@ -340,7 +340,7 @@ copy_dir_recurse (int src_parent_dfd, dest_dfd, dent->d_name, sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), cancellable, error)) - return FALSE; + return glnx_prefix_error (error, "Copying %s", dent->d_name); } } @@ -488,7 +488,7 @@ copy_modified_config_file (int orig_etc_fd, new_etc_fd, path, sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), cancellable, error)) - return FALSE; + return glnx_prefix_error (error, "Copying %s", path); } else { @@ -1028,7 +1028,8 @@ _ostree_kernel_layout_new (void) /* See get_kernel_from_tree() below */ static gboolean -get_kernel_from_tree_usrlib_modules (int deployment_dfd, +get_kernel_from_tree_usrlib_modules (OstreeSysroot *sysroot, + int deployment_dfd, OstreeKernelLayout **out_layout, GCancellable *cancellable, GError **error) @@ -1137,37 +1138,41 @@ get_kernel_from_tree_usrlib_modules (int deployment_dfd, g_clear_object (&in); glnx_close_fd (&fd); - /* Check for /usr/lib/modules/$kver/devicetree first, if it does not - * exist check for /usr/lib/modules/$kver/dtb/ directory. - */ - if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error)) - return FALSE; - if (fd != -1) + /* Testing aid for https://github.com/ostreedev/ostree/issues/2154 */ + const gboolean no_dtb = (sysroot->debug_flags & OSTREE_SYSROOT_DEBUG_TEST_NO_DTB) > 0; + if (!no_dtb) { - ret_layout->devicetree_srcpath = g_strdup ("devicetree"); - ret_layout->devicetree_namever = g_strdup_printf ("devicetree-%s", kver); - in = g_unix_input_stream_new (fd, FALSE); - if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error)) + /* Check for /usr/lib/modules/$kver/devicetree first, if it does not + * exist check for /usr/lib/modules/$kver/dtb/ directory. + */ + if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "devicetree", &fd, error)) return FALSE; - } - else - { - struct stat stbuf; - /* Check for dtb directory */ - if (!glnx_fstatat_allow_noent (ret_layout->boot_dfd, "dtb", &stbuf, 0, error)) - return FALSE; - - if (errno == 0 && S_ISDIR (stbuf.st_mode)) + if (fd != -1) { - /* devicetree_namever set to NULL indicates a complete directory */ - ret_layout->devicetree_srcpath = g_strdup ("dtb"); - ret_layout->devicetree_namever = NULL; - - if (!checksum_dir_recurse(ret_layout->boot_dfd, "dtb", &checksum, cancellable, error)) + ret_layout->devicetree_srcpath = g_strdup ("devicetree"); + ret_layout->devicetree_namever = g_strdup_printf ("devicetree-%s", kver); + in = g_unix_input_stream_new (fd, FALSE); + if (!ot_gio_splice_update_checksum (NULL, in, &checksum, cancellable, error)) return FALSE; } - } + else + { + struct stat stbuf; + /* Check for dtb directory */ + if (!glnx_fstatat_allow_noent (ret_layout->boot_dfd, "dtb", &stbuf, 0, error)) + return FALSE; + if (errno == 0 && S_ISDIR (stbuf.st_mode)) + { + /* devicetree_namever set to NULL indicates a complete directory */ + ret_layout->devicetree_srcpath = g_strdup ("dtb"); + ret_layout->devicetree_namever = NULL; + + if (!checksum_dir_recurse(ret_layout->boot_dfd, "dtb", &checksum, cancellable, error)) + return FALSE; + } + } + } g_clear_object (&in); glnx_close_fd (&fd); @@ -1336,7 +1341,8 @@ get_kernel_from_tree_legacy_layouts (int deployment_dfd, * initramfs there, so we need to look in /usr/lib/ostree-boot first. */ static gboolean -get_kernel_from_tree (int deployment_dfd, +get_kernel_from_tree (OstreeSysroot *sysroot, + int deployment_dfd, OstreeKernelLayout **out_layout, GCancellable *cancellable, GError **error) @@ -1345,7 +1351,7 @@ get_kernel_from_tree (int deployment_dfd, g_autoptr(OstreeKernelLayout) legacy_layout = NULL; /* First, gather from usr/lib/modules/$kver if it exists */ - if (!get_kernel_from_tree_usrlib_modules (deployment_dfd, &usrlib_modules_layout, cancellable, error)) + if (!get_kernel_from_tree_usrlib_modules (sysroot, deployment_dfd, &usrlib_modules_layout, cancellable, error)) return FALSE; /* Gather the legacy layout */ @@ -1761,7 +1767,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, /* Find the kernel/initramfs/devicetree in the tree */ g_autoptr(OstreeKernelLayout) kernel_layout = NULL; - if (!get_kernel_from_tree (deployment_dfd, &kernel_layout, + if (!get_kernel_from_tree (sysroot, deployment_dfd, &kernel_layout, cancellable, error)) return FALSE; @@ -1771,7 +1777,6 @@ install_deployment_kernel (OstreeSysroot *sysroot, const char *osname = ostree_deployment_get_osname (deployment); const char *bootcsum = ostree_deployment_get_bootcsum (deployment); - g_assert_cmpstr (kernel_layout->bootcsum, ==, bootcsum); g_autofree char *bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum); g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion); g_autofree char *bootconf_name = g_strdup_printf ("ostree-%d-%s.conf", @@ -1854,6 +1859,47 @@ install_deployment_kernel (OstreeSysroot *sysroot, } } + g_autoptr(GPtrArray) overlay_initrds = NULL; + for (char **it = _ostree_deployment_get_overlay_initrds (deployment); it && *it; it++) + { + char *checksum = *it; + + /* Overlay initrds are not part of the bootcsum dir; they're not part of the tree + * proper. Instead they're in /boot/ostree/initramfs-overlays/ named by their csum. + * Doing it this way allows sharing the same bootcsum dir for multiple deployments + * with the only change being in overlay initrds (or conversely, the same overlay + * across different boocsums). Eventually, it'd be nice to have an OSTree repo in + * /boot itself and drop the boocsum dir concept entirely. */ + + g_autofree char *destpath = + g_strdup_printf ("/" _OSTREE_SYSROOT_BOOT_INITRAMFS_OVERLAYS "/%s.img", checksum); + const char *rel_destpath = destpath + 1; + + /* lazily allocate array and create dir so we don't pollute /boot if not needed */ + if (overlay_initrds == NULL) + { + overlay_initrds = g_ptr_array_new_with_free_func (g_free); + + if (!glnx_shutil_mkdir_p_at (boot_dfd, _OSTREE_SYSROOT_BOOT_INITRAMFS_OVERLAYS, + 0755, cancellable, error)) + return FALSE; + } + + if (!glnx_fstatat_allow_noent (boot_dfd, rel_destpath, NULL, 0, error)) + return FALSE; + if (errno == ENOENT) + { + g_autofree char *srcpath = + g_strdup_printf (_OSTREE_SYSROOT_RUNSTATE_STAGED_INITRDS_DIR "/%s", checksum); + if (!install_into_boot (repo, sepolicy, AT_FDCWD, srcpath, boot_dfd, rel_destpath, + cancellable, error)) + return FALSE; + } + + /* these are used lower down to populate the bootconfig */ + g_ptr_array_add (overlay_initrds, g_steal_pointer (&destpath)); + } + g_autofree char *contents = NULL; if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/lib/os-release", &stbuf, 0, error)) return FALSE; @@ -1933,6 +1979,12 @@ install_deployment_kernel (OstreeSysroot *sysroot, g_autofree char * initrd_boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->initramfs_namever, NULL); ostree_bootconfig_parser_set (bootconfig, "initrd", initrd_boot_relpath); + + if (overlay_initrds) + { + g_ptr_array_add (overlay_initrds, NULL); + ostree_bootconfig_parser_set_overlay_initrds (bootconfig, (char**)overlay_initrds->pdata); + } } else { @@ -1945,8 +1997,8 @@ install_deployment_kernel (OstreeSysroot *sysroot, if (kernel_layout->devicetree_namever) { - g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL); - ostree_bootconfig_parser_set (bootconfig, "devicetree", boot_relpath); + g_autofree char * dt_boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_namever, NULL); + ostree_bootconfig_parser_set (bootconfig, "devicetree", dt_boot_relpath); } else if (kernel_layout->devicetree_srcpath) { @@ -1954,8 +2006,8 @@ install_deployment_kernel (OstreeSysroot *sysroot, * want to point to a whole directory of device trees. * See: https://github.com/ostreedev/ostree/issues/1900 */ - g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_srcpath, NULL); - ostree_bootconfig_parser_set (bootconfig, "fdtdir", boot_relpath); + g_autofree char * dt_boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->devicetree_srcpath, NULL); + ostree_bootconfig_parser_set (bootconfig, "fdtdir", dt_boot_relpath); } /* Note this is parsed in ostree-impl-system-generator.c */ @@ -2130,6 +2182,10 @@ deployment_bootconfigs_equal (OstreeRepo *repo, if (strcmp (a_bootcsum, b_bootcsum) != 0) return FALSE; + /* same initrd overlays? */ + if (g_strcmp0 (a->overlay_initrds_id, b->overlay_initrds_id) != 0) + return FALSE; + /* same kargs? */ g_autofree char *a_boot_options_without_ostree = get_deployment_nonostree_kargs (a); g_autofree char *b_boot_options_without_ostree = get_deployment_nonostree_kargs (b); @@ -2683,7 +2739,7 @@ sysroot_initialize_deployment (OstreeSysroot *self, const char *osname, const char *revision, GKeyFile *origin, - char **override_kernel_argv, + OstreeSysrootDeployTreeOpts *opts, OstreeDeployment **out_new_deployment, GCancellable *cancellable, GError **error) @@ -2711,12 +2767,13 @@ sysroot_initialize_deployment (OstreeSysroot *self, return FALSE; g_autoptr(OstreeKernelLayout) kernel_layout = NULL; - if (!get_kernel_from_tree (deployment_dfd, &kernel_layout, + if (!get_kernel_from_tree (self, deployment_dfd, &kernel_layout, cancellable, error)) return FALSE; _ostree_deployment_set_bootcsum (new_deployment, kernel_layout->bootcsum); - _ostree_deployment_set_bootconfig_from_kargs (new_deployment, override_kernel_argv); + _ostree_deployment_set_bootconfig_from_kargs (new_deployment, opts ? opts->override_kernel_argv : NULL); + _ostree_deployment_set_overlay_initrds (new_deployment, opts ? opts->overlay_initrds : NULL); if (!prepare_deployment_etc (self, repo, new_deployment, deployment_dfd, cancellable, error)) @@ -2847,6 +2904,53 @@ sysroot_finalize_deployment (OstreeSysroot *self, return TRUE; } +/** + * ostree_sysroot_deploy_tree_with_options: + * @self: Sysroot + * @osname: (allow-none): osname to use for merge deployment + * @revision: Checksum to add + * @origin: (allow-none): Origin to use for upgrades + * @provided_merge_deployment: (allow-none): Use this deployment for merge path + * @opts: (allow-none): Options + * @out_new_deployment: (out): The new deployment path + * @cancellable: Cancellable + * @error: Error + * + * Check out deployment tree with revision @revision, performing a 3 + * way merge with @provided_merge_deployment for configuration. + * + * When booted into the sysroot, you should use the + * ostree_sysroot_stage_tree() API instead. + * + * Since: 2020.7 + */ +gboolean +ostree_sysroot_deploy_tree_with_options (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *provided_merge_deployment, + OstreeSysrootDeployTreeOpts *opts, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error) +{ + if (!_ostree_sysroot_ensure_writable (self, error)) + return FALSE; + + g_autoptr(OstreeDeployment) deployment = NULL; + if (!sysroot_initialize_deployment (self, osname, revision, origin, opts, + &deployment, cancellable, error)) + return FALSE; + + if (!sysroot_finalize_deployment (self, deployment, provided_merge_deployment, + cancellable, error)) + return FALSE; + + *out_new_deployment = g_steal_pointer (&deployment); + return TRUE; +} + /** * ostree_sysroot_deploy_tree: * @self: Sysroot @@ -2859,11 +2963,9 @@ sysroot_finalize_deployment (OstreeSysroot *self, * @cancellable: Cancellable * @error: Error * - * Check out deployment tree with revision @revision, performing a 3 - * way merge with @provided_merge_deployment for configuration. + * Older version of ostree_sysroot_stage_tree_with_options(). * - * When booted into the sysroot, you should use the - * ostree_sysroot_stage_tree() API instead. + * Since: 2018.5 */ gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self, @@ -2876,20 +2978,10 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - if (!_ostree_sysroot_ensure_writable (self, error)) - return FALSE; - - g_autoptr(OstreeDeployment) deployment = NULL; - if (!sysroot_initialize_deployment (self, osname, revision, origin, override_kernel_argv, - &deployment, cancellable, error)) - return FALSE; - - if (!sysroot_finalize_deployment (self, deployment, provided_merge_deployment, - cancellable, error)) - return FALSE; - - *out_new_deployment = g_steal_pointer (&deployment); - return TRUE; + OstreeSysrootDeployTreeOpts opts = { .override_kernel_argv = override_kernel_argv }; + return ostree_sysroot_deploy_tree_with_options (self, osname, revision, origin, + provided_merge_deployment, &opts, + out_new_deployment, cancellable, error); } /* Serialize information about a deployment to a variant, used by the staging @@ -2951,6 +3043,63 @@ _ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, } +/** + * ostree_sysroot_stage_overlay_initrd: + * @self: Sysroot + * @fd: (transfer none): File descriptor to overlay initrd + * @out_checksum: (out) (transfer full): Overlay initrd checksum + * @cancellable: Cancellable + * @error: Error + * + * Stage an overlay initrd to be used in an upcoming deployment. Returns a checksum which + * can be passed to ostree_sysroot_deploy_tree_with_options() or + * ostree_sysroot_stage_tree_with_options() via the `overlay_initrds` array option. + * + * Since: 2020.7 + */ +gboolean +ostree_sysroot_stage_overlay_initrd (OstreeSysroot *self, + int fd, + char **out_checksum, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (fd != -1, FALSE); + g_return_val_if_fail (out_checksum != NULL, FALSE); + + if (!glnx_shutil_mkdir_p_at (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_INITRDS_DIR, + 0755, cancellable, error)) + return FALSE; + + glnx_autofd int staged_initrds_dfd = -1; + if (!glnx_opendirat (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_INITRDS_DIR, FALSE, + &staged_initrds_dfd, error)) + return FALSE; + + g_auto(GLnxTmpfile) overlay_initrd = { 0, }; + if (!glnx_open_tmpfile_linkable_at (staged_initrds_dfd, ".", O_WRONLY | O_CLOEXEC, + &overlay_initrd, error)) + return FALSE; + + char checksum[_OSTREE_SHA256_STRING_LEN+1]; + { + g_autoptr(GOutputStream) output = g_unix_output_stream_new (overlay_initrd.fd, FALSE); + g_autoptr(GInputStream) input = g_unix_input_stream_new (fd, FALSE); + g_autofree guchar *digest = NULL; + if (!ot_gio_splice_get_checksum (output, input, &digest, cancellable, error)) + return FALSE; + ot_bin2hex (checksum, (guint8*)digest, _OSTREE_SHA256_DIGEST_LEN); + } + + if (!glnx_link_tmpfile_at (&overlay_initrd, GLNX_LINK_TMPFILE_REPLACE, + staged_initrds_dfd, checksum, error)) + return FALSE; + + *out_checksum = g_strdup (checksum); + return TRUE; +} + + /** * ostree_sysroot_stage_tree: * @self: Sysroot @@ -2963,8 +3112,7 @@ _ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, * @cancellable: Cancellable * @error: Error * - * Like ostree_sysroot_deploy_tree(), but "finalization" only occurs at OS - * shutdown time. + * Older version of ostree_sysroot_stage_tree_with_options(). * * Since: 2018.5 */ @@ -2978,6 +3126,41 @@ ostree_sysroot_stage_tree (OstreeSysroot *self, OstreeDeployment **out_new_deployment, GCancellable *cancellable, GError **error) +{ + OstreeSysrootDeployTreeOpts opts = { .override_kernel_argv = override_kernel_argv }; + return ostree_sysroot_stage_tree_with_options (self, osname, revision, origin, + merge_deployment, &opts, + out_new_deployment, cancellable, error); +} + + +/** + * ostree_sysroot_stage_tree_with_options: + * @self: Sysroot + * @osname: (allow-none): osname to use for merge deployment + * @revision: Checksum to add + * @origin: (allow-none): Origin to use for upgrades + * @merge_deployment: (allow-none): Use this deployment for merge path + * @opts: Options + * @out_new_deployment: (out): The new deployment path + * @cancellable: Cancellable + * @error: Error + * + * Like ostree_sysroot_deploy_tree(), but "finalization" only occurs at OS + * shutdown time. + * + * Since: 2020.7 + */ +gboolean +ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *merge_deployment, + OstreeSysrootDeployTreeOpts *opts, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error) { if (!_ostree_sysroot_ensure_writable (self, error)) return FALSE; @@ -3009,8 +3192,8 @@ ostree_sysroot_stage_tree (OstreeSysroot *self, } /* OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH */ g_autoptr(OstreeDeployment) deployment = NULL; - if (!sysroot_initialize_deployment (self, osname, revision, origin, override_kernel_argv, - &deployment, cancellable, error)) + if (!sysroot_initialize_deployment (self, osname, revision, origin, opts, &deployment, + cancellable, error)) return FALSE; /* Write out the origin file using the sepolicy from the non-merged root for @@ -3045,9 +3228,12 @@ ostree_sysroot_stage_tree (OstreeSysroot *self, g_variant_builder_add (builder, "{sv}", "merge-deployment", serialize_deployment_to_variant (merge_deployment)); - if (override_kernel_argv) + if (opts && opts->override_kernel_argv) g_variant_builder_add (builder, "{sv}", "kargs", - g_variant_new_strv ((const char *const*)override_kernel_argv, -1)); + g_variant_new_strv ((const char *const*)opts->override_kernel_argv, -1)); + if (opts && opts->overlay_initrds) + g_variant_builder_add (builder, "{sv}", "overlay-initrds", + g_variant_new_strv ((const char *const*)opts->overlay_initrds, -1)); const char *parent = dirname (strdupa (_OSTREE_SYSROOT_RUNSTATE_STAGED)); if (!glnx_shutil_mkdir_p_at (AT_FDCWD, parent, 0755, cancellable, error)) diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index fa1e5336..318b0b19 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -38,6 +38,7 @@ typedef enum { /* This is a temporary flag until we fully drop the explicit `systemctl start * ostree-finalize-staged.service` so that tests can exercise the new path unit. */ OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH = 1 << 3, + OSTREE_SYSROOT_DEBUG_TEST_NO_DTB = 1 << 4, /* https://github.com/ostreedev/ostree/issues/2154 */ } OstreeSysrootDebugFlags; typedef enum { @@ -83,10 +84,14 @@ struct OstreeSysroot { /* We keep some transient state in /run */ #define _OSTREE_SYSROOT_RUNSTATE_STAGED "/run/ostree/staged-deployment" #define _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED "/run/ostree/staged-deployment-locked" +#define _OSTREE_SYSROOT_RUNSTATE_STAGED_INITRDS_DIR "/run/ostree/staged-initrds/" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_DIR "/run/ostree/deployment-state/" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT "unlocked-development" #define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_TRANSIENT "unlocked-transient" +#define _OSTREE_SYSROOT_BOOT_INITRAMFS_OVERLAYS "ostree/initramfs-overlays" +#define _OSTREE_SYSROOT_INITRAMFS_OVERLAYS "boot/" _OSTREE_SYSROOT_BOOT_INITRAMFS_OVERLAYS + gboolean _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error); diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index b211fea7..e0813b55 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -190,6 +190,7 @@ ostree_sysroot_init (OstreeSysroot *self) { "test-fifreeze", OSTREE_SYSROOT_DEBUG_TEST_FIFREEZE }, { "no-xattrs", OSTREE_SYSROOT_DEBUG_NO_XATTRS }, { "test-staged-path", OSTREE_SYSROOT_DEBUG_TEST_STAGED_PATH }, + { "no-dtb", OSTREE_SYSROOT_DEBUG_TEST_NO_DTB }, }; self->debug_flags = g_parse_debug_string (g_getenv ("OSTREE_SYSROOT_DEBUG"), @@ -814,6 +815,24 @@ list_deployments_process_one_boot_entry (OstreeSysroot *self, return FALSE; ostree_deployment_set_bootconfig (deployment, config); + char **overlay_initrds = ostree_bootconfig_parser_get_overlay_initrds (config); + g_autoptr(GPtrArray) initrds_chksums = NULL; + for (char **it = overlay_initrds; it && *it; it++) + { + const char *basename = glnx_basename (*it); + if (strlen (basename) != (_OSTREE_SHA256_STRING_LEN + strlen (".img"))) + return glnx_throw (error, "Malformed overlay initrd filename: %s", basename); + + if (!initrds_chksums) /* lazy init */ + initrds_chksums = g_ptr_array_new_full (g_strv_length (overlay_initrds), g_free); + g_ptr_array_add (initrds_chksums, g_strndup (basename, _OSTREE_SHA256_STRING_LEN)); + } + + if (initrds_chksums) + { + g_ptr_array_add (initrds_chksums, NULL); + _ostree_deployment_set_overlay_initrds (deployment, (char**)initrds_chksums->pdata); + } g_ptr_array_add (inout_deployments, g_object_ref (deployment)); return TRUE; @@ -966,8 +985,10 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, /* Parse it */ g_autoptr(GVariant) target = NULL; g_autofree char **kargs = NULL; + g_autofree char **overlay_initrds = NULL; g_variant_dict_lookup (staged_deployment_dict, "target", "@a{sv}", &target); g_variant_dict_lookup (staged_deployment_dict, "kargs", "^a&s", &kargs); + g_variant_dict_lookup (staged_deployment_dict, "overlay-initrds", "^a&s", &overlay_initrds); if (target) { g_autoptr(OstreeDeployment) staged = @@ -979,6 +1000,8 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, if (!load_origin (self, staged, NULL, error)) return FALSE; + _ostree_deployment_set_overlay_initrds (staged, overlay_initrds); + self->staged_deployment = g_steal_pointer (&staged); self->staged_deployment_data = g_steal_pointer (&staged_deployment_data); /* We set this flag for ostree_deployment_is_staged() because that API diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index d9f5a546..3a3b6a77 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -186,6 +186,21 @@ gboolean ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_sysroot_stage_overlay_initrd (OstreeSysroot *self, + int fd, + char **out_checksum, + GCancellable *cancellable, + GError **error); + +typedef struct { + gboolean unused_bools[8]; + int unused_ints[8]; + char **override_kernel_argv; + char **overlay_initrds; + gpointer unused_ptrs[6]; +} OstreeSysrootDeployTreeOpts; + _OSTREE_PUBLIC gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self, const char *osname, @@ -197,6 +212,17 @@ gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_sysroot_deploy_tree_with_options (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *provided_merge_deployment, + OstreeSysrootDeployTreeOpts *opts, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC gboolean ostree_sysroot_stage_tree (OstreeSysroot *self, const char *osname, @@ -208,6 +234,18 @@ gboolean ostree_sysroot_stage_tree (OstreeSysroot *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, + const char *osname, + const char *revision, + GKeyFile *origin, + OstreeDeployment *merge_deployment, + OstreeSysrootDeployTreeOpts *opts, + OstreeDeployment **out_new_deployment, + GCancellable *cancellable, + GError **error); + + _OSTREE_PUBLIC gboolean ostree_sysroot_deployment_set_mutable (OstreeSysroot *self, OstreeDeployment *deployment, diff --git a/src/libostree/ostree-version.h b/src/libostree/ostree-version.h index b2b3ec73..90e96ea9 100644 --- a/src/libostree/ostree-version.h +++ b/src/libostree/ostree-version.h @@ -43,7 +43,7 @@ * * Since: 2017.4 */ -#define OSTREE_RELEASE_VERSION (6) +#define OSTREE_RELEASE_VERSION (7) /** * OSTREE_VERSION @@ -52,7 +52,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION (2020.6) +#define OSTREE_VERSION (2020.7) /** * OSTREE_VERSION_S: @@ -62,7 +62,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION_S "2020.6" +#define OSTREE_VERSION_S "2020.7" #define OSTREE_ENCODE_VERSION(year,release) \ ((year) << 16 | (release)) diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c index 66767368..26e0280a 100644 --- a/src/libotutil/ot-checksum-utils.c +++ b/src/libotutil/ot-checksum-utils.c @@ -275,3 +275,13 @@ ot_checksum_file_at (int dfd, ot_checksum_get_hexdigest (&checksum, hexdigest, sizeof (hexdigest)); return g_strdup (hexdigest); } + +void +ot_checksum_bytes (GBytes *data, + guint8 out_digest[_OSTREE_SHA256_DIGEST_LEN]) +{ + g_auto(OtChecksum) hasher = { 0, }; + ot_checksum_init (&hasher); + ot_checksum_update_bytes (&hasher, data); + ot_checksum_get_digest (&hasher, out_digest, _OSTREE_SHA256_DIGEST_LEN); +} diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h index 411ef25d..5432c81e 100644 --- a/src/libotutil/ot-checksum-utils.h +++ b/src/libotutil/ot-checksum-utils.h @@ -96,4 +96,7 @@ char * ot_checksum_file_at (int dfd, GCancellable *cancellable, GError **error); +void ot_checksum_bytes (GBytes *data, + guint8 out_digest[_OSTREE_SHA256_DIGEST_LEN]); + G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index cd312365..7db7270d 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -52,6 +52,31 @@ #define ot_journal_print(...) {} #endif +typedef GMainContext GMainContextPopDefault; +static inline void +_ostree_main_context_pop_default_destroy (void *p) +{ + GMainContext *main_context = p; + + if (main_context) + { + g_main_context_pop_thread_default (main_context); + g_main_context_unref (main_context); + } +} + +static inline GMainContextPopDefault * +_ostree_main_context_new_default (void) +{ + GMainContext *main_context = g_main_context_new (); + + g_main_context_push_thread_default (main_context); + return main_context; +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GMainContextPopDefault, _ostree_main_context_pop_default_destroy) + + #include #include #include diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index bcece3f6..8156cc15 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -44,6 +44,7 @@ static gboolean opt_kernel_proc_cmdline; static char *opt_osname; static char *opt_origin_path; static gboolean opt_kernel_arg_none; +static char **opt_overlay_initrds; static GOptionEntry options[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, @@ -59,6 +60,7 @@ static GOptionEntry options[] = { { "karg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv, "Set kernel argument, like root=/dev/sda1; this overrides any earlier argument with the same name", "NAME=VALUE" }, { "karg-append", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv_append, "Append kernel argument; useful with e.g. console= that can be used multiple times", "NAME=VALUE" }, { "karg-none", 0, 0, G_OPTION_ARG_NONE, &opt_kernel_arg_none, "Do not import kernel arguments", NULL }, + { "overlay-initrd", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_overlay_initrds, "Overlay iniramfs file", "FILE" }, { NULL } }; @@ -167,24 +169,76 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); } - g_autoptr(OstreeDeployment) new_deployment = NULL; + g_autoptr(GPtrArray) overlay_initrd_chksums = NULL; + for (char **it = opt_overlay_initrds; it && *it; it++) + { + const char *path = *it; + + glnx_autofd int fd = -1; + if (!glnx_openat_rdonly (AT_FDCWD, path, TRUE, &fd, error)) + return FALSE; + + g_autofree char *chksum = NULL; + if (!ostree_sysroot_stage_overlay_initrd (sysroot, fd, &chksum, cancellable, error)) + return FALSE; + + if (!overlay_initrd_chksums) + overlay_initrd_chksums = g_ptr_array_new_full (g_strv_length (opt_overlay_initrds), g_free); + g_ptr_array_add (overlay_initrd_chksums, g_steal_pointer (&chksum)); + } + + if (overlay_initrd_chksums) + g_ptr_array_add (overlay_initrd_chksums, NULL); + g_auto(GStrv) kargs_strv = kargs ? ostree_kernel_args_to_strv (kargs) : NULL; + + OstreeSysrootDeployTreeOpts opts = { + .override_kernel_argv = kargs_strv, + .overlay_initrds = overlay_initrd_chksums ? (char**)overlay_initrd_chksums->pdata : NULL, + }; + + g_autoptr(OstreeDeployment) new_deployment = NULL; if (opt_stage) { if (opt_retain_pending || opt_retain_rollback) return glnx_throw (error, "--stage cannot currently be combined with --retain arguments"); if (opt_not_as_default) return glnx_throw (error, "--stage cannot currently be combined with --not-as-default"); - if (!ostree_sysroot_stage_tree (sysroot, opt_osname, revision, origin, merge_deployment, - kargs_strv, &new_deployment, cancellable, error)) - return FALSE; + /* use old API if we can to exercise it in CI */ + if (!overlay_initrd_chksums) + { + if (!ostree_sysroot_stage_tree (sysroot, opt_osname, revision, origin, + merge_deployment, kargs_strv, &new_deployment, + cancellable, error)) + return FALSE; + } + else + { + if (!ostree_sysroot_stage_tree_with_options (sysroot, opt_osname, revision, + origin, merge_deployment, &opts, + &new_deployment, cancellable, error)) + return FALSE; + } g_assert (new_deployment); } else { - if (!ostree_sysroot_deploy_tree (sysroot, opt_osname, revision, origin, merge_deployment, - kargs_strv, &new_deployment, cancellable, error)) - return FALSE; + /* use old API if we can to exercise it in CI */ + if (!overlay_initrd_chksums) + { + if (!ostree_sysroot_deploy_tree (sysroot, opt_osname, revision, origin, + merge_deployment, kargs_strv, &new_deployment, + cancellable, error)) + return FALSE; + } + else + { + if (!ostree_sysroot_deploy_tree_with_options (sysroot, opt_osname, revision, + origin, merge_deployment, &opts, + &new_deployment, cancellable, + error)) + return FALSE; + } g_assert (new_deployment); OstreeSysrootSimpleWriteDeploymentFlags flags = OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN; diff --git a/src/ostree/ot-admin-builtin-set-origin.c b/src/ostree/ot-admin-builtin-set-origin.c index 9d96512e..4dc68a00 100644 --- a/src/ostree/ot-admin-builtin-set-origin.c +++ b/src/ostree/ot-admin-builtin-set-origin.c @@ -95,7 +95,7 @@ ot_admin_builtin_set_origin (int argc, char **argv, OstreeCommandInvocation *inv { char **iter; g_autoptr(GVariantBuilder) optbuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); - g_autoptr(GVariant) options = NULL; + g_autoptr(GVariant) remote_options = NULL; for (iter = opt_set; iter && *iter; iter++) { @@ -110,12 +110,12 @@ ot_admin_builtin_set_origin (int argc, char **argv, OstreeCommandInvocation *inv subkey, g_variant_new_variant (g_variant_new_string (subvalue))); } - options = g_variant_ref_sink (g_variant_builder_end (optbuilder)); + remote_options = g_variant_ref_sink (g_variant_builder_end (optbuilder)); if (!ostree_repo_remote_change (repo, NULL, OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS, remotename, url, - options, + remote_options, cancellable, error)) goto out; } diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index 813dbb9e..fe9558c8 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -84,7 +84,7 @@ static GOptionEntry options[] = { { "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" }, { "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" }, { "require-hardlinks", 'H', 0, G_OPTION_ARG_NONE, &opt_require_hardlinks, "Do not fall back to full copies if hardlinking fails", NULL }, - { "force-copy-zerosized", 'z', 0, G_OPTION_ARG_NONE, &opt_force_copy_zerosized, "Do not hardlink zero-sized files", NULL }, + { "force-copy-zerosized", 'z', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_force_copy_zerosized, "Do not hardlink zero-sized files", NULL }, { "force-copy", 'C', 0, G_OPTION_ARG_NONE, &opt_force_copy, "Never hardlink (but may reflink if available)", NULL }, { "bareuseronly-dirs", 'M', 0, G_OPTION_ARG_NONE, &opt_bareuseronly_dirs, "Suppress mode bits outside of 0775 for directories (suid, world writable, etc.)", NULL }, { "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "FILE" }, @@ -135,14 +135,14 @@ process_one_checkout (OstreeRepo *repo, opt_bareuseronly_dirs || opt_union_identical || opt_skiplist_file || opt_selinux_policy || opt_selinux_prefix) { - OstreeRepoCheckoutAtOptions options = { 0, }; + OstreeRepoCheckoutAtOptions checkout_options = { 0, }; /* do this early so option checking also catches force copy conflicts */ if (opt_selinux_policy) opt_force_copy = TRUE; if (opt_user_mode) - options.mode = OSTREE_REPO_CHECKOUT_MODE_USER; + checkout_options.mode = OSTREE_REPO_CHECKOUT_MODE_USER; /* Can't union these */ if (opt_union && opt_union_add) { @@ -173,9 +173,9 @@ process_one_checkout (OstreeRepo *repo, goto out; } else if (opt_union) - options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; + checkout_options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; else if (opt_union_add) - options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES; + checkout_options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES; else if (opt_union_identical) { if (!opt_require_hardlinks) @@ -184,12 +184,12 @@ process_one_checkout (OstreeRepo *repo, "--union-identical requires --require-hardlinks"); goto out; } - options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL; + checkout_options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL; } if (opt_whiteouts) - options.process_whiteouts = TRUE; + checkout_options.process_whiteouts = TRUE; if (subpath) - options.subpath = subpath; + checkout_options.subpath = subpath; g_autoptr(OstreeSePolicy) policy = NULL; if (opt_selinux_policy) @@ -203,8 +203,8 @@ process_one_checkout (OstreeRepo *repo, policy = ostree_sepolicy_new_at (rootfs_dfd, cancellable, error); if (!policy) goto out; - options.sepolicy = policy; - options.sepolicy_prefix = opt_selinux_prefix; + checkout_options.sepolicy = policy; + checkout_options.sepolicy_prefix = opt_selinux_prefix; } g_autoptr(GHashTable) skip_list = @@ -214,16 +214,16 @@ process_one_checkout (OstreeRepo *repo, if (!ot_parse_file_by_line (opt_skiplist_file, handle_skiplist_line, skip_list, cancellable, error)) goto out; - options.filter = checkout_filter; - options.filter_user_data = skip_list; + checkout_options.filter = checkout_filter; + checkout_options.filter_user_data = skip_list; } - options.no_copy_fallback = opt_require_hardlinks; - options.force_copy = opt_force_copy; - options.force_copy_zerosized = opt_force_copy_zerosized; - options.bareuseronly_dirs = opt_bareuseronly_dirs; + checkout_options.no_copy_fallback = opt_require_hardlinks; + checkout_options.force_copy = opt_force_copy; + checkout_options.force_copy_zerosized = opt_force_copy_zerosized; + checkout_options.bareuseronly_dirs = opt_bareuseronly_dirs; - if (!ostree_repo_checkout_at (repo, &options, + if (!ostree_repo_checkout_at (repo, &checkout_options, AT_FDCWD, destination, resolved_commit, cancellable, error)) diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index e2fcf103..48fa2928 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -614,10 +614,10 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio if (opt_base) { g_autofree char *base_commit = NULL; - g_autoptr(GFile) root = NULL; - if (!ostree_repo_read_commit (repo, opt_base, &root, &base_commit, cancellable, error)) + g_autoptr(GFile) base_root = NULL; + if (!ostree_repo_read_commit (repo, opt_base, &base_root, &base_commit, cancellable, error)) goto out; - OstreeRepoFile *rootf = (OstreeRepoFile*) root; + OstreeRepoFile *rootf = (OstreeRepoFile*) base_root; mtree = ostree_mutable_tree_new_from_checksum (repo, ostree_repo_file_tree_get_contents_checksum (rootf), diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index 811a8381..64e434aa 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -134,7 +134,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio else if (!strcmp (op, "get")) { GKeyFile *readonly_config = NULL; - g_autofree char *value = NULL; + g_autofree char *read_value = NULL; if (opt_group) { if (argc < 3) @@ -160,11 +160,11 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio } readonly_config = ostree_repo_get_config (repo); - value = g_key_file_get_string (readonly_config, section, key, error); - if (value == NULL) + read_value = g_key_file_get_string (readonly_config, section, key, error); + if (read_value == NULL) return FALSE; - g_print ("%s\n", value); + g_print ("%s\n", read_value); } else if (!strcmp (op, "unset")) { diff --git a/src/ostree/ot-builtin-gpg-sign.c b/src/ostree/ot-builtin-gpg-sign.c index 6babbf22..bde9180a 100644 --- a/src/ostree/ot-builtin-gpg-sign.c +++ b/src/ostree/ot-builtin-gpg-sign.c @@ -171,9 +171,8 @@ delete_signatures (OstreeRepo *repo, while (!g_queue_is_empty (&signatures)) { - GVariant *child = g_queue_pop_head (&signatures); - g_variant_builder_add_value (&signature_builder, child); - g_variant_unref (child); + g_autoptr(GVariant) sigchild = g_queue_pop_head (&signatures); + g_variant_builder_add_value (&signature_builder, sigchild); } g_variant_dict_insert_value (&metadata_dict, diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index e69d62e3..ed0ec556 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -271,7 +271,7 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation, { GVariantBuilder builder; - g_autoptr(GVariant) options = NULL; + g_autoptr(GVariant) pull_options = NULL; g_auto(GLnxConsoleRef) console = { 0, }; g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); @@ -378,9 +378,9 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation, #endif /* OSTREE_DISABLE_GPGME */ } - options = g_variant_ref_sink (g_variant_builder_end (&builder)); + pull_options = g_variant_ref_sink (g_variant_builder_end (&builder)); - if (!ostree_repo_pull_with_options (repo, remote, options, + if (!ostree_repo_pull_with_options (repo, remote, pull_options, progress, cancellable, error)) goto out; diff --git a/src/ostree/ot-builtin-sign.c b/src/ostree/ot-builtin-sign.c index c7777489..2f90acd1 100644 --- a/src/ostree/ot-builtin-sign.c +++ b/src/ostree/ot-builtin-sign.c @@ -167,7 +167,7 @@ ostree_builtin_sign (int argc, char **argv, OstreeCommandInvocation *invocation, if ((n_key_ids == 0) || opt_filename) { g_autoptr (GVariantBuilder) builder = NULL; - g_autoptr (GVariant) options = NULL; + g_autoptr (GVariant) sign_options = NULL; builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); /* Use custom directory with public and revoked keys instead of system-wide directories */ @@ -176,9 +176,9 @@ ostree_builtin_sign (int argc, char **argv, OstreeCommandInvocation *invocation, /* The last chance for verification source -- system files */ if (opt_filename) g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (opt_filename)); - options = g_variant_builder_end (builder); + sign_options = g_variant_builder_end (builder); - if (!ostree_sign_load_pk (sign, options, error)) + if (!ostree_sign_load_pk (sign, sign_options, error)) goto out; if (ostree_sign_commit_verify (sign, diff --git a/src/ostree/ot-builtin-static-delta.c b/src/ostree/ot-builtin-static-delta.c index 4f9ff2b2..3e0af5bd 100644 --- a/src/ostree/ot-builtin-static-delta.c +++ b/src/ostree/ot-builtin-static-delta.c @@ -40,6 +40,10 @@ static gboolean opt_swap_endianness; static gboolean opt_inline; static gboolean opt_disable_bsdiff; static gboolean opt_if_not_exists; +static char **opt_key_ids; +static char *opt_sign_name; +static char *opt_keysfilename; +static char *opt_keysdir; #define BUILTINPROTO(name) static gboolean ot_static_delta_builtin_ ## name (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) @@ -48,6 +52,7 @@ BUILTINPROTO(show); BUILTINPROTO(delete); BUILTINPROTO(generate); BUILTINPROTO(apply_offline); +BUILTINPROTO(verify); #undef BUILTINPROTO @@ -67,6 +72,9 @@ static OstreeCommand static_delta_subcommands[] = { { "apply-offline", OSTREE_BUILTIN_FLAG_NONE, ot_static_delta_builtin_apply_offline, "Apply static delta file" }, + { "verify", OSTREE_BUILTIN_FLAG_NONE, + ot_static_delta_builtin_verify, + "Verify static delta signatures" }, { NULL, 0, NULL, NULL } }; @@ -88,10 +96,20 @@ static GOptionEntry generate_options[] = { { "max-bsdiff-size", 0, 0, G_OPTION_ARG_STRING, &opt_max_bsdiff_size, "Maximum size in megabytes to consider bsdiff compression for input files", NULL}, { "max-chunk-size", 0, 0, G_OPTION_ARG_STRING, &opt_max_chunk_size, "Maximum size of delta chunks in megabytes", NULL}, { "filename", 0, 0, G_OPTION_ARG_FILENAME, &opt_filename, "Write the delta content to PATH (a directory). If not specified, the OSTree repository is used", "PATH"}, + { "sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "Sign the delta with", "KEY_ID"}, + { "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"}, +#if defined(HAVE_LIBSODIUM) + { "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME"}, +#endif { NULL } }; static GOptionEntry apply_offline_options[] = { + { "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"}, +#if defined(HAVE_LIBSODIUM) + { "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME"}, + { "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir, "Redefine system-wide directories with public and revoked keys for verification", "NAME"}, +#endif { NULL } }; @@ -99,6 +117,15 @@ static GOptionEntry list_options[] = { { NULL } }; +static GOptionEntry verify_options[] = { + { "sign-type", 0, 0, G_OPTION_ARG_STRING, &opt_sign_name, "Signature type to use (defaults to 'ed25519')", "NAME"}, +#if defined(HAVE_LIBSODIUM) + { "keys-file", 0, 0, G_OPTION_ARG_STRING, &opt_keysfilename, "Read key(s) from file", "NAME"}, + { "keys-dir", 0, 0, G_OPTION_ARG_STRING, &opt_keysdir, "Redefine system-wide directories with public and revoked keys for verification", "NAME"}, +#endif + { NULL } +}; + static void static_delta_usage (char **argv, gboolean is_error) @@ -326,6 +353,60 @@ ot_static_delta_builtin_generate (int argc, char **argv, OstreeCommandInvocation if (opt_endianness || opt_swap_endianness) g_variant_builder_add (parambuilder, "{sv}", "endianness", g_variant_new_uint32 (endianness)); + if (opt_key_ids || opt_keysfilename) + { + g_autoptr(GPtrArray) key_ids = g_ptr_array_new (); + + for (char **iter = opt_key_ids; iter != NULL && *iter != NULL; ++iter) + g_ptr_array_add (key_ids, *iter); + + if (opt_keysfilename) + { + g_autoptr (GFile) keyfile = NULL; + g_autoptr (GFileInputStream) key_stream_in = NULL; + g_autoptr (GDataInputStream) key_data_in = NULL; + + if (!g_file_test (opt_keysfilename, G_FILE_TEST_IS_REGULAR)) + { + g_warning ("Can't open file '%s' with keys", opt_keysfilename); + return glnx_throw (error, "File object '%s' is not a regular file", opt_keysfilename); + } + + keyfile = g_file_new_for_path (opt_keysfilename); + key_stream_in = g_file_read (keyfile, NULL, error); + if (key_stream_in == NULL) + return FALSE; + + key_data_in = g_data_input_stream_new (G_INPUT_STREAM(key_stream_in)); + g_assert (key_data_in != NULL); + + /* Use simple file format with just a list of base64 public keys per line */ + while (TRUE) + { + gsize len = 0; + g_autofree char *line = g_data_input_stream_read_line (key_data_in, &len, NULL, error); + g_autoptr (GVariant) sk = NULL; + + if (*error != NULL) + return FALSE; + + if (line == NULL) + break; + + // Pass the key as a string + g_ptr_array_add (key_ids, g_strdup (line)); + } + } + + g_autoptr(GVariant) key_ids_v = g_variant_new_strv ((const char *const *)key_ids->pdata, + key_ids->len); + g_variant_builder_add (parambuilder, "{s@v}", "sign-key-ids", + g_variant_new_variant (g_steal_pointer (&key_ids_v))); + } + opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519; + g_variant_builder_add (parambuilder, "{sv}", "sign-name", + g_variant_new_bytestring (opt_sign_name)); + g_print ("Generating static delta:\n"); g_print (" From: %s\n", from_resolved ? from_resolved : "empty"); g_print (" To: %s\n", to_resolved); @@ -347,6 +428,9 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvoc { g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; + g_autoptr (OstreeSign) sign = NULL; + char **key_ids; + int n_key_ids; context = g_option_context_new (""); if (!ostree_option_context_parse (context, apply_offline_options, &argc, &argv, invocation, &repo, cancellable, error)) @@ -362,13 +446,59 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvoc return FALSE; } +#if defined(HAVE_LIBSODIUM) + /* Initialize crypto system */ + opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519; +#endif + + if (opt_sign_name) + { + sign = ostree_sign_get_by_name (opt_sign_name, error); + if (!sign) + return glnx_throw (error, "Signing type %s is not supported", opt_sign_name); + + key_ids = argv + 3; + n_key_ids = argc - 3; + for (int i = 0; i < n_key_ids; i++) + { + g_autoptr (GVariant) pk = g_variant_new_string(key_ids[i]); + if (!ostree_sign_add_pk(sign, pk, error)) + return FALSE; + } + if ((n_key_ids == 0) || opt_keysfilename) + { + g_autoptr (GVariantBuilder) builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + g_autoptr (GVariant) options = NULL; + + /* Use custom directory with public and revoked keys instead of system-wide directories */ + if (opt_keysdir) + g_variant_builder_add (builder, "{sv}", "basedir", g_variant_new_string (opt_keysdir)); + /* The last chance for verification source -- system files */ + if (opt_keysfilename) + g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (opt_keysfilename)); + options = g_variant_builder_end (builder); + + if (!ostree_sign_load_pk (sign, options, error)) + { + /* If it fails to load system default public keys, consider there no signature engine */ + if (!opt_keysdir && !opt_keysfilename) + { + g_clear_error(error); + g_clear_object(&sign); + } + else + return FALSE; + } + } + } + const char *patharg = argv[2]; g_autoptr(GFile) path = g_file_new_for_path (patharg); if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) return FALSE; - if (!ostree_repo_static_delta_execute_offline (repo, path, FALSE, cancellable, error)) + if (!ostree_repo_static_delta_execute_offline_with_signature (repo, path, sign, FALSE, cancellable, error)) return FALSE; if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) @@ -377,6 +507,68 @@ ot_static_delta_builtin_apply_offline (int argc, char **argv, OstreeCommandInvoc return TRUE; } +static gboolean +ot_static_delta_builtin_verify (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) +{ + g_autoptr (GOptionContext) context = g_option_context_new ("STATIC-DELTA-FILE [KEY-ID...]"); + g_autoptr (OstreeRepo) repo = NULL; + gboolean verified; + char **key_ids; + int n_key_ids; + + if (!ostree_option_context_parse (context, verify_options, &argc, &argv, invocation, &repo, cancellable, error)) + return FALSE; + + if (argc < 3) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "DELTA must be specified"); + return FALSE; + } + + opt_sign_name = opt_sign_name ?: OSTREE_SIGN_NAME_ED25519; + + const char *delta_id = argv[2]; + + g_autoptr (OstreeSign) sign = ostree_sign_get_by_name (opt_sign_name, error); + if (!sign) + { + g_print("Sign-type not supported\n"); + return FALSE; + } + + key_ids = argv + 3; + n_key_ids = argc - 3; + for (int i = 0; i < n_key_ids; i++) + { + g_autoptr (GVariant) pk = g_variant_new_string(key_ids[i]); + if (!ostree_sign_add_pk(sign, pk, error)) + return FALSE; + } + if ((n_key_ids == 0) || opt_keysfilename) + { + g_autoptr (GVariantBuilder) builder = NULL; + g_autoptr (GVariant) options = NULL; + + builder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + /* Use custom directory with public and revoked keys instead of system-wide directories */ + if (opt_keysdir) + g_variant_builder_add (builder, "{sv}", "basedir", g_variant_new_string (opt_keysdir)); + /* The last chance for verification source -- system files */ + if (opt_keysfilename) + g_variant_builder_add (builder, "{sv}", "filename", g_variant_new_string (opt_keysfilename)); + options = g_variant_builder_end (builder); + + if (!ostree_sign_load_pk (sign, options, error)) + return FALSE; + } + + verified = ostree_repo_static_delta_verify_signature (repo, delta_id, sign, NULL, error); + g_print ("Verification %s\n", verified ? "OK" : "fails"); + + return verified; +} + gboolean ostree_builtin_static_delta (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) { diff --git a/src/ostree/ot-dump.c b/src/ostree/ot-dump.c index 225d1845..a8ed54a2 100644 --- a/src/ostree/ot-dump.c +++ b/src/ostree/ot-dump.c @@ -322,10 +322,11 @@ ot_dump_summary_bytes (GBytes *summary_bytes, collection_map = g_variant_lookup_value (exts, OSTREE_SUMMARY_COLLECTION_MAP, G_VARIANT_TYPE ("a{sa(s(taya{sv}))}")); if (collection_map != NULL) { + g_autoptr(GVariant) collection_refs = NULL; g_variant_iter_init (&iter, collection_map); - while (g_variant_iter_loop (&iter, "{&s@a(s(taya{sv}))}", &collection_id, &refs)) - dump_summary_refs (collection_id, refs); + while (g_variant_iter_loop (&iter, "{&s@a(s(taya{sv}))}", &collection_id, &collection_refs)) + dump_summary_refs (collection_id, collection_refs); } /* Print out the additional metadata. */ @@ -361,6 +362,22 @@ ot_dump_summary_bytes (GBytes *summary_bytes, pretty_key = "Collection Map"; value_str = g_strdup ("(printed above)"); } + else if (g_strcmp0 (key, OSTREE_SUMMARY_MODE) == 0) + { + OstreeRepoMode repo_mode; + const char *repo_mode_str = g_variant_get_string (value, NULL); + + pretty_key = "Repository Mode"; + if (!ostree_repo_mode_from_string (repo_mode_str, &repo_mode, NULL)) + value_str = g_strdup_printf ("Invalid (‘%s’)", repo_mode_str); + else + value_str = g_strdup (repo_mode_str); + } + else if (g_strcmp0 (key, OSTREE_SUMMARY_TOMBSTONE_COMMITS) == 0) + { + pretty_key = "Has Tombstone Commits"; + value_str = g_strdup (g_variant_get_boolean (value) ? "Yes" : "No"); + } else { value_str = g_variant_print (value, FALSE); diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index 172625d2..61539ec1 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -104,7 +104,6 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio g_autoptr(GString) sign_verify = NULL; const char *remote_name; const char *remote_url; - char **iter; g_autoptr(GVariantBuilder) optbuilder = NULL; g_autoptr(GVariant) options = NULL; gboolean ret = FALSE; @@ -161,7 +160,7 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio g_variant_builder_add (optbuilder, "{s@v}", "contenturl", g_variant_new_variant (g_variant_new_string (opt_contenturl))); - for (iter = opt_set; iter && *iter; iter++) + for (char **iter = opt_set; iter && *iter; iter++) { const char *keyvalue = *iter; g_autofree char *subkey = NULL; diff --git a/tests/basic-test.sh b/tests/basic-test.sh index fc193f4f..9227b0cd 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -750,15 +750,17 @@ rm files -rf && mkdir files touch files/anemptyfile touch files/anotheremptyfile $CMD_PREFIX ostree --repo=repo commit --consume -b tree-with-empty-files --tree=dir=files +$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} tree-with-empty-files tree-with-empty-files +if files_are_hardlinked tree-with-empty-files/an{,other}emptyfile; then + fatal "--force-copy-zerosized failed" +fi +# And pass the now-defunct -z option to validate it does nothing +rm tree-with-empty-files -rf $CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} -z tree-with-empty-files tree-with-empty-files if files_are_hardlinked tree-with-empty-files/an{,other}emptyfile; then fatal "--force-copy-zerosized failed" fi -rm tree-with-empty-files -rf -$CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} tree-with-empty-files tree-with-empty-files -assert_files_hardlinked tree-with-empty-files/an{,other}emptyfile -rm tree-with-empty-files -rf -echo "ok checkout --force-copy-zerosized" +echo "ok checkout zero sized files are not hardlinked" # These should merge, they're identical $CMD_PREFIX ostree --repo=repo checkout ${CHECKOUT_H_ARGS} --union-identical -z tree-with-empty-files tree-with-empty-files diff --git a/tests/libtest.sh b/tests/libtest.sh index ca457fa2..7c66a5c6 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -700,6 +700,12 @@ has_sign_ed25519 () { return ${ret} } +skip_without_sign_ed25519() { + if ! has_sign_ed25519; then + skip "no ed25519 support compiled in" + fi +} + # Keys for ed25519 signing tests ED25519PUBLIC= ED25519SEED= diff --git a/tests/repo-finder-mount.c b/tests/repo-finder-mount.c index 2cb1d230..3d068af7 100644 --- a/tests/repo-finder-mount.c +++ b/tests/repo-finder-mount.c @@ -93,16 +93,16 @@ main (int argc, char **argv) g_ptr_array_add (refs, NULL); /* NULL terminator */ - g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GAsyncResult) async_result = NULL; ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), (const OstreeCollectionRef * const *) refs->pdata, - parent_repo, NULL, result_cb, &result); + parent_repo, NULL, result_cb, &async_result); - while (result == NULL) + while (async_result == NULL) g_main_context_iteration (context, TRUE); g_autoptr(GPtrArray) results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), - result, &error); + async_result, &error); g_assert_no_error (error); /* Check that the results are correct: the invalid refs should have been diff --git a/tests/test-basic-user.sh b/tests/test-basic-user.sh index e56f828a..fa17beee 100755 --- a/tests/test-basic-user.sh +++ b/tests/test-basic-user.sh @@ -75,6 +75,8 @@ $OSTREE fsck rm test2-checkout -rf $OSTREE checkout -U -H test2-unreadable test2-checkout assert_file_has_mode test2-checkout/unreadable 400 +# Should not be hardlinked +assert_streq $(stat -c "%h" test2-checkout/unreadable) 1 echo "ok bare-user handled unreadable file" cd ${test_tmpdir} diff --git a/tests/test-delta-ed25519.sh b/tests/test-delta-ed25519.sh new file mode 100755 index 00000000..ef732cf9 --- /dev/null +++ b/tests/test-delta-ed25519.sh @@ -0,0 +1,322 @@ +#!/bin/bash +# +# Copyright (C) 2011,2013 Colin Walters +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +skip_without_user_xattrs + +skip_without_sign_ed25519 + +bindatafiles="bash true ostree" + +echo '1..12' + +mkdir repo +ostree_repo_init repo --mode=archive + +mkdir files +for bin in ${bindatafiles}; do + cp $(which ${bin}) files +done + +${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files + +function permuteFile() { + permutation=$(($1 % 2)) + output=$2 + case $permutation in + 0) dd if=/dev/zero count=40 bs=1 >> $output;; + 1) echo aheader | cat - $output >> $output.new && mv $output.new $output;; + esac +} + +function permuteDirectory() { + permutation=$1 + dir=$2 + for x in ${dir}/*; do + for z in $(seq ${permutation}); do + permuteFile ${z} ${x} + done + done +} + +get_assert_one_direntry_matching() { + local path=$1 + local r=$2 + local child="" + local bn + for p in ${path}/*; do + bn=$(basename $p) + if ! echo ${bn} | grep -q "$r"; then + continue + fi + if test -z "${child}"; then + child=${bn} + else + assert_not_reached "Expected only one child matching ${r} in ${path}"; + fi + done + if test -z "${child}"; then + assert_not_reached "Failed to find child matching ${r}" + fi + echo ${child} +} + +origrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test) + +permuteDirectory 1 files +${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files + +newrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test) + +# Test ostree sign with 'ed25519' module +gen_ed25519_keys +PUBLIC=${ED25519PUBLIC} +SEED=${ED25519SEED} +SECRET=${ED25519SECRET} +WRONG_PUBLIC="$(gen_ed25519_random_public)" + +SECRETKEYS="$(mktemp -p ${test_tmpdir} ed25519_XXXXXX.ed25519)" +echo ${SECRET} > ${SECRETKEYS} + +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-key-signed-1.txt +assert_file_has_content show-ed25519-key-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" "${WRONG_PUBLIC}" > show-ed25519-key-signed-2.txt +assert_file_has_content show-ed25519-key-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" "${PUBLIC}" > show-ed25519-key-signed-3.txt +assert_file_has_content show-ed25519-key-signed-3.txt "Verification OK" + +deltaprefix=$(get_assert_one_direntry_matching repo/deltas '.') +deltadir=$(get_assert_one_direntry_matching repo/deltas/${deltaprefix} '-') + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-key-inline-signed-1.txt +assert_file_has_content show-ed25519-key-inline-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" "${WRONG_PUBLIC}" > show-ed25519-key-inline-signed-2.txt +assert_file_has_content show-ed25519-key-inline-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" "${PUBLIC}" > show-ed25519-key-inline-signed-3.txt +assert_file_has_content show-ed25519-key-inline-signed-3.txt "Verification OK" + +echo 'ok verified with ed25519 (sign - key)' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-keyfile-signed-1.txt +assert_file_has_content show-ed25519-keyfile-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" "${WRONG_PUBLIC}" > show-ed25519-keyfile-signed-2.txt +assert_file_has_content show-ed25519-keyfile-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" "${PUBLIC}" > show-ed25519-keyfile-signed-3.txt +assert_file_has_content show-ed25519-keyfile-signed-3.txt "Verification OK" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-keyfile-inline-signed-1.txt +assert_file_has_content show-ed25519-keyfile-inline-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" "${WRONG_PUBLIC}" > show-ed25519-keyfile-inline-signed-2.txt +assert_file_has_content show-ed25519-keyfile-inline-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" "${PUBLIC}" > show-ed25519-keyfile-inline-signed-3.txt +assert_file_has_content show-ed25519-keyfile-inline-signed-3.txt "Verification OK" + +echo 'ok verified with ed25519 (keyfile - key)' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-key-bad-signed.txt && exit 1 +assert_file_has_content show-ed25519-key-bad-signed.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-key-bad-inline-signed.txt && exit 1 +assert_file_has_content show-ed25519-key-bad-inline-signed.txt "Verification fails" + +echo 'ok Verification fails with ed25519 (sign - bad key)' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-keyfile-bad-signed.txt && exit 1 +assert_file_has_content show-ed25519-keyfile-bad-signed.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-keyfile-bad-inline-signed.txt && exit 1 +assert_file_has_content show-ed25519-keyfile-bad-inline-signed.txt "Verification fails" + +echo 'ok Verification fails with ed25519 (keyfile - bad key)' + +# Prepare files with public ed25519 signatures +PUBKEYS="$(mktemp -p ${test_tmpdir} ed25519_XXXXXX.ed25519)" +for((i=0;i<100;i++)); do + # Generate a list with some public signatures + gen_ed25519_random_public +done > ${PUBKEYS} + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-bad-signed-1.txt && exit 1 +assert_file_has_content show-ed25519-file-bad-signed-1.txt "Verification fails" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-bad-signed-2.txt && exit 1 +assert_file_has_content show-ed25519-file-bad-signed-2.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-inline-bad-signed-1.txt && exit 1 +assert_file_has_content show-ed25519-file-inline-bad-signed-1.txt "Verification fails" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-inline-bad-signed-2.txt && exit 1 +assert_file_has_content show-ed25519-file-inline-bad-signed-2.txt "Verification fails" + +echo 'ok Verification fails with ed25519 (sign - bad keys)' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-bad-signed-3.txt && exit 1 +assert_file_has_content show-ed25519-file-bad-signed-3.txt "Verification fails" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-bad-signed-4.txt && exit 1 +assert_file_has_content show-ed25519-file-bad-signed-4.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-inline-bad-signed-3.txt && exit 1 +assert_file_has_content show-ed25519-file-inline-bad-signed-3.txt "Verification fails" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-inline-bad-signed-4.txt && exit 1 +assert_file_has_content show-ed25519-file-inline-bad-signed-4.txt "Verification fails" + +echo 'ok Verification fails with ed25519 (keyfile - bad keys)' + +# Add correct key into the list +echo ${PUBLIC} >> ${PUBKEYS} + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-signed-1.txt +assert_file_has_content show-ed25519-file-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-signed-2.txt +assert_file_has_content show-ed25519-file-signed-2.txt "Verification OK" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --sign=${SECRET} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-inline-signed-1.txt +assert_file_has_content show-ed25519-file-inline-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-inline-signed-2.txt +assert_file_has_content show-ed25519-file-inline-signed-2.txt "Verification OK" + +echo 'ok verified with ed25519 (sign - file)' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-signed-3.txt +assert_file_has_content show-ed25519-file-signed-3.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-signed-4.txt +assert_file_has_content show-ed25519-file-signed-4.txt "Verification OK" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-file-inline-signed-3.txt +assert_file_has_content show-ed25519-file-inline-signed-3.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-file-inline-signed-4.txt +assert_file_has_content show-ed25519-file-inline-signed-4.txt "Verification OK" + +echo 'ok verified with ed25519 (keyfile - file)' + +# Test ostree sign with multiple 'ed25519' keys +gen_ed25519_keys +PUBLIC2=${ED25519PUBLIC} +SEED2=${ED25519SEED} +SECRET2=${ED25519SECRET} + +echo ${SECRET2} >> ${SECRETKEYS} +echo ${PUBLIC2} >> ${PUBKEYS} + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-multiplekeys-signed-1.txt +assert_file_has_content show-ed25519-multiplekeys-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC2}" > show-ed25519-multiplekeys-signed-2.txt +assert_file_has_content show-ed25519-multiplekeys-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-multiplekeys-bad-signed.txt && exit 1 +assert_file_has_content show-ed25519-multiplekeys-bad-signed.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-multiplekeys-signed-3.txt +assert_file_has_content show-ed25519-multiplekeys-signed-3.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-multiplekeys-signed-4.txt +assert_file_has_content show-ed25519-multiplekeys-signed-4.txt "Verification OK" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC}" > show-ed25519-multiplekeys-inline-signed-1.txt +assert_file_has_content show-ed25519-multiplekeys-inline-signed-1.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${PUBLIC2}" > show-ed25519-multiplekeys-inline-signed-2.txt +assert_file_has_content show-ed25519-multiplekeys-inline-signed-2.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} "${WRONG_PUBLIC}" > show-ed25519-multiplekeys-bad-inline-signed.txt && exit 1 +assert_file_has_content show-ed25519-multiplekeys-bad-inline-signed.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=ed25519 --keys-file=${SECRETKEYS} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} > show-ed25519-multiplekeys-inline-signed-3.txt +assert_file_has_content show-ed25519-multiplekeys-inline-signed-3.txt "Verification OK" +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=ed25519 ${origrev}-${newrev} --keys-file=${PUBKEYS} "${WRONG_PUBLIC}" > show-ed25519-multiplekeys-inline-signed-4.txt +assert_file_has_content show-ed25519-multiplekeys-inline-signed-4.txt "Verification OK" + +echo 'ok verified with ed25519 (multiple keys)' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline --sign-type=ed25519 --keys-file=${PUBKEYS} repo/deltas/${deltaprefix}/${deltadir} +${CMD_PREFIX} ostree --repo=repo2 fsck +${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null + +echo 'ok apply offline with ed25519 (keyfile)' + +mkdir -p ${test_tmpdir}/{trusted,revoked}.ed25519.d + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +echo ${PUBLIC} > ${test_tmpdir}/trusted.ed25519.d/correct +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline --keys-dir=${test_tmpdir} repo/deltas/${deltaprefix}/${deltadir} +${CMD_PREFIX} ostree --repo=repo2 fsck +${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null + +echo 'ok apply offline with ed25519 (keydir)' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +echo ${PUBLIC} > ${test_tmpdir}/revoked.ed25519.d/correct +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +if ${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline --keys-dir=${test_tmpdir} repo/deltas/${deltaprefix}/${deltadir}; then + exit 1 +fi + +rm -rf ${test_tmpdir}/{trusted,revoked}.ed25519.d + +echo 'ok apply offline with ed25519 revoking key mechanism (keydir)' diff --git a/tests/test-delta-sign.sh b/tests/test-delta-sign.sh new file mode 100755 index 00000000..86f12f96 --- /dev/null +++ b/tests/test-delta-sign.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# +# Copyright (C) 2011,2013 Colin Walters +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +skip_without_user_xattrs + +bindatafiles="bash true ostree" + +echo '1..7' + +# This is explicitly opt in for testing +export OSTREE_DUMMY_SIGN_ENABLED=1 + +mkdir repo +ostree_repo_init repo --mode=archive + +mkdir files +for bin in ${bindatafiles}; do + cp $(which ${bin}) files +done + +${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files + +function permuteFile() { + permutation=$(($1 % 2)) + output=$2 + case $permutation in + 0) dd if=/dev/zero count=40 bs=1 >> $output;; + 1) echo aheader | cat - $output >> $output.new && mv $output.new $output;; + esac +} + +function permuteDirectory() { + permutation=$1 + dir=$2 + for x in ${dir}/*; do + for z in $(seq ${permutation}); do + permuteFile ${z} ${x} + done + done +} + +get_assert_one_direntry_matching() { + local path=$1 + local r=$2 + local child="" + local bn + for p in ${path}/*; do + bn=$(basename $p) + if ! echo ${bn} | grep -q "$r"; then + continue + fi + if test -z "${child}"; then + child=${bn} + else + assert_not_reached "Expected only one child matching ${r} in ${path}"; + fi + done + if test -z "${child}"; then + assert_not_reached "Failed to find child matching ${r}" + fi + echo ${child} +} + +origrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test) + +permuteDirectory 1 files +${CMD_PREFIX} ostree --repo=repo commit -b test -s test --tree=dir=files + +newrev=$(${CMD_PREFIX} ostree --repo=repo rev-parse test) + +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} dummysign > show-not-signed.txt 2>&1 && exit 1 +assert_file_has_content show-not-signed.txt "Verification fails" +assert_file_has_content show-not-signed.txt "no signatures in static-delta" + +deltaprefix=$(get_assert_one_direntry_matching repo/deltas '.') +deltadir=$(get_assert_one_direntry_matching repo/deltas/${deltaprefix} '-') + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} dummysign > show-inline-not-signed.txt 2>&1 && exit 1 +assert_file_has_content show-not-signed.txt "Verification fails" +assert_file_has_content show-not-signed.txt "no signatures in static-delta" + +echo 'ok verify ok with unsigned deltas' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=dummy --sign=dummysign +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} dummysign > show-dummy-signed.txt +assert_file_has_content show-dummy-signed.txt "Verification OK" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=dummy --sign=dummysign +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} dummysign > show-dummy-inline-signed.txt +assert_file_has_content show-dummy-inline-signed.txt "Verification OK" + +echo 'ok verified with dummy' + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --sign-type=dummy --sign=dummysign +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} badsign > show-dummy-bad-signed.txt && exit 1 +assert_file_has_content show-dummy-bad-signed.txt "Verification fails" + +rm -rf repo/deltas/${deltaprefix}/${deltadir}/* +${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${newrev} --inline --sign-type=dummy --sign=dummysign +${CMD_PREFIX} ostree --repo=repo static-delta verify --sign-type=dummy ${origrev}-${newrev} badsign > show-dummy-bad-inline-signed.txt && exit 1 +assert_file_has_content show-dummy-bad-inline-signed.txt "Verification fails" + +echo 'ok verification failed with dummy and bad key' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline repo/deltas/${deltaprefix}/${deltadir} +${CMD_PREFIX} ostree --repo=repo2 fsck +${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null + +echo 'ok apply offline with no signature verification and no key' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +${CMD_PREFIX} ostree --repo=repo2 config set core.sign-verify-deltas true +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline repo/deltas/${deltaprefix}/${deltadir} 2> apply-offline-verification-no-key.txt && exit 1 +assert_file_has_content apply-offline-verification-no-key.txt "Key is mandatory to check delta signature" + +echo 'ok apply offline failed with signature verification forced and no key' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline --sign-type=dummy repo/deltas/${deltaprefix}/${deltadir} dummysign +${CMD_PREFIX} ostree --repo=repo2 fsck +${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null + +echo 'ok apply offline with dummy' + +rm -rf repo2 +ostree_repo_init repo2 --mode=bare-user + +${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} +${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null +${CMD_PREFIX} ostree --repo=repo2 static-delta apply-offline --sign-type=dummy repo/deltas/${deltaprefix}/${deltadir} badsign 2> apply-offline-bad-key.txt && exit 1 +assert_file_has_content apply-offline-bad-key.txt "signature: dummy: incorrect signature" + +echo 'ok apply offline failed with dummy and bad key' diff --git a/tests/test-libarchive.sh b/tests/test-libarchive.sh index 174be800..73a58ddd 100755 --- a/tests/test-libarchive.sh +++ b/tests/test-libarchive.sh @@ -37,7 +37,7 @@ mkdir foo cd foo mkdir -p usr/bin usr/lib echo contents > usr/bin/foo -touch usr/bin/foo0 +echo foo0 > usr/bin/foo0 ln usr/bin/foo usr/bin/bar ln usr/bin/foo0 usr/bin/bar0 ln -s foo usr/bin/sl @@ -45,8 +45,8 @@ mkdir -p usr/local/bin ln usr/bin/foo usr/local/bin/baz ln usr/bin/foo0 usr/local/bin/baz0 ln usr/bin/sl usr/local/bin/slhl -touch usr/bin/setuidme -touch usr/bin/skipme +echo setuidme > usr/bin/setuidme +echo skipme > usr/bin/skipme echo "a library" > usr/lib/libfoo.so echo "another library" > usr/lib/libbar.so @@ -102,9 +102,9 @@ assert_valid_content () { assert_file_has_content usr/bin/foo contents assert_file_has_content usr/bin/bar contents assert_file_has_content usr/local/bin/baz contents - assert_file_empty usr/bin/foo0 - assert_file_empty usr/bin/bar0 - assert_file_empty usr/local/bin/baz0 + assert_file_has_content usr/bin/foo0 foo0 + assert_file_has_content usr/bin/bar0 foo0 + assert_file_has_content usr/local/bin/baz0 foo0 assert_file_has_content usr/lib/libfoo.so 'a library' assert_file_has_content usr/lib/libbar.so 'another library' @@ -244,7 +244,7 @@ ${CMD_PREFIX} ostree --repo=repo2 commit \ --generate-sizes \ --tree=tar=foo.tar.gz ${CMD_PREFIX} ostree --repo=repo2 show --print-sizes test-tar > sizes.txt -assert_file_has_content sizes.txt 'Compressed size (needed/total): 0[  ]bytes/1.1[  ]kB' -assert_file_has_content sizes.txt 'Unpacked size (needed/total): 0[  ]bytes/900[  ]bytes' -assert_file_has_content sizes.txt 'Number of objects (needed/total): 0/12' +assert_file_has_content sizes.txt 'Compressed size (needed/total): 0[  ]bytes/1.2[  ]kB' +assert_file_has_content sizes.txt 'Unpacked size (needed/total): 0[  ]bytes/921[  ]bytes' +assert_file_has_content sizes.txt 'Number of objects (needed/total): 0/14' echo "ok tar sizes metadata" diff --git a/tests/test-osupdate-dtb.sh b/tests/test-osupdate-dtb.sh new file mode 100755 index 00000000..9e0c4686 --- /dev/null +++ b/tests/test-osupdate-dtb.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# Copyright (C) 2020 Red Hat, Inc. +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +echo "1..1" + +# Exports OSTREE_SYSROOT so --sysroot not needed. +kver="3.6.0" +modulesdir="usr/lib/modules/${kver}" +setup_os_repository "archive" "syslinux" ${modulesdir} + +cd ${test_tmpdir} +os_repository_new_commit "test" "test with device tree directory" + +devicetree_path=osdata/${modulesdir}/dtb/asoc-board.dtb +devicetree_overlay_path=osdata/${modulesdir}/dtb/overlays/overlay.dtbo + +mkdir -p osdata/${modulesdir}/dtb +echo "a device tree" > ${devicetree_path} +mkdir -p osdata/${modulesdir}/dtb/overlays +echo "a device tree overlay" > ${devicetree_overlay_path} + +${CMD_PREFIX} ostree --repo=testos-repo commit --tree=dir=osdata/ -b testos/buildmaster/x86_64-runtime +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos file://$(pwd)/testos-repo testos/buildmaster/x86_64-runtime +${CMD_PREFIX} env OSTREE_SYSROOT_DEBUG=${OSTREE_SYSROOT_DEBUG},no-dtb ostree admin deploy --os=testos testos:testos/buildmaster/x86_64-runtime +assert_has_file sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 +assert_not_has_file sysroot/boot/ostree/testos-${bootcsum}/dtb/asoc-board.dtb 'a device tree' +assert_streq $(ls sysroot/boot/ostree | wc -l) 1 +assert_streq $(find sysroot/boot/ostree -name '*.dtb' | wc -l) 0 +${CMD_PREFIX} ostree --repo=testos-repo commit --tree=dir=osdata/ -b testos/buildmaster/x86_64-runtime +env OSTREE_SYSROOT_DEBUG=${OSTREE_SYSROOT_DEBUG},no-dtb ${CMD_PREFIX} ostree admin upgrade --os=testos +${CMD_PREFIX} ostree --repo=testos-repo commit --tree=dir=osdata/ -b testos/buildmaster/x86_64-runtime +${CMD_PREFIX} ostree admin upgrade --os=testos +assert_streq $(ls sysroot/boot/ostree | wc -l) 2 +# Note that the bootcsum computed by the test suite doesn't include devicetree +# And currently we end up installing the dtb for the *previous* deployment +# too which is a bug - in the future this should be fixed to assert 1. +assert_streq $(find sysroot/boot/ostree -name '*.dtb' | wc -l) 2 + +echo "ok update with no dtb to dtb" diff --git a/tests/test-repo-finder-config.c b/tests/test-repo-finder-config.c index ead9e907..b3e8a264 100644 --- a/tests/test-repo-finder-config.c +++ b/tests/test-repo-finder-config.c @@ -230,7 +230,7 @@ test_repo_finder_config_mixed_configs (Fixture *fixture, { g_autoptr(OstreeRepoFinderConfig) finder = NULL; g_autoptr(GMainContext) context = NULL; - g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GAsyncResult) async_result = NULL; g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */ g_autoptr(GError) error = NULL; gsize i; @@ -266,13 +266,13 @@ test_repo_finder_config_mixed_configs (Fixture *fixture, /* Resolve the refs. */ ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs, - fixture->parent_repo, NULL, result_cb, &result); + fixture->parent_repo, NULL, result_cb, &async_result); - while (result == NULL) + while (async_result == NULL) g_main_context_iteration (context, TRUE); results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), - result, &error); + async_result, &error); g_assert_no_error (error); g_assert_nonnull (results); g_assert_cmpuint (results->len, ==, 3); diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index e4130921..45e58fa4 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -317,7 +317,7 @@ test_repo_finder_mount_mixed_mounts (Fixture *fixture, g_autoptr(OstreeRepoFinderMount) finder = NULL; g_autoptr(GVolumeMonitor) monitor = NULL; g_autoptr(GMainContext) context = NULL; - g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GAsyncResult) async_result = NULL; g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */ g_autoptr(GError) error = NULL; g_autoptr(GList) mounts = NULL; /* (element-type OstreeMockMount) */ @@ -395,13 +395,13 @@ test_repo_finder_mount_mixed_mounts (Fixture *fixture, /* Resolve the refs. */ ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs, fixture->parent_repo, - NULL, result_cb, &result); + NULL, result_cb, &async_result); - while (result == NULL) + while (async_result == NULL) g_main_context_iteration (context, TRUE); results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), - result, &error); + async_result, &error); g_assert_no_error (error); g_assert_nonnull (results); g_assert_cmpuint (results->len, ==, 4); @@ -466,7 +466,7 @@ test_repo_finder_mount_well_known (Fixture *fixture, g_autoptr(OstreeRepoFinderMount) finder = NULL; g_autoptr(GVolumeMonitor) monitor = NULL; g_autoptr(GMainContext) context = NULL; - g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GAsyncResult) async_result = NULL; g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */ g_autoptr(GError) error = NULL; g_autoptr(GList) mounts = NULL; /* (element-type OstreeMockMount) */ @@ -507,13 +507,13 @@ test_repo_finder_mount_well_known (Fixture *fixture, /* Resolve the refs. */ ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs, fixture->parent_repo, - NULL, result_cb, &result); + NULL, result_cb, &async_result); - while (result == NULL) + while (async_result == NULL) g_main_context_iteration (context, TRUE); results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), - result, &error); + async_result, &error); g_assert_no_error (error); g_assert_nonnull (results); g_assert_cmpuint (results->len, ==, 2); diff --git a/tests/test-summary-view.sh b/tests/test-summary-view.sh index 14de0294..f6278a85 100755 --- a/tests/test-summary-view.sh +++ b/tests/test-summary-view.sh @@ -64,5 +64,5 @@ echo "ok view summary" ${OSTREE} summary --raw > raw-summary.txt assert_file_has_content_literal raw-summary.txt "('main', (" assert_file_has_content_literal raw-summary.txt "('other', (" -assert_file_has_content_literal raw-summary.txt "{'ostree.summary.last-modified': released-sha256.txt <