]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
liblib: Added istream-hash, similar to ostream-hash.
authorTimo Sirainen <tss@iki.fi>
Mon, 9 Sep 2013 01:34:58 +0000 (04:34 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 9 Sep 2013 01:34:58 +0000 (04:34 +0300)
src/lib/Makefile.am
src/lib/istream-hash.c [new file with mode: 0644]
src/lib/istream-hash.h [new file with mode: 0644]

index eec3376f176f5c2e3edb044d2bad06dc6675210a..054996b6089d580c4b78685ea4b027adcc8ef775 100644 (file)
@@ -62,6 +62,7 @@ liblib_la_SOURCES = \
        istream-crlf.c \
        istream-data.c \
        istream-file.c \
+       istream-hash.c \
        istream-jsonstr.c \
        istream-limit.c \
        istream-mmap.c \
@@ -189,6 +190,7 @@ headers = \
        istream-chain.h \
        istream-concat.h \
        istream-crlf.h \
+       istream-hash.h \
        istream-jsonstr.h \
        istream-private.h \
        istream-rawlog.h \
diff --git a/src/lib/istream-hash.c b/src/lib/istream-hash.c
new file mode 100644 (file)
index 0000000..855e30b
--- /dev/null
@@ -0,0 +1,60 @@
+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "hash-method.h"
+#include "istream-private.h"
+#include "istream-hash.h"
+
+struct hash_istream {
+       struct istream_private istream;
+
+       const struct hash_method *method;
+       void *hash_context;
+};
+
+static ssize_t
+i_stream_hash_read(struct istream_private *stream)
+{
+       struct hash_istream *hstream = (struct hash_istream *)stream;
+       const unsigned char *data;
+       size_t size;
+       ssize_t ret;
+
+       i_stream_seek(stream->parent, stream->parent_start_offset +
+                     stream->istream.v_offset);
+
+       ret = i_stream_read_copy_from_parent(&stream->istream);
+       if (ret > 0 && hstream->hash_context != NULL) {
+               data = i_stream_get_data(&stream->istream, &size);
+               i_assert((size_t)ret <= size);
+               hstream->method->loop(hstream->hash_context,
+                                     data+(size-ret), ret);
+       } else if (ret < 0) {
+               /* we finished hashing it. don't access it anymore, because
+                  the memory pointed by the hash may be freed before the
+                  istream itself */
+               hstream->hash_context = NULL;
+       }
+       return ret;
+}
+
+struct istream *
+i_stream_create_hash(struct istream *input, const struct hash_method *method,
+                    void *hash_context)
+{
+       struct hash_istream *hstream;
+
+       hstream = i_new(struct hash_istream, 1);
+       hstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
+       hstream->istream.stream_size_passthrough = TRUE;
+
+       hstream->istream.read = i_stream_hash_read;
+
+       hstream->istream.istream.blocking = input->blocking;
+       hstream->istream.istream.seekable = FALSE;
+
+       hstream->method = method;
+       hstream->hash_context = hash_context;
+       return i_stream_create(&hstream->istream, input,
+                              i_stream_get_fd(input));
+}
diff --git a/src/lib/istream-hash.h b/src/lib/istream-hash.h
new file mode 100644 (file)
index 0000000..bd22201
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef ISTREAM_HASH_H
+#define ISTREAM_HASH_H
+
+struct hash_method;
+
+/* hash_context must be allocated and initialized by caller. This istream will
+   simply call method->loop() for all the data going through the istream. */
+struct istream *
+i_stream_create_hash(struct istream *input, const struct hash_method *method,
+                    void *hash_context);
+
+#endif