From 345754a5641525116e85b2b0b9643acbb75a6d16 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 29 Jan 2015 23:00:51 -0500 Subject: [PATCH] deltas: Initial code to copy content from existing objects This is preparatory work for implementing rollsum support. --- .../ostree-repo-static-delta-processing.c | 84 +++++++++++++++++-- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/src/libostree/ostree-repo-static-delta-processing.c b/src/libostree/ostree-repo-static-delta-processing.c index 10372a02..1cb66de4 100644 --- a/src/libostree/ostree-repo-static-delta-processing.c +++ b/src/libostree/ostree-repo-static-delta-processing.c @@ -58,6 +58,8 @@ typedef struct { guint64 content_size; GOutputStream *content_out; char checksum[65]; + char *read_source_object; + int read_source_fd; gboolean have_obj; guint32 uid; guint32 gid; @@ -654,12 +656,52 @@ dispatch_write (OstreeRepo *repo, if (!state->have_obj) { - if (!g_output_stream_write_all (state->content_out, - state->payload_data + content_offset, - content_size, - &bytes_written, - cancellable, error)) - goto out; + if (state->read_source_fd != -1) + { + if (lseek (state->read_source_fd, content_offset, SEEK_SET) == -1) + { + gs_set_error_from_errno (error, errno); + goto out; + } + while (content_size > 0) + { + char buf[4096]; + gssize bytes_read; + + do + bytes_read = read (state->read_source_fd, buf, MIN(sizeof(buf), content_size)); + while (G_UNLIKELY (bytes_read == -1 && errno == EINTR)); + if (bytes_read == -1) + { + gs_set_error_from_errno (error, errno); + goto out; + } + if (G_UNLIKELY (bytes_read == 0)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unexpected EOF reading object %s", state->read_source_object); + goto out; + } + + if (!g_output_stream_write_all (state->content_out, + buf, + bytes_read, + &bytes_written, + cancellable, error)) + goto out; + + content_size -= bytes_read; + } + } + else + { + if (!g_output_stream_write_all (state->content_out, + state->payload_data + content_offset, + content_size, + &bytes_written, + cancellable, error)) + goto out; + } } ret = TRUE; @@ -676,13 +718,30 @@ dispatch_set_read_source (OstreeRepo *repo, GError **error) { gboolean ret = FALSE; + guint64 source_offset; - g_assert_not_reached (); + if (state->read_source_fd) + { + (void) close (state->read_source_fd); + state->read_source_fd = -1; + } + + if (!read_varuint64 (state, &source_offset, error)) + goto out; + if (!validate_ofs (state, source_offset, 32, error)) + goto out; + + g_free (state->read_source_object); + state->read_source_object = ostree_checksum_from_bytes (state->payload_data + source_offset); + + if (!_ostree_repo_read_bare_fd (repo, state->read_source_object, &state->read_source_fd, + cancellable, error)) + goto out; ret = TRUE; - /* out: */ + out: if (!ret) - g_prefix_error (error, "opcode open-splice-and-close: "); + g_prefix_error (error, "opcode set-read-source: "); return ret; } @@ -705,8 +764,15 @@ dispatch_close (OstreeRepo *repo, cancellable, error)) goto out; } + + if (state->read_source_fd) + { + (void) close (state->read_source_fd); + state->read_source_fd = -1; + } g_clear_pointer (&state->xattrs, g_variant_unref); + g_clear_pointer (&state->read_source_object, g_free); g_clear_object (&state->content_out); state->checksum_index++;