Mercurial > dovecot > original-hg > dovecot-2.2
changeset 16773:76d5e3c8cec3
iostreams: Set stream error string when it provides extra information.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 20 Sep 2013 00:12:45 +0300 |
parents | e35be66003e2 |
children | 28df180ec3ab |
files | 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 |
diffstat | 19 files changed, 138 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-compression/istream-bzlib.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-compression/istream-bzlib.c Fri Sep 20 00:12:45 2013 +0300 @@ -38,10 +38,13 @@ 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 @@ 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 @@ 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:
--- a/src/lib-compression/istream-zlib.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-compression/istream-zlib.c Fri Sep 20 00:12:45 2013 +0300 @@ -55,10 +55,13 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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:
--- a/src/lib-fs/istream-metawrap.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-fs/istream-metawrap.c Fri Sep 20 00:12:45 2013 +0300 @@ -24,6 +24,8 @@ } 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; }
--- a/src/lib-mail/istream-dot.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-mail/istream-dot.c Fri Sep 20 00:12:45 2013 +0300 @@ -36,6 +36,8 @@ 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;
--- a/src/lib-mail/istream-qp-decoder.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-mail/istream-qp-decoder.c Fri Sep 20 00:12:45 2013 +0300 @@ -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 @@ 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 @@ { 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 @@ } /* 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; }
--- a/src/lib-ssl-iostream/iostream-openssl.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-openssl.c Fri Sep 20 00:12:45 2013 +0300 @@ -270,6 +270,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ break; } - if (errstr != NULL) - openssl_iostream_set_error(ssl_io, errstr); + openssl_iostream_set_error(ssl_io, errstr); return -1; }
--- a/src/lib-ssl-iostream/iostream-openssl.h Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-openssl.h Fri Sep 20 00:12:45 2013 +0300 @@ -31,6 +31,7 @@ char *host; char *last_error; char *log_prefix; + char *plain_stream_errstr; int plain_stream_errno; /* copied settings */
--- a/src/lib-ssl-iostream/istream-openssl.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-ssl-iostream/istream-openssl.c Fri Sep 20 00:12:45 2013 +0300 @@ -52,6 +52,8 @@ 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 @@ 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;
--- a/src/lib-ssl-iostream/ostream-openssl.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-ssl-iostream/ostream-openssl.c Fri Sep 20 00:12:45 2013 +0300 @@ -98,6 +98,8 @@ 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 @@ 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) {
--- a/src/lib-storage/index/istream-mail.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-storage/index/istream-mail.c Fri Sep 20 00:12:45 2013 +0300 @@ -46,10 +46,12 @@ 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; }
--- a/src/lib-storage/index/mbox/istream-raw-mbox.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib-storage/index/mbox/istream-raw-mbox.c Fri Sep 20 00:12:45 2013 +0300 @@ -85,6 +85,8 @@ &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 @@ 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 @@ 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;
--- a/src/lib/istream-base64-decoder.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-base64-decoder.c Fri Sep 20 00:12:45 2013 +0300 @@ -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 @@ 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 @@ { 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 @@ 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;
--- a/src/lib/istream-concat.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-concat.c Fri Sep 20 00:12:45 2013 +0300 @@ -204,9 +204,13 @@ 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;
--- a/src/lib/istream-file.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-file.c Fri Sep 20 00:12:45 2013 +0300 @@ -43,8 +43,9 @@ 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 @@ } 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 @@ 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 @@ { 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; }
--- a/src/lib/istream-hash.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-hash.c Fri Sep 20 00:12:45 2013 +0300 @@ -53,7 +53,8 @@ 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;
--- a/src/lib/istream-jsonstr.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-jsonstr.c Fri Sep 20 00:12:45 2013 +0300 @@ -135,6 +135,8 @@ 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; }
--- a/src/lib/istream-mmap.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-mmap.c Fri Sep 20 00:12:45 2013 +0300 @@ -119,6 +119,8 @@ 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;
--- a/src/lib/istream-sized.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/istream-sized.c Fri Sep 20 00:12:45 2013 +0300 @@ -46,8 +46,14 @@ 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 @@ } 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; }
--- a/src/lib/ostream-file.c Fri Sep 20 00:00:49 2013 +0300 +++ b/src/lib/ostream-file.c Fri Sep 20 00:12:45 2013 +0300 @@ -153,11 +153,15 @@ 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 @@ { 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;