diff --git a/builder/builder-source-archive.c b/builder/builder-source-archive.c index 47d02c530..4b7afe5a7 100644 --- a/builder/builder-source-archive.c +++ b/builder/builder-source-archive.c @@ -265,39 +265,6 @@ get_source_file (BuilderSourceArchive *self, return NULL; } -static GBytes * -download_uri (const char *url, - GChecksum *checksum, - BuilderContext *context, - GError **error) -{ - SoupSession *session; - - g_autoptr(SoupRequest) req = NULL; - g_autoptr(GInputStream) input = NULL; - g_autoptr(GOutputStream) out = NULL; - - session = builder_context_get_soup_session (context); - - req = soup_session_request (session, url, error); - if (req == NULL) - return NULL; - - input = soup_request_send (req, NULL, error); - if (input == NULL) - return NULL; - - out = g_memory_output_stream_new_resizable (); - if (!flatpak_splice_update_checksum (out, input, checksum, NULL, error)) - return NULL; - - /* Manually close to flush and detect write errors */ - if (!g_output_stream_close (out, NULL, error)) - return NULL; - - return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (out)); -} - static gboolean builder_source_archive_show_deps (BuilderSource *source, GError **error) @@ -310,7 +277,6 @@ builder_source_archive_show_deps (BuilderSource *source, return TRUE; } - static gboolean builder_source_archive_download (BuilderSource *source, gboolean update_vcs, @@ -325,7 +291,6 @@ builder_source_archive_download (BuilderSource *source, const char *sha256 = NULL; g_autofree char *base_name = NULL; g_autoptr(GBytes) content = NULL; - g_autoptr(GChecksum) checksum = NULL; gboolean is_local; file = get_source_file (self, context, &is_local, error); @@ -361,35 +326,12 @@ builder_source_archive_download (BuilderSource *source, return FALSE; } - checksum = g_checksum_new (G_CHECKSUM_SHA256); - g_print ("Downloading %s\n", self->url); - content = download_uri (self->url, - checksum, - context, - error); - if (content == NULL) - return FALSE; - - base_name = g_file_get_basename (file); - - sha256 = g_checksum_get_string (checksum); - if (strcmp (sha256, self->sha256) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256); - return FALSE; - } - - dir = g_file_get_parent (file); - dir_path = g_file_get_path (dir); - g_mkdir_with_parents (dir_path, 0755); - - if (!g_file_replace_contents (file, - g_bytes_get_data (content, NULL), - g_bytes_get_size (content), - NULL, FALSE, G_FILE_CREATE_NONE, NULL, - NULL, error)) + if (!builder_download_uri (self->url, + file, + self->sha256, + builder_context_get_soup_session (context), + error)) return FALSE; return TRUE; diff --git a/builder/builder-source-file.c b/builder/builder-source-file.c index d7d9b1de8..26799b8b6 100644 --- a/builder/builder-source-file.c +++ b/builder/builder-source-file.c @@ -318,34 +318,17 @@ builder_source_file_download (BuilderSource *source, return FALSE; } - content = download_uri (self->url, - context, - error); - if (content == NULL) - return FALSE; - - sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, - g_bytes_get_data (content, NULL), - g_bytes_get_size (content)); - - /* sha256 is optional for inline data */ - if (((self->sha256 != NULL && *self->sha256 != 0) || !is_inline) && - strcmp (sha256, self->sha256) != 0) + if ((self->sha256 == NULL || *self->sha256 == 0) && !is_inline) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified"); return FALSE; } - dir = g_file_get_parent (file); - dir_path = g_file_get_path (dir); - g_mkdir_with_parents (dir_path, 0755); - - if (!g_file_replace_contents (file, - g_bytes_get_data (content, NULL), - g_bytes_get_size (content), - NULL, FALSE, G_FILE_CREATE_NONE, NULL, - NULL, error)) + if (!builder_download_uri (self->url, + file, + self->sha256, + builder_context_get_soup_session (context), + error)) return FALSE; return TRUE; diff --git a/builder/builder-utils.c b/builder/builder-utils.c index 4fef37d49..d22c3767a 100644 --- a/builder/builder-utils.c +++ b/builder/builder-utils.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -1598,3 +1599,70 @@ builder_maybe_host_spawnv (GFile *dir, return flatpak_spawnv (dir, output, error, argv); } + +gboolean +builder_download_uri (const char *url, + GFile *dest, + char *sha256, + SoupSession *session, + GError **error) +{ + g_autoptr(SoupRequest) req = NULL; + g_autoptr(GInputStream) input = NULL; + g_autoptr(GFileOutputStream) out = NULL; + g_autoptr(GFile) tmp = NULL; + g_autoptr(GFile) dir = NULL; + g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256); + + g_autofree char *basename = g_file_get_basename (dest); + g_autofree char *template = g_strconcat (".", basename, "XXXXXX", NULL); + + dir = g_file_get_parent (dest); + g_mkdir_with_parents (flatpak_file_get_path_cached (dir), 0755); + + tmp = flatpak_file_new_tmp_in (dir, template, error); + if (tmp == NULL) + return FALSE; + + out = g_file_replace (tmp, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, + NULL, error); + if (out == NULL) + return FALSE; + + req = soup_session_request (session, url, error); + if (req == NULL) + return FALSE; + + input = soup_request_send (req, NULL, error); + if (input == NULL) + return FALSE; + + if (!flatpak_splice_update_checksum (G_OUTPUT_STREAM (out), input, checksum, NULL, error)) + { + unlink (flatpak_file_get_path_cached (tmp)); + return FALSE; + } + + /* Manually close to flush and detect write errors */ + if (!g_output_stream_close (G_OUTPUT_STREAM (out), NULL, error)) + { + unlink (flatpak_file_get_path_cached (tmp)); + return FALSE; + } + + if (sha256 != NULL && strcmp (g_checksum_get_string (checksum), sha256) != 0) + { + unlink (flatpak_file_get_path_cached (tmp)); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Wrong sha256 for %s, expected %s, was %s", basename, sha256, g_checksum_get_string (checksum)); + return FALSE; + } + + if (rename (flatpak_file_get_path_cached (tmp), flatpak_file_get_path_cached (dest)) != 0) + { + glnx_set_error_from_errno (error); + return FALSE; + } + + return TRUE; +} diff --git a/builder/builder-utils.h b/builder/builder-utils.h index 77120657e..6cf00944e 100644 --- a/builder/builder-utils.h +++ b/builder/builder-utils.h @@ -62,6 +62,11 @@ gboolean builder_maybe_host_spawnv (GFile *dir, GError **error, const gchar * const *argv); +gboolean builder_download_uri (const char *url, + GFile *dest, + char *sha256, + SoupSession *soup_session, + GError **error); G_END_DECLS diff --git a/common/flatpak-utils.c b/common/flatpak-utils.c index 5dd0f4bde..adc68b99e 100644 --- a/common/flatpak-utils.c +++ b/common/flatpak-utils.c @@ -74,6 +74,24 @@ flatpak_error_quark (void) return (GQuark) quark_volatile; } +GFile * +flatpak_file_new_tmp_in (GFile *dir, + const char *template, + GError **error) +{ + glnx_fd_close int tmp_fd = -1; + g_autofree char *tmpl = g_build_filename (flatpak_file_get_path_cached (dir), template, NULL); + + tmp_fd = g_mkstemp_full (tmpl, O_RDWR, 0644); + if (tmp_fd == -1) + { + glnx_set_error_from_errno (error); + return NULL; + } + + return g_file_new_for_path (tmpl); +} + gboolean flatpak_write_update_checksum (GOutputStream *out, gconstpointer data, diff --git a/common/flatpak-utils.h b/common/flatpak-utils.h index e5b9f6b39..53aa6c31d 100644 --- a/common/flatpak-utils.h +++ b/common/flatpak-utils.h @@ -75,6 +75,10 @@ char ** flatpak_get_current_locale_subpaths (void); void flatpak_migrate_from_xdg_app (void); +GFile *flatpak_file_new_tmp_in (GFile *dir, + const char *templatename, + GError **error); + gboolean flatpak_write_update_checksum (GOutputStream *out, gconstpointer data, gsize len,