istream-hash.c revision 25fb397382c6f7d39bfeee85774e7675f02bfb3c
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file */
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen#include "lib.h"
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen#include "hash-method.h"
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen#include "istream-private.h"
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen#include "istream-hash.h"
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainenstruct hash_istream {
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen struct istream_private istream;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen const struct hash_method *method;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen void *hash_context;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen uoff_t high_offset;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen};
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainenstatic ssize_t
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Siraineni_stream_hash_read(struct istream_private *stream)
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen{
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen struct hash_istream *hstream = (struct hash_istream *)stream;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen const unsigned char *data;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen size_t size;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen uoff_t skip;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen ssize_t ret;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen i_stream_seek(stream->parent, stream->parent_start_offset +
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen stream->istream.v_offset);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen ret = i_stream_read_copy_from_parent(&stream->istream);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen if (ret > 0 && hstream->hash_context != NULL) {
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen data = i_stream_get_data(&stream->istream, &size);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen i_assert((size_t)ret <= size);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen i_assert(stream->istream.v_offset <= hstream->high_offset);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen skip = hstream->high_offset - stream->istream.v_offset;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen if (skip < (size_t)size) {
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->high_offset += (size-skip);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->method->loop(hstream->hash_context,
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen data+skip, size-skip);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen }
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen } else if (ret < 0) {
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen /* we finished hashing it. don't access it anymore, because
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen the memory pointed by the hash may be freed before the
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen istream itself */
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->hash_context = NULL;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen }
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen return ret;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen}
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainenstatic void
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Siraineni_stream_hash_seek(struct istream_private *stream,
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen uoff_t v_offset, bool mark ATTR_UNUSED)
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen{
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen struct hash_istream *hstream = (struct hash_istream *)stream;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen if (hstream->hash_context != NULL) {
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen io_stream_set_error(&stream->iostream,
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen "Seeking not supported before hashing is finished");
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen stream->istream.stream_errno = ESPIPE;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen }
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen stream->istream.v_offset = v_offset;
0ddff4c8aefa66f7e19eddc6d61cd040fb803321Timo Sirainen stream->skip = stream->pos = 0;
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen}
3efdcb59492bd1e0602340a4204003a32b34654aTimo Sirainen
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainenstruct istream *
906520ee2cece20c875835697db08cd5e29b919bTimo Siraineni_stream_create_hash(struct istream *input, const struct hash_method *method,
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen void *hash_context)
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen{
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen struct hash_istream *hstream;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
3efdcb59492bd1e0602340a4204003a32b34654aTimo Sirainen hstream = i_new(struct hash_istream, 1);
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->istream.stream_size_passthrough = TRUE;
3efdcb59492bd1e0602340a4204003a32b34654aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->istream.read = i_stream_hash_read;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->istream.seek = i_stream_hash_seek;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen hstream->istream.istream.readable_fd = input->readable_fd;
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen hstream->istream.istream.blocking = input->blocking;
3efdcb59492bd1e0602340a4204003a32b34654aTimo Sirainen hstream->istream.istream.seekable = input->seekable;
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen hstream->method = method;
906520ee2cece20c875835697db08cd5e29b919bTimo Sirainen hstream->hash_context = hash_context;
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen return i_stream_create(&hstream->istream, input,
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen i_stream_get_fd(input));
f877ee033a0737100c2f661a7ca4c559ea2ddb8aTimo Sirainen}
3efdcb59492bd1e0602340a4204003a32b34654aTimo Sirainen