From 3ca1035e989ae2efec3103bd70128ff34aa515aa Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 24 Apr 2019 16:14:24 -0400 Subject: [PATCH 01/62] Post-release version bump Closes: #1844 Approved by: rfairley --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e6e145db..3f125638 100644 --- a/configure.ac +++ b/configure.ac @@ -4,10 +4,10 @@ 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], [2]) +m4_define([release_version], [3]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=yes +is_release_build=no AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) From b35f337dc7c48a15546148d984466fc97731c141 Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Sat, 4 May 2019 21:59:52 +0000 Subject: [PATCH 02/62] docs: fix switchroot source link This change updates the switchroot source relative url to an absolute url so that it works from the readthedocs service. This change also removes redundant switchroot.sh reference. Closes: #1849 Approved by: cgwalters --- docs/manual/adapting-existing.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/manual/adapting-existing.md b/docs/manual/adapting-existing.md index f73c2264..4353db93 100644 --- a/docs/manual/adapting-existing.md +++ b/docs/manual/adapting-existing.md @@ -83,8 +83,9 @@ After these steps, systemd switches root. If you are not using dracut or systemd, using OSTree should still be possible, but you will have to write the integration code. See the -existing sources in [src/switchroot](/src/switchroot) as a reference, -as well as [src/switchroot/switchroot.sh](/src/switchroot/switchroot.sh). +existing sources in +[src/switchroot](https://github.com/ostreedev/ostree/tree/master/src/switchroot) +as a reference. Patches to support other initramfs technologies and init systems, if sufficiently clean, will likely be accepted upstream. From 27b7d468e6a00628d5eb3af1bc3968a0ea798f41 Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Sun, 5 May 2019 03:33:35 +0000 Subject: [PATCH 03/62] prepare-root: remove ignored MS_MGC_VAL flag Since Linux 2.4 this is no longer required and the flag is ignored. Closes: #1851 Approved by: cgwalters --- src/switchroot/ostree-prepare-root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 15d49963..3d6e7833 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -182,7 +182,7 @@ main(int argc, char *argv[]) mount_var = true; /* Link to the deployment's /var */ - if (mount_var && mount ("../../var", "var", NULL, MS_MGC_VAL|MS_BIND, NULL) < 0) + if (mount_var && mount ("../../var", "var", NULL, MS_BIND, NULL) < 0) err (EXIT_FAILURE, "failed to bind mount ../../var to var"); char srcpath[PATH_MAX]; From 82eccad945a30a404ffb61d22d2350a775c8b511 Mon Sep 17 00:00:00 2001 From: Tristan Cacqueray Date: Sun, 5 May 2019 03:31:52 +0000 Subject: [PATCH 04/62] docs: fix missing as typo This change fixes a typo in the adapting-existing doc. Closes: #1850 Approved by: cgwalters --- docs/manual/adapting-existing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manual/adapting-existing.md b/docs/manual/adapting-existing.md index 4353db93..14b36a88 100644 --- a/docs/manual/adapting-existing.md +++ b/docs/manual/adapting-existing.md @@ -91,7 +91,7 @@ Patches to support other initramfs technologies and init systems, if sufficiently clean, will likely be accepted upstream. A further specific note regarding `sysvinit`: OSTree used to support -recording device files such the `/dev/initctl` FIFO, but no longer +recording device files such as the `/dev/initctl` FIFO, but no longer does. It's recommended to just patch your initramfs to create this at boot. From f31d77969085f549cedbeec70367afdcf6e02393 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Wed, 8 May 2019 20:23:17 +0100 Subject: [PATCH 05/62] lib: mmap the summary to reduce RSS in clients Closes: #1855 Closes: #1856 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 48935523..7ae992ad 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -2868,7 +2868,7 @@ _ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self, if (prev_fd < 0) return TRUE; /* Note early return */ - g_autoptr(GBytes) old_sig_contents = glnx_fd_readall_bytes (prev_fd, cancellable, error); + g_autoptr(GBytes) old_sig_contents = ot_fd_readall_or_mmap (prev_fd, 0, error); if (!old_sig_contents) return FALSE; From 01c471a6f333a0ef032fa85c30fe0f6a990ed9af Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Fri, 17 May 2019 17:35:12 +0200 Subject: [PATCH 06/62] README: update link to ostree-rs Closes: #1860 Approved by: jlebon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa7b23e0..a5773ca0 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ write higher level manual bindings on top; this is more common for statically compiled languages. Here's a list of such bindings: - [ostree-go](https://github.com/ostreedev/ostree-go/) - - [rust-libostree](https://gitlab.com/fkrull/rust-libostree/) + - [ostree-rs](https://gitlab.com/fkrull/ostree-rs/) Building -------- From 4aeba118b003a515f60a9c8ee866c5b169168510 Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Fri, 17 May 2019 21:33:06 +0200 Subject: [PATCH 07/62] lib: fix doc comment for ostree_repo_get_min_free_space_bytes Closes: #1861 Approved by: cgwalters --- src/libostree/ostree-repo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 9ffa103f..9515a110 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3466,7 +3466,7 @@ ostree_repo_get_mode (OstreeRepo *self) } /** - * ostree_repo_get_min_free_space: + * ostree_repo_get_min_free_space_bytes: * @self: Repo * @out_reserved_bytes: (out): Location to store the result * @error: Return location for a #GError @@ -3576,7 +3576,7 @@ list_loose_objects_at (OstreeRepo *self, if (objtype != OSTREE_OBJECT_TYPE_COMMIT) continue; - /* commit checksum does not match "starting with", do not add to array */ + /* commit checksum does not match "starting with", do not add to array */ if (!g_str_has_prefix (buf, commit_starting_with)) continue; } @@ -4446,7 +4446,7 @@ ostree_repo_load_variant (OstreeRepo *self, */ gboolean ostree_repo_load_commit (OstreeRepo *self, - const char *checksum, + const char *checksum, GVariant **out_variant, OstreeRepoCommitState *out_state, GError **error) @@ -6098,10 +6098,10 @@ ostree_repo_get_default_repo_finders (OstreeRepo *self) /** * ostree_repo_get_bootloader: * @self: an #OstreeRepo - * + * * Get the bootloader configured. See the documentation for the * "sysroot.bootloader" config key. - * + * * Returns: bootloader configuration for the sysroot * Since: 2019.2 */ From e607e79f4eacf78d479c93b14253a33e4851eeee Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Fri, 17 May 2019 22:24:52 +0200 Subject: [PATCH 08/62] lib: add minimum version to various symbols based on libostree-released.sym Closes: #1861 Approved by: cgwalters --- src/libostree/ostree-core.c | 32 ++++++++++++++++-------- src/libostree/ostree-deployment.c | 10 ++++++++ src/libostree/ostree-diff.c | 14 ++++++----- src/libostree/ostree-gpg-verify-result.c | 2 ++ src/libostree/ostree-gpg-verify-result.h | 5 ++++ src/libostree/ostree-mutable-tree.c | 10 ++++++-- src/libostree/ostree-repo-checkout.c | 8 ++++-- src/libostree/ostree-repo-commit.c | 2 ++ src/libostree/ostree-repo-prune.c | 2 ++ src/libostree/ostree-repo-pull.c | 6 +++-- src/libostree/ostree-repo-refs.c | 4 +++ src/libostree/ostree-repo.c | 21 ++++++++++++++++ src/libostree/ostree-sepolicy.c | 6 ++++- src/libostree/ostree-sysroot-deploy.c | 4 +++ src/libostree/ostree-sysroot.c | 13 ++++++++++ 15 files changed, 115 insertions(+), 24 deletions(-) diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 4e1a67e0..36539698 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -485,6 +485,8 @@ _ostree_raw_file_to_archive_stream (GInputStream *input, * * Convert from a "bare" file representation into an * OSTREE_OBJECT_TYPE_FILE stream suitable for ostree pull. + * + * Since: 2016.6 */ gboolean ostree_raw_file_to_archive_z2_stream (GInputStream *input, @@ -581,7 +583,7 @@ ostree_raw_file_to_content_stream (GInputStream *input, * @input_length: Length of stream * @trusted: If %TRUE, assume the content has been validated * @out_input: (out): The raw file content stream - * @out_file_info: (out): Normal metadata + * @out_file_info: (out): Normal metadata * @out_xattrs: (out): Extended attributes * @cancellable: Cancellable * @error: Error @@ -680,7 +682,7 @@ ostree_content_stream_parse (gboolean compressed, * @path: Subpath * @trusted: If %TRUE, assume the content has been validated * @out_input: (out): The raw file content stream - * @out_file_info: (out): Normal metadata + * @out_file_info: (out): Normal metadata * @out_xattrs: (out): Extended attributes * @cancellable: Cancellable * @error: Error @@ -730,7 +732,7 @@ ostree_content_file_parse_at (gboolean compressed, * @content_path: Path to file containing content * @trusted: If %TRUE, assume the content has been validated * @out_input: (out): The raw file content stream - * @out_file_info: (out): Normal metadata + * @out_file_info: (out): Normal metadata * @out_xattrs: (out): Extended attributes * @cancellable: Cancellable * @error: Error @@ -1068,7 +1070,7 @@ checksum_file_async_data_free (gpointer datap) g_free (data->csum); g_free (data); } - + /** * ostree_checksum_file_async: * @f: File path @@ -1098,7 +1100,7 @@ ostree_checksum_file_async (GFile *f, res = g_simple_async_result_new (G_OBJECT (f), callback, user_data, ostree_checksum_file_async); g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)checksum_file_async_data_free); - + g_simple_async_result_run_in_thread (res, checksum_file_async_thread, io_priority, cancellable); g_object_unref (res); } @@ -1323,7 +1325,7 @@ ostree_hash_object_name (gconstpointer a) const char *checksum; OstreeObjectType objtype; gint objtype_int; - + ostree_object_name_deserialize (variant, &checksum, &objtype); objtype_int = (gint) objtype; return g_str_hash (checksum) + g_int_hash (&objtype_int); @@ -1472,6 +1474,8 @@ ostree_checksum_to_bytes_v (const char *checksum) * @checksum: An ASCII checksum * * Returns: (transfer full) (array fixed-size=32): Binary version of @checksum. + * + * Since: 2016.8 */ guchar * ostree_checksum_b64_to_bytes (const char *checksum) @@ -1571,6 +1575,8 @@ ostree_checksum_from_bytes_v (GVariant *csum_v) * * The "modified" term refers to the fact that instead of '/', the '_' * character is used. + * + * Since: 2016.8 */ char * ostree_checksum_b64_from_bytes (const guchar *csum) @@ -1849,7 +1855,7 @@ _ostree_get_relative_static_delta_path (const char *from, g_string_append_c (ret, '/'); g_string_append (ret, target); } - + return g_string_free (ret, FALSE); } @@ -2174,7 +2180,7 @@ _ostree_verify_metadata_object (OstreeObjectType objtype, * ostree_validate_structureof_commit: * @commit: A commit object, %OSTREE_OBJECT_TYPE_COMMIT * @error: Error - * + * * Use this to validate the basic structure of @commit, independent of * any other objects it references. * @@ -2214,7 +2220,7 @@ ostree_validate_structureof_commit (GVariant *commit, * ostree_validate_structureof_dirtree: * @dirtree: A dirtree object, %OSTREE_OBJECT_TYPE_DIR_TREE * @error: Error - * + * * Use this to validate the basic structure of @dirtree, independent of * any other objects it references. * @@ -2326,7 +2332,7 @@ ostree_validate_structureof_file_mode (guint32 mode, * ostree_validate_structureof_dirmeta: * @dirmeta: A dirmeta object, %OSTREE_OBJECT_TYPE_DIR_META * @error: Error - * + * * Use this to validate the basic structure of @dirmeta. * * Returns: %TRUE if @dirmeta is structurally valid @@ -2340,7 +2346,7 @@ ostree_validate_structureof_dirmeta (GVariant *dirmeta, if (!validate_variant (dirmeta, OSTREE_DIRMETA_GVARIANT_FORMAT, error)) return FALSE; - g_variant_get_child (dirmeta, 2, "u", &mode); + g_variant_get_child (dirmeta, 2, "u", &mode); mode = GUINT32_FROM_BE (mode); if (!S_ISDIR (mode)) @@ -2395,6 +2401,8 @@ ostree_commit_get_timestamp (GVariant *commit_variant) * root "dirmeta" checksum (both in binary form, not hexadecimal). * * Returns: (nullable): A SHA-256 hex string, or %NULL if @commit_variant is not well-formed + * + * Since: 2018.2 */ gchar * ostree_commit_get_content_checksum (GVariant *commit_variant) @@ -2513,6 +2521,8 @@ _ostree_get_default_sysroot_path (void) * @required_release: Release version required * * Returns: %TRUE if current libostree has at least the requested version, %FALSE otherwise + * + * Since: 2017.4 */ gboolean ostree_check_version (guint required_year, guint required_release) diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 820c2632..6532a973 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -302,6 +302,11 @@ ostree_deployment_get_origin_relpath (OstreeDeployment *self) ostree_deployment_get_deployserial (self)); } +/** + * ostree_deployment_unlocked_state_to_string: + * + * Since: 2016.4 + */ const char * ostree_deployment_unlocked_state_to_string (OstreeDeploymentUnlockedState state) { @@ -317,6 +322,11 @@ ostree_deployment_unlocked_state_to_string (OstreeDeploymentUnlockedState state) g_assert_not_reached (); } +/** + * ostree_deployment_get_unlocked: + * + * Since: 2016.4 + */ OstreeDeploymentUnlockedState ostree_deployment_get_unlocked (OstreeDeployment *self) { diff --git a/src/libostree/ostree-diff.c b/src/libostree/ostree-diff.c index 92b0227c..da018db4 100644 --- a/src/libostree/ostree-diff.c +++ b/src/libostree/ostree-diff.c @@ -239,6 +239,8 @@ ostree_diff_dirs (OstreeDiffFlags flags, * * Compute the difference between directory @a and @b as 3 separate * sets of #OstreeDiffItem in @modified, @removed, and @added. + * + * Since: 2017.4 */ gboolean ostree_diff_dirs_with_options (OstreeDiffFlags flags, @@ -305,7 +307,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, { OstreeRepoFile *a_repof = (OstreeRepoFile*) a; OstreeRepoFile *b_repof = (OstreeRepoFile*) b; - + if (strcmp (ostree_repo_file_tree_get_contents_checksum (a_repof), ostree_repo_file_tree_get_contents_checksum (b_repof)) == 0) { @@ -317,7 +319,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, g_clear_object (&child_a_info); g_clear_object (&child_b_info); - dir_enum = g_file_enumerate_children (a, OSTREE_GIO_FAST_QUERYINFO, + dir_enum = g_file_enumerate_children (a, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!dir_enum) @@ -368,7 +370,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, { OstreeDiffItem *diff_item = diff_item_new (child_a, child_a_info, child_b, child_b_info, NULL, NULL); - + g_ptr_array_add (modified, diff_item); } else @@ -378,7 +380,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, if (!diff_files (flags, child_a, child_a_info, child_b, child_b_info, &diff_item, cancellable, error)) goto out; - + if (diff_item) g_ptr_array_add (modified, diff_item); /* Transfer ownership */ @@ -391,7 +393,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, } } } - + g_clear_object (&child_a_info); } if (temp_error != NULL) @@ -401,7 +403,7 @@ ostree_diff_dirs_with_options (OstreeDiffFlags flags, } g_clear_object (&dir_enum); - dir_enum = g_file_enumerate_children (b, OSTREE_GIO_FAST_QUERYINFO, + dir_enum = g_file_enumerate_children (b, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!dir_enum) diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index e3c5edec..2e69e2f9 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -695,6 +695,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, * * Returns: %TRUE if @result was not %NULL and had at least one * signature from trusted keyring, otherwise %FALSE + * + * Since: 2016.6 */ gboolean ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result, diff --git a/src/libostree/ostree-gpg-verify-result.h b/src/libostree/ostree-gpg-verify-result.h index fc1fe991..0a77ec53 100644 --- a/src/libostree/ostree-gpg-verify-result.h +++ b/src/libostree/ostree-gpg-verify-result.h @@ -161,6 +161,11 @@ typedef enum { OSTREE_GPG_ERROR_MISSING_KEY, } OstreeGpgError; +/** + * ostree_gpg_error_quark: + * + * Since: 2017.10 + */ _OSTREE_PUBLIC GQuark ostree_gpg_error_quark (void); #define OSTREE_GPG_ERROR (ostree_gpg_error_quark ()) diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c index f6577210..a213fd4a 100644 --- a/src/libostree/ostree-mutable-tree.c +++ b/src/libostree/ostree-mutable-tree.c @@ -331,6 +331,8 @@ ostree_mutable_tree_replace_file (OstreeMutableTree *self, * @error: a #GError * * Remove the file or subdirectory named @name from the mutable tree @self. + * + * Since: 2018.9 */ gboolean ostree_mutable_tree_remove (OstreeMutableTree *self, @@ -494,6 +496,8 @@ const char empty_tree_csum[] = "6e340b9cffb37a989ca544e6bb780a2c78901d3fb3373876 * This function enables optimisations when composing trees. The provided * checksums are not loaded or checked when this function is called. Instead * the contents will be loaded only when needed. + * + * Since: 2018.7 */ gboolean ostree_mutable_tree_fill_empty_from_dirtree (OstreeMutableTree *self, @@ -585,7 +589,7 @@ ostree_mutable_tree_walk (OstreeMutableTree *self, /** * ostree_mutable_tree_get_subdirs: * @self: - * + * * Returns: (transfer none) (element-type utf8 OstreeMutableTree): All children directories */ GHashTable * @@ -598,7 +602,7 @@ ostree_mutable_tree_get_subdirs (OstreeMutableTree *self) /** * ostree_mutable_tree_get_files: * @self: - * + * * Returns: (transfer none) (element-type utf8 utf8): All children files (the value is a checksum) */ GHashTable * @@ -654,6 +658,8 @@ ostree_mutable_tree_new (void) * and checksums. The data will be loaded from the repo lazily as needed. * * Returns: (transfer full): A new tree + * + * Since: 2018.7 */ OstreeMutableTree * ostree_mutable_tree_new_from_checksum (OstreeRepo *repo, diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index e190a14a..49ec995f 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -771,7 +771,7 @@ checkout_one_file_at (OstreeRepo *repo, */ g_mutex_lock (&repo->cache_lock); { - gpointer key = GUINT_TO_POINTER ((g_ascii_xdigit_value (checksum[0]) << 4) + + gpointer key = GUINT_TO_POINTER ((g_ascii_xdigit_value (checksum[0]) << 4) + g_ascii_xdigit_value (checksum[1])); if (repo->updated_uncompressed_dirs == NULL) repo->updated_uncompressed_dirs = g_hash_table_new (NULL, NULL); @@ -1321,6 +1321,8 @@ ostree_repo_checkout_tree_at (OstreeRepo *self, * Note in addition that unlike ostree_repo_checkout_tree(), the * default is not to use the repository-internal uncompressed objects * cache. + * + * Since: 2016.8 */ gboolean ostree_repo_checkout_at (OstreeRepo *self, @@ -1391,6 +1393,8 @@ ostree_repo_checkout_at (OstreeRepo *self, * * Note that cache does *not* have its refcount incremented - the lifetime of * @cache must be equal to or greater than that of @opts. + * + * Since: 2017.13 */ void ostree_repo_checkout_at_options_set_devino (OstreeRepoCheckoutAtOptions *opts, @@ -1418,7 +1422,7 @@ devino_equal (gconstpointer a, /** * ostree_repo_devino_cache_new: - * + * * OSTree has support for pairing ostree_repo_checkout_tree_at() using * hardlinks in combination with a later * ostree_repo_write_directory_to_mtree() using a (normally modified) diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index f44446ca..e7bc9820 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -2065,6 +2065,8 @@ ostree_repo_set_ref_immediate (OstreeRepo *self, * @error: GError * * Like ostree_repo_set_ref_immediate(), but creates an alias. + * + * Since: 2017.10 */ gboolean ostree_repo_set_alias_ref_immediate (OstreeRepo *self, diff --git a/src/libostree/ostree-repo-prune.c b/src/libostree/ostree-repo-prune.c index 7ab9dc8d..0b953628 100644 --- a/src/libostree/ostree-repo-prune.c +++ b/src/libostree/ostree-repo-prune.c @@ -473,6 +473,8 @@ ostree_repo_prune (OstreeRepo *self, * statistics on objects that would be deleted, without actually deleting them. * * Locking: exclusive + * + * Since: 2017.1 */ gboolean ostree_repo_prune_from_reachable (OstreeRepo *self, diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 7ae992ad..bb7bc02b 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1063,7 +1063,7 @@ content_fetch_on_write_complete (GObject *object, static void content_fetch_on_complete (GObject *object, GAsyncResult *result, - gpointer user_data) + gpointer user_data) { OstreeFetcher *fetcher = (OstreeFetcher *)object; FetchObjectData *fetch_data = user_data; @@ -1167,7 +1167,7 @@ on_metadata_written (GObject *object, g_autofree guchar *csum = NULL; g_autofree char *stringified_object = NULL; - if (!ostree_repo_write_metadata_finish ((OstreeRepo*)object, result, + if (!ostree_repo_write_metadata_finish ((OstreeRepo*)object, result, &csum, error)) goto out; @@ -6103,6 +6103,8 @@ ostree_repo_pull_from_remotes_finish (OstreeRepo *self, * means return errors without retrying * * Returns: %TRUE on success, %FALSE on failure + * + * Since: 2016.6 */ gboolean ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, diff --git a/src/libostree/ostree-repo-refs.c b/src/libostree/ostree-repo-refs.c index c512787a..536a763a 100644 --- a/src/libostree/ostree-repo-refs.c +++ b/src/libostree/ostree-repo-refs.c @@ -482,6 +482,8 @@ ostree_repo_resolve_rev (OstreeRepo *self, * * The flag %OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY is implied so * using it has no effect. + * + * Since: 2016.7 */ gboolean ostree_repo_resolve_rev_ext (OstreeRepo *self, @@ -856,6 +858,8 @@ ostree_repo_list_refs (OstreeRepo *self, * @out_all_refs will be returned as a mapping from refspecs (including the * remote name) to checksums. Differently from ostree_repo_list_refs(), the * @refspec_prefix will not be removed from the refspecs in the hash table. + * + * Since: 2016.4 */ gboolean ostree_repo_list_refs_ext (OstreeRepo *self, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 9515a110..3238e429 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -786,6 +786,8 @@ _ostree_repo_remote_name_is_file (const char *remote_name) * option name. If an error is returned, @out_value will be set to %NULL. * * Returns: %TRUE on success, otherwise %FALSE with @error set + * + * Since: 2016.5 */ gboolean ostree_repo_get_remote_option (OstreeRepo *self, @@ -864,6 +866,8 @@ ostree_repo_get_remote_option (OstreeRepo *self, * to %NULL. * * Returns: %TRUE on success, otherwise %FALSE with @error set + * + * Since: 2016.5 */ gboolean ostree_repo_get_remote_list_option (OstreeRepo *self, @@ -939,6 +943,8 @@ ostree_repo_get_remote_list_option (OstreeRepo *self, * error is returned, @out_value will be set to %FALSE. * * Returns: %TRUE on success, otherwise %FALSE with @error set + * + * Since: 2016.5 */ gboolean ostree_repo_get_remote_boolean_option (OstreeRepo *self, @@ -1255,6 +1261,8 @@ repo_open_at_take_fd (int *dfd, * already extant repository. If you want to create one, use ostree_repo_create_at(). * * Returns: (transfer full): An accessor object for an OSTree repository located at @dfd + @path + * + * Since: 2017.10 */ OstreeRepo* ostree_repo_open_at (int dfd, @@ -2570,6 +2578,8 @@ ostree_repo_create (OstreeRepo *self, * - collection-id: s: Set as collection ID in repo/config (Since 2017.9) * * Returns: (transfer full): A new OSTree repository reference + * + * Since: 2017.10 */ OstreeRepo * ostree_repo_create_at (int dfd, @@ -3149,6 +3159,8 @@ reload_sysroot_config (OstreeRepo *self, * * By default, an #OstreeRepo will cache the remote configuration and its * own repo/config data. This API can be used to reload it. + * + * Since: 2017.2 */ gboolean ostree_repo_reload_config (OstreeRepo *self, @@ -3313,6 +3325,8 @@ ostree_repo_set_disable_fsync (OstreeRepo *self, * per-remote summary caches. Setting this manually is useful when * doing operations on a system repo as a user because you don't have * write permissions in the repo, where the cache is normally stored. + * + * Since: 2016.5 */ gboolean ostree_repo_set_cache_dir (OstreeRepo *self, @@ -3394,6 +3408,7 @@ ostree_repo_get_path (OstreeRepo *self) * repository (to see whether a ref was written). * * Returns: File descriptor for repository root - owned by @self + * Since: 2016.4 */ int ostree_repo_get_dfd (OstreeRepo *self) @@ -4334,6 +4349,8 @@ ostree_repo_import_object_from (OstreeRepo *self, * this will simply be a fast Unix hard link operation. * * Otherwise, a copy will be performed. + * + * Since: 2016.5 */ gboolean ostree_repo_import_object_from_with_trust (OstreeRepo *self, @@ -5431,6 +5448,8 @@ ostree_repo_verify_commit_ext (OstreeRepo *self, * configured for @remote. * * Returns: (transfer full): an #OstreeGpgVerifyResult, or %NULL on error + * + * Since: 2016.14 */ OstreeGpgVerifyResult * ostree_repo_verify_commit_for_remote (OstreeRepo *self, @@ -5466,6 +5485,8 @@ ostree_repo_verify_commit_for_remote (OstreeRepo *self, * the verifications using GPG keys in the keyrings of all remotes. * * Returns: (transfer full): an #OstreeGpgVerifyResult, or %NULL on error + * + * Since: 2016.6 */ OstreeGpgVerifyResult * ostree_repo_gpg_verify_data (OstreeRepo *self, diff --git a/src/libostree/ostree-sepolicy.c b/src/libostree/ostree-sepolicy.c index 4f8223b3..e6b9a0e1 100644 --- a/src/libostree/ostree-sepolicy.c +++ b/src/libostree/ostree-sepolicy.c @@ -351,7 +351,7 @@ initable_init (GInitable *initable, if (g_str_has_prefix (line, selinuxtype_prefix)) { - policytype = g_strstrip (g_strdup (line + strlen (selinuxtype_prefix))); + policytype = g_strstrip (g_strdup (line + strlen (selinuxtype_prefix))); policy_root = g_file_get_child (etc_selinux_dir, policytype); } else if (g_str_has_prefix (line, selinux_prefix)) @@ -430,6 +430,8 @@ ostree_sepolicy_new (GFile *path, * @error: Error * * Returns: (transfer full): An accessor object for SELinux policy in root located at @rootfs_dfd + * + * Since: 2017.4 */ OstreeSePolicy* ostree_sepolicy_new_at (int rootfs_dfd, @@ -472,6 +474,8 @@ ostree_sepolicy_get_name (OstreeSePolicy *self) * @self: * * Returns: (transfer none): Checksum of current policy + * + * Since: 2016.5 */ const char * ostree_sepolicy_get_csum (OstreeSePolicy *self) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 3ca6c148..1096b0b0 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2170,6 +2170,8 @@ write_deployments_finish (OstreeSysroot *self, * 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. + * + * Since: 2017.4 */ gboolean ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, @@ -2756,6 +2758,8 @@ _ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, * * Like ostree_sysroot_deploy_tree(), but "finalization" only occurs at OS * shutdown time. + * + * Since: 2018.5 */ gboolean ostree_sysroot_stage_tree (OstreeSysroot *self, diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 21ea1734..43744565 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -855,6 +855,11 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, return TRUE; } +/** + * ostree_sysroot_load_if_changed: + * + * Since: 2016.4 + */ gboolean ostree_sysroot_load_if_changed (OstreeSysroot *self, gboolean *out_changed, @@ -1033,6 +1038,8 @@ ostree_sysroot_get_booted_deployment (OstreeSysroot *self) * @self: Sysroot * * Returns: (transfer none): The currently staged deployment, or %NULL if none + * + * Since: 2018.5 */ OstreeDeployment * ostree_sysroot_get_staged_deployment (OstreeSysroot *self) @@ -1144,6 +1151,8 @@ ostree_sysroot_get_repo (OstreeSysroot *self, * has been invoked successfully. * * Returns: (transfer none): The OSTree repository in sysroot @self. + * + * Since: 2017.7 */ OstreeRepo * ostree_sysroot_repo (OstreeSysroot *self) @@ -1475,6 +1484,8 @@ ostree_sysroot_lock_finish (OstreeSysroot *self, * Initialize the directory structure for an "osname", which is a * group of operating system deployments, with a shared `/var`. One * is required for generating a deployment. + * + * Since: 2016.4 */ gboolean ostree_sysroot_init_osname (OstreeSysroot *self, @@ -1729,6 +1740,8 @@ static gboolean mkdir_unmasked (int dfd, * * The `OSTREE_DEPLOYMENT_UNLOCKED_HOTFIX` state is persistent * across reboots. + * + * Since: 2016.4 */ gboolean ostree_sysroot_deployment_unlock (OstreeSysroot *self, From 0872708ea1deb393234ee043f0e1d2fd92d43fa4 Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Sat, 18 May 2019 13:58:34 +0200 Subject: [PATCH 09/62] lib: fix up some nullability annotations Closes: #1861 Approved by: cgwalters --- src/libostree/ostree-ref.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libostree/ostree-ref.c b/src/libostree/ostree-ref.c index 35fd5821..ea372b84 100644 --- a/src/libostree/ostree-ref.c +++ b/src/libostree/ostree-ref.c @@ -47,7 +47,7 @@ G_DEFINE_BOXED_TYPE (OstreeCollectionRef, ostree_collection_ref, * refspec; no remote name is included), which can be used for non-P2P * operations. * - * Returns: (transfer full): a new #OstreeCollectionRef + * Returns: (transfer full) (nullable): a new #OstreeCollectionRef * Since: 2018.6 */ OstreeCollectionRef * @@ -69,7 +69,7 @@ ostree_collection_ref_new (const gchar *collection_id, /** * ostree_collection_ref_dup: - * @ref: an #OstreeCollectionRef + * @ref: (not nullable): an #OstreeCollectionRef * * Create a copy of the given @ref. * @@ -104,7 +104,7 @@ ostree_collection_ref_free (OstreeCollectionRef *ref) /** * ostree_collection_ref_hash: - * @ref: an #OstreeCollectionRef + * @ref: (not nullable): an #OstreeCollectionRef * * Hash the given @ref. This function is suitable for use with #GHashTable. * @ref must be non-%NULL. @@ -125,8 +125,8 @@ ostree_collection_ref_hash (gconstpointer ref) /** * ostree_collection_ref_equal: - * @ref1: an #OstreeCollectionRef - * @ref2: another #OstreeCollectionRef + * @ref1: (not nullable): an #OstreeCollectionRef + * @ref2 : (not nullable): another #OstreeCollectionRef * * Compare @ref1 and @ref2 and return %TRUE if they have the same collection ID and * ref name, and %FALSE otherwise. Both @ref1 and @ref2 must be non-%NULL. From aa5df8995ef330d723081a5c443442ce90aa0b3e Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Sat, 18 May 2019 16:12:30 +0200 Subject: [PATCH 10/62] lib: add some missing (out) annotations Closes: #1861 Approved by: cgwalters --- src/libostree/ostree-mutable-tree.c | 8 ++++++++ src/libostree/ostree-repo-file.c | 24 ++++++++++++++++++++++++ src/libostree/ostree-repo.c | 12 +++++++++--- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c index a213fd4a..8509d156 100644 --- a/src/libostree/ostree-mutable-tree.c +++ b/src/libostree/ostree-mutable-tree.c @@ -401,6 +401,14 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self, return TRUE; } +/** + * ostree_mutable_tree_lookup: + * @self: Tree + * @name: name + * @out_file_checksum: (out) (transfer full): checksum + * @out_subdir: (out) (transfer full): subdirectory + * @error: a #GError + */ gboolean ostree_mutable_tree_lookup (OstreeMutableTree *self, const char *name, diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c index 740b4624..7ad11529 100644 --- a/src/libostree/ostree-repo-file.c +++ b/src/libostree/ostree-repo-file.c @@ -292,6 +292,13 @@ ostree_repo_file_ensure_resolved (OstreeRepoFile *self, return TRUE; } +/** + * ostree_repo_file_get_xattrs: + * @self: #OstreeRepoFile + * @out_xattrs: (out) (optional): the extended attributes + * @cancellable: Cancellable + * @error: Error + */ gboolean ostree_repo_file_get_xattrs (OstreeRepoFile *self, GVariant **out_xattrs, @@ -724,6 +731,13 @@ query_child_info_dir (OstreeRepo *repo, return TRUE; } +/** + * ostree_repo_file_tree_find_child: + * @self: #OstreeRepoFile + * @name: name of the child + * @is_dir: (out caller-allocates): + * @out_container: (out): + */ int ostree_repo_file_tree_find_child (OstreeRepoFile *self, const char *name, @@ -769,6 +783,16 @@ ostree_repo_file_tree_find_child (OstreeRepoFile *self, return i; } +/** + * ostree_repo_file_tree_query_child: + * @self: #OstreeRepoFile + * @n: + * @attributes: + * @flags: + * @out_info: (out): + * @cancellable: Cancellable + * @error: Error + */ gboolean ostree_repo_file_tree_query_child (OstreeRepoFile *self, int n, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 3238e429..da128c6a 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2048,9 +2048,9 @@ ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self, * ostree_repo_remote_gpg_import: * @self: Self * @name: name of a remote - * @source_stream: (allow-none): a #GInputStream, or %NULL - * @key_ids: (array zero-terminated=1) (element-type utf8) (allow-none): a %NULL-terminated array of GPG key IDs, or %NULL - * @out_imported: (allow-none): return location for the number of imported + * @source_stream: (nullable): a #GInputStream, or %NULL + * @key_ids: (array zero-terminated=1) (element-type utf8) (nullable): a %NULL-terminated array of GPG key IDs, or %NULL + * @out_imported: (out) (optional): return location for the number of imported * keys, or %NULL * @cancellable: a #GCancellable * @error: a #GError @@ -2385,6 +2385,12 @@ ostree_repo_mode_to_string (OstreeRepoMode mode, return TRUE; } +/** + * ostree_repo_mode_from_string: + * @mode: a repo mode as a string + * @out_mode: (out): the corresponding #OstreeRepoMode + * @error: a #GError if the string is not a valid mode + */ gboolean ostree_repo_mode_from_string (const char *mode, OstreeRepoMode *out_mode, From 2c1658538f8fde5813e95e7408d65662a489be91 Mon Sep 17 00:00:00 2001 From: Felix Krull Date: Sat, 18 May 2019 21:16:28 +0200 Subject: [PATCH 11/62] lib: add parameter annotations for sysroot_load_if_changed Closes: #1861 Approved by: cgwalters --- src/libostree/ostree-sysroot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 43744565..4862b7b4 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -857,6 +857,10 @@ _ostree_sysroot_reload_staged (OstreeSysroot *self, /** * ostree_sysroot_load_if_changed: + * @self: #OstreeSysroot + * @out_changed: (out caller-allocates): + * @cancellable: Cancellable + * @error: Error * * Since: 2016.4 */ From e493505ade01d3d03a0b366bee611cd710f72909 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 8 May 2019 19:13:12 -0400 Subject: [PATCH 12/62] tests: Drop unused variable Closes: #1857 Approved by: cgwalters --- tests/test-repo-finder-config.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test-repo-finder-config.c b/tests/test-repo-finder-config.c index a87e3f4b..0a2e9e60 100644 --- a/tests/test-repo-finder-config.c +++ b/tests/test-repo-finder-config.c @@ -308,7 +308,6 @@ static void test_repo_finder_config_find_remotes (Fixture *fixture, gconstpointer test_data) { - g_autoptr(OstreeRepoFinder) finder = NULL; g_autoptr(GMainContext) context = NULL; g_autoptr(GAsyncResult) result = NULL; g_auto(OstreeRepoFinderResultv) results = NULL; From 4929fc38e98a384d4f29d8710338b9e2e750f5a7 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 8 May 2019 19:15:53 -0400 Subject: [PATCH 13/62] lib/fetcher-util: Use GIOErrorEnum instead of GIOError Use GIOErrorEnum as the return value for _ostree_fetcher_http_status_code_to_io_error(), to avoid an implicit cast from GIOError. Closes: #1857 Approved by: cgwalters --- src/libostree/ostree-fetcher-util.c | 4 ++-- src/libostree/ostree-fetcher-util.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-fetcher-util.c b/src/libostree/ostree-fetcher-util.c index ef02ba1e..a9bd60a5 100644 --- a/src/libostree/ostree-fetcher-util.c +++ b/src/libostree/ostree-fetcher-util.c @@ -219,9 +219,9 @@ _ostree_fetcher_should_retry_request (const GError *error, } /* Convert a HTTP status code representing an error from libsoup or libcurl to - * a #GIOError. This will return %G_IO_ERROR_FAILED if the status code is + * a #GIOErrorEnum. This will return %G_IO_ERROR_FAILED if the status code is * unknown or otherwise unhandled. */ -GIOError +GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code) { switch (status_code) diff --git a/src/libostree/ostree-fetcher-util.h b/src/libostree/ostree-fetcher-util.h index 1cade068..46935402 100644 --- a/src/libostree/ostree-fetcher-util.h +++ b/src/libostree/ostree-fetcher-util.h @@ -78,7 +78,7 @@ void _ostree_fetcher_journal_failure (const char *remote_name, gboolean _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remaining); -GIOError _ostree_fetcher_http_status_code_to_io_error (guint status_code); +GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code); G_END_DECLS From 1c0933b40ca090d3c748bda69eb9a1957a136e72 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 23 May 2019 13:05:07 -0400 Subject: [PATCH 14/62] ci: Split out installdeps.sh from build.sh This script is useful to run individually when setting up a development environment for OSTree. Closes: #1865 Approved by: jlebon --- ci/build.sh | 16 +--------------- ci/installdeps.sh | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 15 deletions(-) create mode 100755 ci/installdeps.sh diff --git a/ci/build.sh b/ci/build.sh index 4f7d02c4..09015074 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -6,21 +6,7 @@ set -xeuo pipefail dn=$(dirname $0) . ${dn}/libpaprci/libbuild.sh -pkg_upgrade -pkg_install_buildroot -pkg_builddep ostree -pkg_install sudo which attr fuse strace \ - libubsan libasan libtsan PyYAML redhat-rpm-config \ - elfutils -if test -n "${CI_PKGS:-}"; then - pkg_install ${CI_PKGS} -fi -pkg_install_if_os fedora gjs gnome-desktop-testing parallel coccinelle clang \ - python3-PyYAML -if test "${OS_ID}" = "centos"; then - rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - pkg_install python34{,-PyYAML} -fi +${dn}/installdeps.sh # Default libcurl on by default in fedora unless libsoup is enabled if test "${OS_ID}" = 'fedora'; then diff --git a/ci/installdeps.sh b/ci/installdeps.sh new file mode 100755 index 00000000..29bd4e41 --- /dev/null +++ b/ci/installdeps.sh @@ -0,0 +1,23 @@ +#!/usr/bin/bash +# Install build dependencies. + +set -xeuo pipefail + +dn=$(dirname $0) +. ${dn}/libpaprci/libbuild.sh + +pkg_upgrade +pkg_install_buildroot +pkg_builddep ostree +pkg_install sudo which attr fuse strace \ + libubsan libasan libtsan PyYAML redhat-rpm-config \ + elfutils +if test -n "${CI_PKGS:-}"; then + pkg_install ${CI_PKGS} +fi +pkg_install_if_os fedora gjs gnome-desktop-testing parallel coccinelle clang \ + python3-PyYAML +if test "${OS_ID}" = "centos"; then + rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + pkg_install python34{,-PyYAML} +fi From da4d0245af9b937c7fe65540f022bc77bc0354ed Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Tue, 21 May 2019 22:01:09 +0900 Subject: [PATCH 15/62] lib/commit: Added new ostree_repo_write_archive_to_mtree_from_fd() Similar to ostree_repo_write_archive_to_mtree(), but takes a file descriptor to read the archive from instead of mandating a file path. Usefull for importing archives into an OSTree repo over a socket or from standard input in command line tools. Closes: #1862 Approved by: jlebon --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree-devel.sym | 2 + src/libostree/ostree-libarchive-private.h | 30 +++++++- src/libostree/ostree-repo-libarchive.c | 94 +++++++++++++++++------ src/libostree/ostree-repo.h | 10 +++ 5 files changed, 110 insertions(+), 27 deletions(-) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 1a26e1eb..7a59b5a7 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -380,6 +380,7 @@ ostree_repo_devino_cache_get_type ostree_repo_write_directory_to_mtree ostree_repo_write_dfd_to_mtree ostree_repo_write_archive_to_mtree +ostree_repo_write_archive_to_mtree_from_fd ostree_repo_write_mtree ostree_repo_write_commit ostree_repo_write_commit_with_time diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 8d9a7bfc..cdbdbb32 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -19,6 +19,8 @@ /* Add new symbols here. Release commits should copy this section into -released.sym. */ LIBOSTREE_2019.3 { +global: + ostree_repo_write_archive_to_mtree_from_fd; } LIBOSTREE_2018.9; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-libarchive-private.h b/src/libostree/ostree-libarchive-private.h index 4a98b6d1..46da3e18 100644 --- a/src/libostree/ostree-libarchive-private.h +++ b/src/libostree/ostree-libarchive-private.h @@ -44,9 +44,9 @@ typedef struct archive OtAutoArchiveRead; G_DEFINE_AUTOPTR_CLEANUP_FUNC(OtAutoArchiveRead, archive_read_free) static inline OtAutoArchiveRead * -ot_open_archive_read (const char *path, GError **error) +ot_archive_read_new (void) { - g_autoptr(OtAutoArchiveRead) a = archive_read_new (); + OtAutoArchiveRead *a = archive_read_new (); #ifdef HAVE_ARCHIVE_READ_SUPPORT_FILTER_ALL archive_read_support_filter_all (a); @@ -54,10 +54,34 @@ ot_open_archive_read (const char *path, GError **error) archive_read_support_compression_all (a); #endif archive_read_support_format_all (a); + + return a; +} + +static inline OtAutoArchiveRead * +ot_open_archive_read (const char *path, GError **error) +{ + g_autoptr(OtAutoArchiveRead) a = ot_archive_read_new (); + if (archive_read_open_filename (a, path, 8192) != ARCHIVE_OK) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "%s", archive_error_string (a)); + "archive_read_open_filename: %s", archive_error_string (a)); + return NULL; + } + + return g_steal_pointer (&a); +} + +static inline OtAutoArchiveRead * +ot_open_archive_read_fd (int fd, GError **error) +{ + g_autoptr(OtAutoArchiveRead) a = ot_archive_read_new (); + + if (archive_read_open_fd (a, fd, 8192) != ARCHIVE_OK) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "archive_read_open_fd: %s", archive_error_string (a)); return NULL; } diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index 2852e78e..1850f99f 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -901,6 +901,37 @@ ostree_repo_import_archive_to_mtree (OstreeRepo *self, #endif } +#ifdef HAVE_LIBARCHIVE +static gboolean +write_archive_to_mtree (OstreeRepo *self, + OtAutoArchiveRead *archive, + OstreeMutableTree *mtree, + OstreeRepoCommitModifier *modifier, + gboolean autocreate_parents, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + OstreeRepoImportArchiveOptions opts = { 0, }; + + opts.autocreate_parents = !!autocreate_parents; + + if (!ostree_repo_import_archive_to_mtree (self, &opts, archive, mtree, modifier, cancellable, error)) + goto out; + + if (archive_read_close (archive) != ARCHIVE_OK) + { + propagate_libarchive_error (error, archive); + goto out; + } + + ret = TRUE; + out: + (void)archive_read_close (archive); + return ret; +} +#endif + /** * ostree_repo_write_archive_to_mtree: * @self: An #OstreeRepo @@ -924,31 +955,46 @@ ostree_repo_write_archive_to_mtree (OstreeRepo *self, GError **error) { #ifdef HAVE_LIBARCHIVE - gboolean ret = FALSE; - g_autoptr(OtAutoArchiveRead) a = archive_read_new (); - OstreeRepoImportArchiveOptions opts = { 0, }; - - a = ot_open_archive_read (gs_file_get_path_cached (archive), error); - if (!a) - goto out; - opts.autocreate_parents = !!autocreate_parents; - - if (!ostree_repo_import_archive_to_mtree (self, &opts, a, mtree, modifier, cancellable, error)) - goto out; - - if (archive_read_close (a) != ARCHIVE_OK) - { - propagate_libarchive_error (error, a); - goto out; - } - - ret = TRUE; - out: + g_autoptr(OtAutoArchiveRead) a = ot_open_archive_read (gs_file_get_path_cached (archive), error); if (a) - { - (void)archive_read_close (a); - } - return ret; + return write_archive_to_mtree (self, a, mtree, modifier, autocreate_parents, cancellable, error); + + return FALSE; +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "This version of ostree is not compiled with libarchive support"); + return FALSE; +#endif +} + +/** + * ostree_repo_write_archive_to_mtree_from_fd: + * @self: An #OstreeRepo + * @fd: A file descriptor to read the archive from + * @mtree: The #OstreeMutableTree to write to + * @modifier: (allow-none): Optional commit modifier + * @autocreate_parents: Autocreate parent directories + * @cancellable: Cancellable + * @error: Error + * + * Read an archive from @fd and import it into the repository, writing + * its file structure to @mtree. + */ +gboolean +ostree_repo_write_archive_to_mtree_from_fd (OstreeRepo *self, + int fd, + OstreeMutableTree *mtree, + OstreeRepoCommitModifier *modifier, + gboolean autocreate_parents, + GCancellable *cancellable, + GError **error) +{ +#ifdef HAVE_LIBARCHIVE + g_autoptr(OtAutoArchiveRead) a = ot_open_archive_read_fd (fd, error); + if (a) + return write_archive_to_mtree (self, a, mtree, modifier, autocreate_parents, cancellable, error); + + return FALSE; #else g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "This version of ostree is not compiled with libarchive support"); diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index afa33155..b5af2f82 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -737,6 +737,16 @@ gboolean ostree_repo_write_archive_to_mtree (OstreeRepo * GCancellable *cancellable, GError **error); + +_OSTREE_PUBLIC +gboolean ostree_repo_write_archive_to_mtree_from_fd (OstreeRepo *self, + int fd, + OstreeMutableTree *mtree, + OstreeRepoCommitModifier *modifier, + gboolean autocreate_parents, + GCancellable *cancellable, + GError **error); + /** * OstreeRepoImportArchiveTranslatePathname: * @repo: Repo From bebd8d6980f8ec0a182d2b69073b55085580a29c Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Tue, 21 May 2019 22:26:55 +0900 Subject: [PATCH 16/62] bin/commit: Support committing archives from stdin This commit interprets archive filenames specified as '-' to indicate that the input should be read from stdin. Closes: #1862 Approved by: jlebon --- src/ostree/ot-builtin-commit.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index b7c61a9e..56f59681 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -636,11 +636,22 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio { if (!opt_tar_pathname_filter) { - object_to_commit = g_file_new_for_path (tree); - if (!ostree_repo_write_archive_to_mtree (repo, object_to_commit, mtree, modifier, - opt_tar_autocreate_parents, - cancellable, error)) - goto out; + if (strcmp (tree, "-") == 0) + { + if (!ostree_repo_write_archive_to_mtree_from_fd (repo, STDIN_FILENO, mtree, modifier, + opt_tar_autocreate_parents, + cancellable, error)) + goto out; + } + else + { + object_to_commit = g_file_new_for_path (tree); + + if (!ostree_repo_write_archive_to_mtree (repo, object_to_commit, mtree, modifier, + opt_tar_autocreate_parents, + cancellable, error)) + goto out; + } } else { @@ -666,7 +677,13 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio goto out; } opts.translate_pathname_user_data = &tpdata; - g_autoptr(OtAutoArchiveRead) archive = ot_open_archive_read (tree, error); + + g_autoptr(OtAutoArchiveRead) archive; + if (strcmp (tree, "-") == 0) + archive = ot_open_archive_read_fd (STDIN_FILENO, error); + else + archive = ot_open_archive_read (tree, error); + if (!archive) goto out; if (!ostree_repo_import_archive_to_mtree (repo, &opts, archive, mtree, From 1c7bddd57ad686eaba7ac1f2d5b288ce8be9e11e Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Tue, 21 May 2019 22:28:19 +0900 Subject: [PATCH 17/62] man: Document ability to commit archives from stdin Closes: #1862 Approved by: jlebon --- man/ostree-commit.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/ostree-commit.xml b/man/ostree-commit.xml index 4131d607..c64a7a00 100644 --- a/man/ostree-commit.xml +++ b/man/ostree-commit.xml @@ -102,7 +102,7 @@ Boston, MA 02111-1307, USA. ="dir=PATH" or "tar=TARFILE" or "ref=COMMIT" - Overlay the given argument as a tree. + Overlay the given argument as a tree. When committing an archive, the TARFILE can be specified as - to read the archive from standard input. From b847cc37bbaf0a89d04428fbee004dd5010f6fcc Mon Sep 17 00:00:00 2001 From: Tristan Van Berkom Date: Tue, 21 May 2019 22:30:03 +0900 Subject: [PATCH 18/62] tests: Test committing archives from stdin This updates test-libarchive.sh to test committing archives from stdin and verifying their content is correct. Closes: #1862 Approved by: jlebon --- tests/test-libarchive.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/test-libarchive.sh b/tests/test-libarchive.sh index 0a51d442..24de55b2 100755 --- a/tests/test-libarchive.sh +++ b/tests/test-libarchive.sh @@ -28,7 +28,7 @@ fi . $(dirname $0)/libtest.sh -echo "1..13" +echo "1..17" setup_test_repository "bare" @@ -75,6 +75,16 @@ $OSTREE commit -s "from cpio" -b test-cpio \ --skip-list=skiplist.txt \ --tree=tar=foo.cpio echo "ok cpio commit" +cat foo.tar.gz | $OSTREE commit -s "from tar" -b test-tar-stdin \ + --statoverride=statoverride.txt \ + --skip-list=skiplist.txt \ + --tree=tar=- +echo "ok tar commit from stdin" +cat foo.cpio | $OSTREE commit -s "from cpio" -b test-cpio-stdin \ + --statoverride=statoverride.txt \ + --skip-list=skiplist.txt \ + --tree=tar=- +echo "ok cpio commit from stdin" assert_valid_checkout () { ref=$1 @@ -124,6 +134,10 @@ assert_valid_checkout tar echo "ok tar contents" assert_valid_checkout cpio echo "ok cpio contents" +assert_valid_checkout tar-stdin +echo "ok tar contents from stdin" +assert_valid_checkout cpio-stdin +echo "ok cpio contents from stdin" cd ${test_tmpdir} mkdir multicommit-files From e0ddaa811b2f7a1af7e24c6b8c6f1074e216609e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 24 May 2019 13:43:34 +0100 Subject: [PATCH 19/62] ostree-repo-finder: Clarify immutability after construction I think this was the intention, but I forgot to document it. Signed-off-by: Philip Withnall Closes: #1863 Approved by: mwleeds --- src/libostree/ostree-repo-finder.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libostree/ostree-repo-finder.h b/src/libostree/ostree-repo-finder.h index 7c9be300..f9c26199 100644 --- a/src/libostree/ostree-repo-finder.h +++ b/src/libostree/ostree-repo-finder.h @@ -111,6 +111,8 @@ GPtrArray *ostree_repo_finder_resolve_all_finish (GAsyncResult *result, * which allow ostree_repo_pull_from_remotes_async() (for example) to prioritise * how to pull the refs. * + * An #OstreeRepoFinderResult is immutable after construction. + * * The @priority is used as one input of many to ordering functions like * ostree_repo_finder_result_compare(). * From 6733843f87aa3b1ad3dfe1ae76f0c76329617909 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Wed, 5 Jun 2019 10:30:31 -0400 Subject: [PATCH 20/62] lib/util: Fix segfault when validating filename This change fixes the segfault issue when calling ostree_repo_checkout_tree with empty GFileInfo. A simple condition check for NULL value is added at src/libotutil/ot-unix-utils.c:46. Closes: ostreedev#1864. Closes: #1868 Approved by: jlebon --- src/libotutil/ot-unix-utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libotutil/ot-unix-utils.c b/src/libotutil/ot-unix-utils.c index 7778ca11..17016ae1 100644 --- a/src/libotutil/ot-unix-utils.c +++ b/src/libotutil/ot-unix-utils.c @@ -43,6 +43,8 @@ gboolean ot_util_filename_validate (const char *name, GError **error) { + if (name == NULL) + return glnx_throw (error, "Invalid NULL filename"); if (strcmp (name, ".") == 0) return glnx_throw (error, "Invalid self-referential filename '.'"); if (strcmp (name, "..") == 0) From d916383953121f7bbd016a977caf85bc6f917422 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 10 Jun 2019 09:47:44 -0500 Subject: [PATCH 21/62] bin/refs: Allow overwriting existing ref Currently if you want to update a non-alias ref, you need to first check if it exists and use either `ostree refs --create` or `ostree reset` as appropriate. That's unnecessarily complicated and is much less convenient than the old `write-refs` builtin that simply called `ostree_repo_set_ref_immediate()` without any checks. Add a `--force` option to be used with `--create` that does not raise an error when the destination ref already exists. Closes: #1870 Approved by: jlebon --- bash/ostree | 1 + man/ostree-refs.xml | 10 ++++++++++ src/ostree/ot-builtin-refs.c | 10 +++++++--- tests/test-refs.sh | 5 +++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/bash/ostree b/bash/ostree index 5ba3d475..fc429983 100644 --- a/bash/ostree +++ b/bash/ostree @@ -952,6 +952,7 @@ _ostree_refs() { --collections -c --delete --list + --force " local options_with_args=" diff --git a/man/ostree-refs.xml b/man/ostree-refs.xml index 8d5a1d23..0ba6b1d7 100644 --- a/man/ostree-refs.xml +++ b/man/ostree-refs.xml @@ -126,6 +126,16 @@ Boston, MA 02111-1307, USA. PREFIX are deleted. + + + + + + When creating NEWREF with + , allow an existing ref to be + updated instead of erroring. + + diff --git a/src/ostree/ot-builtin-refs.c b/src/ostree/ot-builtin-refs.c index 630605a0..1e0b1011 100644 --- a/src/ostree/ot-builtin-refs.c +++ b/src/ostree/ot-builtin-refs.c @@ -32,6 +32,7 @@ static gboolean opt_list; static gboolean opt_alias; static char *opt_create; static gboolean opt_collections; +static gboolean opt_force; /* ATTENTION: * Please remember to update the bash-completion script (bash/ostree) and @@ -44,6 +45,7 @@ static GOptionEntry options[] = { { "alias", 'A', 0, G_OPTION_ARG_NONE, &opt_alias, "If used with --create, create an alias, otherwise just list aliases", NULL }, { "create", 0, 0, G_OPTION_ARG_STRING, &opt_create, "Create a new ref for an existing commit", "NEWREF" }, { "collections", 'c', 0, G_OPTION_ARG_NONE, &opt_collections, "Enable listing collection IDs for refs", NULL }, + { "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, "Overwrite existing refs when creating", NULL }, { NULL } }; @@ -89,7 +91,7 @@ do_ref_with_collections (OstreeRepo *repo, else goto out; } - if (checksum_existing != NULL) + if (!opt_force && checksum_existing != NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "--create specified but ref %s already exists", opt_create); @@ -205,9 +207,11 @@ static gboolean do_ref (OstreeRepo *repo, const char *refspec_prefix, GCancellab else goto out; } - /* We want to allow replacing an existing alias */ + /* We want to allow replacing an existing alias or a normal ref when + * forced + */ gboolean replacing_alias = opt_alias && g_hash_table_contains (ref_aliases, opt_create); - if (!replacing_alias && checksum_existing != NULL) + if (!replacing_alias && !opt_force && checksum_existing != NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "--create specified but ref %s already exists", opt_create); diff --git a/tests/test-refs.sh b/tests/test-refs.sh index 83da04ff..d0f8e7da 100755 --- a/tests/test-refs.sh +++ b/tests/test-refs.sh @@ -90,6 +90,11 @@ if ${CMD_PREFIX} ostree --repo=repo refs foo/ctest --create=ctest; then assert_not_reached "refs --create unexpectedly succeeded in overwriting an existing prefix!" fi +# Force overwriting ctest and check the revision got updated +foo_ctest_rev=$(${CMD_PREFIX} ostree --repo=repo rev-parse foo/ctest) +${CMD_PREFIX} ostree --repo=repo refs foo/ctest --create=ctest --force +assert_ref repo ctest ${foo_ctest_rev} + # https://github.com/ostreedev/ostree/issues/1285 # One tool was creating .latest_rsync files in each dir, let's ignore stuff like # that. From 2db79fb398fba2f9ab2e05c517ebccfe1834674b Mon Sep 17 00:00:00 2001 From: Rafael Fonseca Date: Mon, 17 Jun 2019 16:41:00 +0200 Subject: [PATCH 22/62] admin: allow multiple args for pin subcommand Fixes #1816 Signed-off-by: Rafael Fonseca Closes: #1874 Approved by: rfairley --- src/ostree/ot-admin-builtin-pin.c | 49 ++++++++++++++++++++----------- tests/test-admin-deploy-2.sh | 3 +- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/ostree/ot-admin-builtin-pin.c b/src/ostree/ot-admin-builtin-pin.c index f110983b..ced0fcf3 100644 --- a/src/ostree/ot-admin-builtin-pin.c +++ b/src/ostree/ot-admin-builtin-pin.c @@ -52,24 +52,39 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation return FALSE; } - const char *deploy_index_str = argv[1]; - const int deploy_index = atoi (deploy_index_str); - - g_autoptr(OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, error); - if (!target_deployment) - return FALSE; - - - gboolean current_pin = ostree_deployment_is_pinned (target_deployment); - const gboolean desired_pin = !opt_unpin; - if (current_pin == desired_pin) - g_print ("Deployment is already %s\n", current_pin ? "pinned" : "unpinned"); - else + unsigned int nsuccess = 0; + for (unsigned int i = 1; i < argc; i++) { - if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error)) - return FALSE; - g_print ("Deployment is now %s\n", desired_pin ? "pinned" : "unpinned"); + const char *deploy_index_str = argv[i]; + const int deploy_index = atoi (deploy_index_str); + + g_autoptr(GError) e = NULL; + g_autoptr(OstreeDeployment) target_deployment = ot_admin_get_indexed_deployment (sysroot, deploy_index, &e); + if (!target_deployment) + { + g_print ("Invalid deployment %s: %s\n", deploy_index_str, e->message); + continue; + } + + gboolean current_pin = ostree_deployment_is_pinned (target_deployment); + const gboolean desired_pin = !opt_unpin; + if (current_pin == desired_pin) + { + g_print ("Deployment %s is already %s\n", deploy_index_str, current_pin ? "pinned" : "unpinned"); + nsuccess++; + } + else + { + g_autoptr(GError) e = NULL; + if (ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, &e)) + { + g_print ("Deployment %s is now %s\n", deploy_index_str, desired_pin ? "pinned" : "unpinned"); + nsuccess++; + } + else + g_print ("Failed to %s deployment %s: %s\n", desired_pin ? "pin" : "unpin", deploy_index_str, e->message); + } } - return TRUE; + return nsuccess > 0; } diff --git a/tests/test-admin-deploy-2.sh b/tests/test-admin-deploy-2.sh index 3e68ecf3..0fa2df9b 100755 --- a/tests/test-admin-deploy-2.sh +++ b/tests/test-admin-deploy-2.sh @@ -102,8 +102,7 @@ ${CMD_PREFIX} ostree admin pin -u 0 assert_n_pinned 0 echo "ok pin unpin" -${CMD_PREFIX} ostree admin pin 0 -${CMD_PREFIX} ostree admin pin 1 +${CMD_PREFIX} ostree admin pin 0 1 assert_n_pinned 2 assert_n_deployments 2 os_repository_new_commit From be2572bf68090a5e277338d2613d3c7d53b0c9e8 Mon Sep 17 00:00:00 2001 From: Allen Bai Date: Tue, 28 May 2019 14:02:54 -0400 Subject: [PATCH 23/62] lib/kargs: Make API public and upstream new rpm-ostree APIs This change makes public the current kargs API in src/libostree/ostree-kernel-args.c and adds documentations. Upstreams the new kargs API from rpm-ostree/src/libpriv/rpmostree-kargs-process.c Merges libostree_kernel_args_la_SOURCES to libostree_1_la_SOURCES in Makefile-libostree.am Upstreams tests/check/test-kargs.c from rpm-ostree. Closes: #1833 Closes: #1869 Approved by: jlebon --- Makefile-libostree-defines.am | 1 + Makefile-libostree.am | 13 +- Makefile-ostree.am | 2 +- Makefile-tests.am | 6 +- apidoc/Makefile.am | 1 - apidoc/ostree-sections.txt | 22 + src/libostree/libostree-devel.sym | 17 + src/libostree/ostree-bootloader-uboot.c | 4 +- src/libostree/ostree-kernel-args.c | 449 ++++++++++++++++-- src/libostree/ostree-kernel-args.h | 101 +++- src/libostree/ostree-sysroot-deploy.c | 26 +- src/libostree/ostree-sysroot-private.h | 1 - src/libostree/ostree-sysroot.c | 6 +- src/libostree/ostree.h | 1 + src/libotutil/ot-tool-util.c | 52 ++ src/libotutil/ot-tool-util.h | 5 + src/libotutil/otutil.h | 1 + src/ostree/ot-admin-builtin-deploy.c | 22 +- src/ostree/ot-admin-builtin-unlock.c | 2 - .../ot-admin-instutil-builtin-set-kargs.c | 17 +- tests/.gitignore | 1 + tests/test-kargs.c | 251 ++++++++++ 22 files changed, 887 insertions(+), 114 deletions(-) create mode 100644 tests/test-kargs.c diff --git a/Makefile-libostree-defines.am b/Makefile-libostree-defines.am index 77748a41..06035157 100644 --- a/Makefile-libostree-defines.am +++ b/Makefile-libostree-defines.am @@ -45,6 +45,7 @@ libostree_public_headers = \ src/libostree/ostree-repo-finder-config.h \ src/libostree/ostree-repo-finder-mount.h \ src/libostree/ostree-repo-finder-override.h \ + src/libostree/ostree-kernel-args.h \ $(NULL) # This one is generated via configure.ac, and the gtk-doc diff --git a/Makefile-libostree.am b/Makefile-libostree.am index dbc9ebb8..0ea54cf8 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -21,8 +21,6 @@ include Makefile-libostree-defines.am -noinst_LTLIBRARIES += libostree-kernel-args.la - if ENABLE_RUST bupsplitpath = @abs_top_builddir@/target/@RUST_TARGET_SUBDIR@/libbupsplit_rs.a @@ -36,13 +34,6 @@ noinst_LTLIBRARIES += libbupsplit.la libbupsplit_la_SOURCES = src/libostree/bupsplit.h src/libostree/bupsplit.c endif # ENABLE_RUST -libostree_kernel_args_la_SOURCES = \ - src/libostree/ostree-kernel-args.h \ - src/libostree/ostree-kernel-args.c \ - $(NULL) -libostree_kernel_args_la_CFLAGS = -I$(srcdir)/libglnx $(OT_INTERNAL_GIO_UNIX_CFLAGS) -libostree_kernel_args_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) - lib_LTLIBRARIES += libostree-1.la libostreeincludedir = $(includedir)/ostree-1 @@ -147,6 +138,8 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-repo-finder-config.c \ src/libostree/ostree-repo-finder-mount.c \ src/libostree/ostree-repo-finder-override.c \ + src/libostree/ostree-kernel-args.h \ + src/libostree/ostree-kernel-args.c \ $(NULL) if USE_LIBARCHIVE libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \ @@ -191,7 +184,7 @@ libostree_1_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/bsdiff -I$(srcdir)/libglnx -I$( $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(OT_DEP_LZMA_CFLAGS) $(OT_DEP_ZLIB_CFLAGS) $(OT_DEP_CRYPTO_CFLAGS) \ -fvisibility=hidden '-D_OSTREE_PUBLIC=__attribute__((visibility("default"))) extern' libostree_1_la_LDFLAGS = -version-number 1:0:0 -Bsymbolic-functions $(addprefix $(wl_versionscript_arg),$(symbol_files)) -libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la libostree-kernel-args.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ +libostree_1_la_LIBADD = libotutil.la libglnx.la libbsdiff.la $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) \ $(OT_DEP_LZMA_LIBS) $(OT_DEP_ZLIB_LIBS) $(OT_DEP_CRYPTO_LIBS) # Some change between rust-1.21.0-1.fc27 and rust-1.22.1-1.fc27.x86_64 if ENABLE_RUST diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 8d352e38..92881a31 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -125,7 +125,7 @@ ostree_bin_shared_ldadd = $(AM_LDFLAGS) libglnx.la libotutil.la libostree-1.la \ $(OT_INTERNAL_GIO_UNIX_LIBS) ostree_CFLAGS = $(ostree_bin_shared_cflags) -ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la libostree-kernel-args.la $(LIBSYSTEMD_LIBS) +ostree_LDADD = $(ostree_bin_shared_ldadd) libbsdiff.la $(LIBSYSTEMD_LIBS) if USE_CURL_OR_SOUP diff --git a/Makefile-tests.am b/Makefile-tests.am index 2c0916f6..ac59b94b 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -246,7 +246,7 @@ endif _installed_or_uninstalled_test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \ tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \ tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \ - tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo tests/test-include-ostree-h + tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo tests/test-include-ostree-h tests/test-kargs if USE_AVAHI test_programs += tests/test-repo-finder-avahi @@ -295,6 +295,10 @@ tests_test_repo_finder_avahi_CFLAGS = $(TESTS_CFLAGS) tests_test_repo_finder_avahi_LDADD = $(TESTS_LDADD) endif +tests_test_kargs_SOURCES = src/libostree/ostree-kernel-args.c tests/test-kargs.c +tests_test_kargs_CFLAGS = $(TESTS_CFLAGS) +tests_test_kargs_LDADD = $(TESTS_LDADD) + tests_test_repo_finder_config_SOURCES = tests/test-repo-finder-config.c tests_test_repo_finder_config_CFLAGS = $(TESTS_CFLAGS) tests_test_repo_finder_config_LDADD = $(TESTS_LDADD) diff --git a/apidoc/Makefile.am b/apidoc/Makefile.am index d64ce451..98a84d5f 100644 --- a/apidoc/Makefile.am +++ b/apidoc/Makefile.am @@ -78,7 +78,6 @@ IGNORE_HFILES= \ ostree-fetcher.h \ ostree-gpg-verifier.h \ ostree-gpg-verify-result-private.h \ - ostree-kernel-args.h \ ostree-libarchive-input-stream.h \ ostree-lzma-compressor.h \ ostree-lzma-decompressor.h \ diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 7a59b5a7..3838be4c 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -669,3 +669,25 @@ ostree_repo_set_collection_ref_immediate ostree_repo_transaction_set_collection_ref ostree_repo_resolve_collection_ref + +
+ostree-kernel-args +OstreeKernelArgs +ostree_kernel_args_free +ostree_kernel_args_new +ostree_kernel_args_cleanup +ostree_kernel_args_replace_take +ostree_kernel_args_replace +ostree_kernel_args_replace_argv +ostree_kernel_args_append +ostree_kernel_args_append_argv +ostree_kernel_args_append_argv_filtered +ostree_kernel_args_new_replace +ostree_kernel_args_delete +ostree_kernel_args_delete_key_entry +ostree_kernel_args_append_proc_cmdline +ostree_kernel_args_parse_append +ostree_kernel_args_from_string +ostree_kernel_args_to_strv +ostree_kernel_args_to_string +
diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index cdbdbb32..125d9457 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -21,6 +21,23 @@ LIBOSTREE_2019.3 { global: ostree_repo_write_archive_to_mtree_from_fd; + ostree_kernel_args_free; + ostree_kernel_args_new; + ostree_kernel_args_cleanup; + ostree_kernel_args_replace_take; + ostree_kernel_args_replace; + ostree_kernel_args_replace_argv; + ostree_kernel_args_append; + ostree_kernel_args_append_argv; + ostree_kernel_args_append_argv_filtered; + ostree_kernel_args_new_replace; + ostree_kernel_args_delete; + ostree_kernel_args_delete_key_entry; + ostree_kernel_args_append_proc_cmdline; + ostree_kernel_args_parse_append; + ostree_kernel_args_from_string; + ostree_kernel_args_to_strv; + ostree_kernel_args_to_string; } LIBOSTREE_2018.9; /* Stub section for the stable release *after* this development one; don't diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c index 87a93806..4cd955d5 100644 --- a/src/libostree/ostree-bootloader-uboot.c +++ b/src/libostree/ostree-bootloader-uboot.c @@ -78,8 +78,8 @@ append_system_uenv (OstreeBootloaderUboot *self, const char *uenv_path = NULL; const char *ostree_arg = NULL; - kargs = _ostree_kernel_args_from_string (bootargs); - ostree_arg = _ostree_kernel_args_get_last_value (kargs, "ostree"); + kargs = ostree_kernel_args_from_string (bootargs); + ostree_arg = ostree_kernel_args_get_last_value (kargs, "ostree"); if (!ostree_arg) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, diff --git a/src/libostree/ostree-kernel-args.c b/src/libostree/ostree-kernel-args.c index ac4014fa..dbf2ec8a 100644 --- a/src/libostree/ostree-kernel-args.c +++ b/src/libostree/ostree-kernel-args.c @@ -21,6 +21,7 @@ #include "ostree-kernel-args.h" #include "libglnx.h" +#include "otutil.h" #include @@ -60,8 +61,24 @@ _arg_has_prefix (const char *arg, return FALSE; } +static gboolean +strcmp0_equal (gconstpointer v1, + gconstpointer v2) +{ + return g_strcmp0 (v1, v2) == 0; +} + +/** + * ostree_kernel_args_new: (skip) + * + * Initializes a new OstreeKernelArgs structure and returns it + * + * Returns: (transfer full): A newly created #OstreeKernelArgs for kernel arguments + * + * Since: 2019.3 + **/ OstreeKernelArgs * -_ostree_kernel_args_new (void) +ostree_kernel_args_new (void) { OstreeKernelArgs *ret; ret = g_new0 (OstreeKernelArgs, 1); @@ -71,8 +88,16 @@ _ostree_kernel_args_new (void) return ret; } +/** + * ostree_kernel_args_free: + * @kargs: An OstreeKernelArgs that represents kernel arguments + * + * Frees the kargs structure + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_free (OstreeKernelArgs *kargs) +ostree_kernel_args_free (OstreeKernelArgs *kargs) { if (!kargs) return; @@ -81,9 +106,238 @@ _ostree_kernel_args_free (OstreeKernelArgs *kargs) g_free (kargs); } +/** + * ostree_kernel_args_cleanup: + * @loc: Address of an OstreeKernelArgs pointer + * + * Frees the OstreeKernelArgs structure pointed by *loc + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, - char *arg) +ostree_kernel_args_cleanup (void *loc) +{ + ostree_kernel_args_free (*((OstreeKernelArgs**)loc)); +} + +/** + * _ostree_kernel_arg_get_kargs_table: + * @kargs: An OstreeKernelArgs that represents kernel arguments + * + * Returns: (transfer none): #GHashTable that associates with the @kargs + * + * Note: this function is private for now, since the data structures underneath might be changed + * + * Since: 2019.3 + **/ +GHashTable* +_ostree_kernel_arg_get_kargs_table (OstreeKernelArgs *kargs) +{ + if (kargs != NULL) + return kargs->table; + return NULL; +} + +/** + * _ostree_kernel_arg_get_key_array: + * @kargs: An OstreeKernelArgs that represents kernel arguments + * + * Returns: (transfer none) (element-type utf8): #GPtrArray that associates with @kargs + * + * Note: this function is private for now, since the data structures underneath might be changed + * + * Since: 2019.3 + **/ +GPtrArray* +_ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs) +{ + if (kargs != NULL) + return kargs->order; + return NULL; +} + +/** + * ostree_kernel_args_new_replace: + * @kargs: OstreeKernelArgs instance + * @arg: a string argument + * @error: error instance + * + * This function implements the basic logic behind key/value pair + * replacement. Do note that the arg need to be properly formatted + * + * When replacing key with exact one value, the arg can be in + * the form: + * key, key=new_val, or key=old_val=new_val + * The first one swaps the old_val with the key to an empty value + * The second and third replace the old_val into the new_val + * + * When replacing key with multiple values, the arg can only be + * in the form of: + * key=old_val=new_val. Unless there is a special case where + * there is an empty value associated with the key, then + * key=new_val will work because old_val is empty. The empty + * val will be swapped with the new_val in that case + * + * Returns: %TRUE on success, %FALSE on failure (and in some other instances such as: + * 1. key not found in @kargs + * 2. old value not found when @arg is in the form of key=old_val=new_val + * 3. multiple old values found when @arg is in the form of key=old_val) + * + * Since: 2019.3 + **/ +gboolean +ostree_kernel_args_new_replace (OstreeKernelArgs *kargs, + const char *arg, + GError **error) +{ + g_autofree char *arg_owned = g_strdup (arg); + const char *key = arg_owned; + const char *val = split_keyeq (arg_owned); + + GPtrArray *values = g_hash_table_lookup (kargs->table, key); + if (!values) + return glnx_throw (error, "No key '%s' found", key); + g_assert_cmpuint (values->len, >, 0); + + /* first handle the case where the user just wants to replace an old value */ + if (val && strchr (val, '=')) + { + g_autofree char *old_val = g_strdup (val); + const char *new_val = split_keyeq (old_val); + g_assert (new_val); + + guint i = 0; + if (!ot_ptr_array_find_with_equal_func (values, old_val, strcmp0_equal, &i)) + return glnx_throw (error, "No karg '%s=%s' found", key, old_val); + + g_clear_pointer (&values->pdata[i], g_free); + values->pdata[i] = g_strdup (new_val); + return TRUE; + } + + /* can't know which val to replace without the old_val=new_val syntax */ + if (values->len > 1) + return glnx_throw (error, "Multiple values for key '%s' found", key); + + g_clear_pointer (&values->pdata[0], g_free); + values->pdata[0] = g_strdup (val); + return TRUE; +} + +/** + * ostree_kernel_args_delete_key_entry + * @kargs: an OstreeKernelArgs instance + * @key: the key to remove + * @error: an GError instance + * + * This function removes the key entry from the hashtable + * as well from the order pointer array inside kargs + * + * Note: since both table and order inside kernel args + * are with free function, no extra free functions are + * being called as they are done automatically by GLib + * + * Returns: %TRUE on success, %FALSE on failure + * + * Since: 2019.3 + **/ +gboolean +ostree_kernel_args_delete_key_entry (OstreeKernelArgs *kargs, + const char *key, + GError **error) +{ + if (!g_hash_table_remove (kargs->table, key)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to find kernel argument '%s'", + key); + return FALSE; + } + + /* Then remove the key from order table */ + guint key_index; + g_assert (ot_ptr_array_find_with_equal_func (kargs->order, key, g_str_equal, &key_index)); + g_assert (g_ptr_array_remove_index (kargs->order, key_index)); + return TRUE; +} + +/** + * ostree_kernel_args_delete: + * @kargs: a OstreeKernelArgs instance + * @arg: key or key/value pair for deletion + * @error: an GError instance + * + * There are few scenarios being handled for deletion: + * + * 1: for input arg with a single key(i.e without = for split), + * the key/value pair will be deleted if there is only + * one value that is associated with the key + * + * 2: for input arg wth key/value pair, the specific key + * value pair will be deleted from the pointer array + * if those exist. + * + * 3: If the found key has only one value + * associated with it, the key entry in the table will also + * be removed, and the key will be removed from order table + * + * Returns: %TRUE on success, %FALSE on failure + * + * Since: 2019.3 + **/ +gboolean +ostree_kernel_args_delete (OstreeKernelArgs *kargs, + const char *arg, + GError **error) +{ + g_autofree char *arg_owned = g_strdup (arg); + const char *key = arg_owned; + const char *val = split_keyeq (arg_owned); + + GPtrArray *values = g_hash_table_lookup (kargs->table, key); + if (!values) + return glnx_throw (error, "No key '%s' found", key); + g_assert_cmpuint (values->len, >, 0); + + /* special-case: we allow deleting by key only if there's only one val */ + if (values->len == 1) + { + /* but if a specific val was passed, check that it's the same */ + if (val && !strcmp0_equal (val, values->pdata[0])) + return glnx_throw (error, "No karg '%s=%s' found", key, val); + return ostree_kernel_args_delete_key_entry (kargs, key, error); + } + + /* note val might be NULL here, in which case we're looking for `key`, not `key=` or + * `key=val` */ + guint i = 0; + if (!ot_ptr_array_find_with_equal_func (values, val, strcmp0_equal, &i)) + { + if (!val) + /* didn't find NULL -> only key= key=val1 key=val2 style things left, so the user + * needs to be more specific */ + return glnx_throw (error, "Multiple values for key '%s' found", arg); + return glnx_throw (error, "No karg '%s' found", arg); + } + + g_ptr_array_remove_index (values, i); + return TRUE; +} + +/** + * ostree_kernel_args_replace_take: + * @kargs: a OstreeKernelArgs instance + * @arg: (transfer full): key or key/value pair for replacement + * + * Finds and replaces the old key if @arg is already in the hash table, + * otherwise adds @arg as new key and split_keyeq (arg) as value. + * Note that when replacing old key, the old values are freed. + * + * Since: 2019.3 + **/ +void +ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, + char *arg) { gboolean existed; GPtrArray *values = g_ptr_array_new_with_free_func (g_free); @@ -105,16 +359,38 @@ _ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, } } +/** + * ostree_kernel_args_replace: + * @kargs: a OstreeKernelArgs instance + * @arg: key or key/value pair for replacement + * + * Finds and replaces the old key if @arg is already in the hash table, + * otherwise adds @arg as new key and split_keyeq (arg) as value. + * Note that when replacing old key value pair, the old values are freed. + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_replace (OstreeKernelArgs *kargs, - const char *arg) +ostree_kernel_args_replace (OstreeKernelArgs *kargs, + const char *arg) { - _ostree_kernel_args_replace_take (kargs, g_strdup (arg)); + ostree_kernel_args_replace_take (kargs, g_strdup (arg)); } +/** + * ostree_kernel_args_append: + * @kargs: a OstreeKernelArgs instance + * @arg: key or key/value pair to be added + * + * Appends @arg which is in the form of key=value pair to the hash table kargs->table + * (appends to the value list if key is already in the hash table) + * and appends key to kargs->order if it is not in the hash table already. + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_append (OstreeKernelArgs *kargs, - const char *arg) +ostree_kernel_args_append (OstreeKernelArgs *kargs, + const char *arg) { gboolean existed = TRUE; GPtrArray *values; @@ -141,23 +417,44 @@ _ostree_kernel_args_append (OstreeKernelArgs *kargs, } } +/** + * ostree_kernel_args_replace_argv: + * @kargs: a OstreeKernelArgs instance + * @argv: an array of key or key/value pairs + * + * Finds and replaces each non-null arguments of @argv in the hash table, + * otherwise adds individual arg as new key and split_keyeq (arg) as value. + * Note that when replacing old key value pair, the old values are freed. + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs, - char **argv) +ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs, + char **argv) { char **strviter; for (strviter = argv; strviter && *strviter; strviter++) { const char *arg = *strviter; - _ostree_kernel_args_replace (kargs, arg); + ostree_kernel_args_replace (kargs, arg); } } +/** + * ostree_kernel_args_append_argv_filtered: + * @kargs: a OstreeKernelArgs instance + * @argv: an array of key=value argument pairs + * @prefixes: an array of prefix strings + * + * Appends each argument that does not have one of the @prefixes as prefix to the @kargs + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs, - char **argv, - char **prefixes) +ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs, + char **argv, + char **prefixes) { char **strviter; @@ -166,21 +463,44 @@ _ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs, const char *arg = *strviter; if (!_arg_has_prefix (arg, prefixes)) - _ostree_kernel_args_append (kargs, arg); + ostree_kernel_args_append (kargs, arg); } } +/** + * ostree_kernel_args_append_argv: + * @kargs: a OstreeKernelArgs instance + * @argv: an array of key=value argument pairs + * + * Appends each value in @argv to the corresponding value array and + * appends key to kargs->order if it is not in the hash table already. + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_append_argv (OstreeKernelArgs *kargs, - char **argv) +ostree_kernel_args_append_argv (OstreeKernelArgs *kargs, + char **argv) { - _ostree_kernel_args_append_argv_filtered (kargs, argv, NULL); + ostree_kernel_args_append_argv_filtered (kargs, argv, NULL); } +/** + * ostree_kernel_args_append_proc_cmdline: + * @kargs: a OstreeKernelArgs instance + * @cancellable: optional GCancellable object, NULL to ignore + * @error: an GError instance + * + * Appends the command line arguments in the file "/proc/cmdline" + * that does not have "BOOT_IMAGE=" and "initrd=" as prefixes to the @kargs + * + * Returns: %TRUE on success, %FALSE on failure + * + * Since: 2019.3 + **/ gboolean -_ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs, - GCancellable *cancellable, - GError **error) +ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs, + GCancellable *cancellable, + GError **error) { g_autoptr(GFile) proc_cmdline_path = g_file_new_for_path ("/proc/cmdline"); g_autofree char *proc_cmdline = NULL; @@ -202,44 +522,76 @@ _ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs, g_strchomp (proc_cmdline); proc_cmdline_args = g_strsplit (proc_cmdline, " ", -1); - _ostree_kernel_args_append_argv_filtered (kargs, proc_cmdline_args, + ostree_kernel_args_append_argv_filtered (kargs, proc_cmdline_args, filtered_prefixes); return TRUE; } +/** + * ostree_kernel_args_parse_append: + * @kargs: a OstreeKernelArgs instance + * @options: a string representing command line arguments + * + * Parses @options by separating it by whitespaces and appends each argument to @kargs + * + * Since: 2019.3 + **/ void -_ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, - const char *options) +ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, + const char *options) { char **args = NULL; char **iter; if (!options) return; - + args = g_strsplit (options, " ", -1); for (iter = args; *iter; iter++) { char *arg = *iter; - _ostree_kernel_args_append (kargs, arg); + ostree_kernel_args_append (kargs, arg); } g_strfreev (args); } +/** + * ostree_kernel_args_from_string: (skip) + * @options: a string representing command line arguments + * + * Initializes a new OstreeKernelArgs then parses and appends @options + * to the empty OstreeKernelArgs + * + * Returns: (transfer full): newly allocated #OstreeKernelArgs with @options appended + * + * Since: 2019.3 + **/ OstreeKernelArgs * -_ostree_kernel_args_from_string (const char *options) +ostree_kernel_args_from_string (const char *options) { OstreeKernelArgs *ret; - ret = _ostree_kernel_args_new (); - _ostree_kernel_args_parse_append (ret, options); + ret = ostree_kernel_args_new (); + ostree_kernel_args_parse_append (ret, options); return ret; } +/** + * ostree_kernel_args_to_strv: + * @kargs: a OstreeKernelArgs instance + * + * Extracts all key value pairs in @kargs and appends to a temporary + * array in forms of "key=value" or "key" if value is NULL, and returns + * the temporary array with the GPtrArray wrapper freed + * + * Returns: (transfer full): an array of "key=value" pairs or "key" if value is NULL + * + * Since: 2019.3 + **/ char ** -_ostree_kernel_args_to_strv (OstreeKernelArgs *kargs) +ostree_kernel_args_to_strv (OstreeKernelArgs *kargs) { GPtrArray *strv = g_ptr_array_new (); guint i; @@ -266,8 +618,25 @@ _ostree_kernel_args_to_strv (OstreeKernelArgs *kargs) return (char**)g_ptr_array_free (strv, FALSE); } +/** + * ostree_kernel_args_to_string: + * @kargs: a OstreeKernelArgs instance + * + * Extracts all key value pairs in @kargs and appends to a temporary + * GString in forms of "key=value" or "key" if value is NULL separated + * by a single whitespace, and returns the temporary string with the + * GString wrapper freed + * + * Note: the application will be terminated if one of the values array + * in @kargs is NULL + * + * Returns: (transfer full): a string of "key=value" pairs or "key" if value is NULL, + * separated by single whitespaces + * + * Since: 2019.3 + **/ char * -_ostree_kernel_args_to_string (OstreeKernelArgs *kargs) +ostree_kernel_args_to_string (OstreeKernelArgs *kargs) { GString *buf = g_string_new (""); gboolean first = TRUE; @@ -302,8 +671,22 @@ _ostree_kernel_args_to_string (OstreeKernelArgs *kargs) return g_string_free (buf, FALSE); } +/** + * ostree_kernel_args_get_last_value: + * @kargs: a OstreeKernelArgs instance + * @key: a key to look for in @kargs hash table + * + * Finds and returns the last element of value array + * corresponding to the @key in @kargs hash table. Note that the application + * will be terminated if the @key is found but the value array is empty + * + * Returns: NULL if @key is not found in the @kargs hash table, + * otherwise returns last element of value array corresponding to @key + * + * Since: 2019.3 + **/ const char * -_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key) +ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key) { GPtrArray *values = g_hash_table_lookup (kargs->table, key); diff --git a/src/libostree/ostree-kernel-args.h b/src/libostree/ostree-kernel-args.h index 0bc43704..d7beca51 100644 --- a/src/libostree/ostree-kernel-args.h +++ b/src/libostree/ostree-kernel-args.h @@ -19,41 +19,90 @@ #pragma once -#include "libglnx.h" +#include +#include +#include +#include "ostree-types.h" G_BEGIN_DECLS typedef struct _OstreeKernelArgs OstreeKernelArgs; -void _ostree_kernel_args_free (OstreeKernelArgs *kargs); -G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelArgs, _ostree_kernel_args_free); -OstreeKernelArgs *_ostree_kernel_args_new (void); -void _ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, - char *key); -void _ostree_kernel_args_replace (OstreeKernelArgs *kargs, - const char *key); -void _ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs, - char **argv); -void _ostree_kernel_args_append (OstreeKernelArgs *kargs, - const char *key); -void _ostree_kernel_args_append_argv (OstreeKernelArgs *kargs, - char **argv); -void _ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs, - char **argv, - char **prefixes); +GHashTable *_ostree_kernel_arg_get_kargs_table (OstreeKernelArgs *kargs); -gboolean _ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs, - GCancellable *cancellable, - GError **error); +GPtrArray *_ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs); -void _ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, - const char *options); +_OSTREE_PUBLIC +void ostree_kernel_args_free (OstreeKernelArgs *kargs); -const char *_ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, const char *key); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelArgs, ostree_kernel_args_free) -OstreeKernelArgs * _ostree_kernel_args_from_string (const char *options); +_OSTREE_PUBLIC +OstreeKernelArgs *ostree_kernel_args_new (void); -char ** _ostree_kernel_args_to_strv (OstreeKernelArgs *kargs); -char * _ostree_kernel_args_to_string (OstreeKernelArgs *kargs); +_OSTREE_PUBLIC +void ostree_kernel_args_cleanup (void *loc); + +_OSTREE_PUBLIC +void ostree_kernel_args_replace_take (OstreeKernelArgs *kargs, + char *arg); + +_OSTREE_PUBLIC +void ostree_kernel_args_replace (OstreeKernelArgs *kargs, + const char *arg); + +_OSTREE_PUBLIC +void ostree_kernel_args_replace_argv (OstreeKernelArgs *kargs, + char **argv); + +_OSTREE_PUBLIC +void ostree_kernel_args_append (OstreeKernelArgs *kargs, + const char *arg); + +_OSTREE_PUBLIC +void ostree_kernel_args_append_argv (OstreeKernelArgs *kargs, + char **argv); + +_OSTREE_PUBLIC +void ostree_kernel_args_append_argv_filtered (OstreeKernelArgs *kargs, + char **argv, + char **prefixes); + +_OSTREE_PUBLIC +gboolean ostree_kernel_args_new_replace (OstreeKernelArgs *kargs, + const char *arg, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_kernel_args_delete (OstreeKernelArgs *kargs, + const char *arg, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_kernel_args_delete_key_entry (OstreeKernelArgs *kargs, + const char *key, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_kernel_args_append_proc_cmdline (OstreeKernelArgs *kargs, + GCancellable *cancellable, + GError **error); + +_OSTREE_PUBLIC +void ostree_kernel_args_parse_append (OstreeKernelArgs *kargs, + const char *options); + +_OSTREE_PUBLIC +const char *ostree_kernel_args_get_last_value (OstreeKernelArgs *kargs, + const char *key); + +_OSTREE_PUBLIC +OstreeKernelArgs *ostree_kernel_args_from_string (const char *options); + +_OSTREE_PUBLIC +char **ostree_kernel_args_to_strv (OstreeKernelArgs *kargs); + +_OSTREE_PUBLIC +char *ostree_kernel_args_to_string (OstreeKernelArgs *kargs); G_END_DECLS diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index 1096b0b0..d47f6438 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1759,7 +1759,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath); val = ostree_bootconfig_parser_get (bootconfig, "options"); - g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_from_string (val); + g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (val); if (kernel_layout->initramfs_namever) { @@ -1772,7 +1772,7 @@ install_deployment_kernel (OstreeSysroot *sysroot, prepare_root_arg = g_strdup_printf ("init=/ostree/boot.%d/%s/%s/%d/usr/lib/ostree/ostree-prepare-root", new_bootversion, osname, bootcsum, ostree_deployment_get_bootserial (deployment)); - _ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg)); + ostree_kernel_args_replace_take (kargs, g_steal_pointer (&prepare_root_arg)); } if (kernel_layout->devicetree_namever) @@ -1785,9 +1785,9 @@ install_deployment_kernel (OstreeSysroot *sysroot, 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)); - _ostree_kernel_args_replace_take (kargs, g_steal_pointer (&ostree_kernel_arg)); + ostree_kernel_args_replace_take (kargs, g_steal_pointer (&ostree_kernel_arg)); - g_autofree char *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_autofd int bootconf_dfd = -1; @@ -1895,9 +1895,9 @@ get_deployment_nonostree_kargs (OstreeDeployment *deployment) /* pick up kernel arguments but filter out ostree= */ OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment); const char *boot_options = ostree_bootconfig_parser_get (bootconfig, "options"); - g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_from_string (boot_options); - _ostree_kernel_args_replace (kargs, "ostree"); - return _ostree_kernel_args_to_string (kargs); + g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (boot_options); + ostree_kernel_args_replace (kargs, "ostree"); + return ostree_kernel_args_to_string (kargs); } static char* @@ -2463,9 +2463,9 @@ _ostree_deployment_set_bootconfig_from_kargs (OstreeDeployment *deployment, */ if (override_kernel_argv) { - g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_append_argv (kargs, override_kernel_argv); - g_autofree char *new_options = _ostree_kernel_args_to_string (kargs); + g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new (); + ostree_kernel_args_append_argv (kargs, override_kernel_argv); + g_autofree char *new_options = ostree_kernel_args_to_string (kargs); ostree_bootconfig_parser_set (bootconfig, "options", new_options); } } @@ -3004,9 +3004,9 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self, g_autoptr(OstreeDeployment) new_deployment = ostree_deployment_clone (deployment); OstreeBootconfigParser *new_bootconfig = ostree_deployment_get_bootconfig (new_deployment); - g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_append_argv (kargs, new_kargs); - g_autofree char *new_options = _ostree_kernel_args_to_string (kargs); + g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new (); + ostree_kernel_args_append_argv (kargs, new_kargs); + g_autofree char *new_options = ostree_kernel_args_to_string (kargs); ostree_bootconfig_parser_set (new_bootconfig, "options", new_options); g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref); diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h index e4b2039e..858673c5 100644 --- a/src/libostree/ostree-sysroot-private.h +++ b/src/libostree/ostree-sysroot-private.h @@ -23,7 +23,6 @@ #include "libglnx.h" #include "ostree.h" -#include "ostree-kernel-args.h" #include "ostree-bootloader.h" G_BEGIN_DECLS diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 4862b7b4..b3ad2498 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1688,12 +1688,12 @@ clone_deployment (OstreeSysroot *sysroot, /* Copy the bootloader config options */ OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); - g_autoptr(OstreeKernelArgs) kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_append_argv (kargs, previous_args); + g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_new (); + ostree_kernel_args_append_argv (kargs, previous_args); /* Deploy the copy */ g_autoptr(OstreeDeployment) new_deployment = NULL; - g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); + g_auto(GStrv) kargs_strv = ostree_kernel_args_to_strv (kargs); if (!ostree_sysroot_deploy_tree (sysroot, ostree_deployment_get_osname (target_deployment), ostree_deployment_get_csum (target_deployment), diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h index cbeb99b2..ca19bc85 100644 --- a/src/libostree/ostree.h +++ b/src/libostree/ostree.h @@ -41,3 +41,4 @@ #include #include #include +#include diff --git a/src/libotutil/ot-tool-util.c b/src/libotutil/ot-tool-util.c index d6f37bc9..35e6a343 100644 --- a/src/libotutil/ot-tool-util.c +++ b/src/libotutil/ot-tool-util.c @@ -62,3 +62,55 @@ ot_parse_keyvalue (const char *keyvalue, *out_value = g_strdup (eq + 1); return TRUE; } + +/** + * Note: temporarily copied from GLib: https://github.com/GNOME/glib/blob/a419146578a42c760cff684292465b38df855f75/glib/garray.c#L1664 + * See documentation at: https://developer.gnome.org/glib/stable/glib-Pointer-Arrays.html#g-ptr-array-find-with-equal-func + * + * ot_ptr_array_find_with_equal_func: (skip) + * @haystack: pointer array to be searched + * @needle: pointer to look for + * @equal_func: (nullable): the function to call for each element, which should + * return %TRUE when the desired element is found; or %NULL to use pointer + * equality + * @index_: (optional) (out caller-allocates): return location for the index of + * the element, if found + * + * Checks whether @needle exists in @haystack, using the given @equal_func. + * If the element is found, %TRUE is returned and the element’s index is + * returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_ + * is undefined. If @needle exists multiple times in @haystack, the index of + * the first instance is returned. + * + * @equal_func is called with the element from the array as its first parameter, + * and @needle as its second parameter. If @equal_func is %NULL, pointer + * equality is used. + * + * Returns: %TRUE if @needle is one of the elements of @haystack + * Since: 2.54 + */ +gboolean +ot_ptr_array_find_with_equal_func (GPtrArray *haystack, + gconstpointer needle, + GEqualFunc equal_func, + guint *index_) +{ + guint i; + + g_return_val_if_fail (haystack != NULL, FALSE); + + if (equal_func == NULL) + equal_func = g_direct_equal; + + for (i = 0; i < haystack->len; i++) + { + if (equal_func (g_ptr_array_index (haystack, i), needle)) + { + if (index_ != NULL) + *index_ = i; + return TRUE; + } + } + + return FALSE; +} diff --git a/src/libotutil/ot-tool-util.h b/src/libotutil/ot-tool-util.h index e3381730..70f7d55d 100644 --- a/src/libotutil/ot-tool-util.h +++ b/src/libotutil/ot-tool-util.h @@ -34,5 +34,10 @@ ot_parse_keyvalue (const char *keyvalue, char **out_key, char **out_value, GError **error); +gboolean +ot_ptr_array_find_with_equal_func (GPtrArray *haystack, + gconstpointer needle, + GEqualFunc equal_func, + guint *index_); G_END_DECLS diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index eced95f9..8f1bd4e7 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -62,3 +62,4 @@ #include #include #include +#include diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index 38ec923f..c1c3353d 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -29,8 +29,6 @@ #include "ostree.h" #include "otutil.h" -#include "../libostree/ostree-kernel-args.h" - #include static gboolean opt_retain; @@ -133,20 +131,20 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat g_autoptr(OstreeKernelArgs) kargs = NULL; if (opt_kernel_arg_none) { - kargs = _ostree_kernel_args_new (); + kargs = ostree_kernel_args_new (); } else if (opt_kernel_proc_cmdline) { - kargs = _ostree_kernel_args_new (); - if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) + kargs = ostree_kernel_args_new (); + if (!ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) return FALSE; } else if (merge_deployment && (opt_kernel_argv || opt_kernel_argv_append)) { OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment); g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); - kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_append_argv (kargs, previous_args); + kargs = ostree_kernel_args_new (); + ostree_kernel_args_append_argv (kargs, previous_args); } /* Now replace/extend the above set. Note that if no options are specified, @@ -156,19 +154,19 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeCommandInvocation *invocat if (opt_kernel_argv) { if (!kargs) - kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_replace_argv (kargs, opt_kernel_argv); + kargs = ostree_kernel_args_new (); + ostree_kernel_args_replace_argv (kargs, opt_kernel_argv); } if (opt_kernel_argv_append) { if (!kargs) - kargs = _ostree_kernel_args_new (); - _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); + kargs = ostree_kernel_args_new (); + ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); } g_autoptr(OstreeDeployment) new_deployment = NULL; - g_auto(GStrv) kargs_strv = kargs ? _ostree_kernel_args_to_strv (kargs) : NULL; + g_auto(GStrv) kargs_strv = kargs ? ostree_kernel_args_to_strv (kargs) : NULL; if (opt_stage) { if (opt_retain_pending || opt_retain_rollback) diff --git a/src/ostree/ot-admin-builtin-unlock.c b/src/ostree/ot-admin-builtin-unlock.c index f0efa44a..cd466183 100644 --- a/src/ostree/ot-admin-builtin-unlock.c +++ b/src/ostree/ot-admin-builtin-unlock.c @@ -27,8 +27,6 @@ #include "ostree.h" #include "otutil.h" -#include "../libostree/ostree-kernel-args.h" - #include #include diff --git a/src/ostree/ot-admin-instutil-builtin-set-kargs.c b/src/ostree/ot-admin-instutil-builtin-set-kargs.c index 666e5369..fb5c7d2d 100644 --- a/src/ostree/ot-admin-instutil-builtin-set-kargs.c +++ b/src/ostree/ot-admin-instutil-builtin-set-kargs.c @@ -26,8 +26,7 @@ #include "ot-admin-instutil-builtins.h" #include "otutil.h" - -#include "../libostree/ostree-kernel-args.h" +#include "ostree.h" static gboolean opt_proc_cmdline; static gboolean opt_merge; @@ -69,14 +68,14 @@ ot_admin_instutil_builtin_set_kargs (int argc, char **argv, OstreeCommandInvocat } first_deployment = deployments->pdata[0]; - kargs = _ostree_kernel_args_new (); + kargs = ostree_kernel_args_new (); /* If they want the current kernel's args, they very likely don't * want the ones from the merge. */ if (opt_proc_cmdline) { - if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) + if (!ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error)) goto out; } else if (opt_merge) @@ -84,24 +83,24 @@ ot_admin_instutil_builtin_set_kargs (int argc, char **argv, OstreeCommandInvocat OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (first_deployment); g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1); - _ostree_kernel_args_append_argv (kargs, previous_args); + ostree_kernel_args_append_argv (kargs, previous_args); } if (opt_replace) { - _ostree_kernel_args_replace_argv (kargs, opt_replace); + ostree_kernel_args_replace_argv (kargs, opt_replace); } if (opt_append) { - _ostree_kernel_args_append_argv (kargs, opt_append); + ostree_kernel_args_append_argv (kargs, opt_append); } for (i = 1; i < argc; i++) - _ostree_kernel_args_append (kargs, argv[i]); + ostree_kernel_args_append (kargs, argv[i]); { - g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); + g_auto(GStrv) kargs_strv = ostree_kernel_args_to_strv (kargs); if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment, kargs_strv, diff --git a/tests/.gitignore b/tests/.gitignore index 8f03c026..f5e95e49 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -22,3 +22,4 @@ test-repo-finder-avahi test-repo-finder-config test-repo-finder-mount test-rollsum-cli +test-kargs diff --git a/tests/test-kargs.c b/tests/test-kargs.c new file mode 100644 index 00000000..8d34f73c --- /dev/null +++ b/tests/test-kargs.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2015 Red Hat, 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. + */ + +#include "config.h" +#include "ostree-kernel-args.h" +#include "otutil.h" + +static gboolean +check_string_existance (OstreeKernelArgs *karg, + const char *string_to_find) +{ + g_autofree gchar* string_with_spaces = ostree_kernel_args_to_string (karg); + g_auto(GStrv) string_list = g_strsplit (string_with_spaces, " ", -1); + return g_strv_contains ((const char* const*) string_list, string_to_find); +} + +static void +test_kargs_delete (void) +{ + g_autoptr(GError) error = NULL; + gboolean ret; + __attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *karg = ostree_kernel_args_new (); + + ostree_kernel_args_append (karg, "single_key=test"); + ostree_kernel_args_append (karg, "test=firstval"); + ostree_kernel_args_append (karg, "test=secondval"); + ostree_kernel_args_append (karg, "test="); + ostree_kernel_args_append (karg, "test"); + + /* Delete a non-existant key should fail */ + ret = ostree_kernel_args_delete (karg, "non_existant_key", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Delete a key with multiple values when only specifying key should work if a no-value + * variant exists */ + ret = ostree_kernel_args_delete (karg, "test", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test")); + + /* Trying again now should fail since there are only kargs with various values */ + ret = ostree_kernel_args_delete (karg, "test", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Delete a key with a non existant value should fail */ + ret = ostree_kernel_args_delete (karg, "test=non_existant_value", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Delete a key with only one value should fail if the value doesn't match */ + ret = ostree_kernel_args_delete (karg, "single_key=non_existent_value", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Delete a key with only one value should succeed by only specifying key */ + ret = ostree_kernel_args_delete (karg, "single_key", &error); + g_assert_no_error (error); + g_assert (ret); + /* verify the value array is properly updated */ + GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (karg); + g_assert (!ot_ptr_array_find_with_equal_func (kargs_array, "single_key", g_str_equal, NULL)); + g_assert (!check_string_existance (karg, "single_key")); + + /* Delete specific key/value pair */ + ret = ostree_kernel_args_delete (karg, "test=secondval", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test=secondval")); + + /* Delete key/value pair with empty string value */ + ret = ostree_kernel_args_delete (karg, "test=", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test=")); + + ret = ostree_kernel_args_delete (karg, "test=firstval", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test=firstval")); + + /* Check that we can delete duplicate keys */ + ostree_kernel_args_append (karg, "test=foo"); + ostree_kernel_args_append (karg, "test=foo"); + check_string_existance (karg, "test=foo"); + ret = ostree_kernel_args_delete (karg, "test=foo", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (check_string_existance (karg, "test=foo")); + ret = ostree_kernel_args_delete (karg, "test=foo", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test=foo")); + + /* Make sure we also gracefully do this for key-only args */ + ostree_kernel_args_append (karg, "nosmt"); + ostree_kernel_args_append (karg, "nosmt"); + check_string_existance (karg, "nosmt"); + ret = ostree_kernel_args_delete (karg, "nosmt", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (check_string_existance (karg, "nosmt")); + ret = ostree_kernel_args_delete (karg, "nosmt", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "nosmt")); +} + +static void +test_kargs_replace (void) +{ + g_autoptr(GError) error = NULL; + gboolean ret; + __attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *karg = ostree_kernel_args_new (); + + ostree_kernel_args_append (karg, "single_key"); + ostree_kernel_args_append (karg, "test=firstval"); + ostree_kernel_args_append (karg, "test=secondval"); + + /* Replace when the input key is non-existant should fail */ + ret = ostree_kernel_args_new_replace (karg, "nonexistantkey", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Replace non-existant value with input key=nonexistantvalue=newvalue should fail */ + ret = ostree_kernel_args_new_replace (karg, "single_key=nonexistantval=newval", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Replace with input key=value will fail for a key with multiple values */ + ret = ostree_kernel_args_new_replace (karg, "test=newval", &error); + g_assert (!ret); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); + g_clear_error (&error); + + /* Replace with input key=value for a key with single value should succeed + * Also note, we also allow ''(empty string) valid to be a value + */ + ret = ostree_kernel_args_new_replace (karg, "single_key=newvalue", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "single_key")); + g_assert (check_string_existance (karg, "single_key=newvalue")); + + /* Replace with input key=value=newvalue if key and value both + * exist, the action should succeed + */ + ret = ostree_kernel_args_new_replace (karg, "test=firstval=newval", &error); + g_assert_no_error (error); + g_assert (ret); + g_assert (!check_string_existance (karg, "test=firstval")); + g_assert (check_string_existance (karg, "test=newval")); +} + +static gboolean +strcmp0_equal (gconstpointer v1, + gconstpointer v2) +{ + return g_strcmp0 (v1, v2) == 0; +} + +/* In this function, we want to verify that ostree_kernel_args_append + * and ostree_kernel_args_to_string is correct. After that + * we will use these two functions(append and tostring) in other tests: delete and replace + */ +static void +test_kargs_append (void) +{ + __attribute__((cleanup(ostree_kernel_args_cleanup))) OstreeKernelArgs *append_arg = ostree_kernel_args_new (); + /* Some valid cases (key=value) pair */ + ostree_kernel_args_append (append_arg, "test=valid"); + ostree_kernel_args_append (append_arg, "test=secondvalid"); + ostree_kernel_args_append (append_arg, "test="); + ostree_kernel_args_append (append_arg, "test"); + ostree_kernel_args_append (append_arg, "second_test"); + + /* We loops through the kargs inside table to verify + * the functionality of append because at this stage + * we have yet to find the conversion kargs to string fully "functional" + */ + GHashTable *kargs_table = _ostree_kernel_arg_get_kargs_table (append_arg); + GLNX_HASH_TABLE_FOREACH_KV (kargs_table, const char*, key, GPtrArray*, value_array) + { + if (g_str_equal (key, "test")) + { + g_assert (ot_ptr_array_find_with_equal_func (value_array, "valid", strcmp0_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (value_array, "secondvalid", strcmp0_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (value_array, "", strcmp0_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL)); + } + else + { + g_assert_cmpstr (key, ==, "second_test"); + g_assert (ot_ptr_array_find_with_equal_func (value_array, NULL, strcmp0_equal, NULL)); + } + } + + /* verify the value array is properly updated */ + GPtrArray *kargs_array = _ostree_kernel_arg_get_key_array (append_arg); + g_assert (ot_ptr_array_find_with_equal_func (kargs_array, "test", g_str_equal, NULL)); + g_assert (ot_ptr_array_find_with_equal_func (kargs_array, "second_test", g_str_equal, NULL)); + + /* Up till this point, we verified that the above was all correct, we then + * check ostree_kernel_args_to_string has the right result + */ + g_autofree gchar* kargs_str = ostree_kernel_args_to_string (append_arg); + g_auto(GStrv) kargs_list = g_strsplit(kargs_str, " ", -1); + g_assert (g_strv_contains ((const char* const *)kargs_list, "test=valid")); + g_assert (g_strv_contains ((const char* const *)kargs_list, "test=secondvalid")); + g_assert (g_strv_contains ((const char* const *)kargs_list, "test=")); + g_assert (g_strv_contains ((const char* const *)kargs_list, "test")); + g_assert (g_strv_contains ((const char* const *)kargs_list, "second_test")); + g_assert_cmpint (5, ==, g_strv_length (kargs_list)); +} + +int +main (int argc, + char *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/kargs/kargs_append", test_kargs_append); + g_test_add_func ("/kargs/kargs_delete", test_kargs_delete); + g_test_add_func ("/kargs/kargs_replace", test_kargs_replace); + return g_test_run (); +} From 901c2f5e5fe3ccefbdb005ee593848d2630c5d39 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 10 Jun 2019 12:01:25 -0500 Subject: [PATCH 24/62] lib/gpg: Factor out expiration timestamp formatting This will be reused to format a key expiration message. Closes: #1872 Approved by: cgwalters --- src/libostree/ostree-gpg-verify-result.c | 74 ++++++++++++++---------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index 2e69e2f9..a2fb8620 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -513,6 +513,49 @@ ostree_gpg_verify_result_describe (OstreeGpgVerifyResult *result, ostree_gpg_verify_result_describe_variant (variant, output_buffer, line_prefix, flags); } +static void +append_expire_info (GString *output_buffer, + const gchar *line_prefix, + const gchar *exp_type, + gint64 exp_timestamp, + gboolean expired) +{ + g_autoptr(GDateTime) date_time_utc = NULL; + g_autoptr(GDateTime) date_time_local = NULL; + g_autofree char *formatted_date_time = NULL; + + if (line_prefix != NULL) + g_string_append (output_buffer, line_prefix); + + date_time_utc = g_date_time_new_from_unix_utc (exp_timestamp); + if (date_time_utc == NULL) + { + g_string_append_printf (output_buffer, + "%s expiry timestamp (%" G_GINT64_FORMAT ") is invalid\n", + exp_type, + exp_timestamp); + return; + } + + date_time_local = g_date_time_to_local (date_time_utc); + formatted_date_time = g_date_time_format (date_time_local, "%c"); + + if (expired) + { + g_string_append_printf (output_buffer, + "%s expired %s\n", + exp_type, + formatted_date_time); + } + else + { + g_string_append_printf (output_buffer, + "%s expires %s\n", + exp_type, + formatted_date_time); + } +} + /** * ostree_gpg_verify_result_describe_variant: * @variant: a #GVariant from ostree_gpg_verify_result_get_all() @@ -652,35 +695,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, } if (exp_timestamp > 0) - { - if (line_prefix != NULL) - g_string_append (output_buffer, line_prefix); - - date_time_utc = g_date_time_new_from_unix_utc (exp_timestamp); - if (date_time_utc == NULL) - { - g_string_append_printf (output_buffer, - "Signature expiry timestamp (%" G_GINT64_FORMAT ") is invalid\n", - exp_timestamp); - return; - } - - date_time_local = g_date_time_to_local (date_time_utc); - formatted_date_time = g_date_time_format (date_time_local, "%c"); - - if (sig_expired) - { - g_string_append_printf (output_buffer, - "Signature expired %s\n", - formatted_date_time); - } - else - { - g_string_append_printf (output_buffer, - "Signature expires %s\n", - formatted_date_time); - } - } + append_expire_info (output_buffer, line_prefix, "Signature", exp_timestamp, + sig_expired); } /** From d714e622b8318f38007d50471b8e3bc565f3c0b6 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 10 Jun 2019 12:05:21 -0500 Subject: [PATCH 25/62] lib/gpg: Show information for expired keys Introduce a new signature attribute for the key expiration timestamp and display it when the key has a non-zero expiration time. Without this, the error shown is `BAD signature`, which isn't correct. Closes: #1872 Approved by: cgwalters --- src/libostree/ostree-gpg-verify-result.c | 49 ++++++++++++++++++++++-- src/libostree/ostree-gpg-verify-result.h | 10 +++++ tests/test-gpg-verify-result.c | 40 +++++++++++++------ 3 files changed, 84 insertions(+), 15 deletions(-) diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index a2fb8620..5a8888e7 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -65,7 +65,9 @@ static OstreeGpgSignatureAttr all_signature_attrs[] = { OSTREE_GPG_SIGNATURE_ATTR_HASH_ALGO_NAME, OSTREE_GPG_SIGNATURE_ATTR_USER_NAME, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL, - OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY + OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY, + OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP, + OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY, }; static void ostree_gpg_verify_result_initable_iface_init (GInitableIface *iface); @@ -331,7 +333,9 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result, { if (attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_NAME || attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL || - attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY) + attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY || + attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP || + attrs[ii] == OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY) { (void) gpgme_get_key (result->context, signature->fpr, &key, 0); break; @@ -345,6 +349,7 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result, GVariant *child; gboolean v_boolean; const char *v_string = NULL; + gint64 v_int64; switch (attrs[ii]) { @@ -423,6 +428,29 @@ ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result, child = g_variant_new_string (v_string); break; + case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP: + v_int64 = 0; + if (key != NULL) + { + gpgme_subkey_t subkey = key->subkeys; + + while (subkey != NULL && (g_strcmp0 (subkey->fpr, signature->fpr) != 0)) + subkey = subkey->next; + + if (subkey != NULL) + v_int64 = subkey->expires; + } + child = g_variant_new_int64 (v_int64); + break; + + case OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY: + if (key != NULL && key->subkeys != NULL) + v_int64 = key->subkeys->expires; + else + v_int64 = 0; + child = g_variant_new_int64 (v_int64); + break; + default: g_critical ("Invalid signature attribute (%d)", attrs[ii]); g_variant_builder_clear (&builder); @@ -581,6 +609,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, g_autofree char *formatted_date_time = NULL; gint64 timestamp; gint64 exp_timestamp; + gint64 key_exp_timestamp; + gint64 key_exp_timestamp_primary; const char *type_string; const char *fingerprint; const char *fingerprint_primary; @@ -590,6 +620,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, const char *key_id; gboolean valid; gboolean sig_expired; + gboolean key_expired; gboolean key_missing; gsize len; @@ -599,7 +630,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, /* Verify the variant's type string. This code is * not prepared to handle just any random GVariant. */ type_string = g_variant_get_type_string (variant); - g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssss)") == 0); + g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssssxx)") == 0); /* The default format roughly mimics the verify output generated by * check_sig_and_print() in gnupg/g10/mainproc.c, though obviously @@ -609,6 +640,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, "b", &valid); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED, "b", &sig_expired); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED, + "b", &key_expired); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING, "b", &key_missing); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT, @@ -625,6 +658,10 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, "&s", &user_name); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL, "&s", &user_email); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP, + "x", &key_exp_timestamp); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY, + "x", &key_exp_timestamp_primary); len = strlen (fingerprint); key_id = (len > 16) ? fingerprint + len - 16 : fingerprint; @@ -697,6 +734,12 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, if (exp_timestamp > 0) append_expire_info (output_buffer, line_prefix, "Signature", exp_timestamp, sig_expired); + if (key_exp_timestamp > 0) + append_expire_info (output_buffer, line_prefix, "Key", key_exp_timestamp, + key_expired); + if (key_exp_timestamp_primary > 0 && (g_strcmp0 (fingerprint, fingerprint_primary) != 0)) + append_expire_info (output_buffer, line_prefix, "Primary key", + key_exp_timestamp_primary, key_expired); } /** diff --git a/src/libostree/ostree-gpg-verify-result.h b/src/libostree/ostree-gpg-verify-result.h index 0a77ec53..7c71ecdc 100644 --- a/src/libostree/ostree-gpg-verify-result.h +++ b/src/libostree/ostree-gpg-verify-result.h @@ -70,6 +70,14 @@ typedef struct OstreeGpgVerifyResult OstreeGpgVerifyResult; * (will be the same as OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT if the * the signature is already from the primary key rather than a subkey, * and will be the empty string if the key is missing.) + * @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP: + * [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp (0 if no + * expiration or if the key is missing) + * @OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY: + * [#G_VARIANT_TYPE_INT64] Key expiration Unix timestamp of the signing key's + * primary key (will be the same as OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP + * if the signing key is the primary key and 0 if no expiration or if the key + * is missing) * * Signature attributes available from an #OstreeGpgVerifyResult. * The attribute's #GVariantType is shown in brackets. @@ -88,6 +96,8 @@ typedef enum { OSTREE_GPG_SIGNATURE_ATTR_USER_NAME, OSTREE_GPG_SIGNATURE_ATTR_USER_EMAIL, OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT_PRIMARY, + OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP, + OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP_PRIMARY, } OstreeGpgSignatureAttr; _OSTREE_PUBLIC diff --git a/tests/test-gpg-verify-result.c b/tests/test-gpg-verify-result.c index 19d6f71e..95de1873 100644 --- a/tests/test-gpg-verify-result.c +++ b/tests/test-gpg-verify-result.c @@ -45,7 +45,8 @@ static OstreeGpgSignatureAttr some_attributes[] = { OSTREE_GPG_SIGNATURE_ATTR_SIG_EXPIRED, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED, OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED, - OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING + OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING, + OSTREE_GPG_SIGNATURE_ATTR_KEY_EXP_TIMESTAMP, }; static void @@ -174,7 +175,7 @@ test_attribute_basics (TestFixture *fixture, tuple = ostree_gpg_verify_result_get_all (fixture->result, ii); type_string = g_variant_get_type_string (tuple); - g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssss)"); + g_assert_cmpstr (type_string, ==, "(bbbbbsxxsssssxx)"); /* Check attributes which should be common to all signatures. */ @@ -221,24 +222,27 @@ test_valid_signature (TestFixture *fixture, gboolean key_expired; gboolean key_revoked; gboolean key_missing; + gint64 key_exp_timestamp; tuple = ostree_gpg_verify_result_get (fixture->result, signature_index, some_attributes, G_N_ELEMENTS (some_attributes)); - g_variant_get (tuple, "(bbbbb)", + g_variant_get (tuple, "(bbbbbx)", &valid, &sig_expired, &key_expired, &key_revoked, - &key_missing); + &key_missing, + &key_exp_timestamp); g_assert_true (valid); g_assert_false (sig_expired); g_assert_false (key_expired); g_assert_false (key_revoked); g_assert_false (key_missing); + g_assert_cmpint (key_exp_timestamp, ==, 0); } static void @@ -252,24 +256,27 @@ test_expired_key (TestFixture *fixture, gboolean key_expired; gboolean key_revoked; gboolean key_missing; + gint64 key_exp_timestamp; tuple = ostree_gpg_verify_result_get (fixture->result, signature_index, some_attributes, G_N_ELEMENTS (some_attributes)); - g_variant_get (tuple, "(bbbbb)", + g_variant_get (tuple, "(bbbbbx)", &valid, &sig_expired, &key_expired, &key_revoked, - &key_missing); + &key_missing, + &key_exp_timestamp); g_assert_false (valid); g_assert_false (sig_expired); g_assert_true (key_expired); g_assert_false (key_revoked); g_assert_false (key_missing); + g_assert_cmpint (key_exp_timestamp, ==, 1426782201); } static void @@ -283,24 +290,27 @@ test_revoked_key (TestFixture *fixture, gboolean key_expired; gboolean key_revoked; gboolean key_missing; + gint64 key_exp_timestamp; tuple = ostree_gpg_verify_result_get (fixture->result, signature_index, some_attributes, G_N_ELEMENTS (some_attributes)); - g_variant_get (tuple, "(bbbbb)", + g_variant_get (tuple, "(bbbbbx)", &valid, &sig_expired, &key_expired, &key_revoked, - &key_missing); + &key_missing, + &key_exp_timestamp); g_assert_false (valid); g_assert_false (sig_expired); g_assert_false (key_expired); g_assert_true (key_revoked); g_assert_false (key_missing); + g_assert_cmpint (key_exp_timestamp, ==, 0); } static void @@ -314,24 +324,27 @@ test_missing_key (TestFixture *fixture, gboolean key_expired; gboolean key_revoked; gboolean key_missing; + gint64 key_exp_timestamp; tuple = ostree_gpg_verify_result_get (fixture->result, signature_index, some_attributes, G_N_ELEMENTS (some_attributes)); - g_variant_get (tuple, "(bbbbb)", + g_variant_get (tuple, "(bbbbbx)", &valid, &sig_expired, &key_expired, &key_revoked, - &key_missing); + &key_missing, + &key_exp_timestamp); g_assert_false (valid); g_assert_false (sig_expired); g_assert_false (key_expired); g_assert_false (key_revoked); g_assert_true (key_missing); + g_assert_cmpint (key_exp_timestamp, ==, 0); } static void @@ -345,24 +358,27 @@ test_expired_signature (TestFixture *fixture, gboolean key_expired; gboolean key_revoked; gboolean key_missing; + gint64 key_exp_timestamp; tuple = ostree_gpg_verify_result_get (fixture->result, signature_index, some_attributes, G_N_ELEMENTS (some_attributes)); - g_variant_get (tuple, "(bbbbb)", + g_variant_get (tuple, "(bbbbbx)", &valid, &sig_expired, &key_expired, &key_revoked, - &key_missing); + &key_missing, + &key_exp_timestamp); g_assert_true (valid); g_assert_true (sig_expired); g_assert_false (key_expired); g_assert_false (key_revoked); g_assert_false (key_missing); + g_assert_cmpint (key_exp_timestamp, ==, 0); } int From d0ec319b6b763deb8f25226175e7ff709a4af8c8 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 10 Jun 2019 12:15:04 -0500 Subject: [PATCH 26/62] lib/gpg: Show if GPG key has been revoked Rather then showing the incorrect `BAD signature`. Closes: #1872 Approved by: cgwalters --- src/libostree/ostree-gpg-verify-result.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libostree/ostree-gpg-verify-result.c b/src/libostree/ostree-gpg-verify-result.c index 5a8888e7..d4d1cef6 100644 --- a/src/libostree/ostree-gpg-verify-result.c +++ b/src/libostree/ostree-gpg-verify-result.c @@ -621,6 +621,7 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, gboolean valid; gboolean sig_expired; gboolean key_expired; + gboolean key_revoked; gboolean key_missing; gsize len; @@ -642,6 +643,8 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, "b", &sig_expired); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_EXPIRED, "b", &key_expired); + g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_REVOKED, + "b", &key_revoked); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_KEY_MISSING, "b", &key_missing); g_variant_get_child (variant, OSTREE_GPG_SIGNATURE_ATTR_FINGERPRINT, @@ -703,6 +706,10 @@ ostree_gpg_verify_result_describe_variant (GVariant *variant, "Good signature from \"%s <%s>\"\n", user_name, user_email); } + else if (key_revoked) + { + g_string_append (output_buffer, "Key revoked\n"); + } else if (sig_expired) { g_string_append_printf (output_buffer, From d8649f4d5618b0a64988aa092bb566b5c50174e6 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 17 Jun 2019 13:37:35 -0500 Subject: [PATCH 27/62] tests/libtest: Allow specifying GPG homedir to cleanup In case the tests want to use a custom GPG homedir, allow passing in the homedir to use when cleaning up a running gpg-agent. Closes: #1872 Approved by: cgwalters --- tests/libtest.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index e0022512..5f381c67 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -601,7 +601,8 @@ has_gpgme () { } libtest_cleanup_gpg () { - gpg-connect-agent --homedir ${test_tmpdir}/gpghome killagent /bye || true + local gpg_homedir=${1:-${test_tmpdir}/gpghome} + gpg-connect-agent --homedir "${gpg_homedir}" killagent /bye || true } is_bare_user_only_repo () { From 0c63f30783076915fc0ea5892a4908e53583146d Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 17 Jun 2019 15:25:22 -0500 Subject: [PATCH 28/62] tests/test-gpg-signed-commit: Test more key states Extend test-gpg-signed-commit.sh to test various key states. If gpg is found that supports the required options, keys will be generated on the fly and changed in various ways to exercise the output from `ostree_gpg_verify_result_describe_variant` used in `ostree show`. I tested this using gnupg 2.2.12, so I hope it works well enough on various gpgs found in the wild. Closes: #1872 Approved by: cgwalters --- tests/libtest.sh | 33 +++++ tests/test-gpg-signed-commit.sh | 224 +++++++++++++++++++++++++++++++- 2 files changed, 256 insertions(+), 1 deletion(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index 5f381c67..99d7c967 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -600,6 +600,39 @@ has_gpgme () { true } +# Find an appropriate gpg program to use. We want one that has the +# --generate-key, --quick-set-expire and --quick-add-key options. The +# gpg program to use is returend. +which_gpg () { + local gpg + local gpg_options + local needed_options=( + --generate-key + --quick-set-expire + --quick-add-key + ) + local opt + + # Prefer gpg2 in case gpg refers to gpg1 + if which gpg2 &>/dev/null; then + gpg=gpg2 + elif which gpg &>/dev/null; then + gpg=gpg + else + # Succeed but don't return anything. + return 0 + fi + + # Make sure all the needed options are available + gpg_options=$(${gpg} --dump-options) || return 0 + for opt in ${needed_options[*]}; do + grep -q -x -e "${opt}" <<< "${gpg_options}" || return 0 + done + + # Found an appropriate gpg + echo ${gpg} +} + libtest_cleanup_gpg () { local gpg_homedir=${1:-${test_tmpdir}/gpghome} gpg-connect-agent --homedir "${gpg_homedir}" killagent /bye || true diff --git a/tests/test-gpg-signed-commit.sh b/tests/test-gpg-signed-commit.sh index 992a2ba1..7bd59502 100755 --- a/tests/test-gpg-signed-commit.sh +++ b/tests/test-gpg-signed-commit.sh @@ -29,7 +29,16 @@ if ! has_gpgme; then exit 0 fi -echo "1..1" +num_tests=1 + +# Run some more tests if an appropriate GPG is available +num_gpg_tests=8 +GPG=$(which_gpg) +if [ -n "${GPG}" ]; then + let num_tests+=num_gpg_tests +fi + +echo "1..${num_tests}" setup_test_repository "archive" @@ -83,3 +92,216 @@ fi libtest_cleanup_gpg echo "ok" + +# Remaining tests require gpg +if [ -z "${GPG}" ]; then + exit 0 +fi + +# Create a temporary GPG homedir +tmpgpg_home=${test_tmpdir}/tmpgpghome +mkdir -m700 ${tmpgpg_home} + +# Create an temporary trusted GPG directory +tmpgpg_trusted=${test_tmpdir}/tmpgpgtrusted +tmpgpg_trusted_keyring=${tmpgpg_trusted}/keyring.gpg +export OSTREE_GPG_HOME=${tmpgpg_trusted} +mkdir -p ${tmpgpg_trusted} + +# Create one normal signing key and one signing key with a subkey. See +# https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html. +${GPG} --homedir=${tmpgpg_home} --batch --generate-key <<"EOF" +Key-Type: RSA +Key-Length: 2048 +Key-Usage: sign +Name-Real: Test Key 1 +Expire-Date: 0 +%no-protection +%transient-key +%commit +Key-Type: RSA +Key-Length: 2048 +Key-Usage: sign +Subkey-Type: RSA +Subkey-Length: 2048 +Subkey-Usage: sign +Name-Real: Test Key 2 +Expire-Date: 0 +%no-protection +%transient-key +%commit +EOF + +# Figure out the key IDs and fingerprints. Assume that the order of the +# keys matches those specified in the generation. +# +# https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS +key1_id= +key1_fpr= +key2_id= +key2_fpr= +key2_sub_id= +key2_sub_fpr= +gpg_seckey_listing=$(${GPG} --homedir=${tmpgpg_home} --list-secret-keys --with-colons) +while IFS=: read -a fields; do + if [ "${fields[0]}" = sec ]; then + # Secret key - key ID is in field 5 + if [ -z "${key1_id}" ]; then + key1_id=${fields[4]} + else + key2_id=${fields[4]} + fi + elif [ "${fields[0]}" = ssb ]; then + # Secret subkey - key ID is in field 5 + key2_sub_id=${fields[4]} + elif [ "${fields[0]}" = fpr ]; then + # Fingerprint record - the fingerprint ID is in field 10 + if [ -z "${key1_fpr}" ]; then + key1_fpr=${fields[9]} + elif [ -z "${key2_fpr}" ]; then + key2_fpr=${fields[9]} + else + key2_sub_fpr=${fields[9]} + fi + fi +done <<< "${gpg_seckey_listing}" + +# Create a commit and sign it with both key1 and key2_sub +${OSTREE} commit -b test2 -s "A GPG signed commit" -m "Signed commit body" \ + --tree=dir=files --gpg-homedir=${tmpgpg_home} \ + --gpg-sign=${key1_id} --gpg-sign=${key2_sub_id} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" + +echo "ok signed with both generated keys" + +# Export the public keys and check again +${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_not_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" +assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'Good signature from "Test Key 2 <>"' +assert_file_has_content test2-show "Primary key ID ${key2_id}" + +echo "ok verified both generated keys" + +# Make key1 expired, wait until it's expired, export the public keys and check +# again +${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key1_fpr} seconds=1 +sleep 2 +${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_not_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" +assert_file_has_content test2-show 'BAD signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'Key expired' +assert_file_has_content test2-show 'Good signature from "Test Key 2 <>"' +assert_file_has_content test2-show "Primary key ID ${key2_id}" + +echo "ok verified with key1 expired" + +# Unexpire key1, expire key2 primary, wait until it's expired, export the +# public keys and check again +${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key1_fpr} seconds=0 +${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=1 +sleep 2 +${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_not_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" +assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' +assert_not_file_has_content test2-show 'Key expired' +assert_file_has_content test2-show "Primary key ID ${key2_id}" +assert_file_has_content test2-show 'Primary key expired' + +echo "ok verified with key2 primary expired" + +# Expire key2 subkey, wait until it's expired, export the public keys and +# check again +${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=1 ${key2_sub_fpr} +sleep 2 +${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_not_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" +assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' +assert_file_has_content test2-show 'Key expired' +assert_file_has_content test2-show "Primary key ID ${key2_id}" +assert_file_has_content test2-show 'Primary key expired' + +echo "ok verified with key2 primary and subkey expired" + +# Unexpire key2 primary, export the public keys and check again +${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=0 +${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_not_file_has_content test2-show 'public key not found' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub_id}" +assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' +assert_file_has_content test2-show 'Key expired' +assert_file_has_content test2-show "Primary key ID ${key2_id}" +assert_not_file_has_content test2-show 'Primary key expired' + +echo "ok verified with key2 subkey expired" + +# Add a second subkey but don't export it to the trusted keyring so that a new +# commit signed with fails. +${GPG} --homedir=${tmpgpg_home} --batch --passphrase '' \ + --quick-add-key ${key2_fpr} rsa2048 sign never +gpg_seckey_listing=$(${GPG} --homedir=${tmpgpg_home} --list-secret-keys --with-colons) +key2_sub2_id=$(awk -F: '{if ($1 == "ssb") print $5}' <<< "${gpg_seckey_listing}" | tail -n1) +key2_sub2_fpr=$(awk -F: '{if ($1 == "fpr") print $10}' <<< "${gpg_seckey_listing}" | tail -n1) +${OSTREE} commit -b test2 -s "A GPG signed commit" -m "Signed commit body" \ + --tree=dir=files --gpg-homedir=${tmpgpg_home} \ + --gpg-sign=${key1_id} --gpg-sign=${key2_sub2_id} +${OSTREE} show test2 > test2-show +assert_file_has_content test2-show '^Found 2 signatures' +assert_file_has_content test2-show "${key1_id}" +assert_file_has_content test2-show "${key2_sub2_id}" +assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' +assert_file_has_content test2-show 'public key not found' + +echo "ok verified with key2 sub2 missing" + +# Revoke key1 by importing the revocation certificate created when generating +# the key. The cert should be in $homedir/openpgp-revocs.d/$fpr.rev with +# recent gnupg. However, it tries to prevent you from accidentally revoking +# things by adding a : before the block, so it needs to be stripped. +key1_rev=${tmpgpg_home}/openpgp-revocs.d/${key1_fpr}.rev +if [ -f ${key1_rev} ]; then + sed -i '/BEGIN PGP PUBLIC KEY BLOCK/s/^://' ${key1_rev} + ${GPG} --homedir=${tmpgpg_home} --import ${key1_rev} + # Export both keys again + ${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} + ${OSTREE} show test2 > test2-show + assert_file_has_content test2-show '^Found 2 signatures' + assert_not_file_has_content test2-show 'public key not found' + assert_file_has_content test2-show "${key1_id}" + assert_file_has_content test2-show "${key2_sub2_id}" + assert_file_has_content test2-show 'Key revoked' + assert_file_has_content test2-show 'Good signature from "Test Key 2 <>"' + assert_file_has_content test2-show "Primary key ID ${key2_id}" + + echo "ok verified with key1 revoked" +else + echo "ok # SKIP could not find key revocation certificate" +fi + +libtest_cleanup_gpg ${tmpgpg_home} From 4670837f7c9d027b8724c4061219ee951dc8cd6e Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 10 Jan 2019 13:49:17 -0600 Subject: [PATCH 29/62] lib/gpg: Add helper to kill GPG agent With GnuPG 2, any time you do basically any operation, a gpg-agent will be spawned for the GPG home directory in use. The classic way to kill a gpg-agent is to use `gpg-connect-agent` and send the `killagent` command as is done in libtest.sh. Closes: #1799 Approved by: cgwalters --- src/libotutil/ot-gpg-utils.c | 26 ++++++++++++++++++++++++++ src/libotutil/ot-gpg-utils.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/libotutil/ot-gpg-utils.c b/src/libotutil/ot-gpg-utils.c index cc5b0ae4..cf5ce3ea 100644 --- a/src/libotutil/ot-gpg-utils.c +++ b/src/libotutil/ot-gpg-utils.c @@ -437,3 +437,29 @@ ot_gpgme_new_ctx (const char *homedir, return g_steal_pointer (&context); } + +void +ot_gpgme_kill_agent (const char *homedir) +{ + g_return_if_fail (homedir != NULL); + + /* Run gpg-connect-agent killagent /bye */ + 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; + } +} diff --git a/src/libotutil/ot-gpg-utils.h b/src/libotutil/ot-gpg-utils.h index 65ae55e4..e8a240b5 100644 --- a/src/libotutil/ot-gpg-utils.h +++ b/src/libotutil/ot-gpg-utils.h @@ -46,4 +46,6 @@ gpgme_data_t ot_gpgme_data_output (GOutputStream *output_stream); gpgme_ctx_t ot_gpgme_new_ctx (const char *homedir, GError **error); +void ot_gpgme_kill_agent (const char *homedir); + G_END_DECLS From b6979e7572395f3f99ba328ed9399ed4b862f9a7 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 10 Jan 2019 14:00:42 -0600 Subject: [PATCH 30/62] lib: Kill GPG agent when cleaning up tmp homedirs When a temporary directory is used for GPG operations, it's pretty clear that the running agent will be useless after the directory is deleted. Call the new `ot_gpgme_kill_agent ()` helper to kill gpg-agent rather than leaving them it hanging around forever. As it turns out, gnupg does have code to make gpg-agent automatically exit when the homedir is removed (https://dev.gnupg.org/T2756), but that's only available on gnupg 2.2 or newer. Possibly this code can be dropped later when that's more widely deployed or users/distros have been advised to backport the necessary changes. Closes: #1799 Approved by: cgwalters --- src/libostree/ostree-gpg-verifier.c | 1 + src/libostree/ostree-repo.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libostree/ostree-gpg-verifier.c b/src/libostree/ostree-gpg-verifier.c index a279348e..95ed36ee 100644 --- a/src/libostree/ostree-gpg-verifier.c +++ b/src/libostree/ostree-gpg-verifier.c @@ -87,6 +87,7 @@ verify_result_finalized_cb (gpointer data, * finalize() method, but I didn't want this keyring hack * bleeding into multiple classes. */ + ot_gpgme_kill_agent (tmp_dir); (void) glnx_shutil_rm_rf_at (AT_FDCWD, tmp_dir, NULL, NULL); } diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index da128c6a..c6860408 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -2300,11 +2300,15 @@ out: if (remote != NULL) ostree_remote_unref (remote); - if (source_tmp_dir != NULL) + if (source_tmp_dir != NULL) { + ot_gpgme_kill_agent (source_tmp_dir); (void) glnx_shutil_rm_rf_at (AT_FDCWD, source_tmp_dir, NULL, NULL); + } - if (target_tmp_dir != NULL) + if (target_tmp_dir != NULL) { + ot_gpgme_kill_agent (target_tmp_dir); (void) glnx_shutil_rm_rf_at (AT_FDCWD, target_tmp_dir, NULL, NULL); + } g_prefix_error (error, "GPG: "); From 0dd27bbf4b5a3f132a9b2418b391dacbcd64a003 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 13 Jun 2019 15:57:17 -0500 Subject: [PATCH 31/62] tests/libtest: Allow appending actions to be run on EXIT Currently if a test script adds a trap on `EXIT` to run some cleanup, it will stomp on the existing trap to run `save_core()`. Allow for scripts to append actions that will run on exit by introducing an array that will be iterated over by a single exit runner. Closes: #1799 Approved by: cgwalters --- tests/libtest.sh | 15 +++++++++++++-- tests/test-repo-finder-mount-integration.sh | 2 +- tests/test-rofiles-fuse.sh | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index 99d7c967..e70b7b87 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -34,13 +34,24 @@ else fi . ${test_srcdir}/libtest-core.sh +# Array of expressions to execute when exiting. Each expression should +# be a single string (quoting if necessary) that will be eval'd. To add +# a command to run on exit, append to the libtest_exit_cmds array like +# libtest_exit_cmds+=(expr). +libtest_exit_cmds=() +run_exit_cmds() { + for expr in "${libtest_exit_cmds[@]}"; do + eval "${expr}" || true + done +} +trap run_exit_cmds EXIT + save_core() { if [ -e core ]; then cp core "$test_srcdir/core" fi } - -trap save_core EXIT; +libtest_exit_cmds+=(save_core) test_tmpdir=$(pwd) diff --git a/tests/test-repo-finder-mount-integration.sh b/tests/test-repo-finder-mount-integration.sh index 243df591..9ecc4cd6 100755 --- a/tests/test-repo-finder-mount-integration.sh +++ b/tests/test-repo-finder-mount-integration.sh @@ -55,7 +55,7 @@ _mount_cleanup () { case "${TEST_SKIP_CLEANUP:-}" in no|"") - trap _mount_cleanup EXIT + libtest_exit_cmds+=(_mount_cleanup) ;; err) trap _mount_cleanup ERR diff --git a/tests/test-rofiles-fuse.sh b/tests/test-rofiles-fuse.sh index 7b7474d0..1e09711c 100755 --- a/tests/test-rofiles-fuse.sh +++ b/tests/test-rofiles-fuse.sh @@ -41,7 +41,7 @@ rofiles-fuse checkout-test2 mnt cleanup_fuse() { fusermount -u ${test_tmpdir}/mnt || true } -trap cleanup_fuse EXIT +libtest_exit_cmds+=(cleanup_fuse) assert_file_has_content mnt/firstfile first echo "ok mount" From abb173352da5fa6017746c27fab1eff220c4cfbd Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Thu, 13 Jun 2019 16:26:47 -0500 Subject: [PATCH 32/62] tests: Always cleanup gpg-agent when exiting Add `libtest_cleanup_gpg()` to the array of commands to run when exiting. This provides 2 improvements: 1. You don't need to worry about whether the test will spawn a gpg-agent and therefore require adding a call to `libtest_cleanup_gpg()`. 2. All the existing users were calling `libtest_cleanup_gpg()` at the end of the script. If there was a failure and the script exited early, then it wouldn't cleanup and there may be a stray gpg-agent hanging around. Closes: #1799 Approved by: cgwalters --- tests/libtest.sh | 1 + tests/test-commit-sign.sh | 1 - tests/test-gpg-signed-commit.sh | 2 -- tests/test-pull-mirror-summary.sh | 2 -- tests/test-pull-summary-sigs.sh | 2 -- tests/test-remote-gpg-import.sh | 2 -- tests/test-summary-view.sh | 2 -- 7 files changed, 1 insertion(+), 11 deletions(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index e70b7b87..632ccee8 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -648,6 +648,7 @@ libtest_cleanup_gpg () { local gpg_homedir=${1:-${test_tmpdir}/gpghome} gpg-connect-agent --homedir "${gpg_homedir}" killagent /bye || true } +libtest_exit_cmds+=(libtest_cleanup_gpg) is_bare_user_only_repo () { grep -q 'mode=bare-user-only' $1/config diff --git a/tests/test-commit-sign.sh b/tests/test-commit-sign.sh index d789d2fb..e9e7a6da 100755 --- a/tests/test-commit-sign.sh +++ b/tests/test-commit-sign.sh @@ -140,4 +140,3 @@ assert_not_file_has_content show.txt 'Found.*signature' echo "ok pull sig deleted" rm -rf repo gnomerepo-files -libtest_cleanup_gpg diff --git a/tests/test-gpg-signed-commit.sh b/tests/test-gpg-signed-commit.sh index 7bd59502..3e41efb8 100755 --- a/tests/test-gpg-signed-commit.sh +++ b/tests/test-gpg-signed-commit.sh @@ -89,8 +89,6 @@ if ${OSTREE} show test2 | grep -o 'Found [[:digit:]] signature'; then assert_not_reached fi -libtest_cleanup_gpg - echo "ok" # Remaining tests require gpg diff --git a/tests/test-pull-mirror-summary.sh b/tests/test-pull-mirror-summary.sh index cc3c6a2c..504cf545 100755 --- a/tests/test-pull-mirror-summary.sh +++ b/tests/test-pull-mirror-summary.sh @@ -120,5 +120,3 @@ echo "ok pull mirror with invalid summary sig and no verification" # assert_file_has_content deltas.txt "${origmain}-${newmain}" # echo "ok pull mirror with signed summary covering static deltas" - -libtest_cleanup_gpg diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index e2864beb..0b6b806c 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -274,5 +274,3 @@ cmp repo/tmp/cache/summaries/origin ${test_tmpdir}/ostree-srv/gnomerepo/summary. cmp repo/tmp/cache/summaries/origin.sig ${test_tmpdir}/ostree-srv/gnomerepo/summary.sig.2 >&2 echo "ok pull with signed summary broken cache" - -libtest_cleanup_gpg diff --git a/tests/test-remote-gpg-import.sh b/tests/test-remote-gpg-import.sh index 1bb42d82..4d73fa11 100755 --- a/tests/test-remote-gpg-import.sh +++ b/tests/test-remote-gpg-import.sh @@ -280,5 +280,3 @@ ${CMD_PREFIX} ostree --repo=${test_tmpdir}/ostree-srv/gnomerepo summary -u --gpg ${OSTREE} pull --require-static-deltas R1:main echo "ok gpg trusted signed commit for delta upgrades" - -libtest_cleanup_gpg diff --git a/tests/test-summary-view.sh b/tests/test-summary-view.sh index a5ddf93e..d26d3431 100755 --- a/tests/test-summary-view.sh +++ b/tests/test-summary-view.sh @@ -62,5 +62,3 @@ assert_file_has_content_literal raw-summary.txt "('main', (" assert_file_has_content_literal raw-summary.txt "('other', (" assert_file_has_content_literal raw-summary.txt "{'ostree.summary.last-modified': Date: Tue, 11 Jun 2019 16:38:16 -0400 Subject: [PATCH 33/62] ci: Use Fedora 29 artifacts Use Fedora 29 artifacts instead of Fedora 28, since 28 is now end-of-life. Also rename `ci/fah28-insttests.sh` -> `ci/fah29-insttests.sh` and use the https://getfedora.org/atomic_qcow2_latest redirect URL for the latest Fedora Atomic Host 29 image. Closes: #1871 Approved by: jlebon --- .papr-ex.yaml | 24 ++++++++++++------------ .papr.yml | 30 +++++++++++++++--------------- ci/fah28-insttests.sh | 9 --------- ci/fah29-insttests.sh | 8 ++++++++ 4 files changed, 35 insertions(+), 36 deletions(-) delete mode 100755 ci/fah28-insttests.sh create mode 100755 ci/fah29-insttests.sh diff --git a/.papr-ex.yaml b/.papr-ex.yaml index 8cba2ca3..fbbd19dd 100644 --- a/.papr-ex.yaml +++ b/.papr-ex.yaml @@ -4,15 +4,15 @@ branches: - auto - try -context: FAH28-insttests +context: FAH29-insttests required: false container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 kvm: true tests: - - ci/fah28-insttests.sh + - ci/fah29-insttests.sh artifacts: - tests/installed/artifacts/ @@ -27,8 +27,8 @@ branches: - try required: true container: - image: registry.fedoraproject.org/fedora:28 -context: f28-primary + image: registry.fedoraproject.org/fedora:29 +context: f29-primary env: # We only use -Werror=maybe-uninitialized here with a "fixed" toolchain CFLAGS: '-fsanitize=undefined -fsanitize-undefined-trap-on-error -fsanitize=address -O2 -Wp,-D_FORTIFY_SOURCE=2' @@ -51,10 +51,10 @@ artifacts: --- # And now the contexts below here are variant container builds -context: f28-rust +context: f29-rust inherit: true container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 env: CONFIGOPTS: '--enable-rust' CI_PKGS: cargo @@ -65,10 +65,10 @@ tests: --- -context: f28-gnutls +context: f29-gnutls inherit: true container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 env: CONFIGOPTS: '--with-crypto=gnutls' CI_PKGS: pkgconfig(gnutls) @@ -81,7 +81,7 @@ tests: inherit: true -context: f28-minimal +context: f29-minimal env: CONFIGOPTS: '--without-curl --without-soup --disable-gtk-doc --disable-man --disable-rust --without-libarchive --without-selinux --without-smack @@ -96,7 +96,7 @@ tests: inherit: true required: true -context: f28-libsoup +context: f29-libsoup env: CONFIGOPTS: "--without-curl --without-openssl --with-soup" @@ -109,7 +109,7 @@ tests: inherit: true required: true -context: f28-introspection-tests +context: f29-introspection-tests env: # ASAN conflicts with introspection testing; diff --git a/.papr.yml b/.papr.yml index 7b3ca018..22d84da5 100644 --- a/.papr.yml +++ b/.papr.yml @@ -6,8 +6,8 @@ branches: - try required: true container: - image: registry.fedoraproject.org/fedora:28 -context: f28-primary + image: registry.fedoraproject.org/fedora:29 +context: f29-primary env: # We only use -Werror=maybe-uninitialized here with a "fixed" toolchain CFLAGS: '-fsanitize=undefined -fsanitize-undefined-trap-on-error -fsanitize=address -O2 -Wp,-D_FORTIFY_SOURCE=2' @@ -31,10 +31,10 @@ artifacts: --- # And now the contexts below here are variant container builds -context: f28-rust +context: f29-rust inherit: true container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 env: CONFIGOPTS: '--enable-rust' CI_PKGS: cargo @@ -45,10 +45,10 @@ tests: --- -context: f28-gnutls +context: f29-gnutls inherit: true container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 env: CONFIGOPTS: '--with-crypto=gnutls' CI_PKGS: pkgconfig(gnutls) @@ -61,7 +61,7 @@ tests: inherit: true -context: f28-minimal +context: f29-minimal env: CONFIGOPTS: '--without-curl --without-soup --disable-gtk-doc --disable-man --disable-rust --without-libarchive --without-selinux --without-smack @@ -76,7 +76,7 @@ tests: inherit: true required: true -context: f28-libsoup +context: f29-libsoup env: CONFIGOPTS: "--without-curl --without-openssl --with-soup" @@ -89,7 +89,7 @@ tests: inherit: true required: true -context: f28-introspection-tests +context: f29-introspection-tests env: # ASAN conflicts with introspection testing; @@ -108,19 +108,19 @@ branches: - auto - try -context: f28-flatpak +context: f29-flatpak required: true # This test case wants an "unprivileged container with bubblewrap", # which we don't have right now; so just provision a VM and do a # docker --privileged run. host: - distro: fedora/28/atomic + distro: fedora/29/atomic specs: ram: 4096 # build-bundle is a static delta, which needs RAM right now tests: - - docker run --rm --privileged -v $(pwd):/srv/code registry.fedoraproject.org/fedora:28 /bin/sh -c "cd /srv/code && ./ci/flatpak.sh" + - docker run --rm --privileged -v $(pwd):/srv/code registry.fedoraproject.org/fedora:29 /bin/sh -c "cd /srv/code && ./ci/flatpak.sh" artifacts: - test-suite.log @@ -136,16 +136,16 @@ branches: - auto - try -context: f28-rpmostree +context: f29-rpmostree # XXX: some issues currently failing that need investigating. required: false cluster: hosts: - name: vmcheck - distro: fedora/28/atomic + distro: fedora/29/atomic container: - image: registry.fedoraproject.org/fedora:28 + image: registry.fedoraproject.org/fedora:29 env: HOSTS: vmcheck diff --git a/ci/fah28-insttests.sh b/ci/fah28-insttests.sh deleted file mode 100755 index 22560bec..00000000 --- a/ci/fah28-insttests.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/bash -set -xeuo pipefail - -./tests/installed/provision.sh -# TODO: enhance papr to have caching, a bit like https://docs.travis-ci.com/user/caching/ -cd tests/installed -# This should be https://getfedora.org/atomic_qcow2_latest but that's broken -curl -Lo fedora-atomic-host.qcow2 https://kojipkgs.fedoraproject.org/compose/twoweek/Fedora-Atomic-28-20180626.0/compose/AtomicHost/x86_64/images/Fedora-AtomicHost-28-20180626.0.x86_64.qcow2 -exec env "TEST_SUBJECTS=$(pwd)/fedora-atomic-host.qcow2" ./run.sh diff --git a/ci/fah29-insttests.sh b/ci/fah29-insttests.sh new file mode 100755 index 00000000..a045cf52 --- /dev/null +++ b/ci/fah29-insttests.sh @@ -0,0 +1,8 @@ +#!/usr/bin/bash +set -xeuo pipefail + +./tests/installed/provision.sh +# TODO: enhance papr to have caching, a bit like https://docs.travis-ci.com/user/caching/ +cd tests/installed +curl -Lo fedora-atomic-host.qcow2 https://getfedora.org/atomic_qcow2_latest +exec env "TEST_SUBJECTS=$(pwd)/fedora-atomic-host.qcow2" ./run.sh From 35cce4972e24c99fd90c5be02e403c2d42825dd5 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 19 Jun 2019 16:04:39 -0400 Subject: [PATCH 34/62] ci/build-check: Remove unused-command-line-argument diagnostic Since `clang-4.0` is no longer being used, it should be safe to remove use of this diagnostic for clang. This enables using `gcc` as a workaround for `g-ir-scanner`, as `unused-command-line-argument` is not recognized by `gcc`. See: https://github.com/ostreedev/ostree/pull/1871#issuecomment-503765624 Closes: #1871 Approved by: jlebon --- ci/build-check.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/build-check.sh b/ci/build-check.sh index ed129c74..bd0686bd 100755 --- a/ci/build-check.sh +++ b/ci/build-check.sh @@ -25,8 +25,7 @@ if test -x /usr/bin/clang; then if grep -q -e 'static inline.*_GLIB_AUTOPTR_LIST_FUNC_NAME' /usr/include/glib-2.0/glib/gmacros.h; then echo 'Skipping clang check, see https://bugzilla.gnome.org/show_bug.cgi?id=796346' else - # Except for clang-4.0: error: argument unused during compilation: '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' [-Werror,-Wunused-command-line-argument] - export CFLAGS="-Wall -Werror -Wno-error=unused-command-line-argument ${CFLAGS:-}" + export CFLAGS="-Wall -Werror ${CFLAGS:-}" git clean -dfx && git submodule foreach git clean -dfx export CC=clang build From fd8795f3874d623db7a82bec56904648fe2c1eb7 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 19 Jun 2019 13:32:00 -0400 Subject: [PATCH 35/62] Makefile-libostree.am: Work around clang issues with g-ir-scanner Work around an issue with clang-7 in Fedora 29 where the `-fstack-clash-protection` flag is not recognized. Force the compiler used by `g-ir-scanner` to `gcc`, so that the flag is recognized. Related: https://github.com/projectatomic/rpm-ostree/pull/1787#issuecomment-473971585 Closes: #1871 Approved by: jlebon --- Makefile-libostree.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 0ea54cf8..1f1e0bc7 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -251,6 +251,10 @@ libostree_1_la_CFLAGS += $(OT_DEP_SELINUX_CFLAGS) libostree_1_la_LIBADD += $(OT_DEP_SELINUX_LIBS) endif +# XXX: work around clang being passed -fstack-clash-protection which it doesn't understand +# See: https://bugzilla.redhat.com/show_bug.cgi?id=1672012 +INTROSPECTION_SCANNER_ENV = CC=gcc + if BUILDOPT_INTROSPECTION OSTree-1.0.gir: libostree-1.la Makefile OSTree_1_0_gir_EXPORT_PACKAGES = ostree-1 From 86cf6ba5c5c42681c8151047aee043b72c3c787f Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Wed, 19 Jun 2019 18:22:11 -0400 Subject: [PATCH 36/62] ci/flatpak: Bump FLATPAK_TAG to 1.4.1 Bump the flatpak version used in CI to avoid a repeated definition of `renameat2()` in libglnx and glibc. See: https://github.com/ostreedev/ostree/pull/1871#issuecomment-503768062 Closes: #1871 Approved by: jlebon --- ci/flatpak.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/flatpak.sh b/ci/flatpak.sh index a0e556ac..fd76b6fd 100755 --- a/ci/flatpak.sh +++ b/ci/flatpak.sh @@ -6,7 +6,7 @@ set -xeuo pipefail # Keep this pinned to avoid arbitrary change for now; it's also # good to test building older code against newer ostree as it helps # us notice any API breaks. -FLATPAK_TAG=0.99.2 +FLATPAK_TAG=1.4.1 dn=$(dirname $0) . ${dn}/libpaprci/libbuild.sh From 322e8697e917446f5d1e69c04bdf9344e032ab26 Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Fri, 17 May 2019 14:23:41 -0400 Subject: [PATCH 37/62] lib/util: Drop unneeded ot-tool-util.h includes With `ot-tool-util.h` made visible in `otutil.h` (in be2572bf68090a5e277338d2613d3c7d53b0c9e8), drop previous includes of `ot-tool-util.h` elsewhere. Closes: #1876 Approved by: zonggen --- src/ostree/ot-admin-builtin-set-origin.c | 1 - src/ostree/ot-builtin-checkout.c | 1 - src/ostree/ot-builtin-commit.c | 1 - src/ostree/ot-remote-builtin-add.c | 1 - 4 files changed, 4 deletions(-) diff --git a/src/ostree/ot-admin-builtin-set-origin.c b/src/ostree/ot-admin-builtin-set-origin.c index 07453a87..9d96512e 100644 --- a/src/ostree/ot-admin-builtin-set-origin.c +++ b/src/ostree/ot-admin-builtin-set-origin.c @@ -25,7 +25,6 @@ #include "ot-admin-builtins.h" #include "ot-admin-functions.h" #include "ostree.h" -#include "ot-tool-util.h" #include "otutil.h" #include diff --git a/src/ostree/ot-builtin-checkout.c b/src/ostree/ot-builtin-checkout.c index 1519e34e..a0fe4be4 100644 --- a/src/ostree/ot-builtin-checkout.c +++ b/src/ostree/ot-builtin-checkout.c @@ -30,7 +30,6 @@ #include "ot-builtins.h" #include "ostree.h" #include "otutil.h" -#include "ot-tool-util.h" static gboolean opt_user_mode; static gboolean opt_allow_noent; diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 56f59681..854983db 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -28,7 +28,6 @@ #include "ot-editor.h" #include "ostree.h" #include "otutil.h" -#include "ot-tool-util.h" #include "parse-datetime.h" #include "ostree-repo-private.h" #include "ostree-libarchive-private.h" diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index f81f7580..2d021d77 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -22,7 +22,6 @@ #include "config.h" #include "otutil.h" -#include "ot-tool-util.h" #include "ot-main.h" #include "ot-remote-builtins.h" From 48624c99ad66dbc20833f2c08e24a0e537518958 Mon Sep 17 00:00:00 2001 From: Matthew Leeds Date: Tue, 25 Jun 2019 16:58:38 -0700 Subject: [PATCH 38/62] lib/repo: Improve docs for get_min_free_space_bytes() Closes: #1879 Approved by: jlebon --- src/libostree/ostree-repo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index c6860408..804ff6c6 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3496,7 +3496,10 @@ ostree_repo_get_mode (OstreeRepo *self) * @out_reserved_bytes: (out): Location to store the result * @error: Return location for a #GError * - * It can be used to query the value (in bytes) of min-free-space-* config option. + * Determine the number of bytes of free disk space that are reserved according + * to the repo config and return that number in @out_reserved_bytes. See the + * documentation for the core.min-free-space-size and + * core.min-free-space-percent repo config options. * * Returns: %TRUE on success, %FALSE otherwise. * Since: 2018.9 From a904f434cd10471e02465781d62669321dea94d7 Mon Sep 17 00:00:00 2001 From: Rafael Fonseca Date: Tue, 2 Jul 2019 13:26:25 +0200 Subject: [PATCH 39/62] lib/kargs: add missing function to symbol-versioning table Signed-off-by: Rafael Fonseca Closes: #1883 Approved by: jlebon --- apidoc/ostree-sections.txt | 1 + src/libostree/libostree-devel.sym | 1 + 2 files changed, 2 insertions(+) diff --git a/apidoc/ostree-sections.txt b/apidoc/ostree-sections.txt index 3838be4c..e8faeb10 100644 --- a/apidoc/ostree-sections.txt +++ b/apidoc/ostree-sections.txt @@ -687,6 +687,7 @@ ostree_kernel_args_delete ostree_kernel_args_delete_key_entry ostree_kernel_args_append_proc_cmdline ostree_kernel_args_parse_append +ostree_kernel_args_get_last_value ostree_kernel_args_from_string ostree_kernel_args_to_strv ostree_kernel_args_to_string diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 125d9457..36f35851 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -35,6 +35,7 @@ global: ostree_kernel_args_delete_key_entry; ostree_kernel_args_append_proc_cmdline; ostree_kernel_args_parse_append; + ostree_kernel_args_get_last_value; ostree_kernel_args_from_string; ostree_kernel_args_to_strv; ostree_kernel_args_to_string; From 2312caad7633d7aae11adebd87e4f932431bf49a Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 8 Jul 2019 15:39:11 -0600 Subject: [PATCH 40/62] tests/sizes: Fix call to commit_transaction() The GIR for commit_transaction() only has a single argument for the GCancellable. Calling it with 2 arguments prints a GJS warning: Gjs-Message: 15:37:40.287: JS WARNING: [/home/dan/src/ostree/tests/test-sizes.js 56]: Too many arguments to method OSTree.Repo.commit_transaction: expected 1, got 2 Currently this is harmless, but it could become a hard error in GJS at some point. Closes: #1884 Approved by: cgwalters --- tests/test-sizes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-sizes.js b/tests/test-sizes.js index 5114dd64..d923e749 100755 --- a/tests/test-sizes.js +++ b/tests/test-sizes.js @@ -53,7 +53,7 @@ let [,dirTree] = repo.write_mtree(mtree, null); let [,commit] = repo.write_commit(null, 'Some subject', 'Some body', null, dirTree, null); print("commit => " + commit); -repo.commit_transaction(null, null); +repo.commit_transaction(null); // Test the sizes metadata let [,commitVariant] = repo.load_variant(OSTree.ObjectType.COMMIT, commit); From 615861443be250cba16d674a6b3c7f96c8b842de Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Mon, 8 Jul 2019 15:08:07 -0600 Subject: [PATCH 41/62] tests/sizes.js: Fix byte array unpacking Recent GJS changed how byte arrays are unpacked with some assumptions that they are likely strings. Manually use get_child_value() and get_byte() to ensure the correct value is parsed when checking the `ostree.sizes` metadata. The upstream test is currently passing fine with GJS 1.56.2, but at Endless we (unfortunately) have a downstream change that adds the object type as an additional byte in the array. This is parsed incorrectly by `deep_unpack()`. We can carry this patch downstream, but this change makes the test more robust regardless. Closes: #1884 Approved by: cgwalters --- tests/test-sizes.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test-sizes.js b/tests/test-sizes.js index d923e749..73b179c5 100755 --- a/tests/test-sizes.js +++ b/tests/test-sizes.js @@ -64,10 +64,10 @@ assertEquals(nSizes, 2); let expectedUncompressedSizes = [12, 18]; let foundExpectedUncompressedSizes = 0; for (let i = 0; i < nSizes; i++) { - let sizeEntry = sizes.get_child_value(i).deep_unpack(); - assertEquals(sizeEntry.length, 34); - let compressedSize = sizeEntry[32]; - let uncompressedSize = sizeEntry[33]; + let sizeEntry = sizes.get_child_value(i); + assertEquals(sizeEntry.n_children(), 34); + let compressedSize = sizeEntry.get_child_value(32).get_byte(); + let uncompressedSize = sizeEntry.get_child_value(33).get_byte(); print("compressed = " + compressedSize); print("uncompressed = " + uncompressedSize); for (let j = 0; j < expectedUncompressedSizes.length; j++) { From 8ac348d19a38b0f1d84488d85152524449da767a Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2019 10:17:07 -0600 Subject: [PATCH 42/62] tests/gpg: Use exit hook to kill agent in temporary GPG homedir This wasn't available when I originally wrote this, but it ensures that the running gpg-agent in tmpgpghome is killed in case the tests exit early. Closes: #1892 Approved by: jlebon --- tests/test-gpg-signed-commit.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test-gpg-signed-commit.sh b/tests/test-gpg-signed-commit.sh index 3e41efb8..2fc2cf2f 100755 --- a/tests/test-gpg-signed-commit.sh +++ b/tests/test-gpg-signed-commit.sh @@ -100,6 +100,12 @@ fi tmpgpg_home=${test_tmpdir}/tmpgpghome mkdir -m700 ${tmpgpg_home} +# Wire up an exit hook to kill the gpg-agent in it +cleanup_tmpgpg_home() { + libtest_cleanup_gpg ${tmpgpg_home} +} +libtest_exit_cmds+=(cleanup_tmpgpg_home) + # Create an temporary trusted GPG directory tmpgpg_trusted=${test_tmpdir}/tmpgpgtrusted tmpgpg_trusted_keyring=${tmpgpg_trusted}/keyring.gpg @@ -301,5 +307,3 @@ if [ -f ${key1_rev} ]; then else echo "ok # SKIP could not find key revocation certificate" fi - -libtest_cleanup_gpg ${tmpgpg_home} From d2a9c8604eb6df7d88c4709f5d6d059bc1487c03 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2019 10:11:00 -0600 Subject: [PATCH 43/62] tests/gpg: Skip tests when subkeys can't be expired The ability to expire subkeys using gpg's --quick-set-expire is only available on gnupg 2.1.22. If expiring a subkey fails, assume this is why and skip the tests that require it but run the actions that the subsequent tests depend on. This was failing on the Debian Stretch CI tests since stretch has gnupg 2.1.18. Closes: #1892 Approved by: jlebon --- tests/test-gpg-signed-commit.sh | 76 +++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/tests/test-gpg-signed-commit.sh b/tests/test-gpg-signed-commit.sh index 2fc2cf2f..090b4bfe 100755 --- a/tests/test-gpg-signed-commit.sh +++ b/tests/test-gpg-signed-commit.sh @@ -96,6 +96,16 @@ if [ -z "${GPG}" ]; then exit 0 fi +# Although we have the gpg --set-expire option, we want to use it to set +# the expiration date for subkeys below. That was only added in gnupg +# 2.1.22. Check if SUBKEY-FPRS is in the usage output. +# (https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=NEWS;hb=HEAD) +if (${GPG} --quick-set-expire 2>&1 || :) | grep -q SUBKEY-FPRS; then + GPG_CAN_EXPIRE_SUBKEYS=true +else + GPG_CAN_EXPIRE_SUBKEYS=false +fi + # Create a temporary GPG homedir tmpgpg_home=${test_tmpdir}/tmpgpghome mkdir -m700 ${tmpgpg_home} @@ -231,39 +241,49 @@ assert_file_has_content test2-show 'Primary key expired' echo "ok verified with key2 primary expired" -# Expire key2 subkey, wait until it's expired, export the public keys and -# check again -${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=1 ${key2_sub_fpr} -sleep 2 -${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} -${OSTREE} show test2 > test2-show -assert_file_has_content test2-show '^Found 2 signatures' -assert_not_file_has_content test2-show 'public key not found' -assert_file_has_content test2-show "${key1_id}" -assert_file_has_content test2-show "${key2_sub_id}" -assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' -assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' -assert_file_has_content test2-show 'Key expired' -assert_file_has_content test2-show "Primary key ID ${key2_id}" -assert_file_has_content test2-show 'Primary key expired' +# If subkey expiration is available, expire key2 subkey, wait until it's +# expired, export the public keys and check again +if ${GPG_CAN_EXPIRE_SUBKEYS}; then + ${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=1 ${key2_sub_fpr} + sleep 2 + ${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} + ${OSTREE} show test2 > test2-show + assert_file_has_content test2-show '^Found 2 signatures' + assert_not_file_has_content test2-show 'public key not found' + assert_file_has_content test2-show "${key1_id}" + assert_file_has_content test2-show "${key2_sub_id}" + assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' + assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' + assert_file_has_content test2-show 'Key expired' + assert_file_has_content test2-show "Primary key ID ${key2_id}" + assert_file_has_content test2-show 'Primary key expired' -echo "ok verified with key2 primary and subkey expired" + echo "ok verified with key2 primary and subkey expired" +else + echo "ok # SKIP gpg --quick-set-expire does not support expiring subkeys" +fi -# Unexpire key2 primary, export the public keys and check again +# Unexpire key2 primary and export the public keys ${GPG} --homedir=${tmpgpg_home} --quick-set-expire ${key2_fpr} seconds=0 ${GPG} --homedir=${tmpgpg_home} --export ${key1_id} ${key2_id} > ${tmpgpg_trusted_keyring} -${OSTREE} show test2 > test2-show -assert_file_has_content test2-show '^Found 2 signatures' -assert_not_file_has_content test2-show 'public key not found' -assert_file_has_content test2-show "${key1_id}" -assert_file_has_content test2-show "${key2_sub_id}" -assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' -assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' -assert_file_has_content test2-show 'Key expired' -assert_file_has_content test2-show "Primary key ID ${key2_id}" -assert_not_file_has_content test2-show 'Primary key expired' -echo "ok verified with key2 subkey expired" +# This test expects the subkey to be expired, so skip it if that didn't happen +if ${GPG_CAN_EXPIRE_SUBKEYS}; then + ${OSTREE} show test2 > test2-show + assert_file_has_content test2-show '^Found 2 signatures' + assert_not_file_has_content test2-show 'public key not found' + assert_file_has_content test2-show "${key1_id}" + assert_file_has_content test2-show "${key2_sub_id}" + assert_file_has_content test2-show 'Good signature from "Test Key 1 <>"' + assert_file_has_content test2-show 'BAD signature from "Test Key 2 <>"' + assert_file_has_content test2-show 'Key expired' + assert_file_has_content test2-show "Primary key ID ${key2_id}" + assert_not_file_has_content test2-show 'Primary key expired' + + echo "ok verified with key2 subkey expired" +else + echo "ok # SKIP gpg --quick-set-expire does not support expiring subkeys" +fi # Add a second subkey but don't export it to the trusted keyring so that a new # commit signed with fails. From 19e764cea24464bd6f6761d35903e204a0e69422 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2019 10:42:42 -0600 Subject: [PATCH 44/62] lib/kargs: Don't expose OstreeKernelArgs autoptr cleanup on old glib Move the OstreeKernelArgs autoptr cleanup definition to ostree-autocleanups.h, which will only expose the definitions when building ostree or if glib is new enough. The include of ostree-kernel-args.h needs to be moved before ostree-autocleanups.h in ostree.h so that the OstreeKernelArgs type is declared when the autoptr cleanup is defined. All the places it's used already pull in libglnx.h first so that the compat macros are picked up if glib it too old during the ostree build. Closes: #1892 Approved by: jlebon --- src/libostree/ostree-autocleanups.h | 1 + src/libostree/ostree-kernel-args.h | 2 -- src/libostree/ostree.h | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libostree/ostree-autocleanups.h b/src/libostree/ostree-autocleanups.h index 9a54aee7..c07f88a8 100644 --- a/src/libostree/ostree-autocleanups.h +++ b/src/libostree/ostree-autocleanups.h @@ -51,6 +51,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeAsyncProgress, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeBootconfigParser, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeDeployment, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeGpgVerifyResult, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeKernelArgs, ostree_kernel_args_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeMutableTree, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepo, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFile, g_object_unref) diff --git a/src/libostree/ostree-kernel-args.h b/src/libostree/ostree-kernel-args.h index d7beca51..3975ae5c 100644 --- a/src/libostree/ostree-kernel-args.h +++ b/src/libostree/ostree-kernel-args.h @@ -35,8 +35,6 @@ GPtrArray *_ostree_kernel_arg_get_key_array (OstreeKernelArgs *kargs); _OSTREE_PUBLIC void ostree_kernel_args_free (OstreeKernelArgs *kargs); -G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelArgs, ostree_kernel_args_free) - _OSTREE_PUBLIC OstreeKernelArgs *ostree_kernel_args_new (void); diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h index ca19bc85..49ca919c 100644 --- a/src/libostree/ostree.h +++ b/src/libostree/ostree.h @@ -39,6 +39,6 @@ #include #include #include +#include #include #include -#include From cf7fc0eabbe20e854dc576d518babb2ec23b4487 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Fri, 26 Jul 2019 14:28:47 -0600 Subject: [PATCH 45/62] ci/rpmostree: Bump to 2019.3 The test-ucontainer.sh test in rpmostree 2019.1 is failing for non-ostree reasons. This is fixed in [1], which is part of 2019.3. I believe this is still a relevant test of f29 since that's what's shipped in f29-updates. 1. https://github.com/projectatomic/rpm-ostree/commit/45b6186be0826889d805ba55bee3be75b042ed35 Closes: #1892 Approved by: jlebon --- ci/rpmostree.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/rpmostree.sh b/ci/rpmostree.sh index 9a162972..76841ffe 100755 --- a/ci/rpmostree.sh +++ b/ci/rpmostree.sh @@ -6,7 +6,7 @@ set -xeuo pipefail # Frozen to a tag for now to help predictability; it's # also useful to test building *older* versions since # that must work. -RPMOSTREE_TAG=v2019.1 +RPMOSTREE_TAG=v2019.3 dn=$(dirname $0) . ${dn}/libpaprci/libbuild.sh From c9ecfb1d81b5592ab9b5978da440b2997b8716a3 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 24 Jul 2019 21:31:54 +0000 Subject: [PATCH 46/62] Add OSTREE_BUILT_FEATURES to ostree-version.h This way projects can dispatch at run-time based on ostree's build time options, e.g. detect the availability of GPG. Closes: #1890 Approved by: jlebon --- configure.ac | 3 +++ src/libostree/ostree-version.h.in | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/configure.ac b/configure.ac index 3f125638..1d083d95 100644 --- a/configure.ac +++ b/configure.ac @@ -584,6 +584,9 @@ OSTREE_FEATURES="$OSTREE_FEATURES $release_build_type" # P2P API is public in OSTree >= 2018.6 OSTREE_FEATURES="$OSTREE_FEATURES p2p" +# Strip leading whitespace +OSTREE_FEATURES=$(echo ${OSTREE_FEATURES}) + AC_CONFIG_FILES([ Makefile apidoc/Makefile diff --git a/src/libostree/ostree-version.h.in b/src/libostree/ostree-version.h.in index 8edb9116..2c7ecdec 100644 --- a/src/libostree/ostree-version.h.in +++ b/src/libostree/ostree-version.h.in @@ -91,3 +91,13 @@ #define OSTREE_CHECK_VERSION(year,release) \ (OSTREE_YEAR_VERSION > (year) || \ (OSTREE_YEAR_VERSION == (year) && OSTREE_RELEASE_VERSION >= (release))) + +/** + * OSTREE_BUILT_FEATURES: + * + * Whitespace separated set of features this libostree was configured with at build time. + * Consult the source code in configure.ac (or the CLI `ostree --version`) for examples. + * + * Since: 2019.3 + */ +#define OSTREE_BUILT_FEATURES "@OSTREE_FEATURES@" From 9332830e09e285ba1db9357a4e695d1251b00dd7 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 26 Jul 2019 11:52:18 -0400 Subject: [PATCH 47/62] lib/pull: Allow downgrade protection with overrides There's a valid use case for enabling the timestamp downgrade check while still also using override commits. We'll make use of this in Fedora CoreOS, where the agent specifies the exact commit to upgrade to, while still enforcing that it be newer. Closes: #1891 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 50 ++++++++++++++++---------------- tests/pull-test.sh | 6 ++++ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index bb7bc02b..67b28f8c 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -4335,16 +4335,16 @@ ostree_repo_pull_with_options (OstreeRepo *self, const char*, override_commitid) { g_autofree char *contents = NULL; + g_autoptr(OstreeCollectionRef) ref_with_collection = NULL; /* Support specifying "" for an override commitid */ if (override_commitid && *override_commitid) { - g_hash_table_replace (updated_requested_refs_to_fetch, ostree_collection_ref_dup (ref), g_strdup (override_commitid)); + ref_with_collection = ostree_collection_ref_dup (ref); + contents = g_strdup (override_commitid); } else { - g_autoptr(OstreeCollectionRef) ref_with_collection = NULL; - if (pull_data->summary) { gsize commit_size = 0; @@ -4367,29 +4367,29 @@ ostree_repo_pull_with_options (OstreeRepo *self, ref_with_collection = ostree_collection_ref_dup (ref); } - - /* If we have timestamp checking enabled, find the current value of - * the ref, and store its timestamp in the hash map, to check later. - */ - if (pull_data->timestamp_check) - { - g_autofree char *from_rev = NULL; - if (!ostree_repo_resolve_rev (pull_data->repo, ref_with_collection->ref_name, TRUE, - &from_rev, error)) - goto out; - /* Explicitly store NULL if there's no previous revision. We do - * this so we can assert() if we somehow didn't find a ref in the - * hash at all. Note we don't copy the collection-ref, so the - * lifetime of this hash must be equal to `requested_refs_to_fetch`. - */ - g_hash_table_insert (pull_data->ref_original_commits, ref_with_collection, - g_steal_pointer (&from_rev)); - } - - g_hash_table_replace (updated_requested_refs_to_fetch, - g_steal_pointer (&ref_with_collection), - g_steal_pointer (&contents)); } + + /* If we have timestamp checking enabled, find the current value of + * the ref, and store its timestamp in the hash map, to check later. + */ + if (pull_data->timestamp_check) + { + g_autofree char *from_rev = NULL; + if (!ostree_repo_resolve_rev (pull_data->repo, ref_with_collection->ref_name, TRUE, + &from_rev, error)) + goto out; + /* Explicitly store NULL if there's no previous revision. We do + * this so we can assert() if we somehow didn't find a ref in the + * hash at all. Note we don't copy the collection-ref, so the + * lifetime of this hash must be equal to `requested_refs_to_fetch`. + */ + g_hash_table_insert (pull_data->ref_original_commits, ref_with_collection, + g_steal_pointer (&from_rev)); + } + + g_hash_table_replace (updated_requested_refs_to_fetch, + g_steal_pointer (&ref_with_collection), + g_steal_pointer (&contents)); } g_hash_table_unref (requested_refs_to_fetch); diff --git a/tests/pull-test.sh b/tests/pull-test.sh index 9d51b151..a8bc49a9 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -334,6 +334,12 @@ if ${CMD_PREFIX} ostree --repo=repo pull -T origin main 2>err.txt; then fi assert_file_has_content err.txt "Upgrade.*is chronologically older" assert_streq ${newrev} "$(${CMD_PREFIX} ostree --repo=repo rev-parse main)" +# And also check we can't pull it when using overrides +if ${CMD_PREFIX} ostree --repo=repo pull -T origin main@${newrev2} 2>err.txt; then + fatal "pulled older commit override with timestamp checking enabled?" +fi +assert_file_has_content err.txt "Upgrade.*is chronologically older" +assert_streq ${newrev} "$(${CMD_PREFIX} ostree --repo=repo rev-parse main)" # But we can pull it without timestamp checking ${CMD_PREFIX} ostree --repo=repo pull origin main echo "ok pull timestamp checking" From 97c673b64bcb351ade811818683fa5609d8994d7 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Fri, 26 Jul 2019 11:52:27 -0400 Subject: [PATCH 48/62] lib/pull: Rename variable for clarity Let's use `checksum` instead of the more general `contents`. Closes: #1891 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 67b28f8c..04551f2c 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -4334,14 +4334,14 @@ ostree_repo_pull_with_options (OstreeRepo *self, GLNX_HASH_TABLE_FOREACH_KV (requested_refs_to_fetch, const OstreeCollectionRef*, ref, const char*, override_commitid) { - g_autofree char *contents = NULL; + g_autofree char *checksum = NULL; g_autoptr(OstreeCollectionRef) ref_with_collection = NULL; /* Support specifying "" for an override commitid */ if (override_commitid && *override_commitid) { ref_with_collection = ostree_collection_ref_dup (ref); - contents = g_strdup (override_commitid); + checksum = g_strdup (override_commitid); } else { @@ -4351,18 +4351,18 @@ ostree_repo_pull_with_options (OstreeRepo *self, guint64 *malloced_size; g_autofree gchar *collection_id = NULL; - if (!lookup_commit_checksum_and_collection_from_summary (pull_data, ref, &contents, &commit_size, &collection_id, error)) + if (!lookup_commit_checksum_and_collection_from_summary (pull_data, ref, &checksum, &commit_size, &collection_id, error)) goto out; ref_with_collection = ostree_collection_ref_new (collection_id, ref->ref_name); malloced_size = g_new0 (guint64, 1); *malloced_size = commit_size; - g_hash_table_insert (pull_data->expected_commit_sizes, g_strdup (contents), malloced_size); + g_hash_table_insert (pull_data->expected_commit_sizes, g_strdup (checksum), malloced_size); } else { - if (!fetch_ref_contents (pull_data, main_collection_id, ref, &contents, cancellable, error)) + if (!fetch_ref_contents (pull_data, main_collection_id, ref, &checksum, cancellable, error)) goto out; ref_with_collection = ostree_collection_ref_dup (ref); @@ -4389,7 +4389,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_hash_table_replace (updated_requested_refs_to_fetch, g_steal_pointer (&ref_with_collection), - g_steal_pointer (&contents)); + g_steal_pointer (&checksum)); } g_hash_table_unref (requested_refs_to_fetch); From b7a9c6d07c5e6f252468bac67a42229080d7580a Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Sun, 19 May 2019 16:24:40 +0300 Subject: [PATCH 49/62] build: Add conditional use of GPGME Allow to disable GPGME support with option "--without-gpgme" for configure. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- configure.ac | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 1d083d95..e37d5f77 100644 --- a/configure.ac +++ b/configure.ac @@ -210,25 +210,35 @@ m4_ifdef([GOBJECT_INTROSPECTION_CHECK], [ AM_CONDITIONAL(BUILDOPT_INTROSPECTION, test "x$found_introspection" = xyes) LIBGPGME_DEPENDENCY="1.1.8" - -PKG_CHECK_MODULES(OT_DEP_GPGME, gpgme-pthread >= $LIBGPGME_DEPENDENCY, have_gpgme=yes, [ - m4_ifdef([AM_PATH_GPGME_PTHREAD], [ - AM_PATH_GPGME_PTHREAD($LIBGPGME_DEPENDENCY, have_gpgme=yes, have_gpgme=no) - ],[ have_gpgme=no ]) -]) -AS_IF([ test x$have_gpgme = xno ], [ - AC_MSG_ERROR([Need GPGME_PTHREAD version $LIBGPGME_DEPENDENCY or later]) -]) -OSTREE_FEATURES="$OSTREE_FEATURES gpgme" -PKG_CHECK_MODULES(OT_DEP_GPG_ERROR, [gpg-error], [], [ +AC_ARG_WITH(gpgme, + AS_HELP_STRING([--with-gpgme], [Use gpgme @<:@default=yes@:>@]), + [], [with_gpgme=yes]) +AS_IF([test x$with_gpgme != xno], [ + PKG_CHECK_MODULES(OT_DEP_GPGME, gpgme-pthread >= $LIBGPGME_DEPENDENCY, have_gpgme=yes, [ + m4_ifdef([AM_PATH_GPGME_PTHREAD], [ + AM_PATH_GPGME_PTHREAD($LIBGPGME_DEPENDENCY, have_gpgme=yes, have_gpgme=no) + ],[ have_gpgme=no ]) + ]) + AS_IF([ test x$have_gpgme = xno ], [ + AC_MSG_ERROR([Need GPGME_PTHREAD version $LIBGPGME_DEPENDENCY or later]) + ]) + OSTREE_FEATURES="$OSTREE_FEATURES gpgme" + PKG_CHECK_MODULES(OT_DEP_GPG_ERROR, [gpg-error], [], [ dnl This apparently doesn't ship a pkg-config file either, and we need dnl to link to it directly. - AC_PATH_PROG(GPG_ERROR_CONFIG, [gpg-error-config], [AC_MSG_ERROR([Missing gpg-error-config])]) - OT_DEP_GPG_ERROR_CFLAGS="$( $GPG_ERROR_CONFIG --cflags )" - OT_DEP_GPG_ERROR_LIBS="$( $GPG_ERROR_CONFIG --libs )" -]) -OT_DEP_GPGME_CFLAGS="${OT_DEP_GPGME_CFLAGS} ${OT_DEP_GPG_ERROR_CFLAGS}" -OT_DEP_GPGME_LIBS="${OT_DEP_GPGME_LIBS} ${OT_DEP_GPG_ERROR_LIBS}" + AC_PATH_PROG(GPG_ERROR_CONFIG, [gpg-error-config], [AC_MSG_ERROR([Missing gpg-error-config])]) + OT_DEP_GPG_ERROR_CFLAGS="$( $GPG_ERROR_CONFIG --cflags )" + OT_DEP_GPG_ERROR_LIBS="$( $GPG_ERROR_CONFIG --libs )" + ]) + OT_DEP_GPGME_CFLAGS="${OT_DEP_GPGME_CFLAGS} ${OT_DEP_GPG_ERROR_CFLAGS}" + OT_DEP_GPGME_LIBS="${OT_DEP_GPGME_LIBS} ${OT_DEP_GPG_ERROR_LIBS}" + ], + [ + AC_DEFINE([OSTREE_DISABLE_GPGME], 1, [Define to disable internal GPGME support]) + with_gpgme=no + ] +) +AM_CONDITIONAL(USE_GPGME, test "x$have_gpgme" = xyes) LIBARCHIVE_DEPENDENCY="libarchive >= 2.8.0" # What's in RHEL7.2. From ca8752e01bdf23650d586a3a5dc6ef04d04cbea6 Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Sun, 19 May 2019 16:47:45 +0300 Subject: [PATCH 50/62] build: Conditionally build GPGME-related sources Do not build GPGME-related sources if flag USE_GPGME is not defined. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- Makefile-libostree.am | 13 +++++++++---- Makefile-man.am | 6 +++++- Makefile-ostree.am | 14 ++++++++++++-- Makefile-otutil.am | 10 ++++++++-- Makefile.am | 2 ++ 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 1f1e0bc7..61763f95 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -126,10 +126,6 @@ libostree_1_la_SOURCES = \ src/libostree/ostree-repo-static-delta-compilation.c \ src/libostree/ostree-repo-static-delta-compilation-analysis.c \ src/libostree/ostree-repo-static-delta-private.h \ - src/libostree/ostree-gpg-verifier.c \ - src/libostree/ostree-gpg-verifier.h \ - src/libostree/ostree-gpg-verify-result.c \ - src/libostree/ostree-gpg-verify-result-private.h \ src/libostree/ostree-autocleanups.h \ src/libostree/ostree-bloom.c \ src/libostree/ostree-bloom-private.h \ @@ -169,6 +165,15 @@ libostree_1_la_SOURCES += \ $(NULL) endif # USE_AVAHI +if USE_GPGME +libostree_1_la_SOURCES += \ + src/libostree/ostree-gpg-verifier.c \ + src/libostree/ostree-gpg-verifier.h \ + src/libostree/ostree-gpg-verify-result.c \ + src/libostree/ostree-gpg-verify-result-private.h \ + $(NULL) +endif # USE_GPGME + symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym if BUILDOPT_IS_DEVEL_BUILD symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym diff --git a/Makefile-man.am b/Makefile-man.am index 8ccbba8c..c27a9a55 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -28,7 +28,7 @@ ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \ ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \ ostree-admin-pin.1 \ ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \ -ostree-commit.1 ostree-create-usb.1 ostree-export.1 ostree-gpg-sign.1 \ +ostree-commit.1 ostree-create-usb.1 ostree-export.1 \ ostree-config.1 ostree-diff.1 ostree-find-remotes.1 ostree-fsck.1 \ ostree-init.1 ostree-log.1 ostree-ls.1 ostree-prune.1 ostree-pull-local.1 \ ostree-pull.1 ostree-refs.1 ostree-remote.1 ostree-reset.1 \ @@ -45,6 +45,10 @@ if BUILDOPT_FUSE man1_files += rofiles-fuse.1 endif +if USE_GPGME +man1_files += ostree-gpg-sign.1 +endif + man5_files = ostree.repo.5 ostree.repo-config.5 man1_MANS = $(addprefix man/,$(man1_files)) diff --git a/Makefile-ostree.am b/Makefile-ostree.am index 92881a31..76f39cad 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -34,7 +34,6 @@ ostree_SOURCES = src/ostree/main.c \ src/ostree/ot-builtin-export.c \ src/ostree/ot-builtin-find-remotes.c \ src/ostree/ot-builtin-fsck.c \ - src/ostree/ot-builtin-gpg-sign.c \ src/ostree/ot-builtin-init.c \ src/ostree/ot-builtin-pull-local.c \ src/ostree/ot-builtin-log.c \ @@ -65,6 +64,12 @@ ostree_SOURCES += \ $(NULL) endif +if USE_GPGME +ostree_SOURCES += \ + src/ostree/ot-builtin-gpg-sign.c \ + $(NULL) +endif + # Admin subcommand ostree_SOURCES += \ src/ostree/ot-admin-builtin-init-fs.c \ @@ -95,13 +100,18 @@ ostree_SOURCES += \ src/ostree/ot-remote-builtins.h \ src/ostree/ot-remote-builtin-add.c \ src/ostree/ot-remote-builtin-delete.c \ - src/ostree/ot-remote-builtin-gpg-import.c \ src/ostree/ot-remote-builtin-list.c \ src/ostree/ot-remote-builtin-show-url.c \ src/ostree/ot-remote-builtin-refs.c \ src/ostree/ot-remote-builtin-summary.c \ $(NULL) +if USE_GPGME +ostree_SOURCES += \ + src/ostree/ot-remote-builtin-gpg-import.c \ + $(NULL) +endif + if USE_CURL_OR_SOUP ostree_SOURCES += src/ostree/ot-remote-builtin-add-cookie.c \ diff --git a/Makefile-otutil.am b/Makefile-otutil.am index 5bafb2d0..e8901b57 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -40,11 +40,17 @@ libotutil_la_SOURCES = \ src/libotutil/ot-variant-builder.h \ src/libotutil/ot-gio-utils.c \ src/libotutil/ot-gio-utils.h \ - src/libotutil/ot-gpg-utils.c \ - src/libotutil/ot-gpg-utils.h \ src/libotutil/otutil.h \ src/libotutil/ot-tool-util.c \ src/libotutil/ot-tool-util.h \ $(NULL) + +if USE_GPGME +libotutil_la_SOURCES += \ + src/libotutil/ot-gpg-utils.c \ + src/libotutil/ot-gpg-utils.h \ + $(NULL) +endif + libotutil_la_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/libglnx -I$(srcdir)/src/libotutil -DLOCALEDIR=\"$(datadir)/locale\" $(OT_INTERNAL_GIO_UNIX_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) $(LIBSYSTEMD_CFLAGS) libotutil_la_LIBADD = $(OT_INTERNAL_GIO_UNIX_LIBS) $(OT_INTERNAL_GPGME_LIBS) $(LIBSYSTEMD_LIBS) diff --git a/Makefile.am b/Makefile.am index 4850cddd..cd04a055 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,8 +57,10 @@ OT_INTERNAL_SOUP_CFLAGS = $(OT_DEP_SOUP_CFLAGS) OT_INTERNAL_SOUP_LIBS = $(OT_DEP_SOUP_LIBS) # This canonicalizes the PKG_CHECK_MODULES or AM_PATH_GPGME results +if USE_GPGME OT_INTERNAL_GPGME_CFLAGS = $(OT_DEP_GPGME_CFLAGS) $(GPGME_PTHREAD_CFLAGS) OT_INTERNAL_GPGME_LIBS = $(OT_DEP_GPGME_LIBS) $(GPGME_PTHREAD_LIBS) +endif if BUILDOPT_INTROSPECTION include $(INTROSPECTION_MAKEFILE) From e187f240fc399f8d9d769cec631e1d046e065066 Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 21 May 2019 01:23:14 +0300 Subject: [PATCH 51/62] build: Conditionally build the GPG-related tests Do not build GPG signing/verification tests if `--without-gpgme` option is used during configuration. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- Makefile-tests.am | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Makefile-tests.am b/Makefile-tests.am index ac59b94b..5498fd43 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -68,7 +68,6 @@ _installed_or_uninstalled_test_scripts = \ tests/test-archivez.sh \ tests/test-remote-add.sh \ tests/test-remote-headers.sh \ - tests/test-remote-gpg-import.sh \ tests/test-commit-sign.sh \ tests/test-export.sh \ tests/test-help.sh \ @@ -91,7 +90,6 @@ _installed_or_uninstalled_test_scripts = \ tests/test-pull-localcache.sh \ tests/test-local-pull.sh \ tests/test-local-pull-depth.sh \ - tests/test-gpg-signed-commit.sh \ tests/test-admin-upgrade-unconfigured.sh \ tests/test-admin-upgrade-endoflife.sh \ tests/test-admin-upgrade-systemd-update.sh \ @@ -110,7 +108,6 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-pull-deploy-split.sh \ tests/test-admin-locking.sh \ tests/test-admin-deploy-clean.sh \ - tests/test-admin-gpg.sh \ tests/test-reset-nonlinear.sh \ tests/test-oldstyle-partial.sh \ tests/test-delta.sh \ @@ -139,6 +136,14 @@ _installed_or_uninstalled_test_scripts = \ tests/test-config.sh \ $(NULL) +if USE_GPGME +_installed_or_uninstalled_test_scripts += \ + tests/test-remote-gpg-import.sh \ + tests/test-gpg-signed-commit.sh \ + tests/test-admin-gpg.sh \ + $(NULL) +endif + experimental_test_scripts = \ $(NULL) test_extra_programs = \ @@ -200,6 +205,7 @@ dist_test_extra_scripts = \ tests/ostree-grub-generator \ $(NULL) +if USE_GPGME # We can't use nobase_ as we need to strip off the tests/, can't # use plain installed_ as we do need the gpghome/ prefix. if ENABLE_INSTALLED_TESTS @@ -217,6 +223,7 @@ gpgvinsttestdir = $(installed_testdir)/gpg-verify-data dist_gpgvinsttest_DATA = $(addprefix tests/gpg-verify-data/, \ gpg.conf lgpl2 lgpl2.sig pubring.gpg secring.gpg trustdb.gpg) endif +endif js_installed_tests = \ tests/test-core.js \ @@ -245,9 +252,15 @@ endif _installed_or_uninstalled_test_programs = tests/test-varint tests/test-ot-unix-utils tests/test-bsdiff tests/test-mutable-tree \ tests/test-keyfile-utils tests/test-ot-opt-utils tests/test-ot-tool-util \ - tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \ + tests/test-checksum tests/test-lzma tests/test-rollsum \ tests/test-basic-c tests/test-sysroot-c tests/test-pull-c tests/test-repo tests/test-include-ostree-h tests/test-kargs +if USE_GPGME +_installed_or_uninstalled_test_programs += \ + tests/test-gpg-verify-result \ + $(NULL) +endif + if USE_AVAHI test_programs += tests/test-repo-finder-avahi endif @@ -354,16 +367,21 @@ tests_test_lzma_SOURCES = src/libostree/ostree-lzma-common.c src/libostree/ostre tests_test_lzma_CFLAGS = $(TESTS_CFLAGS) $(OT_DEP_LZMA_CFLAGS) tests_test_lzma_LDADD = $(TESTS_LDADD) $(OT_DEP_LZMA_LIBS) +if USE_GPGME tests_test_gpg_verify_result_SOURCES = \ src/libostree/ostree-gpg-verify-result-private.h \ tests/test-gpg-verify-result.c tests_test_gpg_verify_result_CFLAGS = $(TESTS_CFLAGS) $(OT_INTERNAL_GPGME_CFLAGS) tests_test_gpg_verify_result_LDADD = $(TESTS_LDADD) $(OT_INTERNAL_GPGME_LIBS) +EXTRA_DIST += \ + tests/gpg-verify-data/README.md \ + $(NULL) +endif + EXTRA_DIST += \ tests/libostreetest.h \ tests/libtest.sh \ - tests/gpg-verify-data/README.md \ $(NULL) tests/libreaddir-rand.so: Makefile From 0108e9ea4977ac730b5064b8198fe0ffd74df767 Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 21 May 2019 01:35:25 +0300 Subject: [PATCH 52/62] gpg: conditionally build GPG-related code for sign/verification Do not build the code related to GPG sign and verification if GPGME support is disabled. Public functions return error 'G_IO_ERROR_NOT_SUPPORTED' in case if gpg-related check is rquested. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- src/libostree/ostree-core-private.h | 2 + src/libostree/ostree-core.c | 2 + src/libostree/ostree-repo-private.h | 2 + src/libostree/ostree-repo-pull.c | 55 ++++++++++++++- src/libostree/ostree-repo.c | 97 +++++++++++++++++++++++++- src/libostree/ostree-repo.h | 68 +++++++++--------- src/libotutil/otutil.h | 5 +- src/ostree/main.c | 2 + src/ostree/ot-admin-builtin-status.c | 4 ++ src/ostree/ot-builtin-commit.c | 6 ++ src/ostree/ot-builtin-pull.c | 4 ++ src/ostree/ot-builtin-remote.c | 2 + src/ostree/ot-builtin-show.c | 2 + src/ostree/ot-builtin-summary.c | 2 + src/ostree/ot-builtins.h | 2 + src/ostree/ot-main.c | 2 + src/ostree/ot-remote-builtin-add.c | 4 ++ src/ostree/ot-remote-builtin-summary.c | 4 ++ 18 files changed, 225 insertions(+), 40 deletions(-) diff --git a/src/libostree/ostree-core-private.h b/src/libostree/ostree-core-private.h index dd2cbc7e..43cf22c4 100644 --- a/src/libostree/ostree-core-private.h +++ b/src/libostree/ostree-core-private.h @@ -190,9 +190,11 @@ _ostree_repo_mode_is_bare (OstreeRepoMode mode) mode == OSTREE_REPO_MODE_BARE_USER_ONLY; } +#ifndef OSTREE_DISABLE_GPGME GVariant * _ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata, GBytes *signature_bytes); +#endif GFile * _ostree_get_default_sysroot_path (void); diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 36539698..3d16757e 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -2462,6 +2462,7 @@ _ostree_compare_timestamps (const char *current_rev, } +#ifndef OSTREE_DISABLE_GPGME GVariant * _ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata, GBytes *signature_bytes) @@ -2487,6 +2488,7 @@ _ostree_detached_metadata_append_gpg_sig (GVariant *existing_metadata, return g_variant_dict_end (&metadata_dict); } +#endif /* OSTREE_DISABLE_GPGME */ /** * _ostree_get_default_sysroot_path: diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 6bc74c2d..b57ad799 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -332,6 +332,7 @@ _ostree_repo_commit_modifier_apply (OstreeRepo *self, gboolean _ostree_repo_remote_name_is_file (const char *remote_name); +#ifndef OSTREE_DISABLE_GPGME OstreeGpgVerifyResult * _ostree_repo_gpg_verify_with_metadata (OstreeRepo *self, GBytes *signed_data, @@ -350,6 +351,7 @@ _ostree_repo_verify_commit_internal (OstreeRepo *self, GFile *extra_keyring, GCancellable *cancellable, GError **error); +#endif /* OSTREE_DISABLE_GPGME */ typedef enum { _OSTREE_REPO_IMPORT_FLAGS_NONE, diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 04551f2c..7889eeb2 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -104,9 +104,9 @@ typedef struct { gint n_scanned_metadata; gboolean gpg_verify; + gboolean gpg_verify_summary; gboolean require_static_deltas; gboolean disable_static_deltas; - gboolean gpg_verify_summary; gboolean has_tombstone_commits; GBytes *summary_data; @@ -1294,7 +1294,7 @@ meta_fetch_on_complete (GObject *object, if (!_ostree_verify_metadata_object (objtype, checksum, metadata, error)) goto out; - /* For commit objects, check the GPG signature before writing to the repo, + /* For commit objects, check the signature before writing to the repo, * and also write the .commitpartial to say that we're still processing * this commit. */ @@ -1433,6 +1433,7 @@ static_deltapart_fetch_on_complete (GObject *object, g_clear_pointer (&fetch_data, fetch_static_delta_data_free); } +#ifndef OSTREE_DISABLE_GPGME static gboolean process_verify_result (OtPullData *pull_data, const char *checksum, @@ -1462,6 +1463,7 @@ process_verify_result (OtPullData *pull_data, return TRUE; } +#endif /* OSTREE_DISABLE_GPGME */ static gboolean gpg_verify_unwritten_commit (OtPullData *pull_data, @@ -1472,6 +1474,7 @@ gpg_verify_unwritten_commit (OtPullData *pull_data, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME if (pull_data->gpg_verify) { const char *keyring_remote = NULL; @@ -1494,6 +1497,7 @@ gpg_verify_unwritten_commit (OtPullData *pull_data, if (!process_verify_result (pull_data, checksum, result, error)) return FALSE; } +#endif /* OSTREE_DISABLE_GPGME */ return TRUE; } @@ -1702,6 +1706,7 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME gsize i; g_auto(GStrv) remotes = NULL; g_autoptr(OstreeRemote) keyring_remote = NULL; @@ -1763,6 +1768,12 @@ ostree_repo_resolve_keyring_for_collection (OstreeRepo *self, collection_id); return NULL; } +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return NULL; +#endif /* OSTREE_DISABLE_GPGME */ } #ifdef HAVE_LIBCURL_OR_LIBSOUP @@ -1792,6 +1803,7 @@ scan_commit_object (OtPullData *pull_data, GINT_TO_POINTER (depth)); } +#ifndef OSTREE_DISABLE_GPGME /* See comment in process_verify_result() - we now gpg check before writing, * but also ensure we've done it here if not already. */ @@ -1814,6 +1826,7 @@ scan_commit_object (OtPullData *pull_data, if (!process_verify_result (pull_data, checksum, result, error)) return FALSE; } +#endif /* OSTREE_DISABLE_GPGME */ /* If we found a legacy transaction flag, assume we have to scan. * We always do a scan of dirtree objects; see @@ -2742,6 +2755,7 @@ on_superblock_fetched (GObject *src, ot_checksum_update_bytes (&hasher, delta_superblock_data); ot_checksum_get_digest (&hasher, actual_summary_digest, sizeof (actual_summary_digest)); +#ifndef OSTREE_DISABLE_GPGME /* At this point we've GPG verified the data, so in theory * could trust that they provided the right data, but let's * make this a hard error. @@ -2752,6 +2766,7 @@ on_superblock_fetched (GObject *src, "GPG verification enabled, but no summary signatures found (use gpg-verify-summary=false in remote config to disable)"); goto out; } +#endif /* OSTREE_DISABLE_GPGME */ if (expected_summary_digest && memcmp (expected_summary_digest, actual_summary_digest, sizeof (actual_summary_digest))) { @@ -3618,6 +3633,17 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->remote_name = g_strdup (pull_data->remote_refspec_name); } +#ifdef OSTREE_DISABLE_GPGME + /* Explicitly fail here if gpg verification is requested and we have no GPG support */ + if (opt_gpg_verify_set || opt_gpg_verify_summary_set) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + goto out; + } +#endif + g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE); g_return_val_if_fail (pull_data->maxdepth >= -1, FALSE); g_return_val_if_fail (!pull_data->timestamp_check || pull_data->maxdepth == 0, FALSE); @@ -3745,6 +3771,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_free (pull_data->remote_name); pull_data->remote_name = g_strdup (remote_name_or_baseurl); +#ifndef OSTREE_DISABLE_GPGME /* Fetch GPG verification settings from remote if it wasn't already * explicitly set in the options. */ if (!opt_gpg_verify_set) @@ -3756,6 +3783,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (!ostree_repo_remote_get_gpg_verify_summary (self, pull_data->remote_name, &pull_data->gpg_verify_summary, error)) goto out; +#endif /* OSTREE_DISABLE_GPGME */ /* NOTE: If changing this, see the matching implementation in * ostree-sysroot-upgrader.c @@ -4060,12 +4088,14 @@ ostree_repo_pull_with_options (OstreeRepo *self, goto out; } +#ifndef OSTREE_DISABLE_GPGME if (!bytes_summary && pull_data->gpg_verify_summary) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "GPG verification enabled, but no summary found (use gpg-verify-summary=false in remote config to disable)"); goto out; } +#endif /* OSTREE_DISABLE_GPGME */ if (!bytes_summary && pull_data->require_static_deltas) { @@ -4074,6 +4104,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, goto out; } +#ifndef OSTREE_DISABLE_GPGME if (!bytes_sig && pull_data->gpg_verify_summary) { g_set_error (error, OSTREE_GPG_ERROR, OSTREE_GPG_ERROR_NO_SIGNATURE, @@ -4132,6 +4163,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, } } } +#endif /* OSTREE_DISABLE_GPGME */ if (bytes_summary) { @@ -4614,6 +4646,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->remote_name, g_hash_table_size (requested_refs_to_fetch)); const char *gpg_verify_state; +#ifndef OSTREE_DISABLE_GPGME if (pull_data->gpg_verify_summary) { if (pull_data->gpg_verify) @@ -4624,6 +4657,11 @@ ostree_repo_pull_with_options (OstreeRepo *self, else gpg_verify_state = (pull_data->gpg_verify ? "commit" : "disabled"); g_string_append_printf (msg, "\nsecurity: GPG: %s ", gpg_verify_state); +#else + gpg_verify_state = "disabled"; + g_string_append_printf (msg, "\nsecurity: %s ", gpg_verify_state); +#endif /* OSTREE_DISABLE_GPGME */ + OstreeFetcherURI *first_uri = pull_data->meta_mirrorlist->pdata[0]; g_autofree char *first_scheme = _ostree_fetcher_uri_get_scheme (first_uri); if (g_str_has_prefix (first_scheme, "http")) @@ -5970,7 +6008,11 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self, g_variant_dict_insert (&local_options_dict, "flags", "i", OSTREE_REPO_PULL_FLAGS_UNTRUSTED | flags); g_variant_dict_insert_value (&local_options_dict, "collection-refs", g_variant_builder_end (&refs_to_pull_builder)); +#ifndef OSTREE_DISABLE_GPGME g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", TRUE); +#else + g_variant_dict_insert (&local_options_dict, "gpg-verify", "b", FALSE); +#endif /* OSTREE_DISABLE_GPGME */ g_variant_dict_insert (&local_options_dict, "gpg-verify-summary", "b", FALSE); g_variant_dict_insert (&local_options_dict, "inherit-transaction", "b", TRUE); if (result->remote->refspec_name != NULL) @@ -6118,8 +6160,10 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, g_autofree char *metalink_url_string = NULL; g_autoptr(GBytes) summary = NULL; g_autoptr(GBytes) signatures = NULL; - gboolean ret = FALSE; +#ifndef OSTREE_DISABLE_GPGME gboolean gpg_verify_summary; +#endif + gboolean ret = FALSE; gboolean summary_is_from_cache; g_return_val_if_fail (OSTREE_REPO (self), FALSE); @@ -6140,6 +6184,7 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, error)) goto out; +#ifndef OSTREE_DISABLE_GPGME if (!ostree_repo_remote_get_gpg_verify_summary (self, name, &gpg_verify_summary, error)) goto out; @@ -6193,6 +6238,10 @@ ostree_repo_remote_fetch_summary_with_options (OstreeRepo *self, } } +#else + g_message ("%s: GPG feature is disabled in a build time", __FUNCTION__); +#endif /* OSTREE_DISABLE_GPGME */ + if (out_summary != NULL) *out_summary = g_steal_pointer (&summary); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 804ff6c6..eb652bef 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -139,9 +139,11 @@ G_STATIC_ASSERT(sizeof(OstreeRepoPruneOptions) == typedef struct { GObjectClass parent_class; +#ifndef OSTREE_DISABLE_GPGME void (*gpg_verify_result) (OstreeRepo *self, const char *checksum, OstreeGpgVerifyResult *result); +#endif } OstreeRepoClass; enum { @@ -157,7 +159,9 @@ enum { LAST_SIGNAL }; +#ifndef OSTREE_DISABLE_GPGME static guint signals[LAST_SIGNAL] = { 0 }; +#endif G_DEFINE_TYPE (OstreeRepo, ostree_repo, G_TYPE_OBJECT) @@ -1167,6 +1171,7 @@ ostree_repo_class_init (OstreeRepoClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +#ifndef OSTREE_DISABLE_GPGME /** * OstreeRepo::gpg-verify-result: * @self: an #OstreeRepo @@ -1189,23 +1194,27 @@ ostree_repo_class_init (OstreeRepoClass *klass) G_TYPE_NONE, 2, G_TYPE_STRING, OSTREE_TYPE_GPG_VERIFY_RESULT); +#endif /* OSTREE_DISABLE_GPGME */ } static void ostree_repo_init (OstreeRepo *self) { - static gsize gpgme_initialized; const GDebugKey test_error_keys[] = { { "pre-commit", OSTREE_REPO_TEST_ERROR_PRE_COMMIT }, { "invalid-cache", OSTREE_REPO_TEST_ERROR_INVALID_CACHE }, }; +#ifndef OSTREE_DISABLE_GPGME + static gsize gpgme_initialized; + if (g_once_init_enter (&gpgme_initialized)) { gpgme_check_version (NULL); gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); g_once_init_leave (&gpgme_initialized, 1); } +#endif self->test_error_flags = g_parse_debug_string (g_getenv ("OSTREE_REPO_TEST_ERROR"), test_error_keys, G_N_ELEMENTS (test_error_keys)); @@ -2017,8 +2026,17 @@ ostree_repo_remote_get_gpg_verify (OstreeRepo *self, return TRUE; } - return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify", +#ifndef OSTREE_DISABLE_GPGME + return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify", TRUE, out_gpg_verify, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + if (out_gpg_verify != NULL) + *out_gpg_verify = FALSE; + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -2040,8 +2058,17 @@ ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self, gboolean *out_gpg_verify_summary, GError **error) { +#ifndef OSTREE_DISABLE_GPGME return ostree_repo_get_remote_boolean_option (self, name, "gpg-verify-summary", FALSE, out_gpg_verify_summary, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + if (out_gpg_verify_summary != NULL) + *out_gpg_verify_summary = FALSE; + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -2074,6 +2101,7 @@ ostree_repo_remote_gpg_import (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME OstreeRemote *remote; g_auto(gpgme_ctx_t) source_context = NULL; g_auto(gpgme_ctx_t) target_context = NULL; @@ -2313,6 +2341,12 @@ out: g_prefix_error (error, "GPG: "); return ret; +#else /* OSTREE_DISABLE_GPGME */ + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -4904,6 +4938,7 @@ ostree_repo_append_gpg_signature (OstreeRepo *self, error)) return FALSE; +#ifndef OSTREE_DISABLE_GPGME g_autoptr(GVariant) new_metadata = _ostree_detached_metadata_append_gpg_sig (metadata, signature_bytes); @@ -4915,8 +4950,15 @@ ostree_repo_append_gpg_signature (OstreeRepo *self, return FALSE; return TRUE; +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } +#ifndef OSTREE_DISABLE_GPGME static gboolean sign_data (OstreeRepo *self, GBytes *input_data, @@ -4977,6 +5019,7 @@ sign_data (OstreeRepo *self, *out_signature = g_mapped_file_get_bytes (signature_file); return TRUE; } +#endif /* OSTREE_DISABLE_GPGME */ /** * ostree_repo_sign_commit: @@ -4997,6 +5040,7 @@ ostree_repo_sign_commit (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME g_autoptr(GBytes) commit_data = NULL; g_autoptr(GBytes) signature = NULL; @@ -5060,6 +5104,10 @@ ostree_repo_sign_commit (OstreeRepo *self, return FALSE; return TRUE; +#else + /* FIXME: Return false until refactoring */ + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -5106,6 +5154,7 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME glnx_autofd int fd = -1; if (!glnx_openat_rdonly (self->repo_dir_fd, "summary", TRUE, &fd, error)) return FALSE; @@ -5148,8 +5197,15 @@ ostree_repo_add_gpg_signature_summary (OstreeRepo *self, return FALSE; return TRUE; +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } +#ifndef OSTREE_DISABLE_GPGME /* Special remote for _ostree_repo_gpg_verify_with_metadata() */ static const char *OSTREE_ALL_REMOTES = "__OSTREE_ALL_REMOTES__"; @@ -5383,6 +5439,7 @@ _ostree_repo_verify_commit_internal (OstreeRepo *self, keyringdir, extra_keyring, cancellable, error); } +#endif /* OSTREE_DISABLE_GPGME */ /** * ostree_repo_verify_commit: @@ -5406,6 +5463,7 @@ ostree_repo_verify_commit (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME g_autoptr(OstreeGpgVerifyResult) result = NULL; result = ostree_repo_verify_commit_ext (self, commit_checksum, @@ -5415,6 +5473,13 @@ ostree_repo_verify_commit (OstreeRepo *self, if (!ostree_gpg_verify_result_require_valid_signature (result, error)) return glnx_prefix_error (error, "Commit %s", commit_checksum); return TRUE; +#else + /* FIXME: Return false until refactoring */ + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return FALSE; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -5439,6 +5504,7 @@ ostree_repo_verify_commit_ext (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME return _ostree_repo_verify_commit_internal (self, commit_checksum, NULL, @@ -5446,6 +5512,12 @@ ostree_repo_verify_commit_ext (OstreeRepo *self, extra_keyring, cancellable, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return NULL; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -5471,6 +5543,7 @@ ostree_repo_verify_commit_for_remote (OstreeRepo *self, GCancellable *cancellable, GError **error) { +#ifndef OSTREE_DISABLE_GPGME return _ostree_repo_verify_commit_internal (self, commit_checksum, remote_name, @@ -5478,6 +5551,12 @@ ostree_repo_verify_commit_for_remote (OstreeRepo *self, NULL, cancellable, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return NULL; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -5515,6 +5594,7 @@ ostree_repo_gpg_verify_data (OstreeRepo *self, g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (signatures != NULL, NULL); +#ifndef OSTREE_DISABLE_GPGME return _ostree_repo_gpg_verify_data_internal (self, (remote_name != NULL) ? remote_name : OSTREE_ALL_REMOTES, data, @@ -5523,6 +5603,12 @@ ostree_repo_gpg_verify_data (OstreeRepo *self, extra_keyring, cancellable, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return NULL; +#endif /* OSTREE_DISABLE_GPGME */ } /** @@ -5557,6 +5643,7 @@ ostree_repo_verify_summary (OstreeRepo *self, signatures_variant = g_variant_new_from_bytes (OSTREE_SUMMARY_SIG_GVARIANT_FORMAT, signatures, FALSE); +#ifndef OSTREE_DISABLE_GPGME return _ostree_repo_gpg_verify_with_metadata (self, summary, signatures_variant, @@ -5564,6 +5651,12 @@ ostree_repo_verify_summary (OstreeRepo *self, NULL, NULL, cancellable, error); +#else + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return NULL; +#endif /* OSTREE_DISABLE_GPGME */ } /* Add an entry for a @ref ↦ @checksum mapping to an `a(s(t@ay@a{sv}))` diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index b5af2f82..038bbd41 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -199,18 +199,6 @@ gboolean ostree_repo_remote_get_url (OstreeRepo *self, char **out_url, GError **error); -_OSTREE_PUBLIC -gboolean ostree_repo_remote_get_gpg_verify (OstreeRepo *self, - const char *name, - gboolean *out_gpg_verify, - GError **error); - -_OSTREE_PUBLIC -gboolean ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self, - const char *name, - gboolean *out_gpg_verify_summary, - GError **error); - _OSTREE_PUBLIC gboolean ostree_repo_get_remote_option (OstreeRepo *self, const char *remote_name, @@ -234,14 +222,6 @@ gboolean ostree_repo_get_remote_boolean_option (OstreeRepo *self, gboolean *out_value, GError **error); -_OSTREE_PUBLIC -gboolean ostree_repo_remote_gpg_import (OstreeRepo *self, - const char *name, - GInputStream *source_stream, - const char * const *key_ids, - guint *out_imported, - GCancellable *cancellable, - GError **error); _OSTREE_PUBLIC gboolean ostree_repo_remote_fetch_summary (OstreeRepo *self, @@ -1337,20 +1317,6 @@ gboolean ostree_repo_sign_delta (OstreeRepo *self, GCancellable *cancellable, GError **error); -_OSTREE_PUBLIC -gboolean -ostree_repo_add_gpg_signature_summary (OstreeRepo *self, - const gchar **key_id, - const gchar *homedir, - GCancellable *cancellable, - GError **error); - -_OSTREE_PUBLIC -gboolean ostree_repo_append_gpg_signature (OstreeRepo *self, - const gchar *commit_checksum, - GBytes *signature_bytes, - GCancellable *cancellable, - GError **error); _OSTREE_PUBLIC gboolean ostree_repo_verify_commit (OstreeRepo *self, @@ -1360,6 +1326,40 @@ gboolean ostree_repo_verify_commit (OstreeRepo *self, GCancellable *cancellable, GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_remote_get_gpg_verify (OstreeRepo *self, + const char *name, + gboolean *out_gpg_verify, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_repo_remote_get_gpg_verify_summary (OstreeRepo *self, + const char *name, + gboolean *out_gpg_verify_summary, + GError **error); +_OSTREE_PUBLIC +gboolean ostree_repo_remote_gpg_import (OstreeRepo *self, + const char *name, + GInputStream *source_stream, + const char * const *key_ids, + guint *out_imported, + GCancellable *cancellable, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_repo_add_gpg_signature_summary (OstreeRepo *self, + const gchar **key_id, + const gchar *homedir, + GCancellable *cancellable, + GError **error); + +_OSTREE_PUBLIC +gboolean ostree_repo_append_gpg_signature (OstreeRepo *self, + const gchar *commit_checksum, + GBytes *signature_bytes, + GCancellable *cancellable, + GError **error); + _OSTREE_PUBLIC OstreeGpgVerifyResult * ostree_repo_verify_commit_ext (OstreeRepo *self, const gchar *commit_checksum, diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index 8f1bd4e7..cd312365 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -60,6 +60,9 @@ #include #include #include -#include #include #include + +#ifndef OSTREE_DISABLE_GPGME +#include +#endif diff --git a/src/ostree/main.c b/src/ostree/main.c index c5b45012..a523ff9a 100644 --- a/src/ostree/main.c +++ b/src/ostree/main.c @@ -72,9 +72,11 @@ static OstreeCommand commands[] = { { "fsck", OSTREE_BUILTIN_FLAG_NONE, ostree_builtin_fsck, "Check the repository for consistency" }, +#ifndef OSTREE_DISABLE_GPGME { "gpg-sign", OSTREE_BUILTIN_FLAG_NONE, ostree_builtin_gpg_sign, "Sign a commit" }, +#endif /* OSTREE_DISABLE_GPGME */ { "init", OSTREE_BUILTIN_FLAG_NO_CHECK, ostree_builtin_init, "Initialize a new empty repository" }, diff --git a/src/ostree/ot-admin-builtin-status.c b/src/ostree/ot-admin-builtin-status.c index e625a927..c6c52382 100644 --- a/src/ostree/ot-admin-builtin-status.c +++ b/src/ostree/ot-admin-builtin-status.c @@ -35,6 +35,7 @@ static GOptionEntry options[] = { { NULL } }; +#ifndef OSTREE_DISABLE_GPGME static gboolean deployment_get_gpg_verify (OstreeDeployment *deployment, OstreeRepo *repo) @@ -61,6 +62,7 @@ deployment_get_gpg_verify (OstreeDeployment *deployment, return gpg_verify; } +#endif /* OSTREE_DISABLE_GPGME */ static gboolean @@ -136,6 +138,7 @@ deployment_print_status (OstreeSysroot *sysroot, g_print (" `- %s\n", source_title); } +#ifndef OSTREE_DISABLE_GPGME if (deployment_get_gpg_verify (deployment, repo)) { g_autoptr(GString) output_buffer = g_string_sized_new (256); @@ -168,6 +171,7 @@ deployment_print_status (OstreeSysroot *sysroot, g_print ("%s", output_buffer->str); } +#endif /* OSTREE_DISABLE_GPGME */ return TRUE; } diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c index 854983db..43eb18b3 100644 --- a/src/ostree/ot-builtin-commit.c +++ b/src/ostree/ot-builtin-commit.c @@ -60,8 +60,10 @@ static char **opt_trees; static gint opt_owner_uid = -1; static gint opt_owner_gid = -1; static gboolean opt_table_output; +#ifndef OSTREE_DISABLE_GPGME static char **opt_key_ids; static char *opt_gpg_homedir; +#endif static gboolean opt_generate_sizes; static gboolean opt_disable_fsync; static char *opt_timestamp; @@ -114,8 +116,10 @@ static GOptionEntry options[] = { { "skip-list", 0, 0, G_OPTION_ARG_FILENAME, &opt_skiplist_file, "File containing list of files to skip", "PATH" }, { "consume", 0, 0, G_OPTION_ARG_NONE, &opt_consume, "Consume (delete) content after commit (for local directories)", NULL }, { "table-output", 0, 0, G_OPTION_ARG_NONE, &opt_table_output, "Output more information in a KEY: VALUE format", NULL }, +#ifndef OSTREE_DISABLE_GPGME { "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"}, { "gpg-homedir", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"}, +#endif { "generate-sizes", 0, 0, G_OPTION_ARG_NONE, &opt_generate_sizes, "Generate size information along with commit metadata", NULL }, { "disable-fsync", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_disable_fsync, "Do not invoke fsync()", NULL }, { "fsync", 0, 0, G_OPTION_ARG_CALLBACK, parse_fsync_cb, "Specify how to invoke fsync()", "POLICY" }, @@ -813,6 +817,7 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio goto out; } +#ifndef OSTREE_DISABLE_GPGME if (opt_key_ids) { char **iter; @@ -830,6 +835,7 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio goto out; } } +#endif if (opt_branch) ostree_repo_transaction_set_ref (repo, NULL, opt_branch, commit_checksum); diff --git a/src/ostree/ot-builtin-pull.c b/src/ostree/ot-builtin-pull.c index c68cbc46..1fae0a38 100644 --- a/src/ostree/ot-builtin-pull.c +++ b/src/ostree/ot-builtin-pull.c @@ -77,6 +77,7 @@ static GOptionEntry options[] = { { NULL } }; +#ifndef OSTREE_DISABLE_GPGME static void gpg_verify_result_cb (OstreeRepo *repo, const char *checksum, @@ -93,6 +94,7 @@ gpg_verify_result_cb (OstreeRepo *repo, glnx_console_lock (console); } +#endif /* OSTREE_DISABLE_GPGME */ static gboolean printed_console_progress; @@ -360,9 +362,11 @@ ostree_builtin_pull (int argc, char **argv, OstreeCommandInvocation *invocation, if (console.is_tty) { +#ifndef OSTREE_DISABLE_GPGME signal_handler_id = g_signal_connect (repo, "gpg-verify-result", G_CALLBACK (gpg_verify_result_cb), &console); +#endif /* OSTREE_DISABLE_GPGME */ } options = g_variant_ref_sink (g_variant_builder_end (&builder)); diff --git a/src/ostree/ot-builtin-remote.c b/src/ostree/ot-builtin-remote.c index 0712d5bf..6b3f6a26 100644 --- a/src/ostree/ot-builtin-remote.c +++ b/src/ostree/ot-builtin-remote.c @@ -40,9 +40,11 @@ static OstreeCommand remote_subcommands[] = { { "list", OSTREE_BUILTIN_FLAG_NONE, ot_remote_builtin_list, "List remote repository names" }, +#ifndef OSTREE_DISABLE_GPGME { "gpg-import", OSTREE_BUILTIN_FLAG_NONE, ot_remote_builtin_gpg_import, "Import GPG keys" }, +#endif /* OSTREE_DISABLE_GPGME */ #ifdef HAVE_LIBCURL_OR_LIBSOUP { "add-cookie", OSTREE_BUILTIN_FLAG_NONE, ot_remote_builtin_add_cookie, diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index aca2cddd..5091a93c 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -164,6 +164,7 @@ print_object (OstreeRepo *repo, flags |= OSTREE_DUMP_UNSWAPPED; ot_dump_object (objtype, checksum, variant, flags); +#ifndef OSTREE_DISABLE_GPGME if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { g_autoptr(OstreeGpgVerifyResult) result = NULL; @@ -207,6 +208,7 @@ print_object (OstreeRepo *repo, g_print ("%s", buffer->str); } } +#endif /* OSTREE_DISABLE_GPGME */ return TRUE; } diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c index c95c6df0..0f70f071 100644 --- a/src/ostree/ot-builtin-summary.c +++ b/src/ostree/ot-builtin-summary.c @@ -193,6 +193,7 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati if (!ostree_repo_regenerate_summary (repo, additional_metadata, cancellable, error)) return FALSE; +#ifndef OSTREE_DISABLE_GPGME if (opt_key_ids) { if (!ostree_repo_add_gpg_signature_summary (repo, @@ -202,6 +203,7 @@ ostree_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invocati error)) return FALSE; } +#endif } else if (opt_view || opt_raw) { diff --git a/src/ostree/ot-builtins.h b/src/ostree/ot-builtins.h index 7a7d41bc..12a99b45 100644 --- a/src/ostree/ot-builtins.h +++ b/src/ostree/ot-builtins.h @@ -41,7 +41,9 @@ BUILTINPROTO(diff); BUILTINPROTO(export); BUILTINPROTO(find_remotes); BUILTINPROTO(create_usb); +#ifndef OSTREE_DISABLE_GPGME BUILTINPROTO(gpg_sign); +#endif BUILTINPROTO(init); BUILTINPROTO(log); BUILTINPROTO(pull); diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index a1449aef..c9c4f299 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -491,6 +491,7 @@ ostree_ensure_repo_writable (OstreeRepo *repo, return TRUE; } +#ifndef OSTREE_DISABLE_GPGME void ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result) { @@ -511,6 +512,7 @@ ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result) g_print ("%s", buffer->str); } +#endif /* OSTREE_DISABLE_GPGME */ gboolean ot_enable_tombstone_commits (OstreeRepo *repo, GError **error) diff --git a/src/ostree/ot-remote-builtin-add.c b/src/ostree/ot-remote-builtin-add.c index 2d021d77..cea0b274 100644 --- a/src/ostree/ot-remote-builtin-add.c +++ b/src/ostree/ot-remote-builtin-add.c @@ -133,10 +133,12 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio subkey, g_variant_new_variant (g_variant_new_string (subvalue))); } +#ifndef OSTREE_DISABLE_GPGME if (opt_no_gpg_verify) g_variant_builder_add (optbuilder, "{s@v}", "gpg-verify", g_variant_new_variant (g_variant_new_boolean (FALSE))); +#endif /* OSTREE_DISABLE_GPGME */ if (opt_collection_id != NULL) g_variant_builder_add (optbuilder, "{s@v}", "collection-id", @@ -157,6 +159,7 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio cancellable, error)) goto out; +#ifndef OSTREE_DISABLE_GPGME /* This is just a convenience option and is not as flexible as the full * "ostree remote gpg-import" command. It imports all keys from a file, * which is likely the most common case. @@ -183,6 +186,7 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio g_print ("Imported %u GPG key%s to remote \"%s\"\n", imported, (imported == 1) ? "" : "s", remote_name); } +#endif /* OSTREE_DISABLE_GPGME */ ret = TRUE; out: diff --git a/src/ostree/ot-remote-builtin-summary.c b/src/ostree/ot-remote-builtin-summary.c index bf50b9bc..bd4d026d 100644 --- a/src/ostree/ot-remote-builtin-summary.c +++ b/src/ostree/ot-remote-builtin-summary.c @@ -51,7 +51,9 @@ ot_remote_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invoc g_autoptr(GBytes) summary_bytes = NULL; g_autoptr(GBytes) signature_bytes = NULL; OstreeDumpFlags flags = OSTREE_DUMP_NONE; +#ifndef OSTREE_DISABLE_GPGME gboolean gpg_verify_summary; +#endif gboolean ret = FALSE; context = g_option_context_new ("NAME"); @@ -92,6 +94,7 @@ ot_remote_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invoc ot_dump_summary_bytes (summary_bytes, flags); +#ifndef OSTREE_DISABLE_GPGME if (!ostree_repo_remote_get_gpg_verify_summary (repo, remote_name, &gpg_verify_summary, error)) @@ -124,6 +127,7 @@ ot_remote_builtin_summary (int argc, char **argv, OstreeCommandInvocation *invoc g_print ("\n"); ostree_print_gpg_verify_result (result); } +#endif /* OSTREE_DISABLE_GPGME */ ret = TRUE; out: From 56020b71606a8588b4314e7b6686718cd6661c2e Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Thu, 18 Jul 2019 19:08:21 +0300 Subject: [PATCH 53/62] lib: rename common sign/verification functions and variables Some gpg-named functions/variables should be used for any signature system, so remove "gpg_" prefix from them to avoid confusion. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- src/libostree/ostree-repo-pull.c | 71 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 7889eeb2..3adaa477 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -114,7 +114,7 @@ typedef struct { GVariant *summary; GHashTable *summary_deltas_checksums; GHashTable *ref_original_commits; /* Maps checksum to commit, used by timestamp checks */ - GHashTable *gpg_verified_commits; /* Set of commits that have been verified */ + GHashTable *verified_commits; /* Set of commits that have been verified */ GHashTable *ref_keyring_map; /* Maps OstreeCollectionRef to keyring remote name */ GPtrArray *static_delta_superblocks; GHashTable *expected_commit_sizes; /* Maps commit checksum to known size */ @@ -261,14 +261,13 @@ static gboolean scan_one_metadata_object (OtPullData *pull_data, GError **error); static void scan_object_queue_data_free (ScanObjectQueueData *scan_data); static gboolean -gpg_verify_unwritten_commit (OtPullData *pull_data, - const char *checksum, - GVariant *commit, - GVariant *detached_metadata, - const OstreeCollectionRef *ref, - GCancellable *cancellable, - GError **error); - +ostree_verify_unwritten_commit (OtPullData *pull_data, + const char *checksum, + GVariant *commit, + GVariant *detached_metadata, + const OstreeCollectionRef *ref, + GCancellable *cancellable, + GError **error); static gboolean update_progress (gpointer user_data) @@ -1300,16 +1299,16 @@ meta_fetch_on_complete (GObject *object, */ if (objtype == OSTREE_OBJECT_TYPE_COMMIT) { - /* Do GPG verification. `detached_data` may be NULL if no detached + /* Do signature verification. `detached_data` may be NULL if no detached * metadata was found during pull; that's handled by - * gpg_verify_unwritten_commit(). If we ever change the pull code to + * ostree_ostree_verify_unwritten_commit(). If we ever change the pull code to * not always fetch detached metadata, this bit will have to learn how * to look up from the disk state as well, or insert the on-disk * metadata into this hash. */ GVariant *detached_data = g_hash_table_lookup (pull_data->fetched_detached_metadata, checksum); - if (!gpg_verify_unwritten_commit (pull_data, checksum, metadata, detached_data, - fetch_data->requested_ref, pull_data->cancellable, error)) + if (!ostree_verify_unwritten_commit (pull_data, checksum, metadata, detached_data, + fetch_data->requested_ref, pull_data->cancellable, error)) goto out; if (!ostree_repo_mark_commit_partial (pull_data->repo, checksum, TRUE, error)) @@ -1459,20 +1458,20 @@ process_verify_result (OtPullData *pull_data, * the case of "written but not verified". But we also don't want to check * twice, as that'd result in duplicate signals. */ - g_hash_table_add (pull_data->gpg_verified_commits, g_strdup (checksum)); + g_hash_table_add (pull_data->verified_commits, g_strdup (checksum)); return TRUE; } #endif /* OSTREE_DISABLE_GPGME */ static gboolean -gpg_verify_unwritten_commit (OtPullData *pull_data, - const char *checksum, - GVariant *commit, - GVariant *detached_metadata, - const OstreeCollectionRef *ref, - GCancellable *cancellable, - GError **error) +ostree_verify_unwritten_commit (OtPullData *pull_data, + const char *checksum, + GVariant *commit, + GVariant *detached_metadata, + const OstreeCollectionRef *ref, + GCancellable *cancellable, + GError **error) { #ifndef OSTREE_DISABLE_GPGME if (pull_data->gpg_verify) @@ -1480,7 +1479,7 @@ gpg_verify_unwritten_commit (OtPullData *pull_data, const char *keyring_remote = NULL; /* Shouldn't happen, but see comment in process_verify_result() */ - if (g_hash_table_contains (pull_data->gpg_verified_commits, checksum)) + if (g_hash_table_contains (pull_data->verified_commits, checksum)) return TRUE; if (ref != NULL) @@ -1808,7 +1807,7 @@ scan_commit_object (OtPullData *pull_data, * but also ensure we've done it here if not already. */ if (pull_data->gpg_verify && - !g_hash_table_contains (pull_data->gpg_verified_commits, checksum)) + !g_hash_table_contains (pull_data->verified_commits, checksum)) { g_autoptr(OstreeGpgVerifyResult) result = NULL; const char *keyring_remote = NULL; @@ -2414,8 +2413,8 @@ process_one_static_delta (OtPullData *pull_data, g_autofree char *detached_path = _ostree_get_relative_static_delta_path (from_revision, to_revision, "commitmeta"); g_autoptr(GVariant) detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}")); - if (!gpg_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data, - ref, cancellable, error)) + if (!ostree_verify_unwritten_commit (pull_data, to_revision, to_commit, detached_data, + ref, cancellable, error)) return FALSE; if (detached_data && !ostree_repo_write_commit_detached_metadata (pull_data->repo, @@ -3697,8 +3696,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, pull_data->ref_original_commits = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal, (GDestroyNotify)NULL, (GDestroyNotify)g_free); - pull_data->gpg_verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify)g_free, NULL); + pull_data->verified_commits = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify)g_free, NULL); pull_data->ref_keyring_map = g_hash_table_new_full (ostree_collection_ref_hash, ostree_collection_ref_equal, (GDestroyNotify)ostree_collection_ref_free, (GDestroyNotify)g_free); pull_data->scanned_metadata = g_hash_table_new_full (ostree_hash_object_name, g_variant_equal, @@ -4645,21 +4644,21 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_string_append_printf (msg, "libostree pull from '%s' for %u refs complete", pull_data->remote_name, g_hash_table_size (requested_refs_to_fetch)); - const char *gpg_verify_state; + const char *verify_state; #ifndef OSTREE_DISABLE_GPGME if (pull_data->gpg_verify_summary) { if (pull_data->gpg_verify) - gpg_verify_state = "summary+commit"; + verify_state = "summary+commit"; else - gpg_verify_state = "summary-only"; + verify_state = "summary-only"; } else - gpg_verify_state = (pull_data->gpg_verify ? "commit" : "disabled"); - g_string_append_printf (msg, "\nsecurity: GPG: %s ", gpg_verify_state); + verify_state = (pull_data->gpg_verify ? "commit" : "disabled"); + g_string_append_printf (msg, "\nsecurity: GPG: %s ", verify_state); #else - gpg_verify_state = "disabled"; - g_string_append_printf (msg, "\nsecurity: %s ", gpg_verify_state); + verify_state = "disabled"; + g_string_append_printf (msg, "\nsecurity: %s ", verify_state); #endif /* OSTREE_DISABLE_GPGME */ OstreeFetcherURI *first_uri = pull_data->meta_mirrorlist->pdata[0]; @@ -4696,7 +4695,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, ot_journal_send ("MESSAGE=%s", msg->str, "MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_MESSAGE_FETCH_COMPLETE_ID), "OSTREE_REMOTE=%s", pull_data->remote_name, - "OSTREE_GPG=%s", gpg_verify_state, + "OSTREE_GPG=%s", verify_state, "OSTREE_SECONDS=%u", n_seconds, "OSTREE_XFER_SIZE=%s", formatted_xferred, NULL); @@ -4756,7 +4755,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, g_clear_pointer (&pull_data->fetched_detached_metadata, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->summary_deltas_checksums, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->ref_original_commits, (GDestroyNotify) g_hash_table_unref); - g_clear_pointer (&pull_data->gpg_verified_commits, (GDestroyNotify) g_hash_table_unref); + g_clear_pointer (&pull_data->verified_commits, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->ref_keyring_map, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref); g_clear_pointer (&pull_data->requested_fallback_content, (GDestroyNotify) g_hash_table_unref); From 8322e77a88d65f894698651caa7757cfd5c6edfa Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Sun, 21 Jul 2019 23:40:32 +0300 Subject: [PATCH 54/62] gpg: add dummy public interface Add dummy stubs for GPG public functions to be compiled instead of original code in case if support of GPG is disabled. Need that to keep API backward compatibility. Based on original code from file `ostree-gpg-verify-result.c`. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- Makefile-libostree.am | 4 + .../ostree-gpg-verify-result-dummy.c | 303 ++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 src/libostree/ostree-gpg-verify-result-dummy.c diff --git a/Makefile-libostree.am b/Makefile-libostree.am index 61763f95..46984a75 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -172,6 +172,10 @@ libostree_1_la_SOURCES += \ src/libostree/ostree-gpg-verify-result.c \ src/libostree/ostree-gpg-verify-result-private.h \ $(NULL) +else +libostree_1_la_SOURCES += \ + src/libostree/ostree-gpg-verify-result-dummy.c \ + $(NULL) endif # USE_GPGME symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym diff --git a/src/libostree/ostree-gpg-verify-result-dummy.c b/src/libostree/ostree-gpg-verify-result-dummy.c new file mode 100644 index 00000000..a62ff915 --- /dev/null +++ b/src/libostree/ostree-gpg-verify-result-dummy.c @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2015 Red Hat, Inc. + * Copyright (C) 2019 Collabora Ltd. + * + * 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. + */ + +#include "config.h" + +#include "libglnx.h" + +#include "ostree-gpg-verify-result.h" + +/** + * SECTION: ostree-gpg-verify-result + * @title: GPG signature verification results + * @short_description: Dummy functions for detached GPG signatures + * + * This file contain dummy functions for GPG signatures checks to + * provide API backward compatibility. + */ + +#ifndef OSTREE_DISABLE_GPGME +#error This file should not be compiled if GPG support is enabled +#endif + +/** + * OstreeGpgVerifyResult: + * + * Private instance structure. + */ +struct OstreeGpgVerifyResult { + GObject parent; +}; + + +typedef struct { + GObjectClass parent_class; +} OstreeGpgVerifyResultClass; + +static void ostree_gpg_verify_result_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (OstreeGpgVerifyResult, + ostree_gpg_verify_result, + G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + ostree_gpg_verify_result_initable_iface_init)) + +static void +ostree_gpg_verify_result_class_init (OstreeGpgVerifyResultClass *class) +{ +} + +static void +ostree_gpg_verify_result_initable_iface_init (GInitableIface *iface) +{ +} + +static void +ostree_gpg_verify_result_init (OstreeGpgVerifyResult *result) +{ +} + +/** + * ostree_gpg_verify_result_count_all: + * @result: an #OstreeGpgVerifyResult + * + * Counts all the signatures in @result. + * + * Returns: signature count + */ +guint +ostree_gpg_verify_result_count_all (OstreeGpgVerifyResult *result) +{ + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + return 0; +} + +/** + * ostree_gpg_verify_result_count_valid: + * @result: an #OstreeGpgVerifyResult + * + * Counts only the valid signatures in @result. + * + * Returns: valid signature count + */ +guint +ostree_gpg_verify_result_count_valid (OstreeGpgVerifyResult *result) +{ + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + return 0; +} + +/** + * ostree_gpg_verify_result_lookup: + * @result: an #OstreeGpgVerifyResult + * @key_id: a GPG key ID or fingerprint + * @out_signature_index: (out): return location for the index of the signature + * signed by @key_id, or %NULL + * + * Searches @result for a signature signed by @key_id. If a match is found, + * the function returns %TRUE and sets @out_signature_index so that further + * signature details can be obtained through ostree_gpg_verify_result_get(). + * If no match is found, the function returns %FALSE and leaves + * @out_signature_index unchanged. + * + * Returns: %TRUE on success, %FALSE on failure + **/ +gboolean +ostree_gpg_verify_result_lookup (OstreeGpgVerifyResult *result, + const gchar *key_id, + guint *out_signature_index) +{ + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + return FALSE; +} + +/** + * ostree_gpg_verify_result_get: + * @result: an #OstreeGpgVerifyResult + * @signature_index: which signature to get attributes from + * @attrs: (array length=n_attrs): Array of requested attributes + * @n_attrs: Length of the @attrs array + * + * Builds a #GVariant tuple of requested attributes for the GPG signature at + * @signature_index in @result. See the #OstreeGpgSignatureAttr description + * for the #GVariantType of each available attribute. + * + * It is a programmer error to request an invalid #OstreeGpgSignatureAttr or + * an invalid @signature_index. Use ostree_gpg_verify_result_count_all() to + * find the number of signatures in @result. + * + * Returns: a new, floating, #GVariant tuple + **/ +GVariant * +ostree_gpg_verify_result_get (OstreeGpgVerifyResult *result, + guint signature_index, + OstreeGpgSignatureAttr *attrs, + guint n_attrs) +{ + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + return NULL; +} + +/** + * ostree_gpg_verify_result_get_all: + * @result: an #OstreeGpgVerifyResult + * @signature_index: which signature to get attributes from + * + * Builds a #GVariant tuple of all available attributes for the GPG signature + * at @signature_index in @result. + * + * The child values in the returned #GVariant tuple are ordered to match the + * #OstreeGpgSignatureAttr enumeration, which means the enum values can be + * used as index values in functions like g_variant_get_child(). See the + * #OstreeGpgSignatureAttr description for the #GVariantType of each + * available attribute. + * + * + * + * The #OstreeGpgSignatureAttr enumeration may be extended in the future + * with new attributes, which would affect the #GVariant tuple returned by + * this function. While the position and type of current child values in + * the #GVariant tuple will not change, to avoid backward-compatibility + * issues please do not depend on the tuple's overall size or + * type signature. + * + * + * + * It is a programmer error to request an invalid @signature_index. Use + * ostree_gpg_verify_result_count_all() to find the number of signatures in + * @result. + * + * Returns: a new, floating, #GVariant tuple + **/ +GVariant * +ostree_gpg_verify_result_get_all (OstreeGpgVerifyResult *result, + guint signature_index) +{ + g_return_val_if_fail (OSTREE_IS_GPG_VERIFY_RESULT (result), NULL); + + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + return NULL; +} + +/** + * ostree_gpg_verify_result_describe: + * @result: an #OstreeGpgVerifyResult + * @signature_index: which signature to describe + * @output_buffer: a #GString to hold the description + * @line_prefix: (allow-none): optional line prefix string + * @flags: flags to adjust the description format + * + * Appends a brief, human-readable description of the GPG signature at + * @signature_index in @result to the @output_buffer. The description + * spans multiple lines. A @line_prefix string, if given, will precede + * each line of the description. + * + * The @flags argument is reserved for future variations to the description + * format. Currently must be 0. + * + * It is a programmer error to request an invalid @signature_index. Use + * ostree_gpg_verify_result_count_all() to find the number of signatures in + * @result. + */ +void +ostree_gpg_verify_result_describe (OstreeGpgVerifyResult *result, + guint signature_index, + GString *output_buffer, + const gchar *line_prefix, + OstreeGpgSignatureFormatFlags flags) +{ + g_autoptr(GVariant) variant = NULL; + + g_return_if_fail (OSTREE_IS_GPG_VERIFY_RESULT (result)); + + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); + + variant = ostree_gpg_verify_result_get_all (result, signature_index); + + ostree_gpg_verify_result_describe_variant (variant, output_buffer, line_prefix, flags); +} + +/** + * ostree_gpg_verify_result_describe_variant: + * @variant: a #GVariant from ostree_gpg_verify_result_get_all() + * @output_buffer: a #GString to hold the description + * @line_prefix: (allow-none): optional line prefix string + * @flags: flags to adjust the description format + * + * Similar to ostree_gpg_verify_result_describe() but takes a #GVariant of + * all attributes for a GPG signature instead of an #OstreeGpgVerifyResult + * and signature index. + * + * The @variant MUST have been created by + * ostree_gpg_verify_result_get_all(). + */ +void +ostree_gpg_verify_result_describe_variant (GVariant *variant, + GString *output_buffer, + const gchar *line_prefix, + OstreeGpgSignatureFormatFlags flags) +{ + const char *type_string; + + g_return_if_fail (variant != NULL); + g_return_if_fail (output_buffer != NULL); + + /* Verify the variant's type string. This code is + * not prepared to handle just any random GVariant. */ + type_string = g_variant_get_type_string (variant); + g_return_if_fail (strcmp (type_string, "(bbbbbsxxsssssxx)") == 0); + + g_string_append (output_buffer, + "GPG feature is disabled in a build time\n"); + + g_critical ("%s: GPG feature is disabled in a build time", __FUNCTION__); +} + +/** + * ostree_gpg_verify_result_require_valid_signature: + * @result: (nullable): an #OstreeGpgVerifyResult + * @error: A #GError + * + * Checks if the result contains at least one signature from the + * trusted keyring. You can call this function immediately after + * ostree_repo_verify_summary() or ostree_repo_verify_commit_ext() - + * it will handle the %NULL @result and filled @error too. + * + * Returns: %TRUE if @result was not %NULL and had at least one + * signature from trusted keyring, otherwise %FALSE + * + * Since: 2016.6 + */ +gboolean +ostree_gpg_verify_result_require_valid_signature (OstreeGpgVerifyResult *result, + GError **error) +{ + if (result == NULL) + return FALSE; + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "'%s': GPG feature is disabled in a build time", + __FUNCTION__); + return FALSE; +} + +G_DEFINE_QUARK (OstreeGpgError, ostree_gpg_error) From 453ce83379364172206945fad78a3cbc2ae51df5 Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 30 Jul 2019 02:16:57 +0300 Subject: [PATCH 55/62] tests/gpg: fix the check of GPG support Shell function `has_gpgme` shouldn't exit if GPG support is not detected since it stop any test with error. Added function `skip_without_gpgme` to skip the whole test if it is useless without GPG support Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- tests/libtest.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/libtest.sh b/tests/libtest.sh index 632ccee8..8832e63c 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -605,10 +605,18 @@ skip_without_experimental () { } has_gpgme () { + local ret ${CMD_PREFIX} ostree --version > version.txt - assert_file_has_content version.txt '- gpgme' + grep -q -e '- gpgme' version.txt + ret=$? rm -f version.txt - true + return ${ret} +} + +skip_without_gpgme() { + if ! has_gpgme; then + skip "no gpg support compiled in" + fi } # Find an appropriate gpg program to use. We want one that has the From 3767d87107b74d121738c733ca37767494b6be9c Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 30 Jul 2019 02:39:12 +0300 Subject: [PATCH 56/62] tests/gpg: fix GPG-dependent shell tests if no GPG support Skip tests or run them without GPG-related functionality if GPGME wasn't enabled in a build time. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- tests/pull-test.sh | 67 ++++++++++++++++++------------- tests/test-create-usb.sh | 2 + tests/test-find-remotes.sh | 2 + tests/test-local-pull.sh | 31 +++++++++----- tests/test-parent.sh | 2 + tests/test-pull-collections.sh | 18 +++++++-- tests/test-pull-mirror-summary.sh | 10 ++++- tests/test-pull-repeated.sh | 7 +++- tests/test-pull-summary-sigs.sh | 10 ++++- tests/test-summary-update.sh | 10 ++++- tests/test-summary-view.sh | 6 ++- 11 files changed, 113 insertions(+), 52 deletions(-) diff --git a/tests/pull-test.sh b/tests/pull-test.sh index a8bc49a9..0a97a119 100644 --- a/tests/pull-test.sh +++ b/tests/pull-test.sh @@ -54,7 +54,12 @@ function verify_initial_contents() { assert_file_has_content baz/cow '^moo$' } -echo "1..34" +if has_gpgme; then + echo "1..34" +else + # 3 tests needs GPG support + echo "1..31" +fi # Try both syntaxes repo_init --no-gpg-verify @@ -543,13 +548,15 @@ fi assert_file_has_content err.txt "404" echo "ok pull repo 404" -cd ${test_tmpdir} -repo_init --set=gpg-verify=true -if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main 2>err.txt; then - assert_not_reached "pull repo 404 succeeded?" +if has_gpgme; then + cd ${test_tmpdir} + repo_init --set=gpg-verify=true + if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main 2>err.txt; then + assert_not_reached "pull repo 404 succeeded?" + fi + assert_file_has_content err.txt "GPG verification enabled, but no signatures found" + echo "ok pull repo 404 (gpg)" fi -assert_file_has_content err.txt "GPG verification enabled, but no signatures found" -echo "ok pull repo 404 (gpg)" cd ${test_tmpdir} find ostree-srv/gnomerepo/objects -name '*.dirtree' | while read f; do mv ${f}{,.orig}; done @@ -561,29 +568,31 @@ assert_file_has_content err.txt "404" find ostree-srv/gnomerepo/objects -name '*.dirtree.orig' | while read f; do mv ${f} $(dirname $f)/$(basename ${f} .orig); done echo "ok pull repo 404 on dirtree object" -cd ${test_tmpdir} -repo_init --set=gpg-verify=true -${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit ${COMMIT_ARGS} \ - --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1} -b main \ - -s "A signed commit" --tree=ref=main -${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u -# make sure gpg verification is correctly on -csum=$(${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo rev-parse main) -objpath=objects/${csum::2}/${csum:2}.commitmeta -remotesig=ostree-srv/gnomerepo/$objpath -localsig=repo/$objpath -mv $remotesig $remotesig.bak -if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main; then - assert_not_reached "pull with gpg-verify unexpectedly succeeded?" +if has_gpgme; then + cd ${test_tmpdir} + repo_init --set=gpg-verify=true + ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo commit ${COMMIT_ARGS} \ + --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1} -b main \ + -s "A signed commit" --tree=ref=main + ${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo summary -u + # make sure gpg verification is correctly on + csum=$(${CMD_PREFIX} ostree --repo=ostree-srv/gnomerepo rev-parse main) + objpath=objects/${csum::2}/${csum:2}.commitmeta + remotesig=ostree-srv/gnomerepo/$objpath + localsig=repo/$objpath + mv $remotesig $remotesig.bak + if ${CMD_PREFIX} ostree --repo=repo --depth=0 pull origin main; then + assert_not_reached "pull with gpg-verify unexpectedly succeeded?" + fi + # ok now check that we can pull correctly + mv $remotesig.bak $remotesig + ${CMD_PREFIX} ostree --repo=repo pull origin main + echo "ok pull signed commit" + rm $localsig + ${CMD_PREFIX} ostree --repo=repo pull origin main + test -f $localsig + echo "ok re-pull signature for stored commit" fi -# ok now check that we can pull correctly -mv $remotesig.bak $remotesig -${CMD_PREFIX} ostree --repo=repo pull origin main -echo "ok pull signed commit" -rm $localsig -${CMD_PREFIX} ostree --repo=repo pull origin main -test -f $localsig -echo "ok re-pull signature for stored commit" cd ${test_tmpdir} repo_init --no-gpg-verify diff --git a/tests/test-create-usb.sh b/tests/test-create-usb.sh index 8040ed9c..8187ea75 100755 --- a/tests/test-create-usb.sh +++ b/tests/test-create-usb.sh @@ -26,6 +26,8 @@ set -euo pipefail . $(dirname $0)/libtest.sh +skip_without_gpgme + echo "1..5" cd ${test_tmpdir} diff --git a/tests/test-find-remotes.sh b/tests/test-find-remotes.sh index 226053ce..5dd880f0 100755 --- a/tests/test-find-remotes.sh +++ b/tests/test-find-remotes.sh @@ -23,6 +23,8 @@ set -euo pipefail . $(dirname $0)/libtest.sh +skip_without_gpgme + echo '1..1' # Create two upstream collection repositories with some example commits diff --git a/tests/test-local-pull.sh b/tests/test-local-pull.sh index 8168486c..97bb9954 100755 --- a/tests/test-local-pull.sh +++ b/tests/test-local-pull.sh @@ -28,7 +28,12 @@ unset OSTREE_GPG_HOME skip_without_user_xattrs -echo "1..8" +if has_gpgme; then + echo "1..8" +else + # Only some tests doesn't need GPG support + echo "1..5" +fi setup_test_repository "archive" echo "ok setup" @@ -63,6 +68,20 @@ cmp checkout1.files checkout2.files cmp checkout1.files checkout3.files echo "ok checkouts same" +mkdir repo7 +ostree_repo_init repo7 --mode="archive" +${CMD_PREFIX} ostree --repo=repo7 pull-local repo +${CMD_PREFIX} ostree --repo=repo7 fsck +for src_object in `find repo/objects -name '*.filez'`; do + dst_object=${src_object/repo/repo7} + assert_files_hardlinked "$src_object" "$dst_object" +done +echo "ok pull-local z2 to z2 default hardlink" + +if ! has_gpgme; then + exit 0 +fi + mkdir repo4 ostree_repo_init repo4 --mode="archive" ${CMD_PREFIX} ostree --repo=repo4 remote add --gpg-import ${test_tmpdir}/gpghome/key1.asc origin repo @@ -97,13 +116,3 @@ ${OSTREE} summary --update --gpg-sign=${TEST_GPG_KEYID_1} --gpg-homedir=${TEST_G ${CMD_PREFIX} ostree --repo=repo6 pull-local --remote=origin --gpg-verify-summary repo test2 2>&1 echo "ok --gpg-verify-summary" - -mkdir repo7 -ostree_repo_init repo7 --mode="archive" -${CMD_PREFIX} ostree --repo=repo7 pull-local repo -${CMD_PREFIX} ostree --repo=repo7 fsck -for src_object in `find repo/objects -name '*.filez'`; do - dst_object=${src_object/repo/repo7} - assert_files_hardlinked "$src_object" "$dst_object" -done -echo "ok pull-local z2 to z2 default hardlink" diff --git a/tests/test-parent.sh b/tests/test-parent.sh index a9a3494c..b62b9557 100755 --- a/tests/test-parent.sh +++ b/tests/test-parent.sh @@ -25,6 +25,8 @@ set -euo pipefail skip_without_user_xattrs +skip_without_gpgme + echo '1..2' setup_test_repository "archive" diff --git a/tests/test-pull-collections.sh b/tests/test-pull-collections.sh index fd782af9..d1de5f88 100755 --- a/tests/test-pull-collections.sh +++ b/tests/test-pull-collections.sh @@ -34,7 +34,11 @@ do_commit() { mkdir -p files pushd files - ${CMD_PREFIX} ostree --repo="../${repo}" commit -s "Test ${repo} commit for branch ${branch}" -b "${branch}" --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" "$@" > "../${branch}-checksum" + local GPG_ARGS="" + if has_gpgme; then + GPG_ARGS="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" + fi + ${CMD_PREFIX} ostree --repo="../${repo}" commit -s "Test ${repo} commit for branch ${branch}" -b "${branch}" ${GPG_ARGS} "$@" > "../${branch}-checksum" popd } @@ -42,7 +46,11 @@ do_summary() { local repo=$1 shift 1 - ${CMD_PREFIX} ostree "--repo=${repo}" summary --update --gpg-homedir="${TEST_GPG_KEYHOME}" --gpg-sign="${TEST_GPG_KEYID_1}" + local GPG_ARGS="" + if has_gpgme; then + GPG_ARGS="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" + fi + ${CMD_PREFIX} ostree "--repo=${repo}" summary --update ${GPG_ARGS} } do_collection_ref_show() { @@ -96,7 +104,11 @@ do_remote_add() { local remote_repo=$2 shift 2 - ${CMD_PREFIX} ostree "--repo=${repo}" remote add "${remote_repo}-remote" "file://$(pwd)/${remote_repo}" "$@" --gpg-import="${test_tmpdir}/gpghome/key1.asc" + local GPG_ARGS="" + if has_gpgme; then + GPG_ARGS="--gpg-import=${test_tmpdir}/gpghome/key1.asc" + fi + ${CMD_PREFIX} ostree "--repo=${repo}" remote add "${remote_repo}-remote" "file://$(pwd)/${remote_repo}" "$@" ${GPG_ARGS} } do_pull() { diff --git a/tests/test-pull-mirror-summary.sh b/tests/test-pull-mirror-summary.sh index 504cf545..a2a98bad 100755 --- a/tests/test-pull-mirror-summary.sh +++ b/tests/test-pull-mirror-summary.sh @@ -23,9 +23,15 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo "1..5" +COMMIT_SIGN="" +if has_gpgme; then + COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" + echo "1..5" +else + # Only one test don't need GPG support + echo "1..1" +fi -COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" setup_fake_remote_repo1 "archive" "${COMMIT_SIGN}" # Now, setup multiple branches diff --git a/tests/test-pull-repeated.sh b/tests/test-pull-repeated.sh index a2707d6d..237a863c 100755 --- a/tests/test-pull-repeated.sh +++ b/tests/test-pull-repeated.sh @@ -23,9 +23,12 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo "1..4" +COMMIT_SIGN="" +if has_gpgme; then + COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" +fi -COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" +echo "1..4" # Test pulling from a repo which gives error 500 (internal server error) a lot of the time. setup_fake_remote_repo1 "archive" "${COMMIT_SIGN}" --random-500s=50 diff --git a/tests/test-pull-summary-sigs.sh b/tests/test-pull-summary-sigs.sh index 0b6b806c..821ae953 100755 --- a/tests/test-pull-summary-sigs.sh +++ b/tests/test-pull-summary-sigs.sh @@ -23,9 +23,15 @@ set -euo pipefail . $(dirname $0)/libtest.sh -echo "1..10" +COMMIT_SIGN="" +if has_gpgme; then + COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" + echo "1..10" +else + # Only one test don't need GPG support + echo "1..1" +fi -COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" setup_fake_remote_repo1 "archive" "${COMMIT_SIGN}" # Now, setup multiple branches diff --git a/tests/test-summary-update.sh b/tests/test-summary-update.sh index 062d5bd4..ceaa5409 100755 --- a/tests/test-summary-update.sh +++ b/tests/test-summary-update.sh @@ -28,6 +28,12 @@ set -euo pipefail echo "1..2" +COMMIT_SIGN="" +if has_gpgme; then + COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" +fi + + cd ${test_tmpdir} mkdir repo ostree_repo_init repo @@ -45,7 +51,7 @@ done ${CMD_PREFIX} ostree --repo=repo summary --update # Generate a signed summary file. -${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1} +${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN} # Try various ways of adding additional data. ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true @@ -77,7 +83,7 @@ done ${CMD_PREFIX} ostree --repo=repo summary --update # Generate a signed summary file. -${CMD_PREFIX} ostree --repo=repo summary --update --gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1} +${CMD_PREFIX} ostree --repo=repo summary --update ${COMMIT_SIGN} # Try various ways of adding additional data. ${CMD_PREFIX} ostree --repo=repo summary --update --add-metadata key="'value'" --add-metadata=key2=true diff --git a/tests/test-summary-view.sh b/tests/test-summary-view.sh index d26d3431..14de0294 100755 --- a/tests/test-summary-view.sh +++ b/tests/test-summary-view.sh @@ -28,7 +28,11 @@ set -euo pipefail echo "1..2" -COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" +COMMIT_SIGN="" +if has_gpgme; then + COMMIT_SIGN="--gpg-homedir=${TEST_GPG_KEYHOME} --gpg-sign=${TEST_GPG_KEYID_1}" +fi + setup_fake_remote_repo1 "archive" "${COMMIT_SIGN}" # Set up a second branch. From 4c8b0ac2555d0df483e512b81936d85e314bb8eb Mon Sep 17 00:00:00 2001 From: Denis Pynkin Date: Tue, 30 Jul 2019 02:42:43 +0300 Subject: [PATCH 57/62] tests/test-repo-finder-mount: skip some tests if GPG is not supported `ostree_repo_resolve_keyring_for_collection()` function fail the tests if there is no GPG support. Signed-off-by: Denis Pynkin Closes: #1889 Approved by: cgwalters --- tests/test-repo-finder-mount.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test-repo-finder-mount.c b/tests/test-repo-finder-mount.c index 55eb47fb..847f4bec 100644 --- a/tests/test-repo-finder-mount.c +++ b/tests/test-repo-finder-mount.c @@ -557,10 +557,13 @@ int main (int argc, char **argv) g_test_add_func ("/repo-finder-mount/init", test_repo_finder_mount_init); g_test_add ("/repo-finder-mount/no-mounts", Fixture, NULL, setup, test_repo_finder_mount_no_mounts, teardown); +#ifndef OSTREE_DISABLE_GPGME + /*`ostree_repo_resolve_keyring_for_collection()` fail the tests if no GPG support is compiled in. */ g_test_add ("/repo-finder-mount/mixed-mounts", Fixture, NULL, setup, test_repo_finder_mount_mixed_mounts, teardown); g_test_add ("/repo-finder-mount/well-known", Fixture, NULL, setup, test_repo_finder_mount_well_known, teardown); +#endif /* OSTREE_DISABLE_GPGME */ return g_test_run(); } From 729254503c3a4d6c40878e5c7f47375757b88b3b Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 7 Aug 2019 11:40:02 +0000 Subject: [PATCH 58/62] README.md: Rework "projects using" section Update this to mention the 3 Fedora derivatives, RHEL CoreOS etc. Create 3 sections: - OS/Distributions - build tools - rpm-ostree/flatpak Closes: #1895 Approved by: dustymabe --- README.md | 68 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index a5773ca0..a4146f04 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,36 @@ version of projects like [flatpak](https://github.com/flatpak/flatpak) which use libostree for applications, rather than hosts. -Projects using OSTree +Operating systems and distributions using OSTree --------------------- +[Endless OS](https://endlessos.com/) uses libostree for their host system as +well as flatpak. See +their [eos-updater](https://github.com/endlessm/eos-updater) +and [deb-ostree-builder](https://github.com/dbnicholson/deb-ostree-builder) +projects. + +Fedora derivatives use rpm-ostree (noted below); there are 3 variants using OSTree: + + - [Fedora CoreOS](https://getfedora.org/en/coreos/) + - [Fedora Silverblue](https://silverblue.fedoraproject.org/) + - [Fedora IoT](https://iot.fedoraproject.org/) + +Red Hat Enterprise Linux CoreOS is a derivative of Fedora CoreOS, used in [OpenShift 4](https://try.openshift.com/). +The [machine-config-operator](https://github.com/openshift/machine-config-operator/blob/master/docs/OSUpgrades.md) +manages upgrades. RHEL CoreOS is also the successor to RHEL Atomic Host, which +uses rpm-ostree as well. + +[GNOME Continuous](https://wiki.gnome.org/Projects/GnomeContinuous) is +where OSTree was born - as a high performance continuous delivery/testing +system for GNOME. + +[Liri OS](https://liri.io/download/silverblue/) has the option to install +their distribution using ostree. + +Distribution build tools +------------------------ + [meta-updater](https://github.com/advancedtelematic/meta-updater) is a layer available for [OpenEmbedded](http://www.openembedded.org/wiki/Main_Page) systems. @@ -46,37 +73,32 @@ systems. [QtOTA](http://doc.qt.io/QtOTA/) is Qt's over-the-air update framework which uses libostree. -[rpm-ostree](https://github.com/projectatomic/rpm-ostree) is a next-generation -hybrid package/image system for [Fedora](https://getfedora.org/) and [CentOS](https://www.centos.org/), -used by the [Atomic Host](http://www.projectatomic.io/) project. -By default it uses libostree to atomically replicate a base OS (all dependency -resolution is done on the server), but it supports "package layering", where +The [BuildStream](https://gitlab.com/BuildStream/buildstream) build and +integration tool uses libostree as a caching system to store and share +built artifacts. + +Fedora [coreos-assembler](https://github.com/coreos/coreos-assembler) is +the build tool used to generate Fedora CoreOS derivatives. + +Projects linking to libostree +----------------------------- + +[rpm-ostree](https://github.com/projectatomic/rpm-ostree) is used by the +Fedora-derived operating systems listed above. It is a full hybrid +image/package system. By default it uses libostree to atomically replicate a base OS +(all dependency resolution is done on the server), but it supports "package layering", where additional RPMs can be layered on top of the base. This brings a "best of both worlds"" model for image and package systems. +[eos-updater](https://github.com/endlessm/eos-updater) is a daemon that implements updates +on EndlessOS. + [flatpak](https://github.com/flatpak/flatpak) uses libostree for desktop application containers. Unlike most of the other systems here, flatpak does not use the "libostree host system" aspects (e.g. bootloader management), just the "git-like hardlink dedup". For example, flatpak supports a per-user OSTree repository. -[Endless OS](https://endlessos.com/) uses libostree for their host system as -well as flatpak. See -their [eos-updater](https://github.com/endlessm/eos-updater) -and [deb-ostree-builder](https://github.com/dbnicholson/deb-ostree-builder) -projects. - -[GNOME Continuous](https://wiki.gnome.org/Projects/GnomeContinuous) is -where OSTree was born - as a high performance continuous delivery/testing -system for GNOME. - -The [BuildStream](https://gitlab.com/BuildStream/buildstream) build and -integration tool uses libostree as a caching system to store and share -built artifacts. - -[Liri OS](https://liri.io/download/silverblue/) has the option to install -their distribution using ostree. - Language bindings ---- From ab73d9f5258a202d0c2a514688091be4db6622e0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 6 Aug 2019 01:59:38 +0000 Subject: [PATCH 59/62] admin/init-fs: Add a --modern switch This skips creating the default stuff in the physical sysroot. I don't recall why I did that to be honest; it originated with the first commit of this file. It might not have ever been necessary. In any case, it's not necessary now with Fedora CoreOS, so prune it and let's have a clean `/`. Keep the old behavior by default though to avoid breaking anyone. Closes: #1894 Approved by: ajeddeloh --- src/ostree/ot-admin-builtin-init-fs.c | 48 ++++++++++++++++++--------- tests/admin-test.sh | 12 +++++-- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/ostree/ot-admin-builtin-init-fs.c b/src/ostree/ot-admin-builtin-init-fs.c index cca63a62..cb1e1b69 100644 --- a/src/ostree/ot-admin-builtin-init-fs.c +++ b/src/ostree/ot-admin-builtin-init-fs.c @@ -30,7 +30,10 @@ #include +static gboolean opt_modern; + static GOptionEntry options[] = { + { "modern", 0, 0, G_OPTION_ARG_NONE, &opt_modern, "Only create /boot and /ostree", NULL }, { NULL } }; @@ -58,26 +61,39 @@ ot_admin_builtin_init_fs (int argc, char **argv, OstreeCommandInvocation *invoca if (!glnx_opendirat (AT_FDCWD, sysroot_path, TRUE, &root_dfd, error)) return FALSE; - const char *normal_toplevels[] = {"boot", "dev", "home", "proc", "run", "sys"}; - for (guint i = 0; i < G_N_ELEMENTS (normal_toplevels); i++) + /* It's common to want to mount this outside of a deployment as well */ + if (!glnx_shutil_mkdir_p_at (root_dfd, "boot", 0755, cancellable, error)) + return FALSE; + + /* See https://github.com/coreos/coreos-assembler/pull/688 + * For Fedora CoreOS at least, we have this now to the point where we don't + * need this stuff in the physical sysroot. I'm not sure we ever really did, + * but to be conservative, make it opt-in to the new model of just boot/ and ostree/. + */ + if (!opt_modern) { - if (!glnx_shutil_mkdir_p_at (root_dfd, normal_toplevels[i], 0755, - cancellable, error)) + const char *traditional_toplevels[] = {"boot", "dev", "home", "proc", "run", "sys"}; + for (guint i = 0; i < G_N_ELEMENTS (traditional_toplevels); i++) + { + if (!glnx_shutil_mkdir_p_at (root_dfd, traditional_toplevels[i], 0755, + cancellable, error)) + return FALSE; + } + + if (!glnx_shutil_mkdir_p_at (root_dfd, "root", 0700, + cancellable, error)) return FALSE; + + if (!glnx_shutil_mkdir_p_at (root_dfd, "tmp", 01777, + cancellable, error)) + return FALSE; + if (fchmodat (root_dfd, "tmp", 01777, 0) == -1) + { + glnx_set_prefix_error_from_errno (error, "chmod: %s", "tmp"); + return FALSE; + } } - if (!glnx_shutil_mkdir_p_at (root_dfd, "root", 0700, - cancellable, error)) - return FALSE; - - if (!glnx_shutil_mkdir_p_at (root_dfd, "tmp", 01777, - cancellable, error)) - return FALSE; - if (fchmodat (root_dfd, "tmp", 01777, 0) == -1) - { - glnx_set_prefix_error_from_errno (error, "chmod: %s", "tmp"); - return FALSE; - } g_autoptr(GFile) dir = g_file_new_for_path (sysroot_path); g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new (dir); if (!ostree_sysroot_ensure_initialized (sysroot, cancellable, error)) diff --git a/tests/admin-test.sh b/tests/admin-test.sh index 31e969c2..0defebc0 100644 --- a/tests/admin-test.sh +++ b/tests/admin-test.sh @@ -21,7 +21,15 @@ set -euo pipefail -echo "1..$((26 + ${extra_admin_tests:-0}))" +echo "1..$((27 + ${extra_admin_tests:-0}))" + +mkdir sysrootmin +${CMD_PREFIX} ostree admin init-fs --modern sysrootmin +assert_has_dir sysrootmin/boot +assert_has_dir sysrootmin/ostree/repo +assert_not_has_dir sysrootmin/home +rm sysrootmin -rf +echo "ok init-fs --modern" function validate_bootloader() { cd ${test_tmpdir}; @@ -48,7 +56,7 @@ orig_mtime=$(stat -c '%.Y' sysroot/ostree/deploy) ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) export rev -# This initial deployment gets kicked off with some kernel arguments +# This initial deployment gets kicked off with some kernel arguments ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime new_mtime=$(stat -c '%.Y' sysroot/ostree/deploy) assert_not_streq "${orig_mtime}" "${new_mtime}" From 0c48769de3965b9d62688f671e95267b3f40c998 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 13 Aug 2019 15:05:09 -0400 Subject: [PATCH 60/62] bin: Better handle -- We would stop passing through `--` and args after it to the underlying command in `ostree_run`. This made it impossible to use `--` to tell the parser that following args starting with `-` really are positional. AFAICT, that logic for `--` here came from a time when we parse options manually in a big loop, in which case breaking out made sense (see 97558276e4f855442337be01abc8f90cf0dd1810). There's an extra step here, which is that glib by default leaves the `--` in the list of args, so we need to take care to remove it from the list after parsing. Closes: #1898 Closes: #1899 Approved by: rfairley --- src/ostree/ot-main.c | 21 ++++++++++++++++----- tests/test-config.sh | 4 +++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/ostree/ot-main.c b/src/ostree/ot-main.c index c9c4f299..4b72f399 100644 --- a/src/ostree/ot-main.c +++ b/src/ostree/ot-main.c @@ -152,11 +152,6 @@ ostree_run (int argc, } } - else if (g_str_equal (argv[in], "--")) - { - break; - } - argv[out] = argv[in]; } @@ -348,6 +343,22 @@ ostree_option_context_parse (GOptionContext *context, if (!g_option_context_parse (context, argc, argv, error)) return FALSE; + /* Filter out the first -- we see; g_option_context_parse() leaves it in */ + int in, out; + gboolean removed_double_dashes = FALSE; + for (in = 1, out = 1; in < *argc; in++, out++) + { + if (g_str_equal ((*argv)[in], "--") && !removed_double_dashes) + { + removed_double_dashes = TRUE; + out--; + continue; + } + + (*argv)[out] = (*argv)[in]; + } + *argc = out; + if (opt_version) { /* This should now be YAML, like `docker version`, so it's both nice to read diff --git a/tests/test-config.sh b/tests/test-config.sh index 7e913d32..2f44c30b 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -66,9 +66,11 @@ fi assert_file_has_content err.txt "error: Too many arguments given" echo "ok config set" -# Check that "ostree config unset" works +# Check that using `--` works and that "ostree config unset" works ${CMD_PREFIX} ostree config --repo=repo set core.lock-timeout-secs 60 assert_file_has_content repo/config "lock-timeout-secs=60" +${CMD_PREFIX} ostree config --repo=repo -- set core.lock-timeout-secs -1 +assert_file_has_content repo/config "lock-timeout-secs=-1" ${CMD_PREFIX} ostree config --repo=repo unset core.lock-timeout-secs assert_not_file_has_content repo/config "lock-timeout-secs=" From 99d56215e65c4bf2ab0765218606f07a7550cbca Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 21 Aug 2019 14:42:48 +0800 Subject: [PATCH 61/62] lib/deploy: handle FIFREEZE ENOSYS failure When running under qemu, unimplemented ioctls such as FIFREEZE return ENOSYS, and this causes the deployment to fail. Catch this and handle it like EOPNOTSUPP. I'm not sure if qemu's behaviour is fully correct here (or if it should return EOPNOTSUPP) but it's trivial to handle regardless. Closes: #1901 Approved by: cgwalters --- src/libostree/ostree-sysroot-deploy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index d47f6438..9de5464a 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -1374,7 +1374,7 @@ fsfreeze_thaw_cycle (OstreeSysroot *self, * the filesystem is already frozen (EBUSY). * OK, let's just do a syncfs. */ - if (G_IN_SET (errno, EOPNOTSUPP, EPERM, EBUSY)) + if (G_IN_SET (errno, EOPNOTSUPP, ENOSYS, EPERM, EBUSY)) { /* Warn if the filesystem was already frozen */ if (errno == EBUSY) From b15ed42111c25bd3fcb0d9bdc425f79f771fcece Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 22 Aug 2019 18:04:40 +0000 Subject: [PATCH 62/62] Release 2019.3 It's been a while, and we need the new kargs API for rpm-ostree. Closes: #1902 Approved by: rfairley --- configure.ac | 2 +- src/libostree/libostree-devel.sym | 22 ---------------------- src/libostree/libostree-released.sym | 22 ++++++++++++++++++++++ tests/test-symbols.sh | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index e37d5f77..15c60bb4 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ m4_define([year_version], [2019]) m4_define([release_version], [3]) m4_define([package_version], [year_version.release_version]) AC_INIT([libostree], [package_version], [walters@verbum.org]) -is_release_build=no +is_release_build=yes AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([buildutil]) AC_CONFIG_AUX_DIR([build-aux]) diff --git a/src/libostree/libostree-devel.sym b/src/libostree/libostree-devel.sym index 36f35851..9339c0fd 100644 --- a/src/libostree/libostree-devel.sym +++ b/src/libostree/libostree-devel.sym @@ -18,28 +18,6 @@ ***/ /* Add new symbols here. Release commits should copy this section into -released.sym. */ -LIBOSTREE_2019.3 { -global: - ostree_repo_write_archive_to_mtree_from_fd; - ostree_kernel_args_free; - ostree_kernel_args_new; - ostree_kernel_args_cleanup; - ostree_kernel_args_replace_take; - ostree_kernel_args_replace; - ostree_kernel_args_replace_argv; - ostree_kernel_args_append; - ostree_kernel_args_append_argv; - ostree_kernel_args_append_argv_filtered; - ostree_kernel_args_new_replace; - ostree_kernel_args_delete; - ostree_kernel_args_delete_key_entry; - ostree_kernel_args_append_proc_cmdline; - ostree_kernel_args_parse_append; - ostree_kernel_args_get_last_value; - ostree_kernel_args_from_string; - ostree_kernel_args_to_strv; - ostree_kernel_args_to_string; -} LIBOSTREE_2018.9; /* Stub section for the stable release *after* this development one; don't * edit this other than to update the year. This is just a copy/paste diff --git a/src/libostree/libostree-released.sym b/src/libostree/libostree-released.sym index a4daaf1c..fbcb2d56 100644 --- a/src/libostree/libostree-released.sym +++ b/src/libostree/libostree-released.sym @@ -548,6 +548,28 @@ LIBOSTREE_2019.2 { ostree_repo_get_bootloader; } LIBOSTREE_2018.9; +LIBOSTREE_2019.3 { +global: + ostree_repo_write_archive_to_mtree_from_fd; + ostree_kernel_args_free; + ostree_kernel_args_new; + ostree_kernel_args_cleanup; + ostree_kernel_args_replace_take; + ostree_kernel_args_replace; + ostree_kernel_args_replace_argv; + ostree_kernel_args_append; + ostree_kernel_args_append_argv; + ostree_kernel_args_append_argv_filtered; + ostree_kernel_args_new_replace; + ostree_kernel_args_delete; + ostree_kernel_args_delete_key_entry; + ostree_kernel_args_append_proc_cmdline; + ostree_kernel_args_parse_append; + ostree_kernel_args_get_last_value; + ostree_kernel_args_from_string; + ostree_kernel_args_to_strv; + ostree_kernel_args_to_string; +} LIBOSTREE_2018.9; /* NOTE: Only add more content here in release commits! See the * comments at the top of this file. diff --git a/tests/test-symbols.sh b/tests/test-symbols.sh index ac058fad..5ec06d72 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 <