diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2015-02-23 10:35:17 +0100 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2015-03-03 12:16:17 -0500 |
commit | 3f3bb8e37dffec1143328db43fdd806baf346d1e (patch) | |
tree | 2361066774d0df0cfbe8aaf38e947c5543187862 /src/libostree/ostree-repo-static-delta-processing.c | |
parent | a705d9cf29cff0426dc735a0ad562b367a3c5124 (diff) | |
download | ostree-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.c | 82 |
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, |