core: Clean up checksumming

Don't expose GChecksum in APIs.  Add a new stream class which allows
us to pass an input stream somewhere, but gather a checksum as it's
read.

Move some bits of the internals towards binary csums.
This commit is contained in:
Colin Walters 2012-04-10 16:40:22 -04:00
parent fa4cbc8b89
commit f15c184584
17 changed files with 605 additions and 274 deletions

View File

@ -22,6 +22,8 @@ privlib_LTLIBRARIES += libostree.la
libostree_la_SOURCES = src/libostree/ostree.h \
src/libostree/ostree-core.c \
src/libostree/ostree-core.h \
src/libostree/ostree-checksum-input-stream.c \
src/libostree/ostree-checksum-input-stream.h \
src/libostree/ostree-mutable-tree.c \
src/libostree/ostree-mutable-tree.h \
src/libostree/ostree-repo.c \

View File

@ -20,6 +20,8 @@
noinst_LTLIBRARIES += libotutil.la
libotutil_la_SOURCES = \
src/libotutil/ot-checksum-utils.c \
src/libotutil/ot-checksum-utils.h \
src/libotutil/ot-local-alloc.c \
src/libotutil/ot-local-alloc.h \
src/libotutil/ot-opt-utils.c \

View File

@ -0,0 +1,169 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gio/gio.h>
#include "ostree-checksum-input-stream.h"
enum {
PROP_0,
PROP_CHECKSUM
};
G_DEFINE_TYPE (OstreeChecksumInputStream, ostree_checksum_input_stream, G_TYPE_FILTER_INPUT_STREAM)
struct _OstreeChecksumInputStreamPrivate {
GChecksum *checksum;
};
static void ostree_checksum_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void ostree_checksum_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static gssize ostree_checksum_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static void
ostree_checksum_input_stream_class_init (OstreeChecksumInputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (OstreeChecksumInputStreamPrivate));
gobject_class->get_property = ostree_checksum_input_stream_get_property;
gobject_class->set_property = ostree_checksum_input_stream_set_property;
stream_class->read_fn = ostree_checksum_input_stream_read;
/**
* OstreeChecksumInputStream:checksum:
*
* The checksum that the stream updates.
*/
g_object_class_install_property (gobject_class,
PROP_CHECKSUM,
g_param_spec_pointer ("checksum",
"", "",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
static void
ostree_checksum_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
OstreeChecksumInputStream *self;
self = OSTREE_CHECKSUM_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_CHECKSUM:
self->priv->checksum = g_value_get_pointer (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
ostree_checksum_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
OstreeChecksumInputStream *self;
self = OSTREE_CHECKSUM_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_CHECKSUM:
g_value_set_pointer (value, self->priv->checksum);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
ostree_checksum_input_stream_init (OstreeChecksumInputStream *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
OSTREE_TYPE_CHECKSUM_INPUT_STREAM,
OstreeChecksumInputStreamPrivate);
}
OstreeChecksumInputStream *
ostree_checksum_input_stream_new (GInputStream *base,
GChecksum *checksum)
{
OstreeChecksumInputStream *stream;
g_return_val_if_fail (G_IS_INPUT_STREAM (base), NULL);
stream = g_object_new (OSTREE_TYPE_CHECKSUM_INPUT_STREAM,
"base-stream", base,
"checksum", checksum,
NULL);
return (OstreeChecksumInputStream*) (stream);
}
static gssize
ostree_checksum_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
OstreeChecksumInputStream *self = (OstreeChecksumInputStream*) stream;
GFilterInputStream *fself = (GFilterInputStream*) self;
gssize res = -1;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
res = g_input_stream_read (fself->base_stream,
buffer,
count,
cancellable,
error);
if (res > 0)
g_checksum_update (self->priv->checksum, buffer, res);
return res;
}

View File

@ -0,0 +1,68 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef __OSTREE_CHECKSUM_INPUT_STREAM_H__
#define __OSTREE_CHECKSUM_INPUT_STREAM_H__
#include <gio/gio.h>
G_BEGIN_DECLS
#define OSTREE_TYPE_CHECKSUM_INPUT_STREAM (ostree_checksum_input_stream_get_type ())
#define OSTREE_CHECKSUM_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_CHECKSUM_INPUT_STREAM, OstreeChecksumInputStream))
#define OSTREE_CHECKSUM_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_CHECKSUM_INPUT_STREAM, OstreeChecksumInputStreamClass))
#define OSTREE_IS_CHECKSUM_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_CHECKSUM_INPUT_STREAM))
#define OSTREE_IS_CHECKSUM_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_CHECKSUM_INPUT_STREAM))
#define OSTREE_CHECKSUM_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_CHECKSUM_INPUT_STREAM, OstreeChecksumInputStreamClass))
typedef struct _OstreeChecksumInputStream OstreeChecksumInputStream;
typedef struct _OstreeChecksumInputStreamClass OstreeChecksumInputStreamClass;
typedef struct _OstreeChecksumInputStreamPrivate OstreeChecksumInputStreamPrivate;
struct _OstreeChecksumInputStream
{
GFilterInputStream parent_instance;
/*< private >*/
OstreeChecksumInputStreamPrivate *priv;
};
struct _OstreeChecksumInputStreamClass
{
GFilterInputStreamClass parent_class;
/*< private >*/
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType ostree_checksum_input_stream_get_type (void) G_GNUC_CONST;
OstreeChecksumInputStream * ostree_checksum_input_stream_new (GInputStream *stream,
GChecksum *checksum);
G_END_DECLS
#endif /* __OSTREE_CHECKSUM_INPUT_STREAM_H__ */

View File

@ -79,15 +79,63 @@ ostree_validate_rev (const char *rev,
}
void
ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode)
ostree_checksum_update_meta (GChecksum *checksum,
GFileInfo *file_info,
GVariant *xattrs)
{
guint32 mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
guint32 uid = g_file_info_get_attribute_uint32 (file_info, "unix::uid");
guint32 gid = g_file_info_get_attribute_uint32 (file_info, "unix::gid");
guint32 perms;
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR
|| g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
/* Nothing */
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
{
const char *symlink_target = g_file_info_get_symlink_target (file_info);
g_assert (symlink_target != NULL);
g_checksum_update (checksum, (guint8*)symlink_target, strlen (symlink_target));
}
else if (S_ISCHR(mode) || S_ISBLK(mode))
{
guint32 rdev = g_file_info_get_attribute_uint32 (file_info, "unix::rdev");
rdev = GUINT32_TO_BE (rdev);
g_checksum_update (checksum, (guint8*)&rdev, 4);
}
else if (S_ISFIFO(mode))
{
/* Nothing */
}
else
{
g_assert_not_reached ();
}
perms = GUINT32_TO_BE (mode & ~S_IFMT);
uid = GUINT32_TO_BE (uid);
gid = GUINT32_TO_BE (gid);
g_checksum_update (checksum, (guint8*) &uid, 4);
g_checksum_update (checksum, (guint8*) &gid, 4);
g_checksum_update (checksum, (guint8*) &perms, 4);
if (xattrs)
{
g_checksum_update (checksum, (guint8*)g_variant_get_data (xattrs),
g_variant_get_size (xattrs));
}
else
{
ot_lvariant GVariant *tmp_attrs = g_variant_new_array (G_VARIANT_TYPE ("(ayay)"),
NULL, 0);
g_variant_ref_sink (tmp_attrs);
g_checksum_update (checksum, (guint8*)g_variant_get_data (tmp_attrs),
g_variant_get_size (tmp_attrs));
}
}
static char *
@ -220,87 +268,71 @@ gboolean
ostree_checksum_file_from_input (GFileInfo *file_info,
GVariant *xattrs,
GInputStream *in,
OstreeObjectType objtype,
GChecksum **out_checksum,
OstreeObjectType objtype,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
guint8 buf[8192];
gsize bytes_read;
guint32 mode;
ot_lvariant GVariant *dirmeta = NULL;
GChecksum *ret_checksum = NULL;
ot_lfree guchar *ret_csum = NULL;
GChecksum *checksum = NULL;
checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (OSTREE_OBJECT_TYPE_IS_META (objtype))
return ot_gio_checksum_stream (in, out_checksum, cancellable, error);
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
dirmeta = ostree_create_directory_metadata (file_info, xattrs);
g_checksum_update (ret_checksum, g_variant_get_data (dirmeta),
g_variant_get_size (dirmeta));
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
{
while ((bytes_read = g_input_stream_read (in, buf, sizeof (buf), cancellable, error)) > 0)
g_checksum_update (ret_checksum, buf, bytes_read);
if (bytes_read < 0)
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
goto out;
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK)
{
const char *symlink_target = g_file_info_get_symlink_target (file_info);
g_assert (symlink_target != NULL);
g_checksum_update (ret_checksum, (guint8*)symlink_target, strlen (symlink_target));
}
else if (S_ISCHR(mode) || S_ISBLK(mode))
{
guint32 rdev = g_file_info_get_attribute_uint32 (file_info, "unix::rdev");
rdev = GUINT32_TO_BE (rdev);
g_checksum_update (ret_checksum, (guint8*)&rdev, 4);
}
else if (S_ISFIFO(mode))
{
;
}
else
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Unsupported file (must be regular, symbolic link, fifo, or character/block device)");
goto out;
mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
dirmeta = ostree_create_directory_metadata (file_info, xattrs);
g_checksum_update (checksum, g_variant_get_data (dirmeta),
g_variant_get_size (dirmeta));
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
{
if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
goto out;
}
else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_SYMBOLIC_LINK
|| S_ISCHR(mode) || S_ISBLK(mode)
|| S_ISFIFO(mode))
{
/* We update the checksum below */
}
else
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
"Unsupported file (must be regular, symbolic link, fifo, or character/block device)");
goto out;
}
if (objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
ostree_checksum_update_meta (checksum, file_info, xattrs);
}
if (objtype != OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT)
{
ostree_checksum_update_stat (ret_checksum,
g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
g_file_info_get_attribute_uint32 (file_info, "unix::gid"),
g_file_info_get_attribute_uint32 (file_info, "unix::mode"));
/* FIXME - ensure empty xattrs are the same as NULL xattrs */
if (xattrs)
g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
}
ret_csum = ot_csum_from_gchecksum (checksum);
ret = TRUE;
ot_transfer_out_value (out_checksum, &ret_checksum);
ot_transfer_out_value (out_csum, &ret_csum);
out:
ot_clear_checksum (&ret_checksum);
ot_clear_checksum (&checksum);
return ret;
}
gboolean
ostree_checksum_file (GFile *f,
OstreeObjectType objtype,
GChecksum **out_checksum,
OstreeObjectType objtype,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
@ -308,7 +340,7 @@ ostree_checksum_file (GFile *f,
ot_lobj GFileInfo *file_info = NULL;
ot_lobj GInputStream *in = NULL;
ot_lvariant GVariant *xattrs = NULL;
GChecksum *ret_checksum = NULL;
ot_lfree guchar *ret_csum = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@ -333,20 +365,19 @@ ostree_checksum_file (GFile *f,
}
if (!ostree_checksum_file_from_input (file_info, xattrs, in, objtype,
&ret_checksum, cancellable, error))
&ret_csum, cancellable, error))
goto out;
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
ot_transfer_out_value(out_csum, &ret_csum);
out:
ot_clear_checksum(&ret_checksum);
return ret;
}
typedef struct {
GFile *f;
OstreeObjectType objtype;
GChecksum *checksum;
guchar *csum;
} ChecksumFileAsyncData;
static void
@ -356,13 +387,13 @@ checksum_file_async_thread (GSimpleAsyncResult *res,
{
GError *error = NULL;
ChecksumFileAsyncData *data;
GChecksum *checksum = NULL;
guchar *csum = NULL;
data = g_simple_async_result_get_op_res_gpointer (res);
if (!ostree_checksum_file (data->f, data->objtype, &checksum, cancellable, &error))
if (!ostree_checksum_file (data->f, data->objtype, &csum, cancellable, &error))
g_simple_async_result_take_error (res, error);
else
data->checksum = checksum;
data->csum = csum;
}
static void
@ -371,7 +402,7 @@ checksum_file_async_data_free (gpointer datap)
ChecksumFileAsyncData *data = datap;
g_object_unref (data->f);
ot_clear_checksum (&data->checksum);
g_free (data->csum);
g_free (data);
}
@ -400,7 +431,7 @@ ostree_checksum_file_async (GFile *f,
gboolean
ostree_checksum_file_async_finish (GFile *f,
GAsyncResult *result,
GChecksum **out_checksum,
guchar **out_csum,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
@ -413,8 +444,8 @@ ostree_checksum_file_async_finish (GFile *f,
data = g_simple_async_result_get_op_res_gpointer (simple);
/* Transfer ownership */
*out_checksum = data->checksum;
data->checksum = NULL;
*out_csum = data->csum;
data->csum = NULL;
return TRUE;
}
@ -810,21 +841,13 @@ ostree_create_file_from_input (GFile *dest_file,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
OstreeObjectType objtype,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
const char *dest_path;
guint32 uid, gid, mode;
gboolean is_meta;
gboolean is_archived_content;
ot_lobj GFileOutputStream *out = NULL;
GChecksum *ret_checksum = NULL;
is_meta = OSTREE_OBJECT_TYPE_IS_META (objtype);
is_archived_content = objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@ -832,12 +855,6 @@ ostree_create_file_from_input (GFile *dest_file,
if (finfo != NULL)
{
mode = g_file_info_get_attribute_uint32 (finfo, "unix::mode");
/* Archived content files should always be readable by all and
* read/write by owner. If the base file is executable then
* we're also executable.
*/
if (is_archived_content)
mode |= 0644;
}
else
{
@ -861,9 +878,8 @@ ostree_create_file_from_input (GFile *dest_file,
if (input)
{
if (!ot_gio_splice_and_checksum ((GOutputStream*)out, input,
out_checksum ? &ret_checksum : NULL,
cancellable, error))
if (g_output_stream_splice ((GOutputStream*)out, input, 0,
cancellable, error) < 0)
goto out;
}
@ -873,11 +889,6 @@ ostree_create_file_from_input (GFile *dest_file,
else if (S_ISLNK (mode))
{
const char *target = g_file_info_get_attribute_byte_string (finfo, "standard::symlink-target");
g_assert (!is_meta);
if (out_checksum)
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (ret_checksum)
g_checksum_update (ret_checksum, (guint8*)target, strlen (target));
if (symlink (target, dest_path) < 0)
{
ot_util_set_error_from_errno (error, errno);
@ -887,13 +898,6 @@ ostree_create_file_from_input (GFile *dest_file,
else if (S_ISCHR (mode) || S_ISBLK (mode))
{
guint32 dev = g_file_info_get_attribute_uint32 (finfo, "unix::rdev");
guint32 dev_be;
g_assert (!is_meta);
dev_be = GUINT32_TO_BE (dev);
if (out_checksum)
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (ret_checksum)
g_checksum_update (ret_checksum, (guint8*)&dev_be, 4);
if (mknod (dest_path, mode, dev) < 0)
{
ot_util_set_error_from_errno (error, errno);
@ -902,9 +906,6 @@ ostree_create_file_from_input (GFile *dest_file,
}
else if (S_ISFIFO (mode))
{
g_assert (!is_meta);
if (out_checksum)
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (mkfifo (dest_path, mode) < 0)
{
ot_util_set_error_from_errno (error, errno);
@ -918,7 +919,7 @@ ostree_create_file_from_input (GFile *dest_file,
goto out;
}
if (finfo != NULL && !is_meta && !is_archived_content)
if (finfo != NULL)
{
uid = g_file_info_get_attribute_uint32 (finfo, "unix::uid");
gid = g_file_info_get_attribute_uint32 (finfo, "unix::gid");
@ -941,31 +942,16 @@ ostree_create_file_from_input (GFile *dest_file,
if (xattrs != NULL)
{
g_assert (!is_meta);
if (!ostree_set_xattrs (dest_file, xattrs, cancellable, error))
goto out;
}
if (ret_checksum && !is_meta && !is_archived_content)
{
g_assert (finfo != NULL);
ostree_checksum_update_stat (ret_checksum,
g_file_info_get_attribute_uint32 (finfo, "unix::uid"),
g_file_info_get_attribute_uint32 (finfo, "unix::gid"),
mode);
if (xattrs)
g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
}
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
if (!ret && !S_ISDIR(mode))
{
(void) unlink (dest_path);
}
ot_clear_checksum (&ret_checksum);
return ret;
}
@ -1016,9 +1002,7 @@ ostree_create_temp_file_from_input (GFile *dir,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
OstreeObjectType objtype,
GFile **out_file,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error)
{
@ -1027,7 +1011,7 @@ ostree_create_temp_file_from_input (GFile *dir,
int i = 0;
ot_lfree char *possible_name = NULL;
ot_lobj GFile *possible_file = NULL;
GChecksum *ret_checksum = NULL;
ot_lfree guchar *ret_csum = NULL;
GString *tmp_name = NULL;
tmp_name = create_tmp_string (ot_gfile_get_path_cached (dir),
@ -1045,8 +1029,6 @@ ostree_create_temp_file_from_input (GFile *dir,
possible_file = g_file_get_child (dir, possible_name);
if (!ostree_create_file_from_input (possible_file, finfo, xattrs, input,
objtype,
out_checksum ? &ret_checksum : NULL,
cancellable, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
@ -1073,12 +1055,10 @@ ostree_create_temp_file_from_input (GFile *dir,
}
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
ot_transfer_out_value(out_file, &possible_file);
out:
if (tmp_name)
g_string_free (tmp_name, TRUE);
ot_clear_checksum (&ret_checksum);
return ret;
}
@ -1096,8 +1076,7 @@ ostree_create_temp_regular_file (GFile *dir,
ot_lobj GOutputStream *ret_stream = NULL;
if (!ostree_create_temp_file_from_input (dir, prefix, suffix, NULL, NULL, NULL,
OSTREE_OBJECT_TYPE_RAW_FILE, &ret_file,
NULL, cancellable, error))
&ret_file, cancellable, error))
goto out;
ret_stream = (GOutputStream*)g_file_append_to (ret_file, 0, cancellable, error);

View File

@ -147,7 +147,7 @@ int ostree_cmp_checksum_bytes (const guchar *a, const guchar *b);
gboolean ostree_validate_rev (const char *rev, GError **error);
void ostree_checksum_update_stat (GChecksum *checksum, guint32 uid, guint32 gid, guint32 mode);
void ostree_checksum_update_meta (GChecksum *checksum, GFileInfo *file_info, GVariant *xattrs);
const char * ostree_object_type_to_string (OstreeObjectType objtype);
@ -199,13 +199,13 @@ gboolean ostree_checksum_file_from_input (GFileInfo *file_info,
GVariant *xattrs,
GInputStream *in,
OstreeObjectType objtype,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error);
gboolean ostree_checksum_file (GFile *f,
OstreeObjectType type,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error);
@ -218,7 +218,7 @@ void ostree_checksum_file_async (GFile *f,
gboolean ostree_checksum_file_async_finish (GFile *f,
GAsyncResult *result,
GChecksum **out_checksum,
guchar **out_csum,
GError **error);
GVariant *ostree_create_directory_metadata (GFileInfo *dir_info,
@ -228,8 +228,6 @@ gboolean ostree_create_file_from_input (GFile *file,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
OstreeObjectType objtype,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error);
@ -239,9 +237,7 @@ gboolean ostree_create_temp_file_from_input (GFile *dir,
GFileInfo *finfo,
GVariant *xattrs,
GInputStream *input,
OstreeObjectType objtype,
GFile **out_file,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error);

View File

@ -764,7 +764,7 @@ stage_object_impl (OstreeRepo *self,
GVariant *xattrs,
GInputStream *input,
const char *expected_checksum,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error);
@ -810,7 +810,7 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
GVariant *xattrs,
GInputStream *input,
const char *expected_checksum,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
@ -822,7 +822,16 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
ot_lobj GFile *meta_temp_file = NULL;
ot_lobj GFile *content_temp_file = NULL;
ot_lobj GInputStream *mem = NULL;
GChecksum *ret_checksum = NULL;
ot_lobj OstreeChecksumInputStream *checksum_input = NULL;
ot_lfree guchar *ret_csum = NULL;
GChecksum *checksum = NULL;
if (expected_checksum || out_csum)
{
checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (input)
checksum_input = ostree_checksum_input_stream_new (input, checksum);
}
archive_metadata = ostree_create_archive_file_metadata (file_info, xattrs);
@ -833,42 +842,36 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
if (!ostree_create_temp_file_from_input (priv->tmp_dir,
"archive-tmp-", NULL,
NULL, NULL, mem,
OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META,
&meta_temp_file,
NULL,
cancellable, error))
goto out;
temp_info = dup_file_info_owned_by_me (file_info);
/* Archived content files should always be readable by all and
* read/write by owner. If the base file is executable then
* we're also executable.
*/
g_file_info_set_attribute_uint32 (temp_info, "unix::mode",
g_file_info_get_attribute_uint32 (file_info, "unix::mode") | 0644);
if (!ostree_create_temp_file_from_input (priv->tmp_dir,
"archive-tmp-", NULL,
temp_info, NULL, input,
OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
temp_info, NULL,
checksum_input ? (GInputStream*)checksum_input : input,
&content_temp_file,
out_checksum ? &ret_checksum : NULL,
cancellable, error))
goto out;
if (out_checksum)
{
g_assert (ret_checksum);
ostree_checksum_update_stat (ret_checksum,
g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
g_file_info_get_attribute_uint32 (file_info, "unix::gid"),
g_file_info_get_attribute_uint32 (file_info, "unix::mode"));
/* FIXME - ensure empty xattrs are the same as NULL xattrs */
if (xattrs)
g_checksum_update (ret_checksum, (guint8*)g_variant_get_data (xattrs), g_variant_get_size (xattrs));
}
if (checksum)
ostree_checksum_update_meta (checksum, file_info, xattrs);
if (expected_checksum && ret_checksum)
if (expected_checksum && checksum)
{
if (strcmp (g_checksum_get_string (ret_checksum), expected_checksum) != 0)
if (strcmp (g_checksum_get_string (checksum), expected_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Corrupted %s object %s (actual checksum is %s)",
ostree_object_type_to_string (OSTREE_OBJECT_TYPE_RAW_FILE),
expected_checksum, g_checksum_get_string (ret_checksum));
expected_checksum, g_checksum_get_string (checksum));
goto out;
}
actual_checksum = expected_checksum;
@ -876,7 +879,7 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
else if (expected_checksum)
actual_checksum = expected_checksum;
else
actual_checksum = g_checksum_get_string (ret_checksum);
actual_checksum = g_checksum_get_string (checksum);
if (!commit_tmpfile_trusted (self, actual_checksum, OSTREE_OBJECT_TYPE_ARCHIVED_FILE_CONTENT,
content_temp_file, cancellable, error))
@ -886,10 +889,13 @@ impl_stage_archive_file_object_from_raw (OstreeRepo *self,
meta_temp_file, cancellable, error))
goto out;
if (checksum)
ret_csum = ot_csum_from_gchecksum (checksum);
ret = TRUE;
ot_transfer_out_value (out_checksum, &ret_checksum);
ot_transfer_out_value (out_csum, &ret_csum);
out:
ot_clear_checksum (&ret_checksum);
ot_clear_checksum (&checksum);
return ret;
}
@ -901,7 +907,7 @@ stage_object_impl (OstreeRepo *self,
GVariant *xattrs,
GInputStream *input,
const char *expected_checksum,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
@ -913,14 +919,16 @@ stage_object_impl (OstreeRepo *self,
ot_lobj GFile *temp_file = NULL;
ot_lobj GFile *stored_path = NULL;
ot_lfree char *pack_checksum = NULL;
GChecksum *ret_checksum = NULL;
ot_lfree guchar *ret_csum = NULL;
ot_lobj OstreeChecksumInputStream *checksum_input = NULL;
GChecksum *checksum = NULL;
g_return_val_if_fail (priv->in_transaction, FALSE);
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
g_assert (expected_checksum || out_checksum);
g_assert (expected_checksum || out_csum);
if (expected_checksum)
{
@ -961,26 +969,35 @@ stage_object_impl (OstreeRepo *self,
{
if (!impl_stage_archive_file_object_from_raw (self, file_info, xattrs, input,
expected_checksum,
out_checksum ? &ret_checksum : NULL,
out_csum ? &ret_csum : NULL,
cancellable, error))
goto out;
}
else
else
{
if (out_csum)
{
checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (input)
checksum_input = ostree_checksum_input_stream_new (input, checksum);
}
if (!ostree_create_temp_file_from_input (priv->tmp_dir,
ostree_object_type_to_string (objtype), NULL,
file_info, xattrs, input,
objtype,
file_info, xattrs,
checksum_input ? (GInputStream*)checksum_input : input,
&temp_file,
out_checksum ? &ret_checksum : NULL,
cancellable, error))
goto out;
if (checksum && !OSTREE_OBJECT_TYPE_IS_META (objtype))
ostree_checksum_update_meta (checksum, file_info, xattrs);
if (!ret_checksum)
if (!checksum)
actual_checksum = expected_checksum;
else
{
actual_checksum = g_checksum_get_string (ret_checksum);
actual_checksum = g_checksum_get_string (checksum);
if (expected_checksum && strcmp (actual_checksum, expected_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@ -995,6 +1012,9 @@ stage_object_impl (OstreeRepo *self,
temp_file, cancellable, error))
goto out;
g_clear_object (&temp_file);
if (checksum)
ret_csum = ot_csum_from_gchecksum (checksum);
}
}
else
@ -1004,11 +1024,11 @@ stage_object_impl (OstreeRepo *self,
}
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
ot_transfer_out_value(out_csum, &ret_csum);
out:
if (temp_file)
(void) unlink (ot_gfile_get_path_cached (temp_file));
ot_clear_checksum (&ret_checksum);
ot_clear_checksum (&checksum);
return ret;
}
@ -1064,13 +1084,12 @@ static gboolean
stage_gvariant_object (OstreeRepo *self,
OstreeObjectType type,
GVariant *variant,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
ot_lobj GInputStream *mem = NULL;
GChecksum *ret_checksum = NULL;
mem = g_memory_input_stream_new_from_data (g_variant_get_data (variant),
g_variant_get_size (variant),
@ -1078,13 +1097,11 @@ stage_gvariant_object (OstreeRepo *self,
if (!stage_object_impl (self, type, FALSE,
NULL, NULL, mem,
NULL, &ret_checksum, cancellable, error))
NULL, out_csum, cancellable, error))
goto out;
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
ot_clear_checksum (&ret_checksum);
return ret;
}
@ -1092,13 +1109,12 @@ static gboolean
stage_directory_meta (OstreeRepo *self,
GFileInfo *file_info,
GVariant *xattrs,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
ot_lvariant GVariant *dirmeta = NULL;
GChecksum *ret_checksum = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@ -1106,13 +1122,11 @@ stage_directory_meta (OstreeRepo *self,
dirmeta = ostree_create_directory_metadata (file_info, xattrs);
if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_META,
dirmeta, &ret_checksum, cancellable, error))
dirmeta, out_csum, cancellable, error))
goto out;
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
ot_clear_checksum (&ret_checksum);
return ret;
}
@ -1159,16 +1173,16 @@ ostree_repo_stage_object (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
GChecksum *actual_checksum = NULL;
ot_lfree guchar *actual_csum = NULL;
if (!stage_object_impl (self, objtype, FALSE,
file_info, xattrs, input,
expected_checksum, &actual_checksum, cancellable, error))
expected_checksum, &actual_csum,
cancellable, error))
goto out;
ret = TRUE;
out:
ot_clear_checksum (&actual_checksum);
return ret;
}
@ -1352,7 +1366,7 @@ ostree_repo_stage_commit (OstreeRepo *self,
gboolean ret = FALSE;
ot_lfree char *ret_commit = NULL;
ot_lvariant GVariant *commit = NULL;
GChecksum *ret_commit_obj = NULL;
ot_lfree guchar *commit_csum = NULL;
GDateTime *now = NULL;
g_return_val_if_fail (branch != NULL, FALSE);
@ -1372,15 +1386,14 @@ ostree_repo_stage_commit (OstreeRepo *self,
ostree_checksum_to_bytes_v (root_metadata_checksum));
g_variant_ref_sink (commit);
if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_COMMIT,
commit, &ret_commit_obj, NULL, error))
commit, &commit_csum, cancellable, error))
goto out;
ret_commit = g_strdup (g_checksum_get_string (ret_commit_obj));
ret_commit = ostree_checksum_from_bytes (commit_csum);
ret = TRUE;
ot_transfer_out_value(out_commit, &ret_commit);
out:
ot_clear_checksum (&ret_commit_obj);
if (now)
g_date_time_unref (now);
return ret;
@ -2344,7 +2357,8 @@ stage_directory_to_mtree_internal (OstreeRepo *self,
ot_lobj GFile *child = NULL;
ot_lvariant GVariant *xattrs = NULL;
ot_lobj GInputStream *file_input = NULL;
GChecksum *child_file_checksum = NULL;
ot_lfree guchar *child_file_csum = NULL;
ot_lfree char *tmp_checksum = NULL;
/* We can only reuse checksums directly if there's no modifier */
if (OSTREE_IS_REPO_FILE (dir) && modifier == NULL)
@ -2380,11 +2394,13 @@ stage_directory_to_mtree_internal (OstreeRepo *self,
goto out;
}
if (!stage_directory_meta (self, modified_info, xattrs, &child_file_checksum,
if (!stage_directory_meta (self, modified_info, xattrs, &child_file_csum,
cancellable, error))
goto out;
ostree_mutable_tree_set_metadata_checksum (mtree, g_checksum_get_string (child_file_checksum));
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (child_file_csum);
ostree_mutable_tree_set_metadata_checksum (mtree, tmp_checksum);
g_clear_object (&child_info);
g_clear_object (&modified_info);
@ -2432,10 +2448,7 @@ stage_directory_to_mtree_internal (OstreeRepo *self,
}
else
{
ot_clear_checksum (&child_file_checksum);
ot_clear_gvariant (&xattrs);
g_clear_object (&file_input);
if (g_file_info_get_file_type (modified_info) == G_FILE_TYPE_REGULAR)
{
file_input = (GInputStream*)g_file_read (child, cancellable, error);
@ -2445,17 +2458,21 @@ stage_directory_to_mtree_internal (OstreeRepo *self,
if (!(modifier && modifier->skip_xattrs))
{
ot_clear_gvariant (&xattrs);
if (!ostree_get_xattrs_for_file (child, &xattrs, cancellable, error))
goto out;
}
g_free (child_file_csum);
child_file_csum = NULL;
if (!stage_object_impl (self, OSTREE_OBJECT_TYPE_RAW_FILE, FALSE,
modified_info, xattrs, file_input, NULL,
&child_file_checksum, cancellable, error))
&child_file_csum, cancellable, error))
goto out;
if (!ostree_mutable_tree_replace_file (mtree, name,
g_checksum_get_string (child_file_checksum),
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (child_file_csum);
if (!ostree_mutable_tree_replace_file (mtree, name, tmp_checksum,
error))
goto out;
}
@ -2477,7 +2494,6 @@ stage_directory_to_mtree_internal (OstreeRepo *self,
ret = TRUE;
out:
ot_clear_checksum (&child_file_checksum);
return ret;
}
@ -2518,7 +2534,7 @@ ostree_repo_stage_mtree (OstreeRepo *self,
ot_lhash GHashTable *dir_metadata_checksums = NULL;
ot_lhash GHashTable *dir_contents_checksums = NULL;
ot_lvariant GVariant *serialized_tree = NULL;
GChecksum *ret_contents_checksum_obj = NULL;
ot_lfree guchar *contents_csum = NULL;
existing_checksum = ostree_mutable_tree_get_contents_checksum (mtree);
if (existing_checksum)
@ -2558,16 +2574,15 @@ ostree_repo_stage_mtree (OstreeRepo *self,
dir_metadata_checksums);
if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_TREE,
serialized_tree, &ret_contents_checksum_obj,
serialized_tree, &contents_csum,
cancellable, error))
goto out;
ret_contents_checksum = g_strdup (g_checksum_get_string (ret_contents_checksum_obj));
ret_contents_checksum = ostree_checksum_from_bytes (contents_csum);
}
ret = TRUE;
ot_transfer_out_value(out_contents_checksum, &ret_contents_checksum);
out:
ot_clear_checksum (&ret_contents_checksum_obj);
return ret;
}
@ -2624,13 +2639,12 @@ import_libarchive_entry_file (OstreeRepo *self,
struct archive *a,
struct archive_entry *entry,
GFileInfo *file_info,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
ot_lobj GInputStream *archive_stream = NULL;
GChecksum *ret_checksum = NULL;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return FALSE;
@ -2640,14 +2654,12 @@ import_libarchive_entry_file (OstreeRepo *self,
if (!stage_object_impl (self, OSTREE_OBJECT_TYPE_RAW_FILE, FALSE,
file_info, NULL, archive_stream,
NULL, &ret_checksum,
NULL, out_csum,
cancellable, error))
goto out;
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
ot_clear_checksum (&ret_checksum);
return ret;
}
@ -2657,7 +2669,7 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
struct archive *a,
struct archive_entry *entry,
OstreeRepoCommitModifier *modifier,
const char *tmp_dir_checksum,
const guchar *tmp_dir_csum,
GCancellable *cancellable,
GError **error)
{
@ -2673,7 +2685,8 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
ot_lobj OstreeMutableTree *hardlink_source_parent = NULL;
ot_lfree char *hardlink_source_checksum = NULL;
ot_lobj OstreeMutableTree *hardlink_source_subdir = NULL;
GChecksum *tmp_checksum = NULL;
ot_lfree guchar *tmp_csum = NULL;
ot_lfree char *tmp_checksum = NULL;
pathname = archive_entry_pathname (entry);
@ -2687,10 +2700,12 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
}
else
{
if (tmp_dir_checksum)
if (tmp_dir_csum)
{
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (tmp_dir_csum);
if (!ostree_mutable_tree_ensure_parent_dirs (root, split_path,
tmp_dir_checksum,
tmp_checksum,
&parent,
error))
goto out;
@ -2762,7 +2777,7 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
if (!stage_directory_meta (self, file_info, NULL, &tmp_checksum, cancellable, error))
if (!stage_directory_meta (self, file_info, NULL, &tmp_csum, cancellable, error))
goto out;
if (parent == NULL)
@ -2775,7 +2790,9 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
goto out;
}
ostree_mutable_tree_set_metadata_checksum (subdir, g_checksum_get_string (tmp_checksum));
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (tmp_csum);
ostree_mutable_tree_set_metadata_checksum (subdir, tmp_checksum);
}
else
{
@ -2786,11 +2803,13 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
goto out;
}
if (!import_libarchive_entry_file (self, a, entry, file_info, &tmp_checksum, cancellable, error))
if (!import_libarchive_entry_file (self, a, entry, file_info, &tmp_csum, cancellable, error))
goto out;
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (tmp_csum);
if (!ostree_mutable_tree_replace_file (parent, basename,
g_checksum_get_string (tmp_checksum),
tmp_checksum,
error))
goto out;
}
@ -2798,7 +2817,6 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
ret = TRUE;
out:
ot_clear_checksum (&tmp_checksum);
return ret;
}
#endif
@ -2818,7 +2836,7 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
struct archive_entry *entry;
int r;
ot_lobj GFileInfo *tmp_dir_info = NULL;
GChecksum *tmp_dir_checksum = NULL;
ot_lfree guchar *tmp_csum = NULL;
a = archive_read_new ();
archive_read_support_compression_all (a);
@ -2840,7 +2858,7 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
goto out;
}
if (autocreate_parents && !tmp_dir_checksum)
if (autocreate_parents && !tmp_csum)
{
tmp_dir_info = g_file_info_new ();
@ -2848,13 +2866,13 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", archive_entry_gid (entry));
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
if (!stage_directory_meta (self, tmp_dir_info, NULL, &tmp_dir_checksum, cancellable, error))
if (!stage_directory_meta (self, tmp_dir_info, NULL, &tmp_csum, cancellable, error))
goto out;
}
if (!stage_libarchive_entry_to_mtree (self, root, a,
entry, modifier,
autocreate_parents ? g_checksum_get_string (tmp_dir_checksum) : NULL,
autocreate_parents ? tmp_csum : NULL,
cancellable, error))
goto out;
}
@ -2866,7 +2884,6 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
ret = TRUE;
out:
ot_clear_checksum (&tmp_dir_checksum);
if (a)
(void)archive_read_close (a);
return ret;
@ -3626,8 +3643,8 @@ checkout_file_from_input (GFile *file,
if (g_file_info_get_file_type (temp_info ? temp_info : finfo) == G_FILE_TYPE_DIRECTORY)
{
if (!ostree_create_file_from_input (file, temp_info ? temp_info : finfo,
xattrs, input, OSTREE_OBJECT_TYPE_RAW_FILE,
NULL, cancellable, &temp_error))
xattrs, input,
cancellable, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
{
@ -3645,8 +3662,7 @@ checkout_file_from_input (GFile *file,
dir = g_file_get_parent (file);
if (!ostree_create_temp_file_from_input (dir, NULL, "checkout",
temp_info ? temp_info : finfo,
xattrs, input, OSTREE_OBJECT_TYPE_RAW_FILE,
&temp_file, NULL,
xattrs, input, &temp_file,
cancellable, error))
goto out;
@ -3660,8 +3676,7 @@ checkout_file_from_input (GFile *file,
else
{
if (!ostree_create_file_from_input (file, temp_info ? temp_info : finfo,
xattrs, input, OSTREE_OBJECT_TYPE_RAW_FILE,
NULL, cancellable, error))
xattrs, input, cancellable, error))
goto out;
}

View File

@ -22,6 +22,7 @@
#ifndef __OSTREE_H__
#include <ostree-checksum-input-stream.h>
#include <ostree-core.h>
#include <ostree-repo.h>
#include <ostree-mutable-tree.h>

View File

@ -0,0 +1,38 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include "otutil.h"
#include <string.h>
guchar *
ot_csum_from_gchecksum (GChecksum *checksum)
{
guchar *ret = g_malloc (32);
gsize len = 32;
g_checksum_get_digest (checksum, ret, &len);
g_assert (len == 32);
return ret;
}

View File

@ -0,0 +1,34 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#ifndef __OSTREE_CHECKSUM_UTILS_H__
#define __OSTREE_CHECKSUM_UTILS_H__
#include <gio/gio.h>
G_BEGIN_DECLS
guchar *ot_csum_from_gchecksum (GChecksum *checksum);
G_END_DECLS
#endif

View File

@ -229,21 +229,17 @@ ot_gfile_get_basename_cached (GFile *file)
}
gboolean
ot_gio_splice_and_checksum (GOutputStream *out,
GInputStream *in,
GChecksum **out_checksum,
GCancellable *cancellable,
GError **error)
ot_gio_splice_update_checksum (GOutputStream *out,
GInputStream *in,
GChecksum *checksum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GChecksum *ret_checksum = NULL;
g_return_val_if_fail (out != NULL || out_checksum != NULL, FALSE);
g_return_val_if_fail (out != NULL || checksum != NULL, FALSE);
if (out_checksum)
ret_checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (ret_checksum != NULL)
if (checksum != NULL)
{
gsize bytes_read, bytes_written;
char buf[4096];
@ -251,8 +247,7 @@ ot_gio_splice_and_checksum (GOutputStream *out,
{
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);
g_checksum_update (checksum, (guint8*)buf, bytes_read);
if (out)
{
if (!g_output_stream_write_all (out, buf, bytes_read, &bytes_written, cancellable, error))
@ -268,21 +263,44 @@ ot_gio_splice_and_checksum (GOutputStream *out,
}
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
ot_clear_checksum (&ret_checksum);
return ret;
}
gboolean
ot_gio_splice_get_checksum (GOutputStream *out,
GInputStream *in,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GChecksum *checksum = NULL;
ot_lfree guchar *ret_csum = NULL;
checksum = g_checksum_new (G_CHECKSUM_SHA256);
if (!ot_gio_splice_update_checksum (out, in, checksum, cancellable, error))
goto out;
ret_csum = ot_csum_from_gchecksum (checksum);
ret = TRUE;
ot_transfer_out_value (out_csum, &ret_csum);
out:
ot_clear_checksum (&checksum);
return ret;
}
gboolean
ot_gio_checksum_stream (GInputStream *in,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error)
{
if (!out_checksum)
if (!out_csum)
return TRUE;
return ot_gio_splice_and_checksum (NULL, in, out_checksum, cancellable, error);
return ot_gio_splice_get_checksum (NULL, in, out_csum, cancellable, error);
}
gboolean

View File

@ -61,14 +61,20 @@ gboolean ot_gfile_load_contents_utf8 (GFile *file,
GCancellable *cancellable,
GError **error);
gboolean ot_gio_splice_and_checksum (GOutputStream *out,
gboolean ot_gio_splice_get_checksum (GOutputStream *out,
GInputStream *in,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error);
gboolean ot_gio_splice_update_checksum (GOutputStream *out,
GInputStream *in,
GChecksum *checksum,
GCancellable *cancellable,
GError **error);
gboolean ot_gio_checksum_stream (GInputStream *in,
GChecksum **out_checksum,
guchar **out_csum,
GCancellable *cancellable,
GError **error);

View File

@ -159,9 +159,9 @@ ot_util_variant_from_stream (GInputStream *src,
data_stream = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
if (!g_output_stream_splice ((GOutputStream*)data_stream, src,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
cancellable, error))
if (g_output_stream_splice ((GOutputStream*)data_stream, src,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
cancellable, error) < 0)
goto out;
ret_variant = g_variant_new_from_data (type, g_memory_output_stream_get_data (data_stream),

View File

@ -47,5 +47,6 @@
#include <ot-opt-utils.h>
#include <ot-unix-utils.h>
#include <ot-variant-utils.h>
#include <ot-checksum-utils.h>
#endif

View File

@ -41,14 +41,14 @@ on_checksum_received (GObject *obj,
GAsyncResult *result,
gpointer user_data)
{
GChecksum *checksum = NULL;
ot_lfree guchar *csum = NULL;
ot_lfree char *checksum = NULL;
AsyncChecksumData *data = user_data;
if (ostree_checksum_file_async_finish ((GFile*)obj, result, &checksum, data->error))
if (ostree_checksum_file_async_finish ((GFile*)obj, result, &csum, data->error))
{
g_print ("%s\n", g_checksum_get_string (checksum));
ot_clear_checksum (&checksum);
checksum = ostree_checksum_from_bytes (csum);
g_print ("%s\n", checksum);
}
g_main_loop_quit (data->loop);

View File

@ -69,7 +69,7 @@ get_file_checksum (GFile *f,
{
gboolean ret = FALSE;
ot_lfree char *ret_checksum = NULL;
GChecksum *tmp_checksum = NULL;
ot_lfree guchar *csum = NULL;
if (OSTREE_IS_REPO_FILE (f))
{
@ -78,15 +78,14 @@ get_file_checksum (GFile *f,
else
{
if (!ostree_checksum_file (f, OSTREE_OBJECT_TYPE_RAW_FILE,
&tmp_checksum, cancellable, error))
&csum, cancellable, error))
goto out;
ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
ret_checksum = ostree_checksum_from_bytes (csum);
}
ret = TRUE;
ot_transfer_out_value(out_checksum, &ret_checksum);
out:
ot_clear_checksum (&tmp_checksum);
return ret;
}

View File

@ -59,7 +59,8 @@ fsck_one_pack_file (OtFsckData *data,
ot_lvariant GVariant *index_variant = NULL;
ot_lobj GFile *pack_index_path = NULL;
ot_lobj GFile *pack_data_path = NULL;
GChecksum *pack_content_checksum = NULL;
ot_lfree guchar *pack_content_csum = NULL;
ot_lfree char *tmp_checksum = NULL;
GVariantIter *index_content_iter = NULL;
g_free (path);
@ -88,14 +89,15 @@ fsck_one_pack_file (OtFsckData *data,
goto out;
pack_size = g_file_info_get_attribute_uint64 (pack_info, "standard::size");
if (!ot_gio_checksum_stream (input, &pack_content_checksum, cancellable, error))
if (!ot_gio_checksum_stream (input, &pack_content_csum, cancellable, error))
goto out;
if (strcmp (g_checksum_get_string (pack_content_checksum), pack_checksum) != 0)
tmp_checksum = ostree_checksum_from_bytes (pack_content_csum);
if (strcmp (tmp_checksum, pack_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"corrupted pack '%s', expected checksum %s",
pack_checksum, g_checksum_get_string (pack_content_checksum));
"corrupted pack '%s', actual checksum is %s",
pack_checksum, tmp_checksum);
goto out;
}
@ -119,7 +121,6 @@ fsck_one_pack_file (OtFsckData *data,
out:
if (index_content_iter)
g_variant_iter_free (index_content_iter);
ot_clear_checksum (&pack_content_checksum);
return ret;
}
@ -175,7 +176,8 @@ fsck_reachable_objects_from_commits (OtFsckData *data,
ot_lobj GFileInfo *file_info = NULL;
ot_lvariant GVariant *xattrs = NULL;
ot_lvariant GVariant *metadata = NULL;
GChecksum *computed_checksum = NULL;
ot_lfree guchar *computed_csum = NULL;
ot_lfree char *tmp_checksum = NULL;
reachable_objects = ostree_traverse_new_reachable ();
@ -277,25 +279,26 @@ fsck_reachable_objects_from_commits (OtFsckData *data,
g_assert_not_reached ();
}
ot_clear_checksum (&computed_checksum);
g_free (computed_csum);
if (!ostree_checksum_file_from_input (file_info, xattrs, input,
checksum_objtype, &computed_checksum,
checksum_objtype, &computed_csum,
cancellable, error))
goto out;
if (strcmp (checksum, g_checksum_get_string (computed_checksum)) != 0)
g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes (computed_csum);
if (strcmp (checksum, tmp_checksum) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"corrupted object %s.%s; actual checksum: %s",
checksum, ostree_object_type_to_string (objtype),
g_checksum_get_string (computed_checksum));
tmp_checksum);
goto out;
}
}
ret = TRUE;
out:
ot_clear_checksum (&computed_checksum);
return ret;
}