summaryrefslogtreecommitdiff
path: root/src/libostree/ostree-repo-static-delta-processing.c
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2015-02-23 10:35:17 +0100
committerColin Walters <walters@verbum.org>2015-03-03 12:16:17 -0500
commit3f3bb8e37dffec1143328db43fdd806baf346d1e (patch)
tree2361066774d0df0cfbe8aaf38e947c5543187862 /src/libostree/ostree-repo-static-delta-processing.c
parenta705d9cf29cff0426dc735a0ad562b367a3c5124 (diff)
downloadostree-3f3bb8e37dffec1143328db43fdd806baf346d1e.tar.gz
Add bsdiff support to deltas
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Diffstat (limited to 'src/libostree/ostree-repo-static-delta-processing.c')
-rw-r--r--src/libostree/ostree-repo-static-delta-processing.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c
index 5cfdba90..0ddf79f1 100644
--- a/src/libostree/ostree-repo-static-delta-processing.c
+++ b/src/libostree/ostree-repo-static-delta-processing.c
@@ -33,6 +33,7 @@
#include "ostree-lzma-decompressor.h"
#include "otutil.h"
#include "ostree-varint.h"
+#include "bsdiff/bspatch.h"
/* This should really always be true, but hey, let's just assert it */
G_STATIC_ASSERT (sizeof (guint) >= sizeof (guint32));
@@ -100,6 +101,7 @@ OPPROTO(write)
OPPROTO(set_read_source)
OPPROTO(unset_read_source)
OPPROTO(close)
+OPPROTO(bspatch)
#undef OPPROTO
static gboolean
@@ -259,6 +261,10 @@ _ostree_static_delta_part_execute_raw (OstreeRepo *repo,
if (!dispatch_close (repo, state, cancellable, error))
goto out;
break;
+ case OSTREE_STATIC_DELTA_OP_BSPATCH:
+ if (!dispatch_bspatch (repo, state, cancellable, error))
+ goto out;
+ break;
default:
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Unknown opcode %u at offset %u", opcode, n_executed);
@@ -486,6 +492,82 @@ do_content_open_generic (OstreeRepo *repo,
return ret;
}
+struct bzpatch_opaque_s
+{
+ StaticDeltaExecutionState *state;
+ guint64 offset, length;
+};
+
+static int
+bspatch_read (const struct bspatch_stream* stream, void* buffer, int length)
+{
+ struct bzpatch_opaque_s *opaque = stream->opaque;
+
+ g_assert (length <= opaque->length);
+ g_assert (opaque->offset + length <= opaque->state->payload_size);
+
+ memcpy (buffer, opaque->state->payload_data + opaque->offset, length);
+ opaque->offset += length;
+ opaque->length -= length;
+ return 0;
+}
+
+static gboolean
+dispatch_bspatch (OstreeRepo *repo,
+ StaticDeltaExecutionState *state,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ guint64 offset, length;
+ gs_unref_object GInputStream *in_stream = NULL;
+ gs_unref_object GOutputStream *out_mem_stream = NULL;
+ gs_free guchar *buf = NULL;
+ struct bspatch_stream stream;
+ struct bzpatch_opaque_s opaque;
+ gsize bytes_written;
+
+ if (!read_varuint64 (state, &offset, error))
+ goto out;
+ if (!read_varuint64 (state, &length, error))
+ goto out;
+
+ buf = g_malloc0 (state->content_size);
+
+ in_stream = g_unix_input_stream_new (state->read_source_fd, FALSE);
+
+ out_mem_stream = g_memory_output_stream_new_resizable ();
+
+ if (!g_output_stream_splice (out_mem_stream, in_stream, G_OUTPUT_STREAM_SPLICE_NONE,
+ cancellable, error) < 0)
+ goto out;
+
+ opaque.state = state;
+ opaque.offset = offset;
+ opaque.length = length;
+ stream.read = bspatch_read;
+ stream.opaque = &opaque;
+ if (bspatch (g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (out_mem_stream)),
+ g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (out_mem_stream)),
+ buf,
+ state->content_size,
+ &stream) < 0)
+ goto out;
+
+ if (!g_output_stream_write_all (state->content_out,
+ buf,
+ state->content_size,
+ &bytes_written,
+ cancellable, error))
+ goto out;
+
+ g_assert (bytes_written == state->content_size);
+
+ ret = TRUE;
+ out:
+ return ret;
+}
+
static gboolean
dispatch_open_splice_and_close (OstreeRepo *repo,
StaticDeltaExecutionState *state,