New upstream version 2019.2
This commit is contained in:
commit
bd32d1e5de
79 files changed
+2910
-1852
No files matched your search
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
*/
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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, §ion, &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, §ion, &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, §ion, &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;
|
||||
}
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user