From f72726c7d88b6640e6cebb974f907aa585aab074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Fri, 10 Mar 2017 22:24:57 +0100 Subject: [PATCH 01/56] Avoid unnecessary includes "return" will do the same here. Also that style is used at the end of the function. Closes: #732 Approved by: jlebon --- tests/test-rollsum-cli.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test-rollsum-cli.c b/tests/test-rollsum-cli.c index 4f24477c..a00e4b73 100644 --- a/tests/test-rollsum-cli.c +++ b/tests/test-rollsum-cli.c @@ -21,8 +21,6 @@ #include "config.h" #include "ostree-rollsum.h" -#include -#include int main (int argc, char **argv) @@ -39,7 +37,7 @@ main (int argc, char **argv) g_setenv ("GIO_USE_VFS", "local", TRUE); if (argc < 3) - exit (EXIT_FAILURE); + return 1; from_path = argv[1]; to_path = argv[2]; From 75907cb51351cef76d4c8d29374190e21710e767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Fri, 10 Mar 2017 22:01:21 +0100 Subject: [PATCH 02/56] Fix includes if built against musl LOCK_* is defined in sys/file.h http://git.musl-libc.org/cgit/musl/tree/include/sys/file.h Closes: #730 Approved by: cgwalters --- src/libostree/ostree-repo.c | 1 + src/libostree/ostree-sysroot.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 71604480..0f1c3631 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -42,6 +42,7 @@ #include #include +#include /** * SECTION:ostree-repo diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index f50e34bd..4ed0d759 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -21,6 +21,7 @@ #include "config.h" #include "otutil.h" +#include #include #include From fda4a47cae26733e80952b70ad27a0891e20d6c5 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Fri, 10 Mar 2017 14:33:52 -0300 Subject: [PATCH 03/56] libostree: add versioning macros OSTree currently provides no way to inspect the versioning information at run time, being only available at compile time through pkg-config. This is a problem for e.g. Flatpak, that needs to check whether the 'update-frequency' option is available. Checking at compile time isn't great since it's not looking for new symbols, but only if an optional feature is present. This commit, then, adds a new header that is generated at compile time, exposing OSTree's versioning information. Closes: #728 Approved by: cgwalters --- Makefile-libostree-defines.am | 4 ++ Makefile-libostree.am | 5 +- Makefile-ostree.am | 2 +- apidoc/Makefile.am | 2 +- configure.ac | 12 ++++- src/libostree/ostree-version.h.in | 82 +++++++++++++++++++++++++++++++ src/libostree/ostree.h | 1 + 7 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 src/libostree/ostree-version.h.in diff --git a/Makefile-libostree-defines.am b/Makefile-libostree-defines.am index e3ec3950..1531cf8c 100644 --- a/Makefile-libostree-defines.am +++ b/Makefile-libostree-defines.am @@ -37,3 +37,7 @@ libostree_public_headers = \ src/libostree/ostree-bootconfig-parser.h \ src/libostree/ostree-repo-deprecated.h \ $(NULL) + +# This one is generated via configure.ac, and the gtk-doc +# code hence needs to look in the builddir. +libostree_public_built_headers = src/libostree/ostree-version.h diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 70452f1a..901208a2 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -44,7 +44,7 @@ libostree_kernel_args_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) lib_LTLIBRARIES += libostree-1.la libostreeincludedir = $(includedir)/ostree-1 -libostreeinclude_HEADERS = $(libostree_public_headers) +libostreeinclude_HEADERS = $(libostree_public_headers) $(libostree_public_built_headers) ENUM_TYPES = $(NULL) ENUM_TYPES += $(srcdir)/src/libostree/ostree-fetcher.h @@ -225,7 +225,8 @@ EXTRA_DIST += src/libostree/README-gpg src/libostree/bupsplit.h \ src/libostree/ostree-enumtypes.h.template \ src/libostree/ostree-enumtypes.c.template \ src/libostree/ostree-deployment-private.h \ - src/libostree/ostree-repo-deprecated.h + src/libostree/ostree-repo-deprecated.h \ + src/libostree/ostree-version.h install-mkdir-remotes-d-hook: mkdir -p $(DESTDIR)$(sysconfdir)/ostree/remotes.d diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 0b520c68..4bd623d7 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -105,7 +105,7 @@ EXTRA_DIST += src/ostree/parse-datetime.y CLEANFILES += src/ostree/parse-datetime.c ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree \ - -I$(srcdir)/src/ostree -I$(srcdir)/libglnx $(OT_INTERNAL_GIO_UNIX_CFLAGS) \ + -I$(builddir)/src/libostree -I$(srcdir)/src/ostree -I$(srcdir)/libglnx $(OT_INTERNAL_GIO_UNIX_CFLAGS) \ -DPKGLIBEXECDIR=\"$(pkglibexecdir)\" ostree_bin_shared_ldadd = $(AM_LDFLAGS) libglnx.la libotutil.la libostree-1.la \ $(OT_INTERNAL_GIO_UNIX_LIBS) diff --git a/apidoc/Makefile.am b/apidoc/Makefile.am index baa7207a..730a4c33 100644 --- a/apidoc/Makefile.am +++ b/apidoc/Makefile.am @@ -60,7 +60,7 @@ FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c -HFILE_GLOB=$(addprefix $(top_srcdir)/,$(libostree_public_headers)) +HFILE_GLOB=$(addprefix $(top_srcdir)/,$(libostree_public_headers)) $(addprefix $(top_builddir)/,$(libostree_public_built_headers)) CFILE_GLOB=$(top_srcdir)/src/libostree/*.c # Header files to ignore when scanning. diff --git a/configure.ac b/configure.ac index 08894480..64f1fa4b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,10 @@ AC_PREREQ([2.63]) dnl If incrementing the version here, remember to update libostree.sym too -AC_INIT([libostree], [2017.3], [walters@verbum.org]) +m4_define([year_version], [2017]) +m4_define([release_version], [3]) +m4_define([package_version], [year_version.release_version]) + +AC_INIT([libostree], [package_version], [walters@verbum.org]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) @@ -16,6 +20,11 @@ AC_PROG_CC AM_PROG_CC_C_O AC_PROG_YACC +dnl Versioning information +AC_SUBST([YEAR_VERSION], [year_version]) +AC_SUBST([RELEASE_VERSION], [release_version]) +AC_SUBST([PACKAGE_VERSION], [package_version]) + CC_CHECK_FLAGS_APPEND([WARN_CFLAGS], [CFLAGS], [\ -pipe \ -Wall \ @@ -398,6 +407,7 @@ AC_CONFIG_FILES([ Makefile apidoc/Makefile src/libostree/ostree-1.pc +src/libostree/ostree-version.h ]) AC_OUTPUT diff --git a/src/libostree/ostree-version.h.in b/src/libostree/ostree-version.h.in new file mode 100644 index 00000000..8a4776d8 --- /dev/null +++ b/src/libostree/ostree-version.h.in @@ -0,0 +1,82 @@ +/* -*- 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 + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the licence 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 + +/** + * SECTION:ostree-version + * @short_description: ostree version checking + * + * ostree provides macros to check the version of the library + * at compile-time + */ + +/** + * OSTREE_YEAR_VERSION: + * + * ostree year version component (e.g. 2017 if %OSTREE_VERSION is 2017.2) + */ +#define OSTREE_YEAR_VERSION (@YEAR_VERSION@) + +/** + * OSTREE_RELEASE_VERSION: + * + * ostree release version component (e.g. 2 if %OSTREE_VERSION is 2017.2) + */ +#define OSTREE_RELEASE_VERSION (@RELEASE_VERSION@) + +/** + * OSTREE_VERSION + * + * ostree version. + */ +#define OSTREE_VERSION (@VERSION@) + +/** + * OSTREE_VERSION_S: + * + * ostree version, encoded as a string, useful for printing and + * concatenation. + */ +#define OSTREE_VERSION_S "@VERSION@" + +#define OSTREE_ENCODE_VERSION(year,release) \ + ((year) << 16 | (release)) + +/** + * OSTREE_VERSION_HEX: + * + * ostree version, encoded as an hexadecimal number, useful for + * integer comparisons. + */ +#define OSTREE_VERSION_HEX \ + (OSTREE_ENCODE_VERSION (OSTREE_YEAR_VERSION, OSTREE_RELEASE_VERSION)) + +/** + * OSTREE_CHECK_VERSION: + * @year: required year version + * @release: required release version + * + * Compile-time version checking. Evaluates to %TRUE if the version + * of ostree is equal or greater than the required one. + */ +#define OSTREE_CHECK_VERSION(year,release) \ + (OSTREE_YEAR_VERSION >= (year) || \ + (OSTREE_YEAR_VERSION == (year) && OSTREE_RELEASE_VERSION >= (release))) diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h index 9846a7e3..eb4ed8d3 100644 --- a/src/libostree/ostree.h +++ b/src/libostree/ostree.h @@ -33,3 +33,4 @@ #include #include +#include From b825aac0ead84c28108e647abb2e444d1492bcf0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 7 Mar 2017 17:32:50 -0500 Subject: [PATCH 04/56] Disable "ostree trivial-httpd" by default now This goes farther along the path of deprecating it; consumers should have been ported at this point. Though probably a lot of people may still use `rpm-ostree-toolbox`. Closes: #723 Approved by: jlebon --- configure.ac | 9 +++++++++ src/ostree/main.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 64f1fa4b..be1e0e13 100644 --- a/configure.ac +++ b/configure.ac @@ -143,6 +143,14 @@ if test x$with_soup != xno; then OSTREE_FEATURES="$OSTREE_FEATURES libsoup"; fi AM_CONDITIONAL(USE_LIBSOUP, test x$with_soup != xno) AM_CONDITIONAL(HAVE_LIBSOUP_CLIENT_CERTS, test x$have_libsoup_client_certs = xyes) +AC_ARG_ENABLE(trivial-httpd-cmdline, + [AS_HELP_STRING([--enable-trivial-httpd-cmdline], + [Continue to support "ostree trivial-httpd" [default=no]])],, + enable_trivial_httpd_cmdline=no) +AS_IF([test x$enable_trivial_httpd_cmdline = xyes], + [AC_DEFINE([BUILDOPT_ENABLE_TRIVIAL_HTTPD_CMDLINE], 1, [Define if we are enabling ostree trivial-httpd entrypoint])] +) + AS_IF([test x$with_curl = xyes && test x$with_soup = xno], [ AC_MSG_ERROR([Curl enabled, but libsoup is not; libsoup is needed for tests]) ]) @@ -420,6 +428,7 @@ echo " Rust (internal oxidation): $rust_debug_release rofiles-fuse: $enable_rofiles_fuse HTTP backend: $fetcher_backend + \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux systemd: $have_libsystemd libmount: $with_libmount diff --git a/src/ostree/main.c b/src/ostree/main.c index eff3082d..c6dee4ee 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -58,7 +58,7 @@ static OstreeCommand commands[] = { { "show", ostree_builtin_show }, { "static-delta", ostree_builtin_static_delta }, { "summary", ostree_builtin_summary }, -#ifdef HAVE_LIBSOUP +#if defined(HAVE_LIBSOUP) && defined(BUILDOPT_ENABLE_TRIVIAL_HTTPD_CMDLINE) { "trivial-httpd", ostree_builtin_trivial_httpd }, #endif { NULL } From 46001f4a5bff67f356407c51b4e2b29117565bb1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 13 Mar 2017 09:45:51 -0400 Subject: [PATCH 05/56] core: Add runtime ostree_check_version() [Previously](https://github.com/ostreedev/ostree/pull/728) we added compile-time checking for versions, but there are use cases for runtime checking as well, because in a number of API calls we use `GVariant` as an API extension mechanism. Closes: #735 Approved by: jlebon --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree.sym | 8 +++----- src/libostree/ostree-core.c | 13 +++++++++++++ src/libostree/ostree-core.h | 3 +++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 787664b3..cba6ec46 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -133,6 +133,7 @@ ostree_validate_structureof_dirtree ostree_validate_structureof_dirmeta ostree_commit_get_parent ostree_commit_get_timestamp +ostree_check_version
diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index b7cfc454..9067a26c 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -386,12 +386,10 @@ global: * NOTE NOTE NOTE */ -/* Stub section for new version, uncomment when the first symbol is added -LIBOSTREE_2017.$NEWVERSION { +LIBOSTREE_2017.4 { global: - someostree_symbol_deleteme; -} LIBOSTREE_2017.2; -*/ + ostree_check_version; +} LIBOSTREE_2017.3; /* 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 --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index cf238b41..db03c034 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -2153,3 +2153,16 @@ _ostree_get_default_sysroot_path (void) return default_sysroot_path; } + +/** + * ostree_check_version: + * @required_year: Major/year required + * @required_release: Release version required + * + * Returns: %TRUE if current libostree has at least the requested version, %FALSE otherwise + */ +gboolean +ostree_check_version (guint required_year, guint required_release) +{ + return OSTREE_CHECK_VERSION(required_year, required_release); +} diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index bd3d5f2c..bcade9db 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -399,4 +399,7 @@ gchar * ostree_commit_get_parent (GVariant *commit_variant); _OSTREE_PUBLIC guint64 ostree_commit_get_timestamp (GVariant *commit_variant); +_OSTREE_PUBLIC +gboolean ostree_check_version (guint required_year, guint required_release); + G_END_DECLS From 943c6c36c706d155fd5e35bc8be05f9674e3c815 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 12 Mar 2017 20:53:28 -0400 Subject: [PATCH 06/56] builtin/show: Convert to direct return/decl-after-stmt style I just happened to be reading this code; still testing the waters for the new code style. If we decide to do more of this it's likely worth trying out a [Coccinelle](http://coccinelle.lip6.fr/) patch or something. Closes: #733 Approved by: jlebon --- src/ostree/ot-builtin-show.c | 142 +++++++++++++---------------------- 1 file changed, 52 insertions(+), 90 deletions(-) diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index 6c45002a..3aaa2303 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -52,17 +52,13 @@ do_print_variant_generic (const GVariantType *type, const char *filename, GError **error) { - gboolean ret = FALSE; g_autoptr(GVariant) variant = NULL; if (!ot_util_variant_map_at (AT_FDCWD, filename, type, TRUE, &variant, error)) - goto out; + return FALSE; ot_dump_variant (variant); - - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -71,34 +67,23 @@ do_print_related (OstreeRepo *repo, const char *resolved_rev, GError **error) { - gboolean ret = FALSE; - const char *name; - g_autoptr(GVariant) csum_v = NULL; g_autoptr(GVariant) variant = NULL; - g_autoptr(GVariant) related = NULL; - GVariantIter *viter = NULL; - if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, resolved_rev, &variant, error)) - goto out; - - /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */ - related = g_variant_get_child_value (variant, 2); - - viter = g_variant_iter_new (related); + return FALSE; + /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */ + g_autoptr(GVariant) related = g_variant_get_child_value (variant, 2); + g_autoptr(GVariantIter) viter = g_variant_iter_new (related); + + const char *name; + GVariant* csum_v; while (g_variant_iter_loop (viter, "(&s@ay)", &name, &csum_v)) { g_autofree char *checksum = ostree_checksum_from_bytes_v (csum_v); g_print ("%s %s\n", name, checksum); } - csum_v = NULL; - - ret = TRUE; - out: - if (viter) - g_variant_iter_free (viter); - return ret; + return TRUE; } static gboolean @@ -108,8 +93,6 @@ do_print_metadata_key (OstreeRepo *repo, const char *key, GError **error) { - gboolean ret = FALSE; - g_autoptr(GVariant) value = NULL; g_autoptr(GVariant) commit = NULL; g_autoptr(GVariant) metadata = NULL; @@ -117,7 +100,7 @@ do_print_metadata_key (OstreeRepo *repo, { if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, resolved_rev, &commit, error)) - goto out; + return FALSE; /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */ metadata = g_variant_get_child_value (commit, 0); } @@ -125,28 +108,25 @@ do_print_metadata_key (OstreeRepo *repo, { if (!ostree_repo_read_commit_detached_metadata (repo, resolved_rev, &metadata, NULL, error)) - goto out; + return FALSE; if (metadata == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No detached metadata for commit %s", resolved_rev); - goto out; + return FALSE; } } - - value = g_variant_lookup_value (metadata, key, NULL); + + g_autoptr(GVariant) value = g_variant_lookup_value (metadata, key, NULL); if (!value) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No such metadata key '%s'", key); - goto out; + return FALSE; } ot_dump_variant (value); - - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -155,13 +135,12 @@ print_object (OstreeRepo *repo, const char *checksum, GError **error) { - g_autoptr(GVariant) variant = NULL; OstreeDumpFlags flags = OSTREE_DUMP_NONE; - gboolean ret = FALSE; + g_autoptr(GVariant) variant = NULL; if (!ostree_repo_load_variant (repo, objtype, checksum, &variant, error)) - goto out; + return FALSE; if (opt_raw) flags |= OSTREE_DUMP_RAW; ot_dump_object (objtype, checksum, variant, flags); @@ -169,7 +148,7 @@ print_object (OstreeRepo *repo, if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { glnx_unref_object OstreeGpgVerifyResult *result = NULL; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; g_autoptr(GFile) gpg_homedir = opt_gpg_homedir ? g_file_new_for_path (opt_gpg_homedir) : NULL; if (opt_gpg_verify_remote) @@ -186,24 +165,20 @@ print_object (OstreeRepo *repo, if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { - g_clear_error (&local_error); + /* Ignore */ } else if (local_error != NULL) { - g_propagate_error (error, local_error); - goto out; + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; } else { - GString *buffer; - guint n_sigs, ii; - - n_sigs = ostree_gpg_verify_result_count_all (result); + guint n_sigs = ostree_gpg_verify_result_count_all (result); g_print ("Found %u signature%s:\n", n_sigs, n_sigs == 1 ? "" : "s"); - buffer = g_string_sized_new (256); - - for (ii = 0; ii < n_sigs; ii++) + g_autoptr(GString) buffer = g_string_sized_new (256); + for (guint ii = 0; ii < n_sigs; ii++) { g_string_append_c (buffer, '\n'); ostree_gpg_verify_result_describe (result, ii, buffer, " ", @@ -211,13 +186,10 @@ print_object (OstreeRepo *repo, } g_print ("%s", buffer->str); - g_string_free (buffer, TRUE); } } - ret = TRUE; -out: - return ret; + return TRUE; } static gboolean @@ -228,7 +200,6 @@ print_if_found (OstreeRepo *repo, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; gboolean have_object = FALSE; if (*inout_was_found) @@ -236,62 +207,56 @@ print_if_found (OstreeRepo *repo, if (!ostree_repo_has_object (repo, objtype, checksum, &have_object, cancellable, error)) - goto out; + return FALSE; if (have_object) { if (!print_object (repo, objtype, checksum, error)) - goto out; + return FALSE; *inout_was_found = TRUE; } - - ret = TRUE; - out: - return ret; + + return TRUE; } gboolean ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError **error) { - g_autoptr(GOptionContext) context = NULL; + g_autoptr(GOptionContext) context = g_option_context_new ("OBJECT - Output a metadata object"); + glnx_unref_object OstreeRepo *repo = NULL; - gboolean ret = FALSE; - const char *rev; - g_autofree char *resolved_rev = NULL; - - context = g_option_context_new ("OBJECT - Output a metadata object"); - if (!ostree_option_context_parse (context, options, &argc, &argv, OSTREE_BUILTIN_FLAG_NONE, &repo, cancellable, error)) - goto out; + return FALSE; if (argc <= 1) { ot_util_usage_error (context, "An object argument is required", error); - goto out; + return FALSE; } - rev = argv[1]; + const char *rev = argv[1]; + g_autofree char *resolved_rev = NULL; if (opt_print_metadata_key || opt_print_detached_metadata_key) { gboolean detached = opt_print_detached_metadata_key != NULL; const char *key = detached ? opt_print_detached_metadata_key : opt_print_metadata_key; if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) - goto out; + return FALSE; if (!do_print_metadata_key (repo, resolved_rev, detached, key, error)) - goto out; + return FALSE; } else if (opt_print_related) { if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) - goto out; + return FALSE; if (!do_print_related (repo, rev, resolved_rev, error)) - goto out; + return FALSE; } else if (opt_print_variant_type) { if (!do_print_variant_generic (G_VARIANT_TYPE (opt_print_variant_type), rev, error)) - goto out; + return FALSE; } else { @@ -299,33 +264,32 @@ ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError ** if (!ostree_validate_checksum_string (rev, NULL)) { if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) - goto out; + return FALSE; if (!print_object (repo, OSTREE_OBJECT_TYPE_COMMIT, resolved_rev, error)) - goto out; + return FALSE; } else { if (!print_if_found (repo, OSTREE_OBJECT_TYPE_COMMIT, rev, &found, cancellable, error)) - goto out; + return FALSE; if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_META, rev, &found, cancellable, error)) - goto out; + return FALSE; if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_TREE, rev, &found, cancellable, error)) - goto out; + return FALSE; if (!found) { g_autoptr(GFileInfo) finfo = NULL; g_autoptr(GVariant) xattrs = NULL; - GFileType filetype; - + if (!ostree_repo_load_file (repo, rev, NULL, &finfo, &xattrs, cancellable, error)) - goto out; + return FALSE; g_print ("Object: %s\nType: %s\n", rev, ostree_object_type_to_string (OSTREE_OBJECT_TYPE_FILE)); - filetype = g_file_info_get_file_type (finfo); + GFileType filetype = g_file_info_get_file_type (finfo); g_print ("File Type: "); switch (filetype) { @@ -358,8 +322,6 @@ ostree_builtin_show (int argc, char **argv, GCancellable *cancellable, GError ** } } } - - ret = TRUE; - out: - return ret; + + return TRUE; } From 340144265f38e9b186f6f89b6ad46a5640f62f2f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 12 Mar 2017 20:56:28 -0400 Subject: [PATCH 07/56] pull: Squash a `-Wmaybe-uninitialized` warning Tempting to make it fatal...but we'd have to basically init all of our variables I think. Closes: #734 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 5ee43918..ec085a81 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1882,7 +1882,7 @@ get_best_static_delta_start_for (OtPullData *pull_data, /* Array of possible from checksums */ g_autoptr(GPtrArray) candidates = g_ptr_array_new_with_free_func (g_free); const char *newest_candidate = NULL; - guint64 newest_candidate_timestamp; + guint64 newest_candidate_timestamp = 0; g_assert (pull_data->summary_deltas_checksums != NULL); g_hash_table_iter_init (&hiter, pull_data->summary_deltas_checksums); @@ -1911,7 +1911,7 @@ get_best_static_delta_start_for (OtPullData *pull_data, for (guint i = 0; i < candidates->len; i++) { const char *candidate = candidates->pdata[i]; - guint64 candidate_ts; + guint64 candidate_ts = 0; g_autoptr(GVariant) commit = NULL; OstreeRepoCommitState state; gboolean have_candidate; From 741911d0fcb285401513f38bfb968b7942d763cf Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 12 Mar 2017 21:04:51 -0400 Subject: [PATCH 08/56] lib: Exclude soup header from introspection We should fix this more reliably by defining a separate variable for introspection (and gtk-doc) sources at some point, but this does the trick for now. Avoids a spam of warnings, and it's definitely not public API. Closes: #734 Approved by: jlebon --- Makefile-libostree.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 901208a2..15711dc9 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -209,7 +209,7 @@ OSTree_1_0_gir_INCLUDES = Gio-2.0 OSTree_1_0_gir_CFLAGS = $(libostree_1_la_CFLAGS) OSTree_1_0_gir_LIBS = libostree-1.la OSTree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=Ostree --symbol-prefix=ostree -OSTree_1_0_gir_FILES = $(libostreeinclude_HEADERS) $(filter-out %-private.h,$(libostree_1_la_SOURCES)) +OSTree_1_0_gir_FILES = $(libostreeinclude_HEADERS) $(filter-out %-private.h %/ostree-soup-uri.h,$(libostree_1_la_SOURCES)) INTROSPECTION_GIRS += OSTree-1.0.gir gir_DATA += OSTree-1.0.gir typelib_DATA += OSTree-1.0.typelib From 0b214566a244df2da1fcd2db09b5560a9b3d7280 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 12 Mar 2017 21:11:41 -0400 Subject: [PATCH 09/56] lib: Squash most of the gtk-doc warnings for missing parameters This isn't all of them, just trying to make a dent. Closes: #734 Approved by: jlebon --- src/libostree/ostree-repo.c | 7 +++++++ src/libostree/ostree-sepolicy.c | 3 +++ src/libostree/ostree-sysroot-upgrader.c | 14 ++++++++++++++ src/libostree/ostree-sysroot.c | 3 ++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 0f1c3631..34da969f 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -4226,6 +4226,13 @@ out: /** * ostree_repo_sign_delta: + * @self: Self + * @from_commit: From commit + * @to_commit: To commit + * @key_id: key id + * @homedir: homedir + * @cancellable: cancellable + * @error: error * * This function is deprecated, sign the summary file instead. * Add a GPG signature to a static delta. diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index fa264704..716cbd8c 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -378,6 +378,8 @@ initable_iface_init (GInitableIface *initable_iface) /** * ostree_sepolicy_new: * @path: Path to a root directory + * @cancellable: Cancellable + * @error: Error * * Returns: (transfer full): An accessor object for SELinux policy in root located at @path */ @@ -621,6 +623,7 @@ ostree_sepolicy_setfscreatecon (OstreeSePolicy *self, /** * ostree_sepolicy_fscreatecon_cleanup: + * @unused: Not used, just in case you didn't infer that from the parameter name * * Cleanup function for ostree_sepolicy_setfscreatecon(). */ diff --git a/src/libostree/ostree-sysroot-upgrader.c b/src/libostree/ostree-sysroot-upgrader.c index 232f8435..4e7c8bf3 100644 --- a/src/libostree/ostree-sysroot-upgrader.c +++ b/src/libostree/ostree-sysroot-upgrader.c @@ -293,6 +293,8 @@ ostree_sysroot_upgrader_init (OstreeSysrootUpgrader *self) /** * ostree_sysroot_upgrader_new: * @sysroot: An #OstreeSysroot + * @cancellable: Cancellable + * @error: Error * * Returns: (transfer full): An upgrader */ @@ -309,6 +311,8 @@ ostree_sysroot_upgrader_new (OstreeSysroot *sysroot, * ostree_sysroot_upgrader_new_for_os: * @sysroot: An #OstreeSysroot * @osname: (allow-none): Operating system name + * @cancellable: Cancellable + * @error: Error * * Returns: (transfer full): An upgrader */ @@ -327,6 +331,8 @@ ostree_sysroot_upgrader_new_for_os (OstreeSysroot *sysroot, * @sysroot: An #OstreeSysroot * @osname: (allow-none): Operating system name * @flags: Flags + * @cancellable: Cancellable + * @error: Error * * Returns: (transfer full): An upgrader */ @@ -514,6 +520,14 @@ ostree_sysroot_upgrader_pull (OstreeSysrootUpgrader *self, /** * ostree_sysroot_upgrader_pull_one_dir: + * @self: Upgrader + * @dir_to_pull: Subdirectory path (should include a leading /) + * @flags: Flags controlling pull behavior + * @upgrader_flags: Flags controlling upgrader behavior + * @progress: (allow-none): Progress + * @out_changed: (out): Whether or not the origin changed + * @cancellable: Cancellable + * @error: Error * * Like ostree_sysroot_upgrader_pull(), but allows retrieving just a * subpath of the tree. This can be used to download metadata files diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 4ed0d759..238ee74a 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1269,12 +1269,13 @@ ostree_sysroot_get_merge_deployment (OstreeSysroot *self, /** * ostree_sysroot_origin_new_from_refspec: + * @self: Sysroot * @refspec: A refspec * * Returns: (transfer full): A new config file which sets @refspec as an origin */ GKeyFile * -ostree_sysroot_origin_new_from_refspec (OstreeSysroot *sysroot, +ostree_sysroot_origin_new_from_refspec (OstreeSysroot *self, const char *refspec) { GKeyFile *ret = g_key_file_new (); From c2f5a999bfd865696b5456858e3cae984fba46f5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 13 Mar 2017 15:40:24 -0400 Subject: [PATCH 10/56] lib: Add a private copy of checksum-instream The current `OstreeChecksumInputStream` is public due to a historical mistake. I'd like to add an OpenSSL checksum backend, but that's harder without breaking this API. Let's ignore it and create a new private version, so it's easier to do the GLib/OpenSSL abstraction in one place. Closes: #738 Approved by: jlebon --- Makefile-otutil.am | 2 + src/libostree/ostree-repo-commit.c | 23 +++-- src/libotutil/ot-checksum-instream.c | 129 +++++++++++++++++++++++++++ src/libotutil/ot-checksum-instream.h | 64 +++++++++++++ src/libotutil/otutil.h | 1 + 5 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 src/libotutil/ot-checksum-instream.c create mode 100644 src/libotutil/ot-checksum-instream.h diff --git a/Makefile-otutil.am b/Makefile-otutil.am index ee892a70..5b6d4e48 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -22,6 +22,8 @@ noinst_LTLIBRARIES += libotutil.la libotutil_la_SOURCES = \ src/libotutil/ot-checksum-utils.c \ src/libotutil/ot-checksum-utils.h \ + src/libotutil/ot-checksum-instream.c \ + src/libotutil/ot-checksum-instream.h \ src/libotutil/ot-fs-utils.c \ src/libotutil/ot-fs-utils.h \ src/libotutil/ot-keyfile-utils.c \ diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index f6129ca6..d02154f8 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -619,12 +619,11 @@ write_object (OstreeRepo *self, OstreeRepoMode repo_mode; g_autofree char *temp_filename = NULL; g_autofree guchar *ret_csum = NULL; - glnx_unref_object OstreeChecksumInputStream *checksum_input = NULL; + glnx_unref_object OtChecksumInstream *checksum_input = NULL; g_autoptr(GInputStream) file_input = NULL; g_autoptr(GFileInfo) file_info = NULL; g_autoptr(GVariant) xattrs = NULL; gboolean have_obj; - GChecksum *checksum = NULL; gboolean temp_file_is_regular; gboolean temp_file_is_symlink; glnx_fd_close int temp_fd = -1; @@ -654,11 +653,7 @@ write_object (OstreeRepo *self, repo_mode = ostree_repo_get_mode (self); if (out_csum) - { - checksum = g_checksum_new (G_CHECKSUM_SHA256); - if (input) - checksum_input = ostree_checksum_input_stream_new (input, checksum); - } + checksum_input = ot_checksum_instream_new (input, G_CHECKSUM_SHA256); if (objtype == OSTREE_OBJECT_TYPE_FILE) { @@ -778,11 +773,11 @@ write_object (OstreeRepo *self, temp_file_is_regular = TRUE; } - if (!checksum) + if (!checksum_input) actual_checksum = expected_checksum; else { - actual_checksum = g_checksum_get_string (checksum); + actual_checksum = ot_checksum_instream_get_string (checksum_input); if (expected_checksum && strcmp (actual_checksum, expected_checksum) != 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, @@ -892,16 +887,18 @@ write_object (OstreeRepo *self, else self->txn_stats.content_objects_total++; g_mutex_unlock (&self->txn_stats_lock); - - if (checksum) - ret_csum = ot_csum_from_gchecksum (checksum); + + if (checksum_input) + { + g_assert (actual_checksum); + ret_csum = ostree_checksum_to_bytes (actual_checksum); + } ret = TRUE; ot_transfer_out_value(out_csum, &ret_csum); out: if (temp_filename) (void) unlinkat (self->tmp_dir_fd, temp_filename, 0); - g_clear_pointer (&checksum, (GDestroyNotify) g_checksum_free); return ret; } diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c new file mode 100644 index 00000000..14d5b5f0 --- /dev/null +++ b/src/libotutil/ot-checksum-instream.c @@ -0,0 +1,129 @@ +/* -*- 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 + * 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 "ot-checksum-instream.h" + +G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM) + +struct _OtChecksumInstreamPrivate { + GChecksum *checksum; +}; + +static gssize ot_checksum_instream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); + +static void +ot_checksum_instream_finalize (GObject *object) +{ + OtChecksumInstream *self = (OtChecksumInstream*)object; + + g_checksum_free (self->priv->checksum); + + G_OBJECT_CLASS (ot_checksum_instream_parent_class)->finalize (object); +} + +static void +ot_checksum_instream_class_init (OtChecksumInstreamClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (OtChecksumInstreamPrivate)); + + object_class->finalize = ot_checksum_instream_finalize; + stream_class->read_fn = ot_checksum_instream_read; +} + +static void +ot_checksum_instream_init (OtChecksumInstream *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate); + +} + +OtChecksumInstream * +ot_checksum_instream_new (GInputStream *base, + GChecksumType checksum_type) +{ + OtChecksumInstream *stream; + + g_return_val_if_fail (G_IS_INPUT_STREAM (base), NULL); + + stream = g_object_new (OT_TYPE_CHECKSUM_INSTREAM, + "base-stream", base, + NULL); + stream->priv->checksum = g_checksum_new (checksum_type); + + return (OtChecksumInstream*) (stream); +} + +static gssize +ot_checksum_instream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + OtChecksumInstream *self = (OtChecksumInstream*) stream; + GFilterInputStream *fself = (GFilterInputStream*) self; + gssize res = -1; + + res = g_input_stream_read (fself->base_stream, + buffer, + count, + cancellable, + error); + if (res > 0) + g_checksum_update (self->priv->checksum, buffer, res); + + return res; +} + +void +ot_checksum_instream_get_digest (OtChecksumInstream *stream, + guint8 *buffer, + gsize *digest_len) +{ + g_checksum_get_digest (stream->priv->checksum, buffer, digest_len); +} + +guint8* +ot_checksum_instream_dup_digest (OtChecksumInstream *stream, + gsize *ret_len) +{ + gsize len = 32; + guchar *ret = g_malloc (len); + g_checksum_get_digest (stream->priv->checksum, ret, &len); + g_assert (len == 32); + if (ret_len) + *ret_len = len; + return ret; +} + +char * +ot_checksum_instream_get_string (OtChecksumInstream *stream) +{ + return g_strdup (g_checksum_get_string (stream->priv->checksum)); +} diff --git a/src/libotutil/ot-checksum-instream.h b/src/libotutil/ot-checksum-instream.h new file mode 100644 index 00000000..78a5d44e --- /dev/null +++ b/src/libotutil/ot-checksum-instream.h @@ -0,0 +1,64 @@ +/* -*- 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 + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define OT_TYPE_CHECKSUM_INSTREAM (ot_checksum_instream_get_type ()) +#define OT_CHECKSUM_INSTREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstream)) +#define OT_CHECKSUM_INSTREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass)) +#define OT_IS_CHECKSUM_INSTREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OT_TYPE_CHECKSUM_INPUT_STREAM)) +#define OT_IS_CHECKSUM_INSTREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OT_TYPE_CHECKSUM_INPUT_STREAM)) +#define OT_CHECKSUM_INSTREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass)) + +typedef struct _OtChecksumInstream OtChecksumInstream; +typedef struct _OtChecksumInstreamClass OtChecksumInstreamClass; +typedef struct _OtChecksumInstreamPrivate OtChecksumInstreamPrivate; + +struct _OtChecksumInstream +{ + GFilterInputStream parent_instance; + + /*< private >*/ + OtChecksumInstreamPrivate *priv; +}; + +struct _OtChecksumInstreamClass +{ + GFilterInputStreamClass parent_class; +}; + +GType ot_checksum_instream_get_type (void) G_GNUC_CONST; + +OtChecksumInstream * ot_checksum_instream_new (GInputStream *stream, GChecksumType checksum); + +void ot_checksum_instream_get_digest (OtChecksumInstream *stream, + guint8 *buffer, + gsize *digest_len); + +guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream, + gsize *ret_len); +char * ot_checksum_instream_get_string (OtChecksumInstream *stream); + +G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index c66d5634..f6158de8 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -53,5 +53,6 @@ #include #include #include +#include void ot_ptrarray_add_many (GPtrArray *a, ...) G_GNUC_NULL_TERMINATED; From df5cbc9be9bb25c6eaeff12db9727d1ba28118a1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 13 Mar 2017 14:41:14 -0400 Subject: [PATCH 11/56] core: Support building with OpenSSL for checksums Add an OpenSSL backend to the checksum input stream, which is where we do a lot of checksumming (object commit, static deltas). The raw OpenSSL performance is [approximately double](https://gist.github.com/cgwalters/169349fd1c06fd4fb4d3a7ce33303222) on my laptop; not only does OpenSSL have e.g. hand-tuned x86_64 assembly, the current implementation uses the [Intel SHA extensions](https://en.wikipedia.org/wiki/Intel_SHA_extensions). Another reason to do this is I was idly thinking about adding [Curve25519](https://en.wikipedia.org/wiki/Curve25519) signatures (like e.g. Alpine does) instead of/in addition to GPG. The rationale for that is that GPG is pretty heavyweight, both in code footprint and the simple fact that EC keys are way smaller. I didn't benchmark ostree with this; we have bigger performance problems really like the fact we just malloc way too much. But, it's a step in the right direction I think in combination with the libcurl work where we're linking to openssl anyways. Closes: #738 Approved by: jlebon --- .redhat-ci.yml | 4 +- configure.ac | 18 +++++++ src/libostree/ostree-core.c | 11 +---- src/libotutil/ot-checksum-instream.c | 74 ++++++++++++++++++++++++++-- src/libotutil/ot-checksum-utils.c | 16 ++++++ src/libotutil/ot-checksum-utils.h | 2 + 6 files changed, 110 insertions(+), 15 deletions(-) diff --git a/.redhat-ci.yml b/.redhat-ci.yml index 74778f8a..8073ed9c 100644 --- a/.redhat-ci.yml +++ b/.redhat-ci.yml @@ -76,10 +76,11 @@ tests: inherit: true required: true -context: curl +context: curl-openssl packages: - pkgconfig(libcurl) + - pkgconfig(openssl) build: config-opts: > @@ -88,6 +89,7 @@ build: --enable-installed-tests --enable-gtk-doc --with-curl + --with-openssl tests: - make check diff --git a/configure.ac b/configure.ac index be1e0e13..0afd87e1 100644 --- a/configure.ac +++ b/configure.ac @@ -298,6 +298,23 @@ AS_IF([ test x$with_smack = xyes], [ ]) AM_CONDITIONAL(USE_SMACK, test $with_smack != no) +dnl begin openssl +OPENSSL_DEPENDENCY="libselinux >= 1.0.1" +AC_ARG_WITH(openssl, +AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL (checksums)]), +:, with_openssl=no) + +AS_IF([ test x$with_openssl != xno ], [ + PKG_CHECK_MODULES(OT_DEP_OPENSSL, $OPENSSL_DEPENDENCY) + AC_DEFINE([HAVE_OPENSSL], 1, [Define if we have openssl]) + with_openssl=yes +], [ + with_openssl=no +]) +if test x$with_openssl != xno; then OSTREE_FEATURES="$OSTREE_FEATURES openssl"; fi +AM_CONDITIONAL(USE_OPENSSL, test $with_openssl != no) +dnl end openssl + dnl This is what is in RHEL7.2 right now, picking it arbitrarily LIBMOUNT_DEPENDENCY="mount >= 2.23.0" @@ -430,6 +447,7 @@ echo " HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux + OpenSSL (checksums): $with_openssl systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index db03c034..4d7b431b 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1351,16 +1351,7 @@ void ostree_checksum_inplace_from_bytes (const guchar *csum, char *buf) { - static const gchar hexchars[] = "0123456789abcdef"; - guint i, j; - - for (i = 0, j = 0; i < OSTREE_SHA256_DIGEST_LEN; i++, j += 2) - { - guchar byte = csum[i]; - buf[j] = hexchars[byte >> 4]; - buf[j+1] = hexchars[byte & 0xF]; - } - buf[j] = '\0'; + ot_bin2hex (buf, csum, OSTREE_SHA256_DIGEST_LEN); } /** diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c index 14d5b5f0..686554df 100644 --- a/src/libotutil/ot-checksum-instream.c +++ b/src/libotutil/ot-checksum-instream.c @@ -21,11 +21,21 @@ #include "config.h" #include "ot-checksum-instream.h" +#include "ot-checksum-utils.h" + +#ifdef HAVE_OPENSSL +#include +#endif G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM) struct _OtChecksumInstreamPrivate { +#ifdef HAVE_OPENSSL + EVP_MD_CTX *checksum; +#else + GChecksumType checksum_type; GChecksum *checksum; +#endif }; static gssize ot_checksum_instream_read (GInputStream *stream, @@ -39,7 +49,11 @@ ot_checksum_instream_finalize (GObject *object) { OtChecksumInstream *self = (OtChecksumInstream*)object; +#ifdef HAVE_OPENSSL + EVP_MD_CTX_destroy (self->priv->checksum); +#else g_checksum_free (self->priv->checksum); +#endif G_OBJECT_CLASS (ot_checksum_instream_parent_class)->finalize (object); } @@ -60,9 +74,23 @@ static void ot_checksum_instream_init (OtChecksumInstream *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate); - } +#ifdef HAVE_OPENSSL +static const EVP_MD * +gchecksum_type_to_openssl (GChecksumType checksum_type) +{ + switch (checksum_type) + { + case G_CHECKSUM_SHA256: + return EVP_sha256 (); + default: + /* If there's something else, fill in here */ + g_assert_not_reached (); + } +} +#endif + OtChecksumInstream * ot_checksum_instream_new (GInputStream *base, GChecksumType checksum_type) @@ -74,7 +102,18 @@ ot_checksum_instream_new (GInputStream *base, stream = g_object_new (OT_TYPE_CHECKSUM_INSTREAM, "base-stream", base, NULL); + + /* For now */ + g_assert (checksum_type == G_CHECKSUM_SHA256); + +#ifdef 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)); +#else stream->priv->checksum = g_checksum_new (checksum_type); + stream->priv->checksum_type = checksum_type; +#endif return (OtChecksumInstream*) (stream); } @@ -96,7 +135,13 @@ ot_checksum_instream_read (GInputStream *stream, cancellable, error); if (res > 0) - g_checksum_update (self->priv->checksum, buffer, res); + { +#ifdef HAVE_OPENSSL + g_assert (EVP_DigestUpdate (self->priv->checksum, buffer, res)); +#else + g_checksum_update (self->priv->checksum, buffer, res); +#endif + } return res; } @@ -106,17 +151,29 @@ ot_checksum_instream_get_digest (OtChecksumInstream *stream, guint8 *buffer, gsize *digest_len) { +#ifdef HAVE_OPENSSL + unsigned len; + EVP_DigestFinal_ex (stream->priv->checksum, buffer, &len); + if (digest_len) + *digest_len = len; +#else g_checksum_get_digest (stream->priv->checksum, buffer, digest_len); +#endif } guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream, gsize *ret_len) { - gsize len = 32; +#ifdef HAVE_OPENSSL + guint len; + guchar *ret = g_malloc0 (EVP_MAX_MD_SIZE); + g_assert (EVP_DigestFinal_ex (stream->priv->checksum, ret, &len)); +#else + gsize len = g_checksum_type_get_length (stream->priv->checksum_type); guchar *ret = g_malloc (len); g_checksum_get_digest (stream->priv->checksum, ret, &len); - g_assert (len == 32); +#endif if (ret_len) *ret_len = len; return ret; @@ -125,5 +182,14 @@ ot_checksum_instream_dup_digest (OtChecksumInstream *stream, char * ot_checksum_instream_get_string (OtChecksumInstream *stream) { +#ifdef 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; +#else return g_strdup (g_checksum_get_string (stream->priv->checksum)); +#endif } diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c index 8d30bdc3..4b5c824a 100644 --- a/src/libotutil/ot-checksum-utils.c +++ b/src/libotutil/ot-checksum-utils.c @@ -26,6 +26,22 @@ #include + +void +ot_bin2hex (char *out_buf, const guint8 *inbuf, gsize len) +{ + static const gchar hexchars[] = "0123456789abcdef"; + guint i, j; + + for (i = 0, j = 0; i < len; i++, j += 2) + { + guchar byte = inbuf[i]; + out_buf[j] = hexchars[byte >> 4]; + out_buf[j+1] = hexchars[byte & 0xF]; + } + out_buf[j] = '\0'; +} + guchar * ot_csum_from_gchecksum (GChecksum *checksum) { diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h index 8b3a394e..b580fc1c 100644 --- a/src/libotutil/ot-checksum-utils.h +++ b/src/libotutil/ot-checksum-utils.h @@ -26,6 +26,8 @@ G_BEGIN_DECLS +void ot_bin2hex (char *out_buf, const guint8 *inbuf, gsize len); + guchar *ot_csum_from_gchecksum (GChecksum *checksum); gboolean ot_gio_write_update_checksum (GOutputStream *out, From ec2f52e62532017a79d70ce6ea2870d010a22b99 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 18 Mar 2017 11:51:44 -0400 Subject: [PATCH 12/56] sysroot/deploy: Some cleanup to decl-after-stmt/return FALSE style And fd-relative. I also introduced some helpers here which I'll use later in more invasive patches. Closes: #742 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 196 ++++++++++---------------- src/libotutil/ot-fs-utils.c | 34 +++++ src/libotutil/ot-fs-utils.h | 7 + 3 files changed, 115 insertions(+), 122 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 1cfe6ab1..2321cbba 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -701,89 +701,62 @@ selinux_relabel_dir (OstreeSysroot *sysroot, return ret; } -static gboolean -selinux_relabel_file (OstreeSysroot *sysroot, - OstreeSePolicy *sepolicy, - GFile *path, - const char *prefix, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - g_autoptr(GPtrArray) path_parts = g_ptr_array_new (); - g_autoptr(GFileInfo) file_info = g_file_query_info (path, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - if (!file_info) - goto out; - - g_ptr_array_add (path_parts, (char*)prefix); - g_ptr_array_add (path_parts, (char*)g_file_info_get_name (file_info)); - if (!relabel_one_path (sysroot, sepolicy, path, file_info, path_parts, - cancellable, error)) - { - g_prefix_error (error, "Relabeling /%s/%s: ", prefix, - g_file_info_get_name (file_info)); - goto out; - } - - ret = TRUE; - out: - return ret; -} - static gboolean selinux_relabel_var_if_needed (OstreeSysroot *sysroot, OstreeSePolicy *sepolicy, - GFile *deployment_var_path, + int os_deploy_dfd, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; /* This is a bit of a hack; we should change the code at some * point in the distant future to only create (and label) /var * when doing a deployment. */ - g_autoptr(GFile) deployment_var_labeled = - g_file_get_child (deployment_var_path, ".ostree-selabeled"); - g_autoptr(GFile) deployment_var_labeled_tmp = - g_file_get_child (deployment_var_path, ".ostree-selabeled.tmp"); - - if (!g_file_query_exists (deployment_var_labeled, NULL)) + const char selabeled[] = "var/.ostree-selabeled"; + gboolean deployment_var_labeled; + + if (!ot_query_exists_at (os_deploy_dfd, selabeled, &deployment_var_labeled, error)) + return FALSE; + + if (!deployment_var_labeled) { ot_log_structured_print_id_v (OSTREE_VARRELABEL_ID, "Relabeling /var (no stamp file '%s' found)", - gs_file_get_path_cached (deployment_var_labeled)); + selabeled); + g_autoptr(GFile) deployment_var_path = ot_fdrel_to_gfile (os_deploy_dfd, "var"); if (!selinux_relabel_dir (sysroot, sepolicy, deployment_var_path, "var", cancellable, error)) { g_prefix_error (error, "Relabeling /var: "); - goto out; + return FALSE; } - if (!g_file_replace_contents (deployment_var_labeled_tmp, "", 0, NULL, FALSE, - G_FILE_CREATE_REPLACE_DESTINATION, NULL, - cancellable, error)) - goto out; - - if (!selinux_relabel_file (sysroot, sepolicy, - deployment_var_labeled_tmp, "var", - cancellable, error)) - goto out; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + { ostree_cleanup_sepolicy_fscreatecon gpointer dummy = NULL; +#pragma GCC diagnostic pop - if (rename (gs_file_get_path_cached (deployment_var_labeled_tmp), - gs_file_get_path_cached (deployment_var_labeled)) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + if (sysroot->sepolicy != NULL + && ostree_sepolicy_get_name (sysroot->sepolicy) != NULL) + { + const char *selabeled_abspath = glnx_strjoina ("/", selabeled); + if (!ostree_sepolicy_setfscreatecon (sysroot->sepolicy, + selabeled_abspath, + 0644, + error)) + return FALSE; + } + + if (!glnx_file_replace_contents_at (os_deploy_dfd, selabeled, (guint8*)"", 0, + GLNX_FILE_REPLACE_DATASYNC_NEW, + cancellable, error)) + return FALSE; + } } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1997,7 +1970,6 @@ allocate_deployserial (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; guint i; int new_deployserial = 0; g_autoptr(GFile) osdir = NULL; @@ -2008,7 +1980,7 @@ allocate_deployserial (OstreeSysroot *self, if (!_ostree_sysroot_list_deployment_dirs_for_os (osdir, tmp_current_deployments, cancellable, error)) - goto out; + return FALSE; for (i = 0; i < tmp_current_deployments->len; i++) { @@ -2020,12 +1992,10 @@ allocate_deployserial (OstreeSysroot *self, new_deployserial = MAX(new_deployserial, ostree_deployment_get_deployserial (deployment)+1); } - ret = TRUE; *out_deployserial = new_deployserial; - out: - return ret; + return TRUE; } - + /** * ostree_sysroot_deploy_tree: * @self: Sysroot @@ -2052,103 +2022,93 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - gint new_deployserial; - glnx_unref_object OstreeDeployment *new_deployment = NULL; - glnx_unref_object OstreeDeployment *merge_deployment = NULL; - glnx_unref_object OstreeRepo *repo = NULL; - g_autoptr(GFile) osdeploydir = NULL; - g_autoptr(GFile) deployment_var = NULL; - glnx_fd_close int tree_boot_dfd = -1; - g_autofree char *tree_kernel_path = NULL; - g_autofree char *tree_initramfs_path = NULL; - glnx_fd_close int deployment_dfd = -1; - glnx_unref_object OstreeSePolicy *sepolicy = NULL; - g_autofree char *new_bootcsum = NULL; - glnx_unref_object OstreeBootconfigParser *bootconfig = NULL; - g_return_val_if_fail (osname != NULL || self->booted_deployment != NULL, FALSE); if (osname == NULL) osname = ostree_deployment_get_osname (self->booted_deployment); - osdeploydir = ot_gfile_get_child_build_path (self->path, "ostree", "deploy", osname, NULL); - if (!g_file_query_exists (osdeploydir, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No OS named \"%s\" known", osname); - goto out; - } - - deployment_var = g_file_get_child (osdeploydir, "var"); + const char *osdeploypath = glnx_strjoina ("ostree/deploy/", osname); + glnx_fd_close int os_deploy_dfd = -1; + if (!glnx_opendirat (self->sysroot_fd, osdeploypath, TRUE, &os_deploy_dfd, error)) + return FALSE; + glnx_unref_object OstreeRepo *repo = NULL; if (!ostree_sysroot_get_repo (self, &repo, cancellable, error)) - goto out; + return FALSE; + glnx_unref_object OstreeDeployment *merge_deployment = NULL; if (provided_merge_deployment != NULL) merge_deployment = g_object_ref (provided_merge_deployment); + gint new_deployserial; if (!allocate_deployserial (self, osname, revision, &new_deployserial, cancellable, error)) - goto out; + return FALSE; - new_deployment = ostree_deployment_new (0, osname, revision, new_deployserial, - new_bootcsum, -1); + g_autofree char *new_bootcsum = NULL; + glnx_unref_object OstreeDeployment *new_deployment = + ostree_deployment_new (0, osname, revision, new_deployserial, + new_bootcsum, -1); ostree_deployment_set_origin (new_deployment, origin); /* Check out the userspace tree onto the filesystem */ + glnx_fd_close int deployment_dfd = -1; if (!checkout_deployment_tree (self, repo, new_deployment, &deployment_dfd, cancellable, error)) { g_prefix_error (error, "Checking out tree: "); - goto out; + return FALSE; } + glnx_fd_close int tree_boot_dfd = -1; + g_autofree char *tree_kernel_path = NULL; + g_autofree char *tree_initramfs_path = NULL; if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd, &tree_kernel_path, &tree_initramfs_path, cancellable, error)) - goto out; - + return FALSE; + if (tree_initramfs_path != NULL) { if (!checksum_from_kernel_src (tree_initramfs_path, &new_bootcsum, error)) - goto out; + return FALSE; } else { if (!checksum_from_kernel_src (tree_kernel_path, &new_bootcsum, error)) - goto out; + return FALSE; } - + _ostree_deployment_set_bootcsum (new_deployment, new_bootcsum); /* Create an empty boot configuration; we will merge things into * it as we go. */ - bootconfig = ostree_bootconfig_parser_new (); + glnx_unref_object OstreeBootconfigParser *bootconfig = ostree_bootconfig_parser_new (); ostree_deployment_set_bootconfig (new_deployment, bootconfig); + glnx_unref_object OstreeSePolicy *sepolicy = NULL; if (!merge_configuration (self, merge_deployment, new_deployment, deployment_dfd, &sepolicy, cancellable, error)) { g_prefix_error (error, "During /etc merge: "); - goto out; + return FALSE; } g_clear_object (&self->sepolicy); self->sepolicy = g_object_ref (sepolicy); - if (!selinux_relabel_var_if_needed (self, sepolicy, deployment_var, + if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, cancellable, error)) - goto out; + return FALSE; if (!(self->debug_flags & OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS)) { if (!ostree_sysroot_deployment_set_mutable (self, new_deployment, FALSE, cancellable, error)) - goto out; + return FALSE; } #pragma GCC diagnostic push @@ -2166,7 +2126,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, "/etc/ostree/remotes.d/dummy.conf", 0644, error)) - goto out; + return FALSE; } /* Don't fsync here, as we assume that's all done in @@ -2177,7 +2137,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, cancellable, error)) { g_prefix_error (error, "Writing out origin file: "); - goto out; + return FALSE; } } @@ -2195,10 +2155,8 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, ostree_bootconfig_parser_set (bootconfig, "options", new_options); } - ret = TRUE; ot_transfer_out_value (out_new_deployment, &new_deployment); - out: - return ret; + return TRUE; } /** @@ -2219,7 +2177,6 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; guint i; g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref); glnx_unref_object OstreeDeployment *new_deployment = NULL; @@ -2246,11 +2203,9 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self, if (!ostree_sysroot_write_deployments (self, new_deployments, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2271,20 +2226,17 @@ ostree_sysroot_deployment_set_mutable (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); - glnx_fd_close int fd = -1; if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; + g_autofree char *deployment_path = ostree_sysroot_get_deployment_dirpath (self, deployment); + glnx_fd_close int fd = -1; if (!glnx_opendirat (self->sysroot_fd, deployment_path, TRUE, &fd, error)) - goto out; + return FALSE; if (!_ostree_linuxfs_fd_alter_immutable_flag (fd, !is_mutable, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } diff --git a/src/libotutil/ot-fs-utils.c b/src/libotutil/ot-fs-utils.c index 4575effe..a0a72ca5 100644 --- a/src/libotutil/ot-fs-utils.c +++ b/src/libotutil/ot-fs-utils.c @@ -25,6 +25,16 @@ #include #include +/* Convert a fd-relative path to a GFile* - use + * for legacy code. + */ +GFile * +ot_fdrel_to_gfile (int dfd, const char *path) +{ + g_autofree char *abspath = glnx_fdrel_abspath (dfd, path); + return g_file_new_for_path (abspath); +} + int ot_opendirat (int dfd, const char *path, gboolean follow) { @@ -205,6 +215,30 @@ ot_ensure_unlinked_at (int dfd, 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) + { + glnx_set_error_from_errno (error); + return FALSE; + } + ret_exists = FALSE; + } + else + ret_exists = TRUE; + + *out_exists = ret_exists; + return TRUE; +} + gboolean ot_openat_ignore_enoent (int dfd, const char *path, diff --git a/src/libotutil/ot-fs-utils.h b/src/libotutil/ot-fs-utils.h index 27f0f38e..13909c8e 100644 --- a/src/libotutil/ot-fs-utils.h +++ b/src/libotutil/ot-fs-utils.h @@ -24,6 +24,8 @@ G_BEGIN_DECLS +GFile * ot_fdrel_to_gfile (int dfd, const char *path); + int ot_opendirat (int dfd, const char *path, gboolean follow); gboolean ot_gopendirat (int dfd, const char *path, @@ -57,6 +59,11 @@ gboolean ot_openat_read_stream (int dfd, 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); From 5d413dff882efe1ee4faa6e4642d5b04598c01b8 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 20 Mar 2017 10:35:40 -0400 Subject: [PATCH 13/56] sysroot: Prep refactoring of cleanup logic For future work I'm going to tweak how we handle cleanup, and the private cleanup flags didn't really end up being used - we only specify "prune repo or not". So fold that into a boolean for now. The sysroot deploy logic then has a single "do_postclean" boolean, which is all I want to expose as public API. Closes: #744 Approved by: jlebon --- src/libostree/ostree-sysroot-cleanup.c | 53 +++++++++----------------- src/libostree/ostree-sysroot-deploy.c | 15 ++++---- src/libostree/ostree-sysroot-private.h | 17 +++------ src/libostree/ostree-sysroot.c | 3 +- 4 files changed, 31 insertions(+), 57 deletions(-) diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 2a78d2ce..022654c3 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -515,12 +515,7 @@ ostree_sysroot_cleanup (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - OstreeSysrootCleanupFlags flags; - - /* Do everything. */ - flags = OSTREE_SYSROOT_CLEANUP_ALL; - - return _ostree_sysroot_piecemeal_cleanup (self, flags, cancellable, error); + return _ostree_sysroot_cleanup_internal (self, TRUE, cancellable, error); } /** @@ -537,55 +532,41 @@ ostree_sysroot_prepare_cleanup (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - OstreeSysrootCleanupFlags flags; - - /* Do everything EXCEPT pruning the repository. */ - flags = OSTREE_SYSROOT_CLEANUP_ALL & ~OSTREE_SYSROOT_CLEANUP_PRUNE_REPO; - - return _ostree_sysroot_piecemeal_cleanup (self, flags, cancellable, error); + return _ostree_sysroot_cleanup_internal (self, FALSE, cancellable, error); } gboolean -_ostree_sysroot_piecemeal_cleanup (OstreeSysroot *self, - OstreeSysrootCleanupFlags flags, - GCancellable *cancellable, - GError **error) +_ostree_sysroot_cleanup_internal (OstreeSysroot *self, + gboolean do_prune_repo, + GCancellable *cancellable, + GError **error) { - gboolean ret = FALSE; glnx_unref_object OstreeRepo *repo = NULL; g_return_val_if_fail (OSTREE_IS_SYSROOT (self), FALSE); g_return_val_if_fail (self->loaded, FALSE); - if (flags & OSTREE_SYSROOT_CLEANUP_BOOTVERSIONS) - { - if (!cleanup_other_bootversions (self, cancellable, error)) - goto out; - } + if (!cleanup_other_bootversions (self, cancellable, error)) + return FALSE; - if (flags & OSTREE_SYSROOT_CLEANUP_DEPLOYMENTS) - { - if (!cleanup_old_deployments (self, cancellable, error)) - goto out; - } + if (!cleanup_old_deployments (self, cancellable, error)) + return FALSE; if (!ostree_sysroot_get_repo (self, &repo, cancellable, error)) - goto out; - + return FALSE; + if (!generate_deployment_refs (self, repo, self->bootversion, self->subbootversion, self->deployments, cancellable, error)) - goto out; - - if (flags & OSTREE_SYSROOT_CLEANUP_PRUNE_REPO) + return FALSE; + + if (do_prune_repo) { if (!prune_repo (repo, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 2321cbba..6bf01a16 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1703,14 +1703,13 @@ ostree_sysroot_write_deployments (OstreeSysroot *self, GError **error) { return _ostree_sysroot_write_deployments_internal (self, new_deployments, - OSTREE_SYSROOT_CLEANUP_ALL, - cancellable, error); + TRUE, cancellable, error); } gboolean _ostree_sysroot_write_deployments_internal (OstreeSysroot *self, GPtrArray *new_deployments, - OstreeSysrootCleanupFlags cleanup_flags, + gboolean do_clean, GCancellable *cancellable, GError **error) { @@ -1938,11 +1937,13 @@ _ostree_sysroot_write_deployments_internal (OstreeSysroot *self, /* And finally, cleanup of any leftover data. */ - if (!_ostree_sysroot_piecemeal_cleanup (self, cleanup_flags, - cancellable, error)) + if (do_clean) { - g_prefix_error (error, "Performing final cleanup: "); - goto out; + if (!ostree_sysroot_cleanup (self, cancellable, error)) + { + g_prefix_error (error, "Performing final cleanup: "); + goto out; + } } ret = TRUE; diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index b2def7fa..18fc0cb0 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -109,21 +109,14 @@ gboolean _ostree_sysroot_query_bootloader (OstreeSysroot *sysroot, gboolean _ostree_sysroot_bump_mtime (OstreeSysroot *sysroot, GError **error); -typedef enum { - OSTREE_SYSROOT_CLEANUP_BOOTVERSIONS = 1 << 0, - OSTREE_SYSROOT_CLEANUP_DEPLOYMENTS = 1 << 1, - OSTREE_SYSROOT_CLEANUP_PRUNE_REPO = 1 << 2, - OSTREE_SYSROOT_CLEANUP_ALL = 0xffff -} OstreeSysrootCleanupFlags; - -gboolean _ostree_sysroot_piecemeal_cleanup (OstreeSysroot *sysroot, - OstreeSysrootCleanupFlags flags, - GCancellable *cancellable, - GError **error); +gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot, + gboolean prune_repo, + GCancellable *cancellable, + GError **error); gboolean _ostree_sysroot_write_deployments_internal (OstreeSysroot *self, GPtrArray *new_deployments, - OstreeSysrootCleanupFlags cleanup_flags, + gboolean do_clean, GCancellable *cancellable, GError **error); diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 238ee74a..575cb6df 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1604,8 +1604,7 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, } if (!_ostree_sysroot_write_deployments_internal (sysroot, new_deployments, - postclean ? OSTREE_SYSROOT_CLEANUP_ALL : 0, - cancellable, error)) + postclean, cancellable, error)) goto out; ret = TRUE; From e665e5140838f5b44efefef0b5c4180e3bf3cfc1 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Wed, 8 Feb 2017 21:59:38 +0100 Subject: [PATCH 14/56] diff: Add ostree_diff_dirs_with_options(), expose via cmdline The first options are owner_uid/owner_gid, which makes it possible to use diff on local files where --owner-uid/gid have been passed to commit. Closes: #740 Approved by: cgwalters --- apidoc/ostree-sections.txt | 1 + man/ostree-diff.xml | 14 +++++++++++ src/libostree/libostree.sym | 1 + src/libostree/ostree-diff.c | 45 ++++++++++++++++++++++++++++++++++-- src/libostree/ostree-diff.h | 36 +++++++++++++++++++++++++++++ src/ostree/ot-builtin-diff.c | 10 ++++++-- tests/basic-test.sh | 17 +++++++++++++- 7 files changed, 119 insertions(+), 5 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index cba6ec46..027f25c5 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -172,6 +172,7 @@ OstreeDiffItem ostree_diff_item_ref ostree_diff_item_unref ostree_diff_dirs +ostree_diff_dirs_with_options ostree_diff_print ostree_diff_item_get_type diff --git a/man/ostree-diff.xml b/man/ostree-diff.xml index aaa76b13..906374b4 100644 --- a/man/ostree-diff.xml +++ b/man/ostree-diff.xml @@ -78,6 +78,20 @@ Boston, MA 02111-1307, USA. Print filesystem diff. + + + + + Use file ownership user id for local files. + + + + + + + Use file ownership group id for local files. + + diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 9067a26c..649c6f1f 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -389,6 +389,7 @@ global: LIBOSTREE_2017.4 { global: ostree_check_version; + ostree_diff_dirs_with_options; } LIBOSTREE_2017.3; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index 69a67b76..5537ee87 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -225,6 +225,37 @@ ostree_diff_dirs (OstreeDiffFlags flags, GPtrArray *added, GCancellable *cancellable, GError **error) +{ + return ostree_diff_dirs_with_options (flags, a, b, modified, + removed, added, NULL, + cancellable, error); +} + +/** + * ostree_diff_dirs_with_options: + * @flags: Flags + * @a: First directory path, or %NULL + * @b: First directory path + * @modified: (element-type OstreeDiffItem): Modified files + * @removed: (element-type Gio.File): Removed files + * @added: (element-type Gio.File): Added files + * @cancellable: Cancellable + * @options: (allow-none): Options + * @error: Error + * + * Compute the difference between directory @a and @b as 3 separate + * sets of #OstreeDiffItem in @modified, @removed, and @added. + */ +gboolean +ostree_diff_dirs_with_options (OstreeDiffFlags flags, + GFile *a, + GFile *b, + GPtrArray *modified, + GPtrArray *removed, + GPtrArray *added, + OstreeDiffDirsOptions *options, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; GError *temp_error = NULL; @@ -233,6 +264,10 @@ ostree_diff_dirs (OstreeDiffFlags flags, g_autoptr(GFile) child_b = NULL; g_autoptr(GFileInfo) child_a_info = NULL; g_autoptr(GFileInfo) child_b_info = NULL; + OstreeDiffDirsOptions default_opts = OSTREE_DIFF_DIRS_OPTIONS_INIT; + + if (!options) + options = &default_opts; if (a == NULL) { @@ -316,6 +351,11 @@ ostree_diff_dirs (OstreeDiffFlags flags, } else { + if (options->owner_uid >= 0) + g_file_info_set_attribute_uint32 (child_b_info, "unix::uid", options->owner_uid); + if (options->owner_gid >= 0) + g_file_info_set_attribute_uint32 (child_b_info, "unix::gid", options->owner_gid); + child_b_type = g_file_info_get_file_type (child_b_info); if (child_a_type != child_b_type) { @@ -337,8 +377,9 @@ ostree_diff_dirs (OstreeDiffFlags flags, if (child_a_type == G_FILE_TYPE_DIRECTORY) { - if (!ostree_diff_dirs (flags, child_a, child_b, modified, - removed, added, cancellable, error)) + if (!ostree_diff_dirs_with_options (flags, child_a, child_b, modified, + removed, added, options, + cancellable, error)) goto out; } } diff --git a/src/libostree/ostree-diff.h b/src/libostree/ostree-diff.h index 781bf768..b33bd63a 100644 --- a/src/libostree/ostree-diff.h +++ b/src/libostree/ostree-diff.h @@ -71,6 +71,42 @@ gboolean ostree_diff_dirs (OstreeDiffFlags flags, GCancellable *cancellable, GError **error); +/** + * OstreeDiffDirsOptions: + * + * An extensible options structure controlling diff dirs. Make sure + * that owner_uid/gid is set to -1 when not used. This is used by + * ostree_diff_dirs_with_options(). + */ +typedef struct { + gint owner_uid; + gint owner_gid; + + OstreeRepoDevInoCache *devino_to_csum_cache; + + gboolean unused_bools[7]; + int unused_ints[6]; + gpointer unused_ptrs[7]; +} OstreeDiffDirsOptions; + +/** + * OSTREE_DIFF_DIRS_OPTIONS_INIT: + * + * Use this to initialize an `OstreeDiffDirsOptions` structure. + */ +#define OSTREE_DIFF_DIRS_OPTIONS_INIT { .owner_uid = -1, .owner_gid = -1, } + +_OSTREE_PUBLIC +gboolean ostree_diff_dirs_with_options (OstreeDiffFlags flags, + GFile *a, + GFile *b, + GPtrArray *modified, + GPtrArray *removed, + GPtrArray *added, + OstreeDiffDirsOptions *options, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC void ostree_diff_print (GFile *a, GFile *b, diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index 963a8b7c..a7e2aad2 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -30,11 +30,15 @@ static gboolean opt_stats; static gboolean opt_fs_diff; static gboolean opt_no_xattrs; +static gint opt_owner_uid = -1; +static gint opt_owner_gid = -1; static GOptionEntry options[] = { { "stats", 0, 0, G_OPTION_ARG_NONE, &opt_stats, "Print various statistics", NULL }, { "fs-diff", 0, 0, G_OPTION_ARG_NONE, &opt_fs_diff, "Print filesystem diff", NULL }, { "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Skip output of extended attributes", NULL }, + { "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Use file ownership user id for local files", "UID" }, + { "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Use file ownership group id for local files", "GID" }, { NULL } }; @@ -177,8 +181,10 @@ ostree_builtin_diff (int argc, char **argv, GCancellable *cancellable, GError ** modified = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_diff_item_unref); removed = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); added = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); - - if (!ostree_diff_dirs (diff_flags, srcf, targetf, modified, removed, added, cancellable, error)) + + OstreeDiffDirsOptions diff_opts = { opt_owner_uid, opt_owner_gid }; + if (!ostree_diff_dirs_with_options (diff_flags, srcf, targetf, modified, removed, + added, &diff_opts, cancellable, error)) goto out; ostree_diff_print (srcf, targetf, modified, removed, added); diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 045e4217..68c7b0a6 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -19,7 +19,7 @@ set -euo pipefail -echo "1..63" +echo "1..65" $CMD_PREFIX ostree --version > version.yaml python -c 'import yaml; yaml.safe_load(open("version.yaml"))' @@ -171,6 +171,21 @@ cd ${test_tmpdir} assert_file_has_content diff-test2-2 'A *oh-look-a-file$' echo "ok diff cwd" +cd ${test_tmpdir}/checkout-test2-4 +$OSTREE diff test2 ./ > ${test_tmpdir}/diff-test2 +assert_file_empty ${test_tmpdir}/diff-test2 +$OSTREE diff test2 --owner-uid=$((`id -u`+1)) ./ > ${test_tmpdir}/diff-test2 +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' +echo "ok diff file with different uid" + +$OSTREE diff test2 --owner-gid=$((`id -g`+1)) ./ > ${test_tmpdir}/diff-test2 +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' +assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' +echo "ok diff file with different gid" + cd ${test_tmpdir}/checkout-test2-4 rm four mkdir four From 4ebe1ee94b9e59b79950ce53619fcc3497ea133b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 21 Mar 2017 15:14:06 -0400 Subject: [PATCH 15/56] build: Quiet automake warning for bupsplit Use `_SRCS` and not `_SOURCES`, the latter of which makes automake assume there's something for it to do. Closes: #749 Approved by: jlebon --- Makefile-libostree.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 15711dc9..192db36e 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -24,9 +24,9 @@ noinst_LTLIBRARIES += libostree-kernel-args.la if ENABLE_RUST bupsplitpath = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/libbupsplit_rs.a -BUPSPLIT_RUST_SOURCES = rust/src/bupsplit.rs -EXTRA_DIST += $(BUPSPLIT_RUST_SOURCES) -$(bupsplitpath): Makefile $(BUPSPLIT_RUST_SOURCES) +BUPSPLIT_RUST_SRCS = rust/src/bupsplit.rs +EXTRA_DIST += $(BUPSPLIT_RUST_SRCS) +$(bupsplitpath): Makefile $(BUPSPLIT_RUST_SRCS) cd $(top_srcdir)/rust && CARGO_TARGET_DIR=@abs_top_builddir@/target cargo build --verbose $(CARGO_RELEASE_ARGS) else bupsplitpath = libbupsplit.la From 94c47cde6a1e2f091cd4081ebfba1e8ef34eb2b5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 21 Mar 2017 15:07:41 -0400 Subject: [PATCH 16/56] build: Various fixes for openssl build This actually worked before because `pkg-config --cflags openssl` is empty, and the linker was satisfying `-lssl -lcrypto` from our indirect dependencies. Also, in fact we *currently* just want `pkg-config libcrypto` i.e. `-lcrypto`, since we aren't actually using openssl to speak TLS. This doesn't actually matter on Fedora at least since they're both in the `openssl-libs` package, but they are separate for a reason. Closes: #749 Approved by: jlebon --- Makefile-libostree.am | 5 +++-- configure.ac | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 192db36e..28126487 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -147,10 +147,11 @@ libostree_1_la_SOURCES += \ endif 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_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_OPENSSL_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions -Wl,--version-script=$(top_srcdir)/src/libostree/libostree.sym -libostree_1_la_LIBADD = libotutil.la 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) +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) libostree_1_la_LIBADD += $(bupsplitpath) EXTRA_libostree_1_la_DEPENDENCIES = $(top_srcdir)/src/libostree/libostree.sym diff --git a/configure.ac b/configure.ac index 0afd87e1..d43536e3 100644 --- a/configure.ac +++ b/configure.ac @@ -298,10 +298,10 @@ AS_IF([ test x$with_smack = xyes], [ ]) AM_CONDITIONAL(USE_SMACK, test $with_smack != no) -dnl begin openssl -OPENSSL_DEPENDENCY="libselinux >= 1.0.1" +dnl begin openssl (really just libcrypto right now) +OPENSSL_DEPENDENCY="libcrypto >= 1.0.1" AC_ARG_WITH(openssl, -AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL (checksums)]), +AS_HELP_STRING([--with-openssl], [Enable use of OpenSSL libcrypto (checksums)]), :, with_openssl=no) AS_IF([ test x$with_openssl != xno ], [ @@ -447,7 +447,7 @@ echo " HTTP backend: $fetcher_backend \"ostree trivial-httpd\": $enable_trivial_httpd_cmdline SELinux: $with_selinux - OpenSSL (checksums): $with_openssl + OpenSSL libcrypto (checksums): $with_openssl systemd: $have_libsystemd libmount: $with_libmount libarchive (parse tar files directly): $with_libarchive From 4cf210b128f390e2cdd149e40984acd239c37cd2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 21 Mar 2017 11:27:19 -0400 Subject: [PATCH 17/56] Bump libglnx, port a few callers to new error API Testing out the waters here. I think we should roll this into any future code cleanup reworking we do. Closes: #747 Approved by: jlebon --- libglnx | 2 +- src/libostree/ostree-core.c | 14 +++----------- src/libostree/ostree-repo.c | 15 +++------------ 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/libglnx b/libglnx index 5309e363..602fdd93 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 5309e363aa30d2108a264ae35d8d870ee3e0c443 +Subproject commit 602fdd93cb7a339c6b5749eee73df926429a5ab8 diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 4d7b431b..2130797e 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -1798,13 +1798,9 @@ ostree_validate_structureof_objtype (guchar objtype, GError **error) { OstreeObjectType objtype_v = (OstreeObjectType) objtype; - if (objtype_v < OSTREE_OBJECT_TYPE_FILE + if (objtype_v < OSTREE_OBJECT_TYPE_FILE || objtype_v > OSTREE_OBJECT_TYPE_COMMIT) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid object type '%u'", objtype); - return FALSE; - } + return glnx_throw (error, "Invalid object type '%u'", objtype); return TRUE; } @@ -1837,11 +1833,7 @@ ostree_validate_structureof_checksum_string (const char *checksum, size_t len = strlen (checksum); if (len != OSTREE_SHA256_STRING_LEN) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid rev '%s'", checksum); - return FALSE; - } + return glnx_throw (error, "Invalid rev '%s'", checksum); for (i = 0; i < len; i++) { diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 34da969f..733db27b 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1831,10 +1831,7 @@ ostree_repo_create (OstreeRepo *self, if (mkdir (repopath, 0755) != 0) { if (G_UNLIKELY (errno != EEXIST)) - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); } if (!glnx_opendirat (AT_FDCWD, repopath, TRUE, &dfd, error)) @@ -1858,10 +1855,7 @@ ostree_repo_create (OstreeRepo *self, return FALSE; } else - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); } for (guint i = 0; i < G_N_ELEMENTS (state_dirs); i++) @@ -1870,10 +1864,7 @@ ostree_repo_create (OstreeRepo *self, if (mkdirat (dfd, elt, 0755) == -1) { if (G_UNLIKELY (errno != EEXIST)) - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); } } From d7f4a326b98cb1bfe3fb939348620013e1ec5a9b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 18 Mar 2017 09:49:59 -0400 Subject: [PATCH 18/56] sepolicy: Add ostree_sepolicy_new_at() I'm porting other code away from `GFile`, and while we don't use this internally, it will let us do so at a later date. I'm averse to changing the code right now as we don't have good CI coverage of this. Closes: #746 Approved by: jlebon --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree.sym | 1 + src/libostree/ostree-sepolicy.c | 64 ++++++++++++++++++++++++++++++--- src/libostree/ostree-sepolicy.h | 6 ++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 027f25c5..c323065f 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -426,6 +426,7 @@ ostree_repo_file_get_type ostree-sepolicy OstreeSePolicy ostree_sepolicy_new +ostree_sepolicy_new_at ostree_sepolicy_get_path ostree_sepolicy_get_name ostree_sepolicy_get_label diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 649c6f1f..8530bc75 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -390,6 +390,7 @@ LIBOSTREE_2017.4 { global: ostree_check_version; ostree_diff_dirs_with_options; + ostree_sepolicy_new_at; } LIBOSTREE_2017.3; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index 716cbd8c..833583da 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -42,6 +42,8 @@ struct OstreeSePolicy { GObject parent; + int rootfs_dfd; + int rootfs_dfd_owned; GFile *path; gboolean runtime_enabled; @@ -63,7 +65,8 @@ static void initable_iface_init (GInitableIface *initable_iface); enum { PROP_0, - PROP_PATH + PROP_PATH, + PROP_ROOTFS_DFD }; G_DEFINE_TYPE_WITH_CODE (OstreeSePolicy, ostree_sepolicy, G_TYPE_OBJECT, @@ -75,6 +78,8 @@ ostree_sepolicy_finalize (GObject *object) OstreeSePolicy *self = OSTREE_SEPOLICY (object); g_clear_object (&self->path); + if (self->rootfs_dfd_owned != -1) + (void) close (self->rootfs_dfd_owned); #ifdef HAVE_SELINUX g_clear_object (&self->selinux_policy_root); g_clear_pointer (&self->selinux_policy_name, g_free); @@ -100,8 +105,22 @@ ostree_sepolicy_set_property(GObject *object, switch (prop_id) { case PROP_PATH: - /* Canonicalize */ - self->path = g_file_new_for_path (gs_file_get_path_cached (g_value_get_object (value))); + { + GFile *path = g_value_get_object (value); + if (path) + { + /* Canonicalize */ + self->path = g_file_new_for_path (gs_file_get_path_cached (path)); + } + self->rootfs_dfd = -1; + } + break; + case PROP_ROOTFS_DFD: + { + self->rootfs_dfd = g_value_get_int (value); + g_clear_object (&self->path); + self->path = ot_fdrel_to_gfile (self->rootfs_dfd, "."); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -122,6 +141,9 @@ ostree_sepolicy_get_property(GObject *object, case PROP_PATH: g_value_set_object (value, self->path); break; + case PROP_ROOTFS_DFD: + g_value_set_int (value, self->rootfs_dfd); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -133,7 +155,7 @@ ostree_sepolicy_constructed (GObject *object) { OstreeSePolicy *self = OSTREE_SEPOLICY (object); - g_assert (self->path != NULL); + g_assert (self->path != NULL || self->rootfs_dfd != -1); G_OBJECT_CLASS (ostree_sepolicy_parent_class)->constructed (object); } @@ -155,6 +177,13 @@ ostree_sepolicy_class_init (OstreeSePolicyClass *klass) "", G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, + PROP_ROOTFS_DFD, + g_param_spec_int ("rootfs-dfd", + "", "", + -1, G_MAXINT, -1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + } #ifdef HAVE_SELINUX @@ -262,6 +291,15 @@ initable_init (GInitable *initable, const char *selinux_prefix = "SELINUX="; const char *selinuxtype_prefix = "SELINUXTYPE="; + /* TODO - use this below */ + if (self->rootfs_dfd == -1) + { + if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->path), TRUE, + &self->rootfs_dfd_owned, error)) + goto out; + self->rootfs_dfd = self->rootfs_dfd_owned; + } + etc_selinux_dir = g_file_resolve_relative_path (self->path, "etc/selinux"); if (!g_file_query_exists (etc_selinux_dir, NULL)) { @@ -367,6 +405,8 @@ initable_init (GInitable *initable, static void ostree_sepolicy_init (OstreeSePolicy *self) { + self->rootfs_dfd = -1; + self->rootfs_dfd_owned = -1; } static void @@ -391,6 +431,22 @@ ostree_sepolicy_new (GFile *path, return g_initable_new (OSTREE_TYPE_SEPOLICY, cancellable, error, "path", path, NULL); } +/** + * ostree_sepolicy_new_at: + * @rootfs_dfd: Directory fd for rootfs (will not be cloned) + * @cancellable: Cancellable + * @error: Error + * + * Returns: (transfer full): An accessor object for SELinux policy in root located at @rootfs_dfd + */ +OstreeSePolicy* +ostree_sepolicy_new_at (int rootfs_dfd, + GCancellable *cancellable, + GError **error) +{ + return g_initable_new (OSTREE_TYPE_SEPOLICY, cancellable, error, "rootfs-dfd", rootfs_dfd, NULL); +} + /** * ostree_sepolicy_get_path: * @self: diff --git a/src/libostree/ostree-sepolicy.h b/src/libostree/ostree-sepolicy.h index d204953e..1c1a5786 100644 --- a/src/libostree/ostree-sepolicy.h +++ b/src/libostree/ostree-sepolicy.h @@ -38,6 +38,12 @@ OstreeSePolicy* ostree_sepolicy_new (GFile *path, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +OstreeSePolicy* ostree_sepolicy_new_at (int rootfs_dfd, + GCancellable *cancellable, + GError **error); + + _OSTREE_PUBLIC GFile * ostree_sepolicy_get_path (OstreeSePolicy *self); From 7b2370dc869ce5ba76769853ef7fd0b081b15010 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 20 Mar 2017 20:51:22 -0400 Subject: [PATCH 19/56] sepolicy: Add better private API for setfscreatecon Use `g_auto()` more sanely with a struct implmenting the "is initialized" pattern. This is way less ugly for callers, and fixes bugs like us calling `setfscreatecon()` even if an error occurred beforehand. Also fold in the logic for "NULL or not loaded" sepolicy into the setup rather than requiring callers to inline it. Prep for more users of this function. Closes: #746 Approved by: jlebon --- src/libostree/ostree-sepolicy-private.h | 41 ++++++++++++++++++++++++ src/libostree/ostree-sepolicy.c | 29 +++++++++++++++++ src/libostree/ostree-sysroot-deploy.c | 42 +++++++------------------ 3 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 src/libostree/ostree-sepolicy-private.h diff --git a/src/libostree/ostree-sepolicy-private.h b/src/libostree/ostree-sepolicy-private.h new file mode 100644 index 00000000..55d49eaf --- /dev/null +++ b/src/libostree/ostree-sepolicy-private.h @@ -0,0 +1,41 @@ +/* -*- 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 + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include "ostree-types.h" + +G_BEGIN_DECLS + +typedef struct { + gboolean initialized; +} OstreeSepolicyFsCreatecon; + +void _ostree_sepolicy_fscreatecon_clear (OstreeSepolicyFsCreatecon *con); +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(OstreeSepolicyFsCreatecon, _ostree_sepolicy_fscreatecon_clear) + +gboolean _ostree_sepolicy_preparefscreatecon (OstreeSepolicyFsCreatecon *con, + OstreeSePolicy *self, + const char *path, + guint32 mode, + GError **error); + + +G_END_DECLS diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index 833583da..ea4e46b1 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -28,6 +28,7 @@ #include "otutil.h" #include "ostree-sepolicy.h" +#include "ostree-sepolicy-private.h" #include "ostree-bootloader-uboot.h" #include "ostree-bootloader-syslinux.h" @@ -690,3 +691,31 @@ ostree_sepolicy_fscreatecon_cleanup (void **unused) setfscreatecon (NULL); #endif } + +/* Currently private copy of the older sepolicy/fscreatecon API with a nicer + * g_auto() cleanup. May be made public later. + */ +gboolean +_ostree_sepolicy_preparefscreatecon (OstreeSepolicyFsCreatecon *con, + OstreeSePolicy *self, + const char *path, + guint32 mode, + GError **error) +{ + if (!self || ostree_sepolicy_get_name (self) == NULL) + return TRUE; + + if (!ostree_sepolicy_setfscreatecon (self, path, mode, error)) + return FALSE; + + con->initialized = TRUE; + return TRUE; +} + +void +_ostree_sepolicy_fscreatecon_clear (OstreeSepolicyFsCreatecon *con) +{ + if (!con->initialized) + return; + ostree_sepolicy_fscreatecon_cleanup (NULL); +} diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 6bf01a16..45707fe7 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -30,6 +30,7 @@ #endif #include "ostree-sysroot-private.h" +#include "ostree-sepolicy-private.h" #include "ostree-deployment-private.h" #include "ostree-core-private.h" #include "ostree-linuxfsutil.h" @@ -733,21 +734,13 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, return FALSE; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - { ostree_cleanup_sepolicy_fscreatecon gpointer dummy = NULL; -#pragma GCC diagnostic pop + { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; + const char *selabeled_abspath = glnx_strjoina ("/", selabeled); - if (sysroot->sepolicy != NULL - && ostree_sepolicy_get_name (sysroot->sepolicy) != NULL) - { - const char *selabeled_abspath = glnx_strjoina ("/", selabeled); - if (!ostree_sepolicy_setfscreatecon (sysroot->sepolicy, - selabeled_abspath, - 0644, - error)) - return FALSE; - } + if (!_ostree_sepolicy_preparefscreatecon (&con, sysroot->sepolicy, + selabeled_abspath, + 0644, error)) + return FALSE; if (!glnx_file_replace_contents_at (os_deploy_dfd, selabeled, (guint8*)"", 0, GLNX_FILE_REPLACE_DATASYNC_NEW, @@ -2112,23 +2105,12 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, return FALSE; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" - { ostree_cleanup_sepolicy_fscreatecon gpointer dummy = NULL; -#pragma GCC diagnostic pop + { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; - /* Explicitly override the label for the origin file to ensure - * it's system_conf_t. - */ - if (self->sepolicy != NULL - && ostree_sepolicy_get_name (self->sepolicy) != NULL) - { - if (!ostree_sepolicy_setfscreatecon (self->sepolicy, - "/etc/ostree/remotes.d/dummy.conf", - 0644, - error)) - return FALSE; - } + if (!_ostree_sepolicy_preparefscreatecon (&con, self->sepolicy, + "/etc/ostree/remotes.d/dummy.conf", + 0644, error)) + return FALSE; /* Don't fsync here, as we assume that's all done in * ostree_sysroot_write_deployments(). From f6255763fda0ecd8126bd5436ab25839ac59bb5e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 23 Mar 2017 12:07:06 -0400 Subject: [PATCH 20/56] cfg.mk: Add a syntax check for a redundant : in glnx_throw This is going to be an easy bug to make when porting. Example spotted by jlebon in https://github.com/ostreedev/ostree/pull/752/files/435c2dc35c06218b8fe5b4ede0fe4f6cda535b45#diff-dbc2359685171239c4708f2a8f6aa921 Closes: #752 Approved by: jlebon --- cfg.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cfg.mk b/cfg.mk index d6a5039d..b4ffaf5f 100644 --- a/cfg.mk +++ b/cfg.mk @@ -23,6 +23,10 @@ local-checks-to-skip = \ sc_prohibit_path_max_allocation \ sc_trailing_blank \ +sc_glnx_errno_prefix_colon: + @prohibit='\ Date: Wed, 22 Mar 2017 14:10:53 -0400 Subject: [PATCH 21/56] repo/refs: Convert to new code style I happened to be reading this one recently for a reason I forget, and it's a relatively easy conversion. Also one not conflicting with any outstanding patches. Closes: #752 Approved by: jlebon --- src/libostree/ostree-repo-refs.c | 284 +++++++++++-------------------- 1 file changed, 100 insertions(+), 184 deletions(-) diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index 18308d0c..adab50fe 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -32,30 +32,23 @@ add_ref_to_set (const char *remote, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - char *contents; gsize len; - GString *refname; - - contents = glnx_file_get_contents_utf8_at (base_fd, path, &len, cancellable, error); + char *contents = glnx_file_get_contents_utf8_at (base_fd, path, &len, cancellable, error); if (!contents) - goto out; + return FALSE; g_strchomp (contents); - refname = g_string_new (""); + g_autoptr(GString) refname = g_string_new (""); if (remote) { g_string_append (refname, remote); g_string_append_c (refname, ':'); } g_string_append (refname, path); - - g_hash_table_insert (refs, g_string_free (refname, FALSE), contents); + g_hash_table_insert (refs, g_string_free (g_steal_pointer (&refname), FALSE), contents); - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -66,27 +59,16 @@ write_checksum_file_at (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - const char *lastslash; - if (!ostree_validate_checksum_string (sha256, error)) - goto out; + return FALSE; if (ostree_validate_checksum_string (name, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Rev name '%s' looks like a checksum", name); - goto out; - } + return glnx_throw (error, "Rev name '%s' looks like a checksum", name); if (!*name) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid empty ref name"); - goto out; - } + return glnx_throw (error, "Invalid empty ref name"); - lastslash = strrchr (name, '/'); + const char *lastslash = strrchr (name, '/'); if (lastslash) { @@ -94,7 +76,7 @@ write_checksum_file_at (OstreeRepo *self, parent[lastslash - name] = '\0'; if (!glnx_shutil_mkdir_p_at (dfd, parent, 0777, cancellable, error)) - goto out; + return FALSE; } { @@ -118,38 +100,32 @@ write_checksum_file_at (OstreeRepo *self, g_clear_error (&temp_error); if (!ostree_repo_list_refs (self, name, &refs, cancellable, error)) - goto out; + return FALSE; g_hash_table_iter_init (&hashiter, refs); while ((g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue))) { if (strcmp (name, (char *)hashkey) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Conflict: %s exists under %s when attempting write", (char*)hashkey, name); - goto out; - } + return glnx_throw (error, "Conflict: %s exists under %s when attempting write", (char*)hashkey, name); } if (!glnx_shutil_rm_rf_at (dfd, name, cancellable, error)) - goto out; + return FALSE; if (!_ostree_repo_file_replace_contents (self, dfd, name, (guint8*)bufnl, l + 1, cancellable, error)) - goto out; + return FALSE; } else { g_propagate_error (error, g_steal_pointer (&temp_error)); - goto out; + return FALSE; } } } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -158,12 +134,11 @@ find_ref_in_remotes (OstreeRepo *self, int *out_fd, GError **error) { - gboolean ret = FALSE; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; glnx_fd_close int ret_fd = -1; if (!glnx_dirfd_iterator_init_at (self->repo_dir_fd, "refs/remotes", TRUE, &dfd_iter, error)) - goto out; + return FALSE; while (TRUE) { @@ -171,7 +146,7 @@ find_ref_in_remotes (OstreeRepo *self, glnx_fd_close int remote_dfd = -1; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, NULL, error)) - goto out; + return FALSE; if (dent == NULL) break; @@ -179,19 +154,17 @@ find_ref_in_remotes (OstreeRepo *self, continue; if (!glnx_opendirat (dfd_iter.fd, dent->d_name, TRUE, &remote_dfd, error)) - goto out; + return FALSE; if (!ot_openat_ignore_enoent (remote_dfd, rev, &ret_fd, error)) - goto out; + return FALSE; if (ret_fd != -1) break; } - ret = TRUE; *out_fd = ret_fd; ret_fd = -1; - out: - return ret; + return TRUE; } static gboolean @@ -213,14 +186,13 @@ resolve_refspec_fallback (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autofree char *ret_rev = NULL; if (self->parent_repo) { if (!resolve_refspec (self->parent_repo, remote, ref, allow_noent, fallback_remote, &ret_rev, error)) - goto out; + return FALSE; } else if (!allow_noent) { @@ -229,13 +201,11 @@ resolve_refspec_fallback (OstreeRepo *self, remote ? remote : "", remote ? ":" : "", ref); - goto out; + return FALSE; } - ret = TRUE; ot_transfer_out_value (out_rev, &ret_rev); - out: - return ret; + return TRUE; } static gboolean @@ -247,11 +217,10 @@ resolve_refspec (OstreeRepo *self, char **out_rev, GError **error) { - gboolean ret = FALSE; __attribute__((unused)) GCancellable *cancellable = NULL; g_autofree char *ret_rev = NULL; glnx_fd_close int target_fd = -1; - + g_return_val_if_fail (ref != NULL, FALSE); /* We intentionally don't allow a ref that looks like a checksum */ @@ -264,26 +233,26 @@ resolve_refspec (OstreeRepo *self, const char *remote_ref = glnx_strjoina ("refs/remotes/", remote, "/", ref); if (!ot_openat_ignore_enoent (self->repo_dir_fd, remote_ref, &target_fd, error)) - goto out; + return FALSE; } else { const char *local_ref = glnx_strjoina ("refs/heads/", ref); if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error)) - goto out; + return FALSE; if (target_fd == -1 && fallback_remote) { local_ref = glnx_strjoina ("refs/remotes/", ref); if (!ot_openat_ignore_enoent (self->repo_dir_fd, local_ref, &target_fd, error)) - goto out; + return FALSE; if (target_fd == -1) { if (!find_ref_in_remotes (self, ref, &target_fd, error)) - goto out; + return FALSE; } } } @@ -294,24 +263,22 @@ resolve_refspec (OstreeRepo *self, if (!ret_rev) { g_prefix_error (error, "Couldn't open ref '%s': ", ref); - goto out; + return FALSE; } - + g_strchomp (ret_rev); if (!ostree_validate_checksum_string (ret_rev, error)) - goto out; + return FALSE; } else { if (!resolve_refspec_fallback (self, remote, ref, allow_noent, fallback_remote, &ret_rev, cancellable, error)) - goto out; + return FALSE; } ot_transfer_out_value (out_rev, &ret_rev); - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -330,65 +297,51 @@ ostree_repo_resolve_partial_checksum (OstreeRepo *self, char **full_checksum, GError **error) { - gboolean ret = FALSE; static const char hexchars[] = "0123456789abcdef"; - gsize off; - g_autoptr(GHashTable) ref_list = NULL; g_autofree char *ret_rev = NULL; - guint length; - const char *checksum = NULL; - OstreeObjectType objtype; - GHashTableIter hashiter; - gpointer key, value; - GVariant *first_commit; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* If the input is longer than OSTREE_SHA256_STRING_LEN chars or contains non-hex chars, don't bother looking for it as an object */ - off = strspn (refspec, hexchars); + const gsize off = strspn (refspec, hexchars); if (off > OSTREE_SHA256_STRING_LEN || refspec[off] != '\0') return TRUE; /* this looks through all objects and adds them to the ref_list if: a) they are a commit object AND b) the obj checksum starts with the partual checksum defined by "refspec" */ + g_autoptr(GHashTable) ref_list = NULL; if (!ostree_repo_list_commit_objects_starting_with (self, refspec, &ref_list, NULL, error)) - goto out; + return FALSE; - length = g_hash_table_size (ref_list); + guint length = g_hash_table_size (ref_list); + GHashTableIter hashiter; + gpointer key, value; + GVariant *first_commit = NULL; g_hash_table_iter_init (&hashiter, ref_list); if (g_hash_table_iter_next (&hashiter, &key, &value)) first_commit = (GVariant*) key; - else - first_commit = NULL; - if (first_commit) + OstreeObjectType objtype; + const char *checksum = NULL; + if (first_commit) ostree_object_name_deserialize (first_commit, &checksum, &objtype); /* length more than one - multiple commits match partial refspec: is not unique */ if (length > 1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Refspec %s not unique", refspec); - goto out; - } - + return glnx_throw (error, "Refspec %s not unique", refspec); /* length is 1 - a single matching commit gives us our revision */ else if (length == 1) - { - ret_rev = g_strdup (checksum); - } + ret_rev = g_strdup (checksum); /* Note: if length is 0, then code will return TRUE because there is no error, but it will return full_checksum = NULL to signal to continue parsing */ - ret = TRUE; ot_transfer_out_value (full_checksum, &ret_rev); - out: - return ret; + return TRUE; } static gboolean @@ -399,7 +352,6 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self, char **out_rev, GError **error) { - gboolean ret = FALSE; g_autofree char *ret_rev = NULL; g_return_val_if_fail (refspec != NULL, FALSE); @@ -410,12 +362,12 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self, } else if (!ostree_repo_resolve_partial_checksum (self, refspec, &ret_rev, error)) - goto out; + return FALSE; if (!ret_rev) { if (error != NULL && *error != NULL) - goto out; + return FALSE; if (g_str_has_suffix (refspec, "^")) { @@ -427,18 +379,14 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self, parent_refspec[strlen(parent_refspec) - 1] = '\0'; if (!ostree_repo_resolve_rev (self, parent_refspec, allow_noent, &parent_rev, error)) - goto out; - + return FALSE; + if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, parent_rev, &commit, error)) - goto out; - + return FALSE; + if (!(ret_rev = ostree_commit_get_parent (commit))) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Commit %s has no parent", parent_rev); - goto out; - } + return glnx_throw (error, "Commit %s has no parent", parent_rev); } else { @@ -446,18 +394,16 @@ _ostree_repo_resolve_rev_internal (OstreeRepo *self, g_autofree char *ref = NULL; if (!ostree_parse_refspec (refspec, &remote, &ref, error)) - goto out; - + return FALSE; + if (!resolve_refspec (self, remote, ref, allow_noent, fallback_remote, &ret_rev, error)) - goto out; + return FALSE; } } - ret = TRUE; ot_transfer_out_value (out_rev, &ret_rev); - out: - return ret; + return TRUE; } /** @@ -518,11 +464,10 @@ enumerate_refs_recurse (OstreeRepo *repo, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!glnx_dirfd_iterator_init_at (child_dfd, path, FALSE, &dfd_iter, error)) - goto out; + return FALSE; while (TRUE) { @@ -530,7 +475,7 @@ enumerate_refs_recurse (OstreeRepo *repo, struct dirent *dent = NULL; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) - goto out; + return FALSE; if (dent == NULL) break; @@ -543,22 +488,19 @@ enumerate_refs_recurse (OstreeRepo *repo, if (!enumerate_refs_recurse (repo, remote, base_dfd, base_path, dfd_iter.fd, dent->d_name, refs, cancellable, error)) - goto out; - + return FALSE; } else if (dent->d_type == DT_REG) { if (!add_ref_to_set (remote, base_dfd, base_path->str, refs, cancellable, error)) - goto out; + return FALSE; } g_string_truncate (base_path, len); } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -569,7 +511,6 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GHashTable) ret_all_refs = NULL; g_autofree char *remote = NULL; g_autofree char *ref_prefix = NULL; @@ -583,7 +524,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, const char *path; if (!ostree_parse_refspec (refspec_prefix, &remote, &ref_prefix, error)) - goto out; + return FALSE; if (remote) { @@ -599,10 +540,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, if (fstatat (self->repo_dir_fd, path, &stbuf, 0) < 0) { if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); } else { @@ -614,23 +552,23 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, g_string_printf (base_path, "%s/", ref_prefix); if (!glnx_opendirat (self->repo_dir_fd, cut_prefix ? path : prefix_path, TRUE, &base_fd, error)) - goto out; + return FALSE; if (!enumerate_refs_recurse (self, remote, base_fd, base_path, base_fd, cut_prefix ? "." : ref_prefix, ret_all_refs, cancellable, error)) - goto out; + return FALSE; } else { glnx_fd_close int prefix_dfd = -1; - + if (!glnx_opendirat (self->repo_dir_fd, prefix_path, TRUE, &prefix_dfd, error)) - goto out; + return FALSE; if (!add_ref_to_set (remote, prefix_dfd, ref_prefix, ret_all_refs, cancellable, error)) - goto out; + return FALSE; } } } @@ -639,19 +577,19 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; g_autoptr(GString) base_path = g_string_new (""); glnx_fd_close int refs_heads_dfd = -1; - + if (!glnx_opendirat (self->repo_dir_fd, "refs/heads", TRUE, &refs_heads_dfd, error)) - goto out; + return FALSE; if (!enumerate_refs_recurse (self, NULL, refs_heads_dfd, base_path, refs_heads_dfd, ".", ret_all_refs, cancellable, error)) - goto out; + return FALSE; g_string_truncate (base_path, 0); if (!glnx_dirfd_iterator_init_at (self->repo_dir_fd, "refs/remotes", TRUE, &dfd_iter, error)) - goto out; + return FALSE; while (TRUE) { @@ -659,7 +597,7 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, glnx_fd_close int remote_dfd = -1; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) - goto out; + return FALSE; if (!dent) break; @@ -667,20 +605,18 @@ _ostree_repo_list_refs_internal (OstreeRepo *self, continue; if (!glnx_opendirat (dfd_iter.fd, dent->d_name, TRUE, &remote_dfd, error)) - goto out; - + return FALSE; + if (!enumerate_refs_recurse (self, dent->d_name, remote_dfd, base_path, remote_dfd, ".", ret_all_refs, cancellable, error)) - goto out; + return FALSE; } } - ret = TRUE; ot_transfer_out_value (out_all_refs, &ret_all_refs); - out: - return ret; + return TRUE; } /** @@ -748,19 +684,16 @@ ostree_repo_remote_list_refs (OstreeRepo *self, GError **error) { g_autoptr(GBytes) summary_bytes = NULL; - gboolean ret = FALSE; g_autoptr(GHashTable) ret_all_refs = NULL; if (!ostree_repo_remote_fetch_summary (self, remote_name, &summary_bytes, NULL, cancellable, error)) - goto out; + return FALSE; if (summary_bytes == NULL) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Remote refs not available; server has no summary file\n"); - goto out; + return glnx_throw (error, "Remote refs not available; server has no summary file"); } else { @@ -786,12 +719,11 @@ ostree_repo_remote_list_refs (OstreeRepo *self, if (ref_name != NULL) { - const guchar *csum_bytes; - g_variant_get_child (child, 1, "(t@aya{sv})", NULL, &csum_v, NULL); - csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, error); + + const guchar *csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, error); if (csum_bytes == NULL) - goto out; + return FALSE; ostree_checksum_inplace_from_bytes (csum_bytes, tmp_checksum); @@ -804,14 +736,11 @@ ostree_repo_remote_list_refs (OstreeRepo *self, } } - ret = TRUE; ot_transfer_out_value (out_all_refs, &ret_all_refs); - - out: - return ret; + return TRUE; } -gboolean +gboolean _ostree_repo_write_ref (OstreeRepo *self, const char *remote, const char *ref, @@ -819,7 +748,6 @@ _ostree_repo_write_ref (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; glnx_fd_close int dfd = -1; if (remote == NULL) @@ -828,7 +756,7 @@ _ostree_repo_write_ref (OstreeRepo *self, &dfd, error)) { g_prefix_error (error, "Opening %s: ", "refs/heads"); - goto out; + return FALSE; } } else @@ -839,23 +767,19 @@ _ostree_repo_write_ref (OstreeRepo *self, &refs_remotes_dfd, error)) { g_prefix_error (error, "Opening %s: ", "refs/remotes"); - goto out; + return FALSE; } if (rev != NULL) { /* Ensure we have a dir for the remote */ if (!glnx_shutil_mkdir_p_at (refs_remotes_dfd, remote, 0777, cancellable, error)) - goto out; + return FALSE; } dfd = glnx_opendirat_with_errno (refs_remotes_dfd, remote, TRUE); if (dfd < 0 && (errno != ENOENT || rev != NULL)) - { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Opening remotes/ dir %s: ", remote); - goto out; - } + return glnx_throw_errno_prefix (error, "Opening remotes/ dir %s", remote); } if (rev == NULL) @@ -863,27 +787,22 @@ _ostree_repo_write_ref (OstreeRepo *self, if (dfd >= 0) { if (unlinkat (dfd, ref, 0) != 0) - { - if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - goto out; - } - } + { + if (errno != ENOENT) + return glnx_throw_errno (error); + } } } else { if (!write_checksum_file_at (self, dfd, ref, rev, cancellable, error)) - goto out; + return FALSE; } if (!_ostree_repo_update_mtime (self, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } gboolean @@ -892,7 +811,6 @@ _ostree_repo_update_refs (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; GHashTableIter hash_iter; gpointer key, value; @@ -905,14 +823,12 @@ _ostree_repo_update_refs (OstreeRepo *self, g_autofree char *ref = NULL; if (!ostree_parse_refspec (refspec, &remote, &ref, error)) - goto out; + return FALSE; if (!_ostree_repo_write_ref (self, remote, ref, rev, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } From a5d5333c83c7d0a7ec477243ec602987bf104ce5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 20 Mar 2017 10:19:04 -0400 Subject: [PATCH 22/56] sysroot: Add ostree_sysroot_write_deployments_with_options() More sophisticated users of libostree like rpm-ostree need control over things like the system repository. Previously we introduced a "no cleanup" flag to `ostree_sysroot_simple_write_deployment()`, but that's a high level API that does filtering on its own. Since rpm-ostree needs more control, let's expose the bare essentials of the "sysroot commit" operation with an extensible options structure, where one of the options is whether or not to do post-transaction repository operations. Closes: #745 Approved by: jlebon --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree.sym | 1 + src/libostree/ostree-sysroot-deploy.c | 36 +++++++++++++++++++------- src/libostree/ostree-sysroot-private.h | 6 ----- src/libostree/ostree-sysroot.c | 5 ++-- src/libostree/ostree-sysroot.h | 14 ++++++++++ 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index c323065f..6f0cf4a8 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -473,6 +473,7 @@ ostree_sysroot_deployment_set_kargs ostree_sysroot_deployment_set_mutable ostree_sysroot_deployment_unlock ostree_sysroot_write_deployments +ostree_sysroot_write_deployments_with_options ostree_sysroot_write_origin_file ostree_sysroot_deploy_tree ostree_sysroot_get_merge_deployment diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 8530bc75..749b0c36 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -391,6 +391,7 @@ global: ostree_check_version; ostree_diff_dirs_with_options; ostree_sepolicy_new_at; + ostree_sysroot_write_deployments_with_options; } LIBOSTREE_2017.3; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 45707fe7..acbf4619 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1686,8 +1686,8 @@ is_ro_mount (const char *path) * @cancellable: Cancellable * @error: Error * - * Assuming @new_deployments have already been deployed in place on - * disk, atomically update bootloader configuration. + * Older version of ostree_sysroot_write_deployments_with_options(). This + * version will perform post-deployment cleanup by default. */ gboolean ostree_sysroot_write_deployments (OstreeSysroot *self, @@ -1695,16 +1695,32 @@ ostree_sysroot_write_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - return _ostree_sysroot_write_deployments_internal (self, new_deployments, - TRUE, cancellable, error); + OstreeSysrootWriteDeploymentsOpts opts = { .do_postclean = TRUE }; + return ostree_sysroot_write_deployments_with_options (self, new_deployments, &opts, + cancellable, error); } +/** + * ostree_sysroot_write_deployments_with_options: + * @self: Sysroot + * @new_deployments: (element-type OstreeDeployment): List of new deployments + * @opts: Options + * @cancellable: Cancellable + * @error: Error + * + * Assuming @new_deployments have already been deployed in place on disk via + * ostree_sysroot_deploy_tree(), atomically update bootloader configuration. By + * default, no post-transaction cleanup will be performed. You should invoke + * ostree_sysroot_cleanup() at some point after the transaction, or specify + * `do_postclean` in @opts. Skipping the post-transaction cleanup is useful + * if for example you want to control pruning of the repository. + */ gboolean -_ostree_sysroot_write_deployments_internal (OstreeSysroot *self, - GPtrArray *new_deployments, - gboolean do_clean, - GCancellable *cancellable, - GError **error) +ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, + GPtrArray *new_deployments, + OstreeSysrootWriteDeploymentsOpts *opts, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; guint i; @@ -1930,7 +1946,7 @@ _ostree_sysroot_write_deployments_internal (OstreeSysroot *self, /* And finally, cleanup of any leftover data. */ - if (do_clean) + if (opts->do_postclean) { if (!ostree_sysroot_cleanup (self, cancellable, error)) { diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 18fc0cb0..c2f5d2d9 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -114,10 +114,4 @@ gboolean _ostree_sysroot_cleanup_internal (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error); -gboolean _ostree_sysroot_write_deployments_internal (OstreeSysroot *self, - GPtrArray *new_deployments, - gboolean do_clean, - GCancellable *cancellable, - GError **error); - G_END_DECLS diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 575cb6df..c4f608a2 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1553,6 +1553,7 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, g_autoptr(GPtrArray) deployments = NULL; g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref); const gboolean postclean = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN) == 0; + OstreeSysrootWriteDeploymentsOpts write_opts = { .do_postclean = postclean }; gboolean retain = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN) > 0; const gboolean make_default = !((flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT) > 0); gboolean added_new = FALSE; @@ -1603,8 +1604,8 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, added_new = TRUE; } - if (!_ostree_sysroot_write_deployments_internal (sysroot, new_deployments, - postclean, cancellable, error)) + if (!ostree_sysroot_write_deployments_with_options (sysroot, new_deployments, &write_opts, + cancellable, error)) goto out; ret = TRUE; diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index 1e98cc10..09614b55 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -145,6 +145,20 @@ gboolean ostree_sysroot_write_deployments (OstreeSysroot *self, GCancellable *cancellable, GError **error); +typedef struct { + gboolean do_postclean; + gboolean unused_bools[7]; + int unused_ints[7]; + gpointer unused_ptrs[7]; +} OstreeSysrootWriteDeploymentsOpts; + +_OSTREE_PUBLIC +gboolean ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, + GPtrArray *new_deployments, + OstreeSysrootWriteDeploymentsOpts *opts, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC gboolean ostree_sysroot_deploy_tree (OstreeSysroot *self, const char *osname, From 193f5c16f27580e6639c483179993b5695b051e0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 23 Mar 2017 08:59:33 -0400 Subject: [PATCH 23/56] core: Convert some functions to new code style Not doing the whole file since it's big, these are some simple ones to keep momentum up. Closes: #753 Approved by: jlebon --- src/libostree/ostree-core.c | 135 +++++++++++------------------------- 1 file changed, 39 insertions(+), 96 deletions(-) diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 2130797e..bab2ab33 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -121,13 +121,8 @@ ostree_parse_refspec (const char *refspec, char **out_ref, GError **error) { - gboolean ret = FALSE; - GMatchInfo *match = NULL; - g_autofree char *remote = NULL; - - static gsize regex_initialized; static GRegex *regex; - + static gsize regex_initialized; if (g_once_init_enter (®ex_initialized)) { regex = g_regex_new ("^(" OSTREE_REF_FRAGMENT_REGEXP ":)?(" OSTREE_REF_REGEXP ")$", 0, 0, NULL); @@ -135,14 +130,11 @@ ostree_parse_refspec (const char *refspec, g_once_init_leave (®ex_initialized, 1); } + g_autoptr(GMatchInfo) match = NULL; if (!g_regex_match (regex, refspec, 0, &match)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid refspec %s", refspec); - goto out; - } + return glnx_throw (error, "Invalid refspec %s", refspec); - remote = g_match_info_fetch (match, 1); + g_autofree char *remote = g_match_info_fetch (match, 1); if (*remote == '\0') { g_clear_pointer (&remote, g_free); @@ -153,16 +145,11 @@ ostree_parse_refspec (const char *refspec, remote[strlen(remote)-1] = '\0'; } - ret = TRUE; - if (out_remote) *out_remote = g_steal_pointer (&remote); if (out_ref != NULL) *out_ref = g_match_info_fetch (match, 2); - out: - if (match) - g_match_info_unref (match); - return ret; + return TRUE; } /** @@ -176,12 +163,10 @@ gboolean ostree_validate_rev (const char *rev, GError **error) { - gboolean ret = FALSE; - GMatchInfo *match = NULL; + g_autoptr(GMatchInfo) match = NULL; static gsize regex_initialized; static GRegex *regex; - if (g_once_init_enter (®ex_initialized)) { regex = g_regex_new ("^" OSTREE_REF_REGEXP "$", 0, 0, NULL); @@ -190,17 +175,9 @@ ostree_validate_rev (const char *rev, } if (!g_regex_match (regex, rev, 0, &match)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid ref name %s", rev); - goto out; - } + return glnx_throw (error, "Invalid ref name %s", rev); - ret = TRUE; - out: - if (match) - g_match_info_unref (match); - return ret; + return TRUE; } GVariant * @@ -282,7 +259,6 @@ write_padding (GOutputStream *output, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; guint bits; guint padding_len; guchar padding_nuls[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -298,12 +274,10 @@ write_padding (GOutputStream *output, if (!ot_gio_write_update_checksum (output, (guchar*)padding_nuls, padding_len, out_bytes_written, checksum, cancellable, error)) - goto out; + return FALSE; } - - ret = TRUE; - out: - return ret; + + return TRUE; } /* @@ -330,7 +304,6 @@ _ostree_write_variant_with_size (GOutputStream *output, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; guint64 variant_size; guint32 variant_size_u32_be; gsize bytes_written; @@ -345,7 +318,7 @@ _ostree_write_variant_with_size (GOutputStream *output, if (!ot_gio_write_update_checksum (output, &variant_size_u32_be, 4, &bytes_written, checksum, cancellable, error)) - goto out; + return FALSE; ret_bytes_written += bytes_written; alignment_offset += bytes_written; @@ -353,21 +326,19 @@ _ostree_write_variant_with_size (GOutputStream *output, /* Pad to offset of 8, write variant */ if (!write_padding (output, 8, alignment_offset, &bytes_written, checksum, cancellable, error)) - goto out; + return FALSE; ret_bytes_written += bytes_written; bytes_written = 0; if (!ot_gio_write_update_checksum (output, g_variant_get_data (variant), variant_size, &bytes_written, checksum, cancellable, error)) - goto out; + return FALSE; ret_bytes_written += bytes_written; - ret = TRUE; if (out_bytes_written) *out_bytes_written = ret_bytes_written; - out: - return ret; + return TRUE; } /* @@ -388,16 +359,13 @@ write_file_header_update_checksum (GOutputStream *out, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; gsize bytes_written; if (!_ostree_write_variant_with_size (out, header, 0, &bytes_written, checksum, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /* @@ -724,32 +692,28 @@ ostree_content_file_parse_at (gboolean compressed, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - struct stat stbuf; g_autoptr(GInputStream) file_input = NULL; - g_autoptr(GInputStream) ret_input = NULL; - g_autoptr(GFileInfo) ret_file_info = NULL; - g_autoptr(GVariant) ret_xattrs = NULL; - if (!ot_openat_read_stream (parent_dfd, path, TRUE, &file_input, cancellable, error)) - goto out; - + return FALSE; + + struct stat stbuf; if (!glnx_stream_fstat ((GFileDescriptorBased*)file_input, &stbuf, error)) - goto out; - + return FALSE; + + g_autoptr(GFileInfo) ret_file_info = NULL; + g_autoptr(GVariant) ret_xattrs = NULL; + g_autoptr(GInputStream) ret_input = NULL; if (!ostree_content_stream_parse (compressed, file_input, stbuf.st_size, trusted, out_input ? &ret_input : NULL, &ret_file_info, &ret_xattrs, cancellable, error)) - goto out; - - ret = TRUE; + return FALSE; + ot_transfer_out_value (out_input, &ret_input); ot_transfer_out_value (out_file_info, &ret_file_info); ot_transfer_out_value (out_xattrs, &ret_xattrs); - out: - return ret; + return TRUE; } /** @@ -804,23 +768,19 @@ ostree_checksum_file_from_input (GFileInfo *file_info, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autofree guchar *ret_csum = NULL; - GChecksum *checksum = NULL; - checksum = g_checksum_new (G_CHECKSUM_SHA256); + g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256); if (OSTREE_OBJECT_TYPE_IS_META (objtype)) { if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error)) - goto out; + return FALSE; } else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) { g_autoptr(GVariant) dirmeta = ostree_create_directory_metadata (file_info, xattrs); g_checksum_update (checksum, g_variant_get_data (dirmeta), g_variant_get_size (dirmeta)); - } else { @@ -830,22 +790,17 @@ ostree_checksum_file_from_input (GFileInfo *file_info, if (!write_file_header_update_checksum (NULL, file_header, checksum, cancellable, error)) - goto out; + return FALSE; if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error)) - goto out; + return FALSE; } } - ret_csum = ot_csum_from_gchecksum (checksum); - - ret = TRUE; - ot_transfer_out_value (out_csum, &ret_csum); - out: - g_clear_pointer (&checksum, (GDestroyNotify)g_checksum_free); - return ret; + *out_csum = ot_csum_from_gchecksum (checksum); + return TRUE; } /** @@ -1042,10 +997,9 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - char *tmpname = g_strdup ("tmplink.XXXXXX"); - guint i; + g_autofree char *tmpname = g_strdup ("tmplink.XXXXXX"); const int max_attempts = 128; + guint i; for (i = 0; i < max_attempts; i++) { @@ -1055,28 +1009,17 @@ _ostree_make_temporary_symlink_at (int tmp_dirfd, if (errno == EEXIST) continue; else - { - int errsv = errno; - g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errsv), - g_strerror (errsv)); - goto out; - } + return glnx_throw_errno (error); } else break; } if (i == max_attempts) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Exhausted attempts to open temporary file"); - goto out; - } + return glnx_throw (error, "Exhausted attempts to open temporary file"); - ret = TRUE; if (out_name) *out_name = g_steal_pointer (&tmpname); - out: - return ret; + return TRUE; } From ffc178311e36e9f4785d1fdc42e2adca0b9d12eb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 23 Mar 2017 14:29:59 -0400 Subject: [PATCH 24/56] build: Dist ostree-sepolicy-private.h Should fix the Travis builds which actually generate a legacy tarball via Automake. Closes: #755 Approved by: jlebon --- Makefile-libostree.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 28126487..0a114884 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -107,6 +107,7 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-repo-file-enumerator.c \ src/libostree/ostree-repo-file-enumerator.h \ src/libostree/ostree-sepolicy.c \ + src/libostree/ostree-sepolicy-private.h \ src/libostree/ostree-sysroot-private.h \ src/libostree/ostree-sysroot.c \ src/libostree/ostree-sysroot-cleanup.c \ From 4d873389f0aae45e18c8c40b2b868b8264beaade Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 24 Mar 2017 09:16:06 -0400 Subject: [PATCH 25/56] commit: Prefix error with target object name on failure to write Helpful to debug things later. Closes: #759 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index d02154f8..3848a03c 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -344,6 +344,8 @@ commit_loose_object_trusted (OstreeRepo *self, ret = TRUE; out: + if (G_UNLIKELY (error && *error)) + g_prefix_error (error, "Writing object %s.%s: ", checksum, ostree_object_type_to_string (objtype)); return ret; } From 455cc5e8926350cf4386792090068ff71af08f15 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 24 Mar 2017 10:35:59 -0400 Subject: [PATCH 26/56] repo+tests: Add [core]disable-xattrs=true, use it on overlayfs There are a lot of things suboptimal about this approach, but on the other hand we need to get our CI back up and running. The basic approach is to - in the test suite, detect if we're on overlayfs. If so, set a flag in the repo, which gets picked up by a few strategic places in the core to turn on "ignore xattrs". I also had to add a variant of this for the sysroot work. The core problem here is while overlayfs will let us read and see the SELinux labels, it won't let us write them. Down the line, we should improve this so that we can selectively ignore e.g. `security.*` attributes but not `user.*` say. Closes: https://github.com/ostreedev/ostree/issues/758 Closes: #759 Approved by: jlebon --- .../static-delta-generate-crosscheck.sh | 2 +- src/libostree/ostree-diff.c | 14 +++++ src/libostree/ostree-repo-commit.c | 3 +- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo.c | 24 ++++--- src/libostree/ostree-sysroot-deploy.c | 63 ++++++++++++------- src/libostree/ostree-sysroot-private.h | 4 +- src/libostree/ostree-sysroot.c | 3 +- tests/archive-test.sh | 2 +- tests/basic-test.sh | 16 ++--- tests/libostreetest.c | 20 +++++- tests/libtest.sh | 46 ++++++++++---- tests/pull-test.sh | 8 +-- tests/test-archivez.sh | 2 +- tests/test-commit-sign.sh | 12 ++-- tests/test-delta.sh | 12 ++-- tests/test-demo-buildsystem.sh | 4 +- tests/test-local-pull-depth.sh | 2 +- tests/test-local-pull.sh | 12 ++-- tests/test-oldstyle-partial.sh | 2 +- tests/test-parent.sh | 2 +- tests/test-prune.sh | 10 +-- tests/test-pull-commit-only.sh | 2 +- tests/test-pull-contenturl.sh | 2 +- tests/test-pull-corruption.sh | 2 +- tests/test-pull-depth.sh | 2 +- tests/test-pull-large-metadata.sh | 2 +- tests/test-pull-metalink.sh | 6 +- tests/test-pull-mirror-summary.sh | 13 ++-- tests/test-pull-mirrorlist.sh | 6 +- tests/test-pull-override-url.sh | 4 +- tests/test-pull-repeated.sh | 2 +- tests/test-pull-resume.sh | 2 +- tests/test-pull-subpath.sh | 4 +- tests/test-pull-summary-sigs.sh | 4 +- tests/test-pull-untrusted.sh | 6 +- tests/test-refs.sh | 2 +- tests/test-remote-cookies.sh | 2 +- tests/test-remote-headers.sh | 2 +- tests/test-xattrs.sh | 3 + 40 files changed, 208 insertions(+), 122 deletions(-) diff --git a/manual-tests/static-delta-generate-crosscheck.sh b/manual-tests/static-delta-generate-crosscheck.sh index 831e0b62..fd8f2189 100755 --- a/manual-tests/static-delta-generate-crosscheck.sh +++ b/manual-tests/static-delta-generate-crosscheck.sh @@ -43,7 +43,7 @@ assert_streq() { validate_delta_options() { mkdir testrepo - ostree --repo=testrepo init --mode=bare-user + ostree_repo_init testrepo --mode=bare-user ostree --repo=testrepo remote add --set=gpg-verify=false local file://${repo} ostree --repo=${repo} static-delta generate $@ --from=${from} --to=${to} ostree --repo=testrepo pull --require-static-deltas local ${branch}@${from} diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index 5537ee87..b428fb44 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -24,6 +24,7 @@ #include "libglnx.h" #include "ostree.h" +#include "ostree-repo-private.h" #include "otutil.h" static gboolean @@ -269,6 +270,19 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, if (!options) options = &default_opts; + /* If we're diffing versus a repo, and either of them have xattrs disabled, + * then disable for both. + */ + OstreeRepo *repo; + if (OSTREE_IS_REPO_FILE (a)) + repo = ostree_repo_file_get_repo ((OstreeRepoFile*)a); + else if (OSTREE_IS_REPO_FILE (b)) + repo = ostree_repo_file_get_repo ((OstreeRepoFile*)b); + else + repo = NULL; + if (repo != NULL && repo->disable_xattrs) + flags |= OSTREE_DIFF_FLAGS_IGNORE_XATTRS; + if (a == NULL) { if (!diff_add_dir_recurse (b, added, cancellable, error)) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 3848a03c..7a641de8 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2304,7 +2304,8 @@ get_modified_xattrs (OstreeRepo *self, 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) > 0)) + else if (!(modifier && (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS) > 0) + && !self->disable_xattrs) { if (path && OSTREE_IS_REPO_FILE (path)) { diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index f1e00f27..b1a58d61 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -100,6 +100,7 @@ struct OstreeRepo { GError *writable_error; gboolean in_transaction; gboolean disable_fsync; + gboolean disable_xattrs; guint zlib_compression_level; GHashTable *loose_object_devino_hash; GHashTable *updated_uncompressed_dirs; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 733db27b..3fa32336 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1584,8 +1584,9 @@ ostree_repo_remote_gpg_import (OstreeRepo *self, if (fstatat (self->repo_dir_fd, remote->keyring, &stbuf, AT_SYMLINK_NOFOLLOW) == 0) { + GLnxFileCopyFlags copyflags = self->disable_xattrs ? GLNX_FILE_COPY_NOXATTRS : 0; if (!glnx_file_copy_at (self->repo_dir_fd, remote->keyring, - &stbuf, target_temp_fd, "pubring.gpg", 0, + &stbuf, target_temp_fd, "pubring.gpg", copyflags, cancellable, error)) { g_prefix_error (error, "Unable to copy remote's keyring: "); @@ -2067,6 +2068,11 @@ reload_core_config (OstreeRepo *self, ostree_repo_set_disable_fsync (self, TRUE); } + /* See https://github.com/ostreedev/ostree/issues/758 */ + if (!ot_keyfile_get_boolean_with_default (self->config, "core", "disable-xattrs", + TRUE, &self->disable_xattrs, error)) + return FALSE; + { g_autofree char *tmp_expiry_seconds = NULL; /* 86400 secs = one day */ @@ -2920,8 +2926,10 @@ ostree_repo_load_file (OstreeRepo *self, if (out_xattrs) { - if (!glnx_fd_get_all_xattrs (fd, &ret_xattrs, - cancellable, error)) + if (self->disable_xattrs) + ret_xattrs = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0)); + else if (!glnx_fd_get_all_xattrs (fd, &ret_xattrs, + cancellable, error)) goto out; } @@ -2934,15 +2942,17 @@ ostree_repo_load_file (OstreeRepo *self, else if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_SYMBOLIC_LINK && out_xattrs) { - if (!glnx_dfd_name_get_all_xattrs (self->objects_dir_fd, loose_path_buf, - &ret_xattrs, - cancellable, error)) + if (self->disable_xattrs) + ret_xattrs = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("(ayay)"), NULL, 0)); + else if (!glnx_dfd_name_get_all_xattrs (self->objects_dir_fd, loose_path_buf, + &ret_xattrs, + cancellable, error)) goto out; } } } } - + if (!found) { if (self->parent_repo) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index acbf4619..d12e47b2 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -88,6 +88,15 @@ symlink_at_replace (const char *oldpath, return ret; } +static GLnxFileCopyFlags +sysroot_flags_to_copy_flags (GLnxFileCopyFlags defaults, + OstreeSysrootDebugFlags sysrootflags) +{ + if (sysrootflags & OSTREE_SYSROOT_DEBUG_NO_XATTRS) + defaults |= GLNX_FILE_COPY_NOXATTRS; + return defaults; +} + /* Try a hardlink if we can, otherwise fall back to copying. Used * right now for kernels/initramfs in /boot, where we can just * hardlink if we're on the same partition. @@ -97,6 +106,7 @@ hardlink_or_copy_at (int src_dfd, const char *src_subpath, int dest_dfd, const char *dest_subpath, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -106,7 +116,8 @@ hardlink_or_copy_at (int src_dfd, { if (errno == EMLINK || errno == EXDEV) { - return glnx_file_copy_at (src_dfd, src_subpath, NULL, dest_dfd, dest_subpath, 0, + return glnx_file_copy_at (src_dfd, src_subpath, NULL, dest_dfd, dest_subpath, + sysroot_flags_to_copy_flags (0, flags), cancellable, error); } else @@ -126,6 +137,7 @@ dirfd_copy_attributes_and_xattrs (int src_parent_dfd, const char *src_name, int src_dfd, int dest_dfd, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -136,13 +148,16 @@ dirfd_copy_attributes_and_xattrs (int src_parent_dfd, /* Clone all xattrs first, so we get the SELinux security context * right. This will allow other users access if they have ACLs, but * oh well. - */ - if (!glnx_dfd_name_get_all_xattrs (src_parent_dfd, src_name, - &xattrs, cancellable, error)) - goto out; - if (!glnx_fd_set_all_xattrs (dest_dfd, xattrs, - cancellable, error)) - goto out; + */ + if (!(flags & OSTREE_SYSROOT_DEBUG_NO_XATTRS)) + { + if (!glnx_dfd_name_get_all_xattrs (src_parent_dfd, src_name, + &xattrs, cancellable, error)) + goto out; + if (!glnx_fd_set_all_xattrs (dest_dfd, xattrs, + cancellable, error)) + goto out; + } if (fstat (src_dfd, &src_stbuf) != 0) { @@ -169,6 +184,7 @@ static gboolean copy_dir_recurse (int src_parent_dfd, int dest_parent_dfd, const char *name, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -190,7 +206,7 @@ copy_dir_recurse (int src_parent_dfd, return FALSE; if (!dirfd_copy_attributes_and_xattrs (src_parent_dfd, name, src_dfd_iter.fd, dest_dfd, - cancellable, error)) + flags, cancellable, error)) return FALSE; while (TRUE) @@ -212,14 +228,14 @@ copy_dir_recurse (int src_parent_dfd, if (S_ISDIR (child_stbuf.st_mode)) { if (!copy_dir_recurse (src_dfd_iter.fd, dest_dfd, dent->d_name, - cancellable, error)) + flags, cancellable, error)) return FALSE; } else { if (!glnx_file_copy_at (src_dfd_iter.fd, dent->d_name, &child_stbuf, dest_dfd, dent->d_name, - GLNX_FILE_COPY_OVERWRITE, + sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), cancellable, error)) return FALSE; } @@ -234,6 +250,7 @@ ensure_directory_from_template (int orig_etc_fd, int new_etc_fd, const char *path, int *out_dfd, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -262,7 +279,7 @@ ensure_directory_from_template (int orig_etc_fd, if (strcmp (parent_path, ".") != 0) { if (!ensure_directory_from_template (orig_etc_fd, modified_etc_fd, new_etc_fd, - parent_path, NULL, cancellable, error)) + parent_path, NULL, flags, cancellable, error)) goto out; /* Loop */ @@ -286,7 +303,7 @@ ensure_directory_from_template (int orig_etc_fd, goto out; if (!dirfd_copy_attributes_and_xattrs (modified_etc_fd, path, src_dfd, target_dfd, - cancellable, error)) + flags, cancellable, error)) goto out; ret = TRUE; @@ -312,6 +329,7 @@ copy_modified_config_file (int orig_etc_fd, int modified_etc_fd, int new_etc_fd, const char *path, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -332,7 +350,7 @@ copy_modified_config_file (int orig_etc_fd, g_autofree char *parent = g_path_get_dirname (path); if (!ensure_directory_from_template (orig_etc_fd, modified_etc_fd, new_etc_fd, - parent, &dest_parent_dfd, cancellable, error)) + parent, &dest_parent_dfd, flags, cancellable, error)) goto out; } else @@ -386,7 +404,7 @@ copy_modified_config_file (int orig_etc_fd, if (S_ISDIR (modified_stbuf.st_mode)) { - if (!copy_dir_recurse (modified_etc_fd, new_etc_fd, path, + if (!copy_dir_recurse (modified_etc_fd, new_etc_fd, path, flags, cancellable, error)) goto out; } @@ -394,7 +412,7 @@ copy_modified_config_file (int orig_etc_fd, { if (!glnx_file_copy_at (modified_etc_fd, path, &modified_stbuf, new_etc_fd, path, - GLNX_FILE_COPY_OVERWRITE, + sysroot_flags_to_copy_flags (GLNX_FILE_COPY_OVERWRITE, flags), cancellable, error)) goto out; } @@ -426,6 +444,7 @@ static gboolean merge_etc_changes (GFile *orig_etc, GFile *modified_etc, GFile *new_etc, + OstreeSysrootDebugFlags flags, GCancellable *cancellable, GError **error) { @@ -496,7 +515,7 @@ merge_etc_changes (GFile *orig_etc, g_assert (path); if (!copy_modified_config_file (orig_etc_fd, modified_etc_fd, new_etc_fd, path, - cancellable, error)) + flags, cancellable, error)) goto out; } for (i = 0; i < added->len; i++) @@ -507,7 +526,7 @@ merge_etc_changes (GFile *orig_etc, g_assert (path); if (!copy_modified_config_file (orig_etc_fd, modified_etc_fd, new_etc_fd, path, - cancellable, error)) + flags, cancellable, error)) goto out; } @@ -827,7 +846,7 @@ merge_configuration (OstreeSysroot *sysroot, /* TODO - set out labels as we copy files */ g_assert (!etc_exists); if (!copy_dir_recurse (deployment_usr_dfd, deployment_dfd, "etc", - cancellable, error)) + sysroot->debug_flags, cancellable, error)) goto out; /* Here, we initialize SELinux policy from the /usr/etc inside @@ -847,8 +866,8 @@ merge_configuration (OstreeSysroot *sysroot, if (source_etc_path) { - if (!merge_etc_changes (source_etc_pristine_path, source_etc_path, deployment_etc_path, - cancellable, error)) + if (!merge_etc_changes (source_etc_pristine_path, source_etc_path, deployment_etc_path, + sysroot->debug_flags, cancellable, error)) goto out; } @@ -1319,6 +1338,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, } if (!hardlink_or_copy_at (tree_boot_dfd, tree_kernel_name, bootcsum_dfd, dest_kernel_name, + sysroot->debug_flags, cancellable, error)) goto out; } @@ -1336,6 +1356,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, } if (!hardlink_or_copy_at (tree_boot_dfd, tree_initramfs_name, bootcsum_dfd, dest_initramfs_name, + sysroot->debug_flags, cancellable, error)) goto out; } diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index c2f5d2d9..3900092a 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -30,7 +30,9 @@ G_BEGIN_DECLS typedef enum { /* Don't flag deployments as immutable. */ - OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0 + OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS = 1 << 0, + /* See https://github.com/ostreedev/ostree/pull/759 */ + OSTREE_SYSROOT_DEBUG_NO_XATTRS = 1 << 1, } OstreeSysrootDebugFlags; diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index c4f608a2..446dd4ab 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -161,9 +161,10 @@ ostree_sysroot_init (OstreeSysroot *self) { const GDebugKey keys[] = { { "mutable-deployments", OSTREE_SYSROOT_DEBUG_MUTABLE_DEPLOYMENTS }, + { "no-xattrs", OSTREE_SYSROOT_DEBUG_NO_XATTRS }, }; - self->debug_flags = g_parse_debug_string (g_getenv("OSTREE_SYSROOT_DEBUG"), + self->debug_flags = g_parse_debug_string (g_getenv ("OSTREE_SYSROOT_DEBUG"), keys, G_N_ELEMENTS (keys)); self->sysroot_fd = -1; diff --git a/tests/archive-test.sh b/tests/archive-test.sh index 9c5f8a47..76bc2635 100644 --- a/tests/archive-test.sh +++ b/tests/archive-test.sh @@ -31,7 +31,7 @@ echo "ok content" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init +ostree_repo_init repo2 ${CMD_PREFIX} ostree --repo=repo2 pull-local repo echo "ok local clone" diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 68c7b0a6..c1c6173b 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -46,8 +46,8 @@ echo "ok shortened checksum" echo "ok repo-in-cwd" rm test-repo -rf -$OSTREE --repo=test-repo init --mode=bare-user -$OSTREE --repo=test-repo init --mode=bare-user +ostree_repo_init test-repo --mode=bare-user +ostree_repo_init test-repo --mode=bare-user rm test-repo -rf echo "ok repo-init on existing repo" @@ -197,7 +197,7 @@ echo "ok diff file changing type" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init +ostree_repo_init repo2 ${CMD_PREFIX} ostree --repo=repo2 pull-local repo echo "ok pull-local" @@ -315,7 +315,7 @@ echo "ok checkout union add" cd ${test_tmpdir} rm -rf shadow-repo mkdir shadow-repo -${CMD_PREFIX} ostree --repo=shadow-repo init +ostree_repo_init shadow-repo ${CMD_PREFIX} ostree --repo=shadow-repo config set core.parent $(pwd)/repo rm -rf test2-checkout parent_rev_test2=$(${CMD_PREFIX} ostree --repo=repo rev-parse test2) @@ -335,7 +335,7 @@ echo "ok subdir noent" cd ${test_tmpdir} mkdir repo3 -${CMD_PREFIX} ostree --repo=repo3 init +ostree_repo_init repo3 ${CMD_PREFIX} ostree --repo=repo3 pull-local --remote=aremote repo test2 ${CMD_PREFIX} ostree --repo=repo3 rev-parse aremote/test2 echo "ok pull-local with --remote arg" @@ -354,7 +354,7 @@ echo "ok prune" cd ${test_tmpdir} rm repo3 -rf -${CMD_PREFIX} ostree --repo=repo3 init --mode=archive +ostree_repo_init repo3 --mode=archive ${CMD_PREFIX} ostree --repo=repo3 pull-local --remote=aremote repo test2 rm repo3/refs/remotes -rf mkdir repo3/refs/remotes @@ -437,7 +437,7 @@ echo "ok metadata commit with strings" cd ${test_tmpdir} rm repo2 -rf mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init +ostree_repo_init repo2 ${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${CMD_PREFIX} ostree --repo=repo2 show --print-detached-metadata-key=SIGNATURE test2 > test2-meta assert_file_has_content test2-meta "HANCOCK" @@ -481,7 +481,7 @@ echo "ok commit of fifo was rejected" cd ${test_tmpdir} rm repo2 -rf mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode=archive +ostree_repo_init repo2 --mode=archive ${CMD_PREFIX} ostree --repo=repo2 pull-local repo rm -rf test2-checkout ${CMD_PREFIX} ostree --repo=repo2 checkout -U --disable-cache test2 test2-checkout diff --git a/tests/libostreetest.c b/tests/libostreetest.c index d0eb3e81..cda1649d 100644 --- a/tests/libostreetest.c +++ b/tests/libostreetest.c @@ -21,6 +21,8 @@ #include "config.h" #include #include +#include +#include #include "libglnx.h" #include "libostreetest.h" @@ -90,12 +92,26 @@ ot_test_setup_sysroot (GCancellable *cancellable, gboolean ret = FALSE; g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot"); glnx_unref_object OstreeSysroot *ret_sysroot = NULL; + struct statfs stbuf; if (!ot_test_run_libtest ("setup_os_repository \"archive-z2\" \"syslinux\"", error)) goto out; - /* Make sure deployments are mutable */ - g_setenv ("OSTREE_SYSROOT_DEBUG", "mutable-deployments", TRUE); + { g_autoptr(GString) buf = g_string_new ("mutable-deployments"); + if (statfs ("/", &stbuf) < 0) + return glnx_throw_errno (error), NULL; + /* 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); + } ret_sysroot = ostree_sysroot_new (sysroot_path); diff --git a/tests/libtest.sh b/tests/libtest.sh index 0126827e..363413fd 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -86,6 +86,18 @@ chmod -R u+w "${test_tmpdir}" 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 +echo done + if test -n "${OT_TESTS_DEBUG:-}"; then set -x fi @@ -195,15 +207,13 @@ setup_test_repository () { oldpwd=`pwd` cd ${test_tmpdir} - mkdir repo - cd repo - ot_repo="--repo=`pwd`" - export OSTREE="${CMD_PREFIX} ostree ${ot_repo}" - if test -n "$mode"; then - $OSTREE init --mode=${mode} + if test -n "${mode}"; then + ostree_repo_init repo --mode=${mode} else - $OSTREE init + ostree_repo_init repo fi + ot_repo="--repo=$(pwd)/repo" + export OSTREE="${CMD_PREFIX} ostree ${ot_repo}" cd ${test_tmpdir} mkdir files @@ -232,6 +242,16 @@ setup_test_repository () { cd $oldpwd } +# A wrapper which also possibly disables xattrs for CI testing +ostree_repo_init() { + repo=$1 + shift + ${CMD_PREFIX} ostree --repo=${repo} init "$@" + if test -n "${OSTREE_NO_XATTRS:-}"; then + echo -e 'disable-xattrs=true\n' >> ${repo}/config + fi +} + setup_fake_remote_repo1() { mode=$1 commit_opts=${2:-} @@ -241,7 +261,7 @@ setup_fake_remote_repo1() { mkdir ostree-srv cd ostree-srv mkdir gnomerepo - ${CMD_PREFIX} ostree --repo=gnomerepo init --mode=$mode + ostree_repo_init gnomerepo --mode=$mode mkdir gnomerepo-files cd gnomerepo-files echo first > firstfile @@ -284,8 +304,8 @@ setup_exampleos_repo() { mkdir -p ostree-srv/exampleos/{repo,build-repo} export ORIGIN_REPO=ostree-srv/exampleos/repo export ORIGIN_BUILD_REPO=ostree-srv/exampleos/build-repo - ${CMD_PREFIX} ostree --repo=${ORIGIN_REPO} init --mode=archive - ${CMD_PREFIX} ostree --repo=${ORIGIN_BUILD_REPO} init --mode=bare-user + ostree_repo_init ${ORIGIN_REPO} --mode=archive + ostree_repo_init ${ORIGIN_BUILD_REPO} --mode=bare-user cd ${test_tmpdir} rm main -rf mkdir main @@ -365,7 +385,7 @@ setup_exampleos_repo() { cd ${test_tmpdir} rm repo -rf - ${CMD_PREFIX} ostree --repo=repo init --mode=bare-user + ostree_repo_init repo --mode=bare-user ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat ostree-srv/httpd/address)/exampleos/repo export OSTREE="${CMD_PREFIX} ostree --repo=repo" } @@ -413,9 +433,9 @@ setup_os_repository () { cd ${test_tmpdir} mkdir testos-repo if test -n "$mode"; then - ${CMD_PREFIX} ostree --repo=testos-repo init --mode=${mode} + ostree_repo_init testos-repo --mode=${mode} else - ${CMD_PREFIX} ostree --repo=testos-repo init + ostree_repo_init testos-repo fi cd ${test_tmpdir} diff --git a/tests/pull-test.sh b/tests/pull-test.sh index f6176079..f2486c31 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -23,7 +23,7 @@ function repo_init() { cd ${test_tmpdir} rm repo -rf mkdir repo - ${CMD_PREFIX} ostree --repo=repo init + ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo } @@ -50,7 +50,7 @@ echo "ok pull contents" cd ${test_tmpdir} mkdir mirrorrepo -${CMD_PREFIX} ostree --repo=mirrorrepo init --mode=archive-z2 +ostree_repo_init mirrorrepo --mode=archive-z2 ${CMD_PREFIX} ostree --repo=mirrorrepo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=mirrorrepo pull --mirror origin main ${CMD_PREFIX} ostree --repo=mirrorrepo fsck @@ -96,7 +96,7 @@ echo "ok pull commit metadata only (should not apply deltas)" cd ${test_tmpdir} mkdir mirrorrepo-local -${CMD_PREFIX} ostree --repo=mirrorrepo-local init --mode=archive-z2 +ostree_repo_init mirrorrepo-local --mode=archive-z2 ${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 @@ -114,7 +114,7 @@ echo "ok pull detached metadata" cd ${test_tmpdir} mkdir parentpullrepo -${CMD_PREFIX} ostree --repo=parentpullrepo init --mode=archive-z2 +ostree_repo_init parentpullrepo --mode=archive-z2 ${CMD_PREFIX} ostree --repo=parentpullrepo remote add --set=gpg-verify=false origin file://$(pwd)/ostree-srv/gnomerepo parent_rev=$(ostree --repo=ostree-srv/gnomerepo rev-parse main^) rev=$(ostree --repo=ostree-srv/gnomerepo rev-parse main) diff --git a/tests/test-archivez.sh b/tests/test-archivez.sh index b8793284..836e9180 100755 --- a/tests/test-archivez.sh +++ b/tests/test-archivez.sh @@ -29,7 +29,7 @@ setup_test_repository "archive-z2" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init +ostree_repo_init repo2 ${CMD_PREFIX} ostree --repo=repo2 remote add --set=gpg-verify=false aremote file://$(pwd)/repo test2 ${CMD_PREFIX} ostree --repo=repo2 pull aremote ${CMD_PREFIX} ostree --repo=repo2 rev-parse aremote/test2 diff --git a/tests/test-commit-sign.sh b/tests/test-commit-sign.sh index f963b104..96608e88 100755 --- a/tests/test-commit-sign.sh +++ b/tests/test-commit-sign.sh @@ -33,7 +33,7 @@ oldpwd=`pwd` mkdir ostree-srv cd ostree-srv mkdir gnomerepo -${CMD_PREFIX} ostree --repo=gnomerepo init --mode="archive-z2" +ostree_repo_init gnomerepo --mode="archive-z2" mkdir gnomerepo-files cd gnomerepo-files echo first > firstfile @@ -67,7 +67,7 @@ cp -a ${repopath} ${repopath}.orig # Set OSTREE_GPG_HOME to a place with no keyrings, we shouldn't trust the signature cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo if env OSTREE_GPG_HOME=${test_tmpdir} ${CMD_PREFIX} ostree --repo=repo pull origin main; then assert_not_reached "pull with no trusted GPG keys unexpectedly succeeded!" @@ -77,7 +77,7 @@ rm repo -rf # And a test case with valid signature cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 @@ -90,7 +90,7 @@ find ${test_tmpdir}/ostree-srv/gnomerepo -name '*.commitmeta' | while read fname echo borkborkbork > ${fname}; done mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo if ${CMD_PREFIX} ostree --repo=repo pull origin main; then assert_not_reached "pull with corrupted signature unexpectedly succeeded!" @@ -101,7 +101,7 @@ rm repo -rf # verification off cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 rm repo -rf @@ -114,7 +114,7 @@ echo secret > signme ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo commit -b main -s "Don't forget to sign me!" cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 diff --git a/tests/test-delta.sh b/tests/test-delta.sh index b9883830..84320b80 100755 --- a/tests/test-delta.sh +++ b/tests/test-delta.sh @@ -29,7 +29,7 @@ morebindatafiles="false ls" echo '1..12' mkdir repo -${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 mkdir files for bin in ${bindatafiles}; do @@ -121,7 +121,7 @@ if ${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to assert_not_reached "static-delta generate --from=${origrev} --empty unexpectedly succeeded" fi -${CMD_PREFIX} ostree --repo=temp-repo init --mode=archive +ostree_repo_init temp-repo --mode=archive ${CMD_PREFIX} ostree --repo=temp-repo pull-local repo ${CMD_PREFIX} ostree --repo=temp-repo static-delta generate --empty --to=${newrev} --filename=some.delta assert_has_file some.delta @@ -168,7 +168,7 @@ echo 'ok heuristic endian detection' ${CMD_PREFIX} ostree --repo=repo summary -u -mkdir repo2 && ${CMD_PREFIX} ostree --repo=repo2 init --mode=bare-user +mkdir repo2 && ostree_repo_init repo2 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo2 pull-local --require-static-deltas repo ${newrev} ${CMD_PREFIX} ostree --repo=repo2 fsck ${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null @@ -176,7 +176,7 @@ ${CMD_PREFIX} ostree --repo=repo2 ls ${newrev} >/dev/null echo 'ok pull delta' rm repo2 -rf -mkdir repo2 && ${CMD_PREFIX} ostree --repo=repo2 init --mode=bare-user +mkdir repo2 && ostree_repo_init repo2 --mode=bare-user mkdir deltadir deltaprefix=$(get_assert_one_direntry_matching repo/deltas '.') @@ -194,7 +194,7 @@ ${CMD_PREFIX} ostree --repo=repo static-delta generate --from=${origrev} --to=${ assert_not_has_file repo/deltas/${deltaprefix}/${deltadir}/0 rm repo2 -rf -mkdir repo2 && ostree --repo=repo2 init --mode=bare-user +ostree_repo_init repo2 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${origrev} ${CMD_PREFIX} ostree --repo=repo2 ls ${origrev} >/dev/null @@ -236,7 +236,7 @@ echo 'ok generate + show empty delta part' ${CMD_PREFIX} ostree --repo=repo summary -u rm -rf repo2 -mkdir repo2 && ${CMD_PREFIX} ostree --repo=repo2 init --mode=bare-user +mkdir repo2 && ostree_repo_init repo2 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${newrev} ${CMD_PREFIX} ostree --repo=repo2 pull-local --require-static-deltas repo ${samerev} ${CMD_PREFIX} ostree --repo=repo2 fsck diff --git a/tests/test-demo-buildsystem.sh b/tests/test-demo-buildsystem.sh index cc926979..99ddc505 100755 --- a/tests/test-demo-buildsystem.sh +++ b/tests/test-demo-buildsystem.sh @@ -66,9 +66,9 @@ exampleos_recompose() { packages="bash systemd" mkdir build-repo -${CMD_PREFIX} ostree --repo=build-repo init --mode=bare-user +ostree_repo_init build-repo --mode=bare-user mkdir repo -${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 # Our FUSE mount point mkdir mnt diff --git a/tests/test-local-pull-depth.sh b/tests/test-local-pull-depth.sh index e89d0914..fef2f2dc 100755 --- a/tests/test-local-pull-depth.sh +++ b/tests/test-local-pull-depth.sh @@ -27,7 +27,7 @@ echo "1..1" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode="archive-z2" +ostree_repo_init repo2 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo2 pull-local repo find repo2/objects -name '*.commit' | wc -l > commitcount diff --git a/tests/test-local-pull.sh b/tests/test-local-pull.sh index 9e8c8a00..43b96010 100755 --- a/tests/test-local-pull.sh +++ b/tests/test-local-pull.sh @@ -33,14 +33,14 @@ echo "ok setup" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode="bare-user" +ostree_repo_init repo2 --mode="bare-user" ${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${CMD_PREFIX} ostree --repo=repo2 fsck echo "ok pull-local z2 to bare-user" mkdir repo3 -${CMD_PREFIX} ostree --repo=repo3 init --mode="archive-z2" +ostree_repo_init repo3 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo3 pull-local repo2 ${CMD_PREFIX} ostree --repo=repo3 fsck echo "ok pull-local bare-user to z2" @@ -62,7 +62,7 @@ cmp checkout1.files checkout3.files echo "ok checkouts same" mkdir repo4 -${CMD_PREFIX} ostree --repo=repo4 init --mode="archive-z2" +ostree_repo_init repo4 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo4 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo if ${CMD_PREFIX} ostree --repo=repo4 pull-local --remote=origin --gpg-verify repo test2 2>&1; then assert_not_reached "GPG verification unexpectedly succeeded" @@ -72,13 +72,13 @@ echo "ok --gpg-verify with no signature" ${OSTREE} gpg-sign --gpg-homedir=${TEST_GPG_KEYHOME} test2 ${TEST_GPG_KEYID_1} mkdir repo5 -${CMD_PREFIX} ostree --repo=repo5 init --mode="archive-z2" +ostree_repo_init repo5 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo5 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo ${CMD_PREFIX} ostree --repo=repo5 pull-local --remote=origin --gpg-verify repo test2 echo "ok --gpg-verify" mkdir repo6 -${CMD_PREFIX} ostree --repo=repo6 init --mode="archive-z2" +ostree_repo_init repo6 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo6 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo if ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1; then assert_not_reached "GPG summary verification with no summary unexpectedly succeeded" @@ -97,7 +97,7 @@ ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summar echo "ok --gpg-verify-summary" mkdir repo7 -${CMD_PREFIX} ostree --repo=repo7 init --mode="archive-z2" +ostree_repo_init repo7 --mode="archive-z2" ${CMD_PREFIX} ostree --repo=repo7 pull-local repo ${CMD_PREFIX} ostree --repo=repo7 fsck for src_object in `find repo/objects -name '*.filez'`; do diff --git a/tests/test-oldstyle-partial.sh b/tests/test-oldstyle-partial.sh index a578e7d2..08be69d3 100755 --- a/tests/test-oldstyle-partial.sh +++ b/tests/test-oldstyle-partial.sh @@ -28,7 +28,7 @@ echo '1..1' cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 --subpath /baz diff --git a/tests/test-parent.sh b/tests/test-parent.sh index d1f5d7c9..4d5520dd 100755 --- a/tests/test-parent.sh +++ b/tests/test-parent.sh @@ -32,7 +32,7 @@ export OSTREE_GPG_SIGN="${OSTREE} gpg-sign --gpg-homedir=${TEST_GPG_KEYHOME}" cd ${test_tmpdir} # Create a repo -${CMD_PREFIX} ostree --repo=repo2 init +ostree_repo_init repo2 ${CMD_PREFIX} ostree --repo=repo2 remote add --gpg-import=${test_tmpdir}/gpghome/trusted/pubring.gpg --set=gpg-verify=true aremote file://$(pwd)/repo test2 # Create a repo with repo2 as parent diff --git a/tests/test-prune.sh b/tests/test-prune.sh index 51ec7948..0781b543 100755 --- a/tests/test-prune.sh +++ b/tests/test-prune.sh @@ -29,7 +29,7 @@ echo '1..5' cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo mkdir -p tree/root @@ -142,7 +142,7 @@ assert_file_has_content deltascount "^1$" echo "ok prune" rm repo -rf -${CMD_PREFIX} ostree --repo=repo init --mode=bare-user +ostree_repo_init repo --mode=bare-user ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 --commit-metadata-only origin test ${CMD_PREFIX} ostree --repo=repo prune @@ -158,7 +158,7 @@ assert_has_n_objects() { cd ${test_tmpdir} for repo in repo child-repo tmp-repo; do rm ${repo} -rf - ${CMD_PREFIX} ostree --repo=${repo} init --mode=archive + ostree_repo_init ${repo} --mode=archive done echo parent=${test_tmpdir}/repo >> child-repo/config mkdir files @@ -189,7 +189,7 @@ echo "ok prune with parent repo" # would interact. We make a new repo test suite, then clone it # for "subtests" below with reinitialize_datesnap_repo() rm repo datetest-snapshot-repo -rf -${CMD_PREFIX} ostree --repo=datetest-snapshot-repo init --mode=archive +ostree_repo_init datetest-snapshot-repo --mode=archive # Some ancient commits on the both a stable/dev branch for day in $(seq 5); do ${CMD_PREFIX} ostree --repo=datetest-snapshot-repo commit --branch=stable -m test -s "old stable build $day" tree --timestamp="October $day 1985" @@ -206,7 +206,7 @@ assert_file_has_content commitcount "^16$" # Snapshot the above reinitialize_datesnap_repo() { rm repo -rf - ${CMD_PREFIX} ostree --repo=repo init --mode=archive + ostree_repo_init repo --mode=archive ${CMD_PREFIX} ostree --repo=repo pull-local --depth=-1 datetest-snapshot-repo } diff --git a/tests/test-pull-commit-only.sh b/tests/test-pull-commit-only.sh index 775b2f71..0cbdebc8 100755 --- a/tests/test-pull-commit-only.sh +++ b/tests/test-pull-commit-only.sh @@ -27,7 +27,7 @@ echo '1..1' cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 --commit-metadata-only origin main diff --git a/tests/test-pull-contenturl.sh b/tests/test-pull-contenturl.sh index d74d619b..5d72fb23 100755 --- a/tests/test-pull-contenturl.sh +++ b/tests/test-pull-contenturl.sh @@ -57,7 +57,7 @@ echo "http://127.0.0.1:${content_port}" > ${test_tmpdir}/httpd-content-address cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo if has_gpgme; then VERIFY=true; else VERIFY=false; fi ${CMD_PREFIX} ostree --repo=repo remote add origin \ --set=gpg-verify=$VERIFY --set=gpg-verify-summary=$VERIFY \ diff --git a/tests/test-pull-corruption.sh b/tests/test-pull-corruption.sh index 646113a1..89d89b75 100755 --- a/tests/test-pull-corruption.sh +++ b/tests/test-pull-corruption.sh @@ -38,7 +38,7 @@ do_corrupt_pull_test() { cd ${test_tmpdir} rm repo -rf mkdir repo - ${CMD_PREFIX} ostree --repo=repo init + ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo if ${CMD_PREFIX} ostree --repo=repo pull origin main; then assert_not_reached "pull unexpectedly succeeded!" diff --git a/tests/test-pull-depth.sh b/tests/test-pull-depth.sh index 7a52f9cb..372bef49 100755 --- a/tests/test-pull-depth.sh +++ b/tests/test-pull-depth.sh @@ -27,7 +27,7 @@ echo '1..1' cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +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 --depth=0 origin main diff --git a/tests/test-pull-large-metadata.sh b/tests/test-pull-large-metadata.sh index 0fe02031..2fdf0d91 100755 --- a/tests/test-pull-large-metadata.sh +++ b/tests/test-pull-large-metadata.sh @@ -32,7 +32,7 @@ dd if=/dev/zero bs=1M count=20 of=ostree-srv/gnomerepo/objects/$(echo $rev | cut cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo if ${CMD_PREFIX} ostree --repo=repo pull origin main 2>pulllog.txt 1>&2; then diff --git a/tests/test-pull-metalink.sh b/tests/test-pull-metalink.sh index 07d619df..171c8d4b 100755 --- a/tests/test-pull-metalink.sh +++ b/tests/test-pull-metalink.sh @@ -68,7 +68,7 @@ EOF cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin metalink=$(cat metalink-httpd-address)/metalink.xml ${CMD_PREFIX} ostree --repo=repo pull origin:main ${CMD_PREFIX} ostree --repo=repo rev-parse origin:main @@ -87,7 +87,7 @@ test_metalink_pull_error() { msg=$1 rm repo -rf mkdir repo - ${CMD_PREFIX} ostree --repo=repo init + ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin metalink=$(cat metalink-httpd-address)/metalink.xml if ${CMD_PREFIX} ostree --repo=repo pull origin:main 2>err.txt; then assert_not_reached "pull unexpectedly succeeded" @@ -157,7 +157,7 @@ EOF cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin metalink=$(cat metalink-httpd-address)/metalink.xml ${CMD_PREFIX} ostree --repo=repo pull origin:main ${CMD_PREFIX} ostree --repo=repo rev-parse origin:main diff --git a/tests/test-pull-mirror-summary.sh b/tests/test-pull-mirror-summary.sh index 1ef6a09c..883c0245 100755 --- a/tests/test-pull-mirror-summary.sh +++ b/tests/test-pull-mirror-summary.sh @@ -41,7 +41,7 @@ ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u prev_dir=`pwd` cd ${test_tmpdir} -${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull --mirror origin assert_has_file repo/summary @@ -69,15 +69,13 @@ cd $prev_dir cd ${test_tmpdir} rm -rf repo -mkdir repo -${OSTREE} --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${OSTREE} --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo echo "ok pull mirror without checking signed summary" cd ${test_tmpdir} rm -rf repo -mkdir repo -${OSTREE} --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${OSTREE} --repo=repo remote add --set=gpg-verify-summary=true origin $(cat httpd-address)/ostree/gnomerepo if ${OSTREE} --repo=repo pull --mirror origin 2>err.txt; then assert_not_reached "Mirroring unexpectedly succeeded" @@ -88,8 +86,7 @@ ${OSTREE} --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u ${COMMIT_SIGN} cd ${test_tmpdir} rm -rf repo -mkdir repo -${OSTREE} --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${OSTREE} --repo=repo remote add --set=gpg-verify-summary=true origin $(cat httpd-address)/ostree/gnomerepo ${OSTREE} --repo=repo pull --mirror origin assert_has_file repo/summary @@ -102,7 +99,7 @@ truncate --size=1 ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig cd ${test_tmpdir} rm -rf repo mkdir repo -${OSTREE} --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${OSTREE} --repo=repo remote add origin $(cat httpd-address)/ostree/gnomerepo ${OSTREE} --repo=repo pull --mirror origin assert_has_file repo/summary diff --git a/tests/test-pull-mirrorlist.sh b/tests/test-pull-mirrorlist.sh index 13f40e7a..35320506 100755 --- a/tests/test-pull-mirrorlist.sh +++ b/tests/test-pull-mirrorlist.sh @@ -72,7 +72,7 @@ EOF cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin --no-gpg-verify \ mirrorlist=$(cat httpd-address)/ostree/mirrorlist ${CMD_PREFIX} ostree --repo=repo pull origin:main @@ -84,7 +84,7 @@ echo "ok pull objects from mirrorlist" cd ${test_tmpdir} rm -rf repo mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin --no-gpg-verify \ --contenturl=mirrorlist=$(cat httpd-address)/ostree/mirrorlist \ $(cat httpd-address)/ostree/gnomerepo @@ -97,7 +97,7 @@ echo "ok pull objects from contenturl mirrorlist" cd ${test_tmpdir} rm -rf repo mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add origin --no-gpg-verify \ --contenturl=mirrorlist=$(cat httpd-address)/ostree/mirrorlist \ mirrorlist=$(cat httpd-address)/ostree/mirrorlist diff --git a/tests/test-pull-override-url.sh b/tests/test-pull-override-url.sh index 928013a5..16f79a02 100755 --- a/tests/test-pull-override-url.sh +++ b/tests/test-pull-override-url.sh @@ -34,7 +34,7 @@ gnomerepo_url="$(cat httpd-address)/ostree/gnomerepo" mkdir mirror-srv cd mirror-srv mkdir gnomerepo -${CMD_PREFIX} ostree --repo=gnomerepo init --mode "archive-z2" +ostree_repo_init gnomerepo --mode "archive-z2" ${CMD_PREFIX} ostree --repo=gnomerepo remote add --set=gpg-verify=false origin ${gnomerepo_url} ${CMD_PREFIX} ostree --repo=gnomerepo pull --mirror --depth=-1 origin main @@ -57,7 +57,7 @@ echo "http://127.0.0.1:${port}" > ${test_tmpdir}/mirror-httpd-address cd ${test_tmpdir} mirrorrepo_url="$(cat mirror-httpd-address)/ostree/gnomerepo" mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${gnomerepo_url} rm -rf ${test_tmpdir}/ostree-srv/gnomerepo if ${CMD_PREFIX} ostree --repo=repo pull --depth=-1 origin main diff --git a/tests/test-pull-repeated.sh b/tests/test-pull-repeated.sh index 8934e430..108c2057 100755 --- a/tests/test-pull-repeated.sh +++ b/tests/test-pull-repeated.sh @@ -27,7 +27,7 @@ COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" setup_fake_remote_repo1 "archive-z2" "${COMMIT_SIGN}" --random-500s=50 cd ${test_tmpdir} -${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo for x in $(seq 200); do if ${CMD_PREFIX} ostree --repo=repo pull --mirror origin main 2>err.txt; then diff --git a/tests/test-pull-resume.sh b/tests/test-pull-resume.sh index 06cd0793..51746b9c 100755 --- a/tests/test-pull-resume.sh +++ b/tests/test-pull-resume.sh @@ -31,7 +31,7 @@ cp -a ${repopath} ${repopath}.orig cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo maxtries=`find ${repopath}/objects | wc -l` diff --git a/tests/test-pull-subpath.sh b/tests/test-pull-subpath.sh index dba8b495..27eb64be 100755 --- a/tests/test-pull-subpath.sh +++ b/tests/test-pull-subpath.sh @@ -33,7 +33,7 @@ for remoteurl in $(cat httpd-address)/ostree/gnomerepo \ cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${remoteurl} ${CMD_PREFIX} ostree --repo=repo pull --subpath=/baz/deeper --subpath=/baz/another origin main @@ -58,7 +58,7 @@ echo "ok subpaths" rm -rf repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin ${remoteurl} # Pull a directory which is not the first in the commit (/baz/another is before) diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index 2dcfbd65..016ee4b9 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -41,7 +41,7 @@ ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u prev_dir=`pwd` cd ${test_tmpdir} -${CMD_PREFIX} ostree --repo=repo init --mode=archive-z2 +ostree_repo_init repo --mode=archive-z2 ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo ${CMD_PREFIX} ostree --repo=repo pull --mirror origin assert_has_file repo/summary @@ -66,7 +66,7 @@ repo_reinit () { cd ${test_tmpdir} rm -rf repo mkdir repo - ${OSTREE} --repo=repo init --mode=archive-z2 + ostree_repo_init repo --mode=archive-z2 ${OSTREE} --repo=repo remote add --set=gpg-verify-summary=true origin $(cat httpd-address)/ostree/gnomerepo } diff --git a/tests/test-pull-untrusted.sh b/tests/test-pull-untrusted.sh index 53636224..247a34f9 100755 --- a/tests/test-pull-untrusted.sh +++ b/tests/test-pull-untrusted.sh @@ -28,7 +28,7 @@ setup_test_repository "bare" cd ${test_tmpdir} mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode="bare" +ostree_repo_init repo2 --mode="bare" ${CMD_PREFIX} ostree --repo=repo2 --untrusted pull-local repo @@ -52,7 +52,7 @@ done rm -rf repo2 mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode="bare" +ostree_repo_init repo2 --mode="bare" if ${CMD_PREFIX} ostree --repo=repo2 pull-local repo; then echo "ok trusted pull with corruption succeeded" else @@ -61,7 +61,7 @@ fi rm -rf repo2 mkdir repo2 -${CMD_PREFIX} ostree --repo=repo2 init --mode="bare" +ostree_repo_init repo2 --mode="bare" if ${CMD_PREFIX} ostree --repo=repo2 pull-local --untrusted repo; then assert_not_reached "corrupted untrusted pull unexpectedly failed!" else diff --git a/tests/test-refs.sh b/tests/test-refs.sh index ee7841bd..d4db0013 100755 --- a/tests/test-refs.sh +++ b/tests/test-refs.sh @@ -27,7 +27,7 @@ echo '1..1' cd ${test_tmpdir} mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo mkdir -p tree/root touch tree/root/a diff --git a/tests/test-remote-cookies.sh b/tests/test-remote-cookies.sh index ab2bf263..14e3dd12 100755 --- a/tests/test-remote-cookies.sh +++ b/tests/test-remote-cookies.sh @@ -36,7 +36,7 @@ assert_fail (){ cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo # Sanity check the setup, without cookies the pull should fail diff --git a/tests/test-remote-headers.sh b/tests/test-remote-headers.sh index bca46204..6902cefb 100755 --- a/tests/test-remote-headers.sh +++ b/tests/test-remote-headers.sh @@ -38,7 +38,7 @@ assert_fail (){ cd ${test_tmpdir} rm repo -rf mkdir repo -${CMD_PREFIX} ostree --repo=repo init +ostree_repo_init repo ${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin $(cat httpd-address)/ostree/gnomerepo # Sanity check the setup, without headers the pull should fail diff --git a/tests/test-xattrs.sh b/tests/test-xattrs.sh index cdc06e87..ae7ae39f 100755 --- a/tests/test-xattrs.sh +++ b/tests/test-xattrs.sh @@ -21,6 +21,9 @@ set -euo pipefail . $(dirname $0)/libtest.sh +skip "We don't really have a use case for committing user. xattrs right now. See also https://github.com/ostreedev/ostree/issues/758" + +# Dead code below skip_without_user_xattrs echo "1..2" From 612150f143e5c8f7b8982273f29e3536d2dde5fd Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 22 Mar 2017 11:52:41 +0100 Subject: [PATCH 27/56] Add _ostree_repo_mode_is_bare helper This cleans up some existing code, but it also allows us to later add new bare modes. Closes: #750 Approved by: cgwalters --- src/libostree/ostree-core-private.h | 8 ++++++++ src/libostree/ostree-repo-checkout.c | 2 +- src/libostree/ostree-repo-commit.c | 5 ++--- src/libostree/ostree-repo.c | 5 ++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index cfd8a998..fbd9490e 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -139,6 +139,14 @@ _ostree_loose_path (char *buf, #define _OSTREE_METADATA_GPGSIGS_NAME "ostree.gpgsigs" #define _OSTREE_METADATA_GPGSIGS_TYPE G_VARIANT_TYPE ("aay") +static inline gboolean +_ostree_repo_mode_is_bare (OstreeRepoMode mode) +{ + return + mode == OSTREE_REPO_MODE_BARE || + mode == OSTREE_REPO_MODE_BARE_USER; +} + GVariant * _ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata, GBytes *signature_bytes); diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 7ae7cd55..5611e6e9 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -363,7 +363,7 @@ checkout_file_hardlink (OstreeRepo *self, GError **error) { HardlinkResult ret_result = HARDLINK_RESULT_NOT_SUPPORTED; - int srcfd = (self->mode == OSTREE_REPO_MODE_BARE || self->mode == OSTREE_REPO_MODE_BARE_USER) ? + int srcfd = _ostree_repo_mode_is_bare (self->mode) ? self->objects_dir_fd : self->uncompressed_objects_dir_fd; again: diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 7a641de8..1308ef5c 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -306,8 +306,7 @@ commit_loose_object_trusted (OstreeRepo *self, goto out; } - if (objtype == OSTREE_OBJECT_TYPE_FILE && (self->mode == OSTREE_REPO_MODE_BARE || - self->mode == OSTREE_REPO_MODE_BARE_USER)) + if (objtype == OSTREE_OBJECT_TYPE_FILE && _ostree_repo_mode_is_bare (self->mode)) { /* To satisfy tools such as guile which compare mtimes * to determine whether or not source files need to be compiled, @@ -700,7 +699,7 @@ write_object (OstreeRepo *self, * binary with trailing garbage, creating a window on the local * system where a malicious setuid binary exists. */ - if ((repo_mode == OSTREE_REPO_MODE_BARE || repo_mode == OSTREE_REPO_MODE_BARE_USER) && temp_file_is_regular) + if ((_ostree_repo_mode_is_bare (repo_mode)) && temp_file_is_regular) { guint64 size = g_file_info_get_size (file_info); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 3fa32336..adc74c0e 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2472,7 +2472,7 @@ list_loose_objects_at (OstreeRepo *self, if ((self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && strcmp (dot, ".filez") == 0) || - ((self->mode == OSTREE_REPO_MODE_BARE || self->mode == OSTREE_REPO_MODE_BARE_USER) + ((_ostree_repo_mode_is_bare (self->mode)) && strcmp (dot, ".file") == 0)) objtype = OSTREE_OBJECT_TYPE_FILE; else if (strcmp (dot, ".dirtree") == 0) @@ -2743,8 +2743,7 @@ _ostree_repo_read_bare_fd (OstreeRepo *self, { char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; - g_assert (self->mode == OSTREE_REPO_MODE_BARE || - self->mode == OSTREE_REPO_MODE_BARE_USER); + g_assert (_ostree_repo_mode_is_bare (self->mode)); _ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode); From be28c10849607d3dec4ff75553d8467745cc149b Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 22 Mar 2017 11:59:18 +0100 Subject: [PATCH 28/56] Add bare-user-only repo mode This mode is similar to bare-user, but does not store the permission, ownership (uid/gid) and xattrs in an xattr on the file objects in the repo. Additionally it stores symlinks as symlinks rather than as regular files+xattrs, like the bare mode. The later is needed because we can't store the is-symlink in the xattr. This means that some metadata is lost, such as the uid. When reading a repo like this we always report uid, gid as 0, and no xattrs, so unless this is true in the commit the resulting repository will not fsck correctly. However, it the main usecase of the repository is to check out with --user-mode, then no information is lost, and the repository can work on filesystems without xattrs (such as tmpfs). Closes: #750 Approved by: cgwalters --- src/libostree/ostree-core-private.h | 3 ++- src/libostree/ostree-core.h | 4 +++- src/libostree/ostree-repo-checkout.c | 15 +++++++++++- src/libostree/ostree-repo-commit.c | 17 +++++++++---- src/libostree/ostree-repo.c | 36 ++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index fbd9490e..a66a068f 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -144,7 +144,8 @@ _ostree_repo_mode_is_bare (OstreeRepoMode mode) { return mode == OSTREE_REPO_MODE_BARE || - mode == OSTREE_REPO_MODE_BARE_USER; + mode == OSTREE_REPO_MODE_BARE_USER || + mode == OSTREE_REPO_MODE_BARE_USER_ONLY; } GVariant * diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index bcade9db..b25112db 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -179,6 +179,7 @@ typedef enum { * @OSTREE_REPO_MODE_BARE: Files are stored as themselves; checkouts are hardlinks; can only be written as root * @OSTREE_REPO_MODE_ARCHIVE_Z2: Files are compressed, should be owned by non-root. Can be served via HTTP * @OSTREE_REPO_MODE_BARE_USER: Files are stored as themselves, except ownership; can be written by user. 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. * * See the documentation of #OstreeRepo for more information about the * possible modes. @@ -186,7 +187,8 @@ typedef enum { typedef enum { OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_ARCHIVE_Z2, - OSTREE_REPO_MODE_BARE_USER + OSTREE_REPO_MODE_BARE_USER, + OSTREE_REPO_MODE_BARE_USER_ONLY, } OstreeRepoMode; _OSTREE_PUBLIC diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 5611e6e9..09966a94 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -473,7 +473,9 @@ checkout_one_file_at (OstreeRepo *repo, (current_repo->mode == OSTREE_REPO_MODE_BARE_USER && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER /* NOTE: bare-user symlinks are not stored as symlinks */ - && !is_symlink)); + && !is_symlink) || + (current_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY + && 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 @@ -862,6 +864,9 @@ ostree_repo_checkout_tree (OstreeRepo *self, { OstreeRepoCheckoutAtOptions options = { 0, }; + if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_BARE_USER_ONLY) + mode = OSTREE_REPO_CHECKOUT_MODE_USER; + options.mode = mode; options.overwrite_mode = overwrite_mode; /* Backwards compatibility */ @@ -948,6 +953,7 @@ ostree_repo_checkout_at (OstreeRepo *self, GError **error) { OstreeRepoCheckoutAtOptions default_options = { 0, }; + OstreeRepoCheckoutAtOptions real_options; if (!options) { @@ -955,6 +961,13 @@ ostree_repo_checkout_at (OstreeRepo *self, options = &default_options; } + /* Make a copy so we can modify the options */ + real_options = *options; + options = &real_options; + + if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_BARE_USER_ONLY) + options->mode = OSTREE_REPO_CHECKOUT_MODE_USER; + g_autoptr(GFile) commit_root = (GFile*) _ostree_repo_file_new_for_commit (self, commit, error); if (!commit_root) return FALSE; diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 1308ef5c..80c35f44 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -227,7 +227,11 @@ commit_loose_object_trusted (OstreeRepo *self, } /* Special handling for symlinks in bare repositories */ - if (object_is_symlink && self->mode == OSTREE_REPO_MODE_BARE) + if (object_is_symlink && self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY) + { + /* We don't store the metadata in bare-user-only, so we're done. */ + } + else if (object_is_symlink && self->mode == OSTREE_REPO_MODE_BARE) { /* Now that we know the checksum is valid, apply uid/gid, mode bits, * and extended attributes. @@ -283,7 +287,8 @@ commit_loose_object_trusted (OstreeRepo *self, } } - if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE_USER) + if (objtype == OSTREE_OBJECT_TYPE_FILE && + (self->mode == OSTREE_REPO_MODE_BARE_USER || self->mode == OSTREE_REPO_MODE_BARE_USER_ONLY)) { if (!object_is_symlink) { @@ -302,7 +307,8 @@ commit_loose_object_trusted (OstreeRepo *self, } } - if (!write_file_metadata_to_xattr (fd, uid, gid, mode, xattrs, error)) + if (self->mode == OSTREE_REPO_MODE_BARE_USER && + !write_file_metadata_to_xattr (fd, uid, gid, mode, xattrs, error)) goto out; } @@ -708,8 +714,10 @@ write_object (OstreeRepo *self, cancellable, error)) goto out; } - else if (repo_mode == OSTREE_REPO_MODE_BARE && temp_file_is_symlink) + else if (_ostree_repo_mode_is_bare (repo_mode) && temp_file_is_symlink) { + /* Note: This will not be hit for bare-user mode because its converted to a + regular file and take the branch above */ if (!_ostree_make_temporary_symlink_at (self->tmp_dir_fd, g_file_info_get_symlink_target (file_info), &temp_filename, @@ -959,6 +967,7 @@ scan_one_loose_devino (OstreeRepo *self, case OSTREE_REPO_MODE_ARCHIVE_Z2: case OSTREE_REPO_MODE_BARE: case OSTREE_REPO_MODE_BARE_USER: + case OSTREE_REPO_MODE_BARE_USER_ONLY: skip = !g_str_has_suffix (name, ".file"); break; default: diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index adc74c0e..5e0a93ec 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -1754,6 +1754,9 @@ ostree_repo_mode_to_string (OstreeRepoMode mode, case OSTREE_REPO_MODE_BARE_USER: ret_mode = "bare-user"; break; + case OSTREE_REPO_MODE_BARE_USER_ONLY: + ret_mode = "bare-user-only"; + break; case OSTREE_REPO_MODE_ARCHIVE_Z2: ret_mode ="archive-z2"; break; @@ -1781,6 +1784,8 @@ ostree_repo_mode_from_string (const char *mode, ret_mode = OSTREE_REPO_MODE_BARE; else if (strcmp (mode, "bare-user") == 0) ret_mode = OSTREE_REPO_MODE_BARE_USER; + else if (strcmp (mode, "bare-user-only") == 0) + 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; @@ -2907,6 +2912,37 @@ ostree_repo_load_file (OstreeRepo *self, g_file_info_set_symlink_target (ret_file_info, targetbuf); } } + else if (repo_mode == OSTREE_REPO_MODE_BARE_USER_ONLY) + { + glnx_fd_close int fd = -1; + + /* Canonical info is: uid/gid is 0 and no xattrs, which + might be wrong and thus not validate correctly, but + at least we report something consistent. */ + g_file_info_set_attribute_uint32 (ret_file_info, "unix::uid", 0); + g_file_info_set_attribute_uint32 (ret_file_info, "unix::gid", 0); + + if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR && + out_input) + { + fd = openat (self->objects_dir_fd, loose_path_buf, O_RDONLY | O_CLOEXEC); + if (fd < 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + ret_input = g_unix_input_stream_new (fd, TRUE); + fd = -1; /* Transfer ownership */ + } + + if (out_xattrs) + { + GVariantBuilder builder; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayay)")); + ret_xattrs = g_variant_ref_sink (g_variant_builder_end (&builder)); + } + } else { g_assert (repo_mode == OSTREE_REPO_MODE_BARE); From b2d10dcaaa7c2bd65916887cadb046033cebdc4e Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Sun, 26 Mar 2017 11:01:25 +0200 Subject: [PATCH 29/56] commit: Add --canonical-permissions argument This adds to file permission masks the same bitmask that will be applied to file objects in bare-user* repos. This will be needed in the testsuite to ensure that the things we commit will be expressable in bare-user-only repos. Closes: #750 Approved by: cgwalters --- src/libostree/ostree-repo-commit.c | 29 ++++++++++++++++++++++++----- src/libostree/ostree-repo.h | 4 +++- src/ostree/ot-builtin-commit.c | 4 ++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 80c35f44..0e85bcb1 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2236,17 +2236,33 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self, GFileInfo *file_info, GFileInfo **out_modified_info) { - OstreeRepoCommitFilterResult result; + OstreeRepoCommitFilterResult result = OSTREE_REPO_COMMIT_FILTER_ALLOW; GFileInfo *modified_info; - if (modifier == NULL || modifier->filter == NULL) + if (modifier == NULL || + (modifier->filter == NULL && + (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS) == 0)) { *out_modified_info = g_object_ref (file_info); return OSTREE_REPO_COMMIT_FILTER_ALLOW; } modified_info = g_file_info_dup (file_info); - result = modifier->filter (self, path, modified_info, modifier->user_data); + if (modifier->filter) + result = modifier->filter (self, path, modified_info, modifier->user_data); + + if ((modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS) != 0) + { + + if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) + { + guint current_mode = g_file_info_get_attribute_uint32 (modified_info, "unix::mode"); + g_file_info_set_attribute_uint32 (modified_info, "unix::mode", current_mode | 0744); + } + g_file_info_set_attribute_uint32 (modified_info, "unix::uid", 0); + g_file_info_set_attribute_uint32 (modified_info, "unix::gid", 0); + } + *out_modified_info = modified_info; return result; @@ -2283,7 +2299,9 @@ apply_commit_filter (OstreeRepo *self, GFileInfo *file_info, GFileInfo **out_modified_info) { - if (modifier == NULL || modifier->filter == NULL) + if (modifier == NULL || + (modifier->filter == NULL && + (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS) == 0)) { *out_modified_info = g_object_ref (file_info); return OSTREE_REPO_COMMIT_FILTER_ALLOW; @@ -2312,7 +2330,8 @@ get_modified_xattrs (OstreeRepo *self, 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) > 0) + else if (!(modifier && (modifier->flags & (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS | + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS)) > 0) && !self->disable_xattrs) { if (path && OSTREE_IS_REPO_FILE (path)) diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 34685cc6..b88b980f 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -536,11 +536,13 @@ typedef OstreeRepoCommitFilterResult (*OstreeRepoCommitFilter) (OstreeRepo *r * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE: No special flags * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS: Do not process extended attributes * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES: Generate size information. + * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS: Canonicalize permissions for bare-user-only mode. */ typedef enum { OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE = 0, OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS = (1 << 0), - OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES = (1 << 1) + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES = (1 << 1), + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS = (1 << 2), } OstreeRepoCommitModifierFlags; /** diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 218fb701..e6738c89 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -45,6 +45,7 @@ static gboolean opt_link_checkout_speedup; static gboolean opt_skip_if_unchanged; static gboolean opt_tar_autocreate_parents; static gboolean opt_no_xattrs; +static gboolean opt_canonical_permissions; static char **opt_trees; static gint opt_owner_uid = -1; static gint opt_owner_gid = -1; @@ -84,6 +85,7 @@ static GOptionEntry options[] = { { "add-detached-metadata-string", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_detached_metadata_strings, "Add a key/value pair to detached metadata", "KEY=VALUE" }, { "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Set file ownership user id", "UID" }, { "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Set file ownership group id", "GID" }, + { "canonical-permissions", 0, 0, G_OPTION_ARG_NONE, &opt_canonical_permissions, "Canonicalize permissions in the same way bare-user does for hardlinked files", NULL }, { "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Do not import extended attributes", NULL }, { "link-checkout-speedup", 0, 0, G_OPTION_ARG_NONE, &opt_link_checkout_speedup, "Optimize for commits of trees composed of hardlinks into the repository", NULL }, { "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &opt_tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL }, @@ -399,6 +401,8 @@ ostree_builtin_commit (int argc, char **argv, GCancellable *cancellable, GError if (opt_no_xattrs) flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS; + if (opt_canonical_permissions) + flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS; if (opt_generate_sizes) flags |= OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES; if (opt_disable_fsync) From 7c8f95c86f24427abaa3336cf7477c1504e48cfc Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Sun, 26 Mar 2017 11:03:47 +0200 Subject: [PATCH 30/56] Add basic tests for bare-user-only repo modes This is somewhat complicated by such repos only properly supporting some subset of file metadata (uid/gid 0, etc). We fix this by always commiting with filters that make it work. Closes: #750 Approved by: cgwalters --- Makefile-tests.am | 1 + tests/basic-test.sh | 111 +++++++++++++++++++--------------- tests/libtest.sh | 9 ++- tests/test-basic-user-only.sh | 25 ++++++++ 4 files changed, 96 insertions(+), 50 deletions(-) create mode 100755 tests/test-basic-user-only.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index fd755ee1..bba8f008 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -46,6 +46,7 @@ dist_uninstalled_test_scripts = tests/test-symbols.sh dist_test_scripts = \ tests/test-basic.sh \ tests/test-basic-user.sh \ + tests/test-basic-user-only.sh \ tests/test-pull-subpath.sh \ tests/test-archivez.sh \ tests/test-remote-add.sh \ diff --git a/tests/basic-test.sh b/tests/basic-test.sh index c1c6173b..27b79026 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -25,6 +25,19 @@ $CMD_PREFIX ostree --version > version.yaml python -c 'import yaml; yaml.safe_load(open("version.yaml"))' echo "ok yaml version" +CHECKOUT_U_ARG="" +COMMIT_ARGS="" +DIFF_ARGS="" +if grep bare-user-only repo/config; then + # In bare-user-only repos we can only represent files with uid/gid 0, no + # xattrs and canonical permissions, so we need to commit them as such, or + # we end up with repos that don't pass fsck + COMMIT_ARGS="--canonical-permissions" + DIFF_ARGS="--owner-uid=0 --owner-gid=0 --no-xattrs" + # Also, since we can't check out uid=0 files we need to check out in user mode + CHECKOUT_U_ARG="-U" +fi + $OSTREE checkout test2 checkout-test2 echo "ok checkout" @@ -59,7 +72,7 @@ assert_has_file baz/deeper/ohyeah echo "ok content" rm firstfile -$OSTREE commit -b test2 -s delete +$OSTREE commit ${COMMIT_ARGS} -b test2 -s delete cd $test_tmpdir $OSTREE checkout test2 $test_tmpdir/checkout-test2-2 @@ -80,7 +93,7 @@ mkdir -p another/nested/tree echo anotherone > another/nested/tree/1 echo whee2 > another/whee # FIXME - remove grep for . -$OSTREE commit -b test2 -s "Another commit" +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Another commit" echo "ok commit" cd ${test_tmpdir} @@ -96,7 +109,7 @@ mkdir -p yet/another/tree echo leaf > yet/another/tree/green echo helloworld > yet/message rm a/5 -$OSTREE commit -b test2 -s "Current directory" +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Current directory" echo "ok cwd commit" cd ${test_tmpdir} @@ -107,15 +120,15 @@ assert_file_has_content four '4' echo "ok cwd contents" cd ${test_tmpdir} -$OSTREE commit -b test2-no-parent -s '' $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-no-parent -s '' $test_tmpdir/checkout-test2-4 assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1" -$OSTREE commit -b test2-no-parent -s '' --parent=none $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-no-parent -s '' --parent=none $test_tmpdir/checkout-test2-4 assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1" echo "ok commit no parent" cd ${test_tmpdir} -empty_rev=$($OSTREE commit -b test2-no-subject -s '' --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4) -omitted_rev=$($OSTREE commit -b test2-no-subject-2 --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4) +empty_rev=$($OSTREE commit ${COMMIT_ARGS} -b test2-no-subject -s '' --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4) +omitted_rev=$($OSTREE commit ${COMMIT_ARGS} -b test2-no-subject-2 --timestamp="2005-10-29 12:43:29 +0000" $test_tmpdir/checkout-test2-4) assert_streq $empty_rev $omitted_rev echo "ok commit no subject" @@ -127,7 +140,7 @@ commit message. Build-Host: foo.example.com Crunchy-With-Extra-Ketchup: true EOF -$OSTREE commit -b branch-with-commitmsg -F commitmsg.txt -s 'a message' $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b branch-with-commitmsg -F commitmsg.txt -s 'a message' $test_tmpdir/checkout-test2-4 $OSTREE log branch-with-commitmsg > log.txt assert_file_has_content log.txt '^ *This is a long$' assert_file_has_content log.txt '^ *Build-Host:.*example.com$' @@ -136,17 +149,17 @@ $OSTREE refs --delete branch-with-commitmsg echo "ok commit body file" cd ${test_tmpdir} -$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 -$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 -$OSTREE commit -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-custom-parent -s '' $test_tmpdir/checkout-test2-4 assert_streq $($OSTREE log test2-custom-parent |grep '^commit' | wc -l) "3" prevparent=$($OSTREE rev-parse test2-custom-parent^) -$OSTREE commit -b test2-custom-parent -s '' --parent=${prevparent} $test_tmpdir/checkout-test2-4 +$OSTREE commit ${COMMIT_ARGS} -b test2-custom-parent -s '' --parent=${prevparent} $test_tmpdir/checkout-test2-4 assert_streq $($OSTREE log test2-custom-parent |grep '^commit' | wc -l) "3" echo "ok commit custom parent" cd ${test_tmpdir} -orphaned_rev=$($OSTREE commit --orphan -s "$(date)" $test_tmpdir/checkout-test2-4) +orphaned_rev=$($OSTREE commit ${COMMIT_ARGS} --orphan -s "$(date)" $test_tmpdir/checkout-test2-4) $OSTREE ls ${orphaned_rev} >/dev/null $OSTREE prune --refs-only if $OSTREE ls ${orphaned_rev} 2>err.txt; then @@ -172,15 +185,15 @@ assert_file_has_content diff-test2-2 'A *oh-look-a-file$' echo "ok diff cwd" cd ${test_tmpdir}/checkout-test2-4 -$OSTREE diff test2 ./ > ${test_tmpdir}/diff-test2 +$OSTREE diff ${DIFF_ARGS} test2 ./ > ${test_tmpdir}/diff-test2 assert_file_empty ${test_tmpdir}/diff-test2 -$OSTREE diff test2 --owner-uid=$((`id -u`+1)) ./ > ${test_tmpdir}/diff-test2 +$OSTREE diff ${DIFF_ARGS} test2 --owner-uid=$((`id -u`+1)) ./ > ${test_tmpdir}/diff-test2 assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' echo "ok diff file with different uid" -$OSTREE diff test2 --owner-gid=$((`id -g`+1)) ./ > ${test_tmpdir}/diff-test2 +$OSTREE diff ${DIFF_ARGS} test2 --owner-gid=$((`id -g`+1)) ./ > ${test_tmpdir}/diff-test2 assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet$' assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/message$' assert_file_has_content ${test_tmpdir}/diff-test2 'M */yet/another/tree/green$' @@ -197,12 +210,12 @@ echo "ok diff file changing type" cd ${test_tmpdir} mkdir repo2 -ostree_repo_init repo2 +ostree_repo_init repo2 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo2 pull-local repo echo "ok pull-local" cd ${test_tmpdir} -${CMD_PREFIX} ostree --repo=repo2 checkout test2 test2-checkout-from-local-clone +${CMD_PREFIX} ostree --repo=repo2 checkout ${CHECKOUT_U_ARG} test2 test2-checkout-from-local-clone cd test2-checkout-from-local-clone assert_file_has_content yet/another/tree/green 'leaf' echo "ok local clone checkout" @@ -210,31 +223,33 @@ echo "ok local clone checkout" $OSTREE checkout -U test2 checkout-user-test2 echo "ok user checkout" -$OSTREE commit -b test2 -s "Another commit" --tree=ref=test2 +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Another commit" --tree=ref=test2 echo "ok commit from ref" -$OSTREE commit -b test2 -s "Another commit with modifier" --tree=ref=test2 --owner-uid=`id -u` +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Another commit with modifier" --tree=ref=test2 --owner-uid=`id -u` echo "ok commit from ref with modifier" -$OSTREE commit -b trees/test2 -s 'ref with / in it' --tree=ref=test2 +$OSTREE commit ${COMMIT_ARGS} -b trees/test2 -s 'ref with / in it' --tree=ref=test2 echo "ok commit ref with /" old_rev=$($OSTREE rev-parse test2) -$OSTREE commit --skip-if-unchanged -b test2 -s 'should not be committed' --tree=ref=test2 +$OSTREE ls -R -C test2 +$OSTREE commit ${COMMIT_ARGS} --skip-if-unchanged -b trees/test2 -s 'should not be committed' --tree=ref=test2 +$OSTREE ls -R -C test2 new_rev=$($OSTREE rev-parse test2) assert_streq "${old_rev}" "${new_rev}" echo "ok commit --skip-if-unchanged" cd ${test_tmpdir}/checkout-test2-4 -$OSTREE commit -b test2 -s "no xattrs" --no-xattrs +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "no xattrs" --no-xattrs echo "ok commit with no xattrs" mkdir tree-A tree-B touch tree-A/file-a tree-B/file-b -$OSTREE commit -b test3-1 -s "Initial tree" --tree=dir=tree-A -$OSTREE commit -b test3-2 -s "Replacement tree" --tree=dir=tree-B -$OSTREE commit -b test3-combined -s "combined tree" --tree=ref=test3-1 --tree=ref=test3-2 +$OSTREE commit ${COMMIT_ARGS} -b test3-1 -s "Initial tree" --tree=dir=tree-A +$OSTREE commit ${COMMIT_ARGS} -b test3-2 -s "Replacement tree" --tree=dir=tree-B +$OSTREE commit ${COMMIT_ARGS} -b test3-combined -s "combined tree" --tree=ref=test3-1 --tree=ref=test3-2 $OSTREE checkout test3-combined checkout-test3-combined @@ -250,7 +265,7 @@ cat > test-statoverride.txt < test-skiplist.txt < union-files-count -$OSTREE checkout --union test2 checkout-test2-union +$OSTREE checkout --union test2 checkout-test2-union find checkout-test2-union | wc -l > union-files-count.new cmp union-files-count{,.new} cd checkout-test2-union @@ -295,11 +310,11 @@ assert_file_has_content ./yet/another/tree/green "leaf" echo "ok checkout union 1" cd ${test_tmpdir} -$OSTREE commit -b test-union-add --tree=ref=test2 +$OSTREE commit ${COMMIT_ARGS} -b test-union-add --tree=ref=test2 $OSTREE checkout test-union-add checkout-test-union-add echo 'file for union add testing' > checkout-test-union-add/union-add-test echo 'another file for union add testing' > checkout-test-union-add/union-add-test2 -$OSTREE commit -b test-union-add --tree=dir=checkout-test-union-add +$OSTREE commit ${COMMIT_ARGS} -b test-union-add --tree=dir=checkout-test-union-add rm checkout-test-union-add -rf # Check out previous $OSTREE checkout test-union-add^ checkout-test-union-add @@ -319,7 +334,7 @@ ostree_repo_init shadow-repo ${CMD_PREFIX} ostree --repo=shadow-repo config set core.parent $(pwd)/repo rm -rf test2-checkout parent_rev_test2=$(${CMD_PREFIX} ostree --repo=repo rev-parse test2) -${CMD_PREFIX} ostree --repo=shadow-repo checkout "${parent_rev_test2}" test2-checkout +${CMD_PREFIX} ostree --repo=shadow-repo checkout ${CHECKOUT_U_ARG} "${parent_rev_test2}" test2-checkout echo "ok checkout from shadow repo" cd ${test_tmpdir} @@ -335,7 +350,7 @@ echo "ok subdir noent" cd ${test_tmpdir} mkdir repo3 -ostree_repo_init repo3 +ostree_repo_init repo3 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo3 pull-local --remote=aremote repo test2 ${CMD_PREFIX} ostree --repo=repo3 rev-parse aremote/test2 echo "ok pull-local with --remote arg" @@ -368,7 +383,7 @@ echo "ok prune in archive-z2 deleted everything" cd ${test_tmpdir} rm -rf test2-checkout $OSTREE checkout test2 test2-checkout -(cd test2-checkout && $OSTREE commit --link-checkout-speedup -b test2 -s "tmp") +(cd test2-checkout && $OSTREE commit ${COMMIT_ARGS} --link-checkout-speedup -b test2 -s "tmp") echo "ok commit with link speedup" cd ${test_tmpdir} @@ -387,7 +402,7 @@ $OSTREE show test2 echo "ok show with non-checksum" cd $test_tmpdir/checkout-test2 -checksum=$($OSTREE commit -b test4 -s "Third commit") +checksum=$($OSTREE commit ${COMMIT_ARGS} -b test4 -s "Third commit") cd ${test_tmpdir} $OSTREE show test4 > show-output assert_file_has_content show-output "Third commit" @@ -395,8 +410,8 @@ assert_file_has_content show-output "commit $checksum" echo "ok show full output" cd $test_tmpdir/checkout-test2 -checksum1=$($OSTREE commit -b test5 -s "First commit") -checksum2=$($OSTREE commit -b test5 -s "Second commit") +checksum1=$($OSTREE commit ${COMMIT_ARGS} -b test5 -s "First commit") +checksum2=$($OSTREE commit ${COMMIT_ARGS} -b test5 -s "Second commit") cd ${test_tmpdir} $OSTREE log test5 > log-output assert_file_has_content log-output "First commit" @@ -406,8 +421,8 @@ assert_file_has_content log-output "commit $checksum2" echo "ok log output" cd $test_tmpdir/checkout-test2 -checksum1=$($OSTREE commit -b test6 -s "First commit") -checksum2=$($OSTREE commit -b test6 -s "Second commit") +checksum1=$($OSTREE commit ${COMMIT_ARGS} -b test6 -s "First commit") +checksum2=$($OSTREE commit ${COMMIT_ARGS} -b test6 -s "Second commit") cd ${test_tmpdir} $OSTREE show test6 > show-output assert_file_has_content show-output "commit $checksum2" @@ -420,11 +435,11 @@ cd ${test_tmpdir} rm checkout-test2 -rf $OSTREE checkout test2 checkout-test2 touch checkout-test2/sometestfile -$OSTREE commit -s sometest -b test2 checkout-test2 +$OSTREE commit ${COMMIT_ARGS} -s sometest -b test2 checkout-test2 echo "ok commit with directory filename" cd $test_tmpdir/checkout-test2 -$OSTREE commit -b test2 -s "Metadata string" --add-metadata-string=FOO=BAR --add-metadata-string=KITTENS=CUTE --add-detached-metadata-string=SIGNATURE=HANCOCK --tree=ref=test2 +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Metadata string" --add-metadata-string=FOO=BAR --add-metadata-string=KITTENS=CUTE --add-detached-metadata-string=SIGNATURE=HANCOCK --tree=ref=test2 cd ${test_tmpdir} $OSTREE show --print-metadata-key=FOO test2 > test2-meta assert_file_has_content test2-meta "BAR" @@ -437,7 +452,7 @@ echo "ok metadata commit with strings" cd ${test_tmpdir} rm repo2 -rf mkdir repo2 -ostree_repo_init repo2 +ostree_repo_init repo2 --mode=bare-user ${CMD_PREFIX} ostree --repo=repo2 pull-local repo ${CMD_PREFIX} ostree --repo=repo2 show --print-detached-metadata-key=SIGNATURE test2 > test2-meta assert_file_has_content test2-meta "HANCOCK" @@ -472,7 +487,7 @@ rm -rf test2-checkout mkdir -p test2-checkout cd test2-checkout mkfifo afifo -if $OSTREE commit -b test2 -s "Attempt to commit a FIFO" 2>../errmsg; then +if $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Attempt to commit a FIFO" 2>../errmsg; then assert_not_reached "Committing a FIFO unexpetedly succeeded!" assert_file_has_content ../errmsg "Unsupported file type" fi @@ -504,7 +519,7 @@ date > checkout-test2/date.txt rm repo/tmp/* -rf export TEST_BOOTID=3072029c-8b10-60d1-d31b-8422eeff9b42 if env OSTREE_REPO_TEST_ERROR=pre-commit OSTREE_BOOTID=${TEST_BOOTID} \ - $OSTREE commit -b test2 -s '' $test_tmpdir/checkout-test2 2>err.txt; then + $OSTREE commit ${COMMIT_ARGS} -b test2 -s '' $test_tmpdir/checkout-test2 2>err.txt; then assert_not_reached "Should have hit OSTREE_REPO_TEST_ERROR_PRE_COMMIT" fi assert_file_has_content err.txt OSTREE_REPO_TEST_ERROR_PRE_COMMIT @@ -526,7 +541,7 @@ if touch overlay/baz/.wh.cow && touch overlay/.wh.deeper; then touch overlay/anewfile mkdir overlay/anewdir/ touch overlay/anewdir/blah - $OSTREE --repo=repo commit -b overlay -s 'overlay' --tree=dir=overlay + $OSTREE --repo=repo commit ${COMMIT_ARGS} -b overlay -s 'overlay' --tree=dir=overlay rm overlay -rf for branch in test2 overlay; do @@ -563,7 +578,7 @@ rm -rf test2-checkout mkdir -p test2-checkout cd test2-checkout touch should-not-be-fsynced -$OSTREE commit -b test2 -s "Unfsynced commit" --fsync=false +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Unfsynced commit" --fsync=false # Run this test only as non-root user. When run as root, the chmod # won't have any effect. @@ -587,7 +602,7 @@ mkdir -p test2-checkout cd test2-checkout touch blah stat --printf="%.Y\n" ${test_tmpdir}/repo > ${test_tmpdir}/timestamp-orig.txt -$OSTREE commit -b test2 -s "Should bump the mtime" +$OSTREE commit ${COMMIT_ARGS} -b test2 -s "Should bump the mtime" stat --printf="%.Y\n" ${test_tmpdir}/repo > ${test_tmpdir}/timestamp-new.txt cd .. if cmp timestamp-{orig,new}.txt; then diff --git a/tests/libtest.sh b/tests/libtest.sh index 363413fd..58351f81 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -206,6 +206,11 @@ setup_test_repository () { oldpwd=`pwd` + COMMIT_ARGS="" + if [ $mode == "bare-user-only" ] ; then + COMMIT_ARGS="--owner-uid=0 --owner-gid=0 --no-xattrs --canonical-permissions" + fi + cd ${test_tmpdir} if test -n "${mode}"; then ostree_repo_init repo --mode=${mode} @@ -224,7 +229,7 @@ setup_test_repository () { echo first > firstfile cd ${test_tmpdir}/files - $OSTREE commit -b test2 -s "Test Commit 1" -m "Commit body first" + $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Test Commit 1" -m "Commit body first" mkdir baz echo moo > baz/cow @@ -236,7 +241,7 @@ setup_test_repository () { echo x > baz/another/y cd ${test_tmpdir}/files - $OSTREE commit -b test2 -s "Test Commit 2" -m "Commit body second" + $OSTREE commit ${COMMIT_ARGS} -b test2 -s "Test Commit 2" -m "Commit body second" $OSTREE fsck -q cd $oldpwd diff --git a/tests/test-basic-user-only.sh b/tests/test-basic-user-only.sh new file mode 100755 index 00000000..a3e63aac --- /dev/null +++ b/tests/test-basic-user-only.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# +# Copyright (C) 2011 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +setup_test_repository "bare-user-only" +. $(dirname $0)/basic-test.sh From 3b09620c2738bce4ed45e099cf2e4c5df7671d39 Mon Sep 17 00:00:00 2001 From: Anton Gerasimov Date: Mon, 27 Mar 2017 16:05:46 +0200 Subject: [PATCH 31/56] Define TARGET_PREFIX to use with grub2 deployment Closes: #760 Approved by: cgwalters --- Makefile.am | 2 +- src/libostree/ostree-bootloader-grub2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index cc0e76f5..78cd6653 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ OSTREE_GITREV=$(shell if command -v git >/dev/null 2>&1 && test -d $(srcdir)/.gi ACLOCAL_AMFLAGS = -I buildutil -I libglnx ${ACLOCAL_FLAGS} AM_CPPFLAGS += -DDATADIR='"$(datadir)"' -DLIBEXECDIR='"$(libexecdir)"' \ -DLOCALEDIR=\"$(datadir)/locale\" -DSYSCONFDIR=\"$(sysconfdir)\" \ - -DSHORTENED_SYSCONFDIR=\"$(shortened_sysconfdir)\" \ + -DTARGET_PREFIX='"$(prefix)"' -DSHORTENED_SYSCONFDIR=\"$(shortened_sysconfdir)\" \ -DOSTREE_FEATURES='"$(OSTREE_FEATURES)"' \ -DOSTREE_COMPILATION \ -DG_LOG_DOMAIN=\"OSTree\" \ diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c index 6f245fb7..2cd02287 100644 --- a/src/libostree/ostree-bootloader-grub2.c +++ b/src/libostree/ostree-bootloader-grub2.c @@ -353,7 +353,7 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader, use_system_grub2_mkconfig = FALSE; } else - grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : "/usr/lib/ostree/ostree-grub-generator"; + grub_exec = use_system_grub2_mkconfig ? GRUB2_MKCONFIG_PATH : TARGET_PREFIX "/lib/ostree/ostree-grub-generator"; if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL && g_file_has_parent (self->sysroot->path, NULL)) From 79c3eb63be9d743128dfa0081e5be758ded4f79c Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 15 Mar 2017 12:13:58 -0400 Subject: [PATCH 32/56] pull: Also skip partial commits for deltas if no summary file I was playing around in a FAH vagrant box, and hit: ``` Receiving delta parts: 3/4 453.2 kB/s 1.8 MB/145.8 MB error: opcode set-read-source: No such file object b6e54ba3471b9c116ce6b9bfbf9e55fec60d35cfdb9ae5ae1ee219af02a591b7 ``` This is because this host version doesn't yet have https://github.com/ostreedev/ostree/pull/710 which incidentally fixed this for the case where the OS vendor is using summary files. Some organizations may not be using summary files - at least we still try to support that case. So let's copy the logic very recently added in that commit to handle the legacy case too. No new tests since this is a nice-to-have - we really do expect people to be using summary files now. Closes: #739 Approved by: jlebon --- src/libostree/ostree-repo-pull.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index ec085a81..b7be8a95 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1197,6 +1197,14 @@ gpg_verify_unwritten_commit (OtPullData *pull_data, return TRUE; } +static gboolean +commitstate_is_partial (OtPullData *pull_data, + OstreeRepoCommitState commitstate) +{ + return pull_data->legacy_transaction_resuming + || (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) > 0; +} + static gboolean scan_commit_object (OtPullData *pull_data, const char *checksum, @@ -1253,8 +1261,7 @@ scan_commit_object (OtPullData *pull_data, goto out; /* If we found a legacy transaction flag, assume all commits are partial */ - is_partial = pull_data->legacy_transaction_resuming - || (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL) > 0; + is_partial = commitstate_is_partial (pull_data, commitstate); /* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */ g_variant_get_child (commit, 1, "@ay", &parent_csum); @@ -3242,6 +3249,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_autofree char *from_revision = NULL; const char *ref = key; const char *to_revision = value; + gboolean have_valid_from_commit = TRUE; /* If we have a summary, find the latest local commit we have * to use as a from revision for static deltas. @@ -3257,9 +3265,27 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (!ostree_repo_resolve_rev (pull_data->repo, ref, TRUE, &from_revision, error)) goto out; + + /* Determine whether the from revision we have is partial; this + * can happen if e.g. one uses `ostree pull --commit-metadata-only`. + * This mirrors the logic in get_best_static_delta_start_for(). + */ + if (from_revision) + { + OstreeRepoCommitState from_commitstate; + + if (!ostree_repo_load_commit (pull_data->repo, from_revision, NULL, + &from_commitstate, error)) + goto out; + + /* Was it partial? OK, we can't use it. */ + if (commitstate_is_partial (pull_data, from_commitstate)) + have_valid_from_commit = FALSE; + } } if (!disable_static_deltas && + have_valid_from_commit && (from_revision == NULL || g_strcmp0 (from_revision, to_revision) != 0)) { g_autofree char *delta_name = From a88881039eef1e3db32f5cf0972099280cbe4227 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 27 Mar 2017 17:31:06 -0400 Subject: [PATCH 33/56] sysroot/unlock: Ensure overlay label on /usr is `usr_t` Otherwise, we get `tmp_t` by default which can break a lot of things; we noticed this with `atomic scan`. Closes: https://github.com/ostreedev/ostree/issues/762 Closes: #763 Approved by: rhatdan --- src/libostree/ostree-sysroot.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 446dd4ab..00db9f0a 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -26,6 +26,7 @@ #include #include "ostree-core-private.h" +#include "ostree-sepolicy-private.h" #include "ostree-sysroot-private.h" #include "ostree-deployment-private.h" #include "ostree-bootloader-uboot.h" @@ -1691,6 +1692,7 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, GError **error) { gboolean ret = FALSE; + glnx_unref_object OstreeSePolicy *sepolicy = NULL; OstreeDeploymentUnlockedState current_unlocked = ostree_deployment_get_unlocked (deployment); glnx_unref_object OstreeDeployment *deployment_clone = @@ -1738,6 +1740,10 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, if (!glnx_opendirat (self->sysroot_fd, deployment_path, TRUE, &deployment_dfd, error)) goto out; + sepolicy = ostree_sepolicy_new_at (deployment_dfd, cancellable, error); + if (!sepolicy) + goto out; + switch (unlocked_state) { case OSTREE_DEPLOYMENT_UNLOCKED_NONE: @@ -1765,8 +1771,16 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self, const char *development_ovl_upper; const char *development_ovl_work; - if (!glnx_mkdtempat (AT_FDCWD, development_ovldir, 0700, error)) - goto out; + /* Ensure that the directory is created with the same label as `/usr` */ + { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; + + if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, + "/usr", 0755, error)) + goto out; + + if (!glnx_mkdtempat (AT_FDCWD, development_ovldir, 0755, error)) + goto out; + } development_ovl_upper = glnx_strjoina (development_ovldir, "/upper"); if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_upper, 0755, cancellable, error)) From 562cb55f511237d2c8e89f5bf1dfa4e68bff9a2d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 13:29:38 -0400 Subject: [PATCH 34/56] ci: Enable -Werror=unused-result with -Wp,-D_FORTIFY_SOURCE=2 (Also rename the other CI contexts to be more consistent) We pass this right now. I just noticed an instance of this in bwrap, and I think we should be trying to match the RPM build baseline. Closes: #765 Approved by: jlebon --- .redhat-ci.yml | 7 ++++--- configure.ac | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.redhat-ci.yml b/.redhat-ci.yml index 8073ed9c..cfff0fa0 100644 --- a/.redhat-ci.yml +++ b/.redhat-ci.yml @@ -4,6 +4,7 @@ branches: - try required: true +context: f25-sanitizer container: image: projectatomic/ostree-tester @@ -12,7 +13,7 @@ packages: - libasan env: - CFLAGS: '-fsanitize=undefined -fsanitize-undefined-trap-on-error -fsanitize=address' + CFLAGS: '-fsanitize=undefined -fsanitize-undefined-trap-on-error -fsanitize=address -O2 -Wp,-D_FORTIFY_SOURCE=2' ASAN_OPTIONS: 'detect_leaks=0' # Right now we're not fully clean, but this gets us use-after-free etc # TODO when we're doing leak checks: G_SLICE: "always-malloc" @@ -38,7 +39,7 @@ artifacts: inherit: true required: true -context: Clang +context: f25-clang env: CC: 'clang' @@ -76,7 +77,7 @@ tests: inherit: true required: true -context: curl-openssl +context: f25-curl-openssl packages: - pkgconfig(libcurl) diff --git a/configure.ac b/configure.ac index d43536e3..dbbd63e5 100644 --- a/configure.ac +++ b/configure.ac @@ -42,6 +42,7 @@ CC_CHECK_FLAGS_APPEND([WARN_CFLAGS], [CFLAGS], [\ -Werror=incompatible-pointer-types \ -Werror=misleading-indentation \ -Werror=missing-include-dirs -Werror=aggregate-return \ + -Werror=unused-result \ ]) AC_SUBST(WARN_CFLAGS) From 5333a429ce124854512d7c88ec05ae50d511bd2a Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 11:16:09 -0400 Subject: [PATCH 35/56] sysroot: Don't cache sepolicy In [this commit](https://github.com/ostreedev/ostree/commit/6ce80f9685e6273dbcb4731d6650a10976ea220a) for some reason I added a `sepolicy` member to the sysroot. I have no idea why I did that, and it's conceptually wrong since the policy is specific to a *deployment*. This bit me when I was working on [a pull request](https://github.com/ostreedev/ostree/pull/763) elsewhere, since at that point it was `NULL`. We already pass around the sepolicy in the deployment code, so just stop caching it. Closes: #764 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 7 ++----- src/libostree/ostree-sysroot-private.h | 2 -- src/libostree/ostree-sysroot.c | 1 - 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d12e47b2..ee25d3f0 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -756,7 +756,7 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot, { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; const char *selabeled_abspath = glnx_strjoina ("/", selabeled); - if (!_ostree_sepolicy_preparefscreatecon (&con, sysroot->sepolicy, + if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, selabeled_abspath, 0644, error)) return FALSE; @@ -2128,9 +2128,6 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, return FALSE; } - g_clear_object (&self->sepolicy); - self->sepolicy = g_object_ref (sepolicy); - if (!selinux_relabel_var_if_needed (self, sepolicy, os_deploy_dfd, cancellable, error)) return FALSE; @@ -2144,7 +2141,7 @@ ostree_sysroot_deploy_tree (OstreeSysroot *self, { g_auto(OstreeSepolicyFsCreatecon) con = { 0, }; - if (!_ostree_sepolicy_preparefscreatecon (&con, self->sepolicy, + if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy, "/etc/ostree/remotes.d/dummy.conf", 0644, error)) return FALSE; diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index 3900092a..4bc7802b 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -49,8 +49,6 @@ struct OstreeSysroot { gboolean loaded; - OstreeSePolicy *sepolicy; - GPtrArray *deployments; int bootversion; int subbootversion; diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 00db9f0a..bdf7376b 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -72,7 +72,6 @@ ostree_sysroot_finalize (GObject *object) OstreeSysroot *self = OSTREE_SYSROOT (object); g_clear_object (&self->path); - g_clear_object (&self->sepolicy); g_clear_object (&self->repo); g_clear_pointer (&self->deployments, g_ptr_array_unref); g_clear_object (&self->booted_deployment); From d994aee0a11701068c831b7768c11a00a361f428 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 27 Mar 2017 14:42:08 -0400 Subject: [PATCH 36/56] repo/commit: Change most of this file to new code style I didn't touch everything since at least `commit_loose_object_trusted` does this: ``` out: if (G_UNLIKELY (error && *error)) g_prefix_error (error, "Writing object %s.%s: ", checksum, ostree_object_type_to_string (objtype)); ``` Which...it'd be interesting to make into an autocleanup. But for now just keeping up with converting things bit by bit. Closes: #761 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 367 ++++++++++------------------- 1 file changed, 130 insertions(+), 237 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 0e85bcb1..56b4e8f8 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -144,7 +144,6 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; int dest_dfd; char tmpbuf[_OSTREE_LOOSE_PATH_MAX]; @@ -157,13 +156,13 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, if (!_ostree_repo_ensure_loose_objdir_at (dest_dfd, tmpbuf, cancellable, error)) - goto out; + return FALSE; if (fd != -1) { if (!glnx_link_tmpfile_at (temp_dfd, GLNX_LINK_TMPFILE_NOREPLACE_IGNORE_EXIST, fd, temp_filename, dest_dfd, tmpbuf, error)) - goto out; + return FALSE; } else { @@ -171,19 +170,13 @@ _ostree_repo_commit_loose_final (OstreeRepo *self, dest_dfd, tmpbuf) == -1)) { if (errno != EEXIST) - { - glnx_set_error_from_errno (error); - g_prefix_error (error, "Storing file '%s': ", temp_filename); - goto out; - } + return glnx_throw_errno_prefix (error, "Storing file '%s'", temp_filename); else (void) unlinkat (temp_dfd, temp_filename, 0); } } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -297,19 +290,13 @@ commit_loose_object_trusted (OstreeRepo *self, checkout. To make this work we apply all user bits and the read bits for group/other. Furthermore, setting user xattrs requires write access, so this makes sure it's at least writable by us. (O_TMPFILE uses mode 0 by default) */ - do - res = fchmod (fd, mode | 0744); - while (G_UNLIKELY (res == -1 && errno == EINTR)); - if (G_UNLIKELY (res == -1)) - { - glnx_set_error_from_errno (error); - goto out; - } + if (fchmod (fd, mode | 0744) < 0) + return glnx_throw_errno (error); } if (self->mode == OSTREE_REPO_MODE_BARE_USER && !write_file_metadata_to_xattr (fd, uid, gid, mode, xattrs, error)) - goto out; + return FALSE; } if (objtype == OSTREE_OBJECT_TYPE_FILE && _ostree_repo_mode_is_bare (self->mode)) @@ -1123,8 +1110,6 @@ ostree_repo_prepare_transaction (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - gboolean ret_transaction_resume = FALSE; g_return_val_if_fail (self->in_transaction == FALSE, FALSE); @@ -1132,6 +1117,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self, self->in_transaction = TRUE; + gboolean ret_transaction_resume = FALSE; if (!_ostree_repo_allocate_tmpdir (self->tmp_dir_fd, self->stagedir_prefix, &self->commit_stagedir_name, @@ -1139,13 +1125,11 @@ ostree_repo_prepare_transaction (OstreeRepo *self, &self->commit_stagedir_lock, &ret_transaction_resume, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; if (out_transaction_resume) *out_transaction_resume = ret_transaction_resume; - out: - return ret; + return TRUE; } static gboolean @@ -1153,11 +1137,10 @@ rename_pending_loose_objects (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!glnx_dirfd_iterator_init_at (self->commit_stagedir_fd, ".", FALSE, &dfd_iter, error)) - goto out; + return FALSE; /* Iterate over the outer checksum dir */ while (TRUE) @@ -1166,7 +1149,7 @@ rename_pending_loose_objects (OstreeRepo *self, g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, }; if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error)) - goto out; + return FALSE; if (dent == NULL) break; @@ -1179,7 +1162,7 @@ rename_pending_loose_objects (OstreeRepo *self, if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE, &child_dfd_iter, error)) - goto out; + return FALSE; /* Iterate over inner checksum dir */ while (TRUE) @@ -1188,7 +1171,7 @@ rename_pending_loose_objects (OstreeRepo *self, char loose_objpath[_OSTREE_LOOSE_PATH_MAX]; if (!glnx_dirfd_iterator_next_dent (&child_dfd_iter, &child_dent, cancellable, error)) - goto out; + return FALSE; if (child_dent == NULL) break; @@ -1200,24 +1183,19 @@ rename_pending_loose_objects (OstreeRepo *self, if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_objpath, cancellable, error)) - goto out; + return FALSE; if (G_UNLIKELY (renameat (child_dfd_iter.fd, loose_objpath + 3, self->objects_dir_fd, loose_objpath) < 0)) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); } } if (!glnx_shutil_rm_rf_at (self->tmp_dir_fd, self->commit_stagedir_name, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1225,14 +1203,13 @@ cleanup_tmpdir (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; guint64 curtime_secs; curtime_secs = g_get_real_time () / 1000000; if (!glnx_dirfd_iterator_init_at (self->tmp_dir_fd, ".", TRUE, &dfd_iter, error)) - goto out; + return FALSE; while (TRUE) { @@ -1243,7 +1220,7 @@ cleanup_tmpdir (OstreeRepo *self, gboolean did_lock; if (!glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, cancellable, error)) - goto out; + return FALSE; if (dent == NULL) break; @@ -1258,8 +1235,7 @@ cleanup_tmpdir (OstreeRepo *self, { if (errno == ENOENT) /* Did another cleanup win? */ continue; - glnx_set_error_from_errno (error); - goto out; + return glnx_throw_errno (error); } /* First, if it's a directory which needs locking, but it's @@ -1269,7 +1245,7 @@ cleanup_tmpdir (OstreeRepo *self, { if (!_ostree_repo_try_lock_tmpdir (dfd_iter.fd, dent->d_name, &lockfile, &did_lock, error)) - goto out; + return FALSE; if (!did_lock) continue; } @@ -1286,7 +1262,7 @@ cleanup_tmpdir (OstreeRepo *self, * from *other* boots */ if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error)) - goto out; + return FALSE; } /* FIXME - move OSTREE_REPO_TMPDIR_FETCHER underneath the * staging/boot-id scheme as well, since all of the "did it get @@ -1311,14 +1287,12 @@ cleanup_tmpdir (OstreeRepo *self, if (delta > self->tmp_expiry_seconds) { if (!glnx_shutil_rm_rf_at (dfd_iter.fd, dent->d_name, cancellable, error)) - goto out; + return FALSE; } } } - ret = TRUE; - out: - return ret; + return TRUE; } static void @@ -1432,16 +1406,10 @@ ostree_repo_commit_transaction (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_return_val_if_fail (self->in_transaction == TRUE, FALSE); if ((self->test_error_flags & OSTREE_REPO_TEST_ERROR_PRE_COMMIT) > 0) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "OSTREE_REPO_TEST_ERROR_PRE_COMMIT specified"); - goto out; - } + 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. @@ -1449,24 +1417,21 @@ ostree_repo_commit_transaction (OstreeRepo *self, if (g_getenv ("OSTREE_SUPPRESS_SYNCFS") == NULL) { if (syncfs (self->tmp_dir_fd) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); } if (!rename_pending_loose_objects (self, cancellable, error)) - goto out; + return FALSE; if (!cleanup_tmpdir (self, cancellable, error)) - goto out; + return FALSE; if (self->loose_object_devino_hash) g_hash_table_remove_all (self->loose_object_devino_hash); if (self->txn_refs) if (!_ostree_repo_update_refs (self, self->txn_refs, cancellable, error)) - goto out; + return FALSE; g_clear_pointer (&self->txn_refs, g_hash_table_destroy); if (self->commit_stagedir_fd != -1) @@ -1482,14 +1447,12 @@ ostree_repo_commit_transaction (OstreeRepo *self, self->in_transaction = FALSE; if (!ot_ensure_unlinked_at (self->repo_dir_fd, "transaction", 0)) - goto out; + return FALSE; if (out_stats) *out_stats = self->txn_stats; - ret = TRUE; - out: - return ret; + return TRUE; } gboolean @@ -1497,13 +1460,12 @@ ostree_repo_abort_transaction (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - + /* Note early return */ if (!self->in_transaction) return TRUE; if (!cleanup_tmpdir (self, cancellable, error)) - goto out; + return FALSE; if (self->loose_object_devino_hash) g_hash_table_remove_all (self->loose_object_devino_hash); @@ -1521,9 +1483,7 @@ ostree_repo_abort_transaction (OstreeRepo *self, self->in_transaction = FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -1551,8 +1511,6 @@ ostree_repo_write_metadata (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GInputStream) input = NULL; g_autoptr(GVariant) normalized = NULL; normalized = g_variant_get_normal_form (object); @@ -1561,25 +1519,19 @@ ostree_repo_write_metadata (OstreeRepo *self, { g_autofree char *input_bytes = g_format_size (g_variant_get_size (normalized)); g_autofree char *max_bytes = g_format_size (OSTREE_MAX_METADATA_SIZE); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Metadata object of type '%s' is %s; maximum metadata size is %s", - ostree_object_type_to_string (objtype), - input_bytes, - max_bytes); - goto out; + return glnx_throw (error, "Metadata object of type '%s' is %s; maximum metadata size is %s", + ostree_object_type_to_string (objtype), input_bytes, max_bytes); } - input = ot_variant_read (normalized); + g_autoptr(GInputStream) input = ot_variant_read (normalized); if (!write_object (self, objtype, expected_checksum, input, g_variant_get_size (normalized), out_csum, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2006,38 +1958,33 @@ ostree_repo_write_commit_with_time (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autofree char *ret_commit = NULL; - g_autoptr(GVariant) commit = NULL; - g_autoptr(GVariant) new_metadata = NULL; - g_autofree guchar *commit_csum = NULL; OstreeRepoFile *repo_root = OSTREE_REPO_FILE (root); /* Add sizes information to our metadata object */ + g_autoptr(GVariant) new_metadata = NULL; if (!add_size_index_to_metadata (self, metadata, &new_metadata, cancellable, error)) - goto out; + return FALSE; - commit = g_variant_new ("(@a{sv}@ay@a(say)sst@ay@ay)", - new_metadata ? new_metadata : create_empty_gvariant_dict (), - parent ? ostree_checksum_to_bytes_v (parent) : ot_gvariant_new_bytearray (NULL, 0), - g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0), - subject ? subject : "", body ? body : "", - GUINT64_TO_BE (time), - ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_contents_checksum (repo_root)), - ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_metadata_checksum (repo_root))); + g_autoptr(GVariant) commit = + g_variant_new ("(@a{sv}@ay@a(say)sst@ay@ay)", + new_metadata ? new_metadata : create_empty_gvariant_dict (), + parent ? ostree_checksum_to_bytes_v (parent) : ot_gvariant_new_bytearray (NULL, 0), + g_variant_new_array (G_VARIANT_TYPE ("(say)"), NULL, 0), + subject ? subject : "", body ? body : "", + GUINT64_TO_BE (time), + ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_contents_checksum (repo_root)), + ostree_checksum_to_bytes_v (ostree_repo_file_tree_get_metadata_checksum (repo_root))); g_variant_ref_sink (commit); + g_autofree guchar *commit_csum = NULL; if (!ostree_repo_write_metadata (self, OSTREE_OBJECT_TYPE_COMMIT, NULL, commit, &commit_csum, cancellable, error)) - goto out; + return FALSE; - ret_commit = ostree_checksum_from_bytes (commit_csum); - - ret = TRUE; + g_autofree char *ret_commit = ostree_checksum_from_bytes (commit_csum); ot_transfer_out_value(out_commit, &ret_commit); - out: - return ret; + return TRUE; } /** @@ -2059,29 +2006,21 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; char buf[_OSTREE_LOOSE_PATH_MAX]; - g_autoptr(GVariant) ret_metadata = NULL; - _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, G_VARIANT_TYPE ("a{sv}"), OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) - { - g_prefix_error (error, "Unable to read existing detached metadata: "); - goto out; - } + return g_prefix_error (error, "Unable to read existing detached metadata: "), FALSE; if (ret_metadata == NULL && !ot_util_variant_map_at (self->objects_dir_fd, buf, G_VARIANT_TYPE ("a{sv}"), OT_VARIANT_MAP_ALLOW_NOENT | OT_VARIANT_MAP_TRUSTED, &ret_metadata, error)) - { - g_prefix_error (error, "Unable to read existing detached metadata: "); - goto out; - } + return g_prefix_error (error, "Unable to read existing detached metadata: "), FALSE; if (ret_metadata == NULL && self->parent_repo) return ostree_repo_read_commit_detached_metadata (self->parent_repo, @@ -2089,10 +2028,8 @@ ostree_repo_read_commit_detached_metadata (OstreeRepo *self, out_metadata, cancellable, error); - ret = TRUE; ot_transfer_out_value (out_metadata, &ret_metadata); - out: - return ret; + return TRUE; } /** @@ -2322,7 +2259,6 @@ get_modified_xattrs (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GVariant) ret_xattrs = NULL; if (modifier && modifier->xattr_callback) @@ -2340,27 +2276,27 @@ get_modified_xattrs (OstreeRepo *self, &ret_xattrs, cancellable, error)) - goto out; + return FALSE; } else if (path) { if (!glnx_dfd_name_get_all_xattrs (AT_FDCWD, gs_file_get_path_cached (path), &ret_xattrs, cancellable, error)) - goto out; + return FALSE; } else if (dfd_subpath == NULL) { g_assert (dfd != -1); if (!glnx_fd_get_all_xattrs (dfd, &ret_xattrs, cancellable, error)) - goto out; + return FALSE; } else { g_assert (dfd != -1); if (!glnx_dfd_name_get_all_xattrs (dfd, dfd_subpath, &ret_xattrs, cancellable, error)) - goto out; + return FALSE; } } @@ -2371,7 +2307,7 @@ get_modified_xattrs (OstreeRepo *self, if (!ostree_sepolicy_get_label (modifier->sepolicy, relpath, g_file_info_get_attribute_uint32 (file_info, "unix::mode"), &label, cancellable, error)) - goto out; + return FALSE; if (label) { @@ -2392,12 +2328,10 @@ get_modified_xattrs (OstreeRepo *self, g_variant_ref_sink (ret_xattrs); } } - - ret = TRUE; + if (out_xattrs) *out_xattrs = g_steal_pointer (&ret_xattrs); - out: - return ret; + return TRUE; } static gboolean @@ -2429,7 +2363,6 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GFile) child = NULL; g_autoptr(GFileInfo) modified_info = NULL; glnx_unref_object OstreeMutableTree *child_mtree = NULL; @@ -2451,8 +2384,8 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW) { g_ptr_array_remove_index (path, path->len - 1); - ret = TRUE; - goto out; + /* Note: early return */ + return TRUE; } file_type = g_file_info_get_file_type (child_info); @@ -2463,10 +2396,8 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, case G_FILE_TYPE_REGULAR: break; default: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unsupported file type: '%s'", - gs_file_get_path_cached (child)); - goto out; + return glnx_throw (error, "Unsupported file type: '%s'", + gs_file_get_path_cached (child)); } if (dir_enum != NULL) @@ -2475,26 +2406,26 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, if (file_type == G_FILE_TYPE_DIRECTORY) { if (!ostree_mutable_tree_ensure_dir (mtree, name, &child_mtree, error)) - goto out; + return FALSE; if (dir_enum != NULL) { if (!write_directory_to_mtree_internal (self, child, child_mtree, modifier, path, cancellable, error)) - goto out; + return FALSE; } else { g_auto(GLnxDirFdIterator) child_dfd_iter = { 0, }; if (!glnx_dirfd_iterator_init_at (dfd_iter->fd, name, FALSE, &child_dfd_iter, error)) - goto out; + return FALSE; if (!write_dfd_iter_to_mtree_internal (self, &child_dfd_iter, child_mtree, modifier, path, cancellable, error)) - goto out; + return FALSE; } } else if (repo_dir) @@ -2504,7 +2435,7 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, if (!ostree_mutable_tree_replace_file (mtree, name, ostree_repo_file_get_checksum ((OstreeRepoFile*) child), error)) - goto out; + return FALSE; } else { @@ -2524,7 +2455,7 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, { if (!ostree_mutable_tree_replace_file (mtree, name, loose_checksum, error)) - goto out; + return FALSE; } else { @@ -2534,13 +2465,13 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, { file_input = (GInputStream*)g_file_read (child, cancellable, error); if (!file_input) - goto out; + return FALSE; } else { if (!ot_openat_read_stream (dfd_iter->fd, name, FALSE, &file_input, cancellable, error)) - goto out; + return FALSE; } } @@ -2548,30 +2479,28 @@ write_directory_content_to_mtree_internal (OstreeRepo *self, child_relpath, child_info, child, dfd_iter != NULL ? dfd_iter->fd : -1, name, &xattrs, cancellable, error)) - goto out; + return FALSE; if (!ostree_raw_file_to_content_stream (file_input, modified_info, xattrs, &file_object_input, &file_obj_length, cancellable, error)) - goto out; + return FALSE; if (!ostree_repo_write_content (self, NULL, file_object_input, file_obj_length, &child_file_csum, cancellable, error)) - goto out; + return FALSE; g_free (tmp_checksum); tmp_checksum = ostree_checksum_from_bytes (child_file_csum); if (!ostree_mutable_tree_replace_file (mtree, name, tmp_checksum, error)) - goto out; + return FALSE; } } g_ptr_array_remove_index (path, path->len - 1); - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -2583,10 +2512,8 @@ write_directory_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; OstreeRepoCommitFilterResult filter_result; OstreeRepoFile *repo_dir = NULL; - g_autoptr(GFileInfo) child_info = NULL; if (dir) g_debug ("Examining: %s", gs_file_get_path_cached (dir)); @@ -2599,7 +2526,7 @@ write_directory_to_mtree_internal (OstreeRepo *self, if (repo_dir) { if (!ostree_repo_file_ensure_resolved (repo_dir, error)) - goto out; + return FALSE; ostree_mutable_tree_set_metadata_checksum (mtree, ostree_repo_file_tree_get_metadata_checksum (repo_dir)); @@ -2607,21 +2534,20 @@ write_directory_to_mtree_internal (OstreeRepo *self, } else { - g_autoptr(GFileInfo) modified_info = NULL; g_autoptr(GVariant) xattrs = NULL; - g_autofree guchar *child_file_csum = NULL; - g_autofree char *tmp_checksum = NULL; - g_autofree char *relpath = NULL; - child_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); + g_autoptr(GFileInfo) child_info = + g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + cancellable, error); if (!child_info) - goto out; + return FALSE; + g_autofree char *relpath = NULL; if (modifier != NULL) relpath = ptrarray_path_join (path); + g_autoptr(GFileInfo) modified_info = NULL; filter_result = apply_commit_filter (self, modifier, relpath, child_info, &modified_info); if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) @@ -2630,18 +2556,16 @@ write_directory_to_mtree_internal (OstreeRepo *self, dir, -1, NULL, &xattrs, cancellable, error)) - goto out; + return FALSE; + g_autofree guchar *child_file_csum = NULL; if (!_ostree_repo_write_directory_meta (self, modified_info, xattrs, &child_file_csum, cancellable, error)) - goto out; + return FALSE; - g_free (tmp_checksum); - tmp_checksum = ostree_checksum_from_bytes (child_file_csum); + g_autofree char *tmp_checksum = ostree_checksum_from_bytes (child_file_csum); ostree_mutable_tree_set_metadata_checksum (mtree, tmp_checksum); } - - g_clear_object (&child_info); } if (filter_result == OSTREE_REPO_COMMIT_FILTER_ALLOW) @@ -2653,15 +2577,15 @@ write_directory_to_mtree_internal (OstreeRepo *self, cancellable, error); if (!dir_enum) - goto out; + return FALSE; while (TRUE) { GFileInfo *child_info; - + if (!g_file_enumerator_iterate (dir_enum, &child_info, NULL, cancellable, error)) - goto out; + return FALSE; if (child_info == NULL) break; @@ -2669,13 +2593,11 @@ write_directory_to_mtree_internal (OstreeRepo *self, child_info, mtree, modifier, path, cancellable, error)) - goto out; + return FALSE; } } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -2687,7 +2609,6 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GFileInfo) child_info = NULL; g_autoptr(GFileInfo) modified_info = NULL; g_autoptr(GVariant) xattrs = NULL; @@ -2698,17 +2619,14 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, struct stat dir_stbuf; if (fstat (src_dfd_iter->fd, &dir_stbuf) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); child_info = _ostree_header_gfile_info_new (dir_stbuf.st_mode, dir_stbuf.st_uid, dir_stbuf.st_gid); if (modifier != NULL) { relpath = ptrarray_path_join (path); - + filter_result = apply_commit_filter (self, modifier, relpath, child_info, &modified_info); } else @@ -2723,11 +2641,11 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, NULL, src_dfd_iter->fd, NULL, &xattrs, cancellable, error)) - goto out; + return FALSE; if (!_ostree_repo_write_directory_meta (self, modified_info, xattrs, &child_file_csum, cancellable, error)) - goto out; + return FALSE; g_free (tmp_checksum); tmp_checksum = ostree_checksum_from_bytes (child_file_csum); @@ -2736,8 +2654,8 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, if (filter_result != OSTREE_REPO_COMMIT_FILTER_ALLOW) { - ret = TRUE; - goto out; + /* Note - early return */ + return TRUE; } while (TRUE) @@ -2746,24 +2664,20 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, struct stat stbuf; g_autoptr(GFileInfo) child_info = NULL; const char *loose_checksum; - if (!glnx_dirfd_iterator_next_dent (src_dfd_iter, &dent, cancellable, error)) - goto out; + return FALSE; if (dent == NULL) break; if (fstatat (src_dfd_iter->fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == -1) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); 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)) - goto out; + return FALSE; continue; } @@ -2779,28 +2693,24 @@ write_dfd_iter_to_mtree_internal (OstreeRepo *self, { if (!ot_readlinkat_gfile_info (src_dfd_iter->fd, dent->d_name, child_info, cancellable, error)) - goto out; + return FALSE; } else if (S_ISDIR (stbuf.st_mode)) ; else { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Not a regular file or symlink: %s", - dent->d_name); - goto out; + return glnx_throw (error, "Not a regular file or symlink: %s", + dent->d_name); } if (!write_directory_content_to_mtree_internal (self, NULL, NULL, src_dfd_iter, child_info, mtree, modifier, path, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2823,30 +2733,26 @@ ostree_repo_write_directory_to_mtree (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GPtrArray) path = NULL; /* Short cut local files */ if (g_file_is_native (dir)) { if (!ostree_repo_write_dfd_to_mtree (self, AT_FDCWD, gs_file_get_path_cached (dir), mtree, modifier, cancellable, error)) - goto out; + return FALSE; } else { if (modifier && modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES) self->generate_sizes = TRUE; - - path = g_ptr_array_new (); + + g_autoptr(GPtrArray) path = g_ptr_array_new (); if (!write_directory_to_mtree_internal (self, dir, mtree, modifier, path, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2872,25 +2778,19 @@ ostree_repo_write_dfd_to_mtree (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GPtrArray) pathbuilder = NULL; - g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - if (modifier && modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES) self->generate_sizes = TRUE; - pathbuilder = g_ptr_array_new (); - + g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; if (!glnx_dirfd_iterator_init_at (dfd, path, FALSE, &dfd_iter, error)) - goto out; + return FALSE; + g_autoptr(GPtrArray) pathbuilder = g_ptr_array_new (); if (!write_dfd_iter_to_mtree_internal (self, &dfd_iter, mtree, modifier, pathbuilder, cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2912,19 +2812,12 @@ ostree_repo_write_mtree (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GHashTableIter hash_iter; - gpointer key, value; const char *contents_checksum, *metadata_checksum; g_autoptr(GFile) ret_file = NULL; metadata_checksum = ostree_mutable_tree_get_metadata_checksum (mtree); if (!metadata_checksum) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't commit an empty tree"); - goto out; - } + return glnx_throw (error, "Can't commit an empty tree"); contents_checksum = ostree_mutable_tree_get_contents_checksum (mtree); if (contents_checksum) @@ -2944,6 +2837,8 @@ ostree_repo_write_mtree (OstreeRepo *self, dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free); + GHashTableIter hash_iter; + gpointer key, value; g_hash_table_iter_init (&hash_iter, ostree_mutable_tree_get_subdirs (mtree)); while (g_hash_table_iter_next (&hash_iter, &key, &value)) { @@ -2953,7 +2848,7 @@ ostree_repo_write_mtree (OstreeRepo *self, if (!ostree_repo_write_mtree (self, child_dir, &child_file, cancellable, error)) - goto out; + return FALSE; g_hash_table_replace (dir_contents_checksums, g_strdup (name), g_strdup (ostree_repo_file_tree_get_contents_checksum (OSTREE_REPO_FILE (child_file)))); @@ -2968,7 +2863,7 @@ ostree_repo_write_mtree (OstreeRepo *self, if (!ostree_repo_write_metadata (self, OSTREE_OBJECT_TYPE_DIR_TREE, NULL, serialized_tree, &contents_csum, cancellable, error)) - goto out; + return FALSE; ostree_checksum_inplace_from_bytes (contents_csum, contents_checksum_buf); ostree_mutable_tree_set_contents_checksum (mtree, contents_checksum_buf); @@ -2976,11 +2871,9 @@ ostree_repo_write_mtree (OstreeRepo *self, ret_file = G_FILE (_ostree_repo_file_new_root (self, contents_checksum_buf, metadata_checksum)); } - ret = TRUE; if (out_file) *out_file = g_steal_pointer (&ret_file); - out: - return ret; + return TRUE; } /** From 97961ed2cec379c0bbee3823503bb8fd5f67257b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 23 Mar 2017 16:49:58 -0400 Subject: [PATCH 37/56] build: Expose autocleanups unconditionally, start using them I'd like to do this in rpm-ostree at least. Originally I was looking at porting to `G_DECLARE_FINAL_TYPE` but eh, this is easier for now and won't bump our GLib dependency which might matter for our embedded users. For now I just did a few replacements in the `remote` command line. A full port can come as we do other code cleanups. This will actually break the flatpak build right now, but that's easy to fix. And we concluded in e.g. https://bugs.freedesktop.org/show_bug.cgi?id=95065#c5 it's a bug for downstream projects to do that. Closes: #756 Approved by: jlebon --- src/libostree/ostree-autocleanups.h | 6 +----- src/ostree/ot-remote-builtin-add-cookie.c | 2 +- src/ostree/ot-remote-builtin-add.c | 2 +- src/ostree/ot-remote-builtin-delete-cookie.c | 2 +- src/ostree/ot-remote-builtin-delete.c | 2 +- src/ostree/ot-remote-builtin-gpg-import.c | 2 +- src/ostree/ot-remote-builtin-list-cookies.c | 2 +- src/ostree/ot-remote-builtin-list.c | 2 +- src/ostree/ot-remote-builtin-refs.c | 2 +- src/ostree/ot-remote-builtin-show-url.c | 2 +- src/ostree/ot-remote-builtin-summary.c | 2 +- 11 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/libostree/ostree-autocleanups.h b/src/libostree/ostree-autocleanups.h index 7301ef1d..f030b50e 100644 --- a/src/libostree/ostree-autocleanups.h +++ b/src/libostree/ostree-autocleanups.h @@ -26,14 +26,10 @@ G_BEGIN_DECLS -#ifndef OSTREE_WITH_AUTOCLEANUPS -#define OSTREE_WITH_AUTOCLEANUPS 0 -#endif - /* ostree can use g_autoptr backports from libglnx when glib is too * old, but still avoid exposing them to users that also have an old * glib */ -#if defined(OSTREE_COMPILATION) || (OSTREE_WITH_AUTOCLEANUPS && GLIB_CHECK_VERSION(2, 44, 0)) +#if defined(OSTREE_COMPILATION) || GLIB_CHECK_VERSION(2, 44, 0) /* * The following types have no specific clear/free/unref functions, so diff --git a/src/ostree/ot-remote-builtin-add-cookie.c b/src/ostree/ot-remote-builtin-add-cookie.c index e4156172..d5ea3da5 100644 --- a/src/ostree/ot-remote-builtin-add-cookie.c +++ b/src/ostree/ot-remote-builtin-add-cookie.c @@ -37,7 +37,7 @@ gboolean ot_remote_builtin_add_cookie (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; const char *domain; const char *path; diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index 93c989f9..3e3aeda9 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -45,7 +45,7 @@ gboolean ot_remote_builtin_add (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; const char *remote_url; char **iter; diff --git a/src/ostree/ot-remote-builtin-delete-cookie.c b/src/ostree/ot-remote-builtin-delete-cookie.c index 6d1b85ad..cb1177fc 100644 --- a/src/ostree/ot-remote-builtin-delete-cookie.c +++ b/src/ostree/ot-remote-builtin-delete-cookie.c @@ -37,7 +37,7 @@ gboolean ot_remote_builtin_delete_cookie (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; const char *domain; const char *path; diff --git a/src/ostree/ot-remote-builtin-delete.c b/src/ostree/ot-remote-builtin-delete.c index 8a4dd5f3..cac1b7ea 100644 --- a/src/ostree/ot-remote-builtin-delete.c +++ b/src/ostree/ot-remote-builtin-delete.c @@ -36,7 +36,7 @@ gboolean ot_remote_builtin_delete (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; gboolean ret = FALSE; diff --git a/src/ostree/ot-remote-builtin-gpg-import.c b/src/ostree/ot-remote-builtin-gpg-import.c index d1db06d0..4df0dfe7 100644 --- a/src/ostree/ot-remote-builtin-gpg-import.c +++ b/src/ostree/ot-remote-builtin-gpg-import.c @@ -94,7 +94,7 @@ gboolean ot_remote_builtin_gpg_import (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; g_autoptr(GInputStream) source_stream = NULL; const char *remote_name; const char * const *key_ids; diff --git a/src/ostree/ot-remote-builtin-list-cookies.c b/src/ostree/ot-remote-builtin-list-cookies.c index 1c3924af..83d75a57 100644 --- a/src/ostree/ot-remote-builtin-list-cookies.c +++ b/src/ostree/ot-remote-builtin-list-cookies.c @@ -36,7 +36,7 @@ gboolean ot_remote_builtin_list_cookies (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; g_autofree char *jar_path = NULL; g_autofree char *cookie_file = NULL; diff --git a/src/ostree/ot-remote-builtin-list.c b/src/ostree/ot-remote-builtin-list.c index faf8d8ad..0769ece7 100644 --- a/src/ostree/ot-remote-builtin-list.c +++ b/src/ostree/ot-remote-builtin-list.c @@ -34,7 +34,7 @@ gboolean ot_remote_builtin_list (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; g_auto(GStrv) remotes = NULL; guint ii, n_remotes = 0; gboolean ret = FALSE; diff --git a/src/ostree/ot-remote-builtin-refs.c b/src/ostree/ot-remote-builtin-refs.c index 9e742912..f5b3afe3 100644 --- a/src/ostree/ot-remote-builtin-refs.c +++ b/src/ostree/ot-remote-builtin-refs.c @@ -36,7 +36,7 @@ gboolean ot_remote_builtin_refs (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; gboolean ret = FALSE; g_autoptr(GHashTable) refs = NULL; diff --git a/src/ostree/ot-remote-builtin-show-url.c b/src/ostree/ot-remote-builtin-show-url.c index 401dfb0b..c1666558 100644 --- a/src/ostree/ot-remote-builtin-show-url.c +++ b/src/ostree/ot-remote-builtin-show-url.c @@ -33,7 +33,7 @@ gboolean ot_remote_builtin_show_url (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; g_autofree char *remote_url = NULL; gboolean ret = FALSE; diff --git a/src/ostree/ot-remote-builtin-summary.c b/src/ostree/ot-remote-builtin-summary.c index 39321b53..b4d99254 100644 --- a/src/ostree/ot-remote-builtin-summary.c +++ b/src/ostree/ot-remote-builtin-summary.c @@ -40,7 +40,7 @@ gboolean ot_remote_builtin_summary (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; - glnx_unref_object OstreeRepo *repo = NULL; + g_autoptr(OstreeRepo) repo = NULL; const char *remote_name; g_autoptr(GBytes) summary_bytes = NULL; g_autoptr(GBytes) signature_bytes = NULL; From b51ce8cb0ac16074a5a3b5656247d9dd6a8884c3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 15:23:14 -0400 Subject: [PATCH 38/56] lib: Fix OSTREE_CHECK_VERSION() Actually trying to use this in rpm-ostree, it kept returning successfully when I didn't expect it to... The first conditional was always succeeding even when I was asking for a newer minor. Closes: #766 Approved by: jlebon --- src/libostree/ostree-version.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-version.h.in b/src/libostree/ostree-version.h.in index 8a4776d8..7d775cc2 100644 --- a/src/libostree/ostree-version.h.in +++ b/src/libostree/ostree-version.h.in @@ -78,5 +78,5 @@ * of ostree is equal or greater than the required one. */ #define OSTREE_CHECK_VERSION(year,release) \ - (OSTREE_YEAR_VERSION >= (year) || \ + (OSTREE_YEAR_VERSION > (year) || \ (OSTREE_YEAR_VERSION == (year) && OSTREE_RELEASE_VERSION >= (release))) From 8392faaffc44ac7f171279b961efab7418f5b45f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 22:31:03 -0400 Subject: [PATCH 39/56] lib: Delete old GFile path helpers, and migrate single last user I happened to read this file and realized there's a lot of cruft left over from the time when I liked `GFile` and `malloc()`ing like 50 times just to make a pathname string. Delete it. Closes: #767 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 4 +- src/libotutil/ot-gio-utils.c | 85 --------------------------- src/libotutil/ot-gio-utils.h | 6 -- 3 files changed, 2 insertions(+), 93 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index ee25d3f0..0db09973 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2003,11 +2003,11 @@ allocate_deployserial (OstreeSysroot *self, { guint i; int new_deployserial = 0; - g_autoptr(GFile) osdir = NULL; g_autoptr(GPtrArray) tmp_current_deployments = g_ptr_array_new_with_free_func (g_object_unref); - osdir = ot_gfile_get_child_build_path (self->path, "ostree/deploy", osname, NULL); + const char *osdir_name = glnx_strjoina ("ostree/deploy/", osname); + g_autoptr(GFile) osdir = g_file_resolve_relative_path (self->path, osdir_name); if (!_ostree_sysroot_list_deployment_dirs_for_os (osdir, tmp_current_deployments, cancellable, error)) diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index da32653e..51c29f39 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -51,91 +51,6 @@ ot_gfile_type_for_mode (guint32 mode) } -GFile * -ot_gfile_from_build_path (const char *first, ...) -{ - va_list args; - const char *arg; - g_autofree char *path = NULL; - g_autoptr(GPtrArray) components = NULL; - - va_start (args, first); - - components = g_ptr_array_new (); - - arg = first; - while (arg != NULL) - { - g_ptr_array_add (components, (char*)arg); - arg = va_arg (args, const char *); - } - - va_end (args); - - g_ptr_array_add (components, NULL); - - path = g_build_filenamev ((char**)components->pdata); - - return g_file_new_for_path (path); -} - -GFile * -ot_gfile_get_child_strconcat (GFile *parent, - const char *first, - ...) -{ - va_list args; - GFile *ret; - GString *buf; - const char *arg; - - g_return_val_if_fail (first != NULL, NULL); - - va_start (args, first); - - buf = g_string_new (first); - - while ((arg = va_arg (args, const char *)) != NULL) - g_string_append (buf, arg); - - va_end (args); - - ret = g_file_get_child (parent, buf->str); - - g_string_free (buf, TRUE); - - return ret; -} - -GFile * -ot_gfile_get_child_build_path (GFile *parent, - const char *first, ...) -{ - va_list args; - const char *arg; - g_autofree char *path = NULL; - g_autoptr(GPtrArray) components = NULL; - - va_start (args, first); - - components = g_ptr_array_new (); - - arg = first; - while (arg != NULL) - { - g_ptr_array_add (components, (char*)arg); - arg = va_arg (args, const char *); - } - - va_end (args); - - g_ptr_array_add (components, NULL); - - path = g_build_filenamev ((char**)components->pdata); - - return g_file_resolve_relative_path (parent, path); -} - GFile * ot_gfile_resolve_path_printf (GFile *path, const char *format, diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h index 34040238..fa7c6997 100644 --- a/src/libotutil/ot-gio-utils.h +++ b/src/libotutil/ot-gio-utils.h @@ -35,12 +35,6 @@ G_BEGIN_DECLS GFileType ot_gfile_type_for_mode (guint32 mode); -GFile *ot_gfile_from_build_path (const char *first, ...) G_GNUC_NULL_TERMINATED; - -GFile *ot_gfile_get_child_strconcat (GFile *parent, const char *first, ...) G_GNUC_NULL_TERMINATED; - -GFile *ot_gfile_get_child_build_path (GFile *parent, const char *first, ...) G_GNUC_NULL_TERMINATED; - GFile * ot_gfile_resolve_path_printf (GFile *path, const char *format, ...) G_GNUC_PRINTF(2, 3); From 8fea1937df3b7b00273f2675eb664c71891ca057 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 22:35:10 -0400 Subject: [PATCH 40/56] lib: Delete old unused GFile helpers This is all unused since the fd-relative/no-GFile porting. Delete delete delete! Closes: #767 Approved by: jlebon --- src/libotutil/ot-gio-utils.c | 124 ----------------------------------- src/libotutil/ot-gio-utils.h | 31 --------- 2 files changed, 155 deletions(-) diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index 51c29f39..5d12d430 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -66,130 +66,6 @@ ot_gfile_resolve_path_printf (GFile *path, return g_file_resolve_relative_path (path, relpath); } - -gboolean -ot_gfile_get_symlink_target_from_info (GFile *path, - GFileInfo *file_info, - GFile **out_target, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - const char *target; - g_autoptr(GFile) path_parent = NULL; - g_autoptr(GFile) ret_target = NULL; - - if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_SYMBOLIC_LINK) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Not a symbolic link"); - goto out; - } - - path_parent = g_file_get_parent (path); - target = g_file_info_get_symlink_target (file_info); - g_assert (target); - ret_target = g_file_resolve_relative_path (path_parent, target); - - ret = TRUE; - out: - ot_transfer_out_value (out_target, &ret_target); - return ret; -} - -gboolean -ot_gfile_query_info_allow_noent (GFile *path, - const char *queryopts, - GFileQueryInfoFlags flags, - GFileInfo **out_info, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - g_autoptr(GFileInfo) ret_file_info = NULL; - GError *temp_error = NULL; - - ret_file_info = g_file_query_info (path, queryopts, flags, - cancellable, &temp_error); - if (!ret_file_info) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - } - else - { - g_propagate_error (error, temp_error); - goto out; - } - } - - ret = TRUE; - ot_transfer_out_value (out_info, &ret_file_info); - out: - return ret; -} - -gboolean -ot_gfile_query_symlink_target_allow_noent (GFile *path, - GFile **out_target, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - g_autoptr(GFileInfo) file_info = NULL; - g_autoptr(GFile) ret_target = NULL; - - if (!ot_gfile_query_info_allow_noent (path, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - &file_info, - cancellable, error)) - goto out; - - if (file_info != NULL) - { - if (!ot_gfile_get_symlink_target_from_info (path, file_info, &ret_target, - cancellable, error)) - goto out; - } - - ret = TRUE; - ot_transfer_out_value (out_target, &ret_target); - out: - return ret; -} - -gboolean -ot_gfile_load_contents_utf8_allow_noent (GFile *path, - char **out_contents, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - GError *temp_error = NULL; - g_autofree char *ret_contents = NULL; - - ret_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (path), NULL, - cancellable, &temp_error); - if (!ret_contents) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - } - else - { - g_propagate_error (error, temp_error); - goto out; - } - } - - ret = TRUE; - ot_transfer_out_value (out_contents, &ret_contents); - out: - return ret; -} - /** * ot_gfile_replace_contents_fsync: * diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h index fa7c6997..0fd3ddf0 100644 --- a/src/libotutil/ot-gio-utils.h +++ b/src/libotutil/ot-gio-utils.h @@ -39,37 +39,6 @@ GFile * ot_gfile_resolve_path_printf (GFile *path, const char *format, ...) G_GNUC_PRINTF(2, 3); - -gboolean ot_gfile_get_symlink_target_from_info (GFile *path, - GFileInfo *file_info, - GFile **out_target, - GCancellable *cancellable, - GError **error); - -gboolean ot_gfile_query_info_allow_noent (GFile *path, - const char *queryopts, - GFileQueryInfoFlags flags, - GFileInfo **out_info, - GCancellable *cancellable, - GError **error); - -gboolean ot_gfile_query_symlink_target_allow_noent (GFile *path, - GFile **out_target, - GCancellable *cancellable, - GError **error); - -gboolean ot_gfile_load_contents_utf8_allow_noent (GFile *path, - char **out_contents, - GCancellable *cancellable, - GError **error); - -gboolean ot_file_replace_contents_at (int dfd, - const char *path, - GBytes *contents, - gboolean datasync, - GCancellable *cancellable, - GError **error); - gboolean ot_gfile_replace_contents_fsync (GFile *path, GBytes *contents, GCancellable *cancellable, From 2571e21b4178a13ad298c637737520ae86b6b988 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 22:37:38 -0400 Subject: [PATCH 41/56] libutil: Delete unused threadpool wrapper This is dead code since 9cc98041953090160dde48afa69b97c936541cdb where pull-local became just a wrapper for pull, which has its own threading. Closes: #767 Approved by: jlebon --- Makefile-otutil.am | 2 -- src/libotutil/ot-spawn-utils.c | 49 ---------------------------------- src/libotutil/ot-spawn-utils.h | 33 ----------------------- src/libotutil/otutil.h | 1 - 4 files changed, 85 deletions(-) delete mode 100644 src/libotutil/ot-spawn-utils.c delete mode 100644 src/libotutil/ot-spawn-utils.h diff --git a/Makefile-otutil.am b/Makefile-otutil.am index 5b6d4e48..db632705 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -32,8 +32,6 @@ libotutil_la_SOURCES = \ src/libotutil/ot-opt-utils.h \ src/libotutil/ot-unix-utils.c \ src/libotutil/ot-unix-utils.h \ - src/libotutil/ot-spawn-utils.c \ - src/libotutil/ot-spawn-utils.h \ src/libotutil/ot-variant-utils.c \ src/libotutil/ot-variant-utils.h \ src/libotutil/ot-gio-utils.c \ diff --git a/src/libotutil/ot-spawn-utils.c b/src/libotutil/ot-spawn-utils.c deleted file mode 100644 index f798264b..00000000 --- a/src/libotutil/ot-spawn-utils.c +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- 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 - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#include "config.h" - -#include "otutil.h" - -#include - -/** - * ot_thread_pool_new_nproc: - * - * Like g_thread_pool_new (), but choose number of threads appropriate - * for CPU bound workers automatically. Also aborts on error. - */ -GThreadPool * -ot_thread_pool_new_nproc (GFunc func, - gpointer user_data) -{ - long nproc_onln; - GThreadPool *ret; - GError *local_error = NULL; - - nproc_onln = sysconf (_SC_NPROCESSORS_ONLN); - if (G_UNLIKELY (nproc_onln == -1 && errno == EINVAL)) - nproc_onln = 2; - ret = g_thread_pool_new (func, user_data, (int)nproc_onln, FALSE, &local_error); - g_assert_no_error (local_error); - return ret; -} diff --git a/src/libotutil/ot-spawn-utils.h b/src/libotutil/ot-spawn-utils.h deleted file mode 100644 index 76ea24e3..00000000 --- a/src/libotutil/ot-spawn-utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- 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 - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Colin Walters - */ - -#pragma once - -#include - -G_BEGIN_DECLS - -GThreadPool * ot_thread_pool_new_nproc (GFunc func, - gpointer user_data); - - -G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index f6158de8..dfe951d0 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include From 0ce7ab382769d63f12370e8325c40e1f997006fd Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 22:39:58 -0400 Subject: [PATCH 42/56] libutil: Delete unused GVariant I/O functions These are dead due to fd-relative porting probably. Closes: #767 Approved by: jlebon --- src/libotutil/ot-variant-utils.c | 67 -------------------------------- src/libotutil/ot-variant-utils.h | 12 ------ 2 files changed, 79 deletions(-) diff --git a/src/libotutil/ot-variant-utils.c b/src/libotutil/ot-variant-utils.c index 1c4c5efa..c8c049fb 100644 --- a/src/libotutil/ot-variant-utils.c +++ b/src/libotutil/ot-variant-utils.c @@ -80,36 +80,6 @@ ot_util_variant_asv_to_hash_table (GVariant *variant) return ret; } -gboolean -ot_util_variant_save (GFile *dest, - GVariant *variant, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - g_autoptr(GOutputStream) out = NULL; - gsize bytes_written; - - out = (GOutputStream*)g_file_replace (dest, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, - cancellable, error); - if (!out) - goto out; - - if (!g_output_stream_write_all (out, - g_variant_get_data (variant), - g_variant_get_size (variant), - &bytes_written, - cancellable, - error)) - goto out; - if (!g_output_stream_close (out, cancellable, error)) - goto out; - - ret = TRUE; - out: - return ret; -} - GVariant * ot_util_variant_take_ref (GVariant *variant) { @@ -198,43 +168,6 @@ ot_util_variant_map_fd (int fd, return ret; } -/** - * Read all input from @src, allocating a new #GVariant from it into - * output variable @out_variant. @src will be closed as a result. - * - * Note the returned @out_variant is not floating. - */ -gboolean -ot_util_variant_from_stream (GInputStream *src, - const GVariantType *type, - gboolean trusted, - GVariant **out_variant, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - g_autoptr(GMemoryOutputStream) data_stream = NULL; - g_autoptr(GVariant) ret_variant = NULL; - - data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free); - - if (g_output_stream_splice ((GOutputStream*)data_stream, src, - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - cancellable, error) < 0) - goto out; - - ret_variant = g_variant_new_from_data (type, g_memory_output_stream_get_data (data_stream), - g_memory_output_stream_get_data_size (data_stream), - trusted, (GDestroyNotify) g_object_unref, data_stream); - data_stream = NULL; /* Transfer ownership */ - g_variant_ref_sink (ret_variant); - - ret = TRUE; - ot_transfer_out_value (out_variant, &ret_variant); - out: - return ret; -} - GInputStream * ot_variant_read (GVariant *variant) { diff --git a/src/libotutil/ot-variant-utils.h b/src/libotutil/ot-variant-utils.h index 8a33cf60..4f2131ee 100644 --- a/src/libotutil/ot-variant-utils.h +++ b/src/libotutil/ot-variant-utils.h @@ -37,11 +37,6 @@ GHashTable *ot_util_variant_asv_to_hash_table (GVariant *variant); GVariant * ot_util_variant_take_ref (GVariant *variant); -gboolean ot_util_variant_save (GFile *dest, - GVariant *variant, - GCancellable *cancellable, - GError **error); - typedef enum { OT_VARIANT_MAP_TRUSTED = (1 << 0), OT_VARIANT_MAP_ALLOW_NOENT = (1 << 1) @@ -61,13 +56,6 @@ gboolean ot_util_variant_map_fd (int fd, GVariant **out_variant, GError **error); -gboolean ot_util_variant_from_stream (GInputStream *src, - const GVariantType *type, - gboolean trusted, - GVariant **out_variant, - GCancellable *cancellable, - GError **error); - GInputStream *ot_variant_read (GVariant *variant); GVariantBuilder *ot_util_variant_builder_from_variant (GVariant *variant, From 5f45ab0bb19d0482506797dc3daf739cd74f11a7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 28 Mar 2017 22:42:26 -0400 Subject: [PATCH 43/56] libutil: Delete some unused checksum helper API This code was last used in 9618232f4da325692dcf98fd6ff5b8abd9fce66c which is sooo old and outdated. Delete. Closes: #767 Approved by: jlebon --- src/libotutil/ot-checksum-utils.c | 43 ------------------------------- src/libotutil/ot-checksum-utils.h | 10 ------- 2 files changed, 53 deletions(-) diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c index 4b5c824a..39417044 100644 --- a/src/libotutil/ot-checksum-utils.c +++ b/src/libotutil/ot-checksum-utils.c @@ -180,46 +180,3 @@ ot_checksum_file_at (int dfd, return ret; } - -static void -checksum_stream_thread (GSimpleAsyncResult *result, - GObject *object, - GCancellable *cancellable) -{ - GError *error = NULL; - guchar *csum; - - if (!ot_gio_checksum_stream ((GInputStream*)object, &csum, - cancellable, &error)) - g_simple_async_result_take_error (result, error); - else - g_simple_async_result_set_op_res_gpointer (result, csum, g_free); -} - -void -ot_gio_checksum_stream_async (GInputStream *in, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *result; - - result = g_simple_async_result_new ((GObject*) in, - callback, user_data, - ot_gio_checksum_stream_async); - - g_simple_async_result_run_in_thread (result, checksum_stream_thread, io_priority, cancellable); - g_object_unref (result); -} - -guchar * -ot_gio_checksum_stream_finish (GInputStream *in, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ot_gio_checksum_stream_async); - return g_memdup (g_simple_async_result_get_op_res_gpointer (simple), 32); -} diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h index b580fc1c..fdf7b09b 100644 --- a/src/libotutil/ot-checksum-utils.h +++ b/src/libotutil/ot-checksum-utils.h @@ -61,14 +61,4 @@ char * ot_checksum_file_at (int dfd, GCancellable *cancellable, GError **error); -void ot_gio_checksum_stream_async (GInputStream *in, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -guchar * ot_gio_checksum_stream_finish (GInputStream *in, - GAsyncResult *result, - GError **error); - G_END_DECLS From ee626c2654b877f5ae6771933330c381efa7e802 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 29 Mar 2017 10:24:35 -0400 Subject: [PATCH 44/56] libutil: Delete some unused error handling APIs The first one is better as `err`, the second might as well just call `err` too. Closes: #767 Approved by: jlebon --- src/libotutil/ot-unix-utils.c | 14 -------------- src/libotutil/ot-unix-utils.h | 4 ---- 2 files changed, 18 deletions(-) diff --git a/src/libotutil/ot-unix-utils.c b/src/libotutil/ot-unix-utils.c index 4f659a27..46dd346e 100644 --- a/src/libotutil/ot-unix-utils.c +++ b/src/libotutil/ot-unix-utils.c @@ -121,17 +121,3 @@ ot_util_path_split_validate (const char *path, out: return ret; } - -void -ot_util_fatal_literal (const char *msg) -{ - g_printerr ("%s\n", msg); - exit (EXIT_FAILURE); -} - -void -ot_util_fatal_gerror (GError *error) -{ - g_assert (error != NULL); - ot_util_fatal_literal (error->message); -} diff --git a/src/libotutil/ot-unix-utils.h b/src/libotutil/ot-unix-utils.h index 0547a54e..817e6fd3 100644 --- a/src/libotutil/ot-unix-utils.h +++ b/src/libotutil/ot-unix-utils.h @@ -36,10 +36,6 @@ G_BEGIN_DECLS -void ot_util_fatal_literal (const char *msg) G_GNUC_NORETURN; - -void ot_util_fatal_gerror (GError *error) G_GNUC_NORETURN; - gboolean ot_util_filename_validate (const char *name, GError **error); gboolean ot_util_path_split_validate (const char *path, GPtrArray **out_components, GError **error); From 305db981d47e4aa417dd90164b1995e008d25757 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 23 Mar 2017 13:06:07 -0400 Subject: [PATCH 45/56] Add Coccinelle usage: one for blacklisting, one for patch collection This is inspired by the [Coccinelle](http://coccinelle.lip6.fr/) usage in systemd. I also took it a bit further and added infrastructure to have spatches which should never apply. This acts as a blacklist. The reason to do the latter is that coccinelle is *way* more powerful than the regular expresssions we have in `make syntax-check`. I started with blacklisting `g_error_free()` directly. The reason that's bad is it leaves a dangling pointer. Closes: #754 Approved by: jlebon --- .redhat-ci.Dockerfile | 1 + .redhat-ci.yml | 1 + Makefile-tests.am | 2 ++ coccinelle/README.md | 6 +++++ coccinelle/newstyle.cocci | 22 +++++++++++++++++ src/libostree/ostree-repo-pull.c | 41 +++++++++++++++++--------------- src/ostree/main.c | 3 +-- src/ostree/ot-main.c | 5 ++-- tests/coccinelle.sh | 29 ++++++++++++++++++++++ tests/coccinelle/README.md | 2 ++ tests/coccinelle/raw-free.cocci | 5 ++++ tests/test-rollsum-cli.c | 5 ++-- 12 files changed, 96 insertions(+), 26 deletions(-) create mode 100644 coccinelle/README.md create mode 100644 coccinelle/newstyle.cocci create mode 100755 tests/coccinelle.sh create mode 100644 tests/coccinelle/README.md create mode 100644 tests/coccinelle/raw-free.cocci diff --git a/.redhat-ci.Dockerfile b/.redhat-ci.Dockerfile index d5a2e255..86d26dfa 100644 --- a/.redhat-ci.Dockerfile +++ b/.redhat-ci.Dockerfile @@ -8,6 +8,7 @@ RUN dnf install -y \ fuse \ gjs \ parallel \ + coccinelle \ clang \ libubsan \ libasan \ diff --git a/.redhat-ci.yml b/.redhat-ci.yml index cfff0fa0..2fce02b8 100644 --- a/.redhat-ci.yml +++ b/.redhat-ci.yml @@ -11,6 +11,7 @@ container: packages: - libasan + - coccinelle env: CFLAGS: '-fsanitize=undefined -fsanitize-undefined-trap-on-error -fsanitize=address -O2 -Wp,-D_FORTIFY_SOURCE=2' diff --git a/Makefile-tests.am b/Makefile-tests.am index bba8f008..8389331d 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -28,6 +28,7 @@ EXTRA_DIST += \ # include the builddir in $PATH so we find our just-built ostree # binary. TESTS_ENVIRONMENT += OT_TESTS_DEBUG=1 \ + OSTREE_UNINSTALLED_SRCDIR=$(abs_top_srcdir) \ OSTREE_UNINSTALLED=$(abs_top_builddir) \ G_DEBUG=fatal-warnings \ GI_TYPELIB_PATH=$$(cd $(top_builddir) && pwd)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH} \ @@ -99,6 +100,7 @@ dist_test_scripts = \ tests/test-switchroot.sh \ tests/test-pull-contenturl.sh \ tests/test-pull-mirrorlist.sh \ + tests/coccinelle.sh \ $(NULL) if BUILDOPT_FUSE diff --git a/coccinelle/README.md b/coccinelle/README.md new file mode 100644 index 00000000..60909b1f --- /dev/null +++ b/coccinelle/README.md @@ -0,0 +1,6 @@ +This is a directory of semantic patches +to apply with coccinelle, like the collection in systemd: +https://github.com/systemd/systemd/tree/29f32655842a0712e8db482bcefc4da8908460c8/coccinelle + +See also the tests/coccinelle directory which +has spatches which detect errors. diff --git a/coccinelle/newstyle.cocci b/coccinelle/newstyle.cocci new file mode 100644 index 00000000..7df248c3 --- /dev/null +++ b/coccinelle/newstyle.cocci @@ -0,0 +1,22 @@ +@@ +expression p; +@@ +- glnx_set_error_from_errno (p); +- goto out; ++ return glnx_throw_errno (p); +@@ +expression p; +@@ +- if (!p) +- goto out; ++ if (!p) ++ return FALSE; +@@ +expression p; +@@ +- gboolean ret = FALSE; +... +- ret = TRUE; +- out: +- return ret; ++ return TRUE; diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index b7be8a95..a7a3a5b0 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -279,18 +279,21 @@ pull_termination_condition (OtPullData *pull_data) static void check_outstanding_requests_handle_error (OtPullData *pull_data, - GError *error) + GError **errorp) { + g_assert (errorp); + + GError *error = *errorp; if (error) { if (!pull_data->caught_error) { pull_data->caught_error = TRUE; - g_propagate_error (pull_data->async_error, error); + g_propagate_error (pull_data->async_error, g_steal_pointer (errorp)); } else { - g_error_free (error); + g_clear_error (errorp); } } else @@ -382,7 +385,7 @@ idle_worker (gpointer user_data) { OtPullData *pull_data = user_data; ScanObjectQueueData *scan_data; - GError *error = NULL; + g_autoptr(GError) error = NULL; scan_data = g_queue_pop_head (&pull_data->scan_object_queue); if (!scan_data) @@ -398,7 +401,7 @@ idle_worker (gpointer user_data) scan_data->recursion_depth, pull_data->cancellable, &error); - check_outstanding_requests_handle_error (pull_data, error); + check_outstanding_requests_handle_error (pull_data, &error); g_free (scan_data->path); g_free (scan_data); @@ -760,7 +763,7 @@ content_fetch_on_write_complete (GObject *object, { FetchObjectData *fetch_data = user_data; OtPullData *pull_data = fetch_data->pull_data; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; OstreeObjectType objtype; const char *expected_checksum; @@ -794,7 +797,7 @@ content_fetch_on_write_complete (GObject *object, pull_data->n_fetched_deltapart_fallbacks++; out: pull_data->n_outstanding_content_write_requests--; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); fetch_object_data_free (fetch_data); } @@ -806,7 +809,7 @@ content_fetch_on_complete (GObject *object, OstreeFetcher *fetcher = (OstreeFetcher *)object; FetchObjectData *fetch_data = user_data; OtPullData *pull_data = fetch_data->pull_data; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; GCancellable *cancellable = NULL; guint64 length; @@ -881,7 +884,7 @@ content_fetch_on_complete (GObject *object, out: pull_data->n_outstanding_content_fetches--; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); if (free_fetch_data) fetch_object_data_free (fetch_data); } @@ -893,7 +896,7 @@ on_metadata_written (GObject *object, { FetchObjectData *fetch_data = user_data; OtPullData *pull_data = fetch_data->pull_data; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; const char *expected_checksum; OstreeObjectType objtype; @@ -927,7 +930,7 @@ on_metadata_written (GObject *object, pull_data->n_outstanding_metadata_write_requests--; fetch_object_data_free (fetch_data); - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); } static void @@ -943,7 +946,7 @@ meta_fetch_on_complete (GObject *object, const char *checksum; g_autofree char *checksum_obj = NULL; OstreeObjectType objtype; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; glnx_fd_close int fd = -1; gboolean free_fetch_data = TRUE; @@ -1038,7 +1041,7 @@ meta_fetch_on_complete (GObject *object, g_assert (pull_data->n_outstanding_metadata_fetches > 0); pull_data->n_outstanding_metadata_fetches--; pull_data->n_fetched_metadata++; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); if (free_fetch_data) fetch_object_data_free (fetch_data); } @@ -1061,7 +1064,7 @@ on_static_delta_written (GObject *object, { FetchStaticDeltaData *fetch_data = user_data; OtPullData *pull_data = fetch_data->pull_data; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; g_debug ("execute static delta part %s complete", fetch_data->expected_checksum); @@ -1072,7 +1075,7 @@ on_static_delta_written (GObject *object, out: g_assert (pull_data->n_outstanding_deltapart_write_requests > 0); pull_data->n_outstanding_deltapart_write_requests--; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); /* Always free state */ fetch_static_delta_data_free (fetch_data); } @@ -1088,7 +1091,7 @@ static_deltapart_fetch_on_complete (GObject *object, g_autofree char *temp_path = NULL; g_autoptr(GInputStream) in = NULL; g_autoptr(GVariant) part = NULL; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; glnx_fd_close int fd = -1; gboolean free_fetch_data = TRUE; @@ -1132,7 +1135,7 @@ static_deltapart_fetch_on_complete (GObject *object, g_assert (pull_data->n_outstanding_deltapart_fetches > 0); pull_data->n_outstanding_deltapart_fetches--; pull_data->n_fetched_deltaparts++; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); if (free_fetch_data) fetch_static_delta_data_free (fetch_data); } @@ -1968,7 +1971,7 @@ on_superblock_fetched (GObject *src, { FetchDeltaSuperData *fdata = data; OtPullData *pull_data = fdata->pull_data; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; g_autoptr(GBytes) delta_superblock_data = NULL; const char *from_revision = fdata->from_revision; @@ -2045,7 +2048,7 @@ on_superblock_fetched (GObject *src, g_assert (pull_data->n_outstanding_metadata_fetches > 0); pull_data->n_outstanding_metadata_fetches--; pull_data->n_fetched_metadata++; - check_outstanding_requests_handle_error (pull_data, local_error); + check_outstanding_requests_handle_error (pull_data, &local_error); } static gboolean diff --git a/src/ostree/main.c b/src/ostree/main.c index c6dee4ee..5a2ed661 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -68,7 +68,7 @@ int main (int argc, char **argv) { - GError *error = NULL; + g_autoptr(GError) error = NULL; int ret; setlocale (LC_ALL, ""); @@ -88,7 +88,6 @@ main (int argc, suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */ } g_printerr ("%serror: %s%s\n", prefix, suffix, error->message); - g_error_free (error); } return ret; diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index 3484b18e..7eb65602 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -259,7 +259,7 @@ ostree_option_context_parse (GOptionContext *context, if (opt_repo == NULL && !(flags & OSTREE_BUILTIN_FLAG_NO_REPO)) { - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; repo = ostree_repo_new_default (); if (!ostree_repo_open (repo, cancellable, &local_error)) @@ -270,14 +270,13 @@ ostree_option_context_parse (GOptionContext *context, g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Command requires a --repo argument"); - g_error_free (local_error); help = g_option_context_get_help (context, FALSE, NULL); g_printerr ("%s", help); } else { - g_propagate_error (error, local_error); + g_propagate_error (error, g_steal_pointer (&local_error)); } goto out; } diff --git a/tests/coccinelle.sh b/tests/coccinelle.sh new file mode 100755 index 00000000..eb22662d --- /dev/null +++ b/tests/coccinelle.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Run the .cocci files in the tests directory; these act +# as a blacklist. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +if ! spatch --version 2>/dev/null; then + skip "no spatch; get it from http://coccinelle.lip6.fr/" +fi + +if test -z "${OSTREE_UNINSTALLED_SRCDIR:-}"; then + skip "running installed?" +fi + +coccitests=$(ls $(dirname $0)/coccinelle/*.cocci) +echo "1.."$(echo ${coccitests} | wc -l) + +for cocci in $(dirname $0)/coccinelle/*.cocci; do + echo "Running: ${cocci}" + spatch --very-quiet --dir ${OSTREE_UNINSTALLED_SRCDIR} ${cocci} > cocci.out + if test -s cocci.out; then + sed -e 's/^/# /' < cocci.out >&2 + fatal "Failed semantic patch: ${cocci}" + fi + echo ok ${cocci} +done diff --git a/tests/coccinelle/README.md b/tests/coccinelle/README.md new file mode 100644 index 00000000..b81dada3 --- /dev/null +++ b/tests/coccinelle/README.md @@ -0,0 +1,2 @@ +Add patches here which should never match in the code; i.e. the suggested +replacement may be junk. diff --git a/tests/coccinelle/raw-free.cocci b/tests/coccinelle/raw-free.cocci new file mode 100644 index 00000000..9b63b7a5 --- /dev/null +++ b/tests/coccinelle/raw-free.cocci @@ -0,0 +1,5 @@ +@@ +expression p; +@@ +- g_error_free (p); ++ g_clear_error (&p); diff --git a/tests/test-rollsum-cli.c b/tests/test-rollsum-cli.c index a00e4b73..256c79fe 100644 --- a/tests/test-rollsum-cli.c +++ b/tests/test-rollsum-cli.c @@ -22,10 +22,12 @@ #include "ostree-rollsum.h" +#include "libglnx.h" + int main (int argc, char **argv) { - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; GError **error = &local_error; GBytes *from_bytes = NULL; GBytes *to_bytes = NULL; @@ -64,7 +66,6 @@ main (int argc, char **argv) if (local_error) { g_printerr ("%s\n", local_error->message); - g_error_free (local_error); return 1; } return 0; From 8d4dec1b531f8cb6080887362a897f78c13fd098 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Mar 2017 13:38:08 -0400 Subject: [PATCH 46/56] sepolicy: Fix regressions from introduction of sepolicy_new_at() Being bitten by lack of PR testing here. There are two bugs: - First and foremost, I forgot that GObject will call the property setters with the defaults. This meant we were getting both path="/var/tmp/blah" and fd=-1, and we were accepting -1 as a fd, which then got converted into AT_FDCWD which was wrong. - Since these properties are construct only and mutually exclusive, don't try to handle one resetting the other. Assert that exactly one of them is set. Closes: #769 Approved by: jlebon --- src/libostree/ostree-sepolicy.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index ea4e46b1..2013f523 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -112,15 +112,18 @@ ostree_sepolicy_set_property(GObject *object, { /* Canonicalize */ self->path = g_file_new_for_path (gs_file_get_path_cached (path)); + g_assert_cmpint (self->rootfs_dfd, ==, -1); } - self->rootfs_dfd = -1; } break; case PROP_ROOTFS_DFD: { - self->rootfs_dfd = g_value_get_int (value); - g_clear_object (&self->path); - self->path = ot_fdrel_to_gfile (self->rootfs_dfd, "."); + int fd = g_value_get_int (value); + if (fd != -1) + { + g_assert (self->path == NULL); + self->rootfs_dfd = fd; + } } break; default: @@ -282,6 +285,7 @@ initable_init (GInitable *initable, #ifdef HAVE_SELINUX gboolean ret = FALSE; OstreeSePolicy *self = OSTREE_SEPOLICY (initable); + g_autoptr(GFile) path = NULL; g_autoptr(GFile) etc_selinux_dir = NULL; g_autoptr(GFile) policy_config_path = NULL; g_autoptr(GFile) policy_root = NULL; @@ -293,19 +297,27 @@ initable_init (GInitable *initable, const char *selinuxtype_prefix = "SELINUXTYPE="; /* TODO - use this below */ - if (self->rootfs_dfd == -1) + if (self->rootfs_dfd != -1) + path = ot_fdrel_to_gfile (self->rootfs_dfd, "."); + else if (self->path) { + path = g_object_ref (self->path); +#if 0 + /* TODO - use this below */ if (!glnx_opendirat (AT_FDCWD, gs_file_get_path_cached (self->path), TRUE, &self->rootfs_dfd_owned, error)) goto out; self->rootfs_dfd = self->rootfs_dfd_owned; +#endif } + else + g_assert_not_reached (); - etc_selinux_dir = g_file_resolve_relative_path (self->path, "etc/selinux"); + etc_selinux_dir = g_file_resolve_relative_path (path, "etc/selinux"); if (!g_file_query_exists (etc_selinux_dir, NULL)) { g_object_unref (etc_selinux_dir); - etc_selinux_dir = g_file_resolve_relative_path (self->path, "usr/etc/selinux"); + etc_selinux_dir = g_file_resolve_relative_path (path, "usr/etc/selinux"); } policy_config_path = g_file_get_child (etc_selinux_dir, "config"); From 9016e9e8be4d33b31718c407a5302263ccb5eb70 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 29 Mar 2017 16:51:39 -0400 Subject: [PATCH 47/56] Add flag to make SELinux label failure fatal, add hack for /proc I was working on `rpm-ostree livefs` which does some ostree-based filesystem diffs, and noticed that we were ending up with `/proc` not being labeled in our base trees. Reading the selinux-policy source, indeed we have: ``` /proc -d <> /proc/.* <> ``` This dates pretty far back. We really don't want unlabeled content in ostree. In this case it's mostly OK since the kernel will assign a label, but again *everything* should be labeled via OSTree so that it's all consistent, which will fix `ostree diff`. Notably, `/proc` is the *only* file path that isn't covered when composing a Fedora Atomic Host. So I added a hack here to hardcode it (although I'm a bit uncertain about whether it should really be `proc_t` on disk before systemd mounts or not). Out of conservatism, I made this a flag, so if we hit issues down the line, we could easily change rpm-ostree to stumble on as it did before. Closes: #768 Approved by: jlebon --- src/libostree/ostree-repo-commit.c | 6 +++- src/libostree/ostree-repo.h | 2 ++ src/libostree/ostree-sepolicy.c | 45 +++++++++++++++--------------- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 56b4e8f8..45577373 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2309,7 +2309,11 @@ get_modified_xattrs (OstreeRepo *self, &label, cancellable, error)) return FALSE; - if (label) + if (!label && (modifier->flags & OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED) > 0) + { + return glnx_throw (error, "Failed to look up SELinux label for '%s'", relpath); + } + else if (label) { g_autoptr(GVariantBuilder) builder = NULL; diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index b88b980f..482ede7a 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -537,12 +537,14 @@ typedef OstreeRepoCommitFilterResult (*OstreeRepoCommitFilter) (OstreeRepo *r * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS: Do not process extended attributes * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES: Generate size information. * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS: Canonicalize permissions for bare-user-only mode. + * @OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED: Emit an error if configured SELinux policy does not provide a label */ typedef enum { OSTREE_REPO_COMMIT_MODIFIER_FLAGS_NONE = 0, OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS = (1 << 0), OSTREE_REPO_COMMIT_MODIFIER_FLAGS_GENERATE_SIZES = (1 << 1), OSTREE_REPO_COMMIT_MODIFIER_FLAGS_CANONICAL_PERMISSIONS = (1 << 2), + OSTREE_REPO_COMMIT_MODIFIER_FLAGS_ERROR_ON_UNLABELED = (1 << 3), } OstreeRepoCommitModifierFlags; /** diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index 2013f523..6063022c 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -526,35 +526,34 @@ ostree_sepolicy_get_label (OstreeSePolicy *self, GError **error) { #ifdef HAVE_SELINUX - gboolean ret = FALSE; - int res; - char *con = NULL; + /* Early return if no policy */ + if (!self->selinux_hnd) + return TRUE; - if (self->selinux_hnd) + /* http://marc.info/?l=selinux&m=149082134430052&w=2 + * https://github.com/ostreedev/ostree/pull/768 + */ + if (strcmp (relpath, "/proc") == 0) + relpath = "/mnt"; + + char *con = NULL; + int res = selabel_lookup_raw (self->selinux_hnd, &con, relpath, unix_mode); + if (res != 0) { - res = selabel_lookup_raw (self->selinux_hnd, &con, relpath, unix_mode); - if (res != 0) - { - if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - goto out; - } - } + if (errno == ENOENT) + *out_label = NULL; else - { - /* Ensure we consistently allocate with g_malloc */ - *out_label = g_strdup (con); - freecon (con); - } + return glnx_throw_errno (error); + } + else + { + /* Ensure we consistently allocate with g_malloc */ + *out_label = g_strdup (con); + freecon (con); } - ret = TRUE; - out: - return ret; -#else - return TRUE; #endif + return TRUE; } /** From b74e4e79cca897b98358cf299a48095ea70aac17 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 30 Mar 2017 16:47:57 -0400 Subject: [PATCH 48/56] ci: Add a check that submodule changes include "Update submodule: " To prevent repeats of https://github.com/ostreedev/ostree/pull/693 I tested this script in https://github.com/cgwalters/playground/pull/48 Closes: #770 Approved by: jlebon --- .redhat-ci.Dockerfile | 1 + .redhat-ci.yml | 2 ++ tests/ci-commitmessage-submodules.sh | 49 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100755 tests/ci-commitmessage-submodules.sh diff --git a/.redhat-ci.Dockerfile b/.redhat-ci.Dockerfile index 86d26dfa..0081998c 100644 --- a/.redhat-ci.Dockerfile +++ b/.redhat-ci.Dockerfile @@ -2,6 +2,7 @@ FROM fedora:25 RUN dnf install -y \ gcc \ + git \ sudo \ which \ attr \ diff --git a/.redhat-ci.yml b/.redhat-ci.yml index 2fce02b8..9eaf93ca 100644 --- a/.redhat-ci.yml +++ b/.redhat-ci.yml @@ -11,6 +11,7 @@ container: packages: - libasan + - git - coccinelle env: @@ -27,6 +28,7 @@ build: tests: - make syntax-check + - ./tests/ci-commitmessage-submodules.sh - make check - gnome-desktop-testing-runner -p 0 ostree diff --git a/tests/ci-commitmessage-submodules.sh b/tests/ci-commitmessage-submodules.sh new file mode 100755 index 00000000..77a4e1a1 --- /dev/null +++ b/tests/ci-commitmessage-submodules.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -euo pipefail +# Copyright 2017 Colin Walters +# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) + +# This script is intended to be used as a CI gating check +# that if a submodule is changed, the commit message contains +# the text: +# +# Update submodule: submodulepath +# +# It's very common for people to accidentally change submodules, and having this +# requirement is a small hurdle to pass. + +tmpd=$(mktemp -d) +touch ${tmpd}/.tmpdir +cleanup_tmp() { + # This sanity check ensures we don't delete something else + if test -f ${tmpd}/.tmpdir; then + rm -rf ${tmpd} + fi +} +trap cleanup_tmp EXIT + +gitdir=$(pwd) +# Create a temporary copy of this (using cp not git clone) so git doesn't +# try to read the submodules from the Internet again. If we wanted to +# require a newer git, we could use `git worktree`. +cp -a ${gitdir} ${tmpd}/workdir +cd ${tmpd}/workdir +git log --pretty=oneline origin/master.. | while read logline; do + commit=$(echo ${logline} | cut -f 1 -d ' ') + git diff --name-only ${commit}^..${commit} > ${tmpd}/diff.txt + git log -1 ${commit} > ${tmpd}/log.txt + echo "Validating commit for submodules: $commit" + git checkout -q "${commit}" + git submodule update --init + git submodule foreach --quiet 'echo $path'| while read submodule; do + if grep -q -e '^'${submodule} ${tmpd}/diff.txt; then + echo "Commit $commit modifies submodule: $submodule" + expected_match="Update submodule: $submodule" + if ! grep -q -e "$expected_match" ${tmpd}/log.txt; then + echo "error: Commit message for ${commit} changes a submodule, but does not match regex ${expected_match}" + exit 1 + fi + echo "Verified commit $commit matches regexp ${expected_match}" + fi + done +done From c937305c0e7f5609273e25753912c294b040a6ac Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 3 Apr 2017 20:35:58 -0400 Subject: [PATCH 49/56] core: Fix default value of disable_xattrs Sigh. Rather awful regression from https://github.com/ostreedev/ostree/pull/759 Closes: #775 Approved by: jlebon --- src/libostree/ostree-repo.c | 2 +- tests/test-remote-gpg-import.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 5e0a93ec..a8789b0e 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2075,7 +2075,7 @@ reload_core_config (OstreeRepo *self, /* See https://github.com/ostreedev/ostree/issues/758 */ if (!ot_keyfile_get_boolean_with_default (self->config, "core", "disable-xattrs", - TRUE, &self->disable_xattrs, error)) + FALSE, &self->disable_xattrs, error)) return FALSE; { g_autofree char *tmp_expiry_seconds = NULL; diff --git a/tests/test-remote-gpg-import.sh b/tests/test-remote-gpg-import.sh index 4429d8bc..a5803785 100755 --- a/tests/test-remote-gpg-import.sh +++ b/tests/test-remote-gpg-import.sh @@ -30,7 +30,7 @@ echo "1..4" cd ${test_tmpdir} mkdir repo -${OSTREE} init +ostree_repo_init repo #---------------------------------------------- # Test synchronicity of keyring file and remote From a0e15ecbedcfe86e544fb74f1d909af0d43ddbf9 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 4 Apr 2017 16:46:31 -0400 Subject: [PATCH 50/56] repo/core: Convert some functions to new code style I was planning to change one here, decided to do a conversion of some of the simpler functions in this file to keep up momentum. Closes: #776 Approved by: jlebon --- src/libostree/ostree-repo.c | 322 ++++++++++++------------------------ 1 file changed, 105 insertions(+), 217 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index a8789b0e..c8a12543 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -892,26 +892,21 @@ ostree_repo_write_config (OstreeRepo *self, GKeyFile *new_config, GError **error) { - gboolean ret = FALSE; - g_autofree char *data = NULL; - gsize len; - g_return_val_if_fail (self->inited, FALSE); - data = g_key_file_to_data (new_config, &len, error); + gsize len; + g_autofree char *data = g_key_file_to_data (new_config, &len, error); if (!glnx_file_replace_contents_at (self->repo_dir_fd, "config", (guint8*)data, len, 0, NULL, error)) - goto out; + return FALSE; g_key_file_free (self->config); self->config = g_key_file_new (); if (!g_key_file_load_from_data (self->config, data, len, 0, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } /* Bind a subset of an a{sv} to options in a given GKeyfile section */ @@ -954,34 +949,24 @@ impl_repo_remote_add (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(OstreeRemote) remote = NULL; - gboolean different_sysroot = FALSE; - gboolean ret = FALSE; - g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (url != NULL, FALSE); g_return_val_if_fail (options == NULL || g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE); if (strchr (name, '/') != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid character '/' in remote name: %s", - name); - goto out; - } + return glnx_throw (error, "Invalid character '/' in remote name: %s", name); - remote = ost_repo_get_remote (self, name, NULL); + g_autoptr(OstreeRemote) remote = ost_repo_get_remote (self, name, NULL); if (remote != NULL && if_not_exists) { - ret = TRUE; - goto out; + /* Note early return */ + return TRUE; } else if (remote != NULL) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Remote configuration for \"%s\" already exists: %s", - name, remote->file ? gs_file_get_path_cached (remote->file) : "(in config)"); - goto out; + return glnx_throw (error, + "Remote configuration for \"%s\" already exists: %s", + name, remote->file ? gs_file_get_path_cached (remote->file) : "(in config)"); } remote = ost_remote_new (); @@ -995,20 +980,18 @@ impl_repo_remote_add (OstreeRepo *self, * * XXX Having API regret about the "sysroot" argument now. */ + gboolean different_sysroot = FALSE; if (sysroot != NULL) different_sysroot = !g_file_equal (sysroot, self->sysroot_dir); if (different_sysroot || ostree_repo_is_system (self)) { - g_autofree char *basename = g_strconcat (name, ".conf", NULL); - g_autoptr(GFile) etc_ostree_remotes_d = NULL; - GError *local_error = NULL; + g_autoptr(GError) local_error = NULL; if (sysroot == NULL) sysroot = self->sysroot_dir; - etc_ostree_remotes_d = g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES); - + g_autoptr(GFile) etc_ostree_remotes_d = g_file_resolve_relative_path (sysroot, SYSCONF_REMOTES); if (!g_file_make_directory_with_parents (etc_ostree_remotes_d, cancellable, &local_error)) { @@ -1018,11 +1001,12 @@ impl_repo_remote_add (OstreeRepo *self, } else { - g_propagate_error (error, local_error); - goto out; + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; } } + g_autofree char *basename = g_strconcat (name, ".conf", NULL); remote->file = g_file_get_child (etc_ostree_remotes_d, basename); } @@ -1036,16 +1020,14 @@ impl_repo_remote_add (OstreeRepo *self, if (remote->file != NULL) { - g_autofree char *data = NULL; gsize length; - - data = g_key_file_to_data (remote->options, &length, NULL); + g_autofree char *data = g_key_file_to_data (remote->options, &length, NULL); if (!g_file_replace_contents (remote->file, data, length, NULL, FALSE, 0, NULL, cancellable, error)) - goto out; + return FALSE; } else { @@ -1055,15 +1037,12 @@ impl_repo_remote_add (OstreeRepo *self, ot_keyfile_copy_group (remote->options, config, remote->group); if (!ostree_repo_write_config (self, config, error)) - goto out; + return FALSE; } ost_repo_add_remote (self, remote); - ret = TRUE; - - out: - return ret; + return TRUE; } /** @@ -1104,67 +1083,52 @@ impl_repo_remote_delete (OstreeRepo *self, GCancellable *cancellable, GError **error) { - g_autoptr(OstreeRemote) remote = NULL; - gboolean ret = FALSE; - g_return_val_if_fail (name != NULL, FALSE); if (strchr (name, '/') != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid character '/' in remote name: %s", - name); - goto out; - } + return glnx_throw (error, "Invalid character '/' in remote name: %s", name); + g_autoptr(OstreeRemote) remote = NULL; if (if_exists) { remote = ost_repo_get_remote (self, name, NULL); if (!remote) { - ret = TRUE; - goto out; + /* Note early return */ + return TRUE; } } else remote = ost_repo_get_remote (self, name, error); if (remote == NULL) - goto out; + return FALSE; if (remote->file != NULL) { if (unlink (gs_file_get_path_cached (remote->file)) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); } else { - g_autoptr(GKeyFile) config = NULL; - - config = ostree_repo_copy_config (self); + g_autoptr(GKeyFile) config = ostree_repo_copy_config (self); /* XXX Not sure it's worth failing if the group to remove * isn't found. It's the end result we want, after all. */ if (g_key_file_remove_group (config, remote->group, NULL)) { if (!ostree_repo_write_config (self, config, error)) - goto out; + return FALSE; } } /* Delete the remote's keyring file, if it exists. */ if (!ot_ensure_unlinked_at (self->repo_dir_fd, remote->keyring, error)) - goto out; + return FALSE; ost_repo_remove_remote (self, remote); - ret = TRUE; - - out: - return ret; + return TRUE; } /** @@ -1320,11 +1284,9 @@ ostree_repo_remote_get_url (OstreeRepo *self, char **out_url, GError **error) { - g_autofree char *url = NULL; - gboolean ret = FALSE; - g_return_val_if_fail (name != NULL, FALSE); + g_autofree char *url = NULL; if (_ostree_repo_remote_name_is_file (name)) { url = g_strdup (name); @@ -1332,23 +1294,19 @@ ostree_repo_remote_get_url (OstreeRepo *self, else { if (!ostree_repo_get_remote_option (self, name, "url", NULL, &url, error)) - goto out; + return FALSE; if (url == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No \"url\" option in remote \"%s\"", name); - goto out; + return FALSE; } } if (out_url != NULL) *out_url = g_steal_pointer (&url); - - ret = TRUE; - - out: - return ret; + return TRUE; } /** @@ -1743,7 +1701,6 @@ ostree_repo_mode_to_string (OstreeRepoMode mode, const char **out_mode, GError **error) { - gboolean ret = FALSE; const char *ret_mode; switch (mode) @@ -1761,15 +1718,11 @@ ostree_repo_mode_to_string (OstreeRepoMode mode, ret_mode ="archive-z2"; break; default: - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid mode '%d'", mode); - goto out; + return glnx_throw (error, "Invalid mode '%d'", mode); } - ret = TRUE; *out_mode = ret_mode; - out: - return ret; + return TRUE; } gboolean @@ -1777,7 +1730,6 @@ ostree_repo_mode_from_string (const char *mode, OstreeRepoMode *out_mode, GError **error) { - gboolean ret = FALSE; OstreeRepoMode ret_mode; if (strcmp (mode, "bare") == 0) @@ -1790,16 +1742,10 @@ ostree_repo_mode_from_string (const char *mode, strcmp (mode, "archive") == 0) ret_mode = OSTREE_REPO_MODE_ARCHIVE_Z2; else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid mode '%s' in repository configuration", mode); - goto out; - } + return glnx_throw (error, "Invalid mode '%s' in repository configuration", mode); - ret = TRUE; *out_mode = ret_mode; - out: - return ret; + return TRUE; } #define DEFAULT_CONFIG_CONTENTS ("[core]\n" \ @@ -1847,11 +1793,12 @@ ostree_repo_create (OstreeRepo *self, { if (errno == ENOENT) { - const char *mode_str; + 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); g_string_append_printf (config_data, "mode=%s\n", mode_str); @@ -1888,8 +1835,7 @@ enumerate_directory_allow_noent (GFile *dirpath, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - GError *temp_error = NULL; + g_autoptr(GError) temp_error = NULL; g_autoptr(GFileEnumerator) ret_direnum = NULL; ret_direnum = g_file_enumerate_children (dirpath, queryargs, queryflags, @@ -1897,21 +1843,17 @@ enumerate_directory_allow_noent (GFile *dirpath, if (!ret_direnum) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - ret = TRUE; - } + g_clear_error (&temp_error); else - g_propagate_error (error, temp_error); - - goto out; + { + g_propagate_error (error, g_steal_pointer (&temp_error)); + return FALSE; + } } - ret = TRUE; if (out_direnum) *out_direnum = g_steal_pointer (&ret_direnum); - out: - return ret; + return TRUE; } static gboolean @@ -1977,17 +1919,12 @@ append_one_remote_config (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; g_autoptr(GKeyFile) remotedata = g_key_file_new (); - if (!g_key_file_load_from_file (remotedata, gs_file_get_path_cached (path), 0, error)) - goto out; + return FALSE; - ret = add_remotes_from_keyfile (self, remotedata, path, error); - - out: - return ret; + return add_remotes_from_keyfile (self, remotedata, path, error); } static GFile * @@ -2031,11 +1968,7 @@ reload_core_config (OstreeRepo *self, return FALSE; if (strcmp (version, "1") != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid repository version '%s'", version); - return FALSE; - } + return glnx_throw (error, "Invalid repository version '%s'", version); if (!ot_keyfile_get_boolean_with_default (self->config, "core", "archive", FALSE, &is_archive, error)) @@ -2128,25 +2061,23 @@ reload_remote_config (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GFile) remotes_d = NULL; - g_autoptr(GFileEnumerator) direnum = NULL; g_mutex_lock (&self->remotes_lock); g_hash_table_remove_all (self->remotes); g_mutex_unlock (&self->remotes_lock); if (!add_remotes_from_keyfile (self, self->config, NULL, error)) - goto out; + return FALSE; - remotes_d = get_remotes_d_dir (self); + g_autoptr(GFile) remotes_d = get_remotes_d_dir (self); if (remotes_d == NULL) return TRUE; + g_autoptr(GFileEnumerator) direnum = NULL; if (!enumerate_directory_allow_noent (remotes_d, OSTREE_GIO_FAST_QUERYINFO, 0, &direnum, cancellable, error)) - goto out; + return FALSE; if (direnum) { while (TRUE) @@ -2158,7 +2089,7 @@ reload_remote_config (OstreeRepo *self, if (!g_file_enumerator_iterate (direnum, &file_info, &path, NULL, error)) - goto out; + return FALSE; if (file_info == NULL) break; @@ -2169,14 +2100,12 @@ reload_remote_config (OstreeRepo *self, g_str_has_suffix (name, ".conf")) { if (!append_one_remote_config (self, path, cancellable, error)) - goto out; + return FALSE; } } } - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2205,7 +2134,6 @@ ostree_repo_open (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; struct stat stbuf; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -2228,7 +2156,7 @@ ostree_repo_open (OstreeRepo *self, &boot_id, NULL, error)) - goto out; + return FALSE; g_strdelimit (boot_id, "\n", '\0'); } @@ -2239,14 +2167,14 @@ ostree_repo_open (OstreeRepo *self, &self->repo_dir_fd, error)) { g_prefix_error (error, "%s: ", gs_file_get_path_cached (self->repodir)); - goto out; + return FALSE; } if (!glnx_opendirat (self->repo_dir_fd, "objects", TRUE, &self->objects_dir_fd, error)) { g_prefix_error (error, "Opening objects/ directory: "); - goto out; + return FALSE; } self->writable = faccessat (self->objects_dir_fd, ".", W_OK, 0) == 0; @@ -2254,13 +2182,11 @@ ostree_repo_open (OstreeRepo *self, { /* This is returned through ostree_repo_is_writable(). */ glnx_set_error_from_errno (&self->writable_error); + /* Note - we don't return this error yet! */ } if (fstat (self->objects_dir_fd, &stbuf) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); if (stbuf.st_uid != getuid () || stbuf.st_gid != getgid ()) { @@ -2273,37 +2199,34 @@ ostree_repo_open (OstreeRepo *self, } if (!glnx_opendirat (self->repo_dir_fd, "tmp", TRUE, &self->tmp_dir_fd, error)) - goto out; + return FALSE; if (self->writable) { if (!glnx_shutil_mkdir_p_at (self->tmp_dir_fd, _OSTREE_CACHE_DIR, 0775, cancellable, error)) - goto out; + return FALSE; if (!glnx_opendirat (self->tmp_dir_fd, _OSTREE_CACHE_DIR, TRUE, &self->cache_dir_fd, error)) - goto out; + return FALSE; } if (!ostree_repo_reload_config (self, cancellable, error)) - goto out; + return FALSE; /* TODO - delete this */ if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && self->enable_uncompressed_cache) { if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, "uncompressed-objects-cache", 0755, cancellable, error)) - goto out; + return FALSE; if (!glnx_opendirat (self->repo_dir_fd, "uncompressed-objects-cache", TRUE, &self->uncompressed_objects_dir_fd, error)) - goto out; + return FALSE; } self->inited = TRUE; - - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -2371,8 +2294,8 @@ ostree_repo_get_disable_fsync (OstreeRepo *self) /* Replace the contents of a file, honoring the repository's fsync * policy. - */ -gboolean + */ +gboolean _ostree_repo_file_replace_contents (OstreeRepo *self, int dfd, const char *path, @@ -2532,7 +2455,6 @@ list_loose_objects (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; guint c; int dfd = -1; static const gchar hexchars[] = "0123456789abcdef"; @@ -2549,21 +2471,16 @@ list_loose_objects (OstreeRepo *self, if (errno == ENOENT) continue; else - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); } /* Takes ownership of dfd */ if (!list_loose_objects_at (self, inout_objects, buf, dfd, commit_starting_with, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -2577,7 +2494,6 @@ load_metadata_internal (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; struct stat stbuf; glnx_fd_close int fd = -1; @@ -2590,22 +2506,19 @@ load_metadata_internal (OstreeRepo *self, if (!ot_openat_ignore_enoent (self->objects_dir_fd, loose_path_buf, &fd, error)) - goto out; + return FALSE; if (fd < 0 && self->commit_stagedir_fd != -1) { if (!ot_openat_ignore_enoent (self->commit_stagedir_fd, loose_path_buf, &fd, error)) - goto out; + return FALSE; } if (fd != -1) { if (fstat (fd, &stbuf) < 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); if (out_variant) { @@ -2616,7 +2529,7 @@ load_metadata_internal (OstreeRepo *self, mfile = g_mapped_file_new_from_fd (fd, FALSE, error); if (!mfile) - goto out; + return FALSE; ret_variant = g_variant_new_from_data (ostree_metadata_variant_type (objtype), g_mapped_file_get_contents (mfile), g_mapped_file_get_length (mfile), @@ -2629,7 +2542,7 @@ load_metadata_internal (OstreeRepo *self, { g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, cancellable, error); if (!data) - goto out; + return FALSE; ret_variant = g_variant_new_from_bytes (ostree_metadata_variant_type (objtype), data, TRUE); g_variant_ref_sink (ret_variant); @@ -2639,7 +2552,7 @@ load_metadata_internal (OstreeRepo *self, { ret_stream = g_unix_input_stream_new (fd, TRUE); if (!ret_stream) - goto out; + return FALSE; fd = -1; /* Transfer ownership */ } @@ -2649,21 +2562,19 @@ load_metadata_internal (OstreeRepo *self, else if (self->parent_repo) { if (!ostree_repo_load_variant (self->parent_repo, objtype, sha256, &ret_variant, error)) - goto out; + return FALSE; } else if (error_if_not_found) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No such metadata object %s.%s", sha256, ostree_object_type_to_string (objtype)); - goto out; + return FALSE; } - ret = TRUE; ot_transfer_out_value (out_variant, &ret_variant); ot_transfer_out_value (out_stream, &ret_stream); - out: - return ret; + return TRUE; } static gboolean @@ -3513,26 +3424,20 @@ ostree_repo_query_object_storage_size (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; char loose_path[_OSTREE_LOOSE_PATH_MAX]; int res; struct stat stbuf; _ostree_loose_path (loose_path, sha256, objtype, self->mode); - do + do res = fstatat (self->objects_dir_fd, loose_path, &stbuf, AT_SYMLINK_NOFOLLOW); while (G_UNLIKELY (res == -1 && errno == EINTR)); if (G_UNLIKELY (res == -1)) - { - glnx_set_prefix_error_from_errno (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype)); - goto out; - } + return glnx_throw_errno_prefix (error, "Querying object %s.%s", sha256, ostree_object_type_to_string (objtype)); *out_size = stbuf.st_size; - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -3600,13 +3505,11 @@ ostree_repo_load_commit (OstreeRepo *self, OstreeRepoCommitState *out_state, GError **error) { - gboolean ret = FALSE; - if (out_variant) { if (!load_metadata_internal (self, OSTREE_OBJECT_TYPE_COMMIT, checksum, TRUE, out_variant, NULL, NULL, NULL, error)) - goto out; + return FALSE; } if (out_state) @@ -3622,14 +3525,11 @@ ostree_repo_load_commit (OstreeRepo *self, } else if (errno != ENOENT) { - glnx_set_error_from_errno (error); - goto out; + return glnx_throw_errno (error); } } - ret = TRUE; - out: - return ret; + return TRUE; } /** @@ -3655,15 +3555,13 @@ ostree_repo_list_objects (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GHashTable) ret_objects = NULL; - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (self->inited, FALSE); - ret_objects = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, - (GDestroyNotify) g_variant_unref, - (GDestroyNotify) g_variant_unref); + g_autoptr(GHashTable) ret_objects = + g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, + (GDestroyNotify) g_variant_unref, + (GDestroyNotify) g_variant_unref); if (flags & OSTREE_REPO_LIST_OBJECTS_ALL) flags |= (OSTREE_REPO_LIST_OBJECTS_LOOSE | OSTREE_REPO_LIST_OBJECTS_PACKED); @@ -3671,11 +3569,11 @@ ostree_repo_list_objects (OstreeRepo *self, if (flags & OSTREE_REPO_LIST_OBJECTS_LOOSE) { if (!list_loose_objects (self, ret_objects, NULL, cancellable, error)) - goto out; + return FALSE; if ((flags & OSTREE_REPO_LIST_OBJECTS_NO_PARENTS) == 0 && self->parent_repo) { if (!list_loose_objects (self->parent_repo, ret_objects, NULL, cancellable, error)) - goto out; + return FALSE; } } @@ -3684,10 +3582,8 @@ ostree_repo_list_objects (OstreeRepo *self, /* Nothing for now... */ } - ret = TRUE; ot_transfer_out_value (out_objects, &ret_objects); - out: - return ret; + return TRUE; } /** @@ -3757,25 +3653,20 @@ ostree_repo_read_commit (OstreeRepo *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autoptr(GFile) ret_root = NULL; g_autofree char *resolved_commit = NULL; - if (!ostree_repo_resolve_rev (self, ref, FALSE, &resolved_commit, error)) - goto out; + return FALSE; - ret_root = (GFile*) _ostree_repo_file_new_for_commit (self, resolved_commit, error); + g_autoptr(GFile) ret_root = (GFile*) _ostree_repo_file_new_for_commit (self, resolved_commit, error); if (!ret_root) - goto out; + return FALSE; if (!ostree_repo_file_ensure_resolved ((OstreeRepoFile*)ret_root, error)) - goto out; + return FALSE; - ret = TRUE; ot_transfer_out_value(out_root, &ret_root); ot_transfer_out_value(out_commit, &resolved_commit); - out: - return ret; + return TRUE; } /** @@ -4903,7 +4794,6 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd, gboolean *out_did_lock, GError **error) { - gboolean ret = FALSE; g_autofree char *lock_name = g_strconcat (tmpdir_name, "-lock", NULL); gboolean did_lock = FALSE; g_autoptr(GError) local_error = NULL; @@ -4920,7 +4810,7 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd, else { g_propagate_error (error, g_steal_pointer (&local_error)); - goto out; + return FALSE; } } else @@ -4928,10 +4818,8 @@ _ostree_repo_try_lock_tmpdir (int tmpdir_dfd, did_lock = TRUE; } - ret = TRUE; *out_did_lock = did_lock; - out: - return ret; + return TRUE; } /* This allocates and locks a subdir of the repo tmp dir, using an existing From 89d663d94a12439ecc5ab0cc68b13e92906309c2 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 3 Apr 2017 12:46:37 -0400 Subject: [PATCH 51/56] soup: Hold a ref to the pending URI during completion processing It was reported that in the range request handling, we called `remove_pending()` twice (once in processing it, and once potentially in the local_error cleanup), and this could be viewed as a use-after-free. However, right now the range cleanup and `local_error` being set are mututally exclusive. Further, the task object already holds a strong reference, so I observed the refcount was 2. For both of these reasons, there is no use-after-free in practice. Reported-By: "Siddharth Sharma" Closes: #774 Approved by: jlebon --- src/libostree/ostree-fetcher-soup.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libostree/ostree-fetcher-soup.c b/src/libostree/ostree-fetcher-soup.c index b130b48c..fdcbea52 100644 --- a/src/libostree/ostree-fetcher-soup.c +++ b/src/libostree/ostree-fetcher-soup.c @@ -1040,21 +1040,21 @@ on_request_sent (GObject *object, gpointer user_data) { GTask *task = G_TASK (user_data); - OstreeFetcherPendingURI *pending; - GCancellable *cancellable; + /* Hold a ref to the pending across this function, since we remove + * it from the hash early in some cases, not in others. */ + OstreeFetcherPendingURI *pending = pending_uri_ref (g_task_get_task_data (task)); + GCancellable *cancellable = g_task_get_cancellable (task); GError *local_error = NULL; glnx_unref_object SoupMessage *msg = NULL; - pending = g_task_get_task_data (task); - cancellable = g_task_get_cancellable (task); - pending->state = OSTREE_FETCHER_STATE_COMPLETE; pending->request_body = soup_request_send_finish ((SoupRequest*) object, result, &local_error); if (!pending->request_body) goto out; - + g_assert_no_error (local_error); + if (SOUP_IS_REQUEST_HTTP (object)) { msg = soup_request_http_get_message ((SoupRequestHTTP*) object); @@ -1183,6 +1183,7 @@ on_request_sent (GObject *object, remove_pending (pending); } + pending_uri_unref (pending); g_object_unref (task); } From 6fa0fa750f861dc49899c83fccce89c236d93315 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 5 Apr 2017 16:51:31 -0400 Subject: [PATCH 52/56] sysroot/deploy: More code style conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In particular the 26-variable monster 👹 in `install_deployment_kernel()` is slain🗡. I didn't touch every function here, trying to keep things gradual. Closes: #781 Approved by: jlebon --- src/libostree/ostree-sysroot-deploy.c | 296 +++++++++----------------- 1 file changed, 97 insertions(+), 199 deletions(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 0db09973..c5d15af5 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -197,10 +197,7 @@ copy_dir_recurse (int src_parent_dfd, /* Create with mode 0700, we'll fchmod/fchown later */ if (mkdirat (dest_parent_dfd, name, 0700) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); if (!glnx_opendirat (dest_parent_dfd, name, TRUE, &dest_dfd, error)) return FALSE; @@ -220,10 +217,7 @@ copy_dir_recurse (int src_parent_dfd, if (fstatat (src_dfd_iter.fd, dent->d_name, &child_stbuf, AT_SYMLINK_NOFOLLOW) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); if (S_ISDIR (child_stbuf.st_mode)) { @@ -1055,20 +1049,13 @@ syncfs_dir_at (int dfd, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; glnx_fd_close int child_dfd = -1; - if (!glnx_opendirat (dfd, path, TRUE, &child_dfd, error)) - goto out; + return FALSE; if (syncfs (child_dfd) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); - ret = TRUE; - out: - return ret; + return TRUE; } /* First, sync the root directory as well as /var and /boot which may @@ -1080,16 +1067,11 @@ full_system_sync (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - if (syncfs (self->sysroot_fd) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); if (!syncfs_dir_at (self->sysroot_fd, "boot", cancellable, error)) - goto out; + return FALSE; /* And now out of an excess of conservativism, we still invoke * sync(). The advantage of still using `syncfs()` above is that we @@ -1099,9 +1081,7 @@ full_system_sync (OstreeSysroot *self, */ sync (); - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1111,43 +1091,36 @@ create_new_bootlinks (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - guint i; - int old_subbootversion; - int new_subbootversion; glnx_fd_close int ostree_dfd = -1; - glnx_fd_close int ostree_subbootdir_dfd = -1; - g_autofree char *ostree_bootdir_name = NULL; - g_autofree char *ostree_subbootdir_name = NULL; - if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error)) - goto out; - - ostree_bootdir_name = g_strdup_printf ("boot.%d", bootversion); + return FALSE; + int old_subbootversion; if (bootversion != self->bootversion) { if (!_ostree_sysroot_read_current_subbootversion (self, bootversion, &old_subbootversion, cancellable, error)) - goto out; + return FALSE; } else old_subbootversion = self->subbootversion; - new_subbootversion = old_subbootversion == 0 ? 1 : 0; + int new_subbootversion = old_subbootversion == 0 ? 1 : 0; /* Create the "subbootdir", which is a directory holding a symlink farm pointing to * deployments per-osname. */ - ostree_subbootdir_name = g_strdup_printf ("boot.%d.%d", bootversion, new_subbootversion); + g_autofree char *ostree_subbootdir_name = g_strdup_printf ("boot.%d.%d", bootversion, new_subbootversion); if (!glnx_shutil_rm_rf_at (ostree_dfd, ostree_subbootdir_name, cancellable, error)) - goto out; + return FALSE; if (!glnx_shutil_mkdir_p_at (ostree_dfd, ostree_subbootdir_name, 0755, cancellable, error)) - goto out; - if (!glnx_opendirat (ostree_dfd, ostree_subbootdir_name, FALSE, &ostree_subbootdir_dfd, error)) - goto out; + return FALSE; - for (i = 0; i < new_deployments->len; i++) + glnx_fd_close int ostree_subbootdir_dfd = -1; + if (!glnx_opendirat (ostree_dfd, ostree_subbootdir_name, FALSE, &ostree_subbootdir_dfd, error)) + return FALSE; + + for (guint i = 0; i < new_deployments->len; i++) { OstreeDeployment *deployment = new_deployments->pdata[i]; g_autofree char *bootlink_parent = g_strconcat (ostree_deployment_get_osname (deployment), @@ -1161,16 +1134,14 @@ create_new_bootlinks (OstreeSysroot *self, ostree_deployment_get_deployserial (deployment)); if (!glnx_shutil_mkdir_p_at (ostree_subbootdir_dfd, bootlink_parent, 0755, cancellable, error)) - goto out; + return FALSE; if (!symlink_at_replace (bootlink_target, ostree_subbootdir_dfd, bootlink_pathname, cancellable, error)) - goto out; + return FALSE; } - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1180,37 +1151,28 @@ swap_bootlinks (OstreeSysroot *self, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - int old_subbootversion, new_subbootversion; glnx_fd_close int ostree_dfd = -1; - g_autofree char *ostree_bootdir_name = NULL; - g_autofree char *ostree_subbootdir_name = NULL; - if (!glnx_opendirat (self->sysroot_fd, "ostree", TRUE, &ostree_dfd, error)) - goto out; - - ostree_bootdir_name = g_strdup_printf ("boot.%d", bootversion); + return FALSE; + int old_subbootversion; if (bootversion != self->bootversion) { if (!_ostree_sysroot_read_current_subbootversion (self, bootversion, &old_subbootversion, cancellable, error)) - goto out; + return FALSE; } else old_subbootversion = self->subbootversion; - new_subbootversion = old_subbootversion == 0 ? 1 : 0; - - ostree_subbootdir_name = g_strdup_printf ("boot.%d.%d", bootversion, new_subbootversion); - + int new_subbootversion = old_subbootversion == 0 ? 1 : 0; + g_autofree char *ostree_bootdir_name = g_strdup_printf ("boot.%d", bootversion); + g_autofree char *ostree_subbootdir_name = g_strdup_printf ("boot.%d.%d", bootversion, new_subbootversion); if (!symlink_at_replace (ostree_subbootdir_name, ostree_dfd, ostree_bootdir_name, cancellable, error)) - goto out; - - ret = TRUE; - out: - return ret; + return FALSE; + + return TRUE; } static char * @@ -1227,29 +1189,25 @@ parse_os_release (const char *contents, const char *split) { g_autofree char **lines = g_strsplit (contents, split, -1); - char **iter; GHashTable *ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - for (iter = lines; *iter; iter++) + for (char **iter = lines; *iter; iter++) { g_autofree char *line = *iter; - char *eq; - const char *quotedval; - char *val; if (g_str_has_prefix (line, "#")) continue; - - eq = strchr (line, '='); + + char *eq = strchr (line, '='); if (!eq) continue; - + *eq = '\0'; - quotedval = eq + 1; - val = g_shell_unquote (quotedval, NULL); + const char *quotedval = eq + 1; + char *val = g_shell_unquote (quotedval, NULL); if (!val) continue; - + g_hash_table_insert (ret, g_steal_pointer (&line), val); } @@ -1258,7 +1216,7 @@ parse_os_release (const char *contents, /* * install_deployment_kernel: - * + * * Write out an entry in /boot/loader/entries for @deployment. */ static gboolean @@ -1272,77 +1230,55 @@ install_deployment_kernel (OstreeSysroot *sysroot, GError **error) { - gboolean ret = FALSE; - struct stat stbuf; - const char *osname = ostree_deployment_get_osname (deployment); - const char *bootcsum = ostree_deployment_get_bootcsum (deployment); - g_autofree char *bootcsumdir = NULL; - g_autofree char *bootconfdir = NULL; - g_autofree char *bootconf_name = NULL; - g_autofree char *dest_kernel_name = NULL; - g_autofree char *dest_initramfs_name = NULL; - g_autofree char *tree_kernel_name = NULL; - g_autofree char *tree_initramfs_name = NULL; - g_autofree char *deployment_dirpath = NULL; + OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); + g_autofree char *deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment); glnx_fd_close int deployment_dfd = -1; - glnx_fd_close int tree_boot_dfd = -1; - glnx_fd_close int boot_dfd = -1; - glnx_fd_close int bootcsum_dfd = -1; - g_autofree char *contents = NULL; - g_autofree char *deployment_version = NULL; - g_autoptr(GHashTable) osrelease_values = NULL; - g_autofree char *version_key = NULL; - g_autofree char *ostree_kernel_arg = NULL; - g_autofree char *options_key = NULL; - GString *title_key; - __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL; - const char *val; - OstreeBootconfigParser *bootconfig; - - bootconfig = ostree_deployment_get_bootconfig (deployment); - deployment_dirpath = ostree_sysroot_get_deployment_dirpath (sysroot, deployment); - if (!glnx_opendirat (sysroot->sysroot_fd, deployment_dirpath, FALSE, &deployment_dfd, error)) - goto out; + return FALSE; + glnx_fd_close int tree_boot_dfd = -1; + g_autofree char *tree_kernel_name = NULL; + g_autofree char *tree_initramfs_name = NULL; if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd, &tree_kernel_name, &tree_initramfs_name, cancellable, error)) - goto out; + return FALSE; + glnx_fd_close int boot_dfd = -1; if (!glnx_opendirat (sysroot->sysroot_fd, "boot", TRUE, &boot_dfd, error)) - goto out; + return FALSE; - bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum); - bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion); - bootconf_name = g_strdup_printf ("ostree-%s-%d.conf", osname, + const char *osname = ostree_deployment_get_osname (deployment); + const char *bootcsum = ostree_deployment_get_bootcsum (deployment); + g_autofree char *bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum); + g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion); + g_autofree char *bootconf_name = g_strdup_printf ("ostree-%s-%d.conf", osname, ostree_deployment_get_index (deployment)); - if (!glnx_shutil_mkdir_p_at (boot_dfd, bootcsumdir, 0775, cancellable, error)) - goto out; + return FALSE; + + glnx_fd_close int bootcsum_dfd = -1; if (!glnx_opendirat (boot_dfd, bootcsumdir, TRUE, &bootcsum_dfd, error)) - goto out; + return FALSE; if (!glnx_shutil_mkdir_p_at (boot_dfd, bootconfdir, 0775, cancellable, error)) - goto out; - - dest_kernel_name = remove_checksum_from_kernel_name (tree_kernel_name, bootcsum); + return FALSE; + g_autofree char *dest_kernel_name = remove_checksum_from_kernel_name (tree_kernel_name, bootcsum); + struct stat stbuf; if (fstatat (bootcsum_dfd, dest_kernel_name, &stbuf, 0) != 0) { if (errno != ENOENT) - { - glnx_set_prefix_error_from_errno (error, "fstat %s", dest_kernel_name); - goto out; - } + return glnx_throw_errno_prefix (error, "fstat %s", dest_kernel_name); if (!hardlink_or_copy_at (tree_boot_dfd, tree_kernel_name, bootcsum_dfd, dest_kernel_name, sysroot->debug_flags, cancellable, error)) - goto out; + return FALSE; } + g_autofree char *dest_initramfs_name = NULL; if (tree_initramfs_name) { dest_initramfs_name = remove_checksum_from_kernel_name (tree_initramfs_name, bootcsum); @@ -1350,34 +1286,28 @@ install_deployment_kernel (OstreeSysroot *sysroot, if (fstatat (bootcsum_dfd, dest_initramfs_name, &stbuf, 0) != 0) { if (errno != ENOENT) - { - glnx_set_prefix_error_from_errno (error, "fstat %s", dest_initramfs_name); - goto out; - } + return glnx_throw_errno_prefix (error, "fstat %s", dest_initramfs_name); if (!hardlink_or_copy_at (tree_boot_dfd, tree_initramfs_name, bootcsum_dfd, dest_initramfs_name, sysroot->debug_flags, cancellable, error)) - goto out; + return FALSE; } } + g_autofree char *contents = NULL; if (fstatat (deployment_dfd, "usr/lib/os-release", &stbuf, 0) != 0) { if (errno != ENOENT) { - glnx_set_error_from_errno (error); - goto out; + return glnx_throw_errno (error); } else { contents = glnx_file_get_contents_utf8_at (deployment_dfd, "etc/os-release", NULL, cancellable, error); if (!contents) - { - g_prefix_error (error, "Reading /etc/os-release: "); - goto out; - } + return g_prefix_error (error, "Reading /etc/os-release: "), FALSE; } } else @@ -1385,26 +1315,18 @@ install_deployment_kernel (OstreeSysroot *sysroot, contents = glnx_file_get_contents_utf8_at (deployment_dfd, "usr/lib/os-release", NULL, cancellable, error); if (!contents) - { - g_prefix_error (error, "Reading /usr/lib/os-release: "); - goto out; - } + return g_prefix_error (error, "Reading /usr/lib/os-release: "), FALSE; } - osrelease_values = parse_os_release (contents, "\n"); - + g_autoptr(GHashTable) osrelease_values = parse_os_release (contents, "\n"); /* title */ - val = g_hash_table_lookup (osrelease_values, "PRETTY_NAME"); + const char *val = g_hash_table_lookup (osrelease_values, "PRETTY_NAME"); if (val == NULL) val = g_hash_table_lookup (osrelease_values, "ID"); if (val == NULL) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No PRETTY_NAME or ID in /etc/os-release"); - goto out; - } - + return glnx_throw (error, "No PRETTY_NAME or ID in /etc/os-release"); + g_autofree char *deployment_version = NULL; if (repo) { /* Try extracting a version for this deployment. */ @@ -1426,7 +1348,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, /* XXX The SYSLINUX bootloader backend actually parses the title string * (specifically, it looks for the substring "(ostree"), so further * changes to the title format may require updating that backend. */ - title_key = g_string_new (val); + g_autoptr(GString) title_key = g_string_new (val); if (deployment_version && *deployment_version) { g_string_append_c (title_key, ' '); @@ -1444,14 +1366,11 @@ install_deployment_kernel (OstreeSysroot *sysroot, } g_string_append_c (title_key, ')'); ostree_bootconfig_parser_set (bootconfig, "title", title_key->str); - g_string_free (title_key, TRUE); - version_key = g_strdup_printf ("%d", n_deployments - ostree_deployment_get_index (deployment)); + g_autofree char *version_key = g_strdup_printf ("%d", n_deployments - ostree_deployment_get_index (deployment)); ostree_bootconfig_parser_set (bootconfig, "version", version_key); - - { g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", dest_kernel_name, NULL); - ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath); - } + g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", dest_kernel_name, NULL); + ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath); if (dest_initramfs_name) { @@ -1461,29 +1380,25 @@ install_deployment_kernel (OstreeSysroot *sysroot, val = ostree_bootconfig_parser_get (bootconfig, "options"); - ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d", + g_autofree char *ostree_kernel_arg = g_strdup_printf ("ostree=/ostree/boot.%d/%s/%s/%d", new_bootversion, osname, bootcsum, ostree_deployment_get_bootserial (deployment)); - kargs = _ostree_kernel_args_from_string (val); + __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = _ostree_kernel_args_from_string (val); _ostree_kernel_args_replace_take (kargs, ostree_kernel_arg); ostree_kernel_arg = NULL; - options_key = _ostree_kernel_args_to_string (kargs); + g_autofree char *options_key = _ostree_kernel_args_to_string (kargs); ostree_bootconfig_parser_set (bootconfig, "options", options_key); - - { glnx_fd_close int bootconf_dfd = -1; - if (!glnx_opendirat (boot_dfd, bootconfdir, TRUE, &bootconf_dfd, error)) - goto out; + glnx_fd_close int bootconf_dfd = -1; + if (!glnx_opendirat (boot_dfd, bootconfdir, TRUE, &bootconf_dfd, error)) + return FALSE; - if (!ostree_bootconfig_parser_write_at (ostree_deployment_get_bootconfig (deployment), - bootconf_dfd, bootconf_name, - cancellable, error)) - goto out; - } + if (!ostree_bootconfig_parser_write_at (ostree_deployment_get_bootconfig (deployment), + bootconf_dfd, bootconf_name, + cancellable, error)) + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1493,23 +1408,18 @@ prepare_new_bootloader_link (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; - g_autofree char *new_target = NULL; - g_assert ((current_bootversion == 0 && new_bootversion == 1) || (current_bootversion == 1 && new_bootversion == 0)); - new_target = g_strdup_printf ("loader.%d", new_bootversion); + g_autofree char *new_target = g_strdup_printf ("loader.%d", new_bootversion); /* We shouldn't actually need to replace but it's easier to reuse that code */ if (!symlink_at_replace (new_target, sysroot->sysroot_fd, "boot/loader.tmp", cancellable, error)) - goto out; + return FALSE; - ret = TRUE; - out: - return ret; + return TRUE; } static gboolean @@ -1519,7 +1429,6 @@ swap_bootloader (OstreeSysroot *sysroot, GCancellable *cancellable, GError **error) { - gboolean ret = FALSE; glnx_fd_close int boot_dfd = -1; int res; @@ -1527,7 +1436,7 @@ swap_bootloader (OstreeSysroot *sysroot, (current_bootversion == 1 && new_bootversion == 0)); if (!glnx_opendirat (sysroot->sysroot_fd, "boot", TRUE, &boot_dfd, error)) - goto out; + return FALSE; /* The symlink was already written, and we used syncfs() to ensure * its data is in place. Renaming now should give us atomic semantics; @@ -1537,10 +1446,7 @@ swap_bootloader (OstreeSysroot *sysroot, res = renameat (boot_dfd, "loader.tmp", boot_dfd, "loader"); while (G_UNLIKELY (res == -1 && errno == EINTR)); if (res == -1) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); /* Now we explicitly fsync this directory, even though it * isn't required for atomicity, for two reasons: @@ -1552,14 +1458,9 @@ swap_bootloader (OstreeSysroot *sysroot, * admin by going back to the previous session. */ if (fsync (boot_dfd) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + return glnx_throw_errno (error); - ret = TRUE; - out: - return ret; + return TRUE; } static GHashTable * @@ -1644,10 +1545,7 @@ cleanup_legacy_current_symlinks (OstreeSysroot *self, if (unlinkat (self->sysroot_fd, buf->str, 0) < 0) { if (errno != ENOENT) - { - glnx_set_error_from_errno (error); - return FALSE; - } + return glnx_throw_errno (error); } } From 076dfeba6b0c905336e281e1c9136596bfe1e4d5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 5 Apr 2017 14:43:39 -0400 Subject: [PATCH 53/56] curl: Enable pipelining for HTTP/2 Testing a fetch of `fedora-atomic/.../docker-host` from an nginx instance over `https://127.0.0.1` using Fedora 25 versions. Average over 3 runs: Before: ~24.6 seconds After: ~19 seconds Speedup: ~30% Closes: https://github.com/ostreedev/ostree/issues/778 Closes: #780 Approved by: jlebon --- src/libostree/ostree-fetcher-curl.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libostree/ostree-fetcher-curl.c b/src/libostree/ostree-fetcher-curl.c index be0e4b41..829f4447 100644 --- a/src/libostree/ostree-fetcher-curl.c +++ b/src/libostree/ostree-fetcher-curl.c @@ -36,6 +36,14 @@ #define CURL_AT_LEAST_VERSION(x,y,z) (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z)) #endif +/* Cargo culted from https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c */ +#ifndef CURLPIPE_MULTIPLEX +/* This little trick will just make sure that we don't enable pipelining for + libcurls old enough to not have this symbol. It is _not_ defined to zero in + a recent libcurl header. */ +#define CURLPIPE_MULTIPLEX 0 +#endif + #include "ostree-fetcher.h" #include "ostree-fetcher-util.h" #include "ostree-enumtypes.h" @@ -219,6 +227,12 @@ _ostree_fetcher_init (OstreeFetcher *self) #if CURL_AT_LEAST_VERSION(7, 30, 0) /* Let's do something reasonable here. */ curl_multi_setopt (self->multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 8); +#endif + /* This version mirrors the version at which we're enabling HTTP2 support. + * See also https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c + */ +#if CURL_AT_LEAST_VERSION(7, 51, 0) + curl_multi_setopt (self->multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); #endif } @@ -764,6 +778,11 @@ initiate_next_curl_request (FetcherRequest *req, */ #if CURL_AT_LEAST_VERSION(7, 51, 0) curl_easy_setopt (req->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); +#endif + /* https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c */ +#if (CURLPIPE_MULTIPLEX > 0) + /* wait for pipe connection to confirm */ + curl_easy_setopt (req->easy, CURLOPT_PIPEWAIT, 1L); #endif curl_easy_setopt (req->easy, CURLOPT_WRITEFUNCTION, write_cb); if (g_getenv ("OSTREE_DEBUG_HTTP")) From 6a7ee4860f737a52b2a879ad8690456bbd9440bf Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 11 Apr 2017 21:54:14 -0400 Subject: [PATCH 54/56] Fix a few gtk-doc warnings Just continuing to chip away at this. Closes: #788 Approved by: jlebon --- apidoc/ostree-sections.txt | 10 ++++++++++ src/libostree/ostree-repo.h | 4 ++++ src/libostree/ostree-sysroot-deploy.c | 1 + 3 files changed, 15 insertions(+) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 6f0cf4a8..07dbaf1f 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -71,6 +71,16 @@ OstreeChecksumInputStreamPrivate ostree_checksum_input_stream_get_type
+
+ostree-version +OSTREE_CHECK_VERSION +OSTREE_YEAR_VERSION +OSTREE_RELEASE_VERSION +OSTREE_VERSION +OSTREE_VERSION_S +OSTREE_VERSION_HEX +
+
ostree-core OSTREE_MAX_METADATA_SIZE diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 482ede7a..1664d65d 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -123,6 +123,10 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self, /** * OstreeRepoRemoteChange: * The remote change operation. + * @OSTREE_REPO_REMOTE_CHANGE_ADD: Add a remote + * @OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS: Like above, but do nothing if the remote exists + * @OSTREE_REPO_REMOTE_CHANGE_DELETE: Delete a remote + * @OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: Delete a remote, do nothing if the remote does not exist */ typedef enum { OSTREE_REPO_REMOTE_CHANGE_ADD, diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index c5d15af5..ed8c8bca 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2128,6 +2128,7 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self, * @self: Sysroot * @deployment: A deployment * @is_mutable: Whether or not deployment's files can be changed + * @cancellable: Cancellable * @error: Error * * By default, deployment directories are not mutable. This function From d3385a3014e173299094133d644763e34e5ecd52 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 5 Apr 2017 13:11:34 -0400 Subject: [PATCH 55/56] checkout: Provide useful error with checkout -H and incompat mode Previously we'd assert and dump core if one used `checkout -H` without `-U` on a bare-user repo, because we'd hit the bare-user symlink case. Rework the code to handle this, and add tests. I hit this when I was going to suggest to someone to use `-H` to ensure they were getting hardlinks. Closes: #779 Approved by: jlebon --- src/libostree/ostree-repo-checkout.c | 48 ++++++++++++++++++++++------ tests/basic-test.sh | 44 +++++++++++++++++++++---- 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 09966a94..392e16fd 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -423,6 +423,7 @@ checkout_one_file_at (OstreeRepo *repo, gboolean ret = FALSE; const char *checksum; gboolean is_symlink; + gboolean is_bare_user_symlink = FALSE; gboolean can_cache; gboolean need_copy = TRUE; char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; @@ -431,7 +432,6 @@ checkout_one_file_at (OstreeRepo *repo, gboolean is_whiteout; is_symlink = g_file_info_get_file_type (source_info) == G_FILE_TYPE_SYMBOLIC_LINK; - checksum = ostree_repo_file_get_checksum ((OstreeRepoFile*)source); is_whiteout = !is_symlink && options->process_whiteouts && @@ -468,20 +468,42 @@ checkout_one_file_at (OstreeRepo *repo, while (current_repo) { - gboolean is_bare = ((current_repo->mode == OSTREE_REPO_MODE_BARE - && options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) || - (current_repo->mode == OSTREE_REPO_MODE_BARE_USER - && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER - /* NOTE: bare-user symlinks are not stored as symlinks */ - && !is_symlink) || - (current_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY - && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER)); + /* TODO - Hoist this up to the toplevel at least for checking out from + * !parent; don't need to compute it for each file. + */ + gboolean repo_is_usermode = + current_repo->mode == OSTREE_REPO_MODE_BARE_USER || + current_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY; + /* We're hardlinkable if the checkout mode matches the repo mode */ + gboolean is_hardlinkable = + (current_repo->mode == OSTREE_REPO_MODE_BARE + && options->mode == OSTREE_REPO_CHECKOUT_MODE_NONE) || + (repo_is_usermode && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER); + gboolean is_bare = is_hardlinkable && !is_bare_user_symlink; 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 && options->mode == OSTREE_REPO_CHECKOUT_MODE_USER && current_can_cache); + /* NOTE: bare-user symlinks are not stored as symlinks; see + * https://github.com/ostreedev/ostree/commit/47c612e5a0688c3452a125655a245e8f4f01b2b0 + * as well as write_object(). + */ + is_bare_user_symlink = (repo_is_usermode && is_symlink); + + /* Verify if no_copy_fallback is set that we can hardlink, with a + * special exception for bare-user symlinks. + */ + if (options->no_copy_fallback && !is_hardlinkable && !is_bare_user_symlink) + { + glnx_throw (error, + repo_is_usermode ? + "User repository mode requires user checkout mode to hardlink" : + "Bare repository mode cannot hardlink in user checkout mode"); + goto out; + } + /* But only under these conditions */ if (is_bare || is_archive_z2_with_cache) { @@ -596,7 +618,13 @@ checkout_one_file_at (OstreeRepo *repo, /* Fall back to copy if we couldn't hardlink */ if (need_copy) { - g_assert (!options->no_copy_fallback); + /* Bare user mode can't hardlink symlinks, so we need to do a copy for + * those. (Although in the future we could hardlink inside checkouts) This + * assertion is intended to ensure that for regular files at least, we + * succeeded at hardlinking above. + */ + if (options->no_copy_fallback) + g_assert (is_bare_user_symlink); if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs, cancellable, error)) goto out; diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 27b79026..294854bf 100644 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -38,9 +38,45 @@ if grep bare-user-only repo/config; then CHECKOUT_U_ARG="-U" fi +validate_checkout_basic() { + (cd $1; + assert_has_file firstfile + assert_has_file baz/cow + assert_file_has_content baz/cow moo + assert_has_file baz/deeper/ohyeah + ) +} + $OSTREE checkout test2 checkout-test2 +validate_checkout_basic checkout-test2 echo "ok checkout" +# Note this tests bare-user *and* bare-user-only +rm checkout-test2 -rf +if grep bare-user repo/config; then + $OSTREE checkout -U -H test2 checkout-test2 +else + $OSTREE checkout -H test2 checkout-test2 +fi +validate_checkout_basic checkout-test2 +rm checkout-test2 -rf +# Only do these tests on bare-user/bare, not bare-user-only +# since the latter automatically synthesizes -U if it's not passed. +if ! grep -q bare-user-only repo/config; then +if grep -q bare-user repo/config; then + if $OSTREE checkout -H test2 checkout-test2 2>err.txt; then + assert_not_reached "checkout -H worked?" + fi + assert_file_has_content err.txt "User repository.*requires.*user" +else + if $OSTREE checkout -U -H test2 checkout-test2 2>err.txt; then + assert_not_reached "checkout -H worked?" + fi + assert_file_has_content err.txt "Bare repository mode cannot hardlink in user" +fi +fi +echo "ok checkout -H" + $OSTREE rev-parse test2 $OSTREE rev-parse 'test2^' $OSTREE rev-parse 'test2^^' 2>/dev/null && fatal "rev-parse test2^^ unexpectedly succeeded!" @@ -64,13 +100,9 @@ ostree_repo_init test-repo --mode=bare-user rm test-repo -rf echo "ok repo-init on existing repo" +rm checkout-test2 -rf +$OSTREE checkout test2 checkout-test2 cd checkout-test2 -assert_has_file firstfile -assert_has_file baz/cow -assert_file_has_content baz/cow moo -assert_has_file baz/deeper/ohyeah -echo "ok content" - rm firstfile $OSTREE commit ${COMMIT_ARGS} -b test2 -s delete From 8742287b117cb8a04d4106d37bfe0e15f9666ef7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 11 Apr 2017 15:29:17 -0400 Subject: [PATCH 56/56] Release 2017.4 Closes: #786 Approved by: jlebon --- configure.ac | 2 +- src/libostree/libostree.sym | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index dbbd63e5..f6512c1f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.63]) dnl If incrementing the version here, remember to update libostree.sym too m4_define([year_version], [2017]) -m4_define([release_version], [3]) +m4_define([release_version], [4]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) diff --git a/src/libostree/libostree.sym b/src/libostree/libostree.sym index 749b0c36..d9339bf2 100644 --- a/src/libostree/libostree.sym +++ b/src/libostree/libostree.sym @@ -381,11 +381,6 @@ global: ostree_raw_file_to_archive_z2_stream_with_options; } LIBOSTREE_2017.2; -/* NOTE NOTE NOTE - * Versions above here are released. Only add symbols below this line. - * NOTE NOTE NOTE - */ - LIBOSTREE_2017.4 { global: ostree_check_version; @@ -394,6 +389,19 @@ global: ostree_sysroot_write_deployments_with_options; } LIBOSTREE_2017.3; +/* NOTE NOTE NOTE + * Versions above here are released. Only add symbols below this line. + * NOTE NOTE NOTE + */ + +/* Uncomment when adding the first new symbol */ +/* +LIBOSTREE_2017.$NEWVERSION { +global: + someostree_symbol_deleteme; +} LIBOSTREE_2017.4; +*/ + /* 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 * source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION