Merge tag 'upstream/2016.6' into debian/master

Upstream version 2016.6
This commit is contained in:
Simon McVittie 2016-06-26 12:12:28 +01:00
commit 051e7acbe2
115 changed files with 4857 additions and 2074 deletions

View File

@ -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

View File

@ -18,7 +18,7 @@
# Common variables
AM_CPPFLAGS =
AM_CFLAGS =
DISTCHECK_CONFIGURE_FLAGS =
AM_DISTCHECK_CONFIGURE_FLAGS =
SUBDIRS =
NULL =
BUILT_SOURCES =

View File

@ -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 \

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

2
apidoc/.gitignore vendored
View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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]),

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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

View File

@ -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:
*

View File

@ -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);

View File

@ -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)
{

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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: ");
}

View File

@ -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;
}
}
/**

View File

@ -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>

View File

@ -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/*

View File

@ -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;
*/

View File

@ -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
*

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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.

View File

@ -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
{

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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 ***/

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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;
}
}
}
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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++)

View File

@ -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));

View File

@ -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

View File

@ -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,

View File

@ -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
*

View File

@ -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 ();

View File

@ -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;
}
}

View File

@ -34,6 +34,10 @@ typedef enum {
} OstreeSysrootDebugFlags;
/**
* OstreeSysroot:
* Internal struct
*/
struct OstreeSysroot {
GObject parent;

View File

@ -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
*

View File

@ -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;

View File

@ -31,3 +31,5 @@
#include <ostree-bootconfig-parser.h>
#include <ostree-diff.h>
#include <ostree-gpg-verify-result.h>
#include <ostree-autocleanups.h>

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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>

View File

@ -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)

View File

@ -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;

View File

@ -22,6 +22,7 @@
#include "config.h"
#include "libglnx.h"
#include "ot-admin-functions.h"
#include "otutil.h"
#include "ostree.h"

View File

@ -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)

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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 }
};

View File

@ -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;

View File

@ -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])
{

View File

@ -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)

View 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;

View File

@ -22,8 +22,8 @@
#pragma once
#include "ostree.h"
#include "libglnx.h"
#include "ostree.h"
typedef enum {
OSTREE_BUILTIN_FLAG_NONE = 0,

View File

@ -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"

535
tests/glib.supp Normal file
View File

@ -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
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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