istream-hash.c revision 202a34580f6204672d9b0d6a0756f35a3c4cdef6
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "hash-method.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "istream-private.h"
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen#include "istream-hash.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct hash_istream {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct istream_private istream;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct hash_method *method;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen void *hash_context;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen uoff_t high_offset;
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen};
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainenstatic ssize_t
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Siraineni_stream_hash_read(struct istream_private *stream)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen{
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen struct hash_istream *hstream = (struct hash_istream *)stream;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen const unsigned char *data;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen size_t size;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen uoff_t skip;
373492be949e159fda651807b3acda2c5c077027Timo Sirainen ssize_t ret;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_stream_seek(stream->parent, stream->parent_start_offset +
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen stream->istream.v_offset);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen ret = i_stream_read_copy_from_parent(&stream->istream);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if (ret > 0 && hstream->hash_context != NULL) {
373492be949e159fda651807b3acda2c5c077027Timo Sirainen data = i_stream_get_data(&stream->istream, &size);
373492be949e159fda651807b3acda2c5c077027Timo Sirainen i_assert((size_t)ret <= size);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_assert(stream->istream.v_offset <= hstream->high_offset);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen skip = hstream->high_offset - stream->istream.v_offset;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if (skip < (size_t)size) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->high_offset += (size-skip);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->method->loop(hstream->hash_context,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen data+skip, size-skip);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen } else if (ret < 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* we finished hashing it. don't access it anymore, because
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen the memory pointed by the hash may be freed before the
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen istream itself */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hstream->hash_context = NULL;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return ret;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic void
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Siraineni_stream_hash_seek(struct istream_private *stream,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen uoff_t v_offset, bool mark ATTR_UNUSED)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct hash_istream *hstream = (struct hash_istream *)stream;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (hstream->hash_context != NULL) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* we support seeking only after the hash is finished */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen stream->istream.stream_errno = ESPIPE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen stream->istream.v_offset = v_offset;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen stream->skip = stream->pos = 0;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen}
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct istream *
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Siraineni_stream_create_hash(struct istream *input, const struct hash_method *method,
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen void *hash_context)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct hash_istream *hstream;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream = i_new(struct hash_istream, 1);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->istream.stream_size_passthrough = TRUE;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->istream.read = i_stream_hash_read;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen hstream->istream.seek = i_stream_hash_seek;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hstream->istream.istream.blocking = input->blocking;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hstream->istream.istream.seekable = input->seekable;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hstream->method = method;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hstream->hash_context = hash_context;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return i_stream_create(&hstream->istream, input,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_stream_get_fd(input));
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen