]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Input streams: Improved error handling and added more asserts.
authorTimo Sirainen <tss@iki.fi>
Sat, 13 Sep 2008 10:06:06 +0000 (13:06 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 13 Sep 2008 10:06:06 +0000 (13:06 +0300)
--HG--
branch : HEAD

src/lib-mail/istream-header-filter.c
src/lib-storage/index/mbox/istream-raw-mbox.c
src/lib/istream-concat.c
src/lib/istream-crlf.c
src/lib/istream-file.c
src/lib/istream-limit.c
src/lib/istream-mmap.c
src/lib/istream-seekable.c
src/lib/istream-tee.c
src/lib/istream.c
src/plugins/zlib/istream-zlib.c

index 4064c15d4ea02feacb7708fe6918efc58121ab34..ed8e821e40a11989ab76f71e723e9ae76bfc604d 100644 (file)
@@ -92,6 +92,7 @@ read_mixed(struct header_filter_istream *mstream, size_t body_highwater_size)
 
        mstream->istream.buffer = buffer_get_data(mstream->hdr_buf, &pos);
        ret = (ssize_t)(pos - mstream->istream.pos - mstream->istream.skip);
+       i_assert(ret > 0);
        mstream->istream.pos = pos;
        return ret;
 }
@@ -244,8 +245,10 @@ static ssize_t read_header(struct header_filter_istream *mstream)
        ret = (ssize_t)(pos - mstream->istream.pos - mstream->istream.skip);
        mstream->istream.pos = pos;
 
-       if (hdr_ret == 0)
+       if (hdr_ret == 0) {
+               i_assert(ret > 0);
                return ret;
+       }
 
        if (hdr == NULL) {
                /* finished */
index 91eb4b65a8d39d1f02eae1b914bec3b344647add..7c2792db5aaa2e0879109230dcf9ab73dd026f17 100644 (file)
@@ -61,7 +61,11 @@ static int mbox_read_from_line(struct raw_mbox_istream *rstream)
 
        while ((p = memchr(buf+skip, '\n', pos-skip)) == NULL) {
                if (i_stream_read(rstream->istream.parent) < 0) {
-                       /* EOF - shouldn't happen */
+                       /* EOF shouldn't happen */
+                       rstream->istream.istream.eof =
+                               rstream->istream.parent->eof;
+                       rstream->istream.istream.stream_errno =
+                               rstream->istream.parent->stream_errno;
                        return -1;
                }
                buf = i_stream_get_data(rstream->istream.parent, &pos);
@@ -79,6 +83,7 @@ static int mbox_read_from_line(struct raw_mbox_istream *rstream)
            mbox_from_parse(buf+5, pos-5, &received_time, &tz, &sender) < 0) {
                /* broken From - should happen only at beginning of
                   file if this isn't a mbox.. */
+               rstream->istream.istream.stream_errno = EBADMSG;
                return -1;
        }
 
@@ -302,6 +307,7 @@ static ssize_t i_stream_raw_mbox_read(struct istream_private *stream)
                        rstream->hdr_offset + rstream->mail_size);
                rstream->eof = TRUE;
                rstream->corrupted = TRUE;
+               rstream->istream.istream.stream_errno = EBADMSG;
                return -1;
        }
 
index d3ccf094357c2a61a74e075ad6a3860d51483345..eb922efd099a2f5bb35f753d6937b8a869497ef6 100644 (file)
@@ -138,6 +138,7 @@ static ssize_t i_stream_concat_read(struct istream_private *stream)
                }
 
                stream->istream.eof = cstream->cur_input->eof && last_stream;
+               i_assert(ret != -1 || stream->istream.eof);
                data = i_stream_get_data(cstream->cur_input, &pos);
        }
 
