All pastes #33020 Raw Edit

Untitled

public text v1 · immutable
#33020 ·published 2005-12-08 22:04 UTC
rendered paste body
Index: subversion/libsvn_subr/stream.c
===================================================================
--- subversion/libsvn_subr/stream.c     (revision 17698)
+++ subversion/libsvn_subr/stream.c     (working copy)
@@ -26,6 +26,7 @@
 #include <apr_strings.h>
 #include <apr_file_io.h>
 #include <apr_errno.h>
+#include <apr_md5.h>
  
 #ifdef SVN_HAVE_ZLIB
 #include <zlib.h>
@@ -607,6 +608,93 @@
 }
  
 
+/* MD5 checked stream support */
+
+struct md5_stream_baton
+{
+  apr_md5_ctx_t read_ctx, write_ctx;
+  unsigned char *read_digest;
+  unsigned char *write_digest;
+  svn_stream_t *proxy;
+};
+
+static svn_error_t *
+read_handler_md5 (void *baton, char *buffer, apr_size_t *len)
+{
+  struct md5_stream_baton *btn = baton;
+
+  SVN_ERR (svn_stream_read (btn->proxy, buffer, len));
+
+  if (btn->read_digest)
+    apr_md5_update (&btn->read_ctx, buffer, *len);
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+write_handler_md5 (void *baton, const char *buffer, apr_size_t *len)
+{
+  struct md5_stream_baton *btn = baton;
+
+  if (btn->write_digest)
+    apr_md5_update (&btn->write_ctx, buffer, *len);
+
+  return svn_stream_write (btn->proxy, buffer, len);
+}
+
+
+static svn_error_t *
+close_handler_md5 (void *baton)
+{
+  struct md5_stream_baton *btn = baton;
+  unsigned char digest[APR_MD5_DIGESTSIZE];
+
+  if (btn->read_digest)
+    {
+      apr_md5_final (digest, &btn->read_ctx);
+      memcpy (btn->read_digest, digest, sizeof (digest));
+    }
+
+  if (btn->write_digest)
+    {
+      apr_md5_final (digest, &btn->write_ctx);
+      memcpy (btn->write_digest, digest, sizeof (digest));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_stream_t *
+svn_stream_checksummed (svn_stream_t *stream,
+                        unsigned char *read_digest,
+                        unsigned char *write_digest,
+                        apr_pool_t *pool)
+{
+  svn_stream_t *s;
+  struct md5_stream_baton *baton;
+
+  if (! read_digest && ! write_digest)
+    return stream;
+
+  baton = apr_palloc (pool, sizeof (*baton));
+  apr_md5_init (&baton->read_ctx);
+  apr_md5_init (&baton->write_ctx);
+  baton->read_digest = read_digest;
+  baton->write_digest = write_digest;
+  baton->proxy = stream;
+
+  s = svn_stream_create (baton, pool);
+  svn_stream_set_read (s, read_handler_md5);
+  svn_stream_set_write (s, write_handler_md5);
+  svn_stream_set_close (s, close_handler_md5);
+  return s;
+}
+
+
+
+
 /* Miscellaneous stream functions. */
 struct string_stream_baton
 {
Index: subversion/include/svn_io.h
===================================================================
--- subversion/include/svn_io.h (revision 17698)
+++ subversion/include/svn_io.h (working copy)
@@ -582,6 +582,22 @@
 svn_stream_t *svn_stream_compressed (svn_stream_t *stream,
                                      apr_pool_t *pool);
  
+/** Return a stream that checksums all data read or written.  The stream
+ * @a stream is used to read and write all data.  The stream is allocated
+ * in @a pool.  @a read_digest and @a write_digest should point to an array
+ * of @c APR_MD5_DIGESTSIZE unsigned chars.
+ *
+ * When closed, the digests are written to @a read_digest and
+ * @a write_digest respectively.  Both @a read_digest and @a write_digest
+ * can be @c NULL, in which case the respective checksum isn't calculated.
+ *
+ * Read and write operations can be mixed without interfering.
+ */
+svn_stream_t * svn_stream_checksummed (svn_stream_t *stream,
+                                       unsigned char *read_digest,
+                                       unsigned char *write_digest,
+                                       apr_pool_t *pool);
+
 /** Read from a generic stream. */
 svn_error_t *svn_stream_read (svn_stream_t *stream, char *buffer,
                               apr_size_t *len);