dovecot-2.2: iostream: Added ability to set/get error strings fo...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Sep 20 00:13:04 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/e35be66003e2
changeset: 16772:e35be66003e2
user: Timo Sirainen <tss at iki.fi>
date: Fri Sep 20 00:00:49 2013 +0300
description:
iostream: Added ability to set/get error strings for streams.
diffstat:
src/lib/iostream-private.h | 7 +++++++
src/lib/iostream.c | 12 ++++++++++++
src/lib/istream.c | 18 ++++++++++++++++++
src/lib/istream.h | 2 ++
src/lib/ostream.c | 33 +++++++++++++++++++++++++++++----
src/lib/ostream.h | 3 +++
6 files changed, 71 insertions(+), 4 deletions(-)
diffs (187 lines):
diff -r 5a334879572b -r e35be66003e2 src/lib/iostream-private.h
--- 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
diff -r 5a334879572b -r e35be66003e2 src/lib/iostream.c
--- 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);
+}
diff -r 5a334879572b -r e35be66003e2 src/lib/istream.c
--- 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);
diff -r 5a334879572b -r e35be66003e2 src/lib/istream.h
--- 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. */
diff -r 5a334879572b -r e35be66003e2 src/lib/ostream.c
--- 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)) {
diff -r 5a334879572b -r e35be66003e2 src/lib/ostream.h
--- 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);
More information about the dovecot-cvs
mailing list