istream-limit.c revision 9511a40d933181045343110c8101b75887062aae
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "lib.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "istream-internal.h"
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstruct limit_istream {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct istream_private istream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz uoff_t v_size;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz};
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void i_stream_limit_destroy(struct iostream_private *stream)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream = (struct limit_istream *) stream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* get to same position in parent stream */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_seek(lstream->istream.parent,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.parent_start_offset +
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.istream.v_offset);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_unref(&lstream->istream.parent);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzi_stream_limit_set_max_buffer_size(struct iostream_private *stream,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz size_t max_size)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream = (struct limit_istream *) stream;
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.max_buffer_size = max_size;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz i_stream_set_max_buffer_size(lstream->istream.parent, max_size);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic ssize_t i_stream_limit_read(struct istream_private *stream)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream = (struct limit_istream *) stream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz uoff_t left;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz ssize_t ret;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz size_t pos;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (stream->istream.v_offset +
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz (stream->pos - stream->skip) >= lstream->v_size) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->istream.eof = TRUE;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz return -1;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (stream->parent->v_offset !=
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz lstream->istream.parent_start_offset + stream->istream.v_offset) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_seek(stream->parent,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.parent_start_offset +
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz stream->istream.v_offset);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->buffer = i_stream_get_data(stream->parent, &pos);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (pos <= stream->pos) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if ((ret = i_stream_read(stream->parent)) == -2)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return -2;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->istream.stream_errno = stream->parent->stream_errno;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->istream.eof = stream->parent->eof;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->buffer = i_stream_get_data(stream->parent, &pos);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz } else {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz ret = 0;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->pos -= stream->skip;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->skip = 0;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (lstream->v_size != (uoff_t)-1) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz left = lstream->v_size - stream->istream.v_offset;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (pos >= left) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz pos = left;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->istream.eof = TRUE;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz (ret == 0 ? 0 : -1);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->pos = pos;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz return ret;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz}
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void i_stream_limit_seek(struct istream_private *stream, uoff_t v_offset,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz bool mark ATTR_UNUSED)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream = (struct limit_istream *) stream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_assert(v_offset <= lstream->v_size);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->istream.stream_errno = 0;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->istream.v_offset = v_offset;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz stream->skip = stream->pos = 0;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz}
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic const struct stat *
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzi_stream_limit_stat(struct istream_private *stream, bool exact)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream = (struct limit_istream *) stream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct stat *st;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz st = i_stream_stat(stream->parent, exact);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (st == NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return NULL;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz stream->statbuf = *st;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (lstream->v_size != (uoff_t)-1)
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen stream->statbuf.st_size = lstream->v_size;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return &stream->statbuf;
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen}
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainenstruct istream *i_stream_create_limit(struct istream *input, uoff_t v_size)
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct limit_istream *lstream;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_ref(input);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream = i_new(struct limit_istream, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->v_size = v_size;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
a44595f7b1afc7ccbd8653598753b32899d01c76Timo Sirainen
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.iostream.destroy = i_stream_limit_destroy;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.iostream.set_max_buffer_size =
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_limit_set_max_buffer_size;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.parent = input;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.read = i_stream_limit_read;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.seek = i_stream_limit_seek;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.stat = i_stream_limit_stat;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.istream.blocking = input->blocking;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lstream->istream.istream.seekable = input->seekable;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return i_stream_create(&lstream->istream, input,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_stream_get_fd(input));
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz