]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
iostreams: Set stream error string when it provides extra information.
authorTimo Sirainen <tss@iki.fi>
Thu, 19 Sep 2013 21:12:45 +0000 (00:12 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 19 Sep 2013 21:12:45 +0000 (00:12 +0300)
19 files changed:
src/lib-compression/istream-bzlib.c
src/lib-compression/istream-zlib.c
src/lib-fs/istream-metawrap.c
src/lib-mail/istream-dot.c
src/lib-mail/istream-qp-decoder.c
src/lib-ssl-iostream/iostream-openssl.c
src/lib-ssl-iostream/iostream-openssl.h
src/lib-ssl-iostream/istream-openssl.c
src/lib-ssl-iostream/ostream-openssl.c
src/lib-storage/index/istream-mail.c
src/lib-storage/index/mbox/istream-raw-mbox.c
src/lib/istream-base64-decoder.c
src/lib/istream-concat.c
src/lib/istream-file.c
src/lib/istream-hash.c
src/lib/istream-jsonstr.c
src/lib/istream-mmap.c
src/lib/istream-sized.c
src/lib/ostream-file.c

index 3937cb14922df4059356489300dc71fc0a275b61..fbf49244d2a99ee21f3b51de5cf643cc84ded5e9 100644 (file)
@@ -38,10 +38,13 @@ static void i_stream_bzlib_close(struct iostream_private *stream,
 
 static void bzlib_read_error(struct bzlib_istream *zstream, const char *error)
 {
-       i_error("bzlib.read(%s): %s at %"PRIuUOFF_T,
-               i_stream_get_name(&zstream->istream.istream), error,
-               zstream->istream.abs_start_offset +
-               zstream->istream.istream.v_offset);
+       io_stream_set_error(&zstream->istream.iostream,
+                           "bzlib.read(%s): %s at %"PRIuUOFF_T,
+                           i_stream_get_name(&zstream->istream.istream), error,
+                           zstream->istream.abs_start_offset +
+                           zstream->istream.istream.v_offset);
+       if (zstream->log_errors)
+               i_error("%s", zstream->istream.iostream.error);
 }
 
 static ssize_t i_stream_bzlib_read(struct istream_private *stream)
@@ -104,8 +107,7 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
                                stream->parent->stream_errno;
                } else {
                        i_assert(stream->parent->eof);
-                       if (zstream->log_errors)
-                               bzlib_read_error(zstream, "unexpected EOF");
+                       bzlib_read_error(zstream, "unexpected EOF");
                        stream->istream.stream_errno = EINVAL;
                }
                return -1;
@@ -135,15 +137,12 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
        case BZ_PARAM_ERROR:
                i_unreached();
        case BZ_DATA_ERROR:
-               if (zstream->log_errors)
-                       bzlib_read_error(zstream, "corrupted data");
+               bzlib_read_error(zstream, "corrupted data");
                stream->istream.stream_errno = EINVAL;
                return -1;
        case BZ_DATA_ERROR_MAGIC:
-               if (zstream->log_errors) {
-                       bzlib_read_error(zstream,
-                               "wrong magic in header (not bz2 file?)");
-               }
+               bzlib_read_error(zstream,
+                       "wrong magic in header (not bz2 file?)");
                stream->istream.stream_errno = EINVAL;
                return -1;
        case BZ_MEM_ERROR:
index c7ac2c429b1d981d570c2de74d98b42024b98c28..5e92bc6c85c19c103bcf58a7226be193541254c8 100644 (file)
@@ -55,10 +55,13 @@ static void i_stream_zlib_close(struct iostream_private *stream,
 
 static void zlib_read_error(struct zlib_istream *zstream, const char *error)
 {
-       i_error("zlib.read(%s): %s at %"PRIuUOFF_T,
-               i_stream_get_name(&zstream->istream.istream), error,
-               zstream->istream.abs_start_offset +
-               zstream->istream.istream.v_offset);
+       io_stream_set_error(&zstream->istream.iostream,
+                           "zlib.read(%s): %s at %"PRIuUOFF_T,
+                           i_stream_get_name(&zstream->istream.istream), error,
+                           zstream->istream.abs_start_offset +
+                           zstream->istream.istream.v_offset);
+       if (zstream->log_errors)
+               i_error("%s", zstream->istream.iostream.error);
 }
 
 static int i_stream_zlib_read_header(struct istream_private *stream)
@@ -73,8 +76,7 @@ static int i_stream_zlib_read_header(struct istream_private *stream)
                                 zstream->prev_size);
        if (size == zstream->prev_size) {
                if (ret == -1) {
-                       if (zstream->log_errors)
-                               zlib_read_error(zstream, "missing gz header");
+                       zlib_read_error(zstream, "missing gz header");
                        stream->istream.stream_errno = EINVAL;
                }
                return ret;
@@ -87,10 +89,7 @@ static int i_stream_zlib_read_header(struct istream_private *stream)
 
        if (data[0] != GZ_MAGIC1 || data[1] != GZ_MAGIC2) {
                /* missing gzip magic header */
-               if (zstream->log_errors) {
-                       zlib_read_error(zstream, "wrong magic in header "
-                                       "(not gz file?)");
-               }
+               zlib_read_error(zstream, "wrong magic in header (not gz file?)");
                stream->istream.stream_errno = EINVAL;
                return -1;
        }
@@ -143,8 +142,7 @@ static int i_stream_zlib_read_trailer(struct zlib_istream *zstream)
                                 GZ_TRAILER_SIZE-1);
        if (size == zstream->prev_size) {
                if (ret == -1) {
-                       if (zstream->log_errors)
-                               zlib_read_error(zstream, "missing gz trailer");
+                       zlib_read_error(zstream, "missing gz trailer");
                        stream->istream.stream_errno = EINVAL;
                }
                return ret;
@@ -155,10 +153,7 @@ static int i_stream_zlib_read_trailer(struct zlib_istream *zstream)
                return 0;
 
        if (data_get_uint32(data) != zstream->crc32) {
-               if (zstream->log_errors) {
-                       zlib_read_error(zstream,
-                                       "gz trailer has wrong CRC value");
-               }
+               zlib_read_error(zstream, "gz trailer has wrong CRC value");
                stream->istream.stream_errno = EINVAL;
                return -1;
        }
@@ -254,8 +249,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
                                stream->parent->stream_errno;
                } else {
                        i_assert(stream->parent->eof);
-                       if (zstream->log_errors)
-                               zlib_read_error(zstream, "unexpected EOF");
+                       zlib_read_error(zstream, "unexpected EOF");
                        stream->istream.stream_errno = EPIPE;
                }
                return -1;
@@ -286,13 +280,11 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
        case Z_OK:
                break;
        case Z_NEED_DICT:
-               if (zstream->log_errors)
-                       zlib_read_error(zstream, "can't read file without dict");
+               zlib_read_error(zstream, "can't read file without dict");
                stream->istream.stream_errno = EINVAL;
                return -1;
        case Z_DATA_ERROR:
-               if (zstream->log_errors)
-                       zlib_read_error(zstream, "corrupted data");
+               zlib_read_error(zstream, "corrupted data");
                stream->istream.stream_errno = EINVAL;
                return -1;
        case Z_MEM_ERROR:
index e09ca0d95eb586b3724e0264c1f758b5b2397d50..c518c28fb35084d80ddadd789378aade925d79b2 100644 (file)
@@ -24,6 +24,8 @@ static int metadata_header_read(struct metawrap_istream *mstream)
                }
                p = strchr(line, ':');
                if (p == NULL) {
+                       io_stream_set_error(&mstream->istream.iostream,
+                               "Metadata header line is missing ':'");
                        mstream->istream.istream.stream_errno = EINVAL;
                        return -1;
                }
index e2922b480f4c1f638c4d4204ea1255ca119faaaa..75f76a4a946168c65ecbfd127ce9cbaf4322f538 100644 (file)
@@ -36,6 +36,8 @@ static int i_stream_dot_read_some(struct dot_istream *dstream)
                                        stream->parent->stream_errno;
                        } else if (ret < 0 && stream->parent->eof) {
                                /* we didn't see "." line */
+                               io_stream_set_error(&stream->iostream,
+                                       "dot-input stream ends without '.' line");
                                stream->istream.stream_errno = EPIPE;
                        }
                        return ret;
index 3a4c0f321bcc1213bdf86ea8b28630e9f8f2c34c..67885a5741d9638d366665202b0e639151814333 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "buffer.h"
+#include "hex-binary.h"
 #include "istream-private.h"
 #include "quoted-printable.h"
 #include "istream-qp.h"
@@ -64,6 +65,9 @@ i_stream_qp_try_decode_input(struct qp_decoder_istream *bstream, bool eof)
        ret = !eof ? quoted_printable_decode(data, size, &pos, &buf) :
                quoted_printable_decode_final(data, size, &pos, &buf);
        if (ret < 0) {
+               io_stream_set_error(&stream->iostream,
+                       "Invalid quoted-printable data: 0x%s",
+                       binary_to_hex(data+pos, I_MAX(size-pos, 8)));
                stream->istream.stream_errno = EINVAL;
                return -1;
        }
@@ -77,7 +81,8 @@ static ssize_t i_stream_qp_decoder_read(struct istream_private *stream)
 {
        struct qp_decoder_istream *bstream =
                (struct qp_decoder_istream *)stream;
-       size_t pre_count, post_count;
+       const unsigned char *data;
+       size_t pre_count, post_count, size;
        int ret;
        size_t prev_size = 0;
 
@@ -95,6 +100,10 @@ static ssize_t i_stream_qp_decoder_read(struct istream_private *stream)
                        }
                        /* partial qp input */
                        i_assert(ret < 0);
+                       data = i_stream_get_data(stream->parent, &size);
+                       io_stream_set_error(&stream->iostream,
+                               "quoted-printable input ends with a partial block: 0x%s",
+                               binary_to_hex(data, size));
                        stream->istream.stream_errno = EINVAL;
                        return -1;
                }
index e0cf98b47fed0c00ae82c2d92f3270a8df3c68d9..353c35d6daf84ee331b6861bd371ea5c22f586d4 100644 (file)
@@ -270,6 +270,7 @@ static void openssl_iostream_free(struct ssl_iostream *ssl_io)
        o_stream_unref(&ssl_io->plain_output);
        BIO_free(ssl_io->bio_ext);
        SSL_free(ssl_io->ssl);
+       i_free(ssl_io->plain_stream_errstr);
        i_free(ssl_io->last_error);
        i_free(ssl_io->host);
        i_free(ssl_io->log_prefix);
@@ -331,6 +332,9 @@ static bool openssl_iostream_bio_output(struct ssl_iostream *ssl_io)
                if (sent < 0) {
                        i_assert(ssl_io->plain_output->closed ||
                                 ssl_io->plain_output->stream_errno != 0);
+                       i_free(ssl_io->plain_stream_errstr);
+                       ssl_io->plain_stream_errstr =
+                               i_strdup(o_stream_get_error(ssl_io->plain_output));
                        ssl_io->plain_stream_errno =
                                ssl_io->plain_output->stream_errno;
                        ssl_io->closed = TRUE;
@@ -376,6 +380,9 @@ static bool openssl_iostream_bio_input(struct ssl_iostream *ssl_io)
                ret = openssl_iostream_read_more(ssl_io, &data, &size);
                ssl_io->plain_input->real_stream->try_alloc_limit = 0;
                if (ret == -1 && size == 0 && !bytes_read) {
+                       i_free(ssl_io->plain_stream_errstr);
+                       ssl_io->plain_stream_errstr =
+                               i_strdup(i_stream_get_error(ssl_io->plain_input));
                        ssl_io->plain_stream_errno =
                                ssl_io->plain_input->stream_errno;
                        ssl_io->closed = TRUE;
@@ -397,12 +404,18 @@ static bool openssl_iostream_bio_input(struct ssl_iostream *ssl_io)
        if (bytes == 0 && !bytes_read && ssl_io->want_read) {
                /* shouldn't happen */
                i_error("SSL BIO buffer size too small");
+               i_free(ssl_io->plain_stream_errstr);
+               ssl_io->plain_stream_errstr =
+                       i_strdup("SSL BIO buffer size too small");
                ssl_io->plain_stream_errno = EINVAL;
                ssl_io->closed = TRUE;
                return FALSE;
        }
        if (i_stream_get_data_size(ssl_io->plain_input) > 0) {
                i_error("SSL: Too much data in buffered plain input buffer");
+               i_free(ssl_io->plain_stream_errstr);
+               ssl_io->plain_stream_errstr =
+                       i_strdup("SSL: Too much data in buffered plain input buffer");
                ssl_io->plain_stream_errno = EINVAL;
                ssl_io->closed = TRUE;
                return FALSE;
@@ -455,6 +468,8 @@ openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret,
                        return 0;
                }
                if (ssl_io->closed) {
+                       if (ssl_io->plain_stream_errstr != NULL)
+                               openssl_iostream_set_error(ssl_io, ssl_io->plain_stream_errstr);
                        errno = ssl_io->plain_stream_errno != 0 ?
                                ssl_io->plain_stream_errno : EPIPE;
                        return -1;
@@ -464,6 +479,8 @@ openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret,
                ssl_io->want_read = TRUE;
                (void)openssl_iostream_bio_sync(ssl_io);
                if (ssl_io->closed) {
+                       if (ssl_io->plain_stream_errstr != NULL)
+                               openssl_iostream_set_error(ssl_io, ssl_io->plain_stream_errstr);
                        errno = ssl_io->plain_stream_errno != 0 ?
                                ssl_io->plain_stream_errno : EPIPE;
                        return -1;
@@ -489,7 +506,8 @@ openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret,
        case SSL_ERROR_ZERO_RETURN:
                /* clean connection closing */
                errno = ECONNRESET;
-               break;
+               i_free_and_null(ssl_io->last_error);
+               return -1;
        case SSL_ERROR_SSL:
                errstr = t_strdup_printf("%s failed: %s",
                                         func_name, openssl_iostream_error());
@@ -503,8 +521,7 @@ openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret,
                break;
        }
 
-       if (errstr != NULL)
-               openssl_iostream_set_error(ssl_io, errstr);
+       openssl_iostream_set_error(ssl_io, errstr);
        return -1;
 }
 
index 44904019eec086f2ce46f86149971869043d4932..5e9f4c80066b9dff2f27a6c6d78277196cd8f193 100644 (file)
@@ -31,6 +31,7 @@ struct ssl_iostream {
        char *host;
        char *last_error;
        char *log_prefix;
+       char *plain_stream_errstr;
        int plain_stream_errno;
 
        /* copied settings */
index 8fa6d10451a4d10331ceb7ad90edcb249be78ce4..536b4b3374516757a0f84709c3a37297cb26ab86 100644 (file)
@@ -52,6 +52,8 @@ static ssize_t i_stream_ssl_read_real(struct istream_private *stream)
                if (ret < 0) {
                        /* handshake failed */
                        i_assert(errno != 0);
+                       io_stream_set_error(&stream->iostream,
+                                           "%s", ssl_io->last_error);
                        stream->istream.stream_errno = errno;
                }
                return ret;
@@ -70,6 +72,8 @@ static ssize_t i_stream_ssl_read_real(struct istream_private *stream)
                ret = openssl_iostream_handle_error(ssl_io, ret, "SSL_read");
                if (ret <= 0) {
                        if (ret < 0) {
+                               io_stream_set_error(&stream->iostream,
+                                                   "%s", ssl_io->last_error);
                                stream->istream.stream_errno = errno;
                                stream->istream.eof = TRUE;
                                sstream->seen_eof = TRUE;
index b4c5b3354a7de2e69ee56830a866ab3018a3320a..341115df67ff6c793920919ee27100c4337cfb5f 100644 (file)
@@ -98,6 +98,8 @@ static int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream)
                        ret = openssl_iostream_handle_write_error(sstream->ssl_io,
                                                                  ret, "SSL_write");
                        if (ret < 0) {
+                               io_stream_set_error(&sstream->ostream.iostream,
+                                       "%s", sstream->ssl_io->last_error);
                                sstream->ostream.ostream.stream_errno = errno;
                                break;
                        }
@@ -119,6 +121,8 @@ static int o_stream_ssl_flush(struct ostream_private *stream)
 
        if ((ret = openssl_iostream_more(sstream->ssl_io)) < 0) {
                /* handshake failed */
+               io_stream_set_error(&stream->iostream, "%s",
+                                   sstream->ssl_io->last_error);
                stream->ostream.stream_errno = errno;
        } else if (ret > 0 && sstream->buffer != NULL &&
                   sstream->buffer->used > 0) {
index 9364d7fac5d4b68110fc4644374ce402d92997c4..1bab4b52f6d98dea78ba4b2c797563a5ff41ba0c 100644 (file)
@@ -46,10 +46,12 @@ i_stream_mail_set_size_corrupted(struct mail_istream *mstream, size_t size)
                chr = '>';
        }
 
-       mail_storage_set_critical(mstream->mail->box->storage,
+       io_stream_set_error(&mstream->istream.iostream,
                "Cached message size %s than expected "
                "(%"PRIuUOFF_T" %c %"PRIuUOFF_T")", str,
                mstream->expected_size, chr, cur_size);
+       mail_storage_set_critical(mstream->mail->box->storage, "%s",
+                                 mstream->istream.iostream.error);
        mail_set_cache_corrupted(mstream->mail, MAIL_FETCH_PHYSICAL_SIZE);
        mstream->istream.istream.stream_errno = EINVAL;
 }
index 99c1b70d5d8d6978d818f132ade05d9b7ed31018..2de275d0ffd9f9b0cef7cb4b229e89018949afde 100644 (file)
@@ -85,6 +85,8 @@ static int mbox_read_from_line(struct raw_mbox_istream *rstream)
                            &received_time, &tz, &sender) < 0) {
                /* broken From - should happen only at beginning of
                   file if this isn't a mbox.. */
+               io_stream_set_error(&rstream->istream.iostream,
+                       "mbox file doesn't begin with 'From ' line");
                rstream->istream.istream.stream_errno = EINVAL;
                return -1;
        }
@@ -253,12 +255,13 @@ static ssize_t i_stream_raw_mbox_read(struct istream_private *stream)
                        return i_stream_raw_mbox_read(stream);
                }
                if (mbox_read_from_line(rstream) < 0) {
-                       if (stream->istream.v_offset != 0) {
-                               i_error("Next message unexpectedly corrupted in mbox file "
-                                       "%s at %"PRIuUOFF_T,
-                                       i_stream_get_name(&stream->istream),
-                                       stream->istream.v_offset);
-                       }
+                       io_stream_set_error(&stream->iostream,
+                               "Next message unexpectedly corrupted in mbox file "
+                               "%s at %"PRIuUOFF_T,
+                               i_stream_get_name(&stream->istream),
+                               stream->istream.v_offset);
+                       if (stream->istream.v_offset != 0)
+                               i_error("%s", stream->iostream.error);
                        stream->pos = 0;
                        rstream->eof = TRUE;
                        rstream->corrupted = TRUE;
@@ -356,11 +359,13 @@ static ssize_t i_stream_raw_mbox_read(struct istream_private *stream)
            rstream->hdr_offset + new_pos > rstream->mail_size) {
                /* istream_raw_mbox_set_next_offset() used invalid
                   cached next_offset? */
-               i_error("Next message unexpectedly lost from mbox file "
+               io_stream_set_error(&stream->iostream,
+                       "Next message unexpectedly lost from mbox file "
                        "%s at %"PRIuUOFF_T" (%s)",
                        i_stream_get_name(&stream->istream),
                        rstream->hdr_offset + rstream->mail_size,
                        rstream->mail_size_forced ? "cached" : "noncached");
+               i_error("%s", stream->iostream.error);
                rstream->eof = TRUE;
                rstream->corrupted = TRUE;
                rstream->istream.istream.stream_errno = EINVAL;
index 551dc50b5562e497ae58b93d2b467117fb508c90..6d61fea9aa49377a3f47aa3f97d20883525ba58e 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "buffer.h"
 #include "base64.h"
+#include "hex-binary.h"
 #include "istream-private.h"
 #include "istream-base64.h"
 
@@ -58,6 +59,9 @@ i_stream_base64_try_decode_block(struct base64_decoder_istream *bstream)
        buffer_create_from_data(&buf, stream->w_buffer + stream->pos,
                                buffer_avail);
        if (base64_decode(data, size, &pos, &buf) < 0) {
+               io_stream_set_error(&stream->iostream,
+                       "Invalid base64 data: 0x%s",
+                       binary_to_hex(data+pos, I_MAX(size-pos, 8)));
                stream->istream.stream_errno = EINVAL;
                return -1;
        }
@@ -71,7 +75,8 @@ static ssize_t i_stream_base64_decoder_read(struct istream_private *stream)
 {
        struct base64_decoder_istream *bstream =
                (struct base64_decoder_istream *)stream;
-       size_t pre_count, post_count;
+       const unsigned char *data;
+       size_t pre_count, post_count, size;
        int ret;
 
        do {
@@ -80,6 +85,10 @@ static ssize_t i_stream_base64_decoder_read(struct istream_private *stream)
                        if (ret < 0 && stream->istream.stream_errno == 0 &&
                            i_stream_get_data_size(stream->parent) > 0) {
                                /* base64 input with a partial block */
+                               data = i_stream_get_data(stream->parent, &size);
+                               io_stream_set_error(&stream->iostream,
+                                       "base64 input ends with a partial block: 0x%s",
+                                       binary_to_hex(data, size));
                                stream->istream.stream_errno = EINVAL;
                        }
                        return ret;
index e6632eedf01623fb8454c7778a0fd19e979674d5..f2f71af1a71889ca77066c2ee972ae58747965d0 100644 (file)
@@ -204,9 +204,13 @@ find_v_offset(struct concat_istream *cstream, uoff_t *v_offset)
                if (i == cstream->unknown_size_idx) {
                        /* we'll need to figure out this stream's size */
                        if (i_stream_stat(cstream->input[i], TRUE, &st) < 0) {
-                               i_error("istream-concat: "
-                                       "Failed to get size of stream %s",
-                                       i_stream_get_name(cstream->input[i]));
+                               io_stream_set_error(&cstream->istream.iostream,
+                                       "stat(%s) failed: %s",
+                                       i_stream_get_name(cstream->input[i]),
+                                       i_stream_get_error(cstream->input[i]));
+                               i_error("istream-concat: stat(%s) failed: %s",
+                                       i_stream_get_name(cstream->input[i]),
+                                       i_stream_get_error(cstream->input[i]));
                                cstream->istream.istream.stream_errno =
                                        cstream->input[i]->stream_errno;
                                return UINT_MAX;
index 61247eb2315e46949ecf0895401bc9e1f1f2b3bb..2d04106e852d7813a1d679bb9271e14a994f1580 100644 (file)
@@ -43,8 +43,9 @@ static int i_stream_file_open(struct istream_private *stream)
 
        stream->fd = open(path, O_RDONLY);
        if (stream->fd == -1) {
+               io_stream_set_error(&stream->iostream,
+                                   "open(%s) failed: %m", path);
                stream->istream.stream_errno = errno;
-               i_error("file_istream.open(%s) failed: %m", path);
                return -1;
        }
        return 0;
@@ -169,7 +170,8 @@ i_stream_file_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
 }
 
 static struct istream *
-i_stream_create_file_common(int fd, size_t max_buffer_size, bool autoclose_fd)
+i_stream_create_file_common(int fd, const char *path,
+                           size_t max_buffer_size, bool autoclose_fd)
 {
        struct file_istream *fstream;
        struct istream *input;
@@ -198,6 +200,9 @@ i_stream_create_file_common(int fd, size_t max_buffer_size, bool autoclose_fd)
        else {
                /* we're trying to open a directory.
                   we're not designed for it. */
+               io_stream_set_error(&fstream->istream.iostream,
+                       "%s is a directory, can't read it as file",
+                       path != NULL ? path : t_strdup_printf("<fd %d>", fd));
                fstream->istream.istream.stream_errno = EISDIR;
                is_file = FALSE;
        }
@@ -218,14 +223,14 @@ struct istream *i_stream_create_fd(int fd, size_t max_buffer_size,
 {
        i_assert(fd != -1);
 
-       return i_stream_create_file_common(fd, max_buffer_size, autoclose_fd);
+       return i_stream_create_file_common(fd, NULL, max_buffer_size, autoclose_fd);
 }
 
 struct istream *i_stream_create_file(const char *path, size_t max_buffer_size)
 {
        struct istream *input;
 
-       input = i_stream_create_file_common(-1, max_buffer_size, TRUE);
+       input = i_stream_create_file_common(-1, path, max_buffer_size, TRUE);
        i_stream_set_name(input, path);
        return input;
 }
index b64929c09f77153feac813629b78c2274f05980c..d86a46e3533a3d0c08793890d4e0da30f3a19976 100644 (file)
@@ -53,7 +53,8 @@ i_stream_hash_seek(struct istream_private *stream,
        struct hash_istream *hstream = (struct hash_istream *)stream;
 
        if (hstream->hash_context != NULL) {
-               /* we support seeking only after the hash is finished */
+               io_stream_set_error(&stream->iostream,
+                       "Seeking not supported before hashing is finished");
                stream->istream.stream_errno = ESPIPE;
        }
        stream->istream.v_offset = v_offset;
index 087c94a7aadd1c8f42a9daa8b56837925f1d6b93..ec98497148172fe799af694c06f3cf7aa7eb8172 100644 (file)
@@ -135,6 +135,8 @@ static ssize_t i_stream_jsonstr_read(struct istream_private *stream)
                                                   stream->w_buffer + dest,
                                                   &srcskip, &destskip) < 0) {
                                /* invalid string */
+                               io_stream_set_error(&stream->iostream,
+                                                   "Invalid JSON string");
                                stream->istream.stream_errno = EINVAL;
                                return -1;
                        }
index 77d5ff211e9d9259cf5a8fe8f81951c71d4790b0..7d8bb604ef00df20edd9d4daea7b8177f87a77f7 100644 (file)
@@ -119,6 +119,8 @@ static ssize_t i_stream_mmap_read(struct istream_private *stream)
                        stream->buffer = NULL;
                        stream->buffer_size = 0;
                        stream->skip = stream->pos = 0;
+                       io_stream_set_error(&stream->iostream,
+                                           "mmap() failed: %m");
                        i_error("mmap_istream.mmap(%s) failed: %m",
                                i_stream_get_name(&stream->istream));
                        return -1;
index 4db1bb65d0531a9b25213ab8a9ab1c10547d9294..9ef44d11785a6ac4ff916b771f33baf3a48b0f4b 100644 (file)
@@ -46,8 +46,14 @@ static ssize_t i_stream_sized_read(struct istream_private *stream)
        if (pos == left)
                stream->istream.eof = TRUE;
        else if (pos > left) {
-               i_error("%s is larger than expected (%"PRIuUOFF_T")",
-                       i_stream_get_name(stream->parent), sstream->size);
+               io_stream_set_error(&stream->iostream,
+                       "Stream is larger than expected "
+                       "(%"PRIuUOFF_T" > %"PRIuUOFF_T", eof=%d)",
+                       stream->istream.v_offset+pos, sstream->size,
+                       stream->istream.eof);
+               i_error("read(%s) failed: %s",
+                       i_stream_get_name(stream->parent),
+                       stream->iostream.error);
                pos = left;
                stream->istream.eof = TRUE;
        } else if (!stream->istream.eof) {
@@ -55,10 +61,13 @@ static ssize_t i_stream_sized_read(struct istream_private *stream)
        } else if (stream->istream.stream_errno == ENOENT) {
                /* lost the file */
        } else {
-               i_error("%s smaller than expected "
-                       "(%"PRIuUOFF_T" < %"PRIuUOFF_T")",
+               io_stream_set_error(&stream->iostream,
+                                   "Stream is smaller than expected "
+                                   "(%"PRIuUOFF_T" < %"PRIuUOFF_T")",
+                                   stream->istream.v_offset+pos, sstream->size);
+               i_error("read(%s) failed: %s",
                        i_stream_get_name(stream->parent),
-                       stream->istream.v_offset, sstream->size);
+                       stream->iostream.error);
                stream->istream.stream_errno = EINVAL;
        }
 
index 2868fd04a985eac470d12b03e30557f7bba53fb6..6365aeb1d77b137c96e84e44a029a20baee99385 100644 (file)
@@ -153,11 +153,15 @@ static int o_stream_lseek(struct file_ostream *fstream)
 
        ret = lseek(fstream->fd, (off_t)fstream->buffer_offset, SEEK_SET);
        if (ret < 0) {
+               io_stream_set_error(&fstream->ostream.iostream,
+                                   "lseek() failed: %m");
                fstream->ostream.ostream.stream_errno = errno;
                return -1;
        }
 
        if (ret != (off_t)fstream->buffer_offset) {
+               io_stream_set_error(&fstream->ostream.iostream,
+                                   "lseek() returned wrong value");
                fstream->ostream.ostream.stream_errno = EINVAL;
                return -1;
        }
@@ -397,10 +401,14 @@ static int o_stream_file_seek(struct ostream_private *stream, uoff_t offset)
 {
        struct file_ostream *fstream = (struct file_ostream *)stream;
 
-       if (offset > OFF_T_MAX || !fstream->file) {
+       if (offset > OFF_T_MAX) {
                stream->ostream.stream_errno = EINVAL;
                return -1;
        }
+       if (!fstream->file) {
+               stream->ostream.stream_errno = ESPIPE;
+               return -1;
+       }
 
        if (buffer_flush(fstream) < 0)
                return -1;