core: Extract stage_and_checksum() internal API
This will be used for staging both metadata and data consistently before actually importing it.
This commit is contained in:
parent
99bf19314e
commit
556662b24c
|
|
@ -703,41 +703,6 @@ ostree_pack_object (GOutputStream *output,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
splice_and_checksum (GOutputStream *out,
|
||||
GInputStream *in,
|
||||
GChecksum *checksum,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (checksum != NULL)
|
||||
{
|
||||
gsize bytes_read, bytes_written;
|
||||
char buf[4096];
|
||||
do
|
||||
{
|
||||
if (!g_input_stream_read_all (in, buf, sizeof(buf), &bytes_read, cancellable, error))
|
||||
goto out;
|
||||
if (checksum)
|
||||
g_checksum_update (checksum, (guint8*)buf, bytes_read);
|
||||
if (!g_output_stream_write_all (out, buf, bytes_read, &bytes_written, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
while (bytes_read > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_output_stream_splice (out, in, 0, cancellable, error) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
unpack_meta (GFile *file,
|
||||
GFile *dest_file,
|
||||
|
|
@ -749,9 +714,6 @@ unpack_meta (GFile *file,
|
|||
GChecksum *ret_checksum = NULL;
|
||||
GFileOutputStream *out = NULL;
|
||||
|
||||
if (out_checksum)
|
||||
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
in = g_file_read (file, NULL, error);
|
||||
if (!in)
|
||||
goto out;
|
||||
|
|
@ -760,7 +722,8 @@ unpack_meta (GFile *file,
|
|||
if (!out)
|
||||
goto out;
|
||||
|
||||
if (!splice_and_checksum ((GOutputStream*)out, (GInputStream*)in, ret_checksum, NULL, error))
|
||||
if (!ot_gio_splice_and_checksum ((GOutputStream*)out, (GInputStream*)in,
|
||||
out_checksum ? &ret_checksum : NULL, NULL, error))
|
||||
goto out;
|
||||
|
||||
if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
|
||||
|
|
@ -768,8 +731,10 @@ unpack_meta (GFile *file,
|
|||
|
||||
ret = TRUE;
|
||||
if (out_checksum)
|
||||
{
|
||||
*out_checksum = ret_checksum;
|
||||
ret_checksum = NULL;
|
||||
}
|
||||
out:
|
||||
ot_clear_checksum (&ret_checksum);
|
||||
g_clear_object (&in);
|
||||
|
|
@ -869,16 +834,13 @@ unpack_file (GFile *file,
|
|||
mode = GUINT32_FROM_BE (mode);
|
||||
content_len = GUINT64_FROM_BE (content_len);
|
||||
|
||||
if (out_checksum)
|
||||
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
if (S_ISREG (mode))
|
||||
{
|
||||
out = g_file_replace (dest_file, NULL, FALSE, 0, NULL, error);
|
||||
if (!out)
|
||||
goto out;
|
||||
|
||||
if (!splice_and_checksum ((GOutputStream*)out, in, ret_checksum, NULL, error))
|
||||
if (!ot_gio_splice_and_checksum ((GOutputStream*)out, in, out_checksum ? &ret_checksum : NULL, NULL, error))
|
||||
goto out;
|
||||
|
||||
if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
|
||||
|
|
|
|||
|
|
@ -562,6 +562,76 @@ ostree_repo_is_archive (OstreeRepo *self)
|
|||
return priv->archive;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
stage_and_checksum (OstreeRepo *self,
|
||||
OstreeObjectType objtype,
|
||||
GInputStream *input,
|
||||
GFile **out_tmpname,
|
||||
GChecksum **out_checksum,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
const char *prefix = NULL;
|
||||
OstreeRepoPrivate *priv = GET_PRIVATE (self);
|
||||
GFile *tmp_f = NULL;
|
||||
GOutputStream *stream = NULL;
|
||||
GFile *ret_tmpname = NULL;
|
||||
GChecksum *ret_checksum = NULL;
|
||||
|
||||
switch (objtype)
|
||||
{
|
||||
case OSTREE_OBJECT_TYPE_FILE:
|
||||
prefix = "file-tmp-";
|
||||
break;
|
||||
case OSTREE_OBJECT_TYPE_META:
|
||||
prefix = "meta-tmp-";
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ot_gfile_create_tmp (priv->tmp_dir, prefix, NULL, 0666,
|
||||
&tmp_f, &stream, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!ot_gio_splice_and_checksum (stream, input, &ret_checksum, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!g_output_stream_close ((GOutputStream*)stream, NULL, error))
|
||||
goto out;
|
||||
|
||||
ret_tmpname = g_file_get_child (priv->tmp_dir, g_checksum_get_string (ret_checksum));
|
||||
if (rename (ot_gfile_get_path_cached (tmp_f), ot_gfile_get_path_cached (ret_tmpname)) < 0)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
/* Clear it here, since we know the file is now gone */
|
||||
g_clear_object (&tmp_f);
|
||||
|
||||
ret = TRUE;
|
||||
if (out_tmpname)
|
||||
{
|
||||
*out_tmpname = ret_tmpname;
|
||||
ret_tmpname = NULL;
|
||||
}
|
||||
if (out_checksum)
|
||||
{
|
||||
*out_checksum = ret_checksum;
|
||||
ret_checksum = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_f)
|
||||
(void) g_file_delete (tmp_f, NULL, NULL);
|
||||
g_clear_object (&tmp_f);
|
||||
g_clear_object (&stream);
|
||||
g_clear_object (&ret_tmpname);
|
||||
ot_clear_checksum (&ret_checksum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_gvariant_to_tmp (OstreeRepo *self,
|
||||
OstreeSerializedVariantType type,
|
||||
|
|
@ -570,58 +640,34 @@ write_gvariant_to_tmp (OstreeRepo *self,
|
|||
GChecksum **out_checksum,
|
||||
GError **error)
|
||||
{
|
||||
OstreeRepoPrivate *priv = GET_PRIVATE (self);
|
||||
GVariant *serialized = NULL;
|
||||
gboolean ret = FALSE;
|
||||
gsize bytes_written;
|
||||
GFile *tmp_f = NULL;
|
||||
GOutputStream *stream = NULL;
|
||||
GChecksum *checksum = NULL;
|
||||
GVariant *serialized = NULL;
|
||||
GInputStream *mem = NULL;
|
||||
GChecksum *ret_checksum = NULL;
|
||||
GFile *ret_tmpname = NULL;
|
||||
|
||||
serialized = ostree_wrap_metadata_variant (type, variant);
|
||||
|
||||
if (!ot_gfile_create_tmp (priv->tmp_dir, "variant-tmp-", NULL, 0666,
|
||||
&tmp_f, &stream, NULL, error))
|
||||
goto out;
|
||||
|
||||
checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
if (!g_output_stream_write_all ((GOutputStream*)stream,
|
||||
g_variant_get_data (serialized),
|
||||
mem = g_memory_input_stream_new_from_data (g_variant_get_data (serialized),
|
||||
g_variant_get_size (serialized),
|
||||
&bytes_written,
|
||||
NULL,
|
||||
error))
|
||||
NULL);
|
||||
if (!stage_and_checksum (self, OSTREE_OBJECT_TYPE_META,
|
||||
mem, &ret_tmpname, &ret_checksum, NULL, error))
|
||||
goto out;
|
||||
|
||||
g_checksum_update (checksum, (guint8*)g_variant_get_data (serialized), g_variant_get_size (serialized));
|
||||
|
||||
if (!g_output_stream_close ((GOutputStream*)stream,
|
||||
NULL, error))
|
||||
goto out;
|
||||
|
||||
ret_tmpname = g_file_get_child (priv->tmp_dir, g_checksum_get_string (checksum));
|
||||
if (rename (ot_gfile_get_path_cached (tmp_f), ot_gfile_get_path_cached (ret_tmpname)) < 0)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
g_clear_object (&tmp_f);
|
||||
|
||||
ret = TRUE;
|
||||
if (out_tmpname)
|
||||
{
|
||||
*out_tmpname = ret_tmpname;
|
||||
ret_tmpname = NULL;
|
||||
*out_checksum = checksum;
|
||||
checksum = NULL;
|
||||
}
|
||||
if (out_checksum)
|
||||
{
|
||||
*out_checksum = ret_checksum;
|
||||
ret_checksum = NULL;
|
||||
}
|
||||
out:
|
||||
if (tmp_f)
|
||||
(void) g_file_delete (tmp_f, NULL, NULL);
|
||||
g_clear_object (&tmp_f);
|
||||
g_clear_object (&stream);
|
||||
g_clear_object (&ret_tmpname);
|
||||
ot_clear_checksum (&checksum);
|
||||
ot_clear_gvariant (&serialized);
|
||||
ot_clear_checksum (&ret_checksum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,52 @@ ot_gfile_get_basename_cached (GFile *file)
|
|||
return name;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_gio_splice_and_checksum (GOutputStream *out,
|
||||
GInputStream *in,
|
||||
GChecksum **out_checksum,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GChecksum *ret_checksum = NULL;
|
||||
|
||||
if (out_checksum)
|
||||
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
|
||||
if (ret_checksum != NULL)
|
||||
{
|
||||
gsize bytes_read, bytes_written;
|
||||
char buf[4096];
|
||||
do
|
||||
{
|
||||
if (!g_input_stream_read_all (in, buf, sizeof(buf), &bytes_read, cancellable, error))
|
||||
goto out;
|
||||
if (ret_checksum)
|
||||
g_checksum_update (ret_checksum, (guint8*)buf, bytes_read);
|
||||
if (!g_output_stream_write_all (out, buf, bytes_read, &bytes_written, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
while (bytes_read > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_output_stream_splice (out, in, 0, cancellable, error) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
if (out_checksum)
|
||||
{
|
||||
*out_checksum = ret_checksum;
|
||||
ret_checksum = NULL;
|
||||
}
|
||||
out:
|
||||
ot_clear_checksum (&ret_checksum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
ot_gfile_create_tmp (GFile *dir,
|
||||
const char *prefix,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,13 @@ gboolean ot_gfile_load_contents_utf8 (GFile *file,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean ot_gio_splice_and_checksum (GOutputStream *out,
|
||||
GInputStream *in,
|
||||
GChecksum **out_checksum,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
|
||||
gboolean ot_gfile_create_tmp (GFile *dir,
|
||||
const char *prefix,
|
||||
const char *suffix,
|
||||
|
|
|
|||
Loading…
Reference in New Issue