diff -Nru ostree-2017.11/apidoc/html/index.html ostree-2017.12/apidoc/html/index.html --- ostree-2017.11/apidoc/html/index.html 2017-09-14 16:17:57.000000000 +0000 +++ ostree-2017.12/apidoc/html/index.html 2017-10-02 17:11:38.000000000 +0000 @@ -14,7 +14,7 @@
-

for OSTree 2017.11

+

for OSTree 2017.12


diff -Nru ostree-2017.11/apidoc/html/ostree.devhelp2 ostree-2017.12/apidoc/html/ostree.devhelp2 --- ostree-2017.11/apidoc/html/ostree.devhelp2 2017-09-14 16:17:57.000000000 +0000 +++ ostree-2017.12/apidoc/html/ostree.devhelp2 2017-10-02 17:11:38.000000000 +0000 @@ -97,6 +97,8 @@ + + @@ -387,6 +389,7 @@ + @@ -431,6 +434,7 @@ + diff -Nru ostree-2017.11/apidoc/html/ostree-OstreeRepo.html ostree-2017.12/apidoc/html/ostree-OstreeRepo.html --- ostree-2017.11/apidoc/html/ostree-OstreeRepo.html 2017-09-14 16:17:57.000000000 +0000 +++ ostree-2017.12/apidoc/html/ostree-OstreeRepo.html 2017-10-02 17:11:38.000000000 +0000 @@ -169,6 +169,22 @@ +guint + + +ostree_repo_hash () + + + + +gboolean + + +ostree_repo_equal () + + + + GKeyFile * @@ -1629,6 +1645,78 @@
+

ostree_repo_hash ()

+
guint
+ostree_repo_hash (OstreeRepo *self);
+

Calculate a hash value for the given open repository, suitable for use when +putting it into a hash table. It is an error to call this on an OstreeRepo +which is not yet open, as a persistent hash value cannot be calculated until +the repository is open and the inode of its root directory has been loaded.

+

This function does no I/O.

+
+

Parameters

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

self

an OstreeRepo

 
+
+
+

Returns

+

hash value for the OstreeRepo

+
+

Since: 2017.12

+
+
+
+

ostree_repo_equal ()

+
gboolean
+ostree_repo_equal (OstreeRepo *a,
+                   OstreeRepo *b);
+

Check whether two opened repositories are the same on disk: if their root +directories are the same inode. If a + or b + are not open yet (due to +ostree_repo_open() not being called on them yet), FALSE will be returned.

+
+

Parameters

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

a

an OstreeRepo

 

b

an OstreeRepo

 
+
+
+

Returns

+

TRUE if a +and b +are the same repository on disk, FALSE otherwise

+
+

Since: 2017.12

+
+
+

ostree_repo_copy_config ()

GKeyFile *
 ostree_repo_copy_config (OstreeRepo *self);
@@ -7217,9 +7305,16 @@   +

OSTREE_REPO_MODE_ARCHIVE

+ +

Files are compressed, should be owned by non-root. Can be served via HTTP. Since: 2017.12

+ +  + +

OSTREE_REPO_MODE_ARCHIVE_Z2

-

Files are compressed, should be owned by non-root. Can be served via HTTP

+

Legacy alias for OSTREE_REPO_MODE_ARCHIVE

  @@ -7816,7 +7911,7 @@

OSTREE_REPO_PULL_FLAGS_UNTRUSTED

-

Don't trust local remote

+

Do verify checksums of local (filesystem-accessible) repositories (defaults on for HTTP)

  @@ -7827,6 +7922,13 @@   + +

OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP

+ +

Don't verify checksums of objects HTTP repositories (Since: 2017.12)

+ +  +
diff -Nru ostree-2017.11/apidoc/html/reference.html ostree-2017.12/apidoc/html/reference.html --- ostree-2017.11/apidoc/html/reference.html 2017-09-14 16:17:57.000000000 +0000 +++ ostree-2017.12/apidoc/html/reference.html 2017-10-02 17:11:38.000000000 +0000 @@ -790,6 +790,10 @@
+ostree_repo_equal, function in OstreeRepo +
+
+
ostree_repo_export_tree_to_archive, function in OstreeRepo
@@ -882,6 +886,10 @@
+ostree_repo_hash, function in OstreeRepo +
+
+
ostree_repo_has_object, function in OstreeRepo
diff -Nru ostree-2017.11/apidoc/Makefile.in ostree-2017.12/apidoc/Makefile.in --- ostree-2017.11/apidoc/Makefile.in 2017-09-14 16:17:45.000000000 +0000 +++ ostree-2017.12/apidoc/Makefile.in 2017-10-02 17:11:27.000000000 +0000 @@ -265,6 +265,8 @@ OTOOL64 = @OTOOL64@ OT_DEP_AVAHI_CFLAGS = @OT_DEP_AVAHI_CFLAGS@ OT_DEP_AVAHI_LIBS = @OT_DEP_AVAHI_LIBS@ +OT_DEP_CRYPTO_CFLAGS = @OT_DEP_CRYPTO_CFLAGS@ +OT_DEP_CRYPTO_LIBS = @OT_DEP_CRYPTO_LIBS@ OT_DEP_CURL_CFLAGS = @OT_DEP_CURL_CFLAGS@ OT_DEP_CURL_LIBS = @OT_DEP_CURL_LIBS@ OT_DEP_E2P_CFLAGS = @OT_DEP_E2P_CFLAGS@ @@ -279,8 +281,6 @@ OT_DEP_LIBMOUNT_LIBS = @OT_DEP_LIBMOUNT_LIBS@ OT_DEP_LZMA_CFLAGS = @OT_DEP_LZMA_CFLAGS@ OT_DEP_LZMA_LIBS = @OT_DEP_LZMA_LIBS@ -OT_DEP_OPENSSL_CFLAGS = @OT_DEP_OPENSSL_CFLAGS@ -OT_DEP_OPENSSL_LIBS = @OT_DEP_OPENSSL_LIBS@ OT_DEP_SELINUX_CFLAGS = @OT_DEP_SELINUX_CFLAGS@ OT_DEP_SELINUX_LIBS = @OT_DEP_SELINUX_LIBS@ OT_DEP_SOUP_CFLAGS = @OT_DEP_SOUP_CFLAGS@ diff -Nru ostree-2017.11/apidoc/ostree-experimental-sections.txt ostree-2017.12/apidoc/ostree-experimental-sections.txt --- ostree-2017.11/apidoc/ostree-experimental-sections.txt 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/apidoc/ostree-experimental-sections.txt 2017-10-01 17:38:12.000000000 +0000 @@ -85,4 +85,5 @@ ostree_repo_remote_list_collection_refs ostree_repo_set_collection_ref_immediate ostree_repo_transaction_set_collection_ref +ostree_repo_resolve_collection_ref diff -Nru ostree-2017.11/apidoc/ostree-sections.txt ostree-2017.12/apidoc/ostree-sections.txt --- ostree-2017.11/apidoc/ostree-sections.txt 2017-09-14 16:17:57.000000000 +0000 +++ ostree-2017.12/apidoc/ostree-sections.txt 2017-10-02 17:11:38.000000000 +0000 @@ -287,6 +287,8 @@ ostree_repo_get_mode ostree_repo_get_config ostree_repo_get_dfd +ostree_repo_hash +ostree_repo_equal ostree_repo_copy_config ostree_repo_remote_add ostree_repo_remote_delete diff -Nru ostree-2017.11/apidoc/version.xml ostree-2017.12/apidoc/version.xml --- ostree-2017.11/apidoc/version.xml 2017-09-08 00:47:13.000000000 +0000 +++ ostree-2017.12/apidoc/version.xml 2017-10-02 17:07:57.000000000 +0000 @@ -1 +1 @@ -2017.11 \ No newline at end of file +2017.12 \ No newline at end of file diff -Nru ostree-2017.11/buildutil/tap-test ostree-2017.12/buildutil/tap-test --- ostree-2017.11/buildutil/tap-test 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/buildutil/tap-test 2017-10-01 17:38:12.000000000 +0000 @@ -8,7 +8,8 @@ srcd=$(cd $(dirname $1) && pwd) bn=$(basename $1) -tempdir=$(mktemp -d /var/tmp/tap-test.XXXXXX) +TEST_TMPDIR=${TEST_TMPDIR:-/var/tmp} +tempdir=$(mktemp -d $TEST_TMPDIR/tap-test.XXXXXX) touch ${tempdir}/.testtmp function cleanup () { if test -f ${tempdir}/.testtmp; then diff -Nru ostree-2017.11/config.h.in ostree-2017.12/config.h.in --- ostree-2017.11/config.h.in 2017-09-14 16:17:49.000000000 +0000 +++ ostree-2017.12/config.h.in 2017-10-02 17:11:31.000000000 +0000 @@ -40,6 +40,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define if we have gnutls */ +#undef HAVE_GNUTLS + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H diff -Nru ostree-2017.11/configure ostree-2017.12/configure --- ostree-2017.11/configure 2017-09-14 16:17:45.000000000 +0000 +++ ostree-2017.12/configure 2017-10-02 17:11:26.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libostree 2017.11. +# Generated by GNU Autoconf 2.69 for libostree 2017.12. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='libostree' PACKAGE_TARNAME='libostree' -PACKAGE_VERSION='2017.11' -PACKAGE_STRING='libostree 2017.11' +PACKAGE_VERSION='2017.12' +PACKAGE_STRING='libostree 2017.12' PACKAGE_BUGREPORT='walters@verbum.org' PACKAGE_URL='' @@ -676,10 +676,12 @@ USE_AVAHI_TRUE OT_DEP_AVAHI_LIBS OT_DEP_AVAHI_CFLAGS +USE_GNUTLS_FALSE +USE_GNUTLS_TRUE USE_OPENSSL_FALSE USE_OPENSSL_TRUE -OT_DEP_OPENSSL_LIBS -OT_DEP_OPENSSL_CFLAGS +OT_DEP_CRYPTO_LIBS +OT_DEP_CRYPTO_CFLAGS USE_SMACK_FALSE USE_SMACK_TRUE USE_SELINUX_FALSE @@ -938,6 +940,7 @@ with_libarchive with_selinux with_smack +with_crypto with_openssl with_avahi with_libmount @@ -987,8 +990,8 @@ OT_DEP_LIBARCHIVE_LIBS OT_DEP_SELINUX_CFLAGS OT_DEP_SELINUX_LIBS -OT_DEP_OPENSSL_CFLAGS -OT_DEP_OPENSSL_LIBS +OT_DEP_CRYPTO_CFLAGS +OT_DEP_CRYPTO_LIBS OT_DEP_AVAHI_CFLAGS OT_DEP_AVAHI_LIBS OT_DEP_LIBMOUNT_CFLAGS @@ -1537,7 +1540,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libostree 2017.11 to adapt to many kinds of systems. +\`configure' configures libostree 2017.12 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1607,7 +1610,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libostree 2017.11:";; + short | recursive ) echo "Configuration of libostree 2017.12:";; esac cat <<\_ACEOF @@ -1677,6 +1680,8 @@ --without-libarchive Do not use libarchive --without-selinux Do not use SELinux --with-smack Enable smack + --with-crypto Choose library for checksums, one of glib, openssl, + gnutls (default: glib) --with-openssl Enable use of OpenSSL libcrypto (checksums) --without-avahi Do not use Avahi --without-libmount Do not use libmount @@ -1759,10 +1764,10 @@ C compiler flags for OT_DEP_SELINUX, overriding pkg-config OT_DEP_SELINUX_LIBS linker flags for OT_DEP_SELINUX, overriding pkg-config - OT_DEP_OPENSSL_CFLAGS - C compiler flags for OT_DEP_OPENSSL, overriding pkg-config - OT_DEP_OPENSSL_LIBS - linker flags for OT_DEP_OPENSSL, overriding pkg-config + OT_DEP_CRYPTO_CFLAGS + C compiler flags for OT_DEP_CRYPTO, overriding pkg-config + OT_DEP_CRYPTO_LIBS + linker flags for OT_DEP_CRYPTO, overriding pkg-config OT_DEP_AVAHI_CFLAGS C compiler flags for OT_DEP_AVAHI, overriding pkg-config OT_DEP_AVAHI_LIBS @@ -1846,7 +1851,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libostree configure 2017.11 +libostree configure 2017.12 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2261,7 +2266,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libostree $as_me 2017.11, which was +It was created by libostree $as_me 2017.12, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3129,7 +3134,7 @@ # Define the identity of the package. PACKAGE='libostree' - VERSION='2017.11' + VERSION='2017.12' # Some tools Automake needs. @@ -5863,9 +5868,9 @@ YEAR_VERSION=2017 -RELEASE_VERSION=11 +RELEASE_VERSION=12 -PACKAGE_VERSION=2017.11 +PACKAGE_VERSION=2017.12 if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then : @@ -16390,25 +16395,44 @@ fi + +# Check whether --with-crypto was given. +if test "${with_crypto+set}" = set; then : + withval=$with_crypto; : +else + with_crypto=glib +fi + + +if test $with_crypto = glib; then : + +elif test $with_crypto = openssl; then : + with_openssl=yes +elif test $with_crypto = gnutls; then : + +else + as_fn_error $? "Invalid --with-crypto $with_crypto" "$LINENO" 5 + +fi + OPENSSL_DEPENDENCY="libcrypto >= 1.0.1" # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : - withval=$with_openssl; : + withval=$with_openssl; with_openssl=$withval else with_openssl=no fi - if test x$with_openssl != xno ; then : pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_OPENSSL" >&5 -$as_echo_n "checking for OT_DEP_OPENSSL... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_CRYPTO" >&5 +$as_echo_n "checking for OT_DEP_CRYPTO... " >&6; } -if test -n "$OT_DEP_OPENSSL_CFLAGS"; then - pkg_cv_OT_DEP_OPENSSL_CFLAGS="$OT_DEP_OPENSSL_CFLAGS" +if test -n "$OT_DEP_CRYPTO_CFLAGS"; then + pkg_cv_OT_DEP_CRYPTO_CFLAGS="$OT_DEP_CRYPTO_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$OPENSSL_DEPENDENCY\""; } >&5 @@ -16416,7 +16440,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OT_DEP_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "$OPENSSL_DEPENDENCY" 2>/dev/null` + pkg_cv_OT_DEP_CRYPTO_CFLAGS=`$PKG_CONFIG --cflags "$OPENSSL_DEPENDENCY" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -16424,8 +16448,8 @@ else pkg_failed=untried fi -if test -n "$OT_DEP_OPENSSL_LIBS"; then - pkg_cv_OT_DEP_OPENSSL_LIBS="$OT_DEP_OPENSSL_LIBS" +if test -n "$OT_DEP_CRYPTO_LIBS"; then + pkg_cv_OT_DEP_CRYPTO_LIBS="$OT_DEP_CRYPTO_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$OPENSSL_DEPENDENCY\""; } >&5 @@ -16433,7 +16457,7 @@ ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_OT_DEP_OPENSSL_LIBS=`$PKG_CONFIG --libs "$OPENSSL_DEPENDENCY" 2>/dev/null` + pkg_cv_OT_DEP_CRYPTO_LIBS=`$PKG_CONFIG --libs "$OPENSSL_DEPENDENCY" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -16454,22 +16478,22 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - OT_DEP_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` else - OT_DEP_OPENSSL_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$OPENSSL_DEPENDENCY" 2>&1` fi # Put the nasty error message in config.log where it belongs - echo "$OT_DEP_OPENSSL_PKG_ERRORS" >&5 + echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 as_fn_error $? "Package requirements ($OPENSSL_DEPENDENCY) were not met: -$OT_DEP_OPENSSL_PKG_ERRORS +$OT_DEP_CRYPTO_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. -Alternatively, you may set the environment variables OT_DEP_OPENSSL_CFLAGS -and OT_DEP_OPENSSL_LIBS to avoid the need to call pkg-config. +Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS +and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -16480,15 +16504,15 @@ is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. -Alternatively, you may set the environment variables OT_DEP_OPENSSL_CFLAGS -and OT_DEP_OPENSSL_LIBS to avoid the need to call pkg-config. +Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS +and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else - OT_DEP_OPENSSL_CFLAGS=$pkg_cv_OT_DEP_OPENSSL_CFLAGS - OT_DEP_OPENSSL_LIBS=$pkg_cv_OT_DEP_OPENSSL_LIBS + OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS + OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -16496,6 +16520,7 @@ $as_echo "#define HAVE_OPENSSL 1" >>confdefs.h + with_crypto=openssl with_openssl=yes else @@ -16513,6 +16538,115 @@ fi +GNUTLS_DEPENDENCY="gnutls >= 3.5.0" +if test $with_crypto = gnutls ; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OT_DEP_CRYPTO" >&5 +$as_echo_n "checking for OT_DEP_CRYPTO... " >&6; } + +if test -n "$OT_DEP_CRYPTO_CFLAGS"; then + pkg_cv_OT_DEP_CRYPTO_CFLAGS="$OT_DEP_CRYPTO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GNUTLS_DEPENDENCY\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$GNUTLS_DEPENDENCY") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OT_DEP_CRYPTO_CFLAGS=`$PKG_CONFIG --cflags "$GNUTLS_DEPENDENCY" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$OT_DEP_CRYPTO_LIBS"; then + pkg_cv_OT_DEP_CRYPTO_LIBS="$OT_DEP_CRYPTO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GNUTLS_DEPENDENCY\""; } >&5 + ($PKG_CONFIG --exists --print-errors "$GNUTLS_DEPENDENCY") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_OT_DEP_CRYPTO_LIBS=`$PKG_CONFIG --libs "$GNUTLS_DEPENDENCY" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` + else + OT_DEP_CRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GNUTLS_DEPENDENCY" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$OT_DEP_CRYPTO_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements ($GNUTLS_DEPENDENCY) were not met: + +$OT_DEP_CRYPTO_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS +and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables OT_DEP_CRYPTO_CFLAGS +and OT_DEP_CRYPTO_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + OT_DEP_CRYPTO_CFLAGS=$pkg_cv_OT_DEP_CRYPTO_CFLAGS + OT_DEP_CRYPTO_LIBS=$pkg_cv_OT_DEP_CRYPTO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +$as_echo "#define HAVE_GNUTLS 1" >>confdefs.h + + OSTREE_FEATURES="$OSTREE_FEATURES gnutls" + +fi + if test $with_crypto = gnutls; then + USE_GNUTLS_TRUE= + USE_GNUTLS_FALSE='#' +else + USE_GNUTLS_TRUE='#' + USE_GNUTLS_FALSE= +fi + + AVAHI_DEPENDENCY="avahi-client >= 0.6.31 avahi-glib >= 0.6.31" @@ -17577,6 +17711,10 @@ as_fn_error $? "conditional \"USE_OPENSSL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${USE_GNUTLS_TRUE}" && test -z "${USE_GNUTLS_FALSE}"; then + as_fn_error $? "conditional \"USE_GNUTLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${USE_AVAHI_TRUE}" && test -z "${USE_AVAHI_FALSE}"; then as_fn_error $? "conditional \"USE_AVAHI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -18030,7 +18168,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libostree $as_me 2017.11, which was +This file was extended by libostree $as_me 2017.12, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18096,7 +18234,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libostree config.status 2017.11 +libostree config.status 2017.12 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -19796,7 +19934,7 @@ HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux - OpenSSL libcrypto (checksums): $with_openssl + cryptographic checksums: $with_crypto systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive diff -Nru ostree-2017.11/configure.ac ostree-2017.12/configure.ac --- ostree-2017.11/configure.ac 2017-09-14 15:27:57.000000000 +0000 +++ ostree-2017.12/configure.ac 2017-10-02 17:11:19.000000000 +0000 @@ -4,7 +4,7 @@ dnl in test-symbols.sh, and also set is_release_build=yes below. Then make dnl another post-release commit to bump the version, and set is_release_build=no. m4_define([year_version], [2017]) -m4_define([release_version], [11]) +m4_define([release_version], [12]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) is_release_build=yes @@ -329,15 +329,29 @@ ]) AM_CONDITIONAL(USE_SMACK, test $with_smack != no) +dnl crypto +AC_ARG_WITH(crypto, +AS_HELP_STRING([--with-crypto], [Choose library for checksums, one of glib, openssl, gnutls (default: glib)]), +:, with_crypto=glib) + +AS_IF([test $with_crypto = glib], + [], + [test $with_crypto = openssl], + [with_openssl=yes], + [test $with_crypto = gnutls], + [], + [AC_MSG_ERROR([Invalid --with-crypto $with_crypto])] + ) + dnl begin openssl (really just libcrypto right now) +dnl Note this option is now deprecated in favor of --with-crypto=openssl OPENSSL_DEPENDENCY="libcrypto >= 1.0.1" AC_ARG_WITH(openssl, -AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]), -:, with_openssl=no) - +AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]),with_openssl=$withval,with_openssl=no) AS_IF([ test x$with_openssl != xno ], [ - PKG_CHECK_MODULES(OT_DEP_OPENSSL, $OPENSSL_DEPENDENCY) + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $OPENSSL_DEPENDENCY) AC_DEFINE([HAVE_OPENSSL], 1, [Define if we have openssl]) + with_crypto=openssl with_openssl=yes ], [ with_openssl=no @@ -346,6 +360,17 @@ AM_CONDITIONAL(USE_OPENSSL, test $with_openssl != no) dnl end openssl +dnl begin gnutls; in contrast to openssl this one only +dnl supports --with-crypto=gnutls +GNUTLS_DEPENDENCY="gnutls >= 3.5.0" +AS_IF([ test $with_crypto = gnutls ], [ + PKG_CHECK_MODULES(OT_DEP_CRYPTO, $GNUTLS_DEPENDENCY) + AC_DEFINE([HAVE_GNUTLS], 1, [Define if we have gnutls]) + OSTREE_FEATURES="$OSTREE_FEATURES gnutls" +]) +AM_CONDITIONAL(USE_GNUTLS, test $with_crypto = gnutls) +dnl end gnutls + dnl Avahi dependency for finding repos AVAHI_DEPENDENCY="avahi-client >= 0.6.31 avahi-glib >= 0.6.31" @@ -536,7 +561,7 @@ HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux - OpenSSL libcrypto (checksums): $with_openssl + cryptographic checksums: $with_crypto systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive diff -Nru ostree-2017.11/debian/changelog ostree-2017.12/debian/changelog --- ostree-2017.11/debian/changelog 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/changelog 2017-10-04 17:39:04.000000000 +0000 @@ -1,3 +1,30 @@ +ostree (2017.12-1ubuntu1) artful; urgency=medium + + * Sync with Debian. Remaining change: + - Don't Depend or Build-Depend on gjs on s390x since gjs is not built + for that architecture. + + -- Jeremy Bicha Wed, 04 Oct 2017 13:39:04 -0400 + +ostree (2017.12-1) unstable; urgency=medium + + * New upstream release + - Drop all current patches, applied upstream + - Update symbols file + * Add some post-release bug fix patches + * Simplify autopkgtest now that test-local-pull seems to be stable + * Unexport HTTP proxy variables in autopkgtest to work around lack of + support for no_proxy, which breaks the tests on Ubuntu autopkgtest. + We don't actually need Internet access, so this is OK. + * debian/test.sh: Unexport HTTP proxy variables for build-time tests + too + * Make build-time test failures fatal if they fail at least twice + out of 5 tries (previously they had to fail at least 3 times) + * Add patch to reinstate test-libglnx-shutil.c, which was missed out + of the upstream tarball + + -- Simon McVittie Tue, 03 Oct 2017 22:47:48 +0100 + ostree (2017.11-2ubuntu1) artful; urgency=medium * Sync with Debian. diff -Nru ostree-2017.11/debian/libostree-1-1.symbols ostree-2017.12/debian/libostree-1-1.symbols --- ostree-2017.11/debian/libostree-1-1.symbols 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/libostree-1-1.symbols 2017-10-04 17:39:04.000000000 +0000 @@ -17,6 +17,7 @@ LIBOSTREE_2017.9@LIBOSTREE_2017.9 2017.9 LIBOSTREE_2017.10@LIBOSTREE_2017.10 2017.10 LIBOSTREE_2017.11@LIBOSTREE_2017.11 2017.11 + LIBOSTREE_2017.12@LIBOSTREE_2017.12 2017.12 ostree_async_progress_finish@LIBOSTREE_2016.3 2016.4 ostree_async_progress_get@LIBOSTREE_2017.6 2017.6 ostree_async_progress_get_status@LIBOSTREE_2016.3 2016.4 @@ -161,6 +162,7 @@ ostree_repo_devino_cache_new@LIBOSTREE_2016.3 2016.4 ostree_repo_devino_cache_ref@LIBOSTREE_2016.3 2016.4 ostree_repo_devino_cache_unref@LIBOSTREE_2016.3 2016.4 + ostree_repo_equal@LIBOSTREE_2017.12 2017.12 ostree_repo_export_tree_to_archive@LIBOSTREE_2016.3 2016.3 ostree_repo_file_ensure_resolved@LIBOSTREE_2016.3 2016.4 ostree_repo_file_get_checksum@LIBOSTREE_2016.3 2016.4 @@ -187,6 +189,7 @@ ostree_repo_get_type@LIBOSTREE_2016.3 2016.4 ostree_repo_gpg_verify_data@LIBOSTREE_2016.6 2016.6 ostree_repo_has_object@LIBOSTREE_2016.3 2016.4 + ostree_repo_hash@LIBOSTREE_2017.12 2017.12 ostree_repo_import_archive_to_mtree@LIBOSTREE_2016.3 2016.3 ostree_repo_import_object_from@LIBOSTREE_2016.3 2016.4 ostree_repo_import_object_from_with_trust@LIBOSTREE_2016.5 2016.5 diff -Nru ostree-2017.11/debian/patches/2017.12/rofiles-fuse-also-pass-mode-for-O_RDONLY.patch ostree-2017.12/debian/patches/2017.12/rofiles-fuse-also-pass-mode-for-O_RDONLY.patch --- ostree-2017.11/debian/patches/2017.12/rofiles-fuse-also-pass-mode-for-O_RDONLY.patch 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.12/rofiles-fuse-also-pass-mode-for-O_RDONLY.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -From: Jonathan Lebon -Date: Wed, 20 Sep 2017 18:38:16 +0000 -Subject: rofiles-fuse: also pass mode for O_RDONLY - -In the `O_RDONLY` case, we were calling `openat` without a mode -argument. However, it's perfectly legal (albeit unusual) to do -`open(O_RDONLY|O_CREAT)`. One such application that makes use of this is -`flock(1)`. - -This was actually caught by `_FORTIFY_SOURCE=2`, and once we run -`rofiles-fuse` with `-f`, the message is clear: - -``` -*** invalid openat64 call: O_CREAT or O_TMPFILE without mode ***: -rofiles-fuse terminated -======= Backtrace: ========= -/lib64/libc.so.6(+0x7c8dc)[0x7f36d9f188dc] -/lib64/libc.so.6(__fortify_fail+0x37)[0x7f36d9fbfaa7] -/lib64/libc.so.6(+0x10019a)[0x7f36d9f9c19a] -rofiles-fuse[0x401768] -... -``` - -Without `_FORTIFY_SOURCE`, the file gets created, but its mode is -completely random. - -I ran into this while investigating -https://github.com/projectatomic/rpm-ostree/pull/1003. - -Closes: #1200 -Approved by: cgwalters -Origin: upstream, 2017.12, commit:d4c7093e370843c57eab2f89f0c39ef449e6b32e ---- - src/rofiles-fuse/main.c | 2 +- - tests/test-rofiles-fuse.sh | 5 ++++- - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/rofiles-fuse/main.c b/src/rofiles-fuse/main.c -index 6deaa6d..f2b1b65 100644 ---- a/src/rofiles-fuse/main.c -+++ b/src/rofiles-fuse/main.c -@@ -313,7 +313,7 @@ do_open (const char *path, mode_t mode, struct fuse_file_info *finfo) - if ((finfo->flags & O_ACCMODE) == O_RDONLY) - { - /* Read */ -- fd = openat (basefd, path, finfo->flags); -+ fd = openat (basefd, path, finfo->flags, mode); - if (fd == -1) - return -errno; - } -diff --git a/tests/test-rofiles-fuse.sh b/tests/test-rofiles-fuse.sh -index d329d76..6222929 100755 ---- a/tests/test-rofiles-fuse.sh -+++ b/tests/test-rofiles-fuse.sh -@@ -26,7 +26,7 @@ skip_without_user_xattrs - - setup_test_repository "bare" - --echo "1..7" -+echo "1..8" - - cd ${test_tmpdir} - mkdir mnt -@@ -114,3 +114,6 @@ fi - assert_file_has_content err.txt "Unable to do hardlink checkout across devices" - - echo "ok checkout copy fallback" -+ -+# check that O_RDONLY|O_CREAT is handled correctly; used by flock(1) at least -+flock mnt/nonexistent-file echo "ok create file in ro mode" diff -Nru ostree-2017.11/debian/patches/2017.12/tests-Explicitly-unset-LANGUAGE-after-setting-LC_ALL.patch ostree-2017.12/debian/patches/2017.12/tests-Explicitly-unset-LANGUAGE-after-setting-LC_ALL.patch --- ostree-2017.11/debian/patches/2017.12/tests-Explicitly-unset-LANGUAGE-after-setting-LC_ALL.patch 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.12/tests-Explicitly-unset-LANGUAGE-after-setting-LC_ALL.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -From: Simon McVittie -Date: Tue, 19 Sep 2017 14:41:18 +0100 -Subject: tests: Explicitly unset LANGUAGE after setting LC_ALL - -As a GNU extension, LANGUAGE takes precedence over LC_ALL for -gettext(3) whenever the locale is not C, causing tests that grep for -specific English strings to fail when run in non-English locales. -The upstream glibc proposal for C.UTF-8 would give C.UTF-8 the same -special case as C here, but the implementation in Debian does not -currently have this, so we have to unset LANGUAGE too. - -Signed-off-by: Simon McVittie -Forwarded: https://github.com/ostreedev/ostree/pull/1188 -Applied-upstream: 2017.12, commit:223c940b46a4bb335665df7436566b73cdf0effd ---- - tests/libtest-core.sh | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/tests/libtest-core.sh b/tests/libtest-core.sh -index d0b7d37..ce0e4bb 100644 ---- a/tests/libtest-core.sh -+++ b/tests/libtest-core.sh -@@ -40,6 +40,8 @@ if locale -a | grep C.UTF-8 >/dev/null; then - else - export LC_ALL=C - fi -+# A GNU extension, used whenever LC_ALL is not C -+unset LANGUAGE - - # This should really be the default IMO - export G_DEBUG=fatal-warnings diff -Nru ostree-2017.11/debian/patches/2017.12/tests-Fix-JavaScript-tests-with-gjs-1.50.0.patch ostree-2017.12/debian/patches/2017.12/tests-Fix-JavaScript-tests-with-gjs-1.50.0.patch --- ostree-2017.11/debian/patches/2017.12/tests-Fix-JavaScript-tests-with-gjs-1.50.0.patch 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.12/tests-Fix-JavaScript-tests-with-gjs-1.50.0.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -From: Simon McVittie -Date: Fri, 15 Sep 2017 15:32:55 +0100 -Subject: tests: Fix JavaScript tests with gjs 1.50.0 - -In recent gjs, you can't declare a variable with "let" multiple times. - -Signed-off-by: Simon McVittie -Closes: #1178 -Approved by: cgwalters -Forwarded: https://github.com/ostreedev/ostree/pull/1178 -Applied-upstream: 2017.12, commit:1b430a776486d68be2d16a0ec53ad5512c604988 ---- - tests/corrupt-repo-ref.js | 1 - - tests/test-sysroot.js | 6 +++--- - 2 files changed, 3 insertions(+), 4 deletions(-) - -diff --git a/tests/corrupt-repo-ref.js b/tests/corrupt-repo-ref.js -index c5f2806..bcde86b 100755 ---- a/tests/corrupt-repo-ref.js -+++ b/tests/corrupt-repo-ref.js -@@ -47,7 +47,6 @@ function listObjectChecksumsRecurse(dir, allObjects) { - e.close(null); - } - --let [,commit] = repo.resolve_rev(refToCorrupt, false); - let [,root,commit] = repo.read_commit(refToCorrupt, null); - let allObjects = {}; - allObjects[commit + '.commit'] = true; -diff --git a/tests/test-sysroot.js b/tests/test-sysroot.js -index 40397fe..e7250a8 100755 ---- a/tests/test-sysroot.js -+++ b/tests/test-sysroot.js -@@ -97,9 +97,9 @@ assertEquals(deploymentPath.query_exists(null), false); - - //// Ok, redeploy, then add a new revision upstream and pull it - --let [,deployment] = sysroot.deploy_tree('testos', rev, origin, -- mergeDeployment, null, -- null); -+[,deployment] = sysroot.deploy_tree('testos', rev, origin, -+ mergeDeployment, null, -+ null); - newDeployments = deployments; - deployments = null; - newDeployments.unshift(deployment); diff -Nru ostree-2017.11/debian/patches/2017.12/tests-Reset-umask-to-022-while-creating-test-repository.patch ostree-2017.12/debian/patches/2017.12/tests-Reset-umask-to-022-while-creating-test-repository.patch --- ostree-2017.11/debian/patches/2017.12/tests-Reset-umask-to-022-while-creating-test-repository.patch 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.12/tests-Reset-umask-to-022-while-creating-test-repository.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -From: Simon McVittie -Date: Tue, 19 Sep 2017 18:37:58 +0100 -Subject: tests: Reset umask to 022 while creating test repository - -In test-basic-root.sh we make assertions about the permissions -of files like baz/cow, which were created without an explicit chmod. -We can't do that unless we control the permissions. - -For some reason the "debomatic" autobuilder used to do some Debian -archive rebuilds does the entire build including build-time tests -as uid 0 with umask 002, which broke those assertions. This seems -a weird thing to do, and I've opened a bug, but it also seems -reasonable to fix this test. - -This also lets us remove a couple of existing workarounds for the -same issue. - -Bug-Debian: https://bugs.debian.org/876138 -Signed-off-by: Simon McVittie -Closes: #1192 -Approved by: cgwalters -Forwarded: https://github.com/ostreedev/ostree/pull/1192 -Applied-upstream: 2017.12, commit:e3c3ec5dd91492e82c79223052443d038c60f41c ---- - tests/libtest.sh | 3 +++ - tests/test-basic-user.sh | 8 ++------ - 2 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/tests/libtest.sh b/tests/libtest.sh -index 73e8889..1ae04a7 100755 ---- a/tests/libtest.sh -+++ b/tests/libtest.sh -@@ -150,6 +150,8 @@ setup_test_repository () { - export OSTREE="${CMD_PREFIX} ostree ${ot_repo}" - - cd ${test_tmpdir} -+ local oldumask="$(umask)" -+ umask 022 - mkdir files - cd files - ot_files=`pwd` -@@ -172,6 +174,7 @@ setup_test_repository () { - ln -s nonexistent baz/alink - mkdir baz/another/ - echo x > baz/another/y -+ umask "${oldumask}" - - cd ${test_tmpdir}/files - $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Test Commit 2" -m "Commit body second" -diff --git a/tests/test-basic-user.sh b/tests/test-basic-user.sh -index 9486655..291806c 100755 ---- a/tests/test-basic-user.sh -+++ b/tests/test-basic-user.sh -@@ -34,11 +34,7 @@ setup_test_repository "bare-user" - - cd ${test_tmpdir} - objpath_nonexec=$(ostree_file_path_to_object_path repo test2 baz/cow) --# Sigh, umask --touch testfile --default_mode=$(stat -c '%a' testfile) --rm testfile --assert_file_has_mode ${objpath_nonexec} ${default_mode} -+assert_file_has_mode ${objpath_nonexec} 644 - objpath_ro=$(ostree_file_path_to_object_path repo test2 baz/cowro) - assert_file_has_mode ${objpath_ro} 600 - objpath_exec=$(ostree_file_path_to_object_path repo test2 baz/deeper/ohyeahx) -@@ -48,7 +44,7 @@ echo "ok bare-user committed modes" - rm test2-checkout -rf - $OSTREE checkout -U -H test2 test2-checkout - cd test2-checkout --assert_file_has_mode baz/cow ${default_mode} -+assert_file_has_mode baz/cow 644 - assert_file_has_mode baz/cowro 600 - assert_file_has_mode baz/deeper/ohyeahx 755 - echo "ok bare-user checkout modes" diff -Nru ostree-2017.11/debian/patches/2017.13/lib-pull-Fix-regression-with-pull-local-for-nonexistent-r.patch ostree-2017.12/debian/patches/2017.13/lib-pull-Fix-regression-with-pull-local-for-nonexistent-r.patch --- ostree-2017.11/debian/patches/2017.13/lib-pull-Fix-regression-with-pull-local-for-nonexistent-r.patch 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.13/lib-pull-Fix-regression-with-pull-local-for-nonexistent-r.patch 2017-10-04 17:39:04.000000000 +0000 @@ -0,0 +1,90 @@ +From: Colin Walters +Date: Mon, 2 Oct 2017 11:24:05 -0400 +Subject: lib/pull: Fix regression with pull-local for nonexistent refs + +I was reading the pull code for the last release, and spotted +a bug in commit f923c2e1eaebe0c781f07d34ae1a03f94357bccd - in +the case where the ref doesn't exist, we don't set an error, +tripping an assertion in the main code. + +The previous code wanted the ref to always exist, so just flip back the boolean +for "ignore noent". I moved the `g_strchomp()` just into the HTTP path - if a +local repo is corrupted in this way it's something to fix in that repo. + +Closes: #1238 +Approved by: pwithnall +Origin: upstream, 2017.13, commit:b8c15ae859de7a353b99c98c6266ee626cd94e7e +--- + src/libostree/ostree-repo-pull.c | 13 ++++++------- + tests/pull-test.sh | 10 +++++++++- + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c +index 8a699ca..d5062e0 100644 +--- a/src/libostree/ostree-repo-pull.c ++++ b/src/libostree/ostree-repo-pull.c +@@ -844,7 +844,7 @@ fetch_ref_contents (OtPullData *pull_data, + { + #ifdef OSTREE_ENABLE_EXPERIMENTAL_API + if (!ostree_repo_resolve_collection_ref (pull_data->remote_repo_local, +- ref, TRUE /* ignore enoent */, ++ ref, FALSE, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, cancellable, error)) + return FALSE; +@@ -855,7 +855,7 @@ fetch_ref_contents (OtPullData *pull_data, + else if (pull_data->remote_repo_local != NULL) + { + if (!ostree_repo_resolve_rev_ext (pull_data->remote_repo_local, +- ref->ref_name, TRUE /* ignore enoent */, ++ ref->ref_name, FALSE, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, error)) + return FALSE; +@@ -874,14 +874,13 @@ fetch_ref_contents (OtPullData *pull_data, + filename, &ret_contents, + cancellable, error)) + return FALSE; ++ ++ g_strchomp (ret_contents); + } + +- /* Validate and return. */ +- if (ret_contents != NULL) +- g_strchomp (ret_contents); ++ g_assert (ret_contents); + +- if (ret_contents == NULL || +- !ostree_validate_checksum_string (ret_contents, error)) ++ if (!ostree_validate_checksum_string (ret_contents, error)) + return glnx_prefix_error (error, "Fetching checksum for ref (%s, %s)", + ref->collection_id ? ref->collection_id : "(empty)", + ref->ref_name); +diff --git a/tests/pull-test.sh b/tests/pull-test.sh +index 7d4b57f..2afc0ac 100644 +--- a/tests/pull-test.sh ++++ b/tests/pull-test.sh +@@ -35,7 +35,7 @@ function verify_initial_contents() { + assert_file_has_content baz/cow '^moo$' + } + +-echo "1..31" ++echo "1..32" + + # Try both syntaxes + repo_init --no-gpg-verify +@@ -238,6 +238,14 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo-local rev-parse localbranch + ${CMD_PREFIX} ostree --repo=mirrorrepo-local fsck + echo "ok pull-local mirror errors with mixed refs" + ++rm -f otherrepo/summary ++if ${CMD_PREFIX} ostree --repo=mirrorrepo-local pull-local otherrepo nosuchbranch 2>err.txt; then ++ fatal "pulled nonexistent branch" ++fi ++# So true ++assert_file_has_content_literal err.txt "error: Refspec 'nosuchbranch' not found" ++echo "ok pull-local nonexistent branch" ++ + cd ${test_tmpdir} + ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit -b main -s "Metadata string" --add-detached-metadata-string=SIGNATURE=HANCOCK --tree=ref=main + ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u diff -Nru ostree-2017.11/debian/patches/2017.13/lib-repo-commit-Import-detached-metadata-even-if-hardlink.patch ostree-2017.12/debian/patches/2017.13/lib-repo-commit-Import-detached-metadata-even-if-hardlink.patch --- ostree-2017.11/debian/patches/2017.13/lib-repo-commit-Import-detached-metadata-even-if-hardlink.patch 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/debian/patches/2017.13/lib-repo-commit-Import-detached-metadata-even-if-hardlink.patch 2017-10-04 17:39:04.000000000 +0000 @@ -0,0 +1,30 @@ +From: Philip Withnall +Date: Tue, 3 Oct 2017 15:45:34 +0100 +Subject: lib/repo-commit: Import detached metadata even if hardlink exists + +Spotted while reading through the code, it looks like the +copy_detached_metadata() call is accidentally omitted if a hardlink +already exists for the .commit object. + +Signed-off-by: Philip Withnall + +Closes: #1242 +Approved by: cgwalters +Origin: upstream, 2017.13, commit:86e072bdbe48a4f16efb05c00eb79114e5fdbf61 +--- + src/libostree/ostree-repo-commit.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c +index c4484f4..76bc187 100644 +--- a/src/libostree/ostree-repo-commit.c ++++ b/src/libostree/ostree-repo-commit.c +@@ -3255,7 +3255,7 @@ import_one_object_direct (OstreeRepo *dest_repo, + if (linkat (src_repo->objects_dir_fd, loose_path_buf, dest_dfd, loose_path_buf, 0) != 0) + { + if (errno == EEXIST) +- return TRUE; ++ did_hardlink = TRUE; + else if (errno == EMLINK || errno == EXDEV || errno == EPERM) + { + /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do diff -Nru ostree-2017.11/debian/patches/dist/Add-missing-test-libglnx-shutil.patch ostree-2017.12/debian/patches/dist/Add-missing-test-libglnx-shutil.patch --- ostree-2017.11/debian/patches/dist/Add-missing-test-libglnx-shutil.patch 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/debian/patches/dist/Add-missing-test-libglnx-shutil.patch 2017-10-04 17:39:04.000000000 +0000 @@ -0,0 +1,108 @@ +From: Simon McVittie +Date: Tue, 3 Oct 2017 21:30:36 +0100 +Subject: Add missing test-libglnx-shutil + +Because we re-run autogen.sh, we'll regenerate Makefile-libglnx.am.inc +(which results in the version after this patch, including +test-libglnx-shutil, being present) and then try to build +test-libglnx-shutil; but its source code wasn't included in the upstream +tarball, because Makefile-libglnx.am.inc wasn't up to date at +"make dist" time. + +Signed-off-by: Simon McVittie +--- + libglnx/Makefile-libglnx.am.inc | 6 +++- + libglnx/tests/test-libglnx-shutil.c | 63 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 1 deletion(-) + create mode 100644 libglnx/tests/test-libglnx-shutil.c + +diff --git a/libglnx/Makefile-libglnx.am.inc b/libglnx/Makefile-libglnx.am.inc +index 8766e63..ff2700c 100644 +--- a/libglnx/Makefile-libglnx.am.inc ++++ b/libglnx/Makefile-libglnx.am.inc +@@ -53,7 +53,7 @@ libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) + libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined -export-dynamic + libglnx_la_LIBADD = $(libglnx_libs) + +-libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros ++libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros test-libglnx-shutil + TESTS += $(libglnx_tests) + + check_PROGRAMS += $(libglnx_tests) +@@ -72,3 +72,7 @@ test_libglnx_errors_LDADD = $(libglnx_libs) libglnx.la + test_libglnx_macros_SOURCES = libglnx/tests/test-libglnx-macros.c + test_libglnx_macros_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) + test_libglnx_macros_LDADD = $(libglnx_libs) libglnx.la ++ ++test_libglnx_shutil_SOURCES = libglnx/tests/test-libglnx-shutil.c ++test_libglnx_shutil_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) ++test_libglnx_shutil_LDADD = $(libglnx_libs) libglnx.la +diff --git a/libglnx/tests/test-libglnx-shutil.c b/libglnx/tests/test-libglnx-shutil.c +new file mode 100644 +index 0000000..39f261b +--- /dev/null ++++ b/libglnx/tests/test-libglnx-shutil.c +@@ -0,0 +1,63 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- ++ * ++ * Copyright © 2017 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. ++ */ ++ ++#include "config.h" ++#include "libglnx.h" ++#include ++#include ++#include ++#include ++#include ++ ++#include "libglnx-testlib.h" ++ ++static void ++test_mkdir_p_enoent (void) ++{ ++ _GLNX_TEST_DECLARE_ERROR(local_error, error); ++ glnx_fd_close int dfd = -1; ++ ++ if (!glnx_ensure_dir (AT_FDCWD, "test", 0755, error)) ++ return; ++ if (!glnx_opendirat (AT_FDCWD, "test", FALSE, &dfd, error)) ++ return; ++ if (rmdir ("test") < 0) ++ return (void) glnx_throw_errno_prefix (error, "rmdir(%s)", "test"); ++ ++ /* This should fail with ENOENT. */ ++ glnx_shutil_mkdir_p_at (dfd, "blah/baz", 0755, NULL, error); ++ g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND); ++ g_clear_error (&local_error); ++} ++ ++int ++main (int argc, ++ char **argv) ++{ ++ int ret; ++ ++ g_test_init (&argc, &argv, NULL); ++ ++ g_test_add_func ("/mkdir-p/enoent", test_mkdir_p_enoent); ++ ++ ret = g_test_run(); ++ ++ return ret; ++} diff -Nru ostree-2017.11/debian/patches/series ostree-2017.12/debian/patches/series --- ostree-2017.11/debian/patches/series 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/patches/series 2017-10-04 17:39:04.000000000 +0000 @@ -1,4 +1,3 @@ -2017.12/tests-Fix-JavaScript-tests-with-gjs-1.50.0.patch -2017.12/tests-Explicitly-unset-LANGUAGE-after-setting-LC_ALL.patch -2017.12/tests-Reset-umask-to-022-while-creating-test-repository.patch -2017.12/rofiles-fuse-also-pass-mode-for-O_RDONLY.patch +2017.13/lib-pull-Fix-regression-with-pull-local-for-nonexistent-r.patch +2017.13/lib-repo-commit-Import-detached-metadata-even-if-hardlink.patch +dist/Add-missing-test-libglnx-shutil.patch diff -Nru ostree-2017.11/debian/tests/control ostree-2017.12/debian/tests/control --- ostree-2017.11/debian/tests/control 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/tests/control 2017-10-04 17:39:04.000000000 +0000 @@ -1,4 +1,4 @@ -Tests: gnome-desktop-testing, test-local-pull +Tests: gnome-desktop-testing Depends: gnome-desktop-testing, ostree-tests Tests: build diff -Nru ostree-2017.11/debian/tests/gnome-desktop-testing ostree-2017.12/debian/tests/gnome-desktop-testing --- ostree-2017.11/debian/tests/gnome-desktop-testing 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/tests/gnome-desktop-testing 2017-10-04 17:39:04.000000000 +0000 @@ -3,20 +3,12 @@ set -e exec 2>&1 -e=0 +# Ubuntu provides internet access via a proxy, but libostree doesn't need +# that. However, libostree also doesn't support no_proxy, so it will try +# to use Ubuntu's proxy for localhost, and fail to reach itself. +unset ftp_proxy +unset http_proxy +unset https_proxy +unset no_proxy -tests="$(gnome-desktop-testing-runner -l libostree | while read t; do - t="${t%% *}" - - case "$t" in - (libostree/test-local-pull.sh.test) - # frequently times out, https://bugs.debian.org/842606 - # https://github.com/ostreedev/ostree/issues/605 - continue - ;; - esac - - echo "$t" -done)" - -gnome-desktop-testing-runner $tests +exec gnome-desktop-testing-runner libostree diff -Nru ostree-2017.11/debian/tests/test-local-pull ostree-2017.12/debian/tests/test-local-pull --- ostree-2017.11/debian/tests/test-local-pull 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/tests/test-local-pull 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ -#!/bin/sh - -set -e -exec 2>&1 - -N=3 -passed=0 - -for i in `seq 1 $N`; do - if gnome-desktop-testing-runner libostree/test-local-pull.sh.test; then - passed=$(( $passed + 1)) - fi -done - -echo "test-local-pull: passed $passed/$N attempts" - -if [ "$passed" -ne "$N" ]; then - exit 1 -fi diff -Nru ostree-2017.11/debian/test.sh ostree-2017.12/debian/test.sh --- ostree-2017.11/debian/test.sh 2017-09-25 13:14:36.000000000 +0000 +++ ostree-2017.12/debian/test.sh 2017-10-04 17:39:04.000000000 +0000 @@ -4,6 +4,15 @@ export VERBOSE=1 +# Ubuntu autopkgtest infra provides internet access via a proxy, and +# buildds could conceivably do the same, but libostree doesn't need +# that. However, libostree also doesn't support no_proxy, so it will try +# to use Ubuntu's proxy for localhost, and fail to reach itself. +unset ftp_proxy +unset http_proxy +unset https_proxy +unset no_proxy + try_tests=5 failed=0 @@ -29,7 +38,7 @@ # There are several race conditions that cause intermittent failures. # They are not actually a regression - we've just been luckier in the # past - so let newer versions build reliably. -if [ "$failed" -gt 2 ]; then +if [ "$failed" -gt 1 ]; then echo "Failed $failed out of $try_tests test runs; that seems bad" exit 1 elif [ "$failed" -gt 0 ]; then diff -Nru ostree-2017.11/libglnx/glnx-dirfd.c ostree-2017.12/libglnx/glnx-dirfd.c --- ostree-2017.11/libglnx/glnx-dirfd.c 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-dirfd.c 2017-10-01 17:38:42.000000000 +0000 @@ -23,8 +23,10 @@ #include #include +#include #include #include +#include /** * glnx_opendirat_with_errno: @@ -203,8 +205,8 @@ if (ret_dent->d_type == DT_UNKNOWN) { struct stat stbuf; - if (TEMP_FAILURE_RETRY (fstatat (dfd_iter->fd, ret_dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) != 0) - return glnx_throw_errno (error); + if (!glnx_fstatat (dfd_iter->fd, ret_dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; ret_dent->d_type = IFTODT (stbuf.st_mode); } } @@ -283,27 +285,36 @@ /** * 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 + * @tmpl: (type filename): Initial template directory name, last 6 characters will be replaced + * @mode: permissions with which to create the temporary directory + * @out_tmpdir: (out caller-allocates): Initialized tempdir structure * @error: Error * - * Similar to g_mkdtemp_full, but using openat. + * Somewhat similar to g_mkdtemp_full(), but fd-relative, and returns a + * structure that uses autocleanups. Note that the supplied @dfd lifetime + * must match or exceed that of @out_tmpdir in order to remove the directory. */ gboolean -glnx_mkdtempat (int dfd, - gchar *tmpl, - int mode, - GError **error) +glnx_mkdtempat (int dfd, const char *tmpl, int mode, + GLnxTmpDir *out_tmpdir, GError **error) { - int count; + g_return_val_if_fail (tmpl != NULL, FALSE); + g_return_val_if_fail (out_tmpdir != NULL, FALSE); + g_return_val_if_fail (!out_tmpdir->initialized, FALSE); - g_return_val_if_fail (tmpl != NULL, -1); + dfd = glnx_dirfd_canonicalize (dfd); - for (count = 0; count < 100; count++) + g_autofree char *path = g_strdup (tmpl); + for (int count = 0; count < 100; count++) { - glnx_gen_temp_name (tmpl); + glnx_gen_temp_name (path); - if (mkdirat (dfd, tmpl, mode) == -1) + /* Ideally we could use openat(O_DIRECTORY | O_CREAT | O_EXCL) here + * to create and open the directory atomically, but that’s not supported by + * current kernel versions: http://www.openwall.com/lists/oss-security/2014/11/26/14 + * (Tested on kernel 4.10.10-200.fc25.x86_64). For the moment, accept a + * TOCTTOU race here. */ + if (mkdirat (dfd, path, mode) == -1) { if (errno == EEXIST) continue; @@ -314,77 +325,109 @@ return glnx_throw_errno_prefix (error, "mkdirat"); } + /* And open it */ + glnx_fd_close int ret_dfd = -1; + if (!glnx_opendirat (dfd, path, FALSE, &ret_dfd, error)) + { + /* If we fail to open, let's try to clean up */ + (void)unlinkat (dfd, path, AT_REMOVEDIR); + return FALSE; + } + + /* Return the initialized directory struct */ + out_tmpdir->initialized = TRUE; + out_tmpdir->src_dfd = dfd; /* referenced; see above docs */ + out_tmpdir->fd = glnx_steal_fd (&ret_dfd); + out_tmpdir->path = g_steal_pointer (&path); return TRUE; } + /* Failure */ g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, - "mkstempat ran out of combinations to try."); + "glnx_mkdtempat ran out of combinations to try"); return FALSE; } /** - * glnx_mkdtempat_open: - * @dfd: Directory FD - * @tmpl: (type filename): template directory name, last 6 characters will be replaced + * glnx_mkdtemp: + * @tmpl: (type filename): Source template directory name, last 6 characters will be replaced * @mode: permissions to create the temporary directory with - * @out_dfd: (out caller-allocates): Return location for an FD for the new - * temporary directory, or `-1` on error + * @out_tmpdir: (out caller-allocates): Return location for tmpdir data * @error: Return location for a #GError, or %NULL * - * Similar to glnx_mkdtempat(), except it will open the resulting temporary - * directory and return a directory FD to it. + * Similar to glnx_mkdtempat(), but will use g_get_tmp_dir() as the parent + * directory to @tmpl. * * Returns: %TRUE on success, %FALSE otherwise * Since: UNRELEASED */ gboolean -glnx_mkdtempat_open (int dfd, - gchar *tmpl, - int mode, - int *out_dfd, - GError **error) -{ - /* FIXME: Ideally we could use openat(O_DIRECTORY | O_CREAT | O_EXCL) here - * to create and open the directory atomically, but that’s not supported by - * current kernel versions: http://www.openwall.com/lists/oss-security/2014/11/26/14 - * (Tested on kernel 4.10.10-200.fc25.x86_64). For the moment, accept a - * TOCTTOU race here. */ - *out_dfd = -1; - - if (!glnx_mkdtempat (dfd, tmpl, mode, error)) - return FALSE; - - return glnx_opendirat (dfd, tmpl, FALSE, out_dfd, error); +glnx_mkdtemp (const gchar *tmpl, + int mode, + GLnxTmpDir *out_tmpdir, + GError **error) +{ + g_autofree char *path = g_build_filename (g_get_tmp_dir (), tmpl, NULL); + return glnx_mkdtempat (AT_FDCWD, path, mode, + out_tmpdir, error); +} + +static gboolean +_glnx_tmpdir_free (GLnxTmpDir *tmpd, + gboolean delete_dir, + GCancellable *cancellable, + GError **error) +{ + /* Support being passed NULL so we work nicely in a GPtrArray */ + if (!(tmpd && tmpd->initialized)) + return TRUE; + g_assert_cmpint (tmpd->fd, !=, -1); + (void) close (tmpd->fd); + tmpd->fd = -1; + g_assert (tmpd->path); + g_assert_cmpint (tmpd->src_dfd, !=, -1); + g_autofree char *path = tmpd->path; /* Take ownership */ + tmpd->initialized = FALSE; + if (delete_dir) + { + if (!glnx_shutil_rm_rf_at (tmpd->src_dfd, path, cancellable, error)) + return FALSE; + } + return TRUE; } /** - * glnx_mkdtempat_open_in_system: - * @tmpl: (type filename): template directory name, last 6 characters will be replaced - * @mode: permissions to create the temporary directory with - * @out_dfd: (out caller-allocates): Return location for an FD for the new - * temporary directory, or `-1` on error - * @error: Return location for a #GError, or %NULL + * glnx_tmpdir_delete: + * @tmpf: Temporary dir + * @cancellable: Cancellable + * @error: Error * - * Similar to glnx_mkdtempat_open(), except it will use the system temporary - * directory (from g_get_tmp_dir()) as the parent directory to @tmpl. + * Deallocate a tmpdir, closing the fd and recursively deleting the path. This + * is normally called indirectly via glnx_tmpdir_cleanup() by the autocleanup + * attribute, but you can also invoke this directly. * - * Returns: %TRUE on success, %FALSE otherwise - * Since: UNRELEASED + * If an error occurs while deleting the filesystem path, @tmpf will still have + * been deallocated and should not be reused. + * + * See also `glnx_tmpdir_unset` to avoid deleting the path. */ gboolean -glnx_mkdtempat_open_in_system (gchar *tmpl, - int mode, - int *out_dfd, - GError **error) +glnx_tmpdir_delete (GLnxTmpDir *tmpf, GCancellable *cancellable, GError **error) { - glnx_fd_close int tmp_dfd = -1; - - *out_dfd = -1; - - if (!glnx_opendirat (-1, g_get_tmp_dir (), TRUE, &tmp_dfd, error)) - return FALSE; - - return glnx_mkdtempat_open (tmp_dfd, tmpl, mode, out_dfd, error); + return _glnx_tmpdir_free (tmpf, TRUE, cancellable, error); } - +/** + * glnx_tmpdir_unset: + * @tmpf: Temporary dir + * @cancellable: Cancellable + * @error: Error + * + * Deallocate a tmpdir, but do not delete the filesystem path. See also + * `glnx_tmpdir_delete()`. + */ +void +glnx_tmpdir_unset (GLnxTmpDir *tmpf) +{ + (void) _glnx_tmpdir_free (tmpf, FALSE, NULL, NULL); +} diff -Nru ostree-2017.11/libglnx/glnx-dirfd.h ostree-2017.12/libglnx/glnx-dirfd.h --- ostree-2017.11/libglnx/glnx-dirfd.h 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-dirfd.h 2017-10-02 16:43:47.000000000 +0000 @@ -92,7 +92,7 @@ * @mode: Mode * @error: Return location for a #GError, or %NULL * - * Wrapper around mkdirat() which ignores adds #GError support, ensures that + * Wrapper around mkdirat() which adds #GError support, ensures that * it retries on %EINTR, and also ignores `EEXIST`. * * See also `glnx_shutil_mkdir_p_at()` for recursive handling. @@ -113,20 +113,25 @@ return TRUE; } -gboolean glnx_mkdtempat (int dfd, - gchar *tmpl, - int mode, - GError **error); +typedef struct { + gboolean initialized; + int src_dfd; + int fd; + char *path; +} GLnxTmpDir; +gboolean glnx_tmpdir_delete (GLnxTmpDir *tmpf, GCancellable *cancellable, GError **error); +void glnx_tmpdir_unset (GLnxTmpDir *tmpf); +static inline void +glnx_tmpdir_cleanup (GLnxTmpDir *tmpf) +{ + (void)glnx_tmpdir_delete (tmpf, NULL, NULL); +} +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GLnxTmpDir, glnx_tmpdir_cleanup) -gboolean glnx_mkdtempat_open (int dfd, - gchar *tmpl, - int mode, - int *out_dfd, - GError **error); +gboolean glnx_mkdtempat (int dfd, const char *tmpl, int mode, + GLnxTmpDir *out_tmpdir, GError **error); -gboolean glnx_mkdtempat_open_in_system (gchar *tmpl, - int mode, - int *out_dfd, - GError **error); +gboolean glnx_mkdtemp (const char *tmpl, int mode, + GLnxTmpDir *out_tmpdir, GError **error); G_END_DECLS diff -Nru ostree-2017.11/libglnx/glnx-fdio.c ostree-2017.12/libglnx/glnx-fdio.c --- ostree-2017.11/libglnx/glnx-fdio.c 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-fdio.c 2017-10-02 16:43:47.000000000 +0000 @@ -112,7 +112,7 @@ return TRUE; } else - return glnx_throw_errno (error); + return glnx_throw_errno_prefix (error, "renameat"); } return TRUE; } @@ -168,9 +168,11 @@ return; if (!tmpf->initialized) return; - if (tmpf->fd == -1) - return; - (void) close (tmpf->fd); + if (tmpf->fd != -1) + { + if (close (tmpf->fd) < 0) + g_assert (errno != EBADF); + } /* If ->path is set, we're likely aborting due to an error. Clean it up */ if (tmpf->path) { @@ -180,20 +182,11 @@ tmpf->initialized = FALSE; } -/* Allocate a temporary file, using Linux O_TMPFILE if available. The file mode - * will be 0600. - * - * The result will be stored in @out_tmpf, which is caller allocated - * so you can store it on the stack in common scenarios. - * - * The directory fd @dfd must live at least as long as the output @out_tmpf. - */ -gboolean -glnx_open_tmpfile_linkable_at (int dfd, - const char *subpath, - int flags, - GLnxTmpfile *out_tmpf, - GError **error) +static gboolean +open_tmpfile_core (int dfd, const char *subpath, + int flags, + GLnxTmpfile *out_tmpf, + GError **error) { const guint mode = 0600; glnx_fd_close int fd = -1; @@ -201,9 +194,6 @@ dfd = glnx_dirfd_canonicalize (dfd); - /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */ - g_return_val_if_fail ((flags & O_EXCL) == 0, FALSE); - /* Creates a temporary file, that shall be renamed to "target" * later. If possible, this uses O_TMPFILE – in which case * "ret_path" will be returned as NULL. If not possible a the @@ -260,6 +250,29 @@ return FALSE; } +/* Allocate a temporary file, using Linux O_TMPFILE if available. The file mode + * will be 0600. + * + * The result will be stored in @out_tmpf, which is caller allocated + * so you can store it on the stack in common scenarios. + * + * The directory fd @dfd must live at least as long as the output @out_tmpf. + */ +gboolean +glnx_open_tmpfile_linkable_at (int dfd, + const char *subpath, + int flags, + GLnxTmpfile *out_tmpf, + GError **error) +{ + /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE; + * it's used for glnx_open_anonymous_tmpfile(). + */ + g_return_val_if_fail ((flags & O_EXCL) == 0, FALSE); + + return open_tmpfile_core (dfd, subpath, flags, out_tmpf, error); +} + /* A variant of `glnx_open_tmpfile_linkable_at()` which doesn't support linking. * Useful for true temporary storage. The fd will be allocated in /var/tmp to * ensure maximum storage space. @@ -269,7 +282,8 @@ GLnxTmpfile *out_tmpf, GError **error) { - if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, "/var/tmp", flags, out_tmpf, error)) + /* Add in O_EXCL */ + if (!open_tmpfile_core (AT_FDCWD, "/var/tmp", flags | O_EXCL, out_tmpf, error)) return FALSE; if (out_tmpf->path) { @@ -428,8 +442,8 @@ const guint maxreadlen = 4096; struct stat stbuf; - if (TEMP_FAILURE_RETRY (fstat (fd, &stbuf)) < 0) - return glnx_null_throw_errno (error); + if (!glnx_fstat (fd, &stbuf, error)) + return FALSE; gsize buf_allocated; if (S_ISREG (stbuf.st_mode) && stbuf.st_size > 0) @@ -597,7 +611,7 @@ c = g_malloc (l); n = TEMP_FAILURE_RETRY (readlinkat (dfd, subpath, c, l-1)); if (n < 0) - return glnx_null_throw_errno (error); + return glnx_null_throw_errno_prefix (error, "readlinkat"); if ((size_t) n < l-1) { @@ -644,7 +658,7 @@ if (TEMP_FAILURE_RETRY (fchownat (dest_dfd, dest_subpath, src_stbuf->st_uid, src_stbuf->st_gid, AT_SYMLINK_NOFOLLOW)) != 0) - return glnx_throw_errno (error); + return glnx_throw_errno_prefix (error, "fchownat"); return TRUE; } @@ -852,17 +866,22 @@ * glnx_file_copy_at: * @src_dfd: Source directory fd * @src_subpath: Subpath relative to @src_dfd + * @src_stbuf: (allow-none): Optional stat buffer for source; if a stat() has already been done * @dest_dfd: Target directory fd * @dest_subpath: Destination name * @copyflags: Flags * @cancellable: cancellable * @error: Error * - * Perform a full copy of the regular file or - * symbolic link from @src_subpath to @dest_subpath. - * - * If @src_subpath is anything other than a regular - * file or symbolic link, an error will be returned. + * Perform a full copy of the regular file or symbolic link from @src_subpath to + * @dest_subpath; if @src_subpath is anything other than a regular file or + * symbolic link, an error will be returned. + * + * If the source is a regular file and the destination exists as a symbolic + * link, the symbolic link will not be followed; rather the link itself will be + * replaced. Related to this: for regular files, when `GLNX_FILE_COPY_OVERWRITE` + * is specified, this function always uses `O_TMPFILE` (if available) and does a + * rename-into-place rather than `open(O_TRUNC)`. */ gboolean glnx_file_copy_at (int src_dfd, @@ -874,31 +893,23 @@ GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - int r; - int dest_open_flags; - struct timespec ts[2]; - glnx_fd_close int src_fd = -1; - glnx_fd_close int dest_fd = -1; - struct stat local_stbuf; - - if (g_cancellable_set_error_if_cancelled (cancellable, error)) - goto out; - + /* Canonicalize dfds */ src_dfd = glnx_dirfd_canonicalize (src_dfd); dest_dfd = glnx_dirfd_canonicalize (dest_dfd); + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return FALSE; + /* Automatically do stat() if no stat buffer was supplied */ + struct stat local_stbuf; if (!src_stbuf) { - if (fstatat (src_dfd, src_subpath, &local_stbuf, AT_SYMLINK_NOFOLLOW) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + if (!glnx_fstatat (src_dfd, src_subpath, &local_stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; src_stbuf = &local_stbuf; } + /* For symlinks, defer entirely to copy_symlink_at() */ if (S_ISLNK (src_stbuf->st_mode)) { return copy_symlink_at (src_dfd, src_subpath, src_stbuf, @@ -910,47 +921,31 @@ { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Cannot copy non-regular/non-symlink file: %s", src_subpath); - goto out; + return FALSE; } - if (!glnx_openat_rdonly (src_dfd, src_subpath, FALSE, &src_fd, error)) - goto out; - - dest_open_flags = O_WRONLY | O_CREAT | O_CLOEXEC | O_NOCTTY; - if (!(copyflags & GLNX_FILE_COPY_OVERWRITE)) - dest_open_flags |= O_EXCL; - else - dest_open_flags |= O_TRUNC; - - dest_fd = TEMP_FAILURE_RETRY (openat (dest_dfd, dest_subpath, dest_open_flags, src_stbuf->st_mode)); - if (dest_fd == -1) - { - glnx_set_error_from_errno (error); - goto out; - } + /* Regular file path below here */ - r = glnx_regfile_copy_bytes (src_fd, dest_fd, (off_t) -1); - if (r < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + glnx_fd_close int src_fd = -1; + if (!glnx_openat_rdonly (src_dfd, src_subpath, FALSE, &src_fd, error)) + return FALSE; - if (fchown (dest_fd, src_stbuf->st_uid, src_stbuf->st_gid) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + /* Open a tmpfile for dest. Particularly for AT_FDCWD calls, we really want to + * open in the target directory, otherwise we may not be able to link. + */ + g_auto(GLnxTmpfile) tmp_dest = { 0, }; + { char *dnbuf = strdupa (dest_subpath); + const char *dn = dirname (dnbuf); + if (!glnx_open_tmpfile_linkable_at (dest_dfd, dn, O_WRONLY | O_CLOEXEC, + &tmp_dest, error)) + return FALSE; + } - if (fchmod (dest_fd, src_stbuf->st_mode & 07777) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + if (glnx_regfile_copy_bytes (src_fd, tmp_dest.fd, (off_t) -1) < 0) + return glnx_throw_errno_prefix (error, "regfile copy"); - ts[0] = src_stbuf->st_atim; - ts[1] = src_stbuf->st_mtim; - (void) futimens (dest_fd, ts); + if (fchown (tmp_dest.fd, src_stbuf->st_uid, src_stbuf->st_gid) != 0) + return glnx_throw_errno_prefix (error, "fchown"); if (!(copyflags & GLNX_FILE_COPY_NOXATTRS)) { @@ -958,35 +953,40 @@ if (!glnx_fd_get_all_xattrs (src_fd, &xattrs, cancellable, error)) - goto out; + return FALSE; - if (!glnx_fd_set_all_xattrs (dest_fd, xattrs, + if (!glnx_fd_set_all_xattrs (tmp_dest.fd, xattrs, cancellable, error)) - goto out; + return FALSE; } + /* Always chmod after setting xattrs, in case the file has mode 0400 or less, + * like /etc/shadow. Linux currently allows write() on non-writable open files + * but not fsetxattr(). + */ + if (fchmod (tmp_dest.fd, src_stbuf->st_mode & 07777) != 0) + return glnx_throw_errno_prefix (error, "fchmod"); + + struct timespec ts[2]; + ts[0] = src_stbuf->st_atim; + ts[1] = src_stbuf->st_mtim; + (void) futimens (tmp_dest.fd, ts); + if (copyflags & GLNX_FILE_COPY_DATASYNC) { - if (fdatasync (dest_fd) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } - } - - r = close (dest_fd); - dest_fd = -1; - if (r < 0) - { - glnx_set_error_from_errno (error); - goto out; + if (fdatasync (tmp_dest.fd) < 0) + return glnx_throw_errno_prefix (error, "fdatasync"); } - ret = TRUE; - out: - if (!ret) - (void) unlinkat (dest_dfd, dest_subpath, 0); - return ret; + const GLnxLinkTmpfileReplaceMode replacemode = + (copyflags & GLNX_FILE_COPY_OVERWRITE) ? + GLNX_LINK_TMPFILE_REPLACE : + GLNX_LINK_TMPFILE_NOREPLACE; + + if (!glnx_link_tmpfile_at (&tmp_dest, replacemode, dest_dfd, dest_subpath, error)) + return FALSE; + + return TRUE; } /** @@ -1071,19 +1071,17 @@ return FALSE; if (glnx_loop_write (tmpf.fd, buf, len) < 0) - return glnx_throw_errno (error); + return glnx_throw_errno_prefix (error, "write"); if (!(flags & GLNX_FILE_REPLACE_NODATASYNC)) { struct stat stbuf; gboolean do_sync; - if (fstatat (dfd, subpath, &stbuf, AT_SYMLINK_NOFOLLOW) != 0) - { - if (errno != ENOENT) - return glnx_throw_errno (error); - do_sync = (flags & GLNX_FILE_REPLACE_DATASYNC_NEW) > 0; - } + if (!glnx_fstatat_allow_noent (dfd, subpath, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT) + do_sync = (flags & GLNX_FILE_REPLACE_DATASYNC_NEW) > 0; else do_sync = TRUE; @@ -1097,11 +1095,11 @@ if (uid != (uid_t) -1) { if (fchown (tmpf.fd, uid, gid) != 0) - return glnx_throw_errno (error); + return glnx_throw_errno_prefix (error, "fchown"); } if (fchmod (tmpf.fd, mode) != 0) - return glnx_throw_errno (error); + return glnx_throw_errno_prefix (error, "fchmod"); if (!glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_REPLACE, dfd, subpath, error)) diff -Nru ostree-2017.11/libglnx/glnx-fdio.h ostree-2017.12/libglnx/glnx-fdio.h --- ostree-2017.11/libglnx/glnx-fdio.h 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-fdio.h 2017-10-01 17:38:42.000000000 +0000 @@ -296,6 +296,44 @@ } /** + * glnx_fstatat_allow_noent: + * @dfd: Directory FD to stat beneath + * @path: Path to stat beneath @dfd + * @buf: (out caller-allocates): Return location for stat details + * @flags: Flags to pass to fstatat() + * @error: Return location for a #GError, or %NULL + * + * Like glnx_fstatat(), but handles `ENOENT` in a non-error way. Instead, + * on success `errno` will be zero, otherwise it will be preserved. Hence + * you can test `if (errno == 0)` to conditionalize on the file existing, + * or `if (errno == ENOENT)` for non-existence. + * + * Returns: %TRUE on success, %FALSE otherwise (errno is preserved) + * Since: UNRELEASED + */ +static inline gboolean +glnx_fstatat_allow_noent (int dfd, + const char *path, + struct stat *out_buf, + int flags, + GError **error) +{ + if (TEMP_FAILURE_RETRY (fstatat (dfd, path, out_buf, flags)) != 0) + { + if (errno != ENOENT) + { + int errsv = errno; + (void) glnx_throw_errno_prefix (error, "fstatat(%s)", path); + errno = errsv; + return FALSE; + } + } + else + errno = 0; + return TRUE; +} + +/** * glnx_renameat: * * Wrapper around renameat() which adds #GError support and ensures that it diff -Nru ostree-2017.11/libglnx/glnx-lockfile.c ostree-2017.12/libglnx/glnx-lockfile.c --- ostree-2017.11/libglnx/glnx-lockfile.c 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-lockfile.c 2017-10-02 16:43:47.000000000 +0000 @@ -105,7 +105,7 @@ r = flock(fd, operation); if (r < 0) - return glnx_throw_errno(error); + return glnx_throw_errno_prefix (error, "flock"); } /* If we acquired the lock, let's check if the file @@ -114,9 +114,8 @@ * it. In such a case our acquired lock is worthless, * hence try again. */ - r = fstat(fd, &st); - if (r < 0) - return glnx_throw_errno(error); + if (!glnx_fstat (fd, &st, error)) + return FALSE; if (st.st_nlink > 0) break; @@ -127,21 +126,18 @@ /* Note that if this is not AT_FDCWD, the caller takes responsibility * for the fd's lifetime being >= that of the lock. */ + out_lock->initialized = TRUE; out_lock->dfd = dfd; - out_lock->path = t; - out_lock->fd = fd; + out_lock->path = g_steal_pointer (&t); + out_lock->fd = glnx_steal_fd (&fd); out_lock->operation = operation; - - fd = -1; - t = NULL; - return TRUE; } void glnx_release_lock_file(GLnxLockFile *f) { int r; - if (!f) + if (!(f && f->initialized)) return; if (f->path) { @@ -182,4 +178,5 @@ (void) close (f->fd); f->fd = -1; f->operation = 0; + f->initialized = FALSE; } diff -Nru ostree-2017.11/libglnx/glnx-lockfile.h ostree-2017.12/libglnx/glnx-lockfile.h --- ostree-2017.11/libglnx/glnx-lockfile.h 2017-05-12 20:12:56.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-lockfile.h 2017-10-02 16:43:47.000000000 +0000 @@ -27,6 +27,7 @@ #include "glnx-backport-autoptr.h" typedef struct GLnxLockFile { + gboolean initialized; int dfd; char *path; int fd; @@ -37,5 +38,3 @@ void glnx_release_lock_file(GLnxLockFile *f); G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GLnxLockFile, glnx_release_lock_file) - -#define GLNX_LOCK_FILE_INIT { .fd = -1, .dfd = AT_FDCWD, .path = NULL } diff -Nru ostree-2017.11/libglnx/glnx-macros.h ostree-2017.12/libglnx/glnx-macros.h --- ostree-2017.11/libglnx/glnx-macros.h 2017-09-07 19:50:02.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-macros.h 2017-10-02 16:43:47.000000000 +0000 @@ -38,7 +38,7 @@ ({ \ const char *_appendees_[] = { a, __VA_ARGS__ }; \ char *_d_, *_p_; \ - int _len_ = 0; \ + size_t _len_ = 0; \ unsigned _i_; \ for (_i_ = 0; _i_ < G_N_ELEMENTS(_appendees_) && _appendees_[_i_]; _i_++) \ _len_ += strlen(_appendees_[_i_]); \ diff -Nru ostree-2017.11/libglnx/glnx-shutil.c ostree-2017.12/libglnx/glnx-shutil.c --- ostree-2017.11/libglnx/glnx-shutil.c 2017-09-07 19:50:02.000000000 +0000 +++ ostree-2017.12/libglnx/glnx-shutil.c 2017-10-02 16:43:47.000000000 +0000 @@ -148,7 +148,13 @@ g_assert (!did_recurse); lastslash = strrchr (path, '/'); - g_assert (lastslash != NULL); + if (lastslash == NULL) + { + /* This can happen if @dfd was deleted between being opened and + * passed to mkdir_p_at_internal(). */ + return glnx_throw_errno_prefix (error, "mkdir(%s)", path); + } + /* Note we can mutate the buffer as we dup'd it */ *lastslash = '\0'; @@ -187,6 +193,9 @@ * directory fd @dfd. * * See also glnx_ensure_dir() for a non-recursive version. + * + * This will return %G_IO_ERROR_NOT_FOUND if @dfd has been deleted since being + * opened. It may return other errors from mkdirat() in other situations. */ gboolean glnx_shutil_mkdir_p_at (int dfd, diff -Nru ostree-2017.11/libglnx/Makefile-libglnx.am ostree-2017.12/libglnx/Makefile-libglnx.am --- ostree-2017.11/libglnx/Makefile-libglnx.am 2017-09-07 19:50:02.000000000 +0000 +++ ostree-2017.12/libglnx/Makefile-libglnx.am 2017-10-02 16:43:47.000000000 +0000 @@ -46,13 +46,14 @@ $(libglnx_srcpath)/glnx-shutil.h \ $(libglnx_srcpath)/glnx-shutil.c \ $(libglnx_srcpath)/libglnx.h \ + $(libglnx_srcpath)/tests/libglnx-testlib.h \ $(NULL) libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) libglnx_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^glnx_" -no-undefined -export-dynamic libglnx_la_LIBADD = $(libglnx_libs) -libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros +libglnx_tests = test-libglnx-xattrs test-libglnx-fdio test-libglnx-errors test-libglnx-macros test-libglnx-shutil TESTS += $(libglnx_tests) check_PROGRAMS += $(libglnx_tests) @@ -71,3 +72,7 @@ test_libglnx_macros_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-macros.c test_libglnx_macros_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) test_libglnx_macros_LDADD = $(libglnx_libs) libglnx.la + +test_libglnx_shutil_SOURCES = $(libglnx_srcpath)/tests/test-libglnx-shutil.c +test_libglnx_shutil_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) +test_libglnx_shutil_LDADD = $(libglnx_libs) libglnx.la diff -Nru ostree-2017.11/libglnx/Makefile-libglnx.am.inc ostree-2017.12/libglnx/Makefile-libglnx.am.inc --- ostree-2017.11/libglnx/Makefile-libglnx.am.inc 2017-09-08 00:46:33.000000000 +0000 +++ ostree-2017.12/libglnx/Makefile-libglnx.am.inc 2017-09-27 00:43:12.000000000 +0000 @@ -46,6 +46,7 @@ libglnx/glnx-shutil.h \ libglnx/glnx-shutil.c \ libglnx/libglnx.h \ + libglnx/tests/libglnx-testlib.h \ $(NULL) libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) diff -Nru ostree-2017.11/libglnx/tests/libglnx-testlib.h ostree-2017.12/libglnx/tests/libglnx-testlib.h --- ostree-2017.11/libglnx/tests/libglnx-testlib.h 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/libglnx/tests/libglnx-testlib.h 2017-10-01 17:38:42.000000000 +0000 @@ -0,0 +1,34 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2017 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 + +typedef GError _GLnxTestAutoError; +static inline void +_glnx_test_auto_error_cleanup (_GLnxTestAutoError *autoerror) +{ + g_assert_no_error (autoerror); + /* We could add a clear call here, but no point...we'll have aborted */ +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC(_GLnxTestAutoError, _glnx_test_auto_error_cleanup); + +#define _GLNX_TEST_DECLARE_ERROR(local_error, error) \ + g_autoptr(_GLnxTestAutoError) local_error = NULL; \ + GError **error = &local_error diff -Nru ostree-2017.11/libglnx/tests/test-libglnx-fdio.c ostree-2017.12/libglnx/tests/test-libglnx-fdio.c --- ostree-2017.11/libglnx/tests/test-libglnx-fdio.c 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/tests/test-libglnx-fdio.c 2017-10-02 16:43:47.000000000 +0000 @@ -26,6 +26,8 @@ #include #include +#include "libglnx-testlib.h" + static gboolean renameat_test_setup (int *out_srcfd, int *out_destfd, GError **error) @@ -59,14 +61,13 @@ static void test_renameat2_noreplace (void) { - g_autoptr(GError) local_error = NULL; - GError **error = &local_error; + _GLNX_TEST_DECLARE_ERROR(local_error, error); glnx_fd_close int srcfd = -1; glnx_fd_close int destfd = -1; struct stat stbuf; if (!renameat_test_setup (&srcfd, &destfd, error)) - goto out; + return; if (glnx_renameat2_noreplace (srcfd, "foo", destfd, "bar") == 0) g_assert_not_reached (); @@ -76,117 +77,153 @@ } if (glnx_renameat2_noreplace (srcfd, "foo", destfd, "baz") < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return (void)glnx_throw_errno_prefix (error, "renameat"); if (!glnx_fstatat (destfd, "bar", &stbuf, AT_SYMLINK_NOFOLLOW, error)) - goto out; + return; if (fstatat (srcfd, "foo", &stbuf, AT_SYMLINK_NOFOLLOW) == 0) g_assert_not_reached (); else g_assert_cmpint (errno, ==, ENOENT); - - out: - g_assert_no_error (local_error); } static void test_renameat2_exchange (void) { - g_autoptr(GError) local_error = NULL; - GError **error = &local_error; + _GLNX_TEST_DECLARE_ERROR(local_error, error); + glnx_fd_close int srcfd = -1; glnx_fd_close int destfd = -1; - struct stat stbuf; - if (!renameat_test_setup (&srcfd, &destfd, error)) - goto out; + return; if (glnx_renameat2_exchange (AT_FDCWD, "srcdir", AT_FDCWD, "destdir") < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return (void)glnx_throw_errno_prefix (error, "renameat"); /* Ensure the dir fds are the same */ - if (fstatat (srcfd, "foo", &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } - if (fstatat (destfd, "bar", &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + struct stat stbuf; + if (!glnx_fstatat (srcfd, "foo", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; + if (!glnx_fstatat (destfd, "bar", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; /* But the dirs should be swapped */ - if (fstatat (AT_FDCWD, "destdir/foo", &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } - if (fstatat (AT_FDCWD, "srcdir/bar", &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } - - out: - g_assert_no_error (local_error); + if (!glnx_fstatat (AT_FDCWD, "destdir/foo", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; + if (!glnx_fstatat (AT_FDCWD, "srcdir/bar", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; } static void test_tmpfile (void) { - g_autoptr(GError) local_error = NULL; - GError **error = &local_error; - g_auto(GLnxTmpfile) tmpf = { 0, }; + _GLNX_TEST_DECLARE_ERROR(local_error, error); + g_auto(GLnxTmpfile) tmpf = { 0, }; if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_WRONLY|O_CLOEXEC, &tmpf, error)) - goto out; - + return; if (glnx_loop_write (tmpf.fd, "foo", strlen ("foo")) < 0) - { - (void)glnx_throw_errno_prefix (error, "write"); - goto out; - } - + return (void)glnx_throw_errno_prefix (error, "write"); if (glnx_link_tmpfile_at (&tmpf, GLNX_LINK_TMPFILE_NOREPLACE, AT_FDCWD, "foo", error)) - goto out; - - out: - g_assert_no_error (local_error); + return; } static void test_stdio_file (void) { - g_autoptr(GError) local_error = NULL; - GError **error = &local_error; + _GLNX_TEST_DECLARE_ERROR(local_error, error); g_auto(GLnxTmpfile) tmpf = { 0, }; g_autoptr(FILE) f = NULL; if (!glnx_open_anonymous_tmpfile (O_RDWR|O_CLOEXEC, &tmpf, error)) - goto out; + return; f = fdopen (tmpf.fd, "w"); + tmpf.fd = -1; /* Ownership was transferred via fdopen() */ if (!f) - { - (void)glnx_throw_errno_prefix (error, "fdopen"); - goto out; - } - + return (void)glnx_throw_errno_prefix (error, "fdopen"); if (fwrite ("hello", 1, strlen ("hello"), f) != strlen ("hello")) - { - (void)glnx_throw_errno_prefix (error, "fwrite"); - goto out; - } + return (void)glnx_throw_errno_prefix (error, "fwrite"); if (!glnx_stdio_file_flush (f, error)) - goto out; + return; +} + +static void +test_fstatat (void) +{ + _GLNX_TEST_DECLARE_ERROR(local_error, error); + struct stat stbuf = { 0, }; + + if (!glnx_fstatat_allow_noent (AT_FDCWD, ".", &stbuf, 0, error)) + return; + g_assert_cmpint (errno, ==, 0); + g_assert_no_error (local_error); + g_assert (S_ISDIR (stbuf.st_mode)); + if (!glnx_fstatat_allow_noent (AT_FDCWD, "nosuchfile", &stbuf, 0, error)) + return; + g_assert_cmpint (errno, ==, ENOENT); + g_assert_no_error (local_error); +} - out: +static void +test_filecopy (void) +{ + _GLNX_TEST_DECLARE_ERROR(local_error, error); + g_auto(GLnxTmpfile) tmpf = { 0, }; + const char foo[] = "foo"; + struct stat stbuf; + + if (!glnx_ensure_dir (AT_FDCWD, "subdir", 0755, error)) + return; + + if (!glnx_file_replace_contents_at (AT_FDCWD, foo, (guint8*)foo, sizeof (foo), + GLNX_FILE_REPLACE_NODATASYNC, NULL, error)) + return; + + /* Copy it into both the same dir and a subdir */ + if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "bar", + GLNX_FILE_COPY_NOXATTRS, NULL, error)) + return; + if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "subdir/bar", + GLNX_FILE_COPY_NOXATTRS, NULL, error)) + return; + if (!glnx_fstatat (AT_FDCWD, "subdir/bar", &stbuf, 0, error)) + return; + + if (glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "bar", + GLNX_FILE_COPY_NOXATTRS, NULL, error)) + g_assert_not_reached (); + g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS); + g_clear_error (&local_error); + + if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "bar", + GLNX_FILE_COPY_NOXATTRS | GLNX_FILE_COPY_OVERWRITE, + NULL, error)) + return; + + if (symlinkat ("nosuchtarget", AT_FDCWD, "link") < 0) + return (void) glnx_throw_errno_prefix (error, "symlinkat"); + + /* Shouldn't be able to overwrite a symlink without GLNX_FILE_COPY_OVERWRITE */ + if (glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "link", + GLNX_FILE_COPY_NOXATTRS, + NULL, error)) + g_assert_not_reached (); + g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS); + g_clear_error (&local_error); + + /* Test overwriting symlink */ + if (!glnx_file_copy_at (AT_FDCWD, foo, NULL, AT_FDCWD, "link", + GLNX_FILE_COPY_NOXATTRS | GLNX_FILE_COPY_OVERWRITE, + NULL, error)) + return; + + if (!glnx_fstatat_allow_noent (AT_FDCWD, "nosuchtarget", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; + g_assert_cmpint (errno, ==, ENOENT); g_assert_no_error (local_error); + + if (!glnx_fstatat (AT_FDCWD, "link", &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return; + g_assert (S_ISREG (stbuf.st_mode)); } int main (int argc, char **argv) @@ -197,8 +234,10 @@ g_test_add_func ("/tmpfile", test_tmpfile); g_test_add_func ("/stdio-file", test_stdio_file); + g_test_add_func ("/filecopy", test_filecopy); g_test_add_func ("/renameat2-noreplace", test_renameat2_noreplace); g_test_add_func ("/renameat2-exchange", test_renameat2_exchange); + g_test_add_func ("/fstat", test_fstatat); ret = g_test_run(); diff -Nru ostree-2017.11/libglnx/tests/test-libglnx-xattrs.c ostree-2017.12/libglnx/tests/test-libglnx-xattrs.c --- ostree-2017.11/libglnx/tests/test-libglnx-xattrs.c 2017-09-14 13:59:45.000000000 +0000 +++ ostree-2017.12/libglnx/tests/test-libglnx-xattrs.c 2017-10-01 17:38:42.000000000 +0000 @@ -223,19 +223,17 @@ GThread *threads[nprocs]; g_autoptr(GError) local_error = NULL; GError **error = &local_error; - glnx_fd_close int dfd = -1; - g_autofree char *tmpdir = g_strdup_printf ("%s/libglnx-xattrs-XXXXXX", - getenv ("TMPDIR") ?: "/var/tmp"); + g_auto(GLnxTmpDir) tmpdir = { 0, }; + g_autofree char *tmpdir_path = g_strdup_printf ("%s/libglnx-xattrs-XXXXXX", + getenv ("TMPDIR") ?: "/var/tmp"); guint nread = 0; - if (!glnx_mkdtempat (AT_FDCWD, tmpdir, 0700, error)) - goto out; - - if (!glnx_opendirat (AT_FDCWD, tmpdir, TRUE, &dfd, error)) + if (!glnx_mkdtempat (AT_FDCWD, tmpdir_path, 0700, + &tmpdir, error)) goto out; /* Support people building/testing on tmpfs https://github.com/flatpak/flatpak/issues/686 */ - if (fsetxattr (dfd, "user.test", "novalue", strlen ("novalue"), 0) < 0) + if (fsetxattr (tmpdir.fd, "user.test", "novalue", strlen ("novalue"), 0) < 0) { if (errno == EOPNOTSUPP) { @@ -252,7 +250,7 @@ for (guint i = 0; i < nprocs; i++) { struct XattrWorker *worker = &wdata[i]; - worker->dfd = dfd; + worker->dfd = tmpdir.fd; worker->is_writer = i % 2 == 0; threads[i] = g_thread_new (NULL, xattr_thread, worker); } @@ -267,8 +265,6 @@ g_print ("Read %u xattrs race free!\n", nread); - (void) glnx_shutil_rm_rf_at (AT_FDCWD, tmpdir, NULL, NULL); - out: g_assert_no_error (local_error); } diff -Nru ostree-2017.11/Makefile.in ostree-2017.12/Makefile.in --- ostree-2017.11/Makefile.in 2017-09-14 16:17:45.000000000 +0000 +++ ostree-2017.12/Makefile.in 2017-10-02 17:11:27.000000000 +0000 @@ -359,13 +359,13 @@ bin_PROGRAMS = ostree$(EXEEXT) $(am__EXEEXT_1) sbin_PROGRAMS = libexec_PROGRAMS = -pkglibexec_PROGRAMS = $(am__EXEEXT_18) -noinst_PROGRAMS = $(am__EXEEXT_15) tests/test-rollsum-cli$(EXEEXT) -ostree_boot_PROGRAMS = $(am__EXEEXT_16) $(am__EXEEXT_17) -TESTS = $(am__EXEEXT_8) $(am__EXEEXT_25) \ - $(dist_uninstalled_test_scripts) $(am__EXEEXT_12) -installed_test_PROGRAMS = $(am__EXEEXT_14) -check_PROGRAMS = $(am__EXEEXT_11) $(am__EXEEXT_12) $(am__EXEEXT_13) +pkglibexec_PROGRAMS = $(am__EXEEXT_20) +noinst_PROGRAMS = $(am__EXEEXT_17) tests/test-rollsum-cli$(EXEEXT) +ostree_boot_PROGRAMS = $(am__EXEEXT_18) $(am__EXEEXT_19) +TESTS = $(am__EXEEXT_8) $(am__EXEEXT_27) \ + $(dist_uninstalled_test_scripts) $(am__EXEEXT_14) +installed_test_PROGRAMS = $(am__EXEEXT_16) +check_PROGRAMS = $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) @ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_1 = $(all_test_ltlibs) @ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_2 = $(all_test_programs) @ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__append_3 = $(all_test_scripts) @@ -464,7 +464,11 @@ @BUILDOPT_INTROSPECTION_TRUE@am__append_44 = OSTree-1.0.gir @BUILDOPT_INTROSPECTION_TRUE@am__append_45 = OSTree-1.0.typelib @BUILDOPT_INTROSPECTION_TRUE@am__append_46 = $(gir_DATA) $(typelib_DATA) -@ENABLE_EXPERIMENTAL_API_TRUE@am__append_47 = src/ostree/ot-builtin-find-remotes.c +@ENABLE_EXPERIMENTAL_API_TRUE@am__append_47 = \ +@ENABLE_EXPERIMENTAL_API_TRUE@ src/ostree/ot-builtin-create-usb.c \ +@ENABLE_EXPERIMENTAL_API_TRUE@ src/ostree/ot-builtin-find-remotes.c \ +@ENABLE_EXPERIMENTAL_API_TRUE@ $(NULL) + @USE_CURL_OR_SOUP_TRUE@am__append_48 = src/ostree/ot-remote-builtin-add-cookie.c \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ot-remote-builtin-delete-cookie.c \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ot-remote-builtin-list-cookies.c \ @@ -499,38 +503,39 @@ @BUILDOPT_FUSE_TRUE@am__append_62 = rofiles-fuse @BUILDOPT_ASAN_TRUE@am__append_63 = OT_SKIP_READDIR_RAND=1 G_SLICE=always-malloc @ENABLE_EXPERIMENTAL_API_TRUE@am__append_64 = $(experimental_test_scripts) -@ENABLE_EXPERIMENTAL_API_FALSE@am__append_65 = $(experimental_test_scripts) -@BUILDOPT_FUSE_TRUE@am__append_66 = tests/test-rofiles-fuse.sh -@BUILDOPT_FUSE_FALSE@am__append_67 = tests/test-rofiles-fuse.sh -@USE_LIBSOUP_TRUE@am__append_68 = tests/test-remote-cookies.sh -@BUILDOPT_GJS_TRUE@am__append_69 = $(js_tests) $(js_installed_tests) -@BUILDOPT_GJS_FALSE@am__append_70 = $(js_tests) -@BUILDOPT_GJS_FALSE@am__append_71 = $(js_installed_tests) -@ENABLE_INSTALLED_TESTS_FALSE@am__append_72 = -rpath $(abs_builddir) -@ENABLE_EXPERIMENTAL_API_TRUE@am__append_73 = \ +@ENABLE_EXPERIMENTAL_API_TRUE@am__append_65 = tests/repo-finder-mount +@ENABLE_EXPERIMENTAL_API_FALSE@am__append_66 = $(experimental_test_scripts) +@BUILDOPT_FUSE_TRUE@am__append_67 = tests/test-rofiles-fuse.sh +@BUILDOPT_FUSE_FALSE@am__append_68 = tests/test-rofiles-fuse.sh +@USE_LIBSOUP_TRUE@am__append_69 = tests/test-remote-cookies.sh +@BUILDOPT_GJS_TRUE@am__append_70 = $(js_tests) $(js_installed_tests) +@BUILDOPT_GJS_FALSE@am__append_71 = $(js_tests) +@BUILDOPT_GJS_FALSE@am__append_72 = $(js_installed_tests) +@ENABLE_INSTALLED_TESTS_FALSE@am__append_73 = -rpath $(abs_builddir) +@ENABLE_EXPERIMENTAL_API_TRUE@am__append_74 = \ @ENABLE_EXPERIMENTAL_API_TRUE@ tests/test-bloom \ @ENABLE_EXPERIMENTAL_API_TRUE@ tests/test-repo-finder-config \ @ENABLE_EXPERIMENTAL_API_TRUE@ tests/test-repo-finder-mount \ @ENABLE_EXPERIMENTAL_API_TRUE@ $(NULL) -@ENABLE_EXPERIMENTAL_API_TRUE@@USE_AVAHI_TRUE@am__append_74 = tests/test-repo-finder-avahi -@USE_LIBARCHIVE_TRUE@am__append_75 = tests/test-libarchive-import -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_76 = $(_installed_or_uninstalled_test_scripts) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_77 = $(_installed_or_uninstalled_test_programs) -@ENABLE_INSTALLED_TESTS_TRUE@am__append_78 = install-installed-tests-extra +@ENABLE_EXPERIMENTAL_API_TRUE@@USE_AVAHI_TRUE@am__append_75 = tests/test-repo-finder-avahi +@USE_LIBARCHIVE_TRUE@am__append_76 = tests/test-libarchive-import +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_77 = $(_installed_or_uninstalled_test_scripts) +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__append_78 = $(_installed_or_uninstalled_test_programs) +@ENABLE_INSTALLED_TESTS_TRUE@am__append_79 = install-installed-tests-extra # Allow the distcheck install under $prefix test to pass -@BUILDOPT_SYSTEMD_TRUE@am__append_79 = --with-systemdsystemunitdir='$${libdir}/systemd/system' +@BUILDOPT_SYSTEMD_TRUE@am__append_80 = --with-systemdsystemunitdir='$${libdir}/systemd/system' # We're using the system grub2-mkconfig generator -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_80 = src/boot/grub2/grub2-15_ostree -@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_81 = install-grub2-config-hook -@BUILDOPT_TRIVIAL_HTTPD_TRUE@@ENABLE_MAN_TRUE@am__append_82 = ostree-trivial-httpd.1 +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_81 = src/boot/grub2/grub2-15_ostree +@BUILDOPT_BUILTIN_GRUB2_MKCONFIG_FALSE@am__append_82 = install-grub2-config-hook +@BUILDOPT_TRIVIAL_HTTPD_TRUE@@ENABLE_MAN_TRUE@am__append_83 = ostree-trivial-httpd.1 # We still want to distribute the source, even if we are not building it -@BUILDOPT_TRIVIAL_HTTPD_FALSE@@ENABLE_MAN_TRUE@am__append_83 = man/ostree-trivial-httpd.xml -@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_84 = rofiles-fuse.1 -@ENABLE_MAN_TRUE@am__append_85 = $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) -@ENABLE_MAN_TRUE@am__append_86 = \ +@BUILDOPT_TRIVIAL_HTTPD_FALSE@@ENABLE_MAN_TRUE@am__append_84 = man/ostree-trivial-httpd.xml +@BUILDOPT_FUSE_TRUE@@ENABLE_MAN_TRUE@am__append_85 = rofiles-fuse.1 +@ENABLE_MAN_TRUE@am__append_86 = $(man1_MANS:.1=.xml) $(man5_MANS:.5=.xml) +@ENABLE_MAN_TRUE@am__append_87 = \ @ENABLE_MAN_TRUE@ $(man1_MANS) \ @ENABLE_MAN_TRUE@ $(man5_MANS) \ @ENABLE_MAN_TRUE@ $(NULL) @@ -911,24 +916,26 @@ tests/test-checksum$(EXEEXT) tests/test-lzma$(EXEEXT) \ tests/test-rollsum$(EXEEXT) tests/test-basic-c$(EXEEXT) \ tests/test-sysroot-c$(EXEEXT) tests/test-pull-c$(EXEEXT) \ - $(am__EXEEXT_5) + tests/test-repo$(EXEEXT) $(am__EXEEXT_5) @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__EXEEXT_7 = \ @ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@ $(am__EXEEXT_6) am__EXEEXT_8 = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \ $(am__EXEEXT_7) @ENABLE_INSTALLED_TESTS_EXCLUSIVE_TRUE@am__EXEEXT_9 = $(am__EXEEXT_6) -am__EXEEXT_10 = $(am__EXEEXT_8) $(am__EXEEXT_9) -@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__EXEEXT_11 = $(am__EXEEXT_10) -am__EXEEXT_12 = test-libglnx-xattrs$(EXEEXT) \ +@ENABLE_EXPERIMENTAL_API_TRUE@am__EXEEXT_10 = tests/repo-finder-mount$(EXEEXT) +am__EXEEXT_11 = $(am__EXEEXT_2) $(am__EXEEXT_10) +am__EXEEXT_12 = $(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_11) +@ENABLE_ALWAYS_BUILD_TESTS_FALSE@am__EXEEXT_13 = $(am__EXEEXT_12) +am__EXEEXT_14 = test-libglnx-xattrs$(EXEEXT) \ test-libglnx-fdio$(EXEEXT) test-libglnx-errors$(EXEEXT) \ test-libglnx-macros$(EXEEXT) -@BUILDOPT_SYSTEMD_FALSE@am__EXEEXT_13 = ostree-remount$(EXEEXT) -@ENABLE_INSTALLED_TESTS_TRUE@am__EXEEXT_14 = $(am__EXEEXT_8) \ -@ENABLE_INSTALLED_TESTS_TRUE@ $(am__EXEEXT_9) -@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__EXEEXT_15 = $(am__EXEEXT_10) -@BUILDOPT_SYSTEMD_TRUE@am__EXEEXT_16 = ostree-remount$(EXEEXT) -@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__EXEEXT_17 = ostree-prepare-root$(EXEEXT) -@USE_LIBSOUP_TRUE@am__EXEEXT_18 = ostree-trivial-httpd$(EXEEXT) +@BUILDOPT_SYSTEMD_FALSE@am__EXEEXT_15 = ostree-remount$(EXEEXT) +@ENABLE_INSTALLED_TESTS_TRUE@am__EXEEXT_16 = $(am__EXEEXT_8) \ +@ENABLE_INSTALLED_TESTS_TRUE@ $(am__EXEEXT_9) $(am__EXEEXT_11) +@ENABLE_ALWAYS_BUILD_TESTS_TRUE@am__EXEEXT_17 = $(am__EXEEXT_12) +@BUILDOPT_SYSTEMD_TRUE@am__EXEEXT_18 = ostree-remount$(EXEEXT) +@BUILDOPT_USE_STATIC_COMPILER_FALSE@am__EXEEXT_19 = ostree-prepare-root$(EXEEXT) +@USE_LIBSOUP_TRUE@am__EXEEXT_20 = ostree-trivial-httpd$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(installed_test_PROGRAMS) \ $(libexec_PROGRAMS) $(noinst_PROGRAMS) $(ostree_boot_PROGRAMS) \ $(pkglibexec_PROGRAMS) $(sbin_PROGRAMS) \ @@ -951,6 +958,7 @@ src/ostree/ot-main.c src/ostree/ot-dump.h src/ostree/ot-dump.c \ src/ostree/ot-editor.c src/ostree/ot-editor.h \ src/ostree/parse-datetime.h src/ostree/parse-datetime.c \ + src/ostree/ot-builtin-create-usb.c \ src/ostree/ot-builtin-find-remotes.c \ src/ostree/ot-admin-builtin-init-fs.c \ src/ostree/ot-admin-builtin-diff.c \ @@ -986,7 +994,9 @@ src/ostree/ot-remote-cookie-util.c \ src/ostree/ot-builtin-pull.c \ src/ostree/ot-builtin-trivial-httpd.c -@ENABLE_EXPERIMENTAL_API_TRUE@am__objects_11 = src/ostree/ostree-ot-builtin-find-remotes.$(OBJEXT) +@ENABLE_EXPERIMENTAL_API_TRUE@am__objects_11 = src/ostree/ostree-ot-builtin-create-usb.$(OBJEXT) \ +@ENABLE_EXPERIMENTAL_API_TRUE@ src/ostree/ostree-ot-builtin-find-remotes.$(OBJEXT) \ +@ENABLE_EXPERIMENTAL_API_TRUE@ $(am__objects_1) @USE_CURL_OR_SOUP_TRUE@am__objects_12 = src/ostree/ostree-ot-remote-builtin-add-cookie.$(OBJEXT) \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ostree-ot-remote-builtin-delete-cookie.$(OBJEXT) \ @USE_CURL_OR_SOUP_TRUE@ src/ostree/ostree-ot-remote-builtin-list-cookies.$(OBJEXT) \ @@ -1128,6 +1138,16 @@ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(test_libglnx_xattrs_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ +am_tests_repo_finder_mount_OBJECTS = \ + tests/tests_repo_finder_mount-repo-finder-mount.$(OBJEXT) +tests_repo_finder_mount_OBJECTS = \ + $(am_tests_repo_finder_mount_OBJECTS) +tests_repo_finder_mount_DEPENDENCIES = $(am__DEPENDENCIES_12) \ + libostreetest.la +tests_repo_finder_mount_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(tests_repo_finder_mount_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ tests_test_basic_c_SOURCES = tests/test-basic-c.c tests_test_basic_c_OBJECTS = \ tests/tests_test_basic_c-test-basic-c.$(OBJEXT) @@ -1241,6 +1261,13 @@ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(tests_test_pull_c_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ +tests_test_repo_SOURCES = tests/test-repo.c +tests_test_repo_OBJECTS = tests/tests_test_repo-test-repo.$(OBJEXT) +tests_test_repo_DEPENDENCIES = $(am__DEPENDENCIES_13) +tests_test_repo_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(tests_test_repo_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ am__tests_test_repo_finder_avahi_SOURCES_DIST = \ src/libostree/ostree-repo-finder-avahi-parser.c \ tests/test-repo-finder-avahi.c @@ -1355,15 +1382,16 @@ $(ostree_trivial_httpd_SOURCES) $(rofiles_fuse_SOURCES) \ $(test_libglnx_errors_SOURCES) $(test_libglnx_fdio_SOURCES) \ $(test_libglnx_macros_SOURCES) $(test_libglnx_xattrs_SOURCES) \ - tests/test-basic-c.c $(tests_test_bloom_SOURCES) \ - tests/test-bsdiff.c $(tests_test_checksum_SOURCES) \ + $(tests_repo_finder_mount_SOURCES) tests/test-basic-c.c \ + $(tests_test_bloom_SOURCES) tests/test-bsdiff.c \ + $(tests_test_checksum_SOURCES) \ $(tests_test_gpg_verify_result_SOURCES) \ tests/test-keyfile-utils.c \ $(tests_test_libarchive_import_SOURCES) \ $(tests_test_lzma_SOURCES) tests/test-mutable-tree.c \ tests/test-ot-opt-utils.c tests/test-ot-tool-util.c \ tests/test-ot-unix-utils.c tests/test-pull-c.c \ - $(tests_test_repo_finder_avahi_SOURCES) \ + tests/test-repo.c $(tests_test_repo_finder_avahi_SOURCES) \ $(tests_test_repo_finder_config_SOURCES) \ $(tests_test_repo_finder_mount_SOURCES) \ $(tests_test_rollsum_SOURCES) \ @@ -1381,14 +1409,16 @@ $(am__rofiles_fuse_SOURCES_DIST) \ $(test_libglnx_errors_SOURCES) $(test_libglnx_fdio_SOURCES) \ $(test_libglnx_macros_SOURCES) $(test_libglnx_xattrs_SOURCES) \ - tests/test-basic-c.c $(tests_test_bloom_SOURCES) \ - tests/test-bsdiff.c $(tests_test_checksum_SOURCES) \ + $(tests_repo_finder_mount_SOURCES) tests/test-basic-c.c \ + $(tests_test_bloom_SOURCES) tests/test-bsdiff.c \ + $(tests_test_checksum_SOURCES) \ $(tests_test_gpg_verify_result_SOURCES) \ tests/test-keyfile-utils.c \ $(tests_test_libarchive_import_SOURCES) \ $(tests_test_lzma_SOURCES) tests/test-mutable-tree.c \ tests/test-ot-opt-utils.c tests/test-ot-tool-util.c \ tests/test-ot-unix-utils.c tests/test-pull-c.c \ + tests/test-repo.c \ $(am__tests_test_repo_finder_avahi_SOURCES_DIST) \ $(tests_test_repo_finder_config_SOURCES) \ $(tests_test_repo_finder_mount_SOURCES) \ @@ -1634,17 +1664,18 @@ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) -am__EXEEXT_19 = tests/test-find-remotes.sh \ +am__EXEEXT_21 = tests/test-create-usb.sh tests/test-find-remotes.sh \ tests/test-fsck-collections.sh tests/test-init-collections.sh \ tests/test-prune-collections.sh tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ + tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh $(am__EXEEXT_2) -@ENABLE_EXPERIMENTAL_API_TRUE@am__EXEEXT_20 = $(am__EXEEXT_19) -am__EXEEXT_21 = tests/test-core.js tests/test-remotes-config-dir.js \ +@ENABLE_EXPERIMENTAL_API_TRUE@am__EXEEXT_22 = $(am__EXEEXT_21) +am__EXEEXT_23 = tests/test-core.js tests/test-remotes-config-dir.js \ tests/test-sizes.js tests/test-sysroot.js $(am__EXEEXT_2) -@BUILDOPT_GJS_TRUE@am__EXEEXT_22 = $(js_tests) $(am__EXEEXT_21) -am__EXEEXT_23 = tests/test-basic.sh tests/test-basic-user.sh \ +@BUILDOPT_GJS_TRUE@am__EXEEXT_24 = $(js_tests) $(am__EXEEXT_23) +am__EXEEXT_25 = tests/test-basic.sh tests/test-basic-user.sh \ tests/test-basic-user-only.sh tests/test-basic-root.sh \ tests/test-pull-subpath.sh tests/test-archivez.sh \ tests/test-remote-add.sh tests/test-remote-headers.sh \ @@ -1680,11 +1711,11 @@ tests/test-refs.sh tests/test-demo-buildsystem.sh \ tests/test-switchroot.sh tests/test-pull-contenturl.sh \ tests/test-pull-mirrorlist.sh tests/test-summary-update.sh \ - tests/test-summary-view.sh $(am__EXEEXT_2) $(am__EXEEXT_20) \ - $(am__append_66) $(am__append_68) $(am__EXEEXT_22) -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__EXEEXT_24 = \ -@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@ $(am__EXEEXT_23) -am__EXEEXT_25 = $(am__EXEEXT_2) $(am__EXEEXT_24) + tests/test-summary-view.sh $(am__EXEEXT_2) $(am__EXEEXT_22) \ + $(am__append_67) $(am__append_69) $(am__EXEEXT_24) +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@am__EXEEXT_26 = \ +@ENABLE_INSTALLED_TESTS_EXCLUSIVE_FALSE@ $(am__EXEEXT_25) +am__EXEEXT_27 = $(am__EXEEXT_2) $(am__EXEEXT_26) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) @@ -1855,6 +1886,8 @@ OTOOL64 = @OTOOL64@ OT_DEP_AVAHI_CFLAGS = @OT_DEP_AVAHI_CFLAGS@ OT_DEP_AVAHI_LIBS = @OT_DEP_AVAHI_LIBS@ +OT_DEP_CRYPTO_CFLAGS = @OT_DEP_CRYPTO_CFLAGS@ +OT_DEP_CRYPTO_LIBS = @OT_DEP_CRYPTO_LIBS@ OT_DEP_CURL_CFLAGS = @OT_DEP_CURL_CFLAGS@ OT_DEP_CURL_LIBS = @OT_DEP_CURL_LIBS@ OT_DEP_E2P_CFLAGS = @OT_DEP_E2P_CFLAGS@ @@ -1869,8 +1902,6 @@ OT_DEP_LIBMOUNT_LIBS = @OT_DEP_LIBMOUNT_LIBS@ OT_DEP_LZMA_CFLAGS = @OT_DEP_LZMA_CFLAGS@ OT_DEP_LZMA_LIBS = @OT_DEP_LZMA_LIBS@ -OT_DEP_OPENSSL_CFLAGS = @OT_DEP_OPENSSL_CFLAGS@ -OT_DEP_OPENSSL_LIBS = @OT_DEP_OPENSSL_LIBS@ OT_DEP_SELINUX_CFLAGS = @OT_DEP_SELINUX_CFLAGS@ OT_DEP_SELINUX_LIBS = @OT_DEP_SELINUX_LIBS@ OT_DEP_SOUP_CFLAGS = @OT_DEP_SOUP_CFLAGS@ @@ -1977,7 +2008,7 @@ # Allow the distcheck install under $prefix test to pass AM_DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-man \ --disable-maintainer-mode $(NULL) $(am__append_61) \ - $(am__append_79) \ + $(am__append_80) \ BASH_COMPLETIONSDIR='$${datadir}/bash-completion/completions' SUBDIRS = . $(am__append_14) NULL = @@ -1990,7 +2021,7 @@ tests/ostree-remount-symlink-stamp \ tests/rofiles-fuse-symlink-stamp tests/ostree \ tests/ostree-prepare-root tests/ostree-remount \ - tests/rofiles-fuse $(am__append_86) + tests/rofiles-fuse $(am__append_87) EXTRA_DIST = $(all_dist_test_scripts) $(all_dist_test_data) autogen.sh \ COPYING README.md $(am__append_15) libglnx/README.md \ libglnx/COPYING libglnx/libglnx.m4 $(NULL) \ @@ -2007,19 +2038,19 @@ src/libostree/ostree-repo-deprecated.h \ src/libostree/ostree-version.h src/ostree/parse-datetime.y \ buildutil/tap-driver.sh buildutil/tap-test tests/glib.supp \ - tests/ostree.supp $(NULL) $(am__append_65) $(am__append_67) \ - $(am__append_70) tests/libtest.sh $(am__append_71) \ + tests/ostree.supp $(NULL) $(am__append_66) $(am__append_68) \ + $(am__append_71) tests/libtest.sh $(am__append_72) \ tests/libostreetest.h tests/libtest.sh \ tests/gpg-verify-data/README.md $(NULL) \ src/boot/dracut/module-setup.sh src/boot/dracut/ostree.conf \ src/boot/mkinitcpio/ostree \ src/boot/ostree-prepare-root.service \ src/boot/ostree-remount.service src/boot/grub2/grub2-15_ostree \ - src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_83) \ - $(am__append_85) + src/boot/grub2/ostree-grub-generator $(NULL) $(am__append_84) \ + $(am__append_86) bin_SCRIPTS = lib_LTLIBRARIES = libostree-1.la -pkglibexec_SCRIPTS = $(am__append_80) +pkglibexec_SCRIPTS = $(am__append_81) noinst_LTLIBRARIES = $(am__append_1) libglnx.la libbsdiff.la \ libotutil.la libostree-kernel-args.la $(am__append_18) \ libostreetest.la @@ -2089,8 +2120,8 @@ # This initializes some more variables # This is a special facility to chain together hooks easily -INSTALL_DATA_HOOKS = install-mkdir-remotes-d-hook $(am__append_78) \ - $(am__append_81) +INSTALL_DATA_HOOKS = install-mkdir-remotes-d-hook $(am__append_79) \ + $(am__append_82) ALL_LOCAL_RULES = tests/libreaddir-rand.so shortened_sysconfdir = $$(echo "$(sysconfdir)" | sed -e 's|^$(prefix)||' -e 's|^/||') OSTREE_GITREV = $(shell cd $(srcdir) && if command -v git >/dev/null 2>&1 && test -d .git; then git describe --abbrev=42 --tags --always HEAD; fi) @@ -2139,6 +2170,7 @@ libglnx/glnx-shutil.h \ libglnx/glnx-shutil.c \ libglnx/libglnx.h \ + libglnx/tests/libglnx-testlib.h \ $(NULL) libglnx_la_CFLAGS = $(AM_CFLAGS) $(libglnx_cflags) @@ -2315,7 +2347,7 @@ -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) \ $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) \ - $(OT_DEP_OPENSSL_CFLAGS) -fvisibility=hidden \ + $(OT_DEP_CRYPTO_CFLAGS) -fvisibility=hidden \ '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) \ extern' $(am__append_26) $(am__append_28) $(am__append_30) \ $(am__append_34) $(am__append_37) $(am__append_39) \ @@ -2324,7 +2356,7 @@ libostree_1_la_LIBADD = libotutil.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) $(OT_DEP_OPENSSL_LIBS) $(bupsplitpath) \ + $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) $(bupsplitpath) \ $(am__append_27) $(am__append_29) $(am__append_31) \ $(am__append_35) $(am__append_38) $(am__append_40) \ $(am__append_42) @@ -2449,9 +2481,9 @@ # tests *only* run installed, to avoid having to run them twice in CI. # This overrides the glib-tap.mk emphasis on doing both, if we'd # used e.g. `dist_test_scripts`. -dist_test_scripts = $(NULL) $(am__append_76) -test_programs = $(NULL) $(am__append_73) $(am__append_74) \ - $(am__append_77) +dist_test_scripts = $(NULL) $(am__append_77) +test_programs = $(NULL) $(am__append_74) $(am__append_75) \ + $(am__append_78) _installed_or_uninstalled_test_scripts = tests/test-basic.sh \ tests/test-basic-user.sh tests/test-basic-user-only.sh \ tests/test-basic-root.sh tests/test-pull-subpath.sh \ @@ -2489,18 +2521,24 @@ tests/test-switchroot.sh tests/test-pull-contenturl.sh \ tests/test-pull-mirrorlist.sh tests/test-summary-update.sh \ tests/test-summary-view.sh $(NULL) $(am__append_64) \ - $(am__append_66) $(am__append_68) $(am__append_69) + $(am__append_67) $(am__append_69) $(am__append_70) experimental_test_scripts = \ + tests/test-create-usb.sh \ tests/test-find-remotes.sh \ tests/test-fsck-collections.sh \ tests/test-init-collections.sh \ tests/test-prune-collections.sh \ tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ + tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh \ $(NULL) +test_extra_programs = $(NULL) $(am__append_65) +tests_repo_finder_mount_SOURCES = tests/repo-finder-mount.c +tests_repo_finder_mount_CFLAGS = $(common_tests_cflags) +tests_repo_finder_mount_LDADD = $(common_tests_ldadd) libostreetest.la # These call into gjs scripts js_tests = tests/test-corruption.sh tests/test-pull-corruption.sh @@ -2552,14 +2590,15 @@ $(NULL) libreaddir_rand_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version \ - $(am__append_72) + $(am__append_73) _installed_or_uninstalled_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-pull-c $(am__append_75) + tests/test-sysroot-c tests/test-pull-c tests/test-repo \ + $(am__append_76) common_tests_cflags = $(ostree_bin_shared_cflags) $(OT_INTERNAL_GIO_UNIX_CFLAGS) -I$(srcdir)/libglnx common_tests_ldadd = $(ostree_bin_shared_ldadd) $(OT_INTERNAL_GIO_UNIX_LIBS) libostreetest_la_SOURCES = tests/libostreetest.c tests/test-mock-gio.c tests/test-mock-gio.h @@ -2593,6 +2632,8 @@ tests_test_sysroot_c_LDADD = $(TESTS_LDADD) tests_test_pull_c_CFLAGS = $(TESTS_CFLAGS) tests_test_pull_c_LDADD = $(TESTS_LDADD) +tests_test_repo_CFLAGS = $(TESTS_CFLAGS) +tests_test_repo_LDADD = $(TESTS_LDADD) tests_test_ot_unix_utils_CFLAGS = $(TESTS_CFLAGS) tests_test_ot_unix_utils_LDADD = $(TESTS_LDADD) tests_test_varint_SOURCES = src/libostree/ostree-varint.c tests/test-varint.c @@ -2660,8 +2701,8 @@ @ENABLE_MAN_TRUE@ ostree-pull.1 ostree-refs.1 ostree-remote.1 \ @ENABLE_MAN_TRUE@ ostree-reset.1 ostree-rev-parse.1 \ @ENABLE_MAN_TRUE@ ostree-show.1 ostree-summary.1 \ -@ENABLE_MAN_TRUE@ ostree-static-delta.1 $(am__append_82) \ -@ENABLE_MAN_TRUE@ $(am__append_84) +@ENABLE_MAN_TRUE@ ostree-static-delta.1 $(am__append_83) \ +@ENABLE_MAN_TRUE@ $(am__append_85) @ENABLE_MAN_TRUE@man5_files = ostree.repo.5 ostree.repo-config.5 @ENABLE_MAN_TRUE@man1_MANS = $(addprefix man/,$(man1_files)) @ENABLE_MAN_TRUE@man5_MANS = $(addprefix man/,$(man5_files)) @@ -3606,6 +3647,9 @@ src/ostree/ostree-parse-datetime.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) +src/ostree/ostree-ot-builtin-create-usb.$(OBJEXT): \ + src/ostree/$(am__dirstamp) \ + src/ostree/$(DEPDIR)/$(am__dirstamp) src/ostree/ostree-ot-builtin-find-remotes.$(OBJEXT): \ src/ostree/$(am__dirstamp) \ src/ostree/$(DEPDIR)/$(am__dirstamp) @@ -3781,6 +3825,12 @@ test-libglnx-xattrs$(EXEEXT): $(test_libglnx_xattrs_OBJECTS) $(test_libglnx_xattrs_DEPENDENCIES) $(EXTRA_test_libglnx_xattrs_DEPENDENCIES) @rm -f test-libglnx-xattrs$(EXEEXT) $(AM_V_CCLD)$(test_libglnx_xattrs_LINK) $(test_libglnx_xattrs_OBJECTS) $(test_libglnx_xattrs_LDADD) $(LIBS) +tests/tests_repo_finder_mount-repo-finder-mount.$(OBJEXT): \ + tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) + +tests/repo-finder-mount$(EXEEXT): $(tests_repo_finder_mount_OBJECTS) $(tests_repo_finder_mount_DEPENDENCIES) $(EXTRA_tests_repo_finder_mount_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/repo-finder-mount$(EXEEXT) + $(AM_V_CCLD)$(tests_repo_finder_mount_LINK) $(tests_repo_finder_mount_OBJECTS) $(tests_repo_finder_mount_LDADD) $(LIBS) tests/tests_test_basic_c-test-basic-c.$(OBJEXT): \ tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp) @@ -3874,6 +3924,12 @@ tests/test-pull-c$(EXEEXT): $(tests_test_pull_c_OBJECTS) $(tests_test_pull_c_DEPENDENCIES) $(EXTRA_tests_test_pull_c_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-pull-c$(EXEEXT) $(AM_V_CCLD)$(tests_test_pull_c_LINK) $(tests_test_pull_c_OBJECTS) $(tests_test_pull_c_LDADD) $(LIBS) +tests/tests_test_repo-test-repo.$(OBJEXT): tests/$(am__dirstamp) \ + tests/$(DEPDIR)/$(am__dirstamp) + +tests/test-repo$(EXEEXT): $(tests_test_repo_OBJECTS) $(tests_test_repo_DEPENDENCIES) $(EXTRA_tests_test_repo_DEPENDENCIES) tests/$(am__dirstamp) + @rm -f tests/test-repo$(EXEEXT) + $(AM_V_CCLD)$(tests_test_repo_LINK) $(tests_test_repo_OBJECTS) $(tests_test_repo_LDADD) $(LIBS) src/libostree/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.$(OBJEXT): \ src/libostree/$(am__dirstamp) \ src/libostree/$(DEPDIR)/$(am__dirstamp) @@ -4279,6 +4335,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-checksum.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-commit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-diff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-export.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/ostree/$(DEPDIR)/ostree-ot-builtin-find-remotes.Po@am__quote@ @@ -4321,6 +4378,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/libostreetest_la-libostreetest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/libostreetest_la-test-mock-gio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/libreaddir_rand_la-readdir-rand.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_basic_c-test-basic-c.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_bloom-test-bloom.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_bsdiff-test-bsdiff.Po@am__quote@ @@ -4334,6 +4392,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_ot_tool_util-test-ot-tool-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_ot_unix_utils-test-ot-unix-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_pull_c-test-pull-c.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_repo-test-repo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_repo_finder_avahi-test-repo-finder-avahi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_repo_finder_config-test-repo-finder-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/tests_test_repo_finder_mount-test-repo-finder-mount.Po@am__quote@ @@ -5346,6 +5405,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-parse-datetime.obj `if test -f 'src/ostree/parse-datetime.c'; then $(CYGPATH_W) 'src/ostree/parse-datetime.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/parse-datetime.c'; fi` +src/ostree/ostree-ot-builtin-create-usb.o: src/ostree/ot-builtin-create-usb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-builtin-create-usb.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Tpo -c -o src/ostree/ostree-ot-builtin-create-usb.o `test -f 'src/ostree/ot-builtin-create-usb.c' || echo '$(srcdir)/'`src/ostree/ot-builtin-create-usb.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Tpo src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-builtin-create-usb.c' object='src/ostree/ostree-ot-builtin-create-usb.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-builtin-create-usb.o `test -f 'src/ostree/ot-builtin-create-usb.c' || echo '$(srcdir)/'`src/ostree/ot-builtin-create-usb.c + +src/ostree/ostree-ot-builtin-create-usb.obj: src/ostree/ot-builtin-create-usb.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-builtin-create-usb.obj -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Tpo -c -o src/ostree/ostree-ot-builtin-create-usb.obj `if test -f 'src/ostree/ot-builtin-create-usb.c'; then $(CYGPATH_W) 'src/ostree/ot-builtin-create-usb.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-builtin-create-usb.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Tpo src/ostree/$(DEPDIR)/ostree-ot-builtin-create-usb.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ostree/ot-builtin-create-usb.c' object='src/ostree/ostree-ot-builtin-create-usb.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -c -o src/ostree/ostree-ot-builtin-create-usb.obj `if test -f 'src/ostree/ot-builtin-create-usb.c'; then $(CYGPATH_W) 'src/ostree/ot-builtin-create-usb.c'; else $(CYGPATH_W) '$(srcdir)/src/ostree/ot-builtin-create-usb.c'; fi` + src/ostree/ostree-ot-builtin-find-remotes.o: src/ostree/ot-builtin-find-remotes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ostree_CFLAGS) $(CFLAGS) -MT src/ostree/ostree-ot-builtin-find-remotes.o -MD -MP -MF src/ostree/$(DEPDIR)/ostree-ot-builtin-find-remotes.Tpo -c -o src/ostree/ostree-ot-builtin-find-remotes.o `test -f 'src/ostree/ot-builtin-find-remotes.c' || echo '$(srcdir)/'`src/ostree/ot-builtin-find-remotes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ostree/$(DEPDIR)/ostree-ot-builtin-find-remotes.Tpo src/ostree/$(DEPDIR)/ostree-ot-builtin-find-remotes.Po @@ -5892,6 +5965,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_libglnx_xattrs_CFLAGS) $(CFLAGS) -c -o libglnx/tests/test_libglnx_xattrs-test-libglnx-xattrs.obj `if test -f 'libglnx/tests/test-libglnx-xattrs.c'; then $(CYGPATH_W) 'libglnx/tests/test-libglnx-xattrs.c'; else $(CYGPATH_W) '$(srcdir)/libglnx/tests/test-libglnx-xattrs.c'; fi` +tests/tests_repo_finder_mount-repo-finder-mount.o: tests/repo-finder-mount.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_repo_finder_mount_CFLAGS) $(CFLAGS) -MT tests/tests_repo_finder_mount-repo-finder-mount.o -MD -MP -MF tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Tpo -c -o tests/tests_repo_finder_mount-repo-finder-mount.o `test -f 'tests/repo-finder-mount.c' || echo '$(srcdir)/'`tests/repo-finder-mount.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Tpo tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/repo-finder-mount.c' object='tests/tests_repo_finder_mount-repo-finder-mount.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_repo_finder_mount_CFLAGS) $(CFLAGS) -c -o tests/tests_repo_finder_mount-repo-finder-mount.o `test -f 'tests/repo-finder-mount.c' || echo '$(srcdir)/'`tests/repo-finder-mount.c + +tests/tests_repo_finder_mount-repo-finder-mount.obj: tests/repo-finder-mount.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_repo_finder_mount_CFLAGS) $(CFLAGS) -MT tests/tests_repo_finder_mount-repo-finder-mount.obj -MD -MP -MF tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Tpo -c -o tests/tests_repo_finder_mount-repo-finder-mount.obj `if test -f 'tests/repo-finder-mount.c'; then $(CYGPATH_W) 'tests/repo-finder-mount.c'; else $(CYGPATH_W) '$(srcdir)/tests/repo-finder-mount.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Tpo tests/$(DEPDIR)/tests_repo_finder_mount-repo-finder-mount.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/repo-finder-mount.c' object='tests/tests_repo_finder_mount-repo-finder-mount.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_repo_finder_mount_CFLAGS) $(CFLAGS) -c -o tests/tests_repo_finder_mount-repo-finder-mount.obj `if test -f 'tests/repo-finder-mount.c'; then $(CYGPATH_W) 'tests/repo-finder-mount.c'; else $(CYGPATH_W) '$(srcdir)/tests/repo-finder-mount.c'; fi` + tests/tests_test_basic_c-test-basic-c.o: tests/test-basic-c.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_basic_c_CFLAGS) $(CFLAGS) -MT tests/tests_test_basic_c-test-basic-c.o -MD -MP -MF tests/$(DEPDIR)/tests_test_basic_c-test-basic-c.Tpo -c -o tests/tests_test_basic_c-test-basic-c.o `test -f 'tests/test-basic-c.c' || echo '$(srcdir)/'`tests/test-basic-c.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_test_basic_c-test-basic-c.Tpo tests/$(DEPDIR)/tests_test_basic_c-test-basic-c.Po @@ -6144,6 +6231,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_pull_c_CFLAGS) $(CFLAGS) -c -o tests/tests_test_pull_c-test-pull-c.obj `if test -f 'tests/test-pull-c.c'; then $(CYGPATH_W) 'tests/test-pull-c.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-pull-c.c'; fi` +tests/tests_test_repo-test-repo.o: tests/test-repo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_repo_CFLAGS) $(CFLAGS) -MT tests/tests_test_repo-test-repo.o -MD -MP -MF tests/$(DEPDIR)/tests_test_repo-test-repo.Tpo -c -o tests/tests_test_repo-test-repo.o `test -f 'tests/test-repo.c' || echo '$(srcdir)/'`tests/test-repo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_test_repo-test-repo.Tpo tests/$(DEPDIR)/tests_test_repo-test-repo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-repo.c' object='tests/tests_test_repo-test-repo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_repo_CFLAGS) $(CFLAGS) -c -o tests/tests_test_repo-test-repo.o `test -f 'tests/test-repo.c' || echo '$(srcdir)/'`tests/test-repo.c + +tests/tests_test_repo-test-repo.obj: tests/test-repo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_repo_CFLAGS) $(CFLAGS) -MT tests/tests_test_repo-test-repo.obj -MD -MP -MF tests/$(DEPDIR)/tests_test_repo-test-repo.Tpo -c -o tests/tests_test_repo-test-repo.obj `if test -f 'tests/test-repo.c'; then $(CYGPATH_W) 'tests/test-repo.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-repo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) tests/$(DEPDIR)/tests_test_repo-test-repo.Tpo tests/$(DEPDIR)/tests_test_repo-test-repo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tests/test-repo.c' object='tests/tests_test_repo-test-repo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_repo_CFLAGS) $(CFLAGS) -c -o tests/tests_test_repo-test-repo.obj `if test -f 'tests/test-repo.c'; then $(CYGPATH_W) 'tests/test-repo.c'; else $(CYGPATH_W) '$(srcdir)/tests/test-repo.c'; fi` + src/libostree/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.o: src/libostree/ostree-repo-finder-avahi-parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tests_test_repo_finder_avahi_CFLAGS) $(CFLAGS) -MT src/libostree/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.o -MD -MP -MF src/libostree/$(DEPDIR)/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.Tpo -c -o src/libostree/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.o `test -f 'src/libostree/ostree-repo-finder-avahi-parser.c' || echo '$(srcdir)/'`src/libostree/ostree-repo-finder-avahi-parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/libostree/$(DEPDIR)/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.Tpo src/libostree/$(DEPDIR)/tests_test_repo_finder_avahi-ostree-repo-finder-avahi-parser.Po @@ -7106,6 +7207,13 @@ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-repo.log: tests/test-repo$(EXEEXT) + @p='tests/test-repo$(EXEEXT)'; \ + b='tests/test-repo'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/test-libarchive-import.log: tests/test-libarchive-import$(EXEEXT) @p='tests/test-libarchive-import$(EXEEXT)'; \ b='tests/test-libarchive-import'; \ @@ -7526,6 +7634,13 @@ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-create-usb.sh.log: tests/test-create-usb.sh + @p='tests/test-create-usb.sh'; \ + b='tests/test-create-usb.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) tests/test-find-remotes.sh.log: tests/test-find-remotes.sh @p='tests/test-find-remotes.sh'; \ b='tests/test-find-remotes.sh'; \ @@ -7567,6 +7682,13 @@ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/test-repo-finder-mount-integration.sh.log: tests/test-repo-finder-mount-integration.sh + @p='tests/test-repo-finder-mount-integration.sh'; \ + b='tests/test-repo-finder-mount-integration.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) tests/test-summary-collections.sh.log: tests/test-summary-collections.sh @p='tests/test-summary-collections.sh'; \ diff -Nru ostree-2017.11/Makefile-libostree.am ostree-2017.12/Makefile-libostree.am --- ostree-2017.11/Makefile-libostree.am 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/Makefile-libostree.am 2017-10-01 17:38:12.000000000 +0000 @@ -193,11 +193,11 @@ $(NULL) libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(builddir)/src/libostree \ - $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_OPENSSL_CFLAGS) \ + $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ - $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_OPENSSL_LIBS) + $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) libostree_1_la_LIBADD += $(bupsplitpath) EXTRA_libostree_1_la_DEPENDENCIES = $(symbol_files) diff -Nru ostree-2017.11/Makefile-ostree.am ostree-2017.12/Makefile-ostree.am --- ostree-2017.11/Makefile-ostree.am 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/Makefile-ostree.am 2017-10-01 17:38:12.000000000 +0000 @@ -54,7 +54,10 @@ $(NULL) if ENABLE_EXPERIMENTAL_API -ostree_SOURCES += src/ostree/ot-builtin-find-remotes.c +ostree_SOURCES += \ + src/ostree/ot-builtin-create-usb.c \ + src/ostree/ot-builtin-find-remotes.c \ + $(NULL) endif # Admin subcommand diff -Nru ostree-2017.11/Makefile-tests.am ostree-2017.12/Makefile-tests.am --- ostree-2017.11/Makefile-tests.am 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/Makefile-tests.am 2017-10-02 16:43:45.000000000 +0000 @@ -115,18 +115,26 @@ $(NULL) experimental_test_scripts = \ + tests/test-create-usb.sh \ tests/test-find-remotes.sh \ tests/test-fsck-collections.sh \ tests/test-init-collections.sh \ tests/test-prune-collections.sh \ tests/test-refs-collections.sh \ tests/test-remote-add-collections.sh \ + tests/test-repo-finder-mount-integration.sh \ tests/test-summary-collections.sh \ tests/test-pull-collections.sh \ $(NULL) +test_extra_programs = $(NULL) + +tests_repo_finder_mount_SOURCES = tests/repo-finder-mount.c +tests_repo_finder_mount_CFLAGS = $(common_tests_cflags) +tests_repo_finder_mount_LDADD = $(common_tests_ldadd) libostreetest.la if ENABLE_EXPERIMENTAL_API _installed_or_uninstalled_test_scripts += $(experimental_test_scripts) +test_extra_programs += tests/repo-finder-mount else EXTRA_DIST += $(experimental_test_scripts) endif @@ -212,7 +220,7 @@ _installed_or_uninstalled_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-pull-c + tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo if ENABLE_EXPERIMENTAL_API test_programs += \ @@ -282,6 +290,9 @@ tests_test_pull_c_CFLAGS = $(TESTS_CFLAGS) tests_test_pull_c_LDADD = $(TESTS_LDADD) +tests_test_repo_CFLAGS = $(TESTS_CFLAGS) +tests_test_repo_LDADD = $(TESTS_LDADD) + tests_test_ot_unix_utils_CFLAGS = $(TESTS_CFLAGS) tests_test_ot_unix_utils_LDADD = $(TESTS_LDADD) diff -Nru ostree-2017.11/man/ostree-summary.xml ostree-2017.12/man/ostree-summary.xml --- ostree-2017.11/man/ostree-summary.xml 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/man/ostree-summary.xml 2017-10-02 16:54:23.000000000 +0000 @@ -83,14 +83,23 @@ your organisation or repository using a dot prefix. The values must be in GVariant text format. For example, exampleos.end-of-life "@t 1445385600". - + + + + + =KEYID - GPG Key ID to sign the delta with. + GPG Key ID to sign the summary with. diff -Nru ostree-2017.11/src/libostree/libostree-devel.sym ostree-2017.12/src/libostree/libostree-devel.sym --- ostree-2017.11/src/libostree/libostree-devel.sym 2017-09-14 15:27:57.000000000 +0000 +++ ostree-2017.12/src/libostree/libostree-devel.sym 2017-10-02 17:06:07.000000000 +0000 @@ -18,9 +18,8 @@ ***/ /* Add new symbols here. Release commits should copy this section into -released.sym. */ -LIBOSTREE_2017.12 { -} LIBOSTREE_2017.11; - +LIBOSTREE_2017.13 { +} LIBOSTREE_2017.12; /* Stub section for the stable release *after* this development one; don't * edit this other than to update the last number. This is just a copy/paste diff -Nru ostree-2017.11/src/libostree/libostree-experimental.sym ostree-2017.12/src/libostree/libostree-experimental.sym --- ostree-2017.11/src/libostree/libostree-experimental.sym 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/libostree-experimental.sym 2017-10-01 17:38:12.000000000 +0000 @@ -77,3 +77,8 @@ ostree_repo_transaction_set_collection_ref; ostree_validate_collection_id; } LIBOSTREE_2017.7_EXPERIMENTAL; + +LIBOSTREE_2017.12_EXPERIMENTAL { +global: + ostree_repo_resolve_collection_ref; +} LIBOSTREE_2017.8_EXPERIMENTAL; diff -Nru ostree-2017.11/src/libostree/libostree-released.sym ostree-2017.12/src/libostree/libostree-released.sym --- ostree-2017.11/src/libostree/libostree-released.sym 2017-09-14 15:27:57.000000000 +0000 +++ ostree-2017.12/src/libostree/libostree-released.sym 2017-10-02 16:54:23.000000000 +0000 @@ -430,6 +430,12 @@ LIBOSTREE_2017.11 { } LIBOSTREE_2017.10; +LIBOSTREE_2017.12 { +global: + ostree_repo_equal; + ostree_repo_hash; +} LIBOSTREE_2017.11; + /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. */ diff -Nru ostree-2017.11/src/libostree/ostree-async-progress.c ostree-2017.12/src/libostree/ostree-async-progress.c --- ostree-2017.11/src/libostree/ostree-async-progress.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-async-progress.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-async-progress.h ostree-2017.12/src/libostree/ostree-async-progress.h --- ostree-2017.11/src/libostree/ostree-async-progress.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-async-progress.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-autocleanups.h ostree-2017.12/src/libostree/ostree-autocleanups.h --- ostree-2017.11/src/libostree/ostree-autocleanups.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-autocleanups.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- 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 diff -Nru ostree-2017.11/src/libostree/ostree-bloom.c ostree-2017.12/src/libostree/ostree-bloom.c --- ostree-2017.11/src/libostree/ostree-bloom.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bloom.c 2017-10-02 16:54:23.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or @@ -247,7 +246,7 @@ { g_assert (bloom->is_mutable); g_assert (idx / 8 < bloom->n_bytes); - bloom->mutable_bytes[idx / 8] |= (1 << (idx % 8)); + bloom->mutable_bytes[idx / 8] |= (guint8) (1 << (idx % 8)); } /** @@ -274,11 +273,11 @@ for (i = 0; i < bloom->k; i++) { - gsize idx; + guint64 idx; idx = bloom->hash_func (element, i); - if (!ostree_bloom_get_bit (bloom, idx % (bloom->n_bytes * 8))) + if (!ostree_bloom_get_bit (bloom, (gsize) (idx % (bloom->n_bytes * 8)))) return FALSE; /* definitely not in the set */ } @@ -338,8 +337,8 @@ for (i = 0; i < bloom->k; i++) { - gsize idx = bloom->hash_func (element, i); - ostree_bloom_set_bit (bloom, idx % (bloom->n_bytes * 8)); + guint64 idx = bloom->hash_func (element, i); + ostree_bloom_set_bit (bloom, (gsize) (idx % (bloom->n_bytes * 8))); } } diff -Nru ostree-2017.11/src/libostree/ostree-bloom-private.h ostree-2017.12/src/libostree/ostree-bloom-private.h --- ostree-2017.11/src/libostree/ostree-bloom-private.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bloom-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-bootconfig-parser.c ostree-2017.12/src/libostree/ostree-bootconfig-parser.c --- ostree-2017.11/src/libostree/ostree-bootconfig-parser.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootconfig-parser.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootconfig-parser.h ostree-2017.12/src/libostree/ostree-bootconfig-parser.h --- ostree-2017.11/src/libostree/ostree-bootconfig-parser.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootconfig-parser.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader.c ostree-2017.12/src/libostree/ostree-bootloader.c --- ostree-2017.11/src/libostree/ostree-bootloader.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-grub2.c ostree-2017.12/src/libostree/ostree-bootloader-grub2.c --- ostree-2017.11/src/libostree/ostree-bootloader-grub2.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-grub2.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-grub2.h ostree-2017.12/src/libostree/ostree-bootloader-grub2.h --- ostree-2017.11/src/libostree/ostree-bootloader-grub2.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-grub2.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader.h ostree-2017.12/src/libostree/ostree-bootloader.h --- ostree-2017.11/src/libostree/ostree-bootloader.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-syslinux.c ostree-2017.12/src/libostree/ostree-bootloader-syslinux.c --- ostree-2017.11/src/libostree/ostree-bootloader-syslinux.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-syslinux.c 2017-10-02 17:11:19.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-syslinux.h ostree-2017.12/src/libostree/ostree-bootloader-syslinux.h --- ostree-2017.11/src/libostree/ostree-bootloader-syslinux.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-syslinux.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-uboot.c ostree-2017.12/src/libostree/ostree-bootloader-uboot.c --- ostree-2017.11/src/libostree/ostree-bootloader-uboot.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-uboot.c 2017-10-02 17:11:19.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Collabora Ltd * * Based on ot-bootloader-syslinux.c by Colin Walters diff -Nru ostree-2017.11/src/libostree/ostree-bootloader-uboot.h ostree-2017.12/src/libostree/ostree-bootloader-uboot.h --- ostree-2017.11/src/libostree/ostree-bootloader-uboot.h 2017-05-12 20:12:56.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-bootloader-uboot.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Collabora Ltd * * Based on ot-bootloader-syslinux.h by Colin Walters diff -Nru ostree-2017.11/src/libostree/ostree-chain-input-stream.c ostree-2017.12/src/libostree/ostree-chain-input-stream.c --- ostree-2017.11/src/libostree/ostree-chain-input-stream.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-chain-input-stream.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-chain-input-stream.h ostree-2017.12/src/libostree/ostree-chain-input-stream.h --- ostree-2017.11/src/libostree/ostree-chain-input-stream.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-chain-input-stream.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-checksum-input-stream.c ostree-2017.12/src/libostree/ostree-checksum-input-stream.c --- ostree-2017.11/src/libostree/ostree-checksum-input-stream.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-checksum-input-stream.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-checksum-input-stream.h ostree-2017.12/src/libostree/ostree-checksum-input-stream.h --- ostree-2017.11/src/libostree/ostree-checksum-input-stream.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-checksum-input-stream.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-cmdprivate.c ostree-2017.12/src/libostree/ostree-cmdprivate.c --- ostree-2017.11/src/libostree/ostree-cmdprivate.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-cmdprivate.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-cmdprivate.h ostree-2017.12/src/libostree/ostree-cmdprivate.h --- ostree-2017.11/src/libostree/ostree-cmdprivate.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-cmdprivate.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-core.c ostree-2017.12/src/libostree/ostree-core.c --- ostree-2017.11/src/libostree/ostree-core.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-core.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -33,6 +32,13 @@ #include "ostree-chain-input-stream.h" #include "otutil.h" +/* Generic ABI checks */ +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE == 0); +G_STATIC_ASSERT(OSTREE_REPO_MODE_ARCHIVE_Z2 == 1); +G_STATIC_ASSERT(OSTREE_REPO_MODE_ARCHIVE == OSTREE_REPO_MODE_ARCHIVE_Z2); +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER == 2); +G_STATIC_ASSERT(OSTREE_REPO_MODE_BARE_USER_ONLY == 3); + #define ALIGN_VALUE(this, boundary) \ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1))) @@ -1525,7 +1531,7 @@ buf++; snprintf (buf, _OSTREE_LOOSE_PATH_MAX - 2, "/%s.%s%s", checksum + 2, ostree_object_type_to_string (objtype), - (!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE_Z2) ? "z" : ""); + (!OSTREE_OBJECT_TYPE_IS_META (objtype) && mode == OSTREE_REPO_MODE_ARCHIVE) ? "z" : ""); } /** @@ -1562,12 +1568,52 @@ g_file_info_set_attribute_uint32 (ret, "unix::uid", stbuf->st_uid); g_file_info_set_attribute_uint32 (ret, "unix::gid", stbuf->st_gid); g_file_info_set_attribute_uint32 (ret, "unix::mode", mode); + + /* those aren't stored by ostree, but used by the devino cache */ + g_file_info_set_attribute_uint32 (ret, "unix::device", stbuf->st_dev); + g_file_info_set_attribute_uint64 (ret, "unix::inode", stbuf->st_ino); + if (S_ISREG (mode)) g_file_info_set_attribute_uint64 (ret, "standard::size", stbuf->st_size); return ret; } +/** + * _ostree_gfileinfo_equal: + * @a: First file info + * @b: Second file info + * + * OSTree only cares about a subset of file attributes. This function + * checks whether two #GFileInfo objects are equal as far as OSTree is + * concerned. + * + * Returns: TRUE if the #GFileInfo objects are OSTree-equivalent. + */ +gboolean +_ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b) +{ + /* trivial case */ + if (a == b) + return TRUE; + +#define CHECK_ONE_ATTR(type, attr, a, b) \ + do { if (g_file_info_get_attribute_##type(a, attr) != \ + g_file_info_get_attribute_##type(b, attr)) \ + return FALSE; \ + } while (0) + + CHECK_ONE_ATTR (uint32, "unix::uid", a, b); + CHECK_ONE_ATTR (uint32, "unix::gid", a, b); + CHECK_ONE_ATTR (uint32, "unix::mode", a, b); + CHECK_ONE_ATTR (uint32, "standard::type", a, b); + CHECK_ONE_ATTR (uint64, "standard::size", a, b); + +#undef CHECK_ONE_ATTR + + return TRUE; +} + GFileInfo * _ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid) { @@ -1997,6 +2043,29 @@ return TRUE; } + +/* This bit mirrors similar code in commit_loose_regfile_object() for the + * bare-user-only mode. It's opt-in though for all pulls. + */ +gboolean +_ostree_validate_bareuseronly_mode (guint32 content_mode, + const char *checksum, + GError **error) +{ + if (S_ISREG (content_mode)) + { + const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775); + if (invalid_modebits > 0) + return glnx_throw (error, "Content object %s: invalid mode 0%04o with bits 0%04o", + checksum, content_mode, invalid_modebits); + } + else if (S_ISLNK (content_mode)) + ; /* Nothing */ + else + g_assert_not_reached (); + + return TRUE; +} static gboolean validate_stat_mode_perms (guint32 mode, diff -Nru ostree-2017.11/src/libostree/ostree-core.h ostree-2017.12/src/libostree/ostree-core.h --- ostree-2017.11/src/libostree/ostree-core.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-core.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -181,7 +180,8 @@ /** * OstreeRepoMode: * @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_ARCHIVE: Files are compressed, should be owned by non-root. Can be served via HTTP. Since: 2017.12 + * @OSTREE_REPO_MODE_ARCHIVE_Z2: Legacy alias for `OSTREE_REPO_MODE_ARCHIVE` * @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. Hardlinks work only in user checkouts. * @OSTREE_REPO_MODE_BARE_USER_ONLY: Same as BARE_USER, but all metadata is not stored, so it can only be used for user checkouts. Does not need xattrs. * @@ -190,7 +190,8 @@ */ typedef enum { OSTREE_REPO_MODE_BARE, - OSTREE_REPO_MODE_ARCHIVE_Z2, + OSTREE_REPO_MODE_ARCHIVE, + OSTREE_REPO_MODE_ARCHIVE_Z2 = OSTREE_REPO_MODE_ARCHIVE, OSTREE_REPO_MODE_BARE_USER, OSTREE_REPO_MODE_BARE_USER_ONLY, } OstreeRepoMode; diff -Nru ostree-2017.11/src/libostree/ostree-core-private.h ostree-2017.12/src/libostree/ostree-core-private.h --- ostree-2017.11/src/libostree/ostree-core-private.h 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-core-private.h 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -90,6 +89,7 @@ GError **error); GFileInfo * _ostree_stbuf_to_gfileinfo (const struct stat *stbuf); +gboolean _ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b); GFileInfo * _ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid); static inline void @@ -135,6 +135,19 @@ } gboolean +_ostree_validate_bareuseronly_mode (guint32 mode, + const char *checksum, + GError **error); +static inline gboolean +_ostree_validate_bareuseronly_mode_finfo (GFileInfo *finfo, + const char *checksum, + GError **error) +{ + const guint32 content_mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode"); + return _ostree_validate_bareuseronly_mode (content_mode, checksum, error); +} + +gboolean _ostree_parse_delta_name (const char *delta_name, char **out_from, char **out_to, diff -Nru ostree-2017.11/src/libostree/ostree-deployment.c ostree-2017.12/src/libostree/ostree-deployment.c --- ostree-2017.11/src/libostree/ostree-deployment.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-deployment.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-deployment.h ostree-2017.12/src/libostree/ostree-deployment.h --- ostree-2017.11/src/libostree/ostree-deployment.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-deployment.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-deployment-private.h ostree-2017.12/src/libostree/ostree-deployment-private.h --- ostree-2017.11/src/libostree/ostree-deployment-private.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-deployment-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-diff.c ostree-2017.12/src/libostree/ostree-diff.c --- ostree-2017.11/src/libostree/ostree-diff.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-diff.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -27,6 +26,16 @@ #include "ostree-repo-private.h" #include "otutil.h" +/* See ostree-repo.c for a bit more info about these ABI checks */ +#if __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 && __SIZEOF_INT__ == 4 +G_STATIC_ASSERT(sizeof(OstreeDiffDirsOptions) == + sizeof(int) * 2 + + sizeof(gpointer) + + sizeof(int) * (7+6) + + sizeof(int) + /* hole */ + sizeof(gpointer) * 7); +#endif + static gboolean get_file_checksum (OstreeDiffFlags flags, GFile *f, diff -Nru ostree-2017.11/src/libostree/ostree-diff.h ostree-2017.12/src/libostree/ostree-diff.h --- ostree-2017.11/src/libostree/ostree-diff.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-diff.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -86,6 +85,7 @@ gboolean unused_bools[7]; int unused_ints[6]; + /* 4 byte hole on 64 bit */ gpointer unused_ptrs[7]; } OstreeDiffDirsOptions; diff -Nru ostree-2017.11/src/libostree/ostree-fetcher-curl.c ostree-2017.12/src/libostree/ostree-fetcher-curl.c --- ostree-2017.11/src/libostree/ostree-fetcher-curl.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher-curl.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or @@ -379,14 +378,13 @@ g_autoptr(GError) local_error = NULL; GError **error = &local_error; - /* TODO - share file naming with soup, and fix it */ g_autofree char *tmpfile_path = - g_compute_checksum_for_string (G_CHECKSUM_SHA256, - eff_url, strlen (eff_url)); + ostree_fetcher_generate_url_tmpname (eff_url); if (!ensure_tmpfile (req, error)) { g_task_return_error (task, g_steal_pointer (&local_error)); } + /* This should match the libsoup chmod */ else if (fchmod (req->tmpf.fd, 0644) < 0) { glnx_set_error_from_errno (error); @@ -748,6 +746,24 @@ if (self->tls_client_cert_path) { + /* Support for pkcs11: + * https://github.com/ostreedev/ostree/pull/1183 + * This will be used by https://github.com/advancedtelematic/aktualizr + * at least to fetch certificates. No test coverage at the moment + * though. See https://gitlab.com/gnutls/gnutls/tree/master/tests/pkcs11 + * and https://github.com/opendnssec/SoftHSMv2 and + * https://github.com/p11-glue/p11-kit/tree/master/p11-kit for + * possible ideas there. + */ + if (g_str_has_prefix (self->tls_client_key_path, "pkcs11:")) + { + curl_easy_setopt (req->easy, CURLOPT_SSLENGINE, "pkcs11"); + curl_easy_setopt (req->easy, CURLOPT_SSLENGINE_DEFAULT, 1L); + curl_easy_setopt (req->easy, CURLOPT_SSLKEYTYPE, "ENG"); + } + if (g_str_has_prefix (self->tls_client_cert_path, "pkcs11:")) + curl_easy_setopt (req->easy, CURLOPT_SSLCERTTYPE, "ENG"); + curl_easy_setopt (req->easy, CURLOPT_SSLCERT, self->tls_client_cert_path); curl_easy_setopt (req->easy, CURLOPT_SSLKEY, self->tls_client_key_path); } diff -Nru ostree-2017.11/src/libostree/ostree-fetcher.h ostree-2017.12/src/libostree/ostree-fetcher.h --- ostree-2017.11/src/libostree/ostree-fetcher.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-fetcher-soup.c ostree-2017.12/src/libostree/ostree-fetcher-soup.c --- ostree-2017.11/src/libostree/ostree-fetcher-soup.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher-soup.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -55,10 +54,7 @@ volatile gint running; GError *initialization_error; /* Any failure to load the db */ - int tmpdir_dfd; char *remote_name; - char *tmpdir_name; - GLnxLockFile tmpdir_lock; int base_tmpdir_dfd; GVariant *extra_headers; @@ -94,7 +90,7 @@ gboolean is_membuf; OstreeFetcherRequestFlags flags; GInputStream *request_body; - char *out_tmpfile; + GLnxTmpfile tmpf; GOutputStream *out_stream; guint64 max_size; @@ -155,17 +151,6 @@ g_clear_pointer (&thread_closure->extra_headers, (GDestroyNotify)g_variant_unref); - if (thread_closure->tmpdir_dfd != -1) - close (thread_closure->tmpdir_dfd); - - /* Note: We don't remove the tmpdir here, because that would cause - us to not reuse it on resume. This happens because we use two - fetchers for each pull, so finalizing the first one would remove - all the files to be resumed from the previous second one */ - - g_free (thread_closure->tmpdir_name); - glnx_release_lock_file (&thread_closure->tmpdir_lock); - g_clear_pointer (&thread_closure->output_stream_set, g_hash_table_unref); g_mutex_clear (&thread_closure->output_stream_set_lock); @@ -210,7 +195,7 @@ g_free (pending->filename); g_clear_object (&pending->request); g_clear_object (&pending->request_body); - g_free (pending->out_tmpfile); + glnx_tmpfile_clear (&pending->tmpf); g_clear_object (&pending->out_stream); g_free (pending); } @@ -477,59 +462,7 @@ } else { - g_autofree char *uristring - = soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); - g_autofree char *tmpfile = NULL; - struct stat stbuf; - gboolean exists; - - /* The tmp directory is lazily created for each fetcher instance, - * since it may require superuser permissions and some instances - * only need _ostree_fetcher_request_uri_to_membuf() which keeps - * everything in memory buffers. */ - if (thread_closure->tmpdir_name == NULL) - { - if (!_ostree_repo_allocate_tmpdir (thread_closure->base_tmpdir_dfd, - OSTREE_REPO_TMPDIR_FETCHER, - &thread_closure->tmpdir_name, - &thread_closure->tmpdir_dfd, - &thread_closure->tmpdir_lock, - NULL, - cancellable, - &local_error)) - { - g_task_return_error (task, local_error); - return; - } - } - - tmpfile = g_compute_checksum_for_string (G_CHECKSUM_SHA256, uristring, strlen (uristring)); - - if (fstatat (thread_closure->tmpdir_dfd, tmpfile, &stbuf, AT_SYMLINK_NOFOLLOW) == 0) - exists = TRUE; - else - { - if (errno == ENOENT) - exists = FALSE; - else - { - glnx_set_error_from_errno (&local_error); - g_task_return_error (task, local_error); - return; - } - } - - if (SOUP_IS_REQUEST_HTTP (pending->request)) - { - glnx_unref_object SoupMessage *msg = NULL; - msg = soup_request_http_get_message ((SoupRequestHTTP*) pending->request); - if (exists && stbuf.st_size > 0) - soup_message_headers_set_range (msg->request_headers, stbuf.st_size, -1); - } - pending->out_tmpfile = tmpfile; - tmpfile = NULL; /* Transfer ownership */ - - start_pending_request (thread_closure, task); + start_pending_request (thread_closure, task); } } @@ -658,7 +591,6 @@ { OstreeFetcher *self = OSTREE_FETCHER (object); g_autoptr(GMainContext) main_context = NULL; - GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; const char *http_proxy; main_context = g_main_context_new (); @@ -668,8 +600,6 @@ self->thread_closure->main_context = g_main_context_ref (main_context); self->thread_closure->running = 1; self->thread_closure->transfer_gzip = (self->config_flags & OSTREE_FETCHER_FLAGS_TRANSFER_GZIP) != 0; - self->thread_closure->tmpdir_dfd = -1; - self->thread_closure->tmpdir_lock = empty_lockfile; 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, @@ -749,7 +679,7 @@ int _ostree_fetcher_get_dfd (OstreeFetcher *fetcher) { - return fetcher->thread_closure->tmpdir_dfd; + return fetcher->thread_closure->base_tmpdir_dfd; } void @@ -874,13 +804,8 @@ if (!pending->is_membuf) { - if (fstatat (pending->thread_closure->tmpdir_dfd, - pending->out_tmpfile, - &stbuf, AT_SYMLINK_NOFOLLOW) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + if (!glnx_fstat (pending->tmpf.fd, &stbuf, error)) + goto out; } pending->state = OSTREE_FETCHER_STATE_COMPLETE; @@ -973,11 +898,39 @@ pending = g_task_get_task_data (task); cancellable = g_task_get_cancellable (task); + /* Only open the output stream on demand to ensure we use as + * few file descriptors as possible. + */ + if (!pending->out_stream) + { + if (!pending->is_membuf) + { + if (!glnx_open_tmpfile_linkable_at (pending->thread_closure->base_tmpdir_dfd, ".", + O_WRONLY | O_CLOEXEC, &pending->tmpf, &local_error)) + goto out; + /* This should match the libcurl chmod */ + if (!glnx_fchmod (pending->tmpf.fd, 0644, &local_error)) + goto out; + pending->out_stream = g_unix_output_stream_new (pending->tmpf.fd, FALSE); + } + else + { + pending->out_stream = g_memory_output_stream_new_resizable (); + } + + g_mutex_lock (&pending->thread_closure->output_stream_set_lock); + g_hash_table_add (pending->thread_closure->output_stream_set, + g_object_ref (pending->out_stream)); + g_mutex_unlock (&pending->thread_closure->output_stream_set_lock); + } + + /* Get a GBytes buffer */ bytes = g_input_stream_read_bytes_finish ((GInputStream*)object, result, &local_error); if (!bytes) goto out; - bytes_read = g_bytes_get_size (bytes); + + /* Was this the end of the stream? */ if (bytes_read == 0) { if (!finish_stream (pending, cancellable, &local_error)) @@ -990,14 +943,24 @@ } else { - g_task_return_pointer (task, - g_strdup (pending->out_tmpfile), - (GDestroyNotify) g_free); + g_autofree char *uristring = + soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); + g_autofree char *tmpfile_path = + ostree_fetcher_generate_url_tmpname (uristring); + if (!glnx_link_tmpfile_at (&pending->tmpf, GLNX_LINK_TMPFILE_REPLACE, + pending->thread_closure->base_tmpdir_dfd, tmpfile_path, + &local_error)) + g_task_return_error (task, g_steal_pointer (&local_error)); + else + g_task_return_pointer (task, + g_steal_pointer (&tmpfile_path), + (GDestroyNotify) g_free); } remove_pending (pending); } else { + /* Verify max size */ if (pending->max_size > 0) { if (bytes_read > pending->max_size || @@ -1011,7 +974,7 @@ goto out; } } - + pending->current_size += bytes_read; /* We do this instead of _write_bytes_async() as that's not @@ -1063,19 +1026,7 @@ if (SOUP_IS_REQUEST_HTTP (object)) { msg = soup_request_http_get_message ((SoupRequestHTTP*) object); - if (!pending->is_membuf && - msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) - { - // We already have the whole file, so just use it. - pending->state = OSTREE_FETCHER_STATE_COMPLETE; - (void) g_input_stream_close (pending->request_body, NULL, NULL); - g_task_return_pointer (task, - g_strdup (pending->out_tmpfile), - (GDestroyNotify) g_free); - remove_pending (pending); - goto out; - } - else if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { /* is there another mirror we can try? */ if (pending->mirrorlist_idx + 1 < pending->mirrorlist->len) @@ -1091,8 +1042,8 @@ } else { - g_autofree char *uristring - = soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); + g_autofree char *uristring = + soup_uri_to_string (soup_request_get_uri (pending->request), FALSE); GIOErrorEnum code; switch (msg->status_code) @@ -1143,38 +1094,6 @@ pending->content_length = soup_request_get_content_length (pending->request); - if (!pending->is_membuf) - { - int oflags = O_CREAT | O_WRONLY | O_CLOEXEC; - int fd; - - /* If we got partial content, we can append; if the server - * ignored our range request, we need to truncate. - */ - if (msg && msg->status_code == SOUP_STATUS_PARTIAL_CONTENT) - oflags |= O_APPEND; - else - oflags |= O_TRUNC; - - fd = openat (pending->thread_closure->tmpdir_dfd, - pending->out_tmpfile, oflags, 0666); - if (fd == -1) - { - glnx_set_error_from_errno (&local_error); - goto out; - } - pending->out_stream = g_unix_output_stream_new (fd, TRUE); - } - else - { - pending->out_stream = g_memory_output_stream_new_resizable (); - } - - g_mutex_lock (&pending->thread_closure->output_stream_set_lock); - g_hash_table_add (pending->thread_closure->output_stream_set, - g_object_ref (pending->out_stream)); - g_mutex_unlock (&pending->thread_closure->output_stream_set_lock); - g_input_stream_read_bytes_async (pending->request_body, 8192, G_PRIORITY_DEFAULT, cancellable, diff -Nru ostree-2017.11/src/libostree/ostree-fetcher-uri.c ostree-2017.12/src/libostree/ostree-fetcher-uri.c --- ostree-2017.11/src/libostree/ostree-fetcher-uri.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher-uri.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-fetcher-util.c ostree-2017.12/src/libostree/ostree-fetcher-util.c --- ostree-2017.11/src/libostree/ostree-fetcher-util.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher-util.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-fetcher-util.h ostree-2017.12/src/libostree/ostree-fetcher-util.h --- ostree-2017.11/src/libostree/ostree-fetcher-util.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-fetcher-util.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or @@ -26,6 +25,16 @@ G_BEGIN_DECLS +/* FIXME - delete this and replace by having fetchers simply + * return O_TMPFILE fds, not file paths. + */ +static inline char * +ostree_fetcher_generate_url_tmpname (const char *url) +{ + return g_compute_checksum_for_string (G_CHECKSUM_SHA256, + url, strlen (url)); +} + gboolean _ostree_fetcher_mirrored_request_to_membuf (OstreeFetcher *fetcher, GPtrArray *mirrorlist, const char *filename, diff -Nru ostree-2017.11/src/libostree/ostree-gpg-verifier.c ostree-2017.12/src/libostree/ostree-gpg-verifier.c --- ostree-2017.11/src/libostree/ostree-gpg-verifier.c 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-gpg-verifier.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Sjoerd Simons * diff -Nru ostree-2017.11/src/libostree/ostree-gpg-verifier.h ostree-2017.12/src/libostree/ostree-gpg-verifier.h --- ostree-2017.11/src/libostree/ostree-gpg-verifier.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-gpg-verifier.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Sjoerd Simons * diff -Nru ostree-2017.11/src/libostree/ostree-gpg-verify-result.c ostree-2017.12/src/libostree/ostree-gpg-verify-result.c --- ostree-2017.11/src/libostree/ostree-gpg-verify-result.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-gpg-verify-result.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-gpg-verify-result.h ostree-2017.12/src/libostree/ostree-gpg-verify-result.h --- ostree-2017.11/src/libostree/ostree-gpg-verify-result.h 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-gpg-verify-result.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-gpg-verify-result-private.h ostree-2017.12/src/libostree/ostree-gpg-verify-result-private.h --- ostree-2017.11/src/libostree/ostree-gpg-verify-result-private.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-gpg-verify-result-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree.h ostree-2017.12/src/libostree/ostree.h --- ostree-2017.11/src/libostree/ostree.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-impl-system-generator.c ostree-2017.12/src/libostree/ostree-impl-system-generator.c --- ostree-2017.11/src/libostree/ostree-impl-system-generator.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-impl-system-generator.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-kernel-args.c ostree-2017.12/src/libostree/ostree-kernel-args.c --- ostree-2017.11/src/libostree/ostree-kernel-args.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-kernel-args.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-kernel-args.h ostree-2017.12/src/libostree/ostree-kernel-args.h --- ostree-2017.11/src/libostree/ostree-kernel-args.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-kernel-args.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libostree/ostree-libarchive-input-stream.c ostree-2017.12/src/libostree/ostree-libarchive-input-stream.c --- ostree-2017.11/src/libostree/ostree-libarchive-input-stream.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-libarchive-input-stream.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-libarchive-input-stream.h ostree-2017.12/src/libostree/ostree-libarchive-input-stream.h --- ostree-2017.11/src/libostree/ostree-libarchive-input-stream.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-libarchive-input-stream.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-libarchive-private.h ostree-2017.12/src/libostree/ostree-libarchive-private.h --- ostree-2017.11/src/libostree/ostree-libarchive-private.h 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-libarchive-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-linuxfsutil.c ostree-2017.12/src/libostree/ostree-linuxfsutil.c --- ostree-2017.11/src/libostree/ostree-linuxfsutil.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-linuxfsutil.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-linuxfsutil.h ostree-2017.12/src/libostree/ostree-linuxfsutil.h --- ostree-2017.11/src/libostree/ostree-linuxfsutil.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-linuxfsutil.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-common.c ostree-2017.12/src/libostree/ostree-lzma-common.c --- ostree-2017.11/src/libostree/ostree-lzma-common.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-common.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-common.h ostree-2017.12/src/libostree/ostree-lzma-common.h --- ostree-2017.11/src/libostree/ostree-lzma-common.h 2017-05-12 20:12:56.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-common.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-compressor.c ostree-2017.12/src/libostree/ostree-lzma-compressor.c --- ostree-2017.11/src/libostree/ostree-lzma-compressor.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-compressor.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-compressor.h ostree-2017.12/src/libostree/ostree-lzma-compressor.h --- ostree-2017.11/src/libostree/ostree-lzma-compressor.h 2017-05-12 20:12:56.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-compressor.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-decompressor.c ostree-2017.12/src/libostree/ostree-lzma-decompressor.c --- ostree-2017.11/src/libostree/ostree-lzma-decompressor.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-decompressor.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-lzma-decompressor.h ostree-2017.12/src/libostree/ostree-lzma-decompressor.h --- ostree-2017.11/src/libostree/ostree-lzma-decompressor.h 2017-05-12 20:12:56.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-lzma-decompressor.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-metalink.c ostree-2017.12/src/libostree/ostree-metalink.c --- ostree-2017.11/src/libostree/ostree-metalink.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-metalink.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-metalink.h ostree-2017.12/src/libostree/ostree-metalink.h --- ostree-2017.11/src/libostree/ostree-metalink.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-metalink.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-mutable-tree.c ostree-2017.12/src/libostree/ostree-mutable-tree.c --- ostree-2017.11/src/libostree/ostree-mutable-tree.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-mutable-tree.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-mutable-tree.h ostree-2017.12/src/libostree/ostree-mutable-tree.h --- ostree-2017.11/src/libostree/ostree-mutable-tree.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-mutable-tree.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-ref.c ostree-2017.12/src/libostree/ostree-ref.c --- ostree-2017.11/src/libostree/ostree-ref.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-ref.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-ref.h ostree-2017.12/src/libostree/ostree-ref.h --- ostree-2017.11/src/libostree/ostree-ref.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-ref.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-remote.c ostree-2017.12/src/libostree/ostree-remote.c --- ostree-2017.11/src/libostree/ostree-remote.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-remote.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. @@ -55,15 +54,24 @@ OstreeRemote * ostree_remote_new (const gchar *name) { + return ostree_remote_new_dynamic (name, NULL); +} + +OstreeRemote * +ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name) +{ OstreeRemote *remote; g_return_val_if_fail (name != NULL && *name != '\0', NULL); + g_return_val_if_fail (refspec_name == NULL || *refspec_name != '\0', NULL); remote = g_slice_new0 (OstreeRemote); remote->ref_count = 1; remote->name = g_strdup (name); - remote->group = g_strdup_printf ("remote \"%s\"", name); - remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", name); + remote->refspec_name = g_strdup (refspec_name); + remote->group = g_strdup_printf ("remote \"%s\"", (refspec_name != NULL) ? refspec_name : name); + remote->keyring = g_strdup_printf ("%s.trustedkeys.gpg", (refspec_name != NULL) ? refspec_name : name); remote->options = g_key_file_new (); return remote; diff -Nru ostree-2017.11/src/libostree/ostree-remote.h ostree-2017.12/src/libostree/ostree-remote.h --- ostree-2017.11/src/libostree/ostree-remote.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-remote.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. diff -Nru ostree-2017.11/src/libostree/ostree-remote-private.h ostree-2017.12/src/libostree/ostree-remote-private.h --- ostree-2017.11/src/libostree/ostree-remote-private.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-remote-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2011 Colin Walters * Copyright © 2015 Red Hat, Inc. * Copyright © 2017 Endless Mobile, Inc. @@ -36,17 +35,24 @@ G_BEGIN_DECLS +/* @refspec_name is set if this is a dynamic remote. It’s the name of the static + * remote which this one inherits from, and is what should be used in refspecs + * for pulls from this remote. If it’s %NULL, @name should be used instead. */ struct OstreeRemote { volatile int ref_count; char *name; /* (not nullable) */ + char *refspec_name; /* (nullable) */ char *group; /* group name in options (not nullable) */ - char *keyring; /* keyring name (NAME.trustedkeys.gpg) (not nullable) */ + char *keyring; /* keyring name ($refspec_name.trustedkeys.gpg) (not nullable) */ GFile *file; /* NULL if remote defined in repo/config */ GKeyFile *options; }; G_GNUC_INTERNAL OstreeRemote *ostree_remote_new (const gchar *name); +G_GNUC_INTERNAL +OstreeRemote *ostree_remote_new_dynamic (const gchar *name, + const gchar *refspec_name); G_GNUC_INTERNAL OstreeRemote *ostree_remote_new_from_keyfile (GKeyFile *keyfile, diff -Nru ostree-2017.11/src/libostree/ostree-repo.c ostree-2017.12/src/libostree/ostree-repo.c --- ostree-2017.11/src/libostree/ostree-repo.c 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2015 Red Hat, Inc. * @@ -49,6 +48,10 @@ /* ABI Size checks for ostree-repo.h, only for LP64 systems; * https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models + * + * To generate this data, I used `pahole` from gdb. More concretely, `gdb --args + * /usr/bin/ostree`, then `start`, (to ensure debuginfo was loaded), then e.g. + * `$ pahole OstreeRepoTransactionStats`. */ #if __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 && __SIZEOF_INT__ == 4 G_STATIC_ASSERT(sizeof(OstreeRepoTransactionStats) == sizeof(int) * 4 + 8 * 5); @@ -487,9 +490,7 @@ g_clear_object (&self->repodir); if (self->repo_dir_fd != -1) (void) close (self->repo_dir_fd); - if (self->commit_stagedir_fd != -1) - (void) close (self->commit_stagedir_fd); - g_free (self->commit_stagedir_name); + glnx_tmpdir_unset (&self->commit_stagedir); glnx_release_lock_file (&self->commit_stagedir_lock); if (self->tmp_dir_fd != -1) (void) close (self->tmp_dir_fd); @@ -661,7 +662,6 @@ ostree_repo_init (OstreeRepo *self) { static gsize gpgme_initialized; - GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; const GDebugKey test_error_keys[] = { { "pre-commit", OSTREE_REPO_TEST_ERROR_PRE_COMMIT }, }; @@ -687,10 +687,8 @@ self->repo_dir_fd = -1; self->cache_dir_fd = -1; self->tmp_dir_fd = -1; - self->commit_stagedir_fd = -1; self->objects_dir_fd = -1; self->uncompressed_objects_dir_fd = -1; - self->commit_stagedir_lock = empty_lockfile; self->sysroot_kind = OSTREE_REPO_SYSROOT_KIND_UNKNOWN; } @@ -1753,7 +1751,8 @@ case OSTREE_REPO_MODE_BARE_USER_ONLY: ret_mode = "bare-user-only"; break; - case OSTREE_REPO_MODE_ARCHIVE_Z2: + case OSTREE_REPO_MODE_ARCHIVE: + /* Legacy alias */ ret_mode ="archive-z2"; break; default: @@ -1779,7 +1778,7 @@ ret_mode = OSTREE_REPO_MODE_BARE_USER_ONLY; else if (strcmp (mode, "archive-z2") == 0 || strcmp (mode, "archive") == 0) - ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z2; + ret_mode = OSTREE_REPO_MODE_ARCHIVE; else return glnx_throw (error, "Invalid mode '%s' in repository configuration", mode); @@ -1809,7 +1808,9 @@ /* Early return if we have an existing repo */ { g_autofree char *objects_path = g_build_filename (path, "objects", NULL); - if (fstatat (dfd, objects_path, &stbuf, 0) == 0) + if (!glnx_fstatat_allow_noent (dfd, objects_path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { glnx_fd_close int repo_dfd = -1; if (!glnx_opendirat (dfd, path, TRUE, &repo_dfd, error)) @@ -1819,8 +1820,6 @@ *out_dfd = glnx_steal_fd (&repo_dfd); return TRUE; } - else if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstatat"); } if (mkdirat (dfd, path, 0755) != 0) @@ -1833,32 +1832,29 @@ if (!glnx_opendirat (dfd, path, TRUE, &repo_dfd, error)) return FALSE; - if (fstatat (repo_dfd, "config", &stbuf, 0) < 0) + if (!glnx_fstatat_allow_noent (repo_dfd, "config", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno == ENOENT) - { - const char *mode_str = NULL; - g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); + const char *mode_str = NULL; + g_autoptr(GString) config_data = g_string_new (DEFAULT_CONFIG_CONTENTS); - if (!ostree_repo_mode_to_string (mode, &mode_str, error)) - return FALSE; - g_assert (mode_str); + if (!ostree_repo_mode_to_string (mode, &mode_str, error)) + return FALSE; + g_assert (mode_str); - g_string_append_printf (config_data, "mode=%s\n", mode_str); + g_string_append_printf (config_data, "mode=%s\n", mode_str); - const char *collection_id = NULL; - if (options) - g_variant_lookup (options, "collection-id", "&s", &collection_id); - if (collection_id != NULL) - g_string_append_printf (config_data, "collection-id=%s\n", collection_id); - - if (!glnx_file_replace_contents_at (repo_dfd, "config", - (guint8*)config_data->str, config_data->len, - 0, cancellable, error)) - return FALSE; - } - else - return glnx_throw_errno_prefix (error, "fstatat"); + const char *collection_id = NULL; + if (options) + g_variant_lookup (options, "collection-id", "&s", &collection_id); + if (collection_id != NULL) + g_string_append_printf (config_data, "collection-id=%s\n", collection_id); + + if (!glnx_file_replace_contents_at (repo_dfd, "config", + (guint8*)config_data->str, config_data->len, + 0, cancellable, error)) + return FALSE; } for (guint i = 0; i < G_N_ELEMENTS (state_dirs); i++) @@ -2480,7 +2476,7 @@ return FALSE; /* TODO - delete this */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->enable_uncompressed_cache) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE && self->enable_uncompressed_cache) { if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, "uncompressed-objects-cache", 0755, cancellable, error)) @@ -2615,6 +2611,61 @@ return self->repo_dir_fd; } +/** + * ostree_repo_hash: + * @self: an #OstreeRepo + * + * Calculate a hash value for the given open repository, suitable for use when + * putting it into a hash table. It is an error to call this on an #OstreeRepo + * which is not yet open, as a persistent hash value cannot be calculated until + * the repository is open and the inode of its root directory has been loaded. + * + * This function does no I/O. + * + * Returns: hash value for the #OstreeRepo + * Since: 2017.12 + */ +guint +ostree_repo_hash (OstreeRepo *self) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), 0); + + /* We cannot hash non-open repositories, since their hash value would change + * once they’re opened, resulting in false lookup misses and the inability to + * remove them from a hash table. */ + g_assert (self->repo_dir_fd >= 0); + + /* device and inode numbers are distributed fairly uniformly, so we can’t + * do much better than just combining them. No need to rehash to even out + * the distribution. */ + return (self->device ^ self->inode); +} + +/** + * ostree_repo_equal: + * @a: an #OstreeRepo + * @b: an #OstreeRepo + * + * Check whether two opened repositories are the same on disk: if their root + * directories are the same inode. If @a or @b are not open yet (due to + * ostree_repo_open() not being called on them yet), %FALSE will be returned. + * + * Returns: %TRUE if @a and @b are the same repository on disk, %FALSE otherwise + * Since: 2017.12 + */ +gboolean +ostree_repo_equal (OstreeRepo *a, + OstreeRepo *b) +{ + g_return_val_if_fail (OSTREE_IS_REPO (a), FALSE); + g_return_val_if_fail (OSTREE_IS_REPO (b), FALSE); + + if (a->repo_dir_fd < 0 || b->repo_dir_fd < 0) + return FALSE; + + return (a->device == b->device && a->inode == b->inode); +} + OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self) { @@ -2676,7 +2727,7 @@ continue; OstreeObjectType objtype; - if ((self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + if ((self->mode == OSTREE_REPO_MODE_ARCHIVE && strcmp (dot, ".filez") == 0) || ((_ostree_repo_mode_is_bare (self->mode)) && strcmp (dot, ".file") == 0)) @@ -2793,9 +2844,9 @@ error)) return FALSE; - if (fd < 0 && self->commit_stagedir_fd != -1) + if (fd < 0 && self->commit_stagedir.initialized) { - if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd, + if (!ot_openat_ignore_enoent (self->commit_stagedir.fd, loose_path_buf, &fd, error)) return FALSE; } @@ -2906,9 +2957,9 @@ error)) return FALSE; - if (fd < 0 && self->commit_stagedir_fd != -1) + if (fd < 0 && self->commit_stagedir.initialized) { - if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd, + if (!ot_openat_ignore_enoent (self->commit_stagedir.fd, loose_path_buf, &fd, error)) return FALSE; } @@ -2967,9 +3018,9 @@ int objdir_fd = self->objects_dir_fd; int res; if ((res = TEMP_FAILURE_RETRY (fstatat (objdir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW))) < 0 - && errno == ENOENT && self->commit_stagedir_fd != -1) + && errno == ENOENT && self->commit_stagedir.initialized) { - objdir_fd = self->commit_stagedir_fd; + objdir_fd = self->commit_stagedir.fd; res = TEMP_FAILURE_RETRY (fstatat (objdir_fd, loose_path_buf, &stbuf, AT_SYMLINK_NOFOLLOW)); } if (res < 0 && errno != ENOENT) @@ -3102,7 +3153,7 @@ GCancellable *cancellable, GError **error) { - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) return repo_load_file_archive (self, checksum, out_input, out_file_info, out_xattrs, cancellable, error); else @@ -3214,7 +3265,9 @@ gboolean found = FALSE; /* It's easier to share code if we make this an array */ - const int dfd_searches[] = { self->commit_stagedir_fd, self->objects_dir_fd }; + int dfd_searches[] = { -1, self->objects_dir_fd }; + if (self->commit_stagedir.initialized) + dfd_searches[0] = self->commit_stagedir.fd; for (guint i = 0; i < G_N_ELEMENTS (dfd_searches); i++) { int dfd = dfd_searches[i]; @@ -3346,114 +3399,6 @@ return TRUE; } -static gboolean -copy_detached_metadata (OstreeRepo *self, - OstreeRepo *source, - const char *checksum, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GVariant) detached_meta = NULL; - if (!ostree_repo_read_commit_detached_metadata (source, - checksum, &detached_meta, - cancellable, error)) - return FALSE; - - if (detached_meta) - { - if (!ostree_repo_write_commit_detached_metadata (self, - checksum, detached_meta, - cancellable, error)) - return FALSE; - } - - return TRUE; -} - -/* Special case between bare-user and bare-user-only, - * mostly for https://github.com/flatpak/flatpak/issues/845 - * see below for any more comments. - */ -static gboolean -import_is_bareuser_only_conversion (OstreeRepo *src_repo, - OstreeRepo *dest_repo, - OstreeObjectType objtype) -{ - return src_repo->mode == OSTREE_REPO_MODE_BARE_USER - && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY - && objtype == OSTREE_OBJECT_TYPE_FILE; -} - -static gboolean -import_one_object_link (OstreeRepo *self, - OstreeRepo *source, - const char *checksum, - OstreeObjectType objtype, - gboolean *out_was_supported, - GCancellable *cancellable, - GError **error) -{ - const char *errprefix = glnx_strjoina ("Importing ", checksum, ".", - ostree_object_type_to_string (objtype)); - GLNX_AUTO_PREFIX_ERROR (errprefix, error); - char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - _ostree_loose_path (loose_path_buf, checksum, objtype, self->mode); - - /* Hardlinking between bare-user → bare-user-only is only possible for regular - * files, *not* symlinks, which in bare-user are stored as regular files. At - * this point we need to parse the file to see the difference. - */ - if (import_is_bareuser_only_conversion (source, self, objtype)) - { - struct stat stbuf; - - if (!_ostree_repo_load_file_bare (source, checksum, NULL, &stbuf, - NULL, NULL, cancellable, error)) - return FALSE; - - if (S_ISREG (stbuf.st_mode)) - { - /* This is OK, we'll drop through and try a hardlink */ - } - else if (S_ISLNK (stbuf.st_mode)) - { - /* NOTE early return */ - *out_was_supported = FALSE; - return TRUE; - } - else - g_assert_not_reached (); - } - - if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path_buf, cancellable, error)) - return FALSE; - - *out_was_supported = TRUE; - if (linkat (source->objects_dir_fd, loose_path_buf, self->objects_dir_fd, loose_path_buf, 0) != 0) - { - if (errno == EEXIST) - return TRUE; - else if (errno == EMLINK || errno == EXDEV || errno == EPERM) - { - /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do the - * optimization of hardlinking instead of copying. - */ - *out_was_supported = FALSE; - return TRUE; - } - else - return glnx_throw_errno_prefix (error, "linkat"); - } - - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - if (!copy_detached_metadata (self, source, checksum, cancellable, error)) - return FALSE; - } - - return TRUE; -} - /** * ostree_repo_import_object_from: * @self: Destination repo @@ -3483,28 +3428,6 @@ checksum, TRUE, cancellable, error); } -static gboolean -import_via_hardlink_is_possible (OstreeRepo *src_repo, - OstreeRepo *dest_repo, - OstreeObjectType objtype) -{ - /* We need the ability to make hardlinks */ - if (src_repo->owner_uid != dest_repo->owner_uid) - return FALSE; - /* Equal modes are always compatible */ - if (src_repo->mode == dest_repo->mode) - return TRUE; - /* Metadata is identical between all modes */ - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) - return TRUE; - /* And now a special case between bare-user and bare-user-only, - * mostly for https://github.com/flatpak/flatpak/issues/845 - */ - if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype)) - return TRUE; - return FALSE; -} - /** * ostree_repo_import_object_from_with_trust: * @self: Destination repo @@ -3531,103 +3454,12 @@ GCancellable *cancellable, GError **error) { - /* We try to import via hardlink. If the remote is explicitly not trusted - * (i.e.) their checksums may be incorrect, we skip that. Also, we require the - * repository modes to match, as well as the owner uid (since we need to be - * able to make hardlinks). - */ - if (trusted && import_via_hardlink_is_possible (source, self, objtype)) - { - gboolean hardlink_was_supported = FALSE; - - if (!import_one_object_link (self, source, checksum, objtype, - &hardlink_was_supported, - cancellable, error)) - return FALSE; - - /* If we hardlinked, we're done! */ - if (hardlink_was_supported) - return TRUE; - } - - /* The copy path */ - - /* First, do we have the object already? */ - gboolean has_object; - if (!ostree_repo_has_object (self, objtype, checksum, &has_object, - cancellable, error)) - return FALSE; - /* If we have it, we're done */ - if (has_object) - return TRUE; - - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) - { - /* Metadata object */ - g_autoptr(GVariant) variant = NULL; - - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - /* FIXME - cleanup detached metadata if copy below fails */ - if (!copy_detached_metadata (self, source, checksum, cancellable, error)) - return FALSE; - } - - if (!ostree_repo_load_variant (source, objtype, checksum, - &variant, error)) - return FALSE; - - if (trusted) - { - if (!ostree_repo_write_metadata_trusted (self, objtype, - checksum, variant, - cancellable, error)) - return FALSE; - } - else - { - g_autofree guchar *real_csum = NULL; - - if (!ostree_repo_write_metadata (self, objtype, - checksum, variant, - &real_csum, - cancellable, error)) - return FALSE; - } - } - else - { - /* Content object */ - guint64 length; - g_autoptr(GInputStream) object_stream = NULL; - - if (!ostree_repo_load_object_stream (source, objtype, checksum, - &object_stream, &length, - cancellable, error)) - return FALSE; - - if (trusted) - { - if (!ostree_repo_write_content_trusted (self, checksum, - object_stream, length, - cancellable, error)) - return FALSE; - } - else - { - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_content (self, checksum, - object_stream, length, - &real_csum, - cancellable, error)) - return FALSE; - } - } - - return TRUE; + /* This just wraps a currently internal API, may make it public later */ + OstreeRepoImportFlags flags = trusted ? _OSTREE_REPO_IMPORT_FLAGS_TRUSTED : 0; + return _ostree_repo_import_object (self, source, objtype, checksum, + flags, cancellable, error); } - /** * ostree_repo_query_object_storage_size: * @self: Repo @@ -3654,8 +3486,8 @@ struct stat stbuf; res = TEMP_FAILURE_RETRY (fstatat (self->objects_dir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); - if (res < 0 && errno == ENOENT && self->commit_stagedir_fd != -1) - res = TEMP_FAILURE_RETRY (fstatat (self->commit_stagedir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); + if (res < 0 && errno == ENOENT && self->commit_stagedir.initialized) + res = TEMP_FAILURE_RETRY (fstatat (self->commit_stagedir.fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW)); if (res < 0) return glnx_throw_errno_prefix (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype)); @@ -4023,7 +3855,7 @@ gpointer user_data) { g_autofree char *status = NULL; - gboolean scanning; + gboolean caught_error, scanning; guint outstanding_fetches; guint outstanding_metadata_fetches; guint outstanding_writes; @@ -4039,6 +3871,7 @@ "outstanding-fetches", "u", &outstanding_fetches, "outstanding-metadata-fetches", "u", &outstanding_metadata_fetches, "outstanding-writes", "u", &outstanding_writes, + "caught-error", "b", &caught_error, "scanning", "u", &scanning, "scanned-metadata", "u", &n_scanned_metadata, "fetched-delta-parts", "u", &fetched_delta_parts, @@ -4052,6 +3885,10 @@ { g_string_append (buf, status); } + else if (caught_error) + { + g_string_append_printf (buf, "Caught error, waiting for outstanding tasks"); + } else if (outstanding_fetches) { guint64 bytes_transferred, start_time, total_delta_part_size; @@ -4191,88 +4028,52 @@ GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_auto(GLnxTmpfile) tmpf = { 0, }; - g_autoptr(GOutputStream) tmp_signature_output = NULL; - gpgme_ctx_t context = NULL; - g_autoptr(GBytes) ret_signature = NULL; - gpgme_error_t err; - gpgme_key_t key = NULL; - gpgme_data_t commit_buffer = NULL; - gpgme_data_t signature_buffer = NULL; - g_autoptr(GMappedFile) signature_file = NULL; - if (!glnx_open_tmpfile_linkable_at (self->tmp_dir_fd, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) - goto out; - tmp_signature_output = g_unix_output_stream_new (tmpf.fd, FALSE); + return FALSE; + g_autoptr(GOutputStream) tmp_signature_output = g_unix_output_stream_new (tmpf.fd, FALSE); - context = ot_gpgme_new_ctx (homedir, error); + g_auto(gpgme_ctx_t) context = ot_gpgme_new_ctx (homedir, error); if (!context) - goto out; + return FALSE; /* Get the secret keys with the given key id */ - err = gpgme_get_key (context, key_id, &key, 1); + g_auto(gpgme_key_t) key = NULL; + gpgme_error_t err = gpgme_get_key (context, key_id, &key, 1); if (gpgme_err_code (err) == GPG_ERR_EOF) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No gpg key found with ID %s (homedir: %s)", key_id, - homedir ? homedir : ""); - goto out; - } + return glnx_throw (error, "No gpg key found with ID %s (homedir: %s)", key_id, + homedir ? homedir : ""); else if (err != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Unable to lookup key ID %s", key_id); - goto out; - } + return ot_gpgme_throw (err, error, "Unable to lookup key ID %s", key_id); /* Add the key to the context as a signer */ if ((err = gpgme_signers_add (context, key)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Error signing commit"); - goto out; - } - - { - gsize len; - const char *buf = g_bytes_get_data (input_data, &len); - if ((err = gpgme_data_new_from_mem (&commit_buffer, buf, len, FALSE)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Failed to create buffer from commit file"); - goto out; - } - } + return ot_gpgme_throw (err, error, "Error signing commit"); - signature_buffer = ot_gpgme_data_output (tmp_signature_output); + /* Get a gpg buffer from the commit */ + g_auto(gpgme_data_t) commit_buffer = NULL; + gsize len; + const char *buf = g_bytes_get_data (input_data, &len); + if ((err = gpgme_data_new_from_mem (&commit_buffer, buf, len, FALSE)) != GPG_ERR_NO_ERROR) + return ot_gpgme_throw (err, error, "Failed to create buffer from commit file"); + /* Sign it */ + g_auto(gpgme_data_t) signature_buffer = ot_gpgme_data_output (tmp_signature_output); if ((err = gpgme_op_sign (context, commit_buffer, signature_buffer, GPGME_SIG_MODE_DETACH)) != GPG_ERR_NO_ERROR) - { - ot_gpgme_throw (err, error, "Failure signing commit file"); - goto out; - } - + return ot_gpgme_throw (err, error, "Failure signing commit file"); if (!g_output_stream_close (tmp_signature_output, cancellable, error)) - goto out; - - signature_file = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); + return FALSE; + + /* Return a mmap() reference */ + g_autoptr(GMappedFile) signature_file = g_mapped_file_new_from_fd (tmpf.fd, FALSE, error); if (!signature_file) - goto out; - ret_signature = g_mapped_file_get_bytes (signature_file); - - ret = TRUE; + return FALSE; + if (out_signature) - *out_signature = g_steal_pointer (&ret_signature); -out: - if (commit_buffer) - gpgme_data_release (commit_buffer); - if (signature_buffer) - gpgme_data_release (signature_buffer); - if (key) - gpgme_key_release (key); - if (context) - gpgme_release (context); - return ret; + *out_signature = g_mapped_file_get_bytes (signature_file); + return TRUE; } /** @@ -5097,8 +4898,7 @@ gboolean _ostree_repo_is_locked_tmpdir (const char *filename) { - return g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_STAGING) || - g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_FETCHER); + return g_str_has_prefix (filename, OSTREE_REPO_TMPDIR_STAGING); } gboolean @@ -5141,8 +4941,7 @@ gboolean _ostree_repo_allocate_tmpdir (int tmpdir_dfd, const char *tmpdir_prefix, - char **tmpdir_name_out, - int *tmpdir_fd_out, + GLnxTmpDir *tmpdir_out, GLnxLockFile *file_lock_out, gboolean *reusing_dir_out, GCancellable *cancellable, @@ -5157,9 +4956,8 @@ gboolean reusing_dir = FALSE; gboolean did_lock = FALSE; - g_autofree char *tmpdir_name = NULL; - glnx_fd_close int tmpdir_fd = -1; - while (tmpdir_name == NULL) + g_auto(GLnxTmpDir) ret_tmpdir = { 0, }; + while (!ret_tmpdir.initialized) { struct dirent *dent; glnx_fd_close int existing_tmpdir_fd = -1; @@ -5179,8 +4977,9 @@ dent->d_type != DT_DIR) continue; + glnx_fd_close int target_dfd = -1; if (!glnx_opendirat (dfd_iter.fd, dent->d_name, FALSE, - &existing_tmpdir_fd, &local_error)) + &target_dfd, &local_error)) { if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_DIRECTORY)) continue; @@ -5203,45 +5002,40 @@ /* Touch the reused directory so that we don't accidentally * remove it due to being old when cleaning up the tmpdir. */ - (void)futimens (existing_tmpdir_fd, NULL); + (void)futimens (target_dfd, NULL); /* We found an existing tmpdir which we managed to lock */ - tmpdir_name = g_strdup (dent->d_name); - tmpdir_fd = glnx_steal_fd (&existing_tmpdir_fd); - reusing_dir = TRUE; + ret_tmpdir.src_dfd = tmpdir_dfd; + ret_tmpdir.fd = glnx_steal_fd (&target_dfd); + ret_tmpdir.path = g_strdup (dent->d_name); + ret_tmpdir.initialized = TRUE; } - while (tmpdir_name == NULL) + const char *tmpdir_name_template = glnx_strjoina (tmpdir_prefix, "XXXXXX"); + while (!ret_tmpdir.initialized) { + g_auto(GLnxTmpDir) new_tmpdir = { 0, }; /* No existing tmpdir found, create a new */ - g_autofree char *tmpdir_name_template = g_strconcat (tmpdir_prefix, "XXXXXX", NULL); - if (!glnx_mkdtempat (tmpdir_dfd, tmpdir_name_template, 0777, error)) - return FALSE; - - glnx_fd_close int new_tmpdir_fd = -1; - if (!glnx_opendirat (tmpdir_dfd, tmpdir_name_template, FALSE, - &new_tmpdir_fd, error)) + if (!glnx_mkdtempat (tmpdir_dfd, tmpdir_name_template, 0755, + &new_tmpdir, error)) return FALSE; /* Note, at this point we can race with another process that picks up this * new directory. If that happens we need to retry, making a new directory. */ - if (!_ostree_repo_try_lock_tmpdir (tmpdir_dfd, tmpdir_name_template, + if (!_ostree_repo_try_lock_tmpdir (new_tmpdir.src_dfd, new_tmpdir.path, file_lock_out, &did_lock, error)) return FALSE; if (!did_lock) continue; - tmpdir_name = g_steal_pointer (&tmpdir_name_template); - tmpdir_fd = glnx_steal_fd (&new_tmpdir_fd); + ret_tmpdir = new_tmpdir; /* Transfer ownership */ + new_tmpdir.initialized = FALSE; } - if (tmpdir_name_out) - *tmpdir_name_out = g_steal_pointer (&tmpdir_name); - if (tmpdir_fd_out) - *tmpdir_fd_out = glnx_steal_fd (&tmpdir_fd); - if (reusing_dir_out) - *reusing_dir_out = reusing_dir; + *tmpdir_out = ret_tmpdir; /* Transfer ownership */ + ret_tmpdir.initialized = FALSE; + *reusing_dir_out = reusing_dir; return TRUE; } diff -Nru ostree-2017.11/src/libostree/ostree-repo-checkout.c ostree-2017.12/src/libostree/ostree-repo-checkout.c --- ostree-2017.11/src/libostree/ostree-repo-checkout.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-checkout.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -303,11 +302,11 @@ return FALSE; /* The add/union/none behaviors map directly to GLnxLinkTmpfileReplaceMode */ - GLnxLinkTmpfileReplaceMode replace_mode; + GLnxLinkTmpfileReplaceMode replace_mode = GLNX_LINK_TMPFILE_NOREPLACE; switch (options->overwrite_mode) { case OSTREE_REPO_CHECKOUT_OVERWRITE_NONE: - replace_mode = GLNX_LINK_TMPFILE_NOREPLACE; + /* Handled above */ break; case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES: replace_mode = GLNX_LINK_TMPFILE_REPLACE; @@ -338,6 +337,41 @@ HARDLINK_RESULT_LINKED } HardlinkResult; +/* Used for OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES. In + * order to atomically replace a target, we add a new link + * in self->tmp_dir_fd, with a name placed into the mutable + * buffer @tmpname. + */ +static gboolean +hardlink_add_tmp_name (OstreeRepo *self, + int srcfd, + const char *loose_path, + char *tmpname, + GCancellable *cancellable, + GError **error) +{ + const int max_attempts = 128; + guint i; + + for (i = 0; i < max_attempts; i++) + { + glnx_gen_temp_name (tmpname); + if (linkat (srcfd, loose_path, self->tmp_dir_fd, tmpname, 0) < 0) + { + if (errno == EEXIST) + continue; + else + return glnx_throw_errno_prefix (error, "linkat"); + } + else + break; + } + if (i == max_attempts) + return glnx_throw (error, "Exhausted attempts to make temporary hardlink"); + + return TRUE; +} + static gboolean checkout_file_hardlink (OstreeRepo *self, OstreeRepoCheckoutAtOptions *options, @@ -353,7 +387,6 @@ int srcfd = _ostree_repo_mode_is_bare (self->mode) ? self->objects_dir_fd : self->uncompressed_objects_dir_fd; - again: if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) == 0) ret_result = HARDLINK_RESULT_LINKED; else if (!options->no_copy_fallback && (errno == EMLINK || errno == EXDEV || errno == EPERM)) @@ -380,27 +413,20 @@ ret_result = HARDLINK_RESULT_SKIP_EXISTED; break; case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES: - { - /* Idiocy, from man rename(2) - * - * "If oldpath and newpath are existing hard links referring to - * the same file, then rename() does nothing, and returns a - * success status." - * - * So we can't make this atomic. - */ - (void) unlinkat (destination_dfd, destination_name, 0); - goto again; - } case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL: { - /* In this mode, we error out on EEXIST *unless* the files are already - * hardlinked, which is what rpm-ostree wants for package layering. - * https://github.com/projectatomic/rpm-ostree/issues/982 + /* In both union-files and union-identical, see if the src/target are + * already hardlinked. If they are, we're done. * + * If not, for union-identical we error out, which is what + * rpm-ostree wants for package layering. + * https://github.com/projectatomic/rpm-ostree/issues/982 * This should be similar to the librpm version: * https://github.com/rpm-software-management/rpm/blob/e3cd2bc85e0578f158d14e6f9624eb955c32543b/lib/rpmfi.c#L921 * in rpmfilesCompare(). + * + * For union-files, we make a temporary link, then rename() it + * into place. */ struct stat src_stbuf; if (!glnx_fstatat (srcfd, loose_path, &src_stbuf, @@ -413,10 +439,25 @@ const gboolean is_identical = (src_stbuf.st_dev == dest_stbuf.st_dev && src_stbuf.st_ino == dest_stbuf.st_ino); + if (is_identical) ret_result = HARDLINK_RESULT_SKIP_EXISTED; + else if (options->overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES) + { + char *tmpname = strdupa ("checkout-union-XXXXXX"); + /* Make a link with a temp name */ + if (!hardlink_add_tmp_name (self, srcfd, loose_path, tmpname, cancellable, error)) + return FALSE; + /* Rename it into place */ + if (!glnx_renameat (self->tmp_dir_fd, tmpname, destination_dfd, destination_name, error)) + return FALSE; + ret_result = HARDLINK_RESULT_LINKED; + } else - return glnx_throw_errno_prefix (error, "Hardlinking %s to %s", loose_path, destination_name); + { + g_assert_cmpint (options->overwrite_mode, ==, OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL); + return glnx_throw_errno_prefix (error, "Hardlinking %s to %s", loose_path, destination_name); + } break; } } @@ -495,7 +536,7 @@ (repo_is_usermode && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER); gboolean current_can_cache = (options->enable_uncompressed_cache && current_repo->enable_uncompressed_cache); - gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER && current_can_cache); @@ -567,7 +608,7 @@ && !is_whiteout && !is_symlink && need_copy - && repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + && repo->mode == OSTREE_REPO_MODE_ARCHIVE && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER) { HardlinkResult hardlink_res = HARDLINK_RESULT_NOT_SUPPORTED; diff -Nru ostree-2017.11/src/libostree/ostree-repo-commit.c ostree-2017.12/src/libostree/ostree-repo-commit.c --- ostree-2017.11/src/libostree/ostree-repo-commit.c 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-commit.c 2017-10-02 17:11:19.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -140,7 +139,7 @@ int dest_dfd; if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; @@ -173,7 +172,7 @@ int dest_dfd; if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; @@ -216,7 +215,7 @@ /* We may be writing as root to a non-root-owned repository; if so, * automatically inherit the non-root ownership. */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 + if (self->mode == OSTREE_REPO_MODE_ARCHIVE && self->target_owner_uid != -1) { if (fchown (tmpf->fd, self->target_owner_uid, self->target_owner_gid) < 0) @@ -262,10 +261,8 @@ } else if (self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY) { - guint32 invalid_modebits = (mode & ~S_IFMT) & ~0775; - if (invalid_modebits > 0) - return glnx_throw (error, "Invalid mode 0%04o with bits 0%04o in bare-user-only repository", - mode, invalid_modebits); + if (!_ostree_validate_bareuseronly_mode (mode, checksum, error)) + return FALSE; if (!glnx_fchmod (tmpf->fd, mode, error)) return FALSE; @@ -606,7 +603,7 @@ cancellable, error)) return FALSE; } - else if (repo_mode != OSTREE_REPO_MODE_ARCHIVE_Z2) + else if (repo_mode != OSTREE_REPO_MODE_ARCHIVE) { if (!create_regular_tmpfile_linkable_with_content (self, size, file_input, &tmpf, cancellable, error)) @@ -619,7 +616,7 @@ g_autoptr(GOutputStream) compressed_out_stream = NULL; g_autoptr(GOutputStream) temp_out = NULL; - g_assert (repo_mode == OSTREE_REPO_MODE_ARCHIVE_Z2); + g_assert (repo_mode == OSTREE_REPO_MODE_ARCHIVE); if (self->generate_sizes) indexable = TRUE; @@ -935,7 +932,7 @@ gboolean skip; switch (self->mode) { - case OSTREE_REPO_MODE_ARCHIVE_Z2: + case OSTREE_REPO_MODE_ARCHIVE: case OSTREE_REPO_MODE_BARE: case OSTREE_REPO_MODE_BARE_USER: case OSTREE_REPO_MODE_BARE_USER_ONLY: @@ -984,7 +981,7 @@ return FALSE; } - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) { if (!scan_one_loose_devino (self, self->uncompressed_objects_dir_fd, devino_cache, cancellable, error)) @@ -1114,8 +1111,7 @@ gboolean ret_transaction_resume = FALSE; if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd, self->stagedir_prefix, - &self->commit_stagedir_name, - &self->commit_stagedir_fd, + &self->commit_stagedir, &self->commit_stagedir_lock, &ret_transaction_resume, cancellable, error)) @@ -1134,7 +1130,7 @@ GLNX_AUTO_PREFIX_ERROR ("rename pending", error); g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - if (!glnx_dirfd_iterator_init_at (self->commit_stagedir_fd, ".", FALSE, &dfd_iter, error)) + if (!glnx_dirfd_iterator_init_at (self->commit_stagedir.fd, ".", FALSE, &dfd_iter, error)) return FALSE; /* Iterate over the outer checksum dir */ @@ -1188,7 +1184,7 @@ renamed_some_object = TRUE; } - if (renamed_some_object) + if (renamed_some_object && !self->disable_fsync) { /* Ensure that in the case of a power cut all the directory metadata that we want has reached the disk. In particular, we want this before we @@ -1209,11 +1205,13 @@ } /* In case we created any loose object subdirs, make sure they are on disk */ - if (fsync (self->objects_dir_fd) == -1) - return glnx_throw_errno_prefix (error, "fsync"); + if (!self->disable_fsync) + { + if (fsync (self->objects_dir_fd) == -1) + return glnx_throw_errno_prefix (error, "fsync"); + } - if (!glnx_shutil_rm_rf_at (self->tmp_dir_fd, self->commit_stagedir_name, - cancellable, error)) + if (!glnx_tmpdir_delete (&self->commit_stagedir, cancellable, error)) return FALSE; return TRUE; @@ -1236,7 +1234,7 @@ guint64 delta; struct dirent *dent; struct stat stbuf; - g_auto(GLnxLockFile) lockfile = GLNX_LOCK_FILE_INIT; + g_auto(GLnxLockFile) lockfile = { 0, }; gboolean did_lock; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) @@ -1251,12 +1249,10 @@ if (strcmp (dent->d_name, "cache") == 0) continue; - if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW)) < 0) - { - if (errno == ENOENT) /* Did another cleanup win? */ - continue; - return glnx_throw_errno_prefix (error, "fstatat(%s)", dent->d_name); - } + if (!glnx_fstatat_allow_noent (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + if (errno == ENOENT) /* Did another cleanup win? */ + continue; /* First, if it's a directory which needs locking, but it's * busy, skip it. @@ -1284,13 +1280,6 @@ if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error)) return glnx_prefix_error (error, "Removing %s", dent->d_name); } - /* 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 @@ -1528,10 +1517,11 @@ if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_PRE_COMMIT) > 0) return glnx_throw (error, "OSTREE_REPO_TEST_ERROR_PRE_COMMIT specified"); - /* FIXME: Added since valgrind in el7 doesn't know about - * `syncfs`...we should delete this later. + /* FIXME: Added OSTREE_SUPPRESS_SYNCFS since valgrind in el7 doesn't know + * about `syncfs`...we should delete this later. */ - if (g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL) + if (!self->disable_fsync && + g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL) { if (syncfs (self->tmp_dir_fd) < 0) return glnx_throw_errno_prefix (error, "syncfs"); @@ -1556,15 +1546,8 @@ return FALSE; g_clear_pointer (&self->txn_collection_refs, g_hash_table_destroy); - if (self->commit_stagedir_fd != -1) - { - (void) close (self->commit_stagedir_fd); - self->commit_stagedir_fd = -1; - - glnx_release_lock_file (&self->commit_stagedir_lock); - } - - g_clear_pointer (&self->commit_stagedir_name, g_free); + glnx_tmpdir_unset (&self->commit_stagedir); + glnx_release_lock_file (&self->commit_stagedir_lock); self->in_transaction = FALSE; @@ -1595,14 +1578,8 @@ g_clear_pointer (&self->txn_refs, g_hash_table_destroy); g_clear_pointer (&self->txn_collection_refs, g_hash_table_destroy); - if (self->commit_stagedir_fd != -1) - { - (void) close (self->commit_stagedir_fd); - self->commit_stagedir_fd = -1; - - glnx_release_lock_file (&self->commit_stagedir_lock); - } - g_clear_pointer (&self->commit_stagedir_name, g_free); + glnx_tmpdir_unset (&self->commit_stagedir); + glnx_release_lock_file (&self->commit_stagedir_lock); self->in_transaction = FALSE; @@ -2093,22 +2070,10 @@ GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GDateTime *now = NULL; - - now = g_date_time_new_now_utc (); - ret = ostree_repo_write_commit_with_time (self, - parent, - subject, - body, - metadata, - root, - g_date_time_to_unix (now), - out_commit, - cancellable, - error); - g_date_time_unref (now); - return ret; + g_autoptr(GDateTime) now = g_date_time_new_now_utc (); + return ostree_repo_write_commit_with_time (self, parent, subject, body, + metadata, root, g_date_time_to_unix (now), + out_commit, cancellable, error); } /** @@ -2188,8 +2153,8 @@ _ostree_loose_path (buf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); g_autoptr(GVariant) ret_metadata = NULL; - if (self->commit_stagedir_fd != -1 && - !ot_util_variant_map_at (self->commit_stagedir_fd, buf, + if (self->commit_stagedir.initialized && + !ot_util_variant_map_at (self->commit_stagedir.fd, buf, G_VARIANT_TYPE ("a{sv}"), OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) return glnx_prefix_error (error, "Unable to read existing detached metadata"); @@ -2229,23 +2194,19 @@ GCancellable *cancellable, GError **error) { - char pathbuf[_OSTREE_LOOSE_PATH_MAX]; - g_autoptr(GVariant) normalized = NULL; - gsize normalized_size = 0; - const guint8 *data = NULL; int dest_dfd; - if (self->in_transaction) - dest_dfd = self->commit_stagedir_fd; + dest_dfd = self->commit_stagedir.fd; else dest_dfd = self->objects_dir_fd; - _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); - if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, checksum, cancellable, error)) return FALSE; + g_autoptr(GVariant) normalized = NULL; + gsize normalized_size = 0; + const guint8 *data = NULL; if (metadata != NULL) { normalized = g_variant_get_normal_form (metadata); @@ -2256,6 +2217,8 @@ if (data == NULL) data = (guint8*)""; + char pathbuf[_OSTREE_LOOSE_PATH_MAX]; + _ostree_loose_path (pathbuf, checksum, OSTREE_OBJECT_TYPE_COMMIT_META, self->mode); if (!glnx_file_replace_contents_at (dest_dfd, pathbuf, data, normalized_size, 0, cancellable, error)) @@ -2273,14 +2236,11 @@ GHashTable *dir_metadata_checksums) { GVariantBuilder files_builder; - GVariantBuilder dirs_builder; - GSList *sorted_filenames = NULL; - GSList *iter; - GVariant *serialized_tree; - g_variant_builder_init (&files_builder, G_VARIANT_TYPE ("a(say)")); + GVariantBuilder dirs_builder; g_variant_builder_init (&dirs_builder, G_VARIANT_TYPE ("a(sayay)")); + GSList *sorted_filenames = NULL; GLNX_HASH_TABLE_FOREACH (file_checksums, const char*, name) { /* Should have been validated earlier, but be paranoid */ @@ -2288,10 +2248,8 @@ sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); } - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - - for (iter = sorted_filenames; iter; iter = iter->next) + for (GSList *iter = sorted_filenames; iter; iter = iter->next) { const char *name = iter->data; const char *value; @@ -2300,25 +2258,20 @@ g_variant_builder_add (&files_builder, "(s@ay)", name, ostree_checksum_to_bytes_v (value)); } - g_slist_free (sorted_filenames); sorted_filenames = NULL; + GLNX_HASH_TABLE_FOREACH (dir_metadata_checksums, const char*, name) sorted_filenames = g_slist_prepend (sorted_filenames, (char*)name); - sorted_filenames = g_slist_sort (sorted_filenames, (GCompareFunc)strcmp); - for (iter = sorted_filenames; iter; iter = iter->next) + for (GSList *iter = sorted_filenames; iter; iter = iter->next) { const char *name = iter->data; - const char *content_checksum; - const char *meta_checksum; + const char *content_checksum = g_hash_table_lookup (dir_contents_checksums, name); + const char *meta_checksum = g_hash_table_lookup (dir_metadata_checksums, name); - content_checksum = g_hash_table_lookup (dir_contents_checksums, name); - meta_checksum = g_hash_table_lookup (dir_metadata_checksums, name); - - g_variant_builder_add (&dirs_builder, "(s@ay@ay)", - name, + g_variant_builder_add (&dirs_builder, "(s@ay@ay)", name, ostree_checksum_to_bytes_v (content_checksum), ostree_checksum_to_bytes_v (meta_checksum)); } @@ -2326,12 +2279,11 @@ g_slist_free (sorted_filenames); sorted_filenames = NULL; - serialized_tree = g_variant_new ("(@a(say)@a(sayay))", - g_variant_builder_end (&files_builder), - g_variant_builder_end (&dirs_builder)); - g_variant_ref_sink (serialized_tree); - - return serialized_tree; + GVariant *serialized_tree = + g_variant_new ("(@a(say)@a(sayay))", + g_variant_builder_end (&files_builder), + g_variant_builder_end (&dirs_builder)); + return g_variant_ref_sink (serialized_tree); } /* If any filtering is set up, perform it, and return modified file info in @@ -2392,16 +2344,13 @@ static char * ptrarray_path_join (GPtrArray *path) { - GString *path_buf; - - path_buf = g_string_new (""); + GString *path_buf = g_string_new (""); if (path->len == 0) g_string_append_c (path_buf, '/'); else { - guint i; - for (i = 0; i < path->len; i++) + for (guint i = 0; i < path->len; i++) { const char *elt = path->pdata[i]; @@ -2414,58 +2363,68 @@ } static gboolean -get_modified_xattrs (OstreeRepo *self, - OstreeRepoCommitModifier *modifier, - const char *relpath, - GFileInfo *file_info, - GFile *path, - int dfd, - const char *dfd_subpath, - GVariant **out_xattrs, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GVariant) ret_xattrs = NULL; - - if (modifier && modifier->xattr_callback) - { - ret_xattrs = modifier->xattr_callback (self, relpath, file_info, - modifier->xattr_user_data); - } - else if (!(modifier && (modifier->flags & (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS | - OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS)) > 0) - && !self->disable_xattrs) +get_final_xattrs (OstreeRepo *self, + OstreeRepoCommitModifier *modifier, + const char *relpath, + GFileInfo *file_info, + GFile *path, + int dfd, + const char *dfd_subpath, + GVariant **out_xattrs, + gboolean *out_modified, + GCancellable *cancellable, + GError **error) +{ + /* track whether the returned xattrs differ from the file on disk */ + gboolean modified = TRUE; + const gboolean skip_xattrs = (modifier && + modifier->flags & (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS | + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS)) > 0; + + /* fetch on-disk xattrs if needed & not disabled */ + g_autoptr(GVariant) original_xattrs = NULL; + if (!skip_xattrs && !self->disable_xattrs) { if (path && OSTREE_IS_REPO_FILE (path)) { - if (!ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (path), - &ret_xattrs, - cancellable, - error)) + if (!ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (path), &original_xattrs, + cancellable, error)) return FALSE; } else if (path) { if (!glnx_dfd_name_get_all_xattrs (AT_FDCWD, gs_file_get_path_cached (path), - &ret_xattrs, cancellable, error)) + &original_xattrs, cancellable, error)) return FALSE; } else if (dfd_subpath == NULL) { g_assert (dfd != -1); - if (!glnx_fd_get_all_xattrs (dfd, &ret_xattrs, - cancellable, error)) + if (!glnx_fd_get_all_xattrs (dfd, &original_xattrs, cancellable, error)) return FALSE; } else { g_assert (dfd != -1); - if (!glnx_dfd_name_get_all_xattrs (dfd, dfd_subpath, &ret_xattrs, - cancellable, error)) + if (!glnx_dfd_name_get_all_xattrs (dfd, dfd_subpath, &original_xattrs, + cancellable, error)) return FALSE; } + + g_assert (original_xattrs); + } + + g_autoptr(GVariant) ret_xattrs = NULL; + if (modifier && modifier->xattr_callback) + { + ret_xattrs = modifier->xattr_callback (self, relpath, file_info, + modifier->xattr_user_data); } + /* if callback returned NULL or didn't exist, default to on-disk state */ + if (!ret_xattrs && original_xattrs) + ret_xattrs = g_variant_ref (original_xattrs); + if (modifier && modifier->sepolicy) { g_autofree char *label = NULL; @@ -2487,10 +2446,9 @@ { /* drop out any existing SELinux policy from the set, so we don't end up * counting it twice in the checksum */ - g_autoptr(GVariant) new_ret_xattrs = NULL; - new_ret_xattrs = _ostree_filter_selinux_xattr (ret_xattrs); + GVariant* new_ret_xattrs = _ostree_filter_selinux_xattr (ret_xattrs); g_variant_unref (ret_xattrs); - ret_xattrs = g_steal_pointer (&new_ret_xattrs); + ret_xattrs = new_ret_xattrs; } /* ret_xattrs may be NULL */ @@ -2509,8 +2467,13 @@ } } + if (original_xattrs && ret_xattrs && g_variant_equal (original_xattrs, ret_xattrs)) + modified = FALSE; + if (out_xattrs) *out_xattrs = g_steal_pointer (&ret_xattrs); + if (out_modified) + *out_modified = modified; return TRUE; } @@ -2531,6 +2494,10 @@ GCancellable *cancellable, GError **error); +/* Given either a dir_enum or a dfd_iter, writes the directory entry to the mtree. For + * subdirs, we go back through either write_dfd_iter_to_mtree_internal (dfd_iter case) or + * write_directory_to_mtree_internal (dir_enum case) which will do the actual dirmeta + + * dirent iteration. */ static gboolean write_directory_content_to_mtree_internal (OstreeRepo *self, OstreeRepoFile *repo_dir, @@ -2543,23 +2510,17 @@ GCancellable *cancellable, GError **error) { - g_autoptr(GFile) child = NULL; - g_autoptr(GFileInfo) modified_info = NULL; - g_autoptr(OstreeMutableTree) child_mtree = NULL; - g_autofree char *child_relpath = NULL; - const char *name; - GFileType file_type; - OstreeRepoCommitFilterResult filter_result; - g_assert (dir_enum != NULL || dfd_iter != NULL); - name = g_file_info_get_name (child_info); + const char *name = g_file_info_get_name (child_info); g_ptr_array_add (path, (char*)name); - if (modifier != NULL) - child_relpath = ptrarray_path_join (path); + g_autofree char *child_relpath = ptrarray_path_join (path); - filter_result = _ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info); + g_autoptr(GFileInfo) modified_info = NULL; + OstreeRepoCommitFilterResult filter_result = + _ostree_repo_commit_modifier_apply (self, modifier, child_relpath, child_info, &modified_info); + const gboolean child_info_was_modified = !_ostree_gfileinfo_equal (child_info, modified_info); if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW) { @@ -2568,7 +2529,7 @@ return TRUE; } - file_type = g_file_info_get_file_type (child_info); + GFileType file_type = g_file_info_get_file_type (child_info); switch (file_type) { case G_FILE_TYPE_DIRECTORY: @@ -2576,15 +2537,16 @@ case G_FILE_TYPE_REGULAR: break; default: - return glnx_throw (error, "Unsupported file type: '%s'", - gs_file_get_path_cached (child)); + return glnx_throw (error, "Unsupported file type for file: '%s'", child_relpath); } + g_autoptr(GFile) child = NULL; if (dir_enum != NULL) child = g_file_enumerator_get_child (dir_enum, child_info); if (file_type == G_FILE_TYPE_DIRECTORY) { + g_autoptr(OstreeMutableTree) child_mtree = NULL; if (!ostree_mutable_tree_ensure_dir (mtree, name, &child_mtree, error)) return FALSE; @@ -2620,16 +2582,26 @@ else { guint64 file_obj_length; - const char *loose_checksum; g_autoptr(GInputStream) file_input = NULL; - g_autoptr(GVariant) xattrs = NULL; g_autoptr(GInputStream) file_object_input = NULL; g_autofree guchar *child_file_csum = NULL; g_autofree char *tmp_checksum = NULL; - loose_checksum = devino_cache_lookup (self, modifier, - g_file_info_get_attribute_uint32 (child_info, "unix::device"), - g_file_info_get_attribute_uint64 (child_info, "unix::inode")); + g_autoptr(GVariant) xattrs = NULL; + gboolean xattrs_were_modified; + if (!get_final_xattrs (self, modifier, child_relpath, child_info, child, + dfd_iter != NULL ? dfd_iter->fd : -1, name, &xattrs, + &xattrs_were_modified, cancellable, error)) + return FALSE; + + /* only check the devino cache if the file info & xattrs were not modified */ + const char *loose_checksum = NULL; + if (!child_info_was_modified && !xattrs_were_modified) + { + guint32 dev = g_file_info_get_attribute_uint32 (child_info, "unix::device"); + guint64 inode = g_file_info_get_attribute_uint64 (child_info, "unix::inode"); + loose_checksum = devino_cache_lookup (self, modifier, dev, inode); + } if (loose_checksum) { @@ -2655,12 +2627,6 @@ } } - if (!get_modified_xattrs (self, modifier, - child_relpath, child_info, child, dfd_iter != NULL ? dfd_iter->fd : -1, name, - &xattrs, - cancellable, error)) - return FALSE; - if (!ostree_raw_file_to_content_stream (file_input, modified_info, xattrs, &file_object_input, &file_obj_length, @@ -2683,6 +2649,8 @@ return TRUE; } +/* Handles the dirmeta for the given GFile dir and then calls + * write_directory_content_to_mtree_internal() for each directory entry. */ static gboolean write_directory_to_mtree_internal (OstreeRepo *self, GFile *dir, @@ -2732,10 +2700,8 @@ if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) { - if (!get_modified_xattrs (self, modifier, relpath, child_info, - dir, -1, NULL, - &xattrs, - cancellable, error)) + if (!get_final_xattrs (self, modifier, relpath, child_info, dir, -1, NULL, + &xattrs, NULL, cancellable, error)) return FALSE; g_autofree guchar *child_file_csum = NULL; @@ -2780,6 +2746,8 @@ return TRUE; } +/* Handles the dirmeta for the dir described by src_dfd_iter and then calls + * write_directory_content_to_mtree_internal() for each directory entry. */ static gboolean write_dfd_iter_to_mtree_internal (OstreeRepo *self, GLnxDirFdIterator *src_dfd_iter, @@ -2817,10 +2785,8 @@ if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) { - if (!get_modified_xattrs (self, modifier, relpath, modified_info, - NULL, src_dfd_iter->fd, NULL, - &xattrs, - cancellable, error)) + if (!get_final_xattrs (self, modifier, relpath, modified_info, NULL, src_dfd_iter->fd, + NULL, &xattrs, NULL, cancellable, error)) return FALSE; if (!_ostree_repo_write_directory_meta (self, modified_info, xattrs, &child_file_csum, @@ -2850,16 +2816,6 @@ if (!glnx_fstatat (src_dfd_iter->fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - const char *loose_checksum = devino_cache_lookup (self, modifier, stbuf.st_dev, stbuf.st_ino); - if (loose_checksum) - { - if (!ostree_mutable_tree_replace_file (mtree, dent->d_name, loose_checksum, - error)) - return FALSE; - - continue; - } - g_autoptr(GFileInfo) child_info = _ostree_stbuf_to_gfileinfo (&stbuf); g_file_info_set_name (child_info, dent->d_name); @@ -3191,6 +3147,354 @@ ostree_repo_commit_modifier_ref, ostree_repo_commit_modifier_unref); +/* Special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 + * see below for any more comments. + */ +static gboolean +import_is_bareuser_only_conversion (OstreeRepo *src_repo, + OstreeRepo *dest_repo, + OstreeObjectType objtype) +{ + return src_repo->mode == OSTREE_REPO_MODE_BARE_USER + && dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY + && objtype == OSTREE_OBJECT_TYPE_FILE; +} + +/* Returns TRUE if we can potentially just call link() to copy an object. */ +static gboolean +import_via_reflink_is_possible (OstreeRepo *src_repo, + OstreeRepo *dest_repo, + OstreeObjectType objtype) +{ + /* Equal modes are always compatible, and metadata + * is identical between all modes. + */ + if (src_repo->mode == dest_repo->mode || + OSTREE_OBJECT_TYPE_IS_META (objtype)) + return TRUE; + /* And now a special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 + */ + if (import_is_bareuser_only_conversion (src_repo, dest_repo, objtype)) + return TRUE; + return FALSE; +} + +/* Copy the detached metadata for commit @checksum from @source repo + * to @self. + */ +static gboolean +copy_detached_metadata (OstreeRepo *self, + OstreeRepo *source, + const char *checksum, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GVariant) detached_meta = NULL; + if (!ostree_repo_read_commit_detached_metadata (source, + checksum, &detached_meta, + cancellable, error)) + return FALSE; + + if (detached_meta) + { + if (!ostree_repo_write_commit_detached_metadata (self, + checksum, detached_meta, + cancellable, error)) + return FALSE; + } + + return TRUE; +} + +/* Try to import an object via reflink or just linkat(); returns a value in + * @out_was_supported if we were able to do it or not. In this path + * we're not verifying the checksum. + */ +static gboolean +import_one_object_direct (OstreeRepo *dest_repo, + OstreeRepo *src_repo, + const char *checksum, + OstreeObjectType objtype, + gboolean *out_was_supported, + GCancellable *cancellable, + GError **error) +{ + const char *errprefix = glnx_strjoina ("Importing ", checksum, ".", + ostree_object_type_to_string (objtype)); + GLNX_AUTO_PREFIX_ERROR (errprefix, error); + char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; + _ostree_loose_path (loose_path_buf, checksum, objtype, dest_repo->mode); + + if (!import_via_reflink_is_possible (src_repo, dest_repo, objtype)) + { + /* If we can't reflink, nothing to do here */ + *out_was_supported = FALSE; + return TRUE; + } + + /* hardlinks require the owner to match and to be on the same device */ + const gboolean can_hardlink = + src_repo->owner_uid == dest_repo->owner_uid && + src_repo->device == dest_repo->device; + + /* Find our target dfd */ + int dest_dfd; + if (dest_repo->commit_stagedir.initialized) + dest_dfd = dest_repo->commit_stagedir.fd; + else + dest_dfd = dest_repo->objects_dir_fd; + + if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, loose_path_buf, cancellable, error)) + return FALSE; + + gboolean did_hardlink = FALSE; + if (can_hardlink) + { + if (linkat (src_repo->objects_dir_fd, loose_path_buf, dest_dfd, loose_path_buf, 0) != 0) + { + if (errno == EEXIST) + return TRUE; + else if (errno == EMLINK || errno == EXDEV || errno == EPERM) + { + /* EMLINK, EXDEV and EPERM shouldn't be fatal; we just can't do + * the optimization of hardlinking instead of copying. Fall + * through below. + */ + } + else + return glnx_throw_errno_prefix (error, "linkat"); + } + else + did_hardlink = TRUE; + } + + /* If we weren't able to hardlink, fall back to a copy (which might be + * reflinked). + */ + if (!did_hardlink) + { + struct stat stbuf; + + if (!glnx_fstatat (src_repo->objects_dir_fd, loose_path_buf, + &stbuf, AT_SYMLINK_NOFOLLOW, error)) + return FALSE; + + /* Let's punt for symlinks right now, it's more complicated */ + if (!S_ISREG (stbuf.st_mode)) + { + *out_was_supported = FALSE; + return TRUE; + } + + /* This is yet another variation of glnx_file_copy_at() + * that basically just optionally does chown(). Perhaps + * in the future we should add flags for those things? + */ + glnx_fd_close int src_fd = -1; + if (!glnx_openat_rdonly (src_repo->objects_dir_fd, loose_path_buf, + FALSE, &src_fd, error)) + return FALSE; + + /* Open a tmpfile for dest */ + g_auto(GLnxTmpfile) tmp_dest = { 0, }; + if (!glnx_open_tmpfile_linkable_at (dest_dfd, ".", O_WRONLY | O_CLOEXEC, + &tmp_dest, error)) + return FALSE; + + if (glnx_regfile_copy_bytes (src_fd, tmp_dest.fd, (off_t) -1) < 0) + return glnx_throw_errno_prefix (error, "regfile copy"); + + /* Only chown for true bare repos */ + if (dest_repo->mode == OSTREE_REPO_MODE_BARE) + { + if (fchown (tmp_dest.fd, stbuf.st_uid, stbuf.st_gid) != 0) + return glnx_throw_errno_prefix (error, "fchown"); + } + + /* Don't want to copy xattrs for archive repos, nor for + * bare-user-only. + */ + const gboolean src_is_bare_or_bare_user = + G_IN_SET (src_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER); + if (src_is_bare_or_bare_user) + { + g_autoptr(GVariant) xattrs = NULL; + + if (!glnx_fd_get_all_xattrs (src_fd, &xattrs, + cancellable, error)) + return FALSE; + + if (!glnx_fd_set_all_xattrs (tmp_dest.fd, xattrs, + cancellable, error)) + return FALSE; + } + + if (fchmod (tmp_dest.fd, stbuf.st_mode & ~S_IFMT) != 0) + return glnx_throw_errno_prefix (error, "fchmod"); + + /* For archive repos, we just let the timestamps be object creation. + * Otherwise, copy the ostree timestamp value. + */ + if (_ostree_repo_mode_is_bare (dest_repo->mode)) + { + struct timespec ts[2]; + ts[0] = stbuf.st_atim; + ts[1] = stbuf.st_mtim; + (void) futimens (tmp_dest.fd, ts); + } + + if (!_ostree_repo_commit_tmpf_final (dest_repo, checksum, objtype, + &tmp_dest, cancellable, error)) + return FALSE; + } + + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + { + if (!copy_detached_metadata (dest_repo, src_repo, checksum, cancellable, error)) + return FALSE; + } + + *out_was_supported = TRUE; + return TRUE; +} + +/* A version of ostree_repo_import_object_from_with_trust() + * with flags; may make this public API later. + */ +gboolean +_ostree_repo_import_object (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + OstreeRepoImportFlags flags, + GCancellable *cancellable, + GError **error) +{ + const gboolean trusted = (flags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0; + /* Implements OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES which was designed for flatpak */ + const gboolean verify_bareuseronly = (flags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; + /* A special case between bare-user and bare-user-only, + * mostly for https://github.com/flatpak/flatpak/issues/845 + */ + const gboolean is_bareuseronly_conversion = + import_is_bareuser_only_conversion (source, self, objtype); + gboolean try_direct = trusted; + + /* If we need to do bareuseronly verification, or we're potentially doing a + * bareuseronly conversion, let's verify those first so we don't complicate + * the rest of the code below. + */ + if ((verify_bareuseronly || is_bareuseronly_conversion) && !OSTREE_OBJECT_TYPE_IS_META (objtype)) + { + g_autoptr(GFileInfo) src_finfo = NULL; + if (!ostree_repo_load_file (source, checksum, + NULL, &src_finfo, NULL, + cancellable, error)) + return FALSE; + + if (verify_bareuseronly) + { + if (!_ostree_validate_bareuseronly_mode_finfo (src_finfo, checksum, error)) + return FALSE; + } + + if (is_bareuseronly_conversion) + { + switch (g_file_info_get_file_type (src_finfo)) + { + case G_FILE_TYPE_REGULAR: + /* This is OK, we'll try a hardlink */ + break; + case G_FILE_TYPE_SYMBOLIC_LINK: + /* Symlinks in bare-user are regular files, we can't + * hardlink them to another repo mode. + */ + try_direct = FALSE; + break; + default: + g_assert_not_reached (); + break; + } + } + } + + /* We try to import via reflink/hardlink. If the remote is explicitly not trusted + * (i.e.) their checksums may be incorrect, we skip that. + */ + if (try_direct) + { + gboolean direct_was_supported = FALSE; + if (!import_one_object_direct (self, source, checksum, objtype, + &direct_was_supported, + cancellable, error)) + return FALSE; + + /* If direct import succeeded, we're done! */ + if (direct_was_supported) + return TRUE; + } + + /* The more expensive copy path; involves parsing the object. For + * example the input might be an archive repo and the destination bare, + * or vice versa. Or we may simply need to verify the checksum. + */ + + /* First, do we have the object already? */ + gboolean has_object; + if (!ostree_repo_has_object (self, objtype, checksum, &has_object, + cancellable, error)) + return FALSE; + /* If we have it, we're done */ + if (has_object) + return TRUE; + + if (OSTREE_OBJECT_TYPE_IS_META (objtype)) + { + /* Metadata object */ + g_autoptr(GVariant) variant = NULL; + + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + { + /* FIXME - cleanup detached metadata if copy below fails */ + if (!copy_detached_metadata (self, source, checksum, cancellable, error)) + return FALSE; + } + + if (!ostree_repo_load_variant (source, objtype, checksum, + &variant, error)) + return FALSE; + + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_metadata (self, objtype, + checksum, variant, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; + } + else + { + /* Content object */ + guint64 length; + g_autoptr(GInputStream) object_stream = NULL; + + if (!ostree_repo_load_object_stream (source, objtype, checksum, + &object_stream, &length, + cancellable, error)) + return FALSE; + + g_autofree guchar *real_csum = NULL; + if (!ostree_repo_write_content (self, checksum, + object_stream, length, + trusted ? NULL : &real_csum, + cancellable, error)) + return FALSE; + } + + return TRUE; +} + static OstreeRepoTransactionStats * ostree_repo_transaction_stats_copy (OstreeRepoTransactionStats *stats) { diff -Nru ostree-2017.11/src/libostree/ostree-repo-deprecated.h ostree-2017.12/src/libostree/ostree-repo-deprecated.h --- ostree-2017.11/src/libostree/ostree-repo-deprecated.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-deprecated.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-file.c ostree-2017.12/src/libostree/ostree-repo-file.c --- ostree-2017.11/src/libostree/ostree-repo-file.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-file.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-file-enumerator.c ostree-2017.12/src/libostree/ostree-repo-file-enumerator.c --- ostree-2017.11/src/libostree/ostree-repo-file-enumerator.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-file-enumerator.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-file-enumerator.h ostree-2017.12/src/libostree/ostree-repo-file-enumerator.h --- ostree-2017.11/src/libostree/ostree-repo-file-enumerator.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-file-enumerator.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-file.h ostree-2017.12/src/libostree/ostree-repo-file.h --- ostree-2017.11/src/libostree/ostree-repo-file.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-file.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-avahi.c ostree-2017.12/src/libostree/ostree-repo-finder-avahi.c --- ostree-2017.11/src/libostree/ostree-repo-finder-avahi.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-avahi.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2016 Kinvolk GmbH * Copyright © 2017 Endless Mobile, Inc. * @@ -166,28 +165,28 @@ typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -197,7 +196,7 @@ { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -206,7 +205,8 @@ { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -214,7 +214,7 @@ uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -771,14 +771,15 @@ for (i = 0; i < possible_refs->len; i++) { const OstreeCollectionRef *ref = g_ptr_array_index (possible_refs, i); - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; + g_autoptr(OstreeRemote) keyring_remote = NULL; /* Look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, ref->collection_id, - cancellable, &error); + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &error); - if (keyring == NULL) + if (keyring_remote == NULL) { g_debug ("Ignoring ref (%s, %s) on host ‘%s’ due to missing keyring: %s", ref->collection_id, refs[i]->ref_name, service->address, @@ -789,10 +790,11 @@ /* Add this repo to the results, keyed by the canonicalised repository URI * to deduplicate the results. */ - g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’.", - ref->collection_id, ref->ref_name, uri, keyring); + g_debug ("Resolved ref (%s, %s) to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, uri, keyring_remote->keyring, + keyring_remote->name); - resolved_repo = uri_and_keyring_new (uri, keyring); + resolved_repo = uri_and_keyring_new (uri, keyring_remote); supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); @@ -819,10 +821,10 @@ /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-avahi.h ostree-2017.12/src/libostree/ostree-repo-finder-avahi.h --- ostree-2017.11/src/libostree/ostree-repo-finder-avahi.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-avahi.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-avahi-parser.c ostree-2017.12/src/libostree/ostree-repo-finder-avahi-parser.c --- ostree-2017.11/src/libostree/ostree-repo-finder-avahi-parser.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-avahi-parser.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2016 Kinvolk GmbH * Copyright © 2017 Endless Mobile, Inc. * diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-avahi-private.h ostree-2017.12/src/libostree/ostree-repo-finder-avahi-private.h --- ostree-2017.11/src/libostree/ostree-repo-finder-avahi-private.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-avahi-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder.c ostree-2017.12/src/libostree/ostree-repo-finder.c --- ostree-2017.11/src/libostree/ostree-repo-finder.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-config.c ostree-2017.12/src/libostree/ostree-repo-finder-config.c --- ostree-2017.11/src/libostree/ostree-repo-finder-config.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-config.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-config.h ostree-2017.12/src/libostree/ostree-repo-finder-config.h --- ostree-2017.11/src/libostree/ostree-repo-finder-config.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-config.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder.h ostree-2017.12/src/libostree/ostree-repo-finder.h --- ostree-2017.11/src/libostree/ostree-repo-finder.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-mount.c ostree-2017.12/src/libostree/ostree-repo-finder-mount.c --- ostree-2017.11/src/libostree/ostree-repo-finder-mount.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-mount.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or @@ -46,19 +45,21 @@ * #OstreeRepoFinderMount is an implementation of #OstreeRepoFinder which looks * refs up in well-known locations on any mounted removable volumes. * - * For an #OstreeCollectionRef, (`C`, `R`), it checks whether `.ostree/repos/C/R` - * exists and is an OSTree repository on each mounted removable volume. Collection - * IDs and ref names are not escaped when building the path, so if either - * contains `/` in its name, the repository will be checked for in a - * subdirectory of `.ostree/repos`. Non-removable volumes are ignored. + * For each mounted removable volume, the directory `.ostree/repos.d` will be + * enumerated, and all OSTree repositories below it will be searched, in lexical + * order, for the requested #OstreeCollectionRefs. The names of the directories + * below `.ostree/repos.d` are irrelevant, apart from their lexical ordering. + * The directories `.ostree/repo`, `ostree/repo` and `var/lib/flatpak` + * will be searched after the others, if they exist. + * Non-removable volumes are ignored. * * For each repository which is found, a result will be returned for the * intersection of the refs being searched for, and the refs in `refs/heads` and * `refs/mirrors` in the repository on the removable volume. * - * Symlinks are followed when resolving the refs, so a volume might contain a - * single OSTree at some arbitrary path, with a number of refs linking to it - * from `.ostree/repos`. Any symlink which points outside the volume’s file + * Symlinks are followed when listing the repositories, so a volume might + * contain a single OSTree at some arbitrary path, with a symlink from + * `.ostree/repos.d`. Any symlink which points outside the volume’s file * system will be ignored. Repositories are deduplicated in the results. * * The volume monitor used to find mounted volumes can be overridden by setting @@ -92,28 +93,28 @@ typedef struct { gchar *uri; - gchar *keyring; + OstreeRemote *keyring_remote; /* (owned) */ } UriAndKeyring; static void uri_and_keyring_free (UriAndKeyring *data) { g_free (data->uri); - g_free (data->keyring); + ostree_remote_unref (data->keyring_remote); g_free (data); } G_DEFINE_AUTOPTR_CLEANUP_FUNC (UriAndKeyring, uri_and_keyring_free) static UriAndKeyring * -uri_and_keyring_new (const gchar *uri, - const gchar *keyring) +uri_and_keyring_new (const gchar *uri, + OstreeRemote *keyring_remote) { g_autoptr(UriAndKeyring) data = NULL; data = g_new0 (UriAndKeyring, 1); data->uri = g_strdup (uri); - data->keyring = g_strdup (keyring); + data->keyring_remote = ostree_remote_ref (keyring_remote); return g_steal_pointer (&data); } @@ -123,7 +124,7 @@ { const UriAndKeyring *_key = key; - return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring); + return g_str_hash (_key->uri) ^ g_str_hash (_key->keyring_remote->keyring); } static gboolean @@ -132,7 +133,8 @@ { const UriAndKeyring *_a = a, *_b = b; - return g_str_equal (_a->uri, _b->uri) && g_str_equal (_a->keyring, _b->keyring); + return (g_str_equal (_a->uri, _b->uri) && + g_str_equal (_a->keyring_remote->keyring, _b->keyring_remote->keyring)); } /* This must return a valid remote name (suitable for use in a refspec). */ @@ -140,7 +142,7 @@ uri_and_keyring_to_name (UriAndKeyring *data) { g_autofree gchar *escaped_uri = g_uri_escape_string (data->uri, NULL, FALSE); - g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring, NULL, FALSE); + g_autofree gchar *escaped_keyring = g_uri_escape_string (data->keyring_remote->keyring, NULL, FALSE); /* FIXME: Need a better separator than `_`, since it’s not escaped in the input. */ g_autofree gchar *out = g_strdup_printf ("%s_%s", escaped_uri, escaped_keyring); @@ -166,6 +168,137 @@ return ostree_repo_finder_result_compare (result_a, result_b); } +typedef struct +{ + char *ordering_name; /* (owned) */ + OstreeRepo *repo; /* (owned) */ + GHashTable *refs; /* (owned) (element-type OstreeCollectionRef utf8) */ +} RepoAndRefs; + +static void +repo_and_refs_clear (RepoAndRefs *data) +{ + g_hash_table_unref (data->refs); + g_object_unref (data->repo); + g_free (data->ordering_name); +} + +static gint +repo_and_refs_compare (gconstpointer a, + gconstpointer b) +{ + const RepoAndRefs *_a = a; + const RepoAndRefs *_b = b; + + return strcmp (_a->ordering_name, _b->ordering_name); +} + +/* Check whether the repo at @dfd/@path is within the given mount, is not equal + * to the @parent_repo, and can be opened. If so, return it as @out_repo and + * all its collection–refs as @out_refs, to be added into the results. */ +static gboolean +scan_repo (int dfd, + const char *path, + const char *mount_name, + const struct stat *mount_root_stbuf, + OstreeRepo *parent_repo, + OstreeRepo **out_repo, + GHashTable **out_refs, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + + g_autoptr(OstreeRepo) repo = ostree_repo_open_at (dfd, path, cancellable, &local_error); + if (repo == NULL) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it could not be opened: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + int repo_dfd = ostree_repo_get_dfd (repo); + struct stat stbuf; + + if (!glnx_fstat (repo_dfd, &stbuf, &local_error)) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as querying its info failed: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* Check the resolved repository path is below the mount point. Do not + * allow ref symlinks to point somewhere outside of the mounted volume. */ + if (stbuf.st_dev != mount_root_stbuf->st_dev) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it’s on a different file system from the mount", + path, mount_name); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* Exclude repositories which resolve to @parent_repo. */ + if (stbuf.st_dev == parent_repo->device && + stbuf.st_ino == parent_repo->inode) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as it is the same as the one we are resolving", + path, mount_name); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + /* List the repo’s refs and return them. */ + g_autoptr(GHashTable) repo_refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + + if (!ostree_repo_list_collection_refs (repo, NULL, &repo_refs, + OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES, + cancellable, &local_error)) + { + g_debug ("Ignoring repository ‘%s’ on mount ‘%s’ as its refs could not be listed: %s", + path, mount_name, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + if (out_repo != NULL) + *out_repo = g_steal_pointer (&repo); + if (out_refs != NULL) + *out_refs = g_steal_pointer (&repo_refs); + + return TRUE; +} + +static void +scan_and_add_repo (int dfd, + const char *path, + gboolean sortable, + const char *mount_name, + const struct stat *mount_root_stbuf, + OstreeRepo *parent_repo, + GArray *inout_repos_refs, + GCancellable *cancellable) +{ + g_autoptr(GHashTable) repo_refs = NULL; + g_autoptr(OstreeRepo) repo = NULL; + + if (scan_repo (dfd, path, + mount_name, mount_root_stbuf, + parent_repo, &repo, &repo_refs, cancellable, NULL)) + { + RepoAndRefs val = { + sortable ? g_strdup (path) : NULL, + g_steal_pointer (&repo), + g_steal_pointer (&repo_refs) + }; + g_array_append_val (inout_repos_refs, val); + + g_debug ("%s: Adding repo ‘%s’ (%ssortable)", + G_STRFUNC, path, sortable ? "" : "not "); + } +} + static void ostree_repo_finder_mount_resolve_async (OstreeRepoFinder *finder, const OstreeCollectionRef * const *refs, @@ -214,7 +347,6 @@ continue; } - /* Check if it contains a .ostree/repos directory. */ mount_root = g_mount_get_root (mount); mount_root_path = g_file_get_path (mount_root); @@ -225,18 +357,6 @@ continue; } - if (!glnx_opendirat (mount_root_dfd, ".ostree/repos", TRUE, &repos_dfd, &local_error)) - { - if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - g_debug ("Ignoring mount ‘%s’ as ‘%s/.ostree/repos’ directory doesn’t exist.", - mount_name, mount_root_path); - else - g_debug ("Ignoring mount ‘%s’ as ‘%s/.ostree/repos’ directory can’t be opened: %s", - mount_name, mount_root_path, local_error->message); - - continue; - } - /* stat() the mount root so we can later check whether the resolved * repositories for individual refs are on the same device (to avoid the * symlinks for them pointing outside the mount root). */ @@ -247,6 +367,68 @@ continue; } + /* Check if it contains a .ostree/repos.d directory. If not, move on and + * try the other well-known subdirectories. */ + if (!glnx_opendirat (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_dfd, NULL)) + repos_dfd = -1; + + /* List all the repositories in the repos.d directory. */ + /* (element-type GHashTable (element-type OstreeCollectionRef utf8)) */ + g_autoptr(GArray) repos_refs = g_array_new (FALSE, TRUE, sizeof (RepoAndRefs)); + g_array_set_clear_func (repos_refs, (GDestroyNotify) repo_and_refs_clear); + + GLnxDirFdIterator repos_iter; + + if (repos_dfd >= 0 && + !glnx_dirfd_iterator_init_at (repos_dfd, ".", TRUE, &repos_iter, &local_error)) + { + g_debug ("Error iterating over ‘%s/.ostree/repos.d’ directory in mount ‘%s’: %s", + mount_root_path, mount_name, local_error->message); + g_clear_error (&local_error); + /* don’t skip this mount as there’s still the ostree/repo directory to try */ + } + else if (repos_dfd >= 0) + { + while (TRUE) + { + struct dirent *repo_dent; + + if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, &local_error)) + { + g_debug ("Error iterating over ‘%s/.ostree/repos.d’ directory in mount ‘%s’: %s", + mount_root_path, mount_name, local_error->message); + g_clear_error (&local_error); + /* don’t skip this mount as there’s still the ostree/repo directory to try */ + break; + } + + if (repo_dent == NULL) + break; + + /* Grab the set of collection–refs from the repo if we can open it. */ + scan_and_add_repo (repos_dfd, repo_dent->d_name, TRUE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); + } + } + + /* Sort the repos lexically. */ + g_array_sort (repos_refs, repo_and_refs_compare); + + /* Also check the well-known special-case directories in the mount. + * Add them after sorting, so they’re always last. */ + const gchar * const well_known_repos[] = + { + ".ostree/repo", + "ostree/repo", + "var/lib/flatpak", + }; + + for (i = 0; i < G_N_ELEMENTS (well_known_repos); i++) + scan_and_add_repo (mount_root_dfd, well_known_repos[i], FALSE, + mount_name, &mount_root_stbuf, + parent_repo, repos_refs, cancellable); + /* Check whether a subdirectory exists for any of the @refs we’re looking * for. If so, and it’s a symbolic link, dereference it so multiple links * to the same repository (containing multiple refs) are coalesced. @@ -256,122 +438,69 @@ for (i = 0; refs[i] != NULL; i++) { - struct stat stbuf; - g_autofree gchar *collection_and_ref = NULL; + const OstreeCollectionRef *ref = refs[i]; g_autofree gchar *resolved_repo_uri = NULL; - g_autofree gchar *keyring = NULL; g_autoptr(UriAndKeyring) resolved_repo = NULL; - collection_and_ref = g_build_filename (refs[i]->collection_id, refs[i]->ref_name, NULL); - - if (!glnx_fstatat (repos_dfd, collection_and_ref, &stbuf, AT_NO_AUTOMOUNT, &local_error)) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as querying info of ‘%s’ failed: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, collection_and_ref, local_error->message); - g_clear_error (&local_error); - continue; - } - - if ((stbuf.st_mode & S_IFMT) != S_IFDIR) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as ‘%s’ is of type %u, not a directory.", - refs[i]->collection_id, refs[i]->ref_name, mount_name, collection_and_ref, (stbuf.st_mode & S_IFMT)); - g_clear_error (&local_error); - continue; - } - - /* Check the resolved repository path is below the mount point. Do not - * allow ref symlinks to point somewhere outside of the mounted - * volume. */ - if (stbuf.st_dev != mount_root_stbuf.st_dev) + for (gsize j = 0; j < repos_refs->len; j++) { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as it’s on a different file system from the mount.", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; + const RepoAndRefs *repo_and_refs = &g_array_index (repos_refs, RepoAndRefs, j); + OstreeRepo *repo = repo_and_refs->repo; + GHashTable *repo_refs = repo_and_refs->refs; + g_autofree char *repo_path = g_file_get_path (ostree_repo_get_path (repo)); + g_autoptr(OstreeRemote) keyring_remote = NULL; + + const gchar *checksum = g_hash_table_lookup (repo_refs, ref); + + if (checksum == NULL) + { + g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ as it doesn’t contain the ref.", + repo_path, ref->collection_id, ref->ref_name, mount_name); + g_clear_error (&local_error); + continue; + } + + /* Finally, look up the GPG keyring for this ref. */ + keyring_remote = ostree_repo_resolve_keyring_for_collection (parent_repo, + ref->collection_id, + cancellable, &local_error); + + if (keyring_remote == NULL) + { + g_debug ("Ignoring repository ‘%s’ when looking for ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", + repo_path, ref->collection_id, ref->ref_name, mount_name, local_error->message); + g_clear_error (&local_error); + continue; + } + + /* There is a valid repo at (or pointed to by) + * $mount_root/.ostree/repos.d/$something. + * Add it to the results, keyed by the canonicalised repository URI + * to deduplicate the results. */ + g_autofree char *canonical_repo_path = realpath (repo_path, NULL); + resolved_repo_uri = g_strconcat ("file://", canonical_repo_path, NULL); + g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’ from remote ‘%s’.", + ref->collection_id, ref->ref_name, mount_name, resolved_repo_uri, + keyring_remote->keyring, keyring_remote->name); + + resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring_remote); + + supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); + + if (supported_ref_to_checksum == NULL) + { + supported_ref_to_checksum = g_hash_table_new_full (ostree_collection_ref_hash, + ostree_collection_ref_equal, + NULL, g_free); + g_hash_table_insert (repo_to_refs, g_steal_pointer (&resolved_repo), supported_ref_to_checksum /* transfer */); + } + + g_hash_table_insert (supported_ref_to_checksum, (gpointer) ref, g_strdup (checksum)); + + /* We’ve found a result for this collection–ref. No point in checking + * the other repos on the mount, since pulling in parallel from them won’t help. */ + break; } - - /* Exclude repositories which resolve to @parent_repo. */ - if (stbuf.st_dev == parent_repo->device && - stbuf.st_ino == parent_repo->inode) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as it is the same as the one we are resolving", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; - } - - /* Grab the given ref and a checksum for it from the repo, if it appears to be a valid repo */ - g_autoptr(OstreeRepo) repo = ostree_repo_open_at (repos_dfd, collection_and_ref, - cancellable, &local_error); - if (!repo) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its repository could not be opened: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - g_autoptr(GHashTable) repo_refs = NULL; /* (element-type OstreeCollectionRef utf8) */ - - if (!ostree_repo_list_collection_refs (repo, refs[i]->collection_id, &repo_refs, - OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES, - cancellable, &local_error)) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its refs could not be listed: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - const gchar *checksum = g_hash_table_lookup (repo_refs, refs[i]); - - if (checksum == NULL) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ as its repository doesn’t contain the ref.", - refs[i]->collection_id, refs[i]->ref_name, mount_name); - g_clear_error (&local_error); - continue; - } - - /* Finally, look up the GPG keyring for this ref. */ - keyring = ostree_repo_resolve_keyring_for_collection (parent_repo, refs[i]->collection_id, - cancellable, &local_error); - - if (keyring == NULL) - { - g_debug ("Ignoring ref (%s, %s) on mount ‘%s’ due to missing keyring: %s", - refs[i]->collection_id, refs[i]->ref_name, mount_name, local_error->message); - g_clear_error (&local_error); - continue; - } - - /* There is a valid repo at (or pointed to by) - * $mount_root/.ostree/repos/$refs[i]->collection_id/$refs[i]->ref_name. - * Add it to the results, keyed by the canonicalised repository URI - * to deduplicate the results. */ - - g_autofree char *repo_abspath = g_build_filename (mount_root_path, ".ostree/repos", - collection_and_ref, NULL); - /* FIXME - why are we using realpath here? */ - g_autofree char *canonical_repo_dir_path = realpath (repo_abspath, NULL); - resolved_repo_uri = g_strconcat ("file://", canonical_repo_dir_path, NULL); - g_debug ("Resolved ref (%s, %s) on mount ‘%s’ to repo URI ‘%s’ with keyring ‘%s’.", - refs[i]->collection_id, refs[i]->ref_name, mount_name, resolved_repo_uri, keyring); - - resolved_repo = uri_and_keyring_new (resolved_repo_uri, keyring); - - supported_ref_to_checksum = g_hash_table_lookup (repo_to_refs, resolved_repo); - - if (supported_ref_to_checksum == NULL) - { - supported_ref_to_checksum = g_hash_table_new_full (ostree_collection_ref_hash, - ostree_collection_ref_equal, - NULL, g_free); - g_hash_table_insert (repo_to_refs, g_steal_pointer (&resolved_repo), supported_ref_to_checksum /* transfer */); - } - - g_hash_table_insert (supported_ref_to_checksum, (gpointer) refs[i], g_strdup (checksum)); } /* Aggregate the results. */ @@ -384,10 +513,10 @@ /* Build an #OstreeRemote. Use the escaped URI, since remote->name * is used in file paths, so needs to not contain special characters. */ g_autofree gchar *name = uri_and_keyring_to_name (repo); - remote = ostree_remote_new (name); + remote = ostree_remote_new_dynamic (name, repo->keyring_remote->name); g_clear_pointer (&remote->keyring, g_free); - remote->keyring = g_strdup (repo->keyring); + remote->keyring = g_strdup (repo->keyring_remote->keyring); /* gpg-verify-summary is false since we use the unsigned summary file support. */ g_key_file_set_string (remote->options, remote->group, "url", repo->uri); diff -Nru ostree-2017.11/src/libostree/ostree-repo-finder-mount.h ostree-2017.12/src/libostree/ostree-repo-finder-mount.h --- ostree-2017.11/src/libostree/ostree-repo-finder-mount.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-finder-mount.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo.h ostree-2017.12/src/libostree/ostree-repo.h --- ostree-2017.11/src/libostree/ostree-repo.h 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -124,6 +123,12 @@ int ostree_repo_get_dfd (OstreeRepo *self); _OSTREE_PUBLIC +guint ostree_repo_hash (OstreeRepo *self); +_OSTREE_PUBLIC +gboolean ostree_repo_equal (OstreeRepo *a, + OstreeRepo *b); + +_OSTREE_PUBLIC OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self); _OSTREE_PUBLIC @@ -466,6 +471,17 @@ char **out_rev, GError **error); +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API +_OSTREE_PUBLIC +gboolean ostree_repo_resolve_collection_ref (OstreeRepo *self, + const OstreeCollectionRef *ref, + gboolean allow_noent, + OstreeRepoResolveRevExtFlags flags, + char **out_rev, + GCancellable *cancellable, + GError **error); +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + _OSTREE_PUBLIC gboolean ostree_repo_list_refs (OstreeRepo *self, const char *refspec_prefix, @@ -1121,15 +1137,17 @@ * @OSTREE_REPO_PULL_FLAGS_NONE: No special options for pull * @OSTREE_REPO_PULL_FLAGS_MIRROR: Write out refs suitable for mirrors and fetch all refs if none requested * @OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY: Fetch only the commit metadata - * @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Don't trust local remote + * @OSTREE_REPO_PULL_FLAGS_UNTRUSTED: Do verify checksums of local (filesystem-accessible) repositories (defaults on for HTTP) * @OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES: Since 2017.7. Reject writes of content objects with modes outside of 0775. + * @OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP: Don't verify checksums of objects HTTP repositories (Since: 2017.12) */ typedef enum { OSTREE_REPO_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_MIRROR = (1 << 0), OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY = (1 << 1), OSTREE_REPO_PULL_FLAGS_UNTRUSTED = (1 << 2), - OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES = (1 << 3) + OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES = (1 << 3), + OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP = (1 << 4), } OstreeRepoPullFlags; _OSTREE_PUBLIC @@ -1152,33 +1170,6 @@ GCancellable *cancellable, GError **error); - - -#if 0 -FIXME -Called with: remote_name, refs, override-commit-ids -or: URL, refs, override-commit-ids -=> we only need refs; could use the remote_name or URL as additional results - -Summary file is downloaded first, so this would result in multiple downloads of -the summary, but we don’t care because of caching. - -Big problem preventing this from being the overall API: presenting the download -sizes in the gnome-software UI before the user chooses to download. - -_OSTREE_PUBLIC -gboolean ostree_repo_find_remotes_squashed (OstreeRepo *self, - const gchar * const *refs, -> options - GVariant *options, - OstreeRepoFinder **finders, -> options - GMainContext *context, -> nope - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error); -#endif - - - _OSTREE_PUBLIC gboolean ostree_repo_pull_with_options (OstreeRepo *self, const char *remote_name_or_baseurl, @@ -1217,10 +1208,10 @@ GError **error); _OSTREE_PUBLIC -gchar *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, - const gchar *collection_id, - GCancellable *cancellable, - GError **error); +OstreeRemote *ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, + const gchar *collection_id, + GCancellable *cancellable, + GError **error); _OSTREE_PUBLIC gboolean ostree_repo_list_collection_refs (OstreeRepo *self, diff -Nru ostree-2017.11/src/libostree/ostree-repo-libarchive.c ostree-2017.12/src/libostree/ostree-repo-libarchive.c --- ostree-2017.11/src/libostree/ostree-repo-libarchive.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-libarchive.c 2017-10-02 16:43:45.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -872,10 +871,14 @@ if (opts->autocreate_parents && ostree_mutable_tree_get_metadata_checksum (mtree) == NULL) { - glnx_unref_object GFileInfo *fi = g_file_info_new (); - g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); - g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); - g_file_info_set_attribute_uint32 (fi, "unix::mode", DEFAULT_DIRMODE); + /* _ostree_stbuf_to_gfileinfo() only looks at these fields, + * but we use it to ensure it sets all of the relevant GFileInfo + * properties. + */ + struct stat stbuf = { .st_mode = DEFAULT_DIRMODE, + .st_uid = 0, + .st_gid = 0 }; + g_autoptr(GFileInfo) fi = _ostree_stbuf_to_gfileinfo (&stbuf); g_autoptr(GFileInfo) mfi = NULL; (void)_ostree_repo_commit_modifier_apply (self, modifier, "/", diff -Nru ostree-2017.11/src/libostree/ostree-repo-private.h ostree-2017.12/src/libostree/ostree-repo-private.h --- ostree-2017.11/src/libostree/ostree-repo-private.h 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -92,8 +91,7 @@ GObject parent; char *stagedir_prefix; - int commit_stagedir_fd; - char *commit_stagedir_name; + GLnxTmpDir commit_stagedir; GLnxLockFile commit_stagedir_lock; /* A cached fd-relative version, distinct from the case where we may have a @@ -205,13 +203,11 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeRepoMemoryCacheRef, _ostree_repo_memory_cache_ref_destroy) #define OSTREE_REPO_TMPDIR_STAGING "staging-" -#define OSTREE_REPO_TMPDIR_FETCHER "fetcher-" gboolean _ostree_repo_allocate_tmpdir (int tmpdir_dfd, const char *tmpdir_prefix, - char **tmpdir_name_out, - int *tmpdir_fd_out, + GLnxTmpDir *tmpdir_out, GLnxLockFile *file_lock_out, gboolean * reusing_dir_out, GCancellable *cancellable, @@ -346,6 +342,21 @@ GCancellable *cancellable, GError **error); +typedef enum { + _OSTREE_REPO_IMPORT_FLAGS_NONE, + _OSTREE_REPO_IMPORT_FLAGS_TRUSTED, + _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY, +} OstreeRepoImportFlags; + +gboolean +_ostree_repo_import_object (OstreeRepo *self, + OstreeRepo *source, + OstreeObjectType objtype, + const char *checksum, + OstreeRepoImportFlags flags, + GCancellable *cancellable, + GError **error); + gboolean _ostree_repo_commit_tmpf_final (OstreeRepo *self, const char *checksum, diff -Nru ostree-2017.11/src/libostree/ostree-repo-prune.c ostree-2017.12/src/libostree/ostree-repo-prune.c --- ostree-2017.11/src/libostree/ostree-repo-prune.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-prune.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-pull.c ostree-2017.12/src/libostree/ostree-repo-pull.c --- ostree-2017.11/src/libostree/ostree-repo-pull.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-pull.c 2017-10-02 17:11:19.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2012,2013 Colin Walters * Copyright © 2017 Endless Mobile, Inc. * @@ -69,7 +68,8 @@ OstreeRepo *repo; int tmpdir_dfd; OstreeRepoPullFlags flags; - char *remote_name; + char *remote_name; + char *remote_refspec_name; OstreeRepoMode remote_mode; OstreeFetcher *fetcher; OstreeFetcherSecurityState fetcher_security_state; @@ -133,9 +133,9 @@ guint n_fetched_deltapart_fallbacks; guint n_fetched_metadata; guint n_fetched_content; - /* Objects from pull --localcache-repo */ - guint n_fetched_localcache_metadata; - guint n_fetched_localcache_content; + /* Objects imported via hardlink/reflink/copying or --localcache-repo*/ + guint n_imported_metadata; + guint n_imported_content; gboolean timestamp_check; /* Verify commit timestamps */ int maxdepth; @@ -143,8 +143,7 @@ gboolean is_mirror; gboolean is_commit_only; - gboolean is_untrusted; - gboolean is_bareuseronly_files; + OstreeRepoImportFlags importflags; GPtrArray *dirs; @@ -218,6 +217,7 @@ const OstreeCollectionRef *ref, GCancellable *cancellable, GError **error); +static void scan_object_queue_data_free (ScanObjectQueueData *scan_data); static gboolean update_progress (gpointer user_data) @@ -258,11 +258,15 @@ "fetched", "u", fetched, "requested", "u", requested, "scanning", "u", g_queue_is_empty (&pull_data->scan_object_queue) ? 0 : 1, + "caught-error", "b", pull_data->caught_error, "scanned-metadata", "u", n_scanned_metadata, "bytes-transferred", "t", bytes_transferred, "start-time", "t", start_time, - "metadata-fetched-localcache", "u", pull_data->n_fetched_localcache_metadata, - "content-fetched-localcache", "u", pull_data->n_fetched_localcache_content, + /* We use these status keys even though we now also + * use these values for filesystem-local pulls. + */ + "metadata-fetched-localcache", "u", pull_data->n_imported_metadata, + "content-fetched-localcache", "u", pull_data->n_imported_content, /* Deltas */ "fetched-delta-parts", "u", pull_data->n_fetched_deltaparts, @@ -309,9 +313,6 @@ /* we only enter the main loop when we're fetching objects */ g_assert (pull_data->phase == OSTREE_PULL_PHASE_FETCHING_OBJECTS); - if (pull_data->caught_error) - return TRUE; - if (pull_data->dry_run) return pull_data->dry_run_emitted_progress; @@ -321,6 +322,10 @@ return current_idle; } +/* Most async operations finish by calling this function; it will consume + * @errorp if set, update statistics, and initiate processing of any further + * requests as appropriate. + */ static void check_outstanding_requests_handle_error (OtPullData *pull_data, GError **errorp) @@ -340,6 +345,18 @@ g_clear_error (errorp); } } + + /* If we're in error state, we wait for any pending operations to complete, + * but ensure that all no further operations are queued. + */ + if (pull_data->caught_error) + { + g_queue_foreach (&pull_data->scan_object_queue, (GFunc) scan_object_queue_data_free, NULL); + g_queue_clear (&pull_data->scan_object_queue); + g_hash_table_remove_all (pull_data->pending_fetch_metadata); + g_hash_table_remove_all (pull_data->pending_fetch_deltaparts); + g_hash_table_remove_all (pull_data->pending_fetch_content); + } else { GHashTableIter hiter; @@ -424,6 +441,15 @@ return fetch_full || deltas_full || writes_full; } +static void +scan_object_queue_data_free (ScanObjectQueueData *scan_data) +{ + g_free (scan_data->path); + if (scan_data->requested_ref != NULL) + ostree_collection_ref_free (scan_data->requested_ref); + g_free (scan_data); +} + static gboolean idle_worker (gpointer user_data) { @@ -447,11 +473,8 @@ pull_data->cancellable, &error); check_outstanding_requests_handle_error (pull_data, &error); + scan_object_queue_data_free (scan_data); - g_free (scan_data->path); - if (scan_data->requested_ref != NULL) - ostree_collection_ref_free (scan_data->requested_ref); - g_free (scan_data); return G_SOURCE_CONTINUE; } @@ -602,100 +625,15 @@ return FALSE; } -/* This bit mirrors similar code in commit_loose_content_object() for the - * bare-user-only mode. It's opt-in though for all pulls. - */ -static gboolean -validate_bareuseronly_mode (OtPullData *pull_data, - const char *checksum, - guint32 content_mode, - GError **error) -{ - if (!pull_data->is_bareuseronly_files) - return TRUE; - - if (S_ISREG (content_mode)) - { - const guint32 invalid_modebits = ((content_mode & ~S_IFMT) & ~0775); - if (invalid_modebits > 0) - return glnx_throw (error, "object %s.file: invalid mode 0%04o with bits 0%04o", - checksum, content_mode, invalid_modebits); - } - else if (S_ISLNK (content_mode)) - ; /* Nothing */ - else - g_assert_not_reached (); - - return TRUE; -} - -/* Synchronously import a single content object; this is used async for content, - * or synchronously for metadata. @src_repo is either - * pull_data->remote_repo_local or one of pull_data->localcache_repos. - * - * One important special case here is handling the - * OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES flag. - */ -static gboolean -import_one_local_content_object_sync (OtPullData *pull_data, - OstreeRepo *src_repo, - const char *checksum, - GCancellable *cancellable, - GError **error) -{ - const gboolean trusted = !pull_data->is_untrusted; - if (trusted && !pull_data->is_bareuseronly_files) - { - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, src_repo, - OSTREE_OBJECT_TYPE_FILE, checksum, - trusted, - cancellable, error)) - return FALSE; - } - else - { - /* In this case we either need to validate the checksum - * or the file mode. - */ - g_autoptr(GInputStream) content_input = NULL; - g_autoptr(GFileInfo) content_finfo = NULL; - g_autoptr(GVariant) content_xattrs = NULL; - - if (!ostree_repo_load_file (src_repo, checksum, - &content_input, &content_finfo, &content_xattrs, - cancellable, error)) - return FALSE; - - if (!validate_bareuseronly_mode (pull_data, checksum, - g_file_info_get_attribute_uint32 (content_finfo, "unix::mode"), - error)) - return FALSE; - - /* Now that we've potentially validated it, convert to object stream */ - guint64 length; - g_autoptr(GInputStream) object_stream = NULL; - if (!ostree_raw_file_to_content_stream (content_input, content_finfo, - content_xattrs, &object_stream, - &length, cancellable, error)) - return FALSE; - - g_autofree guchar *real_csum = NULL; - if (!ostree_repo_write_content (pull_data->repo, checksum, - object_stream, length, - &real_csum, - cancellable, error)) - return FALSE; - } - - return TRUE; -} - typedef struct { OtPullData *pull_data; OstreeRepo *src_repo; char checksum[OSTREE_SHA256_STRING_LEN+1]; } ImportLocalAsyncData; +/* Asynchronously import a single content object. @src_repo is either + * pull_data->remote_repo_local or one of pull_data->localcache_repos. + */ static void async_import_in_thread (GTask *task, gpointer source, @@ -703,12 +641,12 @@ GCancellable *cancellable) { ImportLocalAsyncData *iataskdata = task_data; + OtPullData *pull_data = iataskdata->pull_data; g_autoptr(GError) local_error = NULL; - if (!import_one_local_content_object_sync (iataskdata->pull_data, - iataskdata->src_repo, - iataskdata->checksum, - cancellable, - &local_error)) + /* pull_data->importflags was set up in the pull option processing */ + if (!_ostree_repo_import_object (pull_data->repo, iataskdata->src_repo, + OSTREE_OBJECT_TYPE_FILE, iataskdata->checksum, + pull_data->importflags, cancellable, &local_error)) g_task_return_error (task, g_steal_pointer (&local_error)); else g_task_return_boolean (task, TRUE); @@ -762,6 +700,7 @@ goto out; out: + pull_data->n_imported_content++; g_assert_cmpint (pull_data->n_outstanding_content_write_requests, >, 0); pull_data->n_outstanding_content_write_requests--; check_outstanding_requests_handle_error (pull_data, &local_error); @@ -844,7 +783,6 @@ on_local_object_imported, pull_data); g_hash_table_add (pull_data->requested_content, g_steal_pointer (&file_checksum)); did_import_from_cache_repo = TRUE; - pull_data->n_fetched_localcache_content++; break; } } @@ -900,24 +838,53 @@ GCancellable *cancellable, GError **error) { - g_autofree char *filename = NULL; + g_autofree char *ret_contents = NULL; - if (ref->collection_id == NULL || g_strcmp0 (ref->collection_id, main_collection_id) == 0) - filename = g_build_filename ("refs", "heads", ref->ref_name, NULL); + if (pull_data->remote_repo_local != NULL && ref->collection_id != NULL) + { +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + if (!ostree_repo_resolve_collection_ref (pull_data->remote_repo_local, + ref, TRUE /* ignore enoent */, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, cancellable, error)) + return FALSE; +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + g_assert_not_reached (); +#endif /* !OSTREE_ENABLE_EXPERIMENTAL_API */ + } + else if (pull_data->remote_repo_local != NULL) + { + if (!ostree_repo_resolve_rev_ext (pull_data->remote_repo_local, + ref->ref_name, TRUE /* ignore enoent */, + OSTREE_REPO_RESOLVE_REV_EXT_NONE, + &ret_contents, error)) + return FALSE; + } else - filename = g_build_filename ("refs", "mirrors", ref->collection_id, ref->ref_name, NULL); + { + g_autofree char *filename = NULL; - g_autofree char *ret_contents = NULL; - if (!fetch_mirrored_uri_contents_utf8_sync (pull_data->fetcher, - pull_data->meta_mirrorlist, - filename, &ret_contents, - cancellable, error)) - return FALSE; + if (ref->collection_id == NULL || g_strcmp0 (ref->collection_id, main_collection_id) == 0) + filename = g_build_filename ("refs", "heads", ref->ref_name, NULL); + else + filename = g_build_filename ("refs", "mirrors", ref->collection_id, ref->ref_name, NULL); - g_strchomp (ret_contents); + if (!fetch_mirrored_uri_contents_utf8_sync (pull_data->fetcher, + pull_data->meta_mirrorlist, + filename, &ret_contents, + cancellable, error)) + return FALSE; + } - if (!ostree_validate_checksum_string (ret_contents, error)) - return glnx_prefix_error (error, "Fetching %s", filename); + /* Validate and return. */ + if (ret_contents != NULL) + g_strchomp (ret_contents); + + if (ret_contents == NULL || + !ostree_validate_checksum_string (ret_contents, error)) + return glnx_prefix_error (error, "Fetching checksum for ref (%s, %s)", + ref->collection_id ? ref->collection_id : "(empty)", + ref->ref_name); ot_transfer_out_value (out_contents, &ret_contents); return TRUE; @@ -1069,12 +1036,18 @@ checksum_obj = ostree_object_to_string (checksum, objtype); g_debug ("fetch of %s complete", checksum_obj); - /* If we're mirroring and writing into an archive repo, we can directly copy - * the content rather than paying the cost of exploding it, checksumming, and - * re-gzip. + const gboolean verifying_bareuseronly = + (pull_data->importflags & _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY) > 0; + + /* If we're mirroring and writing into an archive repo, and both checksum and + * bareuseronly are turned off, we can directly copy the content rather than + * paying the cost of exploding it, checksumming, and re-gzip. */ - if (pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 - && !pull_data->is_bareuseronly_files) + const gboolean mirroring_into_archive = + pull_data->is_mirror && pull_data->repo->mode == OSTREE_REPO_MODE_ARCHIVE; + const gboolean import_trusted = !verifying_bareuseronly && + (pull_data->importflags & _OSTREE_REPO_IMPORT_FLAGS_TRUSTED) > 0; + if (mirroring_into_archive && import_trusted) { gboolean have_object; if (!ostree_repo_has_object (pull_data->repo, OSTREE_OBJECT_TYPE_FILE, checksum, @@ -1108,11 +1081,11 @@ */ ot_cleanup_unlinkat (&tmp_unlinker); - if (!validate_bareuseronly_mode (pull_data, - checksum, - g_file_info_get_attribute_uint32 (file_info, "unix::mode"), - error)) - goto out; + if (verifying_bareuseronly) + { + if (!_ostree_validate_bareuseronly_mode_finfo (file_info, checksum, error)) + goto out; + } if (!ostree_raw_file_to_content_stream (file_in, file_info, xattrs, &object_input, &length, @@ -1793,35 +1766,38 @@ g_autofree char *tmp_checksum = ostree_checksum_from_bytes (csum); g_autoptr(GVariant) object = ostree_object_name_serialize (tmp_checksum, objtype); + /* It may happen that we've already looked at this object (think shared + * dirtree subtrees), if that's the case, we're done */ if (g_hash_table_lookup (pull_data->scanned_metadata, object)) return TRUE; gboolean is_requested = g_hash_table_lookup (pull_data->requested_metadata, object) != NULL; + /* Determine if we already have the object */ gboolean is_stored; if (!ostree_repo_has_object (pull_data->repo, objtype, tmp_checksum, &is_stored, cancellable, error)) return FALSE; - if (pull_data->remote_repo_local) + /* Are we pulling an object we don't have from a local repo? */ + if (!is_stored && pull_data->remote_repo_local) { - if (!is_stored) + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - { - /* mark as partial to ensure we scan the commit below */ - if (!write_commitpartial_for (pull_data, tmp_checksum, error)) - return FALSE; - } - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, pull_data->remote_repo_local, - objtype, tmp_checksum, !pull_data->is_untrusted, - cancellable, error)) + /* mark as partial to ensure we scan the commit below */ + if (!write_commitpartial_for (pull_data, tmp_checksum, error)) return FALSE; - /* The import API will fetch both the commit and detached metadata, so - * add it to the hash to avoid re-fetching it below. - */ - if (objtype == OSTREE_OBJECT_TYPE_COMMIT) - g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); } + + if (!_ostree_repo_import_object (pull_data->repo, pull_data->remote_repo_local, + objtype, tmp_checksum, pull_data->importflags, + cancellable, error)) + return FALSE; + /* The import API will fetch both the commit and detached metadata, so + * add it to the hash to avoid re-fetching it below. + */ + if (objtype == OSTREE_OBJECT_TYPE_COMMIT) + g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); + pull_data->n_imported_metadata++; is_stored = TRUE; is_requested = TRUE; } @@ -1844,17 +1820,16 @@ if (!write_commitpartial_for (pull_data, tmp_checksum, error)) return FALSE; } - if (!ostree_repo_import_object_from_with_trust (pull_data->repo, refd_repo, - objtype, tmp_checksum, - !pull_data->is_untrusted, - cancellable, error)) + if (!_ostree_repo_import_object (pull_data->repo, refd_repo, + objtype, tmp_checksum, pull_data->importflags, + cancellable, error)) return FALSE; /* See comment above */ if (objtype == OSTREE_OBJECT_TYPE_COMMIT) g_hash_table_add (pull_data->fetched_detached_metadata, g_strdup (tmp_checksum)); is_stored = TRUE; is_requested = TRUE; - pull_data->n_fetched_localcache_metadata++; + pull_data->n_imported_metadata++; break; } } @@ -3142,10 +3117,14 @@ g_clear_pointer (&delta_from_revision, g_free); } - /* This is similar to the below, except we *might* use the previous - * commit, or we might do a scratch delta first. + /* If the current ref is the same, we don't do a delta request, just a + * scan. Otherise, use the previous commit if available, or a scratch + * delta. */ - initiate_delta_request (pull_data, delta_from_revision ?: NULL, to_revision, ref); + if (delta_from_revision && g_str_equal (delta_from_revision, to_revision)) + queue_scan_one_metadata_object (pull_data, to_revision, OSTREE_OBJECT_TYPE_COMMIT, NULL, 0, ref); + else + initiate_delta_request (pull_data, delta_from_revision ?: NULL, to_revision, ref); } else { @@ -3252,7 +3231,7 @@ flags = flags_i; (void) g_variant_lookup (options, "subdir", "&s", &dir_to_pull); (void) g_variant_lookup (options, "subdirs", "^a&s", &dirs_to_pull); - (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_name); + (void) g_variant_lookup (options, "override-remote-name", "s", &pull_data->remote_refspec_name); opt_gpg_verify_set = g_variant_lookup (options, "gpg-verify", "b", &pull_data->gpg_verify); opt_gpg_verify_summary_set = @@ -3268,6 +3247,9 @@ (void) g_variant_lookup (options, "update-frequency", "u", &update_frequency); (void) g_variant_lookup (options, "localcache-repos", "^a&s", &opt_localcache_repos); (void) g_variant_lookup (options, "timestamp-check", "b", &pull_data->timestamp_check); + + if (pull_data->remote_refspec_name != NULL) + pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); } g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); @@ -3293,8 +3275,9 @@ pull_data->is_mirror = (flags & OSTREE_REPO_PULL_FLAGS_MIRROR) > 0; pull_data->is_commit_only = (flags & OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY) > 0; - pull_data->is_untrusted = (flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) > 0; - pull_data->is_bareuseronly_files = (flags & OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES) > 0; + /* See our processing of OSTREE_REPO_PULL_FLAGS_UNTRUSTED below */ + if ((flags & OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES) > 0) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_VERIFY_BAREUSERONLY; pull_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; if (error) @@ -3385,6 +3368,7 @@ { g_autofree char *unconfigured_state = NULL; + g_free (pull_data->remote_name); pull_data->remote_name = g_strdup (remote_name_or_baseurl); /* Fetch GPG verification settings from remote if it wasn't already @@ -3573,7 +3557,7 @@ &pull_data->has_tombstone_commits, error)) goto out; - if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE_Z2) + if (pull_data->remote_mode != OSTREE_REPO_MODE_ARCHIVE) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't pull from archives with mode \"%s\"", @@ -3583,6 +3567,9 @@ } } + /* Change some option defaults if we're actually pulling from a local + * (filesystem accessible) repo. + */ if (pull_data->remote_repo_local) { /* For local pulls, default to disabling static deltas so that the @@ -3591,10 +3578,25 @@ if (!pull_data->require_static_deltas) pull_data->disable_static_deltas = TRUE; + /* Note the inversion here; PULL_FLAGS_UNTRUSTED is converted to + * IMPORT_FLAGS_TRUSTED only if it's unset (and just for local repos). + */ + if ((flags & OSTREE_REPO_PULL_FLAGS_UNTRUSTED) == 0) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; + } + else + { + /* For non-local repos, we require the TRUSTED_HTTP pull flag to map to + * the TRUSTED object import flag. In practice we don't do object imports + * for HTTP, but it's easiest to use one set of flags between HTTP and + * local imports. + */ + if (flags & OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP) + pull_data->importflags |= _OSTREE_REPO_IMPORT_FLAGS_TRUSTED; } /* We can't use static deltas if pulling into an archive repo. */ - if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2) + if (self->mode == OSTREE_REPO_MODE_ARCHIVE) { if (pull_data->require_static_deltas) { @@ -4055,7 +4057,8 @@ ostree_repo_transaction_set_collection_ref (pull_data->repo, ref, checksum); else - ostree_repo_transaction_set_ref (pull_data->repo, pull_data->remote_name, + ostree_repo_transaction_set_ref (pull_data->repo, + (pull_data->remote_refspec_name != NULL) ? pull_data->remote_refspec_name : pull_data->remote_name, ref->ref_name, checksum); } } @@ -4089,36 +4092,42 @@ end_time = g_get_monotonic_time (); bytes_transferred = _ostree_fetcher_bytes_transferred (pull_data->fetcher); - if (bytes_transferred > 0 && pull_data->progress) + if (pull_data->progress) { - guint shift; g_autoptr(GString) buf = g_string_new (""); /* Ensure the rest of the progress keys are set appropriately. */ update_progress (pull_data); - if (bytes_transferred < 1024) - shift = 1; - else - shift = 1024; - - if (pull_data->n_fetched_deltaparts > 0) + /* See if we did a local-only import */ + if (pull_data->remote_repo_local) + g_string_append_printf (buf, "%u metadata, %u content objects imported", + pull_data->n_imported_metadata, pull_data->n_imported_content); + else if (pull_data->n_fetched_deltaparts > 0) g_string_append_printf (buf, "%u delta parts, %u loose fetched", pull_data->n_fetched_deltaparts, pull_data->n_fetched_metadata + pull_data->n_fetched_content); else g_string_append_printf (buf, "%u metadata, %u content objects fetched", pull_data->n_fetched_metadata, pull_data->n_fetched_content); - if (pull_data->n_fetched_localcache_metadata || - pull_data->n_fetched_localcache_content) + if (!pull_data->remote_repo_local && + (pull_data->n_imported_metadata || pull_data->n_imported_content)) g_string_append_printf (buf, " (%u meta, %u content local)", - pull_data->n_fetched_localcache_metadata, - pull_data->n_fetched_localcache_content); + pull_data->n_imported_metadata, + pull_data->n_imported_content); - g_string_append_printf (buf, "; %" G_GUINT64_FORMAT " %s transferred in %u seconds", - (guint64)(bytes_transferred / shift), - shift == 1 ? "B" : "KiB", - (guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC)); + if (bytes_transferred > 0) + { + guint shift; + if (bytes_transferred < 1024) + shift = 1; + else + shift = 1024; + g_string_append_printf (buf, "; %" G_GUINT64_FORMAT " %s transferred in %u seconds", + (guint64)(bytes_transferred / shift), + shift == 1 ? "B" : "KiB", + (guint) ((end_time - pull_data->start_time) / G_USEC_PER_SEC)); + } ostree_async_progress_set_status (pull_data->progress, buf->str); } @@ -4245,6 +4254,8 @@ g_clear_pointer (&pull_data->pending_fetch_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->pending_fetch_metadata, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->pending_fetch_deltaparts, (GDestroyNotify) g_hash_table_unref); + g_queue_foreach (&pull_data->scan_object_queue, (GFunc) scan_object_queue_data_free, NULL); + g_queue_clear (&pull_data->scan_object_queue); g_clear_pointer (&pull_data->idle_src, (GDestroyNotify) g_source_destroy); g_clear_pointer (&pull_data->dirs, (GDestroyNotify) g_ptr_array_unref); g_clear_pointer (&remote_config, (GDestroyNotify) g_key_file_unref); @@ -4521,7 +4532,7 @@ * will typically be all available finders using their default options (but * this is not guaranteed). * - * GPG verification of the summary and all commits will be used unconditionally. + * GPG verification of commits will be used unconditionally. * * This will use the thread-default #GMainContext, but will not iterate it. * @@ -4820,7 +4831,7 @@ for (i = 0; i < results->len; i++) { OstreeRepoFinderResult *result = g_ptr_array_index (results, i); - g_autoptr(GBytes) summary_bytes = NULL, summary_sig_bytes = NULL; + g_autoptr(GBytes) summary_bytes = NULL; g_autoptr(GVariant) summary_v = NULL; guint64 summary_last_modified; g_autoptr(GVariant) summary_refs = NULL; @@ -4837,13 +4848,12 @@ g_debug ("%s: Fetching summary for remote ‘%s’ with keyring ‘%s’.", G_STRFUNC, result->remote->name, result->remote->keyring); - /* Download the summary and signature, and validate the signature. This - * will load from the cache if possible. */ + /* Download the summary. This will load from the cache if possible. */ ostree_repo_remote_fetch_summary_with_options (self, result->remote->name, NULL, /* no options */ &summary_bytes, - &summary_sig_bytes, + NULL, cancellable, &error); @@ -4937,7 +4947,7 @@ if (commit_metadata->timestamp != 0) continue; - _ostree_loose_path (buf, commit_metadata->checksum, OSTREE_OBJECT_TYPE_COMMIT, OSTREE_REPO_MODE_ARCHIVE_Z2); + _ostree_loose_path (buf, commit_metadata->checksum, OSTREE_OBJECT_TYPE_COMMIT, OSTREE_REPO_MODE_ARCHIVE); commit_filename = g_build_filename ("objects", buf, NULL); /* For each of the remotes whose summary files contain this ref, try @@ -5251,7 +5261,7 @@ * immediately. The results of any successfully completed downloads at that * point will remain cached in the local repository. * - * GPG verification of the summary and all commits will be used unconditionally. + * GPG verification of commits will be used unconditionally. * * The following @options are currently defined: * @@ -5369,6 +5379,8 @@ g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", TRUE); g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE); g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE); + if (result->remote->refspec_name != NULL) + g_variant_dict_insert (&local_options_dict, "override-remote-name", "s", result->remote->refspec_name); copy_option (&options_dict, &local_options_dict, "depth", G_VARIANT_TYPE ("i")); copy_option (&options_dict, &local_options_dict, "disable-static-deltas", G_VARIANT_TYPE ("b")); copy_option (&options_dict, &local_options_dict, "http-headers", G_VARIANT_TYPE ("a(ss)")); @@ -5497,7 +5509,7 @@ * Find the GPG keyring for the given @collection_id, using the local * configuration from the given #OstreeRepo. This will search the configured * remotes for ones whose `collection-id` key matches @collection_id, and will - * return the GPG keyring from the first matching remote. + * return the first matching remote. * * If multiple remotes match and have different keyrings, a debug message will * be emitted, and the first result will be returned. It is expected that the @@ -5505,10 +5517,11 @@ * * If no match can be found, a %G_IO_ERROR_NOT_FOUND error will be returned. * - * Returns: (transfer full): filename of the GPG keyring for @collection_id + * Returns: (transfer full): #OstreeRemote containing the GPG keyring for + * @collection_id * Since: 2017.8 */ -gchar * +OstreeRemote * ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, const gchar *collection_id, GCancellable *cancellable, @@ -5516,7 +5529,7 @@ { gsize i; g_auto(GStrv) remotes = NULL; - const OstreeRemote *keyring_remote = NULL; + OstreeRemote *keyring_remote = NULL; g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); g_return_val_if_fail (ostree_validate_collection_id (collection_id, NULL), NULL); @@ -5566,7 +5579,7 @@ } if (keyring_remote != NULL) - return g_strdup (keyring_remote->keyring); + return ostree_remote_ref (keyring_remote); else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, diff -Nru ostree-2017.11/src/libostree/ostree-repo-refs.c ostree-2017.12/src/libostree/ostree-repo-refs.c --- ostree-2017.11/src/libostree/ostree-repo-refs.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-refs.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -469,6 +468,69 @@ return _ostree_repo_resolve_rev_internal (self, refspec, allow_noent, FALSE, out_rev, error); } +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API +/** + * ostree_repo_resolve_collection_ref: + * @self: an #OstreeRepo + * @ref: a collection–ref to resolve + * @allow_noent: %TRUE to not throw an error if @ref doesn’t exist + * @flags: options controlling behaviour + * @out_rev: (out) (transfer full) (optional) (nullable): return location for + * the checksum corresponding to @ref, or %NULL if @allow_noent is %TRUE and + * the @ref could not be found + * @cancellable: (nullable): a #GCancellable, or %NULL + * @error: return location for a #GError, or %NULL + * + * Look up the checksum for the given collection–ref, returning it in @out_rev. + * This will search through the mirrors and remote refs. + * + * If @allow_noent is %TRUE and the given @ref cannot be found, %TRUE will be + * returned and @out_rev will be set to %NULL. If @allow_noent is %FALSE and + * the given @ref cannot be found, a %G_IO_ERROR_NOT_FOUND error will be + * returned. + * + * There are currently no @flags which affect the behaviour of this function. + * + * Returns: %TRUE on success, %FALSE on failure + * Since: 2017.12 + */ +gboolean +ostree_repo_resolve_collection_ref (OstreeRepo *self, + const OstreeCollectionRef *ref, + gboolean allow_noent, + OstreeRepoResolveRevExtFlags flags, + char **out_rev, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); + g_return_val_if_fail (ref != NULL, FALSE); + g_return_val_if_fail (ref->collection_id != NULL && ref->ref_name != NULL, FALSE); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */ + if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs, + OSTREE_REPO_LIST_REFS_EXT_NONE, + cancellable, error)) + return FALSE; + + const char *ret_contents = g_hash_table_lookup (refs, ref); + + if (ret_contents == NULL && !allow_noent) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "Collection–ref (%s, %s) not found", + ref->collection_id, ref->ref_name); + return FALSE; + } + + if (out_rev != NULL) + *out_rev = g_strdup (ret_contents); + return TRUE; +} +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + static gboolean enumerate_refs_recurse (OstreeRepo *repo, const char *remote, @@ -545,12 +607,10 @@ GCancellable *cancellable, GError **error) { - g_autoptr(GHashTable) ret_all_refs = NULL; g_autofree char *remote = NULL; g_autofree char *ref_prefix = NULL; - ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - + g_autoptr(GHashTable) ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (refspec_prefix) { struct stat stbuf; @@ -571,12 +631,9 @@ path = glnx_strjoina (prefix_path, ref_prefix); } - if (fstatat (self->repo_dir_fd, path, &stbuf, 0) < 0) - { - if (errno != ENOENT) - return glnx_throw_errno (error); - } - else + if (!glnx_fstatat_allow_noent (self->repo_dir_fd, path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { if (S_ISDIR (stbuf.st_mode)) { diff -Nru ostree-2017.11/src/libostree/ostree-repo-static-delta-compilation-analysis.c ostree-2017.12/src/libostree/ostree-repo-static-delta-compilation-analysis.c --- ostree-2017.11/src/libostree/ostree-repo-static-delta-compilation-analysis.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-static-delta-compilation-analysis.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-static-delta-compilation.c ostree-2017.12/src/libostree/ostree-repo-static-delta-compilation.c --- ostree-2017.11/src/libostree/ostree-repo-static-delta-compilation.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-static-delta-compilation.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-static-delta-core.c ostree-2017.12/src/libostree/ostree-repo-static-delta-core.c --- ostree-2017.11/src/libostree/ostree-repo-static-delta-core.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-static-delta-core.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-static-delta-private.h ostree-2017.12/src/libostree/ostree-repo-static-delta-private.h --- ostree-2017.11/src/libostree/ostree-repo-static-delta-private.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-static-delta-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-static-delta-processing.c ostree-2017.12/src/libostree/ostree-repo-static-delta-processing.c --- ostree-2017.11/src/libostree/ostree-repo-static-delta-processing.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-static-delta-processing.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-repo-traverse.c ostree-2017.12/src/libostree/ostree-repo-traverse.c --- ostree-2017.11/src/libostree/ostree-repo-traverse.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-repo-traverse.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-rollsum.c ostree-2017.12/src/libostree/ostree-rollsum.c --- ostree-2017.11/src/libostree/ostree-rollsum.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-rollsum.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-rollsum.h ostree-2017.12/src/libostree/ostree-rollsum.h --- ostree-2017.11/src/libostree/ostree-rollsum.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-rollsum.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sepolicy.c ostree-2017.12/src/libostree/ostree-sepolicy.c --- ostree-2017.11/src/libostree/ostree-sepolicy.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sepolicy.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sepolicy.h ostree-2017.12/src/libostree/ostree-sepolicy.h --- ostree-2017.11/src/libostree/ostree-sepolicy.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sepolicy.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sepolicy-private.h ostree-2017.12/src/libostree/ostree-sepolicy-private.h --- ostree-2017.11/src/libostree/ostree-sepolicy-private.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sepolicy-private.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sysroot.c ostree-2017.12/src/libostree/ostree-sysroot.c --- ostree-2017.11/src/libostree/ostree-sysroot.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -198,7 +197,6 @@ keys, G_N_ELEMENTS (keys)); self->sysroot_fd = -1; - self->lock = (GLnxLockFile)GLNX_LOCK_FILE_INIT; } /** @@ -541,12 +539,9 @@ g_autoptr(GKeyFile) ret_origin = g_key_file_new (); struct stat stbuf; - if (fstatat (deployment_dfd, origin_path, &stbuf, 0) != 0) - { - if (errno != ENOENT) - return glnx_throw_errno (error); - } - else + if (!glnx_fstatat_allow_noent (deployment_dfd, origin_path, &stbuf, 0, error)) + return FALSE; + if (errno == 0) { g_autofree char *origin_contents = glnx_file_get_contents_utf8_at (deployment_dfd, origin_path, @@ -808,8 +803,8 @@ return FALSE; struct stat stbuf; - if (fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0) < 0) - return glnx_throw_errno_prefix (error, "fstatat"); + if (!glnx_fstatat (self->sysroot_fd, "ostree/deploy", &stbuf, 0, error)) + return FALSE; if (out_changed) { diff -Nru ostree-2017.11/src/libostree/ostree-sysroot-cleanup.c ostree-2017.12/src/libostree/ostree-sysroot-cleanup.c --- ostree-2017.11/src/libostree/ostree-sysroot-cleanup.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot-cleanup.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sysroot-deploy.c ostree-2017.12/src/libostree/ostree-sysroot-deploy.c --- ostree-2017.11/src/libostree/ostree-sysroot-deploy.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot-deploy.c 2017-10-02 17:11:19.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2014 Colin Walters * * This library is free software; you can redistribute it and/or @@ -689,12 +688,10 @@ * when doing a deployment. */ const char selabeled[] = "var/.ostree-selabeled"; - gboolean deployment_var_labeled; - - if (!ot_query_exists_at (os_deploy_dfd, selabeled, &deployment_var_labeled, error)) + struct stat stbuf; + if (!glnx_fstatat_allow_noent (os_deploy_dfd, selabeled, &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - - if (!deployment_var_labeled) + if (errno == ENOENT) { { g_autofree char *msg = g_strdup_printf ("Relabeling /var (no stamp file '%s' found)", selabeled); @@ -764,12 +761,13 @@ } } - gboolean etc_exists = FALSE; - if (!ot_query_exists_at (deployment_dfd, "etc", &etc_exists, error)) + struct stat stbuf; + if (!glnx_fstatat_allow_noent (deployment_dfd, "etc", &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; - gboolean usretc_exists = FALSE; - if (!ot_query_exists_at (deployment_dfd, "usr/etc", &usretc_exists, error)) + gboolean etc_exists = (errno == 0); + if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/etc", &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; + gboolean usretc_exists = (errno == 0); if (etc_exists && usretc_exists) return glnx_throw (error, "Tree contains both /etc and /usr/etc"); @@ -1568,10 +1566,10 @@ * it doesn't exist already. */ struct stat stbuf; - if (fstatat (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->kernel_namever); if (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->kernel_srcpath, bootcsum_dfd, kernel_layout->kernel_namever, @@ -1586,10 +1584,10 @@ if (kernel_layout->initramfs_srcpath) { g_assert (kernel_layout->initramfs_namever); - if (fstatat (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->initramfs_namever); if (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->initramfs_srcpath, bootcsum_dfd, kernel_layout->initramfs_namever, sysroot->debug_flags, @@ -1599,19 +1597,14 @@ } g_autofree char *contents = NULL; - if (fstatat (deployment_dfd, "usr/lib/os-release", &stbuf, 0) != 0) + if (!glnx_fstatat_allow_noent (deployment_dfd, "usr/lib/os-release", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT) { - if (errno != ENOENT) - { - return glnx_throw_errno (error); - } - else - { - contents = glnx_file_get_contents_utf8_at (deployment_dfd, "etc/os-release", NULL, - cancellable, error); - if (!contents) - return glnx_prefix_error (error, "Reading /etc/os-release"); - } + contents = glnx_file_get_contents_utf8_at (deployment_dfd, "etc/os-release", NULL, + cancellable, error); + if (!contents) + return glnx_prefix_error (error, "Reading /etc/os-release"); } else { diff -Nru ostree-2017.11/src/libostree/ostree-sysroot.h ostree-2017.12/src/libostree/ostree-sysroot.h --- ostree-2017.11/src/libostree/ostree-sysroot.h 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot.h 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sysroot-private.h ostree-2017.12/src/libostree/ostree-sysroot-private.h --- ostree-2017.11/src/libostree/ostree-sysroot-private.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot-private.h 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sysroot-upgrader.c ostree-2017.12/src/libostree/ostree-sysroot-upgrader.c --- ostree-2017.11/src/libostree/ostree-sysroot-upgrader.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot-upgrader.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-sysroot-upgrader.h ostree-2017.12/src/libostree/ostree-sysroot-upgrader.h --- ostree-2017.11/src/libostree/ostree-sysroot-upgrader.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-sysroot-upgrader.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-tls-cert-interaction.c ostree-2017.12/src/libostree/ostree-tls-cert-interaction.c --- ostree-2017.11/src/libostree/ostree-tls-cert-interaction.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-tls-cert-interaction.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-tls-cert-interaction.h ostree-2017.12/src/libostree/ostree-tls-cert-interaction.h --- ostree-2017.11/src/libostree/ostree-tls-cert-interaction.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-tls-cert-interaction.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-types.h ostree-2017.12/src/libostree/ostree-types.h --- ostree-2017.11/src/libostree/ostree-types.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-types.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-varint.c ostree-2017.12/src/libostree/ostree-varint.c --- ostree-2017.11/src/libostree/ostree-varint.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-varint.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-varint.h ostree-2017.12/src/libostree/ostree-varint.h --- ostree-2017.11/src/libostree/ostree-varint.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-varint.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libostree/ostree-version.h ostree-2017.12/src/libostree/ostree-version.h --- ostree-2017.11/src/libostree/ostree-version.h 2017-09-14 16:17:49.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-version.h 2017-10-02 17:11:31.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Georges Basile Stavracas Neto * * This program is free software: you can redistribute it and/or modify @@ -44,7 +43,7 @@ * * Since: 2017.4 */ -#define OSTREE_RELEASE_VERSION (11) +#define OSTREE_RELEASE_VERSION (12) /** * OSTREE_VERSION @@ -53,7 +52,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION (2017.11) +#define OSTREE_VERSION (2017.12) /** * OSTREE_VERSION_S: @@ -63,7 +62,7 @@ * * Since: 2017.4 */ -#define OSTREE_VERSION_S "2017.11" +#define OSTREE_VERSION_S "2017.12" #define OSTREE_ENCODE_VERSION(year,release) \ ((year) << 16 | (release)) diff -Nru ostree-2017.11/src/libostree/ostree-version.h.in ostree-2017.12/src/libostree/ostree-version.h.in --- ostree-2017.11/src/libostree/ostree-version.h.in 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libostree/ostree-version.h.in 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Georges Basile Stavracas Neto * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/libotutil/ot-checksum-instream.c ostree-2017.12/src/libotutil/ot-checksum-instream.c --- ostree-2017.11/src/libotutil/ot-checksum-instream.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-checksum-instream.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or @@ -23,15 +22,21 @@ #include "ot-checksum-instream.h" #include "ot-checksum-utils.h" -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) #include +#elif defined(HAVE_GNUTLS) +#include +#include #endif G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM) struct _OtChecksumInstreamPrivate { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX *checksum; +#elif defined(HAVE_GNUTLS) + gnutls_digest_algorithm_t checksum_type; + gnutls_hash_hd_t checksum; #else GChecksumType checksum_type; GChecksum *checksum; @@ -49,8 +54,10 @@ { OtChecksumInstream *self = (OtChecksumInstream*)object; -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) EVP_MD_CTX_destroy (self->priv->checksum); +#elif defined(HAVE_GNUTLS) + gnutls_hash_deinit (self->priv->checksum, NULL); #else g_checksum_free (self->priv->checksum); #endif @@ -76,7 +83,7 @@ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate); } -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) static const EVP_MD * gchecksum_type_to_openssl (GChecksumType checksum_type) { @@ -89,6 +96,18 @@ g_assert_not_reached (); } } +#elif defined(HAVE_GNUTLS) +static gnutls_digest_algorithm_t +gchecksum_type_to_gnutls (GChecksumType checksum_type) +{ + switch (checksum_type) + { + case G_CHECKSUM_SHA256: + return GNUTLS_DIG_SHA256; + default: + g_assert_not_reached (); + } +} #endif OtChecksumInstream * @@ -106,10 +125,13 @@ /* For now */ g_assert (checksum_type == G_CHECKSUM_SHA256); -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) stream->priv->checksum = EVP_MD_CTX_create (); g_assert (stream->priv->checksum); g_assert (EVP_DigestInit_ex (stream->priv->checksum, gchecksum_type_to_openssl (checksum_type), NULL)); +#elif defined(HAVE_GNUTLS) + stream->priv->checksum_type = gchecksum_type_to_gnutls (checksum_type); + g_assert (!gnutls_hash_init (&stream->priv->checksum, stream->priv->checksum_type)); #else stream->priv->checksum = g_checksum_new (checksum_type); stream->priv->checksum_type = checksum_type; @@ -136,8 +158,10 @@ error); if (res > 0) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res)); +#elif defined(HAVE_GNUTLS) + g_assert (!gnutls_hash (self->priv->checksum, buffer, res)); #else g_checksum_update (self->priv->checksum, buffer, res); #endif @@ -151,11 +175,15 @@ guint8 *buffer, gsize *digest_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len); if (digest_len) *digest_len = len; +#elif defined(HAVE_GNUTLS) + gnutls_hash_output (stream->priv->checksum, buffer); + if (digest_len) + *digest_len = gnutls_hash_get_len (stream->priv->checksum_type); #else g_checksum_get_digest (stream->priv->checksum, buffer, digest_len); #endif @@ -165,10 +193,14 @@ ot_checksum_instream_dup_digest (OtChecksumInstream *stream, gsize *ret_len) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) guint len; guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE); g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len)); +#elif defined(HAVE_GNUTLS) + guint len = gnutls_hash_get_len (stream->priv->checksum_type); + guchar *ret = g_malloc0 (len); + gnutls_hash_output (stream->priv->checksum, ret); #else gsize len = g_checksum_type_get_length (stream->priv->checksum_type); guchar *ret = g_malloc (len); @@ -182,13 +214,20 @@ char * ot_checksum_instream_get_string (OtChecksumInstream *stream) { -#ifdef HAVE_OPENSSL +#if defined(HAVE_OPENSSL) unsigned len; guint8 csum[EVP_MAX_MD_SIZE]; g_assert (EVP_DigestFinal_ex (stream->priv->checksum, csum, &len)); char *buf = g_malloc (len * 2 + 1); ot_bin2hex (buf, (guint8*)csum, len); return buf; +#elif defined(HAVE_GNUTLS) + gsize len; + guint8 *csum = ot_checksum_instream_dup_digest(stream, &len); + char *buf = g_malloc0 (len * 2 + 1); + ot_bin2hex (buf, csum, len); + g_free (csum); + return buf; #else return g_strdup (g_checksum_get_string (stream->priv->checksum)); #endif diff -Nru ostree-2017.11/src/libotutil/ot-checksum-instream.h ostree-2017.12/src/libotutil/ot-checksum-instream.h --- ostree-2017.11/src/libotutil/ot-checksum-instream.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-checksum-instream.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-checksum-utils.c ostree-2017.12/src/libotutil/ot-checksum-utils.c --- ostree-2017.11/src/libotutil/ot-checksum-utils.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-checksum-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-checksum-utils.h ostree-2017.12/src/libotutil/ot-checksum-utils.h --- ostree-2017.11/src/libotutil/ot-checksum-utils.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-checksum-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-fs-utils.c ostree-2017.12/src/libotutil/ot-fs-utils.c --- ostree-2017.11/src/libotutil/ot-fs-utils.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-fs-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or @@ -104,27 +103,6 @@ return TRUE; } -gboolean -ot_query_exists_at (int dfd, const char *path, - gboolean *out_exists, - GError **error) -{ - struct stat stbuf; - gboolean ret_exists; - - if (fstatat (dfd, path, &stbuf, AT_SYMLINK_NOFOLLOW) < 0) - { - if (errno != ENOENT) - return glnx_throw_errno_prefix (error, "fstatat(%s)", path); - ret_exists = FALSE; - } - else - ret_exists = TRUE; - - *out_exists = ret_exists; - return TRUE; -} - gboolean ot_openat_ignore_enoent (int dfd, const char *path, diff -Nru ostree-2017.11/src/libotutil/ot-fs-utils.h ostree-2017.12/src/libotutil/ot-fs-utils.h --- ostree-2017.11/src/libotutil/ot-fs-utils.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-fs-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters . * * This library is free software; you can redistribute it and/or @@ -66,11 +65,6 @@ GCancellable *cancellable, GError **error); - -gboolean ot_query_exists_at (int dfd, const char *path, - gboolean *out_exists, - GError **error); - gboolean ot_ensure_unlinked_at (int dfd, const char *path, GError **error); diff -Nru ostree-2017.11/src/libotutil/ot-gio-utils.c ostree-2017.12/src/libotutil/ot-gio-utils.c --- ostree-2017.11/src/libotutil/ot-gio-utils.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-gio-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-gio-utils.h ostree-2017.12/src/libotutil/ot-gio-utils.h --- ostree-2017.11/src/libotutil/ot-gio-utils.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-gio-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-gpg-utils.c ostree-2017.12/src/libotutil/ot-gpg-utils.c --- ostree-2017.11/src/libotutil/ot-gpg-utils.c 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-gpg-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-gpg-utils.h ostree-2017.12/src/libotutil/ot-gpg-utils.h --- ostree-2017.11/src/libotutil/ot-gpg-utils.h 2017-09-14 14:05:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-gpg-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-keyfile-utils.c ostree-2017.12/src/libotutil/ot-keyfile-utils.c --- ostree-2017.11/src/libotutil/ot-keyfile-utils.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-keyfile-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-keyfile-utils.h ostree-2017.12/src/libotutil/ot-keyfile-utils.h --- ostree-2017.11/src/libotutil/ot-keyfile-utils.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-keyfile-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-opt-utils.c ostree-2017.12/src/libotutil/ot-opt-utils.c --- ostree-2017.11/src/libotutil/ot-opt-utils.c 2017-07-31 16:11:44.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-opt-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-opt-utils.h ostree-2017.12/src/libotutil/ot-opt-utils.h --- ostree-2017.11/src/libotutil/ot-opt-utils.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-opt-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-tool-util.c ostree-2017.12/src/libotutil/ot-tool-util.c --- ostree-2017.11/src/libotutil/ot-tool-util.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-tool-util.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-tool-util.h ostree-2017.12/src/libotutil/ot-tool-util.h --- ostree-2017.11/src/libotutil/ot-tool-util.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-tool-util.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-unix-utils.c ostree-2017.12/src/libotutil/ot-unix-utils.c --- ostree-2017.11/src/libotutil/ot-unix-utils.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-unix-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-unix-utils.h ostree-2017.12/src/libotutil/ot-unix-utils.h --- ostree-2017.11/src/libotutil/ot-unix-utils.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-unix-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/otutil.c ostree-2017.12/src/libotutil/otutil.c --- ostree-2017.11/src/libotutil/otutil.c 2017-07-31 16:11:44.000000000 +0000 +++ ostree-2017.12/src/libotutil/otutil.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/otutil.h ostree-2017.12/src/libotutil/otutil.h --- ostree-2017.11/src/libotutil/otutil.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/otutil.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-variant-utils.c ostree-2017.12/src/libotutil/ot-variant-utils.c --- ostree-2017.11/src/libotutil/ot-variant-utils.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-variant-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/libotutil/ot-variant-utils.h ostree-2017.12/src/libotutil/ot-variant-utils.h --- ostree-2017.11/src/libotutil/ot-variant-utils.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/libotutil/ot-variant-utils.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/main.c ostree-2017.12/src/ostree/main.c --- ostree-2017.11/src/ostree/main.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/main.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -43,6 +42,7 @@ { "export", ostree_builtin_export }, #ifdef OSTREE_ENABLE_EXPERIMENTAL_API { "find-remotes", ostree_builtin_find_remotes }, + { "create-usb", ostree_builtin_create_usb }, #endif { "fsck", ostree_builtin_fsck }, { "gpg-sign", ostree_builtin_gpg_sign }, diff -Nru ostree-2017.11/src/ostree/ostree-trivial-httpd.c ostree-2017.12/src/ostree/ostree-trivial-httpd.c --- ostree-2017.11/src/ostree/ostree-trivial-httpd.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ostree-trivial-httpd.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-cleanup.c ostree-2017.12/src/ostree/ot-admin-builtin-cleanup.c --- ostree-2017.11/src/ostree/ot-admin-builtin-cleanup.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-cleanup.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-deploy.c ostree-2017.12/src/ostree/ot-admin-builtin-deploy.c --- ostree-2017.11/src/ostree/ot-admin-builtin-deploy.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-deploy.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-diff.c ostree-2017.12/src/ostree/ot-admin-builtin-diff.c --- ostree-2017.11/src/ostree/ot-admin-builtin-diff.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-diff.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-init-fs.c ostree-2017.12/src/ostree/ot-admin-builtin-init-fs.c --- ostree-2017.11/src/ostree/ot-admin-builtin-init-fs.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-init-fs.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-instutil.c ostree-2017.12/src/ostree/ot-admin-builtin-instutil.c --- ostree-2017.11/src/ostree/ot-admin-builtin-instutil.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-instutil.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-os-init.c ostree-2017.12/src/ostree/ot-admin-builtin-os-init.c --- ostree-2017.11/src/ostree/ot-admin-builtin-os-init.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-os-init.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-set-origin.c ostree-2017.12/src/ostree/ot-admin-builtin-set-origin.c --- ostree-2017.11/src/ostree/ot-admin-builtin-set-origin.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-set-origin.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtins.h ostree-2017.12/src/ostree/ot-admin-builtins.h --- ostree-2017.11/src/ostree/ot-admin-builtins.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtins.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-status.c ostree-2017.12/src/ostree/ot-admin-builtin-status.c --- ostree-2017.11/src/ostree/ot-admin-builtin-status.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-status.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-switch.c ostree-2017.12/src/ostree/ot-admin-builtin-switch.c --- ostree-2017.11/src/ostree/ot-admin-builtin-switch.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-switch.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-undeploy.c ostree-2017.12/src/ostree/ot-admin-builtin-undeploy.c --- ostree-2017.11/src/ostree/ot-admin-builtin-undeploy.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-undeploy.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-unlock.c ostree-2017.12/src/ostree/ot-admin-builtin-unlock.c --- ostree-2017.11/src/ostree/ot-admin-builtin-unlock.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-unlock.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-builtin-upgrade.c ostree-2017.12/src/ostree/ot-admin-builtin-upgrade.c --- ostree-2017.11/src/ostree/ot-admin-builtin-upgrade.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-builtin-upgrade.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-functions.c ostree-2017.12/src/ostree/ot-admin-functions.c --- ostree-2017.11/src/ostree/ot-admin-functions.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-functions.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-functions.h ostree-2017.12/src/ostree/ot-admin-functions.h --- ostree-2017.11/src/ostree/ot-admin-functions.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-functions.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2012 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-admin-instutil-builtin-grub2-generate.c ostree-2017.12/src/ostree/ot-admin-instutil-builtin-grub2-generate.c --- ostree-2017.11/src/ostree/ot-admin-instutil-builtin-grub2-generate.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-instutil-builtin-grub2-generate.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c ostree-2017.12/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c --- ostree-2017.11/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-instutil-builtin-selinux-ensure-labeled.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/ostree/ot-admin-instutil-builtin-set-kargs.c ostree-2017.12/src/ostree/ot-admin-instutil-builtin-set-kargs.c --- ostree-2017.11/src/ostree/ot-admin-instutil-builtin-set-kargs.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-instutil-builtin-set-kargs.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This program is free software: you can redistribute it and/or modify diff -Nru ostree-2017.11/src/ostree/ot-admin-instutil-builtins.h ostree-2017.12/src/ostree/ot-admin-instutil-builtins.h --- ostree-2017.11/src/ostree/ot-admin-instutil-builtins.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-admin-instutil-builtins.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-admin.c ostree-2017.12/src/ostree/ot-builtin-admin.c --- ostree-2017.11/src/ostree/ot-builtin-admin.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-admin.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-cat.c ostree-2017.12/src/ostree/ot-builtin-cat.c --- ostree-2017.11/src/ostree/ot-builtin-cat.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-cat.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-checkout.c ostree-2017.12/src/ostree/ot-builtin-checkout.c --- ostree-2017.11/src/ostree/ot-builtin-checkout.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-checkout.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-checksum.c ostree-2017.12/src/ostree/ot-builtin-checksum.c --- ostree-2017.11/src/ostree/ot-builtin-checksum.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-checksum.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-commit.c ostree-2017.12/src/ostree/ot-builtin-commit.c --- ostree-2017.11/src/ostree/ot-builtin-commit.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-commit.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -224,6 +223,7 @@ return OSTREE_REPO_COMMIT_FILTER_ALLOW; } +#ifdef HAVE_LIBARCHIVE typedef struct { GRegex *regex; const char *replacement; @@ -245,6 +245,7 @@ g_assert (ret); return ret; } +#endif static gboolean commit_editor (OstreeRepo *repo, @@ -631,12 +632,12 @@ if (!ostree_repo_import_archive_to_mtree (repo, &opts, archive, mtree, modifier, cancellable, error)) goto out; - } #else - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "This version of ostree is not compiled with libarchive support"); - return FALSE; + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "This version of ostree is not compiled with libarchive support"); + goto out; #endif + } } else if (strcmp (tree_type, "ref") == 0) { diff -Nru ostree-2017.11/src/ostree/ot-builtin-config.c ostree-2017.12/src/ostree/ot-builtin-config.c --- ostree-2017.11/src/ostree/ot-builtin-config.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-config.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-create-usb.c ostree-2017.12/src/ostree/ot-builtin-create-usb.c --- ostree-2017.11/src/ostree/ot-builtin-create-usb.c 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-create-usb.c 2017-10-01 17:38:12.000000000 +0000 @@ -0,0 +1,276 @@ +/* + * Copyright © 2017 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include "ot-main.h" +#include "ot-builtins.h" +#include "ostree.h" +#include "otutil.h" + +#include "ostree-remote-private.h" + +static gboolean opt_disable_fsync = FALSE; +static char *opt_destination_repo = NULL; + +static GOptionEntry options[] = + { + { "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, + { "destination-repo", 0, 0, G_OPTION_ARG_FILENAME, &opt_destination_repo, "Use custom repository directory within the mount", NULL }, + { NULL } + }; + +/* TODO: Add a man page. */ +gboolean +ostree_builtin_create_usb (int argc, + char **argv, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GOptionContext) context = NULL; + g_autoptr(OstreeAsyncProgress) progress = NULL; + g_auto(GLnxConsoleRef) console = { 0, }; + + context = g_option_context_new ("MOUNT-PATH COLLECTION-ID REF [COLLECTION-ID REF...] - Copy the refs to a USB stick"); + + /* Parse options. */ + g_autoptr(OstreeRepo) src_repo = NULL; + + if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &src_repo, cancellable, error)) + return FALSE; + + if (argc < 2) + { + ot_util_usage_error (context, "A MOUNT-PATH must be specified", error); + return FALSE; + } + + if (argc < 4) + { + ot_util_usage_error (context, "At least one COLLECTION-ID REF pair must be specified", error); + return FALSE; + } + + if (argc % 2 == 1) + { + ot_util_usage_error (context, "Only complete COLLECTION-ID REF pairs may be specified", error); + return FALSE; + } + + /* Open the USB stick, which must exist. Allow automounting and following symlinks. */ + const char *mount_root_path = argv[1]; + struct stat mount_root_stbuf; + + glnx_fd_close int mount_root_dfd = -1; + if (!glnx_opendirat (AT_FDCWD, mount_root_path, TRUE, &mount_root_dfd, error)) + return FALSE; + if (!glnx_fstat (mount_root_dfd, &mount_root_stbuf, error)) + return FALSE; + + /* Read in the refs to add to the USB stick. */ + g_autoptr(GPtrArray) refs = g_ptr_array_new_full (argc, (GDestroyNotify) ostree_collection_ref_free); + + for (gsize i = 2; i < argc; i += 2) + { + if (!ostree_validate_collection_id (argv[i], error) || + !ostree_validate_rev (argv[i + 1], error)) + return FALSE; + + g_ptr_array_add (refs, ostree_collection_ref_new (argv[i], argv[i + 1])); + } + + /* Open the destination repository on the USB stick or create it if it doesn’t exist. + * Check it’s below @mount_root_path, and that it’s not the same as the source + * repository. + * + * If the destination file system supports xattrs (for example, ext4), we use + * a BARE_USER repository; if it doesn’t (for example, FAT), we use ARCHIVE. + * In either case, we want a lossless repository. */ + const char *dest_repo_path = (opt_destination_repo != NULL) ? opt_destination_repo : ".ostree/repo"; + + if (!glnx_shutil_mkdir_p_at (mount_root_dfd, dest_repo_path, 0755, cancellable, error)) + return FALSE; + + OstreeRepoMode mode = OSTREE_REPO_MODE_BARE_USER; + + if (TEMP_FAILURE_RETRY (fgetxattr (mount_root_dfd, "user.test", NULL, 0)) < 0 && + errno == ENOTSUP) + mode = OSTREE_REPO_MODE_ARCHIVE; + + g_debug ("%s: Creating repository in mode %u", G_STRFUNC, mode); + + g_autoptr(OstreeRepo) dest_repo = ostree_repo_create_at (mount_root_dfd, dest_repo_path, + mode, NULL, cancellable, error); + + if (dest_repo == NULL) + return FALSE; + + struct stat dest_repo_stbuf; + + if (!glnx_fstat (ostree_repo_get_dfd (dest_repo), &dest_repo_stbuf, error)) + return FALSE; + + if (dest_repo_stbuf.st_dev != mount_root_stbuf.st_dev) + { + ot_util_usage_error (context, "--destination-repo must be a descendent of MOUNT-PATH", error); + return FALSE; + } + + if (ostree_repo_equal (src_repo, dest_repo)) + { + ot_util_usage_error (context, "--destination-repo must not be the source repository", error); + return FALSE; + } + + if (!ostree_ensure_repo_writable (dest_repo, error)) + return FALSE; + + if (opt_disable_fsync) + ostree_repo_set_disable_fsync (dest_repo, TRUE); + + /* Copy across all of the collection–refs to the destination repo. */ + GVariantBuilder refs_builder; + g_variant_builder_init (&refs_builder, G_VARIANT_TYPE ("a(sss)")); + + for (gsize i = 0; i < refs->len; i++) + { + const OstreeCollectionRef *ref = g_ptr_array_index (refs, i); + + g_variant_builder_add (&refs_builder, "(sss)", + ref->collection_id, ref->ref_name, ""); + } + + { + GVariantBuilder builder; + g_autoptr(GVariant) opts = NULL; + OstreeRepoPullFlags flags = OSTREE_REPO_PULL_FLAGS_MIRROR; + + glnx_console_lock (&console); + + if (console.is_tty) + progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + g_variant_builder_add (&builder, "{s@v}", "collection-refs", + g_variant_new_variant (g_variant_builder_end (&refs_builder))); + g_variant_builder_add (&builder, "{s@v}", "flags", + g_variant_new_variant (g_variant_new_int32 (flags))); + g_variant_builder_add (&builder, "{s@v}", "depth", + g_variant_new_variant (g_variant_new_int32 (0))); + opts = g_variant_ref_sink (g_variant_builder_end (&builder)); + + g_autofree char *src_repo_uri = g_file_get_uri (ostree_repo_get_path (src_repo)); + + if (!ostree_repo_pull_with_options (dest_repo, src_repo_uri, + opts, + progress, + cancellable, error)) + { + ostree_repo_abort_transaction (dest_repo, cancellable, NULL); + return FALSE; + } + + if (progress != NULL) + ostree_async_progress_finish (progress); + } + + /* Ensure a summary file is present to make it easier to look up commit checksums. */ + /* FIXME: It should be possible to work without this, but find_remotes_cb() in + * ostree-repo-pull.c currently assumes a summary file (signed or unsigned) is + * present. */ + struct stat stbuf; + if (!glnx_fstatat_allow_noent (ostree_repo_get_dfd (dest_repo), "summary", &stbuf, 0, error)) + return FALSE; + if (errno == ENOENT && + !ostree_repo_regenerate_summary (dest_repo, NULL, cancellable, error)) + return FALSE; + + /* Add the symlinks .ostree/repos.d/@symlink_name → @dest_repo_path, unless + * the @dest_repo_path is a well-known one like ostree/repo, in which case no + * symlink is necessary; #OstreeRepoFinderMount always looks there. */ + if (!g_str_equal (dest_repo_path, "ostree/repo") && + !g_str_equal (dest_repo_path, ".ostree/repo")) + { + if (!glnx_shutil_mkdir_p_at (mount_root_dfd, ".ostree/repos.d", 0755, cancellable, error)) + return FALSE; + + /* Find a unique name for the symlink. If a symlink already targets + * @dest_repo_path, use that and don’t create a new one. */ + GLnxDirFdIterator repos_iter; + gboolean need_symlink = TRUE; + + if (!glnx_dirfd_iterator_init_at (mount_root_dfd, ".ostree/repos.d", TRUE, &repos_iter, error)) + return FALSE; + + while (TRUE) + { + struct dirent *repo_dent; + + if (!glnx_dirfd_iterator_next_dent (&repos_iter, &repo_dent, cancellable, error)) + return FALSE; + + if (repo_dent == NULL) + break; + + /* Does the symlink already point to this repository? (Or is the + * repository itself present in repos.d?) We already guarantee that + * they’re on the same device. */ + if (repo_dent->d_ino == dest_repo_stbuf.st_ino) + { + need_symlink = FALSE; + break; + } + } + + /* If we need a symlink, find a unique name for it and create it. */ + if (need_symlink) + { + /* Relative to .ostree/repos.d. */ + g_autofree char *relative_dest_repo_path = g_build_filename ("..", "..", dest_repo_path, NULL); + guint i; + const guint max_attempts = 100; + + for (i = 0; i < max_attempts; i++) + { + g_autofree char *symlink_path = g_strdup_printf (".ostree/repos.d/%02u-generated", i); + + int ret = TEMP_FAILURE_RETRY (symlinkat (relative_dest_repo_path, mount_root_dfd, symlink_path)); + if (ret < 0 && errno != EEXIST) + return glnx_throw_errno_prefix (error, "symlinkat(%s → %s)", symlink_path, relative_dest_repo_path); + else if (ret >= 0) + break; + } + + if (i == max_attempts) + return glnx_throw (error, "Could not find an unused symlink name for the repository"); + } + } + + /* Report success to the user. */ + g_autofree char *src_repo_path = g_file_get_path (ostree_repo_get_path (src_repo)); + + g_print ("Copied %u/%u refs successfully from ‘%s’ to ‘%s’ repository in ‘%s’.\n", refs->len, refs->len, + src_repo_path, dest_repo_path, mount_root_path); + + return TRUE; +} diff -Nru ostree-2017.11/src/ostree/ot-builtin-diff.c ostree-2017.12/src/ostree/ot-builtin-diff.c --- ostree-2017.11/src/ostree/ot-builtin-diff.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-diff.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-export.c ostree-2017.12/src/ostree/ot-builtin-export.c --- ostree-2017.11/src/ostree/ot-builtin-export.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-export.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or @@ -68,15 +67,15 @@ g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; 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; #ifdef HAVE_LIBARCHIVE + const char *rev; g_autoptr(OtAutoArchiveWrite) a = NULL; -#endif OstreeRepoExportArchiveOptions opts = { 0, }; +#endif context = g_option_context_new ("COMMIT - Stream COMMIT to stdout in tar format"); diff -Nru ostree-2017.11/src/ostree/ot-builtin-find-remotes.c ostree-2017.12/src/ostree/ot-builtin-find-remotes.c --- ostree-2017.11/src/ostree/ot-builtin-find-remotes.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-find-remotes.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-fsck.c ostree-2017.12/src/ostree/ot-builtin-fsck.c --- ostree-2017.11/src/ostree/ot-builtin-fsck.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-fsck.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-gpg-sign.c ostree-2017.12/src/ostree/ot-builtin-gpg-sign.c --- ostree-2017.11/src/ostree/ot-builtin-gpg-sign.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-gpg-sign.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-init.c ostree-2017.12/src/ostree/ot-builtin-init.c --- ostree-2017.11/src/ostree/ot-builtin-init.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-init.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-log.c ostree-2017.12/src/ostree/ot-builtin-log.c --- ostree-2017.11/src/ostree/ot-builtin-log.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-log.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-ls.c ostree-2017.12/src/ostree/ot-builtin-ls.c --- ostree-2017.11/src/ostree/ot-builtin-ls.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-ls.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-prune.c ostree-2017.12/src/ostree/ot-builtin-prune.c --- ostree-2017.11/src/ostree/ot-builtin-prune.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-prune.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -35,6 +34,7 @@ static char *opt_delete_commit; static char *opt_keep_younger_than; static char **opt_retain_branch_depth; +static char **opt_only_branches; /* ATTENTION: * Please remember to update the bash-completion script (bash/ostree) and @@ -49,6 +49,7 @@ { "keep-younger-than", 0, 0, G_OPTION_ARG_STRING, &opt_keep_younger_than, "Prune all commits older than the specified date", "DATE" }, { "static-deltas-only", 0, 0, G_OPTION_ARG_NONE, &opt_static_deltas_only, "Change the behavior of delete-commit and keep-younger-than to prune only static deltas" }, { "retain-branch-depth", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_retain_branch_depth, "Additionally retain BRANCH=DEPTH commits", "BRANCH=DEPTH" }, + { "only-branch", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_only_branches, "Only prune BRANCH (may be specified multiple times)", "BRANCH" }, { NULL } }; @@ -185,7 +186,7 @@ gint n_objects_total; gint n_objects_pruned; guint64 objsize_total; - if (!(opt_retain_branch_depth || opt_keep_younger_than)) + if (!(opt_retain_branch_depth || opt_keep_younger_than || opt_only_branches)) { if (!ostree_repo_prune (repo, pruneflags, opt_depth, &n_objects_total, &n_objects_pruned, &objsize_total, @@ -210,6 +211,7 @@ return glnx_throw (error, "Could not parse '%s'", opt_keep_younger_than); } + /* Process --retain-branch-depth */ for (char **iter = opt_retain_branch_depth; iter && *iter; iter++) { /* bd should look like BRANCH=DEPTH where DEPTH is an int */ @@ -239,6 +241,45 @@ cancellable, error)) return FALSE; + /* Process --only-branch. Note this combines with --retain-branch-depth; one + * could do e.g.: + * * --only-branch exampleos/x86_64/foo + * * --only-branch exampleos/x86_64/bar + * * --retain-branch-depth exampleos/x86_64/foo=0 + * * --depth 5 + * to prune exampleos/x86_64/foo to just the latest commit, and + * exampleos/x86_64/bar to a depth of 5. + */ + if (opt_only_branches) + { + /* Turn --only-branch into a set */ + g_autoptr(GHashTable) only_branches_set = g_hash_table_new (g_str_hash, g_str_equal); + for (char **iter = opt_only_branches; iter && *iter; iter++) + { + const char *ref = *iter; + /* Ensure the specified branch exists */ + if (!ostree_repo_resolve_rev (repo, ref, FALSE, NULL, error)) + return FALSE; + g_hash_table_add (only_branches_set, (char*)ref); + } + + /* Iterate over all refs, add equivalent of --retain-branch-depth=$ref=-1 + * if the ref isn't in --only-branch set and there wasn't already a + * --retain-branch-depth specified for it. + */ + GLNX_HASH_TABLE_FOREACH (all_refs, const char *, ref) + { + if (!g_hash_table_contains (only_branches_set, ref) && + !g_hash_table_contains (retain_branch_depth, ref)) + { + g_hash_table_insert (retain_branch_depth, g_strdup (ref), GINT_TO_POINTER ((int)-1)); + } + } + } + + /* Traverse each ref, and gather all objects pointed to by it up to a + * specific depth (if configured). + */ g_hash_table_iter_init (&hash_iter, all_refs); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { @@ -275,6 +316,7 @@ return FALSE; } + /* We've gathered the reachable set; start the prune ✀ */ { OstreeRepoPruneOptions opts = { pruneflags, reachable }; if (!ostree_repo_prune_from_reachable (repo, &opts, &n_objects_total, diff -Nru ostree-2017.11/src/ostree/ot-builtin-pull.c ostree-2017.12/src/ostree/ot-builtin-pull.c --- ostree-2017.11/src/ostree/ot-builtin-pull.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-pull.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or @@ -34,6 +33,7 @@ static gboolean opt_disable_static_deltas; static gboolean opt_require_static_deltas; static gboolean opt_untrusted; +static gboolean opt_http_trusted; static gboolean opt_timestamp_check; static gboolean opt_bareuseronly_files; static char** opt_subpaths; @@ -57,7 +57,8 @@ { "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL }, { "mirror", 0, 0, G_OPTION_ARG_NONE, &opt_mirror, "Write refs suitable for a mirror and fetches all refs if none provided", NULL }, { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only pull the provided subpath(s)", NULL }, - { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "http-trusted", 0, 0, G_OPTION_ARG_NONE, &opt_http_trusted, "Do not verify checksums of HTTP sources (mostly useful when mirroring)", NULL }, { "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", 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" }, @@ -183,8 +184,14 @@ if (opt_commit_only) pullflags |= OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY; + if (opt_http_trusted) + pullflags |= OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP; if (opt_untrusted) - pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; + { + pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED; + /* If the user specifies both, assume they really mean untrusted */ + pullflags &= ~OSTREE_REPO_PULL_FLAGS_TRUSTED_HTTP; + } if (opt_bareuseronly_files) pullflags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES; diff -Nru ostree-2017.11/src/ostree/ot-builtin-pull-local.c ostree-2017.12/src/ostree/ot-builtin-pull-local.c --- ostree-2017.11/src/ostree/ot-builtin-pull-local.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-pull-local.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -47,7 +46,7 @@ static GOptionEntry options[] = { { "remote", 0, 0, G_OPTION_ARG_STRING, &opt_remote, "Add REMOTE to refspec", "REMOTE" }, { "disable-fsync", 0, 0, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, - { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not verify checksums of local sources (always enabled for HTTP pulls)", NULL }, + { "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Verify checksums of local sources (always enabled for HTTP pulls)", NULL }, { "bareuseronly-files", 0, 0, G_OPTION_ARG_NONE, &opt_bareuseronly_files, "Reject regular files with mode outside of 0775 (world writable, suid, etc.)", NULL }, { "require-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_require_static_deltas, "Require static deltas", NULL }, { "gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_gpg_verify, "GPG verify commits (must specify --remote)", NULL }, @@ -56,6 +55,14 @@ { NULL } }; +/* See canonical version of this in ot-builtin-pull.c */ +static void +noninteractive_console_progress_changed (OstreeAsyncProgress *progress, + gpointer user_data) +{ + /* We do nothing here - we just want the final status */ +} + gboolean ostree_builtin_pull_local (int argc, char **argv, GCancellable *cancellable, GError **error) { @@ -171,6 +178,8 @@ 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 (noninteractive_console_progress_changed, &console); opts = g_variant_ref_sink (g_variant_builder_end (&builder)); if (!ostree_repo_pull_with_options (repo, src_repo_uri, @@ -179,8 +188,14 @@ cancellable, error)) goto out; - if (progress) - ostree_async_progress_finish (progress); + if (!console.is_tty) + { + g_assert (progress); + const char *status = ostree_async_progress_get_status (progress); + if (status) + g_print ("%s\n", status); + } + ostree_async_progress_finish (progress); } ret = TRUE; diff -Nru ostree-2017.11/src/ostree/ot-builtin-refs.c ostree-2017.12/src/ostree/ot-builtin-refs.c --- ostree-2017.11/src/ostree/ot-builtin-refs.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-refs.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-remote.c ostree-2017.12/src/ostree/ot-builtin-remote.c --- ostree-2017.11/src/ostree/ot-builtin-remote.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-remote.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-reset.c ostree-2017.12/src/ostree/ot-builtin-reset.c --- ostree-2017.11/src/ostree/ot-builtin-reset.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-reset.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-rev-parse.c ostree-2017.12/src/ostree/ot-builtin-rev-parse.c --- ostree-2017.11/src/ostree/ot-builtin-rev-parse.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-rev-parse.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtins.h ostree-2017.12/src/ostree/ot-builtins.h --- ostree-2017.11/src/ostree/ot-builtins.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtins.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or @@ -40,6 +39,7 @@ BUILTINPROTO(export); #ifdef OSTREE_ENABLE_EXPERIMENTAL_API BUILTINPROTO(find_remotes); +BUILTINPROTO(create_usb); #endif BUILTINPROTO(gpg_sign); BUILTINPROTO(init); diff -Nru ostree-2017.11/src/ostree/ot-builtin-show.c ostree-2017.12/src/ostree/ot-builtin-show.c --- ostree-2017.11/src/ostree/ot-builtin-show.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-show.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-static-delta.c ostree-2017.12/src/ostree/ot-builtin-static-delta.c --- ostree-2017.11/src/ostree/ot-builtin-static-delta.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-static-delta.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-builtin-summary.c ostree-2017.12/src/ostree/ot-builtin-summary.c --- ostree-2017.11/src/ostree/ot-builtin-summary.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-summary.c 2017-10-02 16:54:23.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2014 Colin Walters * * This library is free software; you can redistribute it and/or @@ -84,7 +83,6 @@ gboolean ostree_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GOptionContext) context = NULL; g_autoptr(OstreeRepo) repo = NULL; OstreeDumpFlags flags = OSTREE_DUMP_NONE; @@ -92,24 +90,115 @@ context = g_option_context_new ("Manage summary metadata"); if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) - goto out; + return FALSE; if (opt_update) { g_autoptr(GVariant) additional_metadata = NULL; if (!ostree_ensure_repo_writable (repo, error)) - goto out; + return FALSE; if (opt_metadata != NULL) { additional_metadata = build_additional_metadata ((const char * const *) opt_metadata, error); if (additional_metadata == NULL) - goto out; + return FALSE; + } + +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + const char *collection_id = ostree_repo_get_collection_id (repo); +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + const char *collection_id = NULL; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ + + /* Write out a new metadata commit for the repository. */ + if (collection_id != NULL) + { +#ifdef OSTREE_ENABLE_EXPERIMENTAL_API + OstreeCollectionRef collection_ref = { (gchar *) collection_id, (gchar *) OSTREE_REPO_METADATA_REF }; + g_autofree char *old_ostree_metadata_checksum = NULL; + g_autofree gchar *new_ostree_metadata_checksum = NULL; + g_autoptr(OstreeMutableTree) mtree = NULL; + g_autoptr(OstreeRepoFile) repo_file = NULL; + g_autoptr(GVariantDict) new_summary_commit_dict = NULL; + g_autoptr(GVariant) new_summary_commit = NULL; + + if (!ostree_repo_resolve_rev (repo, OSTREE_REPO_METADATA_REF, + TRUE, &old_ostree_metadata_checksum, error)) + return FALSE; + + /* Add bindings to the metadata. */ + new_summary_commit_dict = g_variant_dict_new (additional_metadata); + g_variant_dict_insert (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_COLLECTION_BINDING, + "s", collection_ref.collection_id); + g_variant_dict_insert_value (new_summary_commit_dict, OSTREE_COMMIT_META_KEY_REF_BINDING, + g_variant_new_strv ((const gchar * const *) &collection_ref.ref_name, 1)); + new_summary_commit = g_variant_dict_end (new_summary_commit_dict); + + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return FALSE; + + /* Set up an empty mtree. */ + mtree = ostree_mutable_tree_new (); + + glnx_unref_object GFileInfo *fi = g_file_info_new (); + g_file_info_set_attribute_uint32 (fi, "unix::uid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::gid", 0); + g_file_info_set_attribute_uint32 (fi, "unix::mode", (0755 | S_IFDIR)); + + g_autofree guchar *csum_raw = NULL; + g_autofree char *csum = NULL; + + g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (fi, NULL /* xattrs */); + + if (!ostree_repo_write_metadata (repo, OSTREE_OBJECT_TYPE_DIR_META, NULL, + dirmeta, &csum_raw, cancellable, error)) + return FALSE; + + csum = ostree_checksum_from_bytes (csum_raw); + ostree_mutable_tree_set_metadata_checksum (mtree, csum); + + if (!ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, error)) + return FALSE; + + if (!ostree_repo_write_commit (repo, old_ostree_metadata_checksum, + NULL /* subject */, NULL /* body */, + new_summary_commit, repo_file, &new_ostree_metadata_checksum, + NULL, error)) + return FALSE; + + if (opt_key_ids != NULL) + { + for (const char * const *iter = (const char * const *) opt_key_ids; + iter != NULL && *iter != NULL; iter++) + { + const char *key_id = *iter; + + if (!ostree_repo_sign_commit (repo, + new_ostree_metadata_checksum, + key_id, + opt_gpg_homedir, + cancellable, + error)) + return FALSE; + } + } + + ostree_repo_transaction_set_collection_ref (repo, &collection_ref, + new_ostree_metadata_checksum); + + if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) + return FALSE; +#else /* if !OSTREE_ENABLE_EXPERIMENTAL_API */ + g_assert_not_reached (); + return FALSE; +#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */ } + /* Regenerate and sign the conventional summary file. */ if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error)) - goto out; + return FALSE; if (opt_key_ids) { @@ -118,7 +207,7 @@ opt_gpg_homedir, cancellable, error)) - goto out; + return FALSE; } } else if (opt_view) @@ -130,7 +219,7 @@ summary_data = ot_file_mapat_bytes (repo->repo_dir_fd, "summary", error); if (!summary_data) - goto out; + return FALSE; ot_dump_summary_bytes (summary_data, flags); } @@ -138,10 +227,8 @@ { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No option specified; use -u to update summary"); - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } diff -Nru ostree-2017.11/src/ostree/ot-builtin-trivial-httpd.c ostree-2017.12/src/ostree/ot-builtin-trivial-httpd.c --- ostree-2017.11/src/ostree/ot-builtin-trivial-httpd.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-builtin-trivial-httpd.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-dump.c ostree-2017.12/src/ostree/ot-dump.c --- ostree-2017.11/src/ostree/ot-dump.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-dump.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * Copyright (C) 2013 Stef Walter * diff -Nru ostree-2017.11/src/ostree/ot-dump.h ostree-2017.12/src/ostree/ot-dump.h --- ostree-2017.11/src/ostree/ot-dump.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-dump.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-editor.c ostree-2017.12/src/ostree/ot-editor.c --- ostree-2017.11/src/ostree/ot-editor.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-editor.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-editor.h ostree-2017.12/src/ostree/ot-editor.h --- ostree-2017.11/src/ostree/ot-editor.h 2017-05-12 20:12:57.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-editor.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Stef Walter * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-main.c ostree-2017.12/src/ostree/ot-main.c --- ostree-2017.11/src/ostree/ot-main.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-main.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-main.h ostree-2017.12/src/ostree/ot-main.h --- ostree-2017.11/src/ostree/ot-main.h 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-main.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-add.c ostree-2017.12/src/ostree/ot-remote-builtin-add.c --- ostree-2017.11/src/ostree/ot-remote-builtin-add.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-add.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-add-cookie.c ostree-2017.12/src/ostree/ot-remote-builtin-add-cookie.c --- ostree-2017.11/src/ostree/ot-remote-builtin-add-cookie.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-add-cookie.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-delete.c ostree-2017.12/src/ostree/ot-remote-builtin-delete.c --- ostree-2017.11/src/ostree/ot-remote-builtin-delete.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-delete.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-delete-cookie.c ostree-2017.12/src/ostree/ot-remote-builtin-delete-cookie.c --- ostree-2017.11/src/ostree/ot-remote-builtin-delete-cookie.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-delete-cookie.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-gpg-import.c ostree-2017.12/src/ostree/ot-remote-builtin-gpg-import.c --- ostree-2017.11/src/ostree/ot-remote-builtin-gpg-import.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-gpg-import.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-list.c ostree-2017.12/src/ostree/ot-remote-builtin-list.c --- ostree-2017.11/src/ostree/ot-remote-builtin-list.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-list.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-list-cookies.c ostree-2017.12/src/ostree/ot-remote-builtin-list-cookies.c --- ostree-2017.11/src/ostree/ot-remote-builtin-list-cookies.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-list-cookies.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-refs.c ostree-2017.12/src/ostree/ot-remote-builtin-refs.c --- ostree-2017.11/src/ostree/ot-remote-builtin-refs.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-refs.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtins.h ostree-2017.12/src/ostree/ot-remote-builtins.h --- ostree-2017.11/src/ostree/ot-remote-builtins.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtins.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-show-url.c ostree-2017.12/src/ostree/ot-remote-builtin-show-url.c --- ostree-2017.11/src/ostree/ot-remote-builtin-show-url.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-show-url.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-builtin-summary.c ostree-2017.12/src/ostree/ot-remote-builtin-summary.c --- ostree-2017.11/src/ostree/ot-remote-builtin-summary.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-builtin-summary.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/ostree/ot-remote-cookie-util.c ostree-2017.12/src/ostree/ot-remote-cookie-util.c --- ostree-2017.11/src/ostree/ot-remote-cookie-util.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-cookie-util.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons * diff -Nru ostree-2017.11/src/ostree/ot-remote-cookie-util.h ostree-2017.12/src/ostree/ot-remote-cookie-util.h --- ostree-2017.11/src/ostree/ot-remote-cookie-util.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/src/ostree/ot-remote-cookie-util.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/rofiles-fuse/main.c ostree-2017.12/src/rofiles-fuse/main.c --- ostree-2017.11/src/rofiles-fuse/main.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/src/rofiles-fuse/main.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015,2016 Colin Walters * * This library is free software; you can redistribute it and/or @@ -313,7 +312,7 @@ if ((finfo->flags & O_ACCMODE) == O_RDONLY) { /* Read */ - fd = openat (basefd, path, finfo->flags); + fd = openat (basefd, path, finfo->flags, mode); if (fd == -1) return -errno; } diff -Nru ostree-2017.11/src/switchroot/ostree-mount-util.h ostree-2017.12/src/switchroot/ostree-mount-util.h --- ostree-2017.11/src/switchroot/ostree-mount-util.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/switchroot/ostree-mount-util.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011,2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/switchroot/ostree-remount.c ostree-2017.12/src/switchroot/ostree-remount.c --- ostree-2017.11/src/switchroot/ostree-remount.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/switchroot/ostree-remount.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2011 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/src/switchroot/ostree-system-generator.c ostree-2017.12/src/switchroot/ostree-system-generator.c --- ostree-2017.11/src/switchroot/ostree-system-generator.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/src/switchroot/ostree-system-generator.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2017 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/basic-test.sh ostree-2017.12/tests/basic-test.sh --- ostree-2017.11/tests/basic-test.sh 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/tests/basic-test.sh 2017-10-02 16:43:45.000000000 +0000 @@ -19,11 +19,7 @@ set -euo pipefail -echo "1..$((72 + ${extra_basic_tests:-0}))" - -$CMD_PREFIX ostree --version > version.yaml -python -c 'import yaml; yaml.safe_load(open("version.yaml"))' -echo "ok yaml version" +echo "1..$((73 + ${extra_basic_tests:-0}))" CHECKOUT_U_ARG="" CHECKOUT_H_ARGS="-H" @@ -282,7 +278,8 @@ opposite_mode=archive fi ostree_repo_init repo2 --mode=$opposite_mode - ${CMD_PREFIX} ostree --repo=repo2 pull-local repo + ${CMD_PREFIX} ostree --repo=repo2 pull-local repo >out.txt + assert_file_has_content out.txt "[1-9][0-9]* metadata, [1-9][0-9]* content objects imported" test2_commitid=$(${CMD_PREFIX} ostree --repo=repo rev-parse test2) test2_commit_relpath=/objects/${test2_commitid:0:2}/${test2_commitid:2}.commit assert_files_hardlinked repo/${test2_commit_relpath} repo2/${test2_commit_relpath} @@ -314,7 +311,7 @@ if $CMD_PREFIX ostree pull-local --repo=repo --bareuseronly-files repo-input content-with-suid 2>err.txt; then assert_not_reached "copying suid file with --bareuseronly-files worked?" fi -assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*' +assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*' echo "ok pull-local (bareuseronly files)" if ! skip_one_without_user_xattrs; then @@ -606,6 +603,24 @@ echo "ok commit with link speedup" cd ${test_tmpdir} +rm -rf test2-checkout +$OSTREE checkout test2 test2-checkout +# set cow to different perms, but re-set cowro to the same perms +cat > statoverride.txt < stats.txt +$OSTREE diff test2 test2-tmp > diff-test2 +assert_file_has_content diff-test2 'M */baz/cow$' +assert_not_file_has_content diff-test2 'M */baz/cowro$' +assert_not_file_has_content diff-test2 'baz/saucer' +# only /baz/cow is a cache miss +assert_file_has_content stats.txt '^Content Written: 1$' +echo "ok commit with link speedup and modifier" + +cd ${test_tmpdir} $OSTREE ls test2 echo "ok ls with no argument" @@ -809,8 +824,18 @@ rm -rf test2-checkout mkdir -p test2-checkout cd test2-checkout -touch should-not-be-fsynced -$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Unfsynced commit" --fsync=false +echo 'should not be fsynced' > should-not-be-fsynced +if ! skip_one_without_strace_fault_injection; then + # Test that --fsync=false doesn't fsync + fsync_inject_error_ostree="strace -o /dev/null -f -e inject=syncfs,fsync,sync:error=EPERM ostree" + ${fsync_inject_error_ostree} --repo=${test_tmpdir}/repo commit ${COMMIT_ARGS} -b test2-no-fsync --fsync=false + # And test that we get EPERM if we inject an error + if ${fsync_inject_error_ostree} --repo=${test_tmpdir}/repo commit ${COMMIT_ARGS} -b test2-no-fsync 2>err.txt; then + fatal "fsync error injection failed" + fi + assert_file_has_content err.txt 'sync.*Operation not permitted' + echo "ok fsync disabled" +fi # Run this test only as non-root user. When run as root, the chmod # won't have any effect. diff -Nru ostree-2017.11/tests/corrupt-repo-ref.js ostree-2017.12/tests/corrupt-repo-ref.js --- ostree-2017.11/tests/corrupt-repo-ref.js 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/corrupt-repo-ref.js 2017-10-01 17:38:12.000000000 +0000 @@ -47,7 +47,6 @@ e.close(null); } -let [,commit] = repo.resolve_rev(refToCorrupt, false); let [,root,commit] = repo.read_commit(refToCorrupt, null); let allObjects = {}; allObjects[commit + '.commit'] = true; diff -Nru ostree-2017.11/tests/libostreetest.c ostree-2017.12/tests/libostreetest.c --- ostree-2017.11/tests/libostreetest.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/tests/libostreetest.c 2017-10-02 17:06:07.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or @@ -73,6 +72,68 @@ return g_steal_pointer (&ret_repo); } +/* Determine whether we're able to relabel files. Needed for bare tests. */ +gboolean +ot_check_relabeling (gboolean *can_relabel, + GError **error) +{ + g_auto(GLnxTmpfile) tmpf = { 0, }; + if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) + return FALSE; + + g_autoptr(GError) local_error = NULL; + g_autoptr(GBytes) bytes = glnx_fgetxattr_bytes (tmpf.fd, "security.selinux", &local_error); + if (!bytes) + { + /* libglnx preserves errno */ + if (G_IN_SET (errno, ENOTSUP, ENODATA)) + { + *can_relabel = FALSE; + return TRUE; + } + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + gsize data_len; + const guint8 *data = g_bytes_get_data (bytes, &data_len); + if (fsetxattr (tmpf.fd, "security.selinux", data, data_len, 0) < 0) + { + if (errno == ENOTSUP) + { + *can_relabel = FALSE; + return TRUE; + } + return glnx_throw_errno_prefix (error, "fsetxattr"); + } + + *can_relabel = TRUE; + return TRUE; +} + +/* Determine whether the filesystem supports getting/setting user xattrs. */ +gboolean +ot_check_user_xattrs (gboolean *has_user_xattrs, + GError **error) +{ + g_auto(GLnxTmpfile) tmpf = { 0, }; + if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error)) + return FALSE; + + if (fsetxattr (tmpf.fd, "user.test", "novalue", strlen ("novalue"), 0) < 0) + { + if (errno == ENOTSUP) + { + *has_user_xattrs = FALSE; + return TRUE; + } + return glnx_throw_errno_prefix (error, "fsetxattr"); + } + + *has_user_xattrs = TRUE; + return TRUE; +} + OstreeSysroot * ot_test_setup_sysroot (GCancellable *cancellable, GError **error) @@ -80,22 +141,19 @@ if (!ot_test_run_libtest ("setup_os_repository \"archive\" \"syslinux\"", error)) return FALSE; - struct statfs stbuf; - { g_autoptr(GString) buf = g_string_new ("mutable-deployments"); - if (statfs ("/", &stbuf) < 0) - return glnx_null_throw_errno (error); - /* Keep this in sync with the overlayfs bits in libtest.sh */ -#ifndef OVERLAYFS_SUPER_MAGIC -#define OVERLAYFS_SUPER_MAGIC 0x794c7630 -#endif - if (stbuf.f_type == OVERLAYFS_SUPER_MAGIC) - { - g_print ("libostreetest: detected overlayfs\n"); - g_string_append (buf, ",no-xattrs"); - } - /* Make sure deployments are mutable */ - g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE); - } + g_autoptr(GString) buf = g_string_new ("mutable-deployments"); + + gboolean can_relabel; + if (!ot_check_relabeling (&can_relabel, error)) + return FALSE; + if (!can_relabel) + { + g_print ("libostreetest: can't relabel, turning off xattrs\n"); + g_string_append (buf, ",no-xattrs"); + } + + /* Make sure deployments are mutable */ + g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE); g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot"); return ostree_sysroot_new (sysroot_path); diff -Nru ostree-2017.11/tests/libostreetest.h ostree-2017.12/tests/libostreetest.h --- ostree-2017.11/tests/libostreetest.h 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/libostreetest.h 2017-10-02 16:43:45.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Colin Walters * * This library is free software; you can redistribute it and/or @@ -32,6 +31,12 @@ OstreeRepo *ot_test_setup_repo (GCancellable *cancellable, GError **error); +gboolean ot_check_relabeling (gboolean *can_relabel, + GError **error); + +gboolean ot_check_user_xattrs (gboolean *has_user_xattrs, + GError **error); + OstreeSysroot *ot_test_setup_sysroot (GCancellable *cancellable, GError **error); diff -Nru ostree-2017.11/tests/libtest-core.sh ostree-2017.12/tests/libtest-core.sh --- ostree-2017.11/tests/libtest-core.sh 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/libtest-core.sh 2017-10-01 17:38:12.000000000 +0000 @@ -40,6 +40,8 @@ else export LC_ALL=C fi +# A GNU extension, used whenever LC_ALL is not C +unset LANGUAGE # This should really be the default IMO export G_DEBUG=fatal-warnings diff -Nru ostree-2017.11/tests/libtest.sh ostree-2017.12/tests/libtest.sh --- ostree-2017.11/tests/libtest.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/libtest.sh 2017-10-02 16:43:45.000000000 +0000 @@ -70,16 +70,50 @@ export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted -# See comment in ot-builtin-commit.c and https://github.com/ostreedev/ostree/issues/758 -# Also keep this in sync with the bits in libostreetest.c -echo evaluating for overlayfs... -case $(stat -f --printf '%T' /) in - overlayfs) - echo "overlayfs found; enabling OSTREE_NO_XATTRS" - export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs" - export OSTREE_NO_XATTRS=1 ;; - *) ;; -esac +assert_has_setfattr() { + if ! which setfattr 2>/dev/null; then + fatal "no setfattr available to determine xattr support" + fi +} + +_have_selinux_relabel='' +have_selinux_relabel() { + assert_has_setfattr + if test "${_have_selinux_relabel}" = ''; then + pushd ${test_tmpdir} + echo testlabel > testlabel.txt + selinux_xattr=security.selinux + if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then + label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,") + if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then + echo "SELinux enabled in $(pwd), and have privileges to relabel" + _have_selinux_relabel=yes + else + sed -e 's/^/# /' < err.txt >&2 + echo "Found SELinux label, but unable to set (Unprivileged Docker?)" + _have_selinux_relabel=no + fi + else + sed -e 's/^/# /' < err.txt >&2 + echo "Unable to retrieve SELinux label, assuming disabled" + _have_selinux_relabel=no + fi + popd + fi + test ${_have_selinux_relabel} = yes +} + +# just globally turn off xattrs if we can't manipulate security xattrs; this is +# the case for overlayfs -- really, we should only enforce this for tests that +# use bare repos; separate from other tests that should check for user xattrs +# support +# see https://github.com/ostreedev/ostree/issues/758 +# and https://github.com/ostreedev/ostree/pull/1217 +echo -n checking for xattrs... +if ! have_selinux_relabel; then + export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs" + export OSTREE_NO_XATTRS=1 +fi echo done if test -n "${OT_TESTS_DEBUG:-}"; then @@ -141,6 +175,7 @@ fi cd ${test_tmpdir} + rm -rf repo if test -n "${mode}"; then ostree_repo_init repo --mode=${mode} else @@ -150,6 +185,9 @@ export OSTREE="${CMD_PREFIX} ostree ${ot_repo}" cd ${test_tmpdir} + local oldumask="$(umask)" + umask 022 + rm -rf files mkdir files cd files ot_files=`pwd` @@ -172,6 +210,7 @@ ln -s nonexistent baz/alink mkdir baz/another/ echo x > baz/another/y + umask "${oldumask}" cd ${test_tmpdir}/files $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Test Commit 2" -m "Commit body second" @@ -511,10 +550,24 @@ cd ${test_tmpdir} } +_have_user_xattrs='' +have_user_xattrs() { + assert_has_setfattr + if test "${_have_user_xattrs}" = ''; then + touch test-xattrs + if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then + _have_user_xattrs=yes + else + _have_user_xattrs=no + fi + rm -f test-xattrs + fi + test ${_have_user_xattrs} = yes +} + # Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi skip_one_without_user_xattrs () { - touch test-xattrs - if ! setfattr -n user.testvalue -v somevalue test-xattrs; then + if ! have_user_xattrs; then echo "ok # SKIP - this test requires xattr support" return 0 else @@ -523,9 +576,43 @@ } skip_without_user_xattrs () { - touch test-xattrs - setfattr -n user.testvalue -v somevalue test-xattrs || \ + if ! have_user_xattrs; then + skip "this test requires xattr support" + fi +} + +# Skip unless SELinux is disabled, or we can relabel. +# Default Docker has security.selinux xattrs, but returns +# EOPNOTSUPP when trying to set them, even to the existing value. +# https://github.com/ostreedev/ostree/pull/759 +# https://github.com/ostreedev/ostree/pull/1217 +skip_without_no_selinux_or_relabel () { + if ! have_selinux_relabel; then skip "this test requires xattr support" + fi +} + +# https://brokenpi.pe/tools/strace-fault-injection +_have_strace_fault_injection='' +have_strace_fault_injection() { + if test "${_have_strace_fault_injection}" = ''; then + if strace -P ${test_srcdir}/libtest-core.sh -e inject=read:retval=0 cat ${test_srcdir}/libtest-core.sh >out.txt && + test '!' -s out.txt; then + _have_strace_fault_injection=yes + else + _have_strace_fault_injection=no + fi + rm -f out.txt + fi + test ${_have_strace_fault_injection} = yes +} + +skip_one_without_strace_fault_injection() { + if ! have_strace_fault_injection; then + echo "ok # SKIP this test requires strace fault injection" + return 0 + fi + return 1 } skip_without_fuse () { @@ -538,6 +625,12 @@ [ -e /etc/mtab ] || skip "no /etc/mtab" } +skip_without_experimental () { + if ! ostree --version | grep -q -e '- experimental'; then + skip "No experimental API is compiled in" + fi +} + has_gpgme () { ${CMD_PREFIX} ostree --version > version.txt assert_file_has_content version.txt '- gpgme' diff -Nru ostree-2017.11/tests/pull-test.sh ostree-2017.12/tests/pull-test.sh --- ostree-2017.11/tests/pull-test.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/pull-test.sh 2017-10-02 17:11:19.000000000 +0000 @@ -35,14 +35,14 @@ assert_file_has_content baz/cow '^moo$' } -echo "1..29" +echo "1..31" # Try both syntaxes repo_init --no-gpg-verify ${CMD_PREFIX} ostree --repo=repo pull origin main >out.txt assert_file_has_content out.txt "[1-9][0-9]* metadata, [1-9][0-9]* content objects fetched" ${CMD_PREFIX} ostree --repo=repo pull origin:main > out.txt -assert_not_file_has_content out.txt "content objects fetched" +assert_not_file_has_content out.txt "[1-9][0-9]* content objects fetched" ${CMD_PREFIX} ostree --repo=repo fsck echo "ok pull" @@ -127,7 +127,7 @@ if ${CMD_PREFIX} ostree --repo=mirrorrepo pull ${flag} --bareuseronly-files origin content-with-suid 2>err.txt; then assert_not_reached "pulled unsafe bareuseronly" fi - assert_file_has_content err.txt 'object.*\.file: invalid mode.*with bits 040.*' + assert_file_has_content err.txt 'Content object.*: invalid mode.*with bits 040.*' done echo "ok pull (bareuseronly, unsafe)" @@ -137,6 +137,63 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror --bareuseronly-files origin main echo "ok pull (bareuseronly mirror)" +# Corruption tests +cd ${test_tmpdir} +repo_init --no-gpg-verify +if ! is_bare_user_only_repo repo && ! skip_one_without_user_xattrs; then + if is_bare_user_only_repo repo; then + cacherepomode=bare-user-only + else + cacherepomode=bare-user + fi + rm cacherepo -rf + ostree_repo_init cacherepo --mode=${cacherepomode} + ${CMD_PREFIX} ostree --repo=cacherepo pull-local ostree-srv/gnomerepo main + rev=$(ostree --repo=cacherepo rev-parse main) + ${CMD_PREFIX} ostree --repo=cacherepo ls -R -C main > ls.txt + regfile_hash=$(grep -E -e '^-0' ls.txt | head -1 | awk '{ print $5 }') + ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false corruptrepo $(cat httpd-address)/ostree/corruptrepo + # Make this a loop so in the future we can add more object types like commit etc. + for object in ${regfile_hash}.file; do + checksum=$(echo ${object} | sed -e 's,\(.*\)\.[a-z]*$,\1,') + path=cacherepo/objects/${object:0:2}/${object:2} + # Preserve user.ostreemeta xattr + cp -a ${path}{,.new} + (dd if=${path} conv=swab) > ${path}.new + mv ${path}{.new,} + if ${CMD_PREFIX} ostree --repo=cacherepo fsck 2>err.txt; then + fatal "corrupt repo fsck?" + fi + assert_file_has_content err.txt "corrupted.*${checksum}" + rm ostree-srv/corruptrepo -rf + ostree_repo_init ostree-srv/corruptrepo --mode=archive + ${CMD_PREFIX} ostree --repo=ostree-srv/corruptrepo pull-local cacherepo main + # Pulling via HTTP into a non-archive should fail, even with + # --http-trusted. + if ${CMD_PREFIX} ostree --repo=repo pull --http-trusted corruptrepo main 2>err.txt; then + fatal "Pulled from corrupt repo?" + fi + assert_file_has_content err.txt "Corrupted.*${checksum}" + if ${CMD_PREFIX} ostree --repo=repo show corruptrepo:main >/dev/null; then + fatal "Pulled from corrupt repo?" + fi + ${CMD_PREFIX} ostree --repo=repo prune --refs-only + rm repo/tmp/* -rf + ostree_repo_init corruptmirrorrepo --mode=archive + # Pulling via http-trusted should not verify the checksum + ${CMD_PREFIX} ostree --repo=corruptmirrorrepo remote add --set=gpg-verify=false corruptrepo $(cat httpd-address)/ostree/corruptrepo + ${CMD_PREFIX} ostree --repo=corruptmirrorrepo pull --mirror --http-trusted corruptrepo main + # But it should fail to fsck + if ${CMD_PREFIX} ostree --repo=corruptmirrorrepo fsck 2>err.txt; then + fatal "corrupt mirror repo fsck?" + fi + done + + # And ensure the repo is reinitialized + repo_init --no-gpg-verify + echo "ok corruption" +fi + cd ${test_tmpdir} rm mirrorrepo/refs/remotes/* -rf ${CMD_PREFIX} ostree --repo=mirrorrepo prune --refs-only @@ -158,7 +215,7 @@ ${CMD_PREFIX} ostree --repo=mirrorrepo-local remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo ${CMD_PREFIX} ostree --repo=mirrorrepo-local pull --mirror origin main ${CMD_PREFIX} ostree --repo=mirrorrepo-local fsck -$OSTREE show main >/dev/null +${CMD_PREFIX} ostree --repo=mirrorrepo show main >/dev/null echo "ok pull local mirror" cd ${test_tmpdir} @@ -420,6 +477,16 @@ echo "ok pull repo 404 (gpg)" cd ${test_tmpdir} +find ostree-srv/gnomerepo/objects -name '*.dirtree' | while read f; do mv ${f}{,.orig}; done +repo_init --set=gpg-verify=false +if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main 2>err.txt; then + assert_not_reached "pull repo 404 succeeded?" +fi +assert_file_has_content err.txt "404" +find ostree-srv/gnomerepo/objects -name '*.dirtree.orig' | while read f; do mv ${f} $(dirname $f)/$(basename ${f} .orig); done +echo "ok pull repo 404 on dirtree object" + +cd ${test_tmpdir} repo_init --set=gpg-verify=true ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit \ --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1} -b main \ @@ -451,5 +518,5 @@ if ${CMD_PREFIX} ostree --repo=repo pull origin main 2>err.txt; then fatal "pull of invalid ref succeeded" fi -assert_file_has_content_literal err.txt 'error: Fetching refs/heads/main: Invalid rev lots of html here lots of html here lots of html here lots of' +assert_file_has_content_literal err.txt 'error: Fetching checksum for ref ((empty), main): Invalid rev lots of html here lots of html here lots of html here lots of' echo "ok pull got HTML for a ref" diff -Nru ostree-2017.11/tests/readdir-rand.c ostree-2017.12/tests/readdir-rand.c --- ostree-2017.11/tests/readdir-rand.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/readdir-rand.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Colin Walters . * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/repo-finder-mount.c ostree-2017.12/tests/repo-finder-mount.c --- ostree-2017.11/tests/repo-finder-mount.c 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/tests/repo-finder-mount.c 2017-10-01 17:38:12.000000000 +0000 @@ -0,0 +1,126 @@ +/* + * Copyright © 2017 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "ostree-autocleanups.h" +#include "ostree-remote-private.h" +#include "ostree-repo-finder.h" +#include "ostree-repo-finder-mount.h" +#include "ostree-types.h" +#include "test-mock-gio.h" + +static void +result_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + GAsyncResult **result_out = user_data; + *result_out = g_object_ref (result); +} + +static void +collection_ref_free0 (OstreeCollectionRef *ref) +{ + g_clear_pointer (&ref, (GDestroyNotify) ostree_collection_ref_free); +} + +int +main (int argc, char **argv) +{ + g_autoptr(GError) error = NULL; + + setlocale (LC_ALL, ""); + + if (argc < 5 || (argc % 2) != 1) + { + g_printerr ("Usage: %s REPO MOUNT-ROOT COLLECTION-ID REF-NAME [COLLECTION-ID REF-NAME …]\n", argv[0]); + return 1; + } + + g_autoptr(GMainContext) context = g_main_context_new (); + g_main_context_push_thread_default (context); + + g_autoptr(OstreeRepo) parent_repo = ostree_repo_open_at (AT_FDCWD, argv[1], NULL, &error); + g_assert_no_error (error); + + /* Set up a mock volume. */ + g_autoptr(GFile) mount_root = g_file_new_for_commandline_arg (argv[2]); + g_autoptr(GMount) mount = G_MOUNT (ostree_mock_mount_new ("mount", mount_root)); + + g_autoptr(GList) mounts = g_list_prepend (NULL, mount); + + g_autoptr(GVolumeMonitor) monitor = ostree_mock_volume_monitor_new (mounts, NULL); + g_autoptr(OstreeRepoFinderMount) finder = ostree_repo_finder_mount_new (monitor); + + /* Resolve the refs. */ + g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func ((GDestroyNotify) collection_ref_free0); + + for (gsize i = 3; i < argc; i += 2) + { + const char *collection_id = argv[i]; + const char *ref_name = argv[i + 1]; + + g_ptr_array_add (refs, ostree_collection_ref_new (collection_id, ref_name)); + } + + g_ptr_array_add (refs, NULL); /* NULL terminator */ + + g_autoptr(GAsyncResult) result = NULL; + ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), + (const OstreeCollectionRef * const *) refs->pdata, + parent_repo, NULL, result_cb, &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + g_autoptr(GPtrArray) results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), + result, &error); + g_assert_no_error (error); + + /* Check that the results are correct: the invalid refs should have been + * ignored, and the valid results canonicalised and deduplicated. */ + for (gsize i = 0; i < results->len; i++) + { + const OstreeRepoFinderResult *result = g_ptr_array_index (results, i); + GHashTableIter iter; + OstreeCollectionRef *ref; + const gchar *checksum; + + g_hash_table_iter_init (&iter, result->ref_to_checksum); + + while (g_hash_table_iter_next (&iter, (gpointer *) &ref, (gpointer *) &checksum)) + g_print ("%" G_GSIZE_FORMAT " %s %s %s %s\n", + i, ostree_remote_get_name (result->remote), + ref->collection_id, ref->ref_name, + checksum); + } + + g_main_context_pop_thread_default (context); + + return 0; +} diff -Nru ostree-2017.11/tests/test-basic-c.c ostree-2017.12/tests/test-basic-c.c --- ostree-2017.11/tests/test-basic-c.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-basic-c.c 2017-10-02 16:43:45.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or @@ -237,6 +236,131 @@ } } +static GVariant* +xattr_cb (OstreeRepo *repo, + const char *path, + GFileInfo *file_info, + gpointer user_data) +{ + GVariant *xattr = user_data; + if (g_str_equal (path, "/baz/cow")) + return g_variant_ref (xattr); + return NULL; +} + +/* check that using a devino cache doesn't cause us to ignore xattr callbacks */ +static void +test_devino_cache_xattrs (void) +{ + g_autoptr(GError) error = NULL; + gboolean ret = FALSE; + + g_autoptr(GFile) repo_path = g_file_new_for_path ("repo"); + + /* re-initialize as bare */ + ret = ot_test_run_libtest ("setup_test_repository bare", &error); + g_assert_no_error (error); + g_assert (ret); + + gboolean can_relabel; + ret = ot_check_relabeling (&can_relabel, &error); + g_assert_no_error (error); + g_assert (ret); + + gboolean has_user_xattrs; + ret = ot_check_user_xattrs (&has_user_xattrs, &error); + g_assert_no_error (error); + g_assert (ret); + + /* we need both because we're bare and our tests target user xattrs */ + if (!can_relabel || !has_user_xattrs) + { + g_test_skip ("this test requires full xattr support"); + return; + } + + g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); + ret = ostree_repo_open (repo, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autofree char *csum = NULL; + ret = ostree_repo_resolve_rev (repo, "test2", FALSE, &csum, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(OstreeRepoDevInoCache) cache = ostree_repo_devino_cache_new (); + + OstreeRepoCheckoutAtOptions options = {0,}; + options.no_copy_fallback = TRUE; + options.devino_to_csum_cache = cache; + ret = ostree_repo_checkout_at (repo, &options, AT_FDCWD, "checkout", csum, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(OstreeMutableTree) mtree = ostree_mutable_tree_new (); + g_autoptr(OstreeRepoCommitModifier) modifier = + ostree_repo_commit_modifier_new (0, NULL, NULL, NULL); + ostree_repo_commit_modifier_set_devino_cache (modifier, cache); + + g_auto(GVariantBuilder) builder; + g_variant_builder_init (&builder, (GVariantType*)"a(ayay)"); + g_variant_builder_add (&builder, "(@ay@ay)", + g_variant_new_bytestring ("user.myattr"), + g_variant_new_bytestring ("data")); + g_autoptr(GVariant) orig_xattrs = g_variant_ref_sink (g_variant_builder_end (&builder)); + + ret = ostree_repo_prepare_transaction (repo, NULL, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + ostree_repo_commit_modifier_set_xattr_callback (modifier, xattr_cb, NULL, orig_xattrs); + ret = ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, "checkout", + mtree, modifier, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + g_autoptr(GFile) root = NULL; + ret = ostree_repo_write_mtree (repo, mtree, &root, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* now check that the final xattr matches */ + g_autoptr(GFile) baz_child = g_file_get_child (root, "baz"); + g_autoptr(GFile) cow_child = g_file_get_child (baz_child, "cow"); + + g_autoptr(GVariant) xattrs = NULL; + ret = ostree_repo_file_get_xattrs (OSTREE_REPO_FILE (cow_child), &xattrs, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + gboolean found_xattr = FALSE; + gsize n = g_variant_n_children (xattrs); + for (gsize i = 0; i < n; i++) + { + const guint8* name; + const guint8* value; + g_variant_get_child (xattrs, i, "(^&ay^&ay)", &name, &value); + + if (g_str_equal ((const char*)name, "user.myattr")) + { + g_assert_cmpstr ((const char*)value, ==, "data"); + found_xattr = TRUE; + break; + } + } + + g_assert (found_xattr); + + OstreeRepoTransactionStats stats; + ret = ostree_repo_commit_transaction (repo, &stats, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + + /* we should only have had to checksum /baz/cow */ + g_assert_cmpint (stats.content_objects_written, ==, 1); +} + int main (int argc, char **argv) { g_autoptr(GError) error = NULL; @@ -244,13 +368,14 @@ g_test_init (&argc, &argv, NULL); - repo = ot_test_setup_repo (NULL, &error); + repo = ot_test_setup_repo (NULL, &error); if (!repo) goto out; g_test_add_data_func ("/repo-not-system", repo, test_repo_is_not_system); g_test_add_data_func ("/raw-file-to-archive-stream", repo, test_raw_file_to_archive_stream); g_test_add_data_func ("/objectwrites", repo, test_object_writes); + g_test_add_func ("/xattrs-devino-cache", test_devino_cache_xattrs); g_test_add_func ("/remotename", test_validate_remotename); return g_test_run(); diff -Nru ostree-2017.11/tests/test-basic.sh ostree-2017.12/tests/test-basic.sh --- ostree-2017.11/tests/test-basic.sh 2017-09-01 20:10:50.000000000 +0000 +++ ostree-2017.12/tests/test-basic.sh 2017-10-01 17:38:12.000000000 +0000 @@ -21,6 +21,7 @@ . $(dirname $0)/libtest.sh -setup_test_repository "bare" +skip_without_no_selinux_or_relabel +setup_test_repository "bare" . $(dirname $0)/basic-test.sh diff -Nru ostree-2017.11/tests/test-basic-user-only.sh ostree-2017.12/tests/test-basic-user-only.sh --- ostree-2017.11/tests/test-basic-user-only.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-basic-user-only.sh 2017-10-01 17:38:12.000000000 +0000 @@ -22,9 +22,13 @@ . $(dirname $0)/libtest.sh setup_test_repository "bare-user-only" -extra_basic_tests=4 +extra_basic_tests=5 . $(dirname $0)/basic-test.sh +$CMD_PREFIX ostree --version > version.yaml +python -c 'import yaml; yaml.safe_load(open("version.yaml"))' +echo "ok yaml version" + # Reset things so we don't inherit a lot of state from earlier tests cd ${test_tmpdir} rm repo files -rf @@ -45,7 +49,7 @@ if $CMD_PREFIX ostree pull-local --repo=repo repo-input 2>err.txt; then assert_not_reached "copying suid file into bare-user worked?" fi -assert_file_has_content err.txt "Invalid mode.*with bits 040.*in bare-user-only" +assert_file_has_content err.txt "Content object.*invalid mode.*with bits 040.*" echo "ok failed to commit suid" cd ${test_tmpdir} diff -Nru ostree-2017.11/tests/test-basic-user.sh ostree-2017.12/tests/test-basic-user.sh --- ostree-2017.11/tests/test-basic-user.sh 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-basic-user.sh 2017-10-01 17:38:12.000000000 +0000 @@ -34,11 +34,7 @@ cd ${test_tmpdir} objpath_nonexec=$(ostree_file_path_to_object_path repo test2 baz/cow) -# Sigh, umask -touch testfile -default_mode=$(stat -c '%a' testfile) -rm testfile -assert_file_has_mode ${objpath_nonexec} ${default_mode} +assert_file_has_mode ${objpath_nonexec} 644 objpath_ro=$(ostree_file_path_to_object_path repo test2 baz/cowro) assert_file_has_mode ${objpath_ro} 600 objpath_exec=$(ostree_file_path_to_object_path repo test2 baz/deeper/ohyeahx) @@ -48,7 +44,7 @@ rm test2-checkout -rf $OSTREE checkout -U -H test2 test2-checkout cd test2-checkout -assert_file_has_mode baz/cow ${default_mode} +assert_file_has_mode baz/cow 644 assert_file_has_mode baz/cowro 600 assert_file_has_mode baz/deeper/ohyeahx 755 echo "ok bare-user checkout modes" diff -Nru ostree-2017.11/tests/test-bloom.c ostree-2017.12/tests/test-bloom.c --- ostree-2017.11/tests/test-bloom.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-bloom.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-bsdiff.c ostree-2017.12/tests/test-bsdiff.c --- ostree-2017.11/tests/test-bsdiff.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-bsdiff.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-checksum.c ostree-2017.12/tests/test-checksum.c --- ostree-2017.11/tests/test-checksum.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/test-checksum.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-commit-sign.sh ostree-2017.12/tests/test-commit-sign.sh --- ostree-2017.11/tests/test-commit-sign.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-commit-sign.sh 2017-10-02 16:43:45.000000000 +0000 @@ -26,7 +26,7 @@ exit 0 fi -echo "1..1" +echo "1..6" keyid="472CDAFA" oldpwd=`pwd` @@ -73,6 +73,7 @@ assert_not_reached "pull with no trusted GPG keys unexpectedly succeeded!" fi rm repo -rf +echo "ok pull no trusted GPG" # And a test case with valid signature cd ${test_tmpdir} @@ -80,9 +81,10 @@ ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main -${CMD_PREFIX} ostree --repo=repo show --gpg-verify-remote=origin main | grep -o 'Found [[:digit:]] signature' > show-verify-remote -assert_file_has_content show-verify-remote 'Found 1 signature' +${CMD_PREFIX} ostree --repo=repo show --gpg-verify-remote=origin main > show.txt +assert_file_has_content_literal show.txt 'Found 1 signature' rm repo -rf +echo "ok pull verify" # A test with corrupted detached signature cd ${test_tmpdir} @@ -96,6 +98,7 @@ assert_not_reached "pull with corrupted signature unexpectedly succeeded!" fi rm repo -rf +echo "ok pull corrupted sig" # And now attempt to pull the same corrupted commit, but with GPG # verification off @@ -105,6 +108,7 @@ ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main rm repo -rf +echo "ok repull corrupted" # Add an unsigned commit to the repo, then pull, then sign the commit, # then pull again. Make sure we get the expected number of signatures @@ -117,23 +121,21 @@ ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull origin main -if ${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature'; then - assert_not_reached -fi +${CMD_PREFIX} ostree --repo=repo show main > show.txt +assert_not_file_has_content show.txt 'Found.*signature' ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo gpg-sign --gpg-homedir=${test_tmpdir}/gpghome main $keyid ${CMD_PREFIX} ostree --repo=repo pull origin main -${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature' > show -assert_file_has_content show 'Found 1 signature' +${CMD_PREFIX} ostree --repo=repo show main > show.txt +assert_file_has_content_literal show.txt 'Found 1 signature' +echo "ok pull unsigned, then sign" # Delete the signature from the commit so the detached metadata is empty, # then pull and verify the signature is also deleted on the client side. ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo gpg-sign --gpg-homedir=${test_tmpdir}/gpghome --delete main $keyid ${CMD_PREFIX} ostree --repo=repo pull origin main -if ${CMD_PREFIX} ostree --repo=repo show main | grep -o 'Found [[:digit:]] signature'; then - assert_not_reached -fi +${CMD_PREFIX} ostree --repo=repo show main >show.txt +assert_not_file_has_content show.txt 'Found.*signature' +echo "ok pull sig deleted" rm -rf repo gnomerepo-files libtest_cleanup_gpg - -echo "ok" diff -Nru ostree-2017.11/tests/test-create-usb.sh ostree-2017.12/tests/test-create-usb.sh --- ostree-2017.11/tests/test-create-usb.sh 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/tests/test-create-usb.sh 2017-10-01 17:38:12.000000000 +0000 @@ -0,0 +1,110 @@ +#!/bin/bash +# +# Copyright © 2017 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. +# +# Authors: +# - Philip Withnall + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +echo "1..5" + +cd ${test_tmpdir} +mkdir repo +ostree_repo_init repo --collection-id org.example.Collection1 + +mkdir -p tree/root +touch tree/root/a + +# Add a few commits +seq 5 | while read i; do + echo a >> tree/root/a + ${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" tree +done + +${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" + +# Pull into a ‘local’ repository, to more accurately represent the situation of +# creating a USB stick from your local machine. +mkdir local-repo +${CMD_PREFIX} ostree --repo=local-repo init +${CMD_PREFIX} ostree --repo=local-repo remote add remote1 file://$(pwd)/repo --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" +${CMD_PREFIX} ostree --repo=local-repo pull remote1 test-1 test-2 test-3 test-4 test-5 + +# Simple test to put two refs onto a USB stick. +mkdir dest-mount1 +${CMD_PREFIX} ostree --repo=local-repo create-usb dest-mount1 org.example.Collection1 test-1 org.example.Collection1 test-2 + +assert_has_dir dest-mount1/.ostree/repo +${CMD_PREFIX} ostree --repo=dest-mount1/.ostree/repo refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" +assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_has_file dest-mount1/.ostree/repo/summary + +echo "ok 1 simple usb" + +# Test that the repository can be placed in another standard location on the USB stick. +for dest in ostree/repo .ostree/repo; do + rm -rf dest-mount2 + mkdir dest-mount2 + ${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo "$dest" dest-mount2 org.example.Collection1 test-1 + assert_has_dir "dest-mount2/$dest" + if [ -d dest-mount2/.ostree/repos.d ]; then + ls dest-mount2/.ostree/repos.d | wc -l > repo-links + assert_file_has_content repo-links "^0$" + fi +done + +echo "ok 2 usb in standard location" + +# Test that the repository can be placed in a non-standard location and gets a symlink to it. +mkdir dest-mount3 +${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest dest-mount3 org.example.Collection1 test-1 +assert_has_dir "dest-mount3/some-dest" +assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" +${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_has_file dest-mount3/.ostree/repos.d/00-generated/summary + +echo "ok 3 usb in non-standard location" + +# Test that adding an additional ref to an existing USB repository works. +${CMD_PREFIX} ostree --repo=local-repo create-usb --destination-repo some-dest dest-mount3 org.example.Collection1 test-2 org.example.Collection1 test-3 +assert_has_dir "dest-mount3/some-dest" +assert_symlink_has_content "dest-mount3/.ostree/repos.d/00-generated" "/some-dest$" +${CMD_PREFIX} ostree --repo=dest-mount3/.ostree/repos.d/00-generated refs --collections > dest-refs +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" +assert_file_has_content dest-refs "^(org.example.Collection1, test-3)$" +assert_has_file dest-mount3/.ostree/repos.d/00-generated/summary + +echo "ok 4 adding ref to an existing usb" + +# Check that #OstreeRepoFinderMount works from a volume initialised uing create-usb. +mkdir finder-repo +ostree_repo_init finder-repo +${CMD_PREFIX} ostree --repo=finder-repo remote add remote1 file://$(pwd)/just-needed-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" + +${test_builddir}/repo-finder-mount finder-repo dest-mount1 org.example.Collection1 test-1 org.example.Collection1 test-2 &> out +assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-1 $(ostree --repo=repo show test-1)$" +assert_file_has_content out "^0 .*_2Fdest-mount1_2F.ostree_2Frepo_remote1.trustedkeys.gpg org.example.Collection1 test-2 $(ostree --repo=repo show test-2)$" + +echo "ok 5 find from usb repo" diff -Nru ostree-2017.11/tests/test-gpg-verify-result.c ostree-2017.12/tests/test-gpg-verify-result.c --- ostree-2017.11/tests/test-gpg-verify-result.c 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-gpg-verify-result.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-help.sh ostree-2017.12/tests/test-help.sh --- ostree-2017.11/tests/test-help.sh 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/tests/test-help.sh 2017-10-01 17:38:12.000000000 +0000 @@ -75,7 +75,16 @@ assert_file_empty out for subcmd in $builtins; do - test_recursive "$cmd $subcmd" + case "$subcmd" in + (trivial-httpd) + # Skip trivial-httpd if enabled, it doesn't work + # uninstalled (and also doesn't produce the output + # we expect). + ;; + (*) + test_recursive "$cmd $subcmd" + ;; + esac done fi } diff -Nru ostree-2017.11/tests/test-keyfile-utils.c ostree-2017.12/tests/test-keyfile-utils.c --- ostree-2017.11/tests/test-keyfile-utils.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/test-keyfile-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-libarchive-import.c ostree-2017.12/tests/test-libarchive-import.c --- ostree-2017.11/tests/test-libarchive-import.c 2017-09-14 14:03:50.000000000 +0000 +++ ostree-2017.12/tests/test-libarchive-import.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-lzma.c ostree-2017.12/tests/test-lzma.c --- ostree-2017.11/tests/test-lzma.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-lzma.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-mock-gio.c ostree-2017.12/tests/test-mock-gio.c --- ostree-2017.11/tests/test-mock-gio.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-mock-gio.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-mock-gio.h ostree-2017.12/tests/test-mock-gio.h --- ostree-2017.11/tests/test-mock-gio.h 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-mock-gio.h 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-mutable-tree.c ostree-2017.12/tests/test-mutable-tree.c --- ostree-2017.11/tests/test-mutable-tree.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-mutable-tree.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-ot-opt-utils.c ostree-2017.12/tests/test-ot-opt-utils.c --- ostree-2017.11/tests/test-ot-opt-utils.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/test-ot-opt-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-ot-tool-util.c ostree-2017.12/tests/test-ot-tool-util.c --- ostree-2017.11/tests/test-ot-tool-util.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/test-ot-tool-util.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-ot-unix-utils.c ostree-2017.12/tests/test-ot-unix-utils.c --- ostree-2017.11/tests/test-ot-unix-utils.c 2017-08-23 17:06:02.000000000 +0000 +++ ostree-2017.12/tests/test-ot-unix-utils.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-prune.sh ostree-2017.12/tests/test-prune.sh --- ostree-2017.11/tests/test-prune.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-prune.sh 2017-10-01 17:38:12.000000000 +0000 @@ -25,7 +25,7 @@ setup_fake_remote_repo1 "archive" -echo '1..5' +echo '1..12' cd ${test_tmpdir} mkdir repo @@ -44,16 +44,20 @@ ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin test +assert_repo_has_n_commits() { + repo=$1 + count=$2 + assert_streq "$(find ${repo}/objects -name '*.commit' | wc -l)" "${count}" +} + ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=2 -v -find repo | grep \.commit$ | wc -l > commitcount -assert_file_has_content commitcount "^3$" +assert_repo_has_n_commits repo 3 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_file_has_content tombstonecommitcount "^0$" $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=1 -v -find repo | grep \.commit$ | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_file_has_content tombstonecommitcount "^0$" @@ -70,8 +74,7 @@ assert_file_has_content tombstonecommitcount "^0$" ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^1$" +assert_repo_has_n_commits repo 1 find repo/objects -name '*.tombstone-commit' | wc -l > tombstonecommitcount assert_not_file_has_content tombstonecommitcount "^0$" $OSTREE fsck @@ -88,28 +91,22 @@ $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^1$" +assert_repo_has_n_commits repo 1 ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="2005-10-29 12:43:29 +0000" ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="2010-10-29 12:43:29 +0000" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^3$" +assert_repo_has_n_commits repo 3 ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="2015-10-29 12:43:29 +0000" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 $OSTREE fsck ${CMD_PREFIX} ostree prune --repo=repo --refs-only --depth=0 -v -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="October 25 1985" ${CMD_PREFIX} ostree --repo=repo commit --branch=test -m test -s test tree --timestamp="October 21 2015" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^4$" +assert_repo_has_n_commits repo 4 ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^2$" +assert_repo_has_n_commits repo 2 ${CMD_PREFIX} ostree --repo=repo commit --branch=oldcommit tree --timestamp="2005-10-29 12:43:29 +0000" oldcommit_rev=$($OSTREE --repo=repo rev-parse oldcommit) @@ -200,8 +197,7 @@ ${CMD_PREFIX} ostree --repo=datetest-snapshot-repo commit --branch=stable -m test -s "new stable build $x" tree ${CMD_PREFIX} ostree --repo=datetest-snapshot-repo commit --branch=dev -m test -s "new dev build $x" tree done -find datetest-snapshot-repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^16$" +assert_repo_has_n_commits datetest-snapshot-repo 16 # Snapshot the above reinitialize_datesnap_repo() { @@ -219,18 +215,15 @@ fi assert_file_has_content err.txt 'Invalid depth BACON' ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" --retain-branch-depth=stable=-1 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^11$" +assert_repo_has_n_commits repo 11 # Double check our backup is unchanged -find datetest-snapshot-repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^16$" +assert_repo_has_n_commits datetest-snapshot-repo 16 $OSTREE fsck # Again but this time only retain 6 (5+1) commits on stable. This should drop # out 8 - 6 = 2 commits (so the 11 above minus 2 = 9) ${CMD_PREFIX} ostree --repo=repo prune --keep-younger-than="1 week ago" --retain-branch-depth=stable=5 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^9$" +assert_repo_has_n_commits repo 9 $OSTREE fsck echo "ok retain branch depth and keep-younger-than" @@ -238,8 +231,58 @@ # so 8 stable + 1 dev = 9 reinitialize_datesnap_repo ${CMD_PREFIX} ostree --repo=repo prune --depth=0 --retain-branch-depth=stable=-1 -find repo/objects -name '*.commit' | wc -l > commitcount -assert_file_has_content commitcount "^9$" +assert_repo_has_n_commits repo 9 $OSTREE fsck echo "ok retain branch depth (alone)" + +# Test --only-branch with --depth=0; this should be exactly identical to the +# above with a result of 9. +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=0 +assert_repo_has_n_commits repo 9 +$OSTREE fsck +echo "ok --only-branch --depth=0" + +# Test --only-branch with --depth=1; should just add 1 to the above, for 10. +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=1 +assert_repo_has_n_commits repo 10 +echo "ok --only-branch --depth=1" + +# Test --only-branch with all branches +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=0 +assert_repo_has_n_commits repo 2 +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=1 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch (all) --depth=1" + +# Test --only-branch and --retain-branch-depth overlap +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --only-branch=stable --depth=0 \ + --retain-branch-depth=stable=2 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch and --retain-branch-depth overlap" + +# Test --only-branch and --retain-branch-depth together +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=dev --depth=0 --retain-branch-depth=stable=2 +assert_repo_has_n_commits repo 4 +echo "ok --only-branch and --retain-branch-depth together" + +# Test --only-branch with --keep-younger-than; this should be identical to the test +# above for --retain-branch-depth=stable=-1 +reinitialize_datesnap_repo +${CMD_PREFIX} ostree --repo=repo prune --only-branch=stable --keep-younger-than="1 week ago" +assert_repo_has_n_commits repo 11 +echo "ok --only-branch --keep-younger-than" + +# Test --only-branch with a nonexistent ref +reinitialize_datesnap_repo +if ${CMD_PREFIX} ostree --repo=repo prune --only-branch=BACON 2>err.txt; then + fatal "we pruned BACON?" +fi +assert_file_has_content err.txt "Refspec.*BACON.*not found" +echo "ok --only-branch=BACON" diff -Nru ostree-2017.11/tests/test-pull-c.c ostree-2017.12/tests/test-pull-c.c --- ostree-2017.11/tests/test-pull-c.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-pull-c.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-repo.c ostree-2017.12/tests/test-repo.c --- ostree-2017.11/tests/test-repo.c 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/tests/test-repo.c 2017-10-02 16:43:45.000000000 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright © 2017 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. + * + * Authors: + * - Philip Withnall + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "ostree-autocleanups.h" +#include "ostree-types.h" + +/* Test fixture. Creates a temporary directory. */ +typedef struct +{ + GLnxTmpDir tmpdir; /* (owned) */ +} Fixture; + +static void +setup (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + + (void) glnx_mkdtemp ("test-repo-XXXXXX", 0700, &fixture->tmpdir, &error); + g_assert_no_error (error); + + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); +} + +static void +teardown (Fixture *fixture, + gconstpointer test_data) +{ + /* Recursively remove the temporary directory. */ + (void) glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); +} + +/* Test that the hash values for two #OstreeRepo instances pointing at the same + * repository are equal. We can’t test anything else, since hash collisions are + * always a possibility. */ +static void +test_repo_hash (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, ".", + OSTREE_REPO_MODE_ARCHIVE, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo2 = ostree_repo_open_at (fixture->tmpdir.fd, ".", + NULL, &error); + g_assert_no_error (error); + + g_assert_cmpuint (ostree_repo_hash (repo1), ==, ostree_repo_hash (repo2)); +} + +/* Test that trying to hash a closed repo results in an assertion failure. */ +static void +test_repo_hash_closed (Fixture *fixture, + gconstpointer test_data) +{ + if (g_test_subprocess ()) + { + g_autoptr(GFile) repo_path = g_file_new_for_path (fixture->tmpdir.path); + g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); + + ostree_repo_hash (repo); + + return; + } + + g_test_trap_subprocess (NULL, 0, 0); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*ERROR*ostree_repo_hash: assertion failed:*"); +} + +/* Test that various repositories test equal (or not) with each other. */ +static void +test_repo_equal (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(GError) error = NULL; + + /* Create a few separate repos and some #OstreeRepo objects for them. */ + glnx_ensure_dir (fixture->tmpdir.fd, "repo1", 0755, &error); + g_assert_no_error (error); + glnx_ensure_dir (fixture->tmpdir.fd, "repo2", 0755, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo1 = ostree_repo_create_at (fixture->tmpdir.fd, "repo1", + OSTREE_REPO_MODE_ARCHIVE, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo1_alias = ostree_repo_open_at (fixture->tmpdir.fd, "repo1", + NULL, &error); + g_assert_no_error (error); + + g_autoptr(OstreeRepo) repo2 = ostree_repo_create_at (fixture->tmpdir.fd, "repo2", + OSTREE_REPO_MODE_ARCHIVE, + NULL, + NULL, &error); + g_assert_no_error (error); + + g_autoptr(GFile) closed_repo_path = g_file_new_for_path (fixture->tmpdir.path); + g_autoptr(OstreeRepo) closed_repo = ostree_repo_new (closed_repo_path); + + /* Test various equalities. */ + g_assert_true (ostree_repo_equal (repo1, repo1)); + g_assert_true (ostree_repo_equal (repo1_alias, repo1_alias)); + g_assert_true (ostree_repo_equal (repo1, repo1_alias)); + g_assert_true (ostree_repo_equal (repo1_alias, repo1)); + g_assert_true (ostree_repo_equal (repo2, repo2)); + g_assert_false (ostree_repo_equal (repo1, repo2)); + g_assert_false (ostree_repo_equal (repo1_alias, repo2)); + g_assert_false (ostree_repo_equal (repo2, repo1)); + g_assert_false (ostree_repo_equal (repo2, repo1_alias)); + g_assert_false (ostree_repo_equal (repo1, closed_repo)); + g_assert_false (ostree_repo_equal (repo1_alias, closed_repo)); + g_assert_false (ostree_repo_equal (closed_repo, repo1)); + g_assert_false (ostree_repo_equal (closed_repo, repo1_alias)); + g_assert_false (ostree_repo_equal (repo2, closed_repo)); + g_assert_false (ostree_repo_equal (closed_repo, repo2)); + g_assert_false (ostree_repo_equal (closed_repo, closed_repo)); +} + +int +main (int argc, + char **argv) +{ + setlocale (LC_ALL, ""); + g_test_init (&argc, &argv, NULL); + + g_test_add ("/repo/hash", Fixture, NULL, setup, + test_repo_hash, teardown); + g_test_add ("/repo/hash/closed", Fixture, NULL, setup, + test_repo_hash_closed, teardown); + g_test_add ("/repo/equal", Fixture, NULL, setup, + test_repo_equal, teardown); + + return g_test_run (); +} diff -Nru ostree-2017.11/tests/test-repo-finder-avahi.c ostree-2017.12/tests/test-repo-finder-avahi.c --- ostree-2017.11/tests/test-repo-finder-avahi.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-repo-finder-avahi.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-repo-finder-config.c ostree-2017.12/tests/test-repo-finder-config.c --- ostree-2017.11/tests/test-repo-finder-config.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-repo-finder-config.c 2017-10-02 16:43:45.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or @@ -39,7 +38,7 @@ typedef struct { OstreeRepo *parent_repo; /* owned */ - int working_dfd; /* owned */ + GLnxTmpDir tmpdir; /* owned */ GFile *working_dir; /* owned */ } Fixture; @@ -47,20 +46,17 @@ setup (Fixture *fixture, gconstpointer test_data) { - g_autofree gchar *tmp_name = NULL; g_autoptr(GError) error = NULL; - tmp_name = g_strdup ("test-repo-finder-config-XXXXXX"); - glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error); + (void)glnx_mkdtemp ("test-repo-finder-config-XXXXXX", 0700, &fixture->tmpdir, &error); g_assert_no_error (error); - g_test_message ("Using temporary directory: %s", tmp_name); + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); - glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, "repo", 0700, NULL, &error); g_assert_no_error (error); - g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ()); - fixture->working_dir = g_file_get_child (tmp_dir, tmp_name); + fixture->working_dir = g_file_new_for_path (fixture->tmpdir.path); fixture->parent_repo = ot_test_setup_repo (NULL, &error); g_assert_no_error (error); @@ -73,10 +69,7 @@ g_autoptr(GError) error = NULL; /* Recursively remove the temporary directory. */ - glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL); - - close (fixture->working_dfd); - fixture->working_dfd = -1; + (void)glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); /* The repo also needs its source files to be removed. This is the inverse * of setup_test_repository() in libtest.sh. */ @@ -177,14 +170,14 @@ g_autoptr(GError) error = NULL; const gchar *repo_name = (collection_id != NULL) ? collection_id : "no-collection"; - glnx_shutil_mkdir_p_at (fixture->working_dfd, repo_name, 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, repo_name, 0700, NULL, &error); g_assert_no_error (error); g_autoptr(GFile) repo_path = g_file_get_child (fixture->working_dir, repo_name); g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path); ostree_repo_set_collection_id (repo, collection_id, &error); g_assert_no_error (error); - ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error); + ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE, NULL, &error); g_assert_no_error (error); /* Set up the refs from @.... */ diff -Nru ostree-2017.11/tests/test-repo-finder-mount.c ostree-2017.12/tests/test-repo-finder-mount.c --- ostree-2017.11/tests/test-repo-finder-mount.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-repo-finder-mount.c 2017-10-02 16:43:45.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright © 2017 Endless Mobile, Inc. * * This library is free software; you can redistribute it and/or @@ -40,30 +39,27 @@ typedef struct { OstreeRepo *parent_repo; - int working_dfd; /* owned */ - GFile *working_dir; /* owned */ + GLnxTmpDir tmpdir; /* owned */ + GFile *working_dir; /* Points at tmpdir */ } Fixture; static void setup (Fixture *fixture, gconstpointer test_data) { - g_autofree gchar *tmp_name = NULL; g_autoptr(GError) error = NULL; - tmp_name = g_strdup ("test-repo-finder-mount-XXXXXX"); - glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error); + (void)glnx_mkdtemp ("test-repo-finder-mount-XXXXXX", 0700, &fixture->tmpdir, &error); g_assert_no_error (error); - g_test_message ("Using temporary directory: %s", tmp_name); + g_test_message ("Using temporary directory: %s", fixture->tmpdir.path); - glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error); + glnx_shutil_mkdir_p_at (fixture->tmpdir.fd, "repo", 0700, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); - g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ()); - fixture->working_dir = g_file_get_child (tmp_dir, tmp_name); + fixture->working_dir = g_file_new_for_path (fixture->tmpdir.path); fixture->parent_repo = ot_test_setup_repo (NULL, &error); g_assert_no_error (error); @@ -73,13 +69,8 @@ teardown (Fixture *fixture, gconstpointer test_data) { - g_autoptr(GError) error = NULL; - /* Recursively remove the temporary directory. */ - glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL); - - close (fixture->working_dfd); - fixture->working_dfd = -1; + (void)glnx_tmpdir_delete (&fixture->tmpdir, NULL, NULL); /* The repo also needs its source files to be removed. This is the inverse * of setup_test_repository() in libtest.sh. */ @@ -156,7 +147,7 @@ g_main_context_pop_thread_default (context); } -/* Create a .ostree/repos directory under the given @mount_root, or abort. */ +/* Create a .ostree/repos.d directory under the given @mount_root, or abort. */ static gboolean assert_create_repos_dir (Fixture *fixture, const gchar *mount_root_name, @@ -166,8 +157,8 @@ glnx_fd_close int repos_dfd = -1; g_autoptr(GError) error = NULL; - g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos", NULL); - glnx_shutil_mkdir_p_at_open (fixture->working_dfd, path, 0700, &repos_dfd, NULL, &error); + g_autofree gchar *path = g_build_filename (mount_root_name, ".ostree", "repos.d", NULL); + glnx_shutil_mkdir_p_at_open (fixture->tmpdir.fd, path, 0700, &repos_dfd, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); @@ -191,7 +182,7 @@ g_autoptr(GError) error = NULL; g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_dir); - ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error); + ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE, NULL, &error); g_assert_no_error (error); /* Set up the refs from @.... */ @@ -233,22 +224,22 @@ } static OstreeRepo * -assert_create_repo_dir (Fixture *fixture, - int repos_dfd, - GMount *repos_mount, - const OstreeCollectionRef *ref, - gchar **out_uri, +assert_create_repo_dir (Fixture *fixture, + int repos_dfd, + GMount *repos_mount, + const char *repo_name, + gchar **out_uri, ...) G_GNUC_NULL_TERMINATED; -/* Create a @ref directory under the given @repos_dfd, or abort. Create a new - * repository in it with the refs given in @..., as per assert_create_remote_va(). - * Return the URI of the repository. */ +/* Create a @repo_name directory under the given @repos_dfd, or abort. Create a + * new repository in it with the refs given in @..., as per + * assert_create_remote_va(). Return the URI of the repository. */ static OstreeRepo * -assert_create_repo_dir (Fixture *fixture, - int repos_dfd, - GMount *repos_mount, - const OstreeCollectionRef *ref, - gchar **out_uri, +assert_create_repo_dir (Fixture *fixture, + int repos_dfd, + GMount *repos_mount, + const char *repo_name, + gchar **out_uri, ...) { glnx_fd_close int ref_dfd = -1; @@ -256,15 +247,14 @@ g_autoptr(GError) error = NULL; va_list args; - g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL); - glnx_shutil_mkdir_p_at_open (repos_dfd, path, 0700, &ref_dfd, NULL, &error); + glnx_shutil_mkdir_p_at_open (repos_dfd, repo_name, 0700, &ref_dfd, NULL, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) g_clear_error (&error); g_assert_no_error (error); g_autoptr(GFile) mount_root = g_mount_get_root (repos_mount); - g_autoptr(GFile) repos_dir = g_file_get_child (mount_root, ".ostree/repos"); - g_autoptr(GFile) repo_dir = g_file_get_child (repos_dir, path); + g_autoptr(GFile) repos_dir = g_file_get_child (mount_root, ".ostree/repos.d"); + g_autoptr(GFile) repo_dir = g_file_get_child (repos_dir, repo_name); va_start (args, out_uri); repo = assert_create_remote_va (fixture, repo_dir, args); @@ -275,38 +265,19 @@ return g_steal_pointer (&repo); } -/* Create a @ref symlink under the given @repos_dfd, pointing to - * @symlink_target, or abort. */ -static int -assert_create_repo_symlink (int repos_dfd, - const OstreeCollectionRef *ref, - const gchar *symlink_target_path) +/* Create a @repo_name symlink under the given @repos_dfd, pointing to + * @symlink_target_path, or abort. */ +static void +assert_create_repo_symlink (int repos_dfd, + const char *repo_name, + const char *symlink_target_path) { - glnx_fd_close int symlink_target_dfd = -1; - g_autoptr(GError) error = NULL; - - /* The @ref_parent_dir is not necessarily @collection_dir, since @ref may - * contain slashes. */ - g_autofree gchar *path = g_build_filename (ref->collection_id, ref->ref_name, NULL); - g_autofree gchar *path_parent = g_path_get_dirname (path); - - glnx_shutil_mkdir_p_at (repos_dfd, path_parent, 0700, NULL, &error); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS)) - g_clear_error (&error); - g_assert_no_error (error); - - if (TEMP_FAILURE_RETRY (symlinkat (symlink_target_path, repos_dfd, path)) != 0) + if (TEMP_FAILURE_RETRY (symlinkat (symlink_target_path, repos_dfd, repo_name)) != 0) { g_autoptr(GError) error = NULL; glnx_throw_errno_prefix (&error, "symlinkat"); g_assert_no_error (error); } - - /* Return a dir FD for the symlink target. */ - glnx_opendirat (repos_dfd, path, TRUE, &symlink_target_dfd, &error); - g_assert_no_error (error); - - return glnx_steal_fd (&symlink_target_dfd); } /* Add configuration for a remote named @remote_name, at @remote_uri, with a @@ -356,7 +327,7 @@ g_autofree gchar *repo2_repo_a_uri = NULL; g_autofree gchar *repo1_ref0_checksum = NULL, *repo1_ref1_checksum = NULL, *repo1_ref2_checksum = NULL; g_autofree gchar *repo2_ref0_checksum = NULL, *repo2_ref1_checksum = NULL, *repo2_ref2_checksum = NULL; - g_autofree gchar *repo1_ref5_checksum = NULL; + g_autofree gchar *repo1_ref5_checksum = NULL, *repo2_ref3_checksum = NULL; gsize i; const OstreeCollectionRef ref0 = { "org.example.Collection1", "exampleos/x86_64/ref0" }; const OstreeCollectionRef ref1 = { "org.example.Collection1", "exampleos/x86_64/ref1" }; @@ -379,27 +350,26 @@ assert_create_repos_dir (fixture, "no-repos-mount", &no_repos_repos, &no_repos_mount); assert_create_repos_dir (fixture, "repo1-mount", &repo1_repos, &repo1_mount); - repo1_repo_a = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[0], &repo1_repo_a_uri, + repo1_repo_a = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, "repo1-repo-a", &repo1_repo_a_uri, refs[0], &repo1_ref0_checksum, refs[2], &repo1_ref2_checksum, refs[5], &repo1_ref5_checksum, NULL); - repo1_repo_b = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, refs[1], &repo1_repo_b_uri, + repo1_repo_b = assert_create_repo_dir (fixture, repo1_repos, repo1_mount, "repo1-repo-b", &repo1_repo_b_uri, refs[1], &repo1_ref1_checksum, NULL); - assert_create_repo_symlink (repo1_repos, refs[2], "ref0"); /* repo1_repo_a */ - assert_create_repo_symlink (repo1_repos, refs[5], "../../../org.example.Collection1/exampleos/x86_64/ref0"); /* repo1_repo_a */ + assert_create_repo_symlink (repo1_repos, "repo1-repo-a-alias", "repo1-repo-a"); assert_create_repos_dir (fixture, "repo2-mount", &repo2_repos, &repo2_mount); - repo2_repo_a = assert_create_repo_dir (fixture, repo2_repos, repo2_mount, refs[0], &repo2_repo_a_uri, + repo2_repo_a = assert_create_repo_dir (fixture, repo2_repos, repo2_mount, "repo2-repo-a", &repo2_repo_a_uri, refs[0], &repo2_ref0_checksum, refs[1], &repo2_ref1_checksum, refs[2], &repo2_ref2_checksum, - refs[3], NULL, + refs[3], &repo2_ref3_checksum, NULL); - assert_create_repo_symlink (repo2_repos, refs[1], "ref0"); /* repo2_repo_a */ - assert_create_repo_symlink (repo2_repos, refs[2], "ref1"); /* repo2_repo_b */ - assert_create_repo_symlink (repo2_repos, refs[3], "/"); + assert_create_repo_symlink (repo2_repos, "repo2-repo-a-alias", "repo2-repo-a"); + assert_create_repo_symlink (repo2_repos, "dangling-symlink", "repo2-repo-b"); + assert_create_repo_symlink (repo2_repos, "root", "/"); mounts = g_list_prepend (mounts, non_removable_mount); mounts = g_list_prepend (mounts, no_repos_mount); @@ -462,10 +432,108 @@ else if (g_strcmp0 (uri, repo2_repo_a_uri) == 0 && g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0) { - g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 3); + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 4); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[0]), ==, repo2_ref0_checksum); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[1]), ==, repo2_ref1_checksum); g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[2]), ==, repo2_ref2_checksum); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, refs[3]), ==, repo2_ref3_checksum); + } + else + { + g_test_message ("Unknown result ‘%s’ with keyring ‘%s’.", + result->remote->name, result->remote->keyring); + g_assert_not_reached (); + } + } + + g_main_context_pop_thread_default (context); +} + +/* Test resolving the refs against a mock volume which contains two repositories + * in the default repository paths ostree/repo and .ostree/repo, to check that + * those paths are read */ +static void +test_repo_finder_mount_well_known (Fixture *fixture, + gconstpointer test_data) +{ + g_autoptr(OstreeRepoFinderMount) finder = NULL; + g_autoptr(GVolumeMonitor) monitor = NULL; + g_autoptr(GMainContext) context = NULL; + g_autoptr(GAsyncResult) result = NULL; + g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */ + g_autoptr(GError) error = NULL; + g_autoptr(GList) mounts = NULL; /* (element-type OstreeMockMount) */ + g_autoptr(GMount) mount = NULL; + glnx_fd_close int repos = -1; + g_autoptr(OstreeRepo) repo_a = NULL, repo_b = NULL; + g_autofree gchar *repo_a_uri = NULL, *repo_b_uri = NULL; + g_autofree gchar *ref_a_checksum = NULL, *ref_b_checksum = NULL; + gsize i; + const OstreeCollectionRef ref_a = { "org.example.Collection1", "refA" }; + const OstreeCollectionRef ref_b = { "org.example.Collection2", "refB" }; + const OstreeCollectionRef * const refs[] = { &ref_a, &ref_b, NULL }; + + context = g_main_context_new (); + g_main_context_push_thread_default (context); + + /* Build the various mock drives/volumes/mounts, and some repositories with + * refs within them. We use "/" under the assumption that it’s on a separate + * file system from /tmp, so it’s an example of a symlink pointing outside + * its mount point. */ + assert_create_repos_dir (fixture, "mount", &repos, &mount); + repo_a = assert_create_repo_dir (fixture, repos, mount, "../../ostree/repo", &repo_a_uri, + &ref_a, &ref_a_checksum, + NULL); + repo_b = assert_create_repo_dir (fixture, repos, mount, "../../.ostree/repo", &repo_b_uri, + &ref_b, &ref_b_checksum, + NULL); + assert_create_repo_symlink (repos, "repo-a-alias", "../../ostree/repo"); + + mounts = g_list_prepend (mounts, mount); + + monitor = ostree_mock_volume_monitor_new (mounts, NULL); + finder = ostree_repo_finder_mount_new (monitor); + + assert_create_remote_config (fixture->parent_repo, "remote1", "https://nope1", "org.example.Collection1"); + assert_create_remote_config (fixture->parent_repo, "remote2", "https://nope2", "org.example.Collection2"); + + /* Resolve the refs. */ + ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs, + fixture->parent_repo, + NULL, result_cb, &result); + + while (result == NULL) + g_main_context_iteration (context, TRUE); + + results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder), + result, &error); + g_assert_no_error (error); + g_assert_nonnull (results); + g_assert_cmpuint (results->len, ==, 2); + + /* Check that the results are correct: the valid results canonicalised and + * deduplicated. */ + for (i = 0; i < results->len; i++) + { + g_autofree gchar *uri = NULL; + const gchar *keyring; + const OstreeRepoFinderResult *result = g_ptr_array_index (results, i); + + uri = g_key_file_get_string (result->remote->options, result->remote->group, "url", &error); + g_assert_no_error (error); + keyring = result->remote->keyring; + + if (g_strcmp0 (uri, repo_a_uri) == 0 && + g_strcmp0 (keyring, "remote1.trustedkeys.gpg") == 0) + { + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, &ref_a), ==, ref_a_checksum); + } + else if (g_strcmp0 (uri, repo_b_uri) == 0 && + g_strcmp0 (keyring, "remote2.trustedkeys.gpg") == 0) + { + g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1); + g_assert_cmpstr (g_hash_table_lookup (result->ref_to_checksum, &ref_b), ==, ref_b_checksum); } else { @@ -488,6 +556,8 @@ test_repo_finder_mount_no_mounts, teardown); g_test_add ("/repo-finder-mount/mixed-mounts", Fixture, NULL, setup, test_repo_finder_mount_mixed_mounts, teardown); + g_test_add ("/repo-finder-mount/well-known", Fixture, NULL, setup, + test_repo_finder_mount_well_known, teardown); return g_test_run(); } diff -Nru ostree-2017.11/tests/test-repo-finder-mount-integration.sh ostree-2017.12/tests/test-repo-finder-mount-integration.sh --- ostree-2017.11/tests/test-repo-finder-mount-integration.sh 1970-01-01 00:00:00.000000000 +0000 +++ ostree-2017.12/tests/test-repo-finder-mount-integration.sh 2017-10-02 16:43:45.000000000 +0000 @@ -0,0 +1,131 @@ +#!/bin/bash +# +# Copyright © 2017 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. +# +# Authors: +# - Philip Withnall + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +SUDO="sudo --non-interactive" + +# Skip the test if a well-known USB stick is not available. +# To run the test, you must have a throwaway partition on a USB stick (doesn’t +# matter how it’s formatted, as the test will reformat it), and must set +# MOUNT_INTEGRATION_DEV to that partition. For example, +# MOUNT_INTEGRATION_DEV=/dev/sdb1. For safety, the test will be skipped if the +# partition is already mounted. +# +# FIXME: We could potentially automate this in future if there’s a way to trick +# GIO into treating an arbitrary partition (such as a loopback device of our +# creation) as removable. + +if ! [ -b "${MOUNT_INTEGRATION_DEV:-}" ]; then + skip "Test needs a disposable USB stick passed in as MOUNT_INTEGRATION_DEV" +fi + +# Sanity check that the given device is not already mounted, to try and avoid +# hosing the system. +if mount | grep -q "${MOUNT_INTEGRATION_DEV}"; then + skip "${MOUNT_INTEGRATION_DEV} must not be mounted already" +fi + +_mount_cleanup () { + ${SUDO} umount "${MOUNT_INTEGRATION_DEV}" || true +} + +case "${TEST_SKIP_CLEANUP:-}" in + no|"") + trap _mount_cleanup EXIT + ;; + err) + trap _mount_cleanup ERR + ;; +esac + +echo "1..3" + +cd ${test_tmpdir} +mkdir repo +ostree_repo_init repo --collection-id org.example.Collection1 + +mkdir -p tree/root +touch tree/root/a + +# Add a few commits +seq 5 | while read i; do + echo a >> tree/root/a + ${CMD_PREFIX} ostree --repo=repo commit --branch=test-$i -m test -s test --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" tree +done + +${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" +${CMD_PREFIX} ostree --repo=repo rev-parse test-1 > ref1-checksum + +# Pull into a ‘local’ repository, to more accurately represent the situation of +# creating a USB stick from your local machine. +mkdir local-repo +ostree_repo_init local-repo +${CMD_PREFIX} ostree --repo=local-repo remote add remote1 file://$(pwd)/repo --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" +${CMD_PREFIX} ostree --repo=local-repo pull remote1 test-1 test-2 test-3 test-4 test-5 + +for fs_type in ext4 vfat; do + # Prepare a USB stick containing some of the refs on the given file system. + if [ "$fs_type" = "ext4" ]; then + fs_options="-F -E root_owner=$(id -u):$(id -g)" + else + fs_options= + fi + ${SUDO} mkfs.$fs_type $fs_options "${MOUNT_INTEGRATION_DEV}" > /dev/null + usb_mount=$(udisksctl mount --block-device "${MOUNT_INTEGRATION_DEV}" --filesystem-type $fs_type | sed -n "s/^Mounted .* at \(.*\)\.$/\1/p") + + ${CMD_PREFIX} ostree --repo=local-repo create-usb "${usb_mount}" org.example.Collection1 test-1 org.example.Collection1 test-2 + + assert_has_dir "${usb_mount}"/.ostree/repo + ${CMD_PREFIX} ostree --repo="${usb_mount}"/.ostree/repo refs --collections > dest-refs + assert_file_has_content dest-refs "^(org.example.Collection1, test-1)$" + assert_file_has_content dest-refs "^(org.example.Collection1, test-2)$" + assert_not_file_has_content dest-refs "^(org.example.Collection1, test-3)$" + assert_has_file "${usb_mount}"/.ostree/repo/summary + + # Pull into a second local repository (theoretically, a separate computer). + mkdir peer-repo_$fs_type + ostree_repo_init peer-repo_$fs_type + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type remote add remote1 file://just-here-for-the-keyring --collection-id org.example.Collection1 --gpg-import="${test_tmpdir}/gpghome/key1.asc" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes org.example.Collection1 test-1 > find-results + assert_not_file_has_content find-results "^No results.$" + assert_file_has_content find-results "^Result 0: file://${usb_mount}" + assert_file_has_content find-results "(org.example.Collection1, test-1) = $(cat ref1-checksum)$" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type find-remotes --pull org.example.Collection1 test-1 > pull-results + assert_file_has_content pull-results "^Pulled 1/1 refs successfully.$" + + ${CMD_PREFIX} ostree --repo=peer-repo_$fs_type refs --collections > refs + assert_file_has_content refs "^(org.example.Collection1, test-1)$" + + ${SUDO} umount "${MOUNT_INTEGRATION_DEV}" + + echo "ok end-to-end USB on ${fs_type}" +done + +# Check the two repositories are identical. +diff -ur peer-repo_ext4 peer-repo_vfat + +echo "ok end-to-end USB repositories are identical" diff -Nru ostree-2017.11/tests/test-rofiles-fuse.sh ostree-2017.12/tests/test-rofiles-fuse.sh --- ostree-2017.11/tests/test-rofiles-fuse.sh 2017-09-13 19:47:50.000000000 +0000 +++ ostree-2017.12/tests/test-rofiles-fuse.sh 2017-10-01 17:38:12.000000000 +0000 @@ -26,7 +26,7 @@ setup_test_repository "bare" -echo "1..7" +echo "1..8" cd ${test_tmpdir} mkdir mnt @@ -114,3 +114,6 @@ assert_file_has_content err.txt "Unable to do hardlink checkout across devices" echo "ok checkout copy fallback" + +# check that O_RDONLY|O_CREAT is handled correctly; used by flock(1) at least +flock mnt/nonexistent-file echo "ok create file in ro mode" diff -Nru ostree-2017.11/tests/test-rollsum.c ostree-2017.12/tests/test-rollsum.c --- ostree-2017.11/tests/test-rollsum.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-rollsum.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2015 Red Hat, Inc. * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-rollsum-cli.c ostree-2017.12/tests/test-rollsum-cli.c --- ostree-2017.11/tests/test-rollsum-cli.c 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-rollsum-cli.c 2017-10-01 17:38:12.000000000 +0000 @@ -1,5 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * +/* * Copyright (C) 2013 Colin Walters * * This library is free software; you can redistribute it and/or diff -Nru ostree-2017.11/tests/test-summary-update.sh ostree-2017.12/tests/test-summary-update.sh --- ostree-2017.11/tests/test-summary-update.sh 2017-09-07 19:48:17.000000000 +0000 +++ ostree-2017.12/tests/test-summary-update.sh 2017-10-02 16:54:23.000000000 +0000 @@ -91,4 +91,23 @@ ${CMD_PREFIX} ostree --repo=repo summary --view > summary assert_file_has_content summary "^map: {}$" +# Check the ostree-metadata ref has also been created with the same content and appropriate bindings. +${CMD_PREFIX} ostree --repo=repo refs --collections > refs +assert_file_has_content refs "^(org.example.Collection1, ostree-metadata)$" + +${CMD_PREFIX} ostree --repo=repo show ostree-metadata --raw > metadata +assert_file_has_content metadata "'map': <@a{sv} {}>" +assert_file_has_content metadata "'ostree.ref-binding': <\['ostree-metadata'\]>" +assert_file_has_content metadata "'ostree.collection-binding': <'org.example.Collection1'>" + +# There should be 5 commits in the ostree-metadata branch, since we’ve updated the summary 5 times. +${CMD_PREFIX} ostree --repo=repo log ostree-metadata | grep 'commit ' | wc -l > commit-count +assert_file_has_content commit-count "^5$" + +# The ostree-metadata commits should not contain any files +${CMD_PREFIX} ostree --repo=repo ls ostree-metadata > files +assert_file_has_content files " /$" +cat files | wc -l > files-count +assert_file_has_content files-count "^1$" + echo "ok 2 update summary with collections" diff -Nru ostree-2017.11/tests/test-symbols.sh ostree-2017.12/tests/test-symbols.sh --- ostree-2017.11/tests/test-symbols.sh 2017-09-14 15:27:57.000000000 +0000 +++ ostree-2017.12/tests/test-symbols.sh 2017-10-02 16:54:23.000000000 +0000 @@ -52,7 +52,7 @@ # ONLY update this checksum in release commits! cat > released-sha256.txt < * * This library is free software; you can redistribute it and/or