bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "lib.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "istream.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "ostream-private.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen#include "ostream-cmp.h"
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct cmp_ostream {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct ostream_private ostream;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct istream *input;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen bool equals;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen};
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void o_stream_cmp_close(struct iostream_private *stream,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen bool close_parent)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct cmp_ostream *cstream = (struct cmp_ostream *)stream;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (cstream->input == NULL)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_unref(&cstream->input);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (close_parent)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen o_stream_close(cstream->ostream.parent);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenbool stream_cmp_block(struct istream *input,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const unsigned char *data, size_t size)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const unsigned char *indata;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen size_t insize, max;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen while (size > 0) {
534e41e436a7546f36f61e0dc49c0c191d850f6bPhil Carmody (void)i_stream_read_bytes(input, &indata, &insize, size);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen max = I_MIN(insize, size);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (insize == 0 || memcmp(data, indata, max) != 0)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen data += max;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen size -= max;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_skip(input, max);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return TRUE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstatic ssize_t
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Siraineno_stream_cmp_sendv(struct ostream_private *stream,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen const struct const_iovec *iov, unsigned int iov_count)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct cmp_ostream *cstream = (struct cmp_ostream *)stream;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen unsigned int i;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen ssize_t ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (cstream->equals) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen for (i = 0; i < iov_count; i++) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen if (!stream_cmp_block(cstream->input, iov[i].iov_base,
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen iov[i].iov_len)) {
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream->equals = FALSE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen break;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen o_stream_copy_error_from_parent(stream);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return -1;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen }
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen stream->ostream.offset += ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return ret;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenstruct ostream *
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Siraineno_stream_create_cmp(struct ostream *output, struct istream *input)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct cmp_ostream *cstream;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream = i_new(struct cmp_ostream, 1);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream->ostream.sendv = o_stream_cmp_sendv;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream->ostream.iostream.close = o_stream_cmp_close;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream->input = input;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen cstream->equals = TRUE;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen i_stream_ref(input);
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen return o_stream_create(&cstream->ostream, output,
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen o_stream_get_fd(output));
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainenbool o_stream_cmp_equals(struct ostream *_output)
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen{
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen struct cmp_ostream *cstream =
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen (struct cmp_ostream *)_output->real_stream;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen return cstream->equals;
c33d3f93abf8392fdc60e12bea41ffd12cc85a8dTimo Sirainen}