From: Timo Sirainen Date: Fri, 1 May 2009 18:50:08 +0000 (-0400) Subject: istreams: Fixed some parent stream seeking issues. X-Git-Tag: 2.0.alpha1~856 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=61e6367a259e2473f33df42fda8ceeb3b8b48416;p=thirdparty%2Fdovecot%2Fcore.git istreams: Fixed some parent stream seeking issues. --HG-- branch : HEAD --- diff --git a/src/lib-mail/istream-header-filter.c b/src/lib-mail/istream-header-filter.c index 8be3851f0a..bb2a66b8c7 100644 --- a/src/lib-mail/istream-header-filter.c +++ b/src/lib-mail/istream-header-filter.c @@ -295,7 +295,6 @@ static ssize_t i_stream_header_filter_read(struct istream_private *stream) struct header_filter_istream *mstream = (struct header_filter_istream *)stream; ssize_t ret; - size_t pos; if (!mstream->header_read || stream->istream.v_offset < mstream->header_size.virtual_size) { @@ -313,27 +312,7 @@ static ssize_t i_stream_header_filter_read(struct istream_private *stream) stream->istream.v_offset - mstream->header_size.virtual_size + mstream->header_size.physical_size); - - stream->pos -= stream->skip; - stream->skip = 0; - - stream->buffer = i_stream_get_data(stream->parent, &pos); - if (pos <= stream->pos) { - if ((ret = i_stream_read(stream->parent)) == -2) { - i_assert(stream->skip != stream->pos); - return -2; - } - stream->istream.stream_errno = stream->parent->stream_errno; - stream->istream.eof = stream->parent->eof; - stream->buffer = i_stream_get_data(stream->parent, &pos); - } else { - ret = 0; - } - - ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) : - (ret == 0 ? 0 : -1); - stream->pos = pos; - return ret; + return i_stream_read_copy_from_parent(&stream->istream); } static void parse_header(struct header_filter_istream *mstream) diff --git a/src/lib-storage/index/istream-mail-stats.c b/src/lib-storage/index/istream-mail-stats.c index 9eb65cf7de..2c89cd9c9d 100644 --- a/src/lib-storage/index/istream-mail-stats.c +++ b/src/lib-storage/index/istream-mail-stats.c @@ -36,7 +36,6 @@ i_stream_mail_stats_read_mail_stats(struct istream_private *stream) { struct mail_stats_istream *mstream = (struct mail_stats_istream *)stream; - size_t pos; ssize_t ret; if (stream->parent->v_offset != @@ -45,34 +44,14 @@ i_stream_mail_stats_read_mail_stats(struct istream_private *stream) stream->istream.v_offset); } - stream->buffer = i_stream_get_data(stream->parent, &pos); - if (pos <= stream->pos) { - if ((ret = i_stream_read(stream->parent)) == -2) - return -2; - - if (ret > 0) { - mstream->mail->stats_files_read_bytes+= ret; - if (!mstream->files_read_increased) { - mstream->files_read_increased = TRUE; - mstream->mail->stats_files_read_count++; - } + ret = i_stream_read_copy_from_parent(&stream->istream); + if (ret > 0) { + mstream->mail->stats_files_read_bytes += ret; + if (!mstream->files_read_increased) { + mstream->files_read_increased = TRUE; + mstream->mail->stats_files_read_count++; } - - stream->istream.stream_errno = stream->parent->stream_errno; - stream->istream.eof = stream->parent->eof; - stream->buffer = i_stream_get_data(stream->parent, &pos); - } else { - ret = 0; } - - stream->pos -= stream->skip; - stream->skip = 0; - - ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) : - (ret == 0 ? 0 : -1); - stream->pos = pos; - i_assert(ret != -1 || stream->istream.eof || - stream->istream.stream_errno != 0); return ret; } diff --git a/src/lib/istream-internal.h b/src/lib/istream-internal.h index f5f27aa41f..8ebad18b8e 100644 --- a/src/lib/istream-internal.h +++ b/src/lib/istream-internal.h @@ -45,5 +45,6 @@ void i_stream_compress(struct istream_private *stream); void i_stream_grow_buffer(struct istream_private *stream, size_t bytes); bool i_stream_get_buffer_space(struct istream_private *stream, size_t wanted_size, size_t *size_r); +ssize_t i_stream_read_copy_from_parent(struct istream *istream); #endif diff --git a/src/lib/istream-limit.c b/src/lib/istream-limit.c index cc59e0f8f7..53ce46caa8 100644 --- a/src/lib/istream-limit.c +++ b/src/lib/istream-limit.c @@ -54,20 +54,20 @@ static ssize_t i_stream_limit_read(struct istream_private *stream) stream->istream.v_offset); } + stream->pos -= stream->skip; + stream->skip = 0; + stream->buffer = i_stream_get_data(stream->parent, &pos); - if (pos <= stream->pos) { + if (pos > stream->pos) + ret = 0; + else do { if ((ret = i_stream_read(stream->parent)) == -2) return -2; stream->istream.stream_errno = stream->parent->stream_errno; stream->istream.eof = stream->parent->eof; stream->buffer = i_stream_get_data(stream->parent, &pos); - } else { - ret = 0; - } - - stream->pos -= stream->skip; - stream->skip = 0; + } while (pos <= stream->pos && ret > 0); if (lstream->v_size != (uoff_t)-1) { left = lstream->v_size - stream->istream.v_offset; diff --git a/src/lib/istream.c b/src/lib/istream.c index bd5e6516ee..476484e854 100644 --- a/src/lib/istream.c +++ b/src/lib/istream.c @@ -102,6 +102,38 @@ ssize_t i_stream_read(struct istream *stream) return ret; } +ssize_t i_stream_read_copy_from_parent(struct istream *istream) +{ + struct istream_private *stream = istream->real_stream; + size_t pos; + ssize_t ret; + + stream->pos -= stream->skip; + stream->skip = 0; + + stream->buffer = i_stream_get_data(stream->parent, &pos); + if (pos > stream->pos) + ret = 0; + else do { + if ((ret = i_stream_read(stream->parent)) == -2) + return -2; + + stream->istream.stream_errno = stream->parent->stream_errno; + stream->istream.eof = stream->parent->eof; + stream->buffer = i_stream_get_data(stream->parent, &pos); + /* check again, in case the parent stream had been seeked + backwards and the previous read() didn't get us far + enough. */ + } while (pos <= stream->pos && ret > 0); + + ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) : + (ret == 0 ? 0 : -1); + stream->pos = pos; + i_assert(ret != -1 || stream->istream.eof || + stream->istream.stream_errno != 0); + return ret; +} + void i_stream_skip(struct istream *stream, uoff_t count) { struct istream_private *_stream = stream->real_stream;