]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
istreams: Fixed some parent stream seeking issues.
authorTimo Sirainen <tss@iki.fi>
Fri, 1 May 2009 18:50:08 +0000 (14:50 -0400)
committerTimo Sirainen <tss@iki.fi>
Fri, 1 May 2009 18:50:08 +0000 (14:50 -0400)
--HG--
branch : HEAD

src/lib-mail/istream-header-filter.c
src/lib-storage/index/istream-mail-stats.c
src/lib/istream-internal.h
src/lib/istream-limit.c
src/lib/istream.c

index 8be3851f0a9893c0d34784ca8c9bc0837aeaccb4..bb2a66b8c72b4f81e755d342d6018c1cee4d5321 100644 (file)
@@ -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)
index 9eb65cf7debb73f92d6d5fc3d76bd918d0edbb16..2c89cd9c9d858c63103aec539b76eb9b2e373861 100644 (file)
@@ -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;
 }
 
index f5f27aa41ff6aa2c2b4f85a9ca822debfea7ef21..8ebad18b8e672aed3e8e8df56a77f45dd4d0f140 100644 (file)
@@ -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
index cc59e0f8f7e425a67890f659fc7f601ed201d4d5..53ce46caa83fcfe6be678b379d93f0632f2fb7b1 100644 (file)
@@ -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;
index bd5e6516ee85e4ecd63aaf33bce8aca83fdea285..476484e8540c81197182200342a159a2e3833eb4 100644 (file)
@@ -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;