common: Move xdg_app_dir_pull_from_bundle to xdg_app_pull_from_bundle

The only difference is it takes an OstreeRepo, not a XdgAppDir, so we
can use it at a lower level too.
tingping/wmclass
Alexander Larsson 2016-04-19 13:31:55 +02:00
parent 18bb0868e9
commit 1c1bc4acca
6 changed files with 133 additions and 130 deletions

View File

@ -171,13 +171,16 @@ install_bundle (XdgAppDir *dir,
/* From here we need to goto out on error, to clean up */
added_remote = TRUE;
if (!xdg_app_dir_pull_from_bundle (dir,
file,
remote,
ref,
gpg_data != NULL,
cancellable,
error))
if (!xdg_app_dir_ensure_repo (dir, cancellable, error))
goto out;
if (!xdg_app_pull_from_bundle (xdg_app_dir_get_repo (dir),
file,
remote,
ref,
gpg_data != NULL,
cancellable,
error))
goto out;
if (!xdg_app_dir_lock (dir, &lock,

View File

@ -995,115 +995,6 @@ xdg_app_dir_pull (XdgAppDir *self,
return ret;
}
gboolean
xdg_app_dir_pull_from_bundle (XdgAppDir *self,
GFile *file,
const char *remote,
const char *ref,
gboolean require_gpg_signature,
GCancellable *cancellable,
GError **error)
{
g_autofree char *metadata_contents = NULL;
g_autofree char *to_checksum = NULL;
g_autoptr(GFile) root = NULL;
g_autoptr(GFile) metadata_file = NULL;
g_autoptr(GInputStream) in = NULL;
g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL;
g_autoptr(GError) my_error = NULL;
g_autoptr(GVariant) metadata = NULL;
gboolean metadata_valid;
if (!xdg_app_dir_ensure_repo (self, cancellable, error))
return FALSE;
if (!xdg_app_supports_bundles (self->repo))
return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles");
metadata = xdg_app_bundle_load (file, &to_checksum, NULL, NULL, NULL, NULL, error);
if (metadata == NULL)
return FALSE;
g_variant_lookup (metadata, "metadata", "s", &metadata_contents);
if (!ostree_repo_prepare_transaction (self->repo, NULL, cancellable, error))
return FALSE;
ostree_repo_transaction_set_ref (self->repo, remote, ref, to_checksum);
if (!ostree_repo_static_delta_execute_offline (self->repo,
file,
FALSE,
cancellable,
error))
return FALSE;
gpg_result = ostree_repo_verify_commit_ext (self->repo, to_checksum,
NULL, NULL, cancellable, &my_error);
if (gpg_result == NULL)
{
/* NOT_FOUND means no gpg signature, we ignore this *if* there
* is no gpg key specified in the bundle or by the user */
if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
!require_gpg_signature)
g_clear_error (&my_error);
else
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
}
else
{
/* If there is no valid gpg signature we fail, unless there is no gpg
key specified (on the command line or in the file) because then we
trust the source bundle. */
if (ostree_gpg_verify_result_count_valid (gpg_result) == 0 &&
require_gpg_signature)
return xdg_app_fail (error, "GPG signatures found, but none are in trusted keyring");
}
if (!ostree_repo_read_commit (self->repo, to_checksum, &root, NULL, NULL, error))
return FALSE;
if (!ostree_repo_commit_transaction (self->repo, NULL, cancellable, error))
return FALSE;
/* We ensure that the actual installed metadata matches the one in the
header, because you may have made decisions on wheter to install it or not
based on that data. */
metadata_file = g_file_resolve_relative_path (root, "metadata");
in = (GInputStream*)g_file_read (metadata_file, cancellable, NULL);
if (in != NULL)
{
g_autoptr(GMemoryOutputStream) data_stream = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
if (g_output_stream_splice (G_OUTPUT_STREAM (data_stream), in,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
cancellable, error) < 0)
return FALSE;
/* Null terminate */
g_output_stream_write (G_OUTPUT_STREAM (data_stream), "\0", 1, NULL, NULL);
metadata_valid =
metadata_contents != NULL &&
strcmp (metadata_contents, g_memory_output_stream_get_data (data_stream)) == 0;
}
else
metadata_valid = (metadata_contents == NULL);
if (!metadata_valid)
{
/* Immediately remove this broken commit */
ostree_repo_set_ref_immediate (self->repo, remote, ref, NULL, cancellable, error);
return xdg_app_fail (error, "Metadata in header and app are inconsistent");
}
return TRUE;
}
char *
xdg_app_dir_current_ref (XdgAppDir *self,
const char *name,

View File

@ -157,13 +157,6 @@ gboolean xdg_app_dir_pull (XdgAppDir *self,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
gboolean xdg_app_dir_pull_from_bundle (XdgAppDir *self,
GFile *file,
const char *remote,
const char *ref,
gboolean require_gpg_signature,
GCancellable *cancellable,
GError **error);
gboolean xdg_app_dir_list_refs_for_name (XdgAppDir *self,
const char *kind,
const char *name,

View File

@ -2673,3 +2673,108 @@ xdg_app_bundle_load (GFile *file,
g_variant_get_size (metadata)),
FALSE);
}
gboolean
xdg_app_pull_from_bundle (OstreeRepo *repo,
GFile *file,
const char *remote,
const char *ref,
gboolean require_gpg_signature,
GCancellable *cancellable,
GError **error)
{
g_autofree char *metadata_contents = NULL;
g_autofree char *to_checksum = NULL;
g_autoptr(GFile) root = NULL;
g_autoptr(GFile) metadata_file = NULL;
g_autoptr(GInputStream) in = NULL;
g_autoptr(OstreeGpgVerifyResult) gpg_result = NULL;
g_autoptr(GError) my_error = NULL;
g_autoptr(GVariant) metadata = NULL;
gboolean metadata_valid;
if (!xdg_app_supports_bundles (repo))
return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles");
metadata = xdg_app_bundle_load (file, &to_checksum, NULL, NULL, NULL, NULL, error);
if (metadata == NULL)
return FALSE;
g_variant_lookup (metadata, "metadata", "s", &metadata_contents);
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
return FALSE;
ostree_repo_transaction_set_ref (repo, remote, ref, to_checksum);
if (!ostree_repo_static_delta_execute_offline (repo,
file,
FALSE,
cancellable,
error))
return FALSE;
gpg_result = ostree_repo_verify_commit_ext (repo, to_checksum,
NULL, NULL, cancellable, &my_error);
if (gpg_result == NULL)
{
/* NOT_FOUND means no gpg signature, we ignore this *if* there
* is no gpg key specified in the bundle or by the user */
if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) &&
!require_gpg_signature)
g_clear_error (&my_error);
else
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
}
else
{
/* If there is no valid gpg signature we fail, unless there is no gpg
key specified (on the command line or in the file) because then we
trust the source bundle. */
if (ostree_gpg_verify_result_count_valid (gpg_result) == 0 &&
require_gpg_signature)
return xdg_app_fail (error, "GPG signatures found, but none are in trusted keyring");
}
if (!ostree_repo_read_commit (repo, to_checksum, &root, NULL, NULL, error))
return FALSE;
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))
return FALSE;
/* We ensure that the actual installed metadata matches the one in the
header, because you may have made decisions on wheter to install it or not
based on that data. */
metadata_file = g_file_resolve_relative_path (root, "metadata");
in = (GInputStream*)g_file_read (metadata_file, cancellable, NULL);
if (in != NULL)
{
g_autoptr(GMemoryOutputStream) data_stream = (GMemoryOutputStream*)g_memory_output_stream_new_resizable ();
if (g_output_stream_splice (G_OUTPUT_STREAM (data_stream), in,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
cancellable, error) < 0)
return FALSE;
/* Null terminate */
g_output_stream_write (G_OUTPUT_STREAM (data_stream), "\0", 1, NULL, NULL);
metadata_valid =
metadata_contents != NULL &&
strcmp (metadata_contents, g_memory_output_stream_get_data (data_stream)) == 0;
}
else
metadata_valid = (metadata_contents == NULL);
if (!metadata_valid)
{
/* Immediately remove this broken commit */
ostree_repo_set_ref_immediate (repo, remote, ref, NULL, cancellable, error);
return xdg_app_fail (error, "Metadata in header and app are inconsistent");
}
return TRUE;
}

View File

@ -191,6 +191,14 @@ GVariant * xdg_app_bundle_load (GFile *file,
GBytes **gpg_keys,
GError **error);
gboolean xdg_app_pull_from_bundle (OstreeRepo *repo,
GFile *file,
const char *remote,
const char *ref,
gboolean require_gpg_signature,
GCancellable *cancellable,
GError **error);
typedef struct {
char *id;

View File

@ -868,13 +868,16 @@ xdg_app_installation_install_bundle (XdgAppInstallation *self,
/* Pull, prune, etc are not threadsafe, so we work on a copy */
dir_clone = xdg_app_dir_clone (priv->dir);
if (!xdg_app_dir_pull_from_bundle (dir_clone,
file,
remote,
ref,
gpg_data != NULL,
cancellable,
error))
if (!xdg_app_dir_ensure_repo (dir_clone, cancellable, error))
goto out;
if (!xdg_app_pull_from_bundle (xdg_app_dir_get_repo (dir_clone),
file,
remote,
ref,
gpg_data != NULL,
cancellable,
error))
goto out;
if (!xdg_app_dir_lock (dir_clone, &lock,