diff --git a/Makefile-tests.am b/Makefile-tests.am
index 5498fd43..f5a65278 100644
--- a/Makefile-tests.am
+++ b/Makefile-tests.am
@@ -126,6 +126,7 @@ _installed_or_uninstalled_test_scripts = \
tests/test-create-usb.sh \
tests/test-find-remotes.sh \
tests/test-fsck-collections.sh \
+ tests/test-fsck-delete.sh \
tests/test-init-collections.sh \
tests/test-prune-collections.sh \
tests/test-refs-collections.sh \
diff --git a/Makefile.in b/Makefile.in
index ce89b39d..356f5589 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1999,8 +1999,8 @@ am__EXEEXT_25 = tests/test-basic.sh tests/test-basic-user.sh \
tests/test-summary-update.sh tests/test-summary-view.sh \
tests/test-no-initramfs.sh tests/test-create-usb.sh \
tests/test-find-remotes.sh tests/test-fsck-collections.sh \
- tests/test-init-collections.sh tests/test-prune-collections.sh \
- tests/test-refs-collections.sh \
+ tests/test-fsck-delete.sh tests/test-init-collections.sh \
+ tests/test-prune-collections.sh tests/test-refs-collections.sh \
tests/test-remote-add-collections.sh \
tests/test-repo-finder-mount-integration.sh \
tests/test-summary-collections.sh \
@@ -2842,8 +2842,8 @@ _installed_or_uninstalled_test_scripts = tests/test-basic.sh \
tests/test-summary-update.sh tests/test-summary-view.sh \
tests/test-no-initramfs.sh tests/test-create-usb.sh \
tests/test-find-remotes.sh tests/test-fsck-collections.sh \
- tests/test-init-collections.sh tests/test-prune-collections.sh \
- tests/test-refs-collections.sh \
+ tests/test-fsck-delete.sh tests/test-init-collections.sh \
+ tests/test-prune-collections.sh tests/test-refs-collections.sh \
tests/test-remote-add-collections.sh \
tests/test-repo-finder-mount-integration.sh \
tests/test-summary-collections.sh \
@@ -8205,6 +8205,13 @@ tests/test-fsck-collections.sh.log: tests/test-fsck-collections.sh
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/test-fsck-delete.sh.log: tests/test-fsck-delete.sh
+ @p='tests/test-fsck-delete.sh'; \
+ b='tests/test-fsck-delete.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
tests/test-init-collections.sh.log: tests/test-init-collections.sh
@p='tests/test-init-collections.sh'; \
b='tests/test-init-collections.sh'; \
diff --git a/apidoc/html/index.html b/apidoc/html/index.html
index 98f7ed38..bb689ad8 100644
--- a/apidoc/html/index.html
+++ b/apidoc/html/index.html
@@ -14,7 +14,7 @@
diff --git a/apidoc/html/ostree-OstreeRepo.html b/apidoc/html/ostree-OstreeRepo.html
index 490f498b..91b9bc83 100644
--- a/apidoc/html/ostree-OstreeRepo.html
+++ b/apidoc/html/ostree-OstreeRepo.html
@@ -442,6 +442,14 @@
gboolean
+ostree_repo_mark_commit_partial_reason ()
+ |
+
+
+|
+gboolean
+ |
+
ostree_repo_write_metadata ()
|
@@ -3435,9 +3443,10 @@ ostree_repo_mark_commit_partial (const char *checksum,
gboolean is_partial,
GError **error);
-Commits in "partial" state do not have all their child objects written. This
-occurs in various situations, such as during a pull, but also if a "subpath"
-pull is used, as well as "commit only" pulls.
+Commits in the "partial" state do not have all their child objects
+written. This occurs in various situations, such as during a pull,
+but also if a "subpath" pull is used, as well as "commit only"
+pulls.
This function is used by ostree_repo_pull_with_options(); you
should use this if you are implementing a different type of transport.
@@ -3476,6 +3485,62 @@ should use this if you are implementing a different type of transport.
+
ostree_repo_mark_commit_partial_reason ()
+
gboolean
+ostree_repo_mark_commit_partial_reason
+ (OstreeRepo *self,
+ const char *checksum,
+ gboolean is_partial,
+ OstreeRepoCommitState in_state,
+ GError **error);
+
Allows the setting of a reason code for a partial commit. Presently
+it only supports setting reason bitmask to
+OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL, or
+OSTREE_REPO_COMMIT_STATE_NORMAL. This will allow successive ostree
+fsck operations to exit properly with an error code if the
+repository has been truncated as a result of fsck trying to repair
+it.
+
+
Since: 2019.4
+
+
+
diff --git a/apidoc/html/ostree.devhelp2 b/apidoc/html/ostree.devhelp2
index 6804d47e..00931091 100644
--- a/apidoc/html/ostree.devhelp2
+++ b/apidoc/html/ostree.devhelp2
@@ -134,6 +134,7 @@
+
@@ -433,6 +434,7 @@
+
diff --git a/apidoc/html/reference.html b/apidoc/html/reference.html
index b2b92571..ef4b30be 100644
--- a/apidoc/html/reference.html
+++ b/apidoc/html/reference.html
@@ -1235,6 +1235,10 @@ ostree_repo_list_collection_refs, function in ostree-misc-experimental
+ostree_repo_mark_commit_partial_reason, function in OstreeRepo
+
+
+
OSTREE_REPO_METADATA_REF, macro in ostree-repo-experimental
diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt
index e8faeb10..252a563a 100644
--- a/apidoc/ostree-sections.txt
+++ b/apidoc/ostree-sections.txt
@@ -333,6 +333,7 @@ ostree_repo_set_cache_dir
ostree_repo_sign_delta
ostree_repo_has_object
ostree_repo_mark_commit_partial
+ostree_repo_mark_commit_partial_reason
ostree_repo_write_metadata
ostree_repo_write_metadata_async
ostree_repo_write_metadata_finish
diff --git a/apidoc/version.xml b/apidoc/version.xml
index 506ed987..b428e33c 100644
--- a/apidoc/version.xml
+++ b/apidoc/version.xml
@@ -1 +1 @@
-2019.3
\ No newline at end of file
+2019.4
\ No newline at end of file
diff --git a/build-aux/compile b/build-aux/compile
index 99e50524..b89c278e 100755
--- a/build-aux/compile
+++ b/build-aux/compile
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2018-03-07.03; # UTC
diff --git a/build-aux/config.guess b/build-aux/config.guess
index b33c9e89..b5d7a0f3 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# Attempt to guess a canonical system name.
# Copyright 1992-2018 Free Software Foundation, Inc.
diff --git a/build-aux/config.sub b/build-aux/config.sub
index b51fb8cd..be4dc6e5 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2018 Free Software Foundation, Inc.
diff --git a/build-aux/depcomp b/build-aux/depcomp
index 65cbf709..4e0ae31b 100755
--- a/build-aux/depcomp
+++ b/build-aux/depcomp
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2018-03-07.03; # UTC
diff --git a/build-aux/install-sh b/build-aux/install-sh
index 8175c640..defb86ae 100755
--- a/build-aux/install-sh
+++ b/build-aux/install-sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/sh
# install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC
diff --git a/build-aux/missing b/build-aux/missing
index 625aeb11..ab658ed5 100755
--- a/build-aux/missing
+++ b/build-aux/missing
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# Common wrapper for a few potentially missing GNU programs.
scriptversion=2018-03-07.03; # UTC
diff --git a/build-aux/test-driver b/build-aux/test-driver
index b8521a48..d1ef0647 100755
--- a/build-aux/test-driver
+++ b/build-aux/test-driver
@@ -1,4 +1,4 @@
-#! /bin/sh
+#!/usr/bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2018-03-07.03; # UTC
diff --git a/configure b/configure
index 83fd8af5..a1de30db 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libostree 2019.3.
+# Generated by GNU Autoconf 2.69 for libostree 2019.4.
#
# Report bugs to .
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='libostree'
PACKAGE_TARNAME='libostree'
-PACKAGE_VERSION='2019.3'
-PACKAGE_STRING='libostree 2019.3'
+PACKAGE_VERSION='2019.4'
+PACKAGE_STRING='libostree 2019.4'
PACKAGE_BUGREPORT='walters@verbum.org'
PACKAGE_URL=''
@@ -1556,7 +1556,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures libostree 2019.3 to adapt to many kinds of systems.
+\`configure' configures libostree 2019.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1626,7 +1626,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of libostree 2019.3:";;
+ short | recursive ) echo "Configuration of libostree 2019.4:";;
esac
cat <<\_ACEOF
@@ -1885,7 +1885,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-libostree configure 2019.3
+libostree configure 2019.4
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2357,7 +2357,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by libostree $as_me 2019.3, which was
+It was created by libostree $as_me 2019.4, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3225,7 +3225,7 @@ fi
# Define the identity of the package.
PACKAGE='libostree'
- VERSION='2019.3'
+ VERSION='2019.4'
# Some tools Automake needs.
@@ -5959,9 +5959,9 @@ test -n "$YACC" || YACC="yacc"
YEAR_VERSION=2019
-RELEASE_VERSION=3
+RELEASE_VERSION=4
-PACKAGE_VERSION=2019.3
+PACKAGE_VERSION=2019.4
if echo "$CFLAGS" | grep -q -E -e '-Werror($| )'; then :
@@ -18833,7 +18833,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by libostree $as_me 2019.3, which was
+This file was extended by libostree $as_me 2019.4, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -18899,7 +18899,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-libostree config.status 2019.3
+libostree config.status 2019.4
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 15c60bb4..cd3cfd10 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl update libostree-released.sym from libostree-devel.sym, and update the check
dnl in test-symbols.sh, and also set is_release_build=yes below. Then make
dnl another post-release commit to bump the version, and set is_release_build=no.
m4_define([year_version], [2019])
-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])
is_release_build=yes
diff --git a/src/boot/ostree-finalize-staged.service b/src/boot/ostree-finalize-staged.service
index e112bc0c..9c4706e8 100644
--- a/src/boot/ostree-finalize-staged.service
+++ b/src/boot/ostree-finalize-staged.service
@@ -26,6 +26,9 @@ DefaultDependencies=no
RequiresMountsFor=/sysroot
After=local-fs.target
Before=basic.target final.target
+# We want to make sure the transaction logs are persisted to disk:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1751272
+After=systemd-journal-flush.service
Conflicts=final.target
[Service]
diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym
index fbcb2d56..ec9eec66 100644
--- a/src/libostree/libostree-released.sym
+++ b/src/libostree/libostree-released.sym
@@ -571,6 +571,10 @@ global:
ostree_kernel_args_to_string;
} LIBOSTREE_2018.9;
+LIBOSTREE_2019.4 {
+ ostree_repo_mark_commit_partial_reason;
+} LIBOSTREE_2019.3;
+
/* NOTE: Only add more content here in release commits! See the
* comments at the top of this file.
*/
diff --git a/src/libostree/ostree-bootconfig-parser.c b/src/libostree/ostree-bootconfig-parser.c
index 25da6657..67f9fb58 100644
--- a/src/libostree/ostree-bootconfig-parser.c
+++ b/src/libostree/ostree-bootconfig-parser.c
@@ -30,7 +30,6 @@ struct _OstreeBootconfigParser
const char *separators;
GHashTable *options;
- GPtrArray *lines;
};
typedef GObjectClass OstreeBootconfigParserClass;
@@ -48,9 +47,6 @@ ostree_bootconfig_parser_clone (OstreeBootconfigParser *self)
{
OstreeBootconfigParser *parser = ostree_bootconfig_parser_new ();
- for (guint i = 0; i < self->lines->len; i++)
- g_ptr_array_add (parser->lines, g_variant_ref (self->lines->pdata[i]));
-
GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v)
g_hash_table_replace (parser->options, g_strdup (k), g_strdup (v));
@@ -84,7 +80,6 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self,
for (char **iter = lines; *iter; iter++)
{
const char *line = *iter;
- char *keyname = "";
if (g_ascii_isalpha (*line))
{
@@ -92,7 +87,6 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self,
items = g_strsplit_set (line, self->separators, 2);
if (g_strv_length (items) == 2 && items[0][0] != '\0')
{
- keyname = items[0];
g_hash_table_insert (self->options, items[0], items[1]);
g_free (items); /* Transfer ownership */
}
@@ -101,7 +95,6 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self,
g_strfreev (items);
}
}
- g_ptr_array_add (self->lines, g_variant_new ("(ss)", keyname, line));
}
self->parsed = TRUE;
@@ -153,34 +146,29 @@ ostree_bootconfig_parser_write_at (OstreeBootconfigParser *self,
GCancellable *cancellable,
GError **error)
{
+ /* Write the fields in a deterministic order, following what is used
+ * in the bootconfig example of the BootLoaderspec document:
+ * https://systemd.io/BOOT_LOADER_SPECIFICATION
+ */
+ const char *fields[] = { "title", "version", "options", "devicetree", "linux", "initrd" };
+ g_autoptr(GHashTable) keys_written = g_hash_table_new (g_str_hash, g_str_equal);
g_autoptr(GString) buf = g_string_new ("");
- g_autoptr(GHashTable) written_overrides = g_hash_table_new (g_str_hash, g_str_equal);
- for (guint i = 0; i < self->lines->len; i++)
+ for (guint i = 0; i < G_N_ELEMENTS (fields); i++)
{
- GVariant *linedata = self->lines->pdata[i];
- const char *key;
- const char *value;
- const char *line;
-
- g_variant_get (linedata, "(&s&s)", &key, &line);
-
- value = g_hash_table_lookup (self->options, key);
- if (value == NULL)
- {
- g_string_append (buf, line);
- g_string_append_c (buf, '\n');
- }
- else
+ const char *key = fields[i];
+ const char *value = g_hash_table_lookup (self->options, key);
+ if (value != NULL)
{
write_key (self, buf, key, value);
- g_hash_table_add (written_overrides, (gpointer)key);
+ g_hash_table_add (keys_written, (gpointer)key);
}
}
+ /* Write unknown fields */
GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v)
{
- if (g_hash_table_lookup (written_overrides, k))
+ if (g_hash_table_lookup (keys_written, k))
continue;
write_key (self, buf, k, v);
}
@@ -210,7 +198,6 @@ ostree_bootconfig_parser_finalize (GObject *object)
OstreeBootconfigParser *self = OSTREE_BOOTCONFIG_PARSER (object);
g_hash_table_unref (self->options);
- g_ptr_array_unref (self->lines);
G_OBJECT_CLASS (ostree_bootconfig_parser_parent_class)->finalize (object);
}
@@ -219,7 +206,6 @@ static void
ostree_bootconfig_parser_init (OstreeBootconfigParser *self)
{
self->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- self->lines = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
}
void
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c
index e7bc9820..0aaebbdb 100644
--- a/src/libostree/ostree-repo-commit.c
+++ b/src/libostree/ostree-repo-commit.c
@@ -1873,6 +1873,57 @@ ensure_txn_refs (OstreeRepo *self)
g_free);
}
+/**
+ * ostree_repo_mark_commit_partial_reason:
+ * @self: Repo
+ * @checksum: Commit SHA-256
+ * @is_partial: Whether or not this commit is partial
+ * @in_state: Reason bitmask for partial commit
+ * @error: Error
+ *
+ * Allows the setting of a reason code for a partial commit. Presently
+ * it only supports setting reason bitmask to
+ * OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL, or
+ * OSTREE_REPO_COMMIT_STATE_NORMAL. This will allow successive ostree
+ * fsck operations to exit properly with an error code if the
+ * repository has been truncated as a result of fsck trying to repair
+ * it.
+ *
+ * Since: 2019.4
+ */
+gboolean
+ostree_repo_mark_commit_partial_reason (OstreeRepo *self,
+ const char *checksum,
+ gboolean is_partial,
+ OstreeRepoCommitState in_state,
+ GError **error)
+{
+ g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum);
+ if (is_partial)
+ {
+ glnx_autofd int fd = openat (self->repo_dir_fd, commitpartial_path,
+ O_EXCL | O_CREAT | O_WRONLY | O_CLOEXEC | O_NOCTTY, 0644);
+ if (fd == -1)
+ {
+ if (errno != EEXIST)
+ return glnx_throw_errno_prefix (error, "open(%s)", commitpartial_path);
+ }
+ else
+ {
+ if (in_state & OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL)
+ if (glnx_loop_write (fd, "f", 1) < 0)
+ return glnx_throw_errno_prefix (error, "write(%s)", commitpartial_path);
+ }
+ }
+ else
+ {
+ if (!ot_ensure_unlinked_at (self->repo_dir_fd, commitpartial_path, 0))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* ostree_repo_mark_commit_partial:
* @self: Repo
@@ -1880,9 +1931,10 @@ ensure_txn_refs (OstreeRepo *self)
* @is_partial: Whether or not this commit is partial
* @error: Error
*
- * Commits in "partial" state do not have all their child objects written. This
- * occurs in various situations, such as during a pull, but also if a "subpath"
- * pull is used, as well as "commit only" pulls.
+ * Commits in the "partial" state do not have all their child objects
+ * written. This occurs in various situations, such as during a pull,
+ * but also if a "subpath" pull is used, as well as "commit only"
+ * pulls.
*
* This function is used by ostree_repo_pull_with_options(); you
* should use this if you are implementing a different type of transport.
@@ -1895,24 +1947,9 @@ ostree_repo_mark_commit_partial (OstreeRepo *self,
gboolean is_partial,
GError **error)
{
- g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (checksum);
- if (is_partial)
- {
- glnx_autofd int fd = openat (self->repo_dir_fd, commitpartial_path,
- O_EXCL | O_CREAT | O_WRONLY | O_CLOEXEC | O_NOCTTY, 0644);
- if (fd == -1)
- {
- if (errno != EEXIST)
- return glnx_throw_errno_prefix (error, "open(%s)", commitpartial_path);
- }
- }
- else
- {
- if (!ot_ensure_unlinked_at (self->repo_dir_fd, commitpartial_path, 0))
- return FALSE;
- }
-
- return TRUE;
+ return ostree_repo_mark_commit_partial_reason (self, checksum, is_partial,
+ OSTREE_REPO_COMMIT_STATE_NORMAL,
+ error);
}
/**
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 3adaa477..ba6e7289 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -385,6 +385,8 @@ check_outstanding_requests_handle_error (OtPullData *pull_data,
GError *error = *errorp;
if (error)
{
+ g_debug ("Request caught error: %s", error->message);
+
if (!pull_data->caught_error)
{
pull_data->caught_error = TRUE;
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index eb652bef..b654aff2 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -3768,10 +3768,19 @@ load_metadata_internal (OstreeRepo *self,
g_autofree char *commitpartial_path = _ostree_get_commitpartial_path (sha256);
*out_state = 0;
- if (!glnx_fstatat_allow_noent (self->repo_dir_fd, commitpartial_path, NULL, 0, error))
+ glnx_autofd int fd = -1;
+ if (!ot_openat_ignore_enoent (self->repo_dir_fd, commitpartial_path, &fd, error))
return FALSE;
- if (errno == 0)
- *out_state |= OSTREE_REPO_COMMIT_STATE_PARTIAL;
+ if (fd != -1)
+ {
+ *out_state |= OSTREE_REPO_COMMIT_STATE_PARTIAL;
+ char reason;
+ if (read (fd, &reason, 1) == 1)
+ {
+ if (reason == 'f')
+ *out_state |= OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL;
+ }
+ }
}
}
else if (self->parent_repo)
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 038bbd41..40d3f773 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -248,6 +248,26 @@ gboolean ostree_repo_write_config (OstreeRepo *self,
GKeyFile *new_config,
GError **error);
+/**
+ * OstreeRepoCommitState:
+ * @OSTREE_REPO_COMMIT_STATE_NORMAL: Commit is complete. This is the default.
+ * (Since: 2017.14.)
+ * @OSTREE_REPO_COMMIT_STATE_PARTIAL: One or more objects are missing from the
+ * local copy of the commit, but metadata is present. (Since: 2015.7.)
+ * @OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL: One or more objects are missing from the
+ * local copy of the commit, due to an fsck --delete. (Since: 2019.4.)
+ *
+ * Flags representing the state of a commit in the local repository, as returned
+ * by ostree_repo_load_commit().
+ *
+ * Since: 2015.7
+ */
+typedef enum {
+ OSTREE_REPO_COMMIT_STATE_NORMAL = 0,
+ OSTREE_REPO_COMMIT_STATE_PARTIAL = (1 << 0),
+ OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL = (1 << 1),
+} OstreeRepoCommitState;
+
/**
* OstreeRepoTransactionStats:
* @metadata_objects_total: The total number of metadata objects
@@ -315,6 +335,13 @@ gboolean ostree_repo_mark_commit_partial (OstreeRepo *self,
gboolean is_partial,
GError **error);
+_OSTREE_PUBLIC
+gboolean ostree_repo_mark_commit_partial_reason (OstreeRepo *self,
+ const char *checksum,
+ gboolean is_partial,
+ OstreeRepoCommitState in_state,
+ GError **error);
+
_OSTREE_PUBLIC
void ostree_repo_transaction_set_refspec (OstreeRepo *self,
const char *refspec,
@@ -526,23 +553,6 @@ gboolean ostree_repo_load_variant_if_exists (OstreeRepo *self,
GVariant **out_variant,
GError **error);
-/**
- * OstreeRepoCommitState:
- * @OSTREE_REPO_COMMIT_STATE_NORMAL: Commit is complete. This is the default.
- * (Since: 2017.14.)
- * @OSTREE_REPO_COMMIT_STATE_PARTIAL: One or more objects are missing from the
- * local copy of the commit, but metadata is present. (Since: 2015.7.)
- *
- * Flags representing the state of a commit in the local repository, as returned
- * by ostree_repo_load_commit().
- *
- * Since: 2015.7
- */
-typedef enum {
- OSTREE_REPO_COMMIT_STATE_NORMAL = 0,
- OSTREE_REPO_COMMIT_STATE_PARTIAL = (1 << 0),
-} OstreeRepoCommitState;
-
_OSTREE_PUBLIC
gboolean ostree_repo_load_commit (OstreeRepo *self,
const char *checksum,
diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c
index 9de5464a..c342d7e0 100644
--- a/src/libostree/ostree-sysroot-deploy.c
+++ b/src/libostree/ostree-sysroot-deploy.c
@@ -1746,10 +1746,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
g_string_append_c (title_key, ':');
g_string_append (title_key, osname);
}
- if (!(deployment_version && *deployment_version))
- {
- g_string_append_printf (title_key, ":%d", ostree_deployment_get_index (deployment));
- }
+
+ g_string_append_printf (title_key, ":%d", ostree_deployment_get_index (deployment));
+
g_string_append_c (title_key, ')');
ostree_bootconfig_parser_set (bootconfig, "title", title_key->str);
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index b3ad2498..2c0c0546 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -959,7 +959,18 @@ ostree_sysroot_load_if_changed (OstreeSysroot *self,
}
if (self->root_is_ostree_booted && !self->booted_deployment)
- return glnx_throw (error, "Unexpected state: /run/ostree-booted found and in / sysroot but not in a booted deployment");
+ {
+ if (!glnx_fstatat_allow_noent (self->sysroot_fd, "boot/loader", NULL, AT_SYMLINK_NOFOLLOW, error))
+ return FALSE;
+ if (errno == ENOENT)
+ {
+ return glnx_throw (error, "Unexpected state: /run/ostree-booted found, but no /boot/loader directory");
+ }
+ else
+ {
+ return glnx_throw (error, "Unexpected state: /run/ostree-booted found and in / sysroot, but bootloader entry not found");
+ }
+ }
if (!_ostree_sysroot_reload_staged (self, error))
return FALSE;
diff --git a/src/libostree/ostree-version.h b/src/libostree/ostree-version.h
index 82a50373..ebb38d0e 100644
--- a/src/libostree/ostree-version.h
+++ b/src/libostree/ostree-version.h
@@ -43,7 +43,7 @@
*
* Since: 2017.4
*/
-#define OSTREE_RELEASE_VERSION (3)
+#define OSTREE_RELEASE_VERSION (4)
/**
* OSTREE_VERSION
@@ -52,7 +52,7 @@
*
* Since: 2017.4
*/
-#define OSTREE_VERSION (2019.3)
+#define OSTREE_VERSION (2019.4)
/**
* OSTREE_VERSION_S:
@@ -62,7 +62,7 @@
*
* Since: 2017.4
*/
-#define OSTREE_VERSION_S "2019.3"
+#define OSTREE_VERSION_S "2019.4"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))
diff --git a/src/libotutil/ot-gpg-utils.c b/src/libotutil/ot-gpg-utils.c
index cf5ce3ea..743d941e 100644
--- a/src/libotutil/ot-gpg-utils.c
+++ b/src/libotutil/ot-gpg-utils.c
@@ -25,6 +25,7 @@
#include
+#include
#include "libglnx.h"
/* Like glnx_throw_errno_prefix, but takes @gpg_error */
@@ -438,28 +439,102 @@ ot_gpgme_new_ctx (const char *homedir,
return g_steal_pointer (&context);
}
+static gboolean
+get_gnupg_version (guint *major,
+ guint *minor,
+ guint *patch)
+{
+ g_return_val_if_fail (major != NULL, FALSE);
+ g_return_val_if_fail (minor != NULL, FALSE);
+ g_return_val_if_fail (patch != NULL, FALSE);
+
+ gpgme_engine_info_t info;
+ gpgme_error_t err = gpgme_get_engine_info (&info);
+ if (err != GPG_ERR_NO_ERROR)
+ {
+ g_debug ("Failed to get GPGME engine info: %s: %s",
+ gpgme_strsource (err), gpgme_strerror (err));
+ return FALSE;
+ }
+
+ const char *gnupg_version = NULL;
+ for (; info != NULL; info = info->next)
+ {
+ if (info->protocol == GPGME_PROTOCOL_OpenPGP)
+ {
+ gnupg_version = info->version;
+ break;
+ }
+ }
+
+ if (gnupg_version == NULL)
+ {
+ g_debug ("Could not determine GnuPG version");
+ return FALSE;
+ }
+
+ g_auto(GStrv) parts = g_strsplit (gnupg_version, ".", 4);
+ if (g_strv_length (parts) < 3)
+ {
+ g_debug ("Less than 3 components in GnuPG version \"%s\"", gnupg_version);
+ return FALSE;
+ }
+
+ *major = g_ascii_strtoull (parts[0], NULL, 10);
+ *minor = g_ascii_strtoull (parts[1], NULL, 10);
+ *patch = g_ascii_strtoull (parts[2], NULL, 10);
+
+ return TRUE;
+}
+
void
ot_gpgme_kill_agent (const char *homedir)
{
g_return_if_fail (homedir != NULL);
+ /* If gnupg is at least 2.1.17, gpg-agent will exit when the homedir
+ * is deleted.
+ */
+ guint gnupg_major = 0, gnupg_minor = 0, gnupg_patch = 0;
+ if (get_gnupg_version (&gnupg_major, &gnupg_minor, &gnupg_patch))
+ {
+ if ((gnupg_major > 2) ||
+ (gnupg_major == 2 && gnupg_minor > 1) ||
+ (gnupg_major == 2 && gnupg_minor == 1 && gnupg_patch >= 17))
+ {
+ /* Note early return */
+ g_debug ("GnuPG >= 2.1.17, skipping gpg-agent cleanup in %s", homedir);
+ return;
+ }
+ }
+
/* Run gpg-connect-agent killagent /bye */
+ g_autoptr(GPtrArray) argv = g_ptr_array_new ();
+ g_ptr_array_add (argv, "gpg-connect-agent");
+ g_ptr_array_add (argv, "--homedir");
+ g_ptr_array_add (argv, (gpointer)homedir);
+ g_ptr_array_add (argv, "killagent");
+ g_ptr_array_add (argv, "/bye");
+ g_ptr_array_add (argv, NULL);
+
g_autoptr(GError) local_error = NULL;
- g_autoptr(GSubprocess) proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_SILENCE,
- &local_error,
- "gpg-connect-agent",
- "--homedir",
- homedir,
- "killagent",
- "/bye",
- NULL);
- if (proc == NULL) {
- g_debug ("Spawning gpg-connect-agent failed: %s", local_error->message);
- return;
- }
- if (!g_subprocess_wait_check (proc, NULL, &local_error)) {
- g_debug ("Killing GPG agent with gpg-connect-agent failed: %s",
- local_error->message);
- return;
- }
+ GSpawnFlags flags = G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL;
+ gint proc_status = 0;
+ g_autofree gchar *proc_stderr = NULL;
+ g_debug ("Killing gpg-agent in %s", homedir);
+ if (!g_spawn_sync (NULL, (char **)argv->pdata, NULL, flags, NULL, NULL,
+ NULL, &proc_stderr, &proc_status, &local_error))
+ {
+ g_debug ("Spawning gpg-connect-agent failed: %s", local_error->message);
+ return;
+ }
+ if (!g_spawn_check_exit_status (proc_status, &local_error))
+ {
+ /* Dump out stderr on failures */
+ g_printerr ("%s", proc_stderr);
+
+ g_debug ("Killing GPG agent with gpg-connect-agent failed: %s",
+ local_error->message);
+ return;
+ }
}
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index a7ecd3d0..5ad3bf38 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -127,7 +127,7 @@ fsck_one_object (OstreeRepo *repo,
if ((state & OSTREE_REPO_COMMIT_STATE_PARTIAL) == 0)
{
g_printerr ("Marking commit as partial: %s\n", parent_commit);
- if (!ostree_repo_mark_commit_partial (repo, parent_commit, TRUE, error))
+ if (!ostree_repo_mark_commit_partial_reason (repo, parent_commit, TRUE, OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL, error))
return FALSE;
}
}
@@ -302,6 +302,7 @@ ostree_builtin_fsck (int argc, char **argv, OstreeCommandInvocation *invocation,
opt_verify_bindings = TRUE;
guint n_partial = 0;
+ guint n_fsck_partial = 0;
g_hash_table_iter_init (&hash_iter, objects);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
@@ -410,7 +411,11 @@ ostree_builtin_fsck (int argc, char **argv, OstreeCommandInvocation *invocation,
}
if (commitstate & OSTREE_REPO_COMMIT_STATE_PARTIAL)
- n_partial++;
+ {
+ n_partial++;
+ if (commitstate & OSTREE_REPO_COMMIT_STATE_FSCK_PARTIAL)
+ n_fsck_partial++;
+ }
else
g_hash_table_add (commits, g_variant_ref (serialized_key));
}
@@ -450,5 +455,8 @@ ostree_builtin_fsck (int argc, char **argv, OstreeCommandInvocation *invocation,
if (found_corruption)
return glnx_throw (error, "Repository corruption encountered");
+ if (n_fsck_partial > 0)
+ return glnx_throw (error, "%u partial commits from fsck-detected corruption", n_partial);
+
return TRUE;
}
diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c
index 3d6e7833..33c46ff4 100644
--- a/src/switchroot/ostree-prepare-root.c
+++ b/src/switchroot/ostree-prepare-root.c
@@ -273,6 +273,9 @@ main(int argc, char *argv[])
if (mount (".", root_mountpoint, NULL, MS_MOVE, NULL) < 0)
err (EXIT_FAILURE, "failed to MS_MOVE %s to %s", deploy_path, root_mountpoint);
+
+ if (rmdir ("/sysroot.tmp") < 0)
+ err (EXIT_FAILURE, "couldn't remove temporary sysroot /sysroot.tmp");
}
/* The /sysroot mount needs to be private to avoid having a mount for e.g. /var/cache
diff --git a/tests/admin-test.sh b/tests/admin-test.sh
index 0defebc0..11b9ea14 100644
--- a/tests/admin-test.sh
+++ b/tests/admin-test.sh
@@ -290,10 +290,10 @@ echo "ok upgrade with multiple kernel args"
os_repository_new_commit
${CMD_PREFIX} ostree admin upgrade --os=testos
-assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 ${version} (ostree:testos)$"
+assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 ${version} (ostree:testos:0)$"
os_repository_new_commit 0 0 testos/buildmaster/x86_64-runtime 42
${CMD_PREFIX} ostree admin upgrade --os=testos
-assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 (ostree:testos)$"
+assert_file_has_content sysroot/boot/loader/entries/ostree-4-testos.conf "^title TestOS 42 (ostree:testos:0)$"
echo "ok no duplicate version strings in title"
diff --git a/tests/test-fsck-delete.sh b/tests/test-fsck-delete.sh
new file mode 100755
index 00000000..3e7347bb
--- /dev/null
+++ b/tests/test-fsck-delete.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+#
+# Copyright © 2019 Wind River Systems, Inc.
+#
+# SPDX-License-Identifier: LGPL-2.0+
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -euo pipefail
+
+. $(dirname $0)/libtest.sh
+
+echo '1..6'
+
+cd ${test_tmpdir}
+
+rm -rf ./f1
+mkdir -p ./f1
+${CMD_PREFIX} ostree --repo=./f1 init --mode=archive-z2
+rm -rf ./trial
+mkdir -p ./trial
+echo test > ./trial/test
+${CMD_PREFIX} ostree --repo=./f1 commit --tree=dir=./trial --skip-if-unchanged --branch=exp1 --subject="test Commit"
+
+rm -rf ./f2
+mkdir -p ./f2
+${CMD_PREFIX} ostree --repo=./f2 init --mode=archive-z2
+${CMD_PREFIX} ostree --repo=./f2 pull-local ./f1
+echo "ok 1 fsck-pre-commit"
+
+file=`find ./f2 |grep objects |grep \\.file |tail -1 `
+rm $file
+echo whoops > $file
+
+# First check for corruption
+if ${CMD_PREFIX} ostree fsck --repo=./f2 > fsck 2> fsck-error; then
+ assert_not_reached "fsck did not fail"
+fi
+assert_file_has_content fsck "^Validating refs\.\.\.$"
+assert_file_has_content fsck-error "^error: In commits"
+
+echo "ok 2 fsck-fail-check"
+
+# Fix the corruption
+if ${CMD_PREFIX} ostree fsck --delete --repo=./f2 > fsck 2> fsck-error; then
+ assert_not_reached "fsck did not fail"
+fi
+assert_file_has_content fsck "^Validating refs\.\.\.$"
+assert_file_has_content fsck-error "^In commits"
+
+echo "ok 3 fsck-delete-check"
+
+# Check that fsck still exits with non-zero after corruption fix
+if ${CMD_PREFIX} ostree fsck --repo=./f2 > fsck 2> fsck-error; then
+ assert_not_reached "fsck did not fail"
+fi
+assert_file_has_content fsck "^Validating refs\.\.\.$"
+assert_file_has_content fsck-error "^error: 1"
+
+echo "ok 4 fsck-post-delete-check"
+
+${CMD_PREFIX} ostree --repo=./f2 pull-local ./f1 > /dev/null
+echo "ok 5 fsck-repair"
+
+if ! ${CMD_PREFIX} ostree fsck --repo=./f2 > fsck 2> fsck-error; then
+ assert_not_reached "fsck failed when it should have passed"
+fi
+assert_file_has_content fsck "^Validating refs\.\.\.$"
+assert_file_empty fsck-error
+echo "ok 6 fsck-good"
diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh
index 5ec06d72..32285bdc 100755
--- a/tests/test-symbols.sh
+++ b/tests/test-symbols.sh
@@ -54,7 +54,7 @@ echo 'ok documented symbols'
# ONLY update this checksum in release commits!
cat > released-sha256.txt <