istream-rawlog.c revision e93184a9055c2530366dfe617e07199603c399dd
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2011-2016 Dovecot authors, see the included COPYING file */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "lib.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "ostream.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "iostream-rawlog-private.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "istream-private.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen#include "istream-rawlog.h"
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstruct rawlog_istream {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct istream_private istream;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct rawlog_iostream riostream;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen};
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void i_stream_rawlog_close(struct iostream_private *stream,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen bool close_parent)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen iostream_rawlog_close(&rstream->riostream);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (close_parent)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_stream_close(rstream->istream.parent);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic void i_stream_rawlog_destroy(struct iostream_private *stream)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen uoff_t v_offset;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen v_offset = rstream->istream.parent_start_offset +
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen rstream->istream.istream.v_offset;
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen if (rstream->istream.parent->seekable ||
fe779565bda49a0ed0476724819c6e3c1340c94bTimo Sirainen v_offset > rstream->istream.parent->v_offset) {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen /* get to same position in parent stream */
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_stream_seek(rstream->istream.parent, v_offset);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch}
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstatic ssize_t i_stream_rawlog_read(struct istream_private *stream)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen{
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ssize_t ret;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen size_t pos;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_stream_seek(stream->parent, rstream->istream.parent_start_offset +
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->istream.v_offset);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->pos -= stream->skip;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->skip = 0;
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (pos > stream->pos)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ret = 0;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen else do {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if ((ret = i_stream_read(stream->parent)) == -2)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return -2;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->istream.eof = stream->parent->eof;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen } while (pos <= stream->pos && ret > 0);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen if (pos <= stream->pos)
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ret = ret == 0 ? 0 : -1;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen else {
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen ret = (ssize_t)(pos - stream->pos);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen iostream_rawlog_write(&rstream->riostream,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->buffer + stream->pos, ret);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen }
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->pos = pos;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_assert(ret != -1 || stream->istream.eof ||
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen stream->istream.stream_errno != 0);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return ret;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Boschstruct istream *
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Boschi_stream_create_rawlog(struct istream *input, const char *rawlog_path,
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch int rawlog_fd, enum iostream_rawlog_flags flags)
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch{
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch struct ostream *rawlog_output;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen bool autoclose_fd = (flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0;
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch i_assert(rawlog_path != NULL);
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch i_assert(rawlog_fd != -1);
0adc24c0c534944b55a185795e09dfaea2ca3131Stephan Bosch
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rawlog_output = autoclose_fd ?
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen o_stream_create_fd_autoclose(&rawlog_fd, 0) :
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen o_stream_create_fd(rawlog_fd, 0);
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen o_stream_set_name(rawlog_output,
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen t_strdup_printf("rawlog(%s)", rawlog_path));
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen return i_stream_create_rawlog_from_stream(input, rawlog_output, flags);
1c75bf24894a3fc0631caa4954e5130e9bb01d8dTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainenstruct istream *
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Siraineni_stream_create_rawlog_from_stream(struct istream *input,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen struct ostream *rawlog_output,
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch enum iostream_rawlog_flags flags)
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch{
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch struct rawlog_istream *rstream;
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch rstream = i_new(struct rawlog_istream, 1);
8ccdf195768afdfbc32088d7be77dfca7dddd829Stephan Bosch rstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.stream_size_passthrough = TRUE;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->riostream.rawlog_output = rawlog_output;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen iostream_rawlog_init(&rstream->riostream, flags, TRUE);
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.read = i_stream_rawlog_read;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.iostream.close = i_stream_rawlog_close;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.iostream.destroy = i_stream_rawlog_destroy;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.istream.readable_fd = input->readable_fd;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.istream.blocking = input->blocking;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen rstream->istream.istream.seekable = input->seekable;
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen return i_stream_create(&rstream->istream, input,
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen i_stream_get_fd(input));
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen}
02c75e04c6ff80726bb59e3ea34a7995ad1f6f7cTimo Sirainen