@@ -198,7 +199,6 @@ static void i_stream_concat_seek(struct istream_private *stream,
 {
        struct concat_istream *cstream = (struct concat_istream *)stream;
 
-       stream->istream.stream_errno = 0;
        stream->istream.v_offset = v_offset;
        stream->skip = stream->pos = 0;
        cstream->prev_size = 0;
index 5cff3aec384ac1238a5ae6c40f134178bc23fc66..683f3431552c187218b30491b0ab78985e3ed161 100644 (file)
@@ -87,7 +87,7 @@ static ssize_t i_stream_crlf_read_crlf(struct istream_private *stream)
        i_stream_skip(stream->parent, i);
 
        ret = dest - stream->pos;
-       i_assert(ret != 0);
+       i_assert(ret > 0);
        stream->pos = dest;
        return ret;
 }
@@ -147,6 +147,7 @@ static ssize_t i_stream_crlf_read_lf(struct istream_private *stream)
                i_assert(cstream->pending_cr && size == 1);
                return i_stream_crlf_read_lf(stream);
        }
+       i_assert(ret > 0);
        stream->pos = dest;
        return ret;
 }
index 1419bca6f789db27e58f800fef46b5df907e4080..2ad03a6baece0902da3aa3658fcd37693b7bb87d 100644 (file)
@@ -46,7 +46,6 @@ static ssize_t i_stream_file_read(struct istream_private *stream)
        size_t size;
        ssize_t ret;
 
-       stream->istream.stream_errno = 0;
        if (!i_stream_get_buffer_space(stream, 1, &size))
                return -2;
 
@@ -78,7 +77,7 @@ static ssize_t i_stream_file_read(struct istream_private *stream)
                        i_assert(!stream->istream.blocking);
                        ret = 0;
                } else {
-                       stream->istream.eof = TRUE;
+                       i_assert(errno != 0);
                        stream->istream.stream_errno = errno;
                        return -1;
                }
@@ -101,6 +100,7 @@ static ssize_t i_stream_file_read(struct istream_private *stream)
 
        stream->pos += ret;
        i_assert(ret != 0 || !fstream->file);
+       i_assert(ret != -1);
        return ret;
 }
 
@@ -117,7 +117,6 @@ static void i_stream_file_seek(struct istream_private *stream, uoff_t v_offset,
                fstream->skip_left += v_offset - stream->istream.v_offset;
        }
 
-       stream->istream.stream_errno = 0;
        stream->istream.v_offset = v_offset;
        stream->skip = stream->pos = 0;
        fstream->seen_eof = FALSE;
index 18dd4ce8992cdb99ade045f75f4444f52bc18fb9..91ab6b4bbddc88a0656235fc2095abd0d09c1deb 100644 (file)
@@ -80,6 +80,8 @@ static ssize_t i_stream_limit_read(struct istream_private *stream)
        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;
 }
 
@@ -90,7 +92,6 @@ static void i_stream_limit_seek(struct istream_private *stream, uoff_t v_offset,
 
        i_assert(v_offset <= lstream->v_size);
 
-       stream->istream.stream_errno = 0;
        stream->istream.v_offset = v_offset;
        stream->skip = stream->pos = 0;
 }
index fb49084db239435cbf1890b85d434a31079f834d..062b7b1fb2c0f298c430116a8e9315d9deca2f20 100644 (file)
@@ -66,8 +66,6 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
        size_t aligned_skip;
        uoff_t top;
 
-       stream->istream.stream_errno = 0;
-
        if (stream->pos < stream->buffer_size) {
                /* more bytes available without needing to mmap() */
                stream->pos = stream->buffer_size;
@@ -108,6 +106,7 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
                        mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
                             stream->fd, mstream->mmap_offset);
                if (mstream->mmap_base == MAP_FAILED) {
+                       i_assert(errno != 0);
                        stream->istream.stream_errno = errno;
                        mstream->mmap_base = NULL;
                        stream->buffer = NULL;
@@ -126,7 +125,7 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
        }
 
        stream->pos = stream->buffer_size;
-       i_assert(stream->pos - stream->skip != 0);
+       i_assert(stream->pos - stream->skip > 0);
        return stream->pos - stream->skip;
 }
 
index ae09a66a415d6662ee277d5d04c75f8fd31fb58b..903ae62274c0282da307a2ddce8c03776dab3867 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "close-keep-errno.h"
 #include "hex-binary.h"
 #include "randgen.h"
 #include "write-full.h"
@@ -107,14 +108,14 @@ static int copy_to_temp_file(struct seekable_istream *sstream)
        if (unlink(path) < 0) {
                /* shouldn't happen.. */
                i_error("unlink(%s) failed: %m", path);
-               (void)close(fd);
+               close_keep_errno(fd);
                return -1;
        }
 
        /* copy our currently read buffer to it */
        if (write_full(fd, sstream->buffer->data, sstream->buffer->used) < 0) {
                i_error("write_full(%s) failed: %m", path);
-               (void)close(fd);
+               close_keep_errno(fd);
                return -1;
        }
        sstream->write_peak = sstream->buffer->used;
@@ -139,10 +140,10 @@ static ssize_t read_more(struct seekable_istream *sstream)
 
        while ((ret = i_stream_read(sstream->cur_input)) < 0) {
                if (!sstream->cur_input->eof) {
-                       /* error */
+                       /* full / error */
                        sstream->istream.istream.stream_errno =
                                sstream->cur_input->stream_errno;
-                       return -1;
+                       return ret;
                }
 
                /* go to next stream */
@@ -161,7 +162,7 @@ static ssize_t read_more(struct seekable_istream *sstream)
        return ret;
 }
 
-static bool read_from_buffer(struct seekable_istream *sstream, ssize_t *ret)
+static bool read_from_buffer(struct seekable_istream *sstream, ssize_t *ret_r)
 {
        struct istream_private *stream = &sstream->istream;
        const unsigned char *data;
@@ -174,8 +175,8 @@ static bool read_from_buffer(struct seekable_istream *sstream, ssize_t *ret)
                        return FALSE;
 
                /* read more to buffer */
-               *ret = read_more(sstream);
-               if (*ret <= 0)
+               *ret_r = read_more(sstream);
+               if (*ret_r <= 0)
                        return TRUE;
 
                /* we should have more now. */
@@ -188,7 +189,8 @@ static bool read_from_buffer(struct seekable_istream *sstream, ssize_t *ret)
        stream->buffer = CONST_PTR_OFFSET(sstream->buffer->data, offset);
        pos = sstream->buffer->used - offset;
 
-       *ret = pos - stream->pos;
+       *ret_r = pos - stream->pos;
+       i_assert(*ret_r > 0);
        stream->pos = pos;
        return TRUE;
 }
@@ -210,6 +212,8 @@ static ssize_t i_stream_seekable_read(struct istream_private *stream)
 
                /* copy everything to temp file and use it as the stream */
                if (copy_to_temp_file(sstream) < 0) {
+                       i_assert(errno != 0);
+                       stream->istream.stream_errno = errno;
                        i_stream_close(&stream->istream);
                        return -1;
                }
@@ -225,6 +229,8 @@ static ssize_t i_stream_seekable_read(struct istream_private *stream)
                /* save to our file */
                data = i_stream_get_data(sstream->cur_input, &size);
                if (write_full(sstream->fd, data, size) < 0) {
+                       i_assert(errno != 0);
+                       stream->istream.stream_errno = errno;
                        i_error("write_full(%s...) failed: %m",
                                sstream->temp_prefix);
                        i_stream_close(&stream->istream);
@@ -255,7 +261,6 @@ static ssize_t i_stream_seekable_read(struct istream_private *stream)
 static void i_stream_seekable_seek(struct istream_private *stream,
                                   uoff_t v_offset, bool mark ATTR_UNUSED)
 {
-       stream->istream.stream_errno = 0;
        stream->istream.v_offset = v_offset;
        stream->skip = stream->pos = 0;
 }
index 9ddd33e7e1e00e829c8e7058cb51dbd4bb868b91..414b3c677a332c27ba0357455c5a8f597de12b96 100644 (file)
@@ -141,6 +141,7 @@ static ssize_t i_stream_tee_read(struct istream_private *stream)
 
        i_assert(stream->buffer == data);
        ret = size - stream->pos;
+       i_assert(ret > 0);
        stream->pos = size;
        return ret;
 }
