diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 224e7f0..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.pc/ diff --git a/Makefile-boot.am b/Makefile-boot.am index 90f9804..c07b6b8 100644 --- a/Makefile-boot.am +++ b/Makefile-boot.am @@ -42,6 +42,7 @@ systemdsystemunit_DATA = src/boot/ostree-prepare-root.service \ src/boot/ostree-finalize-staged.service \ src/boot/ostree-finalize-staged.path \ src/boot/ostree-finalize-staged-hold.service \ + src/boot/ostree-state-overlay@.service \ $(NULL) systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d dist_systemdtmpfiles_DATA = src/boot/ostree-tmpfiles.conf @@ -72,6 +73,7 @@ EXTRA_DIST += src/boot/dracut/module-setup.sh \ src/boot/ostree-remount.service \ src/boot/ostree-finalize-staged.service \ src/boot/ostree-finalize-staged-hold.service \ + src/boot/ostree-state-overlay@.service \ src/boot/grub2/grub2-15_ostree \ src/boot/grub2/ostree-grub-generator \ $(NULL) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 9611473..b18e1c2 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -175,9 +175,9 @@ endif # USE_GPGME symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym # Uncomment this include when adding new development symbols. -#if BUILDOPT_IS_DEVEL_BUILD +if BUILDOPT_IS_DEVEL_BUILD #symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym -#endif +endif # http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html wl_versionscript_arg = -Wl,--version-script= @@ -186,7 +186,7 @@ EXTRA_DIST += \ $(top_srcdir)/src/libostree/libostree-released.sym \ $(NULL) -libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/composefs -I$(srcdir)/src/libotutil -I$(srcdir)/src/libotcore -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ +libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -I$(srcdir)/src/libotcore -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ -I$(srcdir)/src/switchroot \ $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' \ @@ -265,7 +265,7 @@ libostree_1_la_SOURCES += \ $(NULL) if USE_COMPOSEFS -libostree_1_la_LIBADD += libcomposefs.la +libostree_1_la_LIBADD += $(OT_DEP_COMPOSEFS_LIBS) endif # USE_COMPOSEFS # XXX: work around clang being passed -fstack-clash-protection which it doesn't understand diff --git a/Makefile-man.am b/Makefile-man.am index da229bc..5d1b9d4 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -29,7 +29,8 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \ ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-stateroot-init.1 ostree-admin-os-init.1 \ ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \ ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \ -ostree-admin-pin.1 ostree-admin-set-default.1 \ +ostree-admin-pin.1 ostree-admin-post-copy.1 ostree-admin-set-default.1 \ +ostree-admin-lock-finalization.1 \ ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \ ostree-commit.1 ostree-create-usb.1 ostree-export.1 \ ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \ @@ -48,13 +49,17 @@ endif man5_files = ostree.repo.5 ostree.repo-config.5 +man8_files = ostree-state-overlay@.service.8 + man1_MANS = $(addprefix man/,$(man1_files)) man5_MANS = $(addprefix man/,$(man5_files)) +man8_MANS = $(addprefix man/,$(man8_files)) manhtml_files = \ man/html/index.html \ $(addprefix man/html/,$(man1_files:.1=.html)) \ $(addprefix man/html/,$(man5_files:.5=.html)) \ + $(addprefix man/html/,$(man8_files:.8=.html)) \ $(NULL) if ENABLE_MAN_HTML @@ -64,7 +69,7 @@ noinst_DATA += $(manhtml_files) manhtml: $(manhtml_files) endif -EXTRA_DIST += man/index.xml $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) +EXTRA_DIST += man/index.xml $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) $(man8_MANS:.8=.xml) XSLT_MAN_STYLESHEET = http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl XSLT_HTML_STYLESHEET = man/html.xsl @@ -86,6 +91,9 @@ XSLTPROC_MAN = $(XSLTPROC) $(XSLTPROC_FLAGS) %.5: %.xml $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $< +%.8: %.xml + $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $< + man/html/%.html: man/%.xml @mkdir -p man/html $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_HTML_STYLESHEET) $< @@ -93,6 +101,7 @@ man/html/%.html: man/%.xml CLEANFILES += \ $(man1_MANS) \ $(man5_MANS) \ + $(man8_MANS) \ $(manhtml_files) \ $(NULL) diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 16bb04d..d2447ff 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -70,6 +70,7 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-diff.c \ src/ostree/ot-admin-builtin-deploy.c \ src/ostree/ot-admin-builtin-finalize-staged.c \ + src/ostree/ot-admin-builtin-lock-finalization.c \ src/ostree/ot-admin-builtin-boot-complete.c \ src/ostree/ot-admin-builtin-undeploy.c \ src/ostree/ot-admin-builtin-set-default.c \ @@ -81,8 +82,10 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-pin.c \ + src/ostree/ot-admin-builtin-post-copy.c \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-unlock.c \ + src/ostree/ot-admin-builtin-state-overlay.c \ src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \ src/ostree/ot-admin-instutil-builtin-set-kargs.c \ diff --git a/Makefile-switchroot.am b/Makefile-switchroot.am index 1e458e0..9a1d413 100644 --- a/Makefile-switchroot.am +++ b/Makefile-switchroot.am @@ -49,7 +49,7 @@ ostree-prepare-root : $(ostree_prepare_root_SOURCES) CLEANFILES += ostree-prepare-root else ostree_boot_PROGRAMS += ostree-prepare-root -ostree_prepare_root_CFLAGS += $(AM_CFLAGS) -Isrc/switchroot -I$(srcdir)/composefs -I$(srcdir)/src/libostree -I$(srcdir)/src/libotcore -I$(srcdir)/src/libotutil +ostree_prepare_root_CFLAGS += $(AM_CFLAGS) -Isrc/switchroot -I$(srcdir)/src/libostree -I$(srcdir)/src/libotcore -I$(srcdir)/src/libotutil ostree_prepare_root_SOURCES += src/switchroot/ostree-prepare-root.c ostree_prepare_root_CPPFLAGS += $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) -I $(srcdir)/libglnx ostree_prepare_root_LDADD += $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_DEP_CRYPTO_LIBS) libotcore.la libotutil.la libglnx.la @@ -69,7 +69,7 @@ ostree_remount_LDADD += $(OT_DEP_SELINUX_LIBS) endif if USE_COMPOSEFS -ostree_prepare_root_LDADD += libcomposefs.la +ostree_prepare_root_LDADD += $(OT_DEP_COMPOSEFS_LIBS) endif if BUILDOPT_SYSTEMD diff --git a/Makefile-tests.am b/Makefile-tests.am index e1cea7f..d333b9a 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -104,6 +104,8 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-upgrade-systemd-update.sh \ tests/test-admin-deploy-syslinux.sh \ tests/test-admin-deploy-bootprefix.sh \ + tests/test-admin-deploy-composefs.sh \ + tests/test-admin-deploy-var.sh \ tests/test-admin-deploy-2.sh \ tests/test-admin-deploy-karg.sh \ tests/test-admin-deploy-switch.sh \ @@ -123,6 +125,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-locking.sh \ tests/test-admin-deploy-clean.sh \ tests/test-admin-kargs.sh \ + tests/test-admin-stateroot.sh \ tests/test-reset-nonlinear.sh \ tests/test-oldstyle-partial.sh \ tests/test-delta.sh \ diff --git a/Makefile.am b/Makefile.am index 19abc0c..ddaf790 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,14 +117,8 @@ include bsdiff/Makefile-bsdiff.am.inc EXTRA_DIST += bsdiff/Makefile-bsdiff.am noinst_LTLIBRARIES += libbsdiff.la -COMPOSEFSDIR=$(srcdir)/composefs/libcomposefs LCFS_DEP_CRYPTO_CFLAGS=$(OT_DEP_CRYPTO_CFLAGS) LCFS_DEP_CRYPTO_LIBS=$(OT_DEP_CRYPTO_LIBS) -include composefs/libcomposefs/Makefile-lib.am.inc -EXTRA_DIST += composefs/libcomposefs/Makefile-lib.am -if USE_COMPOSEFS -noinst_LTLIBRARIES += libcomposefs.la -endif include Makefile-otutil.am include Makefile-otcore.am diff --git a/Makefile.in b/Makefile.in index 68c4e4a..9aefd35 100644 --- a/Makefile.in +++ b/Makefile.in @@ -409,47 +409,46 @@ check_PROGRAMS = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) @ENABLE_INSTALLED_TESTS_TRUE@am__append_13 = $(installed_test_meta_DATA) @USE_LIBSOUP_TRUE@am__append_14 = -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_40 '-DSOUP_VERSION_MAX_ALLOWED=G_ENCODE_VERSION(2,48)' @ENABLE_GTK_DOC_TRUE@am__append_15 = apidoc -@USE_COMPOSEFS_TRUE@am__append_16 = libcomposefs.la -@USE_GPGME_TRUE@am__append_17 = \ +@USE_GPGME_TRUE@am__append_16 = \ @USE_GPGME_TRUE@ src/libotutil/ot-gpg-utils.c \ @USE_GPGME_TRUE@ src/libotutil/ot-gpg-utils.h \ @USE_GPGME_TRUE@ src/libotutil/zbase32.c \ @USE_GPGME_TRUE@ src/libotutil/zbase32.h \ @USE_GPGME_TRUE@ $(NULL) -@USE_LIBARCHIVE_TRUE@am__append_18 = src/libostree/ostree-libarchive-input-stream.h \ +@USE_LIBARCHIVE_TRUE@am__append_17 = src/libostree/ostree-libarchive-input-stream.h \ @USE_LIBARCHIVE_TRUE@ src/libostree/ostree-libarchive-input-stream.c \ @USE_LIBARCHIVE_TRUE@ src/libostree/ostree-libarchive-private.h \ @USE_LIBARCHIVE_TRUE@ $(NULL) -@HAVE_LIBSOUP_CLIENT_CERTS_TRUE@am__append_19 = \ +@HAVE_LIBSOUP_CLIENT_CERTS_TRUE@am__append_18 = \ @HAVE_LIBSOUP_CLIENT_CERTS_TRUE@ src/libostree/ostree-tls-cert-interaction.c \ @HAVE_LIBSOUP_CLIENT_CERTS_TRUE@ src/libostree/ostree-tls-cert-interaction-private.h \ @HAVE_LIBSOUP_CLIENT_CERTS_TRUE@ $(NULL) -@USE_AVAHI_TRUE@am__append_20 = \ +@USE_AVAHI_TRUE@am__append_19 = \ @USE_AVAHI_TRUE@ src/libostree/ostree-repo-finder-avahi-parser.c \ @USE_AVAHI_TRUE@ src/libostree/ostree-repo-finder-avahi-private.h \ @USE_AVAHI_TRUE@ $(NULL) -@USE_GPGME_TRUE@am__append_21 = \ +@USE_GPGME_TRUE@am__append_20 = \ @USE_GPGME_TRUE@ src/libostree/ostree-gpg-verifier.c \ @USE_GPGME_TRUE@ src/libostree/ostree-gpg-verifier.h \ @USE_GPGME_TRUE@ src/libostree/ostree-gpg-verify-result.c \ @USE_GPGME_TRUE@ src/libostree/ostree-gpg-verify-result-private.h \ @USE_GPGME_TRUE@ $(NULL) -@USE_GPGME_FALSE@am__append_22 = \ +@USE_GPGME_FALSE@am__append_21 = \ @USE_GPGME_FALSE@ src/libostree/ostree-gpg-verify-result-dummy.c \ @USE_GPGME_FALSE@ $(NULL) -@USE_LIBARCHIVE_TRUE@am__append_23 = $(OT_DEP_LIBARCHIVE_CFLAGS) -@USE_LIBARCHIVE_TRUE@am__append_24 = $(OT_DEP_LIBARCHIVE_LIBS) -@USE_AVAHI_TRUE@am__append_25 = $(OT_DEP_AVAHI_CFLAGS) -@USE_AVAHI_TRUE@am__append_26 = $(OT_DEP_AVAHI_LIBS) -@BUILDOPT_SYSTEMD_TRUE@am__append_27 = $(LIBSYSTEMD_CFLAGS) -@BUILDOPT_SYSTEMD_TRUE@am__append_28 = $(LIBSYSTEMD_LIBS) -@USE_CURL_OR_SOUP_TRUE@am__append_29 = \ +@USE_LIBARCHIVE_TRUE@am__append_22 = $(OT_DEP_LIBARCHIVE_CFLAGS) +@USE_LIBARCHIVE_TRUE@am__append_23 = $(OT_DEP_LIBARCHIVE_LIBS) +@USE_AVAHI_TRUE@am__append_24 = $(OT_DEP_AVAHI_CFLAGS) +@USE_AVAHI_TRUE@am__append_25 = $(OT_DEP_AVAHI_LIBS) +@BUILDOPT_SYSTEMD_TRUE@am__append_26 = $(LIBSYSTEMD_CFLAGS) +@BUILDOPT_SYSTEMD_TRUE@am__append_27 = $(LIBSYSTEMD_LIBS) +@USE_CURL_OR_SOUP_TRUE@am__append_28 = \ @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 \ @@ -460,36 +459,36 @@ check_PROGRAMS = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) # Only enable one fetcher backend. -@USE_CURL_TRUE@am__append_30 = src/libostree/ostree-fetcher-curl.c \ +@USE_CURL_TRUE@am__append_29 = src/libostree/ostree-fetcher-curl.c \ @USE_CURL_TRUE@ $(NULL) -@USE_CURL_TRUE@am__append_31 = $(OT_DEP_CURL_CFLAGS) -@USE_CURL_TRUE@am__append_32 = $(OT_DEP_CURL_LIBS) -@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_33 = src/libostree/ostree-fetcher-soup3.c -@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_34 = $(OT_INTERNAL_SOUP_CFLAGS) -@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_35 = $(OT_INTERNAL_SOUP_LIBS) -@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_36 = src/libostree/ostree-fetcher-soup.c -@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_37 = $(OT_INTERNAL_SOUP_CFLAGS) -@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_38 = $(OT_INTERNAL_SOUP_LIBS) -@USE_LIBMOUNT_TRUE@am__append_39 = $(OT_DEP_LIBMOUNT_CFLAGS) -@USE_LIBMOUNT_TRUE@am__append_40 = $(OT_DEP_LIBMOUNT_LIBS) -@USE_SELINUX_TRUE@am__append_41 = $(OT_DEP_SELINUX_CFLAGS) -@USE_SELINUX_TRUE@am__append_42 = $(OT_DEP_SELINUX_LIBS) -@USE_COMPOSEFS_TRUE@am__append_43 = libcomposefs.la +@USE_CURL_TRUE@am__append_30 = $(OT_DEP_CURL_CFLAGS) +@USE_CURL_TRUE@am__append_31 = $(OT_DEP_CURL_LIBS) +@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_32 = src/libostree/ostree-fetcher-soup3.c +@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_33 = $(OT_INTERNAL_SOUP_CFLAGS) +@USE_CURL_FALSE@@USE_LIBSOUP3_TRUE@am__append_34 = $(OT_INTERNAL_SOUP_LIBS) +@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_35 = src/libostree/ostree-fetcher-soup.c +@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_36 = $(OT_INTERNAL_SOUP_CFLAGS) +@USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__append_37 = $(OT_INTERNAL_SOUP_LIBS) +@USE_LIBMOUNT_TRUE@am__append_38 = $(OT_DEP_LIBMOUNT_CFLAGS) +@USE_LIBMOUNT_TRUE@am__append_39 = $(OT_DEP_LIBMOUNT_LIBS) +@USE_SELINUX_TRUE@am__append_40 = $(OT_DEP_SELINUX_CFLAGS) +@USE_SELINUX_TRUE@am__append_41 = $(OT_DEP_SELINUX_LIBS) +@USE_COMPOSEFS_TRUE@am__append_42 = $(OT_DEP_COMPOSEFS_LIBS) +@BUILDOPT_INTROSPECTION_TRUE@am__append_43 = OSTree-1.0.gir @BUILDOPT_INTROSPECTION_TRUE@am__append_44 = OSTree-1.0.gir -@BUILDOPT_INTROSPECTION_TRUE@am__append_45 = OSTree-1.0.gir -@BUILDOPT_INTROSPECTION_TRUE@am__append_46 = OSTree-1.0.typelib -@BUILDOPT_INTROSPECTION_TRUE@am__append_47 = $(gir_DATA) $(typelib_DATA) -@USE_GPGME_TRUE@am__append_48 = \ +@BUILDOPT_INTROSPECTION_TRUE@am__append_45 = OSTree-1.0.typelib +@BUILDOPT_INTROSPECTION_TRUE@am__append_46 = $(gir_DATA) $(typelib_DATA) +@USE_GPGME_TRUE@am__append_47 = \ @USE_GPGME_TRUE@ src/ostree/ot-builtin-gpg-sign.c \ @USE_GPGME_TRUE@ $(NULL) -@USE_GPGME_TRUE@am__append_49 = \ +@USE_GPGME_TRUE@am__append_48 = \ @USE_GPGME_TRUE@ src/ostree/ot-remote-builtin-gpg-import.c \ @USE_GPGME_TRUE@ src/ostree/ot-remote-builtin-gpg-list-keys.c \ @USE_GPGME_TRUE@ $(NULL) -@USE_CURL_OR_SOUP_TRUE@am__append_50 = src/ostree/ot-remote-builtin-add-cookie.c \ +@USE_CURL_OR_SOUP_TRUE@am__append_49 = 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 \ @@ -497,15 +496,15 @@ check_PROGRAMS = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) @USE_CURL_OR_SOUP_TRUE@ $(NULL) src/ostree/ot-builtin-pull.c # This is necessary for the cookie jar bits -@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_51 = $(OT_INTERNAL_SOUP_CFLAGS) -@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_52 = $(OT_INTERNAL_SOUP_LIBS) -@USE_LIBARCHIVE_TRUE@am__append_53 = $(OT_DEP_LIBARCHIVE_CFLAGS) -@USE_LIBARCHIVE_TRUE@am__append_54 = $(OT_DEP_LIBARCHIVE_LIBS) -@BUILDOPT_SYSTEMD_TRUE@am__append_55 = ostree-remount +@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_50 = $(OT_INTERNAL_SOUP_CFLAGS) +@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_51 = $(OT_INTERNAL_SOUP_LIBS) +@USE_LIBARCHIVE_TRUE@am__append_52 = $(OT_DEP_LIBARCHIVE_CFLAGS) +@USE_LIBARCHIVE_TRUE@am__append_53 = $(OT_DEP_LIBARCHIVE_LIBS) +@BUILDOPT_SYSTEMD_TRUE@am__append_54 = 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_56 = ostree-remount -@BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_57 = src/switchroot/ostree-prepare-root-static.c +@BUILDOPT_SYSTEMD_FALSE@am__append_55 = ostree-remount +@BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_56 = src/switchroot/ostree-prepare-root-static.c # 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 @@ -517,75 +516,77 @@ check_PROGRAMS = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) # 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_57 = ostree-prepare-root @BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_58 = ostree-prepare-root -@BUILDOPT_USE_STATIC_COMPILER_TRUE@am__append_59 = ostree-prepare-root -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_60 = ostree-prepare-root -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_61 = $(AM_CFLAGS) -Isrc/switchroot -I$(srcdir)/composefs -I$(srcdir)/src/libostree -I$(srcdir)/src/libotcore -I$(srcdir)/src/libotutil -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_62 = src/switchroot/ostree-prepare-root.c -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_63 = $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) -I $(srcdir)/libglnx -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_64 = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_DEP_CRYPTO_LIBS) libotcore.la libotutil.la libglnx.la -@USE_SELINUX_TRUE@am__append_65 = $(OT_DEP_SELINUX_CFLAGS) -@USE_SELINUX_TRUE@am__append_66 = $(OT_DEP_SELINUX_LIBS) -@USE_COMPOSEFS_TRUE@am__append_67 = libcomposefs.la -@BUILDOPT_SYSTEMD_TRUE@am__append_68 = -DHAVE_SYSTEMD=1 -@BUILDOPT_SYSTEMD_TRUE@am__append_69 = $(LIBSYSTEMD_LIBS) +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_59 = ostree-prepare-root +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_60 = $(AM_CFLAGS) -Isrc/switchroot -I$(srcdir)/src/libostree -I$(srcdir)/src/libotcore -I$(srcdir)/src/libotutil +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_61 = src/switchroot/ostree-prepare-root.c +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_62 = $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) -I $(srcdir)/libglnx +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__append_63 = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_DEP_CRYPTO_LIBS) libotcore.la libotutil.la libglnx.la +@USE_SELINUX_TRUE@am__append_64 = $(OT_DEP_SELINUX_CFLAGS) +@USE_SELINUX_TRUE@am__append_65 = $(OT_DEP_SELINUX_LIBS) +@USE_COMPOSEFS_TRUE@am__append_66 = $(OT_DEP_COMPOSEFS_LIBS) +@BUILDOPT_SYSTEMD_TRUE@am__append_67 = -DHAVE_SYSTEMD=1 +@BUILDOPT_SYSTEMD_TRUE@am__append_68 = $(LIBSYSTEMD_LIBS) # 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_72 = $(systemdsystemgenerator_PROGRAMS) +@BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@am__append_71 = $(systemdsystemgenerator_PROGRAMS) # Allow the distcheck install under $prefix test to pass -@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 = \ +@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 = \ @USE_GPGME_TRUE@ tests/test-remote-gpg-import.sh \ @USE_GPGME_TRUE@ tests/test-remote-gpg-list-keys.sh \ @USE_GPGME_TRUE@ tests/test-gpg-signed-commit.sh \ @USE_GPGME_TRUE@ tests/test-admin-gpg.sh \ @USE_GPGME_TRUE@ $(NULL) -@BUILDOPT_FUSE_TRUE@am__append_77 = tests/test-rofiles-fuse.sh -@BUILDOPT_FUSE_TRUE@am__append_78 = tests/rofiles-fuse-symlink-stamp -@BUILDOPT_FUSE_FALSE@am__append_79 = tests/test-rofiles-fuse.sh -@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_80 = tests/test-remote-cookies.sh -@BUILDOPT_GJS_TRUE@am__append_81 = $(js_tests) $(js_installed_tests) -@BUILDOPT_GJS_FALSE@am__append_82 = $(js_tests) -@BUILDOPT_GJS_FALSE@am__append_83 = $(js_installed_tests) -@USE_GPGME_TRUE@am__append_84 = \ +@BUILDOPT_FUSE_TRUE@am__append_76 = tests/test-rofiles-fuse.sh +@BUILDOPT_FUSE_TRUE@am__append_77 = tests/rofiles-fuse-symlink-stamp +@BUILDOPT_FUSE_FALSE@am__append_78 = tests/test-rofiles-fuse.sh +@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_79 = tests/test-remote-cookies.sh +@BUILDOPT_GJS_TRUE@am__append_80 = $(js_tests) $(js_installed_tests) +@BUILDOPT_GJS_FALSE@am__append_81 = $(js_tests) +@BUILDOPT_GJS_FALSE@am__append_82 = $(js_installed_tests) +@USE_GPGME_TRUE@am__append_83 = \ @USE_GPGME_TRUE@ tests/test-gpg-verify-result \ @USE_GPGME_TRUE@ $(NULL) -@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_85 = ostree-trivial-httpd -@USE_AVAHI_TRUE@am__append_86 = tests/test-repo-finder-avahi -@USE_LIBARCHIVE_TRUE@am__append_87 = tests/test-libarchive-import -@USE_GPGME_TRUE@am__append_88 = \ +@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__append_84 = ostree-trivial-httpd +@USE_AVAHI_TRUE@am__append_85 = tests/test-repo-finder-avahi +@USE_LIBARCHIVE_TRUE@am__append_86 = tests/test-libarchive-import +@USE_GPGME_TRUE@am__append_87 = \ @USE_GPGME_TRUE@ tests/gpg-verify-data/README.md \ @USE_GPGME_TRUE@ $(NULL) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_89 = $(_installed_or_uninstalled_test_scripts) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_90 = $(_installed_or_uninstalled_test_programs) -@ENABLE_INSTALLED_TESTS_TRUE@am__append_91 = install-installed-tests-extra +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_88 = $(_installed_or_uninstalled_test_scripts) +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_89 = $(_installed_or_uninstalled_test_programs) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_90 = install-installed-tests-extra # Allow the distcheck install under $prefix test to pass -@BUILDOPT_SYSTEMD_TRUE@am__append_92 = --with-systemdsystemunitdir='$${libdir}/systemd/system' +@BUILDOPT_SYSTEMD_TRUE@am__append_91 = --with-systemdsystemunitdir='$${libdir}/systemd/system' # We're using the system grub2-mkconfig generator -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_93 = src/boot/grub2/grub2-15_ostree -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_94 = install-grub2-config-hook +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_92 = src/boot/grub2/grub2-15_ostree +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_93 = install-grub2-config-hook # We're using our internal generator -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_TRUE@am__append_95 = src/boot/grub2/ostree-grub-generator -@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_96 = rofiles-fuse.1 -@ENABLE_MAN_TRUE@@USE_GPGME_TRUE@am__append_97 = ostree-gpg-sign.1 -@ENABLE_MAN_HTML_TRUE@@ENABLE_MAN_TRUE@am__append_98 = $(manhtml_files) -@ENABLE_MAN_TRUE@am__append_99 = man/index.xml $(man1_MANS:.1=.xml) \ -@ENABLE_MAN_TRUE@ $(man5_MANS:.5=.xml) $(XSLT_HTML_STYLESHEET) -@ENABLE_MAN_TRUE@am__append_100 = \ +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_TRUE@am__append_94 = src/boot/grub2/ostree-grub-generator +@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_95 = rofiles-fuse.1 +@ENABLE_MAN_TRUE@@USE_GPGME_TRUE@am__append_96 = ostree-gpg-sign.1 +@ENABLE_MAN_HTML_TRUE@@ENABLE_MAN_TRUE@am__append_97 = $(manhtml_files) +@ENABLE_MAN_TRUE@am__append_98 = man/index.xml $(man1_MANS:.1=.xml) \ +@ENABLE_MAN_TRUE@ $(man5_MANS:.5=.xml) $(man8_MANS:.8=.xml) \ +@ENABLE_MAN_TRUE@ $(XSLT_HTML_STYLESHEET) +@ENABLE_MAN_TRUE@am__append_99 = \ @ENABLE_MAN_TRUE@ $(man1_MANS) \ @ENABLE_MAN_TRUE@ $(man5_MANS) \ +@ENABLE_MAN_TRUE@ $(man8_MANS) \ @ENABLE_MAN_TRUE@ $(manhtml_files) \ @ENABLE_MAN_TRUE@ $(NULL) @@ -630,7 +631,8 @@ am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(mkinitcpioinstalldir)" \ "$(DESTDIR)$(ostree_bootdir)" "$(DESTDIR)$(pkglibexecdir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \ - "$(DESTDIR)$(completionsdir)" "$(DESTDIR)$(gpginsttestdir)" \ + "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(completionsdir)" \ + "$(DESTDIR)$(gpginsttestdir)" \ "$(DESTDIR)$(gpginsttest_revocdir)" \ "$(DESTDIR)$(gpginsttest_trusteddir)" \ "$(DESTDIR)$(gpgvinsttestdir)" \ @@ -734,19 +736,6 @@ am_libbupsplit_la_OBJECTS = src/libostree/bupsplit.lo libbupsplit_la_OBJECTS = $(am_libbupsplit_la_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) -libcomposefs_la_DEPENDENCIES = $(am__DEPENDENCIES_2) -am_libcomposefs_la_OBJECTS = \ - composefs/libcomposefs/libcomposefs_la-hash.lo \ - composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo \ - composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo \ - composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo \ - composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo -libcomposefs_la_OBJECTS = $(am_libcomposefs_la_OBJECTS) -libcomposefs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(libcomposefs_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ - -o $@ -@USE_COMPOSEFS_TRUE@am_libcomposefs_la_rpath = libglnx_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am_libglnx_la_OBJECTS = libglnx/la-glnx-backport-testutils.lo \ libglnx/la-glnx-backports.lo libglnx/la-glnx-local-alloc.lo \ @@ -771,6 +760,7 @@ libglnx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ @USE_CURL_FALSE@@USE_LIBSOUP3_FALSE@@USE_LIBSOUP_TRUE@am__DEPENDENCIES_10 = $(am__DEPENDENCIES_8) @USE_LIBMOUNT_TRUE@am__DEPENDENCIES_11 = $(am__DEPENDENCIES_1) @USE_SELINUX_TRUE@am__DEPENDENCIES_12 = $(am__DEPENDENCIES_1) +@USE_COMPOSEFS_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_1) libostree_1_la_DEPENDENCIES = libotutil.la libotcore.la libglnx.la \ libbsdiff.la $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ @@ -778,7 +768,7 @@ libostree_1_la_DEPENDENCIES = libotutil.la libotcore.la libglnx.la \ $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_6) \ $(am__DEPENDENCIES_7) $(am__DEPENDENCIES_9) \ $(am__DEPENDENCIES_10) $(am__DEPENDENCIES_11) \ - $(am__DEPENDENCIES_12) $(am__append_43) + $(am__DEPENDENCIES_12) $(am__DEPENDENCIES_13) am__libostree_1_la_SOURCES_DIST = \ src/libostree/ostree-async-progress.c \ src/libostree/ostree-cmd-private.h \ @@ -980,10 +970,10 @@ libostree_1_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libostree_1_la_CFLAGS) $(CFLAGS) $(libostree_1_la_LDFLAGS) \ $(LDFLAGS) -o $@ -am__DEPENDENCIES_13 = libglnx.la libotutil.la libostree-1.la \ +am__DEPENDENCIES_14 = libglnx.la libotutil.la libostree-1.la \ $(am__DEPENDENCIES_2) -am__DEPENDENCIES_14 = $(am__DEPENDENCIES_13) $(am__DEPENDENCIES_2) -libostreetest_la_DEPENDENCIES = $(am__DEPENDENCIES_14) +am__DEPENDENCIES_15 = $(am__DEPENDENCIES_14) $(am__DEPENDENCIES_2) +libostreetest_la_DEPENDENCIES = $(am__DEPENDENCIES_15) am_libostreetest_la_OBJECTS = tests/libostreetest_la-libostreetest.lo \ tests/libostreetest_la-test-mock-gio.lo libostreetest_la_OBJECTS = $(am_libostreetest_la_OBJECTS) @@ -1066,6 +1056,7 @@ am__ostree_SOURCES_DIST = src/ostree/main.c \ src/ostree/ot-admin-builtin-diff.c \ src/ostree/ot-admin-builtin-deploy.c \ src/ostree/ot-admin-builtin-finalize-staged.c \ + src/ostree/ot-admin-builtin-lock-finalization.c \ src/ostree/ot-admin-builtin-boot-complete.c \ src/ostree/ot-admin-builtin-undeploy.c \ src/ostree/ot-admin-builtin-set-default.c \ @@ -1077,8 +1068,10 @@ am__ostree_SOURCES_DIST = src/ostree/main.c \ src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-pin.c \ + src/ostree/ot-admin-builtin-post-copy.c \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-unlock.c \ + src/ostree/ot-admin-builtin-state-overlay.c \ src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \ src/ostree/ot-admin-instutil-builtin-set-kargs.c \ @@ -1147,6 +1140,7 @@ am_ostree_OBJECTS = src/ostree/ostree-main.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-diff.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-deploy.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-finalize-staged.$(OBJEXT) \ + src/ostree/ostree-ot-admin-builtin-lock-finalization.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-boot-complete.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-undeploy.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-set-default.$(OBJEXT) \ @@ -1158,8 +1152,10 @@ am_ostree_OBJECTS = src/ostree/ostree-main.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-status.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-pin.$(OBJEXT) \ + src/ostree/ostree-ot-admin-builtin-post-copy.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT) \ src/ostree/ostree-ot-admin-builtin-unlock.$(OBJEXT) \ + src/ostree/ostree-ot-admin-builtin-state-overlay.$(OBJEXT) \ src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.$(OBJEXT) \ src/ostree/ostree-ot-admin-instutil-builtin-set-kargs.$(OBJEXT) \ src/ostree/ostree-ot-admin-instutil-builtin-grub2-generate.$(OBJEXT) \ @@ -1176,9 +1172,9 @@ am_ostree_OBJECTS = src/ostree/ostree-main.$(OBJEXT) \ nodist_ostree_OBJECTS = src/ostree/ostree-parse-datetime.$(OBJEXT) \ $(am__objects_1) ostree_OBJECTS = $(am_ostree_OBJECTS) $(nodist_ostree_OBJECTS) -@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__DEPENDENCIES_15 = $(am__DEPENDENCIES_8) -ostree_DEPENDENCIES = $(am__DEPENDENCIES_13) libbsdiff.la \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_15) \ +@USE_CURL_FALSE@@USE_LIBSOUP_OR_LIBSOUP3_TRUE@am__DEPENDENCIES_16 = $(am__DEPENDENCIES_8) +ostree_DEPENDENCIES = $(am__DEPENDENCIES_14) libbsdiff.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_16) \ $(am__DEPENDENCIES_4) ostree_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ostree_CFLAGS) $(CFLAGS) \ @@ -1191,13 +1187,13 @@ am__ostree_prepare_root_SOURCES_DIST = \ @BUILDOPT_USE_STATIC_COMPILER_FALSE@am__objects_16 = src/switchroot/ostree_prepare_root-ostree-prepare-root.$(OBJEXT) am_ostree_prepare_root_OBJECTS = $(am__objects_15) $(am__objects_16) ostree_prepare_root_OBJECTS = $(am_ostree_prepare_root_OBJECTS) -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__DEPENDENCIES_16 = \ +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__DEPENDENCIES_17 = \ @BUILDOPT_USE_STATIC_COMPILER_FALSE@ $(am__DEPENDENCIES_2) \ @BUILDOPT_USE_STATIC_COMPILER_FALSE@ $(am__DEPENDENCIES_1) \ @BUILDOPT_USE_STATIC_COMPILER_FALSE@ libotcore.la libotutil.la \ @BUILDOPT_USE_STATIC_COMPILER_FALSE@ libglnx.la -ostree_prepare_root_DEPENDENCIES = $(am__DEPENDENCIES_16) \ - $(am__append_67) $(am__DEPENDENCIES_6) +ostree_prepare_root_DEPENDENCIES = $(am__DEPENDENCIES_17) \ + $(am__DEPENDENCIES_13) $(am__DEPENDENCIES_6) ostree_prepare_root_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(ostree_prepare_root_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1226,7 +1222,7 @@ am__ostree_trivial_httpd_SOURCES_DIST = \ @USE_LIBSOUP_OR_LIBSOUP3_TRUE@am_ostree_trivial_httpd_OBJECTS = src/ostree/ostree_trivial_httpd-ostree-trivial-httpd.$(OBJEXT) ostree_trivial_httpd_OBJECTS = $(am_ostree_trivial_httpd_OBJECTS) @USE_LIBSOUP_OR_LIBSOUP3_TRUE@ostree_trivial_httpd_DEPENDENCIES = \ -@USE_LIBSOUP_OR_LIBSOUP3_TRUE@ $(am__DEPENDENCIES_14) \ +@USE_LIBSOUP_OR_LIBSOUP3_TRUE@ $(am__DEPENDENCIES_15) \ @USE_LIBSOUP_OR_LIBSOUP3_TRUE@ $(am__DEPENDENCIES_8) ostree_trivial_httpd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -1303,7 +1299,7 @@ am_tests_repo_finder_mount_OBJECTS = \ tests/repo_finder_mount-repo-finder-mount.$(OBJEXT) tests_repo_finder_mount_OBJECTS = \ $(am_tests_repo_finder_mount_OBJECTS) -tests_repo_finder_mount_DEPENDENCIES = $(am__DEPENDENCIES_14) \ +tests_repo_finder_mount_DEPENDENCIES = $(am__DEPENDENCIES_15) \ libostreetest.la tests_repo_finder_mount_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -1312,8 +1308,8 @@ tests_repo_finder_mount_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_basic_c_SOURCES = tests/test-basic-c.c tests_test_basic_c_OBJECTS = \ tests/test_basic_c-test-basic-c.$(OBJEXT) -am__DEPENDENCIES_17 = $(am__DEPENDENCIES_14) libostreetest.la -tests_test_basic_c_DEPENDENCIES = $(am__DEPENDENCIES_17) +am__DEPENDENCIES_18 = $(am__DEPENDENCIES_15) libostreetest.la +tests_test_basic_c_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_basic_c_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_basic_c_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1322,14 +1318,14 @@ am_tests_test_bloom_OBJECTS = \ src/libostree/tests_test_bloom-ostree-bloom.$(OBJEXT) \ tests/test_bloom-test-bloom.$(OBJEXT) tests_test_bloom_OBJECTS = $(am_tests_test_bloom_OBJECTS) -tests_test_bloom_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_bloom_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_bloom_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_bloom_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ tests_test_bsdiff_SOURCES = tests/test-bsdiff.c tests_test_bsdiff_OBJECTS = tests/test_bsdiff-test-bsdiff.$(OBJEXT) -tests_test_bsdiff_DEPENDENCIES = libbsdiff.la $(am__DEPENDENCIES_17) +tests_test_bsdiff_DEPENDENCIES = libbsdiff.la $(am__DEPENDENCIES_18) tests_test_bsdiff_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_bsdiff_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ @@ -1339,7 +1335,7 @@ am_tests_test_checksum_OBJECTS = \ src/libostree/tests_test_checksum-ostree-varint.$(OBJEXT) \ tests/test_checksum-test-checksum.$(OBJEXT) tests_test_checksum_OBJECTS = $(am_tests_test_checksum_OBJECTS) -tests_test_checksum_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_checksum_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_checksum_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_checksum_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1347,7 +1343,7 @@ tests_test_checksum_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_commit_sign_sh_ext_SOURCES = \ tests/test-commit-sign-sh-ext.c tests_test_commit_sign_sh_ext_OBJECTS = tests/test_commit_sign_sh_ext-test-commit-sign-sh-ext.$(OBJEXT) -tests_test_commit_sign_sh_ext_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_commit_sign_sh_ext_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_commit_sign_sh_ext_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_commit_sign_sh_ext_CFLAGS) $(CFLAGS) \ @@ -1359,7 +1355,7 @@ am__tests_test_gpg_verify_result_SOURCES_DIST = \ tests_test_gpg_verify_result_OBJECTS = \ $(am_tests_test_gpg_verify_result_OBJECTS) @USE_GPGME_TRUE@tests_test_gpg_verify_result_DEPENDENCIES = \ -@USE_GPGME_TRUE@ $(am__DEPENDENCIES_17) $(am__DEPENDENCIES_3) +@USE_GPGME_TRUE@ $(am__DEPENDENCIES_18) $(am__DEPENDENCIES_3) tests_test_gpg_verify_result_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_gpg_verify_result_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1368,7 +1364,7 @@ am_tests_test_include_ostree_h_OBJECTS = \ tests/test_include_ostree_h-test-include-ostree-h.$(OBJEXT) tests_test_include_ostree_h_OBJECTS = \ $(am_tests_test_include_ostree_h_OBJECTS) -tests_test_include_ostree_h_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_include_ostree_h_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_include_ostree_h_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_include_ostree_h_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1377,7 +1373,7 @@ am_tests_test_kargs_OBJECTS = \ src/libostree/tests_test_kargs-ostree-kernel-args.$(OBJEXT) \ tests/test_kargs-test-kargs.$(OBJEXT) tests_test_kargs_OBJECTS = $(am_tests_test_kargs_OBJECTS) -tests_test_kargs_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_kargs_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_kargs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_kargs_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ @@ -1385,7 +1381,7 @@ tests_test_kargs_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_keyfile_utils_SOURCES = tests/test-keyfile-utils.c tests_test_keyfile_utils_OBJECTS = \ tests/test_keyfile_utils-test-keyfile-utils.$(OBJEXT) -tests_test_keyfile_utils_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_keyfile_utils_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_keyfile_utils_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_keyfile_utils_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1394,7 +1390,7 @@ am_tests_test_libarchive_import_OBJECTS = \ tests/test_libarchive_import-test-libarchive-import.$(OBJEXT) tests_test_libarchive_import_OBJECTS = \ $(am_tests_test_libarchive_import_OBJECTS) -tests_test_libarchive_import_DEPENDENCIES = $(am__DEPENDENCIES_17) \ +tests_test_libarchive_import_DEPENDENCIES = $(am__DEPENDENCIES_18) \ $(am__DEPENDENCIES_1) tests_test_libarchive_import_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -1406,7 +1402,7 @@ am_tests_test_lzma_OBJECTS = \ src/libostree/tests_test_lzma-ostree-lzma-decompressor.$(OBJEXT) \ tests/test_lzma-test-lzma.$(OBJEXT) tests_test_lzma_OBJECTS = $(am_tests_test_lzma_OBJECTS) -tests_test_lzma_DEPENDENCIES = $(am__DEPENDENCIES_17) \ +tests_test_lzma_DEPENDENCIES = $(am__DEPENDENCIES_18) \ $(am__DEPENDENCIES_1) tests_test_lzma_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -1415,7 +1411,7 @@ tests_test_lzma_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_mutable_tree_SOURCES = tests/test-mutable-tree.c tests_test_mutable_tree_OBJECTS = \ tests/test_mutable_tree-test-mutable-tree.$(OBJEXT) -tests_test_mutable_tree_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_mutable_tree_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_mutable_tree_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_mutable_tree_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1423,7 +1419,7 @@ tests_test_mutable_tree_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_ot_opt_utils_SOURCES = tests/test-ot-opt-utils.c tests_test_ot_opt_utils_OBJECTS = \ tests/test_ot_opt_utils-test-ot-opt-utils.$(OBJEXT) -tests_test_ot_opt_utils_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_ot_opt_utils_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_ot_opt_utils_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_ot_opt_utils_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1431,7 +1427,7 @@ tests_test_ot_opt_utils_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_ot_tool_util_SOURCES = tests/test-ot-tool-util.c tests_test_ot_tool_util_OBJECTS = \ tests/test_ot_tool_util-test-ot-tool-util.$(OBJEXT) -tests_test_ot_tool_util_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_ot_tool_util_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_ot_tool_util_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_ot_tool_util_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1439,7 +1435,7 @@ tests_test_ot_tool_util_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_ot_unix_utils_SOURCES = tests/test-ot-unix-utils.c tests_test_ot_unix_utils_OBJECTS = \ tests/test_ot_unix_utils-test-ot-unix-utils.$(OBJEXT) -tests_test_ot_unix_utils_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_ot_unix_utils_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_ot_unix_utils_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_ot_unix_utils_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1454,14 +1450,14 @@ tests_test_otcore_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ -o $@ tests_test_pull_c_SOURCES = tests/test-pull-c.c tests_test_pull_c_OBJECTS = tests/test_pull_c-test-pull-c.$(OBJEXT) -tests_test_pull_c_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_pull_c_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_pull_c_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_pull_c_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ tests_test_repo_SOURCES = tests/test-repo.c tests_test_repo_OBJECTS = tests/test_repo-test-repo.$(OBJEXT) -tests_test_repo_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_repo_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_repo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_repo_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ @@ -1474,7 +1470,7 @@ am__tests_test_repo_finder_avahi_SOURCES_DIST = \ tests_test_repo_finder_avahi_OBJECTS = \ $(am_tests_test_repo_finder_avahi_OBJECTS) @USE_AVAHI_TRUE@tests_test_repo_finder_avahi_DEPENDENCIES = \ -@USE_AVAHI_TRUE@ $(am__DEPENDENCIES_17) +@USE_AVAHI_TRUE@ $(am__DEPENDENCIES_18) tests_test_repo_finder_avahi_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_repo_finder_avahi_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1482,7 +1478,7 @@ tests_test_repo_finder_avahi_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ am_tests_test_repo_finder_config_OBJECTS = tests/test_repo_finder_config-test-repo-finder-config.$(OBJEXT) tests_test_repo_finder_config_OBJECTS = \ $(am_tests_test_repo_finder_config_OBJECTS) -tests_test_repo_finder_config_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_repo_finder_config_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_repo_finder_config_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_repo_finder_config_CFLAGS) $(CFLAGS) \ @@ -1491,7 +1487,7 @@ am_tests_test_repo_finder_mount_OBJECTS = \ tests/test_repo_finder_mount-test-repo-finder-mount.$(OBJEXT) tests_test_repo_finder_mount_OBJECTS = \ $(am_tests_test_repo_finder_mount_OBJECTS) -tests_test_repo_finder_mount_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_repo_finder_mount_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_repo_finder_mount_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_repo_finder_mount_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1500,7 +1496,7 @@ am_tests_test_rfc2616_dates_OBJECTS = src/libostree/tests_test_rfc2616_dates-ost tests/test_rfc2616_dates-test-rfc2616-dates.$(OBJEXT) tests_test_rfc2616_dates_OBJECTS = \ $(am_tests_test_rfc2616_dates_OBJECTS) -tests_test_rfc2616_dates_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_rfc2616_dates_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_rfc2616_dates_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_rfc2616_dates_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1510,7 +1506,7 @@ am_tests_test_rollsum_OBJECTS = \ tests/test_rollsum-test-rollsum.$(OBJEXT) tests_test_rollsum_OBJECTS = $(am_tests_test_rollsum_OBJECTS) tests_test_rollsum_DEPENDENCIES = $(bupsplitpath) \ - $(am__DEPENDENCIES_17) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_18) $(am__DEPENDENCIES_1) tests_test_rollsum_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_rollsum_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1520,7 +1516,7 @@ am_tests_test_rollsum_cli_OBJECTS = \ tests/test_rollsum_cli-test-rollsum-cli.$(OBJEXT) tests_test_rollsum_cli_OBJECTS = $(am_tests_test_rollsum_cli_OBJECTS) tests_test_rollsum_cli_DEPENDENCIES = $(bupsplitpath) \ - $(am__DEPENDENCIES_17) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_18) $(am__DEPENDENCIES_1) tests_test_rollsum_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_rollsum_cli_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1528,7 +1524,7 @@ tests_test_rollsum_cli_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ tests_test_sysroot_c_SOURCES = tests/test-sysroot-c.c tests_test_sysroot_c_OBJECTS = \ tests/test_sysroot_c-test-sysroot-c.$(OBJEXT) -tests_test_sysroot_c_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_sysroot_c_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_sysroot_c_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_sysroot_c_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ @@ -1537,7 +1533,7 @@ am_tests_test_varint_OBJECTS = \ src/libostree/tests_test_varint-ostree-varint.$(OBJEXT) \ tests/test_varint-test-varint.$(OBJEXT) tests_test_varint_OBJECTS = $(am_tests_test_varint_OBJECTS) -tests_test_varint_DEPENDENCIES = $(am__DEPENDENCIES_17) +tests_test_varint_DEPENDENCIES = $(am__DEPENDENCIES_18) tests_test_varint_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_varint_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ @@ -1562,11 +1558,6 @@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = bsdiff/$(DEPDIR)/libbsdiff_la-bsdiff.Plo \ bsdiff/$(DEPDIR)/libbsdiff_la-bspatch.Plo \ - composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Plo \ - composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Plo \ - composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Plo \ - composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Plo \ - composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Plo \ libglnx/$(DEPDIR)/la-glnx-backport-testutils.Plo \ libglnx/$(DEPDIR)/la-glnx-backports.Plo \ libglnx/$(DEPDIR)/la-glnx-console.Plo \ @@ -1696,10 +1687,13 @@ am__depfiles_remade = bsdiff/$(DEPDIR)/libbsdiff_la-bsdiff.Plo \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-kargs.Po \ + src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po \ + src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-default.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po \ + src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po \ src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-undeploy.Po \ @@ -1808,12 +1802,12 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libbsdiff_la_SOURCES) $(libbupsplit_la_SOURCES) \ - $(libcomposefs_la_SOURCES) $(libglnx_la_SOURCES) \ - $(libostree_1_la_SOURCES) $(nodist_libostree_1_la_SOURCES) \ - $(libostreetest_la_SOURCES) $(libotcore_la_SOURCES) \ - $(libotutil_la_SOURCES) $(ostree_SOURCES) \ - $(nodist_ostree_SOURCES) $(ostree_prepare_root_SOURCES) \ - $(ostree_remount_SOURCES) $(ostree_system_generator_SOURCES) \ + $(libglnx_la_SOURCES) $(libostree_1_la_SOURCES) \ + $(nodist_libostree_1_la_SOURCES) $(libostreetest_la_SOURCES) \ + $(libotcore_la_SOURCES) $(libotutil_la_SOURCES) \ + $(ostree_SOURCES) $(nodist_ostree_SOURCES) \ + $(ostree_prepare_root_SOURCES) $(ostree_remount_SOURCES) \ + $(ostree_system_generator_SOURCES) \ $(ostree_trivial_httpd_SOURCES) $(rofiles_fuse_SOURCES) \ $(test_libglnx_errors_SOURCES) $(test_libglnx_fdio_SOURCES) \ $(test_libglnx_macros_SOURCES) $(test_libglnx_shutil_SOURCES) \ @@ -1837,10 +1831,9 @@ SOURCES = $(libbsdiff_la_SOURCES) $(libbupsplit_la_SOURCES) \ $(tests_test_rollsum_cli_SOURCES) tests/test-sysroot-c.c \ $(tests_test_varint_SOURCES) DIST_SOURCES = $(libbsdiff_la_SOURCES) $(libbupsplit_la_SOURCES) \ - $(libcomposefs_la_SOURCES) $(libglnx_la_SOURCES) \ - $(am__libostree_1_la_SOURCES_DIST) $(libostreetest_la_SOURCES) \ - $(libotcore_la_SOURCES) $(am__libotutil_la_SOURCES_DIST) \ - $(am__ostree_SOURCES_DIST) \ + $(libglnx_la_SOURCES) $(am__libostree_1_la_SOURCES_DIST) \ + $(libostreetest_la_SOURCES) $(libotcore_la_SOURCES) \ + $(am__libotutil_la_SOURCES_DIST) $(am__ostree_SOURCES_DIST) \ $(am__ostree_prepare_root_SOURCES_DIST) \ $(ostree_remount_SOURCES) \ $(am__ostree_system_generator_SOURCES_DIST) \ @@ -1882,8 +1875,9 @@ am__can_run_installinfo = \ esac man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 NROFF = nroff -MANS = $(man1_MANS) $(man5_MANS) +MANS = $(man1_MANS) $(man5_MANS) $(man8_MANS) am__dist_gpginsttest_DATA_DIST = tests/gpghome/secring.gpg \ tests/gpghome/pubring.gpg tests/gpghome/trustdb.gpg \ tests/gpghome/key1.asc tests/gpghome/key2.asc \ @@ -2124,7 +2118,9 @@ am__EXEEXT_23 = tests/test-basic.sh \ tests/test-admin-upgrade-systemd-update.sh \ tests/test-admin-deploy-syslinux.sh \ tests/test-admin-deploy-bootprefix.sh \ - tests/test-admin-deploy-2.sh tests/test-admin-deploy-karg.sh \ + tests/test-admin-deploy-composefs.sh \ + tests/test-admin-deploy-var.sh tests/test-admin-deploy-2.sh \ + tests/test-admin-deploy-karg.sh \ tests/test-admin-deploy-switch.sh \ tests/test-admin-deploy-etcmerge-cornercases.sh \ tests/test-admin-deploy-uboot.sh \ @@ -2139,19 +2135,19 @@ am__EXEEXT_23 = tests/test-basic.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-admin-kargs.sh 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 tests/test-concurrency.py \ - tests/test-refs.sh tests/test-demo-buildsystem.sh \ - tests/test-switchroot.sh tests/test-pull-contenturl.sh \ - tests/test-pull-mirrorlist.sh tests/test-summary-update.sh \ - tests/test-summary-view.sh tests/test-no-initramfs.sh \ - tests/test-create-usb.sh tests/test-find-remotes.sh \ - tests/test-fsck-collections.sh tests/test-fsck-delete.sh \ - tests/test-init-collections.sh tests/test-prune-collections.sh \ - tests/test-refs-collections.sh \ + tests/test-admin-kargs.sh tests/test-admin-stateroot.sh \ + 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 \ + tests/test-concurrency.py tests/test-refs.sh \ + tests/test-demo-buildsystem.sh tests/test-switchroot.sh \ + tests/test-pull-contenturl.sh tests/test-pull-mirrorlist.sh \ + tests/test-summary-update.sh tests/test-summary-view.sh \ + tests/test-no-initramfs.sh tests/test-create-usb.sh \ + tests/test-find-remotes.sh tests/test-fsck-collections.sh \ + tests/test-fsck-delete.sh tests/test-init-collections.sh \ + tests/test-prune-collections.sh tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ @@ -2159,7 +2155,7 @@ am__EXEEXT_23 = tests/test-basic.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__append_77) $(am__append_80) \ + $(am__EXEEXT_20) $(am__append_76) $(am__append_79) \ $(am__EXEEXT_22) @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__EXEEXT_24 = \ @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@ $(am__EXEEXT_23) @@ -2191,9 +2187,7 @@ am__DIST_COMMON = $(srcdir)/Makefile-bash.am \ $(srcdir)/Makefile-ostree.am $(srcdir)/Makefile-otcore.am \ $(srcdir)/Makefile-otutil.am $(srcdir)/Makefile-switchroot.am \ $(srcdir)/Makefile-tests.am $(srcdir)/Makefile.in \ - $(srcdir)/bsdiff/Makefile-bsdiff.am.inc \ - $(srcdir)/composefs/libcomposefs/Makefile-lib.am.inc \ - $(srcdir)/config.h.in \ + $(srcdir)/bsdiff/Makefile-bsdiff.am.inc $(srcdir)/config.h.in \ $(srcdir)/libglnx/Makefile-libglnx.am.inc \ $(srcdir)/src/rofiles-fuse/Makefile-inc.am \ $(top_srcdir)/build-aux/compile \ @@ -2300,6 +2294,7 @@ GOBJECT_QUERY = @GOBJECT_QUERY@ GPGME_CONFIG = @GPGME_CONFIG@ GPGME_PTHREAD_CFLAGS = @GPGME_PTHREAD_CFLAGS@ GPGME_PTHREAD_LIBS = @GPGME_PTHREAD_LIBS@ +GPGRT_CONFIG = @GPGRT_CONFIG@ GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ GREP = @GREP@ GRUB2_MKCONFIG = @GRUB2_MKCONFIG@ @@ -2347,6 +2342,8 @@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ OT_DEP_AVAHI_CFLAGS = @OT_DEP_AVAHI_CFLAGS@ OT_DEP_AVAHI_LIBS = @OT_DEP_AVAHI_LIBS@ +OT_DEP_COMPOSEFS_CFLAGS = @OT_DEP_COMPOSEFS_CFLAGS@ +OT_DEP_COMPOSEFS_LIBS = @OT_DEP_COMPOSEFS_LIBS@ OT_DEP_CRYPTO_CFLAGS = @OT_DEP_CRYPTO_CFLAGS@ OT_DEP_CRYPTO_LIBS = @OT_DEP_CRYPTO_LIBS@ OT_DEP_CURL_CFLAGS = @OT_DEP_CURL_CFLAGS@ @@ -2474,8 +2471,8 @@ 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_73) \ - $(am__append_92) \ + --disable-maintainer-mode $(NULL) $(am__append_72) \ + $(am__append_91) \ BASH_COMPLETIONSDIR='$${datadir}/bash-completion/completions' SUBDIRS = . $(am__append_15) NULL = @@ -2483,13 +2480,13 @@ BUILT_SOURCES = $(top_builddir)/libglnx-config.h \ $(nodist_libostree_1_la_SOURCES) MANPAGES = CLEANFILES = $(am__append_13) $(top_builddir)/libglnx-config.h \ - $(BUILT_SOURCES) $(am__append_47) src/ostree/parse-datetime.c \ - $(am__append_59) tests/ostree-symlink-stamp \ + $(BUILT_SOURCES) $(am__append_46) src/ostree/parse-datetime.c \ + $(am__append_58) 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_100) + tests/rofiles-fuse $(am__append_99) EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ COPYING README.md libglnx/README.md libglnx/COPYING \ libglnx/LICENSES/LGPL-2.0-or-later.txt \ @@ -2497,7 +2494,6 @@ EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ $(NULL) libglnx/Makefile-libglnx.am bsdiff/bsdiff.h \ bsdiff/bspatch.h bsdiff/LICENSE bsdiff/README.md \ bsdiff/Makefile-bsdiff.am \ - composefs/libcomposefs/Makefile-lib.am \ $(top_srcdir)/src/libostree/libostree-devel.sym \ $(top_srcdir)/src/libostree/libostree-released.sym $(NULL) \ src/libostree/README-gpg src/libostree/bupsplit.h \ @@ -2507,8 +2503,8 @@ 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_79) $(am__append_82) \ - tests/libtest.sh $(am__append_83) $(am__append_88) \ + tests/ostree.supp $(NULL) $(am__append_78) $(am__append_81) \ + tests/libtest.sh $(am__append_82) $(am__append_87) \ tests/libostreetest.h tests/libtest.sh $(NULL) \ src/boot/dracut/module-setup.sh src/boot/dracut/ostree.conf \ src/boot/mkinitcpio src/boot/ostree-boot-complete.service \ @@ -2517,26 +2513,26 @@ 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/ostree-finalize-staged-hold.service \ + src/boot/ostree-state-overlay@.service \ src/boot/grub2/grub2-15_ostree \ - src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_99) + src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_98) bin_SCRIPTS = lib_LTLIBRARIES = libostree-1.la -pkglibexec_SCRIPTS = $(am__append_93) +pkglibexec_SCRIPTS = $(am__append_92) noinst_LTLIBRARIES = $(am__append_1) libglnx.la libbsdiff.la \ - $(am__append_16) libotutil.la libotcore.la libbupsplit.la \ - libostreetest.la + libotutil.la libotcore.la libbupsplit.la libostreetest.la privlibdir = $(pkglibdir) privlib_LTLIBRARIES = pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = src/libostree/ostree-1.pc -INTROSPECTION_GIRS = $(am__append_44) +INTROSPECTION_GIRS = $(am__append_43) girdir = $(datadir)/gir-1.0 -gir_DATA = $(am__append_45) +gir_DATA = $(am__append_44) typelibdir = $(libdir)/girepository-1.0 -typelib_DATA = $(am__append_46) +typelib_DATA = $(am__append_45) gsettings_SCHEMAS = ostree_bootdir = $(prefix)/lib/ostree -ostree_boot_SCRIPTS = $(am__append_58) $(am__append_95) +ostree_boot_SCRIPTS = $(am__append_57) $(am__append_94) # We should probably consider flipping the default for DEBUG. Also, # include the builddir in $PATH so we find our just-built ostree @@ -2554,7 +2550,7 @@ AM_TESTS_ENVIRONMENT = G_TEST_SRCDIR="$(abs_srcdir)" \ $(top_builddir)/tests && pwd):$${PATH} \ OSTREE_FEATURES="$(OSTREE_FEATURES)" PYTHONUNBUFFERED=1 \ GSETTINGS_BACKEND=memory GIO_USE_PROXY_RESOLVER=dummy \ - GIO_USE_VFS=local $(NULL) $(am__append_75) + GIO_USE_VFS=local $(NULL) $(am__append_74) 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) @@ -2562,7 +2558,7 @@ installed_test_SCRIPTS = $(am__append_10) installed_test_DATA = $(am__append_11) nobase_installed_test_DATA = noinst_SCRIPTS = $(am__append_3) -noinst_DATA = $(am__append_4) $(am__append_98) +noinst_DATA = $(am__append_4) $(am__append_97) check_LTLIBRARIES = $(am__append_5) check_SCRIPTS = $(am__append_7) check_DATA = $(am__append_8) @@ -2594,8 +2590,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_91) \ - $(am__append_94) +INSTALL_DATA_HOOKS = install-mkdir-remotes-d-hook $(am__append_90) \ + $(am__append_93) ALL_LOCAL_RULES = 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) @@ -2611,7 +2607,7 @@ ACLOCAL_AMFLAGS = -I buildutil -I libglnx ${ACLOCAL_FLAGS} GITIGNOREFILES = aclocal.m4 build-aux/ buildutil/*.m4 config.h.in \ gtk-doc.make ci-build/ fastbuild-*.qcow2 _kola_temp/ target/ \ Cargo.lock docs/.bundle/ docs/Gemfile.lock docs/_site/ \ - docs/reference/ docs/vendor/ $(NULL) $(am__append_72) + docs/reference/ docs/vendor/ $(NULL) $(am__append_71) OT_INTERNAL_GIO_UNIX_CFLAGS = $(OT_DEP_GIO_UNIX_CFLAGS) OT_INTERNAL_GIO_UNIX_LIBS = $(OT_DEP_GIO_UNIX_LIBS) @USE_LIBSOUP3_FALSE@OT_INTERNAL_SOUP_CFLAGS = $(OT_DEP_SOUP_CFLAGS) @@ -2686,31 +2682,8 @@ libbsdiff_la_SOURCES = \ $(NULL) libbsdiff_la_CFLAGS = $(AM_CFLAGS) -COMPOSEFSDIR = $(srcdir)/composefs/libcomposefs LCFS_DEP_CRYPTO_CFLAGS = $(OT_DEP_CRYPTO_CFLAGS) LCFS_DEP_CRYPTO_LIBS = $(OT_DEP_CRYPTO_LIBS) -COMPOSEFS_HASH_CFLAGS = -DUSE_OBSTACK=0 -DTESTING=0 -DUSE_DIFF_HASH=0 -libcomposefs_la_SOURCES = \ - composefs/libcomposefs/bitrotate.h \ - composefs/libcomposefs/erofs_fs.h \ - composefs/libcomposefs/erofs_fs_wrapper.h \ - composefs/libcomposefs/hash.c \ - composefs/libcomposefs/hash.h \ - composefs/libcomposefs/lcfs-internal.h \ - composefs/libcomposefs/lcfs-erofs.h \ - composefs/libcomposefs/lcfs-erofs-internal.h \ - composefs/libcomposefs/lcfs-fsverity.c \ - composefs/libcomposefs/lcfs-fsverity.h \ - composefs/libcomposefs/lcfs-writer-erofs.c \ - composefs/libcomposefs/lcfs-writer.c \ - composefs/libcomposefs/lcfs-writer.h \ - composefs/libcomposefs/lcfs-utils.h \ - composefs/libcomposefs/lcfs-mount.c \ - composefs/libcomposefs/lcfs-mount.h \ - composefs/libcomposefs/xalloc-oversized.h - -libcomposefs_la_CFLAGS = $(WARN_CFLAGS) $(COMPOSEFS_HASH_CFLAGS) $(LCFS_DEP_CRYPTO_CFLAGS) $(HIDDEN_VISIBILITY_CFLAGS) -libcomposefs_la_LIBADD = $(LCFS_DEP_CRYPTO_LIBS) libotutil_la_SOURCES = src/libotutil/ot-checksum-utils.c \ src/libotutil/ot-checksum-utils.h \ src/libotutil/ot-checksum-instream.c \ @@ -2725,7 +2698,7 @@ libotutil_la_SOURCES = src/libotutil/ot-checksum-utils.c \ src/libotutil/ot-variant-builder.h \ src/libotutil/ot-gio-utils.c src/libotutil/ot-gio-utils.h \ src/libotutil/otutil.h src/libotutil/ot-tool-util.c \ - src/libotutil/ot-tool-util.h $(NULL) $(am__append_17) + src/libotutil/ot-tool-util.h $(NULL) $(am__append_16) libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_CRYPTO_LIBS) $(LIBSYSTEMD_CFLAGS) libotutil_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(LIBSYSTEMD_LIBS) $(OT_DEP_CRYPTO_LIBS) libotcore_la_SOURCES = \ @@ -2861,10 +2834,10 @@ libostree_1_la_SOURCES = src/libostree/ostree-async-progress.c \ src/libostree/ostree-repo-finder-override.c \ src/libostree/ostree-kernel-args.h \ src/libostree/ostree-kernel-args-private.h \ - src/libostree/ostree-kernel-args.c $(NULL) $(am__append_18) \ - $(am__append_19) $(am__append_20) $(am__append_21) \ - $(am__append_22) $(am__append_29) $(am__append_30) \ - $(am__append_33) $(am__append_36) src/libostree/ostree-sign.c \ + src/libostree/ostree-kernel-args.c $(NULL) $(am__append_17) \ + $(am__append_18) $(am__append_19) $(am__append_20) \ + $(am__append_21) $(am__append_28) $(am__append_29) \ + $(am__append_32) $(am__append_35) 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 \ @@ -2873,34 +2846,31 @@ libostree_1_la_SOURCES = src/libostree/ostree-async-progress.c \ symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym # Uncomment this include when adding new development symbols. -#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= libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff \ - -I$(srcdir)/libglnx -I$(srcdir)/composefs \ - -I$(srcdir)/src/libotutil -I$(srcdir)/src/libotcore \ - -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ - -I$(srcdir)/src/switchroot $(OT_INTERNAL_GIO_UNIX_CFLAGS) \ - $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) \ - $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ - -fvisibility=hidden \ + -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil \ + -I$(srcdir)/src/libotcore -I$(srcdir)/src/libostree \ + -I$(builddir)/src/libostree -I$(srcdir)/src/switchroot \ + $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) \ + $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) \ + $(OT_DEP_CRYPTO_CFLAGS) -fvisibility=hidden \ '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) \ - extern' -DPKGLIBEXECDIR=\"$(pkglibexecdir)\" $(am__append_23) \ - $(am__append_25) $(am__append_27) $(am__append_31) \ - $(am__append_34) $(am__append_37) $(am__append_39) \ - $(am__append_41) + extern' -DPKGLIBEXECDIR=\"$(pkglibexecdir)\" $(am__append_22) \ + $(am__append_24) $(am__append_26) $(am__append_30) \ + $(am__append_33) $(am__append_36) $(am__append_38) \ + $(am__append_40) libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) # Some change between rust-1.21.0-1.fc27 and rust-1.22.1-1.fc27.x86_64 libostree_1_la_LIBADD = libotutil.la libotcore.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) $(bupsplitpath) \ - $(am__append_24) $(am__append_26) $(am__append_28) \ - $(am__append_32) $(am__append_35) $(am__append_38) \ - $(am__append_40) $(am__append_42) $(am__append_43) + $(am__append_23) $(am__append_25) $(am__append_27) \ + $(am__append_31) $(am__append_34) $(am__append_37) \ + $(am__append_39) $(am__append_41) $(am__append_42) EXTRA_libostree_1_la_DEPENDENCIES = $(symbol_files) # XXX: work around clang being passed -fstack-clash-protection which it doesn't understand @@ -2938,11 +2908,12 @@ 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_48) \ + src/ostree/parse-datetime.h $(NULL) $(am__append_47) \ 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 \ + src/ostree/ot-admin-builtin-lock-finalization.c \ src/ostree/ot-admin-builtin-boot-complete.c \ src/ostree/ot-admin-builtin-undeploy.c \ src/ostree/ot-admin-builtin-set-default.c \ @@ -2954,8 +2925,10 @@ ostree_SOURCES = src/ostree/main.c src/ostree/ot-builtin-admin.c \ src/ostree/ot-admin-builtin-status.c \ src/ostree/ot-admin-builtin-switch.c \ src/ostree/ot-admin-builtin-pin.c \ + src/ostree/ot-admin-builtin-post-copy.c \ src/ostree/ot-admin-builtin-upgrade.c \ src/ostree/ot-admin-builtin-unlock.c \ + src/ostree/ot-admin-builtin-state-overlay.c \ src/ostree/ot-admin-builtins.h \ src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c \ src/ostree/ot-admin-instutil-builtin-set-kargs.c \ @@ -2972,7 +2945,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_49) $(am__append_50) + $(am__append_48) $(am__append_49) nodist_ostree_SOURCES = \ src/ostree/parse-datetime.c \ $(NULL) @@ -2984,17 +2957,17 @@ 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_51) \ - $(am__append_53) +ostree_CFLAGS = $(ostree_bin_shared_cflags) $(am__append_50) \ + $(am__append_52) ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la \ - $(LIBSYSTEMD_LIBS) $(am__append_52) $(am__append_54) + $(LIBSYSTEMD_LIBS) $(am__append_51) $(am__append_53) ostree_prepare_root_SOURCES = src/switchroot/ostree-mount-util.h \ - $(am__append_57) $(am__append_62) -ostree_prepare_root_CFLAGS = $(am__append_61) -ostree_prepare_root_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_63) \ - $(am__append_68) $(am__append_70) -ostree_prepare_root_LDADD = $(am__append_64) $(am__append_67) \ - $(am__append_69) + $(am__append_56) $(am__append_61) +ostree_prepare_root_CFLAGS = $(am__append_60) +ostree_prepare_root_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_62) \ + $(am__append_67) $(am__append_69) +ostree_prepare_root_LDADD = $(am__append_63) $(am__append_66) \ + $(am__append_68) ostree_remount_SOURCES = \ src/switchroot/ostree-mount-util.h \ src/switchroot/ostree-remount.c \ @@ -3003,9 +2976,9 @@ ostree_remount_SOURCES = \ ostree_remount_CPPFLAGS = $(AM_CPPFLAGS) \ $(OT_INTERNAL_GIO_UNIX_CFLAGS) -Isrc/switchroot \ -I$(srcdir)/src/libotcore -I$(srcdir)/src/libotutil \ - -I$(srcdir)/libglnx $(am__append_65) $(am__append_71) + -I$(srcdir)/libglnx $(am__append_64) $(am__append_70) ostree_remount_LDADD = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) \ - libotcore.la libotutil.la libglnx.la $(am__append_66) + libotcore.la libotutil.la libglnx.la $(am__append_65) @BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@ostree_system_generator_SOURCES = src/switchroot/ostree-mount-util.h \ @BUILDOPT_SYSTEMD_AND_LIBMOUNT_TRUE@ src/switchroot/ostree-system-generator.c @@ -3020,7 +2993,7 @@ ostree_remount_LDADD = $(AM_LDFLAGS) $(OT_INTERNAL_GIO_UNIX_LIBS) \ @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_78) + tests/ostree-remount-symlink-stamp $(am__append_77) dist_uninstalled_test_scripts = tests/test-symbols.sh tests/coccinelle.sh # This logic implements ENABLE_INSTALLED_TESTS_EXCLUSIVE; see below. @@ -3028,10 +3001,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_89) +dist_test_scripts = $(NULL) $(am__append_88) test_programs = tests/test-bloom tests/test-repo-finder-config \ - tests/test-repo-finder-mount $(NULL) $(am__append_86) \ - $(am__append_90) + tests/test-repo-finder-mount $(NULL) $(am__append_85) \ + $(am__append_89) _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-basic-bare-split-xattrs.sh tests/test-basic-user.sh \ tests/test-basic-user-only.sh tests/test-basic-root.sh \ @@ -3058,7 +3031,9 @@ _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-admin-upgrade-systemd-update.sh \ tests/test-admin-deploy-syslinux.sh \ tests/test-admin-deploy-bootprefix.sh \ - tests/test-admin-deploy-2.sh tests/test-admin-deploy-karg.sh \ + tests/test-admin-deploy-composefs.sh \ + tests/test-admin-deploy-var.sh tests/test-admin-deploy-2.sh \ + tests/test-admin-deploy-karg.sh \ tests/test-admin-deploy-switch.sh \ tests/test-admin-deploy-etcmerge-cornercases.sh \ tests/test-admin-deploy-uboot.sh \ @@ -3073,29 +3048,29 @@ _installed_or_uninstalled_test_scripts = tests/test-basic.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-admin-kargs.sh 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 tests/test-concurrency.py \ - tests/test-refs.sh tests/test-demo-buildsystem.sh \ - tests/test-switchroot.sh tests/test-pull-contenturl.sh \ - tests/test-pull-mirrorlist.sh tests/test-summary-update.sh \ - tests/test-summary-view.sh tests/test-no-initramfs.sh \ - tests/test-create-usb.sh tests/test-find-remotes.sh \ - tests/test-fsck-collections.sh tests/test-fsck-delete.sh \ - tests/test-init-collections.sh tests/test-prune-collections.sh \ - tests/test-refs-collections.sh \ + tests/test-admin-kargs.sh tests/test-admin-stateroot.sh \ + 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 \ + tests/test-concurrency.py tests/test-refs.sh \ + tests/test-demo-buildsystem.sh tests/test-switchroot.sh \ + tests/test-pull-contenturl.sh tests/test-pull-mirrorlist.sh \ + tests/test-summary-update.sh tests/test-summary-view.sh \ + tests/test-no-initramfs.sh tests/test-create-usb.sh \ + tests/test-find-remotes.sh tests/test-fsck-collections.sh \ + tests/test-fsck-delete.sh tests/test-init-collections.sh \ + tests/test-prune-collections.sh tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh 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_76) \ - $(am__append_77) $(am__append_80) $(am__append_81) + tests/test-signed-pull-summary.sh $(NULL) $(am__append_75) \ + $(am__append_76) $(am__append_79) $(am__append_80) test_extra_programs = tests/get-byte-order tests/repo-finder-mount \ - $(NULL) $(am__append_85) + $(NULL) $(am__append_84) tests_get_byte_order_SOURCES = tests/get-byte-order.c tests_get_byte_order_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) tests_get_byte_order_LDADD = $(GLIB_LIBS) @@ -3165,7 +3140,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 \ - tests/test-rfc2616-dates $(am__append_84) $(am__append_87) + tests/test-rfc2616-dates $(am__append_83) $(am__append_86) @USE_LIBSOUP_OR_LIBSOUP3_TRUE@ostree_trivial_httpd_SOURCES = src/ostree/ostree-trivial-httpd.c @USE_LIBSOUP_OR_LIBSOUP3_TRUE@ostree_trivial_httpd_CFLAGS = $(common_tests_cflags) $(OT_INTERNAL_SOUP_CFLAGS) @USE_LIBSOUP_OR_LIBSOUP3_TRUE@ostree_trivial_httpd_LDADD = $(common_tests_ldadd) $(OT_INTERNAL_SOUP_LIBS) @@ -3277,6 +3252,7 @@ tests_test_commit_sign_sh_ext_LDADD = $(TESTS_LDADD) @BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-finalize-staged.service \ @BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-finalize-staged.path \ @BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-finalize-staged-hold.service \ +@BUILDOPT_SYSTEMD_TRUE@ src/boot/ostree-state-overlay@.service \ @BUILDOPT_SYSTEMD_TRUE@ $(NULL) @BUILDOPT_SYSTEMD_TRUE@systemdtmpfilesdir = $(prefix)/lib/tmpfiles.d @@ -3294,7 +3270,9 @@ tests_test_commit_sign_sh_ext_LDADD = $(TESTS_LDADD) @ENABLE_MAN_TRUE@ ostree-admin-set-origin.1 \ @ENABLE_MAN_TRUE@ ostree-admin-switch.1 ostree-admin-undeploy.1 \ @ENABLE_MAN_TRUE@ ostree-admin-upgrade.1 ostree-admin-unlock.1 \ -@ENABLE_MAN_TRUE@ ostree-admin-pin.1 ostree-admin-set-default.1 \ +@ENABLE_MAN_TRUE@ ostree-admin-pin.1 ostree-admin-post-copy.1 \ +@ENABLE_MAN_TRUE@ ostree-admin-set-default.1 \ +@ENABLE_MAN_TRUE@ ostree-admin-lock-finalization.1 \ @ENABLE_MAN_TRUE@ ostree-admin.1 ostree-cat.1 ostree-checkout.1 \ @ENABLE_MAN_TRUE@ ostree-checksum.1 ostree-commit.1 \ @ENABLE_MAN_TRUE@ ostree-create-usb.1 ostree-export.1 \ @@ -3306,14 +3284,17 @@ tests_test_commit_sign_sh_ext_LDADD = $(TESTS_LDADD) @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 ostree-prepare-root.1 \ -@ENABLE_MAN_TRUE@ $(am__append_96) $(am__append_97) +@ENABLE_MAN_TRUE@ $(am__append_95) $(am__append_96) @ENABLE_MAN_TRUE@man5_files = ostree.repo.5 ostree.repo-config.5 +@ENABLE_MAN_TRUE@man8_files = ostree-state-overlay@.service.8 @ENABLE_MAN_TRUE@man1_MANS = $(addprefix man/,$(man1_files)) @ENABLE_MAN_TRUE@man5_MANS = $(addprefix man/,$(man5_files)) +@ENABLE_MAN_TRUE@man8_MANS = $(addprefix man/,$(man8_files)) @ENABLE_MAN_TRUE@manhtml_files = \ @ENABLE_MAN_TRUE@ man/html/index.html \ @ENABLE_MAN_TRUE@ $(addprefix man/html/,$(man1_files:.1=.html)) \ @ENABLE_MAN_TRUE@ $(addprefix man/html/,$(man5_files:.5=.html)) \ +@ENABLE_MAN_TRUE@ $(addprefix man/html/,$(man8_files:.8=.html)) \ @ENABLE_MAN_TRUE@ $(NULL) @ENABLE_MAN_TRUE@XSLT_MAN_STYLESHEET = http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl @@ -3338,7 +3319,7 @@ all: $(BUILT_SOURCES) config.h .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs am--refresh: Makefile @: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile-decls.am $(top_srcdir)/buildutil/glib-tap.mk $(srcdir)/libglnx/Makefile-libglnx.am.inc $(srcdir)/bsdiff/Makefile-bsdiff.am.inc $(srcdir)/composefs/libcomposefs/Makefile-lib.am.inc $(srcdir)/Makefile-otutil.am $(srcdir)/Makefile-otcore.am $(srcdir)/Makefile-libostree.am $(srcdir)/Makefile-libostree-defines.am $(srcdir)/Makefile-ostree.am $(srcdir)/Makefile-switchroot.am $(srcdir)/src/rofiles-fuse/Makefile-inc.am $(srcdir)/Makefile-tests.am $(srcdir)/Makefile-boot.am $(srcdir)/Makefile-man.am $(srcdir)/Makefile-bash.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile-decls.am $(top_srcdir)/buildutil/glib-tap.mk $(srcdir)/libglnx/Makefile-libglnx.am.inc $(srcdir)/bsdiff/Makefile-bsdiff.am.inc $(srcdir)/Makefile-otutil.am $(srcdir)/Makefile-otcore.am $(srcdir)/Makefile-libostree.am $(srcdir)/Makefile-libostree-defines.am $(srcdir)/Makefile-ostree.am $(srcdir)/Makefile-switchroot.am $(srcdir)/src/rofiles-fuse/Makefile-inc.am $(srcdir)/Makefile-tests.am $(srcdir)/Makefile-boot.am $(srcdir)/Makefile-man.am $(srcdir)/Makefile-bash.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -3360,7 +3341,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; -$(srcdir)/Makefile-decls.am $(top_srcdir)/buildutil/glib-tap.mk $(srcdir)/libglnx/Makefile-libglnx.am.inc $(srcdir)/bsdiff/Makefile-bsdiff.am.inc $(srcdir)/composefs/libcomposefs/Makefile-lib.am.inc $(srcdir)/Makefile-otutil.am $(srcdir)/Makefile-otcore.am $(srcdir)/Makefile-libostree.am $(srcdir)/Makefile-libostree-defines.am $(srcdir)/Makefile-ostree.am $(srcdir)/Makefile-switchroot.am $(srcdir)/src/rofiles-fuse/Makefile-inc.am $(srcdir)/Makefile-tests.am $(srcdir)/Makefile-boot.am $(srcdir)/Makefile-man.am $(srcdir)/Makefile-bash.am $(am__empty): +$(srcdir)/Makefile-decls.am $(top_srcdir)/buildutil/glib-tap.mk $(srcdir)/libglnx/Makefile-libglnx.am.inc $(srcdir)/bsdiff/Makefile-bsdiff.am.inc $(srcdir)/Makefile-otutil.am $(srcdir)/Makefile-otcore.am $(srcdir)/Makefile-libostree.am $(srcdir)/Makefile-libostree-defines.am $(srcdir)/Makefile-ostree.am $(srcdir)/Makefile-switchroot.am $(srcdir)/src/rofiles-fuse/Makefile-inc.am $(srcdir)/Makefile-tests.am $(srcdir)/Makefile-boot.am $(srcdir)/Makefile-man.am $(srcdir)/Makefile-bash.am $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck @@ -3901,30 +3882,6 @@ src/libostree/bupsplit.lo: src/libostree/$(am__dirstamp) \ libbupsplit.la: $(libbupsplit_la_OBJECTS) $(libbupsplit_la_DEPENDENCIES) $(EXTRA_libbupsplit_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libbupsplit_la_OBJECTS) $(libbupsplit_la_LIBADD) $(LIBS) -composefs/libcomposefs/$(am__dirstamp): - @$(MKDIR_P) composefs/libcomposefs - @: > composefs/libcomposefs/$(am__dirstamp) -composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp): - @$(MKDIR_P) composefs/libcomposefs/$(DEPDIR) - @: > composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) -composefs/libcomposefs/libcomposefs_la-hash.lo: \ - composefs/libcomposefs/$(am__dirstamp) \ - composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) -composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo: \ - composefs/libcomposefs/$(am__dirstamp) \ - composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) -composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo: \ - composefs/libcomposefs/$(am__dirstamp) \ - composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) -composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo: \ - composefs/libcomposefs/$(am__dirstamp) \ - composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) -composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo: \ - composefs/libcomposefs/$(am__dirstamp) \ - composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) - -libcomposefs.la: $(libcomposefs_la_OBJECTS) $(libcomposefs_la_DEPENDENCIES) $(EXTRA_libcomposefs_la_DEPENDENCIES) - $(AM_V_CCLD)$(libcomposefs_la_LINK) $(am_libcomposefs_la_rpath) $(libcomposefs_la_OBJECTS) $(libcomposefs_la_LIBADD) $(LIBS) libglnx/$(am__dirstamp): @$(MKDIR_P) libglnx @: > libglnx/$(am__dirstamp) @@ -4348,6 +4305,9 @@ src/ostree/ostree-ot-admin-builtin-deploy.$(OBJEXT): \ src/ostree/ostree-ot-admin-builtin-finalize-staged.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) +src/ostree/ostree-ot-admin-builtin-lock-finalization.$(OBJEXT): \ + src/ostree/$(am__dirstamp) \ + src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/ostree-ot-admin-builtin-boot-complete.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) @@ -4381,12 +4341,18 @@ src/ostree/ostree-ot-admin-builtin-switch.$(OBJEXT): \ src/ostree/ostree-ot-admin-builtin-pin.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) +src/ostree/ostree-ot-admin-builtin-post-copy.$(OBJEXT): \ + src/ostree/$(am__dirstamp) \ + src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/ostree-ot-admin-builtin-upgrade.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/ostree-ot-admin-builtin-unlock.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) +src/ostree/ostree-ot-admin-builtin-state-overlay.$(OBJEXT): \ + src/ostree/$(am__dirstamp) \ + src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) @@ -4973,8 +4939,6 @@ mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f bsdiff/*.$(OBJEXT) -rm -f bsdiff/*.lo - -rm -f composefs/libcomposefs/*.$(OBJEXT) - -rm -f composefs/libcomposefs/*.lo -rm -f libglnx/*.$(OBJEXT) -rm -f libglnx/*.lo -rm -f libglnx/tests/*.$(OBJEXT) @@ -4995,11 +4959,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@bsdiff/$(DEPDIR)/libbsdiff_la-bsdiff.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@bsdiff/$(DEPDIR)/libbsdiff_la-bspatch.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libglnx/$(DEPDIR)/la-glnx-backport-testutils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libglnx/$(DEPDIR)/la-glnx-backports.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@libglnx/$(DEPDIR)/la-glnx-console.Plo@am__quote@ # am--include-marker @@ -5129,10 +5088,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-kargs.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-default.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-undeploy.Po@am__quote@ # am--include-marker @@ -5266,41 +5228,6 @@ bsdiff/libbsdiff_la-bspatch.lo: bsdiff/bspatch.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libbsdiff_la_CFLAGS) $(CFLAGS) -c -o bsdiff/libbsdiff_la-bspatch.lo `test -f 'bsdiff/bspatch.c' || echo '$(srcdir)/'`bsdiff/bspatch.c -composefs/libcomposefs/libcomposefs_la-hash.lo: composefs/libcomposefs/hash.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -MT composefs/libcomposefs/libcomposefs_la-hash.lo -MD -MP -MF composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Tpo -c -o composefs/libcomposefs/libcomposefs_la-hash.lo `test -f 'composefs/libcomposefs/hash.c' || echo '$(srcdir)/'`composefs/libcomposefs/hash.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Tpo composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='composefs/libcomposefs/hash.c' object='composefs/libcomposefs/libcomposefs_la-hash.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -c -o composefs/libcomposefs/libcomposefs_la-hash.lo `test -f 'composefs/libcomposefs/hash.c' || echo '$(srcdir)/'`composefs/libcomposefs/hash.c - -composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo: composefs/libcomposefs/lcfs-fsverity.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -MT composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo -MD -MP -MF composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Tpo -c -o composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo `test -f 'composefs/libcomposefs/lcfs-fsverity.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-fsverity.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Tpo composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='composefs/libcomposefs/lcfs-fsverity.c' object='composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -c -o composefs/libcomposefs/libcomposefs_la-lcfs-fsverity.lo `test -f 'composefs/libcomposefs/lcfs-fsverity.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-fsverity.c - -composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo: composefs/libcomposefs/lcfs-writer-erofs.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -MT composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo -MD -MP -MF composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Tpo -c -o composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo `test -f 'composefs/libcomposefs/lcfs-writer-erofs.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-writer-erofs.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Tpo composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='composefs/libcomposefs/lcfs-writer-erofs.c' object='composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -c -o composefs/libcomposefs/libcomposefs_la-lcfs-writer-erofs.lo `test -f 'composefs/libcomposefs/lcfs-writer-erofs.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-writer-erofs.c - -composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo: composefs/libcomposefs/lcfs-writer.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -MT composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo -MD -MP -MF composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Tpo -c -o composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo `test -f 'composefs/libcomposefs/lcfs-writer.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-writer.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Tpo composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='composefs/libcomposefs/lcfs-writer.c' object='composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -c -o composefs/libcomposefs/libcomposefs_la-lcfs-writer.lo `test -f 'composefs/libcomposefs/lcfs-writer.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-writer.c - -composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo: composefs/libcomposefs/lcfs-mount.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -MT composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo -MD -MP -MF composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Tpo -c -o composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo `test -f 'composefs/libcomposefs/lcfs-mount.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-mount.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Tpo composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='composefs/libcomposefs/lcfs-mount.c' object='composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcomposefs_la_CFLAGS) $(CFLAGS) -c -o composefs/libcomposefs/libcomposefs_la-lcfs-mount.lo `test -f 'composefs/libcomposefs/lcfs-mount.c' || echo '$(srcdir)/'`composefs/libcomposefs/lcfs-mount.c - libglnx/la-glnx-backport-testutils.lo: libglnx/glnx-backport-testutils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libglnx_la_CFLAGS) $(CFLAGS) -MT libglnx/la-glnx-backport-testutils.lo -MD -MP -MF libglnx/$(DEPDIR)/la-glnx-backport-testutils.Tpo -c -o libglnx/la-glnx-backport-testutils.lo `test -f 'libglnx/glnx-backport-testutils.c' || echo '$(srcdir)/'`libglnx/glnx-backport-testutils.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) libglnx/$(DEPDIR)/la-glnx-backport-testutils.Tpo libglnx/$(DEPDIR)/la-glnx-backport-testutils.Plo @@ -6456,6 +6383,20 @@ src/ostree/ostree-ot-admin-builtin-finalize-staged.obj: src/ostree/ot-admin-buil @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-finalize-staged.obj `if test -f 'src/ostree/ot-admin-builtin-finalize-staged.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-finalize-staged.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-finalize-staged.c'; fi` +src/ostree/ostree-ot-admin-builtin-lock-finalization.o: src/ostree/ot-admin-builtin-lock-finalization.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-lock-finalization.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Tpo -c -o src/ostree/ostree-ot-admin-builtin-lock-finalization.o `test -f 'src/ostree/ot-admin-builtin-lock-finalization.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-lock-finalization.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-lock-finalization.c' object='src/ostree/ostree-ot-admin-builtin-lock-finalization.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-lock-finalization.o `test -f 'src/ostree/ot-admin-builtin-lock-finalization.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-lock-finalization.c + +src/ostree/ostree-ot-admin-builtin-lock-finalization.obj: src/ostree/ot-admin-builtin-lock-finalization.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-lock-finalization.obj -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Tpo -c -o src/ostree/ostree-ot-admin-builtin-lock-finalization.obj `if test -f 'src/ostree/ot-admin-builtin-lock-finalization.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-lock-finalization.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-lock-finalization.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-lock-finalization.c' object='src/ostree/ostree-ot-admin-builtin-lock-finalization.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-lock-finalization.obj `if test -f 'src/ostree/ot-admin-builtin-lock-finalization.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-lock-finalization.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-lock-finalization.c'; fi` + src/ostree/ostree-ot-admin-builtin-boot-complete.o: src/ostree/ot-admin-builtin-boot-complete.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-boot-complete.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-boot-complete.Tpo -c -o src/ostree/ostree-ot-admin-builtin-boot-complete.o `test -f 'src/ostree/ot-admin-builtin-boot-complete.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-boot-complete.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-boot-complete.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-boot-complete.Po @@ -6610,6 +6551,20 @@ src/ostree/ostree-ot-admin-builtin-pin.obj: src/ostree/ot-admin-builtin-pin.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-pin.obj `if test -f 'src/ostree/ot-admin-builtin-pin.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-pin.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-pin.c'; fi` +src/ostree/ostree-ot-admin-builtin-post-copy.o: src/ostree/ot-admin-builtin-post-copy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-post-copy.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Tpo -c -o src/ostree/ostree-ot-admin-builtin-post-copy.o `test -f 'src/ostree/ot-admin-builtin-post-copy.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-post-copy.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-post-copy.c' object='src/ostree/ostree-ot-admin-builtin-post-copy.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-post-copy.o `test -f 'src/ostree/ot-admin-builtin-post-copy.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-post-copy.c + +src/ostree/ostree-ot-admin-builtin-post-copy.obj: src/ostree/ot-admin-builtin-post-copy.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-post-copy.obj -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Tpo -c -o src/ostree/ostree-ot-admin-builtin-post-copy.obj `if test -f 'src/ostree/ot-admin-builtin-post-copy.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-post-copy.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-post-copy.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-post-copy.c' object='src/ostree/ostree-ot-admin-builtin-post-copy.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-post-copy.obj `if test -f 'src/ostree/ot-admin-builtin-post-copy.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-post-copy.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-post-copy.c'; fi` + src/ostree/ostree-ot-admin-builtin-upgrade.o: src/ostree/ot-admin-builtin-upgrade.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-upgrade.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo -c -o src/ostree/ostree-ot-admin-builtin-upgrade.o `test -f 'src/ostree/ot-admin-builtin-upgrade.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-upgrade.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-upgrade.Po @@ -6638,6 +6593,20 @@ src/ostree/ostree-ot-admin-builtin-unlock.obj: src/ostree/ot-admin-builtin-unloc @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-unlock.obj `if test -f 'src/ostree/ot-admin-builtin-unlock.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-unlock.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-unlock.c'; fi` +src/ostree/ostree-ot-admin-builtin-state-overlay.o: src/ostree/ot-admin-builtin-state-overlay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-state-overlay.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Tpo -c -o src/ostree/ostree-ot-admin-builtin-state-overlay.o `test -f 'src/ostree/ot-admin-builtin-state-overlay.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-state-overlay.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-state-overlay.c' object='src/ostree/ostree-ot-admin-builtin-state-overlay.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-state-overlay.o `test -f 'src/ostree/ot-admin-builtin-state-overlay.c' || echo '$(srcdir)/'`src/ostree/ot-admin-builtin-state-overlay.c + +src/ostree/ostree-ot-admin-builtin-state-overlay.obj: src/ostree/ot-admin-builtin-state-overlay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-builtin-state-overlay.obj -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Tpo -c -o src/ostree/ostree-ot-admin-builtin-state-overlay.obj `if test -f 'src/ostree/ot-admin-builtin-state-overlay.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-state-overlay.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-state-overlay.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-admin-builtin-state-overlay.c' object='src/ostree/ostree-ot-admin-builtin-state-overlay.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-admin-builtin-state-overlay.obj `if test -f 'src/ostree/ot-admin-builtin-state-overlay.c'; then $(CYGPATH_W) 'src/ostree/ot-admin-builtin-state-overlay.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-admin-builtin-state-overlay.c'; fi` + src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.o: src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.Tpo -c -o src/ostree/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.o `test -f 'src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c' || echo '$(srcdir)/'`src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.Tpo src/ostree/$(DEPDIR)/ostree-ot-admin-instutil-builtin-selinux-ensure-labeled.Po @@ -7694,7 +7663,6 @@ mostlyclean-libtool: clean-libtool: -rm -rf .libs _libs -rm -rf bsdiff/.libs bsdiff/_libs - -rm -rf composefs/libcomposefs/.libs composefs/libcomposefs/_libs -rm -rf libglnx/.libs libglnx/_libs -rm -rf src/libostree/.libs src/libostree/_libs -rm -rf src/libotcore/.libs src/libotcore/_libs @@ -7785,6 +7753,47 @@ uninstall-man5: } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-dist_completionsDATA: $(dist_completions_DATA) @$(NORMAL_INSTALL) @list='$(dist_completions_DATA)'; test -n "$(completionsdir)" || list=; \ @@ -8862,6 +8871,20 @@ tests/test-admin-deploy-bootprefix.sh.log: tests/test-admin-deploy-bootprefix.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-admin-deploy-composefs.sh.log: tests/test-admin-deploy-composefs.sh + @p='tests/test-admin-deploy-composefs.sh'; \ + b='tests/test-admin-deploy-composefs.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-deploy-var.sh.log: tests/test-admin-deploy-var.sh + @p='tests/test-admin-deploy-var.sh'; \ + b='tests/test-admin-deploy-var.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-deploy-2.sh.log: tests/test-admin-deploy-2.sh @p='tests/test-admin-deploy-2.sh'; \ b='tests/test-admin-deploy-2.sh'; \ @@ -8995,6 +9018,13 @@ tests/test-admin-kargs.sh.log: tests/test-admin-kargs.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-admin-stateroot.sh.log: tests/test-admin-stateroot.sh + @p='tests/test-admin-stateroot.sh'; \ + b='tests/test-admin-stateroot.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-reset-nonlinear.sh.log: tests/test-reset-nonlinear.sh @p='tests/test-reset-nonlinear.sh'; \ b='tests/test-reset-nonlinear.sh'; \ @@ -9601,7 +9631,7 @@ install-privlibLTLIBRARIES: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(ostree_bootdir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(systemdsystemgeneratordir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(privlibdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(dracutmoddir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(mkinitcpioinstalldir)" "$(DESTDIR)$(ostree_bootdir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(completionsdir)" "$(DESTDIR)$(gpginsttestdir)" "$(DESTDIR)$(gpginsttest_revocdir)" "$(DESTDIR)$(gpginsttest_trusteddir)" "$(DESTDIR)$(gpgvinsttestdir)" "$(DESTDIR)$(systemdtmpfilesdir)" "$(DESTDIR)$(dracutconfdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(gpgreadmedir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_test_metadir)" "$(DESTDIR)$(mkinitcpioconfdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(systemdsystemunitdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libostreeincludedir)"; do \ + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(ostree_bootdir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(systemdsystemgeneratordir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(privlibdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(dracutmoddir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(mkinitcpioinstalldir)" "$(DESTDIR)$(ostree_bootdir)" "$(DESTDIR)$(pkglibexecdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(completionsdir)" "$(DESTDIR)$(gpginsttestdir)" "$(DESTDIR)$(gpginsttest_revocdir)" "$(DESTDIR)$(gpginsttest_trusteddir)" "$(DESTDIR)$(gpgvinsttestdir)" "$(DESTDIR)$(systemdtmpfilesdir)" "$(DESTDIR)$(dracutconfdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(gpgreadmedir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(installed_test_metadir)" "$(DESTDIR)$(mkinitcpioconfdir)" "$(DESTDIR)$(installed_testdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(systemdsystemunitdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libostreeincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) @@ -9638,8 +9668,6 @@ distclean-generic: -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f bsdiff/$(DEPDIR)/$(am__dirstamp) -rm -f bsdiff/$(am__dirstamp) - -rm -f composefs/libcomposefs/$(DEPDIR)/$(am__dirstamp) - -rm -f composefs/libcomposefs/$(am__dirstamp) -rm -f libglnx/$(DEPDIR)/$(am__dirstamp) -rm -f libglnx/$(am__dirstamp) -rm -f libglnx/tests/$(DEPDIR)/$(am__dirstamp) @@ -9678,11 +9706,6 @@ distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f bsdiff/$(DEPDIR)/libbsdiff_la-bsdiff.Plo -rm -f bsdiff/$(DEPDIR)/libbsdiff_la-bspatch.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-backport-testutils.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-backports.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-console.Plo @@ -9812,10 +9835,13 @@ distclean: distclean-recursive -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-kargs.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-default.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-undeploy.Po @@ -9956,7 +9982,7 @@ install-info: install-info-recursive install-info-am: -install-man: install-man1 install-man5 +install-man: install-man1 install-man5 install-man8 install-pdf: install-pdf-recursive @@ -9973,11 +9999,6 @@ maintainer-clean: maintainer-clean-recursive -rm -rf $(top_srcdir)/autom4te.cache -rm -f bsdiff/$(DEPDIR)/libbsdiff_la-bsdiff.Plo -rm -f bsdiff/$(DEPDIR)/libbsdiff_la-bspatch.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-hash.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-fsverity.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-mount.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer-erofs.Plo - -rm -f composefs/libcomposefs/$(DEPDIR)/libcomposefs_la-lcfs-writer.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-backport-testutils.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-backports.Plo -rm -f libglnx/$(DEPDIR)/la-glnx-console.Plo @@ -10107,10 +10128,13 @@ maintainer-clean: maintainer-clean-recursive -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-init-fs.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-instutil.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-kargs.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-lock-finalization.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-os-init.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-pin.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-post-copy.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-default.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-set-origin.Po + -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-state-overlay.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-status.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-switch.Po -rm -f src/ostree/$(DEPDIR)/ostree-ot-admin-builtin-undeploy.Po @@ -10238,7 +10262,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-systemdsystemgeneratorPROGRAMS \ uninstall-systemdsystemunitDATA uninstall-typelibDATA -uninstall-man: uninstall-man1 uninstall-man5 +uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8 .MAKE: $(am__recursive_targets) all check check-am install install-am \ install-data-am install-exec install-strip @@ -10272,7 +10296,7 @@ uninstall-man: uninstall-man1 uninstall-man5 install-installed_testPROGRAMS install-installed_testSCRIPTS \ install-installed_test_metaDATA install-libLTLIBRARIES \ install-libexecPROGRAMS install-libostreeincludeHEADERS \ - install-man install-man1 install-man5 \ + install-man install-man1 install-man5 install-man8 \ install-mkinitcpioconfDATA install-mkinitcpioinstallSCRIPTS \ install-nobase_installed_testDATA install-ostree_bootPROGRAMS \ install-ostree_bootSCRIPTS install-pdf install-pdf-am \ @@ -10298,7 +10322,7 @@ uninstall-man: uninstall-man1 uninstall-man5 uninstall-installed_testSCRIPTS \ uninstall-installed_test_metaDATA uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-libostreeincludeHEADERS \ - uninstall-man uninstall-man1 uninstall-man5 \ + uninstall-man uninstall-man1 uninstall-man5 uninstall-man8 \ uninstall-mkinitcpioconfDATA \ uninstall-mkinitcpioinstallSCRIPTS \ uninstall-nobase_installed_testDATA \ @@ -10413,6 +10437,9 @@ install-kola-tests: @ENABLE_MAN_TRUE@%.5: %.xml @ENABLE_MAN_TRUE@ $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $< +@ENABLE_MAN_TRUE@%.8: %.xml +@ENABLE_MAN_TRUE@ $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_MAN_STYLESHEET) $< + @ENABLE_MAN_TRUE@man/html/%.html: man/%.xml @ENABLE_MAN_TRUE@ @mkdir -p man/html @ENABLE_MAN_TRUE@ $(AM_V_GEN) $(XSLTPROC_MAN) --output $@ $(XSLT_HTML_STYLESHEET) $< diff --git a/README.md b/README.md index a5e97f7..fc85a32 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ The [machine-config-operator](https://github.com/openshift/machine-config-operat manages upgrades. RHEL CoreOS is also the successor to RHEL Atomic Host, which uses rpm-ostree as well. +[Red Hat In-Vehicle Operating System](https://www.redhat.com/en/blog/new-standard-red-hat-vehicle-operating-system-modern-and-future-vehicles) is a derivative of CentOS Automotive Stream Distribution that uses OSTree, it's closest Fedora derivative is Fedora IoT although it was created as it's own distribution. + [GNOME Continuous](https://wiki.gnome.org/Projects/GnomeContinuous) is where OSTree was born - as a high performance continuous delivery/testing system for GNOME. @@ -73,7 +75,10 @@ their host system as well as Flatpak. [Liri OS](https://liri.io/download/silverblue/) has the option to install their distribution using ostree. -[TorizonCore](https://developer.toradex.com/torizon/working-with-torizon/torizoncore-technical-overview/) is a Linux distribution for embedded systems that updates via OSTree images delivered via [Uptane](https://uptane.github.io/) and [aktualizr](https://github.com/uptane/aktualizr/). +[Torizon OS](https://developer.toradex.com/torizon/torizoncore/torizoncore-technical-overview/) +is a Linux distribution for embedded systems that updates via OSTree images +delivered via [Uptane](https://uptane.github.io/) and +[aktualizr](https://github.com/uptane/aktualizr/). ## Distribution build tools @@ -97,6 +102,10 @@ the build tool used to generate Fedora CoreOS derivatives. [debos](https://github.com/go-debos/debos) is a tool-chain for simplifying the process of building a Debian-based OS image. +[gardenlinux/ostree-image-builder](https://github.com/gardenlinux/ostree-image-builder) +is a sample for building Debian-based OS images. +It is not production ready but it might be useful to get started. + ## Projects linking to libostree [rpm-ostree](https://github.com/projectatomic/rpm-ostree) is used by the @@ -115,7 +124,10 @@ 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. -[aktualizr](https://github.com/uptane/aktualizr/) is an [Uptane](https://uptane.github.io/)-conformant software update client library intended for use in automotive and other security-sensitive embedded devices. It uses OSTree to manage the OS of the host device by default. +[aktualizr](https://github.com/uptane/aktualizr/) is an +[Uptane](https://uptane.github.io/)-conformant software update client library +intended for use in automotive and other security-sensitive embedded devices. +It uses OSTree to manage the OS of the host device by default. ## Language bindings diff --git a/aclocal.m4 b/aclocal.m4 index 94c6e7f..88e19b6 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -237,7 +237,7 @@ main (void) ]) # gpgme.m4 - autoconf macro to detect GPGME. -# Copyright (C) 2002, 2003, 2004, 2014, 2018 g10 Code GmbH +# Copyright (C) 2002, 2003, 2004, 2014, 2018, 2022 g10 Code GmbH # # This file is free software; as a special exception the author gives # unlimited permission to copy and/or distribute it, with or without @@ -247,13 +247,102 @@ main (void) # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # -# Last-changed: 2020-11-20 +# Last-changed: 2022-11-25 -AC_DEFUN([_AM_PATH_GPGME_CONFIG], -[ AC_ARG_WITH(gpgme-prefix, - AS_HELP_STRING([--with-gpgme-prefix=PFX], - [prefix where GPGME is installed (optional)]), +dnl +dnl Find gpgrt-config, which uses .pc file +dnl (minimum pkg-config functionality, supporting cross build) +dnl +dnl _AM_PATH_GPGRT_CONFIG +AC_DEFUN([_AM_PATH_GPGRT_CONFIG],[dnl + AC_PATH_PROG(GPGRT_CONFIG, gpgrt-config, no, [$prefix/bin:$PATH]) + if test "$GPGRT_CONFIG" != "no"; then + # Determine gpgrt_libdir + # + # Get the prefix of gpgrt-config assuming it's something like: + # /bin/gpgrt-config + gpgrt_prefix=${GPGRT_CONFIG%/*/*} + possible_libdir1=${gpgrt_prefix}/lib + # Determine by using system libdir-format with CC, it's like: + # Normal style: /usr/lib + # GNU cross style: /usr//lib + # Debian style: /usr/lib/ + # Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64 + # It is assumed that CC is specified to the one of host on cross build. + if libdir_candidates=$(${CC:-cc} -print-search-dirs | \ + sed -n -e "/^libraries/{s/libraries: =//;s/:/\\ +/g;p;}"); then + # From the output of -print-search-dirs, select valid pkgconfig dirs. + libdir_candidates=$(for dir in $libdir_candidates; do + if p=$(cd $dir 2>/dev/null && pwd); then + test -d "$p/pkgconfig" && echo $p; + fi + done) + + for possible_libdir0 in $libdir_candidates; do + # possible_libdir0: + # Fallback candidate, the one of system-installed (by $CC) + # (/usr//lib, /usr/lib/ or /usr/lib32) + # possible_libdir1: + # Another candidate, user-locally-installed + # (/lib) + # possible_libdir2 + # Most preferred + # (//lib, + # /lib/ or /lib32) + if test "${possible_libdir0##*/}" = "lib"; then + possible_prefix0=${possible_libdir0%/lib} + possible_prefix0_triplet=${possible_prefix0##*/} + if test -z "$possible_prefix0_triplet"; then + continue + fi + possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib + else + possible_prefix0=${possible_libdir0%%/lib*} + possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0} + fi + if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir2} + elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir1} + elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir0} + fi + if test -n "$gpgrt_libdir"; then break; fi + done + if test -z "$libdir_candidates"; then + # No valid pkgconfig dir in any of the system directories, fallback + gpgrt_libdir=${possible_libdir1} + fi + else + # When we cannot determine system libdir-format, use this: + gpgrt_libdir=${possible_libdir1} + fi + else + unset GPGRT_CONFIG + fi + + if test -n "$gpgrt_libdir"; then + GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir" + if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then + GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error" + AC_MSG_NOTICE([Use gpgrt-config with $gpgrt_libdir as gpg-error-config]) + gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion` + else + unset GPGRT_CONFIG + fi + elif test "$GPG_ERROR_CONFIG" != "no"; then + gpg_error_config_version=`$GPG_ERROR_CONFIG --version` + unset GPGRT_CONFIG + fi +]) + +AC_DEFUN([_AM_PATH_GPGME_CONFIG],[dnl +AC_REQUIRE([_AM_PATH_GPGRT_CONFIG])dnl + AC_ARG_WITH(gpgme-prefix, + AS_HELP_STRING([--with-gpgme-prefix=PFX], + [prefix where GPGME is installed (optional)]), gpgme_config_prefix="$withval", gpgme_config_prefix="") if test x"${GPGME_CONFIG}" = x ; then if test x"${gpgme_config_prefix}" != x ; then @@ -275,7 +364,7 @@ AC_DEFUN([_AM_PATH_GPGME_CONFIG], fi use_gpgrt_config="" - if test x"${GPGME_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then + if test x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then if $GPGRT_CONFIG gpgme --exists; then GPGME_CONFIG="$GPGRT_CONFIG gpgme" AC_MSG_NOTICE([Use gpgrt-config as gpgme-config]) @@ -407,8 +496,9 @@ dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libgpgme and define GPGME_PTHREAD_CFLAGS dnl and GPGME_PTHREAD_LIBS. dnl -AC_DEFUN([AM_PATH_GPGME_PTHREAD], -[ AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl +AC_DEFUN([AM_PATH_GPGME_PTHREAD],[ + AC_OBSOLETE([$0], [; use AM_PATH_GPGME instead to use GPGME_CFLAGS and GPGME_LIBS])dnl + AC_REQUIRE([_AM_PATH_GPGME_CONFIG])dnl tmp=ifelse([$1], ,1:0.4.2,$1) if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` @@ -421,35 +511,37 @@ AC_DEFUN([AM_PATH_GPGME_PTHREAD], AC_MSG_CHECKING(for GPGME pthread - version >= $min_gpgme_version) ok=no if test "$GPGME_CONFIG" != "no" ; then - if `$GPGME_CONFIG --thread=pthread 2> /dev/null` ; then - req_major=`echo $min_gpgme_version | \ + req_major=`echo $min_gpgme_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` - req_minor=`echo $min_gpgme_version | \ + req_minor=`echo $min_gpgme_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` - req_micro=`echo $min_gpgme_version | \ + req_micro=`echo $min_gpgme_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` - if test "$gpgme_version_major" -gt "$req_major"; then + if test "$gpgme_version_major" -gt "$req_major"; then ok=yes - else + else if test "$gpgme_version_major" -eq "$req_major"; then - if test "$gpgme_version_minor" -gt "$req_minor"; then - ok=yes - else - if test "$gpgme_version_minor" -eq "$req_minor"; then - if test "$gpgme_version_micro" -ge "$req_micro"; then - ok=yes - fi + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi fi - fi fi - fi fi fi if test $ok = yes; then # If we have a recent GPGME, we should also check that the # API is compatible. if test "$req_gpgme_api" -gt 0 ; then - tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test -z "$use_gpgrt_config"; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$GPGME_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi if test "$tmp" -gt 0 ; then if test "$req_gpgme_api" -ne "$tmp" ; then ok=no @@ -458,8 +550,8 @@ AC_DEFUN([AM_PATH_GPGME_PTHREAD], fi fi if test $ok = yes; then - GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --thread=pthread --cflags` - GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --thread=pthread --libs` + GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --libs` AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) _AM_PATH_GPGME_CONFIG_HOST_CHECK @@ -701,8 +793,8 @@ AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 11 (pkg-config-0.29.1) +# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson @@ -744,7 +836,7 @@ dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.1]) +[m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ @@ -789,7 +881,7 @@ dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -dnl only at the first occurence in configure.ac, so if the first place +dnl only at the first occurrence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], @@ -845,7 +937,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $1]) +AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -855,17 +947,17 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD - m4_default([$4], [AC_MSG_ERROR( + m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS @@ -876,8 +968,8 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) - m4_default([$4], [AC_MSG_FAILURE( + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. @@ -887,10 +979,10 @@ _PKG_TEXT To get pkg-config, see .])[]dnl ]) else - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) - $3 + $3 fi[]dnl ])dnl PKG_CHECK_MODULES diff --git a/apidoc/Makefile.in b/apidoc/Makefile.in index 4abac48..a17e46e 100644 --- a/apidoc/Makefile.in +++ b/apidoc/Makefile.in @@ -235,6 +235,7 @@ GOBJECT_QUERY = @GOBJECT_QUERY@ GPGME_CONFIG = @GPGME_CONFIG@ GPGME_PTHREAD_CFLAGS = @GPGME_PTHREAD_CFLAGS@ GPGME_PTHREAD_LIBS = @GPGME_PTHREAD_LIBS@ +GPGRT_CONFIG = @GPGRT_CONFIG@ GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ GREP = @GREP@ GRUB2_MKCONFIG = @GRUB2_MKCONFIG@ @@ -282,6 +283,8 @@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ OT_DEP_AVAHI_CFLAGS = @OT_DEP_AVAHI_CFLAGS@ OT_DEP_AVAHI_LIBS = @OT_DEP_AVAHI_LIBS@ +OT_DEP_COMPOSEFS_CFLAGS = @OT_DEP_COMPOSEFS_CFLAGS@ +OT_DEP_COMPOSEFS_LIBS = @OT_DEP_COMPOSEFS_LIBS@ OT_DEP_CRYPTO_CFLAGS = @OT_DEP_CRYPTO_CFLAGS@ OT_DEP_CRYPTO_LIBS = @OT_DEP_CRYPTO_LIBS@ OT_DEP_CURL_CFLAGS = @OT_DEP_CURL_CFLAGS@ @@ -851,7 +854,7 @@ scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ - gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ @@ -897,13 +900,13 @@ xml/gtkdocentities.ent: Makefile html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ - gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ - gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\--path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ @@ -920,7 +923,7 @@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_con pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ - gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ @@ -929,7 +932,7 @@ pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_cont if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ - echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + echo $$mkpdf_options | grep >/dev/null "\--imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ @@ -943,10 +946,10 @@ pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_cont clean-local: @rm -f *~ *.bak @rm -rf .libs - @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + @if echo $(SCAN_OPTIONS) | grep -q "\--rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi - @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + @if echo $(SCAN_OPTIONS) | grep -q "\--rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi diff --git a/apidoc/html/index.html b/apidoc/html/index.html index b651901..bd623aa 100644 --- a/apidoc/html/index.html +++ b/apidoc/html/index.html @@ -14,7 +14,7 @@
-

for OSTree 2023.6

+

for OSTree 2024.6


diff --git a/apidoc/html/ostree-Root-partition-mount-point.html b/apidoc/html/ostree-Root-partition-mount-point.html index 8461c18..28f2b93 100644 --- a/apidoc/html/ostree-Root-partition-mount-point.html +++ b/apidoc/html/ostree-Root-partition-mount-point.html @@ -145,6 +145,14 @@

+gboolean + + +ostree_sysroot_update_post_copy () + + + + void @@ -388,6 +396,14 @@

gboolean +ostree_sysroot_change_finalization () + + + + +gboolean + + ostree_sysroot_deploy_tree () @@ -870,6 +886,40 @@

+

ostree_sysroot_update_post_copy ()

+
gboolean
+ostree_sysroot_update_post_copy (OstreeSysroot *self,
+                                 GCancellable *cancellable,
+                                 GError **error);
+

Update a sysroot as needed after having copied it into place using file-level +operations. This enables options like fs-verity on the required files that may +have been lost during the copy.

+
+

Parameters

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

self

Sysroot

 

error

Error

 
+
+

Since: 2023.11

+ +
+

ostree_sysroot_set_mount_namespace_in_use ()

void
 ostree_sysroot_set_mount_namespace_in_use
@@ -2082,6 +2132,45 @@ 

+

ostree_sysroot_change_finalization ()

+
gboolean
+ostree_sysroot_change_finalization (OstreeSysroot *self,
+                                    OstreeDeployment *deployment,
+                                    GError **error);
+

Given the target deployment (which must be the staged deployment) this API +will toggle its "finalization locking" state. If it is currently locked, +it will be unlocked (and hence queued to apply on shutdown).

+
+

Parameters

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

self

Sysroot

 

deployment

Deployment which must be staged

 

error

Error

 
+
+

Since: 2023.8

+

+
+

ostree_sysroot_deploy_tree ()

gboolean
 ostree_sysroot_deploy_tree (OstreeSysroot *self,
diff --git a/apidoc/html/ostree-SELinux-policy-management.html b/apidoc/html/ostree-SELinux-policy-management.html
index 116c2ac..2a6bff2 100644
--- a/apidoc/html/ostree-SELinux-policy-management.html
+++ b/apidoc/html/ostree-SELinux-policy-management.html
@@ -314,7 +314,7 @@ 

Returns

Type of current policy.

-

[transfer none]

+

[transfer none][nullable]


diff --git a/apidoc/html/ostree-ostree-deployment.html b/apidoc/html/ostree-ostree-deployment.html index b77de84..4ef84dc 100644 --- a/apidoc/html/ostree-ostree-deployment.html +++ b/apidoc/html/ostree-ostree-deployment.html @@ -158,6 +158,14 @@

< +gboolean + + +ostree_deployment_is_finalization_locked () + + + + void @@ -545,6 +553,34 @@

<
+

ostree_deployment_is_finalization_locked ()

+
gboolean
+ostree_deployment_is_finalization_locked
+                               (OstreeDeployment *self);
+
+

Parameters

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

self

Deployment

 
+
+
+

Returns

+

TRUE if deployment is queued to be "finalized" at shutdown time, but requires +additional action.

+
+

Since: 2023.8

+
+
+

ostree_deployment_set_index ()

void
 ostree_deployment_set_index (OstreeDeployment *self,
@@ -757,6 +793,7 @@ 

< GKeyFile *origin; OstreeDeploymentUnlockedState unlocked; gboolean staged; + gboolean finalization_locked; char **overlay_initrds; char *overlay_initrds_id; } OstreeDeployment; @@ -821,6 +858,11 @@

<   +

gboolean finalization_locked;

+  +  + +

char **overlay_initrds;

Checksums of staged additional initrds for this deployment

  diff --git a/apidoc/html/ostree-ostree-version.html b/apidoc/html/ostree-ostree-version.html index e5d04d1..78a663c 100644 --- a/apidoc/html/ostree-ostree-version.html +++ b/apidoc/html/ostree-ostree-version.html @@ -117,7 +117,7 @@

Types and Values

OSTREE_YEAR_VERSION

-
#define OSTREE_YEAR_VERSION (2023)
+
#define OSTREE_YEAR_VERSION (2024)
 

ostree year version component (e.g. 2017 if OSTREE_VERSION is 2017.2)

Since: 2017.4

@@ -125,7 +125,7 @@


OSTREE_RELEASE_VERSION

-
#define OSTREE_RELEASE_VERSION (7)
+
#define OSTREE_RELEASE_VERSION (6)
 

ostree release version component (e.g. 2 if OSTREE_VERSION is 2017.2)

Since: 2017.4

@@ -133,7 +133,7 @@


OSTREE_VERSION

-
#define OSTREE_VERSION (2023.7)
+
#define OSTREE_VERSION (2024.6)
 

ostree version.

Since: 2017.4

@@ -141,7 +141,7 @@


OSTREE_VERSION_S

-
#define OSTREE_VERSION_S "2023.7"
+
#define OSTREE_VERSION_S "2024.6"
 

ostree version, encoded as a string, useful for printing and concatenation.

diff --git a/apidoc/html/ostree.devhelp2 b/apidoc/html/ostree.devhelp2 index d905114..ea7a8fe 100644 --- a/apidoc/html/ostree.devhelp2 +++ b/apidoc/html/ostree.devhelp2 @@ -316,6 +316,7 @@ + @@ -346,6 +347,7 @@ + @@ -454,6 +456,7 @@ + @@ -669,6 +672,7 @@ + diff --git a/apidoc/html/reference.html b/apidoc/html/reference.html index 27b6865..dc305c1 100644 --- a/apidoc/html/reference.html +++ b/apidoc/html/reference.html @@ -451,6 +451,10 @@
+ostree_deployment_is_finalization_locked, function in ostree-deployment +
+
+
ostree_deployment_is_pinned, function in ostree-deployment
@@ -1896,6 +1900,10 @@
+ostree_sysroot_change_finalization, function in Root partition mount point +
+
+
ostree_sysroot_cleanup, function in Root partition mount point
@@ -2080,6 +2088,10 @@
+ostree_sysroot_update_post_copy, function in Root partition mount point +
+
+
ostree_sysroot_upgrader_check_timestamps, function in Simple upgrade class
diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index af57d7c..42bbe69 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -191,6 +191,7 @@ ostree_deployment_get_origin_relpath ostree_deployment_get_unlocked ostree_deployment_is_pinned ostree_deployment_is_staged +ostree_deployment_is_finalization_locked ostree_deployment_set_index ostree_deployment_set_bootserial ostree_deployment_set_bootconfig @@ -560,6 +561,7 @@ ostree_sysroot_lock_async ostree_sysroot_lock_finish ostree_sysroot_unlock ostree_sysroot_unload +ostree_sysroot_update_post_copy ostree_sysroot_set_mount_namespace_in_use ostree_sysroot_is_booted ostree_sysroot_get_fd @@ -590,6 +592,7 @@ ostree_sysroot_write_origin_file ostree_sysroot_stage_tree ostree_sysroot_stage_tree_with_options ostree_sysroot_stage_overlay_initrd +ostree_sysroot_change_finalization ostree_sysroot_deploy_tree ostree_sysroot_deploy_tree_with_options ostree_sysroot_get_merge_deployment diff --git a/apidoc/version.xml b/apidoc/version.xml index e7b67ba..54b2c56 100644 --- a/apidoc/version.xml +++ b/apidoc/version.xml @@ -1 +1 @@ -2023.6 \ No newline at end of file +2024.6 \ No newline at end of file diff --git a/autogen.sh b/autogen.sh index ea2412c..689bba8 100755 --- a/autogen.sh +++ b/autogen.sh @@ -35,7 +35,6 @@ fi # changing this, please also change Makefile.am. sed -e 's,$(libglnx_srcpath),libglnx,g' < libglnx/Makefile-libglnx.am >libglnx/Makefile-libglnx.am.inc sed -e 's,$(libbsdiff_srcpath),bsdiff,g' < bsdiff/Makefile-bsdiff.am >bsdiff/Makefile-bsdiff.am.inc -sed -e 's,$(COMPOSEFSDIR),composefs/libcomposefs,g' < composefs/libcomposefs/Makefile-lib.am >composefs/libcomposefs/Makefile-lib.am.inc # FIXME - figure out how to get aclocal to find this by default ln -sf ../libglnx/libglnx.m4 buildutil/libglnx.m4 diff --git a/build-aux/config.guess b/build-aux/config.guess index c7f17e8..e7a6fe3 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -1,10 +1,10 @@ #!/usr/bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-05-25' +timestamp='2023-06-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] -Output the configuration name of the system \`$me' is run on. +Output the configuration name of the system '$me' is run on. Options: -h, --help print this help, then exit @@ -60,13 +60,13 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -102,8 +102,8 @@ GUESS= # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. +# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still +# use 'HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. @@ -459,7 +459,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in UNAME_RELEASE=`uname -v` ;; esac - # Japanese Language versions have a version number like `4.1.3-JL'. + # Japanese Language versions have a version number like '4.1.3-JL'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; @@ -966,6 +966,12 @@ EOF GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; + x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-pc-managarm-mlibc" + ;; + *:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" + ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; @@ -1036,7 +1042,7 @@ EOF k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; - loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) + loongarch32:Linux:*:* | loongarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) @@ -1191,7 +1197,7 @@ EOF GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility + # If we were able to find 'uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; @@ -1332,7 +1338,7 @@ EOF GUESS=ns32k-sni-sysv fi ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; diff --git a/build-aux/config.sub b/build-aux/config.sub index b41da55..a6d99a0 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -1,10 +1,10 @@ #!/usr/bin/sh # Configuration validation subroutine script. -# Copyright 1992-2022 Free Software Foundation, Inc. +# Copyright 1992-2023 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-01-03' +timestamp='2023-06-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,13 +76,13 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2022 Free Software Foundation, Inc. +Copyright 1992-2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" -Try \`$me --help' for more information." +Try '$me --help' for more information." # Parse command line while test $# -gt 0 ; do @@ -130,7 +130,7 @@ IFS=$saved_IFS # Separate into logical components for further validation case $1 in *-*-*-*-*) - echo Invalid configuration \`"$1"\': more than four components >&2 + echo "Invalid configuration '$1': more than four components" >&2 exit 1 ;; *-*-*-*) @@ -145,7 +145,7 @@ case $1 in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ - | storm-chaos* | os2-emx* | rtmk-nova*) + | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) basic_machine=$field1 basic_os=$maybe_os ;; @@ -943,7 +943,7 @@ $basic_machine EOF IFS=$saved_IFS ;; - # We use `pc' rather than `unknown' + # We use 'pc' rather than 'unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) @@ -1075,7 +1075,7 @@ case $cpu-$vendor in pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) cpu=i586 ;; - pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*) cpu=i686 ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) @@ -1207,7 +1207,7 @@ case $cpu-$vendor in | k1om \ | le32 | le64 \ | lm32 \ - | loongarch32 | loongarch64 | loongarchx32 \ + | loongarch32 | loongarch64 \ | m32c | m32r | m32rle \ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ @@ -1285,7 +1285,7 @@ case $cpu-$vendor in ;; *) - echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2 exit 1 ;; esac @@ -1341,6 +1341,10 @@ EOF kernel=linux os=`echo "$basic_os" | sed -e 's|linux|gnu|'` ;; + managarm*) + kernel=managarm + os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'` + ;; *) kernel= os=$basic_os @@ -1754,7 +1758,7 @@ case $os in | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ - | fiwix* ) + | fiwix* | mlibc* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) @@ -1762,8 +1766,11 @@ case $os in ;; none) ;; + kernel* ) + # Restricted further below + ;; *) - echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2 + echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 exit 1 ;; esac @@ -1772,14 +1779,24 @@ esac # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ - | linux-musl* | linux-relibc* | linux-uclibc* ) + | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) ;; uclinux-uclibc* ) ;; - -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* ) + managarm-mlibc* | managarm-kernel* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. - echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 + exit 1 + ;; + -kernel* ) + echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 + exit 1 + ;; + *-kernel* ) + echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) @@ -1796,7 +1813,7 @@ case $kernel-$os in # Blank kernel with real OS is always fine. ;; *-*) - echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; esac diff --git a/composefs/libcomposefs/Makefile-lib.am b/composefs/libcomposefs/Makefile-lib.am deleted file mode 100644 index 4b4d401..0000000 --- a/composefs/libcomposefs/Makefile-lib.am +++ /dev/null @@ -1,22 +0,0 @@ -COMPOSEFS_HASH_CFLAGS = -DUSE_OBSTACK=0 -DTESTING=0 -DUSE_DIFF_HASH=0 - -libcomposefs_la_SOURCES = \ - $(COMPOSEFSDIR)/bitrotate.h \ - $(COMPOSEFSDIR)/erofs_fs.h \ - $(COMPOSEFSDIR)/erofs_fs_wrapper.h \ - $(COMPOSEFSDIR)/hash.c \ - $(COMPOSEFSDIR)/hash.h \ - $(COMPOSEFSDIR)/lcfs-internal.h \ - $(COMPOSEFSDIR)/lcfs-erofs.h \ - $(COMPOSEFSDIR)/lcfs-erofs-internal.h \ - $(COMPOSEFSDIR)/lcfs-fsverity.c \ - $(COMPOSEFSDIR)/lcfs-fsverity.h \ - $(COMPOSEFSDIR)/lcfs-writer-erofs.c \ - $(COMPOSEFSDIR)/lcfs-writer.c \ - $(COMPOSEFSDIR)/lcfs-writer.h \ - $(COMPOSEFSDIR)/lcfs-utils.h \ - $(COMPOSEFSDIR)/lcfs-mount.c \ - $(COMPOSEFSDIR)/lcfs-mount.h \ - $(COMPOSEFSDIR)/xalloc-oversized.h -libcomposefs_la_CFLAGS = $(WARN_CFLAGS) $(COMPOSEFS_HASH_CFLAGS) $(LCFS_DEP_CRYPTO_CFLAGS) $(HIDDEN_VISIBILITY_CFLAGS) -libcomposefs_la_LIBADD = $(LCFS_DEP_CRYPTO_LIBS) diff --git a/composefs/libcomposefs/Makefile-lib.am.inc b/composefs/libcomposefs/Makefile-lib.am.inc deleted file mode 100644 index 4d1012a..0000000 --- a/composefs/libcomposefs/Makefile-lib.am.inc +++ /dev/null @@ -1,22 +0,0 @@ -COMPOSEFS_HASH_CFLAGS = -DUSE_OBSTACK=0 -DTESTING=0 -DUSE_DIFF_HASH=0 - -libcomposefs_la_SOURCES = \ - composefs/libcomposefs/bitrotate.h \ - composefs/libcomposefs/erofs_fs.h \ - composefs/libcomposefs/erofs_fs_wrapper.h \ - composefs/libcomposefs/hash.c \ - composefs/libcomposefs/hash.h \ - composefs/libcomposefs/lcfs-internal.h \ - composefs/libcomposefs/lcfs-erofs.h \ - composefs/libcomposefs/lcfs-erofs-internal.h \ - composefs/libcomposefs/lcfs-fsverity.c \ - composefs/libcomposefs/lcfs-fsverity.h \ - composefs/libcomposefs/lcfs-writer-erofs.c \ - composefs/libcomposefs/lcfs-writer.c \ - composefs/libcomposefs/lcfs-writer.h \ - composefs/libcomposefs/lcfs-utils.h \ - composefs/libcomposefs/lcfs-mount.c \ - composefs/libcomposefs/lcfs-mount.h \ - composefs/libcomposefs/xalloc-oversized.h -libcomposefs_la_CFLAGS = $(WARN_CFLAGS) $(COMPOSEFS_HASH_CFLAGS) $(LCFS_DEP_CRYPTO_CFLAGS) $(HIDDEN_VISIBILITY_CFLAGS) -libcomposefs_la_LIBADD = $(LCFS_DEP_CRYPTO_LIBS) diff --git a/composefs/libcomposefs/bitrotate.h b/composefs/libcomposefs/bitrotate.h deleted file mode 100644 index 8e8016c..0000000 --- a/composefs/libcomposefs/bitrotate.h +++ /dev/null @@ -1,135 +0,0 @@ -/* bitrotate.h - Rotate bits in integers - Copyright (C) 2008-2021 Free Software Foundation, Inc. - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -/* Written by Simon Josefsson , 2008. */ - -#ifndef _GL_BITROTATE_H -#define _GL_BITROTATE_H - -#include -#include -#include - -#define _GL_INLINE static inline -#define _GL_ATTRIBUTE_CONST const - -#ifndef BITROTATE_INLINE -# define BITROTATE_INLINE _GL_INLINE -#endif - -#ifdef UINT64_MAX -/* Given an unsigned 64-bit argument X, return the value corresponding - to rotating the bits N steps to the left. N must be between 1 and - 63 inclusive. */ -BITROTATE_INLINE uint64_t -rotl64 (uint64_t x, int n) -{ - return ((x << n) | (x >> (64 - n))) & UINT64_MAX; -} - -/* Given an unsigned 64-bit argument X, return the value corresponding - to rotating the bits N steps to the right. N must be between 1 to - 63 inclusive.*/ -BITROTATE_INLINE uint64_t -rotr64 (uint64_t x, int n) -{ - return ((x >> n) | (x << (64 - n))) & UINT64_MAX; -} -#endif - -/* Given an unsigned 32-bit argument X, return the value corresponding - to rotating the bits N steps to the left. N must be between 1 and - 31 inclusive. */ -BITROTATE_INLINE uint32_t -rotl32 (uint32_t x, int n) -{ - return ((x << n) | (x >> (32 - n))) & UINT32_MAX; -} - -/* Given an unsigned 32-bit argument X, return the value corresponding - to rotating the bits N steps to the right. N must be between 1 to - 31 inclusive.*/ -BITROTATE_INLINE uint32_t -rotr32 (uint32_t x, int n) -{ - return ((x >> n) | (x << (32 - n))) & UINT32_MAX; -} - -/* Given a size_t argument X, return the value corresponding - to rotating the bits N steps to the left. N must be between 1 and - (CHAR_BIT * sizeof (size_t) - 1) inclusive. */ -BITROTATE_INLINE size_t -rotl_sz (size_t x, int n) -{ - return ((x << n) | (x >> ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX; -} - -/* Given a size_t argument X, return the value corresponding - to rotating the bits N steps to the right. N must be between 1 to - (CHAR_BIT * sizeof (size_t) - 1) inclusive. */ -BITROTATE_INLINE size_t -rotr_sz (size_t x, int n) -{ - return ((x >> n) | (x << ((CHAR_BIT * sizeof x) - n))) & SIZE_MAX; -} - -/* Given an unsigned 16-bit argument X, return the value corresponding - to rotating the bits N steps to the left. N must be between 1 to - 15 inclusive, but on most relevant targets N can also be 0 and 16 - because 'int' is at least 32 bits and the arguments must widen - before shifting. */ -BITROTATE_INLINE uint16_t -rotl16 (uint16_t x, int n) -{ - return (((unsigned int) x << n) | ((unsigned int) x >> (16 - n))) - & UINT16_MAX; -} - -/* Given an unsigned 16-bit argument X, return the value corresponding - to rotating the bits N steps to the right. N must be in 1 to 15 - inclusive, but on most relevant targets N can also be 0 and 16 - because 'int' is at least 32 bits and the arguments must widen - before shifting. */ -BITROTATE_INLINE uint16_t -rotr16 (uint16_t x, int n) -{ - return (((unsigned int) x >> n) | ((unsigned int) x << (16 - n))) - & UINT16_MAX; -} - -/* Given an unsigned 8-bit argument X, return the value corresponding - to rotating the bits N steps to the left. N must be between 1 to 7 - inclusive, but on most relevant targets N can also be 0 and 8 - because 'int' is at least 32 bits and the arguments must widen - before shifting. */ -BITROTATE_INLINE uint8_t -rotl8 (uint8_t x, int n) -{ - return (((unsigned int) x << n) | ((unsigned int) x >> (8 - n))) & UINT8_MAX; -} - -/* Given an unsigned 8-bit argument X, return the value corresponding - to rotating the bits N steps to the right. N must be in 1 to 7 - inclusive, but on most relevant targets N can also be 0 and 8 - because 'int' is at least 32 bits and the arguments must widen - before shifting. */ -BITROTATE_INLINE uint8_t -rotr8 (uint8_t x, int n) -{ - return (((unsigned int) x >> n) | ((unsigned int) x << (8 - n))) & UINT8_MAX; -} - -#endif /* _GL_BITROTATE_H */ diff --git a/composefs/libcomposefs/erofs_fs.h b/composefs/libcomposefs/erofs_fs.h deleted file mode 100644 index a03ec70..0000000 --- a/composefs/libcomposefs/erofs_fs.h +++ /dev/null @@ -1,461 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ -/* - * EROFS (Enhanced ROM File System) on-disk format definition - * - * Copyright (C) 2017-2018 HUAWEI, Inc. - * https://www.huawei.com/ - * Copyright (C) 2021, Alibaba Cloud - */ -#ifndef __EROFS_FS_H -#define __EROFS_FS_H - -#define EROFS_SUPER_OFFSET 1024 - -#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 -#define EROFS_FEATURE_COMPAT_MTIME 0x00000002 -#define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 - -/* - * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should - * be incompatible with this kernel version. - */ -#define EROFS_FEATURE_INCOMPAT_ZERO_PADDING 0x00000001 -#define EROFS_FEATURE_INCOMPAT_COMPR_CFGS 0x00000002 -#define EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER 0x00000002 -#define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004 -#define EROFS_FEATURE_INCOMPAT_DEVICE_TABLE 0x00000008 -#define EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 0x00000008 -#define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010 -#define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020 -#define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020 -#define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040 -#define EROFS_ALL_FEATURE_INCOMPAT \ - (EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \ - EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \ - EROFS_FEATURE_INCOMPAT_BIG_PCLUSTER | \ - EROFS_FEATURE_INCOMPAT_CHUNKED_FILE | \ - EROFS_FEATURE_INCOMPAT_DEVICE_TABLE | \ - EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \ - EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \ - EROFS_FEATURE_INCOMPAT_FRAGMENTS | \ - EROFS_FEATURE_INCOMPAT_DEDUPE | \ - EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES) - -#define EROFS_SB_EXTSLOT_SIZE 16 - -struct erofs_deviceslot { - u8 tag[64]; /* digest(sha256), etc. */ - __le32 blocks; /* total fs blocks of this device */ - __le32 mapped_blkaddr; /* map starting at mapped_blkaddr */ - u8 reserved[56]; -}; -#define EROFS_DEVT_SLOT_SIZE sizeof(struct erofs_deviceslot) - -/* erofs on-disk super block (currently 128 bytes) */ -struct erofs_super_block { - __le32 magic; /* file system magic number */ - __le32 checksum; /* crc32c(super_block) */ - __le32 feature_compat; - __u8 blkszbits; /* filesystem block size in bit shift */ - __u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */ - - __le16 root_nid; /* nid of root directory */ - __le64 inos; /* total valid ino # (== f_files - f_favail) */ - - __le64 build_time; /* compact inode time derivation */ - __le32 build_time_nsec; /* compact inode time derivation in ns scale */ - __le32 blocks; /* used for statfs */ - __le32 meta_blkaddr; /* start block address of metadata area */ - __le32 xattr_blkaddr; /* start block address of shared xattr area */ - __u8 uuid[16]; /* 128-bit uuid for volume */ - __u8 volume_name[16]; /* volume name */ - __le32 feature_incompat; - union { - /* bitmap for available compression algorithms */ - __le16 available_compr_algs; - /* customized sliding window size instead of 64k by default */ - __le16 lz4_max_distance; - } __packed u1; - __le16 extra_devices; /* # of devices besides the primary device */ - __le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */ - __u8 dirblkbits; /* directory block size in bit shift */ - __u8 xattr_prefix_count; /* # of long xattr name prefixes */ - __le32 xattr_prefix_start; /* start of long xattr prefixes */ - __le64 packed_nid; /* nid of the special packed inode */ - __u8 xattr_filter_reserved; /* reserved for xattr name filter */ - __u8 reserved2[23]; -}; - -/* - * EROFS inode datalayout (i_format in on-disk inode): - * 0 - uncompressed flat inode without tail-packing inline data: - * 1 - compressed inode with non-compact indexes: - * 2 - uncompressed flat inode with tail-packing inline data: - * 3 - compressed inode with compact indexes: - * 4 - chunk-based inode with (optional) multi-device support: - * 5~7 - reserved - */ -enum { - EROFS_INODE_FLAT_PLAIN = 0, - EROFS_INODE_COMPRESSED_FULL = 1, - EROFS_INODE_FLAT_INLINE = 2, - EROFS_INODE_COMPRESSED_COMPACT = 3, - EROFS_INODE_CHUNK_BASED = 4, - EROFS_INODE_DATALAYOUT_MAX -}; - -static inline bool erofs_inode_is_data_compressed(unsigned int datamode) -{ - return datamode == EROFS_INODE_COMPRESSED_COMPACT || - datamode == EROFS_INODE_COMPRESSED_FULL; -} - -/* bit definitions of inode i_format */ -#define EROFS_I_VERSION_MASK 0x01 -#define EROFS_I_DATALAYOUT_MASK 0x07 - -#define EROFS_I_VERSION_BIT 0 -#define EROFS_I_DATALAYOUT_BIT 1 -#define EROFS_I_ALL_BIT 4 - -#define EROFS_I_ALL ((1 << EROFS_I_ALL_BIT) - 1) - -/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */ -#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F -/* with chunk indexes or just a 4-byte blkaddr array */ -#define EROFS_CHUNK_FORMAT_INDEXES 0x0020 - -#define EROFS_CHUNK_FORMAT_ALL \ - (EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES) - -/* 32-byte on-disk inode */ -#define EROFS_INODE_LAYOUT_COMPACT 0 -/* 64-byte on-disk inode */ -#define EROFS_INODE_LAYOUT_EXTENDED 1 - -struct erofs_inode_chunk_info { - __le16 format; /* chunk blkbits, etc. */ - __le16 reserved; -}; - -union erofs_inode_i_u { - /* total compressed blocks for compressed inodes */ - __le32 compressed_blocks; - - /* block address for uncompressed flat inodes */ - __le32 raw_blkaddr; - - /* for device files, used to indicate old/new device # */ - __le32 rdev; - - /* for chunk-based files, it contains the summary info */ - struct erofs_inode_chunk_info c; -}; - -/* 32-byte reduced form of an ondisk inode */ -struct erofs_inode_compact { - __le16 i_format; /* inode format hints */ - -/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ - __le16 i_xattr_icount; - __le16 i_mode; - __le16 i_nlink; - __le32 i_size; - __le32 i_reserved; - union erofs_inode_i_u i_u; - - __le32 i_ino; /* only used for 32-bit stat compatibility */ - __le16 i_uid; - __le16 i_gid; - __le32 i_reserved2; -}; - -/* 64-byte complete form of an ondisk inode */ -struct erofs_inode_extended { - __le16 i_format; /* inode format hints */ - -/* 1 header + n-1 * 4 bytes inline xattr to keep continuity */ - __le16 i_xattr_icount; - __le16 i_mode; - __le16 i_reserved; - __le64 i_size; - union erofs_inode_i_u i_u; - - __le32 i_ino; /* only used for 32-bit stat compatibility */ - __le32 i_uid; - __le32 i_gid; - __le64 i_mtime; - __le32 i_mtime_nsec; - __le32 i_nlink; - __u8 i_reserved2[16]; -}; - -/* - * inline xattrs (n == i_xattr_icount): - * erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes - * 12 bytes / \ - * / \ - * /-----------------------\ - * | erofs_xattr_entries+ | - * +-----------------------+ - * inline xattrs must starts in erofs_xattr_ibody_header, - * for read-only fs, no need to introduce h_refcount - */ -struct erofs_xattr_ibody_header { - __le32 h_name_filter; /* bit value 1 indicates not-present */ - __u8 h_shared_count; - __u8 h_reserved2[7]; - __le32 h_shared_xattrs[]; /* shared xattr id array */ -}; - -/* Name indexes */ -#define EROFS_XATTR_INDEX_USER 1 -#define EROFS_XATTR_INDEX_POSIX_ACL_ACCESS 2 -#define EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 -#define EROFS_XATTR_INDEX_TRUSTED 4 -#define EROFS_XATTR_INDEX_LUSTRE 5 -#define EROFS_XATTR_INDEX_SECURITY 6 - -/* - * bit 7 of e_name_index is set when it refers to a long xattr name prefix, - * while the remained lower bits represent the index of the prefix. - */ -#define EROFS_XATTR_LONG_PREFIX 0x80 -#define EROFS_XATTR_LONG_PREFIX_MASK 0x7f - -#define EROFS_XATTR_FILTER_BITS 32 -#define EROFS_XATTR_FILTER_DEFAULT UINT32_MAX -#define EROFS_XATTR_FILTER_SEED 0x25BBE08F - -/* xattr entry (for both inline & shared xattrs) */ -struct erofs_xattr_entry { - __u8 e_name_len; /* length of name */ - __u8 e_name_index; /* attribute name index */ - __le16 e_value_size; /* size of attribute value */ - /* followed by e_name and e_value */ - char e_name[]; /* attribute name */ -}; - -/* long xattr name prefix */ -struct erofs_xattr_long_prefix { - __u8 base_index; /* short xattr name prefix index */ - char infix[]; /* infix apart from short prefix */ -}; - -static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount) -{ - if (!i_xattr_icount) - return 0; - - return sizeof(struct erofs_xattr_ibody_header) + - sizeof(__u32) * (le16_to_cpu(i_xattr_icount) - 1); -} - -#define EROFS_XATTR_ALIGN(size) round_up(size, sizeof(struct erofs_xattr_entry)) - -static inline unsigned int erofs_xattr_entry_size(struct erofs_xattr_entry *e) -{ - return EROFS_XATTR_ALIGN(sizeof(struct erofs_xattr_entry) + - e->e_name_len + le16_to_cpu(e->e_value_size)); -} - -/* represent a zeroed chunk (hole) */ -#define EROFS_NULL_ADDR -1 - -/* 4-byte block address array */ -#define EROFS_BLOCK_MAP_ENTRY_SIZE sizeof(__le32) - -/* 8-byte inode chunk indexes */ -struct erofs_inode_chunk_index { - __le16 advise; /* always 0, don't care for now */ - __le16 device_id; /* back-end storage id (with bits masked) */ - __le32 blkaddr; /* start block address of this inode chunk */ -}; - -/* dirent sorts in alphabet order, thus we can do binary search */ -struct erofs_dirent { - __le64 nid; /* node number */ - __le16 nameoff; /* start offset of file name */ - __u8 file_type; /* file type */ - __u8 reserved; /* reserved */ -} __packed; - -/* - * EROFS file types should match generic FT_* types and - * it seems no need to add BUILD_BUG_ONs since potential - * unmatchness will break other fses as well... - */ - -#define EROFS_NAME_LEN 255 - -/* maximum supported size of a physical compression cluster */ -#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024) - -/* available compression algorithm types (for h_algorithmtype) */ -enum { - Z_EROFS_COMPRESSION_LZ4 = 0, - Z_EROFS_COMPRESSION_LZMA = 1, - Z_EROFS_COMPRESSION_DEFLATE = 2, - Z_EROFS_COMPRESSION_MAX -}; -#define Z_EROFS_ALL_COMPR_ALGS ((1 << Z_EROFS_COMPRESSION_MAX) - 1) - -/* 14 bytes (+ length field = 16 bytes) */ -struct z_erofs_lz4_cfgs { - __le16 max_distance; - __le16 max_pclusterblks; - u8 reserved[10]; -} __packed; - -/* 14 bytes (+ length field = 16 bytes) */ -struct z_erofs_lzma_cfgs { - __le32 dict_size; - __le16 format; - u8 reserved[8]; -} __packed; - -#define Z_EROFS_LZMA_MAX_DICT_SIZE (8 * Z_EROFS_PCLUSTER_MAX_SIZE) - -/* 6 bytes (+ length field = 8 bytes) */ -struct z_erofs_deflate_cfgs { - u8 windowbits; /* 8..15 for DEFLATE */ - u8 reserved[5]; -} __packed; - -/* - * bit 0 : COMPACTED_2B indexes (0 - off; 1 - on) - * e.g. for 4k logical cluster size, 4B if compacted 2B is off; - * (4B) + 2B + (4B) if compacted 2B is on. - * bit 1 : HEAD1 big pcluster (0 - off; 1 - on) - * bit 2 : HEAD2 big pcluster (0 - off; 1 - on) - * bit 3 : tailpacking inline pcluster (0 - off; 1 - on) - * bit 4 : interlaced plain pcluster (0 - off; 1 - on) - * bit 5 : fragment pcluster (0 - off; 1 - on) - */ -#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001 -#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002 -#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004 -#define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008 -#define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010 -#define Z_EROFS_ADVISE_FRAGMENT_PCLUSTER 0x0020 - -#define Z_EROFS_FRAGMENT_INODE_BIT 7 -struct z_erofs_map_header { - union { - /* fragment data offset in the packed inode */ - __le32 h_fragmentoff; - struct { - __le16 h_reserved1; - /* indicates the encoded size of tailpacking data */ - __le16 h_idata_size; - }; - }; - __le16 h_advise; - /* - * bit 0-3 : algorithm type of head 1 (logical cluster type 01); - * bit 4-7 : algorithm type of head 2 (logical cluster type 11). - */ - __u8 h_algorithmtype; - /* - * bit 0-2 : logical cluster bits - 12, e.g. 0 for 4096; - * bit 3-6 : reserved; - * bit 7 : move the whole file into packed inode or not. - */ - __u8 h_clusterbits; -}; - -/* - * On-disk logical cluster type: - * 0 - literal (uncompressed) lcluster - * 1,3 - compressed lcluster (for HEAD lclusters) - * 2 - compressed lcluster (for NONHEAD lclusters) - * - * In detail, - * 0 - literal (uncompressed) lcluster, - * di_advise = 0 - * di_clusterofs = the literal data offset of the lcluster - * di_blkaddr = the blkaddr of the literal pcluster - * - * 1,3 - compressed lcluster (for HEAD lclusters) - * di_advise = 1 or 3 - * di_clusterofs = the decompressed data offset of the lcluster - * di_blkaddr = the blkaddr of the compressed pcluster - * - * 2 - compressed lcluster (for NONHEAD lclusters) - * di_advise = 2 - * di_clusterofs = - * the decompressed data offset in its own HEAD lcluster - * di_u.delta[0] = distance to this HEAD lcluster - * di_u.delta[1] = distance to the next HEAD lcluster - */ -enum { - Z_EROFS_LCLUSTER_TYPE_PLAIN = 0, - Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1, - Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2, - Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3, - Z_EROFS_LCLUSTER_TYPE_MAX -}; - -#define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2 -#define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0 - -/* (noncompact only, HEAD) This pcluster refers to partial decompressed data */ -#define Z_EROFS_LI_PARTIAL_REF (1 << 15) - -/* - * D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the - * compressed block count of a compressed extent (in logical clusters, aka. - * block count of a pcluster). - */ -#define Z_EROFS_LI_D0_CBLKCNT (1 << 11) - -struct z_erofs_lcluster_index { - __le16 di_advise; - /* where to decompress in the head lcluster */ - __le16 di_clusterofs; - - union { - /* for the HEAD lclusters */ - __le32 blkaddr; - /* - * for the NONHEAD lclusters - * [0] - distance to its HEAD lcluster - * [1] - distance to the next HEAD lcluster - */ - __le16 delta[2]; - } di_u; -}; - -#define Z_EROFS_FULL_INDEX_ALIGN(end) \ - (ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8) - -/* check the EROFS on-disk layout strictly at compile time */ -static inline void erofs_check_ondisk_layout_definitions(void) -{ - const __le64 fmh = *(__le64 *)&(struct z_erofs_map_header) { - .h_clusterbits = 1 << Z_EROFS_FRAGMENT_INODE_BIT - }; - - BUILD_BUG_ON(sizeof(struct erofs_super_block) != 128); - BUILD_BUG_ON(sizeof(struct erofs_inode_compact) != 32); - BUILD_BUG_ON(sizeof(struct erofs_inode_extended) != 64); - BUILD_BUG_ON(sizeof(struct erofs_xattr_ibody_header) != 12); - BUILD_BUG_ON(sizeof(struct erofs_xattr_entry) != 4); - BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4); - BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8); - BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8); - BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8); - BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12); - /* keep in sync between 2 index structures for better extendibility */ - BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != - sizeof(struct z_erofs_lcluster_index)); - BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128); - - BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) < - Z_EROFS_LCLUSTER_TYPE_MAX - 1); - /* exclude old compiler versions like gcc 7.5.0 */ - BUILD_BUG_ON(__builtin_constant_p(fmh) ? - fmh != cpu_to_le64(1ULL << 63) : 0); -} - -#endif diff --git a/composefs/libcomposefs/erofs_fs_wrapper.h b/composefs/libcomposefs/erofs_fs_wrapper.h deleted file mode 100644 index b7ed2aa..0000000 --- a/composefs/libcomposefs/erofs_fs_wrapper.h +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include - -#define __packed __attribute__((__packed__)) -typedef __u8 u8; - -static inline __u16 cpu_to_le16(__u16 val) -{ - return htole16(val); -} - -static inline __u32 cpu_to_le32(__u32 val) -{ - return htole32(val); -} - -static inline __u64 cpu_to_le64(__u64 val) -{ - return htole64(val); -} - -static inline __u16 le16_to_cpu(__u16 val) -{ - return le16toh(val); -} - -static inline __u32 le32_to_cpu(__u32 val) -{ - return le32toh(val); -} - -static inline __u64 le64_to_cpu(__u64 val) -{ - return le64toh(val); -} - -/* Note: These only do power of 2 */ -#define __round_mask(x, y) ((__typeof__(x))((y)-1)) -#define round_up(x, y) ((((x)-1) | __round_mask(x, y)) + 1) -#define round_down(x, y) ((x) & ~__round_mask(x, y)) - -#define ALIGN_TO(_offset, _align_size) \ - (((_offset) + _align_size - 1) & ~(_align_size - 1)) - -#define BIT(nr) (((uint64_t) 1) << (nr)) -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)])) -#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) - -/* We use a fixed block size for all arches of 4k */ -#define EROFS_BLKSIZ 4096 -#define EROFS_BLKSIZ_BITS 12 - -#define EROFS_ISLOTBITS 5 -#define EROFS_SLOTSIZE (1U << EROFS_ISLOTBITS) - -#define EROFS_SUPER_MAGIC_V1 0xE0F5E1E2 - -#define CRC32C_POLY_LE 0x82F63B78 -static inline uint32_t erofs_crc32c(uint32_t crc, const uint8_t *in, size_t len) -{ - int i; - - while (len--) { - crc ^= *in++; - for (i = 0; i < 8; i++) - crc = (crc >> 1) ^ ((crc & 1) ? CRC32C_POLY_LE : 0); - } - return crc; -} - -enum { - EROFS_FT_UNKNOWN, - EROFS_FT_REG_FILE, - EROFS_FT_DIR, - EROFS_FT_CHRDEV, - EROFS_FT_BLKDEV, - EROFS_FT_FIFO, - EROFS_FT_SOCK, - EROFS_FT_SYMLINK, - EROFS_FT_MAX -}; - -#define ilog2(n) \ -( \ - (n) & (1ULL << 63) ? 63 : \ - (n) & (1ULL << 62) ? 62 : \ - (n) & (1ULL << 61) ? 61 : \ - (n) & (1ULL << 60) ? 60 : \ - (n) & (1ULL << 59) ? 59 : \ - (n) & (1ULL << 58) ? 58 : \ - (n) & (1ULL << 57) ? 57 : \ - (n) & (1ULL << 56) ? 56 : \ - (n) & (1ULL << 55) ? 55 : \ - (n) & (1ULL << 54) ? 54 : \ - (n) & (1ULL << 53) ? 53 : \ - (n) & (1ULL << 52) ? 52 : \ - (n) & (1ULL << 51) ? 51 : \ - (n) & (1ULL << 50) ? 50 : \ - (n) & (1ULL << 49) ? 49 : \ - (n) & (1ULL << 48) ? 48 : \ - (n) & (1ULL << 47) ? 47 : \ - (n) & (1ULL << 46) ? 46 : \ - (n) & (1ULL << 45) ? 45 : \ - (n) & (1ULL << 44) ? 44 : \ - (n) & (1ULL << 43) ? 43 : \ - (n) & (1ULL << 42) ? 42 : \ - (n) & (1ULL << 41) ? 41 : \ - (n) & (1ULL << 40) ? 40 : \ - (n) & (1ULL << 39) ? 39 : \ - (n) & (1ULL << 38) ? 38 : \ - (n) & (1ULL << 37) ? 37 : \ - (n) & (1ULL << 36) ? 36 : \ - (n) & (1ULL << 35) ? 35 : \ - (n) & (1ULL << 34) ? 34 : \ - (n) & (1ULL << 33) ? 33 : \ - (n) & (1ULL << 32) ? 32 : \ - (n) & (1ULL << 31) ? 31 : \ - (n) & (1ULL << 30) ? 30 : \ - (n) & (1ULL << 29) ? 29 : \ - (n) & (1ULL << 28) ? 28 : \ - (n) & (1ULL << 27) ? 27 : \ - (n) & (1ULL << 26) ? 26 : \ - (n) & (1ULL << 25) ? 25 : \ - (n) & (1ULL << 24) ? 24 : \ - (n) & (1ULL << 23) ? 23 : \ - (n) & (1ULL << 22) ? 22 : \ - (n) & (1ULL << 21) ? 21 : \ - (n) & (1ULL << 20) ? 20 : \ - (n) & (1ULL << 19) ? 19 : \ - (n) & (1ULL << 18) ? 18 : \ - (n) & (1ULL << 17) ? 17 : \ - (n) & (1ULL << 16) ? 16 : \ - (n) & (1ULL << 15) ? 15 : \ - (n) & (1ULL << 14) ? 14 : \ - (n) & (1ULL << 13) ? 13 : \ - (n) & (1ULL << 12) ? 12 : \ - (n) & (1ULL << 11) ? 11 : \ - (n) & (1ULL << 10) ? 10 : \ - (n) & (1ULL << 9) ? 9 : \ - (n) & (1ULL << 8) ? 8 : \ - (n) & (1ULL << 7) ? 7 : \ - (n) & (1ULL << 6) ? 6 : \ - (n) & (1ULL << 5) ? 5 : \ - (n) & (1ULL << 4) ? 4 : \ - (n) & (1ULL << 3) ? 3 : \ - (n) & (1ULL << 2) ? 2 : \ - (n) & (1ULL << 1) ? 1 : 0 \ -) - -#include "erofs_fs.h" diff --git a/composefs/libcomposefs/hash.c b/composefs/libcomposefs/hash.c deleted file mode 100644 index 918aa0d..0000000 --- a/composefs/libcomposefs/hash.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* hash - hashing table processing. - - Copyright (C) 1998-2004, 2006-2007, 2009-2023 Free Software Foundation, Inc. - - Written by Jim Meyering, 1992. - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -/* A generic hash table package. */ - -/* Define USE_OBSTACK to 1 if you want the allocator to use obstacks instead - of malloc. If you change USE_OBSTACK, you have to recompile! */ - -#include - -#include "hash.h" - -#include "bitrotate.h" -#include "xalloc-oversized.h" - -#include -#include -#include - -#if USE_OBSTACK -# include "obstack.h" -# ifndef obstack_chunk_alloc -# define obstack_chunk_alloc malloc -# endif -# ifndef obstack_chunk_free -# define obstack_chunk_free free -# endif -#endif - -struct hash_entry - { - void *data; - struct hash_entry *next; - }; - -struct hash_table - { - /* The array of buckets starts at BUCKET and extends to BUCKET_LIMIT-1, - for a possibility of N_BUCKETS. Among those, N_BUCKETS_USED buckets - are not empty, there are N_ENTRIES active entries in the table. */ - struct hash_entry *bucket; - struct hash_entry const *bucket_limit; - size_t n_buckets; - size_t n_buckets_used; - size_t n_entries; - - /* Tuning arguments, kept in a physically separate structure. */ - const Hash_tuning *tuning; - - /* Three functions are given to 'hash_initialize', see the documentation - block for this function. In a word, HASHER randomizes a user entry - into a number up from 0 up to some maximum minus 1; COMPARATOR returns - true if two user entries compare equally; and DATA_FREER is the cleanup - function for a user entry. */ - Hash_hasher hasher; - Hash_comparator comparator; - Hash_data_freer data_freer; - - /* A linked list of freed struct hash_entry structs. */ - struct hash_entry *free_entry_list; - -#if USE_OBSTACK - /* Whenever obstacks are used, it is possible to allocate all overflowed - entries into a single stack, so they all can be freed in a single - operation. It is not clear if the speedup is worth the trouble. */ - struct obstack entry_stack; -#endif - }; - -/* A hash table contains many internal entries, each holding a pointer to - some user-provided data (also called a user entry). An entry indistinctly - refers to both the internal entry and its associated user entry. A user - entry contents may be hashed by a randomization function (the hashing - function, or just "hasher" for short) into a number (or "slot") between 0 - and the current table size. At each slot position in the hash table, - starts a linked chain of entries for which the user data all hash to this - slot. A bucket is the collection of all entries hashing to the same slot. - - A good "hasher" function will distribute entries rather evenly in buckets. - In the ideal case, the length of each bucket is roughly the number of - entries divided by the table size. Finding the slot for a data is usually - done in constant time by the "hasher", and the later finding of a precise - entry is linear in time with the size of the bucket. Consequently, a - larger hash table size (that is, a larger number of buckets) is prone to - yielding shorter chains, *given* the "hasher" function behaves properly. - - Long buckets slow down the lookup algorithm. One might use big hash table - sizes in hope to reduce the average length of buckets, but this might - become inordinate, as unused slots in the hash table take some space. The - best bet is to make sure you are using a good "hasher" function (beware - that those are not that easy to write! :-), and to use a table size - larger than the actual number of entries. */ - -/* If an insertion makes the ratio of nonempty buckets to table size larger - than the growth threshold (a number between 0.0 and 1.0), then increase - the table size by multiplying by the growth factor (a number greater than - 1.0). The growth threshold defaults to 0.8, and the growth factor - defaults to 1.414, meaning that the table will have doubled its size - every second time 80% of the buckets get used. */ -#define DEFAULT_GROWTH_THRESHOLD 0.8f -#define DEFAULT_GROWTH_FACTOR 1.414f - -/* If a deletion empties a bucket and causes the ratio of used buckets to - table size to become smaller than the shrink threshold (a number between - 0.0 and 1.0), then shrink the table by multiplying by the shrink factor (a - number greater than the shrink threshold but smaller than 1.0). The shrink - threshold and factor default to 0.0 and 1.0, meaning that the table never - shrinks. */ -#define DEFAULT_SHRINK_THRESHOLD 0.0f -#define DEFAULT_SHRINK_FACTOR 1.0f - -/* Use this to initialize or reset a TUNING structure to - some sensible values. */ -static const Hash_tuning default_tuning = - { - DEFAULT_SHRINK_THRESHOLD, - DEFAULT_SHRINK_FACTOR, - DEFAULT_GROWTH_THRESHOLD, - DEFAULT_GROWTH_FACTOR, - false - }; - -/* Information and lookup. */ - -size_t -hash_get_n_buckets (const Hash_table *table) -{ - return table->n_buckets; -} - -size_t -hash_get_n_buckets_used (const Hash_table *table) -{ - return table->n_buckets_used; -} - -size_t -hash_get_n_entries (const Hash_table *table) -{ - return table->n_entries; -} - -size_t -hash_get_max_bucket_length (const Hash_table *table) -{ - struct hash_entry const *bucket; - size_t max_bucket_length = 0; - - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - struct hash_entry const *cursor = bucket; - size_t bucket_length = 1; - - while (cursor = cursor->next, cursor) - bucket_length++; - - if (bucket_length > max_bucket_length) - max_bucket_length = bucket_length; - } - } - - return max_bucket_length; -} - -bool -hash_table_ok (const Hash_table *table) -{ - struct hash_entry const *bucket; - size_t n_buckets_used = 0; - size_t n_entries = 0; - - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - struct hash_entry const *cursor = bucket; - - /* Count bucket head. */ - n_buckets_used++; - n_entries++; - - /* Count bucket overflow. */ - while (cursor = cursor->next, cursor) - n_entries++; - } - } - - if (n_buckets_used == table->n_buckets_used && n_entries == table->n_entries) - return true; - - return false; -} - -void -hash_print_statistics (const Hash_table *table, FILE *stream) -{ - size_t n_entries = hash_get_n_entries (table); - size_t n_buckets = hash_get_n_buckets (table); - size_t n_buckets_used = hash_get_n_buckets_used (table); - size_t max_bucket_length = hash_get_max_bucket_length (table); - - fprintf (stream, "# entries: %lu\n", (unsigned long int) n_entries); - fprintf (stream, "# buckets: %lu\n", (unsigned long int) n_buckets); - fprintf (stream, "# buckets used: %lu (%.2f%%)\n", - (unsigned long int) n_buckets_used, - (100.0 * n_buckets_used) / n_buckets); - fprintf (stream, "max bucket length: %lu\n", - (unsigned long int) max_bucket_length); -} - -/* Hash KEY and return a pointer to the selected bucket. - If TABLE->hasher misbehaves, abort. */ -static struct hash_entry * -safe_hasher (const Hash_table *table, const void *key) -{ - size_t n = table->hasher (key, table->n_buckets); - if (! (n < table->n_buckets)) - abort (); - return table->bucket + n; -} - -void * -hash_lookup (const Hash_table *table, const void *entry) -{ - struct hash_entry const *bucket = safe_hasher (table, entry); - struct hash_entry const *cursor; - - if (bucket->data == NULL) - return NULL; - - for (cursor = bucket; cursor; cursor = cursor->next) - if (entry == cursor->data || table->comparator (entry, cursor->data)) - return cursor->data; - - return NULL; -} - -/* Walking. */ - -void * -hash_get_first (const Hash_table *table) -{ - struct hash_entry const *bucket; - - if (table->n_entries == 0) - return NULL; - - for (bucket = table->bucket; ; bucket++) - if (! (bucket < table->bucket_limit)) - abort (); - else if (bucket->data) - return bucket->data; -} - -void * -hash_get_next (const Hash_table *table, const void *entry) -{ - struct hash_entry const *bucket = safe_hasher (table, entry); - struct hash_entry const *cursor; - - /* Find next entry in the same bucket. */ - cursor = bucket; - do - { - if (cursor->data == entry && cursor->next) - return cursor->next->data; - cursor = cursor->next; - } - while (cursor != NULL); - - /* Find first entry in any subsequent bucket. */ - while (++bucket < table->bucket_limit) - if (bucket->data) - return bucket->data; - - /* None found. */ - return NULL; -} - -size_t -hash_get_entries (const Hash_table *table, void **buffer, - size_t buffer_size) -{ - size_t counter = 0; - struct hash_entry const *bucket; - struct hash_entry const *cursor; - - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - for (cursor = bucket; cursor; cursor = cursor->next) - { - if (counter >= buffer_size) - return counter; - buffer[counter++] = cursor->data; - } - } - } - - return counter; -} - -size_t -hash_do_for_each (const Hash_table *table, Hash_processor processor, - void *processor_data) -{ - size_t counter = 0; - struct hash_entry const *bucket; - struct hash_entry const *cursor; - - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - for (cursor = bucket; cursor; cursor = cursor->next) - { - if (! processor (cursor->data, processor_data)) - return counter; - counter++; - } - } - } - - return counter; -} - -/* Allocation and clean-up. */ - -#if USE_DIFF_HASH - -/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see - B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm, - Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash - algorithms tend to be domain-specific, so what's good for [diffutils'] io.c - may not be good for your application." */ - -size_t -hash_string (const char *string, size_t n_buckets) -{ -# define HASH_ONE_CHAR(Value, Byte) \ - ((Byte) + rotl_sz (Value, 7)) - - size_t value = 0; - unsigned char ch; - - for (; (ch = *string); string++) - value = HASH_ONE_CHAR (value, ch); - return value % n_buckets; - -# undef HASH_ONE_CHAR -} - -#else /* not USE_DIFF_HASH */ - -/* This one comes from 'recode', and performs a bit better than the above as - per a few experiments. It is inspired from a hashing routine found in the - very old Cyber 'snoop', itself written in typical Greg Mansfield style. - (By the way, what happened to this excellent man? Is he still alive?) */ - -size_t -hash_string (const char *string, size_t n_buckets) -{ - size_t value = 0; - unsigned char ch; - - for (; (ch = *string); string++) - value = (value * 31 + ch) % n_buckets; - return value; -} - -#endif /* not USE_DIFF_HASH */ - -/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd - number at least equal to 11. */ - -static bool _GL_ATTRIBUTE_CONST -is_prime (size_t candidate) -{ - size_t divisor = 3; - size_t square = divisor * divisor; - - while (square < candidate && (candidate % divisor)) - { - divisor++; - square += 4 * divisor; - divisor++; - } - - return (candidate % divisor ? true : false); -} - -/* Round a given CANDIDATE number up to the nearest prime, and return that - prime. Primes lower than 10 are merely skipped. */ - -static size_t _GL_ATTRIBUTE_CONST -next_prime (size_t candidate) -{ - /* Skip small primes. */ - if (candidate < 10) - candidate = 10; - - /* Make it definitely odd. */ - candidate |= 1; - - while (SIZE_MAX != candidate && !is_prime (candidate)) - candidate += 2; - - return candidate; -} - -void -hash_reset_tuning (Hash_tuning *tuning) -{ - *tuning = default_tuning; -} - -/* If the user passes a NULL hasher, we hash the raw pointer. */ -static size_t -raw_hasher (const void *data, size_t n) -{ - /* When hashing unique pointers, it is often the case that they were - generated by malloc and thus have the property that the low-order - bits are 0. As this tends to give poorer performance with small - tables, we rotate the pointer value before performing division, - in an attempt to improve hash quality. */ - size_t val = rotr_sz ((size_t) data, 3); - return val % n; -} - -/* If the user passes a NULL comparator, we use pointer comparison. */ -static bool -raw_comparator (const void *a, const void *b) -{ - return a == b; -} - - -/* For the given hash TABLE, check the user supplied tuning structure for - reasonable values, and return true if there is no gross error with it. - Otherwise, definitively reset the TUNING field to some acceptable default - in the hash table (that is, the user loses the right of further modifying - tuning arguments), and return false. */ - -static bool -check_tuning (Hash_table *table) -{ - const Hash_tuning *tuning = table->tuning; - float epsilon; - if (tuning == &default_tuning) - return true; - - /* Be a bit stricter than mathematics would require, so that - rounding errors in size calculations do not cause allocations to - fail to grow or shrink as they should. The smallest allocation - is 11 (due to next_prime's algorithm), so an epsilon of 0.1 - should be good enough. */ - epsilon = 0.1f; - - if (epsilon < tuning->growth_threshold - && tuning->growth_threshold < 1 - epsilon - && 1 + epsilon < tuning->growth_factor - && 0 <= tuning->shrink_threshold - && tuning->shrink_threshold + epsilon < tuning->shrink_factor - && tuning->shrink_factor <= 1 - && tuning->shrink_threshold + epsilon < tuning->growth_threshold) - return true; - - table->tuning = &default_tuning; - return false; -} - -/* Compute the size of the bucket array for the given CANDIDATE and - TUNING, or return 0 if there is no possible way to allocate that - many entries. */ - -static size_t _GL_ATTRIBUTE_PURE -compute_bucket_size (size_t candidate, const Hash_tuning *tuning) -{ - if (!tuning->is_n_buckets) - { - float new_candidate = candidate / tuning->growth_threshold; - if ((float) SIZE_MAX <= new_candidate) - return 0; - candidate = new_candidate; - } - candidate = next_prime (candidate); - if (xalloc_oversized (candidate, sizeof (struct hash_entry *))) - return 0; - return candidate; -} - -Hash_table * -hash_initialize (size_t candidate, const Hash_tuning *tuning, - Hash_hasher hasher, Hash_comparator comparator, - Hash_data_freer data_freer) -{ - Hash_table *table; - - if (hasher == NULL) - hasher = raw_hasher; - if (comparator == NULL) - comparator = raw_comparator; - - table = malloc (sizeof *table); - if (table == NULL) - return NULL; - - if (!tuning) - tuning = &default_tuning; - table->tuning = tuning; - if (!check_tuning (table)) - { - /* Fail if the tuning options are invalid. This is the only occasion - when the user gets some feedback about it. Once the table is created, - if the user provides invalid tuning options, we silently revert to - using the defaults, and ignore further request to change the tuning - options. */ - goto fail; - } - - table->n_buckets = compute_bucket_size (candidate, tuning); - if (!table->n_buckets) - goto fail; - - table->bucket = calloc (table->n_buckets, sizeof *table->bucket); - if (table->bucket == NULL) - goto fail; - table->bucket_limit = table->bucket + table->n_buckets; - table->n_buckets_used = 0; - table->n_entries = 0; - - table->hasher = hasher; - table->comparator = comparator; - table->data_freer = data_freer; - - table->free_entry_list = NULL; -#if USE_OBSTACK - obstack_init (&table->entry_stack); -#endif - return table; - - fail: - free (table); - return NULL; -} - -void -hash_clear (Hash_table *table) -{ - struct hash_entry *bucket; - - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - struct hash_entry *cursor; - struct hash_entry *next; - - /* Free the bucket overflow. */ - for (cursor = bucket->next; cursor; cursor = next) - { - if (table->data_freer) - table->data_freer (cursor->data); - cursor->data = NULL; - - next = cursor->next; - /* Relinking is done one entry at a time, as it is to be expected - that overflows are either rare or short. */ - cursor->next = table->free_entry_list; - table->free_entry_list = cursor; - } - - /* Free the bucket head. */ - if (table->data_freer) - table->data_freer (bucket->data); - bucket->data = NULL; - bucket->next = NULL; - } - } - - table->n_buckets_used = 0; - table->n_entries = 0; -} - -void -hash_free (Hash_table *table) -{ - struct hash_entry *bucket; - struct hash_entry *cursor; - struct hash_entry *next; - - /* Call the user data_freer function. */ - if (table->data_freer && table->n_entries) - { - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - if (bucket->data) - { - for (cursor = bucket; cursor; cursor = cursor->next) - table->data_freer (cursor->data); - } - } - } - -#if USE_OBSTACK - - obstack_free (&table->entry_stack, NULL); - -#else - - /* Free all bucket overflowed entries. */ - for (bucket = table->bucket; bucket < table->bucket_limit; bucket++) - { - for (cursor = bucket->next; cursor; cursor = next) - { - next = cursor->next; - free (cursor); - } - } - - /* Also reclaim the internal list of previously freed entries. */ - for (cursor = table->free_entry_list; cursor; cursor = next) - { - next = cursor->next; - free (cursor); - } - -#endif - - /* Free the remainder of the hash table structure. */ - free (table->bucket); - free (table); -} - -/* Insertion and deletion. */ - -/* Get a new hash entry for a bucket overflow, possibly by recycling a - previously freed one. If this is not possible, allocate a new one. */ - -static struct hash_entry * -allocate_entry (Hash_table *table) -{ - struct hash_entry *new; - - if (table->free_entry_list) - { - new = table->free_entry_list; - table->free_entry_list = new->next; - } - else - { -#if USE_OBSTACK - new = obstack_alloc (&table->entry_stack, sizeof *new); -#else - new = malloc (sizeof *new); -#endif - } - - return new; -} - -/* Free a hash entry which was part of some bucket overflow, - saving it for later recycling. */ - -static void -free_entry (Hash_table *table, struct hash_entry *entry) -{ - entry->data = NULL; - entry->next = table->free_entry_list; - table->free_entry_list = entry; -} - -/* This private function is used to help with insertion and deletion. When - ENTRY matches an entry in the table, return a pointer to the corresponding - user data and set *BUCKET_HEAD to the head of the selected bucket. - Otherwise, return NULL. When DELETE is true and ENTRY matches an entry in - the table, unlink the matching entry. */ - -static void * -hash_find_entry (Hash_table *table, const void *entry, - struct hash_entry **bucket_head, bool delete) -{ - struct hash_entry *bucket = safe_hasher (table, entry); - struct hash_entry *cursor; - - *bucket_head = bucket; - - /* Test for empty bucket. */ - if (bucket->data == NULL) - return NULL; - - /* See if the entry is the first in the bucket. */ - if (entry == bucket->data || table->comparator (entry, bucket->data)) - { - void *data = bucket->data; - - if (delete) - { - if (bucket->next) - { - struct hash_entry *next = bucket->next; - - /* Bump the first overflow entry into the bucket head, then save - the previous first overflow entry for later recycling. */ - *bucket = *next; - free_entry (table, next); - } - else - { - bucket->data = NULL; - } - } - - return data; - } - - /* Scan the bucket overflow. */ - for (cursor = bucket; cursor->next; cursor = cursor->next) - { - if (entry == cursor->next->data - || table->comparator (entry, cursor->next->data)) - { - void *data = cursor->next->data; - - if (delete) - { - struct hash_entry *next = cursor->next; - - /* Unlink the entry to delete, then save the freed entry for later - recycling. */ - cursor->next = next->next; - free_entry (table, next); - } - - return data; - } - } - - /* No entry found. */ - return NULL; -} - -/* Internal helper, to move entries from SRC to DST. Both tables must - share the same free entry list. If SAFE, only move overflow - entries, saving bucket heads for later, so that no allocations will - occur. Return false if the free entry list is exhausted and an - allocation fails. */ - -static bool -transfer_entries (Hash_table *dst, Hash_table *src, bool safe) -{ - struct hash_entry *bucket; - struct hash_entry *cursor; - struct hash_entry *next; - for (bucket = src->bucket; bucket < src->bucket_limit; bucket++) - if (bucket->data) - { - void *data; - struct hash_entry *new_bucket; - - /* Within each bucket, transfer overflow entries first and - then the bucket head, to minimize memory pressure. After - all, the only time we might allocate is when moving the - bucket head, but moving overflow entries first may create - free entries that can be recycled by the time we finally - get to the bucket head. */ - for (cursor = bucket->next; cursor; cursor = next) - { - data = cursor->data; - new_bucket = safe_hasher (dst, data); - - next = cursor->next; - - if (new_bucket->data) - { - /* Merely relink an existing entry, when moving from a - bucket overflow into a bucket overflow. */ - cursor->next = new_bucket->next; - new_bucket->next = cursor; - } - else - { - /* Free an existing entry, when moving from a bucket - overflow into a bucket header. */ - new_bucket->data = data; - dst->n_buckets_used++; - free_entry (dst, cursor); - } - } - /* Now move the bucket head. Be sure that if we fail due to - allocation failure that the src table is in a consistent - state. */ - data = bucket->data; - bucket->next = NULL; - if (safe) - continue; - new_bucket = safe_hasher (dst, data); - - if (new_bucket->data) - { - /* Allocate or recycle an entry, when moving from a bucket - header into a bucket overflow. */ - struct hash_entry *new_entry = allocate_entry (dst); - - if (new_entry == NULL) - return false; - - new_entry->data = data; - new_entry->next = new_bucket->next; - new_bucket->next = new_entry; - } - else - { - /* Move from one bucket header to another. */ - new_bucket->data = data; - dst->n_buckets_used++; - } - bucket->data = NULL; - src->n_buckets_used--; - } - return true; -} - -bool -hash_rehash (Hash_table *table, size_t candidate) -{ - Hash_table storage; - Hash_table *new_table; - size_t new_size = compute_bucket_size (candidate, table->tuning); - - if (!new_size) - return false; - if (new_size == table->n_buckets) - return true; - new_table = &storage; - new_table->bucket = calloc (new_size, sizeof *new_table->bucket); - if (new_table->bucket == NULL) - return false; - new_table->n_buckets = new_size; - new_table->bucket_limit = new_table->bucket + new_size; - new_table->n_buckets_used = 0; - new_table->n_entries = 0; - new_table->tuning = table->tuning; - new_table->hasher = table->hasher; - new_table->comparator = table->comparator; - new_table->data_freer = table->data_freer; - - /* In order for the transfer to successfully complete, we need - additional overflow entries when distinct buckets in the old - table collide into a common bucket in the new table. The worst - case possible is a hasher that gives a good spread with the old - size, but returns a constant with the new size; if we were to - guarantee table->n_buckets_used-1 free entries in advance, then - the transfer would be guaranteed to not allocate memory. - However, for large tables, a guarantee of no further allocation - introduces a lot of extra memory pressure, all for an unlikely - corner case (most rehashes reduce, rather than increase, the - number of overflow entries needed). So, we instead ensure that - the transfer process can be reversed if we hit a memory - allocation failure mid-transfer. */ - - /* Merely reuse the extra old space into the new table. */ -#if USE_OBSTACK - new_table->entry_stack = table->entry_stack; -#endif - new_table->free_entry_list = table->free_entry_list; - - if (transfer_entries (new_table, table, false)) - { - /* Entries transferred successfully; tie up the loose ends. */ - free (table->bucket); - table->bucket = new_table->bucket; - table->bucket_limit = new_table->bucket_limit; - table->n_buckets = new_table->n_buckets; - table->n_buckets_used = new_table->n_buckets_used; - table->free_entry_list = new_table->free_entry_list; - /* table->n_entries and table->entry_stack already hold their value. */ - return true; - } - - /* We've allocated new_table->bucket (and possibly some entries), - exhausted the free list, and moved some but not all entries into - new_table. We must undo the partial move before returning - failure. The only way to get into this situation is if new_table - uses fewer buckets than the old table, so we will reclaim some - free entries as overflows in the new table are put back into - distinct buckets in the old table. - - There are some pathological cases where a single pass through the - table requires more intermediate overflow entries than using two - passes. Two passes give worse cache performance and takes - longer, but at this point, we're already out of memory, so slow - and safe is better than failure. */ - table->free_entry_list = new_table->free_entry_list; - if (! (transfer_entries (table, new_table, true) - && transfer_entries (table, new_table, false))) - abort (); - /* table->n_entries already holds its value. */ - free (new_table->bucket); - return false; -} - -int -hash_insert_if_absent (Hash_table *table, void const *entry, - void const **matched_ent) -{ - void *data; - struct hash_entry *bucket; - - /* The caller cannot insert a NULL entry, since hash_lookup returns NULL - to indicate "not found", and hash_find_entry uses "bucket->data == NULL" - to indicate an empty bucket. */ - if (! entry) - abort (); - - /* If there's a matching entry already in the table, return that. */ - if ((data = hash_find_entry (table, entry, &bucket, false)) != NULL) - { - if (matched_ent) - *matched_ent = data; - return 0; - } - - /* If the growth threshold of the buckets in use has been reached, increase - the table size and rehash. There's no point in checking the number of - entries: if the hashing function is ill-conditioned, rehashing is not - likely to improve it. */ - - if (table->n_buckets_used - > table->tuning->growth_threshold * table->n_buckets) - { - /* Check more fully, before starting real work. If tuning arguments - became invalid, the second check will rely on proper defaults. */ - check_tuning (table); - if (table->n_buckets_used - > table->tuning->growth_threshold * table->n_buckets) - { - const Hash_tuning *tuning = table->tuning; - float candidate = - (tuning->is_n_buckets - ? (table->n_buckets * tuning->growth_factor) - : (table->n_buckets * tuning->growth_factor - * tuning->growth_threshold)); - - if ((float) SIZE_MAX <= candidate) - return -1; - - /* If the rehash fails, arrange to return NULL. */ - if (!hash_rehash (table, candidate)) - return -1; - - /* Update the bucket we are interested in. */ - if (hash_find_entry (table, entry, &bucket, false) != NULL) - abort (); - } - } - - /* ENTRY is not matched, it should be inserted. */ - - if (bucket->data) - { - struct hash_entry *new_entry = allocate_entry (table); - - if (new_entry == NULL) - return -1; - - /* Add ENTRY in the overflow of the bucket. */ - - new_entry->data = (void *) entry; - new_entry->next = bucket->next; - bucket->next = new_entry; - table->n_entries++; - return 1; - } - - /* Add ENTRY right in the bucket head. */ - - bucket->data = (void *) entry; - table->n_entries++; - table->n_buckets_used++; - - return 1; -} - -void * -hash_insert (Hash_table *table, void const *entry) -{ - void const *matched_ent; - int err = hash_insert_if_absent (table, entry, &matched_ent); - return (err == -1 - ? NULL - : (void *) (err == 0 ? matched_ent : entry)); -} - -void * -hash_remove (Hash_table *table, const void *entry) -{ - void *data; - struct hash_entry *bucket; - - data = hash_find_entry (table, entry, &bucket, true); - if (!data) - return NULL; - - table->n_entries--; - if (!bucket->data) - { - table->n_buckets_used--; - - /* If the shrink threshold of the buckets in use has been reached, - rehash into a smaller table. */ - - if (table->n_buckets_used - < table->tuning->shrink_threshold * table->n_buckets) - { - /* Check more fully, before starting real work. If tuning arguments - became invalid, the second check will rely on proper defaults. */ - check_tuning (table); - if (table->n_buckets_used - < table->tuning->shrink_threshold * table->n_buckets) - { - const Hash_tuning *tuning = table->tuning; - size_t candidate = - (tuning->is_n_buckets - ? table->n_buckets * tuning->shrink_factor - : (table->n_buckets * tuning->shrink_factor - * tuning->growth_threshold)); - - if (!hash_rehash (table, candidate)) - { - /* Failure to allocate memory in an attempt to - shrink the table is not fatal. But since memory - is low, we can at least be kind and free any - spare entries, rather than keeping them tied up - in the free entry list. */ -#if ! USE_OBSTACK - struct hash_entry *cursor = table->free_entry_list; - struct hash_entry *next; - while (cursor) - { - next = cursor->next; - free (cursor); - cursor = next; - } - table->free_entry_list = NULL; -#endif - } - } - } - } - - return data; -} - -void * -hash_delete (Hash_table *table, const void *entry) -{ - return hash_remove (table, entry); -} - -/* Testing. */ - -#if TESTING - -void -hash_print (const Hash_table *table) -{ - struct hash_entry *bucket = (struct hash_entry *) table->bucket; - - for ( ; bucket < table->bucket_limit; bucket++) - { - struct hash_entry *cursor; - - if (bucket) - printf ("%lu:\n", (unsigned long int) (bucket - table->bucket)); - - for (cursor = bucket; cursor; cursor = cursor->next) - { - char const *s = cursor->data; - /* FIXME */ - if (s) - printf (" %s\n", s); - } - } -} - -#endif /* TESTING */ diff --git a/composefs/libcomposefs/hash.h b/composefs/libcomposefs/hash.h deleted file mode 100644 index 7b80859..0000000 --- a/composefs/libcomposefs/hash.h +++ /dev/null @@ -1,277 +0,0 @@ -/* hash - hashing table processing. - Copyright (C) 1998-1999, 2001, 2003, 2009-2023 Free Software Foundation, - Inc. - Written by Jim Meyering , 1998. - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -/* A generic hash table package. */ - -/* Make sure USE_OBSTACK is defined to 1 if you want the allocator to use - obstacks instead of malloc, and recompile 'hash.c' with same setting. */ - -#ifndef HASH_H_ -# define HASH_H_ - -# include - -# include -# include - -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The attribute __pure__ was added in gcc 2.96. */ -# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((deprecated)) -# define _GL_ATTRIBUTE_NODISCARD -# define _GL_ATTRIBUTE_RETURNS_NONNULL -# define _GL_ATTRIBUTE_MALLOC -# define _GL_ATTRIBUTE_DEALLOC(_a,_b) - -# include - -# ifdef __cplusplus -extern "C" { -# endif - -struct hash_tuning - { - /* This structure is mainly used for 'hash_initialize', see the block - documentation of 'hash_reset_tuning' for more complete comments. */ - - float shrink_threshold; /* ratio of used buckets to trigger a shrink */ - float shrink_factor; /* ratio of new smaller size to original size */ - float growth_threshold; /* ratio of used buckets to trigger a growth */ - float growth_factor; /* ratio of new bigger size to original size */ - bool is_n_buckets; /* if CANDIDATE really means table size */ - }; - -typedef struct hash_tuning Hash_tuning; - -struct hash_table; - -typedef struct hash_table Hash_table; - -/* - * Information and lookup. - */ - -/* The following few functions provide information about the overall hash - table organization: the number of entries, number of buckets and maximum - length of buckets. */ - -/* Return the number of buckets in the hash table. The table size, the total - number of buckets (used plus unused), or the maximum number of slots, are - the same quantity. */ -extern size_t hash_get_n_buckets (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -/* Return the number of slots in use (non-empty buckets). */ -extern size_t hash_get_n_buckets_used (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -/* Return the number of active entries. */ -extern size_t hash_get_n_entries (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -/* Return the length of the longest chain (bucket). */ -extern size_t hash_get_max_bucket_length (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -/* Do a mild validation of a hash table, by traversing it and checking two - statistics. */ -extern bool hash_table_ok (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -extern void hash_print_statistics (const Hash_table *table, FILE *stream); - -/* If ENTRY matches an entry already in the hash table, return the - entry from the table. Otherwise, return NULL. */ -extern void *hash_lookup (const Hash_table *table, const void *entry); - -/* - * Walking. - */ - -/* The functions in this page traverse the hash table and process the - contained entries. For the traversal to work properly, the hash table - should not be resized nor modified while any particular entry is being - processed. In particular, entries should not be added, and an entry - may be removed only if there is no shrink threshold and the entry being - removed has already been passed to hash_get_next. */ - -/* Return the first data in the table, or NULL if the table is empty. */ -extern void *hash_get_first (const Hash_table *table) - _GL_ATTRIBUTE_PURE; - -/* Return the user data for the entry following ENTRY, where ENTRY has been - returned by a previous call to either 'hash_get_first' or 'hash_get_next'. - Return NULL if there are no more entries. */ -extern void *hash_get_next (const Hash_table *table, const void *entry); - -/* Fill BUFFER with pointers to active user entries in the hash table, then - return the number of pointers copied. Do not copy more than BUFFER_SIZE - pointers. */ -extern size_t hash_get_entries (const Hash_table *table, void **buffer, - size_t buffer_size); - -typedef bool (*Hash_processor) (void *entry, void *processor_data); - -/* Call a PROCESSOR function for each entry of a hash table, and return the - number of entries for which the processor function returned success. A - pointer to some PROCESSOR_DATA which will be made available to each call to - the processor function. The PROCESSOR accepts two arguments: the first is - the user entry being walked into, the second is the value of PROCESSOR_DATA - as received. The walking continue for as long as the PROCESSOR function - returns nonzero. When it returns zero, the walking is interrupted. */ -extern size_t hash_do_for_each (const Hash_table *table, - Hash_processor processor, void *processor_data); - -/* - * Allocation and clean-up. - */ - -/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1. - This is a convenience routine for constructing other hashing functions. */ -extern size_t hash_string (const char *string, size_t n_buckets) - _GL_ATTRIBUTE_PURE; - -extern void hash_reset_tuning (Hash_tuning *tuning); - -typedef size_t (*Hash_hasher) (const void *entry, size_t table_size); -typedef bool (*Hash_comparator) (const void *entry1, const void *entry2); -typedef void (*Hash_data_freer) (void *entry); - -/* Reclaim all storage associated with a hash table. If a data_freer - function has been supplied by the user when the hash table was created, - this function applies it to the data of each entry before freeing that - entry. */ -extern void hash_free (Hash_table *table); - -/* Allocate and return a new hash table, or NULL upon failure. The initial - number of buckets is automatically selected so as to _guarantee_ that you - may insert at least CANDIDATE different user entries before any growth of - the hash table size occurs. So, if have a reasonably tight a-priori upper - bound on the number of entries you intend to insert in the hash table, you - may save some table memory and insertion time, by specifying it here. If - the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE - argument has its meaning changed to the wanted number of buckets. - - TUNING points to a structure of user-supplied values, in case some fine - tuning is wanted over the default behavior of the hasher. If TUNING is - NULL, the default tuning parameters are used instead. If TUNING is - provided but the values requested are out of bounds or might cause - rounding errors, return NULL. - - The user-supplied HASHER function, when not NULL, accepts two - arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a - slot number for that entry which should be in the range 0..TABLE_SIZE-1. - This slot number is then returned. - - The user-supplied COMPARATOR function, when not NULL, accepts two - arguments pointing to user data, it then returns true for a pair of entries - that compare equal, or false otherwise. This function is internally called - on entries which are already known to hash to the same bucket index, - but which are distinct pointers. - - The user-supplied DATA_FREER function, when not NULL, may be later called - with the user data as an argument, just before the entry containing the - data gets freed. This happens from within 'hash_free' or 'hash_clear'. - You should specify this function only if you want these functions to free - all of your 'data' data. This is typically the case when your data is - simply an auxiliary struct that you have malloc'd to aggregate several - values. */ -_GL_ATTRIBUTE_NODISCARD -extern Hash_table *hash_initialize (size_t candidate, - const Hash_tuning *tuning, - Hash_hasher hasher, - Hash_comparator comparator, - Hash_data_freer data_freer) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (hash_free, 1); - -/* Same as hash_initialize, but invokes xalloc_die on memory exhaustion. */ -/* This function is defined by module 'xhash'. */ -_GL_ATTRIBUTE_NODISCARD -extern Hash_table *hash_xinitialize (size_t candidate, - const Hash_tuning *tuning, - Hash_hasher hasher, - Hash_comparator comparator, - Hash_data_freer data_freer) - _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC (hash_free, 1) - _GL_ATTRIBUTE_RETURNS_NONNULL; - -/* Make all buckets empty, placing any chained entries on the free list. - Apply the user-specified function data_freer (if any) to the datas of any - affected entries. */ -extern void hash_clear (Hash_table *table); - -/* - * Insertion and deletion. - */ - -/* For an already existing hash table, change the number of buckets through - specifying CANDIDATE. The contents of the hash table are preserved. The - new number of buckets is automatically selected so as to _guarantee_ that - the table may receive at least CANDIDATE different user entries, including - those already in the table, before any other growth of the hash table size - occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the - exact number of buckets desired. Return true iff the rehash succeeded. */ -_GL_ATTRIBUTE_NODISCARD -extern bool hash_rehash (Hash_table *table, size_t candidate); - -/* If ENTRY matches an entry already in the hash table, return the pointer - to the entry from the table. Otherwise, insert ENTRY and return ENTRY. - Return NULL if the storage required for insertion cannot be allocated. - This implementation does not support duplicate entries or insertion of - NULL. */ -_GL_ATTRIBUTE_NODISCARD -extern void *hash_insert (Hash_table *table, const void *entry); - -/* Same as hash_insert, but invokes xalloc_die on memory exhaustion. */ -/* This function is defined by module 'xhash'. */ -extern void *hash_xinsert (Hash_table *table, const void *entry); - -/* Insert ENTRY into hash TABLE if there is not already a matching entry. - - Return -1 upon memory allocation failure. - Return 1 if insertion succeeded. - Return 0 if there is already a matching entry in the table, - and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT - to that entry. - - This interface is easier to use than hash_insert when you must - distinguish between the latter two cases. More importantly, - hash_insert is unusable for some types of ENTRY values. When using - hash_insert, the only way to distinguish those cases is to compare - the return value and ENTRY. That works only when you can have two - different ENTRY values that point to data that compares "equal". Thus, - when the ENTRY value is a simple scalar, you must use - hash_insert_if_absent. ENTRY must not be NULL. */ -extern int hash_insert_if_absent (Hash_table *table, const void *entry, - const void **matched_ent); - -/* If ENTRY is already in the table, remove it and return the just-deleted - data (the user may want to deallocate its storage). If ENTRY is not in the - table, don't modify the table and return NULL. */ -extern void *hash_remove (Hash_table *table, const void *entry); - -/* Same as hash_remove. This interface is deprecated. - FIXME: Remove in 2022. */ -_GL_ATTRIBUTE_DEPRECATED -extern void *hash_delete (Hash_table *table, const void *entry); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/composefs/libcomposefs/lcfs-erofs-internal.h b/composefs/libcomposefs/lcfs-erofs-internal.h deleted file mode 100644 index f6f7a97..0000000 --- a/composefs/libcomposefs/lcfs-erofs-internal.h +++ /dev/null @@ -1,134 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_EROFS_INTERNAL_H -#define _LCFS_EROFS_INTERNAL_H - -#include - -#include "lcfs-internal.h" -#include "lcfs-erofs.h" -#include "erofs_fs_wrapper.h" - -typedef union { - __le16 i_format; - struct erofs_inode_compact compact; - struct erofs_inode_extended extended; -} erofs_inode; - -static const char *erofs_xattr_prefixes[] = { - "", - "user.", - "system.posix_acl_access", - "system.posix_acl_default", - "trusted.", - "lustre.", - "security.", -}; - -static inline uint16_t erofs_inode_version(const erofs_inode *cino) -{ - uint16_t i_format = lcfs_u16_from_file(cino->i_format); - return (i_format >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK; -} - -static inline bool erofs_inode_is_compact(const erofs_inode *cino) -{ - return erofs_inode_version(cino) == 0; -} - -static inline uint16_t erofs_inode_datalayout(const erofs_inode *cino) -{ - uint16_t i_format = lcfs_u16_from_file(cino->i_format); - return (i_format >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK; -} - -static inline bool erofs_inode_is_tailpacked(const erofs_inode *cino) -{ - return erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_INLINE; -} - -static inline bool erofs_inode_is_flat(const erofs_inode *cino) -{ - return erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_INLINE || - erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_PLAIN; -} - -static inline size_t erofs_xattr_inode_size(uint16_t xattr_icount) -{ - size_t xattr_size = 0; - if (xattr_icount > 0) - xattr_size = sizeof(struct erofs_xattr_ibody_header) + - (xattr_icount - 1) * 4; - return xattr_size; -} - -#define EROFS_N_XATTR_PREFIXES (sizeof(erofs_xattr_prefixes) / sizeof(char *)) - -static inline bool erofs_is_acl_xattr(int prefix, const char *name, size_t name_len) -{ - const char *const nfs_acl = "system.nfs4_acl"; - - if ((prefix == EROFS_XATTR_INDEX_POSIX_ACL_ACCESS || - prefix == EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT) && - name_len == 0) - return true; - if (prefix == 0 && name_len == strlen(nfs_acl) && - memcmp(name, nfs_acl, strlen(nfs_acl)) == 0) - return true; - return false; -} - -static inline int erofs_get_xattr_prefix(const char *str) -{ - for (int i = 1; i < EROFS_N_XATTR_PREFIXES; i++) { - const char *prefix = erofs_xattr_prefixes[i]; - if (strlen(str) >= strlen(prefix) && - memcmp(str, prefix, strlen(prefix)) == 0) { - return i; - } - } - return 0; -} - -static inline char *erofs_get_xattr_name(uint8_t index, const char *name, - size_t name_len) -{ - char *res; - const char *prefix; - size_t prefix_len; - - if (index >= EROFS_N_XATTR_PREFIXES) { - errno = EINVAL; - return NULL; - } - - prefix = erofs_xattr_prefixes[index]; - prefix_len = strlen(prefix); - - res = malloc(prefix_len + name_len + 1); - if (res == NULL) { - errno = ENOMEM; - return NULL; - } - memcpy(res, prefix, prefix_len); - memcpy(res + prefix_len, name, name_len); - res[prefix_len + name_len] = 0; - - return res; -} - -#endif diff --git a/composefs/libcomposefs/lcfs-erofs.h b/composefs/libcomposefs/lcfs-erofs.h deleted file mode 100644 index 0e607f8..0000000 --- a/composefs/libcomposefs/lcfs-erofs.h +++ /dev/null @@ -1,36 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_EROFS_H -#define _LCFS_EROFS_H - -#include - -#define LCFS_EROFS_VERSION 1 -#define LCFS_EROFS_MAGIC 0xd078629aU - -typedef enum { - LCFS_EROFS_FLAGS_HAS_ACL = (1 << 0), -} lcfs_erofs_flag_t; - -struct lcfs_erofs_header_s { - uint32_t magic; - uint32_t version; - uint32_t flags; - uint32_t unused[5]; -} __attribute__((__packed__)); - -#endif diff --git a/composefs/libcomposefs/lcfs-fsverity.c b/composefs/libcomposefs/lcfs-fsverity.c deleted file mode 100644 index 4949dd9..0000000 --- a/composefs/libcomposefs/lcfs-fsverity.c +++ /dev/null @@ -1,457 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SHA256_DATASIZE 64 - -#ifdef HAVE_OPENSSL -/* For sha256 computation */ -#include - -#else /* SHA256 fallback implementation */ - -typedef struct { - uint32_t buf[8]; - uint32_t bits[2]; - - uint8_t data[SHA256_DATASIZE]; -} Sha256sum; - -/* - * SHA-256 Checksum - */ - -/* adapted from the SHA256 implementation in glib, which is originally: - * - * Copyright (C) 2006 Dave Benson - * Released under the terms of the GNU Lesser General Public License - */ - -static void sha256_sum_init(Sha256sum *sha256) -{ - sha256->buf[0] = 0x6a09e667; - sha256->buf[1] = 0xbb67ae85; - sha256->buf[2] = 0x3c6ef372; - sha256->buf[3] = 0xa54ff53a; - sha256->buf[4] = 0x510e527f; - sha256->buf[5] = 0x9b05688c; - sha256->buf[6] = 0x1f83d9ab; - sha256->buf[7] = 0x5be0cd19; - - sha256->bits[0] = sha256->bits[1] = 0; -} - -#define GET_UINT32(n, b, i) \ - do { \ - (n) = ((uint32_t)(b)[(i)] << 24) | \ - ((uint32_t)(b)[(i) + 1] << 16) | \ - ((uint32_t)(b)[(i) + 2] << 8) | ((uint32_t)(b)[(i) + 3]); \ - } while (0) - -#define PUT_UINT32(n, b, i) \ - do { \ - (b)[(i)] = (uint8_t)((n) >> 24); \ - (b)[(i) + 1] = (uint8_t)((n) >> 16); \ - (b)[(i) + 2] = (uint8_t)((n) >> 8); \ - (b)[(i) + 3] = (uint8_t)((n)); \ - } while (0) - -static void sha256_transform(uint32_t buf[8], uint8_t const data[64]) -{ - uint32_t temp1, temp2, W[64]; - uint32_t A, B, C, D, E, F, G, H; - - GET_UINT32(W[0], data, 0); - GET_UINT32(W[1], data, 4); - GET_UINT32(W[2], data, 8); - GET_UINT32(W[3], data, 12); - GET_UINT32(W[4], data, 16); - GET_UINT32(W[5], data, 20); - GET_UINT32(W[6], data, 24); - GET_UINT32(W[7], data, 28); - GET_UINT32(W[8], data, 32); - GET_UINT32(W[9], data, 36); - GET_UINT32(W[10], data, 40); - GET_UINT32(W[11], data, 44); - GET_UINT32(W[12], data, 48); - GET_UINT32(W[13], data, 52); - GET_UINT32(W[14], data, 56); - GET_UINT32(W[15], data, 60); - -#define SHR(x, n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x, n) (SHR(x, n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) -#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) - -#define F0(x, y, z) ((x & y) | (z & (x | y))) -#define F1(x, y, z) (z ^ (x & (y ^ z))) - -#define R(t) (W[t] = S1(W[t - 2]) + W[t - 7] + S0(W[t - 15]) + W[t - 16]) - -#define P(a, b, c, d, e, f, g, h, x, K) \ - do { \ - temp1 = h + S3(e) + F1(e, f, g) + K + x; \ - temp2 = S2(a) + F0(a, b, c); \ - d += temp1; \ - h = temp1 + temp2; \ - } while (0) - - A = buf[0]; - B = buf[1]; - C = buf[2]; - D = buf[3]; - E = buf[4]; - F = buf[5]; - G = buf[6]; - H = buf[7]; - - P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98); - P(H, A, B, C, D, E, F, G, W[1], 0x71374491); - P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF); - P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5); - P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B); - P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1); - P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4); - P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5); - P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98); - P(H, A, B, C, D, E, F, G, W[9], 0x12835B01); - P(G, H, A, B, C, D, E, F, W[10], 0x243185BE); - P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3); - P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74); - P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE); - P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7); - P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174); - P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1); - P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786); - P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6); - P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC); - P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F); - P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA); - P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC); - P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA); - P(A, B, C, D, E, F, G, H, R(24), 0x983E5152); - P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D); - P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8); - P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7); - P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3); - P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147); - P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351); - P(B, C, D, E, F, G, H, A, R(31), 0x14292967); - P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85); - P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138); - P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC); - P(F, G, H, A, B, C, D, E, R(35), 0x53380D13); - P(E, F, G, H, A, B, C, D, R(36), 0x650A7354); - P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB); - P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E); - P(B, C, D, E, F, G, H, A, R(39), 0x92722C85); - P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1); - P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B); - P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70); - P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3); - P(E, F, G, H, A, B, C, D, R(44), 0xD192E819); - P(D, E, F, G, H, A, B, C, R(45), 0xD6990624); - P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585); - P(B, C, D, E, F, G, H, A, R(47), 0x106AA070); - P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116); - P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08); - P(G, H, A, B, C, D, E, F, R(50), 0x2748774C); - P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5); - P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3); - P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A); - P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F); - P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3); - P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE); - P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F); - P(G, H, A, B, C, D, E, F, R(58), 0x84C87814); - P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208); - P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA); - P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB); - P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7); - P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2); - -#undef SHR -#undef ROTR -#undef S0 -#undef S1 -#undef S2 -#undef S3 -#undef F0 -#undef F1 -#undef R -#undef P - - buf[0] += A; - buf[1] += B; - buf[2] += C; - buf[3] += D; - buf[4] += E; - buf[5] += F; - buf[6] += G; - buf[7] += H; -} - -static void sha256_sum_update(Sha256sum *sha256, const uint8_t *buffer, size_t length) -{ - uint32_t left, fill; - const uint8_t *input = buffer; - - if (length == 0) - return; - - left = sha256->bits[0] & 0x3F; - fill = 64 - left; - - sha256->bits[0] += length; - sha256->bits[0] &= 0xFFFFFFFF; - - if (sha256->bits[0] < length) - sha256->bits[1]++; - - if (left > 0 && length >= fill) { - memcpy((sha256->data + left), input, fill); - - sha256_transform(sha256->buf, sha256->data); - length -= fill; - input += fill; - - left = 0; - } - - while (length >= SHA256_DATASIZE) { - sha256_transform(sha256->buf, input); - - length -= 64; - input += 64; - } - - if (length) - memcpy(sha256->data + left, input, length); -} - -static uint8_t sha256_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -static void sha256_sum_close(Sha256sum *sha256, uint8_t *digest) -{ - uint32_t last, padn; - uint32_t high, low; - uint8_t msglen[8]; - - high = (sha256->bits[0] >> 29) | (sha256->bits[1] << 3); - low = (sha256->bits[0] << 3); - - PUT_UINT32(high, msglen, 0); - PUT_UINT32(low, msglen, 4); - - last = sha256->bits[0] & 0x3F; - padn = (last < 56) ? (56 - last) : (120 - last); - - sha256_sum_update(sha256, sha256_padding, padn); - sha256_sum_update(sha256, msglen, 8); - - PUT_UINT32(sha256->buf[0], digest, 0); - PUT_UINT32(sha256->buf[1], digest, 4); - PUT_UINT32(sha256->buf[2], digest, 8); - PUT_UINT32(sha256->buf[3], digest, 12); - PUT_UINT32(sha256->buf[4], digest, 16); - PUT_UINT32(sha256->buf[5], digest, 20); - PUT_UINT32(sha256->buf[6], digest, 24); - PUT_UINT32(sha256->buf[7], digest, 28); -} - -#undef PUT_UINT32 -#undef GET_UINT32 - -#endif /* SHA256 fallback implementation */ - -#include "lcfs-fsverity.h" - -struct fsverity_descriptor { - uint8_t version; - uint8_t hash_algorithm; - uint8_t log_blocksize; - uint8_t salt_size; - uint32_t reserved1; - uint64_t data_size_be; - uint8_t root_hash[64]; - uint8_t salt[32]; - uint8_t reserved2[144]; -}; - -#define FSVERITY_BLOCK_SIZE 4096 -#define FSVERITY_MAX_LEVELS 8 /* enough for 64bit file size */ - -struct FsVerityContext { - uint8_t buffer[FSVERITY_MAX_LEVELS][FSVERITY_BLOCK_SIZE]; - uint32_t buffer_pos[FSVERITY_MAX_LEVELS]; - uint32_t max_level; - uint64_t file_size; -#ifdef HAVE_OPENSSL - EVP_MD_CTX *md_ctx; -#endif -}; - -FsVerityContext *lcfs_fsverity_context_new(void) -{ - FsVerityContext *ctx; - - ctx = calloc(1, sizeof(FsVerityContext)); - if (ctx == NULL) - return NULL; - -#ifdef HAVE_OPENSSL - ctx->md_ctx = EVP_MD_CTX_create(); - if (ctx->md_ctx == NULL) { - free(ctx); - return NULL; - } -#endif - - return ctx; -} - -void lcfs_fsverity_context_free(FsVerityContext *ctx) -{ -#ifdef HAVE_OPENSSL - EVP_MD_CTX_destroy(ctx->md_ctx); -#endif - free(ctx); -} - -static void do_sha256(FsVerityContext *ctx, const uint8_t *data, - size_t data_len, uint8_t *digest) -{ -#ifdef HAVE_OPENSSL - const EVP_MD *md = EVP_sha256(); - int ret; - - assert(md != NULL); - - ret = EVP_DigestInit_ex(ctx->md_ctx, md, NULL); - assert(ret == 1); - - ret = EVP_DigestUpdate(ctx->md_ctx, data, data_len); - assert(ret == 1); - - ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, NULL); - assert(ret == 1); -#else - Sha256sum sha256; - - sha256_sum_init(&sha256); - sha256_sum_update(&sha256, data, data_len); - sha256_sum_close(&sha256, digest); -#endif -} - -static void lcfs_fsverity_context_update_level(FsVerityContext *ctx, uint8_t *data, - size_t data_len, uint32_t level) -{ - assert(level < FSVERITY_MAX_LEVELS); - - if (level > ctx->max_level) - ctx->max_level = level; - - while (data_len > 0) { - /* First check if block is already full, we want to do this lazyly - so we only flush to the next level if there is more data after - the block is full */ - if (ctx->buffer_pos[level] == FSVERITY_BLOCK_SIZE) { - uint8_t digest[LCFS_SHA256_DIGEST_LEN]; - do_sha256(ctx, ctx->buffer[level], FSVERITY_BLOCK_SIZE, - digest); - lcfs_fsverity_context_update_level(ctx, digest, 32, - level + 1); - ctx->buffer_pos[level] = 0; - } - - size_t to_copy = - MIN(FSVERITY_BLOCK_SIZE - ctx->buffer_pos[level], data_len); - - memcpy(ctx->buffer[level] + ctx->buffer_pos[level], data, to_copy); - ctx->buffer_pos[level] += to_copy; - - data += to_copy; - data_len -= to_copy; - } -} - -void lcfs_fsverity_context_update(FsVerityContext *ctx, void *data, size_t data_len) -{ - lcfs_fsverity_context_update_level(ctx, data, data_len, 0); - ctx->file_size += data_len; -} - -static void lcfs_fsverity_context_flush_level(FsVerityContext *ctx, uint32_t level) -{ - uint8_t digest[LCFS_SHA256_DIGEST_LEN]; - - if (ctx->buffer_pos[level] < FSVERITY_BLOCK_SIZE) { - memset(ctx->buffer[level] + ctx->buffer_pos[level], 0, - FSVERITY_BLOCK_SIZE - ctx->buffer_pos[level]); - ctx->buffer_pos[level] = FSVERITY_BLOCK_SIZE; - } - - if (level == ctx->max_level) - return; - - do_sha256(ctx, ctx->buffer[level], FSVERITY_BLOCK_SIZE, digest); - lcfs_fsverity_context_update_level(ctx, digest, LCFS_SHA256_DIGEST_LEN, - level + 1); - - lcfs_fsverity_context_flush_level(ctx, level + 1); -} - -void lcfs_fsverity_context_get_digest(FsVerityContext *ctx, - uint8_t digest[LCFS_SHA256_DIGEST_LEN]) -{ - struct fsverity_descriptor descriptor; - - lcfs_fsverity_context_flush_level(ctx, 0); - - memset(&descriptor, 0, sizeof(descriptor)); - descriptor.version = 1; - descriptor.hash_algorithm = 1; - descriptor.log_blocksize = 12; - descriptor.salt_size = 0; - descriptor.data_size_be = htole64(ctx->file_size); - - do_sha256(ctx, ctx->buffer[ctx->max_level], FSVERITY_BLOCK_SIZE, - descriptor.root_hash); - - do_sha256(ctx, (uint8_t *)&descriptor, sizeof(descriptor), digest); -} diff --git a/composefs/libcomposefs/lcfs-fsverity.h b/composefs/libcomposefs/lcfs-fsverity.h deleted file mode 100644 index cd38045..0000000 --- a/composefs/libcomposefs/lcfs-fsverity.h +++ /dev/null @@ -1,27 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#include - -typedef struct FsVerityContext FsVerityContext; - -#define LCFS_SHA256_DIGEST_LEN 32 - -FsVerityContext *lcfs_fsverity_context_new(void); -void lcfs_fsverity_context_free(FsVerityContext *ctx); -void lcfs_fsverity_context_update(FsVerityContext *ctx, void *data, size_t data_len); -void lcfs_fsverity_context_get_digest(FsVerityContext *ctx, - uint8_t digest[LCFS_SHA256_DIGEST_LEN]); diff --git a/composefs/libcomposefs/lcfs-internal.h b/composefs/libcomposefs/lcfs-internal.h deleted file mode 100644 index f9cab47..0000000 --- a/composefs/libcomposefs/lcfs-internal.h +++ /dev/null @@ -1,205 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_INTERNAL_H -#define _LCFS_INTERNAL_H - -#include - -#include "lcfs-writer.h" -#include "lcfs-fsverity.h" -#include "hash.h" - -/* When using LCFS_BUILD_INLINE_SMALL in lcfs_load_node_from_file() inline files below this size - * We pick 64 which is the size of a sha256 digest that would otherwise be used as a redirect - * xattr, so the inlined file is smaller. - */ -#define LCFS_BUILD_INLINE_FILE_SIZE_LIMIT 64 - -#define OVERLAY_XATTR_USER_PREFIX "user." -#define OVERLAY_XATTR_TRUSTED_PREFIX "trusted." -#define OVERLAY_XATTR_PARTIAL_PREFIX "overlay." -#define OVERLAY_XATTR_PREFIX \ - OVERLAY_XATTR_TRUSTED_PREFIX OVERLAY_XATTR_PARTIAL_PREFIX -#define OVERLAY_XATTR_USERXATTR_PREFIX \ - OVERLAY_XATTR_USER_PREFIX OVERLAY_XATTR_PARTIAL_PREFIX -#define OVERLAY_XATTR_ESCAPE_PREFIX OVERLAY_XATTR_PREFIX "overlay." -#define OVERLAY_XATTR_METACOPY OVERLAY_XATTR_PREFIX "metacopy" -#define OVERLAY_XATTR_REDIRECT OVERLAY_XATTR_PREFIX "redirect" -#define OVERLAY_XATTR_WHITEOUT OVERLAY_XATTR_PREFIX "whiteout" -#define OVERLAY_XATTR_WHITEOUTS OVERLAY_XATTR_PREFIX "whiteouts" -#define OVERLAY_XATTR_OPAQUE OVERLAY_XATTR_PREFIX "opaque" - -#define OVERLAY_XATTR_ESCAPED_WHITEOUT OVERLAY_XATTR_ESCAPE_PREFIX "whiteout" -#define OVERLAY_XATTR_ESCAPED_WHITEOUTS OVERLAY_XATTR_ESCAPE_PREFIX "whiteouts" - -#define OVERLAY_XATTR_USERXATTR_WHITEOUT \ - OVERLAY_XATTR_USERXATTR_PREFIX "whiteout" -#define OVERLAY_XATTR_USERXATTR_WHITEOUTS \ - OVERLAY_XATTR_USERXATTR_PREFIX "whiteouts" - -#define ALIGN_TO(_offset, _align_size) \ - (((_offset) + _align_size - 1) & ~(_align_size - 1)) - -#define __round_mask(x, y) ((__typeof__(x))((y)-1)) -#define round_up(x, y) ((((x)-1) | __round_mask(x, y)) + 1) -#define round_down(x, y) ((x) & ~__round_mask(x, y)) - -#define LCFS_MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */ - -static inline uint16_t lcfs_u16_to_file(uint16_t val) -{ - return htole16(val); -} - -static inline uint32_t lcfs_u32_to_file(uint32_t val) -{ - return htole32(val); -} - -static inline uint64_t lcfs_u64_to_file(uint64_t val) -{ - return htole64(val); -} - -static inline uint16_t lcfs_u16_from_file(uint16_t val) -{ - return le16toh(val); -} - -static inline uint32_t lcfs_u32_from_file(uint32_t val) -{ - return le32toh(val); -} - -static inline uint64_t lcfs_u64_from_file(uint64_t val) -{ - return le64toh(val); -} - -/* In memory representation used to build the file. */ - -struct lcfs_xattr_s { - char *key; - char *value; - size_t value_len; - - /* Used during writing */ - int64_t erofs_shared_xattr_offset; /* shared offset, or -1 if not shared */ -}; - -struct lcfs_inode_s { - uint32_t st_mode; /* File type and mode. */ - uint32_t st_nlink; /* Number of hard links, only for regular files. */ - uint32_t st_uid; /* User ID of owner. */ - uint32_t st_gid; /* Group ID of owner. */ - uint32_t st_rdev; /* Device ID (if special file). */ - uint64_t st_size; /* Size of file, only used for regular files */ - int64_t st_mtim_sec; - uint32_t st_mtim_nsec; -}; - -struct lcfs_node_s { - int ref_count; - - struct lcfs_node_s *parent; - - struct lcfs_node_s **children; /* Owns refs */ - size_t children_size; - - /* Used to create hard links. */ - struct lcfs_node_s *link_to; /* Owns refs */ - - char *name; - char *payload; /* backing file or symlink target */ - - uint8_t *content; - - struct lcfs_xattr_s *xattrs; - size_t n_xattrs; - - bool digest_set; - uint8_t digest[LCFS_DIGEST_SIZE]; /* sha256 fs-verity digest */ - - struct lcfs_inode_s inode; - - /* Used during compute_tree */ - struct lcfs_node_s *next; /* Use for the queue in compute_tree */ - bool in_tree; - uint32_t inode_num; - - bool erofs_compact; - uint32_t erofs_ipad; /* padding before inode data */ - uint32_t erofs_isize; - uint32_t erofs_nid; - uint32_t erofs_n_blocks; - uint32_t erofs_tailsize; -}; - -struct lcfs_ctx_s { - struct lcfs_write_options_s *options; - struct lcfs_node_s *root; - bool destroy_root; - - /* Used by compute_tree. */ - struct lcfs_node_s *queue_end; - uint32_t num_inodes; - int64_t min_mtim_sec; - uint32_t min_mtim_nsec; - bool has_acl; - - void *file; - lcfs_write_cb write_cb; - off_t bytes_written; - FsVerityContext *fsverity_ctx; - - void (*finalize)(struct lcfs_ctx_s *ctx); -}; - -static inline void lcfs_node_unrefp(struct lcfs_node_s **nodep) -{ - if (*nodep != NULL) { - lcfs_node_unref(*nodep); - *nodep = NULL; - } -} -#define cleanup_node __attribute__((cleanup(lcfs_node_unrefp))) - -/* lcfs-writer.c */ -size_t hash_memory(const char *string, size_t len, size_t n_buckets); -int lcfs_write(struct lcfs_ctx_s *ctx, void *_data, size_t data_len); -int lcfs_write_align(struct lcfs_ctx_s *ctx, size_t align_size); -int lcfs_write_pad(struct lcfs_ctx_s *ctx, size_t data_len); -int lcfs_compute_tree(struct lcfs_ctx_s *ctx, struct lcfs_node_s *root); -int lcfs_clone_root(struct lcfs_ctx_s *ctx); -char *maybe_join_path(const char *a, const char *b); -struct lcfs_node_s *follow_links(struct lcfs_node_s *node); -int node_get_dtype(struct lcfs_node_s *node); - -int lcfs_node_rename_xattr(struct lcfs_node_s *node, size_t index, - const char *new_name); - -/* lcfs-writer-erofs.c */ - -int lcfs_write_erofs_to(struct lcfs_ctx_s *ctx); -struct lcfs_ctx_s *lcfs_ctx_erofs_new(void); - -/* lcfs-writer-cfs.c */ - -int lcfs_write_cfs_to(struct lcfs_ctx_s *ctx); -struct lcfs_ctx_s *lcfs_ctx_cfs_new(void); - -#endif diff --git a/composefs/libcomposefs/lcfs-mount.c b/composefs/libcomposefs/lcfs-mount.c deleted file mode 100644 index 0a4b08f..0000000 --- a/composefs/libcomposefs/lcfs-mount.c +++ /dev/null @@ -1,616 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#define _GNU_SOURCE - -#include "config.h" - -#include "lcfs-writer.h" -#include "lcfs-mount.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#ifdef HAVE_FSCONFIG_CMD_CREATE_LINUX_MOUNT_H -#include -#endif -#if defined HAVE_FSCONFIG_CMD_CREATE_LINUX_MOUNT_H || \ - defined HAVE_FSCONFIG_CMD_CREATE_SYS_MOUNT_H -#define HAVE_NEW_MOUNT_API -#endif - -#include "lcfs-erofs.h" -#include "lcfs-utils.h" -#include "lcfs-internal.h" - -static int syscall_fsopen(const char *fs_name, unsigned int flags) -{ -#if defined __NR_fsopen - return (int)syscall(__NR_fsopen, fs_name, flags); -#else - (void)fs_name; - (void)flags; - errno = ENOSYS; - return -1; -#endif -} - -static int syscall_fsmount(int fsfd, unsigned int flags, unsigned int attr_flags) -{ -#if defined __NR_fsmount - return (int)syscall(__NR_fsmount, fsfd, flags, attr_flags); -#else - (void)fsfd; - (void)flags; - (void)attr_flags; - errno = ENOSYS; - return -1; -#endif -} - -static int syscall_fsconfig(int fsfd, unsigned int cmd, const char *key, - const void *val, int aux) -{ -#if defined __NR_fsconfig - return (int)syscall(__NR_fsconfig, fsfd, cmd, key, val, aux); -#else - (void)fsfd; - (void)cmd; - (void)key; - (void)val; - (void)aux; - errno = ENOSYS; - return -1; -#endif -} - -static int syscall_move_mount(int from_dfd, const char *from_pathname, int to_dfd, - const char *to_pathname, unsigned int flags) - -{ -#if defined __NR_move_mount - return (int)syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, - to_pathname, flags); -#else - (void)from_dfd; - (void)from_pathname; - (void)to_dfd; - (void)to_pathname; - (void)flags; - errno = ENOSYS; - return -1; -#endif -} - -static int syscall_mount_setattr(int dfd, const char *path, unsigned int flags, - struct mount_attr *attr, size_t usize) -{ -#ifdef __NR_mount_setattr - return (int)syscall(__NR_mount_setattr, dfd, path, flags, attr, usize); -#else - (void)dfd; - (void)path; - (void)flags; - (void)attr; - errno = ENOSYS; - return -1; -#endif -} - -#define MAX_DIGEST_SIZE 64 - -struct lcfs_mount_state_s { - const char *image_path; - const char *mountpoint; - struct lcfs_mount_options_s *options; - int fd; - uint8_t expected_digest[MAX_DIGEST_SIZE]; - int expected_digest_len; -}; - -static void escape_mount_option_to(const char *str, char *dest) -{ - const char *s; - char *d; - - d = dest + strlen(dest); - for (s = str; *s != 0; s++) { - if (*s == ',') - *d++ = '\\'; - *d++ = *s; - } - *d++ = 0; -} - -static char *escape_mount_option(const char *str) -{ - const char *s; - char *res; - int n_escapes = 0; - - for (s = str; *s != 0; s++) { - if (*s == ',') - n_escapes++; - } - - res = malloc(strlen(str) + n_escapes + 1); - if (res == NULL) - return NULL; - - *res = 0; - - escape_mount_option_to(str, res); - - return res; -} - -static int hexdigit(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return 10 + (c - 'a'); - if (c >= 'A' && c <= 'F') - return 10 + (c - 'A'); - return -1; -} - -static int digest_to_raw(const char *digest, uint8_t *raw, int max_size) -{ - int size = 0; - - while (*digest) { - char c1, c2; - int n1, n2; - - if (size >= max_size) - return -1; - - c1 = *digest++; - n1 = hexdigit(c1); - if (n1 < 0) - return -1; - - c2 = *digest++; - n2 = hexdigit(c2); - if (n2 < 0) - return -1; - - raw[size++] = (n1 & 0xf) << 4 | (n2 & 0xf); - } - - return size; -} - -static int lcfs_validate_mount_options(struct lcfs_mount_state_s *state) -{ - struct lcfs_mount_options_s *options = state->options; - - if ((options->flags & ~LCFS_MOUNT_FLAGS_MASK) != 0) { - return -EINVAL; - } - - if ((options->flags & LCFS_MOUNT_FLAGS_REQUIRE_VERITY) && - (options->flags & LCFS_MOUNT_FLAGS_DISABLE_VERITY)) { - return -EINVAL; /* Can't have both */ - } - - if (options->n_objdirs == 0) - return -EINVAL; - - if ((options->upperdir && !options->workdir) || - (!options->upperdir && options->workdir)) - return -EINVAL; - - if (options->expected_fsverity_digest) { - int raw_len = digest_to_raw(options->expected_fsverity_digest, - state->expected_digest, MAX_DIGEST_SIZE); - if (raw_len < 0) - return -EINVAL; - state->expected_digest_len = raw_len; - } - - if ((options->flags & LCFS_MOUNT_FLAGS_IDMAP) != 0 && options->idmap_fd < 0) { - return -EINVAL; - } - - return 0; -} - -static int lcfs_validate_verity_fd(struct lcfs_mount_state_s *state) -{ - struct { - struct fsverity_digest fsv; - char buf[MAX_DIGEST_SIZE]; - } buf; - int res; - - if (state->expected_digest_len != 0) { - buf.fsv.digest_size = MAX_DIGEST_SIZE; - res = ioctl(state->fd, FS_IOC_MEASURE_VERITY, &buf.fsv); - if (res == -1) { - if (errno == ENODATA || errno == EOPNOTSUPP || errno == ENOTTY) - return -ENOVERITY; - return -errno; - } - if (buf.fsv.digest_size != state->expected_digest_len || - memcmp(state->expected_digest, buf.fsv.digest, - buf.fsv.digest_size) != 0) - return -EWRONGVERITY; - } - - return 0; -} - -static int setup_loopback(int fd, const char *image_path, char *loopname) -{ - struct loop_config loopconfig = { 0 }; - int loopctlfd, loopfd; - long devnr; - int errsv; - - loopctlfd = open("/dev/loop-control", O_RDWR | O_CLOEXEC); - if (loopctlfd < 0) - return -errno; - - devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE); - errsv = errno; - close(loopctlfd); - if (devnr == -1) { - return -errsv; - } - - sprintf(loopname, "/dev/loop%ld", devnr); - loopfd = open(loopname, O_RDWR | O_CLOEXEC); - if (loopfd < 0) - return -errno; - - loopconfig.fd = fd; - loopconfig.block_size = - 4096; /* This is what we use for the erofs block size, so probably good */ - loopconfig.info.lo_flags = - LO_FLAGS_READ_ONLY | LO_FLAGS_DIRECT_IO | LO_FLAGS_AUTOCLEAR; - if (image_path) - strncat((char *)loopconfig.info.lo_file_name, image_path, - LO_NAME_SIZE - 1); - - if (ioctl(loopfd, LOOP_CONFIGURE, &loopconfig) < 0) { - errsv = errno; - close(loopfd); - return -errsv; - } - - return loopfd; -} - -static char *compute_lower(const char *imagemount, - struct lcfs_mount_state_s *state, bool with_datalower) -{ - size_t size; - char *lower; - size_t i; - - /* Compute the total max size (including escapes) */ - size = 2 * strlen(imagemount); - for (i = 0; i < state->options->n_objdirs; i++) - size += 2 + 2 * strlen(state->options->objdirs[i]); - - lower = malloc(size + 1); - if (lower == NULL) - return NULL; - *lower = 0; - - escape_mount_option_to(imagemount, lower); - - for (i = 0; i < state->options->n_objdirs; i++) { - if (with_datalower) - strcat(lower, "::"); - else - strcat(lower, ":"); - escape_mount_option_to(state->options->objdirs[i], lower); - } - - return lower; -} - -static int lcfs_mount_erofs(const char *source, const char *target, - uint32_t image_flags, struct lcfs_mount_state_s *state) -{ - bool image_has_acls = (image_flags & LCFS_EROFS_FLAGS_HAS_ACL) != 0; - bool use_idmap = (state->options->flags & LCFS_MOUNT_FLAGS_IDMAP) != 0; - int res; - -#ifdef HAVE_NEW_MOUNT_API - /* We have new mount API is in header */ - cleanup_fd int fd_fs = -1; - cleanup_fd int fd_mnt = -1; - - fd_fs = syscall_fsopen("erofs", FSOPEN_CLOEXEC); - if (fd_fs < 0) { - if (errno == ENOSYS) - goto fallback; - return -errno; - } - - res = syscall_fsconfig(fd_fs, FSCONFIG_SET_STRING, "source", source, 0); - if (res < 0) - return -errno; - - res = syscall_fsconfig(fd_fs, FSCONFIG_SET_FLAG, "ro", NULL, 0); - if (res < 0) - return -errno; - - if (!image_has_acls) { - res = syscall_fsconfig(fd_fs, FSCONFIG_SET_FLAG, "noacl", NULL, 0); - if (res < 0) - return -errno; - } - - res = syscall_fsconfig(fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0); - if (res < 0) - return -errno; - - fd_mnt = syscall_fsmount(fd_fs, FSMOUNT_CLOEXEC, MS_RDONLY); - if (fd_mnt < 0) - return -errno; - - if (use_idmap) { - struct mount_attr attr = { - .attr_set = MOUNT_ATTR_IDMAP, - .userns_fd = state->options->idmap_fd, - }; - - res = syscall_mount_setattr(fd_mnt, "", AT_EMPTY_PATH, &attr, - sizeof(struct mount_attr)); - if (res < 0) - return -errno; - } - - res = syscall_move_mount(fd_mnt, "", AT_FDCWD, target, - MOVE_MOUNT_F_EMPTY_PATH); - if (res < 0) - return -errno; - - return 0; - -fallback: -#endif - - /* We need new mount api for idmapped mounts */ - if (use_idmap) - return -ENOTSUP; - - res = mount(source, target, "erofs", MS_RDONLY, - image_has_acls ? "ro" : "ro,noacl"); - if (res < 0) - return -errno; - - return 0; -} - -#define HEADER_SIZE sizeof(struct lcfs_erofs_header_s) - -static int lcfs_mount_erofs_ovl(struct lcfs_mount_state_s *state, - struct lcfs_erofs_header_s *header) -{ - struct lcfs_mount_options_s *options = state->options; - uint32_t image_flags; - char imagemountbuf[] = "/tmp/.composefs.XXXXXX"; - char *imagemount; - bool created_tmpdir = false; - char loopname[PATH_MAX]; - int res, errsv; - cleanup_free char *lowerdir_1 = NULL; - cleanup_free char *lowerdir_2 = NULL; - cleanup_free char *upperdir = NULL; - cleanup_free char *workdir = NULL; - cleanup_free char *overlay_options = NULL; - /* Can point to lowerdir_1 or _2 */ - const char *lowerdir_target = NULL; - int loopfd; - bool require_verity; - bool disable_verity; - bool readonly; - int mount_flags; - - image_flags = lcfs_u32_from_file(header->flags); - - require_verity = (options->flags & LCFS_MOUNT_FLAGS_REQUIRE_VERITY) != 0; - disable_verity = (options->flags & LCFS_MOUNT_FLAGS_DISABLE_VERITY) != 0; - readonly = (options->flags & LCFS_MOUNT_FLAGS_READONLY) != 0; - - loopfd = setup_loopback(state->fd, state->image_path, loopname); - if (loopfd < 0) - return loopfd; - - if (options->image_mountdir) { - imagemount = (char *)options->image_mountdir; - } else { - imagemount = mkdtemp(imagemountbuf); - if (imagemount == NULL) { - errsv = errno; - close(loopfd); - return -errsv; - } - created_tmpdir = true; - } - - res = lcfs_mount_erofs(loopname, imagemount, image_flags, state); - close(loopfd); - if (res < 0) { - rmdir(imagemount); - return res; - } - - /* We use the legacy API to mount overlayfs, because the new API doesn't allow use - * to pass in escaped directory names - */ - - /* First try new version with :: separating datadirs. */ - lowerdir_1 = compute_lower(imagemount, state, true); - if (lowerdir_1 == NULL) { - res = -ENOMEM; - goto fail; - } - lowerdir_target = lowerdir_1; - - /* Then fall back. */ - lowerdir_2 = compute_lower(imagemount, state, false); - if (lowerdir_2 == NULL) { - res = -ENOMEM; - goto fail; - } - - if (options->upperdir) { - upperdir = escape_mount_option(options->upperdir); - if (upperdir == NULL) { - res = -ENOMEM; - goto fail; - } - } - if (options->workdir) { - workdir = escape_mount_option(options->workdir); - if (workdir == NULL) { - res = -ENOMEM; - goto fail; - } - } - -retry: - free(steal_pointer(&overlay_options)); - res = asprintf(&overlay_options, - "metacopy=on,redirect_dir=on,lowerdir=%s%s%s%s%s%s", - lowerdir_target, upperdir ? ",upperdir=" : "", - upperdir ? upperdir : "", workdir ? ",workdir=" : "", - workdir ? workdir : "", - require_verity ? ",verity=require" : - (disable_verity ? ",verity=off" : "")); - if (res < 0) { - res = -ENOMEM; - goto fail; - } - - mount_flags = 0; - if (readonly) - mount_flags |= MS_RDONLY; - if (lowerdir_target == lowerdir_1) - mount_flags |= MS_SILENT; - - res = mount("overlay", state->mountpoint, "overlay", mount_flags, - overlay_options); - if (res != 0) { - res = -errno; - } - - if (res == -EINVAL && lowerdir_target == lowerdir_1) { - lowerdir_target = lowerdir_2; - goto retry; - } - -fail: - umount2(imagemount, MNT_DETACH); - if (created_tmpdir) { - rmdir(imagemount); - } - - return res; -} - -static int lcfs_mount(struct lcfs_mount_state_s *state) -{ - uint8_t header_data[HEADER_SIZE]; - struct lcfs_erofs_header_s *erofs_header; - int res; - - res = lcfs_validate_verity_fd(state); - if (res < 0) - return res; - - res = pread(state->fd, &header_data, HEADER_SIZE, 0); - if (res < 0) - return -errno; - - erofs_header = (struct lcfs_erofs_header_s *)header_data; - if (lcfs_u32_from_file(erofs_header->magic) == LCFS_EROFS_MAGIC) - return lcfs_mount_erofs_ovl(state, erofs_header); - - return -EINVAL; -} - -int lcfs_mount_fd(int fd, const char *mountpoint, struct lcfs_mount_options_s *options) -{ - struct lcfs_mount_state_s state = { .mountpoint = mountpoint, - .options = options, - .fd = fd }; - int res; - - res = lcfs_validate_mount_options(&state); - if (res < 0) { - errno = -res; - return -1; - } - - res = lcfs_mount(&state); - if (res < 0) { - errno = -res; - return -1; - } - return 0; -} - -int lcfs_mount_image(const char *path, const char *mountpoint, - struct lcfs_mount_options_s *options) -{ - struct lcfs_mount_state_s state = { .image_path = path, - .mountpoint = mountpoint, - .options = options, - .fd = -1 }; - int fd, res; - - res = lcfs_validate_mount_options(&state); - if (res < 0) { - errno = -res; - return -1; - } - - fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - return -1; - } - state.fd = fd; - - res = lcfs_mount(&state); - close(fd); - if (res < 0) { - errno = -res; - return -1; - } - - return 0; -} diff --git a/composefs/libcomposefs/lcfs-mount.h b/composefs/libcomposefs/lcfs-mount.h deleted file mode 100644 index d8e837b..0000000 --- a/composefs/libcomposefs/lcfs-mount.h +++ /dev/null @@ -1,63 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_MOUNT_H -#define _LCFS_MOUNT_H - -#include -#include -#include -#include -#include - -#ifndef LCFS_EXTERN -#define LCFS_EXTERN extern -#endif - -#define ENOVERITY ENOTTY -#define EWRONGVERITY EILSEQ -#define ENOSIGNATURE EBADMSG - -enum lcfs_mount_flags_t { - LCFS_MOUNT_FLAGS_NONE = 0, - LCFS_MOUNT_FLAGS_REQUIRE_VERITY = (1 << 0), - LCFS_MOUNT_FLAGS_READONLY = (1 << 1), - LCFS_MOUNT_FLAGS_IDMAP = (1 << 3), - LCFS_MOUNT_FLAGS_DISABLE_VERITY = (1 << 4), - - LCFS_MOUNT_FLAGS_MASK = (1 << 5) - 1, -}; - -struct lcfs_mount_options_s { - const char **objdirs; - size_t n_objdirs; - const char *workdir; - const char *upperdir; - const char *expected_fsverity_digest; - uint32_t flags; - int idmap_fd; /* userns fd */ - const char *image_mountdir; /* Temporary location to mount images if needed */ - - uint32_t reserved[4]; - void *reserved2[4]; -}; - -LCFS_EXTERN int lcfs_mount_image(const char *path, const char *mountpoint, - struct lcfs_mount_options_s *options); -LCFS_EXTERN int lcfs_mount_fd(int fd, const char *mountpoint, - struct lcfs_mount_options_s *options); - -#endif diff --git a/composefs/libcomposefs/lcfs-utils.h b/composefs/libcomposefs/lcfs-utils.h deleted file mode 100644 index e493d6d..0000000 --- a/composefs/libcomposefs/lcfs-utils.h +++ /dev/null @@ -1,111 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_UTILS_H -#define _LCFS_UTILS_H - -#include -#include -#include -#include -#include - -#define max(a, b) ((a > b) ? (a) : (b)) -#define min(a, b) (((a) < (b)) ? (a) : (b)) - -static inline bool str_has_prefix(const char *str, const char *prefix) -{ - return strncmp(str, prefix, strlen(prefix)) == 0; -} - -static inline char *memdup(const char *s, size_t len) -{ - char *s2 = malloc(len); - if (s2 == NULL) { - errno = ENOMEM; - return NULL; - } - memcpy(s2, s, len); - return s2; -} - -static inline char *str_join(const char *a, const char *b) -{ - size_t a_len = strlen(a); - size_t b_len = strlen(b); - char *res = malloc(a_len + b_len + 1); - if (res) { - memcpy(res, a, a_len); - memcpy(res + a_len, b, b_len + 1); - } - return res; -} - -static inline void _lcfs_reset_errno_(int *saved_errno) -{ - if (*saved_errno < 0) - return; - errno = *saved_errno; -} - -// This helper was taken from systemd; it ensures that the value of errno -// is reset. -#define PROTECT_ERRNO \ - __attribute__((cleanup(_lcfs_reset_errno_))) \ - __attribute__((unused)) int _saved_errno_ = errno - -static inline void cleanup_freep(void *p) -{ - void **pp = (void **)p; - - if (*pp) - free(*pp); -} - -// A wrapper around close() that takes a pointer to a file descriptor (integer): -// - Never returns an error (and preserves errno) -// - Sets the value to -1 after closing to make cleanup idempotent -static inline void cleanup_fdp(int *fdp) -{ - PROTECT_ERRNO; - int fd; - - assert(fdp); - - fd = *fdp; - if (fd != -1) - (void)close(fd); - *fdp = -1; -} - -#define cleanup_free __attribute__((cleanup(cleanup_freep))) -#define cleanup_fd __attribute__((cleanup(cleanup_fdp))) - -static inline void *steal_pointer(void *pp) -{ - void **ptr = (void **)pp; - void *ref; - - ref = *ptr; - *ptr = NULL; - - return ref; -} - -/* type safety */ -#define steal_pointer(pp) (0 ? (*(pp)) : (steal_pointer)(pp)) - -#endif diff --git a/composefs/libcomposefs/lcfs-writer-erofs.c b/composefs/libcomposefs/lcfs-writer-erofs.c deleted file mode 100644 index c061703..0000000 --- a/composefs/libcomposefs/lcfs-writer-erofs.c +++ /dev/null @@ -1,1880 +0,0 @@ -/* lcfs - Copyright (C) 2023 Alexander Larsson - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#define _GNU_SOURCE - -#include "config.h" - -#include "lcfs-internal.h" -#include "lcfs-utils.h" -#include "lcfs-writer.h" -#include "lcfs-fsverity.h" -#include "lcfs-erofs-internal.h" -#include "lcfs-utils.h" -#include "hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* The xxh32 hash function is copied from the linux kernel at: - * https://github.com/torvalds/linux/blob/d89775fc929c5a1d91ed518a71b456da0865e5ff/lib/xxhash.c - * - * The original copyright is: - * - * xxHash - Extremely Fast Hash algorithm - * Copyright (C) 2012-2016, Yann Collet. - * - * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License version 2 as published by the - * Free Software Foundation. This program is dual-licensed; you may select - * either version 2 of the GNU General Public License ("GPL") or BSD license - * ("BSD"). - * - * You can contact the author at: - * - xxHash homepage: https://cyan4973.github.io/xxHash/ - * - xxHash source repository: https://github.com/Cyan4973/xxHash - */ - -static const uint32_t PRIME32_1 = 2654435761U; -static const uint32_t PRIME32_2 = 2246822519U; -static const uint32_t PRIME32_3 = 3266489917U; -static const uint32_t PRIME32_4 = 668265263U; -static const uint32_t PRIME32_5 = 374761393U; - -static inline uint32_t get_unaligned_le32(const uint8_t *p) -{ - return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; -} - -#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r))) - -static uint32_t xxh32_round(uint32_t seed, const uint32_t input) -{ - seed += input * PRIME32_2; - seed = xxh_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -static uint32_t xxh32(const void *input, const size_t len, const uint32_t seed) -{ - const uint8_t *p = (const uint8_t *)input; - const uint8_t *b_end = p + len; - uint32_t h32; - - if (len >= 16) { - const uint8_t *const limit = b_end - 16; - uint32_t v1 = seed + PRIME32_1 + PRIME32_2; - uint32_t v2 = seed + PRIME32_2; - uint32_t v3 = seed + 0; - uint32_t v4 = seed - PRIME32_1; - - do { - v1 = xxh32_round(v1, get_unaligned_le32(p)); - p += 4; - v2 = xxh32_round(v2, get_unaligned_le32(p)); - p += 4; - v3 = xxh32_round(v3, get_unaligned_le32(p)); - p += 4; - v4 = xxh32_round(v4, get_unaligned_le32(p)); - p += 4; - } while (p <= limit); - - h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) + - xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18); - } else { - h32 = seed + PRIME32_5; - } - - h32 += (uint32_t)len; - - while (p + 4 <= b_end) { - h32 += get_unaligned_le32(p) * PRIME32_3; - h32 = xxh_rotl32(h32, 17) * PRIME32_4; - p += 4; - } - - while (p < b_end) { - h32 += (*p) * PRIME32_5; - h32 = xxh_rotl32(h32, 11) * PRIME32_1; - p++; - } - - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - -struct lcfs_ctx_erofs_s { - struct lcfs_ctx_s base; - - uint64_t inodes_end; /* start of xattrs */ - uint64_t shared_xattr_size; - uint64_t n_data_blocks; - uint64_t current_end; - struct lcfs_xattr_s **shared_xattrs; - size_t n_shared_xattrs; -}; - -static void lcfs_ctx_erofs_finalize(struct lcfs_ctx_s *ctx) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - - free(ctx_erofs->shared_xattrs); -} - -struct lcfs_ctx_s *lcfs_ctx_erofs_new(void) -{ - struct lcfs_ctx_erofs_s *ret = calloc(1, sizeof(struct lcfs_ctx_erofs_s)); - if (ret == NULL) { - return NULL; - } - - ret->base.finalize = lcfs_ctx_erofs_finalize; - - return &ret->base; -} - -static int erofs_make_file_type(int regular) -{ - switch (regular) { - case DT_LNK: - return EROFS_FT_SYMLINK; - case DT_DIR: - return EROFS_FT_DIR; - case DT_REG: - return EROFS_FT_REG_FILE; - case DT_BLK: - return EROFS_FT_BLKDEV; - case DT_CHR: - return EROFS_FT_CHRDEV; - case DT_SOCK: - return EROFS_FT_SOCK; - case DT_FIFO: - return EROFS_FT_FIFO; - default: - return EROFS_FT_UNKNOWN; - } -} - -struct hasher_xattr_s { - struct lcfs_xattr_s *xattr; - uint32_t count; - - bool shared; - uint64_t shared_offset; /* offset in bytes from start of shared xattrs */ -}; - -static size_t xattrs_ht_hasher(const void *d, size_t n) -{ - const struct hasher_xattr_s *v = d; - return (hash_string(v->xattr->key, n) ^ - hash_memory(v->xattr->value, v->xattr->value_len, n)) % - n; -} - -static bool xattrs_ht_comparator(const void *d1, const void *d2) -{ - const struct hasher_xattr_s *v1 = d1; - const struct hasher_xattr_s *v2 = d2; - - if (strcmp(v1->xattr->key, v2->xattr->key) != 0) - return false; - - if (v1->xattr->value_len != v2->xattr->value_len) - return false; - - return memcmp(v1->xattr->value, v2->xattr->value, v1->xattr->value_len) == 0; -} - -/* Sort alphabetically by key and value to get some canonical order */ -static int xattrs_ht_sort(const void *d1, const void *d2) -{ - const struct hasher_xattr_s *v1 = *(const struct hasher_xattr_s **)d1; - const struct hasher_xattr_s *v2 = *(const struct hasher_xattr_s **)d2; - int r; - - r = strcmp(v2->xattr->key, v1->xattr->key); - if (r != 0) - return r; - - if (v1->xattr->value_len != v2->xattr->value_len) - return (int)v2->xattr->value_len - (int)v1->xattr->value_len; - - return memcmp(v2->xattr->value, v1->xattr->value, v1->xattr->value_len); -} - -static uint8_t xattr_erofs_entry_index(struct lcfs_xattr_s *xattr, char **rest) -{ - char *key = xattr->key; - struct { - const char *prefix; - uint8_t index; - } keys[] = { { "user.", EROFS_XATTR_INDEX_USER }, - { "system.posix_acl_access", EROFS_XATTR_INDEX_POSIX_ACL_ACCESS }, - { "system.posix_acl_default", EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT }, - { "trusted.", EROFS_XATTR_INDEX_TRUSTED }, - { "security.", EROFS_XATTR_INDEX_SECURITY }, - { NULL } }; - for (size_t i = 0; keys[i].prefix != NULL; i++) { - if (str_has_prefix(key, keys[i].prefix)) { - *rest = key + strlen(keys[i].prefix); - return keys[i].index; - } - } - - *rest = key; - return 0; -} - -static size_t xattr_erofs_entry_size(struct lcfs_xattr_s *xattr) -{ - char *key_suffix; - xattr_erofs_entry_index(xattr, &key_suffix); - - return round_up(sizeof(struct erofs_xattr_entry) + strlen(key_suffix) + - xattr->value_len, - sizeof(uint32_t)); -} - -static size_t xattr_erofs_icount(size_t xattr_size) -{ - if (xattr_size == 0) - return 0; - return (xattr_size - sizeof(struct erofs_xattr_ibody_header)) / - sizeof(uint32_t) + - 1; -} - -static size_t xattr_erofs_inode_size(size_t n_shared_xattrs, size_t unshared_xattrs_size) -{ - if (n_shared_xattrs == 0 && unshared_xattrs_size == 0) { - return 0; - } - - return round_up(sizeof(struct erofs_xattr_ibody_header) + - n_shared_xattrs * sizeof(uint32_t) + - unshared_xattrs_size, - sizeof(uint32_t)); -} - -static bool erofs_xattr_should_be_shared(struct hasher_xattr_s *ent) -{ - /* Share multi-use xattrs */ - if (ent->count > 1) - return true; - - return false; -} - -static int compute_erofs_shared_xattrs(struct lcfs_ctx_s *ctx) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - struct lcfs_node_s *node; - Hash_table *xattr_hash; - struct hasher_xattr_s **sorted = NULL; - size_t n_xattrs; - uint64_t xattr_offset; - - /* Find the use count for each xattr key/value in use */ - - xattr_hash = hash_initialize(0, NULL, xattrs_ht_hasher, - xattrs_ht_comparator, free); - if (xattr_hash == NULL) { - return -1; - } - - for (node = ctx->root; node != NULL; node = node->next) { - for (size_t i = 0; i < node->n_xattrs; i++) { - struct hasher_xattr_s hkey = { .xattr = &node->xattrs[i] }; - struct hasher_xattr_s *ent; - - ent = hash_lookup(xattr_hash, &hkey); - if (ent == NULL) { - struct hasher_xattr_s *new_ent = - calloc(1, sizeof(struct hasher_xattr_s)); - if (new_ent == NULL) { - goto fail; - } - new_ent->xattr = &node->xattrs[i]; - ent = hash_insert(xattr_hash, new_ent); - if (ent == NULL) { - goto fail; - } - } - ent->count++; - } - } - - /* Compute the xattr list in canonical order */ - - n_xattrs = hash_get_n_entries(xattr_hash); - sorted = calloc(n_xattrs, sizeof(struct hasher_xattr_s *)); - if (sorted == NULL) - goto fail; - n_xattrs = hash_get_entries(xattr_hash, (void **)sorted, n_xattrs); - qsort(sorted, n_xattrs, sizeof(struct hasher_xattr_s *), xattrs_ht_sort); - - /* Compute the list of shared (multi-use) xattrs and their offsets */ - ctx_erofs->shared_xattrs = calloc(n_xattrs, sizeof(struct lcfs_xattr_s *)); - if (ctx_erofs->shared_xattrs == NULL) - goto fail; - ctx_erofs->n_shared_xattrs = 0; - - xattr_offset = 0; - for (size_t i = 0; i < n_xattrs; i++) { - struct hasher_xattr_s *ent = sorted[i]; - if (erofs_xattr_should_be_shared(ent)) { - ent->shared = true; - ent->shared_offset = xattr_offset; - - ctx_erofs->shared_xattrs[ctx_erofs->n_shared_xattrs] = - ent->xattr; - ctx_erofs->n_shared_xattrs++; - - xattr_offset += xattr_erofs_entry_size(ent->xattr); - } - } - - ctx_erofs->shared_xattr_size = xattr_offset; - - /* Assign shared xattr offsets for all inodes */ - - for (node = ctx->root; node != NULL; node = node->next) { - int n_shared = 0; - for (size_t i = 0; i < node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - struct hasher_xattr_s hkey = { .xattr = xattr }; - struct hasher_xattr_s *ent; - - ent = hash_lookup(xattr_hash, &hkey); - assert(ent != NULL); - if (ent->shared && n_shared < EROFS_XATTR_LONG_PREFIX) { - xattr->erofs_shared_xattr_offset = ent->shared_offset; - n_shared++; - } else { - xattr->erofs_shared_xattr_offset = -1; - } - } - } - - free(sorted); - hash_free(xattr_hash); - return 0; - -fail: - errno = ENOMEM; - free(sorted); - hash_free(xattr_hash); - return -1; -} - -static bool lcfs_fits_in_erofs_compact(struct lcfs_ctx_s *ctx, - struct lcfs_node_s *node) -{ - int type = node->inode.st_mode & S_IFMT; - uint64_t size; - - if (node->inode.st_mtim_sec != ctx->min_mtim_sec || - node->inode.st_mtim_nsec != ctx->min_mtim_nsec) { - return false; - } - - if (node->inode.st_nlink > UINT16_MAX || - node->inode.st_uid > UINT16_MAX || node->inode.st_gid > UINT16_MAX) { - return false; - } - - if (type == S_IFDIR) { - size = (uint64_t)node->erofs_n_blocks * EROFS_BLKSIZ + - node->erofs_tailsize; - } else { - size = node->inode.st_size; - } - if (size > UINT32_MAX) { - return false; - } - - return true; -} - -static void compute_erofs_dir_size(struct lcfs_node_s *node) -{ - uint32_t n_blocks = 0; - size_t block_size = 0; - - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - size_t len = sizeof(struct erofs_dirent) + strlen(child->name); - if (block_size + len > EROFS_BLKSIZ) { - n_blocks++; - block_size = 0; - } - block_size += len; - } - - /* As a heuristic, we never inline more than half a block */ - if (block_size > EROFS_BLKSIZ / 2) { - n_blocks++; - block_size = 0; - } - - node->erofs_n_blocks = n_blocks; - node->erofs_tailsize = block_size; -} - -static uint32_t compute_erofs_chunk_bitsize(struct lcfs_node_s *node) -{ - uint64_t file_size = node->inode.st_size; - - // Compute the chunksize to use for the file size - // We want as few chunks as possible, but not an - // unnecessary large chunk. - uint32_t chunkbits = ilog2(file_size - 1) + 1; - - // At least one logical block - if (chunkbits < EROFS_BLKSIZ_BITS) - chunkbits = EROFS_BLKSIZ_BITS; - - // Not larger chunks than max possible - if (chunkbits - EROFS_BLKSIZ_BITS > EROFS_CHUNK_FORMAT_BLKBITS_MASK) - chunkbits = EROFS_CHUNK_FORMAT_BLKBITS_MASK + EROFS_BLKSIZ_BITS; - - return chunkbits; -} - -static void compute_erofs_inode_size(struct lcfs_node_s *node) -{ - int type = node->inode.st_mode & S_IFMT; - uint64_t file_size = node->inode.st_size; - - if (type == S_IFDIR) { - compute_erofs_dir_size(node); - } else if (type == S_IFLNK) { - node->erofs_n_blocks = 0; - node->erofs_tailsize = strlen(node->payload); - } else if (type == S_IFREG && file_size > 0) { - if (node->content != NULL) { - node->erofs_n_blocks = file_size / EROFS_BLKSIZ; - node->erofs_tailsize = file_size % EROFS_BLKSIZ; - if (node->erofs_tailsize > EROFS_BLKSIZ / 2) { - node->erofs_n_blocks++; - node->erofs_tailsize = 0; - } - } else { - uint32_t chunkbits = compute_erofs_chunk_bitsize(node); - uint64_t chunksize = 1ULL << chunkbits; - uint32_t chunk_count = DIV_ROUND_UP(file_size, chunksize); - - node->erofs_n_blocks = 0; - node->erofs_tailsize = chunk_count * sizeof(uint32_t); - } - } else { - node->erofs_n_blocks = 0; - node->erofs_tailsize = 0; - } -} - -static void compute_erofs_xattr_counts(struct lcfs_node_s *node, - size_t *n_shared_xattrs_out, - size_t *unshared_xattrs_size_out) -{ - size_t n_shared_xattrs = 0; - size_t unshared_xattrs_size = 0; - - for (size_t i = 0; i < node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - if (xattr->erofs_shared_xattr_offset >= 0) { - n_shared_xattrs++; - } else { - unshared_xattrs_size += xattr_erofs_entry_size(xattr); - } - } - - *n_shared_xattrs_out = n_shared_xattrs; - *unshared_xattrs_size_out = unshared_xattrs_size; -} - -static uint32_t compute_erofs_xattr_filter(struct lcfs_node_s *node) -{ - uint32_t name_filter = 0; - - for (size_t i = 0; i < node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - uint32_t name_filter_bit; - uint8_t index; - char *key; - - index = xattr_erofs_entry_index(xattr, &key); - name_filter_bit = - xxh32(key, strlen(key), EROFS_XATTR_FILTER_SEED + index) & - (EROFS_XATTR_FILTER_BITS - 1); - name_filter |= 1UL << name_filter_bit; - } - - return EROFS_XATTR_FILTER_DEFAULT & ~name_filter; -} - -static uint64_t compute_erofs_inode_padding_for_tail(struct lcfs_node_s *node, - uint64_t pos, size_t inode_size, - size_t xattr_size) -{ - int type = node->inode.st_mode & S_IFMT; - uint64_t block_remainder; - size_t non_tail_size = inode_size + xattr_size; - size_t total_size = inode_size + xattr_size + node->erofs_tailsize; - - /* This adds extra padding in front of an inode to ensure that - * the tail data doesn't cross a block boundary. - */ - - if (type == S_IFLNK) { - /* Due to how erofs_fill_symlink is implemented, we - * need *both* the inode data and the symlink tail - * data in the same block, wheras normally just the - * tail data itself need to be inside a block. - */ - if (pos / EROFS_BLKSIZ != (pos + total_size - 1) / EROFS_BLKSIZ) { - return round_up(pos, EROFS_BLKSIZ) - pos; - } - return 0; - } - - block_remainder = EROFS_BLKSIZ - ((pos + non_tail_size) % EROFS_BLKSIZ); - if (block_remainder < node->erofs_tailsize) { - /* Add (aligned) padding so that tail starts in new block */ - uint64_t extra_pad = round_up(block_remainder, EROFS_SLOTSIZE); - - /* Due to the extra_pad round up it is possible the tail does not fit anyway */ - block_remainder = EROFS_BLKSIZ - - ((pos + non_tail_size + extra_pad) % EROFS_BLKSIZ); - if (node->erofs_tailsize <= block_remainder) { - /* It fit! */ - return extra_pad; - } - /* Didn't fit, don't inline the tail. */ - node->erofs_n_blocks++; - node->erofs_tailsize = 0; - } - - return 0; -} - -static int compute_erofs_inodes(struct lcfs_ctx_s *ctx) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - struct lcfs_node_s *node; - uint64_t pos, ppos; - uint64_t meta_start, extra_pad; - - // Start inode data directly after superblock - pos = EROFS_SUPER_OFFSET + sizeof(struct erofs_super_block); - - // But inode offsets (nids) are relative to start of block - meta_start = round_down(pos, EROFS_BLKSIZ); - - for (node = ctx->root; node != NULL; node = node->next) { - size_t n_shared_xattrs, unshared_xattrs_size; - size_t inode_size, xattr_size; - - compute_erofs_inode_size(node); - node->erofs_compact = lcfs_fits_in_erofs_compact(ctx, node); - inode_size = node->erofs_compact ? - sizeof(struct erofs_inode_compact) : - sizeof(struct erofs_inode_extended); - - compute_erofs_xattr_counts(node, &n_shared_xattrs, - &unshared_xattrs_size); - xattr_size = xattr_erofs_inode_size(n_shared_xattrs, - unshared_xattrs_size); - - /* Align inode start to next slot */ - ppos = pos; - pos = round_up(pos, EROFS_SLOTSIZE); - node->erofs_ipad = pos - ppos; - - /* Ensure tail does not straddle block boundaries */ - extra_pad = compute_erofs_inode_padding_for_tail( - node, pos, inode_size, xattr_size); - node->erofs_ipad += extra_pad; - pos += extra_pad; - - node->erofs_isize = inode_size + xattr_size + node->erofs_tailsize; - ctx_erofs->n_data_blocks += node->erofs_n_blocks; - node->erofs_nid = (pos - meta_start) / EROFS_SLOTSIZE; - - /* Assert that tails never span multiple blocks */ - assert(node->erofs_tailsize == 0 || - ((pos + inode_size + xattr_size) / EROFS_BLKSIZ) == - ((pos + node->erofs_isize - 1) / EROFS_BLKSIZ)); - - pos += node->erofs_isize; - } - - ctx_erofs->inodes_end = round_up(pos, EROFS_SLOTSIZE); - - return 0; -} - -static int write_erofs_xattr(struct lcfs_ctx_s *ctx, struct lcfs_xattr_s *xattr) -{ - struct erofs_xattr_entry e = { 0 }; - int ret; - char *key_suffix; - uint8_t index = xattr_erofs_entry_index(xattr, &key_suffix); - - e.e_name_len = strlen(key_suffix); - e.e_name_index = index; - e.e_value_size = lcfs_u16_to_file(xattr->value_len); - - ret = lcfs_write(ctx, &e, sizeof(e)); - if (ret < 0) - return ret; - - ret = lcfs_write(ctx, key_suffix, strlen(key_suffix)); - if (ret < 0) - return ret; - - ret = lcfs_write(ctx, xattr->value, xattr->value_len); - if (ret < 0) - return ret; - - return lcfs_write_align(ctx, sizeof(uint32_t)); -} - -static int write_erofs_dentries_chunk(struct lcfs_ctx_s *ctx, - struct lcfs_node_s *node, int first_child, - int n_children, int alignment) -{ - uint16_t nameoff = n_children * sizeof(struct erofs_dirent); - int ret; - - for (int i = first_child; i < first_child + n_children; i++) { - struct lcfs_node_s *dirent_child = node->children[i]; - struct lcfs_node_s *target_child = follow_links(dirent_child); - - struct erofs_dirent dirent = { 0 }; - dirent.nid = lcfs_u64_to_file(target_child->erofs_nid); - dirent.nameoff = lcfs_u16_to_file(nameoff); - dirent.file_type = - erofs_make_file_type(node_get_dtype(target_child)); - - nameoff += strlen(dirent_child->name); - - ret = lcfs_write(ctx, &dirent, sizeof(dirent)); - if (ret < 0) - return ret; - } - - for (int i = first_child; i < first_child + n_children; i++) { - struct lcfs_node_s *dirent_child = node->children[i]; - - ret = lcfs_write(ctx, dirent_child->name, strlen(dirent_child->name)); - if (ret < 0) - return ret; - } - - return lcfs_write_align(ctx, alignment); -} - -static int write_erofs_dentries(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node, - bool write_blocks, bool write_tail) -{ - size_t block_size = 0; - size_t block_written = 0; - size_t first = 0; - int ret; - - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - size_t len = sizeof(struct erofs_dirent) + strlen(child->name); - if (block_size + len > EROFS_BLKSIZ) { - if (write_blocks) { - ret = write_erofs_dentries_chunk( - ctx, node, first, i - first, EROFS_BLKSIZ); - if (ret < 0) - return ret; - } - - block_written++; - block_size = 0; - first = i; - } - block_size += len; - } - - /* Handle the remaining block which is either tailpacked or block as decided before */ - - if (block_written < node->erofs_n_blocks) { - if (write_blocks) { - ret = write_erofs_dentries_chunk(ctx, node, first, - node->children_size - first, - EROFS_BLKSIZ); - if (ret < 0) - return ret; - } - - block_written++; - block_size = 0; - first = node->children_size; - } - - if (write_tail && block_size > 0) { - ret = write_erofs_dentries_chunk(ctx, node, first, - node->children_size - first, 1); - if (ret < 0) - return ret; - } - - return 0; -} - -static int write_erofs_inode_data(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - int type = node->inode.st_mode & S_IFMT; - size_t xattr_icount; - uint64_t size; - int ret; - uint16_t format; - uint16_t version; - uint16_t datalayout; - off_t orig_bytes_written = ctx->bytes_written; - size_t n_shared_xattrs; - size_t unshared_xattrs_size; - size_t xattr_size; - uint32_t chunk_count = 0; - uint16_t chunk_format = 0; - - ret = lcfs_write_pad(ctx, node->erofs_ipad); - if (ret < 0) - return ret; - - /* All inodes start on slot boundary */ - assert(ctx->bytes_written % EROFS_SLOTSIZE == 0); - - /* compute xattr details */ - - compute_erofs_xattr_counts(node, &n_shared_xattrs, &unshared_xattrs_size); - xattr_size = xattr_erofs_inode_size(n_shared_xattrs, unshared_xattrs_size); - xattr_icount = xattr_erofs_icount(xattr_size); - - version = node->erofs_compact ? 0 : 1; - datalayout = (node->erofs_tailsize > 0) ? EROFS_INODE_FLAT_INLINE : - EROFS_INODE_FLAT_PLAIN; - - if (type == S_IFDIR || type == S_IFLNK) { - size = (uint64_t)node->erofs_n_blocks * EROFS_BLKSIZ + - node->erofs_tailsize; - } else if (type == S_IFREG) { - size = node->inode.st_size; - - if (size > 0 && node->content == NULL) { - uint32_t chunkbits = compute_erofs_chunk_bitsize(node); - uint64_t chunksize = 1ULL << chunkbits; - - datalayout = EROFS_INODE_CHUNK_BASED; - chunk_count = DIV_ROUND_UP(size, chunksize); - chunk_format = chunkbits - EROFS_BLKSIZ_BITS; - } - } else { - size = 0; - } - - format = datalayout << EROFS_I_DATALAYOUT_BIT | version << EROFS_I_VERSION_BIT; - - if (node->erofs_compact) { - struct erofs_inode_compact i = { 0 }; - i.i_format = lcfs_u16_to_file(format); - i.i_xattr_icount = lcfs_u16_to_file(xattr_icount); - i.i_mode = lcfs_u16_to_file(node->inode.st_mode); - i.i_nlink = lcfs_u16_to_file(node->inode.st_nlink); - i.i_size = lcfs_u32_to_file(size); - i.i_ino = lcfs_u32_to_file(node->inode_num); - i.i_uid = lcfs_u16_to_file(node->inode.st_uid); - i.i_gid = lcfs_u16_to_file(node->inode.st_gid); - - if (type == S_IFDIR) { - if (node->erofs_n_blocks > 0) { - i.i_u.raw_blkaddr = lcfs_u32_to_file( - ctx_erofs->current_end / EROFS_BLKSIZ); - ctx_erofs->current_end += - EROFS_BLKSIZ * node->erofs_n_blocks; - } - } else if (type == S_IFCHR || type == S_IFBLK) { - i.i_u.rdev = lcfs_u32_to_file(node->inode.st_rdev); - } else if (type == S_IFREG) { - if (node->erofs_n_blocks > 0) { - i.i_u.raw_blkaddr = lcfs_u32_to_file( - ctx_erofs->current_end / EROFS_BLKSIZ); - ctx_erofs->current_end += - EROFS_BLKSIZ * node->erofs_n_blocks; - } - if (datalayout == EROFS_INODE_CHUNK_BASED) { - i.i_u.c.format = lcfs_u16_to_file(chunk_format); - } - } - - ret = lcfs_write(ctx, &i, sizeof(i)); - if (ret < 0) - return ret; - } else { - struct erofs_inode_extended i = { 0 }; - i.i_format = lcfs_u16_to_file(format); - i.i_xattr_icount = lcfs_u16_to_file(xattr_icount); - i.i_mode = lcfs_u16_to_file(node->inode.st_mode); - i.i_nlink = lcfs_u32_to_file(node->inode.st_nlink); - i.i_size = lcfs_u64_to_file(size); - i.i_ino = lcfs_u32_to_file(node->inode_num); - i.i_uid = lcfs_u32_to_file(node->inode.st_uid); - i.i_gid = lcfs_u32_to_file(node->inode.st_gid); - i.i_mtime = lcfs_u64_to_file(node->inode.st_mtim_sec); - i.i_mtime_nsec = lcfs_u64_to_file(node->inode.st_mtim_nsec); - - if (type == S_IFDIR) { - if (node->erofs_n_blocks > 0) { - i.i_u.raw_blkaddr = lcfs_u32_to_file( - ctx_erofs->current_end / EROFS_BLKSIZ); - ctx_erofs->current_end += - EROFS_BLKSIZ * node->erofs_n_blocks; - } - } else if (type == S_IFCHR || type == S_IFBLK) { - i.i_u.rdev = lcfs_u32_to_file(node->inode.st_rdev); - } else if (type == S_IFREG) { - if (node->erofs_n_blocks > 0) { - i.i_u.raw_blkaddr = lcfs_u32_to_file( - ctx_erofs->current_end / EROFS_BLKSIZ); - ctx_erofs->current_end += - EROFS_BLKSIZ * node->erofs_n_blocks; - } - if (datalayout == EROFS_INODE_CHUNK_BASED) { - i.i_u.c.format = lcfs_u16_to_file(chunk_format); - } - } - - ret = lcfs_write(ctx, &i, sizeof(i)); - if (ret < 0) - return ret; - } - - /* write xattrs */ - if (xattr_size) { - struct erofs_xattr_ibody_header xattr_header = { 0 }; - xattr_header.h_shared_count = n_shared_xattrs; - xattr_header.h_name_filter = - lcfs_u32_to_file(compute_erofs_xattr_filter(node)); - - ret = lcfs_write(ctx, &xattr_header, sizeof(xattr_header)); - if (ret < 0) - return ret; - - /* shared */ - for (size_t i = 0; i < node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - if (xattr->erofs_shared_xattr_offset >= 0) { - uint64_t offset = - ctx_erofs->inodes_end % EROFS_BLKSIZ + - xattr->erofs_shared_xattr_offset; - uint32_t v = - lcfs_u32_to_file(offset / sizeof(uint32_t)); - ret = lcfs_write(ctx, &v, sizeof(v)); - if (ret < 0) - return ret; - } - } - /* unshared */ - for (size_t i = 0; i < node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - if (xattr->erofs_shared_xattr_offset < 0) { - ret = write_erofs_xattr(ctx, xattr); - if (ret < 0) - return ret; - } - } - } - - if (type == S_IFDIR) { - ret = write_erofs_dentries(ctx, node, false, true); - if (ret < 0) - return ret; - } else if (type == S_IFLNK) { - ret = lcfs_write(ctx, node->payload, strlen(node->payload)); - if (ret < 0) - return ret; - } else if (type == S_IFREG) { - if (node->content != NULL) { - if (node->erofs_tailsize) { - uint64_t file_size = node->inode.st_size; - ret = lcfs_write(ctx, - node->content + file_size - - node->erofs_tailsize, - node->erofs_tailsize); - if (ret < 0) - return ret; - } - } else { - for (size_t i = 0; i < chunk_count; i++) { - uint32_t empty_chunk = 0xFFFFFFFF; - ret = lcfs_write(ctx, &empty_chunk, - sizeof(empty_chunk)); - if (ret < 0) - return ret; - } - } - } - - assert(ctx->bytes_written - orig_bytes_written == - node->erofs_isize + node->erofs_ipad); - - return 0; -} - -static int write_erofs_inodes(struct lcfs_ctx_s *ctx) -{ - struct lcfs_node_s *node; - int ret; - - for (node = ctx->root; node != NULL; node = node->next) { - ret = write_erofs_inode_data(ctx, node); - if (ret < 0) - return ret; - } - - ret = lcfs_write_align(ctx, EROFS_SLOTSIZE); - if (ret < 0) - return ret; - - return 0; -} - -/* Writes the non-tailpacked file data, if any */ -static int write_erofs_file_content(struct lcfs_ctx_s *ctx, struct lcfs_node_s *node) -{ - int type = node->inode.st_mode & S_IFMT; - off_t size = node->inode.st_size; - - if (type != S_IFREG || node->erofs_n_blocks == 0) - return 0; - - assert(node->content != NULL); - - for (size_t i = 0; i < node->erofs_n_blocks; i++) { - off_t offset = i * EROFS_BLKSIZ; - off_t len = min(size - offset, EROFS_BLKSIZ); - int ret; - - ret = lcfs_write(ctx, node->content + offset, len); - if (ret < 0) - return ret; - } - - return lcfs_write_align(ctx, EROFS_BLKSIZ); -} - -static int write_erofs_data_blocks(struct lcfs_ctx_s *ctx) -{ - struct lcfs_node_s *node; - int ret; - - for (node = ctx->root; node != NULL; node = node->next) { - ret = write_erofs_dentries(ctx, node, true, false); - if (ret < 0) - return ret; - ret = write_erofs_file_content(ctx, node); - if (ret < 0) - return ret; - } - - return 0; -} - -static int write_erofs_shared_xattrs(struct lcfs_ctx_s *ctx) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - int ret; - - for (size_t i = 0; i < ctx_erofs->n_shared_xattrs; i++) { - struct lcfs_xattr_s *xattr = ctx_erofs->shared_xattrs[i]; - ret = write_erofs_xattr(ctx, xattr); - if (ret < 0) - return ret; - } - - return 0; -} - -static int add_overlayfs_xattrs(struct lcfs_node_s *node) -{ - int type = node->inode.st_mode & S_IFMT; - int ret; - - /* First escape all existing "trusted.overlay.*" xattrs */ - for (size_t i = 0; i < lcfs_node_get_n_xattr(node); i++) { - const char *name = lcfs_node_get_xattr_name(node, i); - - if (str_has_prefix(name, OVERLAY_XATTR_PREFIX)) { - cleanup_free char *renamed = - str_join(OVERLAY_XATTR_ESCAPE_PREFIX, - name + strlen(OVERLAY_XATTR_PREFIX)); - if (renamed == NULL) { - errno = ENOMEM; - return -1; - } - /* We rename in-place, this is safe from - collisions because we also rename any - colliding xattr */ - if (lcfs_node_rename_xattr(node, i, renamed) < 0) - return -1; - } - } - - if (type == S_IFREG && node->inode.st_size > 0 && node->content == NULL) { - uint8_t xattr_data[4 + LCFS_DIGEST_SIZE]; - size_t xattr_len = 0; - - if (node->digest_set) { - xattr_len = sizeof(xattr_data); - xattr_data[0] = 0; /* version */ - xattr_data[1] = xattr_len; - xattr_data[2] = 0; /* flags */ - xattr_data[3] = FS_VERITY_HASH_ALG_SHA256; - memcpy(xattr_data + 4, node->digest, LCFS_DIGEST_SIZE); - } - - ret = lcfs_node_set_xattr(node, OVERLAY_XATTR_METACOPY, - (const char *)xattr_data, xattr_len); - if (ret < 0) - return ret; - - if (node->payload && strlen(node->payload) > 0) { - char *path = maybe_join_path("/", node->payload); - if (path == NULL) { - errno = ENOMEM; - return -1; - } - ret = lcfs_node_set_xattr(node, OVERLAY_XATTR_REDIRECT, - path, strlen(path)); - free(path); - if (ret < 0) - return ret; - } - } - - /* escape whiteouts */ - if (type == S_IFCHR && node->inode.st_rdev == makedev(0, 0)) { - struct lcfs_node_s *parent = lcfs_node_get_parent(node); - - lcfs_node_set_mode(node, - S_IFREG | (lcfs_node_get_mode(node) & ~S_IFMT)); - ret = lcfs_node_set_xattr(node, OVERLAY_XATTR_ESCAPED_WHITEOUT, - "", 0); - if (ret < 0) - return ret; - ret = lcfs_node_set_xattr(node, OVERLAY_XATTR_USERXATTR_WHITEOUT, - "", 0); - if (ret < 0) - return ret; - - /* Mark parent dir containing whiteouts */ - ret = lcfs_node_set_xattr(parent, - OVERLAY_XATTR_ESCAPED_WHITEOUTS, "", 0); - if (ret < 0) - return ret; - ret = lcfs_node_set_xattr(parent, OVERLAY_XATTR_USERXATTR_WHITEOUTS, - "", 0); - if (ret < 0) - return ret; - } - - return 0; -} - -static int add_overlay_whiteouts(struct lcfs_node_s *root) -{ - static const char hexchars[] = "0123456789abcdef"; - const char *selinux; - size_t selinux_len; - int res; - - selinux = lcfs_node_get_xattr(root, "security.selinux", &selinux_len); - - for (int i = 0; i <= 255; i++) { - struct lcfs_node_s *child; - char name[3]; - - name[0] = hexchars[(i >> 4) % 16]; - name[1] = hexchars[i % 16]; - name[2] = 0; - - child = lcfs_node_lookup_child(root, name); - if (child != NULL) - continue; - - child = lcfs_node_new(); - if (child == NULL) { - errno = ENOMEM; - return -1; - } - - lcfs_node_set_mode(child, S_IFCHR | 0644); - lcfs_node_set_rdev(child, 0); - - child->inode.st_uid = root->inode.st_uid; - child->inode.st_gid = root->inode.st_gid; - child->inode.st_mtim_sec = root->inode.st_mtim_sec; - child->inode.st_mtim_nsec = root->inode.st_mtim_nsec; - - /* Inherit selinux context from root dir */ - if (selinux != NULL) { - res = lcfs_node_set_xattr(child, "security.selinux", - selinux, selinux_len); - if (res < 0) { - lcfs_node_unref(child); - return res; - } - } - - res = lcfs_node_add_child(root, child, name); - if (res < 0) - return res; - } - - return 0; -} - -static int rewrite_tree_node_for_erofs(struct lcfs_node_s *node, - struct lcfs_node_s *parent) -{ - int ret; - - ret = add_overlayfs_xattrs(node); - if (ret < 0) - return ret; - - if (lcfs_node_dirp(node)) { - struct lcfs_node_s *existing; - - /* Ensure we have . and .. */ - existing = lcfs_node_lookup_child(node, "."); - if (existing == NULL) { - struct lcfs_node_s *link = lcfs_node_new(); - if (link == NULL) { - errno = ENOMEM; - return -1; - } - lcfs_node_make_hardlink(link, node); - ret = lcfs_node_add_child(node, link, "."); - if (ret < 0) { - lcfs_node_unref(link); - return -1; - } - } - - existing = lcfs_node_lookup_child(node, ".."); - if (existing == NULL) { - struct lcfs_node_s *link = lcfs_node_new(); - if (link == NULL) { - errno = ENOMEM; - return -1; - } - lcfs_node_make_hardlink(link, parent); - ret = lcfs_node_add_child(node, link, ".."); - if (ret < 0) { - lcfs_node_unref(link); - return -1; - } - } - - for (size_t i = 0; i < node->children_size; ++i) { - struct lcfs_node_s *child = node->children[i]; - - if (child->link_to != NULL) { - continue; - } - - ret = rewrite_tree_node_for_erofs(child, node); - if (ret < 0) { - return -1; - } - } - } - - return 0; -} - -static int set_overlay_opaque(struct lcfs_node_s *node) -{ - int ret; - - ret = lcfs_node_set_xattr(node, OVERLAY_XATTR_OPAQUE, "y", 1); - if (ret < 0) - return ret; - - return 0; -} - -static int rewrite_tree_for_erofs(struct lcfs_node_s *root) -{ - int res; - - res = rewrite_tree_node_for_erofs(root, root); - if (res < 0) - return res; - - res = set_overlay_opaque(root); - if (res < 0) - return res; - - res = add_overlay_whiteouts(root); - if (res < 0) - return res; - - return 0; -} - -int lcfs_write_erofs_to(struct lcfs_ctx_s *ctx) -{ - struct lcfs_ctx_erofs_s *ctx_erofs = (struct lcfs_ctx_erofs_s *)ctx; - struct lcfs_node_s *root; - struct lcfs_erofs_header_s header = { - .magic = lcfs_u32_to_file(LCFS_EROFS_MAGIC), - .version = lcfs_u32_to_file(LCFS_EROFS_VERSION), - }; - uint32_t header_flags; - struct erofs_super_block superblock = { - .magic = lcfs_u32_to_file(EROFS_SUPER_MAGIC_V1), - .blkszbits = EROFS_BLKSIZ_BITS, - }; - int ret = 0; - uint64_t data_block_start; - - if (ctx->options->version != 0) { - errno = -EINVAL; - return -1; - } - - /* Clone root so we can make required modifications to it */ - ret = lcfs_clone_root(ctx); - if (ret < 0) - return ret; - - root = ctx->root; /* After we cloned it */ - - /* Rewrite cloned tree as needed for erofs */ - ret = rewrite_tree_for_erofs(root); - if (ret < 0) - return ret; - - ret = lcfs_compute_tree(ctx, root); - if (ret < 0) - return ret; - - ret = compute_erofs_shared_xattrs(ctx); - if (ret < 0) - return ret; - - ret = compute_erofs_inodes(ctx); - if (ret < 0) - return ret; - - header_flags = 0; - if (ctx->has_acl) - header_flags |= LCFS_EROFS_FLAGS_HAS_ACL; - header.flags = lcfs_u32_to_file(header_flags); - - ret = lcfs_write(ctx, &header, sizeof(header)); - if (ret < 0) - return ret; - - ret = lcfs_write_pad(ctx, EROFS_SUPER_OFFSET - sizeof(header)); - if (ret < 0) - return ret; - - superblock.feature_compat = lcfs_u32_to_file( - EROFS_FEATURE_COMPAT_MTIME | EROFS_FEATURE_COMPAT_XATTR_FILTER); - superblock.inos = lcfs_u64_to_file(ctx->num_inodes); - - superblock.build_time = lcfs_u64_to_file(ctx->min_mtim_sec); - superblock.build_time_nsec = lcfs_u32_to_file(ctx->min_mtim_nsec); - - /* metadata is stored directly after superblock */ - superblock.meta_blkaddr = lcfs_u32_to_file( - (EROFS_SUPER_OFFSET + sizeof(superblock)) / EROFS_BLKSIZ); - assert(root->erofs_nid < UINT16_MAX); - superblock.root_nid = lcfs_u16_to_file(root->erofs_nid); - - /* shared xattrs is directly after metadata */ - superblock.xattr_blkaddr = - lcfs_u32_to_file(ctx_erofs->inodes_end / EROFS_BLKSIZ); - - data_block_start = - round_up(ctx_erofs->inodes_end + ctx_erofs->shared_xattr_size, - EROFS_BLKSIZ); - - superblock.blocks = lcfs_u32_to_file(data_block_start / EROFS_BLKSIZ + - ctx_erofs->n_data_blocks); - - /* TODO: More superblock fields: - * uuid? - * volume_name? - */ - - ret = lcfs_write(ctx, &superblock, sizeof(superblock)); - if (ret < 0) - return ret; - - ctx_erofs->current_end = data_block_start; - - ret = write_erofs_inodes(ctx); - if (ret < 0) - return ret; - - assert(ctx_erofs->inodes_end == (uint64_t)ctx->bytes_written); - - ret = write_erofs_shared_xattrs(ctx); - if (ret < 0) - return ret; - - assert(ctx_erofs->inodes_end + ctx_erofs->shared_xattr_size == - (uint64_t)ctx->bytes_written); - - /* Following are full blocks and must be block-aligned */ - ret = lcfs_write_align(ctx, EROFS_BLKSIZ); - if (ret < 0) - return ret; - - assert(data_block_start == (uint64_t)ctx->bytes_written); - - ret = write_erofs_data_blocks(ctx); - if (ret < 0) - return ret; - - assert(ctx_erofs->current_end == (uint64_t)ctx->bytes_written); - assert(data_block_start + ctx_erofs->n_data_blocks * EROFS_BLKSIZ == - (uint64_t)ctx->bytes_written); - - return 0; -} - -struct hasher_node_s { - uint64_t nid; - struct lcfs_node_s *node; -}; - -struct lcfs_image_data { - const uint8_t *erofs_data; - size_t erofs_data_size; - const uint8_t *erofs_metadata; - const uint8_t *erofs_metadata_end; - const uint8_t *erofs_xattrdata; - const uint8_t *erofs_xattrdata_end; - uint64_t erofs_build_time; - uint32_t erofs_build_time_nsec; - Hash_table *node_hash; -}; - -static const erofs_inode *lcfs_image_get_erofs_inode(struct lcfs_image_data *data, - uint64_t nid) -{ - const uint8_t *inode_data = data->erofs_metadata + (nid << EROFS_ISLOTBITS); - - if (inode_data >= data->erofs_metadata_end) - return NULL; - - return (const erofs_inode *)inode_data; -} - -static struct lcfs_node_s *lcfs_build_node_from_image(struct lcfs_image_data *data, - uint64_t nid); - -static int erofs_readdir_block(struct lcfs_image_data *data, - struct lcfs_node_s *parent, const uint8_t *block, - size_t block_size) -{ - const struct erofs_dirent *dirents = (struct erofs_dirent *)block; - size_t dirents_size = lcfs_u16_from_file(dirents[0].nameoff); - size_t n_dirents, i; - - if (dirents_size % sizeof(struct erofs_dirent) != 0) { - /* This should not happen for valid filesystems */ - errno = EINVAL; - return -1; - } - - n_dirents = dirents_size / sizeof(struct erofs_dirent); - - for (i = 0; i < n_dirents; i++) { - char name_buf[PATH_MAX]; - uint64_t nid = lcfs_u64_from_file(dirents[i].nid); - uint16_t nameoff = lcfs_u16_from_file(dirents[i].nameoff); - const char *child_name; - uint16_t child_name_len; - cleanup_node struct lcfs_node_s *child = NULL; - - /* Compute length of the name, which is a bit weird for the last dirent */ - child_name = (char *)(block + nameoff); - if (i + 1 < n_dirents) - child_name_len = - lcfs_u16_from_file(dirents[i + 1].nameoff) - nameoff; - else - child_name_len = strnlen(child_name, block_size - nameoff); - - if ((child_name_len == 1 && child_name[0] == '.') || - (child_name_len == 2 && child_name[0] == '.' && - child_name[1] == '.')) - continue; - - /* Copy to null terminate */ - child_name_len = min(child_name_len, PATH_MAX - 1); - memcpy(name_buf, child_name, child_name_len); - name_buf[child_name_len] = 0; - - child = lcfs_build_node_from_image(data, nid); - if (child == NULL) { - if (errno == ENOTSUP) - continue; /* Skip real whiteouts (00-ff) */ - } - - if (lcfs_node_add_child(parent, child, /* Takes ownership on success */ - name_buf) < 0) - return -1; - steal_pointer(&child); - } - - return 0; -} - -static int lcfs_build_node_erofs_xattr(struct lcfs_node_s *node, uint8_t name_index, - const char *entry_name, uint8_t name_len, - const char *value, uint16_t value_size) -{ - cleanup_free char *name = - erofs_get_xattr_name(name_index, entry_name, name_len); - if (name == NULL) - return -1; - - if (strcmp(name, OVERLAY_XATTR_REDIRECT) == 0) { - if ((node->inode.st_mode & S_IFMT) == S_IFREG) { - if (value_size > 1 && value[0] == '/') { - value_size++; - value++; - } - node->payload = strndup(value, value_size); - if (node->payload == NULL) { - errno = EINVAL; - return -1; - } - } - return 0; - } - - if (strcmp(name, OVERLAY_XATTR_METACOPY) == 0) { - if ((node->inode.st_mode & S_IFMT) == S_IFREG && - value_size == 4 + LCFS_DIGEST_SIZE) - lcfs_node_set_fsverity_digest(node, (uint8_t *)value + 4); - return 0; - } - - if (strcmp(name, OVERLAY_XATTR_ESCAPED_WHITEOUT) == 0 && - (node->inode.st_mode & S_IFMT) == S_IFREG) { - /* Rewrite to regular whiteout */ - node->inode.st_mode = (node->inode.st_mode & ~S_IFMT) | S_IFCHR; - node->inode.st_rdev = makedev(0, 0); - node->inode.st_size = 0; - return 0; - } - if (strcmp(name, OVERLAY_XATTR_ESCAPED_WHITEOUTS) == 0 || - strcmp(name, OVERLAY_XATTR_USERXATTR_WHITEOUT) == 0 || - strcmp(name, OVERLAY_XATTR_USERXATTR_WHITEOUTS) == 0) { - /* skip */ - return 0; - } - - if (str_has_prefix(name, OVERLAY_XATTR_PREFIX)) { - if (str_has_prefix(name, OVERLAY_XATTR_ESCAPE_PREFIX)) { - /* Unescape */ - memmove(name + strlen(OVERLAY_XATTR_TRUSTED_PREFIX), - name + strlen(OVERLAY_XATTR_PREFIX), - strlen(name) - strlen(OVERLAY_XATTR_PREFIX) + 1); - } else { - /* skip */ - return 0; - } - } - - if (lcfs_node_set_xattr(node, name, value, value_size) < 0) - return -1; - - return 0; -} - -static struct lcfs_node_s *lcfs_build_node_from_image(struct lcfs_image_data *data, - uint64_t nid) -{ - const erofs_inode *cino; - cleanup_node struct lcfs_node_s *node = NULL; - uint64_t file_size; - uint16_t xattr_icount; - uint32_t raw_blkaddr; - int type; - size_t isize; - bool tailpacked; - size_t xattr_size; - struct hasher_node_s ht_entry = { nid }; - struct hasher_node_s *new_ht_entry; - struct hasher_node_s *existing; - uint64_t n_blocks; - uint64_t last_oob_block; - size_t tail_size; - const uint8_t *tail_data; - const uint8_t *oob_data; - - cino = lcfs_image_get_erofs_inode(data, nid); - if (cino == NULL) - return NULL; - - node = lcfs_node_new(); - if (node == NULL) { - errno = ENOMEM; - return NULL; - } - - existing = hash_lookup(data->node_hash, &ht_entry); - if (existing) { - node->link_to = lcfs_node_ref(existing->node); - return steal_pointer(&node); - } - - new_ht_entry = malloc(sizeof(struct hasher_node_s)); - if (new_ht_entry == NULL) { - errno = ENOMEM; - return NULL; - } - new_ht_entry->nid = nid; - new_ht_entry->node = node; - if (hash_insert(data->node_hash, new_ht_entry) == NULL) { - errno = ENOMEM; - return NULL; - } - - if (erofs_inode_is_compact(cino)) { - const struct erofs_inode_compact *c = &cino->compact; - - node->inode.st_mode = lcfs_u16_from_file(c->i_mode); - node->inode.st_nlink = lcfs_u16_from_file(c->i_nlink); - node->inode.st_size = lcfs_u32_from_file(c->i_size); - node->inode.st_uid = lcfs_u16_from_file(c->i_uid); - node->inode.st_gid = lcfs_u16_from_file(c->i_gid); - - node->inode.st_mtim_sec = data->erofs_build_time; - node->inode.st_mtim_nsec = data->erofs_build_time_nsec; - - type = node->inode.st_mode & S_IFMT; - - if (type == S_IFCHR || type == S_IFBLK) - node->inode.st_rdev = lcfs_u32_from_file(c->i_u.rdev); - - file_size = lcfs_u32_from_file(c->i_size); - xattr_icount = lcfs_u16_from_file(c->i_xattr_icount); - raw_blkaddr = lcfs_u32_from_file(c->i_u.raw_blkaddr); - isize = sizeof(struct erofs_inode_compact); - - } else { - const struct erofs_inode_extended *e = &cino->extended; - - node->inode.st_mode = lcfs_u16_from_file(e->i_mode); - node->inode.st_size = lcfs_u64_from_file(e->i_size); - node->inode.st_uid = lcfs_u32_from_file(e->i_uid); - node->inode.st_gid = lcfs_u32_from_file(e->i_gid); - node->inode.st_mtim_sec = lcfs_u64_from_file(e->i_mtime); - node->inode.st_mtim_nsec = lcfs_u32_from_file(e->i_mtime_nsec); - node->inode.st_nlink = lcfs_u32_from_file(e->i_nlink); - - type = node->inode.st_mode & S_IFMT; - - if (type == S_IFCHR || type == S_IFBLK) - node->inode.st_rdev = lcfs_u32_from_file(e->i_u.rdev); - - file_size = lcfs_u64_from_file(e->i_size); - xattr_icount = lcfs_u16_from_file(e->i_xattr_icount); - raw_blkaddr = lcfs_u32_from_file(e->i_u.raw_blkaddr); - isize = sizeof(struct erofs_inode_extended); - } - - if (type == S_IFCHR && node->inode.st_rdev == 0) { - errno = ENOTSUP; /* Use this to signal that we found a whiteout */ - return NULL; - } - - xattr_size = erofs_xattr_inode_size(xattr_icount); - - tailpacked = erofs_inode_is_tailpacked(cino); - tail_size = tailpacked ? file_size % EROFS_BLKSIZ : 0; - tail_data = ((uint8_t *)cino) + isize + xattr_size; - oob_data = data->erofs_data + raw_blkaddr * EROFS_BLKSIZ; - - n_blocks = round_up(file_size, EROFS_BLKSIZ) / EROFS_BLKSIZ; - last_oob_block = tailpacked ? n_blocks - 1 : n_blocks; - - if (type == S_IFDIR) { - /* First read the out-of-band blocks */ - for (uint64_t block = 0; block < last_oob_block; block++) { - const uint8_t *block_data = oob_data + block * EROFS_BLKSIZ; - size_t block_size = EROFS_BLKSIZ; - - if (!tailpacked && block + 1 == last_oob_block) { - block_size = file_size % EROFS_BLKSIZ; - if (block_size == 0) { - block_size = EROFS_BLKSIZ; - } - } - - if (erofs_readdir_block(data, node, block_data, block_size) < 0) - return NULL; - } - - /* Then inline */ - if (tailpacked) { - if (erofs_readdir_block(data, node, tail_data, tail_size) < 0) - return NULL; - } - - } else if (type == S_IFLNK) { - char name_buf[PATH_MAX]; - - if (file_size >= PATH_MAX || !tailpacked) { - errno = -EINVAL; - return NULL; - } - - memcpy(name_buf, tail_data, file_size); - name_buf[file_size] = 0; - if (lcfs_node_set_payload(node, name_buf) < 0) - return NULL; - - } else if (type == S_IFREG && file_size != 0 && erofs_inode_is_flat(cino)) { - cleanup_free uint8_t *content = NULL; - size_t oob_size; - - content = malloc(file_size); - if (content == NULL) { - errno = ENOMEM; - return NULL; - } - - oob_size = tailpacked ? last_oob_block * EROFS_BLKSIZ : file_size; - memcpy(content, data->erofs_data + raw_blkaddr * EROFS_BLKSIZ, - oob_size); - if (tailpacked) - memcpy(content + oob_size, tail_data, tail_size); - - lcfs_node_set_content(node, content, file_size); - } - - if (xattr_icount > 0) { - const struct erofs_xattr_ibody_header *xattr_header; - const uint8_t *xattrs_inline; - const uint8_t *xattrs_start; - const uint8_t *xattrs_end; - uint8_t shared_count; - - xattrs_start = ((uint8_t *)cino) + isize; - xattrs_end = ((uint8_t *)cino) + isize + xattr_size; - xattr_header = (struct erofs_xattr_ibody_header *)xattrs_start; - shared_count = xattr_header->h_shared_count; - - xattrs_inline = xattrs_start + - sizeof(struct erofs_xattr_ibody_header) + - shared_count * 4; - - /* Inline xattrs */ - while (xattrs_inline + sizeof(struct erofs_xattr_entry) < xattrs_end) { - const struct erofs_xattr_entry *entry = - (const struct erofs_xattr_entry *)xattrs_inline; - const char *entry_data = (const char *)entry + - sizeof(struct erofs_xattr_entry); - const char *entry_name = entry_data; - uint8_t name_len = entry->e_name_len; - uint8_t name_index = entry->e_name_index; - const char *value = entry_data + name_len; - uint16_t value_size = - lcfs_u16_from_file(entry->e_value_size); - size_t el_size = round_up(sizeof(struct erofs_xattr_entry) + - name_len + value_size, - 4); - - if (lcfs_build_node_erofs_xattr(node, name_index, - entry_name, name_len, - value, value_size) < 0) - return NULL; - - xattrs_inline += el_size; - } - - /* Shared xattrs */ - for (int i = 0; i < shared_count; i++) { - uint32_t idx = lcfs_u32_from_file( - xattr_header->h_shared_xattrs[i]); - const struct erofs_xattr_entry *entry = - (const struct erofs_xattr_entry *)(data->erofs_xattrdata + - idx * 4); - const char *entry_data = (const char *)entry + - sizeof(struct erofs_xattr_entry); - const char *entry_name = entry_data; - uint8_t name_len = entry->e_name_len; - uint8_t name_index = entry->e_name_index; - const char *value = entry_data + name_len; - uint16_t value_size = - lcfs_u16_from_file(entry->e_value_size); - - if (lcfs_build_node_erofs_xattr(node, name_index, - entry_name, name_len, - value, value_size) < 0) - return NULL; - } - } - - return steal_pointer(&node); -} - -static size_t node_ht_hasher(const void *d, size_t n) -{ - const struct hasher_node_s *v = d; - return v->nid % n; -} - -static bool node_ht_comparator(const void *d1, const void *d2) -{ - const struct hasher_node_s *v1 = d1; - const struct hasher_node_s *v2 = d2; - - return v1->nid == v2->nid; -} - -struct lcfs_node_s *lcfs_load_node_from_image(const uint8_t *image_data, - size_t image_data_size) -{ - const uint8_t *image_data_end; - struct lcfs_image_data data = { image_data, image_data_size }; - const struct lcfs_erofs_header_s *cfs_header; - const struct erofs_super_block *erofs_super; - uint64_t erofs_root_nid; - struct lcfs_node_s *root; - - if (image_data_size < EROFS_BLKSIZ) { - errno = EINVAL; - return NULL; - } - - /* Avoid wrapping */ - image_data_end = image_data + image_data_size; - if (image_data_end < image_data) { - errno = EINVAL; - return NULL; - } - - cfs_header = (struct lcfs_erofs_header_s *)(image_data); - if (lcfs_u32_from_file(cfs_header->magic) != LCFS_EROFS_MAGIC) { - errno = EINVAL; /* Wrong cfs magic */ - return NULL; - } - - if (lcfs_u32_from_file(cfs_header->version) != LCFS_EROFS_VERSION) { - errno = ENOTSUP; /* Wrong cfs version */ - return NULL; - } - - erofs_super = (struct erofs_super_block *)(image_data + EROFS_SUPER_OFFSET); - - if (lcfs_u32_from_file(erofs_super->magic) != EROFS_SUPER_MAGIC_V1) { - errno = EINVAL; /* Wrong erofs magic */ - return NULL; - } - - data.erofs_metadata = - image_data + - lcfs_u32_from_file(erofs_super->meta_blkaddr) * EROFS_BLKSIZ; - data.erofs_xattrdata = - image_data + - lcfs_u32_from_file(erofs_super->xattr_blkaddr) * EROFS_BLKSIZ; - - if (data.erofs_metadata >= image_data_end || - data.erofs_xattrdata >= image_data_end) { - errno = EINVAL; - return NULL; - } - - data.erofs_metadata_end = image_data_end; - data.erofs_xattrdata_end = image_data_end; - - data.erofs_build_time = lcfs_u64_from_file(erofs_super->build_time); - data.erofs_build_time_nsec = - lcfs_u32_from_file(erofs_super->build_time_nsec); - - erofs_root_nid = lcfs_u16_from_file(erofs_super->root_nid); - - data.node_hash = - hash_initialize(0, NULL, node_ht_hasher, node_ht_comparator, free); - if (data.node_hash == NULL) { - errno = ENOMEM; - return NULL; - } - - root = lcfs_build_node_from_image(&data, erofs_root_nid); - - hash_free(data.node_hash); - - return root; -} diff --git a/composefs/libcomposefs/lcfs-writer.c b/composefs/libcomposefs/lcfs-writer.c deleted file mode 100644 index 13a8e06..0000000 --- a/composefs/libcomposefs/lcfs-writer.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* lcfs - Copyright (C) 2021 Giuseppe Scrivano - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#define _GNU_SOURCE - -#include "config.h" - -#include "lcfs-internal.h" -#include "lcfs-writer.h" -#include "lcfs-utils.h" -#include "lcfs-fsverity.h" -#include "hash.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void lcfs_node_remove_all_children(struct lcfs_node_s *node); -static void lcfs_node_destroy(struct lcfs_node_s *node); - -static int lcfs_close(struct lcfs_ctx_s *ctx); - -char *maybe_join_path(const char *a, const char *b) -{ - size_t a_len = strlen(a); - size_t b_len = 0; - - if (b != NULL) - b_len = 1 + strlen(b); - - char *res = malloc(a_len + b_len + 1); - if (res) { - strcpy(res, a); - if (b != NULL) { - if (a_len > 0 && res[a_len - 1] != '/') { - strcat(res, "/"); - } - strcat(res, b); - } - } - return res; -} - -size_t hash_memory(const char *string, size_t len, size_t n_buckets) -{ - size_t i, value = 0; - - for (i = 0; i < len; i++) { - value = (value * 31 + string[i]) % n_buckets; - } - return value; -} - -static struct lcfs_ctx_s *lcfs_new_ctx(struct lcfs_node_s *root, - struct lcfs_write_options_s *options) -{ - struct lcfs_ctx_s *ret; - - switch (options->format) { - case LCFS_FORMAT_EROFS: - ret = lcfs_ctx_erofs_new(); - break; - - default: - ret = NULL; - } - - if (ret == NULL) { - return ret; - } - - ret->options = options; - ret->root = lcfs_node_ref(root); - - ret->file = options->file; - ret->write_cb = options->file_write_cb; - if (options->digest_out) { - ret->fsverity_ctx = lcfs_fsverity_context_new(); - if (ret->fsverity_ctx == NULL) { - lcfs_close(ret); - return NULL; - } - } - - return ret; -} - -int lcfs_clone_root(struct lcfs_ctx_s *ctx) -{ - struct lcfs_node_s *clone; - - clone = lcfs_node_clone_deep(ctx->root); - if (clone == NULL) { - errno = -EINVAL; - return -1; - } - - lcfs_node_unref(ctx->root); - ctx->root = clone; - ctx->destroy_root = true; - - return 0; -} - -int node_get_dtype(struct lcfs_node_s *node) -{ - switch ((node->inode.st_mode & S_IFMT)) { - case S_IFLNK: - return DT_LNK; - case S_IFDIR: - return DT_DIR; - case S_IFREG: - return DT_REG; - case S_IFBLK: - return DT_BLK; - case S_IFCHR: - return DT_CHR; - case S_IFSOCK: - return DT_SOCK; - case S_IFIFO: - return DT_FIFO; - default: - return DT_UNKNOWN; - } -} - -static int cmp_nodes(const void *a, const void *b) -{ - const struct lcfs_node_s *na = *((const struct lcfs_node_s **)a); - const struct lcfs_node_s *nb = *((const struct lcfs_node_s **)b); - - return strcmp(na->name, nb->name); -} - -static int cmp_xattr(const void *a, const void *b) -{ - const struct lcfs_xattr_s *na = a; - const struct lcfs_xattr_s *nb = b; - - return strcmp(na->key, nb->key); -} - -/* This ensures that the tree is in a well defined order, with - children sorted by name, and the nodes visited in breadth-first - order. It also updates the inode offset. */ -int lcfs_compute_tree(struct lcfs_ctx_s *ctx, struct lcfs_node_s *root) -{ - uint32_t index; - struct lcfs_node_s *node; - - /* Start with the root node. */ - - ctx->queue_end = root; - root->in_tree = true; - - ctx->min_mtim_sec = root->inode.st_mtim_sec; - ctx->min_mtim_nsec = root->inode.st_mtim_nsec; - ctx->has_acl = false; - - for (node = root, index = 0; node != NULL; node = node->next, index++) { - if ((node->inode.st_mode & S_IFMT) != S_IFDIR && - node->children_size != 0) { - /* Only dirs can have children */ - errno = EINVAL; - return -1; - } - - /* Fix up directory n_links counts, they are 2 + nr of subdirs */ - if ((node->inode.st_mode & S_IFMT) == S_IFDIR) { - size_t n_link = 2; - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - if ((child->inode.st_mode & S_IFMT) == S_IFDIR) { - n_link++; - } - } - node->inode.st_nlink = n_link; - } - - /* Canonical order */ - if (node->children) - qsort(node->children, node->children_size, - sizeof(node->children[0]), cmp_nodes); - if (node->xattrs) - qsort(node->xattrs, node->n_xattrs, - sizeof(node->xattrs[0]), cmp_xattr); - - if (node->inode.st_mtim_sec < ctx->min_mtim_sec || - (node->inode.st_mtim_sec == ctx->min_mtim_sec && - node->inode.st_mtim_nsec < ctx->min_mtim_nsec)) { - ctx->min_mtim_sec = node->inode.st_mtim_sec; - ctx->min_mtim_nsec = node->inode.st_mtim_nsec; - } - - /* Assign inode index */ - node->inode_num = index; - - /* Compute has_acl */ - if (lcfs_node_get_xattr(node, "system.posix_acl_access", NULL) != NULL || - lcfs_node_get_xattr(node, "system.posix_acl_default", NULL) != NULL) - ctx->has_acl = true; - - node->in_tree = true; - /* Append to queue for more work */ - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - - /* Skip hardlinks, they will not be serialized separately */ - if (child->link_to != NULL) { - continue; - } - - /* Avoid recursion */ - assert(!child->in_tree); - - ctx->queue_end->next = child; - ctx->queue_end = child; - } - } - - /* Ensure all hardlinks are in tree */ - for (node = root; node != NULL; node = node->next) { - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - if (child->link_to != NULL && !child->link_to->in_tree) { - /* Link to inode outside tree */ - errno = EINVAL; - return -1; - } - } - } - - /* Reset in_tree back to false for multiple uses */ - for (node = ctx->root; node != NULL; node = node->next) { - node->in_tree = false; - } - - ctx->num_inodes = index; - - return 0; -} - -struct lcfs_node_s *follow_links(struct lcfs_node_s *node) -{ - if (node->link_to) - return follow_links(node->link_to); - return node; -} - -int lcfs_write(struct lcfs_ctx_s *ctx, void *_data, size_t data_len) -{ - uint8_t *data = _data; - if (ctx->fsverity_ctx) - lcfs_fsverity_context_update(ctx->fsverity_ctx, data, data_len); - - ctx->bytes_written += data_len; - - if (ctx->write_cb) { - while (data_len > 0) { - ssize_t r = ctx->write_cb(ctx->file, data, data_len); - if (r <= 0) { - errno = EIO; - return -1; - } - data_len -= r; - data += r; - } - } - - return 0; -} - -int lcfs_write_pad(struct lcfs_ctx_s *ctx, size_t data_len) -{ - char buf[256] = { 0 }; - - for (size_t i = 0; i < data_len; i += sizeof(buf)) { - size_t to_write = MIN(sizeof(buf), data_len - i); - int r = lcfs_write(ctx, buf, to_write); - if (r < 0) { - return r; - } - } - - return 0; -} - -int lcfs_write_align(struct lcfs_ctx_s *ctx, size_t align_size) -{ - off_t end = round_up(ctx->bytes_written, align_size); - if (end > ctx->bytes_written) { - return lcfs_write_pad(ctx, end - ctx->bytes_written); - } - return 0; -} - -static int lcfs_close(struct lcfs_ctx_s *ctx) -{ - if (ctx == NULL) - return 0; - - if (ctx->finalize) - ctx->finalize(ctx); - - if (ctx->fsverity_ctx) - lcfs_fsverity_context_free(ctx->fsverity_ctx); - if (ctx->root) { - if (ctx->destroy_root) { - lcfs_node_destroy(ctx->root); - } else { - lcfs_node_unref(ctx->root); - } - } - free(ctx); - - return 0; -} - -int lcfs_write_to(struct lcfs_node_s *root, struct lcfs_write_options_s *options) -{ - enum lcfs_format_t format = options->format; - struct lcfs_ctx_s *ctx; - int res; - - /* Check for unknown flags */ - if ((options->flags & ~LCFS_FLAGS_MASK) != 0) { - errno = -EINVAL; - return -1; - } - - ctx = lcfs_new_ctx(root, options); - if (ctx == NULL) { - errno = ENOMEM; - return -1; - } - - if (format == LCFS_FORMAT_EROFS) - res = lcfs_write_erofs_to(ctx); - else { - errno = -EINVAL; - res = -1; - } - - if (res < 0) { - lcfs_close(ctx); - return res; - } - - if (options->digest_out) { - lcfs_fsverity_context_get_digest(ctx->fsverity_ctx, - options->digest_out); - } - - lcfs_close(ctx); - return 0; -} - -static int read_xattrs(struct lcfs_node_s *ret, int dirfd, const char *fname) -{ - char path[PATH_MAX]; - ssize_t list_size; - cleanup_free char *list = NULL; - ssize_t r = 0; - cleanup_fd int fd = -1; - - fd = openat(dirfd, fname, O_PATH | O_NOFOLLOW | O_CLOEXEC, 0); - if (fd < 0) - return -1; - - sprintf(path, "/proc/self/fd/%d", fd); - - list_size = listxattr(path, NULL, 0); - if (list_size < 0) { - return list_size; - } - - list = malloc(list_size); - if (list == NULL) { - return -1; - } - - list_size = listxattr(path, list, list_size); - if (list_size < 0) { - return list_size; - } - - for (const char *it = list; it < list + list_size; it += strlen(it) + 1) { - ssize_t value_size; - cleanup_free char *value = NULL; - - value_size = getxattr(path, it, NULL, 0); - if (value_size < 0) { - return value_size; - } - - value = malloc(value_size); - if (value == NULL) { - return -1; - } - - r = getxattr(path, it, value, value_size); - if (r < 0) { - return r; - } - - r = lcfs_node_set_xattr(ret, it, value, value_size); - if (r < 0) { - return r; - } - } - return r; -} - -struct lcfs_node_s *lcfs_node_new(void) -{ - struct lcfs_node_s *node = calloc(1, sizeof(struct lcfs_node_s)); - if (node == NULL) - return NULL; - - node->ref_count = 1; - node->inode.st_nlink = 1; - return node; -} - -static ssize_t fsverity_read_cb(void *_fd, void *buf, size_t count) -{ - int fd = *(int *)_fd; - ssize_t res; - - do - res = read(fd, buf, count); - while (res < 0 && errno == EINTR); - - return res; -} - -int lcfs_compute_fsverity_from_content(uint8_t *digest, void *file, lcfs_read_cb read_cb) -{ - uint8_t buffer[4096]; - ssize_t n_read; - FsVerityContext *ctx; - - ctx = lcfs_fsverity_context_new(); - if (ctx == NULL) { - errno = ENOMEM; - return -1; - } - - while (true) { - n_read = read_cb(file, buffer, sizeof(buffer)); - if (n_read < 0) { - lcfs_fsverity_context_free(ctx); - errno = ENODATA; - return -1; - } - if (n_read == 0) - break; - lcfs_fsverity_context_update(ctx, buffer, n_read); - } - - lcfs_fsverity_context_get_digest(ctx, digest); - - lcfs_fsverity_context_free(ctx); - - return 0; -} - -int lcfs_compute_fsverity_from_fd(uint8_t *digest, int fd) -{ - int _fd = fd; - return lcfs_compute_fsverity_from_content(digest, &_fd, fsverity_read_cb); -} - -int lcfs_compute_fsverity_from_data(uint8_t *digest, uint8_t *data, size_t data_len) -{ - FsVerityContext *ctx; - - ctx = lcfs_fsverity_context_new(); - if (ctx == NULL) { - errno = ENOMEM; - return -1; - } - - lcfs_fsverity_context_update(ctx, data, data_len); - - lcfs_fsverity_context_get_digest(ctx, digest); - - lcfs_fsverity_context_free(ctx); - - return 0; -} - -int lcfs_node_set_fsverity_from_content(struct lcfs_node_s *node, void *file, - lcfs_read_cb read_cb) -{ - uint8_t digest[LCFS_DIGEST_SIZE]; - - if (lcfs_compute_fsverity_from_content(digest, file, read_cb) < 0) - return -1; - - lcfs_node_set_fsverity_digest(node, digest); - - return 0; -} - -int lcfs_node_set_fsverity_from_fd(struct lcfs_node_s *node, int fd) -{ - int _fd = fd; - return lcfs_node_set_fsverity_from_content(node, &_fd, fsverity_read_cb); -} - -static int read_content(int fd, size_t size, uint8_t *buf) -{ - int bytes_read; - - while (size > 0) { - do - bytes_read = read(fd, buf, size); - while (bytes_read < 0 && errno == EINTR); - - if (bytes_read == 0) - break; - - size -= bytes_read; - buf += bytes_read; - } - - if (size > 0) { - errno = ENODATA; - return -1; - } - - return 0; -} - -struct lcfs_node_s *lcfs_load_node_from_file(int dirfd, const char *fname, - int buildflags) -{ - cleanup_node struct lcfs_node_s *ret = NULL; - struct stat sb; - int r; - - if (buildflags & ~(LCFS_BUILD_SKIP_XATTRS | LCFS_BUILD_USE_EPOCH | - LCFS_BUILD_SKIP_DEVICES | LCFS_BUILD_COMPUTE_DIGEST | - LCFS_BUILD_NO_INLINE)) { - errno = EINVAL; - return NULL; - } - - r = fstatat(dirfd, fname, &sb, AT_SYMLINK_NOFOLLOW); - if (r < 0) - return NULL; - - ret = lcfs_node_new(); - if (ret == NULL) - return NULL; - - ret->inode.st_mode = sb.st_mode; - ret->inode.st_uid = sb.st_uid; - ret->inode.st_gid = sb.st_gid; - ret->inode.st_rdev = sb.st_rdev; - ret->inode.st_size = sb.st_size; - - if ((sb.st_mode & S_IFMT) == S_IFREG) { - bool compute_digest = (buildflags & LCFS_BUILD_COMPUTE_DIGEST) != 0; - bool no_inline = (buildflags & LCFS_BUILD_NO_INLINE) != 0; - bool is_zerosized = sb.st_size == 0; - bool do_digest = !is_zerosized && compute_digest; - bool do_inline = !is_zerosized && !no_inline && - sb.st_size <= LCFS_BUILD_INLINE_FILE_SIZE_LIMIT; - - if (do_digest || do_inline) { - cleanup_fd int fd = - openat(dirfd, fname, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return NULL; - if (do_digest) { - r = lcfs_node_set_fsverity_from_fd(ret, fd); - if (r < 0) - return NULL; - /* In case we re-read below */ - lseek(fd, 0, SEEK_SET); - } - if (do_inline) { - uint8_t buf[LCFS_BUILD_INLINE_FILE_SIZE_LIMIT]; - - r = read_content(fd, sb.st_size, buf); - if (r < 0) - return NULL; - r = lcfs_node_set_content(ret, buf, sb.st_size); - if (r < 0) - return NULL; - } - } - } - - if ((buildflags & LCFS_BUILD_USE_EPOCH) == 0) { - ret->inode.st_mtim_sec = sb.st_mtim.tv_sec; - ret->inode.st_mtim_nsec = sb.st_mtim.tv_nsec; - } - - if ((buildflags & LCFS_BUILD_SKIP_XATTRS) == 0) { - r = read_xattrs(ret, dirfd, fname); - if (r < 0) - return NULL; - } - - return steal_pointer(&ret); -} - -struct lcfs_node_s *lcfs_load_node_from_fd(int fd) -{ - struct lcfs_node_s *node; - uint8_t *image_data; - size_t image_data_size; - struct stat s; - int errsv; - int r; - - r = fstat(fd, &s); - if (r < 0) { - return NULL; - } - - image_data_size = s.st_size; - - image_data = mmap(0, image_data_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (image_data == MAP_FAILED) { - return NULL; - } - - node = lcfs_load_node_from_image(image_data, image_data_size); - if (node == NULL) { - errsv = errno; - munmap(image_data, image_data_size); - errno = errsv; - return NULL; - } - - munmap(image_data, image_data_size); - - return node; -} - -int lcfs_node_set_payload(struct lcfs_node_s *node, const char *payload) -{ - char *dup = strdup(payload); - if (dup == NULL) { - errno = ENOMEM; - return -1; - } - free(node->payload); - node->payload = dup; - - return 0; -} - -const char *lcfs_node_get_payload(struct lcfs_node_s *node) -{ - return node->payload; -} - -const uint8_t *lcfs_node_get_fsverity_digest(struct lcfs_node_s *node) -{ - if (node->digest_set) - return node->digest; - return NULL; -} - -/* This is the sha256 fs-verity digest of the file contents */ -void lcfs_node_set_fsverity_digest(struct lcfs_node_s *node, - uint8_t digest[LCFS_DIGEST_SIZE]) -{ - node->digest_set = true; - memcpy(node->digest, digest, LCFS_DIGEST_SIZE); -} - -int lcfs_node_set_content(struct lcfs_node_s *node, const uint8_t *data, - size_t data_size) -{ - uint8_t *dup = NULL; - - if (data && data_size != 0) { - dup = malloc(data_size); - if (dup == NULL) { - errno = ENOMEM; - return -1; - } - memcpy(dup, data, data_size); - } - free(node->content); - node->content = dup; - node->inode.st_size = data_size; - - return 0; -} - -const uint8_t *lcfs_node_get_content(struct lcfs_node_s *node) -{ - return node->content; -} - -const char *lcfs_node_get_name(struct lcfs_node_s *node) -{ - return node->name; -} - -size_t lcfs_node_get_n_children(struct lcfs_node_s *node) -{ - return node->children_size; -} - -struct lcfs_node_s *lcfs_node_get_child(struct lcfs_node_s *node, size_t i) -{ - if (i < node->children_size) - return node->children[i]; - return NULL; -} - -uint32_t lcfs_node_get_mode(struct lcfs_node_s *node) -{ - return node->inode.st_mode; -} - -void lcfs_node_set_mode(struct lcfs_node_s *node, uint32_t mode) -{ - node->inode.st_mode = mode; -} - -uint32_t lcfs_node_get_uid(struct lcfs_node_s *node) -{ - return node->inode.st_uid; -} - -void lcfs_node_set_uid(struct lcfs_node_s *node, uint32_t uid) -{ - node->inode.st_uid = uid; -} - -uint32_t lcfs_node_get_gid(struct lcfs_node_s *node) -{ - return node->inode.st_gid; -} - -void lcfs_node_set_gid(struct lcfs_node_s *node, uint32_t gid) -{ - node->inode.st_gid = gid; -} - -uint32_t lcfs_node_get_rdev(struct lcfs_node_s *node) -{ - return node->inode.st_rdev; -} - -void lcfs_node_set_rdev(struct lcfs_node_s *node, uint32_t rdev) -{ - node->inode.st_rdev = rdev; -} - -uint32_t lcfs_node_get_nlink(struct lcfs_node_s *node) -{ - return node->inode.st_nlink; -} - -void lcfs_node_set_nlink(struct lcfs_node_s *node, uint32_t nlink) -{ - node->inode.st_nlink = nlink; -} - -uint64_t lcfs_node_get_size(struct lcfs_node_s *node) -{ - return node->inode.st_size; -} - -/* Clears content if size changes */ -void lcfs_node_set_size(struct lcfs_node_s *node, uint64_t size) -{ - if (size == node->inode.st_size) - return; - - free(node->content); - node->content = NULL; - node->inode.st_size = size; -} - -void lcfs_node_set_mtime(struct lcfs_node_s *node, struct timespec *time) -{ - node->inode.st_mtim_sec = time->tv_sec; - node->inode.st_mtim_nsec = time->tv_nsec; -} - -void lcfs_node_get_mtime(struct lcfs_node_s *node, struct timespec *time) -{ - time->tv_sec = node->inode.st_mtim_sec; - time->tv_nsec = node->inode.st_mtim_nsec; -} - -struct lcfs_node_s *lcfs_node_lookup_child(struct lcfs_node_s *node, const char *name) -{ - size_t i; - - for (i = 0; i < node->children_size; ++i) { - struct lcfs_node_s *child = node->children[i]; - - if (child->name && strcmp(child->name, name) == 0) - return child; - } - - return NULL; -} - -struct lcfs_node_s *lcfs_node_get_parent(struct lcfs_node_s *node) -{ - return node->parent; -} - -void lcfs_node_make_hardlink(struct lcfs_node_s *node, struct lcfs_node_s *target) -{ - target = follow_links(target); - node->link_to = lcfs_node_ref(target); - target->inode.st_nlink++; -} - -struct lcfs_node_s *lcfs_node_get_hardlink_target(struct lcfs_node_s *node) -{ - return node->link_to; -} - -int lcfs_node_add_child(struct lcfs_node_s *parent, struct lcfs_node_s *child, - const char *name) -{ - struct lcfs_node_s **new_children; - size_t new_size; - char *name_copy; - - if ((parent->inode.st_mode & S_IFMT) != S_IFDIR) { - errno = ENOTDIR; - return -1; - } - - if (strlen(name) > LCFS_MAX_NAME_LENGTH) { - errno = ENAMETOOLONG; - return -1; - } - - /* Each node can only be added once */ - if (child->name != NULL) { - errno = EMLINK; - return -1; - } - - if (lcfs_node_lookup_child(parent, name) != NULL) { - errno = EEXIST; - return -1; - } - - name_copy = strdup(name); - if (name_copy == NULL) { - errno = ENOMEM; - return -1; - } - - new_size = parent->children_size + 1; - - new_children = reallocarray(parent->children, sizeof(*parent->children), - new_size); - if (new_children == NULL) { - errno = ENOMEM; - free(name_copy); - return -1; - } - - parent->children = new_children; - - parent->children[parent->children_size] = child; - parent->children_size = new_size; - child->parent = parent; - child->name = name_copy; - - return 0; -} - -struct lcfs_node_s *lcfs_node_ref(struct lcfs_node_s *node) -{ - node->ref_count++; - return node; -} - -void lcfs_node_unref(struct lcfs_node_s *node) -{ - size_t i; - - node->ref_count--; - - if (node->ref_count > 0) - return; - - /* finalizing */ - - /* if we have a parent, that should have a real ref to us */ - assert(node->parent == NULL); - - lcfs_node_remove_all_children(node); - free(node->children); - - if (node->link_to) - lcfs_node_unref(node->link_to); - - free(node->name); - free(node->payload); - free(node->content); - - for (i = 0; i < node->n_xattrs; i++) { - free(node->xattrs[i].key); - free(node->xattrs[i].value); - } - free(node->xattrs); - - free(node); -} - -static void lcfs_node_remove_all_children(struct lcfs_node_s *node) -{ - for (size_t i = 0; i < node->children_size; i++) { - struct lcfs_node_s *child = node->children[i]; - assert(child->parent == node); - /* Unlink correctly as it may live on outside the tree and be reinserted */ - free(child->name); - child->name = NULL; - child->parent = NULL; - lcfs_node_destroy(child); - } - node->children_size = 0; -} - -/* Unlink all children (recursively) and then unref. Useful to handle refcount loops like dot and dotdot. */ -static void lcfs_node_destroy(struct lcfs_node_s *node) -{ - lcfs_node_remove_all_children(node); - lcfs_node_unref(node); -}; - -struct lcfs_node_s *lcfs_node_clone(struct lcfs_node_s *node) -{ - cleanup_node struct lcfs_node_s *new = lcfs_node_new(); - if (new == NULL) - return NULL; - - /* Note: This copies only data, not structure like name or children */ - - /* We copy the link_to, but clone_deep may rewrite this */ - if (node->link_to) { - new->link_to = lcfs_node_ref(node->link_to); - } - - if (node->payload) { - new->payload = strdup(node->payload); - if (new->payload == NULL) - return NULL; - ; - } - - if (node->content) { - new->content = malloc(node->inode.st_size); - if (new->content == NULL) - return NULL; - ; - memcpy(new->content, node->content, node->inode.st_size); - } - - if (node->n_xattrs > 0) { - new->xattrs = malloc(sizeof(struct lcfs_xattr_s) * node->n_xattrs); - if (new->xattrs == NULL) - return NULL; - for (size_t i = 0; i < node->n_xattrs; i++) { - char *key = strdup(node->xattrs[i].key); - char *value = memdup(node->xattrs[i].value, - node->xattrs[i].value_len); - if (key == NULL || value == NULL) { - free(key); - free(value); - return NULL; - } - new->xattrs[i].key = key; - new->xattrs[i].value = value; - new->xattrs[i].value_len = node->xattrs[i].value_len; - new->n_xattrs++; - } - } - - new->digest_set = node->digest_set; - memcpy(new->digest, node->digest, LCFS_DIGEST_SIZE); - new->inode = node->inode; - - return steal_pointer(&new); -} - -struct lcfs_node_mapping_s { - struct lcfs_node_s *old; - struct lcfs_node_s *new; -}; - -struct lcfs_clone_data { - struct lcfs_node_mapping_s *mapping; - size_t n_mappings; - size_t allocated_mappings; -}; - -static struct lcfs_node_s *_lcfs_node_clone_deep(struct lcfs_node_s *node, - struct lcfs_clone_data *data) -{ - cleanup_node struct lcfs_node_s *new = lcfs_node_clone(node); - if (new == NULL) - return NULL; - - if (data->n_mappings >= data->allocated_mappings) { - struct lcfs_node_mapping_s *new_mapping; - data->allocated_mappings = (data->allocated_mappings == 0) ? - 32 : - data->allocated_mappings * 2; - new_mapping = reallocarray(data->mapping, - sizeof(struct lcfs_node_mapping_s), - data->allocated_mappings); - if (new_mapping == NULL) - return NULL; - data->mapping = new_mapping; - } - - data->mapping[data->n_mappings].old = node; - data->mapping[data->n_mappings].new = new; - data->n_mappings++; - - for (size_t i = 0; i < node->children_size; ++i) { - struct lcfs_node_s *child = node->children[i]; - struct lcfs_node_s *new_child = _lcfs_node_clone_deep(child, data); - if (new_child == NULL) - return NULL; - - if (lcfs_node_add_child(new, new_child, child->name) < 0) - return NULL; - } - - return steal_pointer(&new); -} - -/* Rewrite all hardlinks according to mapping */ -static void _lcfs_node_clone_rewrite_links(struct lcfs_node_s *new, - struct lcfs_clone_data *data) -{ - for (size_t i = 0; i < new->children_size; ++i) { - struct lcfs_node_s *new_child = new->children[i]; - _lcfs_node_clone_rewrite_links(new_child, data); - } - - if (new->link_to != NULL) { - for (size_t i = 0; i < data->n_mappings; ++i) { - if (data->mapping[i].old == new->link_to) { - lcfs_node_unref(new->link_to); - new->link_to = lcfs_node_ref(data->mapping[i].new); - break; - } - } - } -} - -struct lcfs_node_s *lcfs_node_clone_deep(struct lcfs_node_s *node) -{ - struct lcfs_clone_data data = { NULL }; - struct lcfs_node_s *new; - - new = _lcfs_node_clone_deep(node, &data); - if (new) - _lcfs_node_clone_rewrite_links(new, &data); - - free(data.mapping); - - return new; -} - -bool lcfs_node_dirp(struct lcfs_node_s *node) -{ - return (node->inode.st_mode & S_IFMT) == S_IFDIR; -} - -struct lcfs_node_s *lcfs_build(int dirfd, const char *fname, int buildflags, - char **failed_path_out) -{ - struct lcfs_node_s *node = NULL; - struct dirent *de; - DIR *dir = NULL; - int dfd; - char *free_failed_subpath = NULL; - const char *failed_subpath = NULL; - int errsv; - - node = lcfs_load_node_from_file(dirfd, fname, buildflags); - if (node == NULL) { - errsv = errno; - goto fail; - } - - if (!lcfs_node_dirp(node)) { - return node; - } - - dfd = openat(dirfd, fname, O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0); - if (dfd < 0) { - errsv = errno; - goto fail; - } - - dir = fdopendir(dfd); - if (dir == NULL) { - errsv = errno; - close(dfd); - goto fail; - } - - for (;;) { - struct lcfs_node_s *n; - int r; - - errno = 0; - de = readdir(dir); - if (de == NULL) { - if (errno) { - errsv = errno; - goto fail; - } - - break; - } - - if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) - continue; - - if (de->d_type == DT_UNKNOWN) { - struct stat statbuf; - - if (fstatat(dfd, de->d_name, &statbuf, - AT_SYMLINK_NOFOLLOW) < 0) { - errsv = errno; - failed_subpath = de->d_name; - goto fail; - } - - if (S_ISDIR(statbuf.st_mode)) - de->d_type = DT_DIR; - } - - if (de->d_type == DT_DIR) { - n = lcfs_build(dfd, de->d_name, buildflags, - &free_failed_subpath); - if (n == NULL) { - failed_subpath = free_failed_subpath; - errsv = errno; - goto fail; - } - } else { - if (buildflags & LCFS_BUILD_SKIP_DEVICES) { - if (de->d_type == DT_BLK || de->d_type == DT_CHR) - continue; - } - - n = lcfs_load_node_from_file(dfd, de->d_name, buildflags); - if (n == NULL) { - errsv = errno; - failed_subpath = de->d_name; - goto fail; - } - } - - r = lcfs_node_add_child(node, n, de->d_name); - if (r < 0) { - errsv = errno; - goto fail; - } - } - - closedir(dir); - return node; - -fail: - if (failed_path_out) - *failed_path_out = maybe_join_path(fname, failed_subpath); - if (free_failed_subpath) - free(free_failed_subpath); - if (node) - lcfs_node_unref(node); - if (dir) - closedir(dir); - errno = errsv; - return NULL; -} - -size_t lcfs_node_get_n_xattr(struct lcfs_node_s *node) -{ - return node->n_xattrs; -} - -const char *lcfs_node_get_xattr_name(struct lcfs_node_s *node, size_t index) -{ - if (index >= node->n_xattrs) - return NULL; - - return node->xattrs[index].key; -} - -static ssize_t find_xattr(struct lcfs_node_s *node, const char *name) -{ - ssize_t i; - for (i = 0; i < (ssize_t)node->n_xattrs; i++) { - struct lcfs_xattr_s *xattr = &node->xattrs[i]; - if (strcmp(name, xattr->key) == 0) - return i; - } - return -1; -} - -const char *lcfs_node_get_xattr(struct lcfs_node_s *node, const char *name, - size_t *length) -{ - ssize_t index = find_xattr(node, name); - - if (index >= 0) { - struct lcfs_xattr_s *xattr = &node->xattrs[index]; - if (length) - *length = xattr->value_len; - return xattr->value; - } - - return NULL; -} - -int lcfs_node_unset_xattr(struct lcfs_node_s *node, const char *name) -{ - ssize_t index = find_xattr(node, name); - - if (index >= 0) { - if (index != (ssize_t)node->n_xattrs - 1) - node->xattrs[index] = node->xattrs[node->n_xattrs - 1]; - node->n_xattrs--; - } - - return -1; -} - -int lcfs_node_set_xattr(struct lcfs_node_s *node, const char *name, - const char *value, size_t value_len) -{ - struct lcfs_xattr_s *xattrs; - char *k, *v; - ssize_t index = find_xattr(node, name); - - if (index >= 0) { - /* Already set, replace */ - struct lcfs_xattr_s *xattr = &node->xattrs[index]; - v = memdup(value, value_len); - if (v == NULL) { - errno = ENOMEM; - return -1; - } - free(xattr->value); - xattr->value = v; - xattr->value_len = value_len; - - return 0; - } - - xattrs = realloc(node->xattrs, - (node->n_xattrs + 1) * sizeof(struct lcfs_xattr_s)); - if (xattrs == NULL) { - errno = ENOMEM; - return -1; - } - node->xattrs = xattrs; - - k = strdup(name); - v = memdup(value, value_len); - if (k == NULL || v == NULL) { - free(k); - free(v); - errno = ENOMEM; - return -1; - } - - xattrs[node->n_xattrs].key = k; - xattrs[node->n_xattrs].value = v; - xattrs[node->n_xattrs].value_len = value_len; - node->n_xattrs++; - - return 0; -} - -/* This is an internal function. - * Be careful to not cause duplicates if new_name already exist */ -int lcfs_node_rename_xattr(struct lcfs_node_s *node, size_t index, const char *new_name) -{ - struct lcfs_xattr_s *xattr; - cleanup_free char *dup = NULL; - - dup = strdup(new_name); - if (dup == NULL) { - errno = ENOMEM; - return -1; - } - - if (index >= node->n_xattrs) { - errno = EINVAL; - return -1; - } - - xattr = &node->xattrs[index]; - free(xattr->key); - xattr->key = steal_pointer(&dup); - return 0; -} diff --git a/composefs/libcomposefs/lcfs-writer.h b/composefs/libcomposefs/lcfs-writer.h deleted file mode 100644 index 136de48..0000000 --- a/composefs/libcomposefs/lcfs-writer.h +++ /dev/null @@ -1,143 +0,0 @@ -/* lcfs - Copyright (C) 2021 Giuseppe Scrivano - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef _LCFS_OPS_H -#define _LCFS_OPS_H - -#include -#include -#include -#include -#include - -#ifndef LCFS_EXTERN -#define LCFS_EXTERN extern -#endif - -#define LCFS_DIGEST_SIZE 32 - -enum { - LCFS_BUILD_SKIP_XATTRS = (1 << 0), - LCFS_BUILD_USE_EPOCH = (1 << 1), - LCFS_BUILD_SKIP_DEVICES = (1 << 2), - LCFS_BUILD_COMPUTE_DIGEST = (1 << 3), - LCFS_BUILD_NO_INLINE = (1 << 4), -}; - -enum lcfs_format_t { - LCFS_FORMAT_EROFS, -}; - -enum lcfs_flags_t { - LCFS_FLAGS_NONE = 0, - LCFS_FLAGS_MASK = 0, -}; - -typedef ssize_t (*lcfs_read_cb)(void *file, void *buf, size_t count); -typedef ssize_t (*lcfs_write_cb)(void *file, void *buf, size_t count); - -struct lcfs_write_options_s { - uint32_t format; - uint32_t version; - uint32_t flags; - uint8_t *digest_out; - void *file; - lcfs_write_cb file_write_cb; - uint32_t reserved[4]; - void *reserved2[4]; -}; - -LCFS_EXTERN struct lcfs_node_s *lcfs_node_new(void); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_ref(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_unref(struct lcfs_node_s *node); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_clone(struct lcfs_node_s *node); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_clone_deep(struct lcfs_node_s *node); -LCFS_EXTERN struct lcfs_node_s *lcfs_load_node_from_file(int dirfd, const char *fname, - int buildflags); -LCFS_EXTERN struct lcfs_node_s *lcfs_load_node_from_image(const uint8_t *image_data, - size_t image_data_size); -LCFS_EXTERN struct lcfs_node_s *lcfs_load_node_from_fd(int fd); - -LCFS_EXTERN const char *lcfs_node_get_xattr(struct lcfs_node_s *node, - const char *name, size_t *length); -LCFS_EXTERN int lcfs_node_set_xattr(struct lcfs_node_s *node, const char *name, - const char *value, size_t value_len); -LCFS_EXTERN int lcfs_node_unset_xattr(struct lcfs_node_s *node, const char *name); -LCFS_EXTERN size_t lcfs_node_get_n_xattr(struct lcfs_node_s *node); -LCFS_EXTERN const char *lcfs_node_get_xattr_name(struct lcfs_node_s *node, - size_t index); - -LCFS_EXTERN int lcfs_node_set_payload(struct lcfs_node_s *node, const char *payload); -LCFS_EXTERN const char *lcfs_node_get_payload(struct lcfs_node_s *node); - -LCFS_EXTERN int lcfs_node_set_content(struct lcfs_node_s *node, - const uint8_t *data, size_t data_size); -LCFS_EXTERN const uint8_t *lcfs_node_get_content(struct lcfs_node_s *node); - -LCFS_EXTERN struct lcfs_node_s *lcfs_node_lookup_child(struct lcfs_node_s *node, - const char *name); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_get_parent(struct lcfs_node_s *node); -LCFS_EXTERN int lcfs_node_add_child(struct lcfs_node_s *parent, - struct lcfs_node_s *child, /* Takes ownership on success */ - const char *name); -LCFS_EXTERN const char *lcfs_node_get_name(struct lcfs_node_s *node); -LCFS_EXTERN size_t lcfs_node_get_n_children(struct lcfs_node_s *node); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_get_child(struct lcfs_node_s *node, - size_t i); -LCFS_EXTERN void lcfs_node_make_hardlink(struct lcfs_node_s *node, - struct lcfs_node_s *target); -LCFS_EXTERN struct lcfs_node_s *lcfs_node_get_hardlink_target(struct lcfs_node_s *node); - -LCFS_EXTERN bool lcfs_node_dirp(struct lcfs_node_s *node); -LCFS_EXTERN uint32_t lcfs_node_get_mode(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_mode(struct lcfs_node_s *node, uint32_t mode); -LCFS_EXTERN uint32_t lcfs_node_get_uid(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_uid(struct lcfs_node_s *node, uint32_t uid); -LCFS_EXTERN uint32_t lcfs_node_get_gid(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_gid(struct lcfs_node_s *node, uint32_t gid); -LCFS_EXTERN uint32_t lcfs_node_get_rdev(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_rdev(struct lcfs_node_s *node, uint32_t rdev); -LCFS_EXTERN uint32_t lcfs_node_get_nlink(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_nlink(struct lcfs_node_s *node, uint32_t nlink); -LCFS_EXTERN uint64_t lcfs_node_get_size(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_size(struct lcfs_node_s *node, uint64_t size); -LCFS_EXTERN void lcfs_node_set_mtime(struct lcfs_node_s *node, struct timespec *time); -LCFS_EXTERN void lcfs_node_get_mtime(struct lcfs_node_s *node, struct timespec *time); - -LCFS_EXTERN const uint8_t *lcfs_node_get_fsverity_digest(struct lcfs_node_s *node); -LCFS_EXTERN void lcfs_node_set_fsverity_digest(struct lcfs_node_s *node, - uint8_t digest[LCFS_DIGEST_SIZE]); - -LCFS_EXTERN int lcfs_node_set_fsverity_from_content(struct lcfs_node_s *node, - void *file, - lcfs_read_cb read_cb); - -LCFS_EXTERN int lcfs_node_set_fsverity_from_fd(struct lcfs_node_s *node, int fd); - -LCFS_EXTERN struct lcfs_node_s *lcfs_build(int dirfd, const char *fname, - int buildflags, char **failed_path_out); - -LCFS_EXTERN int lcfs_write_to(struct lcfs_node_s *root, - struct lcfs_write_options_s *options); - -/* fsverity helpers */ -LCFS_EXTERN int lcfs_compute_fsverity_from_content(uint8_t *digest, void *file, - lcfs_read_cb read_cb); -LCFS_EXTERN int lcfs_compute_fsverity_from_fd(uint8_t *digest, int fd); -LCFS_EXTERN int lcfs_compute_fsverity_from_data(uint8_t *digest, uint8_t *data, - size_t data_len); - -#endif diff --git a/composefs/libcomposefs/xalloc-oversized.h b/composefs/libcomposefs/xalloc-oversized.h deleted file mode 100644 index 4184f33..0000000 --- a/composefs/libcomposefs/xalloc-oversized.h +++ /dev/null @@ -1,65 +0,0 @@ -/* xalloc-oversized.h -- memory allocation size checking - - Copyright (C) 1990-2000, 2003-2004, 2006-2021 Free Software Foundation, Inc. - - This file 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.1 of the - License, or (at your option) any later version. - - This file 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 program. If not, see . */ - -#ifndef XALLOC_OVERSIZED_H_ -#define XALLOC_OVERSIZED_H_ - -#include -#include - -/* True if N * S does not fit into both ptrdiff_t and size_t. - N and S should be nonnegative and free of side effects. - This expands to a constant expression if N and S are both constants. - By gnulib convention, SIZE_MAX represents overflow in size_t - calculations, so the conservative size_t-based dividend to use here - is SIZE_MAX - 1. */ -#define __xalloc_oversized(n, s) \ - ((s) != 0 \ - && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \ - < (n))) - -/* Return 1 if and only if an array of N objects, each of size S, - cannot exist reliably because its total size in bytes would exceed - MIN (PTRDIFF_MAX, SIZE_MAX - 1). - - N and S should be nonnegative and free of side effects. - - Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can - misbehave if N and S are both narrower than ptrdiff_t and size_t, - and can be rewritten as (xalloc_oversized (N, S) ? NULL - : malloc (N * (size_t) S)). - - This is a macro, not a function, so that it works even if an - argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */ -#if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX -# define xalloc_oversized(n, s) \ - __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1) -#elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \ - && PTRDIFF_MAX < SIZE_MAX) -# define xalloc_oversized(n, s) \ - (__builtin_constant_p (n) && __builtin_constant_p (s) \ - ? __xalloc_oversized (n, s) \ - : ({ ptrdiff_t __xalloc_count; \ - __builtin_mul_overflow (n, s, &__xalloc_count); })) - -/* Other compilers use integer division; this may be slower but is - more portable. */ -#else -# define xalloc_oversized(n, s) __xalloc_oversized (n, s) -#endif - -#endif /* !XALLOC_OVERSIZED_H_ */ diff --git a/config.h.in b/config.h.in index a1c6243..34bda8a 100644 --- a/config.h.in +++ b/config.h.in @@ -61,12 +61,6 @@ /* Define if ed25519 is supported */ #undef HAVE_ED25519 -/* Define if FSCONFIG_CMD_CREATE is available in linux/mount.h */ -#undef HAVE_FSCONFIG_CMD_CREATE_LINUX_MOUNT_H - -/* Define if FSCONFIG_CMD_CREATE is available in sys/mount.h */ -#undef HAVE_FSCONFIG_CMD_CREATE_SYS_MOUNT_H - /* Define if we have gnutls */ #undef HAVE_GNUTLS diff --git a/configure b/configure index 9f70777..1b798a7 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.71 for libostree 2023.7. +# Generated by GNU Autoconf 2.71 for libostree 2024.6. # # Report bugs to . # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libostree' PACKAGE_TARNAME='libostree' -PACKAGE_VERSION='2023.7' -PACKAGE_STRING='libostree 2023.7' +PACKAGE_VERSION='2024.6' +PACKAGE_STRING='libostree 2024.6' PACKAGE_BUGREPORT='walters@verbum.org' PACKAGE_URL='' @@ -749,6 +749,8 @@ OT_DEP_LIBSODIUM_LIBS OT_DEP_LIBSODIUM_CFLAGS USE_COMPOSEFS_FALSE USE_COMPOSEFS_TRUE +OT_DEP_COMPOSEFS_LIBS +OT_DEP_COMPOSEFS_CFLAGS USE_GPGME_FALSE USE_GPGME_TRUE GPG_ERROR_CONFIG @@ -757,6 +759,7 @@ OT_DEP_GPG_ERROR_CFLAGS GPGME_PTHREAD_LIBS GPGME_PTHREAD_CFLAGS GPGME_CONFIG +GPGRT_CONFIG OT_DEP_GPGME_LIBS OT_DEP_GPGME_CFLAGS BUILDOPT_INTROSPECTION_FALSE @@ -1042,6 +1045,8 @@ OT_DEP_GPGME_CFLAGS OT_DEP_GPGME_LIBS OT_DEP_GPG_ERROR_CFLAGS OT_DEP_GPG_ERROR_LIBS +OT_DEP_COMPOSEFS_CFLAGS +OT_DEP_COMPOSEFS_LIBS OT_DEP_LIBSODIUM_CFLAGS OT_DEP_LIBSODIUM_LIBS GTKDOC_DEPS_CFLAGS @@ -1610,7 +1615,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 2023.7 to adapt to many kinds of systems. +\`configure' configures libostree 2024.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1681,7 +1686,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libostree 2023.7:";; + short | recursive ) echo "Configuration of libostree 2024.6:";; esac cat <<\_ACEOF @@ -1743,7 +1748,7 @@ Optional Packages: --with-soup Use libsoup [default=yes] --with-gpgme Use gpgme [default=yes] --with-gpgme-prefix=PFX prefix where GPGME is installed (optional) - --with-composefs Support composefs + --with-composefs Support composefs (default yes) --with-ed25519-libsodium Use libsodium for ed25519 [default=no] --with-html-dir=PATH path to installed docs @@ -1843,6 +1848,10 @@ Some influential environment variables: C compiler flags for OT_DEP_GPG_ERROR, overriding pkg-config OT_DEP_GPG_ERROR_LIBS linker flags for OT_DEP_GPG_ERROR, overriding pkg-config + OT_DEP_COMPOSEFS_CFLAGS + C compiler flags for OT_DEP_COMPOSEFS, overriding pkg-config + OT_DEP_COMPOSEFS_LIBS + linker flags for OT_DEP_COMPOSEFS, overriding pkg-config OT_DEP_LIBSODIUM_CFLAGS C compiler flags for OT_DEP_LIBSODIUM, overriding pkg-config OT_DEP_LIBSODIUM_LIBS @@ -1948,7 +1957,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libostree configure 2023.7 +libostree configure 2024.6 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2321,7 +2330,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 2023.7, which was +It was created by libostree $as_me 2024.6, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3598,7 +3607,7 @@ fi # Define the identity of the package. PACKAGE='libostree' - VERSION='2023.7' + VERSION='2024.6' # Some tools Automake needs. @@ -6474,11 +6483,11 @@ done test -n "$YACC" || YACC="yacc" -YEAR_VERSION=2023 +YEAR_VERSION=2024 -RELEASE_VERSION=7 +RELEASE_VERSION=6 -PACKAGE_VERSION=2023.7 +PACKAGE_VERSION=2024.6 pkglibexecdir=$libexecdir/$PACKAGE @@ -14741,7 +14750,7 @@ CC=$lt_save_CC -OSTREE_FEATURES="inode64" +OSTREE_FEATURES="inode64 initial-var" @@ -15441,8 +15450,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 -printf %s "checking for GLIB... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $pkg_config_args" >&5 +printf %s "checking for $pkg_config_args... " >&6; } if test -n "$GLIB_CFLAGS"; then pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" @@ -15482,7 +15491,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15491,24 +15500,24 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$pkg_config_args" 2>&1` + GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$pkg_config_args" 2>&1` else - GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$pkg_config_args" 2>&1` + GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$pkg_config_args" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$GLIB_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$GLIB_PKG_ERRORS" >&5 - : + : elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - : + : else - GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS - GLIB_LIBS=$pkg_cv_GLIB_LIBS + GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS + GLIB_LIBS=$pkg_cv_GLIB_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - : + : fi @@ -15796,8 +15805,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ GIO_DEPENDENCY="gio-unix-2.0 >= 2.66.0" pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_GIO_UNIX" >&5 -printf %s "checking for OT_DEP_GIO_UNIX... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $GIO_DEPENDENCY" >&5 +printf %s "checking for $GIO_DEPENDENCY... " >&6; } if test -n "$OT_DEP_GIO_UNIX_CFLAGS"; then pkg_cv_OT_DEP_GIO_UNIX_CFLAGS="$OT_DEP_GIO_UNIX_CFLAGS" @@ -15837,7 +15846,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15846,14 +15855,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GIO_DEPENDENCY" 2>&1` + OT_DEP_GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GIO_DEPENDENCY" 2>&1` else - OT_DEP_GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GIO_DEPENDENCY" 2>&1` + OT_DEP_GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GIO_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_GIO_UNIX_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_GIO_UNIX_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($GIO_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($GIO_DEPENDENCY) were not met: $OT_DEP_GIO_UNIX_PKG_ERRORS @@ -15864,9 +15873,9 @@ Alternatively, you may set the environment variables OT_DEP_GIO_UNIX_CFLAGS and OT_DEP_GIO_UNIX_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -15879,8 +15888,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_GIO_UNIX_CFLAGS=$pkg_cv_OT_DEP_GIO_UNIX_CFLAGS - OT_DEP_GIO_UNIX_LIBS=$pkg_cv_OT_DEP_GIO_UNIX_LIBS + OT_DEP_GIO_UNIX_CFLAGS=$pkg_cv_OT_DEP_GIO_UNIX_CFLAGS + OT_DEP_GIO_UNIX_LIBS=$pkg_cv_OT_DEP_GIO_UNIX_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -15888,8 +15897,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_LZMA" >&5 -printf %s "checking for OT_DEP_LZMA... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for liblzma >= 5.0.5" >&5 +printf %s "checking for liblzma >= 5.0.5... " >&6; } if test -n "$OT_DEP_LZMA_CFLAGS"; then pkg_cv_OT_DEP_LZMA_CFLAGS="$OT_DEP_LZMA_CFLAGS" @@ -15929,7 +15938,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -15938,14 +15947,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_LZMA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblzma >= 5.0.5" 2>&1` + OT_DEP_LZMA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liblzma >= 5.0.5" 2>&1` else - OT_DEP_LZMA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblzma >= 5.0.5" 2>&1` + OT_DEP_LZMA_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liblzma >= 5.0.5" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_LZMA_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_LZMA_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (liblzma >= 5.0.5) were not met: + as_fn_error $? "Package requirements (liblzma >= 5.0.5) were not met: $OT_DEP_LZMA_PKG_ERRORS @@ -15956,9 +15965,9 @@ Alternatively, you may set the environment variables OT_DEP_LZMA_CFLAGS and OT_DEP_LZMA_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -15971,8 +15980,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_LZMA_CFLAGS=$pkg_cv_OT_DEP_LZMA_CFLAGS - OT_DEP_LZMA_LIBS=$pkg_cv_OT_DEP_LZMA_LIBS + OT_DEP_LZMA_CFLAGS=$pkg_cv_OT_DEP_LZMA_CFLAGS + OT_DEP_LZMA_LIBS=$pkg_cv_OT_DEP_LZMA_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -15980,8 +15989,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_ZLIB" >&5 -printf %s "checking for OT_DEP_ZLIB... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for zlib" >&5 +printf %s "checking for zlib... " >&6; } if test -n "$OT_DEP_ZLIB_CFLAGS"; then pkg_cv_OT_DEP_ZLIB_CFLAGS="$OT_DEP_ZLIB_CFLAGS" @@ -16021,7 +16030,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16030,14 +16039,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib" 2>&1` + OT_DEP_ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib" 2>&1` else - OT_DEP_ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib" 2>&1` + OT_DEP_ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_ZLIB_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_ZLIB_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (zlib) were not met: + as_fn_error $? "Package requirements (zlib) were not met: $OT_DEP_ZLIB_PKG_ERRORS @@ -16048,9 +16057,9 @@ Alternatively, you may set the environment variables OT_DEP_ZLIB_CFLAGS and OT_DEP_ZLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -16063,8 +16072,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_ZLIB_CFLAGS=$pkg_cv_OT_DEP_ZLIB_CFLAGS - OT_DEP_ZLIB_LIBS=$pkg_cv_OT_DEP_ZLIB_LIBS + OT_DEP_ZLIB_CFLAGS=$pkg_cv_OT_DEP_ZLIB_CFLAGS + OT_DEP_ZLIB_LIBS=$pkg_cv_OT_DEP_ZLIB_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -16072,8 +16081,8 @@ fi pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_E2P" >&5 -printf %s "checking for OT_DEP_E2P... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for e2p" >&5 +printf %s "checking for e2p... " >&6; } if test -n "$OT_DEP_E2P_CFLAGS"; then pkg_cv_OT_DEP_E2P_CFLAGS="$OT_DEP_E2P_CFLAGS" @@ -16113,7 +16122,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16122,14 +16131,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_E2P_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "e2p" 2>&1` + OT_DEP_E2P_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "e2p" 2>&1` else - OT_DEP_E2P_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "e2p" 2>&1` + OT_DEP_E2P_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "e2p" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_E2P_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_E2P_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (e2p) were not met: + as_fn_error $? "Package requirements (e2p) were not met: $OT_DEP_E2P_PKG_ERRORS @@ -16140,9 +16149,9 @@ Alternatively, you may set the environment variables OT_DEP_E2P_CFLAGS and OT_DEP_E2P_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -16155,8 +16164,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_E2P_CFLAGS=$pkg_cv_OT_DEP_E2P_CFLAGS - OT_DEP_E2P_LIBS=$pkg_cv_OT_DEP_E2P_LIBS + OT_DEP_E2P_CFLAGS=$pkg_cv_OT_DEP_E2P_CFLAGS + OT_DEP_E2P_LIBS=$pkg_cv_OT_DEP_E2P_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -16177,8 +16186,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_CURL" >&5 -printf %s "checking for OT_DEP_CURL... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcurl >= $CURL_DEPENDENCY" >&5 +printf %s "checking for libcurl >= $CURL_DEPENDENCY... " >&6; } if test -n "$OT_DEP_CURL_CFLAGS"; then pkg_cv_OT_DEP_CURL_CFLAGS="$OT_DEP_CURL_CFLAGS" @@ -16218,7 +16227,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16227,14 +16236,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl >= $CURL_DEPENDENCY" 2>&1` + OT_DEP_CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcurl >= $CURL_DEPENDENCY" 2>&1` else - OT_DEP_CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl >= $CURL_DEPENDENCY" 2>&1` + OT_DEP_CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcurl >= $CURL_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_CURL_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_CURL_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (libcurl >= $CURL_DEPENDENCY) were not met: + as_fn_error $? "Package requirements (libcurl >= $CURL_DEPENDENCY) were not met: $OT_DEP_CURL_PKG_ERRORS @@ -16245,9 +16254,9 @@ Alternatively, you may set the environment variables OT_DEP_CURL_CFLAGS and OT_DEP_CURL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -16260,8 +16269,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_CURL_CFLAGS=$pkg_cv_OT_DEP_CURL_CFLAGS - OT_DEP_CURL_LIBS=$pkg_cv_OT_DEP_CURL_LIBS + OT_DEP_CURL_CFLAGS=$pkg_cv_OT_DEP_CURL_CFLAGS + OT_DEP_CURL_LIBS=$pkg_cv_OT_DEP_CURL_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -16312,16 +16321,40 @@ if test ${with_soup3+y} then : withval=$with_soup3; else $as_nop - with_soup3=no + with_soup3=check fi if test x$with_soup3 != xno then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $SOUP3_DEPENDENCY" >&5 +printf %s "checking for $SOUP3_DEPENDENCY... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$SOUP3_DEPENDENCY\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$SOUP3_DEPENDENCY") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_soup3=yes +else + have_soup3=no +fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_soup3" >&5 +printf "%s\n" "$have_soup3" >&6; } + if test x$have_soup3 = xno && test x$with_soup3 != xcheck +then : + + as_fn_error $? "libsoup3 is enabled but could not be found" "$LINENO" 5 + +fi + if test x$have_soup3 = xyes +then : + + with_soup3=yes pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_SOUP3" >&5 -printf %s "checking for OT_DEP_SOUP3... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $SOUP3_DEPENDENCY" >&5 +printf %s "checking for $SOUP3_DEPENDENCY... " >&6; } if test -n "$OT_DEP_SOUP3_CFLAGS"; then pkg_cv_OT_DEP_SOUP3_CFLAGS="$OT_DEP_SOUP3_CFLAGS" @@ -16361,7 +16394,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16370,14 +16403,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_SOUP3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SOUP3_DEPENDENCY" 2>&1` + OT_DEP_SOUP3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SOUP3_DEPENDENCY" 2>&1` else - OT_DEP_SOUP3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SOUP3_DEPENDENCY" 2>&1` + OT_DEP_SOUP3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SOUP3_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_SOUP3_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_SOUP3_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($SOUP3_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($SOUP3_DEPENDENCY) were not met: $OT_DEP_SOUP3_PKG_ERRORS @@ -16388,9 +16421,9 @@ Alternatively, you may set the environment variables OT_DEP_SOUP3_CFLAGS and OT_DEP_SOUP3_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -16403,24 +16436,27 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_SOUP3_CFLAGS=$pkg_cv_OT_DEP_SOUP3_CFLAGS - OT_DEP_SOUP3_LIBS=$pkg_cv_OT_DEP_SOUP3_LIBS + OT_DEP_SOUP3_CFLAGS=$pkg_cv_OT_DEP_SOUP3_CFLAGS + OT_DEP_SOUP3_LIBS=$pkg_cv_OT_DEP_SOUP3_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi - with_soup3=yes printf "%s\n" "#define HAVE_LIBSOUP3 1" >>confdefs.h - OSTREE_FEATURES="$OSTREE_FEATURES libsoup3" - with_soup_default=no - have_libsoup_client_certs=yes + OSTREE_FEATURES="$OSTREE_FEATURES libsoup3" + with_soup_default=no + have_libsoup_client_certs=yes + +else $as_nop + with_soup3=no +fi else $as_nop with_soup_default=check fi - if test x$with_soup3 != xno; then + if test x$with_soup3 = xyes; then USE_LIBSOUP3_TRUE= USE_LIBSOUP3_FALSE='#' else @@ -16475,8 +16511,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_SOUP" >&5 -printf %s "checking for OT_DEP_SOUP... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $SOUP_DEPENDENCY" >&5 +printf %s "checking for $SOUP_DEPENDENCY... " >&6; } if test -n "$OT_DEP_SOUP_CFLAGS"; then pkg_cv_OT_DEP_SOUP_CFLAGS="$OT_DEP_SOUP_CFLAGS" @@ -16516,7 +16552,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16525,14 +16561,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_SOUP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SOUP_DEPENDENCY" 2>&1` + OT_DEP_SOUP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SOUP_DEPENDENCY" 2>&1` else - OT_DEP_SOUP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SOUP_DEPENDENCY" 2>&1` + OT_DEP_SOUP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SOUP_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_SOUP_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_SOUP_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($SOUP_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($SOUP_DEPENDENCY) were not met: $OT_DEP_SOUP_PKG_ERRORS @@ -16543,9 +16579,9 @@ Alternatively, you may set the environment variables OT_DEP_SOUP_CFLAGS and OT_DEP_SOUP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -16558,8 +16594,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_SOUP_CFLAGS=$pkg_cv_OT_DEP_SOUP_CFLAGS - OT_DEP_SOUP_LIBS=$pkg_cv_OT_DEP_SOUP_LIBS + OT_DEP_SOUP_CFLAGS=$pkg_cv_OT_DEP_SOUP_CFLAGS + OT_DEP_SOUP_LIBS=$pkg_cv_OT_DEP_SOUP_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -16848,8 +16884,8 @@ then : have_gpgme=yes pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_GPGME" >&5 -printf %s "checking for OT_DEP_GPGME... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gpgme >= $LIBGPGME_DEPENDENCY gpg-error" >&5 +printf %s "checking for gpgme >= $LIBGPGME_DEPENDENCY gpg-error... " >&6; } if test -n "$OT_DEP_GPGME_CFLAGS"; then pkg_cv_OT_DEP_GPGME_CFLAGS="$OT_DEP_GPGME_CFLAGS" @@ -16889,7 +16925,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -16898,29 +16934,157 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpgme >= $LIBGPGME_DEPENDENCY gpg-error" 2>&1` + OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpgme >= $LIBGPGME_DEPENDENCY gpg-error" 2>&1` else - OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpgme >= $LIBGPGME_DEPENDENCY gpg-error" 2>&1` + OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpgme >= $LIBGPGME_DEPENDENCY gpg-error" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_GPGME_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_GPGME_PKG_ERRORS" >&5 - have_gpgme=no + have_gpgme=no elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - have_gpgme=no + have_gpgme=no else - OT_DEP_GPGME_CFLAGS=$pkg_cv_OT_DEP_GPGME_CFLAGS - OT_DEP_GPGME_LIBS=$pkg_cv_OT_DEP_GPGME_LIBS + OT_DEP_GPGME_CFLAGS=$pkg_cv_OT_DEP_GPGME_CFLAGS + OT_DEP_GPGME_LIBS=$pkg_cv_OT_DEP_GPGME_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - have_gpgme=yes + have_gpgme=yes fi +fi + # Extract the first word of "gpgrt-config", so it can be a program name with args. +set dummy gpgrt-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_GPGRT_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $GPGRT_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_GPGRT_CONFIG="$GPGRT_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_dummy="$prefix/bin:$PATH" +for as_dir in $as_dummy +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_GPGRT_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GPGRT_CONFIG" && ac_cv_path_GPGRT_CONFIG="no" + ;; +esac +fi +GPGRT_CONFIG=$ac_cv_path_GPGRT_CONFIG +if test -n "$GPGRT_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GPGRT_CONFIG" >&5 +printf "%s\n" "$GPGRT_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } fi + + if test "$GPGRT_CONFIG" != "no"; then + # Determine gpgrt_libdir + # + # Get the prefix of gpgrt-config assuming it's something like: + # /bin/gpgrt-config + gpgrt_prefix=${GPGRT_CONFIG%/*/*} + possible_libdir1=${gpgrt_prefix}/lib + # Determine by using system libdir-format with CC, it's like: + # Normal style: /usr/lib + # GNU cross style: /usr//lib + # Debian style: /usr/lib/ + # Fedora/openSUSE style: /usr/lib, /usr/lib32 or /usr/lib64 + # It is assumed that CC is specified to the one of host on cross build. + if libdir_candidates=$(${CC:-cc} -print-search-dirs | \ + sed -n -e "/^libraries/{s/libraries: =//;s/:/\\ +/g;p;}"); then + # From the output of -print-search-dirs, select valid pkgconfig dirs. + libdir_candidates=$(for dir in $libdir_candidates; do + if p=$(cd $dir 2>/dev/null && pwd); then + test -d "$p/pkgconfig" && echo $p; + fi + done) + + for possible_libdir0 in $libdir_candidates; do + # possible_libdir0: + # Fallback candidate, the one of system-installed (by $CC) + # (/usr//lib, /usr/lib/ or /usr/lib32) + # possible_libdir1: + # Another candidate, user-locally-installed + # (/lib) + # possible_libdir2 + # Most preferred + # (//lib, + # /lib/ or /lib32) + if test "${possible_libdir0##*/}" = "lib"; then + possible_prefix0=${possible_libdir0%/lib} + possible_prefix0_triplet=${possible_prefix0##*/} + if test -z "$possible_prefix0_triplet"; then + continue + fi + possible_libdir2=${gpgrt_prefix}/$possible_prefix0_triplet/lib + else + possible_prefix0=${possible_libdir0%%/lib*} + possible_libdir2=${gpgrt_prefix}${possible_libdir0#$possible_prefix0} + fi + if test -f ${possible_libdir2}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir2} + elif test -f ${possible_libdir1}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir1} + elif test -f ${possible_libdir0}/pkgconfig/gpg-error.pc; then + gpgrt_libdir=${possible_libdir0} + fi + if test -n "$gpgrt_libdir"; then break; fi + done + if test -z "$libdir_candidates"; then + # No valid pkgconfig dir in any of the system directories, fallback + gpgrt_libdir=${possible_libdir1} + fi + else + # When we cannot determine system libdir-format, use this: + gpgrt_libdir=${possible_libdir1} + fi + else + unset GPGRT_CONFIG + fi + + if test -n "$gpgrt_libdir"; then + GPGRT_CONFIG="$GPGRT_CONFIG --libdir=$gpgrt_libdir" + if $GPGRT_CONFIG gpg-error >/dev/null 2>&1; then + GPG_ERROR_CONFIG="$GPGRT_CONFIG gpg-error" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&5 +printf "%s\n" "$as_me: Use gpgrt-config with $gpgrt_libdir as gpg-error-config" >&6;} + gpg_error_config_version=`$GPG_ERROR_CONFIG --modversion` + else + unset GPGRT_CONFIG + fi + elif test "$GPG_ERROR_CONFIG" != "no"; then + gpg_error_config_version=`$GPG_ERROR_CONFIG --version` + unset GPGRT_CONFIG + fi + + # Check whether --with-gpgme-prefix was given. if test ${with_gpgme_prefix+y} then : @@ -16950,7 +17114,7 @@ printf "%s\n" "$as_me: WARNING: Ignoring \$SYSROOT as it is not an absolute path fi use_gpgrt_config="" - if test x"${GPGME_CONFIG}" = x -a x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then + if test x"$GPGRT_CONFIG" != x -a "$GPGRT_CONFIG" != "no"; then if $GPGRT_CONFIG gpgme --exists; then GPGME_CONFIG="$GPGRT_CONFIG gpgme" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Use gpgrt-config as gpgme-config" >&5 @@ -17026,8 +17190,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_GPGME" >&5 -printf %s "checking for OT_DEP_GPGME... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY" >&5 +printf %s "checking for gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY... " >&6; } if test -n "$OT_DEP_GPGME_CFLAGS"; then pkg_cv_OT_DEP_GPGME_CFLAGS="$OT_DEP_GPGME_CFLAGS" @@ -17067,7 +17231,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17076,16 +17240,17 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY" 2>&1` + OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY" 2>&1` else - OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY" 2>&1` + OT_DEP_GPGME_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpgme-pthread >= $LIBGPGME_PTHREAD_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_GPGME_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_GPGME_PKG_ERRORS" >&5 + - tmp=$LIBGPGME_PTHREAD_DEPENDENCY + tmp=$LIBGPGME_PTHREAD_DEPENDENCY if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` @@ -17098,35 +17263,37 @@ fi printf %s "checking for GPGME pthread - version >= $min_gpgme_version... " >&6; } ok=no if test "$GPGME_CONFIG" != "no" ; then - if `$GPGME_CONFIG --thread=pthread 2> /dev/null` ; then - req_major=`echo $min_gpgme_version | \ + req_major=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` - req_minor=`echo $min_gpgme_version | \ + req_minor=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` - req_micro=`echo $min_gpgme_version | \ + req_micro=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` - if test "$gpgme_version_major" -gt "$req_major"; then + if test "$gpgme_version_major" -gt "$req_major"; then ok=yes - else + else if test "$gpgme_version_major" -eq "$req_major"; then - if test "$gpgme_version_minor" -gt "$req_minor"; then - ok=yes - else - if test "$gpgme_version_minor" -eq "$req_minor"; then - if test "$gpgme_version_micro" -ge "$req_micro"; then - ok=yes - fi + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi fi - fi fi - fi fi fi if test $ok = yes; then # If we have a recent GPGME, we should also check that the # API is compatible. if test "$req_gpgme_api" -gt 0 ; then - tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test -z "$use_gpgrt_config"; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$GPGME_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi if test "$tmp" -gt 0 ; then if test "$req_gpgme_api" -ne "$tmp" ; then ok=no @@ -17135,8 +17302,8 @@ printf %s "checking for GPGME pthread - version >= $min_gpgme_version... " >&6; fi fi if test $ok = yes; then - GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --thread=pthread --cflags` - GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --thread=pthread --libs` + GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --libs` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } have_gpgme=yes @@ -17181,11 +17348,12 @@ printf "%s\n" "no" >&6; } elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - tmp=$LIBGPGME_PTHREAD_DEPENDENCY + + tmp=$LIBGPGME_PTHREAD_DEPENDENCY if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_gpgme_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` min_gpgme_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` @@ -17198,35 +17366,37 @@ printf "%s\n" "no" >&6; } printf %s "checking for GPGME pthread - version >= $min_gpgme_version... " >&6; } ok=no if test "$GPGME_CONFIG" != "no" ; then - if `$GPGME_CONFIG --thread=pthread 2> /dev/null` ; then - req_major=`echo $min_gpgme_version | \ + req_major=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` - req_minor=`echo $min_gpgme_version | \ + req_minor=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` - req_micro=`echo $min_gpgme_version | \ + req_micro=`echo $min_gpgme_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` - if test "$gpgme_version_major" -gt "$req_major"; then + if test "$gpgme_version_major" -gt "$req_major"; then ok=yes - else + else if test "$gpgme_version_major" -eq "$req_major"; then - if test "$gpgme_version_minor" -gt "$req_minor"; then - ok=yes - else - if test "$gpgme_version_minor" -eq "$req_minor"; then - if test "$gpgme_version_micro" -ge "$req_micro"; then - ok=yes - fi + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi fi - fi fi - fi fi fi if test $ok = yes; then # If we have a recent GPGME, we should also check that the # API is compatible. if test "$req_gpgme_api" -gt 0 ; then - tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + if test -z "$use_gpgrt_config"; then + tmp=`$GPGME_CONFIG --api-version 2>/dev/null || echo 0` + else + tmp=`$GPGME_CONFIG --variable=api_version 2>/dev/null || echo 0` + fi if test "$tmp" -gt 0 ; then if test "$req_gpgme_api" -ne "$tmp" ; then ok=no @@ -17235,8 +17405,8 @@ printf %s "checking for GPGME pthread - version >= $min_gpgme_version... " >&6; fi fi if test $ok = yes; then - GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --thread=pthread --cflags` - GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --thread=pthread --libs` + GPGME_PTHREAD_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_PTHREAD_LIBS=`$GPGME_CONFIG --libs` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } have_gpgme=yes @@ -17281,11 +17451,11 @@ printf "%s\n" "no" >&6; } else - OT_DEP_GPGME_CFLAGS=$pkg_cv_OT_DEP_GPGME_CFLAGS - OT_DEP_GPGME_LIBS=$pkg_cv_OT_DEP_GPGME_LIBS + OT_DEP_GPGME_CFLAGS=$pkg_cv_OT_DEP_GPGME_CFLAGS + OT_DEP_GPGME_LIBS=$pkg_cv_OT_DEP_GPGME_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - have_gpgme=yes + have_gpgme=yes fi if test x$have_gpgme = xno then : @@ -17296,8 +17466,8 @@ fi OSTREE_FEATURES="$OSTREE_FEATURES gpgme" pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_GPG_ERROR" >&5 -printf %s "checking for OT_DEP_GPG_ERROR... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gpg-error" >&5 +printf %s "checking for gpg-error... " >&6; } if test -n "$OT_DEP_GPG_ERROR_CFLAGS"; then pkg_cv_OT_DEP_GPG_ERROR_CFLAGS="$OT_DEP_GPG_ERROR_CFLAGS" @@ -17337,7 +17507,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17346,12 +17516,12 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_GPG_ERROR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpg-error" 2>&1` + OT_DEP_GPG_ERROR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gpg-error" 2>&1` else - OT_DEP_GPG_ERROR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpg-error" 2>&1` + OT_DEP_GPG_ERROR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gpg-error" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_GPG_ERROR_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_GPG_ERROR_PKG_ERRORS" >&5 # Extract the first word of "gpg-error-config", so it can be a program name with args. @@ -17404,7 +17574,7 @@ fi OT_DEP_GPG_ERROR_LIBS="$( $GPG_ERROR_CONFIG --libs )" elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } # Extract the first word of "gpg-error-config", so it can be a program name with args. @@ -17457,8 +17627,8 @@ fi OT_DEP_GPG_ERROR_LIBS="$( $GPG_ERROR_CONFIG --libs )" else - OT_DEP_GPG_ERROR_CFLAGS=$pkg_cv_OT_DEP_GPG_ERROR_CFLAGS - OT_DEP_GPG_ERROR_LIBS=$pkg_cv_OT_DEP_GPG_ERROR_LIBS + OT_DEP_GPG_ERROR_CFLAGS=$pkg_cv_OT_DEP_GPG_ERROR_CFLAGS + OT_DEP_GPG_ERROR_LIBS=$pkg_cv_OT_DEP_GPG_ERROR_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -17494,96 +17664,143 @@ else fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for MOUNT_ATTR_IDMAP" >&5 -printf %s "checking for MOUNT_ATTR_IDMAP... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - #include - #include +# Check whether --with-composefs was given. +if test ${with_composefs+y} +then : + withval=$with_composefs; : +else $as_nop + with_composefs=maybe +fi -int -main (void) -{ -int foo = MOUNT_ATTR_IDMAP; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO" +have_composefs=no +if test x$with_composefs != xno then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - have_mount_attr_idmap=yes -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for composefs" >&5 +printf %s "checking for composefs... " >&6; } + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"composefs\""; } >&5 + ($PKG_CONFIG --exists --print-errors "composefs") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + have_composefs=yes +else + have_composefs=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for new mount API (fsconfig)" >&5 -printf %s "checking for new mount API (fsconfig)... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_composefs" >&5 +printf "%s\n" "$have_composefs" >&6; } + if test x$have_composefs = xno && test x$with_composefs != xmaybe +then : - #include - int cmd = FSCONFIG_CMD_CREATE; + as_fn_error $? "composefs is enabled but could not be found" "$LINENO" 5 -_ACEOF -if ac_fn_c_try_compile "$LINENO" +fi + if test x$have_composefs = xyes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } -printf "%s\n" "#define HAVE_FSCONFIG_CMD_CREATE_SYS_MOUNT_H 1" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for composefs" >&5 +printf %s "checking for composefs... " >&6; } + +if test -n "$OT_DEP_COMPOSEFS_CFLAGS"; then + pkg_cv_OT_DEP_COMPOSEFS_CFLAGS="$OT_DEP_COMPOSEFS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"composefs\""; } >&5 + ($PKG_CONFIG --exists --print-errors "composefs") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OT_DEP_COMPOSEFS_CFLAGS=`$PKG_CONFIG --cflags "composefs" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OT_DEP_COMPOSEFS_LIBS"; then + pkg_cv_OT_DEP_COMPOSEFS_LIBS="$OT_DEP_COMPOSEFS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"composefs\""; } >&5 + ($PKG_CONFIG --exists --print-errors "composefs") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OT_DEP_COMPOSEFS_LIBS=`$PKG_CONFIG --libs "composefs" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + if test $_pkg_short_errors_supported = yes; then + OT_DEP_COMPOSEFS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "composefs" 2>&1` + else + OT_DEP_COMPOSEFS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "composefs" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_COMPOSEFS_PKG_ERRORS" >&5 - /* also make sure it doesn't conflict with since it is always used. */ - #include - #include - int cmd = FSCONFIG_CMD_CREATE; + as_fn_error $? "Package requirements (composefs) were not met: -_ACEOF -if ac_fn_c_try_compile "$LINENO" -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +$OT_DEP_COMPOSEFS_PKG_ERRORS -printf "%s\n" "#define HAVE_FSCONFIG_CMD_CREATE_LINUX_MOUNT_H 1" >>confdefs.h +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +Alternatively, you may set the environment variables OT_DEP_COMPOSEFS_CFLAGS +and OT_DEP_COMPOSEFS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. -composefs_default=yes -if test x"$have_mount_attr_idmap" != xyes; then - composefs_default=no -fi +Alternatively, you may set the environment variables OT_DEP_COMPOSEFS_CFLAGS +and OT_DEP_COMPOSEFS_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + OT_DEP_COMPOSEFS_CFLAGS=$pkg_cv_OT_DEP_COMPOSEFS_CFLAGS + OT_DEP_COMPOSEFS_LIBS=$pkg_cv_OT_DEP_COMPOSEFS_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } -# Check whether --with-composefs was given. -if test ${with_composefs+y} -then : - withval=$with_composefs; : -else $as_nop - with_composefs=$composefs_default fi + OSTREE_FEATURES="$OSTREE_FEATURES composefs"; +printf "%s\n" "#define HAVE_COMPOSEFS 1" >>confdefs.h -if test x$with_composefs != xno; then OSTREE_FEATURES="$OSTREE_FEATURES composefs"; -printf "%s\n" "#define HAVE_COMPOSEFS 1" >>confdefs.h +fi fi - if test $with_composefs != no; then + if test x$have_composefs = xyes; then USE_COMPOSEFS_TRUE= USE_COMPOSEFS_FALSE='#' else @@ -17610,8 +17827,8 @@ printf "%s\n" "#define HAVE_LIBSODIUM 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_LIBSODIUM" >&5 -printf %s "checking for OT_DEP_LIBSODIUM... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsodium >= $LIBSODIUM_DEPENDENCY" >&5 +printf %s "checking for libsodium >= $LIBSODIUM_DEPENDENCY... " >&6; } if test -n "$OT_DEP_LIBSODIUM_CFLAGS"; then pkg_cv_OT_DEP_LIBSODIUM_CFLAGS="$OT_DEP_LIBSODIUM_CFLAGS" @@ -17651,7 +17868,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -17660,24 +17877,24 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1` + OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1` else - OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1` + OT_DEP_LIBSODIUM_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsodium >= $LIBSODIUM_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_LIBSODIUM_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_LIBSODIUM_PKG_ERRORS" >&5 - have_libsodium=no + have_libsodium=no elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - have_libsodium=no + have_libsodium=no else - OT_DEP_LIBSODIUM_CFLAGS=$pkg_cv_OT_DEP_LIBSODIUM_CFLAGS - OT_DEP_LIBSODIUM_LIBS=$pkg_cv_OT_DEP_LIBSODIUM_LIBS + OT_DEP_LIBSODIUM_CFLAGS=$pkg_cv_OT_DEP_LIBSODIUM_CFLAGS + OT_DEP_LIBSODIUM_LIBS=$pkg_cv_OT_DEP_LIBSODIUM_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - have_libsodium=yes + have_libsodium=yes fi if test x$have_libsodium = xno then : @@ -17965,8 +18182,8 @@ printf "%s\n" "$enable_gtk_doc" >&6; } if test "x$PACKAGE_NAME" != "xglib"; then pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 -printf %s "checking for GTKDOC_DEPS... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" >&5 +printf %s "checking for glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0... " >&6; } if test -n "$GTKDOC_DEPS_CFLAGS"; then pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" @@ -18006,7 +18223,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18015,21 +18232,21 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` else - GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` + GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 - : + : elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - : + : else - GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS - GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS + GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS + GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -18262,8 +18479,8 @@ printf "%s\n" "#define HAVE_LIBARCHIVE 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_LIBARCHIVE" >&5 -printf %s "checking for OT_DEP_LIBARCHIVE... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LIBARCHIVE_DEPENDENCY" >&5 +printf %s "checking for $LIBARCHIVE_DEPENDENCY... " >&6; } if test -n "$OT_DEP_LIBARCHIVE_CFLAGS"; then pkg_cv_OT_DEP_LIBARCHIVE_CFLAGS="$OT_DEP_LIBARCHIVE_CFLAGS" @@ -18303,7 +18520,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18312,14 +18529,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_LIBARCHIVE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$LIBARCHIVE_DEPENDENCY" 2>&1` + OT_DEP_LIBARCHIVE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$LIBARCHIVE_DEPENDENCY" 2>&1` else - OT_DEP_LIBARCHIVE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$LIBARCHIVE_DEPENDENCY" 2>&1` + OT_DEP_LIBARCHIVE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$LIBARCHIVE_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_LIBARCHIVE_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_LIBARCHIVE_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($LIBARCHIVE_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($LIBARCHIVE_DEPENDENCY) were not met: $OT_DEP_LIBARCHIVE_PKG_ERRORS @@ -18330,9 +18547,9 @@ Alternatively, you may set the environment variables OT_DEP_LIBARCHIVE_CFLAGS and OT_DEP_LIBARCHIVE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -18345,8 +18562,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_LIBARCHIVE_CFLAGS=$pkg_cv_OT_DEP_LIBARCHIVE_CFLAGS - OT_DEP_LIBARCHIVE_LIBS=$pkg_cv_OT_DEP_LIBARCHIVE_LIBS + OT_DEP_LIBARCHIVE_CFLAGS=$pkg_cv_OT_DEP_LIBARCHIVE_CFLAGS + OT_DEP_LIBARCHIVE_LIBS=$pkg_cv_OT_DEP_LIBARCHIVE_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -18425,8 +18642,8 @@ printf "%s\n" "#define HAVE_SELINUX 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_SELINUX" >&5 -printf %s "checking for OT_DEP_SELINUX... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $SELINUX_DEPENDENCY" >&5 +printf %s "checking for $SELINUX_DEPENDENCY... " >&6; } if test -n "$OT_DEP_SELINUX_CFLAGS"; then pkg_cv_OT_DEP_SELINUX_CFLAGS="$OT_DEP_SELINUX_CFLAGS" @@ -18466,7 +18683,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18475,14 +18692,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_SELINUX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SELINUX_DEPENDENCY" 2>&1` + OT_DEP_SELINUX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$SELINUX_DEPENDENCY" 2>&1` else - OT_DEP_SELINUX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SELINUX_DEPENDENCY" 2>&1` + OT_DEP_SELINUX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$SELINUX_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_SELINUX_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_SELINUX_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($SELINUX_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($SELINUX_DEPENDENCY) were not met: $OT_DEP_SELINUX_PKG_ERRORS @@ -18493,9 +18710,9 @@ Alternatively, you may set the environment variables OT_DEP_SELINUX_CFLAGS and OT_DEP_SELINUX_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -18508,8 +18725,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_SELINUX_CFLAGS=$pkg_cv_OT_DEP_SELINUX_CFLAGS - OT_DEP_SELINUX_LIBS=$pkg_cv_OT_DEP_SELINUX_LIBS + OT_DEP_SELINUX_CFLAGS=$pkg_cv_OT_DEP_SELINUX_CFLAGS + OT_DEP_SELINUX_LIBS=$pkg_cv_OT_DEP_SELINUX_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -18600,8 +18817,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_CRYPTO" >&5 -printf %s "checking for OT_DEP_CRYPTO... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $OPENSSL_DEPENDENCY" >&5 +printf %s "checking for $OPENSSL_DEPENDENCY... " >&6; } if test -n "$OT_DEP_CRYPTO_CFLAGS"; then pkg_cv_OT_DEP_CRYPTO_CFLAGS="$OT_DEP_CRYPTO_CFLAGS" @@ -18641,7 +18858,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18650,14 +18867,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` else - OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($OPENSSL_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($OPENSSL_DEPENDENCY) were not met: $OT_DEP_CRYPTO_PKG_ERRORS @@ -18668,9 +18885,9 @@ Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -18683,8 +18900,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS - OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS + OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS + OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -18723,8 +18940,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_CRYPTO" >&5 -printf %s "checking for OT_DEP_CRYPTO... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $GNUTLS_DEPENDENCY" >&5 +printf %s "checking for $GNUTLS_DEPENDENCY... " >&6; } if test -n "$OT_DEP_CRYPTO_CFLAGS"; then pkg_cv_OT_DEP_CRYPTO_CFLAGS="$OT_DEP_CRYPTO_CFLAGS" @@ -18764,7 +18981,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18773,14 +18990,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` else - OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($GNUTLS_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($GNUTLS_DEPENDENCY) were not met: $OT_DEP_CRYPTO_PKG_ERRORS @@ -18791,9 +19008,9 @@ Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -18806,8 +19023,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS - OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS + OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS + OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -18873,8 +19090,8 @@ printf "%s\n" "#define HAVE_AVAHI 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_AVAHI" >&5 -printf %s "checking for OT_DEP_AVAHI... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $AVAHI_DEPENDENCY" >&5 +printf %s "checking for $AVAHI_DEPENDENCY... " >&6; } if test -n "$OT_DEP_AVAHI_CFLAGS"; then pkg_cv_OT_DEP_AVAHI_CFLAGS="$OT_DEP_AVAHI_CFLAGS" @@ -18914,7 +19131,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -18923,14 +19140,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$AVAHI_DEPENDENCY" 2>&1` + OT_DEP_AVAHI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$AVAHI_DEPENDENCY" 2>&1` else - OT_DEP_AVAHI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$AVAHI_DEPENDENCY" 2>&1` + OT_DEP_AVAHI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$AVAHI_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_AVAHI_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_AVAHI_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($AVAHI_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($AVAHI_DEPENDENCY) were not met: $OT_DEP_AVAHI_PKG_ERRORS @@ -18941,9 +19158,9 @@ Alternatively, you may set the environment variables OT_DEP_AVAHI_CFLAGS and OT_DEP_AVAHI_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -18956,8 +19173,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_AVAHI_CFLAGS=$pkg_cv_OT_DEP_AVAHI_CFLAGS - OT_DEP_AVAHI_LIBS=$pkg_cv_OT_DEP_AVAHI_LIBS + OT_DEP_AVAHI_CFLAGS=$pkg_cv_OT_DEP_AVAHI_CFLAGS + OT_DEP_AVAHI_LIBS=$pkg_cv_OT_DEP_AVAHI_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -19026,8 +19243,8 @@ printf "%s\n" "#define HAVE_LIBMOUNT 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_LIBMOUNT" >&5 -printf %s "checking for OT_DEP_LIBMOUNT... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LIBMOUNT_DEPENDENCY" >&5 +printf %s "checking for $LIBMOUNT_DEPENDENCY... " >&6; } if test -n "$OT_DEP_LIBMOUNT_CFLAGS"; then pkg_cv_OT_DEP_LIBMOUNT_CFLAGS="$OT_DEP_LIBMOUNT_CFLAGS" @@ -19067,7 +19284,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19076,14 +19293,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_LIBMOUNT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$LIBMOUNT_DEPENDENCY" 2>&1` + OT_DEP_LIBMOUNT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$LIBMOUNT_DEPENDENCY" 2>&1` else - OT_DEP_LIBMOUNT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$LIBMOUNT_DEPENDENCY" 2>&1` + OT_DEP_LIBMOUNT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$LIBMOUNT_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_LIBMOUNT_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_LIBMOUNT_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($LIBMOUNT_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($LIBMOUNT_DEPENDENCY) were not met: $OT_DEP_LIBMOUNT_PKG_ERRORS @@ -19094,9 +19311,9 @@ Alternatively, you may set the environment variables OT_DEP_LIBMOUNT_CFLAGS and OT_DEP_LIBMOUNT_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -19109,8 +19326,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_LIBMOUNT_CFLAGS=$pkg_cv_OT_DEP_LIBMOUNT_CFLAGS - OT_DEP_LIBMOUNT_LIBS=$pkg_cv_OT_DEP_LIBMOUNT_LIBS + OT_DEP_LIBMOUNT_CFLAGS=$pkg_cv_OT_DEP_LIBMOUNT_CFLAGS + OT_DEP_LIBMOUNT_LIBS=$pkg_cv_OT_DEP_LIBMOUNT_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -19160,8 +19377,8 @@ then : pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FUSE3" >&5 -printf %s "checking for FUSE3... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $FUSE3_DEPENDENCY" >&5 +printf %s "checking for $FUSE3_DEPENDENCY... " >&6; } if test -n "$FUSE3_CFLAGS"; then pkg_cv_FUSE3_CFLAGS="$FUSE3_CFLAGS" @@ -19201,7 +19418,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19210,17 +19427,17 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - FUSE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE3_DEPENDENCY" 2>&1` + FUSE3_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE3_DEPENDENCY" 2>&1` else - FUSE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE3_DEPENDENCY" 2>&1` + FUSE3_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE3_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$FUSE3_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$FUSE3_PKG_ERRORS" >&5 pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FUSE" >&5 -printf %s "checking for FUSE... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $FUSE_DEPENDENCY" >&5 +printf %s "checking for $FUSE_DEPENDENCY... " >&6; } if test -n "$FUSE_CFLAGS"; then pkg_cv_FUSE_CFLAGS="$FUSE_CFLAGS" @@ -19260,7 +19477,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19269,14 +19486,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - FUSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` + FUSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` else - FUSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` + FUSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$FUSE_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$FUSE_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($FUSE_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($FUSE_DEPENDENCY) were not met: $FUSE_PKG_ERRORS @@ -19287,9 +19504,9 @@ Alternatively, you may set the environment variables FUSE_CFLAGS and FUSE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -19302,8 +19519,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - FUSE_CFLAGS=$pkg_cv_FUSE_CFLAGS - FUSE_LIBS=$pkg_cv_FUSE_LIBS + FUSE_CFLAGS=$pkg_cv_FUSE_CFLAGS + FUSE_LIBS=$pkg_cv_FUSE_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -19313,12 +19530,12 @@ printf "%s\n" "yes" >&6; } fi elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for FUSE" >&5 -printf %s "checking for FUSE... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $FUSE_DEPENDENCY" >&5 +printf %s "checking for $FUSE_DEPENDENCY... " >&6; } if test -n "$FUSE_CFLAGS"; then pkg_cv_FUSE_CFLAGS="$FUSE_CFLAGS" @@ -19358,7 +19575,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19367,14 +19584,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - FUSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` + FUSE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` else - FUSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` + FUSE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$FUSE_DEPENDENCY" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$FUSE_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$FUSE_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements ($FUSE_DEPENDENCY) were not met: + as_fn_error $? "Package requirements ($FUSE_DEPENDENCY) were not met: $FUSE_PKG_ERRORS @@ -19385,9 +19602,9 @@ Alternatively, you may set the environment variables FUSE_CFLAGS and FUSE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -19400,8 +19617,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - FUSE_CFLAGS=$pkg_cv_FUSE_CFLAGS - FUSE_LIBS=$pkg_cv_FUSE_LIBS + FUSE_CFLAGS=$pkg_cv_FUSE_CFLAGS + FUSE_LIBS=$pkg_cv_FUSE_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -19411,8 +19628,8 @@ printf "%s\n" "yes" >&6; } fi else - FUSE3_CFLAGS=$pkg_cv_FUSE3_CFLAGS - FUSE3_LIBS=$pkg_cv_FUSE3_LIBS + FUSE3_CFLAGS=$pkg_cv_FUSE3_CFLAGS + FUSE3_LIBS=$pkg_cv_FUSE3_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -19530,8 +19747,8 @@ printf "%s\n" "#define HAVE_LIBSYSTEMD 1" >>confdefs.h pkg_failed=no -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBSYSTEMD" >&5 -printf %s "checking for LIBSYSTEMD... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5 +printf %s "checking for libsystemd... " >&6; } if test -n "$LIBSYSTEMD_CFLAGS"; then pkg_cv_LIBSYSTEMD_CFLAGS="$LIBSYSTEMD_CFLAGS" @@ -19571,7 +19788,7 @@ fi if test $pkg_failed = yes; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -19580,14 +19797,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1` + LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsystemd" 2>&1` else - LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1` + LIBSYSTEMD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsystemd" 2>&1` fi - # Put the nasty error message in config.log where it belongs - echo "$LIBSYSTEMD_PKG_ERRORS" >&5 + # Put the nasty error message in config.log where it belongs + echo "$LIBSYSTEMD_PKG_ERRORS" >&5 - as_fn_error $? "Package requirements (libsystemd) were not met: + as_fn_error $? "Package requirements (libsystemd) were not met: $LIBSYSTEMD_PKG_ERRORS @@ -19598,9 +19815,9 @@ Alternatively, you may set the environment variables LIBSYSTEMD_CFLAGS and LIBSYSTEMD_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full @@ -19613,8 +19830,8 @@ See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS - LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS + LIBSYSTEMD_CFLAGS=$pkg_cv_LIBSYSTEMD_CFLAGS + LIBSYSTEMD_LIBS=$pkg_cv_LIBSYSTEMD_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } @@ -20607,7 +20824,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 2023.7, which was +This file was extended by libostree $as_me 2024.6, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -20675,7 +20892,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libostree config.status 2023.7 +libostree config.status 2024.6 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" @@ -22385,6 +22602,8 @@ echo " introspection: $found_introspection rofiles-fuse: $enable_rofiles_fuse HTTP backend: $fetcher_backend + libsoup: $with_soup + libsoup3: $with_soup3 SELinux: $with_selinux fs-verity: $ac_cv_header_linux_fsverity_h cryptographic checksums: $with_crypto @@ -22403,7 +22622,7 @@ echo " dracut: $with_dracut mkinitcpio: $with_mkinitcpio Static compiler for ostree-prepare-root: $with_static_compiler - Composefs: $with_composefs" + Composefs: $have_composefs" if test x$with_builtin_grub2_mkconfig = xyes then : diff --git a/configure.ac b/configure.ac index a65d879..cea218f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.63]) dnl To perform a release, follow the instructions in `docs/CONTRIBUTING.md`. -m4_define([year_version], [2023]) -m4_define([release_version], [7]) +m4_define([year_version], [2024]) +m4_define([release_version], [6]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) is_release_build=yes @@ -85,7 +85,8 @@ LT_INIT([disable-static]) dnl We have an always-on feature now to signify the fix for dnl https://github.com/ostreedev/ostree/pull/2874/commits/de6fddc6adee09a93901243dc7074090828a1912 dnl "commit: fix ostree deployment on 64-bit inode fs" -OSTREE_FEATURES="inode64" +dnl initial-var signifies this version of ostree propagates /var +OSTREE_FEATURES="inode64 initial-var" AC_SUBST([OSTREE_FEATURES]) GLIB_TESTS @@ -155,17 +156,26 @@ AS_IF([test x$enable_http2 != xno ], [ SOUP3_DEPENDENCY="libsoup-3.0 >= 3.0.0" AC_ARG_WITH(soup3, AS_HELP_STRING([--with-soup3], [Use libsoup3 @<:@default=no@:>@]), - [], [with_soup3=no]) + [], [with_soup3=check]) AS_IF([test x$with_soup3 != xno], [ - PKG_CHECK_MODULES(OT_DEP_SOUP3, $SOUP3_DEPENDENCY) - with_soup3=yes - AC_DEFINE([HAVE_LIBSOUP3], 1, [Define if we have libsoup3]) - OSTREE_FEATURES="$OSTREE_FEATURES libsoup3" - with_soup_default=no - dnl soup3 always supports client certs - have_libsoup_client_certs=yes + AC_MSG_CHECKING([for $SOUP3_DEPENDENCY]) + PKG_CHECK_EXISTS($SOUP3_DEPENDENCY, have_soup3=yes, have_soup3=no) + AC_MSG_RESULT([$have_soup3]) + AS_IF([ test x$have_soup3 = xno && test x$with_soup3 != xcheck], [ + AC_MSG_ERROR([libsoup3 is enabled but could not be found]) + ]) + AS_IF([test x$have_soup3 = xyes], [ + with_soup3=yes + PKG_CHECK_MODULES(OT_DEP_SOUP3, $SOUP3_DEPENDENCY) + AC_DEFINE([HAVE_LIBSOUP3], 1, [Define if we have libsoup3]) + OSTREE_FEATURES="$OSTREE_FEATURES libsoup3" + dnl And disable libsoup2 + with_soup_default=no + dnl soup3 always supports client certs + have_libsoup_client_certs=yes + ], [with_soup3=no]) ], [with_soup_default=check]) -AM_CONDITIONAL(USE_LIBSOUP3, test x$with_soup3 != xno) +AM_CONDITIONAL(USE_LIBSOUP3, test x$with_soup3 = xyes) dnl When bumping the libsoup-2.4 dependency, remember to bump dnl SOUP_VERSION_MIN_REQUIRED and SOUP_VERSION_MAX_ALLOWED in @@ -274,50 +284,25 @@ AS_IF([test x$have_gpgme = xyes], ) AM_CONDITIONAL(USE_GPGME, test "x$have_gpgme" = xyes) -dnl composefs won't work at all without this -AC_MSG_CHECKING([for MOUNT_ATTR_IDMAP]) -AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([ - #include - #include - ],[int foo = MOUNT_ATTR_IDMAP;] - )], - [AC_MSG_RESULT(yes) - have_mount_attr_idmap=yes], - [AC_MSG_RESULT(no)]) -dnl These are needed by libcomposefs to use the new mount API optionally -AC_MSG_CHECKING([for new mount API (fsconfig)]) -AC_COMPILE_IFELSE( - [AC_LANG_SOURCE([[ - #include - int cmd = FSCONFIG_CMD_CREATE; - ]])], - [AC_MSG_RESULT(yes) - AC_DEFINE([HAVE_FSCONFIG_CMD_CREATE_SYS_MOUNT_H], 1, [Define if FSCONFIG_CMD_CREATE is available in sys/mount.h])], - [AC_MSG_RESULT(no)]) -AC_COMPILE_IFELSE( - [AC_LANG_SOURCE([[ - /* also make sure it doesn't conflict with since it is always used. */ - #include - #include - int cmd = FSCONFIG_CMD_CREATE; - ]])], - [AC_MSG_RESULT(yes) - AC_DEFINE([HAVE_FSCONFIG_CMD_CREATE_LINUX_MOUNT_H], 1, [Define if FSCONFIG_CMD_CREATE is available in linux/mount.h])], - [AC_MSG_RESULT(no)]) - -composefs_default=yes -if test x"$have_mount_attr_idmap" != xyes; then - composefs_default=no -fi AC_ARG_WITH(composefs, - AS_HELP_STRING([--with-composefs], [Support composefs]), - :, with_composefs=$composefs_default) - -if test x$with_composefs != xno; then OSTREE_FEATURES="$OSTREE_FEATURES composefs"; - AC_DEFINE([HAVE_COMPOSEFS], 1, [Define if we have libcomposefs]) -fi -AM_CONDITIONAL(USE_COMPOSEFS, test $with_composefs != no) + AS_HELP_STRING([--with-composefs], [Support composefs (default yes)]), + :, with_composefs=maybe) + +have_composefs=no +AS_IF([ test x$with_composefs != xno ], [ + AC_MSG_CHECKING([for composefs]) + PKG_CHECK_EXISTS(composefs, have_composefs=yes, have_composefs=no) + AC_MSG_RESULT([$have_composefs]) + AS_IF([ test x$have_composefs = xno && test x$with_composefs != xmaybe ], [ + AC_MSG_ERROR([composefs is enabled but could not be found]) + ]) + AS_IF([ test x$have_composefs = xyes], [ + PKG_CHECK_MODULES(OT_DEP_COMPOSEFS, [composefs]) + OSTREE_FEATURES="$OSTREE_FEATURES composefs"; + AC_DEFINE([HAVE_COMPOSEFS], 1, [Define if we have libcomposefs]) + ]) +]) +AM_CONDITIONAL(USE_COMPOSEFS, test x$have_composefs = xyes) LIBSODIUM_DEPENDENCY="1.0.14" AC_ARG_WITH(ed25519_libsodium, @@ -704,6 +689,8 @@ echo " introspection: $found_introspection rofiles-fuse: $enable_rofiles_fuse HTTP backend: $fetcher_backend + libsoup: $with_soup + libsoup3: $with_soup3 SELinux: $with_selinux fs-verity: $ac_cv_header_linux_fsverity_h cryptographic checksums: $with_crypto @@ -722,7 +709,7 @@ echo " dracut: $with_dracut mkinitcpio: $with_mkinitcpio Static compiler for ostree-prepare-root: $with_static_compiler - Composefs: $with_composefs" + Composefs: $have_composefs" AS_IF([test x$with_builtin_grub2_mkconfig = xyes], [ echo " builtin grub2-mkconfig (instead of system): $with_builtin_grub2_mkconfig" ], [ diff --git a/debian/changelog b/debian/changelog index c9bd88a..31e908c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,74 @@ +ostree (2024.6-1) unstable; urgency=medium + + * New upstream release + * d/rules: Disable libcomposefs support. + libcompose is not yet packaged in Debian (RFP: #1064457) and there + is no longer a vendored copy included in ostree. I am not able to + take responsibility for maintenance of libcompose, but I have no + objection to re-enabling the relevant libostree features if someone + else packages it. + + -- Simon McVittie Sat, 08 Jun 2024 16:06:43 +0100 + +ostree (2024.5-1) unstable; urgency=medium + + * New upstream release + + -- Simon McVittie Tue, 26 Mar 2024 16:15:22 +0000 + +ostree (2024.4-1) unstable; urgency=medium + + * New upstream release + * Drop non-Debian-specific patches, applied upstream + + -- Simon McVittie Thu, 07 Mar 2024 10:54:27 +0000 + +ostree (2024.3-1) unstable; urgency=medium + + * New upstream release + * d/p/tests-Generalize-has_gpgme-has_sign_ed25519-into-has_ostr.patch, + d/p/tests-Use-skip_without_ostree_feature-to-detect-libarchiv.patch, + d/p/test-admin-deploy-var-Don-t-rely-on-OSTREE_FEATURES.patch: + Add proposed patches to fix an autopkgtest failure + + -- Simon McVittie Mon, 19 Feb 2024 21:02:32 +0000 + +ostree (2024.2-1) unstable; urgency=medium + + * New upstream release + * Re-enable composefs. + We can't run its unit tests on a Debian 12 kernel with /var/tmp on + tmpfs, but they do pass on a sid kernel or if /var/tmp is disk-backed. + * Build-depend on dh-sequence-gir instead of using --with + * Update Lintian overrides for ostree-boot + + -- Simon McVittie Sun, 11 Feb 2024 14:42:35 +0000 + +ostree (2024.1-1) unstable; urgency=medium + + * New upstream release + * Package ostree-state-overlay@.service in ostree-boot + + -- Simon McVittie Wed, 24 Jan 2024 10:21:50 +0000 + +ostree (2023.8-2) unstable; urgency=medium + + * d/control, d/rules: Enable cross-compilation. + When cross-compiling, this requires a version of gobject-introspection + that is currently only available in experimental. When not + cross-compiling, the version in testing is sufficient. + + -- Simon McVittie Sun, 31 Dec 2023 15:34:37 +0000 + +ostree (2023.8-1) unstable; urgency=medium + + * New upstream release + * d/libostree-1-1.symbols: Update + * d/p/bootloader-zipl-No-op-if-run-as-non-root.patch: + Drop patch, applied upstream + + -- Simon McVittie Fri, 08 Dec 2023 10:35:12 +0000 + ostree (2023.7-3) unstable; urgency=medium * Remove version constraints unnecessary since bullseye diff --git a/debian/control b/debian/control index 86523a9..f87a2fa 100644 --- a/debian/control +++ b/debian/control @@ -16,14 +16,17 @@ Build-Depends: cpio, debhelper (>= 13.11.6~), debhelper-compat (= 13), + dh-sequence-gir, docbook-xml , docbook-xsl , libext2fs-dev, elfutils, - fuse3, - gjs [!alpha !hppa !ia64 !m68k !sh4 !sparc64 !x32], + fuse3:native, + gir1.2-gio-2.0-dev, + gjs:native [!alpha !hppa !ia64 !m68k !sh4 !sparc64 !x32], gnupg , gobject-introspection, + gobject-introspection (>= 1.78.1-7~) , gtk-doc-tools , libarchive-dev, libattr1-dev, @@ -32,7 +35,6 @@ Build-Depends: libcap-dev, libcurl4-gnutls-dev | libcurl-dev, libfuse3-dev, - libgirepository1.0-dev, libglib2.0-dev, libgpgme-dev, liblzma-dev, diff --git a/debian/libostree-1-1.symbols b/debian/libostree-1-1.symbols index 8a81cf3..3cd1d62 100644 --- a/debian/libostree-1-1.symbols +++ b/debian/libostree-1-1.symbols @@ -47,6 +47,7 @@ libostree-1.so.1 libostree-1-1 #MINVER# LIBOSTREE_2022.7@LIBOSTREE_2022.7 2022.7 LIBOSTREE_2023.1@LIBOSTREE_2023.1 2023.1 LIBOSTREE_2023.4@LIBOSTREE_2023.4 2023.5 + LIBOSTREE_2023.8@LIBOSTREE_2023.8 2023.8 ostree_async_progress_copy_state@LIBOSTREE_2019.6 2019.6 ostree_async_progress_finish@LIBOSTREE_2016.3 2016.4 ostree_async_progress_get@LIBOSTREE_2017.6 2017.6 @@ -135,6 +136,7 @@ libostree-1.so.1 libostree-1-1 #MINVER# ostree_deployment_get_type@LIBOSTREE_2016.3 2016.4 ostree_deployment_get_unlocked@LIBOSTREE_2016.4 2016.4 ostree_deployment_hash@LIBOSTREE_2016.3 2016.4 + ostree_deployment_is_finalization_locked@LIBOSTREE_2023.8 2023.8 ostree_deployment_is_pinned@LIBOSTREE_2018.3 2018.3 ostree_deployment_is_staged@LIBOSTREE_2018.5 2018.5 ostree_deployment_new@LIBOSTREE_2016.3 2016.4 @@ -451,6 +453,7 @@ libostree-1.so.1 libostree-1-1 #MINVER# ostree_sign_set_pk@LIBOSTREE_2020.4 2020.4 ostree_sign_set_sk@LIBOSTREE_2020.4 2020.4 ostree_sign_summary@LIBOSTREE_2020.4 2020.4 + ostree_sysroot_change_finalization@LIBOSTREE_2023.8 2023.8 ostree_sysroot_cleanup@LIBOSTREE_2016.3 2016.4 ostree_sysroot_cleanup_prune_repo@LIBOSTREE_2018.6 2018.6 ostree_sysroot_deploy_tree@LIBOSTREE_2016.3 2016.4 @@ -498,6 +501,7 @@ libostree-1.so.1 libostree-1-1 #MINVER# ostree_sysroot_try_lock@LIBOSTREE_2016.3 2016.4 ostree_sysroot_unload@LIBOSTREE_2016.3 2016.4 ostree_sysroot_unlock@LIBOSTREE_2016.3 2016.4 + ostree_sysroot_update_post_copy@LIBOSTREE_2023.8 2023.8 ostree_sysroot_upgrader_check_timestamps@LIBOSTREE_2016.3 2016.4 ostree_sysroot_upgrader_deploy@LIBOSTREE_2016.3 2016.4 ostree_sysroot_upgrader_dup_origin@LIBOSTREE_2016.3 2016.4 diff --git a/debian/ostree-boot.install b/debian/ostree-boot.install index 3dcc5ba..1652360 100644 --- a/debian/ostree-boot.install +++ b/debian/ostree-boot.install @@ -10,5 +10,6 @@ usr/lib/systemd/system/ostree-finalize-staged.path usr/lib/systemd/system/ostree-finalize-staged.service usr/lib/systemd/system/ostree-prepare-root.service usr/lib/systemd/system/ostree-remount.service +usr/lib/systemd/system/ostree-state-overlay@.service usr/lib/tmpfiles.d/ostree-tmpfiles.conf usr/libexec/libostree/grub2-15_ostree diff --git a/debian/ostree-boot.lintian-overrides b/debian/ostree-boot.lintian-overrides index f3bbc9f..81b1717 100644 --- a/debian/ostree-boot.lintian-overrides +++ b/debian/ostree-boot.lintian-overrides @@ -1,6 +1,8 @@ -# specific boot ordering requirements unlikely to be satisfiable in sysv-rc -ostree-boot: package-supports-alternative-init-but-no-init.d-script * # statically Wanted by another unit ostree-boot: systemd-service-file-missing-install-key [*/systemd/system/ostree-finalize-staged-hold.service] # ostree-remount genuinely does need to be run that early ostree-boot: systemd-service-file-refers-to-unusual-wantedby-target local-fs.target [*/systemd/system/ostree-remount.service] +# ostree-state-overlay also does need to be run that early +ostree-boot: systemd-service-file-refers-to-unusual-wantedby-target local-fs.target [*/systemd/system/ostree-state-overlay@.service] +# documents an instanced systemd service, not a daemon as such +ostree-boot: spare-manual-page [usr/share/man/man8/ostree-state-overlay@.service.8.gz] diff --git a/debian/ostree-boot.manpages b/debian/ostree-boot.manpages new file mode 100644 index 0000000..a3e2278 --- /dev/null +++ b/debian/ostree-boot.manpages @@ -0,0 +1 @@ +usr/share/man/man8/* diff --git a/debian/ostree.manpages b/debian/ostree.manpages index 918f873..e57ae57 100644 --- a/debian/ostree.manpages +++ b/debian/ostree.manpages @@ -1 +1,2 @@ -usr/share/man/man?/* +usr/share/man/man1/* +usr/share/man/man5/* diff --git a/debian/patches/bootloader-zipl-No-op-if-run-as-non-root.patch b/debian/patches/bootloader-zipl-No-op-if-run-as-non-root.patch deleted file mode 100644 index d2dd935..0000000 --- a/debian/patches/bootloader-zipl-No-op-if-run-as-non-root.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Colin Walters -Date: Tue, 24 Oct 2023 10:40:51 -0400 -Subject: bootloader/zipl: No-op if run as non-root - -Not the most elegant fix but should get the job done. - -Bug: https://github.com/ostreedev/ostree/issues/3084 -Origin: upstream, 2023.8, commit:75c7e51a8bedb5edeadb9f54e84ccfff2adcc755 ---- - src/libostree/ostree-bootloader-zipl.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/libostree/ostree-bootloader-zipl.c b/src/libostree/ostree-bootloader-zipl.c -index c0a2a14..4579a89 100644 ---- a/src/libostree/ostree-bootloader-zipl.c -+++ b/src/libostree/ostree-bootloader-zipl.c -@@ -381,6 +381,12 @@ _ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, int bootver - { - OstreeBootloaderZipl *self = OSTREE_BOOTLOADER_ZIPL (bootloader); - -+ // This can happen in a unit testing environment; at some point what we want to do here -+ // is move all of the zipl logic to a systemd unit instead that's keyed of -+ // ostree-finalize-staged.service. -+ if (getuid () != 0) -+ return TRUE; -+ - /* Note that unlike the grub2-mkconfig backend, we make no attempt to - * chroot(). - */ diff --git a/debian/patches/debian/Skip-test-pull-repeated-during-CI.patch b/debian/patches/debian/Skip-test-pull-repeated-during-CI.patch index 82a65aa..24a1490 100644 --- a/debian/patches/debian/Skip-test-pull-repeated-during-CI.patch +++ b/debian/patches/debian/Skip-test-pull-repeated-during-CI.patch @@ -18,7 +18,7 @@ Signed-off-by: Simon McVittie 1 file changed, 4 insertions(+) diff --git a/tests/test-pull-repeated.sh b/tests/test-pull-repeated.sh -index 7f724c9..d10799b 100755 +index b3e0074..0c77546 100755 --- a/tests/test-pull-repeated.sh +++ b/tests/test-pull-repeated.sh @@ -21,6 +21,10 @@ set -euo pipefail @@ -30,5 +30,5 @@ index 7f724c9..d10799b 100755 +fi + COMMIT_SIGN="" - if has_gpgme; then + if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" diff --git a/debian/patches/series b/debian/patches/series index f5038c4..78a4e05 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,4 +1,3 @@ -bootloader-zipl-No-op-if-run-as-non-root.patch debian/Skip-test-pull-repeated-during-CI.patch debian/test-sysroot-Skip-on-s390x-by-default.patch debian/Skip-test-admin-deploy-uboot.sh-on-s390x.patch diff --git a/debian/rules b/debian/rules index 1b79603..24ec899 100755 --- a/debian/rules +++ b/debian/rules @@ -5,10 +5,14 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all binaries := $(shell dh_listpackages) %: - dh $@ --with=gir + dh $@ override_dh_autoreconf: - env NOCONFIGURE=1 dh_autoreconf ./autogen.sh + mkdir -p debian/tmp-path +ifneq (,$(filter nodoc,$(DEB_BUILD_PROFILES))) + ln -fns /bin/true debian/tmp-path/gtkdocize +endif + env NOCONFIGURE=1 PATH=$(CURDIR)/debian/tmp-path:$(PATH) dh_autoreconf ./autogen.sh configure_options = \ --enable-installed-tests \ @@ -48,6 +52,12 @@ endif override_dh_auto_configure: dh_auto_configure -- $(configure_options) +override_dh_auto_build: + # The upstream build system overrides this to gcc as a way to avoid + # passing unsupported options to clang, but that's wrong for + # cross-builds + dh_auto_build -- INTROSPECTION_SCANNER_ENV="CC=$(DEB_HOST_GNU_TYPE)-gcc" + override_dh_auto_test-arch: ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) chmod +x tests/test-pull-bareuseronly.sh diff --git a/gtk-doc.make b/gtk-doc.make index c673175..fb2e7e2 100644 --- a/gtk-doc.make +++ b/gtk-doc.make @@ -136,7 +136,7 @@ scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ - gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ @@ -198,13 +198,13 @@ GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references"; html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ - gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ - gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\--path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ @@ -227,7 +227,7 @@ GTK_DOC_V_PDF_0=@echo " DOC Building PDF"; pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ - gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ + gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\--verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ @@ -236,7 +236,7 @@ pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_cont if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ - echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ + echo $$mkpdf_options | grep >/dev/null "\--imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ @@ -250,10 +250,10 @@ pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_cont clean-local: @rm -f *~ *.bak @rm -rf .libs - @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ + @if echo $(SCAN_OPTIONS) | grep -q "\--rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi - @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ + @if echo $(SCAN_OPTIONS) | grep -q "\--rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi diff --git a/libglnx/glnx-xattrs.c b/libglnx/glnx-xattrs.c index d0e6ab3..84fd609 100644 --- a/libglnx/glnx-xattrs.c +++ b/libglnx/glnx-xattrs.c @@ -437,7 +437,7 @@ glnx_lsetxattrat (int dfd, char pathbuf[PATH_MAX]; snprintf (pathbuf, sizeof (pathbuf), "/proc/self/fd/%d/%s", dfd, subpath); - if (TEMP_FAILURE_RETRY (lsetxattr (subpath, attribute, value, len, flags)) < 0) + if (TEMP_FAILURE_RETRY (lsetxattr (pathbuf, attribute, value, len, flags)) < 0) return glnx_throw_errno_prefix (error, "lsetxattr(%s)", attribute); return TRUE; diff --git a/man/index.xml b/man/index.xml index 9f52cf7..63ae6e5 100644 --- a/man/index.xml +++ b/man/index.xml @@ -56,6 +56,10 @@ License along with this library. If not, see . ostree-admin-pin1 + + ostree-admin-post-copy1 + + ostree-admin-set-origin1 diff --git a/man/ostree-admin-deploy.xml b/man/ostree-admin-deploy.xml index 8be3390..5ad71ca 100644 --- a/man/ostree-admin-deploy.xml +++ b/man/ostree-admin-deploy.xml @@ -121,6 +121,16 @@ License along with this library. If not, see . + + + + + The deployment will not be "finalized" by default on shutdown; to later + queue it, use ostree admin lock-finalization --unlock. + + + + diff --git a/man/ostree-admin-init-fs.xml b/man/ostree-admin-init-fs.xml index 50e6d44..e06d222 100644 --- a/man/ostree-admin-init-fs.xml +++ b/man/ostree-admin-init-fs.xml @@ -57,17 +57,56 @@ License along with this library. If not, see . Description - Initialize an empty physical root filesystem in the designated PATH, with normal toplevels and correct permissions for each directory. Primarily useful for operating system installers. + Initialize an empty physical root filesystem in the designated PATH, with normal toplevels and correct permissions for each directory. + Primarily useful for operating system installers. + + + Options + + + + + + Equivalent to --epoch=1. + + + + + + + This accepts an integer value in the range [0-1], inclusive. The default is zero + for compatibility. + + + When set to 1, the command will skip adding a number of toplevel "API filesystems" + such as /proc + to the toplevel of the physical root. These should be unnecessary, as they + should only be mounted in the final deployment root. The main exception + is /boot, which may need to be mounted in some setups + before the target root. + + + Epoch 2 is the same as 1, except that the toplevel ostree + directory is mode 0700, denying access from unprivileged code. This + is a new recommended best practice as it avoids access to old configuration + files in /etc in previous deployments, as well as + potentially old setuid binaries in /ostree/repo. + + + + + + Example $ mkdir /example - $ ostree admin init-fs /example + $ ostree admin init-fs --epoch=1 /example $ ls /example - boot   dev   home   ostree   proc   root   run   sys   tmp + boot   diff --git a/man/ostree-admin-lock-finalization.xml b/man/ostree-admin-lock-finalization.xml new file mode 100644 index 0000000..ac469b7 --- /dev/null +++ b/man/ostree-admin-lock-finalization.xml @@ -0,0 +1,93 @@ + + + + + + + + + ostree admin lock-finalization + OSTree + + + + Developer + Colin + Walters + walters@verbum.org + + + + + + ostree admin lock-finalization + 1 + + + + ostree-admin-lock-finalization + Change whether staged deployment will be queued for next boot + + + + + ostree admin lock-finalization OPTIONS + + + + + Description + + + This command requires a staged deployment. By default, this command ensures the deployment + will be set into a "finalization locked" state, which means it will not be queued for the next boot by default. + + + This is the same as the --lock-finalization argument for ostree admin deploy, + which is the recommended way to use this feature in a race-free way. + + + However more commonly, one will use the --unlock argument for this command to later unlock + a deployment which was finalization locked. + + + + + Options + + + + ="PATH" + + + Path to the system to use rather than the current one. + + + + , + + + Unlock the deployment finalization state. + + + + + diff --git a/man/ostree-admin-pin.xml b/man/ostree-admin-pin.xml index ba3aa4a..78edde4 100644 --- a/man/ostree-admin-pin.xml +++ b/man/ostree-admin-pin.xml @@ -58,8 +58,10 @@ License along with this library. If not, see . Ensures the deployment at INDEX, will not be garbage - collected by default. This is termed "pinning". If the + collected by default. This is termed "pinning". If the -u option is provided, undoes a pinning operation. + INDEX can be >= 0 or one of booted, pending or + rollback strings. diff --git a/man/ostree-admin-post-copy.xml b/man/ostree-admin-post-copy.xml new file mode 100644 index 0000000..980e7cd --- /dev/null +++ b/man/ostree-admin-post-copy.xml @@ -0,0 +1,79 @@ + + + + + + + + + ostree admin post-copy + OSTree + + + + Developer + Colin + Walters + walters@verbum.org + + + + + + ostree admin post-copy + 1 + + + + ostree-admin-post-copy + Fix up sysroot after a (file based) copy + + + + + ostree admin post-copy OPTIONS + + + + + Description + + + Applies any fixes to a sysroot that are needed after having copyed it file by file. + This includes enabling fs-verity to any files that lack it, which can happen if + you copy a file. + + + + + Options + + + + ="PATH" + + + Path to the system to use rather than the current one. + + + + + diff --git a/man/ostree-admin-status.xml b/man/ostree-admin-status.xml index dde099b..aefa14d 100644 --- a/man/ostree-admin-status.xml +++ b/man/ostree-admin-status.xml @@ -61,6 +61,65 @@ License along with this library. If not, see . + + Options + + + + ="PATH" + + + Create a new OSTree sysroot at PATH + + + + + + + + Print the commit verification status + + + + + + + + Skip signatures in output + + + + + + + + Output the string default if the default deployment + is the booted one, not-default if we are booted in + a non-default deployment (e.g. the user interactively chose a + different entry in the bootloader menu, or the bootloader rolled back + automatically, etc.). If we are not in a booted OSTree system, an + error is returned. + + + + + + + + Print debug information during command processing + + + + + + + + Print version information and exit + + + + + Example $ ostree admin status diff --git a/man/ostree-admin.xml b/man/ostree-admin.xml index 85f4347..ba18859 100644 --- a/man/ostree-admin.xml +++ b/man/ostree-admin.xml @@ -72,6 +72,7 @@ License along with this library. If not, see . instutil os-init pin + post-copy set-origin status switch diff --git a/man/ostree-prepare-root.xml b/man/ostree-prepare-root.xml index 03bf022..9117c34 100644 --- a/man/ostree-prepare-root.xml +++ b/man/ostree-prepare-root.xml @@ -85,10 +85,10 @@ License along with this library. If not, see . - A read-only bind mount is created over /sysroot/usr. The immutable bit is set on the deployment + A read-only bind mount is created over /sysroot/usr. The immutable bit (see chattr(1)) is set on the deployment root, so this provides basic protection for filesystem mutation. If the sysroot.readonly - option is enabled, instead a writable bind mount for /sysroot/etc, and everything else - is mounted read-only. + option is enabled, then /sysroot/sysroot is mounted read-only to provide further protection and a writable bind mount for + /sysroot/etc is created. @@ -111,12 +111,30 @@ License along with this library. If not, see . sysroot.readonly - A boolean value; the default is false. If this is set to true, then the /sysroot mount point is mounted read-only. + A boolean value; the default is false unless composefs is enabled. If this is set to true, then the /sysroot mount point is mounted read-only. etc.transient A boolean value; the default is false. If this is set to true, then the /etc mount point is mounted transiently i.e. a non-persistent location. + + root.transient + A boolean value; the default is false. + If this is set to true, then the / filesystem will be a writable overlayfs, + with the upper directory being a hidden directory (in the underlying system root filesystem) that will persist across reboots by default. + However, changes will be discarded on OS updates! + + + Enabling this option can be very useful for cases such as packages (dpkg/rpm/etc) that write content into /opt, + particularly where they expect the target to be writable at runtime. To make that work, ensure that your /opt + directory is *not* a symlink to /var/opt, but is just an empty directory. + + + Note the /usr mount point remains read-only by default. This option is independent of etc.transient and sysroot.readonly; + it is supported for example to have root.transient=true but etc.transient=false in which case changes to /etc continue + to persist across updates, with the default OSTree 3-way merge applied. + + composefs.enabled This can be yes, no. maybe or diff --git a/man/ostree-state-overlay@.service.xml b/man/ostree-state-overlay@.service.xml new file mode 100644 index 0000000..a527955 --- /dev/null +++ b/man/ostree-state-overlay@.service.xml @@ -0,0 +1,107 @@ + + + + + + + + + ostree-state-overlay + ostree + + + + Developer + Jonathan + Lebon + jonathan@jlebon.com + + + + + + ostree-state-overlay + 8 + + + + ostree-state-overlay@.service + Set up state overlays + + + + ostree-state-overlay@.service + + + + Experimental + + Note this feature is currently considered + experimental. It may not work correctly and some of its + semantics may be subject to change. Positive or negative feedback are both + welcome and may be provided at + . If using + the feature via rpm-ostree, feedback may also be provided at + . + + + + + Description + + In some cases, it's useful to be able to have a directory as part of the + OSTree commit yet still have this directory be writable client-side. One + example is software that ships in /opt. + /opt is its own vendor-namespaced alternate file + hierarchy which may contain both code and state. With state overlays, it's + possible to have the code part baked in the OSTree, but still allowing the + directory to be writable so that state can be kept there. + + + + Since it's writable, nothing prevents sufficiently privileged code to + modify or delete content that comes from the OSTree commit. This is in + sharp contrast with content in /usr, and more + closely matches a package manager-based distro. + + + + Crucially, this state is automatically rebased during upgrades (or more + generally, anytime a different OSTree commit is booted). The semantics + of the rebase are as follows: any state file or directory that modified + OSTree content is deleted, otherwise it is kept and merged onto the new + base content (using overlayfs). This mostly matches the semantics of a + package manager. + + + + To enable this feature, simply instantiate the unit template, using the + target path (in escaped systemd path notation) as the instance name. For + example, to enable it on /opt: + + + + $ systemctl enable --now ostree-state-overlay@opt.service + + + + + diff --git a/man/ostree.repo-config.xml b/man/ostree.repo-config.xml index c2a9a8c..181d7ba 100644 --- a/man/ostree.repo-config.xml +++ b/man/ostree.repo-config.xml @@ -378,6 +378,15 @@ License along with this library. If not, see . + + readonly + A boolean value. If this is set to true, then the + /sysroot mount point is mounted read-only. This is configured a + legacy repository configuration and the equivalent option in ostree/prepare-root.conf + should be used instead - see ostree-prepare-root1. + + + bootloader Configure the bootloader that OSTree uses when @@ -409,7 +418,7 @@ License along with this library. If not, see . bls-append-except-default - A semicolon seperated string list of key-value pairs. For example: + A semicolon separated string list of key-value pairs. For example: bls-append-except-default=key1=value1;key2=value2. These key-value pairs will be injected into the generated BLS fragments of the non-default deployments. In other words, the BLS fragment of the default deployment will be unaffected by diff --git a/src/boot/grub2/grub2-15_ostree b/src/boot/grub2/grub2-15_ostree index ecd618c..f423561 100644 --- a/src/boot/grub2/grub2-15_ostree +++ b/src/boot/grub2/grub2-15_ostree @@ -1,5 +1,5 @@ #!/bin/sh -# +# # Copyright (C) 2014 Colin Walters # # This program is free software: you can redistribute it and/or modify @@ -24,6 +24,12 @@ if ! test -d /ostree/repo; then exit 0 fi +# Gracefully exit if we can not find the grub2 'default' configuration as it is +# the case on new installations with bootupd where it is not needed. +if ! test -f /etc/default/grub; then + exit 0 +fi + # Gracefully exit if the grub2 configuration has BLS enabled, # and the installed version has support for the blscfg module. # Since there is no need to create menu entries for that case. diff --git a/src/boot/ostree-boot-complete.service b/src/boot/ostree-boot-complete.service index 5c09fdc..98ae3d1 100644 --- a/src/boot/ostree-boot-complete.service +++ b/src/boot/ostree-boot-complete.service @@ -16,10 +16,14 @@ [Unit] Description=OSTree Complete Boot Documentation=man:ostree(1) +ConditionKernelCommandLine=ostree # For now, this is the only condition on which we start, but it's # marked as a triggering condition in case in the future we want # to do something else. ConditionPathExists=|/boot/ostree/finalize-failure.stamp +# We start early +DefaultDependencies=no +After=sysinit.target RequiresMountsFor=/boot # Ensure that we propagate the failure into the current boot before # any further finalization attempts. diff --git a/src/boot/ostree-prepare-root.service b/src/boot/ostree-prepare-root.service index 510d866..4c2b6ba 100644 --- a/src/boot/ostree-prepare-root.service +++ b/src/boot/ostree-prepare-root.service @@ -19,11 +19,13 @@ Documentation=man:ostree(1) DefaultDependencies=no ConditionKernelCommandLine=ostree ConditionPathExists=/etc/initrd-release -OnFailure=emergency.target After=sysroot.mount Requires=sysroot.mount Before=initrd-root-fs.target +OnFailure=emergency.target +OnFailureJobMode=isolate + [Service] Type=oneshot ExecStart=/usr/lib/ostree/ostree-prepare-root /sysroot diff --git a/src/boot/ostree-state-overlay@.service b/src/boot/ostree-state-overlay@.service new file mode 100644 index 0000000..dc8aeac --- /dev/null +++ b/src/boot/ostree-state-overlay@.service @@ -0,0 +1,36 @@ +# Copyright (C) 2023 Red Hat Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see . + +[Unit] +Description=OSTree State Overlay On /%I +Documentation=man:ostree(1) +DefaultDependencies=no +ConditionKernelCommandLine=ostree +# run after /var is setup since that's where the upperdir is stored +# and after boot.mount so we can load the sysroot +After=var.mount boot.mount +# but before local-fs.target, which we consider ourselves a part of +Before=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/bin/ostree admin state-overlay %i /%I +StandardInput=null +StandardOutput=journal +StandardError=journal+console + +[Install] +WantedBy=local-fs.target diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 9168db7..6640e11 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -24,8 +24,8 @@ * edit this other than to update the year. This is just a copy/paste * source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION * with whatever the next version with new symbols will be. -LIBOSTREE_2021.$NEWVERSION { +LIBOSTREE_$YEAR.$NEWVERSION { global: someostree_symbol_deleteme; -} LIBOSTREE_2021.$LASTSTABLE; +} LIBOSTREE_$YEAR.$LASTSTABLE; */ diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index 06cfc15..2729d51 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -706,6 +706,13 @@ global: ostree_repo_commit_add_composefs_metadata; } LIBOSTREE_2023.1; +LIBOSTREE_2023.8 { +global: + ostree_sysroot_update_post_copy; + ostree_deployment_is_finalization_locked; + ostree_sysroot_change_finalization; +} LIBOSTREE_2023.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-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index e1ee786..cbe7605 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -26,6 +26,11 @@ #include +// Written by bootupd +#define BOOTUPD_CONFIG "boot/bootupd-state.json" +// Horrible hack, to avoid including a JSON parser we just grep for this +#define BOOTUPD_CONFIG_STATIC_JSON_FRAGMENT "\"static-configs\"" + /* Maintain backwards compatibility with legacy GRUB * installations that might rely on the -16 suffix * for real-mode booting. @@ -75,6 +80,22 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader, gboolean *out_is_a { OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader); + g_autoptr (GFile) bootupd_config + = g_file_resolve_relative_path (self->sysroot->path, BOOTUPD_CONFIG); + if (g_file_query_exists (bootupd_config, NULL)) + { + g_autofree char *bootupd_config_contents = NULL; + if (!g_file_load_contents (bootupd_config, cancellable, &bootupd_config_contents, NULL, NULL, + error)) + return glnx_prefix_error (error, "Failed to read bootupd config"); + if (strstr (bootupd_config_contents, BOOTUPD_CONFIG_STATIC_JSON_FRAGMENT) != NULL) + { + g_debug ("Found static bootupd config"); + *out_is_active = FALSE; + return TRUE; + } + } + /* Look for the BIOS path first */ if (g_file_query_exists (self->config_path_bios_1, NULL) || g_file_query_exists (self->config_path_bios_2, NULL)) diff --git a/src/libostree/ostree-bootloader-syslinux.c b/src/libostree/ostree-bootloader-syslinux.c index 1e71ef2..dca0a00 100644 --- a/src/libostree/ostree-bootloader-syslinux.c +++ b/src/libostree/ostree-bootloader-syslinux.c @@ -18,6 +18,7 @@ #include "config.h" #include "ostree-bootloader-syslinux.h" +#include "ostree-repo-private.h" #include "ostree-sysroot-private.h" #include "otutil.h" @@ -84,15 +85,16 @@ append_config_from_loader_entries (OstreeBootloaderSyslinux *self, gboolean rege val = ostree_bootconfig_parser_get (config, "linux"); if (!val) return glnx_throw (error, "No \"linux\" key in bootloader config"); - g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL /boot%s", val)); + const char *prefix = self->sysroot->repo->enable_bootprefix ? "" : "/boot"; + g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s%s", prefix, val)); val = ostree_bootconfig_parser_get (config, "initrd"); if (val) - g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD /boot%s", val)); + g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s%s", prefix, val)); val = ostree_bootconfig_parser_get (config, "devicetree"); if (val) - g_ptr_array_add (new_lines, g_strdup_printf ("\tDEVICETREE /boot%s", val)); + g_ptr_array_add (new_lines, g_strdup_printf ("\tDEVICETREE %s%s", prefix, val)); val = ostree_bootconfig_parser_get (config, "options"); if (val) diff --git a/src/libostree/ostree-bootloader-zipl.c b/src/libostree/ostree-bootloader-zipl.c index c0a2a14..2804ed2 100644 --- a/src/libostree/ostree-bootloader-zipl.c +++ b/src/libostree/ostree-bootloader-zipl.c @@ -22,6 +22,7 @@ #include "ostree-libarchive-private.h" #include "ostree-sysroot-private.h" #include "otutil.h" +#include #include #include #include @@ -35,6 +36,7 @@ #define SECURE_EXECUTION_LUKS_ROOT_KEY "/etc/luks/root" #define SECURE_EXECUTION_LUKS_BOOT_KEY "/etc/luks/boot" #define SECURE_EXECUTION_LUKS_CONFIG "/etc/crypttab" +#define SECURE_BOOT_SYSFS_FLAG "/sys/firmware/ipl/secure" #if !(defined HAVE_LIBARCHIVE) && defined(__s390x__) #error libarchive is required for s390x @@ -112,6 +114,52 @@ _ostree_bootloader_zipl_write_config (OstreeBootloader *bootloader, int bootvers return TRUE; } +static gboolean +_ostree_secure_boot_is_enabled (gboolean *out_enabled, GCancellable *cancellable, GError **error) +{ + *out_enabled = FALSE; + glnx_autofd int fd = -1; + if (!ot_openat_ignore_enoent (AT_FDCWD, SECURE_BOOT_SYSFS_FLAG, &fd, error)) + return FALSE; + if (fd != -1) + { + g_autofree char *data = glnx_fd_readall_utf8 (fd, NULL, cancellable, error); + if (!data) + return FALSE; + *out_enabled = strstr (data, "1") != NULL; + ot_journal_print (LOG_INFO, "s390x: sysfs: Secure Boot enabled: %d", *out_enabled); + return TRUE; + } + + // Fallback, RHEL 9 kernel is buggy and doesn't have sysfs flag. + // Let's check kmsg, with Secure Boot enabled kernel prints smth like: + // [ 0.027998] Linux version 5.14.0-284.36.1.el9_2.s390x + // [ 0.023193] setup: Linux is running as a z/VM guest operating system in 64-bit mode + // [ 0.023193] setup: Linux is running with Secure-IPL enabled + // [ 0.023194] setup: The IPL report contains the following components: + // [ 0.023194] setup: 0000000000009000 - 000000000000a000 (not signed) + // [ 0.023196] setup: 000000000000a000 - 000000000000e000 (signed, verified) + // [ 0.023197] setup: 0000000000010000 - 0000000000866000 (signed, verified) + // [ 0.023198] setup: 0000000000867000 - 0000000000868000 (not signed) + // [ 0.023199] setup: 0000000000877000 - 0000000000878000 (not signed) + // [ 0.023200] setup: 0000000000880000 - 0000000003f98000 (not signed) + fd = openat (AT_FDCWD, "/dev/kmsg", O_NONBLOCK | O_RDONLY | O_CLOEXEC); + if (fd == -1) + return glnx_throw_errno_prefix (error, "openat(/dev/kmsg)"); + g_autoptr (GInputStream) istream = g_unix_input_stream_new (g_steal_fd (&fd), TRUE); + g_autoptr (GDataInputStream) stream = g_data_input_stream_new (istream); + unsigned int max_lines = 5; // no need to read dozens of messages, ours comes really early + while (*out_enabled != TRUE && max_lines > 0) + { + gsize len = 0; + g_autofree char *line = g_data_input_stream_read_line (stream, &len, NULL, error); + *out_enabled = strstr (line, "Secure-IPL enabled") != NULL; + --max_lines; + } + ot_journal_print (LOG_INFO, "s390x: kmsg: Secure Boot enabled: %d", *out_enabled); + return TRUE; +} + static gboolean _ostree_secure_execution_is_enabled (gboolean *out_enabled, GCancellable *cancellable, GError **error) @@ -381,10 +429,25 @@ _ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, int bootver { OstreeBootloaderZipl *self = OSTREE_BOOTLOADER_ZIPL (bootloader); - /* Note that unlike the grub2-mkconfig backend, we make no attempt to - * chroot(). - */ - g_assert (self->sysroot->booted_deployment); + // This can happen in a unit testing environment; at some point what we want to do here + // is move all of the zipl logic to a systemd unit instead that's keyed of + // ostree-finalize-staged.service. + if (getuid () != 0) + return TRUE; + + // If we're in a booted deployment, we don't need to spawn a container. + // Also avoid containerizing if there's no deployments to target, which shouldn't + // generally happen. + OstreeDeployment *target_deployment; + if (self->sysroot->booted_deployment || self->sysroot->deployments->len == 0) + { + target_deployment = NULL; + } + else + { + g_assert_cmpint (self->sysroot->deployments->len, >, 0); + target_deployment = self->sysroot->deployments->pdata[0]; + } if (!glnx_fstatat_allow_noent (self->sysroot->sysroot_fd, zipl_requires_execute_path, NULL, 0, error)) @@ -408,11 +471,36 @@ _ostree_bootloader_zipl_post_bls_sync (OstreeBootloader *bootloader, int bootver return _ostree_secure_execution_enable (self, bootversion, keys, cancellable, error); } /* Fallback to non-SE setup */ - const char *const zipl_argv[] = { "zipl", NULL }; - int estatus; - if (!g_spawn_sync (NULL, (char **)zipl_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, - &estatus, error)) + gboolean sb_enabled = FALSE; + if (!_ostree_secure_boot_is_enabled (&sb_enabled, cancellable, error)) return FALSE; + const char *const zipl_argv[] + = { "zipl", "--secure", (sb_enabled == TRUE) ? "1" : "auto", "-V", NULL }; + int estatus; + if (target_deployment != NULL) + { + g_debug ("executing zipl in deployment root"); + g_autofree char *deployment_path + = ostree_sysroot_get_deployment_dirpath (self->sysroot, target_deployment); + glnx_autofd int deployment_dfd = -1; + if (!glnx_opendirat (self->sysroot->sysroot_fd, deployment_path, TRUE, &deployment_dfd, + error)) + return FALSE; + + g_autofree char *sysroot_boot + = g_build_filename (gs_file_get_path_cached (self->sysroot->path), "boot", NULL); + const char *bwrap_args[] = { "--bind", sysroot_boot, "/boot", NULL }; + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, bwrap_args, zipl_argv, &estatus, NULL, + error)) + return glnx_prefix_error (error, "Failed to invoke zipl"); + } + else + { + g_debug ("executing zipl from booted system"); + if (!g_spawn_sync (NULL, (char **)zipl_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, + NULL, &estatus, error)) + return FALSE; + } if (!g_spawn_check_exit_status (estatus, error)) return FALSE; if (!glnx_unlinkat (self->sysroot->sysroot_fd, zipl_requires_execute_path, 0, error)) diff --git a/src/libostree/ostree-deployment-private.h b/src/libostree/ostree-deployment-private.h index 2a28bff..f6766c3 100644 --- a/src/libostree/ostree-deployment-private.h +++ b/src/libostree/ostree-deployment-private.h @@ -51,6 +51,7 @@ struct _OstreeDeployment GKeyFile *origin; OstreeDeploymentUnlockedState unlocked; gboolean staged; + gboolean finalization_locked; char **overlay_initrds; char *overlay_initrds_id; }; diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 1480d74..8be2fdd 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -461,3 +461,18 @@ ostree_deployment_is_staged (OstreeDeployment *self) { return self->staged; } + +/** + * ostree_deployment_is_finalization_locked: + * @self: Deployment + * + * Returns: `TRUE` if deployment is queued to be "finalized" at shutdown time, but requires + * additional action. + * + * Since: 2023.8 + */ +gboolean +ostree_deployment_is_finalization_locked (OstreeDeployment *self) +{ + return self->finalization_locked; +} diff --git a/src/libostree/ostree-deployment.h b/src/libostree/ostree-deployment.h index 0d4a5d7..0536d98 100644 --- a/src/libostree/ostree-deployment.h +++ b/src/libostree/ostree-deployment.h @@ -71,6 +71,8 @@ GKeyFile *ostree_deployment_get_origin (OstreeDeployment *self); _OSTREE_PUBLIC gboolean ostree_deployment_is_staged (OstreeDeployment *self); _OSTREE_PUBLIC +gboolean ostree_deployment_is_finalization_locked (OstreeDeployment *self); +_OSTREE_PUBLIC gboolean ostree_deployment_is_pinned (OstreeDeployment *self); _OSTREE_PUBLIC diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index e9b9672..d690289 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -322,6 +322,8 @@ check_multi_info (OstreeFetcher *fetcher) req = g_task_get_task_data (task); + gboolean retry_all = (!is_file && req->fetcher->opt_retry_all); + if (req->caught_write_error) g_task_return_error (task, g_steal_pointer (&req->caught_write_error)); else if (curlres != CURLE_OK) @@ -337,12 +339,9 @@ check_multi_info (OstreeFetcher *fetcher) /* When it is not a file, we want to retry the request. * We accomplish that by using G_IO_ERROR_TIMED_OUT. */ - gboolean opt_retry_all = req->fetcher->opt_retry_all; - int g_io_error_code - = (is_file || !opt_retry_all) ? G_IO_ERROR_FAILED : G_IO_ERROR_TIMED_OUT; - g_task_return_new_error (task, G_IO_ERROR, g_io_error_code, - "While fetching %s: [%u] %s", eff_url, curlres, - curl_easy_strerror (curlres)); + g_task_return_new_error ( + task, G_IO_ERROR, retry_all ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR, + "While fetching %s: [%u] %s", eff_url, curlres, curl_easy_strerror (curlres)); _ostree_fetcher_journal_failure (req->fetcher->remote_name, eff_url, curl_easy_strerror (curlres)); } @@ -362,12 +361,13 @@ check_multi_info (OstreeFetcher *fetcher) if (!is_file && !(response >= 200 && response < 300) && response != 304) { - GIOErrorEnum giocode = _ostree_fetcher_http_status_code_to_io_error (response); + GIOErrorEnum giocode + = _ostree_fetcher_http_status_code_to_io_error (response, retry_all); if (req->idx + 1 == req->mirrorlist->len) { - g_autofree char *response_msg - = g_strdup_printf ("Server returned HTTP %lu", response); + g_autofree char *response_msg = g_strdup_printf ( + "While fetching %s: Server returned HTTP %lu", eff_url, response); g_task_return_new_error (task, G_IO_ERROR, giocode, "%s", response_msg); if (req->fetcher->remote_name && !((req->flags & OSTREE_FETCHER_REQUEST_OPTIONAL_CONTENT) > 0 diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index e75e72b..b68c4fd 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -1094,7 +1094,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data) #endif break; default: - code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code); + code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code, FALSE); break; } diff --git a/src/libostree/ostree-fetcher-soup3.c b/src/libostree/ostree-fetcher-soup3.c index 6de5c1e..fa71b36 100644 --- a/src/libostree/ostree-fetcher-soup3.c +++ b/src/libostree/ostree-fetcher-soup3.c @@ -621,7 +621,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data) { g_autofree char *uristring = g_uri_to_string (soup_message_get_uri (request->message)); - GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status); + GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status, FALSE); { g_autofree char *errmsg = g_strdup_printf ("Server returned status %u: %s", status, soup_status_get_phrase (status)); diff --git a/src/libostree/ostree-fetcher-util.c b/src/libostree/ostree-fetcher-util.c index b797bee..7ca9f07 100644 --- a/src/libostree/ostree-fetcher-util.c +++ b/src/libostree/ostree-fetcher-util.c @@ -224,7 +224,7 @@ _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remai * a #GIOErrorEnum. This will return %G_IO_ERROR_FAILED if the status code is * unknown or otherwise unhandled. */ GIOErrorEnum -_ostree_fetcher_http_status_code_to_io_error (guint status_code) +_ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean should_retry) { switch (status_code) { @@ -235,8 +235,9 @@ _ostree_fetcher_http_status_code_to_io_error (guint status_code) case 408: /* SOUP_STATUS_REQUEST_TIMEOUT */ return G_IO_ERROR_TIMED_OUT; case 500: /* SOUP_STATUS_INTERNAL_SERVER_ERROR */ - return G_IO_ERROR_BUSY; + /* retries are always mapped to timeouts, see similar logic in the curl error handling */ + return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_BUSY; default: - return G_IO_ERROR_FAILED; + return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_FAILED; } } diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h index 97233e1..ef5ad65 100644 --- a/src/libostree/ostree-fetcher-util.h +++ b/src/libostree/ostree-fetcher-util.h @@ -57,7 +57,7 @@ void _ostree_fetcher_journal_failure (const char *remote_name, const char *url, gboolean _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remaining); -GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code); +GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean retry_all); G_END_DECLS diff --git a/src/libostree/ostree-impl-system-generator.c b/src/libostree/ostree-impl-system-generator.c index ad785eb..c5fe503 100644 --- a/src/libostree/ostree-impl-system-generator.c +++ b/src/libostree/ostree-impl-system-generator.c @@ -126,10 +126,38 @@ require_internal_units (const char *normal_dir, const char *early_dir, const cha #endif } +// Resolve symlink to return osname +static gboolean +_ostree_sysroot_parse_bootlink_aboot (const char *bootlink, char **out_osname, GError **error) +{ + static gsize regex_initialized; + static GRegex *regex; + g_autofree char *symlink_val = glnx_readlinkat_malloc (-1, bootlink, NULL, error); + if (!symlink_val) + return glnx_prefix_error (error, "Failed to read '%s' symlink", bootlink); + + if (g_once_init_enter (®ex_initialized)) + { + regex = g_regex_new ("^deploy/([^/]+)/", 0, 0, NULL); + g_assert (regex); + g_once_init_leave (®ex_initialized, 1); + } + + g_autoptr (GMatchInfo) match = NULL; + if (!g_regex_match (regex, symlink_val, 0, &match)) + return glnx_throw (error, + "Invalid aboot symlink in /ostree, expected symlink to resolve to " + "deploy/OSNAME/... instead it resolves to '%s'", + symlink_val); + + *out_osname = g_match_info_fetch (match, 1); + return TRUE; +} + /* Generate var.mount */ static gboolean -fstab_generator (const char *ostree_cmdline, const char *normal_dir, const char *early_dir, - const char *late_dir, GError **error) +fstab_generator (const char *ostree_target, const bool is_aboot, const char *normal_dir, + const char *early_dir, const char *late_dir, GError **error) { #ifdef HAVE_LIBMOUNT /* Not currently cancellable, but define a var in case we care later */ @@ -144,7 +172,12 @@ fstab_generator (const char *ostree_cmdline, const char *normal_dir, const char * mounted yet. */ g_autofree char *stateroot = NULL; - if (!_ostree_sysroot_parse_bootlink (ostree_cmdline, NULL, &stateroot, NULL, NULL, error)) + if (is_aboot) + { + if (!_ostree_sysroot_parse_bootlink_aboot (ostree_target, &stateroot, error)) + return glnx_prefix_error (error, "Parsing aboot stateroot"); + } + else if (!_ostree_sysroot_parse_bootlink (ostree_target, NULL, &stateroot, NULL, NULL, error)) return glnx_prefix_error (error, "Parsing stateroot"); /* Load /etc/fstab if it exists, and look for a /var mount */ @@ -251,22 +284,31 @@ _ostree_impl_system_generator (const char *normal_dir, const char *early_dir, co if (unlinkat (AT_FDCWD, INITRAMFS_MOUNT_VAR, 0) == 0) return TRUE; + // If we're not booted via ostree, do nothing + if (!glnx_fstatat_allow_noent (AT_FDCWD, OTCORE_RUN_OSTREE, NULL, 0, error)) + return FALSE; + if (errno == ENOENT) + return TRUE; + g_autofree char *cmdline = read_proc_cmdline (); if (!cmdline) return glnx_throw (error, "Failed to read /proc/cmdline"); - /* If we're installed on a system which isn't using OSTree for boot (e.g. - * package installed as a dependency for flatpak or whatever), silently - * exit so that we don't error, but at the same time work where switchroot - * is PID 1 (and so hasn't created /run/ostree-booted). - */ - g_autofree char *ostree_cmdline = otcore_find_proc_cmdline_key (cmdline, "ostree"); - if (!ostree_cmdline) + g_autofree char *ostree_target = NULL; + gboolean is_aboot = false; + if (!otcore_get_ostree_target (cmdline, &is_aboot, &ostree_target, error)) + return glnx_prefix_error (error, "Invalid aboot ostree target"); + + /* If no `ostree=` karg exists, gracefully no-op. + * This could happen in CoreOS live environments, where we hackily mock + * the `ostree=` karg for `ostree-prepare-root.service` specifically, but + * otherwise that karg doesn't exist on the real command-line. */ + if (!ostree_target) return TRUE; if (!require_internal_units (normal_dir, early_dir, late_dir, error)) return FALSE; - if (!fstab_generator (ostree_cmdline, normal_dir, early_dir, late_dir, error)) + if (!fstab_generator (ostree_target, is_aboot, normal_dir, early_dir, late_dir, error)) return FALSE; return TRUE; diff --git a/src/libostree/ostree-kernel-args.c b/src/libostree/ostree-kernel-args.c index 9a9e0be..57357a3 100644 --- a/src/libostree/ostree-kernel-args.c +++ b/src/libostree/ostree-kernel-args.c @@ -163,6 +163,44 @@ strcmp0_equal (gconstpointer v1, gconstpointer v2) return g_strcmp0 (v1, v2) == 0; } +/* Split string with spaces, but keep quotes. + For example, "test=\"1 2\"" will be saved as whole. + */ +static char ** +split_kernel_args (const char *str) +{ + gboolean quoted = FALSE; + g_return_val_if_fail (str != NULL, NULL); + + GPtrArray *strv = g_ptr_array_new (); + + size_t len = strlen (str); + // Skip first spaces + const char *start = str + strspn (str, " "); + for (const char *iter = start; iter && *iter; iter++) + { + if (*iter == '"') + quoted = !quoted; + else if (*iter == ' ' && !quoted) + { + g_ptr_array_add (strv, g_strndup (start, iter - start)); + start = iter + 1; + } + } + + // Add the last slice + if (!quoted) + g_ptr_array_add (strv, g_strndup (start, str + len - start)); + else + { + g_debug ("Missing terminating quote in '%s'.\n", str); + g_assert_false (quoted); + } + + g_ptr_array_add (strv, NULL); + return (char **)g_ptr_array_free (strv, FALSE); +} + /** * ostree_kernel_args_new: (skip) * @@ -285,35 +323,42 @@ _ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs) gboolean ostree_kernel_args_new_replace (OstreeKernelArgs *kargs, const char *arg, GError **error) { - g_autofree char *arg_owned = g_strdup (arg); - const char *key = arg_owned; - const char *val = split_keyeq (arg_owned); - - GPtrArray *entries = g_hash_table_lookup (kargs->table, key); - if (!entries) - return glnx_throw (error, "No key '%s' found", key); - g_assert_cmpuint (entries->len, >, 0); + // Split the arg + g_auto (GStrv) argv = split_kernel_args (arg); - /* first handle the case where the user just wants to replace an old value */ - if (val && strchr (val, '=')) + for (char **iter = argv; iter && *iter; iter++) { - g_autofree char *old_val = g_strdup (val); - const char *new_val = split_keyeq (old_val); - g_assert (new_val); + g_autofree char *arg_owned = g_strdup (*iter); + const char *key = arg_owned; + const char *val = split_keyeq (arg_owned); - guint i = 0; - if (!ot_ptr_array_find_with_equal_func (entries, old_val, kernel_args_entry_value_equal, &i)) - return glnx_throw (error, "No karg '%s=%s' found", key, old_val); + GPtrArray *entries = g_hash_table_lookup (kargs->table, key); + if (!entries) + return glnx_throw (error, "No key '%s' found", key); + g_assert_cmpuint (entries->len, >, 0); - kernel_args_entry_replace_value (entries->pdata[i], new_val); - return TRUE; - } + /* first handle the case where the user just wants to replace an old value */ + if (val && strchr (val, '=')) + { + g_autofree char *old_val = g_strdup (val); + const char *new_val = split_keyeq (old_val); + g_assert (new_val); + + guint i = 0; + if (!ot_ptr_array_find_with_equal_func (entries, old_val, kernel_args_entry_value_equal, + &i)) + return glnx_throw (error, "No karg '%s=%s' found", key, old_val); + + kernel_args_entry_replace_value (entries->pdata[i], new_val); + continue; + } - /* can't know which val to replace without the old_val=new_val syntax */ - if (entries->len > 1) - return glnx_throw (error, "Multiple values for key '%s' found", key); + /* can't know which val to replace without the old_val=new_val syntax */ + if (entries->len > 1) + return glnx_throw (error, "Multiple values for key '%s' found", key); - kernel_args_entry_replace_value (entries->pdata[0], val); + kernel_args_entry_replace_value (entries->pdata[0], val); + } return TRUE; } @@ -381,39 +426,48 @@ ostree_kernel_args_delete_key_entry (OstreeKernelArgs *kargs, const char *key, G gboolean ostree_kernel_args_delete (OstreeKernelArgs *kargs, const char *arg, GError **error) { - g_autofree char *arg_owned = g_strdup (arg); - const char *key = arg_owned; - const char *val = split_keyeq (arg_owned); - - GPtrArray *entries = g_hash_table_lookup (kargs->table, key); - if (!entries) - return glnx_throw (error, "No key '%s' found", key); - g_assert_cmpuint (entries->len, >, 0); + // Split the arg + g_auto (GStrv) argv = split_kernel_args (arg); - /* special-case: we allow deleting by key only if there's only one val */ - if (entries->len == 1) + for (char **iter = argv; iter && *iter; iter++) { - /* but if a specific val was passed, check that it's the same */ - OstreeKernelArgsEntry *e = entries->pdata[0]; - if (val && !strcmp0_equal (val, _ostree_kernel_args_entry_get_value (e))) - return glnx_throw (error, "No karg '%s=%s' found", key, val); - return ostree_kernel_args_delete_key_entry (kargs, key, error); - } + g_autofree char *arg_owned = g_strdup (*iter); - /* note val might be NULL here, in which case we're looking for `key`, not `key=` or - * `key=val` */ - guint i = 0; - if (!ot_ptr_array_find_with_equal_func (entries, val, kernel_args_entry_value_equal, &i)) - { - if (!val) - /* didn't find NULL -> only key= key=val1 key=val2 style things left, so the user - * needs to be more specific */ - return glnx_throw (error, "Multiple values for key '%s' found", arg); - return glnx_throw (error, "No karg '%s' found", arg); - } + const char *key = arg_owned; + const char *val = split_keyeq (arg_owned); + + GPtrArray *entries = g_hash_table_lookup (kargs->table, key); + if (!entries) + return glnx_throw (error, "No key '%s' found", key); + g_assert_cmpuint (entries->len, >, 0); + + /* special-case: we allow deleting by key only if there's only one val */ + if (entries->len == 1) + { + /* but if a specific val was passed, check that it's the same */ + OstreeKernelArgsEntry *e = entries->pdata[0]; + if (val && !strcmp0_equal (val, _ostree_kernel_args_entry_get_value (e))) + return glnx_throw (error, "No karg '%s=%s' found", key, val); + if (!ostree_kernel_args_delete_key_entry (kargs, key, error)) + return glnx_throw (error, "Remove key entry '%s=%s' failed.", key, val); + continue; + } - g_assert (g_ptr_array_remove (kargs->order, entries->pdata[i])); - g_assert (g_ptr_array_remove_index (entries, i)); + /* note val might be NULL here, in which case we're looking for `key`, not `key=` or + * `key=val` */ + guint i = 0; + if (!ot_ptr_array_find_with_equal_func (entries, val, kernel_args_entry_value_equal, &i)) + { + if (!val) + /* didn't find NULL -> only key= key=val1 key=val2 style things left, so the user + * needs to be more specific */ + return glnx_throw (error, "Multiple values for key '%s' found", arg); + return glnx_throw (error, "No karg '%s' found", arg); + } + + g_assert (g_ptr_array_remove (kargs->order, entries->pdata[i])); + g_assert (g_ptr_array_remove_index (entries, i)); + } return TRUE; } @@ -499,27 +553,34 @@ ostree_kernel_args_replace (OstreeKernelArgs *kargs, const char *arg) void ostree_kernel_args_append (OstreeKernelArgs *kargs, const char *arg) { - gboolean existed = TRUE; - GPtrArray *entries = NULL; - char *duped = g_strdup (arg); - const char *val = split_keyeq (duped); + // Split the arg + g_auto (GStrv) argv = split_kernel_args (arg); - entries = g_hash_table_lookup (kargs->table, duped); - if (!entries) + for (char **iter = argv; iter && *iter; iter++) { - entries = g_ptr_array_new_with_free_func (kernel_args_entry_free_from_table); - existed = FALSE; - } + gboolean existed = TRUE; + GPtrArray *entries = NULL; - OstreeKernelArgsEntry *entry = _ostree_kernel_args_entry_new (); - _ostree_kernel_args_entry_set_key (entry, duped); - _ostree_kernel_args_entry_set_value (entry, g_strdup (val)); + char *duped = g_strdup (*iter); + const char *val = split_keyeq (duped); - g_ptr_array_add (entries, entry); - g_ptr_array_add (kargs->order, entry); + entries = g_hash_table_lookup (kargs->table, duped); + if (!entries) + { + entries = g_ptr_array_new_with_free_func (kernel_args_entry_free_from_table); + existed = FALSE; + } + + OstreeKernelArgsEntry *entry = _ostree_kernel_args_entry_new (); + _ostree_kernel_args_entry_set_key (entry, duped); + _ostree_kernel_args_entry_set_value (entry, g_strdup (val)); - if (!existed) - g_hash_table_replace (kargs->table, duped, entries); + g_ptr_array_add (entries, entry); + g_ptr_array_add (kargs->order, entry); + + if (!existed) + g_hash_table_replace (kargs->table, duped, entries); + } } /** @@ -644,7 +705,7 @@ ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, const char *options) if (!options) return; - args = g_strsplit (options, " ", -1); + args = split_kernel_args (options); for (iter = args; *iter; iter++) { char *arg = *iter; diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 0516ef4..6506044 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -195,7 +195,7 @@ create_file_copy_from_input_at (OstreeRepo *repo, OstreeRepoCheckoutAtOptions *o g_autoptr (GVariant) modified_xattrs = NULL; /* If we're doing SELinux labeling, prepare it */ - if (sepolicy_enabled) + if (sepolicy_enabled && _ostree_sepolicy_host_enabled (options->sepolicy)) { /* If doing sepolicy path-based labeling, we don't want to set the * security.selinux attr via the generic xattr paths in either the symlink @@ -1045,7 +1045,7 @@ checkout_tree_at_recurse (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options }; /* If we're doing SELinux labeling, prepare it */ - if (sepolicy_enabled) + if (sepolicy_enabled && _ostree_sepolicy_host_enabled (options->sepolicy)) { /* We'll set the xattr via setfscreatecon(), so don't do it via generic xattrs below. */ modified_xattrs = _ostree_filter_selinux_xattr (xattrs); @@ -1062,6 +1062,22 @@ checkout_tree_at_recurse (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error)) return FALSE; } + else if (options->process_whiteouts + && options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) + { + /* In this mode, we're flattening in a manner similar to overlayfs, so ensure + * any non-directory content there is gone. / + */ + struct stat stbuf; + if (!glnx_fstatat_allow_noent (destination_parent_fd, destination_name, &stbuf, + AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == 0 && !S_ISDIR (stbuf.st_mode)) + { + if (!glnx_shutil_rm_rf_at (destination_parent_fd, destination_name, cancellable, error)) + return FALSE; + } + } /* Create initially with mode 0700, then chown/chmod only when we're * done. This avoids anyone else being able to operate on partially diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index d9fbb25..5a22ad7 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -586,11 +586,11 @@ _ostree_repo_bare_content_cleanup (OstreeRepoBareContent *regwrite) } /* Allocate an O_TMPFILE, write everything from @input to it, but - * not exceeding @length. Used for every object in archive repos, - * and content objects in all bare-type repos. + * not exceeding @length. */ static gboolean -create_regular_tmpfile_linkable_with_content (OstreeRepo *self, guint64 length, GInputStream *input, +create_regular_tmpfile_linkable_with_content (OstreeRepo *self, guint64 length, + GInputStream *original_input, GInputStream *input, GLnxTmpfile *out_tmpf, GCancellable *cancellable, GError **error) { @@ -601,40 +601,44 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self, guint64 length, error)) return FALSE; - if (!glnx_try_fallocate (tmpf.fd, 0, length, error)) - return FALSE; - - if (G_IS_FILE_DESCRIPTOR_BASED (input)) + // Try to do a reflink if possible; if we hit this case we're operating on trusted local input. + gboolean did_clone = FALSE; + if (G_IS_FILE_DESCRIPTOR_BASED (original_input)) { - int infd = g_file_descriptor_based_get_fd ((GFileDescriptorBased *)input); - if (glnx_regfile_copy_bytes (infd, tmpf.fd, (off_t)length) < 0) - return glnx_throw_errno_prefix (error, "regfile copy"); + int infd = g_file_descriptor_based_get_fd ((GFileDescriptorBased *)original_input); + if (ioctl (tmpf.fd, FICLONE, infd) == 0) + { + did_clone = TRUE; + } } else { - /* We used to do a g_output_stream_splice(), but there are two issues with that: - * - We want to honor the size provided, to avoid malicious content that says it's - * e.g. 10 bytes but is actually gigabytes. - * - Due to GLib bugs that pointlessly calls `poll()` on the output fd for every write - */ - gsize buf_size = MIN (length, 1048576); - g_autofree gchar *buf = g_malloc (buf_size); - guint64 remaining = length; - while (remaining > 0) - { - const gssize bytes_read - = g_input_stream_read (input, buf, MIN (remaining, buf_size), cancellable, error); - if (bytes_read < 0) - return FALSE; - else if (bytes_read == 0) - return glnx_throw (error, - "Unexpected EOF with %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT - " bytes remaining", - remaining, length); - if (glnx_loop_write (tmpf.fd, buf, bytes_read) < 0) - return glnx_throw_errno_prefix (error, "write"); - remaining -= bytes_read; - } + if (!glnx_try_fallocate (tmpf.fd, 0, length, error)) + return FALSE; + } + + /* We used to do a g_output_stream_splice(), but there are two issues with that: + * - We want to honor the size provided, to avoid malicious content that says it's + * e.g. 10 bytes but is actually gigabytes. + * - Due to GLib bugs that pointlessly calls `poll()` on the output fd for every write + */ + gsize buf_size = MIN (length, 1048576); + g_autofree gchar *buf = g_malloc (buf_size); + guint64 remaining = length; + while (remaining > 0) + { + const gssize bytes_read + = g_input_stream_read (input, buf, MIN (remaining, buf_size), cancellable, error); + if (bytes_read < 0) + return FALSE; + else if (bytes_read == 0) + return glnx_throw (error, + "Unexpected EOF with %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT + " bytes remaining", + remaining, length); + if (!did_clone && glnx_loop_write (tmpf.fd, buf, bytes_read) < 0) + return glnx_throw_errno_prefix (error, "write"); + remaining -= bytes_read; } if (!glnx_fchmod (tmpf.fd, 0644, error)) @@ -989,8 +993,8 @@ write_content_object (OstreeRepo *self, const char *expected_checksum, GInputStr } else if (repo_mode != OSTREE_REPO_MODE_ARCHIVE) { - if (!create_regular_tmpfile_linkable_with_content (self, size, file_input, &tmpf, cancellable, - error)) + if (!create_regular_tmpfile_linkable_with_content (self, size, input, file_input, &tmpf, + cancellable, error)) return FALSE; } else diff --git a/src/libostree/ostree-repo-composefs.c b/src/libostree/ostree-repo-composefs.c index cc5e5fd..5be83e0 100644 --- a/src/libostree/ostree-repo-composefs.c +++ b/src/libostree/ostree-repo-composefs.c @@ -235,6 +235,9 @@ ostree_composefs_target_write (OstreeComposefsTarget *target, int fd, guchar **o options.file_write_cb = _composefs_write_cb; } + options.version = 0; + options.max_version = 1; /* Support new whiteout xattr if required */ + if (lcfs_write_to (root, &options) != 0) return glnx_throw_errno_prefix (error, "lcfs_write_to"); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index ad6457e..e6b26ce 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -412,6 +412,9 @@ gboolean _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fs gboolean _ostree_tmpf_fsverity (OstreeRepo *self, GLnxTmpfile *tmpf, GBytes *signature, GError **error); +gboolean _ostree_ensure_fsverity (OstreeRepo *self, gboolean allow_enoent, int dirfd, + const char *path, gboolean *supported, GError **error); + gboolean _ostree_repo_verify_bindings (const char *collection_id, const char *ref_name, GVariant *commit, GError **error); diff --git a/src/libostree/ostree-repo-verity.c b/src/libostree/ostree-repo-verity.c index 6a7130c..0c85ad3 100644 --- a/src/libostree/ostree-repo-verity.c +++ b/src/libostree/ostree-repo-verity.c @@ -102,28 +102,14 @@ _ostree_repo_parse_fsverity_config (OstreeRepo *self, GError **error) return TRUE; } -/* Wrapper around the fsverity ioctl, compressing the result to - * "success, unsupported or error". This is used for /boot where - * we enable verity if supported. - * */ -gboolean -_ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_requested, - GBytes *signature, gboolean *supported, GError **error) +static gboolean +_ostree_fsverity_enable (int fd, gboolean allow_existing, gboolean *supported, GBytes *signature, + GError **error) { - /* Set this by default to simplify the code below */ if (supported) *supported = FALSE; - if (fsverity_requested == _OSTREE_FEATURE_NO) - return TRUE; - #ifdef HAVE_LINUX_FSVERITY_H - GLNX_AUTO_PREFIX_ERROR ("fsverity", error); - - /* fs-verity requires a read-only file descriptor */ - if (!glnx_tmpfile_reopen_rdonly (tmpf, error)) - return FALSE; - struct fsverity_enable_arg arg = { 0, }; @@ -135,7 +121,7 @@ _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_re arg.sig_size = signature ? g_bytes_get_size (signature) : 0; arg.sig_ptr = signature ? (guint64)g_bytes_get_data (signature, NULL) : 0; - if (ioctl (tmpf->fd, FS_IOC_ENABLE_VERITY, &arg) < 0) + if (ioctl (fd, FS_IOC_ENABLE_VERITY, &arg) < 0) { switch (errno) { @@ -143,13 +129,42 @@ _ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_re case EOPNOTSUPP: return TRUE; default: - return glnx_throw_errno_prefix (error, "ioctl(FS_IOC_ENABLE_VERITY)"); + if (errno != EEXIST || !allow_existing) + return glnx_throw_errno_prefix (error, "ioctl(FS_IOC_ENABLE_VERITY)"); } } if (supported) *supported = TRUE; #endif + + return TRUE; +} + +/* Wrapper around the fsverity ioctl, compressing the result to + * "success, unsupported or error". This is used for /boot where + * we enable verity if supported. + * */ +gboolean +_ostree_tmpf_fsverity_core (GLnxTmpfile *tmpf, _OstreeFeatureSupport fsverity_requested, + GBytes *signature, gboolean *supported, GError **error) +{ + if (fsverity_requested == _OSTREE_FEATURE_NO) + { + if (supported) + *supported = FALSE; + return TRUE; + } + + GLNX_AUTO_PREFIX_ERROR ("fsverity", error); + + /* fs-verity requires a read-only file descriptor */ + if (!glnx_tmpfile_reopen_rdonly (tmpf, error)) + return FALSE; + + if (!_ostree_fsverity_enable (tmpf->fd, FALSE, supported, signature, error)) + return FALSE; + return TRUE; } @@ -206,3 +221,40 @@ _ostree_tmpf_fsverity (OstreeRepo *self, GLnxTmpfile *tmpf, GBytes *signature, G #endif return TRUE; } + +gboolean +_ostree_ensure_fsverity (OstreeRepo *self, gboolean allow_enoent, int dirfd, const char *path, + gboolean *supported_out, GError **error) +{ + struct stat buf; + gboolean supported; + + if (supported_out) + *supported_out = TRUE; + + if (fstatat (dirfd, path, &buf, AT_SYMLINK_NOFOLLOW) != 0) + { + if (errno == ENOENT && allow_enoent) + return TRUE; + + return glnx_throw_errno_prefix (error, "fstatat(%s)", path); + } + + if (!S_ISREG (buf.st_mode)) + return TRUE; /* Ignore symlinks, etc */ + + glnx_autofd int fd = openat (dirfd, path, O_CLOEXEC | O_RDONLY); + if (fd < 0) + return glnx_throw_errno_prefix (error, "openat(%s)", path); + + if (!_ostree_fsverity_enable (fd, TRUE, &supported, NULL, error)) + return FALSE; + + if (!supported && self->fs_verity_wanted == _OSTREE_FEATURE_YES) + return glnx_throw (error, "fsverity required but filesystem does not support it"); + + if (supported_out) + *supported_out = supported; + + return TRUE; +} diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 04a5402..2f4e836 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -6092,6 +6092,23 @@ regenerate_metadata (OstreeRepo *self, gboolean do_metadata_commit, GVariant *ad && !_ostree_sign_summary_at (sign, self, summary_tmpdir.fd, sign_keys, cancellable, error)) return FALSE; + /* If a signature was made, sync the summary times to it. This way an + * HTTP client will consider the files expired at the same time. + */ + if (gpg_key_ids != NULL || sign_keys != NULL) + { + struct stat stbuf; + if (!glnx_fstatat (summary_tmpdir.fd, "summary.sig", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return glnx_prefix_error (error, "Unable to get summary.sig status"); + + struct timespec ts[2]; + ts[0] = stbuf.st_atim; + ts[1] = stbuf.st_mtim; + if (TEMP_FAILURE_RETRY (utimensat (summary_tmpdir.fd, "summary", ts, AT_SYMLINK_NOFOLLOW)) + != 0) + return glnx_throw_errno_prefix (error, "Unable to change summary timestamps"); + } + /* Rename them into place */ if (!glnx_renameat (summary_tmpdir.fd, "summary", self->repo_dir_fd, "summary", error)) return glnx_prefix_error (error, "Unable to rename summary file: "); diff --git a/src/libostree/ostree-sepolicy-private.h b/src/libostree/ostree-sepolicy-private.h index 350ef40..b526d86 100644 --- a/src/libostree/ostree-sepolicy-private.h +++ b/src/libostree/ostree-sepolicy-private.h @@ -36,4 +36,6 @@ gboolean _ostree_sepolicy_preparefscreatecon (OstreeSepolicyFsCreatecon *con, Os GVariant *_ostree_filter_selinux_xattr (GVariant *xattrs); +gboolean _ostree_sepolicy_host_enabled (OstreeSePolicy *self); + G_END_DECLS diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index d61a9cc..2e6ec00 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -497,7 +497,7 @@ ostree_sepolicy_get_path (OstreeSePolicy *self) * ostree_sepolicy_get_name: * @self: * - * Returns: (transfer none): Type of current policy + * Returns: (transfer none) (nullable): Type of current policy */ const char * ostree_sepolicy_get_name (OstreeSePolicy *self) @@ -753,3 +753,19 @@ _ostree_filter_selinux_xattr (GVariant *xattrs) return NULL; return g_variant_ref_sink (g_variant_builder_end (&builder)); } + +/** + * _ostree_sepolicy_host_enabled: + * @self: Policy + * + * Return if the host has selinux enabled + */ +gboolean +_ostree_sepolicy_host_enabled (OstreeSePolicy *self) +{ +#ifdef HAVE_SELINUX + return cached_is_selinux_enabled (); +#else + return FALSE; +#endif +} diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 090b004..e5ffc5a 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -19,8 +19,10 @@ #include "config.h" +#include "ostree-core-private.h" #include "ostree-linuxfsutil.h" #include "ostree-repo-private.h" +#include "otcore.h" #include "otutil.h" #include "ostree-sysroot-private.h" @@ -216,6 +218,7 @@ gboolean _ostree_sysroot_rmrf_deployment (OstreeSysroot *self, OstreeDeployment *deployment, GCancellable *cancellable, GError **error) { + g_autofree char *backing_relpath = _ostree_sysroot_get_deployment_backing_relpath (deployment); g_autofree char *origin_relpath = ostree_deployment_get_origin_relpath (deployment); g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); struct stat stbuf; @@ -236,6 +239,12 @@ _ostree_sysroot_rmrf_deployment (OstreeSysroot *self, OstreeDeployment *deployme /* This deployment wasn't referenced, so delete it */ if (!_ostree_linuxfs_fd_alter_immutable_flag (deployment_fd, FALSE, cancellable, error)) return FALSE; + /* Note we must delete the origin and backing directories first, as the "source of truth" + * is the deployment path. We don't currently have code that detects "orphaned" + * origin files or work directories. + */ + if (!glnx_shutil_rm_rf_at (self->sysroot_fd, backing_relpath, cancellable, error)) + return FALSE; if (!glnx_shutil_rm_rf_at (self->sysroot_fd, origin_relpath, cancellable, error)) return FALSE; if (!glnx_shutil_rm_rf_at (self->sysroot_fd, deployment_path, cancellable, error)) @@ -573,3 +582,68 @@ _ostree_sysroot_cleanup_internal (OstreeSysroot *self, gboolean do_prune_repo, return TRUE; } + +/** + * ostree_sysroot_update_post_copy: + * @self: Sysroot + * @error: Error + * + * Update a sysroot as needed after having copied it into place using file-level + * operations. This enables options like fs-verity on the required files that may + * have been lost during the copy. + * + * Since: 2023.11 + */ +gboolean +ostree_sysroot_update_post_copy (OstreeSysroot *self, GCancellable *cancellable, GError **error) +{ + OstreeRepo *repo = ostree_sysroot_repo (self); + + if (repo->fs_verity_wanted == _OSTREE_FEATURE_NO) + return TRUE; + + g_autoptr (GHashTable) objects + = ostree_repo_list_objects_set (repo, OSTREE_REPO_LIST_OBJECTS_LOOSE, cancellable, error); + if (objects == NULL) + return FALSE; + + GLNX_HASH_TABLE_FOREACH (objects, GVariant *, key) + { + const char *checksum; + OstreeObjectType objtype; + + ostree_object_name_deserialize (key, &checksum, &objtype); + + char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; + _ostree_loose_path (loose_path_buf, checksum, objtype, repo->mode); + + gboolean supported; + if (!_ostree_ensure_fsverity (repo, FALSE, repo->objects_dir_fd, loose_path_buf, &supported, + error)) + return FALSE; + + if (!supported) + break; /* If not supported, skip rest */ + } + + g_autoptr (GPtrArray) all_deployment_dirs = NULL; + if (!list_all_deployment_directories (self, &all_deployment_dirs, cancellable, error)) + return FALSE; + g_assert (all_deployment_dirs); /* Pacify static analysis */ + for (guint i = 0; i < all_deployment_dirs->len; i++) + { + OstreeDeployment *deployment = all_deployment_dirs->pdata[i]; + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); + + g_autofree char *cfs_file = g_build_filename (deployment_path, OSTREE_COMPOSEFS_NAME, NULL); + + gboolean supported; + if (!_ostree_ensure_fsverity (repo, TRUE, self->sysroot_fd, cfs_file, &supported, error)) + return FALSE; + + if (!supported) + break; /* If not supported, skip rest */ + } + + return TRUE; +} diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 116143c..8ee4476 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -48,6 +48,9 @@ #include "ostree.h" #include "otcore.h" +// The path to the systemd tmpfiles.d directory. +#define USRLIB_TMPFILES "usr/lib/tmpfiles.d" + #ifdef HAVE_LIBSYSTEMD #define OSTREE_VARRELABEL_ID \ SD_ID128_MAKE (da, 67, 9b, 08, ac, d3, 45, 04, b7, 89, d9, 6f, 81, 8e, a7, 81) @@ -59,6 +62,12 @@ SD_ID128_MAKE (e8, 64, 6c, d6, 3d, ff, 46, 25, b7, 79, 09, a8, e7, a4, 09, 94) #endif +/* How much additional space we require available on top of what we accounted + * during the early prune fallocate space check. This accounts for anything not + * captured directly by `get_kernel_layout_size()` like writing new BLS entries. + */ +#define EARLY_PRUNE_SAFETY_MARGIN_SIZE (1 << 20) /* 1 MB */ + /* * Like symlinkat() but overwrites (atomically) an existing * symlink. @@ -317,11 +326,20 @@ copy_dir_recurse (int src_parent_dfd, int dest_parent_dfd, const char *name, } else { - if (!glnx_file_copy_at (src_dfd_iter.fd, dent->d_name, &child_stbuf, dest_dfd, - dent->d_name, - sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), - cancellable, error)) - return glnx_prefix_error (error, "Copying %s", dent->d_name); + if (S_ISLNK (child_stbuf.st_mode) || S_ISREG (child_stbuf.st_mode)) + { + if (!glnx_file_copy_at (src_dfd_iter.fd, dent->d_name, &child_stbuf, dest_dfd, + dent->d_name, + sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), + cancellable, error)) + return glnx_prefix_error (error, "Copying %s", dent->d_name); + } + else + { + ot_journal_print (LOG_INFO, + "Ignoring non-regular/non-symlink file found during /etc merge: %s", + dent->d_name); + } } } @@ -642,12 +660,41 @@ checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploy /* Generate hardlink farm, then opendir it */ OstreeRepoCheckoutAtOptions checkout_opts = { .process_passthrough_whiteouts = TRUE }; + if (!ostree_repo_checkout_at (repo, &checkout_opts, osdeploy_dfd, checkout_target_name, csum, cancellable, error)) return FALSE; + glnx_autofd int ret_deployment_dfd = -1; + if (!glnx_opendirat (osdeploy_dfd, checkout_target_name, TRUE, &ret_deployment_dfd, error)) + return FALSE; + #ifdef HAVE_COMPOSEFS - if (repo->composefs_wanted != OT_TRISTATE_NO) + /* TODO: Consider changing things in the future to parse the deployment config from memory, and + * if composefs is enabled, then we can check out in "user mode" (i.e. only have suid binaries + * enabled in composefs, etc.) + * + * However in practice we should get this for free by going to composefs-native backing + * storage. + */ + g_autoptr (GKeyFile) prepare_root_config + = otcore_load_config (ret_deployment_dfd, PREPARE_ROOT_CONFIG_PATH, error); + if (!prepare_root_config) + return glnx_prefix_error (error, "Parsing prepare-root config"); + // We always parse the composefs config, because we want to detect and error + // out if it's enabled, but not supported at compile time. + // However, we don't load the keys here, because they may not exist, such + // as in the initial deploy + g_autoptr (ComposefsConfig) composefs_config + = otcore_load_composefs_config (prepare_root_config, FALSE, error); + if (!composefs_config) + return glnx_prefix_error (error, "Reading composefs config"); + + OtTristate composefs_enabled = composefs_config->enabled; + g_debug ("composefs enabled by config: %d repo: %d", composefs_enabled, repo->composefs_wanted); + if (repo->composefs_wanted == OT_TRISTATE_YES) + composefs_enabled = repo->composefs_wanted; + if (composefs_enabled == OT_TRISTATE_YES) { g_autofree guchar *fsverity_digest = NULL; g_auto (GLnxTmpfile) tmpf = { @@ -676,6 +723,8 @@ checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploy g_autofree char *composefs_cfs_path = g_strdup_printf ("%s/" OSTREE_COMPOSEFS_NAME, checkout_target_name); + g_debug ("writing %s", composefs_cfs_path); + if (!glnx_open_tmpfile_linkable_at (osdeploy_dfd, checkout_target_name, O_WRONLY | O_CLOEXEC, &tmpf, error)) return FALSE; @@ -697,9 +746,13 @@ checkout_deployment_tree (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploy error)) return FALSE; } + else + g_debug ("not using composefs"); #endif - return glnx_opendirat (osdeploy_dfd, checkout_target_name, TRUE, out_deployment_dfd, error); + if (out_deployment_dfd) + *out_deployment_dfd = glnx_steal_fd (&ret_deployment_dfd); + return TRUE; } static char * @@ -1800,6 +1853,30 @@ parse_os_release (const char *contents, const char *split) return ret; } +/* Generate the filename we will use in /boot/loader/entries for this deployment. + * The provided n_deployments should be the total number of target deployments (which + * might be different from the cached value in the sysroot). + */ +static char * +bootloader_entry_filename (OstreeSysroot *sysroot, guint n_deployments, + OstreeDeployment *deployment) +{ + guint index = n_deployments - ostree_deployment_get_index (deployment); + // Allow opt-out to dropping the stateroot in case of compatibility issues. + // As of 2024.5, we have a new naming scheme because grub2 parses the *filename* and ignores + // the version field. xref https://github.com/ostreedev/ostree/issues/2961 + bool use_old_naming = (sysroot->opt_flags & OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_1) > 0; + if (use_old_naming) + { + const char *stateroot = ostree_deployment_get_osname (deployment); + return g_strdup_printf ("ostree-%d-%s.conf", index, stateroot); + } + else + { + return g_strdup_printf ("ostree-%d.conf", index); + } +} + /* Given @deployment, prepare it to be booted; basically copying its * kernel/initramfs into /boot/ostree (if needed) and writing out an entry in * /boot/loader/entries. @@ -1834,15 +1911,8 @@ install_deployment_kernel (OstreeSysroot *sysroot, int new_bootversion, const char *bootcsum = ostree_deployment_get_bootcsum (deployment); 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 = NULL; - guint index = n_deployments - ostree_deployment_get_index (deployment); - // Allow opt-in to dropping the stateroot, because grub2 parses the *filename* and ignores - // the version field. xref https://github.com/ostreedev/ostree/issues/2961 - bool use_new_naming = (sysroot->opt_flags & OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_2) > 0; - if (use_new_naming) - bootconf_name = g_strdup_printf ("ostree-%d.conf", index); - else - bootconf_name = g_strdup_printf ("ostree-%d-%s.conf", index, osname); + g_autofree char *bootconf_name = bootloader_entry_filename (sysroot, n_deployments, deployment); + if (!glnx_shutil_mkdir_p_at (sysroot->boot_fd, bootcsumdir, 0775, cancellable, error)) return FALSE; @@ -2313,6 +2383,12 @@ deployment_bootconfigs_equal (OstreeRepo *repo, OstreeDeployment *a, OstreeDeplo if (g_strcmp0 (a_version, b_version) != 0) return FALSE; + /* same stateroot? */ + const char *a_stateroot = ostree_deployment_get_osname (a); + const char *b_stateroot = ostree_deployment_get_osname (b); + if (g_strcmp0 (a_stateroot, b_stateroot) != 0) + return FALSE; + return TRUE; } @@ -2450,7 +2526,8 @@ write_deployments_finish (OstreeSysroot *self, GCancellable *cancellable, GError } static gboolean -add_file_size_if_nonnull (int dfd, const char *path, guint64 *inout_size, GError **error) +add_file_size_if_nonnull (int dfd, const char *path, guint64 blocksize, guint64 *inout_size, + GError **error) { if (path == NULL) return TRUE; @@ -2460,14 +2537,21 @@ add_file_size_if_nonnull (int dfd, const char *path, guint64 *inout_size, GError return FALSE; *inout_size += stbuf.st_size; + if (blocksize > 0) + { + off_t rem = stbuf.st_size % blocksize; + if (rem > 0) + *inout_size += blocksize - rem; + } + return TRUE; } /* calculates the total size of the bootcsum dir in /boot after we would copy * it. This reflects the logic in install_deployment_kernel(). */ static gboolean -get_kernel_layout_size (OstreeSysroot *self, OstreeDeployment *deployment, guint64 *out_size, - GCancellable *cancellable, GError **error) +get_kernel_layout_size (OstreeSysroot *self, OstreeDeployment *deployment, guint64 blocksize, + guint64 *out_size, GCancellable *cancellable, GError **error) { g_autofree char *deployment_dirpath = ostree_sysroot_get_deployment_dirpath (self, deployment); glnx_autofd int deployment_dfd = -1; @@ -2479,11 +2563,11 @@ get_kernel_layout_size (OstreeSysroot *self, OstreeDeployment *deployment, guint return FALSE; guint64 bootdir_size = 0; - if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->kernel_srcpath, + if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->kernel_srcpath, blocksize, &bootdir_size, error)) return FALSE; if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->initramfs_srcpath, - &bootdir_size, error)) + blocksize, &bootdir_size, error)) return FALSE; if (kernel_layout->devicetree_srcpath) { @@ -2491,22 +2575,22 @@ get_kernel_layout_size (OstreeSysroot *self, OstreeDeployment *deployment, guint if (kernel_layout->devicetree_namever) { if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath, - &bootdir_size, error)) + blocksize, &bootdir_size, error)) return FALSE; } else { guint64 dirsize = 0; if (!ot_get_dir_size (kernel_layout->boot_dfd, kernel_layout->devicetree_srcpath, - &dirsize, cancellable, error)) + blocksize, &dirsize, cancellable, error)) return FALSE; bootdir_size += dirsize; } } if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->kernel_hmac_srcpath, - &bootdir_size, error)) + blocksize, &bootdir_size, error)) return FALSE; - if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->aboot_srcpath, + if (!add_file_size_if_nonnull (kernel_layout->boot_dfd, kernel_layout->aboot_srcpath, blocksize, &bootdir_size, error)) return FALSE; @@ -2533,6 +2617,9 @@ dfd_fallocate_check (int dfd, off_t len, gboolean *out_passed, GError **error) if (!glnx_open_tmpfile_linkable_at (dfd, ".", O_WRONLY | O_CLOEXEC, &tmpf, error)) return FALSE; + /* add the safety margin */ + len += EARLY_PRUNE_SAFETY_MARGIN_SIZE; + *out_passed = TRUE; /* There's glnx_try_fallocate, but not with the same error semantics. */ if (TEMP_FAILURE_RETRY (fallocate (tmpf.fd, 0, 0, len)) < 0) @@ -2560,6 +2647,9 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment if (self->booted_deployment == NULL) return TRUE; + if (!_ostree_sysroot_ensure_boot_fd (self, error)) + return FALSE; + { struct stat stbuf; if (!glnx_fstatat (self->boot_fd, ".", &stbuf, 0, error)) @@ -2583,6 +2673,11 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment g_autoptr (GHashTable) new_bootcsums = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + /* get bootfs block size */ + struct statvfs stvfsbuf; + if (TEMP_FAILURE_RETRY (fstatvfs (self->boot_fd, &stvfsbuf)) < 0) + return glnx_throw_errno_prefix (error, "fstatvfs(boot)"); + g_auto (GStrv) bootdirs = NULL; if (!_ostree_sysroot_list_all_boot_directories (self, &bootdirs, cancellable, error)) return glnx_prefix_error (error, "listing bootcsum directories in bootfs"); @@ -2597,7 +2692,8 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment guint64 bootdir_size; g_autofree char *ostree_bootdir = g_build_filename ("ostree", bootdir, NULL); - if (!ot_get_dir_size (self->boot_fd, ostree_bootdir, &bootdir_size, cancellable, error)) + if (!ot_get_dir_size (self->boot_fd, ostree_bootdir, stvfsbuf.f_bsize, &bootdir_size, + cancellable, error)) return FALSE; /* for our purposes of sizing bootcsums, it's highly unlikely we need a @@ -2609,10 +2705,7 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment * that users report it and we tweak this code to handle this. * * An alternative is working with the block size instead, which would - * be easier to handle. But ideally, `ot_get_dir_size` would be block - * size aware too for better accuracy, which is awkward since the - * function itself is generic over directories and doesn't consider - * e.g. mount points from different filesystems. */ + * be easier to handle. */ g_printerr ("bootcsum %s size exceeds %u; disabling auto-prune optimization\n", bootdir, G_MAXUINT); return TRUE; @@ -2640,7 +2733,8 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment } guint64 bootdir_size = 0; - if (!get_kernel_layout_size (self, deployment, &bootdir_size, cancellable, error)) + if (!get_kernel_layout_size (self, deployment, stvfsbuf.f_bsize, &bootdir_size, cancellable, + error)) return FALSE; /* see similar logic in previous loop */ @@ -2657,6 +2751,7 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment /* it wasn't in current_bootcsums; add */ net_new_bootcsum_dirs_total_size += bootdir_size; } + g_autofree char *net_new_formatted = g_format_size (net_new_bootcsum_dirs_total_size); { gboolean bootfs_has_space = FALSE; @@ -2667,9 +2762,13 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment /* does the bootfs have enough free space for temporarily holding both the new * and old bootdirs? */ if (bootfs_has_space) - return TRUE; /* nothing to do! */ + { + g_printerr ("bootfs is sufficient for calculated new size: %s\n", net_new_formatted); + return TRUE; /* nothing to do! */ + } } + g_printerr ("bootfs requires additional space: %s\n", net_new_formatted); /* OK, we would fail if we tried to write the new bootdirs. Is it salvageable? * First, calculate how much space we could save with the bootcsums scheduled * for removal. */ @@ -2680,6 +2779,11 @@ auto_early_prune_old_deployments (OstreeSysroot *self, GPtrArray *new_deployment bootcsum_dirs_to_remove_total_size += GPOINTER_TO_UINT (sizep); } + { + g_autofree char *to_remove_formated = g_format_size (bootcsum_dirs_to_remove_total_size); + g_printerr ("Size to prune from bootfs: %s\n", to_remove_formated); + } + if (net_new_bootcsum_dirs_total_size > bootcsum_dirs_to_remove_total_size) { /* Check whether if we did early prune, we'd have enough space to write @@ -3016,33 +3120,81 @@ _ostree_deployment_set_bootconfig_from_kargs (OstreeDeployment *deployment, } } -// Perform some basic static analysis and emit warnings for things -// that are likely to fail later. This function only returns -// a hard error if something unexpected (e.g. I/O error) occurs. +// If the stateroot /var is uninitialized, copy the /var content from the deployment. +// This is intended to mirror the semantics of Docker volumes. static gboolean -lint_deployment_fs (OstreeSysroot *self, OstreeDeployment *deployment, int deployment_dfd, - GCancellable *cancellable, GError **error) +prepare_deployment_var (OstreeSysroot *self, OstreeDeployment *deployment, int deployment_dfd, + GCancellable *cancellable, GError **error) { - g_auto (GLnxDirFdIterator) dfd_iter = { - 0, - }; - gboolean exists; + GLNX_AUTO_PREFIX_ERROR ("Preparing deployment /var", error); + + // Does the deployment have a var? If not, we're done. (Though this will probably + // cause problems at boot time) + { + g_auto (GLnxDirFdIterator) dfd_iter = { + 0, + }; + gboolean exists; - if (!ot_dfd_iter_init_allow_noent (deployment_dfd, "var", &dfd_iter, &exists, error)) + if (!ot_dfd_iter_init_allow_noent (deployment_dfd, "var", &dfd_iter, &exists, error)) + return FALSE; + if (!exists) + { + g_debug ("deployment has no /var"); + return TRUE; + } + } + + // Open the stateroot which holds the shared /var + const char *stateroot = ostree_deployment_get_osname (deployment); + g_autofree char *stateroot_path = g_build_filename ("ostree/deploy/", stateroot, "var", NULL); + glnx_autofd int stateroot_dfd = -1; + if (!glnx_opendirat (self->sysroot_fd, stateroot_path, FALSE, &stateroot_dfd, error)) + return glnx_prefix_error (error, "Opening stateroot"); + + // Check if the stateroot is empty + { + g_auto (GLnxDirFdIterator) dfd_iter = { + 0, + }; + + if (!glnx_dirfd_iterator_init_at (stateroot_dfd, ".", FALSE, &dfd_iter, error)) + return FALSE; + + struct dirent *dent; + + if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) + return FALSE; + + if (dent != NULL) + { + // We found existing content in the stateroot var, so we're done. + // There is no merge semantics. + g_debug ("Stateroot %s is non-empty", stateroot); + return TRUE; + } + } + + g_debug ("Copying initial deployment /var"); + // At this point we should initialize the stateroot var with the content from + // the commit/image. Note we need to force a copy; hopefully reflinks are available. + OstreeRepoCheckoutAtOptions co_opts + = { .force_copy = TRUE, + .subpath = "/var", + .overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES }; + if (!ostree_repo_checkout_at (self->repo, &co_opts, stateroot_dfd, ".", + ostree_deployment_get_csum (deployment), cancellable, error)) return FALSE; - while (exists) - { - struct dirent *dent; - if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) + if (!glnx_fstatat_allow_noent (deployment_dfd, USRLIB_TMPFILES, NULL, AT_SYMLINK_NOFOLLOW, error)) + return glnx_prefix_error (error, "Querying %s", USRLIB_TMPFILES); + if (errno == ENOENT) + { + g_debug ("deployment has no %s", USRLIB_TMPFILES); + // OK, this OS doesn't appear to use systemd (or tmpfiles.d at least). For full + // backwards compatibility we create some standard things in the stateroot var. + if (!_ostree_sysroot_stateroot_legacy_var_init (stateroot_dfd, error)) return FALSE; - if (dent == NULL) - break; - - fprintf ( - stderr, - "note: Deploying commit %s which contains content in /var/%s that will be ignored.\n", - ostree_deployment_get_csum (deployment), dent->d_name); } return TRUE; @@ -3078,6 +3230,10 @@ sysroot_initialize_deployment (OstreeSysroot *self, const char *osname, const ch if (!require_stateroot (self, osname, error)) return FALSE; + g_autofree char *stateroot_backing = g_strdup_printf ("ostree/deploy/%s/backing", osname); + if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, stateroot_backing, 0700, cancellable, error)) + return glnx_prefix_error (error, "Creating backing directory"); + OstreeRepo *repo = ostree_sysroot_repo (self); gint new_deployserial; @@ -3106,7 +3262,7 @@ sysroot_initialize_deployment (OstreeSysroot *self, const char *osname, const ch if (!prepare_deployment_etc (self, repo, new_deployment, deployment_dfd, cancellable, error)) return FALSE; - if (!lint_deployment_fs (self, new_deployment, deployment_dfd, cancellable, error)) + if (!prepare_deployment_var (self, new_deployment, deployment_dfd, cancellable, error)) return FALSE; ot_transfer_out_value (out_new_deployment, &new_deployment); @@ -3151,7 +3307,6 @@ get_var_dfd (OstreeSysroot *self, int osdeploy_dfd, OstreeDeployment *deployment return glnx_opendirat (base_dfd, base_path, TRUE, ret_fd, error); } -#ifdef HAVE_SELINUX static void child_setup_fchdir (gpointer data) { @@ -3164,87 +3319,88 @@ child_setup_fchdir (gpointer data) /* * Derived from rpm-ostree's rust/src/bwrap.rs */ -static gboolean -run_in_deployment (int deployment_dfd, const gchar *const *child_argv, gsize child_argc, - gint *exit_status, gchar **stdout, GError **error) -{ - static const gchar *const COMMON_ARGV[] = { - "/usr/bin/bwrap", - "--dev", - "/dev", - "--proc", - "/proc", - "--dir", - "/run", - "--dir", - "/tmp", - "--chdir", - "/", - "--die-with-parent", - "--unshare-pid", - "--unshare-uts", - "--unshare-ipc", - "--unshare-cgroup-try", - "--ro-bind", - "/sys/block", - "/sys/block", - "--ro-bind", - "/sys/bus", - "/sys/bus", - "--ro-bind", - "/sys/class", - "/sys/class", - "--ro-bind", - "/sys/dev", - "/sys/dev", - "--ro-bind", - "/sys/devices", - "/sys/devices", - "--bind", - "usr", - "/usr", - "--bind", - "etc", - "/etc", - "--bind", - "var", - "/var", - "--symlink", - "/usr/lib", - "/lib", - "--symlink", - "/usr/lib32", - "/lib32", - "--symlink", - "/usr/lib64", - "/lib64", - "--symlink", - "/usr/bin", - "/bin", - "--symlink", - "/usr/sbin", - "/sbin", - }; - static const gsize COMMON_ARGC = sizeof (COMMON_ARGV) / sizeof (*COMMON_ARGV); - - gsize i; - GPtrArray *args = g_ptr_array_sized_new (COMMON_ARGC + child_argc + 1); - g_autofree gchar **args_raw = NULL; - - for (i = 0; i < COMMON_ARGC; i++) - g_ptr_array_add (args, (gchar *)COMMON_ARGV[i]); - - for (i = 0; i < child_argc; i++) - g_ptr_array_add (args, (gchar *)child_argv[i]); +gboolean +_ostree_sysroot_run_in_deployment (int deployment_dfd, const char *const *bwrap_argv, + const gchar *const *child_argv, gint *exit_status, + gchar **stdout, GError **error) +{ + static const gchar *const COMMON_ARGV[] = { "/usr/bin/bwrap", + "--dev", + "/dev", + "--proc", + "/proc", + "--dir", + "/run", + "--dir", + "/tmp", + "--chdir", + "/", + "--die-with-parent", + "--unshare-pid", + "--unshare-uts", + "--unshare-ipc", + "--unshare-cgroup-try", + "--ro-bind", + "/sys/block", + "/sys/block", + "--ro-bind", + "/sys/bus", + "/sys/bus", + "--ro-bind", + "/sys/class", + "/sys/class", + "--ro-bind", + "/sys/dev", + "/sys/dev", + "--ro-bind", + "/sys/devices", + "/sys/devices", + "--bind", + "usr", + "/usr", + "--bind", + "etc", + "/etc", + "--bind", + "var", + "/var", + "--symlink", + "/usr/lib", + "/lib", + "--symlink", + "/usr/lib32", + "/lib32", + "--symlink", + "/usr/lib64", + "/lib64", + "--symlink", + "/usr/bin", + "/bin", + "--symlink", + "/usr/sbin", + "/sbin", + NULL }; + + g_autoptr (GPtrArray) args = g_ptr_array_new (); + + for (char **it = (char **)COMMON_ARGV; it && *it; it++) + g_ptr_array_add (args, *it); + for (char **it = (char **)bwrap_argv; it && *it; it++) + g_ptr_array_add (args, *it); + + // Separate bwrap args from child args + g_ptr_array_add (args, "--"); + + for (char **it = (char **)child_argv; it && *it; it++) + g_ptr_array_add (args, *it); g_ptr_array_add (args, NULL); - args_raw = (gchar **)g_ptr_array_free (args, FALSE); - - return g_spawn_sync (NULL, args_raw, NULL, 0, &child_setup_fchdir, + return g_spawn_sync (NULL, (char **)args->pdata, NULL, 0, &child_setup_fchdir, (gpointer)(uintptr_t)deployment_dfd, stdout, NULL, exit_status, error); } +#ifdef HAVE_SELINUX /* * Run semodule to check if the module content changed after merging /etc * and rebuild the policy if needed. @@ -3269,11 +3425,9 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) * Skip the SELinux policy refresh if the --refresh * flag is not supported by semodule. */ - static const gchar *const SEMODULE_HELP_ARGV[] = { "semodule", "--help" }; - static const gsize SEMODULE_HELP_ARGC - = sizeof (SEMODULE_HELP_ARGV) / sizeof (*SEMODULE_HELP_ARGV); - if (!run_in_deployment (deployment_dfd, SEMODULE_HELP_ARGV, SEMODULE_HELP_ARGC, &exit_status, - &stdout, error)) + static const gchar *const SEMODULE_HELP_ARGV[] = { "semodule", "--help", NULL }; + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, NULL, SEMODULE_HELP_ARGV, &exit_status, + &stdout, error)) return FALSE; if (!g_spawn_check_exit_status (exit_status, error)) return glnx_prefix_error (error, "failed to run semodule"); @@ -3283,14 +3437,12 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) return TRUE; } - static const gchar *const SEMODULE_REBUILD_ARGV[] = { "semodule", "-N", "--refresh" }; - static const gsize SEMODULE_REBUILD_ARGC - = sizeof (SEMODULE_REBUILD_ARGV) / sizeof (*SEMODULE_REBUILD_ARGV); + static const gchar *const SEMODULE_REBUILD_ARGV[] = { "semodule", "-N", "--refresh", NULL }; ot_journal_print (LOG_INFO, "Refreshing SELinux policy"); guint64 start_msec = g_get_monotonic_time () / 1000; - if (!run_in_deployment (deployment_dfd, SEMODULE_REBUILD_ARGV, SEMODULE_REBUILD_ARGC, - &exit_status, NULL, error)) + if (!_ostree_sysroot_run_in_deployment (deployment_dfd, NULL, SEMODULE_REBUILD_ARGV, &exit_status, + NULL, error)) return FALSE; guint64 end_msec = g_get_monotonic_time () / 1000; ot_journal_print (LOG_INFO, "Refreshed SELinux policy in %" G_GUINT64_FORMAT " ms", @@ -3299,6 +3451,49 @@ sysroot_finalize_selinux_policy (int deployment_dfd, GError **error) } #endif /* HAVE_SELINUX */ +static gboolean +sysroot_initialize_deployment_backing (OstreeSysroot *self, OstreeDeployment *deployment, + OstreeSePolicy *sepolicy, GError **error) +{ + GLNX_AUTO_PREFIX_ERROR ("Preparing deployment backing dir", error); + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); + g_autofree char *backing_relpath = _ostree_sysroot_get_deployment_backing_relpath (deployment); + struct stat stbuf; + + if (!glnx_fstatat (self->sysroot_fd, deployment_path, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + + // Create the "backing" directory with additional data */ + if (!glnx_ensure_dir (self->sysroot_fd, backing_relpath, 0700, error)) + return glnx_prefix_error (error, "Creating backing dir"); + + // The root-transient holds overlayfs directories for the root + g_autofree char *rootovldir + = g_build_filename (backing_relpath, OSTREE_DEPLOYMENT_ROOT_TRANSIENT_DIR, NULL); + if (!glnx_ensure_dir (self->sysroot_fd, rootovldir, 0700, error)) + return glnx_prefix_error (error, "Creating root ovldir"); + + // The overlayfs work (subdirectory of root-transient) + g_autofree char *workdir = g_build_filename (rootovldir, "work", NULL); + if (!glnx_ensure_dir (self->sysroot_fd, workdir, 0700, error)) + return glnx_prefix_error (error, "Creating work dir"); + + // Create the overlayfs upper; this needs to have the same mode and SELinux label as the root + { + g_auto (OstreeSepolicyFsCreatecon) con = { + 0, + }; + + if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, "/", stbuf.st_mode, error)) + return glnx_prefix_error (error, "Looking up SELinux label for /"); + g_autofree char *upperdir = g_build_filename (rootovldir, "upper", NULL); + if (!glnx_ensure_dir (self->sysroot_fd, upperdir, stbuf.st_mode, error)) + return glnx_prefix_error (error, "Creating upper dir"); + } + + return TRUE; +} + static gboolean sysroot_finalize_deployment (OstreeSysroot *self, OstreeDeployment *deployment, OstreeDeployment *merge_deployment, GCancellable *cancellable, @@ -3364,6 +3559,9 @@ sysroot_finalize_deployment (OstreeSysroot *self, OstreeDeployment *deployment, if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, cancellable, error)) return FALSE; + if (!sysroot_initialize_deployment_backing (self, deployment, sepolicy, error)) + return FALSE; + /* Rewrite the origin using the final merged selinux config, just to be * conservative about getting the right labels. */ @@ -3657,6 +3855,10 @@ ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, const char *osname, g_autoptr (GVariantBuilder) builder = g_variant_builder_new ((GVariantType *)"a{sv}"); g_variant_builder_add (builder, "{sv}", "target", serialize_deployment_to_variant (deployment)); + if (opts->locked) + g_variant_builder_add (builder, "{sv}", _OSTREE_SYSROOT_STAGED_KEY_LOCKED, + g_variant_new_boolean (TRUE)); + if (merge_deployment) g_variant_builder_add (builder, "{sv}", "merge-deployment", serialize_deployment_to_variant (merge_deployment)); @@ -3706,6 +3908,73 @@ ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, const char *osname, return TRUE; } +/** + * ostree_sysroot_change_finalization: + * @self: Sysroot + * @deployment: Deployment which must be staged + * @error: Error + * + * Given the target deployment (which must be the staged deployment) this API + * will toggle its "finalization locking" state. If it is currently locked, + * it will be unlocked (and hence queued to apply on shutdown). + * + * Since: 2023.8 + */ +_OSTREE_PUBLIC +gboolean +ostree_sysroot_change_finalization (OstreeSysroot *self, OstreeDeployment *deployment, + GError **error) +{ + GCancellable *cancellable = NULL; + g_assert (ostree_deployment_is_staged (deployment)); + + gboolean new_locked_state = !ostree_deployment_is_finalization_locked (deployment); + + /* Read the staged state from disk */ + glnx_autofd int fd = -1; + if (!glnx_openat_rdonly (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED, TRUE, &fd, error)) + return FALSE; + + g_autoptr (GBytes) contents = ot_fd_readall_or_mmap (fd, 0, error); + if (!contents) + return FALSE; + g_autoptr (GVariant) staged_deployment_data + = g_variant_new_from_bytes ((GVariantType *)"a{sv}", contents, TRUE); + g_autoptr (GVariantDict) staged_deployment_dict = g_variant_dict_new (staged_deployment_data); + + g_variant_dict_insert (staged_deployment_dict, _OSTREE_SYSROOT_STAGED_KEY_LOCKED, "b", + new_locked_state); + g_autoptr (GVariant) new_staged_deployment_data = g_variant_dict_end (staged_deployment_dict); + + if (!glnx_file_replace_contents_at (fd, _OSTREE_SYSROOT_RUNSTATE_STAGED, + g_variant_get_data (new_staged_deployment_data), + g_variant_get_size (new_staged_deployment_data), + GLNX_FILE_REPLACE_NODATASYNC, cancellable, error)) + return FALSE; + + if (!new_locked_state) + { + /* Delete the legacy lock if there was any. */ + if (!ot_ensure_unlinked_at (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED, error)) + return FALSE; + } + else + { + /* Create the legacy lockfile; see also the code in ot-admin-builtin-deploy.c */ + if (!glnx_shutil_mkdir_p_at (AT_FDCWD, + dirname (strdupa (_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED)), 0755, + cancellable, error)) + return FALSE; + + glnx_autofd int lockfd = open (_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED, + O_CREAT | O_WRONLY | O_NOCTTY | O_CLOEXEC, 0640); + if (lockfd == -1) + return glnx_throw_errno_prefix (error, "touch(%s)", _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED); + } + + return TRUE; +} + /* Invoked at shutdown time by ostree-finalize-staged.service */ static gboolean _ostree_sysroot_finalize_staged_inner (OstreeSysroot *self, GCancellable *cancellable, @@ -3722,11 +3991,22 @@ _ostree_sysroot_finalize_staged_inner (OstreeSysroot *self, GCancellable *cancel } /* Check if finalization is locked. */ - if (!glnx_fstatat_allow_noent (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED, NULL, 0, error)) - return FALSE; - if (errno == 0) + gboolean locked = false; + (void)g_variant_lookup (self->staged_deployment_data, _OSTREE_SYSROOT_STAGED_KEY_LOCKED, "b", + &locked); + if (locked) + g_debug ("staged is locked via metadata"); + else + { + if (!glnx_fstatat_allow_noent (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED, NULL, 0, + error)) + return FALSE; + if (errno == 0) + locked = TRUE; + } + if (locked) { - ot_journal_print (LOG_INFO, "Not finalizing; found " _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED); + ot_journal_print (LOG_INFO, "Not finalizing; deployment is locked for finalization"); return TRUE; } @@ -3967,9 +4247,8 @@ ostree_sysroot_deployment_set_kargs_in_place (OstreeSysroot *self, OstreeDeploym OstreeBootconfigParser *new_bootconfig = ostree_deployment_get_bootconfig (deployment); ostree_bootconfig_parser_set (new_bootconfig, "options", kargs_str); - g_autofree char *bootconf_name = g_strdup_printf ( - "ostree-%d-%s.conf", self->deployments->len - ostree_deployment_get_index (deployment), - ostree_deployment_get_osname (deployment)); + g_autofree char *bootconf_name + = bootloader_entry_filename (self, self->deployments->len, deployment); g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", self->bootversion); glnx_autofd int bootconf_dfd = -1; diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 8e6945b..3dd6939 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -45,7 +45,7 @@ typedef enum OSTREE_SYSROOT_GLOBAL_OPT_SKIP_SYNC = 1 << 0, /* See https://github.com/ostreedev/ostree/pull/2847 */ OSTREE_SYSROOT_GLOBAL_OPT_NO_EARLY_PRUNE = 1 << 1, - OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_2 = 1 << 2, + OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_1 = 1 << 2, } OstreeSysrootGlobalOptFlags; typedef enum @@ -74,8 +74,9 @@ struct OstreeSysroot /* The device/inode for / and /etc, used to detect booted deployment */ dev_t root_device; ino_t root_inode; - dev_t etc_device; - ino_t etc_inode; + + // The parsed data from /run/ostree + GVariantDict *run_ostree_metadata; gboolean is_physical; /* TRUE if we're pointed at physical storage root and not a deployment */ GPtrArray *deployments; @@ -84,6 +85,8 @@ struct OstreeSysroot OstreeDeployment *booted_deployment; OstreeDeployment *staged_deployment; GVariant *staged_deployment_data; + // True if loaded_ts is initialized + gboolean has_loaded; struct timespec loaded_ts; /* Only access through ostree_sysroot_[_get]repo() */ @@ -93,6 +96,9 @@ struct OstreeSysroot OstreeSysrootDebugFlags debug_flags; }; +/* Key in staged deployment variant for finalization locking */ +#define _OSTREE_SYSROOT_STAGED_KEY_LOCKED "locked" + #define OSTREE_SYSROOT_LOCKFILE "ostree/lock" /* We keep some transient state in /run */ #define _OSTREE_SYSROOT_RUNSTATE_STAGED "/run/ostree/staged-deployment" @@ -139,14 +145,19 @@ gboolean _ostree_sysroot_boot_complete (OstreeSysroot *self, GCancellable *cance OstreeDeployment *_ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, GError **error); -char *_ostree_sysroot_get_origin_relpath (GFile *path, guint32 *out_device, guint64 *out_inode, - GCancellable *cancellable, GError **error); +char *_ostree_sysroot_get_deployment_backing_relpath (OstreeDeployment *deployment); gboolean _ostree_sysroot_rmrf_deployment (OstreeSysroot *sysroot, OstreeDeployment *deployment, GCancellable *cancellable, GError **error); +gboolean _ostree_sysroot_stateroot_legacy_var_init (int dfd, GError **error); + char *_ostree_sysroot_get_runstate_path (OstreeDeployment *deployment, const char *key); +gboolean _ostree_sysroot_run_in_deployment (int deployment_dfd, const char *const *bwrap_argv, + const gchar *const *child_argv, gint *exit_status, + gchar **stdout, GError **error); + char *_ostree_sysroot_join_lines (GPtrArray *lines); gboolean _ostree_sysroot_ensure_boot_fd (OstreeSysroot *self, GError **error); diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 91b63f9..af9e07c 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -36,7 +36,7 @@ #include "ostree-repo-private.h" #include "ostree-sepolicy-private.h" #include "ostree-sysroot-private.h" -#include "ostree.h" +#include "otcore.h" /** * SECTION:ostree-sysroot @@ -83,6 +83,7 @@ ostree_sysroot_finalize (GObject *object) g_clear_object (&self->path); g_clear_object (&self->repo); + g_clear_pointer (&self->run_ostree_metadata, g_variant_dict_unref); g_clear_pointer (&self->deployments, g_ptr_array_unref); g_clear_object (&self->booted_deployment); g_clear_object (&self->staged_deployment); @@ -180,7 +181,7 @@ ostree_sysroot_init (OstreeSysroot *self) const GDebugKey globalopt_keys[] = { { "skip-sync", OSTREE_SYSROOT_GLOBAL_OPT_SKIP_SYNC }, { "no-early-prune", OSTREE_SYSROOT_GLOBAL_OPT_NO_EARLY_PRUNE }, - { "bootloader-naming-2", OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_2 }, + { "bootloader-naming-1", OSTREE_SYSROOT_GLOBAL_OPT_BOOTLOADER_NAMING_1 }, }; const GDebugKey keys[] = { { "mutable-deployments", OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS }, @@ -774,6 +775,9 @@ parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment * g_autofree char *osname = NULL; g_autofree char *bootcsum = NULL; int treebootserial = -1; + + // Note is_boot should always be false here, this boot_link is taken from BLS file, not + // /proc/cmdline, BLS files are present in aboot images if (!_ostree_sysroot_parse_bootlink (boot_link, &entry_boot_version, &osname, &bootcsum, &treebootserial, error)) return FALSE; @@ -808,26 +812,35 @@ parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment * if (looking_for_booted_deployment) { struct stat stbuf; - struct stat etc_stbuf = {}; if (!glnx_fstat (deployment_dfd, &stbuf, error)) return FALSE; - /* We look for either the root or the etc subdir of the - * deployment. We need to do this, because when using composefs, - * the root is not a bind mount of the deploy dir, but the etc - * dir is. + /* ostree-prepare-root records the (device, inode) pair of the underlying real deployment + * directory (before we might have mounted a composefs or overlayfs on top). + * + * Because this parser is operating outside the mounted namespace, we compare against + * that backing directory. */ - - if (!glnx_fstatat_allow_noent (deployment_dfd, "etc", &etc_stbuf, 0, error)) - return FALSE; + g_assert (self->run_ostree_metadata); + guint64 expected_root_dev = 0; + guint64 expected_root_inode = 0; + if (!g_variant_dict_lookup (self->run_ostree_metadata, + OTCORE_RUN_BOOTED_KEY_BACKING_ROOTDEVINO, "(tt)", + &expected_root_dev, &expected_root_inode)) + { + g_debug ("Missing %s", OTCORE_RUN_BOOTED_KEY_BACKING_ROOTDEVINO); + expected_root_dev = (guint64)self->root_device; + expected_root_inode = (guint64)self->root_inode; + } + else + g_debug ("Target rootdev key %s found", OTCORE_RUN_BOOTED_KEY_BACKING_ROOTDEVINO); /* A bit ugly, we're assigning to a sysroot-owned variable from deep in * this parsing code. But eh, if something fails the sysroot state can't * be relied on anyways. */ is_booted_deployment - = (stbuf.st_dev == self->root_device && stbuf.st_ino == self->root_inode) - || (etc_stbuf.st_dev == self->etc_device && etc_stbuf.st_ino == self->etc_inode); + = stbuf.st_dev == expected_root_dev && stbuf.st_ino == expected_root_inode; } g_autoptr (OstreeDeployment) ret_deployment @@ -1016,10 +1029,21 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error) * we'll use it to sanity check that we found a booted deployment for example. * Second, we also find out whether sysroot == /. */ - if (!glnx_fstatat_allow_noent (AT_FDCWD, OSTREE_PATH_BOOTED, NULL, 0, error)) + glnx_autofd int booted_state_fd = -1; + if (!ot_openat_ignore_enoent (AT_FDCWD, OSTREE_PATH_BOOTED, &booted_state_fd, error)) return FALSE; - const gboolean ostree_booted = (errno == 0); + const gboolean ostree_booted = booted_state_fd != -1; + + if (booted_state_fd != -1) + { + g_autoptr (GVariant) ostree_run_metadata_v = NULL; + if (!ot_variant_read_fd (booted_state_fd, 0, G_VARIANT_TYPE_VARDICT, TRUE, + &ostree_run_metadata_v, error)) + return glnx_prefix_error (error, "failed to read %s", OTCORE_RUN_BOOTED); + self->run_ostree_metadata = g_variant_dict_new (ostree_run_metadata_v); + } + // Gather the root device/inode { struct stat root_stbuf; if (!glnx_fstatat (AT_FDCWD, "/", &root_stbuf, 0, error)) @@ -1028,17 +1052,6 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error) self->root_inode = root_stbuf.st_ino; } - { - struct stat etc_stbuf; - if (!glnx_fstatat_allow_noent (AT_FDCWD, "/etc", &etc_stbuf, 0, error)) - return FALSE; - if (errno != ENOENT) - { - self->etc_device = etc_stbuf.st_dev; - self->etc_inode = etc_stbuf.st_ino; - } - } - struct stat self_stbuf; if (!glnx_fstatat (AT_FDCWD, gs_file_get_path_cached (self->path), &self_stbuf, 0, error)) return FALSE; @@ -1047,6 +1060,7 @@ ostree_sysroot_initialize (OstreeSysroot *self, GError **error) = (self->root_device == self_stbuf.st_dev && self->root_inode == self_stbuf.st_ino); self->root_is_ostree_booted = (ostree_booted && root_is_sysroot); + g_debug ("root_is_ostree_booted: %d", self->root_is_ostree_booted); self->loadstate = OSTREE_SYSROOT_LOAD_STATE_INIT; } @@ -1106,6 +1120,8 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, GError **error) * canonical "staged_deployment" reference. */ self->staged_deployment->staged = TRUE; + (void)g_variant_dict_lookup (staged_deployment_dict, _OSTREE_SYSROOT_STAGED_KEY_LOCKED, + "b", &self->staged_deployment->finalization_locked); } } @@ -1245,7 +1261,7 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self, gboolean *out_changed, if (!glnx_fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0, error)) return FALSE; - if (self->loaded_ts.tv_sec == stbuf.st_mtim.tv_sec + if (self->has_loaded && self->loaded_ts.tv_sec == stbuf.st_mtim.tv_sec && self->loaded_ts.tv_nsec == stbuf.st_mtim.tv_nsec) { if (out_changed) @@ -1264,6 +1280,7 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self, gboolean *out_changed, return FALSE; self->loaded_ts = stbuf.st_mtim; + self->has_loaded = TRUE; if (out_changed) *out_changed = TRUE; @@ -1779,6 +1796,46 @@ ostree_sysroot_lock_finish (OstreeSysroot *self, GAsyncResult *result, GError ** return g_task_propagate_boolean ((GTask *)result, error); } +// This is a legacy subset of what happens normally via systemd tmpfiles.d; +// it is only run in the case that the deployment it self comes without +// usr/lib/tmpfiles.d +gboolean +_ostree_sysroot_stateroot_legacy_var_init (int dfd, GError **error) +{ + GLNX_AUTO_PREFIX_ERROR ("Legacy mode stateroot var initialization", error); + + /* This is a bit of a legacy hack...but we have to keep it around + * now. We're ensuring core subdirectories of /var exist. + */ + if (!glnx_ensure_dir (dfd, "tmp", 0777, error)) + return FALSE; + + if (fchmodat (dfd, "tmp", 01777, 0) < 0) + return glnx_throw_errno_prefix (error, "fchmod %s", "var/tmp"); + + if (!glnx_ensure_dir (dfd, "lib", 0777, error)) + return FALSE; + + /* This needs to be available and properly labeled early during the boot + * process (before tmpfiles.d kicks in), so that journald can flush logs from + * the first boot there. https://bugzilla.redhat.com/show_bug.cgi?id=1265295 + * */ + if (!glnx_ensure_dir (dfd, "log", 0755, error)) + return FALSE; + + if (!glnx_fstatat_allow_noent (dfd, "run", NULL, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT && symlinkat ("../run", dfd, "run") < 0) + return glnx_throw_errno_prefix (error, "Symlinking %s", "var/run"); + + if (!glnx_fstatat_allow_noent (dfd, "lock", NULL, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT && symlinkat ("../run/lock", dfd, "lock") < 0) + return glnx_throw_errno_prefix (error, "Symlinking %s", "var/lock"); + + return TRUE; +} + /** * ostree_sysroot_init_osname: * @self: Sysroot @@ -1810,31 +1867,6 @@ ostree_sysroot_init_osname (OstreeSysroot *self, const char *osname, GCancellabl if (mkdirat (dfd, "var", 0777) < 0) return glnx_throw_errno_prefix (error, "Creating %s", "var"); - /* This is a bit of a legacy hack...but we have to keep it around - * now. We're ensuring core subdirectories of /var exist. - */ - if (mkdirat (dfd, "var/tmp", 0777) < 0) - return glnx_throw_errno_prefix (error, "Creating %s", "var/tmp"); - - if (fchmodat (dfd, "var/tmp", 01777, 0) < 0) - return glnx_throw_errno_prefix (error, "fchmod %s", "var/tmp"); - - if (mkdirat (dfd, "var/lib", 0777) < 0) - return glnx_throw_errno_prefix (error, "Creating %s", "var/lib"); - - /* This needs to be available and properly labeled early during the boot - * process (before tmpfiles.d kicks in), so that journald can flush logs from - * the first boot there. https://bugzilla.redhat.com/show_bug.cgi?id=1265295 - * */ - if (mkdirat (dfd, "var/log", 0755) < 0) - return glnx_throw_errno_prefix (error, "Creating %s", "var/log"); - - if (symlinkat ("../run", dfd, "var/run") < 0) - return glnx_throw_errno_prefix (error, "Symlinking %s", "var/run"); - - if (symlinkat ("../run/lock", dfd, "var/lock") < 0) - return glnx_throw_errno_prefix (error, "Symlinking %s", "var/lock"); - if (!_ostree_sysroot_bump_mtime (self, error)) return FALSE; @@ -1963,6 +1995,17 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, const char *osna return TRUE; } +/* Return the sysroot-relative path to the "backing" directory of a deployment + * which can hold additional data. + */ +char * +_ostree_sysroot_get_deployment_backing_relpath (OstreeDeployment *deployment) +{ + return g_strdup_printf ( + "ostree/deploy/%s/backing/%s.%d", ostree_deployment_get_osname (deployment), + ostree_deployment_get_csum (deployment), ostree_deployment_get_deployserial (deployment)); +} + /* Deploy a copy of @target_deployment */ static gboolean clone_deployment (OstreeSysroot *sysroot, OstreeDeployment *target_deployment, @@ -2197,9 +2240,9 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, OstreeDeployment *deploym g_autofree char *devpath = unlocked_state == OSTREE_DEPLOYMENT_UNLOCKED_DEVELOPMENT ? _ostree_sysroot_get_runstate_path ( - deployment, _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT) + deployment, _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT) : _ostree_sysroot_get_runstate_path ( - deployment, _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_TRANSIENT); + deployment, _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_TRANSIENT); g_autofree char *devpath_parent = dirname (g_strdup (devpath)); if (!glnx_shutil_mkdir_p_at (AT_FDCWD, devpath_parent, 0755, cancellable, error)) diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index e84007a..3c23f8d 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -178,7 +178,10 @@ gboolean ostree_sysroot_stage_overlay_initrd (OstreeSysroot *self, int fd, char typedef struct { - gboolean unused_bools[8]; + /* If set to true, then this deployment will be staged but "locked" and not automatically applied + * on reboot. */ + gboolean locked; + gboolean unused_bools[7]; int unused_ints[8]; char **override_kernel_argv; char **overlay_initrds; @@ -215,6 +218,10 @@ gboolean ostree_sysroot_stage_tree_with_options (OstreeSysroot *self, const char OstreeDeployment **out_new_deployment, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_sysroot_change_finalization (OstreeSysroot *self, OstreeDeployment *deployment, + GError **error); + _OSTREE_PUBLIC gboolean ostree_sysroot_deployment_set_mutable (OstreeSysroot *self, OstreeDeployment *deployment, gboolean is_mutable, GCancellable *cancellable, @@ -237,6 +244,10 @@ void ostree_sysroot_query_deployments_for (OstreeSysroot *self, const char *osna _OSTREE_PUBLIC OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot *self, const char *osname); +_OSTREE_PUBLIC +gboolean ostree_sysroot_update_post_copy (OstreeSysroot *self, GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC GKeyFile *ostree_sysroot_origin_new_from_refspec (OstreeSysroot *self, const char *refspec); diff --git a/src/libostree/ostree-version.h b/src/libostree/ostree-version.h index 7ef08d5..5a4bb66 100644 --- a/src/libostree/ostree-version.h +++ b/src/libostree/ostree-version.h @@ -32,7 +32,7 @@ * * Since: 2017.4 */ -#define OSTREE_YEAR_VERSION (2023) +#define OSTREE_YEAR_VERSION (2024) /** * OSTREE_RELEASE_VERSION: @@ -41,7 +41,7 @@ * * Since: 2017.4 */ -#define OSTREE_RELEASE_VERSION (7) +#define OSTREE_RELEASE_VERSION (6) /** * OSTREE_VERSION @@ -50,7 +50,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION (2023.7) +#define OSTREE_VERSION (2024.6) /** * OSTREE_VERSION_S: @@ -60,7 +60,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION_S "2023.7" +#define OSTREE_VERSION_S "2024.6" #define OSTREE_ENCODE_VERSION(year,release) \ ((year) << 16 | (release)) @@ -99,5 +99,5 @@ * Since: 2019.3 */ #ifndef __GI_SCANNER__ -#define OSTREE_BUILT_FEATURES "inode64 libsoup gpgme composefs ex-fsverity libarchive selinux libmount systemd release p2p" +#define OSTREE_BUILT_FEATURES "inode64 initial-var libsoup3 gpgme composefs ex-fsverity libarchive selinux libmount systemd release p2p" #endif diff --git a/src/libotcore/otcore-prepare-root.c b/src/libotcore/otcore-prepare-root.c index f7523ef..f76db04 100644 --- a/src/libotcore/otcore-prepare-root.c +++ b/src/libotcore/otcore-prepare-root.c @@ -19,6 +19,12 @@ #include "otcore.h" +// This key is used by default if present in the initramfs to verify +// the signature on the target commit object. When composefs is +// in use, the ostree commit metadata will contain the composefs image digest, +// which can be used to fully verify the target filesystem tree. +#define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key" + static bool proc_cmdline_has_key_starting_with (const char *cmdline, const char *key) { @@ -69,7 +75,8 @@ otcore_find_proc_cmdline_key (const char *cmdline, const char *key) // // If invalid data is found, @error will be set. gboolean -otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error) +otcore_get_ostree_target (const char *cmdline, gboolean *is_aboot, char **out_target, + GError **error) { g_assert (cmdline); g_assert (out_target && *out_target == NULL); @@ -78,8 +85,14 @@ otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error // First, handle the Android boot case g_autofree char *slot_suffix = otcore_find_proc_cmdline_key (cmdline, "androidboot.slot_suffix"); + if (is_aboot) + *is_aboot = false; + if (slot_suffix) { + if (is_aboot) + *is_aboot = true; + if (strcmp (slot_suffix, "_a") == 0) { *out_target = g_strdup (slot_a); @@ -98,6 +111,8 @@ otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error */ if (proc_cmdline_has_key_starting_with (cmdline, "androidboot.")) { + if (is_aboot) + *is_aboot = true; *out_target = g_strdup (slot_a); return TRUE; } @@ -126,8 +141,6 @@ otcore_load_config (int rootfs_fd, const char *filename, GError **error) if (fd == -1) continue; - g_print ("Loading %s\n", path); - g_autofree char *buf = glnx_fd_readall_utf8 (fd, NULL, NULL, error); if (!buf) return NULL; @@ -137,3 +150,69 @@ otcore_load_config (int rootfs_fd, const char *filename, GError **error) return g_steal_pointer (&ret); } + +void +otcore_free_composefs_config (ComposefsConfig *config) +{ + g_clear_pointer (&config->pubkeys, g_ptr_array_unref); + g_free (config->signature_pubkey); + g_free (config); +} + +// Parse the [composefs] section of the prepare-root.conf. +ComposefsConfig * +otcore_load_composefs_config (GKeyFile *config, gboolean load_keys, GError **error) +{ + GLNX_AUTO_PREFIX_ERROR ("Loading composefs config", error); + + g_autoptr (ComposefsConfig) ret = g_new0 (ComposefsConfig, 1); + + g_autofree char *enabled = g_key_file_get_value (config, OTCORE_PREPARE_ROOT_COMPOSEFS_KEY, + OTCORE_PREPARE_ROOT_ENABLED_KEY, NULL); + if (g_strcmp0 (enabled, "signed") == 0) + { + ret->enabled = OT_TRISTATE_YES; + ret->is_signed = true; + } + else if (!ot_keyfile_get_tristate_with_default (config, OTCORE_PREPARE_ROOT_COMPOSEFS_KEY, + OTCORE_PREPARE_ROOT_ENABLED_KEY, + OT_TRISTATE_MAYBE, &ret->enabled, error)) + return NULL; + + // Look for a key - we default to the initramfs binding path. + if (!ot_keyfile_get_value_with_default (config, OTCORE_PREPARE_ROOT_COMPOSEFS_KEY, + OTCORE_PREPARE_ROOT_KEYPATH_KEY, BINDING_KEYPATH, + &ret->signature_pubkey, error)) + return NULL; + + if (ret->is_signed && load_keys) + { + ret->pubkeys = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref); + + g_autofree char *pubkeys = NULL; + gsize pubkeys_size; + + /* Load keys */ + + if (!g_file_get_contents (ret->signature_pubkey, &pubkeys, &pubkeys_size, error)) + return glnx_prefix_error_null (error, "Reading public key file '%s'", + ret->signature_pubkey); + + g_auto (GStrv) lines = g_strsplit (pubkeys, "\n", -1); + for (char **iter = lines; *iter; iter++) + { + const char *line = *iter; + if (!*line) + continue; + + gsize pubkey_size; + g_autofree guchar *pubkey = g_base64_decode (line, &pubkey_size); + g_ptr_array_add (ret->pubkeys, g_bytes_new_take (g_steal_pointer (&pubkey), pubkey_size)); + } + + if (ret->pubkeys->len == 0) + return glnx_null_throw (error, "public key file specified, but no public keys found"); + } + + return g_steal_pointer (&ret); +} diff --git a/src/libotcore/otcore.h b/src/libotcore/otcore.h index 1593e7b..fc6b81c 100644 --- a/src/libotcore/otcore.h +++ b/src/libotcore/otcore.h @@ -44,10 +44,24 @@ gboolean otcore_validate_ed25519_signature (GBytes *data, GBytes *pubkey, GBytes bool *out_valid, GError **error); char *otcore_find_proc_cmdline_key (const char *cmdline, const char *key); -gboolean otcore_get_ostree_target (const char *cmdline, char **out_target, GError **error); +gboolean otcore_get_ostree_target (const char *cmdline, gboolean *is_aboot, char **out_target, + GError **error); GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error); +typedef struct +{ + OtTristate enabled; + gboolean is_signed; + char *signature_pubkey; + GPtrArray *pubkeys; +} ComposefsConfig; +void otcore_free_composefs_config (ComposefsConfig *config); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComposefsConfig, otcore_free_composefs_config) + +ComposefsConfig *otcore_load_composefs_config (GKeyFile *config, gboolean load_keys, + GError **error); + // Our directory with transient state (eventually /run/ostree-booted should be a link to // /run/ostree/booted) #define OTCORE_RUN_OSTREE "/run/ostree" @@ -55,6 +69,16 @@ GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error); // we make it with mode 0 (which requires CAP_DAC_OVERRIDE to pass through). #define OTCORE_RUN_OSTREE_PRIVATE "/run/ostree/.private" +#define PREPARE_ROOT_CONFIG_PATH "ostree/prepare-root.conf" + +// The directory holding extra/backing data for a deployment, such as overlayfs workdirs +#define OSTREE_DEPLOYMENT_BACKING_DIR "backing" +// The directory holding the root overlayfs +#define OSTREE_DEPLOYMENT_ROOT_TRANSIENT_DIR "root-transient" + +// Written by ostree admin unlock --hotfix, read by ostree-prepare-root +#define OTCORE_HOTFIX_USR_OVL_WORK ".usr-ovl-work" + // The name of the composefs metadata root #define OSTREE_COMPOSEFS_NAME ".ostree.cfs" // The temporary directory used for the EROFS mount; it's in the .private directory @@ -62,6 +86,10 @@ GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error); // EROFS mount if we somehow leaked it (but it *should* be unmounted always). #define OSTREE_COMPOSEFS_LOWERMNT OTCORE_RUN_OSTREE_PRIVATE "/cfsroot-lower" +#define OTCORE_PREPARE_ROOT_COMPOSEFS_KEY "composefs" +#define OTCORE_PREPARE_ROOT_ENABLED_KEY "enabled" +#define OTCORE_PREPARE_ROOT_KEYPATH_KEY "keypath" + // The file written in the initramfs which contains an a{sv} of metadata // from ostree-prepare-root. #define OTCORE_RUN_BOOTED "/run/ostree-booted" @@ -70,7 +98,11 @@ GKeyFile *otcore_load_config (int rootfs, const char *filename, GError **error); // This key if present contains the public key successfully used // to verify the signature. #define OTCORE_RUN_BOOTED_KEY_COMPOSEFS_SIGNATURE "composefs.signed" +// This key will be present if the root is transient +#define OTCORE_RUN_BOOTED_KEY_ROOT_TRANSIENT "root.transient" // This key will be present if the sysroot-ro flag was found #define OTCORE_RUN_BOOTED_KEY_SYSROOT_RO "sysroot-ro" +// Always holds the (device, inode) pair of the booted deployment +#define OTCORE_RUN_BOOTED_KEY_BACKING_ROOTDEVINO "backing-root-device-inode" #define OTCORE_RUN_BOOTED_KEY_TRANSIENT_ETC "transient-etc" diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index efbb2f2..1e961a9 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -227,11 +227,12 @@ ot_parse_file_by_line (const char *path, gboolean (*cb) (const char *, void *, G return TRUE; } -/* Calculate the size of the files contained in a directory. Symlinks are not - * followed. */ +/* Calculate the size of the files contained in a directory. Symlinks are + * not followed. If `blocksize` is nonzero, all sizes are rounded to its next + * multiple. */ gboolean -ot_get_dir_size (int dfd, const char *path, guint64 *out_size, GCancellable *cancellable, - GError **error) +ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size, + GCancellable *cancellable, GError **error) { g_auto (GLnxDirFdIterator) dfd_iter = { 0, @@ -256,11 +257,18 @@ ot_get_dir_size (int dfd, const char *path, guint64 *out_size, GCancellable *can return FALSE; *out_size += stbuf.st_size; + if (blocksize > 0) + { + off_t rem = stbuf.st_size % blocksize; + if (rem > 0) + *out_size += blocksize - rem; + } } else if (dent->d_type == DT_DIR) { guint64 subdir_size; - if (!ot_get_dir_size (dfd_iter.fd, dent->d_name, &subdir_size, cancellable, error)) + if (!ot_get_dir_size (dfd_iter.fd, dent->d_name, blocksize, &subdir_size, cancellable, + error)) return FALSE; *out_size += subdir_size; diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index b64adce..7df79ba 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -75,7 +75,7 @@ GBytes *ot_fd_readall_or_mmap (int fd, goffset offset, GError **error); gboolean ot_parse_file_by_line (const char *path, gboolean (*cb) (const char *, void *, GError **), void *cbdata, GCancellable *cancellable, GError **error); -gboolean ot_get_dir_size (int dfd, const char *path, guint64 *out_size, GCancellable *cancellable, - GError **error); +gboolean ot_get_dir_size (int dfd, const char *path, guint64 blocksize, guint64 *out_size, + GCancellable *cancellable, GError **error); G_END_DECLS diff --git a/src/ostree/ostree-trivial-httpd.c b/src/ostree/ostree-trivial-httpd.c index facc152..4a0c6b0 100644 --- a/src/ostree/ostree-trivial-httpd.c +++ b/src/ostree/ostree-trivial-httpd.c @@ -25,7 +25,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-boot-complete.c b/src/ostree/ot-admin-builtin-boot-complete.c index 4599606..df99f89 100644 --- a/src/ostree/ot-admin-builtin-boot-complete.c +++ b/src/ostree/ot-admin-builtin-boot-complete.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include "ostree-cmd-private.h" diff --git a/src/ostree/ot-admin-builtin-cleanup.c b/src/ostree/ot-admin-builtin-cleanup.c index b2d3423..ff33830 100644 --- a/src/ostree/ot-admin-builtin-cleanup.c +++ b/src/ostree/ot-admin-builtin-cleanup.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index c0faaab..66d8572 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -26,7 +26,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include @@ -60,7 +59,7 @@ static GOptionEntry options[] = { "Do not apply configuration (/etc and kernel arguments) from booted deployment", NULL }, { "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployments", NULL }, { "stage", 0, 0, G_OPTION_ARG_NONE, &opt_stage, "Complete deployment at OS shutdown", NULL }, - { "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, + { "lock-finalization", 0, 0, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL }, { "retain-pending", 0, 0, G_OPTION_ARG_NONE, &opt_retain_pending, "Do not delete pending deployments", NULL }, @@ -123,6 +122,10 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat return FALSE; } + // Locking implies staging + if (opt_lock_finalization) + opt_stage = TRUE; + const char *refspec = argv[1]; OstreeRepo *repo = ostree_sysroot_repo (sysroot); @@ -181,10 +184,7 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat && (opt_kernel_argv || opt_kernel_argv_append || opt_kernel_argv_delete)) { OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); - g_auto (GStrv) previous_args - = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); - kargs = ostree_kernel_args_new (); - ostree_kernel_args_append_argv (kargs, previous_args); + kargs = ostree_kernel_args_from_string (ostree_bootconfig_parser_get (bootconfig, "options")); } /* Now replace/extend the above set. Note that if no options are specified, @@ -236,6 +236,7 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat g_auto (GStrv) kargs_strv = kargs ? ostree_kernel_args_to_strv (kargs) : NULL; OstreeSysrootDeployTreeOpts opts = { + .locked = opt_lock_finalization, .override_kernel_argv = kargs_strv, .overlay_initrds = overlay_initrd_chksums ? (char **)overlay_initrd_chksums->pdata : NULL, }; @@ -247,9 +248,11 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat 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"); - /* touch file *before* we stage to avoid races */ + /* For compatibility with older versions of ostree, also write this legacy file. + * This can likely be safely deleted in the middle of 2024 say. */ if (opt_lock_finalization) { + g_debug ("Writing legacy finalization lockfile"); if (!glnx_shutil_mkdir_p_at (AT_FDCWD, dirname (strdupa (_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED)), 0755, cancellable, error)) @@ -262,7 +265,7 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED); } /* use old API if we can to exercise it in CI */ - if (!overlay_initrd_chksums) + if (!(overlay_initrd_chksums || opt_lock_finalization)) { if (!ostree_sysroot_stage_tree (sysroot, opt_osname, revision, origin, merge_deployment, kargs_strv, &new_deployment, cancellable, error)) diff --git a/src/ostree/ot-admin-builtin-diff.c b/src/ostree/ot-admin-builtin-diff.c index 8a123a2..7d96c82 100644 --- a/src/ostree/ot-admin-builtin-diff.c +++ b/src/ostree/ot-admin-builtin-diff.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include diff --git a/src/ostree/ot-admin-builtin-finalize-staged.c b/src/ostree/ot-admin-builtin-finalize-staged.c index a60f468..2ae1674 100644 --- a/src/ostree/ot-admin-builtin-finalize-staged.c +++ b/src/ostree/ot-admin-builtin-finalize-staged.c @@ -28,7 +28,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include "ostree-cmd-private.h" diff --git a/src/ostree/ot-admin-builtin-init-fs.c b/src/ostree/ot-admin-builtin-init-fs.c index bf00f19..5815a83 100644 --- a/src/ostree/ot-admin-builtin-init-fs.c +++ b/src/ostree/ot-admin-builtin-init-fs.c @@ -23,15 +23,18 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include static gboolean opt_modern; +static gint opt_epoch; static GOptionEntry options[] = { { "modern", 0, 0, G_OPTION_ARG_NONE, &opt_modern, "Only create /boot and /ostree", NULL }, + { "epoch", 'E', 0, G_OPTION_ARG_INT, &opt_epoch, + "An integer value, defines initial state. Must be in the range [0-1], inclusive.", + NULL }, { NULL } }; gboolean @@ -63,12 +66,19 @@ ot_admin_builtin_init_fs (int argc, char **argv, OstreeCommandInvocation *invoca if (!glnx_shutil_mkdir_p_at (root_dfd, "boot", 0755, cancellable, error)) return FALSE; + if (opt_epoch < 0) + return glnx_throw (error, "Invalid epoch: %d", opt_epoch); + + /* --modern is equivalent to --epoch=1 */ + if (opt_modern && opt_epoch == 0) + opt_epoch = 1; + /* See https://github.com/coreos/coreos-assembler/pull/688 * For Fedora CoreOS at least, we have this now to the point where we don't * need this stuff in the physical sysroot. I'm not sure we ever really did, * but to be conservative, make it opt-in to the new model of just boot/ and ostree/. */ - if (!opt_modern) + if (opt_epoch == 0) { const char *traditional_toplevels[] = { "boot", "dev", "home", "proc", "run", "sys" }; for (guint i = 0; i < G_N_ELEMENTS (traditional_toplevels); i++) @@ -89,6 +99,14 @@ ot_admin_builtin_init_fs (int argc, char **argv, OstreeCommandInvocation *invoca return FALSE; } } + else if (opt_epoch == 2) + { + /* In epoch 2, ostree is 0700 - no access from unprivileged code. See + * https://github.com/ostreedev/ostree/issues/3211 + */ + if (!glnx_shutil_mkdir_p_at (root_dfd, "ostree", 0700, cancellable, error)) + return FALSE; + } g_autoptr (GFile) dir = g_file_new_for_path (sysroot_path); g_autoptr (OstreeSysroot) sysroot = ostree_sysroot_new (dir); diff --git a/src/ostree/ot-admin-builtin-instutil.c b/src/ostree/ot-admin-builtin-instutil.c index d697cb0..4d0711d 100644 --- a/src/ostree/ot-admin-builtin-instutil.c +++ b/src/ostree/ot-admin-builtin-instutil.c @@ -24,7 +24,6 @@ #include "ot-admin-functions.h" #include "ot-admin-instutil-builtins.h" #include "ot-builtins.h" -#include "ot-main.h" #include diff --git a/src/ostree/ot-admin-builtin-kargs.c b/src/ostree/ot-admin-builtin-kargs.c index c4d440b..1433000 100644 --- a/src/ostree/ot-admin-builtin-kargs.c +++ b/src/ostree/ot-admin-builtin-kargs.c @@ -23,7 +23,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" #include "ot-admin-kargs-builtins.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-lock-finalization.c b/src/ostree/ot-admin-builtin-lock-finalization.c new file mode 100644 index 0000000..e093d95 --- /dev/null +++ b/src/ostree/ot-admin-builtin-lock-finalization.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 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, see . + */ + +#include "config.h" + +#include "ostree-sysroot-private.h" + +#include "ostree.h" +#include "ot-admin-builtins.h" +#include "ot-admin-functions.h" +#include "otutil.h" + +#include + +static gboolean opt_unlock; + +static GOptionEntry options[] + = { { "unlock", 'u', 0, G_OPTION_ARG_NONE, &opt_unlock, "Unlock finalization", NULL }, + { NULL } }; + +gboolean +ot_admin_builtin_lock_finalization (int argc, char **argv, OstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + g_autoptr (GOptionContext) context = g_option_context_new (""); + + g_autoptr (OstreeSysroot) sysroot = NULL; + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, invocation, &sysroot, + cancellable, error)) + return FALSE; + + OstreeDeployment *staged = ostree_sysroot_get_staged_deployment (sysroot); + if (!staged) + return glnx_throw (error, "No staged deployment"); + + const gboolean is_locked = ostree_deployment_is_finalization_locked (staged); + if (opt_unlock && !is_locked) + { + g_print ("Staged deployment is already prepared for finalization\n"); + return TRUE; + } + else if (!opt_unlock && is_locked) + { + g_print ("Staged deployment is already finalization locked\n"); + return TRUE; + } + + if (!ostree_sysroot_change_finalization (sysroot, staged, error)) + return FALSE; + + if (opt_unlock) + { + g_print ("Staged deployment is now queued to apply on shutdown\n"); + } + else + { + g_print ("Staged deployment is now finalization locked\n"); + } + return TRUE; +} diff --git a/src/ostree/ot-admin-builtin-os-init.c b/src/ostree/ot-admin-builtin-os-init.c index 561d6cd..8f16246 100644 --- a/src/ostree/ot-admin-builtin-os-init.c +++ b/src/ostree/ot-admin-builtin-os-init.c @@ -23,7 +23,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-pin.c b/src/ostree/ot-admin-builtin-pin.c index 362df44..2ed8fbb 100644 --- a/src/ostree/ot-admin-builtin-pin.c +++ b/src/ostree/ot-admin-builtin-pin.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_unpin; @@ -32,6 +31,53 @@ static gboolean opt_unpin; static GOptionEntry options[] = { { "unpin", 'u', 0, G_OPTION_ARG_NONE, &opt_unpin, "Unset pin", NULL }, { NULL } }; +static gint64 +get_deployment_index_for_type (OstreeSysroot *sysroot, const char *deploy_index_str) +{ + g_autoptr (GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); + OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); + if (booted_deployment && deploy_index_str[0] == 'b') + return ostree_deployment_get_index (booted_deployment); + + g_autoptr (OstreeDeployment) pending_deployment = NULL; + g_autoptr (OstreeDeployment) rollback_deployment = NULL; + if (booted_deployment) + ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, &rollback_deployment); + + if (pending_deployment && deploy_index_str[0] == 'p') + return ostree_deployment_get_index (pending_deployment); + else if (rollback_deployment && deploy_index_str[0] == 'r') + return ostree_deployment_get_index (rollback_deployment); + + return -1; +} + +static gboolean +do_pinning (OstreeSysroot *sysroot, const gint64 deploy_index, GError **error) +{ + g_autoptr (OstreeDeployment) target_deployment + = ot_admin_get_indexed_deployment (sysroot, deploy_index, error); + if (!target_deployment) + return FALSE; + + const gboolean current_pin = ostree_deployment_is_pinned (target_deployment); + const gboolean desired_pin = !opt_unpin; + if (current_pin == desired_pin) + { + g_print ("Deployment %lld is already %s\n", (long long int)deploy_index, + current_pin ? "pinned" : "unpinned"); + return TRUE; + } + else if (ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error)) + { + g_print ("Deployment %lld is now %s\n", (long long int)deploy_index, + desired_pin ? "pinned" : "unpinned"); + return TRUE; + } + + return FALSE; +} + gboolean ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error) @@ -55,32 +101,25 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation char *endptr = NULL; errno = 0; - const guint64 deploy_index = g_ascii_strtoull (deploy_index_str, &endptr, 10); - if (*endptr != '\0') - return glnx_throw (error, "Invalid index: %s", deploy_index_str); - if (errno == ERANGE) - return glnx_throw (error, "Index too large: %s", deploy_index_str); - - g_autoptr (OstreeDeployment) target_deployment - = ot_admin_get_indexed_deployment (sysroot, deploy_index, error); - if (!target_deployment) - return FALSE; - - gboolean current_pin = ostree_deployment_is_pinned (target_deployment); - const gboolean desired_pin = !opt_unpin; - if (current_pin == desired_pin) + gint64 deploy_index; + if (!g_strcmp0 (deploy_index_str, "booted") || !g_strcmp0 (deploy_index_str, "pending") + || !g_strcmp0 (deploy_index_str, "rollback")) { - g_print ("Deployment %s is already %s\n", deploy_index_str, - current_pin ? "pinned" : "unpinned"); + deploy_index = get_deployment_index_for_type (sysroot, deploy_index_str); + if (deploy_index < 0) + return glnx_throw (error, "Deployment type not found: %s", deploy_index_str); } else { - if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, - error)) - return FALSE; - g_print ("Deployment %s is now %s\n", deploy_index_str, - desired_pin ? "pinned" : "unpinned"); + deploy_index = g_ascii_strtoull (deploy_index_str, &endptr, 10); + if (*endptr != '\0') + return glnx_throw (error, "Invalid index: %s", deploy_index_str); + else if (errno == ERANGE) + return glnx_throw (error, "Index too large: %s", deploy_index_str); } + + if (!do_pinning (sysroot, deploy_index, error)) + return FALSE; } return TRUE; diff --git a/src/ostree/ot-admin-builtin-post-copy.c b/src/ostree/ot-admin-builtin-post-copy.c new file mode 100644 index 0000000..6748479 --- /dev/null +++ b/src/ostree/ot-admin-builtin-post-copy.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2023 Alexander Larsson + * + * 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, see . + */ + +#include "config.h" + +#include "ostree-sysroot-private.h" + +#include "ostree.h" +#include "ot-admin-builtins.h" +#include "ot-admin-functions.h" +#include "otutil.h" + +#include + +static GOptionEntry options[] = { { NULL } }; + +gboolean +ot_admin_builtin_post_copy (int argc, char **argv, OstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + g_autoptr (GOptionContext) context = g_option_context_new (""); + + g_autoptr (OstreeSysroot) sysroot = NULL; + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, invocation, &sysroot, + cancellable, error)) + return FALSE; + + if (!ostree_sysroot_update_post_copy (sysroot, cancellable, error)) + return FALSE; + + return TRUE; +} diff --git a/src/ostree/ot-admin-builtin-set-default.c b/src/ostree/ot-admin-builtin-set-default.c index 89e6754..dd47ceb 100644 --- a/src/ostree/ot-admin-builtin-set-default.c +++ b/src/ostree/ot-admin-builtin-set-default.c @@ -22,7 +22,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" static GOptionEntry options[] = { { NULL } }; diff --git a/src/ostree/ot-admin-builtin-set-origin.c b/src/ostree/ot-admin-builtin-set-origin.c index 45b5dbd..1bb0d09 100644 --- a/src/ostree/ot-admin-builtin-set-origin.c +++ b/src/ostree/ot-admin-builtin-set-origin.c @@ -22,7 +22,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-state-overlay.c b/src/ostree/ot-admin-builtin-state-overlay.c new file mode 100644 index 0000000..7bf386c --- /dev/null +++ b/src/ostree/ot-admin-builtin-state-overlay.c @@ -0,0 +1,285 @@ +/* Copyright (C) 2023 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, see . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "glnx-errors.h" +#include "glnx-fdio.h" +#include "glnx-local-alloc.h" +#include "glnx-shutil.h" +#include "glnx-xattrs.h" +#include "ostree-core.h" +#include "ostree-deployment.h" +#include "ot-admin-builtins.h" + +#define OSTREE_STATEOVERLAYS_DIR "/var/ostree/state-overlays" +#define OSTREE_STATEOVERLAY_UPPER_DIR "upper" +#define OSTREE_STATEOVERLAY_WORK_DIR "work" + +#define OSTREE_STATEOVERLAY_XATTR_DEPLOYMENT_CSUM "user.ostree.deploymentcsum" + +/* https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html */ +#define OVERLAYFS_DIR_XATTR_OPAQUE "trusted.overlay.opaque" + +static GOptionEntry options[] = { { NULL } }; + +static gboolean +ensure_overlay_dirs (const char *overlay_dir, int *out_overlay_dfd, GCancellable *cancellable, + GError **error) +{ + glnx_autofd int overlay_dfd = -1; + if (!glnx_shutil_mkdir_p_at_open (AT_FDCWD, overlay_dir, 0700, &overlay_dfd, cancellable, error)) + return FALSE; + + if (!glnx_shutil_mkdir_p_at (overlay_dfd, OSTREE_STATEOVERLAY_WORK_DIR, 0700, cancellable, error)) + return FALSE; + if (!glnx_shutil_mkdir_p_at (overlay_dfd, OSTREE_STATEOVERLAY_UPPER_DIR, 0700, cancellable, + error)) + return FALSE; + + *out_overlay_dfd = glnx_steal_fd (&overlay_dfd); + return TRUE; +} + +/* XXX: upstream to libglnx */ +static gboolean +lgetxattrat_allow_noent (int dfd, const char *path, const char *attribute, GBytes **out_bytes, + GError **error) +{ + g_autoptr (GError) local_error = NULL; + *out_bytes = glnx_lgetxattrat (dfd, path, attribute, &local_error); + if (!*out_bytes) + { + if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA)) + return TRUE; + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + return TRUE; +} + +static gboolean +is_opaque_dir (int dfd, const char *dname, gboolean *out_is_opaque, GError **error) +{ + g_autoptr (GBytes) data = NULL; + if (!lgetxattrat_allow_noent (dfd, dname, OVERLAYFS_DIR_XATTR_OPAQUE, &data, error)) + return FALSE; + + if (!data) + *out_is_opaque = FALSE; + else + { + gsize size; + const guint8 *buf = g_bytes_get_data (data, &size); + *out_is_opaque = (size == 1 && buf[0] == 'y'); + } + return TRUE; +} + +static gboolean +prune_upperdir_recurse (int lower_dfd, int upper_dfd, GCancellable *cancellable, GError **error) +{ + g_auto (GLnxDirFdIterator) dfd_iter = { 0 }; + if (!glnx_dirfd_iterator_init_at (upper_dfd, ".", FALSE, &dfd_iter, error)) + return FALSE; + + while (TRUE) + { + struct dirent *dent = NULL; + if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) + return FALSE; + if (dent == NULL) + break; + + /* do we have an entry of the same name in the lowerdir? */ + struct stat stbuf; + if (!glnx_fstatat_allow_noent (lower_dfd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT) + continue; /* state file (i.e. upperdir only); carry on */ + + /* ok, it shadows; are they both directories? */ + if (dent->d_type == DT_DIR && S_ISDIR (stbuf.st_mode)) + { + /* is the directory opaque? */ + gboolean is_opaque = FALSE; + if (!is_opaque_dir (upper_dfd, dent->d_name, &is_opaque, error)) + return FALSE; + + if (!is_opaque) + { + /* recurse */ + glnx_autofd int lower_subdfd = -1; + if (!glnx_opendirat (lower_dfd, dent->d_name, FALSE, &lower_subdfd, error)) + return FALSE; + glnx_autofd int upper_subdfd = -1; + if (!glnx_opendirat (upper_dfd, dent->d_name, FALSE, &upper_subdfd, error)) + return FALSE; + if (!prune_upperdir_recurse (lower_subdfd, upper_subdfd, cancellable, error)) + return glnx_prefix_error (error, "in %s", dent->d_name); + + continue; + } + + /* fallthrough; implicitly delete opaque directories */ + } + + /* any other case, we prune (this also implicitly covers whiteouts and opaque dirs) */ + if (dent->d_type == DT_DIR) + { + if (!glnx_shutil_rm_rf_at (upper_dfd, dent->d_name, cancellable, error)) + return FALSE; + } + else + { + /* just unlinkat(); saves one openat() call */ + if (!glnx_unlinkat (upper_dfd, dent->d_name, 0, error)) + return FALSE; + } + } + + return TRUE; +} + +static gboolean +prune_upperdir (int sysroot_fd, const char *mountpath, int overlay_dfd, GCancellable *cancellable, + GError **error) +{ + glnx_autofd int lower_dfd = -1; + if (!glnx_opendirat (AT_FDCWD, mountpath, FALSE, &lower_dfd, error)) + return FALSE; + + glnx_autofd int upper_dfd = -1; + if (!glnx_opendirat (overlay_dfd, OSTREE_STATEOVERLAY_UPPER_DIR, FALSE, &upper_dfd, error)) + return FALSE; + + if (!prune_upperdir_recurse (lower_dfd, upper_dfd, cancellable, error)) + return FALSE; + + return TRUE; +} + +static gboolean +mount_overlay (const char *mountpath, const char *name, GError **error) +{ + /* we could use /proc/self/... with overlay_dfd to avoid these allocations, + * but this gets stringified into the options field in the mount table, and + * being cryptic is not helpful */ + g_autofree char *upperdir + = g_build_filename (OSTREE_STATEOVERLAYS_DIR, name, OSTREE_STATEOVERLAY_UPPER_DIR, NULL); + g_autofree char *workdir + = g_build_filename (OSTREE_STATEOVERLAYS_DIR, name, OSTREE_STATEOVERLAY_WORK_DIR, NULL); + g_autofree char *ovl_options + = g_strdup_printf ("lowerdir=%s,upperdir=%s,workdir=%s", mountpath, upperdir, workdir); + if (mount ("overlay", mountpath, "overlay", MS_SILENT, ovl_options) < 0) + return glnx_throw_errno_prefix (error, "mount(%s)", mountpath); + + return TRUE; +} + +static gboolean +get_overlay_deployment_checksum (int overlay_dfd, char **out_checksum, GCancellable *cancellable, + GError **error) +{ + g_autoptr (GBytes) bytes = NULL; + if (!lgetxattrat_allow_noent (overlay_dfd, OSTREE_STATEOVERLAY_UPPER_DIR, + OSTREE_STATEOVERLAY_XATTR_DEPLOYMENT_CSUM, &bytes, error)) + return FALSE; + if (!bytes) + return TRUE; /* probably newly created */ + + gsize len; + const char *data = g_bytes_get_data (bytes, &len); + + if (len != OSTREE_SHA256_STRING_LEN) + return TRUE; /* invalid; gracefully handle as missing */ + + *out_checksum = g_strndup (data, len); + return TRUE; +} + +static gboolean +set_overlay_deployment_checksum (int overlay_dfd, const char *checksum, GCancellable *cancellable, + GError **error) +{ + g_assert_cmpuint (strlen (checksum), ==, OSTREE_SHA256_STRING_LEN); + /* we could store it in binary of course, but let's make it more accessible for debugging */ + if (!glnx_lsetxattrat (overlay_dfd, OSTREE_STATEOVERLAY_UPPER_DIR, + OSTREE_STATEOVERLAY_XATTR_DEPLOYMENT_CSUM, (guint8 *)checksum, + OSTREE_SHA256_STRING_LEN, 0, error)) + return FALSE; + return TRUE; +} + +/* Called by ostree-state-overlay@.service. */ +gboolean +ot_admin_builtin_state_overlay (int argc, char **argv, OstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + g_autoptr (GOptionContext) context = g_option_context_new ("NAME MOUNTPATH"); + g_autoptr (OstreeSysroot) sysroot = NULL; + + /* First parse the args without loading the sysroot to see what options are + * set. */ + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER + | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED, + invocation, &sysroot, cancellable, error)) + return FALSE; + + if (argc < 3) + return glnx_throw (error, "Missing NAME or MOUNTPATH"); + + /* Sanity-check */ + OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); + if (booted_deployment == NULL) + return glnx_throw (error, "Must be booted into an OSTree deployment"); + + const char *overlay_name = argv[1]; + const char *mountpath = argv[2]; + + glnx_autofd int overlay_dfd = -1; + g_autofree char *overlay_dir = g_build_filename (OSTREE_STATEOVERLAYS_DIR, overlay_name, NULL); + if (!ensure_overlay_dirs (overlay_dir, &overlay_dfd, cancellable, error)) + return FALSE; + + g_autofree char *current_checksum = NULL; + if (!get_overlay_deployment_checksum (overlay_dfd, ¤t_checksum, cancellable, error)) + return FALSE; + /* note current_checksum could still be NULL */ + + const char *target_checksum = ostree_deployment_get_csum (booted_deployment); + if (g_strcmp0 (current_checksum, target_checksum) != 0) + { + /* the lowerdir was updated; prune the upperdir */ + if (!prune_upperdir (ostree_sysroot_get_fd (sysroot), mountpath, overlay_dfd, cancellable, + error)) + return glnx_prefix_error (error, "Pruning upperdir for %s", overlay_name); + + if (!set_overlay_deployment_checksum (overlay_dfd, target_checksum, cancellable, error)) + return FALSE; + } + + return mount_overlay (mountpath, overlay_name, error); +} diff --git a/src/ostree/ot-admin-builtin-status.c b/src/ostree/ot-admin-builtin-status.c index 3addfd1..d05d992 100644 --- a/src/ostree/ot-admin-builtin-status.c +++ b/src/ostree/ot-admin-builtin-status.c @@ -25,44 +25,22 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include static gboolean opt_verify; - -static GOptionEntry options[] = { { "verify", 'V', 0, G_OPTION_ARG_NONE, &opt_verify, - "Print the commit verification status", NULL }, - { NULL } }; - -#ifndef OSTREE_DISABLE_GPGME -static gboolean -deployment_get_gpg_verify (OstreeDeployment *deployment, OstreeRepo *repo) -{ - /* XXX Something like this could be added to the OstreeDeployment - * API in libostree if the OstreeRepo parameter is acceptable. */ - GKeyFile *origin = ostree_deployment_get_origin (deployment); - - if (origin == NULL) - return FALSE; - - g_autofree char *refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); - - if (refspec == NULL) - return FALSE; - - g_autofree char *remote = NULL; - if (!ostree_parse_refspec (refspec, &remote, NULL, NULL)) - return FALSE; - - gboolean gpg_verify = FALSE; - if (remote) - (void)ostree_repo_remote_get_gpg_verify (repo, remote, &gpg_verify, NULL); - - return gpg_verify; -} -#endif /* OSTREE_DISABLE_GPGME */ - +static gboolean opt_skip_signatures; +static gboolean opt_is_default; + +static GOptionEntry options[] + = { { "verify", 'V', 0, G_OPTION_ARG_NONE, &opt_verify, "Print the commit verification status", + NULL }, + { "skip-signatures", 'S', 0, G_OPTION_ARG_NONE, &opt_skip_signatures, + "Skip signatures in output", NULL }, + { "is-default", 'D', 0, G_OPTION_ARG_NONE, &opt_is_default, + "Output \"default\" if booted into the default deployment, otherwise \"not-default\"", + NULL }, + { NULL } }; static gboolean deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeployment *deployment, gboolean is_booted, gboolean is_pending, gboolean is_rollback, @@ -96,9 +74,13 @@ deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploym } GKeyFile *origin = ostree_deployment_get_origin (deployment); + g_autofree char *origin_refspec + = origin ? g_key_file_get_string (origin, "origin", "refspec", NULL) : NULL; const char *deployment_status = ""; - if (ostree_deployment_is_staged (deployment)) + if (ostree_deployment_is_finalization_locked (deployment)) + deployment_status = " (finalization locked)"; + else if (ostree_deployment_is_staged (deployment)) deployment_status = " (staged)"; else if (is_pending) deployment_status = " (pending)"; @@ -126,7 +108,6 @@ deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploym g_print (" origin: none\n"); else { - g_autofree char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); if (!origin_refspec) g_print (" origin: \n"); else @@ -136,15 +117,22 @@ deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploym } #ifndef OSTREE_DISABLE_GPGME - if (!opt_verify && deployment_get_gpg_verify (deployment, repo)) + g_autofree char *remote = NULL; + if (origin_refspec && !ostree_parse_refspec (origin_refspec, &remote, NULL, NULL)) + return FALSE; + + gboolean gpg_verify = FALSE; + if (remote) + (void)ostree_repo_remote_get_gpg_verify (repo, remote, &gpg_verify, NULL); + if (!opt_skip_signatures && !opt_verify && gpg_verify) { + g_assert (remote); g_autoptr (GString) output_buffer = g_string_sized_new (256); /* Print any digital signatures on this commit. */ - const char *osname = ostree_deployment_get_osname (deployment); g_autoptr (GError) local_error = NULL; g_autoptr (OstreeGpgVerifyResult) result - = ostree_repo_verify_commit_for_remote (repo, ref, osname, cancellable, &local_error); + = ostree_repo_verify_commit_for_remote (repo, ref, remote, cancellable, &local_error); /* G_IO_ERROR_NOT_FOUND just means the commit is not signed. */ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) @@ -155,7 +143,8 @@ deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploym else if (local_error != NULL) { g_propagate_error (error, g_steal_pointer (&local_error)); - return FALSE; + return glnx_prefix_error (error, "Deployment %i", + ostree_deployment_get_index (deployment)); } const guint n_signatures = ostree_gpg_verify_result_count_all (result); @@ -167,21 +156,15 @@ deployment_print_status (OstreeSysroot *sysroot, OstreeRepo *repo, OstreeDeploym g_print ("%s", output_buffer->str); } +#else + g_autofree char *remote = NULL; #endif /* OSTREE_DISABLE_GPGME */ if (opt_verify) { if (!commit) return glnx_throw (error, "Cannot verify, failed to load commit"); - - if (origin == NULL) - return glnx_throw (error, "Cannot verify deployment with no origin"); - - g_autofree char *refspec = g_key_file_get_string (origin, "origin", "refspec", NULL); - if (refspec == NULL) + if (origin_refspec == NULL) return glnx_throw (error, "No origin/refspec, cannot verify"); - g_autofree char *remote = NULL; - if (!ostree_parse_refspec (refspec, &remote, NULL, NULL)) - return FALSE; if (remote == NULL) return glnx_throw (error, "Cannot verify deployment without remote"); @@ -223,7 +206,15 @@ ot_admin_builtin_status (int argc, char **argv, OstreeCommandInvocation *invocat if (booted_deployment) ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, &rollback_deployment); - if (deployments->len == 0) + if (opt_is_default) + { + if (deployments->len == 0) + return glnx_throw (error, "Not in a booted OSTree system"); + + const gboolean is_default_booted = deployments->pdata[0] == booted_deployment; + g_print ("%s\n", is_default_booted ? "default" : "not-default"); + } + else if (deployments->len == 0) { g_print ("No deployments.\n"); } diff --git a/src/ostree/ot-admin-builtin-switch.c b/src/ostree/ot-admin-builtin-switch.c index cb41cac..5926736 100644 --- a/src/ostree/ot-admin-builtin-switch.c +++ b/src/ostree/ot-admin-builtin-switch.c @@ -22,7 +22,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-undeploy.c b/src/ostree/ot-admin-builtin-undeploy.c index ab028d4..4ed0490 100644 --- a/src/ostree/ot-admin-builtin-undeploy.c +++ b/src/ostree/ot-admin-builtin-undeploy.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" static GOptionEntry options[] = { { NULL } }; @@ -50,7 +49,14 @@ ot_admin_builtin_undeploy (int argc, char **argv, OstreeCommandInvocation *invoc g_autoptr (GPtrArray) current_deployments = ostree_sysroot_get_deployments (sysroot); const char *deploy_index_str = argv[1]; - int deploy_index = atoi (deploy_index_str); + guint deploy_index; + { + char *endptr = NULL; + errno = 0; + deploy_index = (guint)g_ascii_strtoull (deploy_index_str, &endptr, 10); + if (*endptr != '\0') + return glnx_throw (error, "Invalid index: %s", deploy_index_str); + } g_autoptr (OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, error); diff --git a/src/ostree/ot-admin-builtin-unlock.c b/src/ostree/ot-admin-builtin-unlock.c index d0c4145..4140e4c 100644 --- a/src/ostree/ot-admin-builtin-unlock.c +++ b/src/ostree/ot-admin-builtin-unlock.c @@ -22,7 +22,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c index 1171042..96b1575 100644 --- a/src/ostree/ot-admin-builtin-upgrade.c +++ b/src/ostree/ot-admin-builtin-upgrade.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-admin-builtins.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h index 0464a81..cd1472b 100644 --- a/src/ostree/ot-admin-builtins.h +++ b/src/ostree/ot-admin-builtins.h @@ -48,6 +48,9 @@ BUILTINPROTO (diff); BUILTINPROTO (switch); BUILTINPROTO (upgrade); BUILTINPROTO (kargs); +BUILTINPROTO (post_copy); +BUILTINPROTO (lock_finalization); +BUILTINPROTO (state_overlay); #undef BUILTINPROTO diff --git a/src/ostree/ot-admin-functions.h b/src/ostree/ot-admin-functions.h index 50aef16..6a2332b 100644 --- a/src/ostree/ot-admin-functions.h +++ b/src/ostree/ot-admin-functions.h @@ -21,8 +21,7 @@ #pragma once -#include -#include +#include "ot-main.h" G_BEGIN_DECLS diff --git a/src/ostree/ot-admin-instutil-builtin-grub2-generate.c b/src/ostree/ot-admin-instutil-builtin-grub2-generate.c index e73ffa1..e5acbd7 100644 --- a/src/ostree/ot-admin-instutil-builtin-grub2-generate.c +++ b/src/ostree/ot-admin-instutil-builtin-grub2-generate.c @@ -22,7 +22,6 @@ #include "ostree-cmd-private.h" #include "ot-admin-instutil-builtins.h" -#include "ot-main.h" #include "otutil.h" diff --git a/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c b/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c index bc226fb..673b40d 100644 --- a/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c +++ b/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c @@ -21,7 +21,6 @@ #include #include "ot-admin-instutil-builtins.h" -#include "ot-main.h" #include "otutil.h" diff --git a/src/ostree/ot-admin-instutil-builtin-set-kargs.c b/src/ostree/ot-admin-instutil-builtin-set-kargs.c index 90a69b4..21b3d76 100644 --- a/src/ostree/ot-admin-instutil-builtin-set-kargs.c +++ b/src/ostree/ot-admin-instutil-builtin-set-kargs.c @@ -21,7 +21,6 @@ #include #include "ot-admin-instutil-builtins.h" -#include "ot-main.h" #include "ostree.h" #include "otutil.h" diff --git a/src/ostree/ot-admin-kargs-builtin-edit-in-place.c b/src/ostree/ot-admin-kargs-builtin-edit-in-place.c index cd434a7..00025e6 100644 --- a/src/ostree/ot-admin-kargs-builtin-edit-in-place.c +++ b/src/ostree/ot-admin-kargs-builtin-edit-in-place.c @@ -19,9 +19,6 @@ #include "config.h" #include "ot-admin-kargs-builtins.h" -#include "ot-main.h" - -#include "ostree.h" #include "otutil.h" static char **opt_kargs_edit_in_place_append; diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index e48f91e..53face6 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -26,7 +26,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" #include "ot-builtins.h" -#include "ot-main.h" #include @@ -39,8 +38,12 @@ static OstreeCommand admin_subcommands[] = { "Checkout revision REFSPEC as the new default deployment" }, { "finalize-staged", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, ot_admin_builtin_finalize_staged, "Internal command to run at shutdown time" }, + { "lock-finalization", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_lock_finalization, + "Change the finalization locking state of the staged deployment" }, { "boot-complete", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, ot_admin_builtin_boot_complete, "Internal command to run at boot after an update was applied" }, + { "state-overlay", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, + ot_admin_builtin_state_overlay, "Internal command to assemble a state overlay" }, { "init-fs", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_init_fs, "Initialize a root filesystem" }, { "instutil", OSTREE_BUILTIN_FLAG_NO_REPO | OSTREE_BUILTIN_FLAG_HIDDEN, ot_admin_builtin_instutil, @@ -50,7 +53,10 @@ static OstreeCommand admin_subcommands[] = { { "stateroot-init", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_os_init, "Initialize empty state for given operating system" }, { "pin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_pin, - "Change the \"pinning\" state of a deployment" }, + "Change the \"pinning\" state of a deployment, INDEX can be >= 0 or one of booted, pending or " + "rollback strings" }, + { "post-copy", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_post_copy, + "Update the repo and deployments as needed after a copy" }, { "set-origin", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_set_origin, "Set Origin and create a new origin file" }, { "status", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_status, "List deployments" }, diff --git a/src/ostree/ot-builtin-cat.c b/src/ostree/ot-builtin-cat.c index 58201b7..0e44e58 100644 --- a/src/ostree/ot-builtin-cat.c +++ b/src/ostree/ot-builtin-cat.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index 368c1f6..21213da 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -26,7 +26,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_user_mode; diff --git a/src/ostree/ot-builtin-checksum.c b/src/ostree/ot-builtin-checksum.c index b3b15c2..6aa4ba9 100644 --- a/src/ostree/ot-builtin-checksum.c +++ b/src/ostree/ot-builtin-checksum.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 0309e73..7c6d63e 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -27,7 +27,6 @@ #include "ostree.h" #include "ot-builtins.h" #include "ot-editor.h" -#include "ot-main.h" #include "otutil.h" #include "parse-datetime.h" diff --git a/src/ostree/ot-builtin-config.c b/src/ostree/ot-builtin-config.c index ad90b4b..039656c 100644 --- a/src/ostree/ot-builtin-config.c +++ b/src/ostree/ot-builtin-config.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static char *opt_group; diff --git a/src/ostree/ot-builtin-create-usb.c b/src/ostree/ot-builtin-create-usb.c index 0c48295..c0a5172 100644 --- a/src/ostree/ot-builtin-create-usb.c +++ b/src/ostree/ot-builtin-create-usb.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include "ostree-remote-private.h" diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index 2060dc7..13fcd73 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_stats; diff --git a/src/ostree/ot-builtin-export.c b/src/ostree/ot-builtin-export.c index 4dda9c2..5bc1730 100644 --- a/src/ostree/ot-builtin-export.c +++ b/src/ostree/ot-builtin-export.c @@ -23,7 +23,6 @@ #include "ostree-repo-file.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #ifdef HAVE_LIBARCHIVE diff --git a/src/ostree/ot-builtin-find-remotes.c b/src/ostree/ot-builtin-find-remotes.c index b13ab4e..7475aaa 100644 --- a/src/ostree/ot-builtin-find-remotes.c +++ b/src/ostree/ot-builtin-find-remotes.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include "ostree-remote-private.h" diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index cd3c776..bfb7344 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -25,7 +25,6 @@ #include "ostree-cmd-private.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_quiet; diff --git a/src/ostree/ot-builtin-gpg-sign.c b/src/ostree/ot-builtin-gpg-sign.c index a0ddf2a..9f7ac3b 100644 --- a/src/ostree/ot-builtin-gpg-sign.c +++ b/src/ostree/ot-builtin-gpg-sign.c @@ -24,7 +24,6 @@ #include "ostree-core-private.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_delete; diff --git a/src/ostree/ot-builtin-init.c b/src/ostree/ot-builtin-init.c index 114f9ba..fb3ca38 100644 --- a/src/ostree/ot-builtin-init.c +++ b/src/ostree/ot-builtin-init.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" static char *opt_mode = "bare"; static char *opt_collection_id = NULL; diff --git a/src/ostree/ot-builtin-log.c b/src/ostree/ot-builtin-log.c index 222e67a..cf0896e 100644 --- a/src/ostree/ot-builtin-log.c +++ b/src/ostree/ot-builtin-log.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" #include "ot-dump.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_raw; diff --git a/src/ostree/ot-builtin-ls.c b/src/ostree/ot-builtin-ls.c index 780bc01..6b76bab 100644 --- a/src/ostree/ot-builtin-ls.c +++ b/src/ostree/ot-builtin-ls.c @@ -24,7 +24,6 @@ #include "ostree-repo-file.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_dironly; diff --git a/src/ostree/ot-builtin-prune.c b/src/ostree/ot-builtin-prune.c index 1416ed8..e54eff2 100644 --- a/src/ostree/ot-builtin-prune.c +++ b/src/ostree/ot-builtin-prune.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include "parse-datetime.h" diff --git a/src/ostree/ot-builtin-pull-local.c b/src/ostree/ot-builtin-pull-local.c index d489c44..92d53af 100644 --- a/src/ostree/ot-builtin-pull-local.c +++ b/src/ostree/ot-builtin-pull-local.c @@ -26,7 +26,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static char *opt_remote; diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index c06f4e6..477a505 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_disable_fsync; diff --git a/src/ostree/ot-builtin-refs.c b/src/ostree/ot-builtin-refs.c index ec345b5..ff89eba 100644 --- a/src/ostree/ot-builtin-refs.c +++ b/src/ostree/ot-builtin-refs.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" static gboolean opt_delete; static gboolean opt_list; diff --git a/src/ostree/ot-builtin-remote.c b/src/ostree/ot-builtin-remote.c index f50e09b..8c30e4f 100644 --- a/src/ostree/ot-builtin-remote.c +++ b/src/ostree/ot-builtin-remote.c @@ -22,7 +22,6 @@ #include "config.h" #include "ot-builtins.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static OstreeCommand remote_subcommands[] = { diff --git a/src/ostree/ot-builtin-reset.c b/src/ostree/ot-builtin-reset.c index 86c5d9c..126fc89 100644 --- a/src/ostree/ot-builtin-reset.c +++ b/src/ostree/ot-builtin-reset.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" /* ATTENTION: diff --git a/src/ostree/ot-builtin-rev-parse.c b/src/ostree/ot-builtin-rev-parse.c index e94012d..0d20089 100644 --- a/src/ostree/ot-builtin-rev-parse.c +++ b/src/ostree/ot-builtin-rev-parse.c @@ -23,7 +23,6 @@ #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" #include diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index c1fc0fe..0c1a8db 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" #include "ot-dump.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_print_related; diff --git a/src/ostree/ot-builtin-sign.c b/src/ostree/ot-builtin-sign.c index f51fc51..059df5b 100644 --- a/src/ostree/ot-builtin-sign.c +++ b/src/ostree/ot-builtin-sign.c @@ -28,7 +28,6 @@ #include "ostree-sign.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_delete; diff --git a/src/ostree/ot-builtin-static-delta.c b/src/ostree/ot-builtin-static-delta.c index ba9a2f2..ba91175 100644 --- a/src/ostree/ot-builtin-static-delta.c +++ b/src/ostree/ot-builtin-static-delta.c @@ -22,7 +22,6 @@ #include "ostree-cmd-private.h" #include "ostree.h" #include "ot-builtins.h" -#include "ot-main.h" #include "otutil.h" static char *opt_from_rev; diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index df980df..d131f80 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -24,7 +24,6 @@ #include "ostree.h" #include "ot-builtins.h" #include "ot-dump.h" -#include "ot-main.h" #include "otutil.h" static gboolean opt_update, opt_view, opt_raw; diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h index e14f67f..a7e4e8e 100644 --- a/src/ostree/ot-builtins.h +++ b/src/ostree/ot-builtins.h @@ -23,7 +23,6 @@ #include "config.h" -#include "ostree.h" #include "ot-main.h" G_BEGIN_DECLS diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index 59a3fcb..fa4eb53 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include "ostree.h" #include "ot-admin-functions.h" -#include "ot-main.h" #include "otutil.h" static char *opt_repo; @@ -511,6 +511,11 @@ ostree_option_context_parse (GOptionContext *context, const GOptionEntry *main_e if (opt_version) { + /* Ignore SIGPIPE so that piping the output to grep or similar + * doesn't cause the process to fail. */ + if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) + return glnx_throw_errno_prefix (error, "Ignoring SIGPIPE"); + /* This should now be YAML, like `docker version`, so it's both nice to read * possible to parse */ g_auto (GStrv) features = g_strsplit (OSTREE_FEATURES, " ", -1); diff --git a/src/ostree/ot-remote-builtin-add-cookie.c b/src/ostree/ot-remote-builtin-add-cookie.c index 900520d..a868f0f 100644 --- a/src/ostree/ot-remote-builtin-add-cookie.c +++ b/src/ostree/ot-remote-builtin-add-cookie.c @@ -23,7 +23,6 @@ #include "otutil.h" #include "ostree-repo-private.h" -#include "ot-main.h" #include "ot-remote-builtins.h" #include "ot-remote-cookie-util.h" diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index 7fd157b..f79d8b7 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -21,7 +21,6 @@ #include "otutil.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static char **opt_set; diff --git a/src/ostree/ot-remote-builtin-delete-cookie.c b/src/ostree/ot-remote-builtin-delete-cookie.c index f79854e..8af1089 100644 --- a/src/ostree/ot-remote-builtin-delete-cookie.c +++ b/src/ostree/ot-remote-builtin-delete-cookie.c @@ -24,7 +24,6 @@ #include #include "ostree-repo-private.h" -#include "ot-main.h" #include "ot-remote-builtins.h" #include "ot-remote-cookie-util.h" diff --git a/src/ostree/ot-remote-builtin-delete.c b/src/ostree/ot-remote-builtin-delete.c index e5e310f..e93929f 100644 --- a/src/ostree/ot-remote-builtin-delete.c +++ b/src/ostree/ot-remote-builtin-delete.c @@ -21,7 +21,6 @@ #include "otutil.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static gboolean opt_if_exists = FALSE; diff --git a/src/ostree/ot-remote-builtin-gpg-import.c b/src/ostree/ot-remote-builtin-gpg-import.c index 0d9744e..d24eecb 100644 --- a/src/ostree/ot-remote-builtin-gpg-import.c +++ b/src/ostree/ot-remote-builtin-gpg-import.c @@ -24,7 +24,6 @@ #include "otutil.h" -#include "ot-main.h" #include "ot-remote-builtins.h" /* XXX This belongs in libotutil. */ diff --git a/src/ostree/ot-remote-builtin-gpg-list-keys.c b/src/ostree/ot-remote-builtin-gpg-list-keys.c index 8bd4c6b..fa82553 100644 --- a/src/ostree/ot-remote-builtin-gpg-list-keys.c +++ b/src/ostree/ot-remote-builtin-gpg-list-keys.c @@ -22,7 +22,6 @@ #include "otutil.h" #include "ot-dump.h" -#include "ot-main.h" #include "ot-remote-builtins.h" /* ATTENTION: diff --git a/src/ostree/ot-remote-builtin-list-cookies.c b/src/ostree/ot-remote-builtin-list-cookies.c index 2e576d5..5d10df1 100644 --- a/src/ostree/ot-remote-builtin-list-cookies.c +++ b/src/ostree/ot-remote-builtin-list-cookies.c @@ -23,7 +23,6 @@ #include "otutil.h" #include "ostree-repo-private.h" -#include "ot-main.h" #include "ot-remote-builtins.h" #include "ot-remote-cookie-util.h" diff --git a/src/ostree/ot-remote-builtin-list.c b/src/ostree/ot-remote-builtin-list.c index 31c60ec..47ce165 100644 --- a/src/ostree/ot-remote-builtin-list.c +++ b/src/ostree/ot-remote-builtin-list.c @@ -19,7 +19,6 @@ #include "config.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static gboolean opt_show_urls; diff --git a/src/ostree/ot-remote-builtin-refs.c b/src/ostree/ot-remote-builtin-refs.c index 103c913..efd6ea9 100644 --- a/src/ostree/ot-remote-builtin-refs.c +++ b/src/ostree/ot-remote-builtin-refs.c @@ -21,7 +21,6 @@ #include "otutil.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static gboolean opt_revision; diff --git a/src/ostree/ot-remote-builtin-show-url.c b/src/ostree/ot-remote-builtin-show-url.c index 0ce7ee3..63827a0 100644 --- a/src/ostree/ot-remote-builtin-show-url.c +++ b/src/ostree/ot-remote-builtin-show-url.c @@ -21,7 +21,6 @@ #include "otutil.h" -#include "ot-main.h" #include "ot-remote-builtins.h" /* ATTENTION: diff --git a/src/ostree/ot-remote-builtin-summary.c b/src/ostree/ot-remote-builtin-summary.c index ec508cb..3b507e9 100644 --- a/src/ostree/ot-remote-builtin-summary.c +++ b/src/ostree/ot-remote-builtin-summary.c @@ -22,7 +22,6 @@ #include "otutil.h" #include "ot-dump.h" -#include "ot-main.h" #include "ot-remote-builtins.h" static gboolean opt_list_metadata_keys; diff --git a/src/ostree/ot-remote-builtins.h b/src/ostree/ot-remote-builtins.h index 0386478..88a3e31 100644 --- a/src/ostree/ot-remote-builtins.h +++ b/src/ostree/ot-remote-builtins.h @@ -19,7 +19,7 @@ #pragma once -#include +#include "ot-main.h" G_BEGIN_DECLS diff --git a/src/ostree/ot-remote-cookie-util.c b/src/ostree/ot-remote-cookie-util.c index 5b15dd3..5c926ea 100644 --- a/src/ostree/ot-remote-cookie-util.c +++ b/src/ostree/ot-remote-cookie-util.c @@ -23,7 +23,6 @@ #include "ot-remote-cookie-util.h" #include "ostree-repo-private.h" -#include "ot-main.h" #include "ot-remote-builtins.h" #include "otutil.h" diff --git a/src/rofiles-fuse/main.c b/src/rofiles-fuse/main.c index 937ee4a..0c267ea 100644 --- a/src/rofiles-fuse/main.c +++ b/src/rofiles-fuse/main.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -235,16 +236,21 @@ callback_link (const char *from, const char *to) * return -EROFS. Otherwise return 0. */ static gboolean -can_write_stbuf (const struct stat *stbuf) +can_write_stbuf (const struct statx *stbuf) { /* If it's not a regular file or symlink, ostree won't hardlink it, so allow * writes - it might be a FIFO or device that somehow * ended up underneath our mount. */ - if (!(S_ISREG (stbuf->st_mode) || S_ISLNK (stbuf->st_mode))) + if (!(S_ISREG (stbuf->stx_mode) || S_ISLNK (stbuf->stx_mode))) return TRUE; +#ifdef STATX_ATTR_VERITY + /* Can't write to fsverity files */ + if (stbuf->stx_attributes & STATX_ATTR_VERITY) + return FALSE; +#endif /* If the object isn't hardlinked, it's OK to write */ - if (stbuf->st_nlink <= 1) + if (stbuf->stx_nlink <= 1) return TRUE; /* Otherwise, it's a hardlinked file or symlink; it must be * immutable. @@ -275,18 +281,55 @@ gioerror_to_errno (GIOErrorEnum e) } } -static int -verify_write_or_copyup (const char *path, const struct stat *stbuf, gboolean *out_did_copyup) +// The libglnx APIs take a stat buffer, so we need to be able to +// convert from statx. +static inline void +statx_to_stat (const struct statx *stxbuf, struct stat *stbuf) { - struct stat stbuf_local; + stbuf->st_dev = makedev (stxbuf->stx_dev_major, stxbuf->stx_dev_minor); + stbuf->st_rdev = makedev (stxbuf->stx_rdev_major, stxbuf->stx_rdev_minor); + stbuf->st_ino = stxbuf->stx_ino; + stbuf->st_mode = stxbuf->stx_mode; + stbuf->st_nlink = stxbuf->stx_nlink; + stbuf->st_uid = stxbuf->stx_uid; + stbuf->st_gid = stxbuf->stx_gid; + stbuf->st_size = stxbuf->stx_size; + stbuf->st_blksize = stxbuf->stx_blksize; +} - if (out_did_copyup) - *out_did_copyup = FALSE; +// A copy of ostree_break_hardlink but without the check for hardlinks, which +// is mainly relevant for regular files, where we need to handle verity. +static gboolean +copyup (int dfd, const char *path, const struct statx *stxbuf, GError **error) +{ + if (S_ISREG (stxbuf->stx_mode)) + { + struct stat stbuf; + statx_to_stat (stxbuf, &stbuf); + // Note GLNX_FILE_COPY_OVERWRITE always uses O_TMPFILE+rename + return glnx_file_copy_at (dfd, path, &stbuf, dfd, path, GLNX_FILE_COPY_OVERWRITE, NULL, + error); + } + else + { + // For symlinks, we can just directly call the ostree API. This avoids + // more code duplication because atomically copying symlinks requires + // a temp-link dance. + return ostree_break_hardlink (dfd, path, FALSE, NULL, error); + } +} + +static int +verify_write_or_copyup (const char *path, const struct statx *stbuf) +{ + struct statx stbuf_local; /* If a stbuf wasn't provided, gather it now */ if (!stbuf) { - if (fstatat (basefd, path, &stbuf_local, AT_SYMLINK_NOFOLLOW) == -1) + if (statx (basefd, path, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_BASIC_STATS, + &stbuf_local) + < 0) { if (errno == ENOENT) return 0; @@ -302,10 +345,8 @@ verify_write_or_copyup (const char *path, const struct stat *stbuf, gboolean *ou if (opt_copyup) { g_autoptr (GError) tmp_error = NULL; - if (!ostree_break_hardlink (basefd, path, FALSE, NULL, &tmp_error)) + if (!copyup (basefd, path, stbuf, &tmp_error)) return -gioerror_to_errno ((GIOErrorEnum)tmp_error->code); - if (out_did_copyup) - *out_did_copyup = TRUE; } else return -EROFS; @@ -322,7 +363,7 @@ verify_write_or_copyup (const char *path, const struct stat *stbuf, gboolean *ou do \ { \ path = ENSURE_RELPATH (path); \ - int r = verify_write_or_copyup (path, NULL, NULL); \ + int r = verify_write_or_copyup (path, NULL); \ if (r != 0) \ return r; \ } \ @@ -401,7 +442,7 @@ static int do_open (const char *path, mode_t mode, struct fuse_file_info *finfo) { int fd; - struct stat stbuf; + struct statx stbuf; path = ENSURE_RELPATH (path); @@ -415,53 +456,22 @@ do_open (const char *path, mode_t mode, struct fuse_file_info *finfo) else { /* Write */ - - /* We need to specially handle O_TRUNC */ - fd = openat (basefd, path, finfo->flags & ~O_TRUNC, mode); - if (fd == -1) - return -errno; - - if (fstat (fd, &stbuf) == -1) - { - (void)close (fd); - return -errno; - } - - gboolean did_copyup; - int r = verify_write_or_copyup (path, &stbuf, &did_copyup); - if (r != 0) + if (statx (basefd, path, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_BASIC_STATS, &stbuf) + == -1) { - (void)close (fd); - return r; - } - - /* In the copyup case, we need to re-open */ - if (did_copyup) - { - (void)close (fd); - /* Note that unlike the initial open, we will pass through - * O_TRUNC. More ideally in this copyup case we'd avoid copying - * the whole file in the first place, but eh. It's not like we're - * high performance anyways. - */ - fd = openat (basefd, path, finfo->flags & ~(O_EXCL | O_CREAT), mode); - if (fd == -1) + if (errno != ENOENT) return -errno; } else { - /* In the non-copyup case we handle O_TRUNC here, after we've verified - * the hardlink state above with verify_write_or_copyup(). - */ - if (finfo->flags & O_TRUNC) - { - if (ftruncate (fd, 0) == -1) - { - (void)close (fd); - return -errno; - } - } + int r = verify_write_or_copyup (path, &stbuf); + if (r != 0) + return r; } + + fd = openat (basefd, path, finfo->flags, mode); + if (fd == -1) + return -errno; } finfo->fh = fd; diff --git a/src/switchroot/ostree-mount-util.h b/src/switchroot/ostree-mount-util.h index eb79efd..608528f 100644 --- a/src/switchroot/ostree-mount-util.h +++ b/src/switchroot/ostree-mount-util.h @@ -36,6 +36,10 @@ #define _OSTREE_SYSROOT_READONLY_STAMP "/run/ostree-sysroot-ro.stamp" #define _OSTREE_COMPOSEFS_ROOT_STAMP "/run/ostree-composefs-root.stamp" +#define OTCORE_SYSROOT_NOT_WRITEABLE \ + "sysroot.readonly=true requires %s to be writable at this point, the cmdline should contain rw " \ + "but not ro, if that is not the case this is likely the issue" + #define autofree __attribute__ ((cleanup (cleanup_free))) static inline int diff --git a/src/switchroot/ostree-prepare-root-static.c b/src/switchroot/ostree-prepare-root-static.c index 4aaa469..3995a6f 100644 --- a/src/switchroot/ostree-prepare-root-static.c +++ b/src/switchroot/ostree-prepare-root-static.c @@ -204,12 +204,11 @@ main (int argc, char *argv[]) const bool sysroot_readonly = sysroot_is_configured_ro (root_arg); const bool sysroot_currently_writable = !path_is_on_readonly_fs (root_arg); - /* Work-around for a kernel bug: for some reason the kernel - * refuses switching root if any file systems are mounted - * MS_SHARED. Hence remount them MS_PRIVATE here as a - * work-around. + /* Remount root MS_PRIVATE here to avoid errors due to the kernel-enforced + * constraint that disallows MS_SHARED mounts to be moved. * - * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ + * Kernel docs: Documentation/filesystems/sharedsubtree.txt + */ if (mount (NULL, "/", NULL, MS_REC | MS_PRIVATE | MS_SILENT, NULL) < 0) err (EXIT_FAILURE, "failed to make \"/\" private mount"); @@ -229,8 +228,7 @@ main (int argc, char *argv[]) if (sysroot_readonly) { if (!sysroot_currently_writable) - errx (EXIT_FAILURE, "sysroot.readonly=true requires %s to be writable at this point", - root_arg); + errx (EXIT_FAILURE, OTCORE_SYSROOT_NOT_WRITEABLE, root_arg); /* Pass on the fact that we discovered a readonly sysroot to ostree-remount.service */ int fd = open (_OSTREE_SYSROOT_READONLY_STAMP, O_WRONLY | O_CREAT | O_CLOEXEC, 0644); if (fd < 0) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 27d06fa..b93e05c 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -76,24 +76,14 @@ #include "ot-keyfile-utils.h" #include "otcore.h" -#define PREPARE_ROOT_CONFIG_PATH "ostree/prepare-root.conf" - -// This key is used by default if present in the initramfs to verify -// the signature on the target commit object. When composefs is -// in use, the ostree commit metadata will contain the composefs image digest, -// which can be used to fully verify the target filesystem tree. -#define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key" - #define SYSROOT_KEY "sysroot" #define READONLY_KEY "readonly" +/* This key configures the / mount in the deployment root */ +#define ROOT_KEY "root" #define ETC_KEY "etc" #define TRANSIENT_KEY "transient" -#define COMPOSEFS_KEY "composefs" -#define ENABLED_KEY "enabled" -#define KEYPATH_KEY "keypath" - #define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG \ SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7) @@ -134,7 +124,7 @@ resolve_deploy_path (const char *root_mountpoint) g_autoptr (GError) error = NULL; g_autofree char *ostree_target = NULL; - if (!otcore_get_ostree_target (kernel_cmdline, &ostree_target, &error)) + if (!otcore_get_ostree_target (kernel_cmdline, NULL, &ostree_target, &error)) errx (EXIT_FAILURE, "Failed to determine ostree target: %s", error->message); if (!ostree_target) errx (EXIT_FAILURE, "No ostree target found"); @@ -256,79 +246,6 @@ composefs_error_message (int errsv) #endif -typedef struct -{ - OtTristate enabled; - gboolean is_signed; - char *signature_pubkey; - GPtrArray *pubkeys; -} ComposefsConfig; - -static void -free_composefs_config (ComposefsConfig *config) -{ - g_ptr_array_unref (config->pubkeys); - g_free (config->signature_pubkey); - g_free (config); -} - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (ComposefsConfig, free_composefs_config) - -// Parse the [composefs] section of the prepare-root.conf. -static ComposefsConfig * -load_composefs_config (GKeyFile *config, GError **error) -{ - GLNX_AUTO_PREFIX_ERROR ("Loading composefs config", error); - - g_autoptr (ComposefsConfig) ret = g_new0 (ComposefsConfig, 1); - - g_autofree char *enabled = g_key_file_get_value (config, COMPOSEFS_KEY, ENABLED_KEY, NULL); - if (g_strcmp0 (enabled, "signed") == 0) - { - ret->enabled = OT_TRISTATE_YES; - ret->is_signed = true; - } - else if (!ot_keyfile_get_tristate_with_default (config, COMPOSEFS_KEY, ENABLED_KEY, - OT_TRISTATE_MAYBE, &ret->enabled, error)) - return NULL; - - // Look for a key - we default to the initramfs binding path. - if (!ot_keyfile_get_value_with_default (config, COMPOSEFS_KEY, KEYPATH_KEY, BINDING_KEYPATH, - &ret->signature_pubkey, error)) - return NULL; - - if (ret->is_signed) - { - ret->pubkeys = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref); - - g_autofree char *pubkeys = NULL; - gsize pubkeys_size; - - /* Load keys */ - - if (!g_file_get_contents (ret->signature_pubkey, &pubkeys, &pubkeys_size, error)) - return glnx_prefix_error_null (error, "Reading public key file '%s'", - ret->signature_pubkey); - - g_auto (GStrv) lines = g_strsplit (pubkeys, "\n", -1); - for (char **iter = lines; *iter; iter++) - { - const char *line = *iter; - if (!*line) - continue; - - gsize pubkey_size; - g_autofree guchar *pubkey = g_base64_decode (line, &pubkey_size); - g_ptr_array_add (ret->pubkeys, g_bytes_new_take (g_steal_pointer (&pubkey), pubkey_size)); - } - - if (ret->pubkeys->len == 0) - return glnx_null_throw (error, "public key file specified, but no public keys found"); - } - - return g_steal_pointer (&ret); -} - int main (int argc, char *argv[]) { @@ -352,10 +269,16 @@ main (int argc, char *argv[]) errx (EXIT_FAILURE, "Failed to parse config: %s", error->message); gboolean sysroot_readonly = FALSE; + gboolean root_transient = FALSE; + + if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, TRANSIENT_KEY, FALSE, &root_transient, + &error)) + return FALSE; // We always parse the composefs config, because we want to detect and error // out if it's enabled, but not supported at compile time. - g_autoptr (ComposefsConfig) composefs_config = load_composefs_config (config, &error); + g_autoptr (ComposefsConfig) composefs_config + = otcore_load_composefs_config (config, TRUE, &error); if (!composefs_config) errx (EXIT_FAILURE, "%s", error->message); @@ -374,7 +297,12 @@ main (int argc, char *argv[]) const char *root_mountpoint = realpath (root_arg, NULL); if (root_mountpoint == NULL) err (EXIT_FAILURE, "realpath(\"%s\")", root_arg); - char *deploy_path = resolve_deploy_path (root_mountpoint); + g_autofree char *deploy_path = resolve_deploy_path (root_mountpoint); + const char *deploy_directory_name = glnx_basename (deploy_path); + // Note that realpath() should have stripped any trailing `/` which shouldn't + // be in the karg to start with, but we assert here to be sure we have a non-empty + // filename. + g_assert (deploy_directory_name && *deploy_directory_name); if (mkdirat (AT_FDCWD, OTCORE_RUN_OSTREE, 0755) < 0) err (EXIT_FAILURE, "Failed to create %s", OTCORE_RUN_OSTREE); @@ -399,12 +327,11 @@ main (int argc, char *argv[]) g_print ("sysroot.readonly configuration value: %d (fs writable: %d)\n", (int)sysroot_readonly, (int)sysroot_currently_writable); - /* Work-around for a kernel bug: for some reason the kernel - * refuses switching root if any file systems are mounted - * MS_SHARED. Hence remount them MS_PRIVATE here as a - * work-around. + /* Remount root MS_PRIVATE here to avoid errors due to the kernel-enforced + * constraint that disallows MS_SHARED mounts to be moved. * - * https://bugzilla.redhat.com/show_bug.cgi?id=847418 */ + * Kernel docs: Documentation/filesystems/sharedsubtree.txt + */ if (mount (NULL, "/", NULL, MS_REC | MS_PRIVATE | MS_SILENT, NULL) < 0) err (EXIT_FAILURE, "failed to make \"/\" private mount"); @@ -418,6 +345,15 @@ main (int argc, char *argv[]) GVariantBuilder metadata_builder; g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}")); + /* Record the underlying plain deployment directory (device,inode) pair + * so that it can be later checked by the sysroot code to figure out + * which deployment was booted. + */ + if (lstat (".", &stbuf) < 0) + err (EXIT_FAILURE, "lstat deploy_root"); + g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_BACKING_ROOTDEVINO, + g_variant_new ("(tt)", (guint64)stbuf.st_dev, (guint64)stbuf.st_ino)); + // Tracks if we did successfully enable it at runtime bool using_composefs = false; @@ -433,13 +369,39 @@ main (int argc, char *argv[]) 1, }; - cfs_options.flags = LCFS_MOUNT_FLAGS_READONLY; + cfs_options.flags = 0; cfs_options.image_mountdir = OSTREE_COMPOSEFS_LOWERMNT; if (mkdirat (AT_FDCWD, OSTREE_COMPOSEFS_LOWERMNT, 0700) < 0) err (EXIT_FAILURE, "Failed to create %s", OSTREE_COMPOSEFS_LOWERMNT); g_autofree char *expected_digest = NULL; + // For now we just stick the transient root on the default /run tmpfs; + // however, see + // https://github.com/systemd/systemd/blob/604b2001081adcbd64ee1fbe7de7a6d77c5209fe/src/basic/mountpoint-util.h#L36 + // which bumps up these defaults for the rootfs a bit. + g_autofree char *root_upperdir + = root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/upper", NULL) + : NULL; + g_autofree char *root_workdir + = root_transient ? g_build_filename (OTCORE_RUN_OSTREE_PRIVATE, "root/work", NULL) : NULL; + + // Propagate these options for transient root, if provided + if (root_transient) + { + if (!glnx_shutil_mkdir_p_at (AT_FDCWD, root_upperdir, 0755, NULL, &error)) + errx (EXIT_FAILURE, "Failed to create %s: %s", root_upperdir, error->message); + if (!glnx_shutil_mkdir_p_at (AT_FDCWD, root_workdir, 0700, NULL, &error)) + errx (EXIT_FAILURE, "Failed to create %s: %s", root_workdir, error->message); + + cfs_options.workdir = root_workdir; + cfs_options.upperdir = root_upperdir; + } + else + { + cfs_options.flags = LCFS_MOUNT_FLAGS_READONLY; + } + if (composefs_config->is_signed) { const char *composefs_pubkey = composefs_config->signature_pubkey; @@ -487,7 +449,7 @@ main (int argc, char *argv[]) using_composefs = true; g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_COMPOSEFS, g_variant_new_boolean (true)); - g_print ("composefs: mounted successfully"); + g_print ("composefs: mounted successfully\n"); } else { @@ -512,18 +474,26 @@ main (int argc, char *argv[]) if (!using_composefs) { + if (root_transient) + { + errx (EXIT_FAILURE, "Must enable composefs with root.transient"); + } + g_print ("Using legacy ostree bind mount for /\n"); /* The deploy root starts out bind mounted to sysroot.tmp */ if (mount (deploy_path, TMP_SYSROOT, NULL, MS_BIND | MS_SILENT, NULL) < 0) err (EXIT_FAILURE, "failed to make initial bind mount %s", deploy_path); } + /* Pass on the state */ + g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_ROOT_TRANSIENT, + g_variant_new_boolean (root_transient)); + /* This will result in a system with /sysroot read-only. Thus, two additional * writable bind-mounts (for /etc and /var) are required later on. */ if (sysroot_readonly) { if (!sysroot_currently_writable) - errx (EXIT_FAILURE, "sysroot.readonly=true requires %s to be writable at this point", - root_arg); + errx (EXIT_FAILURE, OTCORE_SYSROOT_NOT_WRITEABLE, root_arg); } /* Pass on the state for use by ostree-prepare-root */ g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_SYSROOT_RO, @@ -548,7 +518,7 @@ main (int argc, char *argv[]) /* Prepare /etc. * No action required if sysroot is writable. Otherwise, a bind-mount for * the deployment needs to be created and remounted as read/write. */ - if (sysroot_readonly || using_composefs) + if (sysroot_readonly || using_composefs || root_transient) { gboolean etc_transient = FALSE; if (!ot_keyfile_get_boolean_with_default (config, ETC_KEY, TRANSIENT_KEY, FALSE, @@ -598,25 +568,25 @@ main (int argc, char *argv[]) } /* Prepare /usr. - * It may be either just a read-only bind-mount, or a persistent overlayfs. */ - if (lstat (".usr-ovl-work", &stbuf) == 0) + * It may be either just a read-only bind-mount, or a persistent overlayfs if set up + * with ostree admin unlock --hotfix. + * Note however that root.transient as handled above is effectively a generalization of unlock + * --hotfix. + * Also, hotfixes are incompatible with signed composefs use for security reasons. + */ + if (lstat (OTCORE_HOTFIX_USR_OVL_WORK, &stbuf) == 0 + && !(using_composefs && composefs_config->is_signed)) { /* Do we have a persistent overlayfs for /usr? If so, mount it now. */ const char usr_ovl_options[] - = "lowerdir=" TMP_SYSROOT "/usr,upperdir=.usr-ovl-upper,workdir=.usr-ovl-work"; - - /* Except overlayfs barfs if we try to mount it on a read-only - * filesystem. For this use case I think admins are going to be - * okay if we remount the rootfs here, rather than waiting until - * later boot and `systemd-remount-fs.service`. - */ - if (path_is_on_readonly_fs (TMP_SYSROOT)) - { - if (mount (TMP_SYSROOT, TMP_SYSROOT, NULL, MS_REMOUNT | MS_SILENT, NULL) < 0) - err (EXIT_FAILURE, "failed to remount rootfs writable (for overlayfs)"); - } + = "lowerdir=" TMP_SYSROOT + "/usr,upperdir=.usr-ovl-upper,workdir=" OTCORE_HOTFIX_USR_OVL_WORK; - if (mount ("overlay", TMP_SYSROOT "/usr", "overlay", MS_SILENT, usr_ovl_options) < 0) + unsigned long mflags = MS_SILENT; + // Propagate readonly state + if (!sysroot_currently_writable) + mflags |= MS_RDONLY; + if (mount ("overlay", TMP_SYSROOT "/usr", "overlay", mflags, usr_ovl_options) < 0) err (EXIT_FAILURE, "failed to mount /usr overlayfs"); } else if (!using_composefs) diff --git a/tests/admin-test.sh b/tests/admin-test.sh index 520a875..2adae9d 100644 --- a/tests/admin-test.sh +++ b/tests/admin-test.sh @@ -19,15 +19,21 @@ set -euo pipefail -echo "1..$((30 + ${extra_admin_tests:-0}))" - +echo "1..$((31 + ${extra_admin_tests:-0}))" + +for flag in --modern --epoch=1; do + mkdir sysrootmin + ${CMD_PREFIX} ostree admin init-fs --modern sysrootmin + assert_has_dir sysrootmin/boot + assert_has_dir sysrootmin/ostree/repo + assert_not_has_dir sysrootmin/home + rm sysrootmin -rf +done mkdir sysrootmin -${CMD_PREFIX} ostree admin init-fs --modern sysrootmin -assert_has_dir sysrootmin/boot -assert_has_dir sysrootmin/ostree/repo +${CMD_PREFIX} ostree admin init-fs --epoch=2 sysrootmin +assert_streq "$(stat -c '%f' sysrootmin/ostree)" 41c0 assert_not_has_dir sysrootmin/home -rm sysrootmin -rf -echo "ok init-fs --modern" +echo "ok init-fs" function validate_bootloader() { cd ${test_tmpdir}; @@ -54,7 +60,9 @@ orig_mtime=$(stat -c '%.Y' sysroot/ostree/deploy) ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) export rev -# This initial deployment gets kicked off with some kernel arguments +# This initial deployment gets kicked off with some kernel arguments. We also set the initial +# timestamp of the deploy directory to the epoch as a regression test. +touch -d @0 sysroot/ostree/deploy ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmain/x86_64-runtime new_mtime=$(stat -c '%.Y' sysroot/ostree/deploy) assert_not_streq "${orig_mtime}" "${new_mtime}" @@ -63,6 +71,11 @@ assert_not_file_has_content status.txt "pending" assert_not_file_has_content status.txt "rollback" validate_bootloader +# Someday probably soon we'll turn this on by default, but for now +if test -f sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs; then + fatal "found composefs unexpectedly" +fi + # Test the bootable and linux keys ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo --print-metadata-key=ostree.linux show testos:testos/buildmain/x86_64-runtime >out.txt assert_file_has_content_literal out.txt 3.6.0 @@ -87,9 +100,9 @@ echo "ok nice error for deploy with no stateroot" assert_not_has_dir sysroot/boot/loader.0 assert_has_dir sysroot/boot/loader.1 assert_has_dir sysroot/ostree/boot.1.1 -assert_has_file sysroot/boot/loader/entries/ostree-1-testos.conf -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* quiet' +assert_has_file sysroot/boot/loader/entries/ostree-1.conf +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* quiet' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/os-release 'NAME=TestOS' assert_file_has_content sysroot/ostree/boot.1/testos/${bootcsum}/0/etc/os-release 'NAME=TestOS' @@ -115,7 +128,7 @@ assert_not_has_dir sysroot/ostree/boot.0.0 assert_not_has_dir sysroot/ostree/boot.1.0 assert_not_has_dir sysroot/ostree/boot.1.1 # Ensure we propagated kernel arguments from previous deployment -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.* root=LABEL=MOO' assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.1/etc/os-release 'NAME=TestOS' assert_file_has_content sysroot/ostree/boot.0/testos/${bootcsum}/0/etc/os-release 'NAME=TestOS' assert_ostree_deployment_refs 0/1/{0,1} @@ -142,8 +155,8 @@ ${CMD_PREFIX} ostree admin os-init otheros ${CMD_PREFIX} ostree admin deploy --os=otheros testos/buildmain/x86_64-runtime assert_not_has_dir sysroot/boot/loader.0 assert_has_dir sysroot/boot/loader.1 -assert_has_file sysroot/boot/loader/entries/ostree-2-testos.conf -assert_has_file sysroot/boot/loader/entries/ostree-3-otheros.conf +assert_has_file sysroot/boot/loader/entries/ostree-2.conf +assert_has_file sysroot/boot/loader/entries/ostree-3.conf assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.1/etc/os-release 'NAME=TestOS' assert_file_has_content sysroot/ostree/deploy/otheros/deploy/${rev}.0/etc/os-release 'NAME=TestOS' assert_ostree_deployment_refs 1/1/{0,1,2} @@ -155,9 +168,9 @@ echo "ok independent deploy" ${CMD_PREFIX} ostree admin deploy --retain --os=testos testos:testos/buildmain/x86_64-runtime assert_has_dir sysroot/boot/loader.0 assert_not_has_dir sysroot/boot/loader.1 -assert_has_file sysroot/boot/loader/entries/ostree-4-testos.conf +assert_has_file sysroot/boot/loader/entries/ostree-4.conf assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.2/etc/os-release 'NAME=TestOS' -assert_has_file sysroot/boot/loader/entries/ostree-2-testos.conf +assert_has_file sysroot/boot/loader/entries/ostree-2.conf assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/os-release 'NAME=TestOS' ${CMD_PREFIX} ostree admin status assert_ostree_deployment_refs 0/1/{0,1,2,3} @@ -187,18 +200,24 @@ ${CMD_PREFIX} ostree admin status validate_bootloader echo "ok deploy with modified /etc" +if ${CMD_PREFIX} ostree admin undeploy blah 2>err.txt; then + fatal "undeploy parsed string" +fi +assert_file_has_content_literal err.txt 'error: Invalid index: blah' +echo "ok undeploy error invalid int" + # we now have 5 deployments, let's bring that back down to 1 for i in $(seq 4); do ${CMD_PREFIX} ostree admin undeploy 0 done -assert_has_file sysroot/boot/loader/entries/ostree-1-testos.conf -assert_not_has_file sysroot/boot/loader/entries/ostree-2-testos.conf -assert_not_has_file sysroot/boot/loader/entries/ostree-3-otheros.conf +assert_has_file sysroot/boot/loader/entries/ostree-1.conf +assert_not_has_file sysroot/boot/loader/entries/ostree-2.conf +assert_not_has_file sysroot/boot/loader/entries/ostree-3.conf ${CMD_PREFIX} ostree admin deploy --not-as-default --os=otheros testos:testos/buildmain/x86_64-runtime assert_has_dir sysroot/boot/loader.0 assert_not_has_dir sysroot/boot/loader.1 -assert_has_file sysroot/boot/loader/entries/ostree-2-testos.conf -assert_has_file sysroot/boot/loader/entries/ostree-1-otheros.conf +assert_has_file sysroot/boot/loader/entries/ostree-2.conf +assert_has_file sysroot/boot/loader/entries/ostree-1.conf ${CMD_PREFIX} ostree admin status validate_bootloader @@ -207,9 +226,9 @@ echo "ok deploy --not-as-default" ${CMD_PREFIX} ostree admin deploy --retain-rollback --os=otheros testos:testos/buildmain/x86_64-runtime assert_not_has_dir sysroot/boot/loader.0 assert_has_dir sysroot/boot/loader.1 -assert_has_file sysroot/boot/loader/entries/ostree-3-otheros.conf -assert_has_file sysroot/boot/loader/entries/ostree-2-testos.conf -assert_has_file sysroot/boot/loader/entries/ostree-1-otheros.conf +assert_has_file sysroot/boot/loader/entries/ostree-3.conf +assert_has_file sysroot/boot/loader/entries/ostree-2.conf +assert_has_file sysroot/boot/loader/entries/ostree-1.conf ${CMD_PREFIX} ostree admin status validate_bootloader @@ -217,11 +236,11 @@ echo "ok deploy --retain-rollback" ${CMD_PREFIX} ostree admin status -assert_file_has_content sysroot/boot/loader/entries/ostree-3-otheros.conf "^title.*TestOS 42 1.0.10" +assert_file_has_content sysroot/boot/loader/entries/ostree-3.conf "^title.*TestOS 42 1.0.10" ${CMD_PREFIX} ostree admin set-default 1 -assert_file_has_content sysroot/boot/loader/entries/ostree-3-testos.conf "^title.*TestOS 42 1.0.10" +assert_file_has_content sysroot/boot/loader/entries/ostree-3.conf "^title.*TestOS 42 1.0.10" ${CMD_PREFIX} ostree admin set-default 1 -assert_file_has_content sysroot/boot/loader/entries/ostree-3-otheros.conf "^title.*TestOS 42 1.0.10" +assert_file_has_content sysroot/boot/loader/entries/ostree-3.conf "^title.*TestOS 42 1.0.10" echo "ok set-default" @@ -294,7 +313,7 @@ echo "ok deploy with unknown OS" ${CMD_PREFIX} ostree admin deploy --os=testos --karg-append=console=/dev/foo --karg-append=console=/dev/bar testos:testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf 'console=/dev/foo.*console=/dev/bar' +assert_file_has_content sysroot/boot/loader/entries/ostree-4.conf 'console=/dev/foo.*console=/dev/bar' validate_bootloader echo "ok deploy with multiple kernel args" @@ -304,17 +323,17 @@ os_repository_new_commit 0 "test upgrade multiple kernel args" ${CMD_PREFIX} ostree admin upgrade --os=testos newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) assert_not_streq ${origrev} ${newrev} -assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf 'console=/dev/foo.*console=/dev/bar' +assert_file_has_content sysroot/boot/loader/entries/ostree-4.conf 'console=/dev/foo.*console=/dev/bar' validate_bootloader echo "ok upgrade with multiple kernel args" os_repository_new_commit ${CMD_PREFIX} ostree admin upgrade --os=testos -assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 ${version} (ostree:testos:0)$" +assert_file_has_content sysroot/boot/loader/entries/ostree-4.conf "^title TestOS 42 ${version} (ostree:testos:0)$" os_repository_new_commit 0 0 testos/buildmain/x86_64-runtime 42 ${CMD_PREFIX} ostree admin upgrade --os=testos -assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 (ostree:testos:0)$" +assert_file_has_content sysroot/boot/loader/entries/ostree-4.conf "^title TestOS 42 (ostree:testos:0)$" echo "ok no duplicate version strings in title" diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 7905e6e..c8f853f 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -1159,6 +1159,18 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper && touch overlay/baz/an assert_has_file overlay-co/baz test -L overlay-co/anewdir + rm overlay-co overlay -rf + mkdir -p overlay/somelink overlay/yet/ovlnewdir + echo ovlnewf > overlay/yet/ovlnewdir/ovlnewf + $OSTREE --repo=repo commit ${COMMIT_ARGS} -b overlay-symlink-convert --tree=dir=overlay + for branch in test2 overlay-symlink-convert; do + $OSTREE --repo=repo checkout --union --whiteouts ${branch} overlay-co + done + test -d overlay-co/somelink || fatal "should replace symlink with dir" + assert_has_dir overlay-co/yet/another + assert_has_dir overlay-co/yet/ovlnewdir + assert_file_has_content overlay-co/yet/ovlnewdir/ovlnewf ovlnewf + rm overlay-co overlay -rf echo "ok whiteouts enabled" # Now double check whiteouts are not processed without --whiteouts diff --git a/tests/libtest.sh b/tests/libtest.sh index d1c99ea..2c2a33f 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -696,18 +696,20 @@ skip_without_fuse () { [ -e /etc/mtab ] || skip "no /etc/mtab" } -has_gpgme () { - local ret +has_ostree_feature () { + local ret=0 + # Note that this needs to write to a file and then grep the file, to + # avoid ostree --version being killed with SIGPIPE and exiting with a + # nonzero status under `set -o pipefail`. ${CMD_PREFIX} ostree --version > version.txt - grep -q -e '- gpgme' version.txt - ret=$? + grep -q -e "- $1\$" version.txt || ret=$? rm -f version.txt return ${ret} } -skip_without_gpgme() { - if ! has_gpgme; then - skip "no gpg support compiled in" +skip_without_ostree_feature () { + if ! has_ostree_feature "$1"; then + skip "no $1 support compiled in" fi } @@ -750,21 +752,6 @@ libtest_cleanup_gpg () { } libtest_exit_cmds+=(libtest_cleanup_gpg) -has_sign_ed25519 () { - local ret - ${CMD_PREFIX} ostree --version > version.txt - grep -q -e '- sign-ed25519' version.txt - ret=$? - rm -f version.txt - 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/pull-test.sh b/tests/pull-test.sh index f408429..d61735a 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -54,7 +54,7 @@ function verify_initial_contents() { n_base_tests=35 gpg_tests=3 -if has_gpgme; then +if has_ostree_feature gpgme; then echo "1..$(($n_base_tests+$gpg_tests))" else echo "1..$((n_base_tests))" @@ -633,7 +633,7 @@ fi assert_file_has_content err.txt "404" echo "ok pull repo 404" -if has_gpgme; then +if has_ostree_feature gpgme; then cd ${test_tmpdir} repo_init --set=gpg-verify=true if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main 2>err.txt; then @@ -653,7 +653,7 @@ assert_file_has_content err.txt "404" find ostree-srv/gnomerepo/objects -name '*.dirtree.orig' | while read f; do mv ${f} $(dirname $f)/$(basename ${f} .orig); done echo "ok pull repo 404 on dirtree object" -if has_gpgme; then +if has_ostree_feature gpgme; then cd ${test_tmpdir} repo_init --set=gpg-verify=true ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit ${COMMIT_ARGS} \ diff --git a/tests/test-admin-deploy-2.sh b/tests/test-admin-deploy-2.sh index 23645de..97cd0fd 100755 --- a/tests/test-admin-deploy-2.sh +++ b/tests/test-admin-deploy-2.sh @@ -69,9 +69,9 @@ oldversion=${version} # another commit with *same* bootcsum but *new* content os_repository_new_commit "1" "2" newversion=${version} -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf ${oldversion} +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf ${oldversion} ${CMD_PREFIX} ostree admin upgrade --os=testos -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf ${newversion} +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf ${newversion} echo "ok new version same bootcsum" diff --git a/tests/test-admin-deploy-bootprefix.sh b/tests/test-admin-deploy-bootprefix.sh index d80c310..712855d 100755 --- a/tests/test-admin-deploy-bootprefix.sh +++ b/tests/test-admin-deploy-bootprefix.sh @@ -27,8 +27,8 @@ setup_os_repository "archive" "syslinux" ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set sysroot.bootprefix 'true' ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=root --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content_literal sysroot/boot/loader/entries/ostree-1-testos.conf 'linux /boot/ostree/testos-' -assert_file_has_content_literal sysroot/boot/loader/entries/ostree-1-testos.conf 'initrd /boot/ostree/testos-' +assert_file_has_content_literal sysroot/boot/loader/entries/ostree-1.conf 'linux /boot/ostree/testos-' +assert_file_has_content_literal sysroot/boot/loader/entries/ostree-1.conf 'initrd /boot/ostree/testos-' tap_ok "bootprefix" diff --git a/tests/test-admin-deploy-composefs.sh b/tests/test-admin-deploy-composefs.sh new file mode 100755 index 0000000..fd39dc8 --- /dev/null +++ b/tests/test-admin-deploy-composefs.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# +# Copyright (C) 2024 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, see . + +set -euox pipefail + +. $(dirname $0)/libtest.sh + +skip_without_ostree_feature composefs + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive" "syslinux" + +cd osdata +mkdir -p usr/lib/ostree +cat > usr/lib/ostree/prepare-root.conf << 'EOF' +[composefs] +enabled=true +EOF +${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.composefs -b testos/buildmain/x86_64-runtime +cd - +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime + +${CMD_PREFIX} ostree admin deploy --os=testos --karg=root=LABEL=foo --karg=testkarg=1 testos:testos/buildmain/x86_64-runtime +ls sysroot/ostree/deploy/testos/deploy/*.0/.ostree.cfs + +tap_ok composefs + +tap_end diff --git a/tests/test-admin-deploy-karg.sh b/tests/test-admin-deploy-karg.sh index 39fcdf3..89d613f 100755 --- a/tests/test-admin-deploy-karg.sh +++ b/tests/test-admin-deploy-karg.sh @@ -24,7 +24,7 @@ set -euo pipefail # Exports OSTREE_SYSROOT so --sysroot not needed. setup_os_repository "archive" "syslinux" -echo "1..4" +echo "1..5" ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) @@ -33,12 +33,12 @@ export rev ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree admin deploy --karg=FOO=BAR --os=testos testos:testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree admin deploy --karg=TESTARG=TESTVALUE --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*TESTARG=TESTVALUE' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*TESTARG=TESTVALUE' ${CMD_PREFIX} ostree admin deploy --karg=ANOTHERARG=ANOTHERVALUE --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*TESTARG=TESTVALUE' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*ANOTHERARG=ANOTHERVALUE' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*TESTARG=TESTVALUE' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*ANOTHERARG=ANOTHERVALUE' echo "ok deploy with --karg, but same config" @@ -49,7 +49,7 @@ for arg in $(cat /proc/cmdline); do ;; initrd=*|BOOT_IMAGE=*) # Skip options set by bootloader that gets filtered out ;; - *) assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf "options.*$arg" + *) assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf "options.*$arg" ;; esac done @@ -60,20 +60,27 @@ ${CMD_PREFIX} ostree admin status ${CMD_PREFIX} ostree admin undeploy 0 ${CMD_PREFIX} ostree admin deploy --os=testos --karg-append=APPENDARG=VALAPPEND --karg-append=APPENDARG=2NDAPPEND testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*TESTARG=TESTVALUE' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*TESTARG=TESTVALUE' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' # Check correct ordering of different-valued args of the same key. ${CMD_PREFIX} ostree admin deploy --os=testos --karg-append=FOO=TESTORDERED --karg-append=APPENDARG=3RDAPPEND testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND .*FOO=TESTORDERED .*APPENDARG=3RDAPPEND' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND .*FOO=TESTORDERED .*APPENDARG=3RDAPPEND' echo "ok deploy --karg-append" -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*quiet .*TESTARG=TESTVALUE .*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*quiet .*TESTARG=TESTVALUE .*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' ${CMD_PREFIX} ostree admin deploy --os=testos --karg-delete=TESTARG=TESTVALUE --karg-delete=quiet --karg-delete=APPENDARG=VALAPPEND testos:testos/buildmain/x86_64-runtime -assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*TESTARG=TESTVALUE' -assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*quiet' -assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'options.*APPENDARG=VALAPPEND' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*TESTARG=TESTVALUE' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*quiet' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*APPENDARG=VALAPPEND' echo "ok deploy --karg-delete" + +${CMD_PREFIX} ostree admin deploy --os=testos --karg-append 'test="1 2"' testos:testos/buildmain/x86_64-runtime +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*test="1 2"' +${CMD_PREFIX} ostree admin deploy --os=testos --karg-delete 'test="1 2"' testos:testos/buildmain/x86_64-runtime +assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'options.*test="1 2"' + +echo "ok deploy --karg-delete with quotes" diff --git a/tests/test-admin-deploy-nomerge.sh b/tests/test-admin-deploy-nomerge.sh index 9016f2d..bac5ee4 100755 --- a/tests/test-admin-deploy-nomerge.sh +++ b/tests/test-admin-deploy-nomerge.sh @@ -30,11 +30,11 @@ ${CMD_PREFIX} ostree admin deploy --os=testos --karg=root=LABEL=foo --karg=testk origdeployment=$(${CMD_PREFIX} ostree admin --sysroot=sysroot --print-current-dir) testconfig=etc/modified-config-file-that-will-be-removed touch "${origdeployment}"/"${testconfig}" -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf "^options.*root=LABEL=foo.*testkarg" +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf "^options.*root=LABEL=foo.*testkarg" ${CMD_PREFIX} ostree admin deploy --os=testos --no-merge --karg=root=LABEL=bar testos:testos/buildmain/x86_64-runtime deployment=$(${CMD_PREFIX} ostree admin --sysroot=sysroot --print-current-dir) assert_not_streq "${origdeployment}" "${deployment}" assert_not_has_file "${deployment}/${testconfig}" -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf "^options root=LABEL=bar" -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf "^options .*testkarg" +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf "^options root=LABEL=bar" +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf "^options .*testkarg" echo "ok no merge deployment" diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh index 22a7700..ad79e25 100755 --- a/tests/test-admin-deploy-none.sh +++ b/tests/test-admin-deploy-none.sh @@ -39,7 +39,7 @@ mkdir -p sysroot/boot/grub2 touch sysroot/boot/grub2/grub.cfg ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmain/x86_64-runtime > out.txt assert_file_has_content out.txt "Bootloader updated.*" -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* root=LABEL=MOO' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/.vmlinuz-3.6.0.hmac 'an hmac file' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs' diff --git a/tests/test-admin-deploy-syslinux.sh b/tests/test-admin-deploy-syslinux.sh index d2cb504..3db2198 100755 --- a/tests/test-admin-deploy-syslinux.sh +++ b/tests/test-admin-deploy-syslinux.sh @@ -36,8 +36,8 @@ for test_bootdir in "boot" "usr/lib/ostree-boot"; do ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmain/x86_64-runtime - assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' - assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* quiet' + assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* root=LABEL=MOO' + assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* quiet' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs' # kernel/initrams should also be in the tree's /boot with the checksum @@ -62,7 +62,7 @@ cd ${test_tmpdir} ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.* root=LABEL=MOO' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs' # Note this bootcsum shouldn't be the modules one diff --git a/tests/test-admin-deploy-var.sh b/tests/test-admin-deploy-var.sh new file mode 100755 index 0000000..fc61576 --- /dev/null +++ b/tests/test-admin-deploy-var.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# +# Copyright (C) 2024 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, see . + +set -euox pipefail + +. $(dirname $0)/libtest.sh + +if ! has_ostree_feature initial-var; then + fatal missing initial-var +fi + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive" "syslinux" + +echo "initial ls" +ls -R sysroot/ostree/deploy/testos/var + +cd osdata +mkdir -p var/lib/ +echo somedata > var/lib/somefile +${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit -b testos/buildmain/x86_64-runtime +cd - +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime + +${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime +ls -R sysroot/ostree/deploy/testos/var +assert_file_has_content sysroot/ostree/deploy/testos/var/lib/somefile somedata +# We don't have tmpfiles here yet +assert_not_has_dir sysroot/ostree/deploy/*.0/usr/lib/tmpfiles.d +if ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo ls testos/buildmain/x86_64-runtime /var/log; then + fatal "var/log in commit" +fi +# This one is created via legacy init w/o tmpfiles.d +assert_has_dir sysroot/ostree/deploy/testos/var/log + +tap_ok deployment var init + +cd osdata +echo someotherdata > var/lib/someotherfile +${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit -b testos/buildmain/x86_64-runtime +cd - +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime +${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime +assert_not_has_file sysroot/ostree/deploy/testos/var/lib/someotherfile + +tap_ok deployment var not updated + +${CMD_PREFIX} ostree admin undeploy 0 +${CMD_PREFIX} ostree admin undeploy 0 +rm sysroot/ostree/deploy/testos/var/* -rf + +cd osdata +mkdir -p usr/lib/tmpfiles.d +${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit -b testos/buildmain/x86_64-runtime +cd - +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime +${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime + +# Not in the commit, so not created via legacy init because we have tmpfiles.d +assert_not_has_dir sysroot/ostree/deploy/testos/var/log + +tap_ok deployment var w/o legacy + +tap_end diff --git a/tests/test-admin-gpg.sh b/tests/test-admin-gpg.sh index f71c306..6283b12 100755 --- a/tests/test-admin-gpg.sh +++ b/tests/test-admin-gpg.sh @@ -34,7 +34,7 @@ setup_os_repository_signed () { bootdir=${1:-usr/lib/modules/3.6.0} oldpwd=`pwd` - keyid="472CDAFA" + keyid="7FCA23D8472CDAFA" cd ${test_tmpdir} mkdir testos-repo diff --git a/tests/test-admin-instutil-set-kargs.sh b/tests/test-admin-instutil-set-kargs.sh index a1aabef..27fd1eb 100755 --- a/tests/test-admin-instutil-set-kargs.sh +++ b/tests/test-admin-instutil-set-kargs.sh @@ -32,25 +32,25 @@ ${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-run ${CMD_PREFIX} ostree admin instutil set-kargs FOO=BAR ${CMD_PREFIX} ostree admin instutil set-kargs FOO=BAZ FOO=BIF TESTARG=TESTVALUE KEYWORD EMPTYLIST= -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=BAZ .*FOO=BIF' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=BAZ .*FOO=BIF' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' echo "ok instutil set-kargs (basic)" ${CMD_PREFIX} ostree admin instutil set-kargs --merge FOO=BAR -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=BAZ .*FOO=BIF .*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=BAZ .*FOO=BIF .*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' echo "ok instutil set-kargs --merge" ${CMD_PREFIX} ostree admin instutil set-kargs --merge --replace=FOO=XXX -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=XXX' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=XXX' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*TESTARG=TESTVALUE KEYWORD EMPTYLIST=' echo "ok instutil set-kargs --replace" ${CMD_PREFIX} ostree admin instutil set-kargs --merge --append=FOO=BAR --append=APPENDARG=VALAPPEND --append=APPENDARG=2NDAPPEND testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*FOO=XXX.*FOO=BAR' -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*FOO=XXX.*FOO=BAR' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*APPENDARG=VALAPPEND .*APPENDARG=2NDAPPEND' echo "ok instutil set-kargs --append" ${CMD_PREFIX} ostree admin instutil set-kargs --import-proc-cmdline @@ -60,7 +60,7 @@ for arg in $(cat /proc/cmdline); do ;; initrd=*|BOOT_IMAGE=*) # Skip options set by bootloader that gets filtered out ;; - *) assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf "options.*$arg" + *) assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf "options.*$arg" ;; esac done diff --git a/tests/test-admin-kargs.sh b/tests/test-admin-kargs.sh index afcfc05..8211c25 100755 --- a/tests/test-admin-kargs.sh +++ b/tests/test-admin-kargs.sh @@ -31,14 +31,14 @@ ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testo ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree admin kargs edit-in-place --append-if-missing=TESTARG=TESTVALUE --append-if-missing=ARGWITHOUTKEY testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.*TESTARG=TESTVALUE .*ARGWITHOUTKEY' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'options.*TESTARG=TESTVALUE .*ARGWITHOUTKEY' echo "ok kargs edit-in-place (basic)" ${CMD_PREFIX} ostree admin kargs edit-in-place --append-if-missing=quiet testos:testos/buildmain/x86_64-runtime -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'quiet$' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'quiet$' ${CMD_PREFIX} ostree admin kargs edit-in-place --append-if-missing=TESTARG=TESTVALUE testos:testos/buildmain/x86_64-runtime -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'TESTARG=TESTVALUE$' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'TESTARG=TESTVALUE$' echo "ok kargs edit-in-place (duplicate)" diff --git a/tests/test-admin-pull-deploy-split.sh b/tests/test-admin-pull-deploy-split.sh index 52bec63..ebe3038 100755 --- a/tests/test-admin-pull-deploy-split.sh +++ b/tests/test-admin-pull-deploy-split.sh @@ -44,13 +44,13 @@ ${CMD_PREFIX} ostree admin upgrade --os=testos --pull-only --os=testos > out.txt assert_not_file_has_content out.txt 'No update available' assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'TestOS 42 1\.0\.9' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'TestOS 42 1\.0\.9' assert_streq "${rev}" $(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmain/x86_64-runtime) # Now, generate new content upstream; we shouldn't pull it os_repository_new_commit ${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt assert_not_file_has_content out.txt 'No update available' -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'TestOS 42 1\.0\.10' +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'TestOS 42 1\.0\.10' assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 ${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt diff --git a/tests/test-admin-stateroot.sh b/tests/test-admin-stateroot.sh new file mode 100755 index 0000000..ee746fc --- /dev/null +++ b/tests/test-admin-stateroot.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# +# Copyright (C) 2011 Colin Walters +# Copyright (C) 2022 Huijing Hei +# +# 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, see . + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive" "syslinux" + +echo "1..2" + +# Initial deployment on testos stateroot +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmain/x86_64-runtime +${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime + +REF=$(${CMD_PREFIX} ostree admin status | grep -oE 'testos .*\.0' | sed -e 's/^testos //' -e 's/\.0$//') + +# Should prompt bootloader update as it does have a different stateroot +${CMD_PREFIX} ostree admin stateroot-init testos2 +${CMD_PREFIX} ostree admin deploy ${REF} --os=testos2 +${CMD_PREFIX} ostree admin set-default 1 >out.txt + +assert_file_has_content out.txt 'bootconfig swap: yes' +echo "ok stateroot new-deployment" + +# Should not prompt update to bootloader as stateroot/commit and kargs are all the same. +${CMD_PREFIX} ostree admin deploy ${REF} --os=testos2 +${CMD_PREFIX} ostree admin deploy ${REF} --os=testos2 +${CMD_PREFIX} ostree admin set-default 1 >out.txt + +assert_file_has_content out.txt 'bootconfig swap: no' +echo "ok stateroot equal-deployment" diff --git a/tests/test-admin-upgrade-endoflife.sh b/tests/test-admin-upgrade-endoflife.sh index ecac228..5336ea1 100755 --- a/tests/test-admin-upgrade-endoflife.sh +++ b/tests/test-admin-upgrade-endoflife.sh @@ -63,7 +63,7 @@ ${CMD_PREFIX} ostree admin upgrade --os=testos --pull-only ${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only # Check we got redirected to the new branch -assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf "${bootcsum}" +assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf "${bootcsum}" rev=$(${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo rev-parse testos/buildmain/newbranch) assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/usr/bin/content-iteration "1" diff --git a/tests/test-commit-sign.sh b/tests/test-commit-sign.sh index e0cea0b..8e1ba61 100755 --- a/tests/test-commit-sign.sh +++ b/tests/test-commit-sign.sh @@ -21,10 +21,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -if ! has_gpgme; then - echo "1..0 #SKIP no gpg support compiled in" - exit 0 -fi +skip_without_ostree_feature gpgme if test -z "${OSTREE_HTTPD}"; then echo "1..0 #SKIP no ostree-trivial-httpd" @@ -33,7 +30,7 @@ fi echo "1..7" -keyid="472CDAFA" +keyid="7FCA23D8472CDAFA" oldpwd=`pwd` mkdir ostree-srv cd ostree-srv diff --git a/tests/test-composefs.sh b/tests/test-composefs.sh index 4b91973..f0f5cac 100755 --- a/tests/test-composefs.sh +++ b/tests/test-composefs.sh @@ -19,11 +19,8 @@ set -euo pipefail . $(dirname $0)/libtest.sh -if ! ${CMD_PREFIX} ostree --version | grep -q -e '- composefs'; then - echo "1..0 #SKIP no composefs support compiled in" - exit 0 -fi - +skip_without_ostree_feature composefs +skip_without_user_xattrs setup_test_repository "bare-user" diff --git a/tests/test-create-usb.sh b/tests/test-create-usb.sh index 016d32c..064501f 100755 --- a/tests/test-create-usb.sh +++ b/tests/test-create-usb.sh @@ -24,7 +24,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -skip_without_gpgme +skip_without_ostree_feature gpgme echo "1..5" diff --git a/tests/test-delta-ed25519.sh b/tests/test-delta-ed25519.sh index 9e00fdb..9cd2228 100755 --- a/tests/test-delta-ed25519.sh +++ b/tests/test-delta-ed25519.sh @@ -23,7 +23,7 @@ set -euo pipefail skip_without_user_xattrs -skip_without_sign_ed25519 +skip_without_ostree_feature sign-ed25519 bindatafiles="bash true ostree" diff --git a/tests/test-export.sh b/tests/test-export.sh index 6b8de94..23e5166 100755 --- a/tests/test-export.sh +++ b/tests/test-export.sh @@ -19,13 +19,9 @@ set -euo pipefail -if ! ostree --version | grep -q -e '- libarchive'; then - echo "1..0 #SKIP no libarchive support compiled in" - exit 0 -fi - . $(dirname $0)/libtest.sh +skip_without_ostree_feature libarchive setup_test_repository "archive" echo '1..6' diff --git a/tests/test-find-remotes.sh b/tests/test-find-remotes.sh index abcc41d..3ec81f9 100755 --- a/tests/test-find-remotes.sh +++ b/tests/test-find-remotes.sh @@ -21,7 +21,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -skip_without_gpgme +skip_without_ostree_feature gpgme echo '1..1' diff --git a/tests/test-gpg-signed-commit.sh b/tests/test-gpg-signed-commit.sh index 7b00f9e..d3b5433 100755 --- a/tests/test-gpg-signed-commit.sh +++ b/tests/test-gpg-signed-commit.sh @@ -22,10 +22,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -if ! has_gpgme; then - echo "1..0 #SKIP no gpgme support compiled in" - exit 0 -fi +skip_without_ostree_feature gpgme num_tests=1 diff --git a/tests/test-gpg-verify-result.c b/tests/test-gpg-verify-result.c index e7171a8..5844c66 100644 --- a/tests/test-gpg-verify-result.c +++ b/tests/test-gpg-verify-result.c @@ -183,7 +183,7 @@ test_signature_lookup (TestFixture *fixture, gconstpointer user_data) /* Lookup abbreviated key ID. */ signature_index = 999999; signature_found - = ostree_gpg_verify_result_lookup (fixture->result, fingerprint + 32, &signature_index); + = ostree_gpg_verify_result_lookup (fixture->result, fingerprint + 24, &signature_index); g_assert_true (signature_found); g_assert_cmpint (signature_index, ==, expected_signature_index); diff --git a/tests/test-kargs.c b/tests/test-kargs.c index bd1735d..90f11e5 100644 --- a/tests/test-kargs.c +++ b/tests/test-kargs.c @@ -24,8 +24,7 @@ static gboolean check_string_existance (OstreeKernelArgs *karg, const char *string_to_find) { - g_autofree gchar *string_with_spaces = ostree_kernel_args_to_string (karg); - g_auto (GStrv) string_list = g_strsplit (string_with_spaces, " ", -1); + g_auto (GStrv) string_list = ostree_kernel_args_to_strv (karg); return g_strv_contains ((const char *const *)string_list, string_to_find); } @@ -140,6 +139,16 @@ test_kargs_delete (void) g_assert_no_error (error); g_assert (ret); g_assert (!check_string_existance (karg, "nosmt")); + + /* Make sure we also support quotes and spaces */ + ostree_kernel_args_append (karg, "foo=\"1 2\" bar=0"); + check_string_existance (karg, "foo=\"1 2\""); + check_string_existance (karg, "bar=0"); + ret = ostree_kernel_args_delete (karg, "foo=\"1 2\" bar=0", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "foo=\"1 2\"")); + g_assert (!check_string_existance (karg, "bar=0")); } static void @@ -189,6 +198,16 @@ test_kargs_replace (void) g_assert (ret); g_assert (!check_string_existance (karg, "test=firstval")); g_assert (check_string_existance (karg, "test=newval")); + + /* Replace with input contains quotes and spaces, it should support */ + ostree_kernel_args_append (karg, "foo=1 bar=\"1 2\""); + ret = ostree_kernel_args_new_replace (karg, "foo=\"1 2\" bar", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "foo=1")); + g_assert (!check_string_existance (karg, "bar=\"1 2\"")); + g_assert (check_string_existance (karg, "foo=\"1 2\"")); + g_assert (check_string_existance (karg, "bar")); } /* In this function, we want to verify that ostree_kernel_args_append @@ -206,6 +225,7 @@ test_kargs_append (void) ostree_kernel_args_append (append_arg, "test="); ostree_kernel_args_append (append_arg, "test"); ostree_kernel_args_append (append_arg, "second_test"); + ostree_kernel_args_append (append_arg, "second_test=0 second_test=\"1 2\""); /* We loops through the kargs inside table to verify * the functionality of append because at this stage @@ -230,6 +250,10 @@ test_kargs_append (void) g_assert_cmpstr (key, ==, "second_test"); g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL, kernel_args_entry_value_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (value_array, "0", + kernel_args_entry_value_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (value_array, "\"1 2\"", + kernel_args_entry_value_equal, NULL)); } } @@ -243,14 +267,15 @@ test_kargs_append (void) /* Up till this point, we verified that the above was all correct, we then * check ostree_kernel_args_to_string has the right result */ - g_autofree gchar *kargs_str = ostree_kernel_args_to_string (append_arg); - g_auto (GStrv) kargs_list = g_strsplit (kargs_str, " ", -1); + g_auto (GStrv) kargs_list = ostree_kernel_args_to_strv (append_arg); g_assert (g_strv_contains ((const char *const *)kargs_list, "test=valid")); g_assert (g_strv_contains ((const char *const *)kargs_list, "test=secondvalid")); g_assert (g_strv_contains ((const char *const *)kargs_list, "test=")); g_assert (g_strv_contains ((const char *const *)kargs_list, "test")); g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test")); - g_assert_cmpint (5, ==, g_strv_length (kargs_list)); + g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test=0")); + g_assert (g_strv_contains ((const char *const *)kargs_list, "second_test=\"1 2\"")); + g_assert_cmpint (7, ==, g_strv_length (kargs_list)); } int diff --git a/tests/test-libarchive-import.c b/tests/test-libarchive-import.c index 86536fc..5643db7 100644 --- a/tests/test-libarchive-import.c +++ b/tests/test-libarchive-import.c @@ -629,7 +629,9 @@ test_libarchive_selinux (gconstpointer data) if (skip_if_no_xattr (td)) goto out; - if (getenv ("container")) + // xref https://bugzilla.redhat.com/show_bug.cgi?id=2278652 + if (getenv ("container") || g_file_test ("/run/.containerenv", G_FILE_TEST_EXISTS) + || g_file_test ("/.dockerenv", G_FILE_TEST_EXISTS)) { // FIXME dedup this with libtest.sh have_selinux_relabel g_test_skip ("skip in containers for now"); diff --git a/tests/test-libarchive.sh b/tests/test-libarchive.sh index 6317502..d9ce37b 100755 --- a/tests/test-libarchive.sh +++ b/tests/test-libarchive.sh @@ -19,13 +19,10 @@ set -euo pipefail -if ! ostree --version | grep -q -e '- libarchive'; then - echo "1..0 #SKIP no libarchive support compiled in" - exit 0 -fi - . $(dirname $0)/libtest.sh +skip_without_ostree_feature libarchive + echo "1..18" setup_test_repository "bare" diff --git a/tests/test-local-pull.sh b/tests/test-local-pull.sh index 79b86ab..e1b916c 100755 --- a/tests/test-local-pull.sh +++ b/tests/test-local-pull.sh @@ -61,7 +61,7 @@ cmp checkout1.files checkout2.files cmp checkout1.files checkout3.files echo "ok checkouts same" -if has_gpgme; then +if has_ostree_feature gpgme; then # These tests are needed GPG support mkdir repo4 ostree_repo_init repo4 --mode="archive" diff --git a/tests/test-no-initramfs.sh b/tests/test-no-initramfs.sh index 84c4457..bd25b68 100755 --- a/tests/test-no-initramfs.sh +++ b/tests/test-no-initramfs.sh @@ -12,8 +12,8 @@ ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=fals ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull testos testos/buildmain/x86_64-runtime ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=rootfs --os=testos testos:testos/buildmain/x86_64-runtime -assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'root=LABEL=rootfs' -assert_not_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'init=' +assert_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'root=LABEL=rootfs' +assert_not_file_has_content sysroot/boot/loader/entries/ostree-1.conf 'init=' echo "ok deployment with initramfs" @@ -63,28 +63,28 @@ for layout in /usr/lib/modules /usr/lib/ostree-boot /boot; do pull_test_tree "the kernel only" ${CMD_PREFIX} ostree admin deploy --os=testos --karg=root=/dev/sda2 --karg=rootwait testos:testos/buildmain/x86_64-runtime - assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'rootwait' - assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'init=' - assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'initrd' + assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'rootwait' + assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'init=' + assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'initrd' echo "ok switching to bootdir with no initramfs layout=$layout" pull_test_tree "the kernel" "initramfs to assist the kernel" ${CMD_PREFIX} ostree admin deploy --os=testos --karg-none --karg=root=LABEL=rootfs testos:testos/buildmain/x86_64-runtime - assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'initrd' - assert_file_has_content sysroot/boot/$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2-testos.conf "initrd") "initramfs to assist the kernel" - assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'root=LABEL=rootfs' - assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'rootwait' - assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'init=' + assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'initrd' + assert_file_has_content sysroot/boot/$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2.conf "initrd") "initramfs to assist the kernel" + assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'root=LABEL=rootfs' + assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'rootwait' + assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'init=' echo "ok switching from no initramfs to initramfs enabled sysroot layout=$layout" pull_test_tree "the kernel" "" "my .dtb file" ${CMD_PREFIX} ostree admin deploy --os=testos testos:testos/buildmain/x86_64-runtime - assert_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'init=' - assert_file_has_content sysroot/boot/"$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2-testos.conf 'devicetree')" "my \.dtb file" - assert_not_file_has_content sysroot/boot/loader/entries/ostree-2-testos.conf 'initrd' + assert_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'init=' + assert_file_has_content sysroot/boot/"$(get_key_from_bootloader_conf sysroot/boot/loader/entries/ostree-2.conf 'devicetree')" "my \.dtb file" + assert_not_file_has_content sysroot/boot/loader/entries/ostree-2.conf 'initrd' echo "ok switching from initramfs to no initramfs sysroot with devicetree layout=$layout" done diff --git a/tests/test-otcore.c b/tests/test-otcore.c index 4af575b..2d8003e 100644 --- a/tests/test-otcore.c +++ b/tests/test-otcore.c @@ -36,46 +36,46 @@ test_prepare_root_cmdline (void) { g_autoptr (GError) error = NULL; g_autofree char *target = NULL; - static const char *notfound_cases[] = { "", "foo", "foo=bar baz sometest", "xostree foo", "xostree=blah bar", NULL }; for (const char **iter = notfound_cases; iter && *iter; iter++) { const char *tcase = *iter; - g_assert (otcore_get_ostree_target (tcase, &target, &error)); + g_assert (otcore_get_ostree_target (tcase, NULL, &target, &error)); g_assert_no_error (error); g_assert (target == NULL); } // Test the default ostree= - g_assert (otcore_get_ostree_target ("blah baz=blah ostree=/foo/bar somearg", &target, &error)); + g_assert ( + otcore_get_ostree_target ("blah baz=blah ostree=/foo/bar somearg", NULL, &target, &error)); g_assert_no_error (error); g_assert_cmpstr (target, ==, "/foo/bar"); free (g_steal_pointer (&target)); // Test android boot - g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_b somearg", &target, - &error)); + g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_b somearg", NULL, + &target, &error)); g_assert_no_error (error); g_assert_cmpstr (target, ==, "/ostree/root.b"); free (g_steal_pointer (&target)); - g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_a somearg", &target, - &error)); + g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_a somearg", NULL, + &target, &error)); g_assert_no_error (error); g_assert_cmpstr (target, ==, "/ostree/root.a"); free (g_steal_pointer (&target)); // And an expected failure to parse a "c" suffix - g_assert (!otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_c somearg", &target, - &error)); + g_assert (!otcore_get_ostree_target ("blah baz=blah androidboot.slot_suffix=_c somearg", NULL, + &target, &error)); g_assert (error); g_assert (target == NULL); g_clear_error (&error); // And non-A/B androidboot - g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.somethingelse somearg", &target, - &error)); + g_assert (otcore_get_ostree_target ("blah baz=blah androidboot.somethingelse somearg", NULL, + &target, &error)); g_assert_no_error (error); g_assert_cmpstr (target, ==, "/ostree/root.a"); free (g_steal_pointer (&target)); diff --git a/tests/test-parent.sh b/tests/test-parent.sh index 4b5806c..5a8809f 100755 --- a/tests/test-parent.sh +++ b/tests/test-parent.sh @@ -23,7 +23,7 @@ set -euo pipefail skip_without_user_xattrs -skip_without_gpgme +skip_without_ostree_feature gpgme echo '1..2' diff --git a/tests/test-pre-signed-pull.sh b/tests/test-pre-signed-pull.sh index 2a1a1d2..0ac8e0a 100755 --- a/tests/test-pre-signed-pull.sh +++ b/tests/test-pre-signed-pull.sh @@ -23,7 +23,7 @@ set -euo pipefail echo "1..1" -if ! has_sign_ed25519; then +if ! has_ostree_feature sign-ed25519; then echo "ok pre-signed pull # SKIP due ed25519 unavailability" exit 0 fi diff --git a/tests/test-pull-collections.sh b/tests/test-pull-collections.sh index 1d14e5d..518545d 100755 --- a/tests/test-pull-collections.sh +++ b/tests/test-pull-collections.sh @@ -33,7 +33,7 @@ do_commit() { mkdir -p files pushd files local GPG_ARGS="" - if has_gpgme; then + if has_ostree_feature gpgme; then GPG_ARGS="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi ${CMD_PREFIX} ostree --repo="../${repo}" commit -s "Test ${repo} commit for branch ${branch}" -b "${branch}" ${GPG_ARGS} "$@" > "../${branch}-checksum" @@ -45,7 +45,7 @@ do_summary() { shift 1 local GPG_ARGS="" - if has_gpgme; then + if has_ostree_feature gpgme; then GPG_ARGS="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi ${CMD_PREFIX} ostree "--repo=${repo}" summary --update ${GPG_ARGS} @@ -103,7 +103,7 @@ do_remote_add() { shift 2 local GPG_ARGS="" - if has_gpgme; then + if has_ostree_feature gpgme; then GPG_ARGS="--gpg-import=${test_tmpdir}/gpghome/key1.asc" fi ${CMD_PREFIX} ostree "--repo=${repo}" remote add "${remote_repo}-remote" "file://$(pwd)/${remote_repo}" "$@" ${GPG_ARGS} diff --git a/tests/test-pull-contenturl.sh b/tests/test-pull-contenturl.sh index d47fdfe..63eecf7 100755 --- a/tests/test-pull-contenturl.sh +++ b/tests/test-pull-contenturl.sh @@ -29,7 +29,7 @@ fi echo "1..2" COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi @@ -47,7 +47,7 @@ cp -a ${test_tmpdir}/ostree-srv ostree # delete all the meta stuff from here rm ostree/gnomerepo/summary -if has_gpgme; then +if has_ostree_feature gpgme; then rm ostree/gnomerepo/summary.sig find ostree/gnomerepo/objects -name '*.commitmeta' | xargs rm fi @@ -63,7 +63,7 @@ echo "http://127.0.0.1:${content_port}" > ${test_tmpdir}/httpd-content-address cd ${test_tmpdir} mkdir repo ostree_repo_init repo -if has_gpgme; then VERIFY=true; else VERIFY=false; fi +if has_ostree_feature gpgme; then VERIFY=true; else VERIFY=false; fi ${CMD_PREFIX} ostree --repo=repo remote add origin \ --set=gpg-verify=$VERIFY --set=gpg-verify-summary=$VERIFY \ --contenturl=$(cat httpd-content-address)/ostree/gnomerepo \ @@ -72,7 +72,7 @@ ${CMD_PREFIX} ostree --repo=repo pull origin:main echo "ok pull objects from contenturl" -if ! has_gpgme; then +if ! has_ostree_feature gpgme; then echo "ok don't pull sigs from contenturl # SKIP not compiled with gpgme" else echo "ok don't pull sigs from contenturl" diff --git a/tests/test-pull-mirror-summary.sh b/tests/test-pull-mirror-summary.sh index 94a8c02..88a37b8 100755 --- a/tests/test-pull-mirror-summary.sh +++ b/tests/test-pull-mirror-summary.sh @@ -22,7 +22,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" echo "1..5" else @@ -67,7 +67,7 @@ find repo/objects -name '*.filez' | while read name; do done echo "ok pull mirror summary" -if ! has_gpgme; then +if ! has_ostree_feature gpgme; then exit 0; fi diff --git a/tests/test-pull-repeated.sh b/tests/test-pull-repeated.sh index 7f724c9..b3e0074 100755 --- a/tests/test-pull-repeated.sh +++ b/tests/test-pull-repeated.sh @@ -22,7 +22,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi diff --git a/tests/test-pull-summary-caching.sh b/tests/test-pull-summary-caching.sh index 8c6727d..180f671 100755 --- a/tests/test-pull-summary-caching.sh +++ b/tests/test-pull-summary-caching.sh @@ -24,10 +24,7 @@ set -euo pipefail . $(dirname $0)/libtest.sh -if ! has_gpgme; then - echo "1..0 #SKIP no gpg support compiled in" - exit 0 -fi +skip_without_ostree_feature gpgme # Ensure repo caching is in use. unset OSTREE_SKIP_CACHE diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index e1b0412..8a5cc4f 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -25,7 +25,7 @@ set -euo pipefail unset OSTREE_SKIP_CACHE COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" echo "1..10" else @@ -63,7 +63,7 @@ assert_file_has_content yet-another-copy/yet-another-hello-world "hello world ye ${CMD_PREFIX} ostree --repo=repo fsck echo "ok pull mirror summary" -if ! has_gpgme; then +if ! has_ostree_feature gpgme; then exit 0; fi diff --git a/tests/test-rofiles-fuse.sh b/tests/test-rofiles-fuse.sh index a56a76c..b47bb36 100755 --- a/tests/test-rofiles-fuse.sh +++ b/tests/test-rofiles-fuse.sh @@ -26,7 +26,7 @@ skip_without_user_xattrs setup_test_repository "bare" -echo "1..12" +echo "1..13" cd ${test_tmpdir} mkdir mnt @@ -192,3 +192,21 @@ sed -i -e s,first,second, mnt/firstfile assert_file_has_content_literal mnt/firstfile "second" echo "ok copyup" + +copyup_reset +echo nonhardlinked > checkout-test2/nonhardlinked +if fsverity enable checkout-test2/nonhardlinked 2>err.txt; then + orig_inode=$(stat -c %i checkout-test2/nonhardlinked) + echo "updated content" > mnt/nonhardlinked + new_inode=$(stat -c %i checkout-test2/nonhardlinked) + assert_not_streq "${orig_inode}" "${new_inode}" + # And via chmod + fsverity enable checkout-test2/nonhardlinked + orig_inode=$(stat -c %i checkout-test2/nonhardlinked) + chmod 0700 mnt/nonhardlinked + new_inode=$(stat -c %i checkout-test2/nonhardlinked) + assert_not_streq "${orig_inode}" "${new_inode}" + echo "ok copyup fsverity" +else + echo "ok copyup fsverity # SKIP no fsverity support: $(cat err.txt)" +fi diff --git a/tests/test-signed-commit.sh b/tests/test-signed-commit.sh index 432687d..cf1cd1c 100755 --- a/tests/test-signed-commit.sh +++ b/tests/test-signed-commit.sh @@ -61,7 +61,7 @@ assert_file_has_content_literal err.txt ' No valid signatures found' echo "ok dummy sig requires env" # tests below require libsodium support -if ! has_sign_ed25519; then +if ! has_ostree_feature sign-ed25519; then echo "ok Detached ed25519 signature # SKIP due libsodium unavailability" echo "ok ed25519 signature verified # SKIP due libsodium unavailability" echo "ok multiple signing # SKIP due libsodium unavailability" diff --git a/tests/test-signed-pull-summary.sh b/tests/test-signed-pull-summary.sh index d287389..e533907 100755 --- a/tests/test-signed-pull-summary.sh +++ b/tests/test-signed-pull-summary.sh @@ -52,7 +52,7 @@ do PUBLIC_KEY="dummysign" ;; ed25519) - if ! has_sign_ed25519; then + if ! has_ostree_feature sign-ed25519; then echo "ok ${engine} pull mirror summary # SKIP due libsodium unavailability" echo "ok ${engine} pull with signed summary # SKIP due libsodium unavailability" echo "ok ${engine} prune summary cache # SKIP due libsodium unavailability" @@ -174,7 +174,7 @@ do done -if ! has_sign_ed25519; then +if ! has_ostree_feature sign-ed25519; then echo "ok ${engine} pull with signed summary remote old summary # SKIP due libsodium unavailability" echo "ok ${engine} pull with signed summary broken cache # SKIP due libsodium unavailability" exit 0 diff --git a/tests/test-signed-pull.sh b/tests/test-signed-pull.sh index 5754914..a08d3fb 100755 --- a/tests/test-signed-pull.sh +++ b/tests/test-signed-pull.sh @@ -140,7 +140,7 @@ fi assert_file_has_content err.txt 'Invalid key reference' echo "ok remote add errs" -if ! has_sign_ed25519; then +if ! has_ostree_feature sign-ed25519; then echo "ok ed25519-key pull signed commit # SKIP due libsodium unavailability" echo "ok ed25519-key re-pull signature for stored commit # SKIP due libsodium unavailability" echo "ok ed25519-key+file pull signed commit # SKIP due libsodium unavailability" diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index d85e9c4..643502c 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -27,7 +27,7 @@ set -euo pipefail echo "1..2" COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi @@ -51,6 +51,14 @@ ${CMD_PREFIX} ostree --repo=repo summary --update # Generate a signed summary file. ${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN} +# If the signature file was created, it should have the same +# modification time as the summary file. +if [ -n "${COMMIT_SIGN}" ]; then + stat -c '%y' repo/summary > summary-mtime + stat -c '%y' repo/summary.sig > summary.sig-mtime + assert_files_equal summary-mtime summary.sig-mtime +fi + # Try various ways of adding additional data. ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true ${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123' @@ -87,6 +95,14 @@ ${CMD_PREFIX} ostree --repo=repo summary --update # Generate a signed summary file. ${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN} +# If the signature file was created, it should have the same +# modification time as the summary file. +if [ -n "${COMMIT_SIGN}" ]; then + stat -c '%y' repo/summary > summary-mtime + stat -c '%y' repo/summary.sig > summary.sig-mtime + assert_files_equal summary-mtime summary.sig-mtime +fi + # Try various ways of adding additional data. ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true ${CMD_PREFIX} ostree --repo=repo summary --update -m some-int='@t 123' diff --git a/tests/test-summary-view.sh b/tests/test-summary-view.sh index 9dfc74f..473c6db 100755 --- a/tests/test-summary-view.sh +++ b/tests/test-summary-view.sh @@ -27,7 +27,7 @@ set -euo pipefail echo "1..2" COMMIT_SIGN="" -if has_gpgme; then +if has_ostree_feature gpgme; then COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" fi diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index f9b8f81..574abc7 100755 --- a/tests/test-symbols.sh +++ b/tests/test-symbols.sh @@ -54,7 +54,7 @@ echo 'ok documented symbols' # ONLY update this checksum in release commits! cat > released-sha256.txt <