Add bsdiff support to deltas
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
1 parent
a705d9cf29
commit
3f3bb8e37d
4 files changed
+304
-15
No files matched your search
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user