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.
+
+
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.
+
+
+
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() .
@@ -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.
+
+
Since: 2020.7
+
+
+
+
ostree_bootconfig_parser_get_overlay_initrds ()
+
char **
+ostree_bootconfig_parser_get_overlay_initrds
+ (OstreeBootconfigParser *self );
+
+
+
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.
-z
- 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.
+
+ --sign-type =ENGINE
+
+
+ Use particular signature engine. Currently
+ available ed25519 and dummy
+ signature types.
+
+ The default is ed25519 .
+
+
+
+
+ --sign ="KEY-ID"
+
+ There KEY-ID is:
+
+
+ for ed25519:
+
+ base64 -encoded secret key for signing.
+
+
+
+
+ for dummy:
+
+ ASCII-string used as secret key.
+
+
+
+
+
+
+
+
+
+ 'Apply-offline' Options
+
+
+
+ KEY-ID
+
+
+
+
+ for ed25519:
+
+ base64 -encoded public key for verifying.
+
+
+
+
+ for dummy:
+
+ ASCII-string used as public key.
+
+
+
+
+
+
+
+ --sign-type =ENGINE
+
+
+ Use particular signature engine. Currently
+ available ed25519 and dummy
+ signature types.
+
+
+
+
+ --keys-file
+
+ 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.
+
+
+
+
+ --keys-dir
+
+ Redefine the system path, where to search files and subdirectories with
+ well-known and revoked keys.
+
+
+
+
+
+
+ 'Verify' Options
+
+
+
+ KEY-ID
+
+
+
+
+ for ed25519:
+
+ base64 -encoded public key for verifying.
+
+
+
+
+ for dummy:
+
+ ASCII-string used as public key.
+
+
+
+
+
+
+
+ --sign-type =ENGINE
+
+
+ Use particular signature engine. Currently
+ available ed25519 and dummy
+ signature types.
+
+ The default is ed25519 .
+
+
+
+
+ --keys-file
+
+ 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.
+
+
+
+
+ --keys-dir
+
+ 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 <