[ostree] lib: Create an internal static delta parsing/opening function
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] lib: Create an internal static delta parsing/opening function
- Date: Mon, 8 Feb 2016 13:46:48 +0000 (UTC)
commit 56fc249d08d784ec481b71f2b13e2dbe509b0d9a
Author: Colin Walters <walters verbum org>
Date: Sat Feb 6 13:56:19 2016 +0100
lib: Create an internal static delta parsing/opening function
We had code to deal with opening/checksumming/decompressing static
deltas in a few places. I'd like to teach `ostree static-delta show`
how to display more information, and this will allow it to just use
`_ostree_static_delta_part_open()` too.
src/libostree/ostree-repo-pull.c | 117 ++++------
src/libostree/ostree-repo-static-delta-core.c | 238 +++++++++++++++++---
src/libostree/ostree-repo-static-delta-private.h | 33 ++--
.../ostree-repo-static-delta-processing.c | 141 +-----------
4 files changed, 278 insertions(+), 251 deletions(-)
---
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 6e6f0cd..750c68f 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -935,8 +935,7 @@ static_deltapart_fetch_on_complete (GObject *object,
g_autoptr(GVariant) metadata = NULL;
g_autofree char *temp_path = NULL;
g_autoptr(GInputStream) in = NULL;
- g_autofree char *actual_checksum = NULL;
- g_autofree guint8 *csum = NULL;
+ g_autoptr(GVariant) part = NULL;
GError *local_error = NULL;
GError **error = &local_error;
gs_fd_close int fd = -1;
@@ -950,54 +949,33 @@ static_deltapart_fetch_on_complete (GObject *object,
fd = openat (_ostree_fetcher_get_dfd (fetcher), temp_path, O_RDONLY | O_CLOEXEC);
if (fd == -1)
{
- gs_set_error_from_errno (error, errno);
+ glnx_set_error_from_errno (error);
goto out;
}
- in = g_unix_input_stream_new (fd, FALSE);
-
- /* TODO - consider making async */
- if (!ot_gio_checksum_stream (in, &csum, pull_data->cancellable, error))
- goto out;
-
- actual_checksum = ostree_checksum_from_bytes (csum);
- if (strcmp (actual_checksum, fetch_data->expected_checksum) != 0)
+ /* From here on, if we fail to apply the delta, we'll re-fetch it */
+ if (unlinkat (_ostree_fetcher_get_dfd (fetcher), temp_path, 0) < 0)
{
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted static delta part; checksum expected='%s' actual='%s'",
- fetch_data->expected_checksum, actual_checksum);
+ glnx_set_error_from_errno (error);
goto out;
}
- /* Might as well close the fd here */
- (void) g_input_stream_close (in, NULL, NULL);
+ in = g_unix_input_stream_new (fd, FALSE);
- {
- GMappedFile *mfile = NULL;
- g_autoptr(GBytes) delta_data = NULL;
+ /* TODO - make async */
+ if (!_ostree_static_delta_part_open (in, NULL, 0, fetch_data->expected_checksum,
+ &part, pull_data->cancellable, error))
+ goto out;
- mfile = g_mapped_file_new_from_fd (fd, FALSE, error);
- if (!mfile)
- goto out;
- delta_data = g_mapped_file_get_bytes (mfile);
- g_mapped_file_unref (mfile);
-
- /* Unlink now while we're holding an open fd, so that on success
- * or error, the file will be gone. This is particularly
- * important if say we hit e.g. ENOSPC.
- */
- (void) unlinkat (_ostree_fetcher_get_dfd (fetcher), temp_path, 0);
-
- _ostree_static_delta_part_execute_async (pull_data->repo,
- fetch_data->objects,
- delta_data,
- /* Trust checksums if summary was gpg signed */
- pull_data->gpg_verify_summary && pull_data->summary_data_sig,
- pull_data->cancellable,
- on_static_delta_written,
- fetch_data);
- pull_data->n_outstanding_deltapart_write_requests++;
- }
+ _ostree_static_delta_part_execute_async (pull_data->repo,
+ fetch_data->objects,
+ part,
+ /* Trust checksums if summary was gpg signed */
+ pull_data->gpg_verify_summary && pull_data->summary_data_sig,
+ pull_data->cancellable,
+ on_static_delta_written,
+ fetch_data);
+ pull_data->n_outstanding_deltapart_write_requests++;
out:
g_assert (pull_data->n_outstanding_deltapart_fetches > 0);
@@ -1604,10 +1582,10 @@ process_one_static_delta (OtPullData *pull_data,
FetchStaticDeltaData *fetch_data;
g_autoptr(GVariant) csum_v = NULL;
g_autoptr(GVariant) objects = NULL;
- g_autoptr(GVariant) part_data = NULL;
- g_autoptr(GBytes) delta_data = NULL;
+ g_autoptr(GBytes) inline_part_bytes = NULL;
guint64 size, usize;
guint32 version;
+ const gboolean trusted = pull_data->gpg_verify_summary && pull_data->summary_data_sig;
header = g_variant_get_child_value (headers, i);
g_variant_get (header, "(u aytt@ay)", &version, &csum_v, &size, &usize, &objects);
@@ -1623,31 +1601,6 @@ process_one_static_delta (OtPullData *pull_data,
if (!csum)
goto out;
- deltapart_path = _ostree_get_relative_static_delta_part_path (from_revision, to_revision, i);
-
- part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE ("(yay)"));
- if (part_data)
- {
- g_autofree char *actual_checksum = NULL;
- g_autofree char *expected_checksum = ostree_checksum_from_bytes_v (csum_v);
-
- delta_data = g_variant_get_data_as_bytes (part_data);
-
- /* For inline parts we are relying on per-commit GPG, so this isn't strictly necessary for
security.
- * See https://github.com/GNOME/ostree/pull/139
- */
- actual_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_SHA256, delta_data);
- if (strcmp (actual_checksum, expected_checksum) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted static delta part; checksum expected='%s' actual='%s'",
- expected_checksum, actual_checksum);
- goto out;
- }
- }
-
- pull_data->total_deltapart_size += size;
-
if (!_ostree_repo_static_delta_part_have_all_objects (pull_data->repo,
objects,
&have_all,
@@ -1663,18 +1616,38 @@ process_one_static_delta (OtPullData *pull_data,
continue;
}
+ deltapart_path = _ostree_get_relative_static_delta_part_path (from_revision, to_revision, i);
+
+ { g_autoptr(GVariant) part_datav =
+ g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE ("(yay)"));
+
+ if (part_datav)
+ inline_part_bytes = g_variant_get_data_as_bytes (part_datav);
+ }
+
+ pull_data->total_deltapart_size += size;
+
fetch_data = g_new0 (FetchStaticDeltaData, 1);
fetch_data->pull_data = pull_data;
fetch_data->objects = g_variant_ref (objects);
fetch_data->expected_checksum = ostree_checksum_from_bytes_v (csum_v);
- if (delta_data != NULL)
+ if (inline_part_bytes != NULL)
{
+ g_autoptr(GInputStream) memin = g_memory_input_stream_new_from_bytes (inline_part_bytes);
+ g_autoptr(GVariant) inline_delta_part = NULL;
+
+ /* For inline parts we are relying on per-commit GPG, so don't bother checksumming. */
+ if (!_ostree_static_delta_part_open (memin, inline_part_bytes,
+ OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM,
+ NULL, &inline_delta_part,
+ cancellable, error))
+ goto out;
+
_ostree_static_delta_part_execute_async (pull_data->repo,
fetch_data->objects,
- delta_data,
- /* Trust checksums if summary was gpg signed */
- pull_data->gpg_verify_summary &&
pull_data->summary_data_sig,
+ inline_delta_part,
+ trusted,
pull_data->cancellable,
on_static_delta_written,
fetch_data);
diff --git a/src/libostree/ostree-repo-static-delta-core.c b/src/libostree/ostree-repo-static-delta-core.c
index bc1b460..e9d5c15 100644
--- a/src/libostree/ostree-repo-static-delta-core.c
+++ b/src/libostree/ostree-repo-static-delta-core.c
@@ -20,9 +20,14 @@
#include "config.h"
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+#include <gio/gfiledescriptorbased.h>
#include "ostree-core-private.h"
#include "ostree-repo-private.h"
+#include "ostree-lzma-decompressor.h"
#include "ostree-cmdprivate.h"
+#include "ostree-checksum-input-stream.h"
#include "ostree-repo-static-delta-private.h"
#include "otutil.h"
@@ -226,31 +231,45 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
{
gboolean ret = FALSE;
guint i, n;
- g_autoptr(GFile) meta_file = NULL;
- g_autoptr(GFile) dir = NULL;
+ const char *dir_or_file_path = NULL;
+ glnx_fd_close int meta_fd = -1;
+ glnx_fd_close int dfd = -1;
g_autoptr(GVariant) meta = NULL;
g_autoptr(GVariant) headers = NULL;
g_autoptr(GVariant) metadata = NULL;
g_autoptr(GVariant) fallback = NULL;
g_autofree char *to_checksum = NULL;
g_autofree char *from_checksum = NULL;
- GFileType file_type;
+ dir_or_file_path = gs_file_get_path_cached (dir_or_file);
- file_type = g_file_query_file_type (dir_or_file, 0, cancellable);
- if (file_type == G_FILE_TYPE_DIRECTORY)
+ /* First, try opening it as a directory */
+ dfd = glnx_opendirat_with_errno (AT_FDCWD, dir_or_file_path, TRUE);
+ if (dfd < 0)
{
- dir = g_object_ref (dir_or_file);
- meta_file = g_file_get_child (dir, "superblock");
+ if (errno != ENOTDIR)
+ {
+ glnx_set_error_from_errno (error);
+ goto out;
+ }
+ else
+ {
+ g_autofree char *dir = dirname (g_strdup (dir_or_file_path));
+
+ if (!glnx_opendirat (AT_FDCWD, dir, TRUE, &dfd, error))
+ goto out;
+ }
}
- else
+
+ meta_fd = openat (dfd, "superblock", O_RDONLY | O_CLOEXEC);
+ if (meta_fd < 0)
{
- meta_file = g_object_ref (dir_or_file);
- dir = g_file_get_parent (meta_file);
+ glnx_set_error_from_errno (error);
+ goto out;
}
-
- if (!ot_util_variant_map (meta_file, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
- FALSE, &meta, error))
+
+ if (!ot_util_variant_map_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
+ FALSE, &meta, error))
goto out;
/* Parsing OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */
@@ -330,14 +349,18 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
guint64 size;
guint64 usize;
const guchar *csum;
+ char checksum[65];
gboolean have_all;
+ g_autoptr(GInputStream) part_in = NULL;
g_autoptr(GBytes) delta_data = NULL;
- g_autoptr(GVariant) part_data = NULL;
+ g_autoptr(GVariant) inline_part_data = NULL;
g_autoptr(GVariant) header = NULL;
g_autoptr(GVariant) csum_v = NULL;
g_autoptr(GVariant) objects = NULL;
- g_autoptr(GBytes) bytes = NULL;
+ g_autoptr(GVariant) part = NULL;
g_autofree char *deltapart_path = NULL;
+ OstreeStaticDeltaOpenFlags delta_open_flags =
+ skip_validation ? OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM : 0;
header = g_variant_get_child_value (headers, i);
g_variant_get (header, "(u aytt@ay)", &version, &csum_v, &size, &usize, &objects);
@@ -362,46 +385,195 @@ ostree_repo_static_delta_execute_offline (OstreeRepo *self,
csum = ostree_checksum_bytes_peek_validate (csum_v, error);
if (!csum)
goto out;
+ ostree_checksum_inplace_from_bytes (csum, checksum);
deltapart_path =
_ostree_get_relative_static_delta_part_path (from_checksum, to_checksum, i);
- part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE("(yay)"));
- if (part_data)
+ inline_part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE("(yay)"));
+ if (inline_part_data)
{
- bytes = g_variant_get_data_as_bytes (part_data);
+ g_autoptr(GBytes) inline_part_bytes = g_variant_get_data_as_bytes (inline_part_data);
+ part_in = g_memory_input_stream_new_from_bytes (inline_part_bytes);
+
+ /* For inline parts, we don't checksum, because it's
+ * included with the metadata, so we're not trying to
+ * protect against MITM or such. Non-security related
+ * checksums should be done at the underlying storage layer.
+ */
+ delta_open_flags |= OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM;
+
+ if (!_ostree_static_delta_part_open (part_in, inline_part_bytes,
+ delta_open_flags,
+ NULL,
+ &part,
+ cancellable, error))
+ goto out;
}
else
{
- g_autoptr(GFile) part_path = ot_gfile_resolve_path_printf (dir, "%u", i);
- GMappedFile *mfile = gs_file_map_noatime (part_path, cancellable, error);
- if (!mfile)
+ g_autofree char *relpath = g_strdup_printf ("%u", i); /* TODO avoid malloc here */
+ glnx_fd_close int part_fd = openat (dfd, relpath, O_RDONLY | O_CLOEXEC);
+ if (part_fd < 0)
+ {
+ glnx_set_error_from_errno (error);
+ g_prefix_error (error, "Opening deltapart '%s': ", deltapart_path);
+ goto out;
+ }
+
+ part_in = g_unix_input_stream_new (part_fd, FALSE);
+
+ if (!_ostree_static_delta_part_open (part_in, NULL,
+ delta_open_flags,
+ checksum,
+ &part,
+ cancellable, error))
goto out;
+ }
- bytes = g_mapped_file_get_bytes (mfile);
- g_mapped_file_unref (mfile);
+ if (!_ostree_static_delta_part_execute (self, objects, part, skip_validation,
+ cancellable, error))
+ {
+ g_prefix_error (error, "Executing delta part %i: ", i);
+ goto out;
}
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
+gboolean
+_ostree_static_delta_part_open (GInputStream *part_in,
+ GBytes *inline_part_bytes,
+ OstreeStaticDeltaOpenFlags flags,
+ const char *expected_checksum,
+ GVariant **out_part,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
+ const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
+ gsize bytes_read;
+ guint8 comptype;
+ g_autoptr(GChecksum) checksum = NULL;
+ g_autoptr(GInputStream) checksum_in = NULL;
+ g_autoptr(GVariant) ret_part = NULL;
+ GInputStream *source_in;
+
+ /* We either take a fd or a GBytes reference */
+ g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
+ g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);
+
+ if (!skip_checksum)
+ {
+ checksum = g_checksum_new (G_CHECKSUM_SHA256);
+ checksum_in = (GInputStream*)ostree_checksum_input_stream_new (part_in, checksum);
+ source_in = checksum_in;
+ }
+ else
+ {
+ source_in = part_in;
+ }
+
+ { guint8 buf[1];
+ /* First byte is compression type */
+ if (!g_input_stream_read_all (source_in, buf, sizeof(buf), &bytes_read,
+ cancellable, error))
+ {
+ g_prefix_error (error, "Reading initial compression flag byte: ");
+ goto out;
+ }
+ comptype = buf[0];
+ }
- if (!skip_validation)
+ switch (comptype)
+ {
+ case 0:
+ if (!inline_part_bytes)
{
- g_autoptr(GInputStream) in = g_memory_input_stream_new_from_bytes (bytes);
+ int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in);
- g_autofree char *expected_checksum = ostree_checksum_from_bytes (csum);
- if (!_ostree_static_delta_part_validate (self, in, i,
- expected_checksum,
- cancellable, error))
+ /* No compression, no checksums - a fast path */
+ if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE
(OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+ trusted, &ret_part, error))
goto out;
}
+ else
+ {
+ g_autoptr(GBytes) content_bytes = g_bytes_new_from_bytes (inline_part_bytes, 1,
+ g_bytes_get_size (inline_part_bytes) -
1);
+ ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+ content_bytes, trusted);
+ }
- if (!_ostree_static_delta_part_execute (self, objects, bytes, skip_validation,
- cancellable, error))
+ if (!skip_checksum)
+ g_checksum_update (checksum, g_variant_get_data (ret_part),
+ g_variant_get_size (ret_part));
+
+ break;
+ case 'x':
+ {
+ g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
+ g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
+ g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
+ g_autoptr(GOutputStream) unpacked_out = NULL;
+ glnx_fd_close int unpacked_fd = -1;
+ gssize n_bytes_written;
+
+ unpacked_fd = g_mkstemp_full (tmppath, O_RDWR | O_CLOEXEC, 0640);
+ if (unpacked_fd < 0)
+ {
+ glnx_set_error_from_errno (error);
+ goto out;
+ }
+
+ /* Now make it autocleanup on process exit - in the future, we
+ * should consider caching unpacked deltas as well.
+ */
+ if (unlink (tmppath) < 0)
+ {
+ glnx_set_error_from_errno (error);
+ goto out;
+ }
+
+ unpacked_out = g_unix_output_stream_new (unpacked_fd, FALSE);
+
+ n_bytes_written = g_output_stream_splice (unpacked_out, convin,
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+ G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+ cancellable, error);
+ if (n_bytes_written < 0)
+ goto out;
+
+ if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE
(OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
+ trusted, &ret_part, error))
+ goto out;
+ }
+ break;
+ default:
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid compression type '%u'", comptype);
+ goto out;
+ }
+
+ if (checksum)
+ {
+ const char *actual_checksum = g_checksum_get_string (checksum);
+ g_assert (expected_checksum != NULL);
+ if (strcmp (actual_checksum, expected_checksum) != 0)
{
- g_prefix_error (error, "executing delta part %i: ", i);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Checksum mismatch in static delta part; expected=%s actual=%s",
+ expected_checksum, actual_checksum);
goto out;
}
}
-
+
ret = TRUE;
+ *out_part = g_steal_pointer (&ret_part);
out:
return ret;
}
diff --git a/src/libostree/ostree-repo-static-delta-private.h
b/src/libostree/ostree-repo-static-delta-private.h
index b0e82ad..55777fc 100644
--- a/src/libostree/ostree-repo-static-delta-private.h
+++ b/src/libostree/ostree-repo-static-delta-private.h
@@ -103,35 +103,36 @@ G_BEGIN_DECLS
*/
#define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya"
OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")"
+typedef enum {
+ OSTREE_STATIC_DELTA_OPEN_FLAGS_NONE = 0,
+ OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM = (1 << 0),
+ OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED = (1 << 1)
+} OstreeStaticDeltaOpenFlags;
+
+gboolean
+_ostree_static_delta_part_open (GInputStream *part_in,
+ GBytes *inline_part_bytes,
+ OstreeStaticDeltaOpenFlags flags,
+ const char *expected_checksum,
+ GVariant **out_part,
+ GCancellable *cancellable,
+ GError **error);
+
gboolean _ostree_static_delta_dump (OstreeRepo *repo,
const char *delta_id,
GCancellable *cancellable,
GError **error);
-gboolean _ostree_static_delta_part_validate (OstreeRepo *repo,
- GInputStream *in,
- guint part_offset,
- const char *expected_checksum,
- GCancellable *cancellable,
- GError **error);
-
gboolean _ostree_static_delta_part_execute (OstreeRepo *repo,
GVariant *header,
- GBytes *partdata,
+ GVariant *part_payload,
gboolean trusted,
GCancellable *cancellable,
GError **error);
-gboolean _ostree_static_delta_part_execute_raw (OstreeRepo *repo,
- GVariant *header,
- GVariant *part,
- gboolean trusted,
- GCancellable *cancellable,
- GError **error);
-
void _ostree_static_delta_part_execute_async (OstreeRepo *repo,
GVariant *header,
- GBytes *partdata,
+ GVariant *part_payload,
gboolean trusted,
GCancellable *cancellable,
GAsyncReadyCallback callback,
diff --git a/src/libostree/ostree-repo-static-delta-processing.c
b/src/libostree/ostree-repo-static-delta-processing.c
index 10e533c..74423e7 100644
--- a/src/libostree/ostree-repo-static-delta-processing.c
+++ b/src/libostree/ostree-repo-static-delta-processing.c
@@ -150,42 +150,12 @@ open_output_target (StaticDeltaExecutionState *state,
}
gboolean
-_ostree_static_delta_part_validate (OstreeRepo *repo,
- GInputStream *in,
- guint part_offset,
- const char *expected_checksum,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- g_autofree guchar *actual_checksum_bytes = NULL;
- g_autofree char *actual_checksum = NULL;
-
- if (!ot_gio_checksum_stream (in, &actual_checksum_bytes,
- cancellable, error))
- goto out;
-
- actual_checksum = ostree_checksum_from_bytes (actual_checksum_bytes);
- if (strcmp (actual_checksum, expected_checksum) != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Checksum mismatch in static delta part %u; expected=%s actual=%s",
- part_offset, expected_checksum, actual_checksum);
- goto out;
- }
-
- ret = TRUE;
- out:
- return ret;
-}
-
-gboolean
-_ostree_static_delta_part_execute_raw (OstreeRepo *repo,
- GVariant *objects,
- GVariant *part,
- gboolean trusted,
- GCancellable *cancellable,
- GError **error)
+_ostree_static_delta_part_execute (OstreeRepo *repo,
+ GVariant *objects,
+ GVariant *part,
+ gboolean trusted,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
guint8 *checksums_data;
@@ -280,99 +250,10 @@ _ostree_static_delta_part_execute_raw (OstreeRepo *repo,
return ret;
}
-static gboolean
-decompress_all (GConverter *converter,
- GBytes *data,
- GBytes **out_uncompressed,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- g_autoptr(GMemoryInputStream) memin = (GMemoryInputStream*)g_memory_input_stream_new_from_bytes (data);
- g_autoptr(GMemoryOutputStream) memout = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0,
g_realloc, g_free);
- g_autoptr(GInputStream) convin = g_converter_input_stream_new ((GInputStream*)memin, converter);
-
- {
- gssize n_bytes_written = g_output_stream_splice ((GOutputStream*)memout, convin,
- G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
- G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
- cancellable, error);
- if (n_bytes_written < 0)
- goto out;
- }
-
- ret = TRUE;
- *out_uncompressed = g_memory_output_stream_steal_as_bytes (memout);
- out:
- return ret;
-}
-
-gboolean
-_ostree_static_delta_part_execute (OstreeRepo *repo,
- GVariant *header,
- GBytes *part_bytes,
- gboolean trusted,
- GCancellable *cancellable,
- GError **error)
-{
- gboolean ret = FALSE;
- gsize partlen;
- const guint8*partdata;
- g_autoptr(GBytes) part_payload_bytes = NULL;
- g_autoptr(GBytes) payload_data = NULL;
- g_autoptr(GVariant) payload = NULL;
- guint8 comptype;
-
- partdata = g_bytes_get_data (part_bytes, &partlen);
-
- if (partlen < 1)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Corrupted 0 length delta part");
- goto out;
- }
-
- /* First byte is compression type */
- comptype = partdata[0];
- /* Then the rest may be compressed or uncompressed */
- part_payload_bytes = g_bytes_new_from_bytes (part_bytes, 1, partlen - 1);
- switch (comptype)
- {
- case 0:
- /* No compression */
- payload_data = g_bytes_ref (part_payload_bytes);
- break;
- case 'x':
- {
- g_autoptr(GConverter) decomp =
- (GConverter*) _ostree_lzma_decompressor_new ();
-
- if (!decompress_all (decomp, part_payload_bytes, &payload_data,
- cancellable, error))
- goto out;
- }
- break;
- default:
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid compression type '%u'", comptype);
- goto out;
- }
-
- payload = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
- payload_data, FALSE);
- if (!_ostree_static_delta_part_execute_raw (repo, header, payload, trusted,
- cancellable, error))
- goto out;
-
- ret = TRUE;
- out:
- return ret;
-}
-
typedef struct {
OstreeRepo *repo;
GVariant *header;
- GBytes *partdata;
+ GVariant *part;
GCancellable *cancellable;
GSimpleAsyncResult *result;
gboolean trusted;
@@ -385,7 +266,7 @@ static_delta_part_execute_async_data_free (gpointer user_data)
g_clear_object (&data->repo);
g_variant_unref (data->header);
- g_bytes_unref (data->partdata);
+ g_variant_unref (data->part);
g_clear_object (&data->cancellable);
g_free (data);
}
@@ -401,7 +282,7 @@ static_delta_part_execute_thread (GSimpleAsyncResult *res,
data = g_simple_async_result_get_op_res_gpointer (res);
if (!_ostree_static_delta_part_execute (data->repo,
data->header,
- data->partdata,
+ data->part,
data->trusted,
cancellable, &error))
g_simple_async_result_take_error (res, error);
@@ -410,7 +291,7 @@ static_delta_part_execute_thread (GSimpleAsyncResult *res,
void
_ostree_static_delta_part_execute_async (OstreeRepo *repo,
GVariant *header,
- GBytes *partdata,
+ GVariant *part,
gboolean trusted,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -421,7 +302,7 @@ _ostree_static_delta_part_execute_async (OstreeRepo *repo,
asyncdata = g_new0 (StaticDeltaPartExecuteAsyncData, 1);
asyncdata->repo = g_object_ref (repo);
asyncdata->header = g_variant_ref (header);
- asyncdata->partdata = g_bytes_ref (partdata);
+ asyncdata->part = g_variant_ref (part);
asyncdata->trusted = trusted;
asyncdata->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]