deltas: Flesh out the open/write/close opcodes
Refactor open-splice-and-close to call open/close. We can't just call write as that would require duplicating the object size parameter.
This commit is contained in:
parent
96181da26a
commit
7900c82a36
|
|
@ -54,6 +54,16 @@ typedef struct {
|
||||||
GError **async_error;
|
GError **async_error;
|
||||||
|
|
||||||
OstreeObjectType output_objtype;
|
OstreeObjectType output_objtype;
|
||||||
|
OstreeRepoTrustedContentBareCommit barecommitstate;
|
||||||
|
guint64 content_size;
|
||||||
|
GOutputStream *content_out;
|
||||||
|
char checksum[65];
|
||||||
|
gboolean have_obj;
|
||||||
|
guint32 uid;
|
||||||
|
guint32 gid;
|
||||||
|
guint32 mode;
|
||||||
|
GVariant *xattrs;
|
||||||
|
|
||||||
const guint8 *output_target;
|
const guint8 *output_target;
|
||||||
const guint8 *input_target_csum;
|
const guint8 *input_target_csum;
|
||||||
|
|
||||||
|
|
@ -113,7 +123,6 @@ open_output_target (StaticDeltaExecutionState *state,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
guint8 *objcsum;
|
guint8 *objcsum;
|
||||||
char checksum[65];
|
|
||||||
|
|
||||||
g_assert (state->checksums != NULL);
|
g_assert (state->checksums != NULL);
|
||||||
g_assert (state->output_target == NULL);
|
g_assert (state->output_target == NULL);
|
||||||
|
|
@ -127,7 +136,7 @@ open_output_target (StaticDeltaExecutionState *state,
|
||||||
state->output_objtype = (OstreeObjectType) *objcsum;
|
state->output_objtype = (OstreeObjectType) *objcsum;
|
||||||
state->output_target = objcsum + 1;
|
state->output_target = objcsum + 1;
|
||||||
|
|
||||||
ostree_checksum_inplace_from_bytes (state->output_target, checksum);
|
ostree_checksum_inplace_from_bytes (state->output_target, state->checksum);
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
|
|
@ -438,6 +447,38 @@ validate_ofs (StaticDeltaExecutionState *state,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
do_content_open_generic (OstreeRepo *repo,
|
||||||
|
StaticDeltaExecutionState *state,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
gs_unref_variant GVariant *modev;
|
||||||
|
guint64 mode_offset;
|
||||||
|
guint64 xattr_offset;
|
||||||
|
guint32 uid, gid, mode;
|
||||||
|
|
||||||
|
if (!read_varuint64 (state, &mode_offset, error))
|
||||||
|
goto out;
|
||||||
|
if (!read_varuint64 (state, &xattr_offset, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
state->barecommitstate.fd = -1;
|
||||||
|
|
||||||
|
modev = g_variant_get_child_value (state->mode_dict, mode_offset);
|
||||||
|
g_variant_get (modev, "(uuu)", &uid, &gid, &mode);
|
||||||
|
state->uid = GUINT32_FROM_BE (uid);
|
||||||
|
state->gid = GUINT32_FROM_BE (gid);
|
||||||
|
state->mode = GUINT32_FROM_BE (mode);
|
||||||
|
|
||||||
|
state->xattrs = g_variant_get_child_value (state->xattr_dict, xattr_offset);
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
dispatch_open_splice_and_close (OstreeRepo *repo,
|
dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
StaticDeltaExecutionState *state,
|
StaticDeltaExecutionState *state,
|
||||||
|
|
@ -445,13 +486,10 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
char checksum[65];
|
|
||||||
|
|
||||||
if (!open_output_target (state, cancellable, error))
|
if (!open_output_target (state, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ostree_checksum_inplace_from_bytes (state->output_target, checksum);
|
|
||||||
|
|
||||||
if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype))
|
if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype))
|
||||||
{
|
{
|
||||||
gs_unref_variant GVariant *metadata = NULL;
|
gs_unref_variant GVariant *metadata = NULL;
|
||||||
|
|
@ -469,7 +507,7 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
state->payload_data + offset, length, TRUE, NULL, NULL);
|
state->payload_data + offset, length, TRUE, NULL, NULL);
|
||||||
|
|
||||||
if (!ostree_repo_write_metadata_trusted (state->repo, state->output_objtype,
|
if (!ostree_repo_write_metadata_trusted (state->repo, state->output_objtype,
|
||||||
checksum,
|
state->checksum,
|
||||||
metadata,
|
metadata,
|
||||||
cancellable,
|
cancellable,
|
||||||
error))
|
error))
|
||||||
|
|
@ -477,81 +515,54 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
guint64 mode_offset;
|
|
||||||
guint64 xattr_offset;
|
|
||||||
guint64 content_size;
|
|
||||||
guint64 content_offset;
|
guint64 content_offset;
|
||||||
guint64 objlen;
|
guint64 objlen;
|
||||||
|
guint64 content_size;
|
||||||
|
gsize bytes_written;
|
||||||
gs_unref_object GInputStream *object_input = NULL;
|
gs_unref_object GInputStream *object_input = NULL;
|
||||||
gs_unref_object GInputStream *memin = NULL;
|
gs_unref_object GInputStream *memin = NULL;
|
||||||
gs_unref_variant GVariant *xattrs_buf = NULL;
|
|
||||||
GVariant *modev;
|
|
||||||
GVariant *xattrs;
|
|
||||||
guint32 uid, gid, mode;
|
|
||||||
|
|
||||||
if (!read_varuint64 (state, &mode_offset, error))
|
if (!do_content_open_generic (repo, state, cancellable, error))
|
||||||
goto out;
|
|
||||||
if (!read_varuint64 (state, &xattr_offset, error))
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!read_varuint64 (state, &content_size, error))
|
if (!read_varuint64 (state, &content_size, error))
|
||||||
goto out;
|
goto out;
|
||||||
if (!read_varuint64 (state, &content_offset, error))
|
if (!read_varuint64 (state, &content_offset, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!validate_ofs (state, content_offset, content_size, error))
|
if (!validate_ofs (state, content_offset, content_size, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
modev = g_variant_get_child_value (state->mode_dict, mode_offset);
|
|
||||||
g_variant_get (modev, "(uuu)", &uid, &gid, &mode);
|
|
||||||
uid = GUINT32_FROM_BE (uid);
|
|
||||||
gid = GUINT32_FROM_BE (gid);
|
|
||||||
mode = GUINT32_FROM_BE (mode);
|
|
||||||
|
|
||||||
xattrs = g_variant_get_child_value (state->xattr_dict, xattr_offset);
|
|
||||||
|
|
||||||
/* Fast path for regular files to bare repositories */
|
/* Fast path for regular files to bare repositories */
|
||||||
if (S_ISREG (mode) &&
|
if (S_ISREG (state->mode) &&
|
||||||
(repo->mode == OSTREE_REPO_MODE_BARE ||
|
(repo->mode == OSTREE_REPO_MODE_BARE ||
|
||||||
repo->mode == OSTREE_REPO_MODE_BARE_USER))
|
repo->mode == OSTREE_REPO_MODE_BARE_USER))
|
||||||
{
|
{
|
||||||
OstreeRepoTrustedContentBareCommit barecommitstate = { -1 };
|
if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
|
||||||
gs_unref_object GOutputStream *outstream = NULL;
|
state->content_size,
|
||||||
gsize bytes_written;
|
&state->barecommitstate,
|
||||||
gboolean have_obj;
|
&state->content_out,
|
||||||
|
&state->have_obj,
|
||||||
if (!_ostree_repo_open_trusted_content_bare (repo, checksum,
|
|
||||||
content_size,
|
|
||||||
&barecommitstate,
|
|
||||||
&outstream,
|
|
||||||
&have_obj,
|
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!have_obj)
|
if (!state->have_obj)
|
||||||
{
|
{
|
||||||
if (!g_output_stream_write_all (outstream, state->payload_data + content_offset,
|
if (!g_output_stream_write_all (state->content_out,
|
||||||
|
state->payload_data + content_offset,
|
||||||
content_size,
|
content_size,
|
||||||
&bytes_written,
|
&bytes_written,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!g_output_stream_flush (outstream, cancellable, error))
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_ostree_repo_commit_trusted_content_bare (repo, checksum, &barecommitstate,
|
|
||||||
uid, gid, mode, xattrs,
|
|
||||||
cancellable, error))
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Slower path, for symlinks and unpacking deltas into archive-z2 */
|
/* Slower path, for symlinks and unpacking deltas into archive-z2 */
|
||||||
gs_unref_object GFileInfo *finfo = NULL;
|
gs_unref_object GFileInfo *finfo = NULL;
|
||||||
|
|
||||||
finfo = _ostree_header_gfile_info_new (mode, uid, gid);
|
finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid);
|
||||||
|
|
||||||
if (S_ISLNK (mode))
|
if (S_ISLNK (state->mode))
|
||||||
{
|
{
|
||||||
gs_free char *nulterminated_target =
|
gs_free char *nulterminated_target =
|
||||||
g_strndup ((char*)state->payload_data + content_offset, content_size);
|
g_strndup ((char*)state->payload_data + content_offset, content_size);
|
||||||
|
|
@ -559,18 +570,18 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_assert (S_ISREG (mode));
|
g_assert (S_ISREG (state->mode));
|
||||||
g_file_info_set_size (finfo, content_size);
|
g_file_info_set_size (finfo, content_size);
|
||||||
memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, content_size, NULL);
|
memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, content_size, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ostree_raw_file_to_content_stream (memin, finfo, xattrs,
|
if (!ostree_raw_file_to_content_stream (memin, finfo, state->xattrs,
|
||||||
&object_input, &objlen,
|
&object_input, &objlen,
|
||||||
cancellable, error))
|
cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (!ostree_repo_write_content_trusted (state->repo,
|
if (!ostree_repo_write_content_trusted (state->repo,
|
||||||
checksum,
|
state->checksum,
|
||||||
object_input,
|
object_input,
|
||||||
objlen,
|
objlen,
|
||||||
cancellable,
|
cancellable,
|
||||||
|
|
@ -579,8 +590,8 @@ dispatch_open_splice_and_close (OstreeRepo *repo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->checksum_index++;
|
if (!dispatch_close (repo, state, cancellable, error))
|
||||||
state->output_target = NULL;
|
goto out;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
|
|
@ -597,9 +608,25 @@ dispatch_open (OstreeRepo *repo,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
g_assert (state->output_target == NULL);
|
||||||
|
/* FIXME - lift this restriction */
|
||||||
|
g_assert (repo->mode == OSTREE_REPO_MODE_BARE ||
|
||||||
|
repo->mode == OSTREE_REPO_MODE_BARE_USER);
|
||||||
|
|
||||||
if (!open_output_target (state, cancellable, error))
|
if (!open_output_target (state, cancellable, error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (!do_content_open_generic (repo, state, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
|
||||||
|
state->content_size,
|
||||||
|
&state->barecommitstate,
|
||||||
|
&state->content_out,
|
||||||
|
&state->have_obj,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
out:
|
out:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
@ -614,11 +641,29 @@ dispatch_write (OstreeRepo *repo,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
guint64 content_size;
|
||||||
|
guint64 content_offset;
|
||||||
|
gsize bytes_written;
|
||||||
|
|
||||||
g_assert_not_reached ();
|
if (!read_varuint64 (state, &content_size, error))
|
||||||
|
goto out;
|
||||||
|
if (!read_varuint64 (state, &content_offset, error))
|
||||||
|
goto out;
|
||||||
|
if (!validate_ofs (state, content_offset, content_size, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
/* out: */
|
out:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
g_prefix_error (error, "opcode open-splice-and-close: ");
|
g_prefix_error (error, "opcode open-splice-and-close: ");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -649,10 +694,26 @@ dispatch_close (OstreeRepo *repo,
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
g_assert_not_reached ();
|
if (state->content_out)
|
||||||
|
{
|
||||||
|
if (!g_output_stream_flush (state->content_out, cancellable, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate,
|
||||||
|
state->uid, state->gid, state->mode,
|
||||||
|
state->xattrs,
|
||||||
|
cancellable, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&state->xattrs, g_variant_unref);
|
||||||
|
g_clear_object (&state->content_out);
|
||||||
|
|
||||||
|
state->checksum_index++;
|
||||||
|
state->output_target = NULL;
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
/* out: */
|
out:
|
||||||
if (!ret)
|
if (!ret)
|
||||||
g_prefix_error (error, "opcode open-splice-and-close: ");
|
g_prefix_error (error, "opcode open-splice-and-close: ");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue