diff --git a/Makefile-libostree.am b/Makefile-libostree.am index e2443932..bc64cb75 100644 --- a/Makefile-libostree.am +++ b/Makefile-libostree.am @@ -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 \ diff --git a/Makefile-otutil.am b/Makefile-otutil.am index 4493564e..1bf27649 100644 --- a/Makefile-otutil.am +++ b/Makefile-otutil.am @@ -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 \ diff --git a/src/libostree/ostree-checksum-input-stream.c b/src/libostree/ostree-checksum-input-stream.c new file mode 100644 index 00000000..ef5f0d4a --- /dev/null +++ b/src/libostree/ostree-checksum-input-stream.c @@ -0,0 +1,169 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * 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 +#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; +} diff --git a/src/libostree/ostree-checksum-input-stream.h b/src/libostree/ostree-checksum-input-stream.h new file mode 100644 index 00000000..32676b07 --- /dev/null +++ b/src/libostree/ostree-checksum-input-stream.h @@ -0,0 +1,68 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * 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 + +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__ */ diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 17f026cf..f87f31cf 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -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); diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index 936c87ea..02ccb016 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -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); diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index cc92f2f5..64d65dbe 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -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; } diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h index 571aea96..a4b78450 100644 --- a/src/libostree/ostree.h +++ b/src/libostree/ostree.h @@ -22,6 +22,7 @@ #ifndef __OSTREE_H__ +#include #include #include #include diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c new file mode 100644 index 00000000..7405abfe --- /dev/null +++ b/src/libotutil/ot-checksum-utils.c @@ -0,0 +1,38 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters + * + * 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 + */ + +#include "config.h" + +#include "otutil.h" + +#include + +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; +} diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h new file mode 100644 index 00000000..e9de6387 --- /dev/null +++ b/src/libotutil/ot-checksum-utils.h @@ -0,0 +1,34 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2011 Colin Walters . + * + * 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 + */ + +#ifndef __OSTREE_CHECKSUM_UTILS_H__ +#define __OSTREE_CHECKSUM_UTILS_H__ + +#include + +G_BEGIN_DECLS + +guchar *ot_csum_from_gchecksum (GChecksum *checksum); + +G_END_DECLS + +#endif diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c index c93a7bb9..3cd72eff 100644 --- a/src/libotutil/ot-gio-utils.c +++ b/src/libotutil/ot-gio-utils.c @@ -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 diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h index 5fda5da5..59db7142 100644 --- a/src/libotutil/ot-gio-utils.h +++ b/src/libotutil/ot-gio-utils.h @@ -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); diff --git a/src/libotutil/ot-variant-utils.c b/src/libotutil/ot-variant-utils.c index 34625132..58f3e490 100644 --- a/src/libotutil/ot-variant-utils.c +++ b/src/libotutil/ot-variant-utils.c @@ -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), diff --git a/src/libotutil/otutil.h b/src/libotutil/otutil.h index d6c9fbcb..ad276d4d 100644 --- a/src/libotutil/otutil.h +++ b/src/libotutil/otutil.h @@ -47,5 +47,6 @@ #include #include #include +#include #endif diff --git a/src/ostree/ot-builtin-checksum.c b/src/ostree/ot-builtin-checksum.c index ad33394a..e42454d5 100644 --- a/src/ostree/ot-builtin-checksum.c +++ b/src/ostree/ot-builtin-checksum.c @@ -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); diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index 6d9b50e2..38a22a3f 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -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; } diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index 45ec228b..6046512d 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -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; }