From 87851c7bbe246ec630851f577a77435cbfd5217b Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 10 Jun 2015 15:40:42 -0400 Subject: [PATCH] metalink: Return requested file as a GBytes This may not be the best idea for general usage, but the only use case for metalinks currently is fetching a summary file and those are pretty small. Far more convenient to return the file content in a GBytes. --- src/libostree/ostree-metalink.c | 85 +++++++++++++++----------------- src/libostree/ostree-metalink.h | 2 +- src/libostree/ostree-repo-pull.c | 17 ++----- 3 files changed, 44 insertions(+), 60 deletions(-) diff --git a/src/libostree/ostree-metalink.c b/src/libostree/ostree-metalink.c index 56bd12f1..4d742414 100644 --- a/src/libostree/ostree-metalink.c +++ b/src/libostree/ostree-metalink.c @@ -72,7 +72,7 @@ typedef struct char *verification_sha256; char *verification_sha512; - char *result; + GBytes *result; char *last_metalink_error; guint current_url_index; @@ -431,48 +431,51 @@ on_fetched_url (GObject *src, gpointer user_data) { GTask *task = user_data; + GCancellable *cancellable; OstreeMetalinkRequest *self = g_task_get_task_data (task); GError *local_error = NULL; - struct stat stbuf; int parent_dfd = _ostree_fetcher_get_dfd (self->metalink->fetcher); g_autoptr(GInputStream) instream = NULL; - g_autofree char *result = NULL; - GChecksum *checksum = NULL; + g_autoptr(GOutputStream) outstream = NULL; + g_autoptr(GBytes) bytes = NULL; + g_autofree char *path = NULL; + gssize n_bytes; - result = _ostree_fetcher_request_uri_with_partial_finish ((OstreeFetcher*)src, res, &local_error); - if (!result) + path = _ostree_fetcher_request_uri_with_partial_finish ((OstreeFetcher*)src, res, &local_error); + if (!path) goto out; - if (!ot_openat_read_stream (parent_dfd, result, FALSE, - &instream, NULL, &local_error)) - goto out; - - if (fstat (g_file_descriptor_based_get_fd ((GFileDescriptorBased*)instream), &stbuf) != 0) - { - gs_set_error_from_errno (&local_error, errno); - goto out; - } + cancellable = g_task_get_cancellable (task); - if (stbuf.st_size != self->size) + if (!ot_openat_read_stream (parent_dfd, path, FALSE, &instream, + cancellable, &local_error)) + goto out; + + outstream = g_memory_output_stream_new_resizable (); + + n_bytes = g_output_stream_splice (outstream, instream, + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + cancellable, &local_error); + + if (n_bytes < 0) + goto out; + + bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (outstream)); + + if (n_bytes != self->size) { g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Expected size is %" G_GUINT64_FORMAT " bytes but content is %" G_GUINT64_FORMAT " bytes", - self->size, stbuf.st_size); + "Expected size is %" G_GUINT64_FORMAT " bytes but content is %" G_GSSIZE_FORMAT " bytes", + self->size, n_bytes); goto out; } - + if (self->verification_sha512) { - const char *actual; + g_autofree char *actual = NULL; - checksum = g_checksum_new (G_CHECKSUM_SHA512); - - if (!ot_gio_splice_update_checksum (NULL, instream, checksum, - g_task_get_cancellable (task), - &local_error)) - goto out; - - actual = g_checksum_get_string (checksum); + actual = g_compute_checksum_for_bytes (G_CHECKSUM_SHA512, bytes); if (strcmp (self->verification_sha512, actual) != 0) { @@ -484,16 +487,9 @@ on_fetched_url (GObject *src, } else if (self->verification_sha256) { - const char *actual; + g_autofree char *actual = NULL; - checksum = g_checksum_new (G_CHECKSUM_SHA256); - - if (!ot_gio_splice_update_checksum (NULL, instream, checksum, - g_task_get_cancellable (task), - &local_error)) - goto out; - - actual = g_checksum_get_string (checksum); + actual = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, bytes); if (strcmp (self->verification_sha256, actual) != 0) { @@ -505,8 +501,6 @@ on_fetched_url (GObject *src, } out: - if (checksum) - g_checksum_free (checksum); if (local_error) { g_free (self->last_metalink_error); @@ -519,8 +513,7 @@ on_fetched_url (GObject *src, } else { - self->result = result; - result = NULL; /* Transfer ownership */ + self->result = g_bytes_ref (bytes); g_task_return_boolean (self->task, TRUE); } } @@ -609,7 +602,7 @@ ostree_metalink_request_unref (gpointer data) { OstreeMetalinkRequest *request = data; g_object_unref (request->metalink); - g_free (request->result); + g_clear_pointer (&request->result, g_bytes_unref); g_free (request->last_metalink_error); g_ptr_array_unref (request->urls); g_free (request); @@ -626,7 +619,7 @@ static const GMarkupParser metalink_parser = { typedef struct { SoupURI **out_target_uri; - char **out_data; + GBytes **out_data; gboolean success; GError **error; GMainLoop *loop; @@ -636,7 +629,7 @@ static gboolean ostree_metalink_request_finish (OstreeMetalink *self, GAsyncResult *result, SoupURI **out_target_uri, - char **out_data, + GBytes **out_data, GError **error) { OstreeMetalinkRequest *request; @@ -651,7 +644,7 @@ ostree_metalink_request_finish (OstreeMetalink *self, if (out_target_uri != NULL) *out_target_uri = request->urls->pdata[request->current_url_index]; if (out_data != NULL) - *out_data = g_strdup (request->result); + *out_data = g_bytes_ref (request->result); return TRUE; } else @@ -695,7 +688,7 @@ gboolean _ostree_metalink_request_sync (OstreeMetalink *self, GMainLoop *loop, SoupURI **out_target_uri, - char **out_data, + GBytes **out_data, SoupURI **fetching_sync_uri, GCancellable *cancellable, GError **error) diff --git a/src/libostree/ostree-metalink.h b/src/libostree/ostree-metalink.h index ad3cf2b9..ae80c8f1 100644 --- a/src/libostree/ostree-metalink.h +++ b/src/libostree/ostree-metalink.h @@ -53,7 +53,7 @@ SoupURI *_ostree_metalink_get_uri (OstreeMetalink *self); gboolean _ostree_metalink_request_sync (OstreeMetalink *self, GMainLoop *loop, SoupURI **out_target_uri, - char **out_data, + GBytes **out_data, SoupURI **fetching_sync_uri, GCancellable *cancellable, GError **error); diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index 11e32a3c..78e4855c 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -1709,10 +1709,9 @@ ostree_repo_pull_with_options (OstreeRepo *self, } else { - g_autofree char *metalink_data = NULL; + g_autoptr(GBytes) summary_bytes = NULL; SoupURI *metalink_uri = soup_uri_new (metalink_url_str); SoupURI *target_uri = NULL; - gs_fd_close int fd = -1; if (!metalink_uri) { @@ -1728,7 +1727,7 @@ ostree_repo_pull_with_options (OstreeRepo *self, if (! _ostree_metalink_request_sync (metalink, pull_data->loop, &target_uri, - &metalink_data, + &summary_bytes, &pull_data->fetching_sync_uri, cancellable, error)) @@ -1740,16 +1739,8 @@ ostree_repo_pull_with_options (OstreeRepo *self, soup_uri_set_path (pull_data->base_uri, repo_base); } - fd = openat (pull_data->tmpdir_dfd, metalink_data, O_RDONLY | O_CLOEXEC); - if (fd == -1) - { - gs_set_error_from_errno (error, errno); - goto out; - } - - if (!ot_util_variant_map_fd (fd, 0, OSTREE_SUMMARY_GVARIANT_FORMAT, FALSE, - &pull_data->summary, error)) - goto out; + pull_data->summary = g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, + summary_bytes, FALSE); } if (!_ostree_repo_get_remote_list_option (self,