Mercurial > dovecot > original-hg > dovecot-2.2
changeset 16772:e35be66003e2
iostream: Added ability to set/get error strings for streams.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 20 Sep 2013 00:00:49 +0300 |
parents | 5a334879572b |
children | 76d5e3c8cec3 |
files | src/lib/iostream-private.h src/lib/iostream.c src/lib/istream.c src/lib/istream.h src/lib/ostream.c src/lib/ostream.h |
diffstat | 6 files changed, 71 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/iostream-private.h Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/iostream-private.h Fri Sep 20 00:00:49 2013 +0300 @@ -11,6 +11,7 @@ struct iostream_private { int refcount; char *name; + char *error; void (*close)(struct iostream_private *streami, bool close_parent); void (*destroy)(struct iostream_private *stream); @@ -26,5 +27,11 @@ void io_stream_close(struct iostream_private *stream, bool close_parent); void io_stream_set_max_buffer_size(struct iostream_private *stream, size_t max_size); +/* Set a specific error for the stream. This shouldn't be used for regular + syscall errors where stream's errno is enough, since it's used by default. + The stream errno must always be set even if the error string is also set. + Setting this error replaces the previously set error. */ +void io_stream_set_error(struct iostream_private *stream, + const char *fmt, ...) ATTR_FORMAT(2, 3); #endif
--- a/src/lib/iostream.c Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/iostream.c Fri Sep 20 00:00:49 2013 +0300 @@ -46,6 +46,7 @@ array_free(&stream->destroy_callbacks); } + i_free(stream->error); i_free(stream->name); i_free(stream); } @@ -60,3 +61,14 @@ { stream->set_max_buffer_size(stream, max_size); } + +void io_stream_set_error(struct iostream_private *stream, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + i_free(stream->error); + stream->error = i_strdup_vprintf(fmt, args); + va_end(args); +}
--- a/src/lib/istream.c Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/istream.c Fri Sep 20 00:00:49 2013 +0300 @@ -92,6 +92,24 @@ return _stream->fd; } +const char *i_stream_get_error(struct istream *stream) +{ + struct istream *s; + + /* we'll only return errors for streams that have stream_errno set. + we might be returning unintended error otherwise. */ + if (stream->stream_errno == 0) + return "<no error>"; + + for (s = stream; s != NULL; s = s->real_stream->parent) { + if (s->stream_errno == 0) + break; + if (s->real_stream->iostream.error != NULL) + return s->real_stream->iostream.error; + } + return strerror(stream->stream_errno); +} + void i_stream_close(struct istream *stream) { i_stream_close_full(stream, TRUE);
--- a/src/lib/istream.h Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/istream.h Fri Sep 20 00:00:49 2013 +0300 @@ -65,6 +65,8 @@ /* Return file descriptor for stream, or -1 if none is available. */ int i_stream_get_fd(struct istream *stream); +/* Returns error string for the last error. */ +const char *i_stream_get_error(struct istream *stream); /* Mark the stream and all of its parent streams closed. Any reads after this will return -1. The data already read can still be used. */
--- a/src/lib/ostream.c Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/ostream.c Fri Sep 20 00:00:49 2013 +0300 @@ -25,6 +25,24 @@ return stream->real_stream->fd; } +const char *o_stream_get_error(struct ostream *stream) +{ + struct ostream *s; + + /* we'll only return errors for streams that have stream_errno set. + we might be returning unintended error otherwise. */ + if (stream->stream_errno == 0) + return "<no error>"; + + for (s = stream; s != NULL; s = s->real_stream->parent) { + if (s->stream_errno == 0) + break; + if (s->real_stream->iostream.error != NULL) + return s->real_stream->iostream.error; + } + return strerror(stream->stream_errno); +} + static void o_stream_close_full(struct ostream *stream, bool close_parents) { io_stream_close(&stream->real_stream->iostream, close_parents); @@ -107,6 +125,12 @@ _stream->cork(_stream, FALSE); } +static void o_stream_clear_error(struct ostream *stream) +{ + stream->stream_errno = 0; + i_free_and_null(stream->real_stream->iostream.error); +} + int o_stream_flush(struct ostream *stream) { struct ostream_private *_stream = stream->real_stream; @@ -117,7 +141,7 @@ return -1; } - stream->stream_errno = 0; + o_stream_clear_error(stream); if (unlikely((ret = _stream->flush(_stream)) < 0)) { i_assert(stream->stream_errno != 0); stream->last_failed_errno = stream->stream_errno; @@ -160,7 +184,7 @@ return -1; } - stream->stream_errno = 0; + o_stream_clear_error(stream); if (unlikely(_stream->seek(_stream, offset) < 0)) { i_assert(stream->stream_errno != 0); stream->last_failed_errno = stream->stream_errno; @@ -194,7 +218,7 @@ return -1; } - stream->stream_errno = 0; + o_stream_clear_error(stream); for (i = 0, total_size = 0; i < iov_count; i++) total_size += iov[i].iov_len; if (total_size == 0) @@ -283,7 +307,7 @@ return -1; } - outstream->stream_errno = 0; + o_stream_clear_error(outstream); ret = _outstream->send_istream(_outstream, instream); if (unlikely(ret < 0)) { i_assert(outstream->stream_errno != 0); @@ -303,6 +327,7 @@ return -1; } + o_stream_clear_error(stream); ret = stream->real_stream->write_at(stream->real_stream, data, size, offset); if (unlikely(ret < 0)) {
--- a/src/lib/ostream.h Thu Sep 19 22:44:20 2013 +0300 +++ b/src/lib/ostream.h Fri Sep 20 00:00:49 2013 +0300 @@ -46,6 +46,9 @@ /* Return file descriptor for stream, or -1 if none is available. */ int o_stream_get_fd(struct ostream *stream); +/* Returns error string for the previous error (stream_errno, + not last_failed_errno). */ +const char *o_stream_get_error(struct ostream *stream); /* Close this stream (but not its parents) and unreference it. */ void o_stream_destroy(struct ostream **stream);