bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "lib.h"
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen#include "ostream.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "iostream-rawlog-private.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "istream-private.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "istream-rawlog.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenstruct rawlog_istream {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct istream_private istream;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct rawlog_iostream riostream;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen};
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void i_stream_rawlog_close(struct iostream_private *stream,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen bool close_parent)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen iostream_rawlog_close(&rstream->riostream);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (close_parent)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen i_stream_close(rstream->istream.parent);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenstatic void i_stream_rawlog_destroy(struct iostream_private *stream)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen uoff_t v_offset;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen v_offset = rstream->istream.parent_start_offset +
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.istream.v_offset;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (rstream->istream.parent->seekable ||
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen v_offset > rstream->istream.parent->v_offset) {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen /* get to same position in parent stream */
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_stream_seek(rstream->istream.parent, v_offset);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenstatic ssize_t i_stream_rawlog_read(struct istream_private *stream)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen ssize_t ret;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen size_t pos;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_stream_seek(stream->parent, rstream->istream.parent_start_offset +
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->istream.v_offset);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->pos -= stream->skip;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->skip = 0;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (pos > stream->pos)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen ret = 0;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen else do {
bcd286622779a93f809b11993db0550f8c7cc9b5Timo Sirainen if ((ret = i_stream_read_memarea(stream->parent)) == -2)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return -2;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->istream.eof = stream->parent->eof;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen } while (pos <= stream->pos && ret > 0);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (pos <= stream->pos)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen ret = ret == 0 ? 0 : -1;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen else {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen ret = (ssize_t)(pos - stream->pos);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen iostream_rawlog_write(&rstream->riostream,
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->buffer + stream->pos, ret);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->pos = pos;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_assert(ret != -1 || stream->istream.eof ||
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen stream->istream.stream_errno != 0);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return ret;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenstruct istream *
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Siraineni_stream_create_rawlog(struct istream *input, const char *rawlog_path,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen int rawlog_fd, enum iostream_rawlog_flags flags)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct ostream *rawlog_output;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen bool autoclose_fd = (flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_assert(rawlog_path != NULL);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_assert(rawlog_fd != -1);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi rawlog_output = autoclose_fd ?
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi o_stream_create_fd_autoclose(&rawlog_fd, 0) :
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi o_stream_create_fd(rawlog_fd, 0);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_set_name(rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen t_strdup_printf("rawlog(%s)", rawlog_path));
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen return i_stream_create_rawlog_from_stream(input, rawlog_output, flags);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen}
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainenstruct istream *
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Siraineni_stream_create_rawlog_from_stream(struct istream *input,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct ostream *rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen enum iostream_rawlog_flags flags)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen{
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct rawlog_istream *rstream;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream = i_new(struct rawlog_istream, 1);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen rstream->istream.stream_size_passthrough = TRUE;
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rstream->riostream.rawlog_output = rawlog_output;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen iostream_rawlog_init(&rstream->riostream, flags, TRUE);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.read = i_stream_rawlog_read;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.iostream.close = i_stream_rawlog_close;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.iostream.destroy = i_stream_rawlog_destroy;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.istream.readable_fd = input->readable_fd;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.istream.blocking = input->blocking;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen rstream->istream.istream.seekable = input->seekable;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return i_stream_create(&rstream->istream, input,
2974dca6be5120e49279f06c8aa952e5fac56048Timo Sirainen i_stream_get_fd(input), 0);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}