Imported Upstream version 2016.6
This commit is contained in:
parent
a7b5654e44
commit
24762929e2
|
|
@ -21,7 +21,8 @@ if BUILDOPT_DRACUT
|
|||
# Not using $(libdir) here is intentional, dracut modules go in prefix/lib
|
||||
dracutmoddir = $(prefix)/lib/dracut/modules.d/98ostree
|
||||
dracutmod_SCRIPTS = src/boot/dracut/module-setup.sh
|
||||
|
||||
endif
|
||||
if BUILDOPT_DRACUT_CONF
|
||||
dracutconfdir = $(sysconfdir)/dracut.conf.d
|
||||
dracutconf_DATA = src/boot/dracut/ostree.conf
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# Common variables
|
||||
AM_CPPFLAGS =
|
||||
AM_CFLAGS =
|
||||
DISTCHECK_CONFIGURE_FLAGS =
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS =
|
||||
SUBDIRS =
|
||||
NULL =
|
||||
BUILT_SOURCES =
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
libostree_public_headers = \
|
||||
src/libostree/ostree.h \
|
||||
src/libostree/ostree-async-progress.h \
|
||||
src/libostree/ostree-autocleanups.h \
|
||||
src/libostree/ostree-core.h \
|
||||
src/libostree/ostree-dummy-enumtypes.h \
|
||||
src/libostree/ostree-mutable-tree.h \
|
||||
src/libostree/ostree-repo.h \
|
||||
src/libostree/ostree-types.h \
|
||||
|
|
|
|||
|
|
@ -33,9 +33,11 @@ lib_LTLIBRARIES += libostree-1.la
|
|||
libostreeincludedir = $(includedir)/ostree-1
|
||||
libostreeinclude_HEADERS = $(libostree_public_headers)
|
||||
|
||||
ENUM_TYPES = \
|
||||
$(srcdir)/src/libostree/ostree-fetcher.h \
|
||||
$(NULL)
|
||||
ENUM_TYPES = $(NULL)
|
||||
|
||||
if USE_LIBSOUP
|
||||
ENUM_TYPES += $(srcdir)/src/libostree/ostree-fetcher.h
|
||||
endif
|
||||
|
||||
src/libostree/ostree-enumtypes.h: src/libostree/ostree-enumtypes.h.template $(ENUM_TYPES)
|
||||
$(AM_V_GEN) $(GLIB_MKENUMS) \
|
||||
|
|
@ -48,12 +50,14 @@ src/libostree/ostree-enumtypes.c: src/libostree/ostree-enumtypes.c.template $(EN
|
|||
--fhead "#include \"ostree-enumtypes.h\"" \
|
||||
$(ENUM_TYPES) > $@.tmp && mv $@.tmp $@
|
||||
|
||||
if USE_LIBSOUP
|
||||
ENUM_GENERATED = \
|
||||
src/libostree/ostree-enumtypes.h \
|
||||
src/libostree/ostree-enumtypes.c \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES += $(ENUM_GENERATED)
|
||||
endif
|
||||
|
||||
CLEANFILES += $(BUILT_SOURCES)
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ libostree_1_la_SOURCES = \
|
|||
src/libostree/ostree-cmdprivate.c \
|
||||
src/libostree/ostree-core-private.h \
|
||||
src/libostree/ostree-core.c \
|
||||
src/libostree/ostree-dummy-enumtypes.c \
|
||||
src/libostree/ostree-checksum-input-stream.c \
|
||||
src/libostree/ostree-checksum-input-stream.h \
|
||||
src/libostree/ostree-chain-input-stream.c \
|
||||
|
|
@ -90,6 +95,7 @@ libostree_1_la_SOURCES = \
|
|||
src/libostree/ostree-repo.c \
|
||||
src/libostree/ostree-repo-checkout.c \
|
||||
src/libostree/ostree-repo-commit.c \
|
||||
src/libostree/ostree-repo-pull.c \
|
||||
src/libostree/ostree-repo-libarchive.c \
|
||||
src/libostree/ostree-repo-prune.c \
|
||||
src/libostree/ostree-repo-refs.c \
|
||||
|
|
@ -123,6 +129,7 @@ libostree_1_la_SOURCES = \
|
|||
src/libostree/ostree-gpg-verifier.h \
|
||||
src/libostree/ostree-gpg-verify-result.c \
|
||||
src/libostree/ostree-gpg-verify-result-private.h \
|
||||
src/libostree/ostree-autocleanups.h \
|
||||
$(NULL)
|
||||
if USE_LIBARCHIVE
|
||||
libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \
|
||||
|
|
@ -142,6 +149,8 @@ libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(
|
|||
libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions -Wl,--version-script=$(top_srcdir)/src/libostree/libostree.sym
|
||||
libostree_1_la_LIBADD = libotutil.la libbupsplit.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS)
|
||||
|
||||
EXTRA_DIST += src/libostree/libostree.sym
|
||||
|
||||
if USE_LIBARCHIVE
|
||||
libostree_1_la_CFLAGS += $(OT_DEP_LIBARCHIVE_CFLAGS)
|
||||
libostree_1_la_LIBADD += $(OT_DEP_LIBARCHIVE_LIBS)
|
||||
|
|
@ -153,7 +162,6 @@ libostree_1_la_SOURCES += \
|
|||
src/libostree/ostree-fetcher.c \
|
||||
src/libostree/ostree-metalink.h \
|
||||
src/libostree/ostree-metalink.c \
|
||||
src/libostree/ostree-repo-pull.c \
|
||||
$(NULL)
|
||||
libostree_1_la_CFLAGS += $(OT_INTERNAL_SOUP_CFLAGS)
|
||||
libostree_1_la_LIBADD += $(OT_INTERNAL_SOUP_LIBS)
|
||||
|
|
|
|||
|
|
@ -19,18 +19,25 @@
|
|||
|
||||
include $(top_srcdir)/buildutil/glib-tap.mk
|
||||
|
||||
EXTRA_DIST += \
|
||||
buildutil/tap-driver.sh \
|
||||
buildutil/tap-test \
|
||||
$(NULL)
|
||||
|
||||
# We should probably consider flipping the default for DEBUG. Also,
|
||||
# include the builddir in $PATH so we find our just-built ostree
|
||||
# binary.
|
||||
TESTS_ENVIRONMENT += OT_TESTS_DEBUG=1 \
|
||||
GI_TYPELIB_PATH=$$(cd $(top_builddir) && pwd) \
|
||||
LD_LIBRARY_PATH=$$(cd $(top_builddir)/.libs && pwd) \
|
||||
PATH=$$(cd $(top_builddir) && pwd):$${PATH} \
|
||||
PATH=$$(cd $(top_builddir)/tests && pwd):$${PATH} \
|
||||
$(NULL)
|
||||
|
||||
uninstalled_test_scripts = tests/test-abi.sh
|
||||
uninstalled_test_data = tests/ostree-symlink-stamp
|
||||
|
||||
test_scripts = \
|
||||
dist_uninstalled_test_scripts = tests/test-symbols.sh
|
||||
|
||||
dist_test_scripts = \
|
||||
tests/test-basic.sh \
|
||||
tests/test-pull-subpath.sh \
|
||||
tests/test-archivez.sh \
|
||||
|
|
@ -51,6 +58,7 @@ test_scripts = \
|
|||
tests/test-pull-summary-sigs.sh \
|
||||
tests/test-pull-resume.sh \
|
||||
tests/test-pull-untrusted.sh \
|
||||
tests/test-pull-override-url.sh \
|
||||
tests/test-local-pull.sh \
|
||||
tests/test-local-pull-depth.sh \
|
||||
tests/test-gpg-signed-commit.sh \
|
||||
|
|
@ -62,6 +70,7 @@ test_scripts = \
|
|||
tests/test-admin-deploy-etcmerge-cornercases.sh \
|
||||
tests/test-admin-deploy-uboot.sh \
|
||||
tests/test-admin-deploy-grub2.sh \
|
||||
tests/test-admin-deploy-bootid-gc.sh \
|
||||
tests/test-admin-instutil-set-kargs.sh \
|
||||
tests/test-admin-upgrade-not-backwards.sh \
|
||||
tests/test-admin-pull-deploy-commit.sh \
|
||||
|
|
@ -70,7 +79,6 @@ test_scripts = \
|
|||
tests/test-repo-checkout-subpath.sh \
|
||||
tests/test-reset-nonlinear.sh \
|
||||
tests/test-oldstyle-partial.sh \
|
||||
tests/test-setuid.sh \
|
||||
tests/test-delta.sh \
|
||||
tests/test-xattrs.sh \
|
||||
tests/test-auto-summary.sh \
|
||||
|
|
@ -80,15 +88,15 @@ test_scripts = \
|
|||
$(NULL)
|
||||
|
||||
if BUILDOPT_FUSE
|
||||
test_scripts += tests/test-rofiles-fuse.sh
|
||||
dist_test_scripts += tests/test-rofiles-fuse.sh
|
||||
endif
|
||||
|
||||
# This one uses corrupt-repo-ref.js
|
||||
if BUILDOPT_GJS
|
||||
test_scripts += tests/test-corruption.sh
|
||||
dist_test_scripts += tests/test-corruption.sh
|
||||
endif
|
||||
|
||||
installed_test_data = tests/archive-test.sh \
|
||||
dist_installed_test_data = tests/archive-test.sh \
|
||||
tests/pull-test.sh \
|
||||
tests/libtest.sh \
|
||||
tests/admin-test.sh \
|
||||
|
|
@ -99,29 +107,29 @@ installed_test_data = tests/archive-test.sh \
|
|||
tests/pre-endian-deltas-repo-little.tar.xz \
|
||||
$(NULL)
|
||||
|
||||
test_extra_scripts = tests/bootloader-entries-crosscheck.py \
|
||||
dist_test_extra_scripts = tests/bootloader-entries-crosscheck.py \
|
||||
tests/ostree-grub-generator
|
||||
|
||||
# We can't use nobase_ as we need to strip off the tests/, can't
|
||||
# use plain installed_ as we do need the gpghome/ prefix.
|
||||
if ENABLE_INSTALLED_TESTS
|
||||
gpginsttestdir = $(installed_testdir)/gpghome
|
||||
gpginsttest_DATA = tests/gpghome/secring.gpg \
|
||||
dist_gpginsttest_DATA = tests/gpghome/secring.gpg \
|
||||
tests/gpghome/pubring.gpg \
|
||||
tests/gpghome/trustdb.gpg \
|
||||
tests/gpghome/key1.asc \
|
||||
tests/gpghome/key2.asc \
|
||||
tests/gpghome/key3.asc
|
||||
gpginsttest_trusteddir = $(installed_testdir)/gpghome/trusted
|
||||
gpginsttest_trusted_DATA = tests/gpghome/trusted/pubring.gpg
|
||||
dist_gpginsttest_trusted_DATA = tests/gpghome/trusted/pubring.gpg
|
||||
|
||||
gpgvinsttestdir = $(installed_testdir)/gpg-verify-data
|
||||
gpgvinsttest_DATA = $(addprefix tests/gpg-verify-data/, \
|
||||
dist_gpgvinsttest_DATA = $(addprefix tests/gpg-verify-data/, \
|
||||
gpg.conf lgpl2 lgpl2.sig pubring.gpg secring.gpg trustdb.gpg)
|
||||
endif
|
||||
|
||||
if BUILDOPT_GJS
|
||||
installed_test_scripts = tests/test-core.js \
|
||||
dist_installed_test_scripts = tests/test-core.js \
|
||||
tests/test-sizes.js \
|
||||
tests/test-sysroot.js \
|
||||
$(NULL)
|
||||
|
|
@ -129,9 +137,12 @@ endif
|
|||
|
||||
test_ltlibraries = libreaddir-rand.la
|
||||
libreaddir_rand_la_SOURCES = tests/readdir-rand.c
|
||||
libreaddir_rand_la_CFLAGS = $(OT_INTERNAL_GIO_UNIX_CFLAGS)
|
||||
libreaddir_rand_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS)
|
||||
libreaddir_rand_la_LDFLAGS = -avoid-version
|
||||
libreaddir_rand_la_CFLAGS = $(AM_CFLAGS) $(OT_INTERNAL_GIO_UNIX_CFLAGS)
|
||||
libreaddir_rand_la_LIBADD = \
|
||||
-ldl \
|
||||
$(OT_INTERNAL_GIO_UNIX_LIBS) \
|
||||
$(NULL)
|
||||
libreaddir_rand_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
|
||||
if !ENABLE_INSTALLED_TESTS
|
||||
libreaddir_rand_la_LDFLAGS += -rpath $(abs_builddir)
|
||||
endif
|
||||
|
|
@ -139,7 +150,7 @@ endif
|
|||
test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \
|
||||
tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \
|
||||
tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \
|
||||
tests/test-basic-c tests/test-sysroot-c
|
||||
tests/test-basic-c tests/test-sysroot-c tests/test-pull-c
|
||||
|
||||
# An interactive tool
|
||||
noinst_PROGRAMS += tests/test-rollsum-cli
|
||||
|
|
@ -176,6 +187,9 @@ tests_test_basic_c_LDADD = $(TESTS_LDADD)
|
|||
tests_test_sysroot_c_CFLAGS = $(TESTS_CFLAGS)
|
||||
tests_test_sysroot_c_LDADD = $(TESTS_LDADD)
|
||||
|
||||
tests_test_pull_c_CFLAGS = $(TESTS_CFLAGS)
|
||||
tests_test_pull_c_LDADD = $(TESTS_LDADD)
|
||||
|
||||
tests_test_ot_unix_utils_CFLAGS = $(TESTS_CFLAGS)
|
||||
tests_test_ot_unix_utils_LDADD = $(TESTS_LDADD)
|
||||
|
||||
|
|
@ -216,6 +230,7 @@ tests_test_gpg_verify_result_LDADD = $(TESTS_LDADD) $(OT_INTERNAL_GPGME_LIBS)
|
|||
|
||||
EXTRA_DIST += \
|
||||
tests/libostreetest.h \
|
||||
tests/libtest.sh \
|
||||
tests/gpg-verify-data/README.md \
|
||||
tests/gpg-verify-data/lgpl2 \
|
||||
tests/gpg-verify-data/lgpl2.sig \
|
||||
|
|
@ -227,7 +242,12 @@ EXTRA_DIST += \
|
|||
tests/libreaddir-rand.so: Makefile
|
||||
$(AM_V_GEN) ln -fns ../.libs/libreaddir-rand.so tests
|
||||
ALL_LOCAL_RULES += tests/libreaddir-rand.so
|
||||
CLEANFILES += tests/libreaddir-rand.so
|
||||
CLEANFILES += tests/libreaddir-rand.so tests/ostree-symlink-stamp tests/ostree
|
||||
|
||||
tests/ostree-symlink-stamp: Makefile
|
||||
@real_bin=`cd $(top_builddir) && libtool --mode=execute echo ostree`; \
|
||||
ln -sf "$${real_bin}" tests/ostree; \
|
||||
touch $@
|
||||
|
||||
# Unfortunately the glib test data APIs don't actually handle
|
||||
# non-recursive Automake, so we change our code to canonically look
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ AM_CPPFLAGS += -DDATADIR='"$(datadir)"' -DLIBEXECDIR='"$(libexecdir)"' \
|
|||
-DLOCALEDIR=\"$(datadir)/locale\" -DSYSCONFDIR=\"$(sysconfdir)\" \
|
||||
-DSHORTENED_SYSCONFDIR=\"$(shortened_sysconfdir)\" \
|
||||
-DOSTREE_FEATURES='"$(OSTREE_FEATURES)"' \
|
||||
-DOSTREE_COMPILATION \
|
||||
-DG_LOG_DOMAIN=\"OSTree\" \
|
||||
-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_40 \
|
||||
-DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_40 -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_48
|
||||
AM_CFLAGS += $(WARN_CFLAGS)
|
||||
DISTCHECK_CONFIGURE_FLAGS += --enable-gtk-doc --disable-maintainer-mode
|
||||
AM_CFLAGS += -std=gnu99 $(WARN_CFLAGS)
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS += --enable-gtk-doc --disable-maintainer-mode
|
||||
|
||||
GITIGNOREFILES = aclocal.m4 build-aux/ buildutil/*.m4 config.h.in gtk-doc.make
|
||||
|
||||
|
|
@ -71,7 +72,9 @@ include Makefile-otutil.am
|
|||
include Makefile-libostree.am
|
||||
include Makefile-ostree.am
|
||||
include Makefile-switchroot.am
|
||||
if BUILDOPT_FUSE
|
||||
include src/rofiles-fuse/Makefile-inc.am
|
||||
endif
|
||||
include Makefile-tests.am
|
||||
include Makefile-boot.am
|
||||
include Makefile-man.am
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ provide a minimal host for Docker formatted Linux containers.
|
|||
Replicating a base immutable OS, then using Docker for applications
|
||||
meshes together two different tools with different tradeoffs.
|
||||
|
||||
[xdg-app](https://github.com/alexlarsson/xdg-app) uses OSTree
|
||||
[flatpak](https://github.com/alexlarsson/xdg-app) uses OSTree
|
||||
for desktop application containers.
|
||||
|
||||
[GNOME Continuous](https://wiki.gnome.org/Projects/GnomeContinuous) is
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
/ostree.args
|
||||
/ostree.hierarchy
|
||||
/ostree.interfaces
|
||||
/ostree-overrides.txt
|
||||
/ostree.pdf
|
||||
/ostree.prerequisites
|
||||
/ostree.signals
|
||||
|
|
@ -48,4 +49,5 @@
|
|||
/tmpl/*.bak
|
||||
/tmpl/ostree-unused.sgml
|
||||
/xml
|
||||
/version.xml
|
||||
_libs
|
||||
|
|
|
|||
|
|
@ -13,25 +13,23 @@
|
|||
|
||||
<chapter xml:id="reference">
|
||||
<title>API Reference</title>
|
||||
<xi:include href="xml/libostree-core.xml"/>
|
||||
<xi:include href="xml/libostree-repo.xml"/>
|
||||
<xi:include href="xml/libostree-mutable-tree.xml"/>
|
||||
<xi:include href="xml/libostree-sysroot.xml"/>
|
||||
<xi:include href="xml/libostree-async-progress.xml"/>
|
||||
<xi:include href="xml/libostree-sepolicy.xml"/>
|
||||
<xi:include href="xml/libostree-sysroot-upgrader.xml"/>
|
||||
<xi:include href="xml/libostree-gpg-verify-result.xml"/>
|
||||
<xi:include href="xml/libostree-bootconfig-parser.xml"/>
|
||||
<xi:include href="xml/libostree-chain-input-stream.xml"/>
|
||||
<xi:include href="xml/libostree-checksum-input-stream.xml"/>
|
||||
<xi:include href="xml/libostree-deployment.xml"/>
|
||||
<xi:include href="xml/libostree-diff.xml"/>
|
||||
<xi:include href="xml/libostree-repo-file.xml"/>
|
||||
|
||||
<xi:include href="xml/ostree-core.xml"/>
|
||||
<xi:include href="xml/ostree-repo.xml"/>
|
||||
<xi:include href="xml/ostree-mutable-tree.xml"/>
|
||||
<xi:include href="xml/ostree-sysroot.xml"/>
|
||||
<xi:include href="xml/ostree-async-progress.xml"/>
|
||||
<xi:include href="xml/ostree-sepolicy.xml"/>
|
||||
<xi:include href="xml/ostree-sysroot-upgrader.xml"/>
|
||||
<xi:include href="xml/ostree-gpg-verify-result.xml"/>
|
||||
<xi:include href="xml/ostree-bootconfig-parser.xml"/>
|
||||
<xi:include href="xml/ostree-chain-input-stream.xml"/>
|
||||
<xi:include href="xml/ostree-checksum-input-stream.xml"/>
|
||||
<xi:include href="xml/ostree-deployment.xml"/>
|
||||
<xi:include href="xml/ostree-diff.xml"/>
|
||||
<xi:include href="xml/ostree-repo-file.xml"/>
|
||||
<index id="api-index-full">
|
||||
<title>API Index</title>
|
||||
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
|
||||
</index>
|
||||
|
||||
</chapter>
|
||||
</book>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<SECTION>
|
||||
<FILE>libostree-async-progress</FILE>
|
||||
<FILE>ostree-async-progress</FILE>
|
||||
OstreeAsyncProgress
|
||||
ostree_async_progress_new
|
||||
ostree_async_progress_new_and_connect
|
||||
|
|
@ -22,12 +22,14 @@ ostree_async_progress_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-bootconfig-parser</FILE>
|
||||
<FILE>ostree-bootconfig-parser</FILE>
|
||||
OstreeBootconfigParser
|
||||
ostree_bootconfig_parser_new
|
||||
ostree_bootconfig_parser_clone
|
||||
ostree_bootconfig_parser_parse
|
||||
ostree_bootconfig_parser_parse_at
|
||||
ostree_bootconfig_parser_write
|
||||
ostree_bootconfig_parser_write_at
|
||||
ostree_bootconfig_parser_set
|
||||
ostree_bootconfig_parser_get
|
||||
<SUBSECTION Standard>
|
||||
|
|
@ -38,7 +40,7 @@ ostree_bootconfig_parser_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-chain-input-stream</FILE>
|
||||
<FILE>ostree-chain-input-stream</FILE>
|
||||
OstreeChainInputStream
|
||||
ostree_chain_input_stream_new
|
||||
<SUBSECTION Standard>
|
||||
|
|
@ -54,7 +56,7 @@ ostree_chain_input_stream_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-checksum-input-stream</FILE>
|
||||
<FILE>ostree-checksum-input-stream</FILE>
|
||||
OstreeChecksumInputStream
|
||||
ostree_checksum_input_stream_new
|
||||
<SUBSECTION Standard>
|
||||
|
|
@ -70,7 +72,7 @@ ostree_checksum_input_stream_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-core</FILE>
|
||||
<FILE>ostree-core</FILE>
|
||||
OSTREE_MAX_METADATA_SIZE
|
||||
OSTREE_MAX_METADATA_WARN_SIZE
|
||||
OSTREE_MAX_RECURSION
|
||||
|
|
@ -97,10 +99,11 @@ ostree_checksum_inplace_from_bytes
|
|||
ostree_checksum_inplace_to_bytes
|
||||
ostree_checksum_bytes_peek
|
||||
ostree_checksum_bytes_peek_validate
|
||||
ostree_checksum_b64_inplace_from_bytes
|
||||
ostree_checksum_b64_inplace_to_bytes
|
||||
ostree_cmp_checksum_bytes
|
||||
ostree_validate_rev
|
||||
ostree_parse_refspec
|
||||
ostree_checksum_update_meta
|
||||
ostree_object_type_to_string
|
||||
ostree_object_type_from_string
|
||||
ostree_hash_object_name
|
||||
|
|
@ -110,6 +113,8 @@ ostree_object_to_string
|
|||
ostree_object_from_string
|
||||
ostree_content_stream_parse
|
||||
ostree_content_file_parse
|
||||
ostree_content_file_parse_at
|
||||
ostree_raw_file_to_archive_z2_stream
|
||||
ostree_raw_file_to_content_stream
|
||||
ostree_checksum_file_from_input
|
||||
ostree_checksum_file
|
||||
|
|
@ -128,7 +133,7 @@ ostree_commit_get_timestamp
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-deployment</FILE>
|
||||
<FILE>ostree-deployment</FILE>
|
||||
OstreeDeployment
|
||||
ostree_deployment_hash
|
||||
ostree_deployment_equal
|
||||
|
|
@ -141,11 +146,14 @@ ostree_deployment_get_bootcsum
|
|||
ostree_deployment_get_bootserial
|
||||
ostree_deployment_get_bootconfig
|
||||
ostree_deployment_get_origin
|
||||
ostree_deployment_get_origin_relpath
|
||||
ostree_deployment_get_unlocked
|
||||
ostree_deployment_set_index
|
||||
ostree_deployment_set_bootserial
|
||||
ostree_deployment_set_bootconfig
|
||||
ostree_deployment_set_origin
|
||||
ostree_deployment_clone
|
||||
ostree_deployment_unlocked_state_to_string
|
||||
<SUBSECTION Standard>
|
||||
OSTREE_DEPLOYMENT
|
||||
OSTREE_IS_DEPLOYMENT
|
||||
|
|
@ -154,7 +162,7 @@ ostree_deployment_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-diff</FILE>
|
||||
<FILE>ostree-diff</FILE>
|
||||
OstreeDiffFlags
|
||||
OstreeDiffItem
|
||||
ostree_diff_item_ref
|
||||
|
|
@ -166,7 +174,7 @@ ostree_diff_item_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-gpg-verify-result</FILE>
|
||||
<FILE>ostree-gpg-verify-result</FILE>
|
||||
OstreeGpgVerifyResult
|
||||
OstreeGpgSignatureAttr
|
||||
ostree_gpg_verify_result_count_all
|
||||
|
|
@ -177,6 +185,7 @@ ostree_gpg_verify_result_get_all
|
|||
OstreeGpgSignatureFormatFlags
|
||||
ostree_gpg_verify_result_describe
|
||||
ostree_gpg_verify_result_describe_variant
|
||||
ostree_gpg_verify_result_require_valid_signature
|
||||
<SUBSECTION Standard>
|
||||
OSTREE_GPG_VERIFY_RESULT
|
||||
OSTREE_IS_GPG_VERIFY_RESULT
|
||||
|
|
@ -184,8 +193,33 @@ OSTREE_TYPE_GPG_VERIFY_RESULT
|
|||
ostree_gpg_verify_result_get_type
|
||||
</SECTION>
|
||||
|
||||
<FILE>ostree-lzma-compressor</FILE>
|
||||
<SUBSECTION Standard>
|
||||
OSTREE_IS_LZMA_COMPRESSOR
|
||||
OSTREE_IS_LZMA_COMPRESSOR_CLASS
|
||||
OSTREE_LZMA_COMPRESSOR
|
||||
OSTREE_LZMA_COMPRESSOR_CLASS
|
||||
OSTREE_LZMA_COMPRESSOR_GET_CLASS
|
||||
OSTREE_TYPE_LZMA_COMPRESSOR
|
||||
OstreeLzmaCompressor
|
||||
OstreeLzmaCompressorClass
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-mutable-tree</FILE>
|
||||
<FILE>ostree-lzma-decompressor</FILE>
|
||||
<SUBSECTION Standard>
|
||||
OSTREE_IS_LZMA_DECOMPRESSOR
|
||||
OSTREE_IS_LZMA_DECOMPRESSOR_CLASS
|
||||
OSTREE_LZMA_DECOMPRESSOR
|
||||
OSTREE_LZMA_DECOMPRESSOR_CLASS
|
||||
OSTREE_LZMA_DECOMPRESSOR_GET_CLASS
|
||||
OSTREE_TYPE_LZMA_DECOMPRESSOR
|
||||
OstreeLzmaDecompressor
|
||||
OstreeLzmaDecompressorClass
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>ostree-mutable-tree</FILE>
|
||||
OstreeMutableTree
|
||||
ostree_mutable_tree_new
|
||||
ostree_mutable_tree_set_metadata_checksum
|
||||
|
|
@ -211,7 +245,7 @@ ostree_mutable_tree_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-repo</FILE>
|
||||
<FILE>ostree-repo</FILE>
|
||||
OstreeRepo
|
||||
OstreeRepoMode
|
||||
ostree_repo_mode_from_string
|
||||
|
|
@ -227,6 +261,7 @@ ostree_repo_create
|
|||
ostree_repo_get_path
|
||||
ostree_repo_get_mode
|
||||
ostree_repo_get_config
|
||||
ostree_repo_get_dfd
|
||||
ostree_repo_copy_config
|
||||
ostree_repo_remote_add
|
||||
ostree_repo_remote_delete
|
||||
|
|
@ -238,6 +273,10 @@ ostree_repo_remote_get_gpg_verify
|
|||
ostree_repo_remote_get_gpg_verify_summary
|
||||
ostree_repo_remote_gpg_import
|
||||
ostree_repo_remote_fetch_summary
|
||||
ostree_repo_remote_fetch_summary_with_options
|
||||
ostree_repo_get_remote_boolean_option
|
||||
ostree_repo_get_remote_list_option
|
||||
ostree_repo_get_remote_option
|
||||
ostree_repo_get_parent
|
||||
ostree_repo_write_config
|
||||
OstreeRepoTransactionStats
|
||||
|
|
@ -248,6 +287,8 @@ ostree_repo_abort_transaction
|
|||
ostree_repo_transaction_set_refspec
|
||||
ostree_repo_transaction_set_ref
|
||||
ostree_repo_set_ref_immediate
|
||||
ostree_repo_set_cache_dir
|
||||
ostree_repo_sign_delta
|
||||
ostree_repo_has_object
|
||||
ostree_repo_write_metadata
|
||||
ostree_repo_write_metadata_async
|
||||
|
|
@ -270,6 +311,8 @@ ostree_repo_load_object_stream
|
|||
ostree_repo_query_object_storage_size
|
||||
ostree_repo_import_object_from
|
||||
ostree_repo_import_object_from_with_trust
|
||||
ostree_repo_import_archive_to_mtree
|
||||
ostree_repo_export_tree_to_archive
|
||||
ostree_repo_delete_object
|
||||
OstreeRepoCommitFilterResult
|
||||
OstreeRepoCommitFilter
|
||||
|
|
@ -285,6 +328,7 @@ ostree_repo_commit_modifier_unref
|
|||
ostree_repo_devino_cache_new
|
||||
ostree_repo_devino_cache_ref
|
||||
ostree_repo_devino_cache_unref
|
||||
ostree_repo_devino_cache_get_type
|
||||
ostree_repo_write_directory_to_mtree
|
||||
ostree_repo_write_dfd_to_mtree
|
||||
ostree_repo_write_archive_to_mtree
|
||||
|
|
@ -310,8 +354,16 @@ ostree_repo_static_delta_execute_offline
|
|||
ostree_repo_traverse_new_reachable
|
||||
ostree_repo_traverse_commit
|
||||
ostree_repo_traverse_commit_union
|
||||
ostree_repo_commit_traverse_iter_cleanup
|
||||
ostree_repo_commit_traverse_iter_clear
|
||||
ostree_repo_commit_traverse_iter_get_dir
|
||||
ostree_repo_commit_traverse_iter_get_file
|
||||
ostree_repo_commit_traverse_iter_init_commit
|
||||
ostree_repo_commit_traverse_iter_init_dirtree
|
||||
ostree_repo_commit_traverse_iter_next
|
||||
OstreeRepoPruneFlags
|
||||
ostree_repo_prune
|
||||
ostree_repo_prune_static_deltas
|
||||
OstreeRepoPullFlags
|
||||
ostree_repo_pull
|
||||
ostree_repo_pull_one_dir
|
||||
|
|
@ -319,6 +371,8 @@ ostree_repo_pull_with_options
|
|||
ostree_repo_pull_default_console_progress_changed
|
||||
ostree_repo_sign_commit
|
||||
ostree_repo_append_gpg_signature
|
||||
ostree_repo_add_gpg_signature_summary
|
||||
ostree_repo_gpg_verify_data
|
||||
ostree_repo_verify_commit
|
||||
ostree_repo_verify_commit_ext
|
||||
ostree_repo_verify_summary
|
||||
|
|
@ -333,13 +387,12 @@ ostree_repo_transaction_stats_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-repo-file</FILE>
|
||||
<FILE>ostree-repo-file</FILE>
|
||||
OstreeRepoFile
|
||||
ostree_repo_file_ensure_resolved
|
||||
ostree_repo_file_get_xattrs
|
||||
ostree_repo_file_get_repo
|
||||
ostree_repo_file_get_root
|
||||
ostree_repo_file_make_empty_tree
|
||||
ostree_repo_file_tree_set_metadata
|
||||
ostree_repo_file_tree_get_contents_checksum
|
||||
ostree_repo_file_tree_get_metadata_checksum
|
||||
|
|
@ -360,14 +413,17 @@ ostree_repo_file_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-sepolicy</FILE>
|
||||
<FILE>ostree-sepolicy</FILE>
|
||||
OstreeSePolicy
|
||||
ostree_sepolicy_new
|
||||
ostree_sepolicy_get_path
|
||||
ostree_sepolicy_get_name
|
||||
ostree_sepolicy_get_label
|
||||
ostree_sepolicy_get_csum
|
||||
OstreeSePolicyRestoreconFlags
|
||||
ostree_sepolicy_restorecon
|
||||
ostree_sepolicy_setfscreatecon
|
||||
ostree_sepolicy_fscreatecon_cleanup
|
||||
<SUBSECTION Standard>
|
||||
OSTREE_SEPOLICY
|
||||
OSTREE_IS_SEPOLICY
|
||||
|
|
@ -376,7 +432,7 @@ ostree_sepolicy_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-sysroot</FILE>
|
||||
<FILE>ostree-sysroot</FILE>
|
||||
OstreeSysroot
|
||||
ostree_sysroot_new
|
||||
ostree_sysroot_new_default
|
||||
|
|
@ -388,6 +444,7 @@ ostree_sysroot_try_lock
|
|||
ostree_sysroot_lock_async
|
||||
ostree_sysroot_lock_finish
|
||||
ostree_sysroot_unlock
|
||||
ostree_sysroot_unload
|
||||
ostree_sysroot_get_fd
|
||||
ostree_sysroot_ensure_initialized
|
||||
ostree_sysroot_get_bootversion
|
||||
|
|
@ -395,13 +452,17 @@ ostree_sysroot_get_subbootversion
|
|||
ostree_sysroot_get_deployments
|
||||
ostree_sysroot_get_booted_deployment
|
||||
ostree_sysroot_get_deployment_directory
|
||||
ostree_sysroot_get_deployment_dirpath
|
||||
ostree_sysroot_get_deployment_origin_path
|
||||
ostree_sysroot_cleanup
|
||||
ostree_sysroot_prepare_cleanup
|
||||
ostree_sysroot_get_repo
|
||||
ostree_sysroot_init_osname
|
||||
ostree_sysroot_deployment_set_kargs
|
||||
ostree_sysroot_deployment_set_mutable
|
||||
ostree_sysroot_deployment_unlock
|
||||
ostree_sysroot_write_deployments
|
||||
ostree_sysroot_write_origin_file
|
||||
ostree_sysroot_deploy_tree
|
||||
ostree_sysroot_get_merge_deployment
|
||||
ostree_sysroot_origin_new_from_refspec
|
||||
|
|
@ -415,7 +476,7 @@ ostree_sysroot_get_type
|
|||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>libostree-sysroot-upgrader</FILE>
|
||||
<FILE>ostree-sysroot-upgrader</FILE>
|
||||
OstreeSysrootUpgrader
|
||||
ostree_sysroot_upgrader_new
|
||||
ostree_sysroot_upgrader_new_for_os
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ if ! test -f libglnx/README.md || ! test -f bsdiff/README.md; then
|
|||
git submodule update --init
|
||||
fi
|
||||
# Workaround automake bug with subdir-objects and computed paths
|
||||
sed -e 's,$(libglnx_srcpath),'${srcdir}/libglnx,g < libglnx/Makefile-libglnx.am >libglnx/Makefile-libglnx.am.inc
|
||||
sed -e 's,$(libbsdiff_srcpath),'${srcdir}/bsdiff,g < bsdiff/Makefile-bsdiff.am >bsdiff/Makefile-bsdiff.am.inc
|
||||
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
|
||||
|
||||
autoreconf --force --install --verbose
|
||||
|
||||
|
|
|
|||
24
configure.ac
24
configure.ac
|
|
@ -1,5 +1,5 @@
|
|||
AC_PREREQ([2.63])
|
||||
AC_INIT([ostree], [2016.5], [walters@verbum.org])
|
||||
AC_INIT([ostree], [2016.6], [walters@verbum.org])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_CONFIG_MACRO_DIR([buildutil])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
|
|
@ -38,13 +38,15 @@ GLIB_TESTS
|
|||
|
||||
AC_CHECK_HEADER([sys/xattr.h],,[AC_MSG_ERROR([You must have sys/xattr.h from glibc])])
|
||||
|
||||
AC_CHECK_PROGS(YACC, 'bison -y', :)
|
||||
AS_IF([test "$YACC" = :], [AC_MSG_ERROR([bison not found but required])])
|
||||
AS_IF([test "$YACC" != "bison -y"], [AC_MSG_ERROR([bison not found but required])])
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
AM_PATH_GLIB_2_0
|
||||
|
||||
dnl When bumping the gio-unix-2.0 dependency (or glib-2.0 in general),
|
||||
dnl remember to bump GLIB_VERSION_MIN_REQUIRED and
|
||||
dnl GLIB_VERSION_MAX_ALLOWED in Makefile.am
|
||||
GIO_DEPENDENCY="gio-unix-2.0 >= 2.40.0 libgsystem >= 2015.1"
|
||||
PKG_CHECK_MODULES(OT_DEP_GIO_UNIX, $GIO_DEPENDENCY)
|
||||
|
||||
|
|
@ -57,6 +59,9 @@ PKG_CHECK_MODULES(OT_DEP_ZLIB, zlib)
|
|||
dnl We're not actually linking to this, just using the header
|
||||
PKG_CHECK_MODULES(OT_DEP_E2P, e2p)
|
||||
|
||||
dnl When bumping the libsoup-2.4 dependency, remember to bump
|
||||
dnl SOUP_VERSION_MIN_REQUIRED and SOUP_VERSION_MAX_ALLOWED in
|
||||
dnl Makefile.am
|
||||
SOUP_DEPENDENCY="libsoup-2.4 >= 2.39.1"
|
||||
AC_ARG_WITH(soup,
|
||||
AS_HELP_STRING([--with-soup], [Use libsoup @<:@default=yes@:>@]),
|
||||
|
|
@ -222,7 +227,7 @@ AC_ARG_ENABLE(rofiles-fuse,
|
|||
[AS_HELP_STRING([--enable-rofiles-fuse],
|
||||
[generate rofiles-fuse helper [default=yes]])],,
|
||||
enable_rofiles_fuse=yes)
|
||||
AS_IF([ test $enable_rofiles_fuse != xno ], [
|
||||
AS_IF([ test x$enable_rofiles_fuse != xno ], [
|
||||
PKG_CHECK_MODULES(BUILDOPT_FUSE, $FUSE_DEPENDENCY)
|
||||
], [enable_rofiles_fuse=no])
|
||||
AM_CONDITIONAL(BUILDOPT_FUSE, test x$enable_rofiles_fuse = xyes)
|
||||
|
|
@ -231,7 +236,14 @@ AC_ARG_WITH(dracut,
|
|||
AS_HELP_STRING([--with-dracut],
|
||||
[Install dracut module (default: no)]),,
|
||||
[with_dracut=no])
|
||||
AM_CONDITIONAL(BUILDOPT_DRACUT, test x$with_dracut = xyes)
|
||||
case x$with_dracut in
|
||||
xno) ;;
|
||||
xyes) ;;
|
||||
xyesbutnoconf) ;;
|
||||
*) AC_MSG_ERROR([Unknown --with-dracut value $with_dracut])
|
||||
esac
|
||||
AM_CONDITIONAL(BUILDOPT_DRACUT, test x$with_dracut = xyes || test x$with_dracut = xyesbutnoconf)
|
||||
AM_CONDITIONAL(BUILDOPT_DRACUT_CONF, test x$with_dracut = xyes)
|
||||
|
||||
AC_ARG_WITH(mkinitcpio,
|
||||
AS_HELP_STRING([--with-mkinitcpio],
|
||||
|
|
@ -239,7 +251,7 @@ AC_ARG_WITH(mkinitcpio,
|
|||
[with_mkinitcpio=no])
|
||||
AM_CONDITIONAL(BUILDOPT_MKINITCPIO, test x$with_mkinitcpio = xyes)
|
||||
|
||||
AS_IF([test "x$with_dracut" = "xyes" || test "x$with_mkinitcpio" = "xyes"], [
|
||||
AS_IF([test "x$with_dracut" = "xyes" || test "x$with_dracut" = "xyesbutnoconf" || test "x$with_mkinitcpio" = "xyes"], [
|
||||
with_systemd=yes
|
||||
AC_ARG_WITH([systemdsystemunitdir],
|
||||
AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ operate "live" on the currently booted filesystem. The way they could
|
|||
work with OSTree is instead to take the list of installed packages in
|
||||
the currently booted tree, and compute a new filesystem from that. A
|
||||
later chapter describes in more details how this could work:
|
||||
[adapting-existing.md](Adapting Existing Systems).
|
||||
[Adapting Existing Systems](adapting-existing.md).
|
||||
|
||||
For the purposes of this section, let's assume that we have a
|
||||
newly generated filesystem tree stored in the repo (which shares
|
||||
|
|
@ -56,7 +56,7 @@ checking it back out of the repo into a deployment.
|
|||
|
||||
Given a commit to deploy, OSTree first allocates a directory for
|
||||
it. This is of the form `/boot/loader/entries/ostree-$osname-$checksum.$serial.conf`.
|
||||
The `$serial` is normally 0, but if a
|
||||
The `$serial` is normally `0`, but if a
|
||||
given commit is deployed more than once, it will be incremented.
|
||||
This is supported because the previous deployment may have
|
||||
configuration in `/etc` that we do not want to use or overwrite.
|
||||
|
|
|
|||
|
|
@ -125,8 +125,7 @@ the client executes.
|
|||
|
||||
This "updates as code" model allows for multiple content generation
|
||||
strategies. The design of this was inspired by that of Chromium:
|
||||
[http://dev.chromium.org/chromium-os/chromiumos-design-docs/filesystem-autoupdate](ChromiumOS
|
||||
autoupdate).
|
||||
[ChromiumOS Autoupdate](http://dev.chromium.org/chromium-os/chromiumos-design-docs/filesystem-autoupdate).
|
||||
|
||||
### The delta superblock
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,10 @@ available.
|
|||
All of the above also applies if one replaces "BTRFS" with "LVM
|
||||
snapshots" except for the reflinks.
|
||||
|
||||
OSTree supports using "bare-user" repositories, which do not require
|
||||
root to use. Using a filesystem-level layer without root is more
|
||||
difficult and would likely require a setuid helper or privileged service.
|
||||
|
||||
Finally, see the next portion around ChromiumOS for why a hybrid but
|
||||
integrated package/image system improves on this.
|
||||
|
||||
|
|
@ -130,6 +134,11 @@ believes that at the moment, the "CL updater" is not truly atomic in
|
|||
the sense that because it applies updates live, there is a window
|
||||
where the OS root may be inconsistent.
|
||||
|
||||
## Mender.io
|
||||
|
||||
[Mender.io](https://mender.io/) is another implementation of the dual
|
||||
partition approach.
|
||||
|
||||
## OLPC update
|
||||
|
||||
OSTree is basically a generalization of olpc-update, except using
|
||||
|
|
@ -147,37 +156,54 @@ See
|
|||
[this comment](http://blog.verbum.org/2013/08/26/ostree-v2013-6-released/#comment-1169)
|
||||
for a comparison.
|
||||
|
||||
## NixOS
|
||||
## NixOS / Nix
|
||||
|
||||
See [NixOS](http://nixos.org/). It was a very influential project for
|
||||
OSTree. NixOS and OSTree both support the idea of independent "roots"
|
||||
that are bootable.
|
||||
See [NixOS](http://nixos.org/). It was a very influential project for OSTree.
|
||||
NixOS and OSTree both support the idea of independent "roots" that are bootable.
|
||||
|
||||
In NixOS, the entire system is based on checksums of package inputs
|
||||
(build dependencies) - see [Nix store](http://nixos.org/nix/manual/#chap-package-management/). A both
|
||||
positive and negative of the Nix model is that a change in the build
|
||||
dependencies (e.g. being built with a newer gcc), requires a cascading
|
||||
rebuild of everything.
|
||||
In NixOS, files in a package are accessed by a path depending on the checksums
|
||||
of package inputs (build dependencies) - see
|
||||
[Nix store](http://nixos.org/nix/manual/#chap-package-management/).
|
||||
However, OSTree uses a commit/deploy model - it isn't tied to any particular
|
||||
directory layout, and you can put whatever data you want inside an OSTree, for
|
||||
example the standard FHS layout. A both positive and negative of the Nix model
|
||||
is that a change in the build dependencies (e.g. being built with a newer gcc),
|
||||
requires a cascading rebuild of everything. It's good because it makes it easy
|
||||
to do massive system-wide changes such as gcc upgrades, and allows installing
|
||||
multiple versions of packages at once. However, a security update to e.g. glibc
|
||||
forces a rebuild of everything from scratch, and so Nix is not practical at
|
||||
scale. OSTree supports using a build system that just rebuilds individual
|
||||
components (packages) as they change, without forcing a rebuild of their
|
||||
dependencies.
|
||||
|
||||
In OSTree, the checksums are of object *content* (including extended
|
||||
attributes). This means that any data that's identical is
|
||||
transparently, automatically shared on disk. It's possible to ask the
|
||||
Nix store to deduplicate, (via hard links and immutable bit), but this
|
||||
is significantly less efficient than the OSTree approach. The Nix use
|
||||
of the ext immutable bit is racy, since it has to be briefly removed
|
||||
to make a hard link.
|
||||
Nix automatically detects runtime package dependencies by scanning content for
|
||||
hashes. OSTree only supports only system-level images, and doesn't do dependency
|
||||
management. Nix can store arbitrary files, using nix-store --add, but, more
|
||||
commonly, paths are added as the result of running a derivation file generated
|
||||
using the Nix language. OSTree is build-system agnostic; filesystem trees are
|
||||
committed using a simple C API, and this is the only way to commit files.
|
||||
|
||||
At the lowest level, OSTree is just "git for binaries" - it isn't tied
|
||||
strongly to any particular build system. You can put whatever data you
|
||||
want inside an OSTree repository, built however you like. So for
|
||||
example, while one could make a build system that did the "purely
|
||||
functional" approach of Nix, it also works to have a build system that
|
||||
just rebuilds individual components (packages) as they change, without
|
||||
forcing a rebuild of their dependencies.
|
||||
OSTree automatically shares the storage of identical data using hard links into
|
||||
a content-addressed store. Nix can deduplicate using hard links as well, using
|
||||
the auto-optimise-store option, but this is not on by default, and Nix does not
|
||||
guarantee that all of its files are in the content-addressed store. OSTree
|
||||
provides a git-like command line interface for browsing the content-addressed
|
||||
store, while Nix does not have this functionality.
|
||||
|
||||
The author of OSTree believes that while Nix has some good ideas,
|
||||
forcing a rebuild of everything for a security update to e.g. glibc is
|
||||
not practical at scale.
|
||||
Nix used to use the immutable bit to prevent modifications to /nix/store, but
|
||||
now it uses a read-only bind mount. The bind mount can be privately remounted,
|
||||
allowing per-process privileged write access. OSTree uses the immutable
|
||||
bit on the root of the deployment, and mounts /usr as read-only.
|
||||
|
||||
NixOS supports switching OS images on-the-fly, by maintaining both booted-system
|
||||
and current-system roots. It is not clear how well this approach works. OSTree
|
||||
currently requries a reboot to switch images.
|
||||
|
||||
Finally, NixOS supports installing user-specific packages from trusted
|
||||
repositories without requiring root, using a trusted daemon.
|
||||
[Flatpak](https://lwn.net/Articles/687909/), based on OSTree, similarly has a
|
||||
policykit-based system helper that allows you to authenticate via polkit to
|
||||
install into the system repository.
|
||||
|
||||
## Solaris IPS
|
||||
|
||||
|
|
@ -205,3 +231,40 @@ See
|
|||
[bmap](https://source.tizen.org/documentation/reference/bmaptool/introduction).
|
||||
A tool for optimized copying of disk images. Intended for offline use,
|
||||
so not directly comparable.
|
||||
|
||||
## Git
|
||||
|
||||
Although OSTree has been called "Git for Binaries", and the two share the idea
|
||||
of a hashed content store, the implementation details are quite different.
|
||||
OSTree supports extended attributes and uses SHA256 instead of Git's SHA1. It
|
||||
"checks out" files via hardlinks, rather than copying, and thus requires the
|
||||
checkout to be immutable. At the moment, OSTree commits may have at most one
|
||||
parent, as opposed to Git which allows an arbitrary number. Git uses a
|
||||
smart-delta protocol for updates, while OSTree uses 1 HTTP request per changed
|
||||
file, or can generate static deltas.
|
||||
|
||||
## Conda
|
||||
|
||||
[Conda](http://conda.pydata.org/docs/) is an "OS-agnostic, system-level binary
|
||||
package manager and ecosystem"; although most well-known for its accompanying
|
||||
Python distribution anaconda, its scope has been expanding quickly. The package
|
||||
format is very similar to well-known ones such as RPM. However, unlike typical
|
||||
RPMs, the packages are built to be relocatable. Also, the package manager runs
|
||||
natively on Windows. Conda's main advantage is its ability to install
|
||||
collections of packages into "environments" by unpacking them all to the same
|
||||
directory. Conda reduces duplication across environments using hardlinks,
|
||||
similar to OSTree's sharing between deployments (although Conda uses package /
|
||||
file path instead of file hash). Overall, it is quite similar to rpm-ostree in
|
||||
functionality and scope.
|
||||
|
||||
## rpm-ostree
|
||||
|
||||
This builds on top of ostree to support building RPMs into OSTree images, and
|
||||
even composing RPMs on-the-fly using an overlay filesystem. It is being
|
||||
developed by Fedora, Red Hat, and CentOS as part of Project Atomic.
|
||||
|
||||
## GNOME Continuous
|
||||
|
||||
This is a service that incrementally rebuilds and tests GNOME on every commit.
|
||||
The need to make and distribute snapshots for this system was the original
|
||||
inspiration for ostree.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,22 @@ payload sections. The header contains uid, gid, mode, and symbolic
|
|||
link target (for symlinks), as well as extended attributes. After the
|
||||
header, for regular files, the content follows.
|
||||
|
||||
The OSTree data format intentionally does not contain timestamps. The reasoning
|
||||
is that data files may be downloaded at different times, and by different build
|
||||
systems, and so will have different timestamps but identical physical content.
|
||||
These files may be large, so most users would like them to be shared, both in
|
||||
the repository and between the repository and deployments.
|
||||
|
||||
This could cause problems with programs that check if files are out-of-date by
|
||||
comparing timestamps. For Git, the logical choice is to not mess with
|
||||
timestamps, because unnecessary rebuilding is better than a broken tree.
|
||||
However, OSTree has to hardlink files to check them out, and commits are assumed
|
||||
to be internally consistent with no build steps needed. For this reason, OSTree
|
||||
acts as though all timestamps are set to time_t 1, so that comparisons will be
|
||||
considered up-to-date. 1 is a better choice than 0 because some programs use 0
|
||||
as a special value; for example, GNU Tar warns of an "implausibly old time
|
||||
stamp" with 0.
|
||||
|
||||
# Repository types and locations
|
||||
|
||||
Also unlike git, an OSTree repository can be in one of three separate
|
||||
|
|
@ -98,7 +114,7 @@ that.
|
|||
A later addition to OSTree is the concept of a "summary" file, created
|
||||
via the `ostree summary -u` command. This was introduced for a few
|
||||
reasons. A primary use case is to be a target a
|
||||
(Metalink)[https://en.wikipedia.org/wiki/Metalink], which requires a
|
||||
[Metalink](https://en.wikipedia.org/wiki/Metalink), which requires a
|
||||
single file with a known checksum as a target.
|
||||
|
||||
The summary file primarily contains two mappings:
|
||||
|
|
|
|||
|
|
@ -4,11 +4,12 @@ Once you have a build system going, if you actually want client
|
|||
systems to retrieve the content, you will quickly feel a need for
|
||||
"repository management".
|
||||
|
||||
OSTree itself does not currently come with tools to do this. One
|
||||
reason is that how content is delivered and managed has concerns very
|
||||
specific to the organization. For example, some operating system
|
||||
content vendors may want integration with a specific errata
|
||||
notification system.
|
||||
The command line tool `ostree` does cover some core functionality, but
|
||||
doesn't include very high level workflows. One reason is that how
|
||||
content is delivered and managed has concerns very specific to the
|
||||
organization. For example, some operating system content vendors may
|
||||
want integration with a specific errata notification system when
|
||||
generating commits.
|
||||
|
||||
In this section, we will describe some high level ideas and methods
|
||||
for managing content in OSTree repositories, mostly independent of any
|
||||
|
|
@ -21,6 +22,27 @@ repositories today is the [Pulp Project](http://www.pulpproject.org/),
|
|||
which has a
|
||||
[Pulp OSTree plugin](https://pulp-ostree.readthedocs.org/en/latest/).
|
||||
|
||||
## Mirroring repositories
|
||||
|
||||
It's very common to want to perform a full or partial mirror, in
|
||||
particular across organizational boundaries (e.g. an upstream OS
|
||||
provider, and a user that wants offline and faster access to the
|
||||
content). OSTree supports both full and partial mirroring of the base
|
||||
`archive-z2` content, although not yet of static deltas.
|
||||
|
||||
To create a mirror, first create an `archive-z2` repository (you don't
|
||||
need to run this as root), then add the upstream as a remote, then use
|
||||
`pull --mirror`.
|
||||
|
||||
```
|
||||
ostree --repo=repo init --mode=archive-z2
|
||||
ostree --repo=repo remote add exampleos https://exampleos.com/ostree/repo
|
||||
ostree --repo=repo pull --mirror exampleos:exampleos/x86_64/standard
|
||||
```
|
||||
|
||||
You can use the `--depth=-1` option to retrieve all history, or a
|
||||
positive integer like `3` to retrieve just the last 3 commits.
|
||||
|
||||
## Separate development vs release repositories
|
||||
|
||||
By default, OSTree accumulates server side history. This is actually
|
||||
|
|
|
|||
|
|
@ -177,22 +177,9 @@ printpad (const char *padbuf,
|
|||
fwrite (padbuf, 1, r, stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_console_progress_text_percent:
|
||||
* @text: Show this text before the progress bar
|
||||
* @percentage: An integer in the range of 0 to 100
|
||||
*
|
||||
* On a tty, print to the console @text followed by an ASCII art
|
||||
* progress bar whose percentage is @percentage. If stdout is not a
|
||||
* tty, a more basic line by line change will be printed.
|
||||
*
|
||||
* You must have called glnx_console_lock() before invoking this
|
||||
* function.
|
||||
*
|
||||
*/
|
||||
void
|
||||
glnx_console_progress_text_percent (const char *text,
|
||||
guint percentage)
|
||||
static void
|
||||
text_percent_internal (const char *text,
|
||||
int percentage)
|
||||
{
|
||||
static const char equals[] = "====================";
|
||||
const guint n_equals = sizeof (equals) - 1;
|
||||
|
|
@ -201,10 +188,6 @@ glnx_console_progress_text_percent (const char *text,
|
|||
const guint ncolumns = glnx_console_columns ();
|
||||
const guint bar_min = 10;
|
||||
const guint input_textlen = text ? strlen (text) : 0;
|
||||
guint textlen;
|
||||
guint barlen;
|
||||
|
||||
g_return_if_fail (percentage >= 0 && percentage <= 100);
|
||||
|
||||
if (text && !*text)
|
||||
text = NULL;
|
||||
|
|
@ -236,36 +219,69 @@ glnx_console_progress_text_percent (const char *text,
|
|||
(void) fwrite (beginbuf, 1, sizeof (beginbuf), stdout);
|
||||
}
|
||||
|
||||
textlen = MIN (input_textlen, ncolumns - bar_min);
|
||||
barlen = ncolumns - textlen;
|
||||
|
||||
if (textlen > 0)
|
||||
if (percentage == -1)
|
||||
{
|
||||
fwrite (text, 1, textlen, stdout);
|
||||
fputc (' ', stdout);
|
||||
const guint spacelen = ncolumns - input_textlen;
|
||||
fwrite (text, 1, input_textlen, stdout);
|
||||
printpad (spaces, n_spaces, spacelen);
|
||||
}
|
||||
|
||||
{
|
||||
const guint nbraces = 2;
|
||||
const guint textpercent_len = 5;
|
||||
const guint bar_internal_len = barlen - nbraces - textpercent_len;
|
||||
const guint eqlen = bar_internal_len * (percentage / 100.0);
|
||||
const guint spacelen = bar_internal_len - eqlen;
|
||||
else
|
||||
{
|
||||
const guint textlen = MIN (input_textlen, ncolumns - bar_min);
|
||||
const guint barlen = ncolumns - (textlen + 1);;
|
||||
|
||||
fputc ('[', stdout);
|
||||
printpad (equals, n_equals, eqlen);
|
||||
printpad (spaces, n_spaces, spacelen);
|
||||
fputc (']', stdout);
|
||||
fprintf (stdout, " %3d%%", percentage);
|
||||
}
|
||||
if (textlen > 0)
|
||||
{
|
||||
fwrite (text, 1, textlen, stdout);
|
||||
fputc (' ', stdout);
|
||||
}
|
||||
|
||||
{ const guint spacelen = ncolumns - textlen - barlen;
|
||||
printpad (spaces, n_spaces, spacelen);
|
||||
}
|
||||
{
|
||||
const guint nbraces = 2;
|
||||
const guint textpercent_len = 5;
|
||||
const guint bar_internal_len = barlen - nbraces - textpercent_len;
|
||||
const guint eqlen = bar_internal_len * (percentage / 100.0);
|
||||
const guint spacelen = bar_internal_len - eqlen;
|
||||
|
||||
fputc ('[', stdout);
|
||||
printpad (equals, n_equals, eqlen);
|
||||
printpad (spaces, n_spaces, spacelen);
|
||||
fputc (']', stdout);
|
||||
fprintf (stdout, " %3d%%", percentage);
|
||||
}
|
||||
}
|
||||
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_console_progress_text_percent:
|
||||
* @text: Show this text before the progress bar
|
||||
* @percentage: An integer in the range of 0 to 100
|
||||
*
|
||||
* On a tty, print to the console @text followed by an ASCII art
|
||||
* progress bar whose percentage is @percentage. If stdout is not a
|
||||
* tty, a more basic line by line change will be printed.
|
||||
*
|
||||
* You must have called glnx_console_lock() before invoking this
|
||||
* function.
|
||||
*
|
||||
*/
|
||||
void
|
||||
glnx_console_progress_text_percent (const char *text,
|
||||
guint percentage)
|
||||
{
|
||||
g_return_if_fail (percentage >= 0 && percentage <= 100);
|
||||
|
||||
text_percent_internal (text, percentage);
|
||||
}
|
||||
|
||||
void
|
||||
glnx_console_text (const char *text)
|
||||
{
|
||||
text_percent_internal (text, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_console_unlock:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ typedef struct GLnxConsoleRef GLnxConsoleRef;
|
|||
|
||||
void glnx_console_lock (GLnxConsoleRef *ref);
|
||||
|
||||
void glnx_console_text (const char *text);
|
||||
|
||||
void glnx_console_progress_text_percent (const char *text,
|
||||
guint percentage);
|
||||
|
||||
|
|
|
|||
|
|
@ -277,20 +277,17 @@ glnx_fdrel_abspath (int dfd,
|
|||
}
|
||||
|
||||
/**
|
||||
* glnx_mkdtempat:
|
||||
* @dfd: Directory fd
|
||||
* @tmpl: (type filename): template directory name
|
||||
* @mode: permissions to create the temporary directory with
|
||||
* @error: Error
|
||||
* glnx_gen_temp_name:
|
||||
* @tmpl: (type filename): template directory name, the last 6 characters will be replaced
|
||||
*
|
||||
* Similar to g_mkdtemp_full, but using openat.
|
||||
* Replace the last 6 characters of @tmpl with random ASCII. You must
|
||||
* use this in combination with a mechanism to ensure race-free file
|
||||
* creation such as `O_EXCL`.
|
||||
*/
|
||||
gboolean
|
||||
glnx_mkdtempat (int dfd,
|
||||
gchar *tmpl,
|
||||
int mode,
|
||||
GError **error)
|
||||
void
|
||||
glnx_gen_temp_name (gchar *tmpl)
|
||||
{
|
||||
size_t len;
|
||||
char *XXXXXX;
|
||||
int count;
|
||||
static const char letters[] =
|
||||
|
|
@ -300,17 +297,11 @@ glnx_mkdtempat (int dfd,
|
|||
GTimeVal tv;
|
||||
static int counter = 0;
|
||||
|
||||
g_return_val_if_fail (tmpl != NULL, -1);
|
||||
g_return_if_fail (tmpl != NULL);
|
||||
len = strlen (tmpl);
|
||||
g_return_if_fail (len >= 6);
|
||||
|
||||
/* find the last occurrence of "XXXXXX" */
|
||||
XXXXXX = g_strrstr (tmpl, "XXXXXX");
|
||||
|
||||
if (!XXXXXX || strncmp (XXXXXX, "XXXXXX", 6))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
||||
"Invalid temporary directory template '%s'", tmpl);
|
||||
return FALSE;
|
||||
}
|
||||
XXXXXX = tmpl + (len - 6);
|
||||
|
||||
/* Get some more or less random data. */
|
||||
g_get_current_time (&tv);
|
||||
|
|
@ -332,6 +323,31 @@ glnx_mkdtempat (int dfd,
|
|||
XXXXXX[4] = letters[v % NLETTERS];
|
||||
v /= NLETTERS;
|
||||
XXXXXX[5] = letters[v % NLETTERS];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_mkdtempat:
|
||||
* @dfd: Directory fd
|
||||
* @tmpl: (type filename): template directory name, last 6 characters will be replaced
|
||||
* @mode: permissions to create the temporary directory with
|
||||
* @error: Error
|
||||
*
|
||||
* Similar to g_mkdtemp_full, but using openat.
|
||||
*/
|
||||
gboolean
|
||||
glnx_mkdtempat (int dfd,
|
||||
gchar *tmpl,
|
||||
int mode,
|
||||
GError **error)
|
||||
{
|
||||
int count;
|
||||
|
||||
g_return_val_if_fail (tmpl != NULL, -1);
|
||||
|
||||
for (count = 0; count < 100; count++)
|
||||
{
|
||||
glnx_gen_temp_name (tmpl);
|
||||
|
||||
if (mkdirat (dfd, tmpl, mode) == -1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ gboolean glnx_opendirat (int dfd,
|
|||
char *glnx_fdrel_abspath (int dfd,
|
||||
const char *path);
|
||||
|
||||
void glnx_gen_temp_name (gchar *tmpl);
|
||||
|
||||
gboolean glnx_mkdtempat (int dfd,
|
||||
gchar *tmpl,
|
||||
int mode,
|
||||
|
|
|
|||
|
|
@ -746,5 +746,35 @@ glnx_file_replace_contents_with_perms_at (int dfd,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (!ret)
|
||||
(void) unlink (tmppath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* glnx_stream_fstat:
|
||||
* @stream: A stream containing a Unix file descriptor
|
||||
* @stbuf: Memory location to write stat buffer
|
||||
* @error:
|
||||
*
|
||||
* Some streams created via libgsystem are #GUnixInputStream; these do
|
||||
* not support e.g. g_file_input_stream_query_info(). This function
|
||||
* allows dropping to the raw unix fstat() call for these types of
|
||||
* streams, while still conveniently wrapped with the normal GLib
|
||||
* handling of @error.
|
||||
*/
|
||||
gboolean
|
||||
glnx_stream_fstat (GFileDescriptorBased *stream,
|
||||
struct stat *stbuf,
|
||||
GError **error)
|
||||
{
|
||||
int fd = g_file_descriptor_based_get_fd (stream);
|
||||
|
||||
if (fstat (fd, stbuf) == -1)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "%s", "fstat");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <glnx-backport-autocleanups.h>
|
||||
#include <gio/gfiledescriptorbased.h>
|
||||
#include <limits.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -121,4 +122,9 @@ glnx_file_copy_at (int src_dfd,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
glnx_stream_fstat (GFileDescriptorBased *stream,
|
||||
struct stat *stbuf,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -274,6 +274,14 @@ glnx_libcontainer_run_chroot_private (const char *dest,
|
|||
if (chdir ("/") != 0)
|
||||
_perror_fatal ("chdir: ");
|
||||
|
||||
/* Environment variables like PATH in the end are distribution
|
||||
* specific. The most correct thing would be to run through PAM,
|
||||
* but that's a huge level of pain. We'd like to drive towards a
|
||||
* standard /usr/bin (i.e. unified sbin too), but for now this is
|
||||
* pretty compatible.
|
||||
*/
|
||||
setenv ("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 1);
|
||||
|
||||
if (binary[0] == '/')
|
||||
{
|
||||
if (execv (binary, argv) != 0)
|
||||
|
|
@ -281,9 +289,6 @@ glnx_libcontainer_run_chroot_private (const char *dest,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Set PATH to something sane. */
|
||||
setenv ("PATH", "/usr/sbin:/usr/bin", 1);
|
||||
|
||||
if (execvp (binary, argv) != 0)
|
||||
_perror_fatal ("execvp: ");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <errno.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
|
@ -195,13 +196,17 @@ GLNX_DEFINE_CLEANUP_FUNCTION0(GKeyFile*, glnx_local_keyfile_unref, g_key_file_un
|
|||
static inline void
|
||||
glnx_cleanup_close_fdp (int *fdp)
|
||||
{
|
||||
int fd;
|
||||
int fd, errsv;
|
||||
|
||||
g_assert (fdp);
|
||||
|
||||
fd = *fdp;
|
||||
if (fd != -1)
|
||||
(void) close (fd);
|
||||
{
|
||||
errsv = errno;
|
||||
(void) close (fd);
|
||||
errno = errsv;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ Boston, MA 02111-1307, USA.
|
|||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
This allows you to commit changes to a branch. The specification of the branch is required. If no commit message is specified with <option>--subject</option> then a text editor will be opened. The commit will be aborted if the commit subject is left empty. The command will print the checksum of a successful commit.
|
||||
This allows you to commit changes to a branch. The specification of the branch is required. The command will print the checksum of a successful commit.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ Boston, MA 02111-1307, USA.
|
|||
<term><option>--subject</option>, <option>-s</option>="SUBJECT"</term>
|
||||
|
||||
<listitem><para>
|
||||
One line subject.
|
||||
One line subject. (optional)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -76,7 +76,15 @@ Boston, MA 02111-1307, USA.
|
|||
<term><option>--body</option>, <option>-m</option>="BODY"</term>
|
||||
|
||||
<listitem><para>
|
||||
Full description.
|
||||
Full description. (optional)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--editor</option>, <option>-e</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Open a text editor for the commit description. It will use OSTREE_EDITOR, VISUAL, EDITOR, or vi, in descending order of preference. The commit will be aborted if the message is left empty.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -84,7 +92,7 @@ Boston, MA 02111-1307, USA.
|
|||
<term><option>--branch</option>, <option>-b</option>="BRANCH"</term>
|
||||
|
||||
<listitem><para>
|
||||
Branch.
|
||||
Branch. Required, unless --orphan is given.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -163,7 +171,15 @@ Boston, MA 02111-1307, USA.
|
|||
<term><option>--statoverride</option>="PATH"</term>
|
||||
|
||||
<listitem><para>
|
||||
File containing list of modifications to make permissions.
|
||||
File containing list of modifications to make permissions (file mode, followed by space, followed by file path).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--skip-list</option>="PATH"</term>
|
||||
|
||||
<listitem><para>
|
||||
File containing list of file paths to skip (one path per line).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -206,6 +222,22 @@ Boston, MA 02111-1307, USA.
|
|||
Override the timestamp of the commit to TIMESTAMP.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--orphan</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Create a commit without writing to a ref (branch)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--fsync</option>="POLICY"</term>
|
||||
|
||||
<listitem><para>
|
||||
POLICY is a boolean which specifies whether fsync should be used or not. Default to true.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ env NOCONFIGURE=1 ./autogen.sh
|
|||
%configure --disable-silent-rules \
|
||||
--enable-gtk-doc \
|
||||
--with-selinux \
|
||||
--with-dracut
|
||||
--with-dracut=yesbutnoconf
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
|
|
@ -94,7 +94,6 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%{_bindir}/ostree
|
||||
%{_sbindir}/ostree-prepare-root
|
||||
%{_sbindir}/ostree-remount
|
||||
%{_sysconfdir}/dracut.conf.d/ostree.conf
|
||||
%dir %{_prefix}/lib/dracut/modules.d/98ostree
|
||||
%{_prefix}/lib/systemd/system/ostree*.service
|
||||
%{_prefix}/lib/dracut/modules.d/98ostree/*
|
||||
|
|
|
|||
|
|
@ -323,11 +323,6 @@ global:
|
|||
ostree_deployment_unlocked_state_to_string;
|
||||
} LIBOSTREE_2016.3;
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
* Versions above here are released. Only add symbols below this line.
|
||||
* NOTE NOTE NOTE
|
||||
*/
|
||||
|
||||
LIBOSTREE_2016.5 {
|
||||
global:
|
||||
ostree_repo_import_object_from_with_trust;
|
||||
|
|
@ -337,3 +332,24 @@ global:
|
|||
ostree_repo_get_remote_boolean_option;
|
||||
ostree_repo_set_cache_dir;
|
||||
} LIBOSTREE_2016.4;
|
||||
|
||||
LIBOSTREE_2016.6 {
|
||||
global:
|
||||
ostree_gpg_verify_result_require_valid_signature;
|
||||
ostree_raw_file_to_archive_z2_stream;
|
||||
ostree_repo_gpg_verify_data;
|
||||
ostree_repo_remote_fetch_summary_with_options;
|
||||
} LIBOSTREE_2016.5;
|
||||
|
||||
/* NOTE NOTE NOTE
|
||||
* Versions above here are released. Only add symbols below this line.
|
||||
* NOTE NOTE NOTE
|
||||
*/
|
||||
|
||||
/* Uncomment this when adding a new symbol */
|
||||
/*
|
||||
LIBOSTREE_2016.7 {
|
||||
global:
|
||||
ostree_some_new_symbol;
|
||||
} LIBOSTREE_2016.6;
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "ostree-async-progress.h"
|
||||
|
||||
/**
|
||||
* SECTION:libostree-async-progress
|
||||
* SECTION:ostree-async-progress
|
||||
* @title: Progress notification system for asynchronous operations
|
||||
* @short_description: Values representing progress
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2016 Endless Mobile, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Author: Krzesimir Nowak <krzesimir@kinvolk.io>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ostree.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef OSTREE_WITH_AUTOCLEANUPS
|
||||
#define OSTREE_WITH_AUTOCLEANUPS 0
|
||||
#endif
|
||||
|
||||
/* ostree can use g_autoptr backports from libglnx when glib is too
|
||||
* old, but still avoid exposing them to users that also have an old
|
||||
* glib */
|
||||
#if defined(OSTREE_COMPILATION) || (OSTREE_WITH_AUTOCLEANUPS && GLIB_CHECK_VERSION(2, 44, 0))
|
||||
|
||||
/*
|
||||
* The following types have no specific clear/free/unref functions, so
|
||||
* they can be used as the stack-allocated variables or as the
|
||||
* g_autofree heap-allocated variables.
|
||||
*
|
||||
* OstreeRepoTransactionStats
|
||||
* OstreeRepoImportArchiveOptions
|
||||
* OstreeRepoExportArchiveOptions
|
||||
* OstreeRepoCheckoutOptions
|
||||
*/
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeDiffItem, ostree_diff_item_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoCommitModifier, ostree_repo_commit_modifier_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoDevInoCache, ostree_repo_devino_cache_unref)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeBootconfigParser, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeDeployment, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFile, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSePolicy, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSysroot, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeSysrootUpgrader, g_object_unref)
|
||||
|
||||
G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (OstreeRepoCommitTraverseIter, ostree_repo_commit_traverse_iter_clear)
|
||||
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
|
@ -138,7 +138,8 @@ _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
|
|||
bootversion);
|
||||
|
||||
/* This should follow the symbolic link to the current bootversion. */
|
||||
config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
|
||||
config_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (self->config_path), NULL,
|
||||
cancellable, error);
|
||||
if (!config_contents)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ _ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
|
|||
g_autoptr(GPtrArray) new_lines = NULL;
|
||||
|
||||
/* This should follow the symbolic link to the current bootversion. */
|
||||
config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error);
|
||||
config_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (self->config_path), NULL,
|
||||
cancellable, error);
|
||||
if (!config_contents)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
|
|||
|
||||
GFileInfo * _ostree_header_gfile_info_new (mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
/* XX + / + checksum-2 + . + extension, but let's just use 256 for a
|
||||
/* XX/checksum-2.extension, but let's just use 256 for a
|
||||
* bit of overkill.
|
||||
*/
|
||||
#define _OSTREE_LOOSE_PATH_MAX (256)
|
||||
|
|
@ -112,8 +112,7 @@ _ostree_get_relative_static_delta_part_path (const char *from,
|
|||
const char *to,
|
||||
guint i);
|
||||
|
||||
static inline char *
|
||||
_ostree_get_commitpartial_path (const char *checksum)
|
||||
static inline char * _ostree_get_commitpartial_path (const char *checksum)
|
||||
{
|
||||
return g_strconcat ("state/", checksum, ".commitpartial", NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gfiledescriptorbased.h>
|
||||
#include "libglnx.h"
|
||||
#include "ostree.h"
|
||||
#include "ostree-core-private.h"
|
||||
#include "ostree-chain-input-stream.h"
|
||||
#include "otutil.h"
|
||||
#include "libglnx.h"
|
||||
|
||||
#define ALIGN_VALUE(this, boundary) \
|
||||
(( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
|
||||
|
|
@ -47,7 +47,7 @@ zlib_file_header_parse (GVariant *metadata,
|
|||
GError **error);
|
||||
|
||||
/**
|
||||
* SECTION:libostree-core
|
||||
* SECTION:ostree-core
|
||||
* @title: Core repository-independent functions
|
||||
* @short_description: Create, validate, and convert core data types
|
||||
*
|
||||
|
|
@ -400,6 +400,98 @@ write_file_header_update_checksum (GOutputStream *out,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* header_and_input_to_stream:
|
||||
* @file_header: A file header
|
||||
* @input: File raw content stream
|
||||
* @out_input: (out): Serialized object stream
|
||||
* @out_header_size: (out): Length of the header
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Combines @file_header and @input into a single stream.
|
||||
*/
|
||||
static gboolean
|
||||
header_and_input_to_stream (GVariant *file_header,
|
||||
GInputStream *input,
|
||||
GInputStream **out_input,
|
||||
guint64 *out_header_size,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gpointer header_data;
|
||||
gsize header_size;
|
||||
g_autoptr(GInputStream) ret_input = NULL;
|
||||
g_autoptr(GPtrArray) streams = NULL;
|
||||
g_autoptr(GOutputStream) header_out_stream = NULL;
|
||||
g_autoptr(GInputStream) header_in_stream = NULL;
|
||||
|
||||
header_out_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
|
||||
if (!_ostree_write_variant_with_size (header_out_stream, file_header, 0, NULL, NULL,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
if (!g_output_stream_close (header_out_stream, cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
header_size = g_memory_output_stream_get_data_size ((GMemoryOutputStream*) header_out_stream);
|
||||
header_data = g_memory_output_stream_steal_data ((GMemoryOutputStream*) header_out_stream);
|
||||
header_in_stream = g_memory_input_stream_new_from_data (header_data, header_size, g_free);
|
||||
|
||||
streams = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
|
||||
|
||||
g_ptr_array_add (streams, g_object_ref (header_in_stream));
|
||||
if (input)
|
||||
g_ptr_array_add (streams, g_object_ref (input));
|
||||
|
||||
ret_input = (GInputStream*)ostree_chain_input_stream_new (streams);
|
||||
ot_transfer_out_value (out_input, &ret_input);
|
||||
if (out_header_size)
|
||||
*out_header_size = header_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_raw_file_to_archive_z2_stream:
|
||||
* @input: File raw content stream
|
||||
* @file_info: A file info
|
||||
* @xattrs: (allow-none): Optional extended attributes
|
||||
* @out_input: (out): Serialized object stream
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Convert from a "bare" file representation into an
|
||||
* OSTREE_OBJECT_TYPE_FILE stream suitable for ostree pull.
|
||||
*/
|
||||
gboolean
|
||||
ostree_raw_file_to_archive_z2_stream (GInputStream *input,
|
||||
GFileInfo *file_info,
|
||||
GVariant *xattrs,
|
||||
GInputStream **out_input,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariant) file_header = NULL;
|
||||
g_autoptr(GInputStream) zlib_input = NULL;
|
||||
|
||||
file_header = _ostree_zlib_file_header_new (file_info, xattrs);
|
||||
if (input != NULL)
|
||||
{
|
||||
g_autoptr(GConverter) zlib_compressor = NULL;
|
||||
|
||||
zlib_compressor = G_CONVERTER (g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW, 9));
|
||||
zlib_input = g_converter_input_stream_new (input, zlib_compressor);
|
||||
}
|
||||
return header_and_input_to_stream (file_header,
|
||||
zlib_input,
|
||||
out_input,
|
||||
NULL,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_raw_file_to_content_stream:
|
||||
* @input: File raw content stream
|
||||
|
|
@ -423,44 +515,20 @@ ostree_raw_file_to_content_stream (GInputStream *input,
|
|||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gpointer header_data;
|
||||
gsize header_size;
|
||||
g_autoptr(GInputStream) ret_input = NULL;
|
||||
g_autoptr(GVariant) file_header = NULL;
|
||||
g_autoptr(GPtrArray) streams = NULL;
|
||||
g_autoptr(GOutputStream) header_out_stream = NULL;
|
||||
g_autoptr(GInputStream) header_in_stream = NULL;
|
||||
guint64 header_size;
|
||||
|
||||
file_header = file_header_new (file_info, xattrs);
|
||||
|
||||
header_out_stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
|
||||
if (!_ostree_write_variant_with_size (header_out_stream, file_header, 0, NULL, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!g_output_stream_close (header_out_stream, cancellable, error))
|
||||
goto out;
|
||||
|
||||
header_size = g_memory_output_stream_get_data_size ((GMemoryOutputStream*) header_out_stream);
|
||||
header_data = g_memory_output_stream_steal_data ((GMemoryOutputStream*) header_out_stream);
|
||||
header_in_stream = g_memory_input_stream_new_from_data (header_data, header_size, g_free);
|
||||
|
||||
streams = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref);
|
||||
|
||||
g_ptr_array_add (streams, g_object_ref (header_in_stream));
|
||||
if (input)
|
||||
g_ptr_array_add (streams, g_object_ref (input));
|
||||
|
||||
ret_input = (GInputStream*)ostree_chain_input_stream_new (streams);
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_input, &ret_input);
|
||||
if (!header_and_input_to_stream (file_header,
|
||||
input,
|
||||
out_input,
|
||||
&header_size,
|
||||
cancellable,
|
||||
error))
|
||||
return FALSE;
|
||||
if (out_length)
|
||||
*out_length = header_size + g_file_info_get_size (file_info);
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -613,7 +681,7 @@ ostree_content_file_parse_at (gboolean compressed,
|
|||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!gs_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, cancellable, error))
|
||||
if (!glnx_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_content_stream_parse (compressed, file_input, stbuf.st_size, trusted,
|
||||
|
|
@ -921,14 +989,13 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autofree char *tmpname = NULL;
|
||||
char *tmpname = g_strdup ("tmplink.XXXXXX");
|
||||
guint i;
|
||||
const int max_attempts = 128;
|
||||
|
||||
for (i = 0; i < max_attempts; i++)
|
||||
{
|
||||
g_free (tmpname);
|
||||
tmpname = gs_fileutil_gen_tmp_name (NULL, NULL);
|
||||
glnx_gen_temp_name (tmpname);
|
||||
if (symlinkat (target, tmp_dirfd, tmpname) < 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ G_BEGIN_DECLS
|
|||
* @OSTREE_OBJECT_TYPE_DIR_TREE: List of children (trees or files), and metadata
|
||||
* @OSTREE_OBJECT_TYPE_DIR_META: Directory metadata
|
||||
* @OSTREE_OBJECT_TYPE_COMMIT: Toplevel object, refers to tree and dirmeta for root
|
||||
* @OSTREE_OBJECT_TYPE_COMMIT_TOMBSTONE: Toplevel object, refers to a deleted commit
|
||||
* @OSTREE_OBJECT_TYPE_TOMBSTONE_COMMIT: Toplevel object, refers to a deleted commit
|
||||
*
|
||||
* Enumeration for core object types; %OSTREE_OBJECT_TYPE_FILE is for
|
||||
* content, the other types are metadata.
|
||||
|
|
@ -90,10 +90,10 @@ typedef enum {
|
|||
/**
|
||||
* OSTREE_DIRMETA_GVARIANT_FORMAT:
|
||||
*
|
||||
* u - uid
|
||||
* u - gid
|
||||
* u - mode
|
||||
* a(ayay) - xattrs
|
||||
* - u - uid
|
||||
* - u - gid
|
||||
* - u - mode
|
||||
* - a(ayay) - xattrs
|
||||
*/
|
||||
#define OSTREE_DIRMETA_GVARIANT_STRING "(uuua(ayay))"
|
||||
#define OSTREE_DIRMETA_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_DIRMETA_GVARIANT_STRING)
|
||||
|
|
@ -106,10 +106,10 @@ typedef enum {
|
|||
* can't store in the real filesystem but we can still use a regular .file object
|
||||
* that we can hardlink to in the case of a user-mode checkout.
|
||||
*
|
||||
* u - uid
|
||||
* u - gid
|
||||
* u - mode
|
||||
* a(ayay) - xattrs
|
||||
* - u - uid
|
||||
* - u - gid
|
||||
* - u - mode
|
||||
* - a(ayay) - xattrs
|
||||
*/
|
||||
#define OSTREE_FILEMETA_GVARIANT_STRING "(uuua(ayay))"
|
||||
#define OSTREE_FILEMETA_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_FILEMETA_GVARIANT_STRING)
|
||||
|
|
@ -117,8 +117,8 @@ typedef enum {
|
|||
/**
|
||||
* OSTREE_TREE_GVARIANT_FORMAT:
|
||||
*
|
||||
* a(say) - array of (filename, checksum) for files
|
||||
* a(sayay) - array of (dirname, tree_checksum, meta_checksum) for directories
|
||||
* - a(say) - array of (filename, checksum) for files
|
||||
* - a(sayay) - array of (dirname, tree_checksum, meta_checksum) for directories
|
||||
*/
|
||||
#define OSTREE_TREE_GVARIANT_STRING "(a(say)a(sayay))"
|
||||
#define OSTREE_TREE_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_TREE_GVARIANT_STRING)
|
||||
|
|
@ -126,14 +126,14 @@ typedef enum {
|
|||
/**
|
||||
* OSTREE_COMMIT_GVARIANT_FORMAT:
|
||||
*
|
||||
* a{sv} - Metadata
|
||||
* ay - parent checksum (empty string for initial)
|
||||
* a(say) - Related objects
|
||||
* s - subject
|
||||
* s - body
|
||||
* t - Timestamp in seconds since the epoch (UTC)
|
||||
* ay - Root tree contents
|
||||
* ay - Root tree metadata
|
||||
* - a{sv} - Metadata
|
||||
* - ay - parent checksum (empty string for initial)
|
||||
* - a(say) - Related objects
|
||||
* - s - subject
|
||||
* - s - body
|
||||
* - t - Timestamp in seconds since the epoch (UTC)
|
||||
* - ay - Root tree contents
|
||||
* - ay - Root tree metadata
|
||||
*/
|
||||
#define OSTREE_COMMIT_GVARIANT_STRING "(a{sv}aya(say)sstayay)"
|
||||
#define OSTREE_COMMIT_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_COMMIT_GVARIANT_STRING)
|
||||
|
|
@ -141,8 +141,9 @@ typedef enum {
|
|||
/**
|
||||
* OSTREE_SUMMARY_GVARIANT_FORMAT:
|
||||
*
|
||||
* refs: a(s(taya{sv})) - Map of ref name -> (latest commit size, latest commit checksum, additional metadata), sorted by ref name
|
||||
* extensions: a{sv} - Additional metadata, none defined at the current time
|
||||
* - a(s(taya{sv})) - Map of ref name -> (latest commit size, latest commit checksum, additional metadata), sorted by ref name
|
||||
* - a{sv} - Additional metadata, at the current time the following are defined:
|
||||
* - key: "ostree.static-deltas", value: a{sv}, static delta name -> 32 bytes of checksum
|
||||
*/
|
||||
#define OSTREE_SUMMARY_GVARIANT_STRING "(a(s(taya{sv}))a{sv})"
|
||||
#define OSTREE_SUMMARY_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_SUMMARY_GVARIANT_STRING)
|
||||
|
|
@ -152,9 +153,9 @@ typedef enum {
|
|||
|
||||
/**
|
||||
* OstreeRepoMode:
|
||||
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; can only be written as root
|
||||
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; checkouts are hardlinks; can only be written as root
|
||||
* @OSTREE_REPO_MODE_ARCHIVE_Z2: Files are compressed, should be owned by non-root. Can be served via HTTP
|
||||
* @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user
|
||||
* @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. Hardlinks work only in user checkouts.
|
||||
*
|
||||
* See the documentation of #OstreeRepo for more information about the
|
||||
* possible modes.
|
||||
|
|
@ -165,8 +166,8 @@ typedef enum {
|
|||
OSTREE_REPO_MODE_BARE_USER
|
||||
} OstreeRepoMode;
|
||||
|
||||
const _OSTREE_PUBLIC
|
||||
GVariantType *ostree_metadata_variant_type (OstreeObjectType objtype);
|
||||
_OSTREE_PUBLIC
|
||||
const GVariantType *ostree_metadata_variant_type (OstreeObjectType objtype);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_validate_checksum_string (const char *sha256,
|
||||
|
|
@ -214,9 +215,6 @@ gboolean ostree_parse_refspec (const char *refspec,
|
|||
char **out_ref,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_checksum_update_meta (GChecksum *checksum, GFileInfo *file_info, GVariant *xattrs);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
const char * ostree_object_type_to_string (OstreeObjectType objtype);
|
||||
|
||||
|
|
@ -244,7 +242,8 @@ void ostree_object_from_string (const char *str,
|
|||
gchar **out_checksum,
|
||||
OstreeObjectType *out_objtype);
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_content_stream_parse (gboolean compressed,
|
||||
GInputStream *input,
|
||||
guint64 input_length,
|
||||
|
|
@ -276,6 +275,15 @@ gboolean ostree_content_file_parse_at (gboolean compressed,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_raw_file_to_archive_z2_stream (GInputStream *input,
|
||||
GFileInfo *file_info,
|
||||
GVariant *xattrs,
|
||||
GInputStream **out_input,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_raw_file_to_content_stream (GInputStream *input,
|
||||
GFileInfo *file_info,
|
||||
|
|
|
|||
|
|
@ -24,19 +24,33 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
/**
|
||||
* OstreeDeployment:
|
||||
* @parent_instance:
|
||||
* @index: Global offset
|
||||
* @osname:
|
||||
* @csum: OSTree checksum of tree
|
||||
* @deployserial: How many times this particular csum appears in deployment list
|
||||
* @bootcsum: Checksum of kernel+initramfs
|
||||
* @bootserial: An integer assigned to this tree per its ${bootcsum}
|
||||
* @bootconfig: Bootloader configuration
|
||||
* @origin: How to construct an upgraded version of this tree
|
||||
* @unlocked: The unlocked state
|
||||
*/
|
||||
struct _OstreeDeployment
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
int index; /* Global offset */
|
||||
char *osname; /* osname */
|
||||
char *csum; /* OSTree checksum of tree */
|
||||
int deployserial; /* How many times this particular csum appears in deployment list */
|
||||
char *bootcsum; /* Checksum of kernel+initramfs */
|
||||
int bootserial; /* An integer assigned to this tree per its ${bootcsum} */
|
||||
OstreeBootconfigParser *bootconfig; /* Bootloader configuration */
|
||||
GKeyFile *origin; /* How to construct an upgraded version of this tree */
|
||||
OstreeDeploymentUnlockedState unlocked; /* The unlocked state */
|
||||
int index;
|
||||
char *osname;
|
||||
char *csum;
|
||||
int deployserial;
|
||||
char *bootcsum;
|
||||
int bootserial;
|
||||
OstreeBootconfigParser *bootconfig;
|
||||
GKeyFile *origin;
|
||||
OstreeDeploymentUnlockedState unlocked;
|
||||
};
|
||||
|
||||
void _ostree_deployment_set_bootcsum (OstreeDeployment *self, const char *bootcsum);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree.h"
|
||||
#include "otutil.h"
|
||||
|
||||
|
|
@ -209,6 +210,8 @@ diff_add_dir_recurse (GFile *d,
|
|||
* @modified: (element-type OstreeDiffItem): Modified files
|
||||
* @removed: (element-type Gio.File): Removed files
|
||||
* @added: (element-type Gio.File): Added files
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Compute the difference between directory @a and @b as 3 separate
|
||||
* sets of #OstreeDiffItem in @modified, @removed, and @added.
|
||||
|
|
|
|||
|
|
@ -27,11 +27,17 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* OstreeDiffFlags:
|
||||
*/
|
||||
typedef enum {
|
||||
OSTREE_DIFF_FLAGS_NONE = 0,
|
||||
OSTREE_DIFF_FLAGS_IGNORE_XATTRS = (1 << 0)
|
||||
} OstreeDiffFlags;
|
||||
|
||||
/**
|
||||
* OstreeDiffItem:
|
||||
*/
|
||||
typedef struct _OstreeDiffItem OstreeDiffItem;
|
||||
struct _OstreeDiffItem
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
/* This file declares a stub function that is only exported
|
||||
* to pacify ABI checkers - no one could really have used it.
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "ostree-dummy-enumtypes.h"
|
||||
|
||||
/* Exported for backwards compat - see
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=764131
|
||||
*/
|
||||
GType
|
||||
ostree_fetcher_config_flags_get_type (void)
|
||||
{
|
||||
return G_TYPE_INVALID;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* This file declares a stub function that is only exported
|
||||
* to pacify ABI checkers - no one could really have used it.
|
||||
*
|
||||
* Copyright (C) 2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#ifndef __GI_SCANNER__
|
||||
_OSTREE_PUBLIC GType
|
||||
ostree_fetcher_config_flags_get_type (void);
|
||||
#endif
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
/*** BEGIN value-header ***/
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
_@enum_name@_get_type (void)
|
||||
{
|
||||
static volatile gsize the_type__volatile = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,8 @@ G_BEGIN_DECLS
|
|||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN enumeration-production ***/
|
||||
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
|
||||
_OSTREE_PUBLIC
|
||||
GType @enum_name@_get_type (void) G_GNUC_CONST;
|
||||
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (_@enum_name@_get_type ())
|
||||
GType _@enum_name@_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/*** END enumeration-production ***/
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <gio/gfiledescriptorbased.h>
|
||||
#include <gio/gunixoutputstream.h>
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree-fetcher.h"
|
||||
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
|
||||
#include "ostree-tls-cert-interaction.h"
|
||||
|
|
@ -66,7 +67,12 @@ typedef struct {
|
|||
guint64 total_downloaded;
|
||||
} ThreadClosure;
|
||||
|
||||
static void
|
||||
session_thread_process_pending_queue (ThreadClosure *thread_closure);
|
||||
|
||||
typedef struct {
|
||||
volatile int ref_count;
|
||||
|
||||
ThreadClosure *thread_closure;
|
||||
SoupURI *uri;
|
||||
|
||||
|
|
@ -185,10 +191,22 @@ pending_task_compare (gconstpointer a,
|
|||
(priority_a < priority_b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pending_uri_free (OstreeFetcherPendingURI *pending)
|
||||
static OstreeFetcherPendingURI *
|
||||
pending_uri_ref (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
g_hash_table_remove (pending->thread_closure->outstanding, pending);
|
||||
g_return_val_if_fail (pending != NULL, NULL);
|
||||
g_return_val_if_fail (pending->ref_count > 0, NULL);
|
||||
|
||||
g_atomic_int_inc (&pending->ref_count);
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
static void
|
||||
pending_uri_unref (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
if (!g_atomic_int_dec_and_test (&pending->ref_count))
|
||||
return;
|
||||
|
||||
g_clear_pointer (&pending->thread_closure, thread_closure_unref);
|
||||
|
||||
|
|
@ -273,6 +291,7 @@ session_thread_set_proxy_cb (ThreadClosure *thread_closure,
|
|||
proxy_uri, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBSOUP_CLIENT_CERTS
|
||||
static void
|
||||
session_thread_set_tls_interaction_cb (ThreadClosure *thread_closure,
|
||||
gpointer data)
|
||||
|
|
@ -288,6 +307,7 @@ session_thread_set_tls_interaction_cb (ThreadClosure *thread_closure,
|
|||
SOUP_SESSION_TLS_INTERACTION,
|
||||
interaction, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
session_thread_set_tls_database_cb (ThreadClosure *thread_closure,
|
||||
|
|
@ -328,8 +348,7 @@ session_thread_process_pending_queue (ThreadClosure *thread_closure)
|
|||
pending = g_task_get_task_data (task);
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
/* pending_uri_free() removes this. */
|
||||
g_hash_table_add (thread_closure->outstanding, pending);
|
||||
g_hash_table_add (thread_closure->outstanding, pending_uri_ref (pending));
|
||||
|
||||
soup_request_send_async (pending->request,
|
||||
cancellable,
|
||||
|
|
@ -383,7 +402,7 @@ session_thread_request_uri (ThreadClosure *thread_closure,
|
|||
if (thread_closure->tmpdir_name == NULL)
|
||||
{
|
||||
if (!_ostree_repo_allocate_tmpdir (thread_closure->base_tmpdir_dfd,
|
||||
"fetcher-",
|
||||
OSTREE_REPO_TMPDIR_FETCHER,
|
||||
&thread_closure->tmpdir_name,
|
||||
&thread_closure->tmpdir_dfd,
|
||||
&thread_closure->tmpdir_lock,
|
||||
|
|
@ -537,7 +556,7 @@ _ostree_fetcher_constructed (GObject *object)
|
|||
self->thread_closure->tmpdir_dfd = -1;
|
||||
self->thread_closure->tmpdir_lock = empty_lockfile;
|
||||
|
||||
self->thread_closure->outstanding = g_hash_table_new (NULL, NULL);
|
||||
self->thread_closure->outstanding = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)pending_uri_unref);
|
||||
self->thread_closure->output_stream_set = g_hash_table_new_full (NULL, NULL,
|
||||
(GDestroyNotify) NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
|
|
@ -739,6 +758,18 @@ on_stream_read (GObject *object,
|
|||
GAsyncResult *result,
|
||||
gpointer user_data);
|
||||
|
||||
static void
|
||||
remove_pending_rerun_queue (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
/* Hold a temporary ref to ensure the reference to
|
||||
* pending->thread_closure is valid.
|
||||
*/
|
||||
pending_uri_ref (pending);
|
||||
g_hash_table_remove (pending->thread_closure->outstanding, pending);
|
||||
session_thread_process_pending_queue (pending->thread_closure);
|
||||
pending_uri_unref (pending);
|
||||
}
|
||||
|
||||
static void
|
||||
on_out_splice_complete (GObject *object,
|
||||
GAsyncResult *result,
|
||||
|
|
@ -767,7 +798,10 @@ on_out_splice_complete (GObject *object,
|
|||
|
||||
out:
|
||||
if (local_error)
|
||||
g_task_return_error (task, local_error);
|
||||
{
|
||||
g_task_return_error (task, local_error);
|
||||
remove_pending_rerun_queue (pending);
|
||||
}
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
|
@ -799,6 +833,7 @@ on_stream_read (GObject *object,
|
|||
g_task_return_pointer (task,
|
||||
g_strdup (pending->out_tmpfile),
|
||||
(GDestroyNotify) g_free);
|
||||
remove_pending_rerun_queue (pending);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -834,7 +869,10 @@ on_stream_read (GObject *object,
|
|||
|
||||
out:
|
||||
if (local_error)
|
||||
g_task_return_error (task, local_error);
|
||||
{
|
||||
g_task_return_error (task, local_error);
|
||||
remove_pending_rerun_queue (pending);
|
||||
}
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
|
@ -880,6 +918,7 @@ on_request_sent (GObject *object,
|
|||
g_strdup (pending->out_tmpfile),
|
||||
(GDestroyNotify) g_free);
|
||||
}
|
||||
remove_pending_rerun_queue (pending);
|
||||
goto out;
|
||||
}
|
||||
else if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
|
||||
|
|
@ -944,6 +983,7 @@ on_request_sent (GObject *object,
|
|||
g_task_return_pointer (task,
|
||||
g_object_ref (pending->request_body),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
remove_pending_rerun_queue (pending);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -952,6 +992,7 @@ on_request_sent (GObject *object,
|
|||
if (pending->request_body)
|
||||
(void) g_input_stream_close (pending->request_body, NULL, NULL);
|
||||
g_task_return_error (task, local_error);
|
||||
remove_pending_rerun_queue (pending);
|
||||
}
|
||||
|
||||
g_object_unref (task);
|
||||
|
|
@ -976,6 +1017,7 @@ ostree_fetcher_request_uri_internal (OstreeFetcher *self,
|
|||
|
||||
/* SoupRequest is created in session thread. */
|
||||
pending = g_new0 (OstreeFetcherPendingURI, 1);
|
||||
pending->ref_count = 1;
|
||||
pending->thread_closure = thread_closure_ref (self->thread_closure);
|
||||
pending->uri = soup_uri_copy (uri);
|
||||
pending->max_size = max_size;
|
||||
|
|
@ -983,7 +1025,7 @@ ostree_fetcher_request_uri_internal (OstreeFetcher *self,
|
|||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, source_tag);
|
||||
g_task_set_task_data (task, pending, (GDestroyNotify) pending_uri_free);
|
||||
g_task_set_task_data (task, pending, (GDestroyNotify) pending_uri_unref);
|
||||
|
||||
/* We'll use the GTask priority for our own priority queue. */
|
||||
g_task_set_priority (task, priority);
|
||||
|
|
@ -1067,7 +1109,7 @@ _ostree_fetcher_bytes_transferred (OstreeFetcher *self)
|
|||
|
||||
if (G_IS_FILE_DESCRIPTOR_BASED (stream))
|
||||
{
|
||||
if (gs_stream_fstat ((GFileDescriptorBased*)stream, &stbuf, NULL, NULL))
|
||||
if (glnx_stream_fstat ((GFileDescriptorBased*)stream, &stbuf, NULL))
|
||||
ret += stbuf.st_size;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ G_BEGIN_DECLS
|
|||
|
||||
typedef struct OstreeGpgVerifier OstreeGpgVerifier;
|
||||
|
||||
/* If this type becomes public in future, move this autoptr cleanup
|
||||
* definition to the ostree-autocleanups.h header file. Right now it
|
||||
* relies on glnx's fallback definition of the macro. */
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifier, g_object_unref)
|
||||
|
||||
GType _ostree_gpg_verifier_get_type (void);
|
||||
|
||||
OstreeGpgVerifier *_ostree_gpg_verifier_new (void);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "ostree-gpg-verify-result-private.h"
|
||||
|
||||
/**
|
||||
* SECTION: libostree-gpg-verify-result
|
||||
* SECTION: ostree-gpg-verify-result
|
||||
* @title: GPG signature verification results
|
||||
* @short_description: Inspect detached GPG signatures
|
||||
*
|
||||
|
|
@ -622,3 +622,33 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_gpg_verify_result_require_valid_signature:
|
||||
* @result: (nullable): an #OstreeGpgVerifyResult
|
||||
* @error: A #GError
|
||||
*
|
||||
* Checks if the result contains at least one signature from the
|
||||
* trusted keyring. You can call this function immediately after
|
||||
* ostree_repo_verify_summary() or ostree_repo_verify_commit_ext() -
|
||||
* it will handle the %NULL @result and filled @error too.
|
||||
*
|
||||
* Returns: %TRUE if @result was not %NULL and had at least one
|
||||
* signature from trusted keyring, otherwise %FALSE
|
||||
*/
|
||||
gboolean
|
||||
ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result,
|
||||
GError **error)
|
||||
{
|
||||
if (result == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (ostree_gpg_verify_result_count_valid (result) == 0)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"GPG signatures found, but none are in trusted keyring");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,4 +133,8 @@ void ostree_gpg_verify_result_describe_variant (GVariant *variant,
|
|||
const gchar *line_prefix,
|
||||
OstreeGpgSignatureFormatFlags flags);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ _ostree_linuxfs_alter_immutable_flag (GFile *path,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int fd = -1;
|
||||
glnx_fd_close int fd = -1;
|
||||
|
||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
||||
return FALSE;
|
||||
|
|
@ -129,7 +129,5 @@ _ostree_linuxfs_alter_immutable_flag (GFile *path,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (fd != -1)
|
||||
(void) close (fd);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ enum {
|
|||
|
||||
/**
|
||||
* SECTION:ostree-lzma-compressor
|
||||
* @short_description: LZMA compressor
|
||||
* @title: LZMA compressor
|
||||
*
|
||||
* An implementation of #GConverter that compresses data using
|
||||
* LZMA.
|
||||
|
|
|
|||
|
|
@ -29,6 +29,14 @@ enum {
|
|||
PROP_0,
|
||||
};
|
||||
|
||||
/**
|
||||
* SECTION:ostree-lzma-decompressor
|
||||
* @title: LZMA decompressor
|
||||
*
|
||||
* An implementation of #GConverter that decompresses data using
|
||||
* LZMA.
|
||||
*/
|
||||
|
||||
static void _ostree_lzma_decompressor_iface_init (GConverterIface *iface);
|
||||
|
||||
struct _OstreeLzmaDecompressor
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "ostree-core.h"
|
||||
|
||||
/**
|
||||
* SECTION:libostree-mutable-tree
|
||||
* SECTION:ostree-mutable-tree
|
||||
* @title: In-memory modifiable filesystem tree
|
||||
* @short_description: Modifiable filesystem tree
|
||||
*
|
||||
|
|
@ -159,6 +159,11 @@ ostree_mutable_tree_replace_file (OstreeMutableTree *self,
|
|||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (!ot_util_filename_validate (name, error))
|
||||
goto out;
|
||||
|
||||
if (g_hash_table_lookup (self->subdirs, name))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
|
|
@ -187,6 +192,9 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
|
|||
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (!ot_util_filename_validate (name, error))
|
||||
goto out;
|
||||
|
||||
if (g_hash_table_lookup (self->files, name))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ gboolean ostree_mutable_tree_lookup (OstreeMutableTree *self,
|
|||
OstreeMutableTree **out_subdir,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
|
||||
GPtrArray *split_path,
|
||||
const char *metadata_checksum,
|
||||
|
|
|
|||
|
|
@ -632,7 +632,7 @@ checkout_tree_at (OstreeRepo *self,
|
|||
{
|
||||
gboolean ret = FALSE;
|
||||
gboolean did_exist = FALSE;
|
||||
int destination_dfd = -1;
|
||||
glnx_fd_close int destination_dfd = -1;
|
||||
int res;
|
||||
g_autoptr(GVariant) xattrs = NULL;
|
||||
g_autoptr(GFileEnumerator) dir_enum = NULL;
|
||||
|
|
@ -752,12 +752,12 @@ checkout_tree_at (OstreeRepo *self,
|
|||
}
|
||||
}
|
||||
|
||||
/* Set directory mtime to 0, so that it is constant for all checkouts.
|
||||
/* Set directory mtime to OSTREE_TIMESTAMP, so that it is constant for all checkouts.
|
||||
* Must be done after setting permissions and creating all children.
|
||||
*/
|
||||
if (!did_exist)
|
||||
{
|
||||
const struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, } };
|
||||
const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
|
||||
do
|
||||
res = futimens (destination_dfd, times);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
|
|
@ -779,8 +779,6 @@ checkout_tree_at (OstreeRepo *self,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (destination_dfd != -1)
|
||||
(void) close (destination_dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -957,38 +955,36 @@ ostree_repo_checkout_gc (OstreeRepo *self,
|
|||
g_hash_table_iter_init (&iter, to_clean_dirs);
|
||||
while (to_clean_dirs && g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
g_autoptr(GFile) objdir = NULL;
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
g_autofree char *objdir_name = NULL;
|
||||
g_autofree char *objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
|
||||
objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
|
||||
objdir = g_file_get_child (self->uncompressed_objects_dir, objdir_name);
|
||||
|
||||
enumerator = g_file_enumerate_children (objdir, "standard::name,standard::type,unix::inode,unix::nlink",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable,
|
||||
error);
|
||||
if (!enumerator)
|
||||
if (!glnx_dirfd_iterator_init_at (self->uncompressed_objects_dir_fd, objdir_name, FALSE,
|
||||
&dfd_iter, error))
|
||||
goto out;
|
||||
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GFileInfo *file_info;
|
||||
guint32 nlinks;
|
||||
struct dirent *dent;
|
||||
struct stat stbuf;
|
||||
|
||||
if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL,
|
||||
cancellable, error))
|
||||
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
|
||||
goto out;
|
||||
if (file_info == NULL)
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
|
||||
if (nlinks == 1)
|
||||
|
||||
if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) != 0)
|
||||
{
|
||||
g_autoptr(GFile) objpath = NULL;
|
||||
objpath = g_file_get_child (objdir, g_file_info_get_name (file_info));
|
||||
if (!gs_file_unlink (objpath, cancellable, error))
|
||||
goto out;
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (stbuf.st_nlink == 1)
|
||||
{
|
||||
if (unlinkat (dfd_iter.fd, dent->d_name, 0) != 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,22 +36,6 @@
|
|||
#include <sys/xattr.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
struct OstreeRepoCommitModifier {
|
||||
volatile gint refcount;
|
||||
|
||||
OstreeRepoCommitModifierFlags flags;
|
||||
OstreeRepoCommitFilter filter;
|
||||
gpointer user_data;
|
||||
GDestroyNotify destroy_notify;
|
||||
|
||||
OstreeRepoCommitModifierXattrCallback xattr_callback;
|
||||
GDestroyNotify xattr_destroy;
|
||||
gpointer xattr_user_data;
|
||||
|
||||
OstreeSePolicy *sepolicy;
|
||||
GHashTable *devino_cache;
|
||||
};
|
||||
|
||||
gboolean
|
||||
_ostree_repo_ensure_loose_objdir_at (int dfd,
|
||||
const char *loose_path,
|
||||
|
|
@ -226,7 +210,6 @@ commit_loose_object_trusted (OstreeRepo *self,
|
|||
else
|
||||
{
|
||||
int res;
|
||||
struct timespec times[2];
|
||||
|
||||
if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE)
|
||||
{
|
||||
|
|
@ -282,12 +265,9 @@ commit_loose_object_trusted (OstreeRepo *self,
|
|||
{
|
||||
/* To satisfy tools such as guile which compare mtimes
|
||||
* to determine whether or not source files need to be compiled,
|
||||
* set the modification time to 0.
|
||||
* set the modification time to OSTREE_TIMESTAMP.
|
||||
*/
|
||||
times[0].tv_sec = 0; /* atime */
|
||||
times[0].tv_nsec = UTIME_OMIT;
|
||||
times[1].tv_sec = 0; /* mtime */
|
||||
times[1].tv_nsec = 0;
|
||||
const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
|
||||
do
|
||||
res = futimens (fd, times);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
|
|
@ -573,11 +553,8 @@ _ostree_repo_open_trusted_content_bare (OstreeRepo *self,
|
|||
g_autofree char *temp_filename = NULL;
|
||||
g_autoptr(GOutputStream) ret_stream = NULL;
|
||||
gboolean have_obj;
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
|
||||
if (!_ostree_repo_has_loose_object (self, checksum, OSTREE_OBJECT_TYPE_FILE,
|
||||
&have_obj, loose_objpath,
|
||||
NULL,
|
||||
if (!_ostree_repo_has_loose_object (self, checksum, OSTREE_OBJECT_TYPE_FILE, &have_obj,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
@ -662,7 +639,6 @@ write_object (OstreeRepo *self,
|
|||
gboolean temp_file_is_regular;
|
||||
gboolean temp_file_is_symlink;
|
||||
gboolean object_is_symlink = FALSE;
|
||||
char loose_objpath[_OSTREE_LOOSE_PATH_MAX];
|
||||
gssize unpacked_size = 0;
|
||||
gboolean indexable = FALSE;
|
||||
|
||||
|
|
@ -673,9 +649,8 @@ write_object (OstreeRepo *self,
|
|||
|
||||
if (expected_checksum)
|
||||
{
|
||||
if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype,
|
||||
&have_obj, loose_objpath,
|
||||
NULL, cancellable, error))
|
||||
if (!_ostree_repo_has_loose_object (self, expected_checksum, objtype, &have_obj,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
if (have_obj)
|
||||
{
|
||||
|
|
@ -852,8 +827,7 @@ write_object (OstreeRepo *self,
|
|||
repo_store_size_entry (self, actual_checksum, unpacked_size, stbuf.st_size);
|
||||
}
|
||||
|
||||
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype,
|
||||
&have_obj, loose_objpath, NULL,
|
||||
if (!_ostree_repo_has_loose_object (self, actual_checksum, objtype, &have_obj,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
@ -1167,7 +1141,6 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
|
|||
{
|
||||
gboolean ret = FALSE;
|
||||
gboolean ret_transaction_resume = FALSE;
|
||||
g_autofree char *stagedir_boot_id_prefix = NULL;
|
||||
g_autofree char *stagedir_name = NULL;
|
||||
glnx_fd_close int stagedir_fd = -1;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
|
|
@ -1178,10 +1151,8 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
|
|||
|
||||
self->in_transaction = TRUE;
|
||||
|
||||
stagedir_boot_id_prefix = g_strconcat ("staging-", self->boot_id, "-", NULL);
|
||||
|
||||
if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd,
|
||||
stagedir_boot_id_prefix,
|
||||
self->stagedir_prefix,
|
||||
&self->commit_stagedir_name,
|
||||
&self->commit_stagedir_fd,
|
||||
&self->commit_stagedir_lock,
|
||||
|
|
@ -1287,44 +1258,87 @@ cleanup_tmpdir (OstreeRepo *self,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFileEnumerator) enumerator = NULL;
|
||||
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
|
||||
guint64 curtime_secs;
|
||||
|
||||
enumerator = g_file_enumerate_children (self->tmp_dir, "standard::name,time::modified",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable,
|
||||
error);
|
||||
if (!enumerator)
|
||||
goto out;
|
||||
|
||||
curtime_secs = g_get_real_time () / 1000000;
|
||||
|
||||
if (!glnx_dirfd_iterator_init_at (self->tmp_dir_fd, ".", TRUE, &dfd_iter, error))
|
||||
goto out;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GFileInfo *file_info;
|
||||
GFile *path;
|
||||
guint64 mtime;
|
||||
guint64 delta;
|
||||
struct dirent *dent;
|
||||
struct stat stbuf;
|
||||
g_auto(GLnxLockFile) lockfile = GLNX_LOCK_FILE_INIT;
|
||||
gboolean did_lock;
|
||||
|
||||
if (!gs_file_enumerator_iterate (enumerator, &file_info, &path,
|
||||
cancellable, error))
|
||||
if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error))
|
||||
goto out;
|
||||
if (file_info == NULL)
|
||||
|
||||
if (dent == NULL)
|
||||
break;
|
||||
|
||||
mtime = g_file_info_get_attribute_uint64 (file_info, "time::modified");
|
||||
if (mtime > curtime_secs)
|
||||
continue;
|
||||
/* Only delete files older than a day. To do better, we would
|
||||
* need to coordinate between multiple processes in a reliable
|
||||
* fashion. See
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=709115
|
||||
*/
|
||||
delta = curtime_secs - mtime;
|
||||
if (delta > 60*60*24)
|
||||
if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) < 0)
|
||||
{
|
||||
if (!glnx_shutil_rm_rf_at (AT_FDCWD, gs_file_get_path_cached (path), cancellable, error))
|
||||
if (errno == ENOENT) /* Did another cleanup win? */
|
||||
continue;
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* First, if it's a directory which needs locking, but it's
|
||||
* busy, skip it.
|
||||
*/
|
||||
if (_ostree_repo_is_locked_tmpdir (dent->d_name))
|
||||
{
|
||||
if (!_ostree_repo_try_lock_tmpdir (dfd_iter.fd, dent->d_name,
|
||||
&lockfile, &did_lock, error))
|
||||
goto out;
|
||||
if (!did_lock)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If however this is the staging directory for the *current*
|
||||
* boot, then don't delete it now - we may end up reusing it, as
|
||||
* is the point.
|
||||
*/
|
||||
if (g_str_has_prefix (dent->d_name, self->stagedir_prefix))
|
||||
continue;
|
||||
else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_STAGING))
|
||||
{
|
||||
/* But, crucially we can now clean up staging directories
|
||||
* from *other* boots
|
||||
*/
|
||||
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
/* FIXME - move OSTREE_REPO_TMPDIR_FETCHER underneath the
|
||||
* staging/boot-id scheme as well, since all of the "did it get
|
||||
* fsync'd" concerns apply to that as well. Then we can skip
|
||||
* this special case.
|
||||
*/
|
||||
else if (g_str_has_prefix (dent->d_name, OSTREE_REPO_TMPDIR_FETCHER))
|
||||
continue;
|
||||
else
|
||||
{
|
||||
/* Now we do time-based cleanup. Ignore it if it's somehow
|
||||
* in the future...
|
||||
*/
|
||||
if (stbuf.st_mtime > curtime_secs)
|
||||
continue;
|
||||
|
||||
/* Now, we're pruning content based on the expiry, which
|
||||
* defaults to a day. That's what we were doing before we
|
||||
* had locking...but in future we can be smarter here.
|
||||
*/
|
||||
delta = curtime_secs - stbuf.st_mtime;
|
||||
if (delta > self->tmp_expiry_seconds)
|
||||
{
|
||||
if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1448,12 +1462,25 @@ ostree_repo_commit_transaction (OstreeRepo *self,
|
|||
|
||||
g_return_val_if_fail (self->in_transaction == TRUE, FALSE);
|
||||
|
||||
if (syncfs (self->tmp_dir_fd) < 0)
|
||||
if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_PRE_COMMIT) > 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"OSTREE_REPO_TEST_ERROR_PRE_COMMIT specified");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* FIXME: Added since valgrind in el7 doesn't know about
|
||||
* `syncfs`...we should delete this later.
|
||||
*/
|
||||
if (g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL)
|
||||
{
|
||||
if (syncfs (self->tmp_dir_fd) < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rename_pending_loose_objects (self, cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
@ -1937,7 +1964,7 @@ create_empty_gvariant_dict (void)
|
|||
* ostree_repo_write_commit:
|
||||
* @self: Repo
|
||||
* @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none
|
||||
* @subject: Subject
|
||||
* @subject: (allow-none): Subject
|
||||
* @body: (allow-none): Body
|
||||
* @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none
|
||||
* @root: The tree to point the commit to
|
||||
|
|
@ -1981,10 +2008,11 @@ ostree_repo_write_commit (OstreeRepo *self,
|
|||
* ostree_repo_write_commit_with_time:
|
||||
* @self: Repo
|
||||
* @parent: (allow-none): ASCII SHA256 checksum for parent, or %NULL for none
|
||||
* @subject: Subject
|
||||
* @subject: (allow-none): Subject
|
||||
* @body: (allow-none): Body
|
||||
* @metadata: (allow-none): GVariant of type a{sv}, or %NULL for none
|
||||
* @root: The tree to point the commit to
|
||||
* @time: The time to use to stamp the commit
|
||||
* @out_commit: (out): Resulting ASCII SHA256 checksum for commit
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
|
|
@ -2011,8 +2039,6 @@ ostree_repo_write_commit_with_time (OstreeRepo *self,
|
|||
g_autofree guchar *commit_csum = NULL;
|
||||
OstreeRepoFile *repo_root = OSTREE_REPO_FILE (root);
|
||||
|
||||
g_return_val_if_fail (subject != NULL, FALSE);
|
||||
|
||||
/* Add sizes information to our metadata object */
|
||||
if (!add_size_index_to_metadata (self, metadata, &new_metadata,
|
||||
cancellable, error))
|
||||
|
|
@ -2022,7 +2048,7 @@ ostree_repo_write_commit_with_time (OstreeRepo *self,
|
|||
new_metadata ? new_metadata : create_empty_gvariant_dict (),
|
||||
parent ? ostree_checksum_to_bytes_v (parent) : ot_gvariant_new_bytearray (NULL, 0),
|
||||
g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0),
|
||||
subject, body ? body : "",
|
||||
subject ? subject : "", body ? body : "",
|
||||
GUINT64_TO_BE (time),
|
||||
ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_contents_checksum (repo_root)),
|
||||
ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_metadata_checksum (repo_root)));
|
||||
|
|
@ -2073,21 +2099,13 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self,
|
|||
g_autoptr(GFile) metadata_path =
|
||||
_ostree_repo_get_commit_metadata_loose_path (self, checksum);
|
||||
g_autoptr(GVariant) ret_metadata = NULL;
|
||||
GError *temp_error = NULL;
|
||||
|
||||
if (!ot_util_variant_map (metadata_path, G_VARIANT_TYPE ("a{sv}"),
|
||||
TRUE, &ret_metadata, &temp_error))
|
||||
if (!ot_util_variant_map_at (AT_FDCWD, gs_file_get_path_cached (metadata_path),
|
||||
G_VARIANT_TYPE ("a{sv}"),
|
||||
OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error))
|
||||
{
|
||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&temp_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_prefix_error (error, "Unable to read existing detached metadata: ");
|
||||
g_propagate_error (error, temp_error);
|
||||
goto out;
|
||||
}
|
||||
g_prefix_error (error, "Unable to read existing detached metadata: ");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
|
@ -2184,6 +2202,10 @@ create_tree_variant_from_hashes (GHashTable *file_checksums,
|
|||
while (g_hash_table_iter_next (&hash_iter, &key, &value))
|
||||
{
|
||||
const char *name = key;
|
||||
|
||||
/* Should have been validated earlier, but be paranoid */
|
||||
g_assert (ot_util_filename_validate (name, NULL));
|
||||
|
||||
sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name);
|
||||
}
|
||||
|
||||
|
|
@ -2355,7 +2377,7 @@ get_modified_xattrs (OstreeRepo *self,
|
|||
|
||||
if (label)
|
||||
{
|
||||
GVariantBuilder *builder;
|
||||
g_autoptr(GVariantBuilder) builder = NULL;
|
||||
|
||||
/* ret_xattrs may be NULL */
|
||||
builder = ot_util_variant_builder_from_variant (ret_xattrs,
|
||||
|
|
|
|||
|
|
@ -58,9 +58,6 @@ OstreeRepo * ostree_repo_file_get_repo (OstreeRepoFile *self);
|
|||
_OSTREE_PUBLIC
|
||||
OstreeRepoFile * ostree_repo_file_get_root (OstreeRepoFile *self);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_repo_file_make_empty_tree (OstreeRepoFile *self);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_repo_file_tree_set_metadata (OstreeRepoFile *self,
|
||||
const char *checksum,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -23,10 +23,6 @@
|
|||
#include "ostree-repo.h"
|
||||
#include "libglnx.h"
|
||||
|
||||
#ifdef HAVE_LIBSOUP
|
||||
#include "ostree-fetcher.h"
|
||||
#endif
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OSTREE_DELTAPART_VERSION (0)
|
||||
|
|
@ -36,6 +32,28 @@ G_BEGIN_DECLS
|
|||
#define _OSTREE_SUMMARY_CACHE_DIR "summaries"
|
||||
#define _OSTREE_CACHE_DIR "cache"
|
||||
|
||||
#define OSTREE_TIMESTAMP (1)
|
||||
|
||||
typedef enum {
|
||||
OSTREE_REPO_TEST_ERROR_PRE_COMMIT = (1 << 0)
|
||||
} OstreeRepoTestErrorFlags;
|
||||
|
||||
struct OstreeRepoCommitModifier {
|
||||
volatile gint refcount;
|
||||
|
||||
OstreeRepoCommitModifierFlags flags;
|
||||
OstreeRepoCommitFilter filter;
|
||||
gpointer user_data;
|
||||
GDestroyNotify destroy_notify;
|
||||
|
||||
OstreeRepoCommitModifierXattrCallback xattr_callback;
|
||||
GDestroyNotify xattr_destroy;
|
||||
gpointer xattr_user_data;
|
||||
|
||||
OstreeSePolicy *sepolicy;
|
||||
GHashTable *devino_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* OstreeRepo:
|
||||
*
|
||||
|
|
@ -44,7 +62,7 @@ G_BEGIN_DECLS
|
|||
struct OstreeRepo {
|
||||
GObject parent;
|
||||
|
||||
char *boot_id;
|
||||
char *stagedir_prefix;
|
||||
int commit_stagedir_fd;
|
||||
char *commit_stagedir_name;
|
||||
GLnxLockFile commit_stagedir_lock;
|
||||
|
|
@ -86,12 +104,15 @@ struct OstreeRepo {
|
|||
uid_t target_owner_uid;
|
||||
gid_t target_owner_gid;
|
||||
|
||||
guint test_error_flags; /* OstreeRepoTestErrorFlags */
|
||||
|
||||
GKeyFile *config;
|
||||
GHashTable *remotes;
|
||||
GMutex remotes_lock;
|
||||
OstreeRepoMode mode;
|
||||
gboolean enable_uncompressed_cache;
|
||||
gboolean generate_sizes;
|
||||
guint64 tmp_expiry_seconds;
|
||||
|
||||
OstreeRepo *parent_repo;
|
||||
};
|
||||
|
|
@ -102,6 +123,9 @@ typedef struct {
|
|||
char checksum[65];
|
||||
} OstreeDevIno;
|
||||
|
||||
#define OSTREE_REPO_TMPDIR_STAGING "staging-"
|
||||
#define OSTREE_REPO_TMPDIR_FETCHER "fetcher-"
|
||||
|
||||
gboolean
|
||||
_ostree_repo_allocate_tmpdir (int tmpdir_dfd,
|
||||
const char *tmpdir_prefix,
|
||||
|
|
@ -112,6 +136,16 @@ _ostree_repo_allocate_tmpdir (int tmpdir_dfd,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_ostree_repo_is_locked_tmpdir (const char *filename);
|
||||
|
||||
gboolean
|
||||
_ostree_repo_try_lock_tmpdir (int tmpdir_dfd,
|
||||
const char *tmpdir_name,
|
||||
GLnxLockFile *file_lock_out,
|
||||
gboolean *out_did_lock,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_ostree_repo_ensure_loose_objdir_at (int dfd,
|
||||
const char *loose_path,
|
||||
|
|
@ -135,8 +169,6 @@ _ostree_repo_has_loose_object (OstreeRepo *self,
|
|||
const char *checksum,
|
||||
OstreeObjectType objtype,
|
||||
gboolean *out_is_stored,
|
||||
char *loose_path_buf,
|
||||
GFile **out_stored_path,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
|
|
@ -199,13 +231,6 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self,
|
|||
gboolean
|
||||
_ostree_repo_remote_name_is_file (const char *remote_name);
|
||||
|
||||
#ifdef HAVE_LIBSOUP
|
||||
OstreeFetcher *
|
||||
_ostree_repo_remote_new_fetcher (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
GError **error);
|
||||
#endif
|
||||
|
||||
OstreeGpgVerifyResult *
|
||||
_ostree_repo_gpg_verify_with_metadata (OstreeRepo *self,
|
||||
GBytes *signed_data,
|
||||
|
|
@ -293,22 +318,4 @@ gboolean
|
|||
_ostree_repo_update_mtime (OstreeRepo *self,
|
||||
GError **error);
|
||||
|
||||
/* Load the summary from the cache if the provided .sig file is the same as the
|
||||
cached version. */
|
||||
gboolean
|
||||
_ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
|
||||
const char *remote,
|
||||
GBytes *summary_sig,
|
||||
GBytes **summary,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_ostree_repo_cache_summary (OstreeRepo *self,
|
||||
const char *remote,
|
||||
GBytes *summary,
|
||||
GBytes *summary_sig,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -23,11 +23,15 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "ostree.h"
|
||||
#include "otutil.h"
|
||||
|
||||
#ifdef HAVE_LIBSOUP
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree-core-private.h"
|
||||
#include "ostree-repo-private.h"
|
||||
#include "ostree-repo-static-delta-private.h"
|
||||
#include "ostree-metalink.h"
|
||||
#include "otutil.h"
|
||||
#include "ot-fs-utils.h"
|
||||
|
||||
#include <gio/gunixinputstream.h>
|
||||
|
|
@ -629,6 +633,7 @@ content_fetch_on_write_complete (GObject *object,
|
|||
const char *expected_checksum;
|
||||
g_autofree guchar *csum = NULL;
|
||||
g_autofree char *checksum = NULL;
|
||||
g_autofree char *checksum_obj = NULL;
|
||||
|
||||
if (!ostree_repo_write_content_finish ((OstreeRepo*)object, result,
|
||||
&csum, error))
|
||||
|
|
@ -639,7 +644,8 @@ content_fetch_on_write_complete (GObject *object,
|
|||
ostree_object_name_deserialize (fetch_data->object, &expected_checksum, &objtype);
|
||||
g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
|
||||
|
||||
g_debug ("write of %s complete", ostree_object_to_string (checksum, objtype));
|
||||
checksum_obj = ostree_object_to_string (checksum, objtype);
|
||||
g_debug ("write of %s complete", checksum_obj);
|
||||
|
||||
if (strcmp (checksum, expected_checksum) != 0)
|
||||
{
|
||||
|
|
@ -675,6 +681,7 @@ content_fetch_on_complete (GObject *object,
|
|||
g_autoptr(GInputStream) object_input = NULL;
|
||||
g_autofree char *temp_path = NULL;
|
||||
const char *checksum;
|
||||
g_autofree char *checksum_obj = NULL;
|
||||
OstreeObjectType objtype;
|
||||
|
||||
temp_path = _ostree_fetcher_request_uri_with_partial_finish (fetcher, result, error);
|
||||
|
|
@ -684,7 +691,8 @@ content_fetch_on_complete (GObject *object,
|
|||
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
|
||||
g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);
|
||||
|
||||
g_debug ("fetch of %s complete", ostree_object_to_string (checksum, objtype));
|
||||
checksum_obj = ostree_object_to_string (checksum, objtype);
|
||||
g_debug ("fetch of %s complete", checksum_obj);
|
||||
|
||||
if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
|
||||
{
|
||||
|
|
@ -796,13 +804,16 @@ meta_fetch_on_complete (GObject *object,
|
|||
g_autoptr(GVariant) metadata = NULL;
|
||||
g_autofree char *temp_path = NULL;
|
||||
const char *checksum;
|
||||
g_autofree char *checksum_obj = NULL;
|
||||
OstreeObjectType objtype;
|
||||
GError *local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
glnx_fd_close int fd = -1;
|
||||
gboolean free_fetch_data = FALSE;
|
||||
|
||||
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
|
||||
g_debug ("fetch of %s%s complete", ostree_object_to_string (checksum, objtype),
|
||||
checksum_obj = ostree_object_to_string (checksum, objtype);
|
||||
g_debug ("fetch of %s%s complete", checksum_obj,
|
||||
fetch_data->is_detached_meta ? " (detached)" : "");
|
||||
|
||||
temp_path = _ostree_fetcher_request_uri_with_partial_finish (fetcher, result, error);
|
||||
|
|
@ -864,6 +875,8 @@ meta_fetch_on_complete (GObject *object,
|
|||
|
||||
if (!fetch_data->object_is_stored)
|
||||
enqueue_one_object_request (pull_data, checksum, objtype, FALSE, FALSE);
|
||||
|
||||
free_fetch_data = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -901,7 +914,7 @@ meta_fetch_on_complete (GObject *object,
|
|||
pull_data->n_outstanding_metadata_fetches--;
|
||||
pull_data->n_fetched_metadata++;
|
||||
check_outstanding_requests_handle_error (pull_data, local_error);
|
||||
if (local_error)
|
||||
if (local_error || free_fetch_data)
|
||||
{
|
||||
g_variant_unref (fetch_data->object);
|
||||
g_free (fetch_data);
|
||||
|
|
@ -1445,6 +1458,7 @@ request_static_delta_superblock_sync (OtPullData *pull_data,
|
|||
if (out_delta_superblock)
|
||||
*out_delta_superblock = g_steal_pointer (&ret_delta_superblock);
|
||||
out:
|
||||
g_clear_pointer (&target_uri, (GDestroyNotify) soup_uri_free);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1734,47 +1748,9 @@ validate_variant_is_csum (GVariant *csum,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* documented in ostree-repo.c */
|
||||
gboolean
|
||||
ostree_repo_pull (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
char **refs_to_fetch,
|
||||
OstreeRepoPullFlags flags,
|
||||
OstreeAsyncProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return ostree_repo_pull_one_dir (self, remote_name, NULL, refs_to_fetch, flags, progress, cancellable, error);
|
||||
}
|
||||
|
||||
/* Documented in ostree-repo.c */
|
||||
gboolean
|
||||
ostree_repo_pull_one_dir (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
const char *dir_to_pull,
|
||||
char **refs_to_fetch,
|
||||
OstreeRepoPullFlags flags,
|
||||
OstreeAsyncProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
|
||||
if (dir_to_pull)
|
||||
g_variant_builder_add (&builder, "{s@v}", "subdir",
|
||||
g_variant_new_variant (g_variant_new_string (dir_to_pull)));
|
||||
g_variant_builder_add (&builder, "{s@v}", "flags",
|
||||
g_variant_new_variant (g_variant_new_int32 (flags)));
|
||||
if (refs_to_fetch)
|
||||
g_variant_builder_add (&builder, "{s@v}", "refs",
|
||||
g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch, -1)));
|
||||
|
||||
return ostree_repo_pull_with_options (self, remote_name, g_variant_builder_end (&builder),
|
||||
progress, cancellable, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
/* Load the summary from the cache if the provided .sig file is the same as the
|
||||
cached version. */
|
||||
static gboolean
|
||||
_ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
|
||||
const char *remote,
|
||||
GBytes *summary_sig,
|
||||
|
|
@ -1836,7 +1812,7 @@ _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
|
|||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
_ostree_repo_cache_summary (OstreeRepo *self,
|
||||
const char *remote,
|
||||
GBytes *summary,
|
||||
|
|
@ -1876,7 +1852,311 @@ _ostree_repo_cache_summary (OstreeRepo *self,
|
|||
|
||||
}
|
||||
|
||||
/* Documented in ostree-repo.c */
|
||||
static OstreeFetcher *
|
||||
_ostree_repo_remote_new_fetcher (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
GError **error)
|
||||
{
|
||||
OstreeFetcher *fetcher = NULL;
|
||||
OstreeFetcherConfigFlags fetcher_flags = 0;
|
||||
gboolean tls_permissive = FALSE;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
|
||||
g_return_val_if_fail (remote_name != NULL, NULL);
|
||||
|
||||
if (!ostree_repo_get_remote_boolean_option (self, remote_name,
|
||||
"tls-permissive", FALSE,
|
||||
&tls_permissive, error))
|
||||
goto out;
|
||||
|
||||
if (tls_permissive)
|
||||
fetcher_flags |= OSTREE_FETCHER_FLAGS_TLS_PERMISSIVE;
|
||||
|
||||
fetcher = _ostree_fetcher_new (self->tmp_dir_fd, fetcher_flags);
|
||||
|
||||
{
|
||||
g_autofree char *tls_client_cert_path = NULL;
|
||||
g_autofree char *tls_client_key_path = NULL;
|
||||
|
||||
if (!ostree_repo_get_remote_option (self, remote_name,
|
||||
"tls-client-cert-path", NULL,
|
||||
&tls_client_cert_path, error))
|
||||
goto out;
|
||||
if (!ostree_repo_get_remote_option (self, remote_name,
|
||||
"tls-client-key-path", NULL,
|
||||
&tls_client_key_path, error))
|
||||
goto out;
|
||||
|
||||
if ((tls_client_cert_path != NULL) != (tls_client_key_path != NULL))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Remote \"%s\" must specify both "
|
||||
"\"tls-client-cert-path\" and \"tls-client-key-path\"",
|
||||
remote_name);
|
||||
goto out;
|
||||
}
|
||||
else if (tls_client_cert_path != NULL)
|
||||
{
|
||||
g_autoptr(GTlsCertificate) client_cert = NULL;
|
||||
|
||||
g_assert (tls_client_key_path != NULL);
|
||||
|
||||
client_cert = g_tls_certificate_new_from_files (tls_client_cert_path,
|
||||
tls_client_key_path,
|
||||
error);
|
||||
if (client_cert == NULL)
|
||||
goto out;
|
||||
|
||||
_ostree_fetcher_set_client_cert (fetcher, client_cert);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
g_autofree char *tls_ca_path = NULL;
|
||||
|
||||
if (!ostree_repo_get_remote_option (self, remote_name,
|
||||
"tls-ca-path", NULL,
|
||||
&tls_ca_path, error))
|
||||
goto out;
|
||||
|
||||
if (tls_ca_path != NULL)
|
||||
{
|
||||
g_autoptr(GTlsDatabase) db = NULL;
|
||||
|
||||
db = g_tls_file_database_new (tls_ca_path, error);
|
||||
if (db == NULL)
|
||||
goto out;
|
||||
|
||||
_ostree_fetcher_set_tls_database (fetcher, db);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
g_autofree char *http_proxy = NULL;
|
||||
|
||||
if (!ostree_repo_get_remote_option (self, remote_name,
|
||||
"proxy", NULL,
|
||||
&http_proxy, error))
|
||||
goto out;
|
||||
|
||||
if (http_proxy != NULL)
|
||||
_ostree_fetcher_set_proxy (fetcher, http_proxy);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (!success)
|
||||
g_clear_object (&fetcher);
|
||||
|
||||
return fetcher;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_ostree_preload_metadata_file (OstreeRepo *self,
|
||||
OstreeFetcher *fetcher,
|
||||
SoupURI *base_uri,
|
||||
const char *filename,
|
||||
gboolean is_metalink,
|
||||
GBytes **out_bytes,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (is_metalink)
|
||||
{
|
||||
glnx_unref_object OstreeMetalink *metalink = NULL;
|
||||
GError *local_error = NULL;
|
||||
|
||||
metalink = _ostree_metalink_new (fetcher, filename,
|
||||
OSTREE_MAX_METADATA_SIZE,
|
||||
base_uri);
|
||||
|
||||
_ostree_metalink_request_sync (metalink, NULL, out_bytes, NULL,
|
||||
cancellable, &local_error);
|
||||
|
||||
if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&local_error);
|
||||
*out_bytes = NULL;
|
||||
}
|
||||
else if (local_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, local_error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SoupURI *uri;
|
||||
const char *base_path;
|
||||
g_autofree char *path = NULL;
|
||||
|
||||
base_path = soup_uri_get_path (base_uri);
|
||||
path = g_build_filename (base_path, filename, NULL);
|
||||
uri = soup_uri_new_with_base (base_uri, path);
|
||||
|
||||
ret = _ostree_fetcher_request_uri_to_membuf (fetcher, uri,
|
||||
FALSE, TRUE,
|
||||
out_bytes,
|
||||
OSTREE_MAX_METADATA_SIZE,
|
||||
cancellable, error);
|
||||
soup_uri_free (uri);
|
||||
|
||||
if (!ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
repo_remote_fetch_summary (OstreeRepo *self,
|
||||
const char *name,
|
||||
const char *metalink_url_string,
|
||||
GVariant *options,
|
||||
GBytes **out_summary,
|
||||
GBytes **out_signatures,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
glnx_unref_object OstreeFetcher *fetcher = NULL;
|
||||
g_autoptr(GMainContext) mainctx = NULL;
|
||||
gboolean ret = FALSE;
|
||||
SoupURI *base_uri = NULL;
|
||||
gboolean from_cache = FALSE;
|
||||
g_autofree char *url_override = NULL;
|
||||
|
||||
if (options)
|
||||
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
|
||||
|
||||
mainctx = g_main_context_new ();
|
||||
g_main_context_push_thread_default (mainctx);
|
||||
|
||||
fetcher = _ostree_repo_remote_new_fetcher (self, name, error);
|
||||
if (fetcher == NULL)
|
||||
goto out;
|
||||
|
||||
{
|
||||
g_autofree char *url_string = NULL;
|
||||
if (metalink_url_string)
|
||||
url_string = g_strdup (metalink_url_string);
|
||||
else if (url_override)
|
||||
url_string = g_strdup (url_override);
|
||||
else if (!ostree_repo_remote_get_url (self, name, &url_string, error))
|
||||
goto out;
|
||||
|
||||
base_uri = soup_uri_new (url_string);
|
||||
if (base_uri == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Invalid URL '%s'", url_string);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_ostree_preload_metadata_file (self,
|
||||
fetcher,
|
||||
base_uri,
|
||||
"summary.sig",
|
||||
metalink_url_string ? TRUE : FALSE,
|
||||
out_signatures,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (*out_signatures)
|
||||
{
|
||||
if (!_ostree_repo_load_cache_summary_if_same_sig (self,
|
||||
name,
|
||||
*out_signatures,
|
||||
out_summary,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (*out_summary)
|
||||
from_cache = TRUE;
|
||||
else
|
||||
{
|
||||
if (!_ostree_preload_metadata_file (self,
|
||||
fetcher,
|
||||
base_uri,
|
||||
"summary",
|
||||
metalink_url_string ? TRUE : FALSE,
|
||||
out_summary,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!from_cache && *out_summary && *out_signatures)
|
||||
{
|
||||
g_autoptr(GError) temp_error = NULL;
|
||||
|
||||
if (!_ostree_repo_cache_summary (self,
|
||||
name,
|
||||
*out_summary,
|
||||
*out_signatures,
|
||||
cancellable,
|
||||
&temp_error))
|
||||
{
|
||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
|
||||
g_debug ("No permissions to save summary cache");
|
||||
else
|
||||
{
|
||||
g_propagate_error (error, g_steal_pointer (&temp_error));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
if (mainctx)
|
||||
g_main_context_pop_thread_default (mainctx);
|
||||
if (base_uri != NULL)
|
||||
soup_uri_free (base_uri);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------
|
||||
* Below is the libsoup-invariant API; these should match
|
||||
* the stub functions in the #else clause
|
||||
* ------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* ostree_repo_pull_with_options:
|
||||
* @self: Repo
|
||||
* @remote_name: Name of remote
|
||||
* @options: A GVariant a{sv} with an extensible set of flags.
|
||||
* @progress: (allow-none): Progress
|
||||
* @cancellable: Cancellable
|
||||
* @error: Error
|
||||
*
|
||||
* Like ostree_repo_pull(), but supports an extensible set of flags.
|
||||
* The following are currently defined:
|
||||
*
|
||||
* * refs (as): Array of string refs
|
||||
* * flags (i): An instance of #OstreeRepoPullFlags
|
||||
* * subdir (s): Pull just this subdirectory
|
||||
* * override-remote-name (s): If local, add this remote to refspec
|
||||
* * gpg-verify (b): GPG verify commits
|
||||
* * gpg-verify-summary (b): GPG verify summary
|
||||
* * depth (i): How far in the history to traverse; default is 0, -1 means infinite
|
||||
* * disable-static-deltas (b): Do not use static deltas
|
||||
* * require-static-deltas (b): Require static deltas
|
||||
* * override-commit-ids (as): Array of specific commit IDs to fetch for refs
|
||||
* * dry-run (b): Only print information on what will be downloaded (requires static deltas)
|
||||
* * override-url (s): Fetch objects from this URL if remote specifies no metalink in options
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
const char *remote_name_or_baseurl,
|
||||
|
|
@ -1889,8 +2169,6 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
|||
GHashTableIter hash_iter;
|
||||
gpointer key, value;
|
||||
g_autoptr(GBytes) bytes_summary = NULL;
|
||||
g_autofree char *remote_key = NULL;
|
||||
g_autofree char *path = NULL;
|
||||
g_autofree char *metalink_url_str = NULL;
|
||||
g_autoptr(GHashTable) requested_refs_to_fetch = NULL;
|
||||
g_autoptr(GHashTable) commits_to_fetch = NULL;
|
||||
|
|
@ -1904,13 +2182,14 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
|||
guint64 end_time;
|
||||
OstreeRepoPullFlags flags = 0;
|
||||
const char *dir_to_pull = NULL;
|
||||
char **refs_to_fetch = NULL;
|
||||
g_autofree char **refs_to_fetch = NULL;
|
||||
char **override_commit_ids = NULL;
|
||||
GSource *update_timeout = NULL;
|
||||
gboolean disable_static_deltas = FALSE;
|
||||
gboolean require_static_deltas = FALSE;
|
||||
gboolean opt_gpg_verify = FALSE;
|
||||
gboolean opt_gpg_verify_summary = FALSE;
|
||||
const char *url_override = NULL;
|
||||
|
||||
if (options)
|
||||
{
|
||||
|
|
@ -1928,6 +2207,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
|||
(void) g_variant_lookup (options, "require-static-deltas", "b", &require_static_deltas);
|
||||
(void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
|
||||
(void) g_variant_lookup (options, "dry-run", "b", &pull_data->dry_run);
|
||||
(void) g_variant_lookup (options, "override-url", "&s", &url_override);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE);
|
||||
|
|
@ -2023,7 +2303,9 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
|||
{
|
||||
g_autofree char *baseurl = NULL;
|
||||
|
||||
if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error))
|
||||
if (url_override != NULL)
|
||||
baseurl = g_strdup (url_override);
|
||||
else if (!ostree_repo_remote_get_url (self, remote_name_or_baseurl, &baseurl, error))
|
||||
goto out;
|
||||
|
||||
pull_data->base_uri = soup_uri_new (baseurl);
|
||||
|
|
@ -2587,3 +2869,121 @@ ostree_repo_pull_with_options (OstreeRepo *self,
|
|||
g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_remote_fetch_summary_with_options:
|
||||
* @self: Self
|
||||
* @name: name of a remote
|
||||
* @options: (nullable): A GVariant a{sv} with an extensible set of flags
|
||||
* @out_summary: (nullable): return location for raw summary data, or %NULL
|
||||
* @out_signatures: (nullable): return location for raw summary signature
|
||||
* data, or %NULL
|
||||
* @cancellable: a #GCancellable
|
||||
* @error: a #GError
|
||||
*
|
||||
* Like ostree_repo_remote_fetch_summary(), but supports an extensible set of flags.
|
||||
* The following are currently defined:
|
||||
*
|
||||
* - override-url (s): Fetch summary from this URL if remote specifies no metalink in options
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on failure
|
||||
*/
|
||||
gboolean
|
||||
ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
|
||||
const char *name,
|
||||
GVariant *options,
|
||||
GBytes **out_summary,
|
||||
GBytes **out_signatures,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree char *metalink_url_string = NULL;
|
||||
g_autoptr(GBytes) summary = NULL;
|
||||
g_autoptr(GBytes) signatures = NULL;
|
||||
gboolean ret = FALSE;
|
||||
gboolean gpg_verify_summary;
|
||||
|
||||
g_return_val_if_fail (OSTREE_REPO (self), FALSE);
|
||||
g_return_val_if_fail (name != NULL, FALSE);
|
||||
|
||||
if (!ostree_repo_get_remote_option (self, name, "metalink", NULL,
|
||||
&metalink_url_string, error))
|
||||
goto out;
|
||||
|
||||
if (!repo_remote_fetch_summary (self,
|
||||
name,
|
||||
metalink_url_string,
|
||||
options,
|
||||
&summary,
|
||||
&signatures,
|
||||
cancellable,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_repo_remote_get_gpg_verify_summary (self, name, &gpg_verify_summary, error))
|
||||
goto out;
|
||||
|
||||
if (gpg_verify_summary && signatures == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Verify any summary signatures. */
|
||||
if (gpg_verify_summary && summary != NULL && signatures != NULL)
|
||||
{
|
||||
glnx_unref_object OstreeGpgVerifyResult *result = NULL;
|
||||
|
||||
result = ostree_repo_verify_summary (self,
|
||||
name,
|
||||
summary,
|
||||
signatures,
|
||||
cancellable,
|
||||
error);
|
||||
if (!ostree_gpg_verify_result_require_valid_signature (result, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (out_summary != NULL)
|
||||
*out_summary = g_steal_pointer (&summary);
|
||||
|
||||
if (out_signatures != NULL)
|
||||
*out_signatures = g_steal_pointer (&signatures);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* HAVE_LIBSOUP */
|
||||
|
||||
gboolean
|
||||
ostree_repo_pull_with_options (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
GVariant *options,
|
||||
OstreeAsyncProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
"This version of ostree was built without libsoup, and cannot fetch over HTTP");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
|
||||
const char *name,
|
||||
GVariant *options,
|
||||
GBytes **out_summary,
|
||||
GBytes **out_signatures,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
"This version of ostree was built without libsoup, and cannot fetch over HTTP");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBSOUP */
|
||||
|
|
|
|||
|
|
@ -1226,7 +1226,7 @@ get_fallback_headers (OstreeRepo *self,
|
|||
*
|
||||
* The @params argument should be an a{sv}. The following attributes
|
||||
* are known:
|
||||
* - min-fallback-size: u: Minimume uncompressed size in megabytes to use fallback, 0 to disable fallbacks
|
||||
* - min-fallback-size: u: Minimum uncompressed size in megabytes to use fallback, 0 to disable fallbacks
|
||||
* - max-chunk-size: u: Maximum size in megabytes of a delta part
|
||||
* - max-bsdiff-size: u: Maximum size in megabytes to consider bsdiff compression
|
||||
* for input files
|
||||
|
|
@ -1253,7 +1253,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
|
|||
guint min_fallback_size;
|
||||
guint max_bsdiff_size;
|
||||
guint max_chunk_size;
|
||||
GVariantBuilder metadata_builder;
|
||||
g_auto(GVariantBuilder) metadata_builder = {{0,}};
|
||||
DeltaOpts delta_opts = DELTAOPT_FLAG_NONE;
|
||||
guint64 total_compressed_size = 0;
|
||||
guint64 total_uncompressed_size = 0;
|
||||
|
|
@ -1384,16 +1384,18 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
|
|||
g_autoptr(GVariant) delta_part_content = NULL;
|
||||
g_autoptr(GVariant) delta_part = NULL;
|
||||
g_autoptr(GVariant) delta_part_header = NULL;
|
||||
GVariantBuilder *mode_builder = g_variant_builder_new (G_VARIANT_TYPE ("a(uuu)"));
|
||||
GVariantBuilder *xattr_builder = g_variant_builder_new (G_VARIANT_TYPE ("aa(ayay)"));
|
||||
g_auto(GVariantBuilder) mode_builder = {{0,}};
|
||||
g_auto(GVariantBuilder) xattr_builder = {{0,}};
|
||||
guint8 compression_type_char;
|
||||
|
||||
g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uuu)"));
|
||||
g_variant_builder_init (&xattr_builder, G_VARIANT_TYPE ("aa(ayay)"));
|
||||
{ guint j;
|
||||
for (j = 0; j < part_builder->modes->len; j++)
|
||||
g_variant_builder_add_value (mode_builder, part_builder->modes->pdata[j]);
|
||||
g_variant_builder_add_value (&mode_builder, part_builder->modes->pdata[j]);
|
||||
|
||||
for (j = 0; j < part_builder->xattrs->len; j++)
|
||||
g_variant_builder_add_value (xattr_builder, part_builder->xattrs->pdata[j]);
|
||||
g_variant_builder_add_value (&xattr_builder, part_builder->xattrs->pdata[j]);
|
||||
}
|
||||
|
||||
payload_b = g_string_free_to_bytes (part_builder->payload);
|
||||
|
|
@ -1403,7 +1405,7 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
|
|||
part_builder->operations = NULL;
|
||||
/* FIXME - avoid duplicating memory here */
|
||||
delta_part_content = g_variant_new ("(a(uuu)aa(ayay)@ay@ay)",
|
||||
mode_builder, xattr_builder,
|
||||
&mode_builder, &xattr_builder,
|
||||
ot_gvariant_new_ay_bytes (payload_b),
|
||||
ot_gvariant_new_ay_bytes (operations_b));
|
||||
g_variant_ref_sink (delta_part_content);
|
||||
|
|
@ -1481,7 +1483,8 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
|
|||
|
||||
descriptor_dir = g_file_get_parent (descriptor_path);
|
||||
|
||||
if (!gs_file_ensure_directory (descriptor_dir, TRUE, cancellable, error))
|
||||
if (!glnx_shutil_mkdir_p_at (AT_FDCWD, gs_file_get_path_cached (descriptor_dir), 0755,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < part_tempfiles->len; i++)
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
|
|||
if (g_file_info_get_file_type (file_info2) != G_FILE_TYPE_DIRECTORY)
|
||||
continue;
|
||||
|
||||
name1 = gs_file_get_basename_cached (child);
|
||||
name2 = gs_file_get_basename_cached (child2);
|
||||
name1 = g_file_info_get_name (file_info);
|
||||
name2 = g_file_info_get_name (file_info2);
|
||||
|
||||
{
|
||||
g_autoptr(GFile) meta_path = g_file_get_child (child2, "superblock");
|
||||
|
|
@ -159,7 +159,8 @@ ostree_repo_list_static_delta_names (OstreeRepo *self,
|
|||
}
|
||||
|
||||
ret = TRUE;
|
||||
gs_transfer_out_value (out_deltas, &ret_deltas);
|
||||
if (out_deltas)
|
||||
*out_deltas = g_steal_pointer (&ret_deltas);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -512,6 +513,7 @@ _ostree_static_delta_part_open (GInputStream *part_in,
|
|||
g_bytes_get_size (inline_part_bytes) - 1);
|
||||
ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
|
||||
content_bytes, trusted);
|
||||
g_variant_ref_sink (ret_part);
|
||||
}
|
||||
|
||||
if (!skip_checksum)
|
||||
|
|
@ -840,7 +842,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
|
|||
|
||||
if (!ot_util_variant_map_at (self->repo_dir_fd, superblock_path,
|
||||
(GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT,
|
||||
TRUE, &delta_superblock, error))
|
||||
OT_VARIANT_MAP_TRUSTED, &delta_superblock, error))
|
||||
goto out;
|
||||
|
||||
g_print ("%s\n", g_variant_print (delta_superblock, 1));
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ostree.h"
|
||||
#include "otutil.h"
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -115,6 +115,10 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* OstreeRepoRemoteChange:
|
||||
* The remote change operation.
|
||||
*/
|
||||
typedef enum {
|
||||
OSTREE_REPO_REMOTE_CHANGE_ADD,
|
||||
OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS,
|
||||
|
|
@ -194,6 +198,15 @@ gboolean ostree_repo_remote_fetch_summary (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
gboolean ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self,
|
||||
const char *name,
|
||||
GVariant *options,
|
||||
GBytes **out_summary,
|
||||
GBytes **out_signatures,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeRepo * ostree_repo_get_parent (OstreeRepo *self);
|
||||
|
||||
|
|
@ -214,6 +227,10 @@ gboolean ostree_repo_write_config (OstreeRepo *self,
|
|||
* were written to the repository in this transaction.
|
||||
* @content_bytes_written: The amount of data added to the repository,
|
||||
* in bytes, counting only content objects.
|
||||
* @padding1: reserved
|
||||
* @padding2: reserved
|
||||
* @padding3: reserved
|
||||
* @padding4: reserved
|
||||
*
|
||||
* A list of statistics for each transaction that may be
|
||||
* interesting for reporting purposes.
|
||||
|
|
@ -582,7 +599,9 @@ gboolean ostree_repo_write_archive_to_mtree (OstreeRepo *
|
|||
typedef struct {
|
||||
guint ignore_unsupported_content : 1;
|
||||
guint autocreate_parents : 1;
|
||||
guint reserved : 30;
|
||||
guint use_ostree_convention : 1;
|
||||
guint callback_with_entry_pathname : 1;
|
||||
guint reserved : 28;
|
||||
|
||||
guint unused_uint[8];
|
||||
gpointer unused_ptrs[8];
|
||||
|
|
@ -610,7 +629,10 @@ typedef struct {
|
|||
guint64 timestamp_secs;
|
||||
|
||||
guint unused_uint[8];
|
||||
gpointer unused_ptrs[8];
|
||||
|
||||
char *path_prefix;
|
||||
|
||||
gpointer unused_ptrs[7];
|
||||
} OstreeRepoExportArchiveOptions;
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
|
|
@ -685,7 +707,8 @@ typedef enum {
|
|||
OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES = 1
|
||||
} OstreeRepoCheckoutOverwriteMode;
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_checkout_tree (OstreeRepo *self,
|
||||
OstreeRepoCheckoutMode mode,
|
||||
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
||||
|
|
@ -852,14 +875,16 @@ typedef enum {
|
|||
OSTREE_REPO_COMMIT_TRAVERSE_FLAG_NONE = (1 << 0)
|
||||
} OstreeRepoCommitTraverseFlags;
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_commit_traverse_iter_init_commit (OstreeRepoCommitTraverseIter *iter,
|
||||
OstreeRepo *repo,
|
||||
GVariant *commit,
|
||||
OstreeRepoCommitTraverseFlags flags,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_commit_traverse_iter_init_dirtree (OstreeRepoCommitTraverseIter *iter,
|
||||
OstreeRepo *repo,
|
||||
GVariant *dirtree,
|
||||
|
|
@ -889,8 +914,8 @@ void ostree_repo_commit_traverse_iter_get_dir (OstreeRepoCommitTraverseIter *ite
|
|||
char **out_content_checksum,
|
||||
char **out_meta_checksum);
|
||||
|
||||
_OSTREE_PUBLIC void
|
||||
ostree_repo_commit_traverse_iter_clear (OstreeRepoCommitTraverseIter *iter);
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_repo_commit_traverse_iter_clear (OstreeRepoCommitTraverseIter *iter);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
void ostree_repo_commit_traverse_iter_cleanup (void *p);
|
||||
|
|
@ -909,7 +934,8 @@ typedef enum {
|
|||
OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY
|
||||
} OstreeRepoPruneFlags;
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_prune_static_deltas (OstreeRepo *self, const char *commit,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
|
@ -947,7 +973,8 @@ gboolean ostree_repo_pull (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_pull_one_dir (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
const char *dir_to_pull,
|
||||
|
|
@ -986,7 +1013,8 @@ gboolean ostree_repo_sign_delta (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC gboolean
|
||||
_OSTREE_PUBLIC
|
||||
gboolean
|
||||
ostree_repo_add_gpg_signature_summary (OstreeRepo *self,
|
||||
const gchar **key_id,
|
||||
const gchar *homedir,
|
||||
|
|
@ -1016,6 +1044,16 @@ OstreeGpgVerifyResult * ostree_repo_verify_commit_ext (OstreeRepo *self,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeGpgVerifyResult * ostree_repo_gpg_verify_data (OstreeRepo *self,
|
||||
const gchar *remote_name,
|
||||
GBytes *data,
|
||||
GBytes *signatures,
|
||||
GFile *keyringdir,
|
||||
GFile *extra_keyring,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
_OSTREE_PUBLIC
|
||||
OstreeGpgVerifyResult * ostree_repo_verify_summary (OstreeRepo *self,
|
||||
const char *remote_name,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "ostree-bootloader-syslinux.h"
|
||||
|
||||
/**
|
||||
* SECTION:libostree-sepolicy
|
||||
* SECTION:ostree-sepolicy
|
||||
* @title: SELinux policy management
|
||||
* @short_description: Read SELinux policy and manage filesystem labels
|
||||
*
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ _ostree_sysroot_list_deployment_dirs_for_os (GFile *osdir,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *osname = gs_file_get_basename_cached (osdir);
|
||||
const char *osname = glnx_basename (gs_file_get_path_cached (osdir));
|
||||
g_autoptr(GFileEnumerator) dir_enum = NULL;
|
||||
g_autoptr(GFile) osdeploy_dir = NULL;
|
||||
GError *temp_error = NULL;
|
||||
|
|
@ -370,7 +370,7 @@ cleanup_old_deployments (OstreeSysroot *self,
|
|||
g_autofree char *osname = NULL;
|
||||
g_autofree char *bootcsum = NULL;
|
||||
|
||||
if (!parse_bootdir_name (gs_file_get_basename_cached (bootdir),
|
||||
if (!parse_bootdir_name (glnx_basename (gs_file_get_path_cached (bootdir)),
|
||||
&osname, &bootcsum))
|
||||
g_assert_not_reached ();
|
||||
|
||||
|
|
|
|||
|
|
@ -87,6 +87,39 @@ symlink_at_replace (const char *oldpath,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Try a hardlink if we can, otherwise fall back to copying. Used
|
||||
* right now for kernels/initramfs in /boot, where we can just
|
||||
* hardlink if we're on the same partition.
|
||||
*/
|
||||
static gboolean
|
||||
hardlink_or_copy_at (int src_dfd,
|
||||
const char *src_subpath,
|
||||
int dest_dfd,
|
||||
const char *dest_subpath,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (linkat (src_dfd, src_subpath, dest_dfd, dest_subpath, 0) != 0)
|
||||
{
|
||||
if (errno == EMLINK || errno == EXDEV)
|
||||
{
|
||||
return glnx_file_copy_at (src_dfd, src_subpath, NULL, dest_dfd, dest_subpath, 0,
|
||||
cancellable, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dirfd_copy_attributes_and_xattrs (int src_parent_dfd,
|
||||
const char *src_name,
|
||||
|
|
@ -139,8 +172,8 @@ copy_dir_recurse (int src_parent_dfd,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int src_dfd = -1;
|
||||
int dest_dfd = -1;
|
||||
glnx_fd_close int src_dfd = -1;
|
||||
glnx_fd_close int dest_dfd = -1;
|
||||
DIR *srcd = NULL;
|
||||
struct dirent *dent;
|
||||
|
||||
|
|
@ -207,10 +240,6 @@ copy_dir_recurse (int src_parent_dfd,
|
|||
/* Note the srcd owns src_dfd */
|
||||
src_dfd = -1;
|
||||
}
|
||||
if (src_dfd != -1)
|
||||
(void) close (src_dfd);
|
||||
if (dest_dfd != -1)
|
||||
(void) close (dest_dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -224,8 +253,8 @@ ensure_directory_from_template (int orig_etc_fd,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int src_dfd = -1;
|
||||
int target_dfd = -1;
|
||||
glnx_fd_close int src_dfd = -1;
|
||||
glnx_fd_close int target_dfd = -1;
|
||||
|
||||
g_assert (path != NULL);
|
||||
g_assert (*path != '/' && *path != '\0');
|
||||
|
|
@ -283,10 +312,6 @@ ensure_directory_from_template (int orig_etc_fd,
|
|||
target_dfd = -1;
|
||||
}
|
||||
out:
|
||||
if (src_dfd != -1)
|
||||
(void) close (src_dfd);
|
||||
if (target_dfd != -1)
|
||||
(void) close (target_dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -308,7 +333,7 @@ copy_modified_config_file (int orig_etc_fd,
|
|||
gboolean ret = FALSE;
|
||||
struct stat modified_stbuf;
|
||||
struct stat new_stbuf;
|
||||
int dest_parent_dfd = -1;
|
||||
glnx_fd_close int dest_parent_dfd = -1;
|
||||
|
||||
if (fstatat (modified_etc_fd, path, &modified_stbuf, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
{
|
||||
|
|
@ -398,8 +423,6 @@ copy_modified_config_file (int orig_etc_fd,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (dest_parent_dfd != -1)
|
||||
(void) close (dest_parent_dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -426,9 +449,9 @@ merge_etc_changes (GFile *orig_etc,
|
|||
g_autoptr(GPtrArray) removed = NULL;
|
||||
g_autoptr(GPtrArray) added = NULL;
|
||||
guint i;
|
||||
int orig_etc_fd = -1;
|
||||
int modified_etc_fd = -1;
|
||||
int new_etc_fd = -1;
|
||||
glnx_fd_close int orig_etc_fd = -1;
|
||||
glnx_fd_close int modified_etc_fd = -1;
|
||||
glnx_fd_close int new_etc_fd = -1;
|
||||
|
||||
modified = g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_diff_item_unref);
|
||||
removed = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
|
|
@ -505,12 +528,6 @@ merge_etc_changes (GFile *orig_etc,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (orig_etc_fd != -1)
|
||||
(void) close (orig_etc_fd);
|
||||
if (modified_etc_fd != -1)
|
||||
(void) close (modified_etc_fd);
|
||||
if (new_etc_fd != -1)
|
||||
(void) close (new_etc_fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +668,7 @@ relabel_recursively (OstreeSysroot *sysroot,
|
|||
if (file_info == NULL)
|
||||
break;
|
||||
|
||||
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (child));
|
||||
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
|
||||
|
||||
ftype = g_file_info_get_file_type (file_info);
|
||||
if (ftype == G_FILE_TYPE_DIRECTORY)
|
||||
|
|
@ -723,12 +740,12 @@ selinux_relabel_file (OstreeSysroot *sysroot,
|
|||
goto out;
|
||||
|
||||
g_ptr_array_add (path_parts, (char*)prefix);
|
||||
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (path));
|
||||
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
|
||||
if (!relabel_one_path (sysroot, sepolicy, path, file_info, path_parts,
|
||||
cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Relabeling /%s/%s: ", prefix,
|
||||
gs_file_get_basename_cached (path));
|
||||
g_file_info_get_name (file_info));
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1277,7 +1294,6 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
|||
struct stat stbuf;
|
||||
const char *osname = ostree_deployment_get_osname (deployment);
|
||||
const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
|
||||
g_autoptr(GFile) bootdir = NULL;
|
||||
g_autofree char *bootcsumdir = NULL;
|
||||
g_autofree char *bootconfdir = NULL;
|
||||
g_autofree char *bootconf_name = NULL;
|
||||
|
|
@ -1293,10 +1309,6 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
|||
g_autofree char *contents = NULL;
|
||||
g_autofree char *deployment_version = NULL;
|
||||
g_autoptr(GHashTable) osrelease_values = NULL;
|
||||
g_autofree char *linux_relpath = NULL;
|
||||
g_autofree char *linux_key = NULL;
|
||||
g_autofree char *initramfs_relpath = NULL;
|
||||
g_autofree char *initrd_key = NULL;
|
||||
g_autofree char *version_key = NULL;
|
||||
g_autofree char *ostree_kernel_arg = NULL;
|
||||
g_autofree char *options_key = NULL;
|
||||
|
|
@ -1342,9 +1354,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
|||
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_kernel_name);
|
||||
goto out;
|
||||
}
|
||||
if (!glnx_file_copy_at (tree_boot_dfd, tree_kernel_name, NULL,
|
||||
bootcsum_dfd, dest_kernel_name, 0,
|
||||
cancellable, error))
|
||||
if (!hardlink_or_copy_at (tree_boot_dfd, tree_kernel_name,
|
||||
bootcsum_dfd, dest_kernel_name,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1359,9 +1371,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
|
|||
glnx_set_prefix_error_from_errno (error, "fstat %s", dest_initramfs_name);
|
||||
goto out;
|
||||
}
|
||||
if (!glnx_file_copy_at (tree_boot_dfd, tree_initramfs_name, NULL,
|
||||
bootcsum_dfd, dest_initramfs_name, 0,
|
||||
cancellable, error))
|
||||
if (!hardlink_or_copy_at (tree_boot_dfd, tree_initramfs_name,
|
||||
bootcsum_dfd, dest_initramfs_name,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ typedef enum {
|
|||
|
||||
} OstreeSysrootDebugFlags;
|
||||
|
||||
/**
|
||||
* OstreeSysroot:
|
||||
* Internal struct
|
||||
*/
|
||||
struct OstreeSysroot {
|
||||
GObject parent;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include "ostree-sysroot-upgrader.h"
|
||||
|
||||
/**
|
||||
* SECTION:libostree-sysroot-upgrader
|
||||
* SECTION:ostree-sysroot-upgrader
|
||||
* @title: Simple upgrade class
|
||||
* @short_description: Upgrade OSTree systems
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ find_booted_deployment (OstreeSysroot *self,
|
|||
GError **error);
|
||||
|
||||
/**
|
||||
* SECTION:libostree-sysroot
|
||||
* SECTION:ostree-sysroot
|
||||
* @title: Root partition mount point
|
||||
* @short_description: Manage physical root filesystem
|
||||
*
|
||||
|
|
@ -70,10 +70,12 @@ ostree_sysroot_finalize (GObject *object)
|
|||
g_clear_object (&self->path);
|
||||
g_clear_object (&self->sepolicy);
|
||||
g_clear_object (&self->repo);
|
||||
g_clear_pointer (&self->deployments, g_ptr_array_unref);
|
||||
g_clear_object (&self->booted_deployment);
|
||||
|
||||
glnx_release_lock_file (&self->lock);
|
||||
|
||||
(void) ostree_sysroot_unload (self);
|
||||
ostree_sysroot_unload (self);
|
||||
|
||||
G_OBJECT_CLASS (ostree_sysroot_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -276,28 +278,34 @@ ostree_sysroot_ensure_initialized (OstreeSysroot *self,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFile) dir = NULL;
|
||||
g_autoptr(GFile) ostree_dir = NULL;
|
||||
g_autoptr(GFile) repo_dir = NULL;
|
||||
struct stat stbuf;
|
||||
|
||||
ostree_dir = g_file_get_child (self->path, "ostree");
|
||||
repo_dir = g_file_get_child (ostree_dir, "repo");
|
||||
if (!gs_file_ensure_directory (repo_dir, TRUE, cancellable, error))
|
||||
if (!ensure_sysroot_fd (self, error))
|
||||
goto out;
|
||||
|
||||
g_clear_object (&dir);
|
||||
dir = g_file_get_child (ostree_dir, "deploy");
|
||||
if (!gs_file_ensure_directory (dir, TRUE, cancellable, error))
|
||||
goto out;
|
||||
|
||||
g_clear_object (&dir);
|
||||
dir = ot_gfile_get_child_build_path (ostree_dir, "repo", "objects", NULL);
|
||||
if (!g_file_query_exists (dir, NULL))
|
||||
{
|
||||
glnx_unref_object OstreeRepo *repo = ostree_repo_new (repo_dir);
|
||||
if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE,
|
||||
if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, "ostree/repo", 0755,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
goto out;
|
||||
|
||||
if (!glnx_shutil_mkdir_p_at (self->sysroot_fd, "ostree/deploy", 0755,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (fstatat (self->sysroot_fd, "ostree/repo/objects", &stbuf, 0) != 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "stat %s", "ostree/repo/objects");
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr(GFile) repo_dir = g_file_resolve_relative_path (self->path, "ostree/repo");
|
||||
glnx_unref_object OstreeRepo *repo = ostree_repo_new (repo_dir);
|
||||
if (!ostree_repo_create (repo, OSTREE_REPO_MODE_BARE,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
|
@ -873,7 +881,7 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
|
|||
}
|
||||
|
||||
g_clear_pointer (&self->deployments, g_ptr_array_unref);
|
||||
g_clear_pointer (&self->booted_deployment, g_object_unref);
|
||||
g_clear_object (&self->booted_deployment);
|
||||
self->bootversion = -1;
|
||||
self->subbootversion = -1;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,3 +31,5 @@
|
|||
#include <ostree-bootconfig-parser.h>
|
||||
#include <ostree-diff.h>
|
||||
#include <ostree-gpg-verify-result.h>
|
||||
|
||||
#include <ostree-autocleanups.h>
|
||||
|
|
|
|||
|
|
@ -230,3 +230,24 @@ ot_openat_ignore_enoent (int dfd,
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
GBytes *
|
||||
ot_file_mapat_bytes (int dfd,
|
||||
const char *path,
|
||||
GError **error)
|
||||
{
|
||||
glnx_fd_close int fd = openat (dfd, path, O_RDONLY | O_CLOEXEC);
|
||||
g_autoptr(GMappedFile) mfile = NULL;
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mfile = g_mapped_file_new_from_fd (fd, FALSE, error);
|
||||
if (!mfile)
|
||||
return FALSE;
|
||||
|
||||
return g_mapped_file_get_bytes (mfile);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,4 +66,8 @@ gboolean ot_openat_ignore_enoent (int dfd,
|
|||
int *out_fd,
|
||||
GError **error);
|
||||
|
||||
GBytes *ot_file_mapat_bytes (int dfd,
|
||||
const char *path,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -254,7 +254,8 @@ ot_gfile_load_contents_utf8_allow_noent (GFile *path,
|
|||
GError *temp_error = NULL;
|
||||
g_autofree char *ret_contents = NULL;
|
||||
|
||||
ret_contents = gs_file_load_contents_utf8 (path, cancellable, &temp_error);
|
||||
ret_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (path), NULL,
|
||||
cancellable, &temp_error);
|
||||
if (!ret_contents)
|
||||
{
|
||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
|
|
@ -356,8 +357,8 @@ ot_gfile_replace_contents_fsync (GFile *path,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int parent_dfd;
|
||||
const char *target_basename = gs_file_get_basename_cached (path);
|
||||
glnx_fd_close int parent_dfd = -1;
|
||||
const char *target_basename = glnx_basename (gs_file_get_path_cached (path));
|
||||
g_autoptr(GFile) parent = NULL;
|
||||
|
||||
parent = g_file_get_parent (path);
|
||||
|
|
@ -373,8 +374,6 @@ ot_gfile_replace_contents_fsync (GFile *path,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (parent_dfd != -1)
|
||||
(void) close (parent_dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -389,25 +388,12 @@ ot_gfile_ensure_unlinked (GFile *path,
|
|||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GError *temp_error = NULL;
|
||||
|
||||
if (!gs_file_unlink (path, cancellable, &temp_error))
|
||||
if (unlink (gs_file_get_path_cached (path)) != 0)
|
||||
{
|
||||
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
|
||||
{
|
||||
g_clear_error (&temp_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_propagate_error (error, temp_error);
|
||||
goto out;
|
||||
}
|
||||
if (errno != ENOENT)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -424,7 +410,7 @@ ot_util_fsync_directory (GFile *dir,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int dfd = -1;
|
||||
glnx_fd_close int dfd = -1;
|
||||
|
||||
if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (dir), TRUE,
|
||||
&dfd, error))
|
||||
|
|
@ -438,8 +424,6 @@ ot_util_fsync_directory (GFile *dir,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (dfd != -1)
|
||||
(void) close (dfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -458,8 +442,8 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int parentfd = -1;
|
||||
const char *basename = gs_file_get_basename_cached (dir);
|
||||
glnx_fd_close int parentfd = -1;
|
||||
const char *basename = glnx_basename (gs_file_get_path_cached (dir));
|
||||
g_autoptr(GFile) parent = g_file_get_parent (dir);
|
||||
|
||||
again:
|
||||
|
|
@ -507,7 +491,5 @@ ot_util_ensure_directory_and_fsync (GFile *dir,
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (parentfd != -1)
|
||||
(void) close (parentfd);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,10 @@
|
|||
GVariant *
|
||||
ot_gvariant_new_empty_string_dict (void)
|
||||
{
|
||||
return g_variant_builder_end (g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")));
|
||||
g_auto(GVariantBuilder) builder = {{0,}};
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
return g_variant_builder_end (&builder);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
|
|
@ -114,63 +117,31 @@ ot_util_variant_take_ref (GVariant *variant)
|
|||
return g_variant_take_ref (variant);
|
||||
}
|
||||
|
||||
/**
|
||||
* ot_util_variant_map:
|
||||
* @src: a #GFile
|
||||
* @type: Use this for variant
|
||||
* @trusted: See documentation of g_variant_new_from_data()
|
||||
* @out_variant: (out): Return location for new variant
|
||||
* @error:
|
||||
*
|
||||
* Memory-map @src, and store a new #GVariant referring to this memory
|
||||
* in @out_variant. Note the returned @out_variant is not floating.
|
||||
*/
|
||||
gboolean
|
||||
ot_util_variant_map (GFile *src,
|
||||
const GVariantType *type,
|
||||
gboolean trusted,
|
||||
GVariant **out_variant,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GVariant) ret_variant = NULL;
|
||||
GMappedFile *mfile = NULL;
|
||||
|
||||
mfile = gs_file_map_noatime (src, NULL, error);
|
||||
if (!mfile)
|
||||
goto out;
|
||||
|
||||
ret_variant = g_variant_new_from_data (type,
|
||||
g_mapped_file_get_contents (mfile),
|
||||
g_mapped_file_get_length (mfile),
|
||||
trusted,
|
||||
(GDestroyNotify) g_mapped_file_unref,
|
||||
mfile);
|
||||
g_variant_ref_sink (ret_variant);
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value(out_variant, &ret_variant);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_util_variant_map_at (int dfd,
|
||||
const char *path,
|
||||
const GVariantType *type,
|
||||
gboolean trusted,
|
||||
OtVariantMapFlags flags,
|
||||
GVariant **out_variant,
|
||||
GError **error)
|
||||
{
|
||||
glnx_fd_close int fd = -1;
|
||||
g_autoptr(GVariant) ret_variant = NULL;
|
||||
const gboolean trusted = (flags & OT_VARIANT_MAP_TRUSTED) > 0;
|
||||
|
||||
fd = openat (dfd, path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
g_prefix_error (error, "Opening %s: ", path);
|
||||
return FALSE;
|
||||
if (errno == ENOENT && (flags & OT_VARIANT_MAP_ALLOW_NOENT) > 0)
|
||||
{
|
||||
*out_variant = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
glnx_set_error_from_errno (error);
|
||||
g_prefix_error (error, "Opening %s: ", path);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return ot_util_variant_map_fd (fd, 0, type, trusted, out_variant, error);
|
||||
|
|
@ -186,6 +157,7 @@ variant_map_data_destroy (gpointer data)
|
|||
{
|
||||
VariantMapData *mdata = data;
|
||||
(void) munmap (mdata->addr, mdata->len);
|
||||
g_free (mdata);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -221,8 +193,8 @@ ot_util_variant_map_fd (int fd,
|
|||
mdata->len = len;
|
||||
|
||||
ret = TRUE;
|
||||
*out_variant = g_variant_new_from_data (type, map, len, trusted,
|
||||
variant_map_data_destroy, mdata);
|
||||
*out_variant = g_variant_ref_sink (g_variant_new_from_data (type, map, len, trusted,
|
||||
variant_map_data_destroy, mdata));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,16 +42,15 @@ gboolean ot_util_variant_save (GFile *dest,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean ot_util_variant_map (GFile *src,
|
||||
const GVariantType *type,
|
||||
gboolean trusted,
|
||||
GVariant **out_variant,
|
||||
GError **error);
|
||||
typedef enum {
|
||||
OT_VARIANT_MAP_TRUSTED = (1 << 0),
|
||||
OT_VARIANT_MAP_ALLOW_NOENT = (1 << 1)
|
||||
} OtVariantMapFlags;
|
||||
|
||||
gboolean ot_util_variant_map_at (int dfd,
|
||||
const char *path,
|
||||
const GVariantType *type,
|
||||
gboolean trusted,
|
||||
OtVariantMapFlags flags,
|
||||
GVariant **out_variant,
|
||||
GError **error);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ ot_admin_builtin_init_fs (int argc, char **argv, GCancellable *cancellable, GErr
|
|||
GOptionContext *context;
|
||||
glnx_unref_object OstreeSysroot *sysroot = NULL;
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFile) dir = NULL;
|
||||
g_autoptr(GFile) child = NULL;
|
||||
glnx_fd_close int root_dfd = -1;
|
||||
glnx_unref_object OstreeSysroot *target_sysroot = NULL;
|
||||
guint i;
|
||||
const char *normal_toplevels[] = {"boot", "dev", "home", "proc", "run", "sys"};
|
||||
|
|
@ -58,36 +57,31 @@ ot_admin_builtin_init_fs (int argc, char **argv, GCancellable *cancellable, GErr
|
|||
goto out;
|
||||
}
|
||||
|
||||
dir = g_file_new_for_path (argv[1]);
|
||||
target_sysroot = ostree_sysroot_new (dir);
|
||||
if (!glnx_opendirat (AT_FDCWD, argv[1], TRUE, &root_dfd, error))
|
||||
goto out;
|
||||
{ g_autoptr(GFile) dir = g_file_new_for_path (argv[1]);
|
||||
target_sysroot = ostree_sysroot_new (dir);
|
||||
}
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(normal_toplevels); i++)
|
||||
{
|
||||
child = g_file_get_child (dir, normal_toplevels[i]);
|
||||
if (!gs_file_ensure_directory_mode (child, 0755, cancellable, error))
|
||||
if (!glnx_shutil_mkdir_p_at (root_dfd, normal_toplevels[i], 0755,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
g_clear_object (&child);
|
||||
}
|
||||
|
||||
child = g_file_get_child (dir, "root");
|
||||
if (!gs_file_ensure_directory_mode (child, 0700, cancellable, error))
|
||||
|
||||
if (!glnx_shutil_mkdir_p_at (root_dfd, "root", 0700,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
g_clear_object (&child);
|
||||
|
||||
child = g_file_get_child (dir, "tmp");
|
||||
if (!gs_file_ensure_directory_mode (child, 01777, cancellable, error))
|
||||
if (!glnx_shutil_mkdir_p_at (root_dfd, "tmp", 01777,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
/* FIXME - we should be using an API that explicitly ignores umask;
|
||||
*/
|
||||
{
|
||||
const char *path = gs_file_get_path_cached (child);
|
||||
if (chmod (path, 01777) == -1)
|
||||
{
|
||||
gs_set_prefix_error_from_errno (error, errno, "chmod");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
g_clear_object (&child);
|
||||
if (fchmodat (root_dfd, "tmp", 01777, 0) == -1)
|
||||
{
|
||||
glnx_set_prefix_error_from_errno (error, "chmod: %s", "tmp");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_sysroot_ensure_initialized (target_sysroot, cancellable, error))
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,11 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "ot-main.h"
|
||||
#include "ot-builtins.h"
|
||||
#include "ot-admin-instutil-builtins.h"
|
||||
#include "ot-admin-builtins.h"
|
||||
#include "ot-admin-functions.h"
|
||||
#include "ot-main.h"
|
||||
#include "ostree.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
|
|
|||
|
|
@ -61,8 +61,6 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
|
|||
glnx_unref_object OstreeSysrootUpgrader *upgrader = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
gboolean changed;
|
||||
GSConsole *console = NULL;
|
||||
gboolean in_status_line = FALSE;
|
||||
GKeyFile *old_origin;
|
||||
GKeyFile *new_origin = NULL;
|
||||
|
||||
|
|
@ -125,28 +123,24 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
|
|||
if (!ostree_sysroot_upgrader_set_origin (upgrader, new_origin, cancellable, error))
|
||||
goto out;
|
||||
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
in_status_line = TRUE;
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
}
|
||||
{ g_auto(GLnxConsoleRef) console = { 0, };
|
||||
glnx_console_lock (&console);
|
||||
|
||||
/* Always allow older...there's not going to be a chronological
|
||||
* relationship necessarily.
|
||||
*/
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
|
||||
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
if (console.is_tty)
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
|
||||
|
||||
if (in_status_line)
|
||||
{
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
in_status_line = FALSE;
|
||||
}
|
||||
/* Always allow older...there's not going to be a chronological
|
||||
* relationship necessarily.
|
||||
*/
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0,
|
||||
OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
}
|
||||
|
||||
if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error))
|
||||
goto out;
|
||||
|
|
@ -171,8 +165,6 @@ ot_admin_builtin_switch (int argc, char **argv, GCancellable *cancellable, GErro
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (in_status_line)
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
if (new_origin)
|
||||
g_key_file_unref (new_origin);
|
||||
if (context)
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
|
|||
g_autoptr(GFile) deployment_path = NULL;
|
||||
g_autoptr(GFile) deployment_origin_path = NULL;
|
||||
g_autoptr(GKeyFile) origin = NULL;
|
||||
GSConsole *console = NULL;
|
||||
gboolean in_status_line = FALSE;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
gboolean changed;
|
||||
OstreeSysrootUpgraderPullFlags upgraderpullflags = 0;
|
||||
|
|
@ -108,27 +106,23 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
|
|||
}
|
||||
}
|
||||
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
in_status_line = TRUE;
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
}
|
||||
{ g_auto(GLnxConsoleRef) console = { 0, };
|
||||
glnx_console_lock (&console);
|
||||
|
||||
if (opt_allow_downgrade)
|
||||
upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
|
||||
if (console.is_tty)
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
|
||||
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
if (opt_allow_downgrade)
|
||||
upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER;
|
||||
|
||||
if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags,
|
||||
progress, &changed,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (in_status_line)
|
||||
{
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
in_status_line = FALSE;
|
||||
}
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
}
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
|
|
@ -148,8 +142,6 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr
|
|||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (in_status_line)
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ot-admin-functions.h"
|
||||
#include "otutil.h"
|
||||
#include "ostree.h"
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ relabel_recursively (OstreeSePolicy *sepolicy,
|
|||
if (file_info == NULL)
|
||||
break;
|
||||
|
||||
g_ptr_array_add (path_parts, (char*)gs_file_get_basename_cached (child));
|
||||
g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info));
|
||||
|
||||
ftype = g_file_info_get_file_type (file_info);
|
||||
if (ftype == G_FILE_TYPE_DIRECTORY)
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "ot-main.h"
|
||||
#include "ot-builtins.h"
|
||||
#include "ot-admin-builtins.h"
|
||||
#include "ot-admin-functions.h"
|
||||
#include "ot-main.h"
|
||||
#include "ostree.h"
|
||||
#include "ostree-repo-file.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,12 @@
|
|||
|
||||
static char *opt_subject;
|
||||
static char *opt_body;
|
||||
static gboolean opt_editor;
|
||||
static char *opt_parent;
|
||||
static gboolean opt_orphan;
|
||||
static char *opt_branch;
|
||||
static char *opt_statoverride_file;
|
||||
static char *opt_skiplist_file;
|
||||
static char **opt_metadata_strings;
|
||||
static char **opt_detached_metadata_strings;
|
||||
static gboolean opt_link_checkout_speedup;
|
||||
|
|
@ -72,6 +74,7 @@ static GOptionEntry options[] = {
|
|||
{ "parent", 0, 0, G_OPTION_ARG_STRING, &opt_parent, "Parent ref, or \"none\"", "REF" },
|
||||
{ "subject", 's', 0, G_OPTION_ARG_STRING, &opt_subject, "One line subject", "SUBJECT" },
|
||||
{ "body", 'm', 0, G_OPTION_ARG_STRING, &opt_body, "Full description", "BODY" },
|
||||
{ "editor", 'e', 0, G_OPTION_ARG_NONE, &opt_editor, "Use an editor to write the commit message", NULL },
|
||||
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &opt_branch, "Branch", "BRANCH" },
|
||||
{ "orphan", 0, 0, G_OPTION_ARG_NONE, &opt_orphan, "Create a commit without writing a ref", NULL },
|
||||
{ "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_trees, "Overlay the given argument as a tree", "dir=PATH or tar=TARFILE or ref=COMMIT" },
|
||||
|
|
@ -84,6 +87,7 @@ static GOptionEntry options[] = {
|
|||
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
|
||||
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &opt_skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
|
||||
{ "statoverride", 0, 0, G_OPTION_ARG_FILENAME, &opt_statoverride_file, "File containing list of modifications to make to permissions", "PATH" },
|
||||
{ "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" },
|
||||
{ "table-output", 0, 0, G_OPTION_ARG_NONE, &opt_table_output, "Output more information in a KEY: VALUE format", NULL },
|
||||
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
|
||||
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
|
||||
|
|
@ -95,65 +99,85 @@ static GOptionEntry options[] = {
|
|||
};
|
||||
|
||||
static gboolean
|
||||
parse_statoverride_file (GHashTable **out_mode_add,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
parse_file_by_line (const char *path,
|
||||
gboolean (*cb)(const char*, void*, GError**),
|
||||
void *cbdata,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gsize len;
|
||||
char **iter = NULL; /* nofree */
|
||||
g_autoptr(GHashTable) ret_hash = NULL;
|
||||
g_autoptr(GFile) path = NULL;
|
||||
g_autofree char *contents = NULL;
|
||||
g_autoptr(GFile) file = NULL;
|
||||
char **lines = NULL;
|
||||
|
||||
path = g_file_new_for_path (opt_statoverride_file);
|
||||
|
||||
if (!g_file_load_contents (path, cancellable, &contents, &len, NULL,
|
||||
error))
|
||||
file = g_file_new_for_path (path);
|
||||
if (!g_file_load_contents (file, cancellable, &contents, NULL, NULL, error))
|
||||
goto out;
|
||||
|
||||
ret_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
lines = g_strsplit (contents, "\n", -1);
|
||||
|
||||
for (iter = lines; iter && *iter; iter++)
|
||||
for (char **iter = lines; iter && *iter; iter++)
|
||||
{
|
||||
const char *line = *iter;
|
||||
/* skip empty lines at least */
|
||||
if (**iter == '\0')
|
||||
continue;
|
||||
|
||||
if (*line == '+')
|
||||
{
|
||||
const char *spc;
|
||||
guint mode_add;
|
||||
|
||||
spc = strchr (line + 1, ' ');
|
||||
if (!spc)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Malformed statoverride file");
|
||||
goto out;
|
||||
}
|
||||
|
||||
mode_add = (guint32)(gint32)g_ascii_strtod (line + 1, NULL);
|
||||
g_hash_table_insert (ret_hash,
|
||||
g_strdup (spc + 1),
|
||||
GUINT_TO_POINTER((gint32)mode_add));
|
||||
}
|
||||
if (!cb (*iter, cbdata, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_mode_add, &ret_hash);
|
||||
out:
|
||||
out:
|
||||
g_strfreev (lines);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_statoverride_line (const char *line,
|
||||
void *data,
|
||||
GError **error)
|
||||
{
|
||||
GHashTable *files = data;
|
||||
const char *spc;
|
||||
guint mode_add;
|
||||
|
||||
spc = strchr (line, ' ');
|
||||
if (spc == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Malformed statoverride file (no space found)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mode_add = (guint32)(gint32)g_ascii_strtod (line, NULL);
|
||||
g_hash_table_insert (files, g_strdup (spc + 1),
|
||||
GUINT_TO_POINTER((gint32)mode_add));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_skiplist_line (const char *line,
|
||||
void *data,
|
||||
GError **error)
|
||||
{
|
||||
GHashTable *files = data;
|
||||
g_hash_table_add (files, g_strdup (line));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct CommitFilterData {
|
||||
GHashTable *mode_adds;
|
||||
GHashTable *skip_list;
|
||||
};
|
||||
|
||||
static OstreeRepoCommitFilterResult
|
||||
commit_filter (OstreeRepo *self,
|
||||
const char *path,
|
||||
GFileInfo *file_info,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *mode_adds = user_data;
|
||||
struct CommitFilterData *data = user_data;
|
||||
GHashTable *mode_adds = data->mode_adds;
|
||||
GHashTable *skip_list = data->skip_list;
|
||||
gpointer value;
|
||||
|
||||
if (opt_owner_uid >= 0)
|
||||
|
|
@ -169,7 +193,13 @@ commit_filter (OstreeRepo *self,
|
|||
current_mode | mode_add);
|
||||
g_hash_table_remove (mode_adds, path);
|
||||
}
|
||||
|
||||
|
||||
if (skip_list && g_hash_table_contains (skip_list, path))
|
||||
{
|
||||
g_hash_table_remove (skip_list, path);
|
||||
return OSTREE_REPO_COMMIT_FILTER_SKIP;
|
||||
}
|
||||
|
||||
return OSTREE_REPO_COMMIT_FILTER_ALLOW;
|
||||
}
|
||||
|
||||
|
|
@ -188,14 +218,18 @@ commit_editor (OstreeRepo *repo,
|
|||
char **lines = NULL;
|
||||
int i;
|
||||
|
||||
*subject = NULL;
|
||||
*body = NULL;
|
||||
|
||||
input = g_strdup_printf ("\n"
|
||||
"# Please enter the commit message for your changes. The first line will\n"
|
||||
"# become the subject, and the remainder the body. Lines starting\n"
|
||||
"# with '#' will be ignored, and an empty message aborts the commit."
|
||||
"%s%s\n", branch ? "\n#\n# Branch: " : "", branch ?: "");
|
||||
"%s%s%s%s%s%s\n"
|
||||
, branch ? "\n#\n# Branch: " : "", branch ? branch : ""
|
||||
, *subject ? "\n" : "", *subject ? *subject : ""
|
||||
, *body ? "\n" : "", *body ? *body : ""
|
||||
);
|
||||
|
||||
*subject = NULL;
|
||||
*body = NULL;
|
||||
|
||||
output = ot_editor_prompt (repo, input, cancellable, error);
|
||||
if (output == NULL)
|
||||
|
|
@ -310,9 +344,11 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|
|||
glnx_unref_object OstreeMutableTree *mtree = NULL;
|
||||
g_autofree char *tree_type = NULL;
|
||||
g_autoptr(GHashTable) mode_adds = NULL;
|
||||
g_autoptr(GHashTable) skip_list = NULL;
|
||||
OstreeRepoCommitModifierFlags flags = 0;
|
||||
OstreeRepoCommitModifier *modifier = NULL;
|
||||
OstreeRepoTransactionStats stats;
|
||||
struct CommitFilterData filter_data = { 0, };
|
||||
|
||||
context = g_option_context_new ("[PATH] - Commit a new revision");
|
||||
|
||||
|
|
@ -324,7 +360,17 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|
|||
|
||||
if (opt_statoverride_file)
|
||||
{
|
||||
if (!parse_statoverride_file (&mode_adds, cancellable, error))
|
||||
mode_adds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
if (!parse_file_by_line (opt_statoverride_file, handle_statoverride_line,
|
||||
mode_adds, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opt_skiplist_file)
|
||||
{
|
||||
skip_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
if (!parse_file_by_line (opt_skiplist_file, handle_skiplist_line,
|
||||
skip_list, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -359,9 +405,13 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|
|||
|| opt_owner_uid >= 0
|
||||
|| opt_owner_gid >= 0
|
||||
|| opt_statoverride_file != NULL
|
||||
|| opt_skiplist_file != NULL
|
||||
|| opt_no_xattrs)
|
||||
{
|
||||
modifier = ostree_repo_commit_modifier_new (flags, commit_filter, mode_adds, NULL);
|
||||
filter_data.mode_adds = mode_adds;
|
||||
filter_data.skip_list = skip_list;
|
||||
modifier = ostree_repo_commit_modifier_new (flags, commit_filter,
|
||||
&filter_data, NULL);
|
||||
}
|
||||
|
||||
if (opt_parent)
|
||||
|
|
@ -381,19 +431,12 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!opt_subject && !opt_body)
|
||||
if (opt_editor)
|
||||
{
|
||||
if (!commit_editor (repo, opt_branch, &opt_subject, &opt_body, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!opt_subject)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"A subject must be specified with --subject");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
@ -491,6 +534,22 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (skip_list && g_hash_table_size (skip_list) > 0)
|
||||
{
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key;
|
||||
|
||||
g_hash_table_iter_init (&hash_iter, skip_list);
|
||||
|
||||
while (g_hash_table_iter_next (&hash_iter, &key, NULL))
|
||||
{
|
||||
g_printerr ("Unmatched skip-list path: %s\n", (char*)key);
|
||||
}
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unmatched skip-list paths");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_write_mtree (repo, mtree, &root, cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,14 @@
|
|||
#endif
|
||||
|
||||
static char *opt_output_path;
|
||||
static char *opt_subpath;
|
||||
static char *opt_prefix;
|
||||
static gboolean opt_no_xattrs;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Skip output of extended attributes", NULL },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_STRING, &opt_subpath, "Checkout sub-directory PATH", "PATH" },
|
||||
{ "prefix", 0, 0, G_OPTION_ARG_STRING, &opt_prefix, "Add PATH as prefix to archive pathnames", "PATH" },
|
||||
{ "output", 'o', 0, G_OPTION_ARG_STRING, &opt_output_path, "Output to PATH ", "PATH" },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
@ -60,6 +64,7 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
|
|||
gboolean ret = FALSE;
|
||||
const char *rev;
|
||||
g_autoptr(GFile) root = NULL;
|
||||
g_autoptr(GFile) subtree = NULL;
|
||||
g_autofree char *commit = NULL;
|
||||
g_autoptr(GVariant) commit_data = NULL;
|
||||
struct archive *a;
|
||||
|
|
@ -124,7 +129,14 @@ ostree_builtin_export (int argc, char **argv, GCancellable *cancellable, GError
|
|||
|
||||
opts.timestamp_secs = ostree_commit_get_timestamp (commit_data);
|
||||
|
||||
if (!ostree_repo_export_tree_to_archive (repo, &opts, (OstreeRepoFile*)root, a,
|
||||
if (opt_subpath)
|
||||
subtree = g_file_resolve_relative_path (root, opt_subpath);
|
||||
else
|
||||
subtree = g_object_ref (root);
|
||||
|
||||
opts.path_prefix = opt_prefix;
|
||||
|
||||
if (!ostree_repo_export_tree_to_archive (repo, &opts, (OstreeRepoFile*)subtree, a,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ gboolean
|
|||
ostree_builtin_init (int argc, char **argv, GCancellable *cancellable, GError **error)
|
||||
{
|
||||
GOptionContext *context = NULL;
|
||||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
g_autoptr(OstreeRepo) repo = NULL;
|
||||
gboolean ret = FALSE;
|
||||
OstreeRepoMode mode;
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
|
|||
glnx_unref_object OstreeRepo *repo = NULL;
|
||||
int i;
|
||||
const char *src_repo_arg;
|
||||
GSConsole *console = NULL;
|
||||
g_autofree char *src_repo_uri = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
g_autoptr(GPtrArray) refs_to_fetch = NULL;
|
||||
|
|
@ -132,14 +131,11 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
|
|||
g_ptr_array_add (refs_to_fetch, NULL);
|
||||
}
|
||||
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
}
|
||||
|
||||
{ GVariantBuilder builder;
|
||||
g_auto(GLnxConsoleRef) console = { 0, };
|
||||
|
||||
glnx_console_lock (&console);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
|
||||
g_variant_builder_add (&builder, "{s@v}", "flags",
|
||||
|
|
@ -158,17 +154,21 @@ ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GEr
|
|||
g_variant_builder_add (&builder, "{s@v}", "depth",
|
||||
g_variant_new_variant (g_variant_new_int32 (opt_depth)));
|
||||
|
||||
if (console.is_tty)
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
|
||||
|
||||
if (!ostree_repo_pull_with_options (repo, src_repo_uri,
|
||||
g_variant_builder_end (&builder),
|
||||
progress,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
if (repo)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ static gboolean opt_untrusted;
|
|||
static char* opt_subpath;
|
||||
static char* opt_cache_dir;
|
||||
static int opt_depth = 0;
|
||||
|
||||
static char* opt_url;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "commit-metadata-only", 0, 0, G_OPTION_ARG_NONE, &opt_commit_only, "Fetch only the commit metadata", NULL },
|
||||
{ "cache-dir", 0, 0, G_OPTION_ARG_STRING, &opt_cache_dir, "Use custom cache dir", NULL },
|
||||
|
|
@ -49,6 +50,7 @@ static GOptionEntry options[] = {
|
|||
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust (local) sources", NULL },
|
||||
{ "dry-run", 0, 0, G_OPTION_ARG_NONE, &opt_dry_run, "Only print information on what will be downloaded (requires static deltas)", NULL },
|
||||
{ "depth", 0, 0, G_OPTION_ARG_INT, &opt_depth, "Traverse DEPTH parents (-1=infinite) (default: 0)", "DEPTH" },
|
||||
{ "url", 0, 0, G_OPTION_ARG_STRING, &opt_url, "Pull objects from this URL instead of the one from the remote config", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
|
@ -56,16 +58,17 @@ static void
|
|||
gpg_verify_result_cb (OstreeRepo *repo,
|
||||
const char *checksum,
|
||||
OstreeGpgVerifyResult *result,
|
||||
GSConsole *console)
|
||||
GLnxConsoleRef *console)
|
||||
{
|
||||
/* Temporarily place the GSConsole stream (which is just stdout)
|
||||
* back in normal mode before printing GPG verification results. */
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
/* Temporarily place the tty back in normal mode before printing GPG
|
||||
* verification results.
|
||||
*/
|
||||
glnx_console_unlock (console);
|
||||
|
||||
g_print ("\n");
|
||||
ostree_print_gpg_verify_result (result);
|
||||
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
glnx_console_lock (console);
|
||||
}
|
||||
|
||||
static gboolean printed_console_progress;
|
||||
|
|
@ -109,7 +112,6 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
|
|||
gboolean ret = FALSE;
|
||||
g_autofree char *remote = NULL;
|
||||
OstreeRepoPullFlags pullflags = 0;
|
||||
GSConsole *console = NULL;
|
||||
g_autoptr(GPtrArray) refs_to_fetch = NULL;
|
||||
g_autoptr(GPtrArray) override_commit_ids = NULL;
|
||||
glnx_unref_object OstreeAsyncProgress *progress = NULL;
|
||||
|
|
@ -204,30 +206,16 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
|
|||
g_ptr_array_add (refs_to_fetch, NULL);
|
||||
}
|
||||
|
||||
if (!opt_dry_run)
|
||||
{
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
|
||||
G_CALLBACK (gpg_verify_result_cb),
|
||||
console);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = ostree_async_progress_new_and_connect (dry_run_console_progress_changed, console);
|
||||
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
|
||||
G_CALLBACK (gpg_verify_result_cb),
|
||||
console);
|
||||
}
|
||||
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
g_auto(GLnxConsoleRef) console = { 0, };
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
|
||||
glnx_console_lock (&console);
|
||||
|
||||
if (opt_url)
|
||||
g_variant_builder_add (&builder, "{s@v}", "override-url",
|
||||
g_variant_new_variant (g_variant_new_string (opt_url)));
|
||||
if (opt_subpath)
|
||||
g_variant_builder_add (&builder, "{s@v}", "subdir",
|
||||
g_variant_new_variant (g_variant_new_string (opt_subpath)));
|
||||
|
|
@ -252,25 +240,38 @@ ostree_builtin_pull (int argc, char **argv, GCancellable *cancellable, GError **
|
|||
g_variant_builder_add (&builder, "{s@v}", "override-commit-ids",
|
||||
g_variant_new_variant (g_variant_new_strv ((const char*const*)override_commit_ids->pdata, override_commit_ids->len)));
|
||||
|
||||
if (!opt_dry_run)
|
||||
{
|
||||
if (console.is_tty)
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = ostree_async_progress_new_and_connect (dry_run_console_progress_changed, NULL);
|
||||
}
|
||||
|
||||
if (console.is_tty)
|
||||
{
|
||||
signal_handler_id = g_signal_connect (repo, "gpg-verify-result",
|
||||
G_CALLBACK (gpg_verify_result_cb),
|
||||
&console);
|
||||
}
|
||||
|
||||
if (!ostree_repo_pull_with_options (repo, remote, g_variant_builder_end (&builder),
|
||||
progress, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
|
||||
if (opt_dry_run)
|
||||
g_assert (printed_console_progress);
|
||||
}
|
||||
|
||||
if (progress)
|
||||
ostree_async_progress_finish (progress);
|
||||
|
||||
if (opt_dry_run)
|
||||
g_assert (printed_console_progress);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
if (signal_handler_id > 0)
|
||||
g_signal_handler_disconnect (repo, signal_handler_id);
|
||||
|
||||
if (console)
|
||||
gs_console_end_status_line (console, NULL, NULL);
|
||||
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -28,10 +28,12 @@
|
|||
|
||||
static gboolean opt_delete;
|
||||
static gboolean opt_list;
|
||||
static char *opt_create;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "delete", 0, 0, G_OPTION_ARG_NONE, &opt_delete, "Delete refs which match PREFIX, rather than listing them", NULL },
|
||||
{ "list", 0, 0, G_OPTION_ARG_NONE, &opt_list, "Do not remove the prefix from the refs", NULL },
|
||||
{ "create", 0, 0, G_OPTION_ARG_STRING, &opt_create, "Create a new ref for an existing commit", "NEWREF" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
|
@ -48,10 +50,16 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
|
|||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else if (opt_create)
|
||||
{
|
||||
if (!ostree_repo_list_refs_ext (repo, NULL, &refs, OSTREE_REPO_LIST_REFS_EXT_NONE,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else if (!ostree_repo_list_refs (repo, refspec_prefix, &refs, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!opt_delete)
|
||||
if (!opt_delete && !opt_create)
|
||||
{
|
||||
g_hash_table_iter_init (&hashiter, refs);
|
||||
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
|
||||
|
|
@ -60,7 +68,30 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab
|
|||
g_print ("%s\n", ref);
|
||||
}
|
||||
}
|
||||
else if (opt_create)
|
||||
{
|
||||
g_autofree char *checksum = NULL;
|
||||
g_autofree char *checksum_existing = NULL;
|
||||
|
||||
if (!ostree_repo_resolve_rev (repo, opt_create, TRUE, &checksum_existing, error))
|
||||
goto out;
|
||||
|
||||
if (checksum_existing != NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"--create specified but ref %s already exists", opt_create);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ostree_repo_resolve_rev (repo, refspec_prefix, FALSE, &checksum, error))
|
||||
goto out;
|
||||
|
||||
if (!ostree_repo_set_ref_immediate (repo, NULL, opt_create, checksum,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
/* delete */
|
||||
{
|
||||
g_hash_table_iter_init (&hashiter, refs);
|
||||
while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))
|
||||
|
|
@ -97,6 +128,12 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
|
|||
|
||||
if (argc >= 2)
|
||||
{
|
||||
if (opt_create && argc > 2)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"You must specify only 1 existing ref when creating a new ref");
|
||||
goto out;
|
||||
}
|
||||
for (i = 1; i < argc; i++)
|
||||
if (!do_ref (repo, argv[i], cancellable, error))
|
||||
goto out;
|
||||
|
|
@ -110,6 +147,13 @@ ostree_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **
|
|||
"At least one PREFIX is required when deleting refs");
|
||||
goto out;
|
||||
}
|
||||
else if (opt_create)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"You must specify an existing ref when creating a new ref");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = do_ref (repo, NULL, cancellable, error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,9 @@ do_print_variant_generic (const GVariantType *type,
|
|||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GFile) f = NULL;
|
||||
g_autoptr(GVariant) variant = NULL;
|
||||
|
||||
f = g_file_new_for_path (filename);
|
||||
|
||||
if (!ot_util_variant_map (f, type, TRUE, &variant, error))
|
||||
if (!ot_util_variant_map_at (AT_FDCWD, filename, type, TRUE, &variant, error))
|
||||
goto out;
|
||||
|
||||
ot_dump_variant (variant);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ static char *opt_gpg_homedir;
|
|||
|
||||
static GOptionEntry options[] = {
|
||||
{ "update", 'u', 0, G_OPTION_ARG_NONE, &opt_update, "Update the summary", NULL },
|
||||
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"},
|
||||
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the summary with", "KEY-ID"},
|
||||
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"},
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include <libsoup/soup.h>
|
||||
|
||||
#include <gio/gunixoutputstream.h>
|
||||
|
||||
#include "ot-main.h"
|
||||
#include "ot-builtins.h"
|
||||
#include "ostree.h"
|
||||
|
|
@ -32,6 +34,7 @@
|
|||
#include <signal.h>
|
||||
|
||||
static char *opt_port_file = NULL;
|
||||
static char *opt_log = NULL;
|
||||
static gboolean opt_daemonize;
|
||||
static gboolean opt_autoexit;
|
||||
static gboolean opt_force_ranges;
|
||||
|
|
@ -40,6 +43,7 @@ static gint opt_port = 0;
|
|||
typedef struct {
|
||||
GFile *root;
|
||||
gboolean running;
|
||||
GOutputStream *log;
|
||||
} OtTrivialHttpd;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
|
|
@ -48,9 +52,31 @@ static GOptionEntry options[] = {
|
|||
{ "port", 'P', 0, G_OPTION_ARG_INT, &opt_port, "Use the specified TCP port", NULL },
|
||||
{ "port-file", 'p', 0, G_OPTION_ARG_FILENAME, &opt_port_file, "Write port number to PATH (- for standard output)", "PATH" },
|
||||
{ "force-range-requests", 0, 0, G_OPTION_ARG_NONE, &opt_force_ranges, "Force range requests by only serving half of files", NULL },
|
||||
{ "log-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_log, "Put logs here", "PATH" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
httpd_log (OtTrivialHttpd *httpd, const gchar *format, ...) __attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
static void
|
||||
httpd_log (OtTrivialHttpd *httpd, const gchar *format, ...)
|
||||
{
|
||||
g_autoptr(GString) str = NULL;
|
||||
va_list args;
|
||||
gsize written;
|
||||
|
||||
if (!httpd->log)
|
||||
return;
|
||||
|
||||
str = g_string_new (NULL);
|
||||
va_start (args, format);
|
||||
g_string_vprintf (str, format, args);
|
||||
va_end (args);
|
||||
|
||||
g_output_stream_write_all (httpd->log, str->str, str->len, &written, NULL, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
compare_strings (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
|
|
@ -154,6 +180,7 @@ do_get (OtTrivialHttpd *self,
|
|||
struct stat stbuf;
|
||||
g_autofree char *safepath = NULL;
|
||||
|
||||
httpd_log (self, "serving %s\n", path);
|
||||
if (strstr (path, "../") != NULL)
|
||||
{
|
||||
soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
|
||||
|
|
@ -296,6 +323,16 @@ do_get (OtTrivialHttpd *self,
|
|||
soup_message_set_status (msg, SOUP_STATUS_OK);
|
||||
}
|
||||
out:
|
||||
{
|
||||
guint status = 0;
|
||||
g_autofree gchar *reason = NULL;
|
||||
|
||||
g_object_get (msg,
|
||||
"status-code", &status,
|
||||
"reason-phrase", &reason,
|
||||
NULL);
|
||||
httpd_log (self, " status: %s (%u)\n", reason, status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -305,9 +342,6 @@ httpd_callback (SoupServer *server, SoupMessage *msg,
|
|||
SoupClientContext *context, gpointer data)
|
||||
{
|
||||
OtTrivialHttpd *self = data;
|
||||
SoupMessageHeadersIter iter;
|
||||
|
||||
soup_message_headers_iter_init (&iter, msg->request_headers);
|
||||
|
||||
if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD)
|
||||
do_get (self, server, msg, path, context);
|
||||
|
|
@ -354,6 +388,37 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
|
|||
|
||||
app->root = g_file_new_for_path (dirpath);
|
||||
|
||||
if (opt_log)
|
||||
{
|
||||
GOutputStream *stream = NULL;
|
||||
|
||||
if (g_strcmp0 (opt_log, "-") == 0)
|
||||
{
|
||||
if (opt_daemonize)
|
||||
{
|
||||
ot_util_usage_error (context, "Cannot use --log-file=- and --daemonize at the same time", error);
|
||||
goto out;
|
||||
}
|
||||
stream = G_OUTPUT_STREAM (g_unix_output_stream_new (STDOUT_FILENO, FALSE));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_autoptr(GFile) log_file;
|
||||
GFileOutputStream* log_stream;
|
||||
|
||||
log_file = g_file_new_for_path (opt_log);
|
||||
log_stream = g_file_create (log_file,
|
||||
G_FILE_CREATE_PRIVATE,
|
||||
cancellable,
|
||||
error);
|
||||
if (!log_stream)
|
||||
goto out;
|
||||
stream = G_OUTPUT_STREAM (log_stream);
|
||||
}
|
||||
|
||||
app->log = stream;
|
||||
}
|
||||
|
||||
#if SOUP_CHECK_VERSION(2, 48, 0)
|
||||
server = soup_server_new (SOUP_SERVER_SERVER_HEADER, "ostree-httpd ", NULL);
|
||||
if (!soup_server_listen_all (server, opt_port, 0, error))
|
||||
|
|
@ -459,13 +524,17 @@ ostree_builtin_trivial_httpd (int argc, char **argv, GCancellable *cancellable,
|
|||
goto out;
|
||||
g_signal_connect (dirmon, "changed", G_CALLBACK (on_dir_changed), app);
|
||||
}
|
||||
|
||||
{
|
||||
g_autofree gchar *path = g_file_get_path (app->root);
|
||||
httpd_log (app, "serving at root %s\n", path);
|
||||
}
|
||||
while (app->running)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
g_clear_object (&app->root);
|
||||
g_clear_object (&app->log);
|
||||
if (context)
|
||||
g_option_context_free (context);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -118,8 +118,15 @@ dump_commit (GVariant *variant,
|
|||
g_print ("Version: %s\n", version);
|
||||
}
|
||||
|
||||
g_print ("\n");
|
||||
dump_indented_lines (subject);
|
||||
if (subject[0])
|
||||
{
|
||||
g_print ("\n");
|
||||
dump_indented_lines (subject);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("(no subject)\n");
|
||||
}
|
||||
|
||||
if (body[0])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "libglnx.h"
|
||||
#include "ot-editor.h"
|
||||
#include "libgsystem.h"
|
||||
#include "libglnx.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <string.h>
|
||||
|
|
@ -101,7 +101,8 @@ ot_editor_prompt (OstreeRepo *repo,
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = gs_file_load_contents_utf8 (file, cancellable, error);
|
||||
ret = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (file), NULL,
|
||||
cancellable, error);
|
||||
|
||||
out:
|
||||
if (file)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ot-main.h"
|
||||
#include "ostree.h"
|
||||
#include "ot-admin-functions.h"
|
||||
#include "ot-main.h"
|
||||
#include "otutil.h"
|
||||
|
||||
static char *opt_repo;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ostree.h"
|
||||
#include "libglnx.h"
|
||||
#include "ostree.h"
|
||||
|
||||
typedef enum {
|
||||
OSTREE_BUILTIN_FLAG_NONE = 0,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
echo "1..53"
|
||||
echo "1..57"
|
||||
|
||||
$OSTREE checkout test2 checkout-test2
|
||||
echo "ok checkout"
|
||||
|
|
@ -103,6 +103,12 @@ $OSTREE commit -b test2-no-parent -s '' --parent=none $test_tmpdir/checkout-test
|
|||
assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1"
|
||||
echo "ok commit no parent"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
empty_rev=$($OSTREE commit -b test2-no-subject -s '' --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4)
|
||||
omitted_rev=$($OSTREE commit -b test2-no-subject-2 --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4)
|
||||
assert_streq $empty_rev $omitted_rev
|
||||
echo "ok commit no subject"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4
|
||||
$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4
|
||||
|
|
@ -179,13 +185,31 @@ cd ${test_tmpdir}/checkout-test2-4
|
|||
$OSTREE commit -b test2 -s "no xattrs" --no-xattrs
|
||||
echo "ok commit with no xattrs"
|
||||
|
||||
# NB: The + is optional, but we need to make sure we support it
|
||||
cd ${test_tmpdir}
|
||||
cat > test-statoverride.txt <<EOF
|
||||
+2048 /a/nested/3
|
||||
+1048 /a/nested/2
|
||||
2048 /a/nested/3
|
||||
EOF
|
||||
cd ${test_tmpdir}/checkout-test2-4
|
||||
$OSTREE commit -b test2 -s "with statoverride" --statoverride=../test-statoverride.txt
|
||||
echo "ok commit statoverridde"
|
||||
$OSTREE commit -b test2-override -s "with statoverride" --statoverride=../test-statoverride.txt
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE checkout test2-override checkout-test2-override
|
||||
test -g checkout-test2-override/a/nested/2
|
||||
test -u checkout-test2-override/a/nested/3
|
||||
echo "ok commit statoverride"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
cat > test-skiplist.txt <<EOF
|
||||
/a/nested/3
|
||||
EOF
|
||||
cd ${test_tmpdir}/checkout-test2-4
|
||||
assert_has_file a/nested/3
|
||||
$OSTREE commit -b test2-skiplist -s "with skiplist" --skip-list=../test-skiplist.txt
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE checkout test2-skiplist checkout-test2-skiplist
|
||||
assert_not_has_file checkout-test2-skiplist/a/nested/3
|
||||
echo "ok commit skiplist"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE prune
|
||||
|
|
@ -254,7 +278,7 @@ echo "ok prune"
|
|||
|
||||
cd ${test_tmpdir}
|
||||
rm repo3 -rf
|
||||
${CMD_PREFIX} ostree --repo=repo3 init --mode=archive-z2
|
||||
${CMD_PREFIX} ostree --repo=repo3 init --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=repo3 pull-local --remote=aremote repo test2
|
||||
rm repo3/refs/remotes -rf
|
||||
mkdir repo3/refs/remotes
|
||||
|
|
@ -362,9 +386,9 @@ else
|
|||
$OSTREE checkout test2 test2-checkout
|
||||
fi
|
||||
stat '--format=%Y' test2-checkout/baz/cow > cow-mtime
|
||||
assert_file_has_content cow-mtime 0
|
||||
assert_file_has_content cow-mtime 1
|
||||
stat '--format=%Y' test2-checkout/baz/deeper > deeper-mtime
|
||||
assert_file_has_content deeper-mtime 0
|
||||
assert_file_has_content deeper-mtime 1
|
||||
echo "ok content mtime"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
|
|
@ -381,7 +405,7 @@ echo "ok commit of fifo was rejected"
|
|||
cd ${test_tmpdir}
|
||||
rm repo2 -rf
|
||||
mkdir repo2
|
||||
${CMD_PREFIX} ostree --repo=repo2 init --mode=archive-z2
|
||||
${CMD_PREFIX} ostree --repo=repo2 init --mode=archive
|
||||
${CMD_PREFIX} ostree --repo=repo2 pull-local repo
|
||||
rm -rf test2-checkout
|
||||
${CMD_PREFIX} ostree --repo=repo2 checkout -U --disable-cache test2 test2-checkout
|
||||
|
|
@ -397,6 +421,28 @@ assert_file_has_content test2-checkout/baz/cow moo
|
|||
assert_has_dir repo2/uncompressed-objects-cache
|
||||
echo "ok disable cache checkout"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
rm checkout-test2 -rf
|
||||
$OSTREE checkout test2 checkout-test2
|
||||
date > checkout-test2/date.txt
|
||||
rm repo/tmp/* -rf
|
||||
export TEST_BOOTID=3072029c-8b10-60d1-d31b-8422eeff9b42
|
||||
if env OSTREE_REPO_TEST_ERROR=pre-commit OSTREE_BOOTID=${TEST_BOOTID} \
|
||||
$OSTREE commit -b test2 -s '' $test_tmpdir/checkout-test2 2>err.txt; then
|
||||
assert_not_reached "Should have hit OSTREE_REPO_TEST_ERROR_PRE_COMMIT"
|
||||
fi
|
||||
assert_file_has_content err.txt OSTREE_REPO_TEST_ERROR_PRE_COMMIT
|
||||
found_staging=0
|
||||
for d in $(find repo/tmp/ -maxdepth 1 -type d); do
|
||||
bn=$(basename $d)
|
||||
if test ${bn##staging-} != ${bn}; then
|
||||
assert_str_match "${bn}" "^staging-${TEST_BOOTID}-"
|
||||
found_staging=1
|
||||
fi
|
||||
done
|
||||
assert_streq "${found_staging}" 1
|
||||
echo "ok test error pre commit/bootid"
|
||||
|
||||
# Whiteouts
|
||||
cd ${test_tmpdir}
|
||||
mkdir -p overlay/baz/
|
||||
|
|
@ -468,5 +514,9 @@ cd ..
|
|||
if cmp timestamp-{orig,new}.txt; then
|
||||
assert_not_reached "failed to update mtime on repo"
|
||||
fi
|
||||
|
||||
echo "ok mtime updated"
|
||||
|
||||
cd ${test_tmpdir}
|
||||
$OSTREE init --mode=bare --repo=repo-extensions
|
||||
assert_has_dir repo-extensions/extensions
|
||||
echo "ok extensions dir"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,535 @@
|
|||
# This GLib suppressions file is known to be used at least by:
|
||||
#
|
||||
# - rpm-software-management/libhif
|
||||
#
|
||||
# Please use the upstream verison in libhif for changes.
|
||||
{
|
||||
gobject_init_1
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:gobject_init
|
||||
}
|
||||
{
|
||||
g_type_register_static_1
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_register_static
|
||||
}
|
||||
{
|
||||
g_type_register_fundamental
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_register_fundamental
|
||||
}
|
||||
{
|
||||
g_type_init_with_debug_flags
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_init_with_debug_flags
|
||||
}
|
||||
{
|
||||
g_type_class_ref_1
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:type_iface_vtable_base_init_Wm
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
}
|
||||
{
|
||||
g_type_class_ref_2
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:type_class_init_Wm
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
}
|
||||
{
|
||||
g_type_add_interface_static
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_add_interface_static
|
||||
}
|
||||
{
|
||||
g_param_spec_internal
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
fun:g_type_create_instance
|
||||
fun:g_param_spec_internal
|
||||
}
|
||||
{
|
||||
g_param_spec_enum
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
fun:g_param_spec_enum
|
||||
}
|
||||
{
|
||||
g_param_spec_flags
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
fun:g_param_spec_flags
|
||||
}
|
||||
{
|
||||
g_quark_from_static_string
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_quark_from_static_string
|
||||
}
|
||||
{
|
||||
g_quark_from_string
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_quark_from_string
|
||||
}
|
||||
{
|
||||
g_value_register_transform_func
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_value_register_transform_func
|
||||
}
|
||||
{
|
||||
test_run_seed
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_rand_new_with_seed_array
|
||||
fun:test_run_seed
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_test_init
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_rand_new_with_seed_array
|
||||
...
|
||||
fun:g_test_init
|
||||
}
|
||||
{
|
||||
g_intern_static_string
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_intern_static_string
|
||||
}
|
||||
{
|
||||
g_main_context_push_thread_default
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_queue_new
|
||||
fun:g_main_context_push_thread_default
|
||||
}
|
||||
{
|
||||
g_main_context_push_thread_default_inlined
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_slice_alloc0
|
||||
fun:g_main_context_push_thread_default
|
||||
}
|
||||
{
|
||||
g_dbus_error_register_error
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_dbus_error_register_error
|
||||
}
|
||||
{
|
||||
g_param_spec_pool_insert
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_param_spec_pool_insert
|
||||
}
|
||||
{
|
||||
g_main_context_default
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_main_context_default
|
||||
}
|
||||
{
|
||||
g_main_context_check
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_ptr_array_add
|
||||
fun:g_main_context_check
|
||||
}
|
||||
{
|
||||
g_test_run_suite
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_slist_copy
|
||||
fun:g_test_run_suite_internal
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_dbus_interface_info_cache_build
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_dbus_interface_info_cache_build
|
||||
}
|
||||
{
|
||||
g_cancellable_push_current
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:thread_memory_from_self
|
||||
...
|
||||
fun:g_cancellable_push_current
|
||||
}
|
||||
{
|
||||
_g_io_module_get_default
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_io_module_new
|
||||
fun:g_io_modules_scan_all_in_directory_with_scope
|
||||
fun:_g_io_modules_ensure_loaded
|
||||
fun:_g_io_module_get_default
|
||||
}
|
||||
{
|
||||
g_io_scheduler_push_job
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:init_scheduler
|
||||
fun:g_once_impl
|
||||
fun:g_io_scheduler_push_job
|
||||
}
|
||||
{
|
||||
g_io_scheduler_push_job_2
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_system_thread_new
|
||||
...
|
||||
fun:g_io_scheduler_push_job
|
||||
}
|
||||
{
|
||||
g_bus_get_sync__available_connections
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_hash_table_new
|
||||
fun:initable_init
|
||||
fun:g_initable_init
|
||||
fun:g_bus_get_sync
|
||||
}
|
||||
{
|
||||
g_socket_connection_factory_register_type
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_socket_connection_factory_register_type
|
||||
}
|
||||
{
|
||||
g_test_add_vtable
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_test_add_vtable
|
||||
}
|
||||
{
|
||||
g_mutex_lock
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_mutex_impl_new
|
||||
fun:g_mutex_get_impl
|
||||
fun:g_mutex_lock
|
||||
}
|
||||
{
|
||||
g_thread_self
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_thread_self
|
||||
}
|
||||
{
|
||||
g_rec_mutex_lock
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_rec_mutex_impl_new
|
||||
fun:g_rec_mutex_get_impl
|
||||
fun:g_rec_mutex_lock
|
||||
}
|
||||
{
|
||||
test_case_run
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_malloc0
|
||||
fun:test_case_run
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_get_charset
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_get_charset
|
||||
}
|
||||
{
|
||||
g_test_run_suite__timer_new
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_timer_new
|
||||
fun:test_case_run
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_test_run_suite__timer_new2
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_timer_new
|
||||
fun:test_case_run_suite_internal
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_test_run_suite__strconcat
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_strconcat
|
||||
fun:test_case_run
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
fun:g_test_run
|
||||
}
|
||||
{
|
||||
g_type_interface_add_prerequisite
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_type_interface_add_prerequisite
|
||||
}
|
||||
{
|
||||
<insert_a_suppression_name_here>
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_slist_copy
|
||||
fun:g_test_run_suite_internal
|
||||
...
|
||||
fun:g_test_run_suite
|
||||
}
|
||||
{
|
||||
g_set_prgname
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_set_prgname
|
||||
}
|
||||
{
|
||||
g_test_run_suite__strconcat_2
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_strconcat
|
||||
fun:g_test_run_suite_internal
|
||||
}
|
||||
{
|
||||
g_test_run_suite__strdup
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_strdup
|
||||
fun:g_test_run_suite_internal
|
||||
}
|
||||
{
|
||||
g_private_get
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_private_get
|
||||
}
|
||||
{
|
||||
g_private_set
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_private_set
|
||||
}
|
||||
{
|
||||
g_static_mutex_get_mutex_impl
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_static_mutex_get_mutex_impl
|
||||
}
|
||||
{
|
||||
g_variant_type_info_unref
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_hash_table_remove
|
||||
fun:g_variant_type_info_unref
|
||||
}
|
||||
{
|
||||
g_rw_lock_reader_lock
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_rw_lock_impl_new
|
||||
fun:g_rw_lock_get_impl
|
||||
fun:g_rw_lock_reader_lock
|
||||
}
|
||||
{
|
||||
g_child_watch_finalize__rt_sigaction
|
||||
Memcheck:Param
|
||||
rt_sigaction(act->sa_flags)
|
||||
fun:__libc_sigaction
|
||||
...
|
||||
fun:g_child_watch_finalize
|
||||
}
|
||||
{
|
||||
g_dbus_worker_new
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:_g_dbus_worker_new
|
||||
}
|
||||
{
|
||||
gdbus_shared_thread_func
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
...
|
||||
fun:g_malloc
|
||||
...
|
||||
fun:gdbus_shared_thread_func
|
||||
}
|
||||
{
|
||||
g_task_start_task_thread
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_slice_alloc0
|
||||
...
|
||||
fun:g_thread_pool_push
|
||||
fun:g_task_start_task_thread
|
||||
}
|
||||
{
|
||||
g_get_language_names
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
fun:g_malloc0
|
||||
fun:g_get_language_names
|
||||
}
|
||||
{
|
||||
g_get_filename_charsets
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
...
|
||||
fun:g_get_filename_charsets
|
||||
fun:g_filename_display_name
|
||||
}
|
||||
{
|
||||
g_main_current_source
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
...
|
||||
fun:g_main_current_source
|
||||
fun:g_task_return
|
||||
fun:g_task_thread_pool_thread
|
||||
}
|
||||
{
|
||||
g_once_init_enter
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
...
|
||||
fun:g_once_init_enter
|
||||
}
|
||||
{
|
||||
g_child_watch_source_new
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
...
|
||||
fun:g_thread_new
|
||||
...
|
||||
fun:g_child_watch_source_new
|
||||
}
|
||||
{
|
||||
continue_writing_in_idle_cb
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
...
|
||||
fun:g_task_new
|
||||
...
|
||||
fun:continue_writing_in_idle_cb
|
||||
fun:g_main_context_dispatch
|
||||
}
|
||||
{
|
||||
g_main_current_source
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_main_current_source
|
||||
}
|
||||
{
|
||||
g_thread_pool_push
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_thread_pool_push
|
||||
}
|
||||
{
|
||||
leak_test_dbus_dispose
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_main_loop_run
|
||||
fun:g_test_dbus_down
|
||||
}
|
||||
{
|
||||
leak_test_dbus_down
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
fun:g_malloc0
|
||||
fun:g_main_loop_new
|
||||
fun:g_test_dbus_down
|
||||
}
|
||||
{
|
||||
leak_socket_client_connect
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_slice_alloc
|
||||
fun:g_slice_alloc0
|
||||
fun:g_socket_client_connect_async
|
||||
fun:g_socket_client_connect_to_uri_async
|
||||
}
|
||||
{
|
||||
leak_signal_handlers_disconnect_matched
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:calloc
|
||||
fun:g_malloc0
|
||||
...
|
||||
fun:g_slice_alloc
|
||||
...
|
||||
fun:g_signal_handlers_disconnect_matched
|
||||
}
|
||||
{
|
||||
g_tls_connection_gnutls_init_priorities
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_strdup
|
||||
fun:g_tls_connection_gnutls_init_priorities
|
||||
}
|
||||
{
|
||||
g_tls_connection_gnutls_heisenbug_likely_same_as_above
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
fun:g_strdup
|
||||
...
|
||||
fun:g_tls_client_connection_new
|
||||
}
|
||||
{
|
||||
g_unix_signal_add_full
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:g_malloc
|
||||
...
|
||||
fun:g_thread_new
|
||||
...
|
||||
fun:g_unix_signal_add_full
|
||||
}
|
||||
{
|
||||
glib_worker_1
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:glib_worker_main
|
||||
}
|
||||
|
|
@ -28,11 +28,11 @@
|
|||
/* This function hovers in a quantum superposition of horrifying and
|
||||
* beautiful. Future generations may interpret it as modern art.
|
||||
*/
|
||||
static gboolean
|
||||
run_libtest (const char *cmd, GError **error)
|
||||
gboolean
|
||||
ot_test_run_libtest (const char *cmd, GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *builddir = g_getenv ("G_TEST_BUILDDIR");
|
||||
const char *srcdir = g_getenv ("G_TEST_SRCDIR");
|
||||
int estatus;
|
||||
g_autoptr(GPtrArray) argv = g_ptr_array_new ();
|
||||
g_autoptr(GString) cmdstr = g_string_new ("");
|
||||
|
|
@ -40,8 +40,8 @@ run_libtest (const char *cmd, GError **error)
|
|||
g_ptr_array_add (argv, "bash");
|
||||
g_ptr_array_add (argv, "-c");
|
||||
|
||||
g_string_append (cmdstr, ". ");
|
||||
g_string_append (cmdstr, builddir);
|
||||
g_string_append (cmdstr, "set -xeuo pipefail; . ");
|
||||
g_string_append (cmdstr, srcdir);
|
||||
g_string_append (cmdstr, "/tests/libtest.sh; ");
|
||||
g_string_append (cmdstr, cmd);
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ ot_test_setup_repo (GCancellable *cancellable,
|
|||
g_autoptr(GFile) repo_path = g_file_new_for_path ("repo");
|
||||
glnx_unref_object OstreeRepo* ret_repo = NULL;
|
||||
|
||||
if (!run_libtest ("setup_test_repository", error))
|
||||
if (!ot_test_run_libtest ("setup_test_repository archive-z2", error))
|
||||
goto out;
|
||||
|
||||
ret_repo = ostree_repo_new (repo_path);
|
||||
|
|
@ -91,7 +91,7 @@ ot_test_setup_sysroot (GCancellable *cancellable,
|
|||
g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot");
|
||||
glnx_unref_object OstreeSysroot *ret_sysroot = NULL;
|
||||
|
||||
if (!run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error))
|
||||
if (!ot_test_run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error))
|
||||
goto out;
|
||||
|
||||
ret_sysroot = ostree_sysroot_new (sysroot_path);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean ot_test_run_libtest (const char *cmd, GError **error);
|
||||
|
||||
OstreeRepo *ot_test_setup_repo (GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ export TEST_GPG_KEYID_3="DF444D67"
|
|||
# this by copying locally.
|
||||
echo "Copying gpghome to ${test_tmpdir}"
|
||||
cp -a "${test_srcdir}/gpghome" ${test_tmpdir}
|
||||
chmod -R u+w "${test_tmpdir}"
|
||||
export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome
|
||||
export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted
|
||||
|
||||
|
|
@ -77,15 +78,28 @@ if test -n "${OT_TESTS_DEBUG:-}"; then
|
|||
fi
|
||||
|
||||
if test -n "${OT_TESTS_VALGRIND:-}"; then
|
||||
CMD_PREFIX="env G_SLICE=always-malloc valgrind -q --leak-check=full --num-callers=30 --suppressions=${test_srcdir}/ostree-valgrind.supp"
|
||||
CMD_PREFIX="env G_SLICE=always-malloc OSTREE_SUPPRESS_SYNCFS=1 valgrind -q --error-exitcode=1 --leak-check=full --num-callers=30 --suppressions=${test_srcdir}/glib.supp --suppressions=${test_srcdir}/ostree.supp"
|
||||
else
|
||||
CMD_PREFIX="env LD_PRELOAD=${test_builddir}/libreaddir-rand.so"
|
||||
# In some cases the LD_PRELOAD may cause obscure problems,
|
||||
# e.g. right now it breaks for me with -fsanitize=address, so
|
||||
# let's allow users to skip it.
|
||||
if test -z "${OT_SKIP_READDIR_RAND:-}"; then
|
||||
CMD_PREFIX="env LD_PRELOAD=${test_builddir}/libreaddir-rand.so"
|
||||
else
|
||||
CMD_PREFIX=""
|
||||
fi
|
||||
fi
|
||||
|
||||
assert_streq () {
|
||||
test "$1" = "$2" || (echo 1>&2 "$1 != $2"; exit 1)
|
||||
}
|
||||
|
||||
assert_str_match () {
|
||||
if ! echo "$1" | grep -E -q "$2"; then
|
||||
(echo 1>&2 "$1 does not match regexp $2"; exit 1)
|
||||
fi
|
||||
}
|
||||
|
||||
assert_not_streq () {
|
||||
(! test "$1" = "$2") || (echo 1>&2 "$1 == $2"; exit 1)
|
||||
}
|
||||
|
|
@ -100,13 +114,17 @@ assert_has_dir () {
|
|||
|
||||
assert_not_has_file () {
|
||||
if test -f "$1"; then
|
||||
echo 1>&2 "File '$1' exists"; exit 1
|
||||
sed -e 's/^/# /' < "$1" >&2
|
||||
echo 1>&2 "File '$1' exists"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_not_file_has_content () {
|
||||
if grep -q -e "$2" "$1"; then
|
||||
echo 1>&2 "File '$1' incorrectly matches regexp '$2'"; exit 1
|
||||
sed -e 's/^/# /' < "$1" >&2
|
||||
echo 1>&2 "File '$1' incorrectly matches regexp '$2'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -118,13 +136,38 @@ assert_not_has_dir () {
|
|||
|
||||
assert_file_has_content () {
|
||||
if ! grep -q -e "$2" "$1"; then
|
||||
echo 1>&2 "File '$1' doesn't match regexp '$2'"; exit 1
|
||||
sed -e 's/^/# /' < "$1" >&2
|
||||
echo 1>&2 "File '$1' doesn't match regexp '$2'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_symlink_has_content () {
|
||||
if ! test -L "$1"; then
|
||||
echo 1>&2 "File '$1' is not a symbolic link"
|
||||
exit 1
|
||||
fi
|
||||
if ! readlink "$1" | grep -q -e "$2"; then
|
||||
sed -e 's/^/# /' < "$1" >&2
|
||||
echo 1>&2 "Symbolic link '$1' doesn't match regexp '$2'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_file_empty() {
|
||||
if test -s "$1"; then
|
||||
echo 1>&2 "File '$1' is not empty"; exit 1
|
||||
sed -e 's/^/# /' < "$1" >&2
|
||||
echo 1>&2 "File '$1' is not empty"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_files_hardlinked() {
|
||||
f1=$(stat -c %i $1)
|
||||
f2=$(stat -c %i $2)
|
||||
if [ "$f1" != "$f2" ]; then
|
||||
echo 1>&2 "Files '$1' and '$2' are not hardlinked"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -370,6 +413,11 @@ skip_without_fuse () {
|
|||
exit 0
|
||||
fi
|
||||
|
||||
if ! capsh --print | grep -q 'Bounding set.*[^a-z]cap_sys_admin'; then
|
||||
echo "1..0 # SKIP No cap_sys_admin in bounding set, can't use FUSE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! [ -w /dev/fuse ]; then
|
||||
echo "1..0 # SKIP no write access to /dev/fuse"
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -1,199 +0,0 @@
|
|||
{
|
||||
g_type_init_with_debug_flags calloc
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_type_init_with_debug_flags
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_add_interface_static malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_add_interface_static
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_add_interface_dynamic malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_add_interface_dynamic
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_class_ref malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_register_dynamic malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_register_dynamic
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_init_with_debug_flags malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_init_with_debug_flags
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_init_with_debug_flags realloc
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
...
|
||||
fun:g_type_init_with_debug_flags
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_test_add_vtable malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_test_add_vtable
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_test_init
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_test_init
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_register_static malloc
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_register_static
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_register_static realloc
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
...
|
||||
fun:g_type_register_static
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_register_fundamental never freed
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:g_type_register_fundamental
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_type_class_ref never finalized
|
||||
Memcheck:Leak
|
||||
fun:calloc
|
||||
...
|
||||
fun:g_type_class_ref
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
DBusGValue qdata
|
||||
Memcheck:Leak
|
||||
fun:realloc
|
||||
fun:g_realloc
|
||||
fun:g_type_set_qdata
|
||||
fun:_dbus_g_value_types_init
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
gettext conditional jump
|
||||
Memcheck:Cond
|
||||
fun:__GI___strcasecmp_l
|
||||
fun:__gconv_open
|
||||
fun:_nl_find_msg
|
||||
fun:__dcigettext
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
gettext uninitialized value
|
||||
Memcheck:Value8
|
||||
fun:__GI___strcasecmp_l
|
||||
fun:__gconv_open
|
||||
fun:_nl_find_msg
|
||||
fun:__dcigettext
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
font config invalid reads
|
||||
Memcheck:Addr4
|
||||
...
|
||||
fun:FcConfigParseAndLoad
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
dynamic loader conditional jump
|
||||
Memcheck:Cond
|
||||
fun:index
|
||||
fun:expand_dynamic_string_token
|
||||
fun:_dl_map_object
|
||||
fun:map_doit
|
||||
fun:_dl_catch_error
|
||||
fun:do_preload
|
||||
fun:dl_main
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
g_vfs_get_local
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_vfs_get_local
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
_g_io_modules_ensure_loaded
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:_g_io_modules_ensure_loaded
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
_g_io_module_get_default
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:_g_io_module_get_default
|
||||
...
|
||||
}
|
||||
|
||||
{
|
||||
_dl_allocate_tls
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:_dl_allocate_tls
|
||||
...
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue