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