New upstream version 2019.2

This commit is contained in:
Simon McVittie committed 2019-04-29 08:36:24 +01:00
commit bd32d1e5de
79 files changed
+2910 -1852

No files matched your search

+1 -1
View File
@@ -65,7 +65,7 @@ read_config()
populate_menu()
{
# Default to /boot if OSTREE_BOOT_PARTITION is not set and /boot is on the same device than ostree/repo
# Default to /boot if OSTREE_BOOT_PARTITION is not set and /boot is on the same device as /ostree/repo
if [ -z ${OSTREE_BOOT_PARTITION+x} ] && [ -d /boot/ostree ] && [ -d /ostree/repo ] && [ $(stat -c '%d' /boot/ostree) -eq $(stat -c '%d' /ostree/repo) ]; then
boot_prefix="/boot"
else
+2 -2
View File
@@ -24,8 +24,8 @@ ConditionPathExists=/run/ostree-booted
DefaultDependencies=no
RequiresMountsFor=/sysroot
After=basic.target
Before=multi-user.target final.target
After=local-fs.target
Before=basic.target final.target
Conflicts=final.target
[Service]
+4 -4
View File
@@ -18,15 +18,15 @@
***/
/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2018.10 {
LIBOSTREE_2019.3 {
} LIBOSTREE_2018.9;
/* Stub section for the stable release *after* this development one; don't
* edit this other than to update the last number. This is just a copy/paste
* edit this other than to update the year. This is just a copy/paste
* source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION
* with whatever the next version with new symbols will be.
LIBOSTREE_2018.$NEWVERSION {
LIBOSTREE_2019.$NEWVERSION {
global:
someostree_symbol_deleteme;
} LIBOSTREE_2018.$LASTSTABLE;
} LIBOSTREE_2019.$LASTSTABLE;
*/
+7
View File
@@ -542,6 +542,13 @@ LIBOSTREE_2018.9 {
ostree_repo_get_default_repo_finders;
} LIBOSTREE_2018.7;
/* No new symbols in 2019.1 */
LIBOSTREE_2019.2 {
ostree_repo_get_bootloader;
} LIBOSTREE_2018.9;
/* NOTE: Only add more content here in release commits! See the
* comments at the top of this file.
*/
+5 -6
View File
@@ -332,6 +332,7 @@ grub2_child_setup (gpointer user_data)
static gboolean
_ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
{
@@ -357,15 +358,11 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
if (use_system_grub2_mkconfig && ostree_sysroot_get_booted_deployment (self->sysroot) == NULL
&& g_file_has_parent (self->sysroot->path, NULL))
{
g_autoptr(GPtrArray) deployments = NULL;
OstreeDeployment *tool_deployment;
g_autoptr(GFile) tool_deployment_root = NULL;
deployments = ostree_sysroot_get_deployments (self->sysroot);
g_assert_cmpint (deployments->len, >, 0);
tool_deployment = deployments->pdata[0];
g_assert_cmpint (new_deployments->len, >, 0);
tool_deployment = new_deployments->pdata[0];
/* Sadly we have to execute code to generate the bootloader configuration.
* If we're in a booted deployment, we just don't chroot.
@@ -380,6 +377,8 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader *bootloader,
grub2_mkconfig_chroot = g_file_get_path (tool_deployment_root);
}
g_debug ("Using grub2-mkconfig chroot: %s\n", grub2_mkconfig_chroot);
g_autoptr(GFile) new_config_path = NULL;
g_autoptr(GFile) config_path_efi_dir = NULL;
if (self->is_efi)
+5 -4
View File
@@ -108,10 +108,11 @@ append_config_from_loader_entries (OstreeBootloaderSyslinux *self,
}
static gboolean
_ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
int bootversion,
GCancellable *cancellable,
GError **error)
_ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
{
OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader);
+5 -4
View File
@@ -158,10 +158,11 @@ create_config_from_boot_loader_entries (OstreeBootloaderUboot *self,
}
static gboolean
_ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
int bootversion,
GCancellable *cancellable,
GError **error)
_ostree_bootloader_uboot_write_config (OstreeBootloader *bootloader,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
{
OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader);
+4 -2
View File
@@ -54,13 +54,15 @@ _ostree_bootloader_get_name (OstreeBootloader *self)
gboolean
_ostree_bootloader_write_config (OstreeBootloader *self,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
cancellable, error);
return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
new_deployments,
cancellable, error);
}
gboolean
+2
View File
@@ -44,6 +44,7 @@ struct _OstreeBootloaderInterface
const char * (* get_name) (OstreeBootloader *self);
gboolean (* write_config) (OstreeBootloader *self,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error);
gboolean (* is_atomic) (OstreeBootloader *self);
@@ -61,6 +62,7 @@ const char *_ostree_bootloader_get_name (OstreeBootloader *self);
gboolean _ostree_bootloader_write_config (OstreeBootloader *self,
int bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error);
+2 -2
View File
@@ -645,7 +645,7 @@ _ostree_fetcher_constructed (GObject *object)
}
http_proxy = g_getenv ("http_proxy");
if (http_proxy != NULL)
if (http_proxy != NULL && http_proxy[0] != '\0')
_ostree_fetcher_set_proxy (self, http_proxy);
/* FIXME Maybe implement GInitableIface and use g_thread_try_new()
@@ -711,7 +711,7 @@ _ostree_fetcher_set_proxy (OstreeFetcher *self,
SoupURI *proxy_uri;
g_return_if_fail (OSTREE_IS_FETCHER (self));
g_return_if_fail (http_proxy != NULL);
g_return_if_fail (http_proxy != NULL && http_proxy[0] != '\0');
proxy_uri = soup_uri_new (http_proxy);
+1 -3
View File
@@ -163,18 +163,16 @@ _ostree_fetcher_journal_failure (const char *remote_name,
const char *url,
const char *msg)
{
#ifdef HAVE_LIBSYSTEMD
/* Sanity - we don't want to log this when doing local/file pulls */
if (!remote_name)
return;
sd_journal_send ("MESSAGE=libostree HTTP error from remote %s for <%s>: %s",
ot_journal_send ("MESSAGE=libostree HTTP error from remote %s for <%s>: %s",
remote_name, url, msg,
"MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_HTTP_FAILURE_ID),
"OSTREE_REMOTE=%s", remote_name,
"OSTREE_URL=%s", url,
"PRIORITY=%i", LOG_ERR,
NULL);
#endif
}
/* Check whether a particular operation should be retried. This is entirely
+12 -2
View File
@@ -4269,7 +4269,7 @@ import_one_object_direct (OstreeRepo *dest_repo,
G_IN_SET (src_repo->mode, OSTREE_REPO_MODE_BARE, OSTREE_REPO_MODE_BARE_USER);
if (src_is_bare_or_bare_user && !OSTREE_OBJECT_TYPE_IS_META(objtype))
{
if (src_repo == OSTREE_REPO_MODE_BARE)
if (src_repo->mode == OSTREE_REPO_MODE_BARE)
{
g_autoptr(GVariant) xattrs = NULL;
if (!glnx_fd_get_all_xattrs (src_fd, &xattrs,
@@ -4279,15 +4279,25 @@ import_one_object_direct (OstreeRepo *dest_repo,
cancellable, error))
return FALSE;
}
else if (dest_repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY)
{
/* Nothing; this is the "bareuser-only conversion case",
* we don't need to set any xattrs in the dest repo.
*/
}
else
{
/* And this case must be bare-user → bare-user */
g_assert (src_repo->mode == OSTREE_REPO_MODE_BARE_USER);
g_assert (src_repo->mode == dest_repo->mode);
/* bare-user; we just want ostree.usermeta */
g_autoptr(GBytes) bytes =
glnx_fgetxattr_bytes (src_fd, "user.ostreemeta", error);
if (bytes == NULL)
return FALSE;
if (TEMP_FAILURE_RETRY (fsetxattr (src_fd, "user.ostreemeta",
if (TEMP_FAILURE_RETRY (fsetxattr (tmp_dest.fd, "user.ostreemeta",
(char*)g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes), 0)) != 0)
return glnx_throw_errno_prefix (error, "fsetxattr");
+1
View File
@@ -169,6 +169,7 @@ struct OstreeRepo {
guint64 payload_link_threshold;
gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */
gchar **repo_finders;
gchar *bootloader; /* Configure which bootloader to use. */
OstreeRepo *parent_repo;
};
+88 -20
View File
@@ -115,6 +115,7 @@ typedef struct {
GHashTable *summary_deltas_checksums;
GHashTable *ref_original_commits; /* Maps checksum to commit, used by timestamp checks */
GHashTable *gpg_verified_commits; /* Set<checksum> 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 */
GHashTable *commit_to_depth; /* Maps commit checksum maximum depth */
@@ -260,12 +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,
GCancellable *cancellable,
GError **error);
gpg_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error);
static gboolean
@@ -1307,7 +1309,7 @@ meta_fetch_on_complete (GObject *object,
*/
GVariant *detached_data = g_hash_table_lookup (pull_data->fetched_detached_metadata, checksum);
if (!gpg_verify_unwritten_commit (pull_data, checksum, metadata, detached_data,
pull_data->cancellable, error))
fetch_data->requested_ref, pull_data->cancellable, error))
goto out;
if (!ostree_repo_mark_commit_partial (pull_data->repo, checksum, TRUE, error))
@@ -1462,23 +1464,32 @@ process_verify_result (OtPullData *pull_data,
}
static gboolean
gpg_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
GCancellable *cancellable,
GError **error)
gpg_verify_unwritten_commit (OtPullData *pull_data,
const char *checksum,
GVariant *commit,
GVariant *detached_metadata,
const OstreeCollectionRef *ref,
GCancellable *cancellable,
GError **error)
{
if (pull_data->gpg_verify)
{
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))
return TRUE;
if (ref != NULL)
keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref);
if (keyring_remote == NULL)
keyring_remote = pull_data->remote_name;
g_autoptr(GBytes) signed_data = g_variant_get_data_as_bytes (commit);
g_autoptr(OstreeGpgVerifyResult) result =
_ostree_repo_gpg_verify_with_metadata (pull_data->repo, signed_data,
detached_metadata, pull_data->remote_name,
detached_metadata,
keyring_remote,
NULL, NULL, cancellable, error);
if (!process_verify_result (pull_data, checksum, result, error))
return FALSE;
@@ -1788,10 +1799,16 @@ scan_commit_object (OtPullData *pull_data,
!g_hash_table_contains (pull_data->gpg_verified_commits, checksum))
{
g_autoptr(OstreeGpgVerifyResult) result = NULL;
const char *keyring_remote = NULL;
if (ref != NULL)
keyring_remote = g_hash_table_lookup (pull_data->ref_keyring_map, ref);
if (keyring_remote == NULL)
keyring_remote = pull_data->remote_name;
result = ostree_repo_verify_commit_for_remote (pull_data->repo,
checksum,
pull_data->remote_name,
keyring_remote,
cancellable,
error);
if (!process_verify_result (pull_data, checksum, result, error))
@@ -2385,7 +2402,7 @@ process_one_static_delta (OtPullData *pull_data,
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,
cancellable, error))
ref, cancellable, error))
return FALSE;
if (detached_data && !ostree_repo_write_commit_detached_metadata (pull_data->repo,
@@ -3017,7 +3034,7 @@ _ostree_repo_remote_new_fetcher (OstreeRepo *self,
&http_proxy, error))
goto out;
if (http_proxy != NULL)
if (http_proxy != NULL && http_proxy[0] != '\0')
_ostree_fetcher_set_proxy (fetcher, http_proxy);
}
@@ -3504,7 +3521,15 @@ initiate_request (OtPullData *pull_data,
* * append-user-agent (s): Additional string to append to the user agent
* * n-network-retries (u): Number of times to retry each download on receiving
* a transient network error, such as a socket timeout; default is 5, 0
* means return errors without retrying
* means return errors without retrying. Since: 2018.6
* * ref-keyring-map (a(sss)): Array of (collection ID, ref name, keyring
* remote name) tuples specifying which remote's keyring should be used when
* doing GPG verification of each collection-ref. This is useful to prevent a
* remote from serving malicious updates to refs which did not originate from
* it. This can be a subset or superset of the refs being pulled; any ref
* not being pulled will be ignored and any ref without a keyring remote
* will be verified with the keyring of the remote being pulled from.
* Since: 2019.2
*/
gboolean
ostree_repo_pull_with_options (OstreeRepo *self,
@@ -3539,12 +3564,14 @@ ostree_repo_pull_with_options (OstreeRepo *self,
gboolean opt_gpg_verify_summary_set = FALSE;
gboolean opt_collection_refs_set = FALSE;
gboolean opt_n_network_retries_set = FALSE;
gboolean opt_ref_keyring_map_set = FALSE;
const char *main_collection_id = NULL;
const char *url_override = NULL;
gboolean inherit_transaction = FALSE;
g_autoptr(GHashTable) updated_requested_refs_to_fetch = NULL; /* (element-type OstreeCollectionRef utf8) */
int i;
g_autofree char **opt_localcache_repos = NULL;
g_autoptr(GVariantIter) ref_keyring_map_iter = NULL;
/* If refs or collection-refs has exactly one value, this will point to that
* value, otherwise NULL. Used for logging.
*/
@@ -3584,6 +3611,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(void) g_variant_lookup (options, "append-user-agent", "s", &pull_data->append_user_agent);
opt_n_network_retries_set =
g_variant_lookup (options, "n-network-retries", "u", &pull_data->n_network_retries);
opt_ref_keyring_map_set =
g_variant_lookup (options, "ref-keyring-map", "a(sss)", &ref_keyring_map_iter);
if (pull_data->remote_refspec_name != NULL)
pull_data->remote_name = g_strdup (pull_data->remote_refspec_name);
@@ -3644,6 +3673,8 @@ ostree_repo_pull_with_options (OstreeRepo *self,
(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->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,
(GDestroyNotify)g_variant_unref, NULL);
pull_data->fetched_detached_metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
@@ -4373,6 +4404,30 @@ ostree_repo_pull_with_options (OstreeRepo *self,
}
}
if (opt_ref_keyring_map_set)
{
const gchar *collection_id, *ref_name, *keyring_remote_name;
while (g_variant_iter_loop (ref_keyring_map_iter, "(&s&s&s)", &collection_id, &ref_name, &keyring_remote_name))
{
g_autoptr(OstreeCollectionRef) c_r = NULL;
if (!ostree_validate_collection_id (collection_id, error))
goto out;
if (!ostree_validate_rev (ref_name, error))
goto out;
if (!ostree_validate_remote_name (keyring_remote_name, error))
goto out;
c_r = ostree_collection_ref_new (collection_id, ref_name);
if (!g_hash_table_contains (requested_refs_to_fetch, c_r))
continue;
g_hash_table_insert (pull_data->ref_keyring_map,
g_steal_pointer (&c_r),
g_strdup (keyring_remote_name));
}
}
/* Create the state directory here - it's new with the commitpartial code,
* and may not exist in older repositories.
*/
@@ -4600,7 +4655,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
g_autofree char *formatted_xferred = g_format_size (bytes_transferred);
g_string_append_printf (msg, "\ntransfer: secs: %u size: %s", n_seconds, formatted_xferred);
sd_journal_send ("MESSAGE=%s", msg->str,
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,
@@ -4664,6 +4719,7 @@ ostree_repo_pull_with_options (OstreeRepo *self,
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->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);
g_clear_pointer (&pull_data->requested_metadata, (GDestroyNotify) g_hash_table_unref);
@@ -4950,7 +5006,7 @@ static void find_remotes_cb (GObject *obj,
* provided.
* * `n-network-retries` (`u`): Number of times to retry each download on
* receiving a transient network error, such as a socket timeout; default is
* 5, 0 means return errors without retrying.
* 5, 0 means return errors without retrying. Since: 2018.6
*
* @finders must be a non-empty %NULL-terminated array of the #OstreeRepoFinder
* instances to use, or %NULL to use the system default set of finders, which
@@ -5795,6 +5851,17 @@ copy_option (GVariantDict *master_options,
* * `update-frequency` (`u`): Frequency to call the async progress callback in
* milliseconds, if any; only values higher than 0 are valid
* * `append-user-agent` (`s`): Additional string to append to the user agent
* * `n-network-retries` (`u`): Number of times to retry each download on receiving
* a transient network error, such as a socket timeout; default is 5, 0
* means return errors without retrying. Since: 2018.6
* * `ref-keyring-map` (`a(sss)`): Array of (collection ID, ref name, keyring
* remote name) tuples specifying which remote's keyring should be used when
* doing GPG verification of each collection-ref. This is useful to prevent a
* remote from serving malicious updates to refs which did not originate from
* it. This can be a subset or superset of the refs being pulled; any ref
* not being pulled will be ignored and any ref without a keyring remote
* will be verified with the keyring of the remote being pulled from.
* Since: 2019.2
*
* Since: 2018.6
*/
@@ -5915,6 +5982,7 @@ ostree_repo_pull_from_remotes_async (OstreeRepo *self,
copy_option (&options_dict, &local_options_dict, "update-frequency", G_VARIANT_TYPE ("u"));
copy_option (&options_dict, &local_options_dict, "append-user-agent", G_VARIANT_TYPE ("s"));
copy_option (&options_dict, &local_options_dict, "n-network-retries", G_VARIANT_TYPE ("u"));
copy_option (&options_dict, &local_options_dict, "ref-keyring-map", G_VARIANT_TYPE ("a(sss)"));
local_options = g_variant_dict_end (&local_options_dict);
+67 -13
View File
@@ -479,6 +479,9 @@ ostree_repo_resolve_rev (OstreeRepo *self,
* the parameter @out_rev. Differently from ostree_repo_resolve_rev(),
* this will not fall back to searching through remote repos if a
* local ref is specified but not found.
*
* The flag %OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY is implied so
* using it has no effect.
*/
gboolean
ostree_repo_resolve_rev_ext (OstreeRepo *self,
@@ -511,7 +514,9 @@ ostree_repo_resolve_rev_ext (OstreeRepo *self,
* the given @ref cannot be found, a %G_IO_ERROR_NOT_FOUND error will be
* returned.
*
* There are currently no @flags which affect the behaviour of this function.
* If you want to check only local refs, not remote or mirrored ones, use the
* flag %OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY. This is analogous to using
* ostree_repo_resolve_rev_ext() but for collection-refs.
*
* Returns: %TRUE on success, %FALSE on failure
* Since: 2018.6
@@ -525,19 +530,63 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
g_autofree char *ret_contents = NULL;
g_return_val_if_fail (OSTREE_IS_REPO (self), FALSE);
g_return_val_if_fail (ref != NULL, FALSE);
g_return_val_if_fail (ref->collection_id != NULL && ref->ref_name != NULL, FALSE);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */
if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs,
OSTREE_REPO_LIST_REFS_EXT_NONE,
cancellable, error))
return FALSE;
/* Check for the ref in the current transaction in case it hasn't been
* written to disk, to match the behavior of ostree_repo_resolve_rev() */
if (self->in_transaction)
{
g_mutex_lock (&self->txn_lock);
if (self->txn.collection_refs)
{
const char *repo_collection_id = ostree_repo_get_collection_id (self);
/* If the collection ID doesn't match it's a remote ref */
if (!(flags & OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY) ||
repo_collection_id == NULL ||
g_strcmp0 (repo_collection_id, ref->collection_id) == 0)
{
ret_contents = g_strdup (g_hash_table_lookup (self->txn.collection_refs, ref));
}
}
g_mutex_unlock (&self->txn_lock);
}
const char *ret_contents = g_hash_table_lookup (refs, ref);
/* Check for the ref on disk in the repo */
if (ret_contents == NULL)
{
g_autoptr(GHashTable) refs = NULL; /* (element-type OstreeCollectionRef utf8) */
OstreeRepoListRefsExtFlags list_refs_flags;
if (flags & OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY)
list_refs_flags = OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES | OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS;
else
list_refs_flags = OSTREE_REPO_LIST_REFS_EXT_NONE;
if (!ostree_repo_list_collection_refs (self, ref->collection_id, &refs,
list_refs_flags, cancellable, error))
return FALSE;
ret_contents = g_strdup (g_hash_table_lookup (refs, ref));
}
/* Check for the ref in the parent repo */
if (ret_contents == NULL && self->parent_repo != NULL)
{
if (!ostree_repo_resolve_collection_ref (self->parent_repo,
ref,
TRUE,
flags,
&ret_contents,
cancellable,
error))
return FALSE;
}
if (ret_contents == NULL && !allow_noent)
{
@@ -548,7 +597,7 @@ ostree_repo_resolve_collection_ref (OstreeRepo *self,
}
if (out_rev != NULL)
*out_rev = g_strdup (ret_contents);
*out_rev = g_steal_pointer (&ret_contents);
return TRUE;
}
@@ -1218,7 +1267,9 @@ _ostree_repo_update_collection_refs (OstreeRepo *self,
* (ostree_repo_get_collection_id()).
*
* If you want to exclude refs from `refs/remotes`, use
* %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES in @flags.
* %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES in @flags. Similarly use
* %OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS to exclude refs from
* `refs/mirrors`.
*
* Returns: %TRUE on success, %FALSE otherwise
* Since: 2018.6
@@ -1240,9 +1291,12 @@ ostree_repo_list_collection_refs (OstreeRepo *self,
if (match_collection_id != NULL && !ostree_validate_collection_id (match_collection_id, error))
return FALSE;
const gchar *refs_dirs[] = { "refs/mirrors", "refs/remotes", NULL };
if (flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES)
refs_dirs[1] = NULL;
g_autoptr(GPtrArray) refs_dirs = g_ptr_array_new ();
if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS))
g_ptr_array_add (refs_dirs, "refs/mirrors");
if (!(flags & OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES))
g_ptr_array_add (refs_dirs, "refs/remotes");
g_ptr_array_add (refs_dirs, NULL);
g_autoptr(GHashTable) ret_all_refs = NULL;
@@ -1272,7 +1326,7 @@ ostree_repo_list_collection_refs (OstreeRepo *self,
g_string_truncate (base_path, 0);
for (const char **iter = refs_dirs; iter && *iter; iter++)
for (const char **iter = (const char **)refs_dirs->pdata; iter && *iter; iter++)
{
const char *refs_dir = *iter;
gboolean refs_dir_exists = FALSE;
+40 -10
View File
@@ -725,16 +725,25 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
g_autofree char *from = NULL;
g_autofree char *to = NULL;
if (!_ostree_parse_delta_name (delta_id, &from, &to, error))
return FALSE;
g_autofree char *superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to);
glnx_autofd int superblock_fd = -1;
if (!glnx_openat_rdonly (self->repo_dir_fd, superblock_path, TRUE, &superblock_fd, error))
return FALSE;
if (strchr (delta_id, '/'))
{
if (!glnx_openat_rdonly (AT_FDCWD, delta_id, TRUE, &superblock_fd, error))
return FALSE;
}
else
{
g_autofree char *from = NULL;
g_autofree char *to = NULL;
if (!_ostree_parse_delta_name (delta_id, &from, &to, error))
return FALSE;
g_autofree char *superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to);
if (!glnx_openat_rdonly (self->repo_dir_fd, superblock_path, TRUE, &superblock_fd, error))
return FALSE;
}
g_autoptr(GVariant) delta_superblock = NULL;
if (!ot_variant_read_fd (superblock_fd, 0,
(GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT,
@@ -742,6 +751,26 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
return FALSE;
g_print ("Delta: %s\n", delta_id);
g_autoptr(GVariant) from_commit_v = NULL;
g_variant_get_child (delta_superblock, 2, "@ay", &from_commit_v);
g_autofree char *from_commit = NULL;
if (g_variant_n_children (from_commit_v) > 0)
{
if (!ostree_checksum_bytes_peek_validate (from_commit_v, error))
return FALSE;
from_commit = ostree_checksum_from_bytes_v (from_commit_v);
g_print ("From: %s\n", from_commit);
}
else
{
g_print ("From <scratch>\n");
}
g_autoptr(GVariant) to_commit_v = NULL;
g_variant_get_child (delta_superblock, 3, "@ay", &to_commit_v);
if (!ostree_checksum_bytes_peek_validate (to_commit_v, error))
return FALSE;
g_autofree char *to_commit = ostree_checksum_from_bytes_v (to_commit_v);
g_print ("To: %s\n", to_commit);
gboolean swap_endian = FALSE;
OstreeDeltaEndianness endianness;
@@ -777,6 +806,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
g_print ("Endianness: %s\n", endianness_description);
}
guint64 ts;
g_variant_get_child (delta_superblock, 1, "t", &ts);
g_print ("Timestamp: %" G_GUINT64_FORMAT "\n", GUINT64_FROM_BE (ts));
@@ -821,7 +851,7 @@ _ostree_repo_static_delta_dump (OstreeRepo *self,
for (guint i = 0; i < n_parts; i++)
{
if (!show_one_part (self, swap_endian, from, to, meta_entries, i,
if (!show_one_part (self, swap_endian, from_commit, to_commit, meta_entries, i,
&total_size, &total_usize,
cancellable, error))
return FALSE;
+139 -2
View File
@@ -1036,6 +1036,7 @@ ostree_repo_finalize (GObject *object)
g_mutex_clear (&self->txn_lock);
g_free (self->collection_id);
g_strfreev (self->repo_finders);
g_free (self->bootloader);
g_clear_pointer (&self->remotes, g_hash_table_destroy);
g_mutex_clear (&self->remotes_lock);
@@ -1735,6 +1736,88 @@ ostree_repo_remote_delete (OstreeRepo *self,
return impl_repo_remote_delete (self, NULL, FALSE, name, cancellable, error);
}
static gboolean
impl_repo_remote_replace (OstreeRepo *self,
GFile *sysroot,
const char *name,
const char *url,
GVariant *options,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (url != NULL, FALSE);
g_return_val_if_fail (options == NULL || g_variant_is_of_type (options, G_VARIANT_TYPE ("a{sv}")), FALSE);
if (!ostree_validate_remote_name (name, error))
return FALSE;
g_autoptr(GError) local_error = NULL;
g_autoptr(OstreeRemote) remote = _ostree_repo_get_remote (self, name, &local_error);
if (remote == NULL)
{
if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
g_clear_error (&local_error);
if (!impl_repo_remote_add (self, sysroot, FALSE, name, url, options,
cancellable, error))
return FALSE;
}
else
{
/* Replace the entire option group */
if (!g_key_file_remove_group (remote->options, remote->group, error))
return FALSE;
if (g_str_has_prefix (url, "metalink="))
g_key_file_set_string (remote->options, remote->group, "metalink",
url + strlen ("metalink="));
else
g_key_file_set_string (remote->options, remote->group, "url", url);
if (options != NULL)
keyfile_set_from_vardict (remote->options, remote->group, options);
/* Write out updated settings */
if (remote->file != NULL)
{
gsize length;
g_autofree char *data = g_key_file_to_data (remote->options, &length,
NULL);
if (!g_file_replace_contents (remote->file, data, length,
NULL, FALSE, 0, NULL,
cancellable, error))
return FALSE;
}
else
{
g_autoptr(GKeyFile) config = ostree_repo_copy_config (self);
/* Remove the existing group if it exists */
if (!g_key_file_remove_group (config, remote->group, &local_error))
{
if (!g_error_matches (local_error, G_KEY_FILE_ERROR,
G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
ot_keyfile_copy_group (remote->options, config, remote->group);
if (!ostree_repo_write_config (self, config, error))
return FALSE;
}
}
return TRUE;
}
/**
* ostree_repo_remote_change:
* @self: Repo
@@ -1776,6 +1859,9 @@ ostree_repo_remote_change (OstreeRepo *self,
case OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS:
return impl_repo_remote_delete (self, sysroot, TRUE, name,
cancellable, error);
case OSTREE_REPO_REMOTE_CHANGE_REPLACE:
return impl_repo_remote_replace (self, sysroot, name, url, options,
cancellable, error);
}
g_assert_not_reached ();
}
@@ -3028,6 +3114,33 @@ reload_remote_config (OstreeRepo *self,
return TRUE;
}
static gboolean
reload_sysroot_config (OstreeRepo *self,
GCancellable *cancellable,
GError **error)
{
{ g_autofree char *bootloader = NULL;
if (!ot_keyfile_get_value_with_default_group_optional (self->config, "sysroot",
"bootloader", "auto",
&bootloader, error))
return FALSE;
/* TODO: possibly later add support for specifying a generic bootloader
* binary "x" in /usr/lib/ostree/bootloaders/x). See:
* https://github.com/ostreedev/ostree/issues/1719
* https://github.com/ostreedev/ostree/issues/1801
*/
if (!(g_str_equal (bootloader, "auto") || g_str_equal (bootloader, "none")))
return glnx_throw (error, "Invalid bootloader configuration: '%s'", bootloader);
g_free (self->bootloader);
self->bootloader = g_steal_pointer (&bootloader);
}
return TRUE;
}
/**
* ostree_repo_reload_config:
* @self: repo
@@ -3046,6 +3159,8 @@ ostree_repo_reload_config (OstreeRepo *self,
return FALSE;
if (!reload_remote_config (self, cancellable, error))
return FALSE;
if (!reload_sysroot_config (self, cancellable, error))
return FALSE;
return TRUE;
}
@@ -5101,8 +5216,12 @@ _ostree_repo_gpg_verify_data_internal (OstreeRepo *self,
g_auto(GStrv) gpgkeypath_list = NULL;
if (!ot_keyfile_get_string_as_list (remote->options, remote->group, "gpgkeypath",
";,", &gpgkeypath_list, error))
if (!ot_keyfile_get_string_list_with_separator_choice (remote->options,
remote->group,
"gpgkeypath",
";,",
&gpgkeypath_list,
error))
return NULL;
if (gpgkeypath_list)
@@ -5975,3 +6094,21 @@ ostree_repo_get_default_repo_finders (OstreeRepo *self)
return (const gchar * const *)self->repo_finders;
}
/**
* 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
*/
const gchar *
ostree_repo_get_bootloader (OstreeRepo *self)
{
g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
return self->bootloader;
}
+10 -1
View File
@@ -115,6 +115,9 @@ gboolean ostree_repo_set_collection_id (OstreeRepo *self,
_OSTREE_PUBLIC
const gchar * const * ostree_repo_get_default_repo_finders (OstreeRepo *self);
_OSTREE_PUBLIC
const gchar * ostree_repo_get_bootloader (OstreeRepo *self);
_OSTREE_PUBLIC
GFile * ostree_repo_get_path (OstreeRepo *self);
@@ -166,12 +169,14 @@ gboolean ostree_repo_remote_delete (OstreeRepo *self,
* @OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS: Like above, but do nothing if the remote exists
* @OSTREE_REPO_REMOTE_CHANGE_DELETE: Delete a remote
* @OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS: Delete a remote, do nothing if the remote does not exist
* @OSTREE_REPO_REMOTE_CHANGE_REPLACE: Add or replace a remote (Since: 2019.2)
*/
typedef enum {
OSTREE_REPO_REMOTE_CHANGE_ADD,
OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS,
OSTREE_REPO_REMOTE_CHANGE_DELETE,
OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS
OSTREE_REPO_REMOTE_CHANGE_DELETE_IF_EXISTS,
OSTREE_REPO_REMOTE_CHANGE_REPLACE,
} OstreeRepoRemoteChange;
_OSTREE_PUBLIC
@@ -460,9 +465,11 @@ gboolean ostree_repo_resolve_rev (OstreeRepo *self,
/**
* OstreeRepoResolveRevExtFlags:
* @OSTREE_REPO_RESOLVE_REV_EXT_NONE: No flags.
* @OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY: Exclude remote and mirrored refs. Since: 2019.2
*/
typedef enum {
OSTREE_REPO_RESOLVE_REV_EXT_NONE = 0,
OSTREE_REPO_RESOLVE_REV_EXT_LOCAL_ONLY = (1 << 0),
} OstreeRepoResolveRevExtFlags;
_OSTREE_PUBLIC
@@ -494,11 +501,13 @@ gboolean ostree_repo_list_refs (OstreeRepo *self,
* @OSTREE_REPO_LIST_REFS_EXT_NONE: No flags.
* @OSTREE_REPO_LIST_REFS_EXT_ALIASES: Only list aliases. Since: 2017.10
* @OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES: Exclude remote refs. Since: 2017.11
* @OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS: Exclude mirrored refs. Since: 2019.2
*/
typedef enum {
OSTREE_REPO_LIST_REFS_EXT_NONE = 0,
OSTREE_REPO_LIST_REFS_EXT_ALIASES = (1 << 0),
OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_REMOTES = (1 << 1),
OSTREE_REPO_LIST_REFS_EXT_EXCLUDE_MIRRORS = (1 << 2),
} OstreeRepoListRefsExtFlags;
_OSTREE_PUBLIC
+40 -17
View File
@@ -447,14 +447,12 @@ merge_configuration_from (OstreeSysroot *sysroot,
{ g_autofree char *msg =
g_strdup_printf ("Copying /etc changes: %u modified, %u removed, %u added",
modified->len, removed->len, added->len);
#ifdef HAVE_LIBSYSTEMD
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_CONFIGMERGE_ID),
ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_CONFIGMERGE_ID),
"MESSAGE=%s", msg,
"ETC_N_MODIFIED=%u", modified->len,
"ETC_N_REMOVED=%u", removed->len,
"ETC_N_ADDED=%u", added->len,
NULL);
#endif
_ostree_sysroot_emit_journal_msg (sysroot, msg);
}
@@ -701,11 +699,9 @@ selinux_relabel_var_if_needed (OstreeSysroot *sysroot,
{
{ g_autofree char *msg =
g_strdup_printf ("Relabeling /var (no stamp file '%s' found)", selabeled);
#ifdef HAVE_LIBSYSTEMD
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_VARRELABEL_ID),
ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_VARRELABEL_ID),
"MESSAGE=%s", msg,
NULL);
#endif
_ostree_sysroot_emit_journal_msg (sysroot, msg);
}
@@ -1739,7 +1735,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
* (specifically, it looks for the substring "(ostree"), so further
* changes to the title format may require updating that backend. */
g_autoptr(GString) title_key = g_string_new (val);
if (deployment_version && *deployment_version)
if (deployment_version && *deployment_version && !strstr (val, deployment_version))
{
g_string_append_c (title_key, ' ');
g_string_append (title_key, deployment_version);
@@ -2122,7 +2118,8 @@ write_deployments_bootswap (OstreeSysroot *self,
if (bootloader)
{
if (!_ostree_bootloader_write_config (bootloader, new_bootversion,
cancellable, error))
new_deployments, cancellable,
error))
return glnx_prefix_error (error, "Bootloader write config");
}
@@ -2310,6 +2307,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
gboolean bootloader_is_atomic = FALSE;
SyncStats syncstats = { 0, };
g_autoptr(OstreeBootloader) bootloader = NULL;
const char *bootloader_config = NULL;
if (!requires_new_bootversion)
{
if (!create_new_bootlinks (self, self->bootversion,
@@ -2342,8 +2340,22 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
return glnx_throw_errno_prefix (error, "Remounting /boot read-write");
}
if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error))
return FALSE;
OstreeRepo *repo = ostree_sysroot_repo (self);
bootloader_config = ostree_repo_get_bootloader (repo);
g_debug ("Using bootloader configuration: %s", bootloader_config);
if (g_str_equal (bootloader_config, "auto"))
{
if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error))
return FALSE;
}
else if (g_str_equal (bootloader_config, "none"))
{
/* No bootloader specified; do not query bootloaders to run. */
}
bootloader_is_atomic = bootloader != NULL && _ostree_bootloader_is_atomic (bootloader);
/* Note equivalent of try/finally here */
@@ -2371,10 +2383,10 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
(bootloader_is_atomic ? "Transaction complete" : "Bootloader updated"),
requires_new_bootversion ? "yes" : "no",
new_deployments->len - self->deployments->len);
#ifdef HAVE_LIBSYSTEMD
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID),
ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID),
"MESSAGE=%s", msg,
"OSTREE_BOOTLOADER=%s", bootloader ? _ostree_bootloader_get_name (bootloader) : "none",
"OSTREE_BOOTLOADER_CONFIG=%s", bootloader_config,
"OSTREE_BOOTLOADER_ATOMIC=%s", bootloader_is_atomic ? "yes" : "no",
"OSTREE_DID_BOOTSWAP=%s", requires_new_bootversion ? "yes" : "no",
"OSTREE_N_DEPLOYMENTS=%u", new_deployments->len,
@@ -2382,7 +2394,6 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self,
"OSTREE_SYNCFS_BOOT_MSEC=%" G_GUINT64_FORMAT, syncstats.boot_syncfs_msec,
"OSTREE_SYNCFS_EXTRA_MSEC=%" G_GUINT64_FORMAT, syncstats.extra_syncfs_msec,
NULL);
#endif
_ostree_sysroot_emit_journal_msg (self, msg);
}
@@ -2870,12 +2881,25 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self,
* service when a staged deployment is created.
*/
if (!self->staged_deployment)
return TRUE;
{
ot_journal_print (LOG_INFO, "No deployment staged for finalization");
return TRUE;
}
/* Check if finalization is locked. */
if (!glnx_fstatat_allow_noent (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED,
NULL, 0, error))
return FALSE;
if (errno == 0)
{
ot_journal_print (LOG_INFO, "Not finalizing; found "
_OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED);
return TRUE;
}
/* Notice we send this *after* the trivial `return TRUE` above; this msg implies we've
* committed to finalizing the deployment. */
#ifdef HAVE_LIBSYSTEMD
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR,
ot_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR,
SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_FINALIZING_ID),
"MESSAGE=Finalizing staged deployment",
"OSTREE_OSNAME=%s",
@@ -2885,7 +2909,6 @@ _ostree_sysroot_finalize_staged (OstreeSysroot *self,
"OSTREE_DEPLOYSERIAL=%u",
ostree_deployment_get_deployserial (self->staged_deployment),
NULL);
#endif
g_assert (self->staged_deployment_data);
+1
View File
@@ -76,6 +76,7 @@ struct OstreeSysroot {
#define OSTREE_SYSROOT_LOCKFILE "ostree/lock"
/* We keep some transient state in /run */
#define _OSTREE_SYSROOT_RUNSTATE_STAGED "/run/ostree/staged-deployment"
#define _OSTREE_SYSROOT_RUNSTATE_STAGED_LOCKED "/run/ostree/staged-deployment-locked"
#define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_DIR "/run/ostree/deployment-state/"
#define _OSTREE_SYSROOT_DEPLOYMENT_RUNSTATE_FLAG_DEVELOPMENT "unlocked-development"
+29 -5
View File
@@ -1699,6 +1699,22 @@ clone_deployment (OstreeSysroot *sysroot,
return TRUE;
}
/* Do `mkdir()` followed by `chmod()` immediately afterwards to ensure `umask()` isn't
* masking permissions where we don't want it to. Thus we avoid calling `umask()`, which
* would affect the whole process. */
static gboolean mkdir_unmasked (int dfd,
const char *path,
int mode,
GCancellable *cancellable,
GError **error)
{
if (!glnx_shutil_mkdir_p_at (dfd, path, mode, cancellable, error))
return FALSE;
if (fchmodat (dfd, path, mode, 0) < 0)
return glnx_throw_errno_prefix (error, "chmod(%s)", path);
return TRUE;
}
/**
* ostree_sysroot_deployment_unlock:
* @self: Sysroot
@@ -1755,6 +1771,14 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
if (!sepolicy)
return FALSE;
/* we want our /usr overlay to have the same permission bits as the one we'll shadow */
mode_t usr_mode;
{ struct stat stbuf;
if (!glnx_fstatat (deployment_dfd, "usr", &stbuf, 0, error))
return FALSE;
usr_mode = stbuf.st_mode;
}
const char *ovl_options = NULL;
static const char hotfix_ovl_options[] = "lowerdir=usr,upperdir=.usr-ovl-upper,workdir=.usr-ovl-work";
switch (unlocked_state)
@@ -1768,9 +1792,9 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
* directly for hotfixes. The ostree-prepare-root.c helper
* is also set up to detect and mount these.
*/
if (!glnx_shutil_mkdir_p_at (deployment_dfd, ".usr-ovl-upper", 0755, cancellable, error))
if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-upper", usr_mode, cancellable, error))
return FALSE;
if (!glnx_shutil_mkdir_p_at (deployment_dfd, ".usr-ovl-work", 0755, cancellable, error))
if (!mkdir_unmasked (deployment_dfd, ".usr-ovl-work", usr_mode, cancellable, error))
return FALSE;
ovl_options = hotfix_ovl_options;
}
@@ -1788,7 +1812,7 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
{ g_auto(OstreeSepolicyFsCreatecon) con = { 0, };
if (!_ostree_sepolicy_preparefscreatecon (&con, sepolicy,
"/usr", 0755, error))
"/usr", usr_mode, error))
return FALSE;
if (g_mkdtemp_full (development_ovldir, 0755) == NULL)
@@ -1796,10 +1820,10 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,
}
development_ovl_upper = glnx_strjoina (development_ovldir, "/upper");
if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_upper, 0755, cancellable, error))
if (!mkdir_unmasked (AT_FDCWD, development_ovl_upper, usr_mode, cancellable, error))
return FALSE;
development_ovl_work = glnx_strjoina (development_ovldir, "/work");
if (!glnx_shutil_mkdir_p_at (AT_FDCWD, development_ovl_work, 0755, cancellable, error))
if (!mkdir_unmasked (AT_FDCWD, development_ovl_work, usr_mode, cancellable, error))
return FALSE;
ovl_options = glnx_strjoina ("lowerdir=usr,upperdir=", development_ovl_upper,
",workdir=", development_ovl_work);
+3 -3
View File
@@ -43,7 +43,7 @@
*
* Since: 2017.4
*/
#define OSTREE_RELEASE_VERSION (1)
#define OSTREE_RELEASE_VERSION (2)
/**
* OSTREE_VERSION
@@ -52,7 +52,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION (2019.1)
#define OSTREE_VERSION (2019.2)
/**
* OSTREE_VERSION_S:
@@ -62,7 +62,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION_S "2019.1"
#define OSTREE_VERSION_S "2019.2"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))
+47 -12
View File
@@ -101,20 +101,55 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile,
return ret;
}
/* Read the value of key as a string. If the value string contains
* one of the separators and none of the others, read the
* string as a NULL-terminated array out_value. If the value string contains
* none of the separators, read the string as a single entry into a
* NULL-terminated array out_value. If the value string contains multiple of
* the separators, an error is given.
gboolean
ot_keyfile_get_value_with_default_group_optional (GKeyFile *keyfile,
const char *section,
const char *value,
const char *default_value,
char **out_value,
GError **error)
{
gboolean ret = FALSE;
GError *local_error = NULL;
g_autofree char *ret_value = NULL;
g_return_val_if_fail (keyfile != NULL, ret);
g_return_val_if_fail (section != NULL, ret);
g_return_val_if_fail (value != NULL, ret);
if (!ot_keyfile_get_value_with_default (keyfile, section, value, default_value, &ret_value, &local_error))
{
if (g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
{
g_clear_error (&local_error);
ret_value = g_strdup (default_value);
}
else
{
g_propagate_error (error, local_error);
goto out;
}
}
ret = TRUE;
ot_transfer_out_value(out_value, &ret_value);
out:
return ret;
}
/* Read the value of key as a string. If the value string contains
* zero or one of the separators and none of the others, read the
* string as a NULL-terminated array out_value. If the value string
* contains multiple of the separators, give an error.
*
* Returns TRUE on success, FALSE on error. */
gboolean
ot_keyfile_get_string_as_list (GKeyFile *keyfile,
const char *section,
const char *key,
const char *separators,
char ***out_value,
GError **error)
ot_keyfile_get_string_list_with_separator_choice (GKeyFile *keyfile,
const char *section,
const char *key,
const char *separators,
char ***out_value,
GError **error)
{
guint sep_count = 0;
gchar sep = '\0';
+14 -6
View File
@@ -45,12 +45,20 @@ ot_keyfile_get_value_with_default (GKeyFile *keyfile,
GError **error);
gboolean
ot_keyfile_get_string_as_list (GKeyFile *keyfile,
const char *section,
const char *key,
const char *separators,
char ***out_value_list,
GError **error);
ot_keyfile_get_value_with_default_group_optional (GKeyFile *keyfile,
const char *section,
const char *value,
const char *default_value,
char **out_value,
GError **error);
gboolean
ot_keyfile_get_string_list_with_separator_choice (GKeyFile *keyfile,
const char *section,
const char *key,
const char *separators,
char ***out_value_list,
GError **error);
gboolean
ot_keyfile_get_string_list_with_default (GKeyFile *keyfile,
+8
View File
@@ -44,6 +44,14 @@
} \
} G_STMT_END;
#ifdef HAVE_LIBSYSTEMD
#define ot_journal_send(...) sd_journal_send(__VA_ARGS__)
#define ot_journal_print(...) sd_journal_print(__VA_ARGS__)
#else
#define ot_journal_send(...) {}
#define ot_journal_print(...) {}
#endif
#include <ot-keyfile-utils.h>
#include <ot-gio-utils.h>
#include <ot-fs-utils.h>
+67 -19
View File
@@ -65,27 +65,38 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(OstreeRepo) repo = NULL;
gboolean ret = FALSE;
const char *op;
const char *section_key;
const char *value;
g_autofree char *section = NULL;
g_autofree char *key = NULL;
GKeyFile *config = NULL;
g_autoptr(GKeyFile) config = NULL;
int correct_argc;
context = g_option_context_new ("(get KEY|set KEY VALUE)");
context = g_option_context_new ("(get KEY|set KEY VALUE|unset KEY)");
if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (argc < 2)
{
ot_util_usage_error (context, "OPERATION must be specified", error);
goto out;
return FALSE;
}
op = argv[1];
if (!strcmp (op, "set"))
correct_argc = 4;
else
correct_argc = 3;
if (argc > correct_argc)
{
ot_util_usage_error (context, "Too many arguments given", error);
return FALSE;
}
if (!strcmp (op, "set"))
{
if (opt_group)
@@ -94,7 +105,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"GROUP name, KEY and VALUE must be specified");
goto out;
return FALSE;
}
section = g_strdup(opt_group);
key = g_strdup(argv[2]);
@@ -106,19 +117,19 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"KEY and VALUE must be specified");
goto out;
return FALSE;
}
section_key = argv[2];
value = argv[3];
if(!split_key_string (section_key, &section, &key, error))
goto out;
return FALSE;
}
config = ostree_repo_copy_config (repo);
g_key_file_set_string (config, section, key, value);
if (!ostree_repo_write_config (repo, config, error))
goto out;
return FALSE;
}
else if (!strcmp (op, "get"))
{
@@ -130,7 +141,7 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Group name and key must be specified");
goto out;
return FALSE;
}
section = g_strdup(opt_group);
key = g_strdup(argv[2]);
@@ -141,30 +152,67 @@ ostree_builtin_config (int argc, char **argv, OstreeCommandInvocation *invocatio
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"KEY must be specified");
goto out;
return FALSE;
}
section_key = argv[2];
if (!split_key_string (section_key, &section, &key, error))
goto out;
return FALSE;
}
readonly_config = ostree_repo_get_config (repo);
value = g_key_file_get_string (readonly_config, section, key, error);
if (value == NULL)
goto out;
return FALSE;
g_print ("%s\n", value);
}
else if (!strcmp (op, "unset"))
{
g_autoptr(GError) local_error = NULL;
if (opt_group)
{
if (argc < 3)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Group name and key must be specified");
return FALSE;
}
section = g_strdup(opt_group);
key = g_strdup(argv[2]);
}
else
{
if (argc < 3)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"KEY must be specified");
return FALSE;
}
section_key = argv[2];
if (!split_key_string (section_key, &section, &key, error))
return FALSE;
}
config = ostree_repo_copy_config (repo);
if (!g_key_file_remove_key (config, section, key, &local_error))
{
if (!g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND) &&
!g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
if (local_error == NULL && !ostree_repo_write_config (repo, config, error))
return FALSE;
}
else
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unknown operation %s", op);
goto out;
return FALSE;
}
ret = TRUE;
out:
if (config)
g_key_file_free (config);
return ret;
return TRUE;
}
+18 -3
View File
@@ -30,6 +30,7 @@
static char **opt_set;
static gboolean opt_no_gpg_verify;
static gboolean opt_if_not_exists;
static gboolean opt_force;
static char *opt_gpg_import;
static char *opt_contenturl;
static char *opt_collection_id;
@@ -45,6 +46,7 @@ static GOptionEntry option_entries[] = {
{ "set", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, "Set config option KEY=VALUE for remote", "KEY=VALUE" },
{ "no-gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_gpg_verify, "Disable GPG verification", NULL },
{ "if-not-exists", 0, 0, G_OPTION_ARG_NONE, &opt_if_not_exists, "Do nothing if the provided remote exists", NULL },
{ "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, "Replace the provided remote if it exists", NULL },
{ "gpg-import", 0, 0, G_OPTION_ARG_FILENAME, &opt_gpg_import, "Import GPG key from FILE", "FILE" },
{ "contenturl", 0, 0, G_OPTION_ARG_STRING, &opt_contenturl, "Use URL when fetching content", "URL" },
{ "collection-id", 0, 0, G_OPTION_ARG_STRING, &opt_collection_id,
@@ -84,6 +86,14 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio
goto out;
}
if (opt_if_not_exists && opt_force)
{
ot_util_usage_error (context,
"Can only specify one of --if-not-exists and --force",
error);
goto out;
}
remote_name = argv[1];
remote_url = argv[2];
@@ -135,9 +145,14 @@ ot_remote_builtin_add (int argc, char **argv, OstreeCommandInvocation *invocatio
options = g_variant_ref_sink (g_variant_builder_end (optbuilder));
if (!ostree_repo_remote_change (repo, NULL,
opt_if_not_exists ? OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS :
OSTREE_REPO_REMOTE_CHANGE_ADD,
OstreeRepoRemoteChange changeop;
if (opt_if_not_exists)
changeop = OSTREE_REPO_REMOTE_CHANGE_ADD_IF_NOT_EXISTS;
else if (opt_force)
changeop = OSTREE_REPO_REMOTE_CHANGE_REPLACE;
else
changeop = OSTREE_REPO_REMOTE_CHANGE_ADD;
if (!ostree_repo_remote_change (repo, NULL, changeop,
remote_name, remote_url,
options,
cancellable, error))
+21 -2
View File
@@ -47,6 +47,15 @@
#include <errno.h>
#include <ctype.h>
#if defined(HAVE_LIBSYSTEMD) && !defined(OSTREE_PREPARE_ROOT_STATIC)
#define USE_LIBSYSTEMD
#endif
#ifdef USE_LIBSYSTEMD
#include <systemd/sd-journal.h>
#define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG SD_ID128_MAKE(71,70,33,6a,73,ba,46,01,ba,d3,1a,f8,88,aa,0d,f7)
#endif
#include "ostree-mount-util.h"
/* Initialized early in main */
@@ -71,9 +80,19 @@ resolve_deploy_path (const char * root_mountpoint)
deploy_path = realpath (destpath, NULL);
if (deploy_path == NULL)
err (EXIT_FAILURE, "realpath(%s) failed", destpath);
if (stat (deploy_path, &stbuf) < 0)
err (EXIT_FAILURE, "stat(%s) failed", deploy_path);
/* Quiet logs if there's no journal */
if (!running_as_pid1)
printf ("Resolved OSTree target to: %s\n", deploy_path);
#ifdef USE_LIBSYSTEMD
const char *resolved_path = deploy_path + strlen (root_mountpoint);
sd_journal_send ("MESSAGE=Resolved OSTree target to: %s", deploy_path,
"MESSAGE_ID=" SD_ID128_FORMAT_STR,
SD_ID128_FORMAT_VAL(OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG),
"DEPLOYMENT_PATH=%s", resolved_path,
"DEPLOYMENT_DEVICE=%u", stbuf.st_dev,
"DEPLOYMENT_INODE=%u", stbuf.st_ino,
NULL);
#endif
return deploy_path;
}