index 8cc803d3d39d6dfb7c65a86b497c78b66680d27a..e6eefd06308f4ef0ad8ff460a953d6076bc02afb 100644 (file)
@@ -51,7 +51,7 @@ void i_stream_close(struct istream *stream)
        stream->closed = TRUE;
 
        if (stream->stream_errno == 0)
-               stream->stream_errno = ECONNRESET;
+               stream->stream_errno = EBADFD;
 }
 
 void i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
@@ -62,12 +62,27 @@ void i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
 ssize_t i_stream_read(struct istream *stream)
 {
        struct istream_private *_stream = stream->real_stream;
+       ssize_t ret;
 
        if (unlikely(stream->closed))
                return -1;
 
        stream->eof = FALSE;
-       return _stream->read(_stream);
+       stream->stream_errno = 0;
+
+       ret = _stream->read(_stream);
+       if (ret < 0) {
+               if (stream->stream_errno != 0) {
+                       /* error handling should be easier if we now just
+                          assume the stream is now at EOF */
+                       stream->eof = TRUE;
+               } else {
+                       i_assert(stream->eof);
+               }
+       } else {
+               i_assert(ret != 0 || !stream->blocking);
+       }
+       return ret;
 }
 
 void i_stream_skip(struct istream *stream, uoff_t count)
@@ -91,6 +106,7 @@ void i_stream_skip(struct istream *stream, uoff_t count)
        if (unlikely(stream->closed))
                return;
 
+       stream->stream_errno = 0;
        _stream->seek(_stream, stream->v_offset + count, FALSE);
 }
 
@@ -295,11 +311,14 @@ int i_stream_read_data(struct istream *stream, const unsigned char **data_r,
                i_assert(!stream->blocking);
                return 0;
        }
-       if (read_more && stream->eof) {
-               /* we read at least some new data */
-               return 0;
+       if (stream->eof) {
+               if (read_more) {
+                       /* we read at least some new data */
+                       return 0;
+               }
+       } else {
+               i_assert(stream->stream_errno != 0);
        }
-       i_assert(stream->stream_errno != 0);
        return -1;
 }
 
index d48249f5d6c24a80c6bb10e2970992e3b40a2db0..3626be536a5996001142e0d40f0cc2fb6a110fe8 100644 (file)
@@ -55,11 +55,6 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
        size_t size;
        int ret;
 
-       if (stream->istream.closed)
-               return -1;
-
-       stream->istream.stream_errno = 0;
-
        if (stream->pos == stream->buffer_size) {
                if (!zstream->marked && stream->skip > 0) {
                        /* don't try to keep anything cached if we don't
@@ -104,7 +99,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
                        i_assert(!stream->istream.blocking);
                        ret = 0;
                } else {
-                       stream->istream.eof = TRUE;
+                       i_assert(errno != 0);
                        stream->istream.stream_errno = errno;
                        return -1;
                }
@@ -112,7 +107,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
 
        zstream->seek_offset += ret;
        stream->pos += ret;
-       i_assert(ret != 0);
+       i_assert(ret > 0);
        return ret;
 }
 
@@ -122,8 +117,6 @@ i_stream_zlib_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
        struct zlib_istream *zstream = (struct zlib_istream *) stream;
        uoff_t start_offset = stream->istream.v_offset - stream->skip;
 
-       stream->istream.stream_errno = 0;
-
 #ifndef HAVE_GZSEEK
        if (v_offset < start_offset) {
                /* need to reopen, but since closing the file closes the