[ostree/wip/archive-v3: 9/10] core: Clean up checksumming



commit 0d43b60787e03e7e461a418a03f21395e4728ed3
Author: Colin Walters <walters verbum org>
Date:   Tue Apr 10 16:40:22 2012 -0400

    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.

 Makefile-libostree.am                        |    2 +
 Makefile-otutil.am                           |    2 +
 src/libostree/ostree-checksum-input-stream.c |  169 ++++++++++++++++++
 src/libostree/ostree-checksum-input-stream.h |   68 ++++++++
 src/libostree/ostree-core.c                  |  235 ++++++++++++--------------
 src/libostree/ostree-core.h                  |   12 +-
 src/libostree/ostree-repo.c                  |  201 ++++++++++++----------
 src/libostree/ostree.h                       |    1 +
 src/libotutil/ot-checksum-utils.c            |   38 ++++
 src/libotutil/ot-checksum-utils.h            |   34 ++++
 src/libotutil/ot-gio-utils.c                 |   54 ++++--
 src/libotutil/ot-gio-utils.h                 |   12 +-
 src/libotutil/ot-variant-utils.c             |    6 +-
 src/libotutil/otutil.h                       |    1 +
 src/ostree/ot-builtin-checksum.c             |   10 +-
 src/ostree/ot-builtin-diff.c                 |    7 +-
 src/ostree/ot-builtin-fsck.c                 |   27 ++--
 17 files changed, 605 insertions(+), 274 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index e244393..bc64cb7 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 4493564..1bf2764 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 0000000..ef5f0d4
--- /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 <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;
+}
diff --git a/src/libostree/ostree-checksum-input-stream.h b/src/libostree/ostree-checksum-input-stream.h
new file mode 100644
index 0000000..32676b0
--- /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 <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__ */
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 17f026c..f87f31c 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;
-
-  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);
+  ot_lfree guchar *ret_csum = NULL;
+  GChecksum *checksum = NULL;
 
-  mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
+  checksum = g_checksum_new (G_CHECKSUM_SHA256);
 
-  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)
+  if (OSTREE_OBJECT_TYPE_IS_META (objtype))
     {
-      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 (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));
+      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);
     }
 
+  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 936c87e..02ccb01 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 cc92f2f..64d65db 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 571aea9..a4b7845 100644
--- a/src/libostree/ostree.h
+++ b/src/libostree/ostree.h
@@ -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>
diff --git a/src/libotutil/ot-checksum-utils.c b/src/libotutil/ot-checksum-utils.c
new file mode 100644
index 0000000..7405abf
--- /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 <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;
+}
diff --git a/src/libotutil/ot-checksum-utils.h b/src/libotutil/ot-checksum-utils.h
new file mode 100644
index 0000000..e9de638
--- /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 <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
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index c93a7bb..3cd72ef 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 5fda5da..59db714 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 3462513..58f3e49 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 d6c9fbc..ad276d4 100644
--- a/src/libotutil/otutil.h
+++ b/src/libotutil/otutil.h
@@ -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
diff --git a/src/ostree/ot-builtin-checksum.c b/src/ostree/ot-builtin-checksum.c
index ad33394..e42454d 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 6d9b50e..38a22a3 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 45ec228..6046512 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;
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]