dovecot-2.2: lib: Added i_stream_create_sized_with_callback(). T...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 28 12:01:34 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/5fa5cbdf65a3
changeset: 19239:5fa5cbdf65a3
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Sep 28 14:59:04 2015 +0300
description:
lib: Added i_stream_create_sized_with_callback(). The callback returns the wanted error string.

diffstat:

 src/lib/istream-sized.c |  72 ++++++++++++++++++++++++++++++++++++++++--------
 src/lib/istream-sized.h |  26 +++++++++++++++++
 2 files changed, 86 insertions(+), 12 deletions(-)

diffs (161 lines):

diff -r ea56193d05b3 -r 5fa5cbdf65a3 src/lib/istream-sized.c
--- a/src/lib/istream-sized.c	Mon Sep 28 14:41:15 2015 +0300
+++ b/src/lib/istream-sized.c	Mon Sep 28 14:59:04 2015 +0300
@@ -7,6 +7,9 @@
 struct sized_istream {
 	struct istream_private istream;
 
+	istream_sized_callback_t *error_callback;
+	void *error_context;
+
 	uoff_t size;
 	bool failed;
 };
@@ -26,10 +29,28 @@
 	i_stream_unref(&sstream->istream.parent);
 }
 
+static const char *
+i_stream_create_sized_default_error_callback(
+	const struct istream_sized_error_data *data, void *context ATTR_UNUSED)
+{
+	if (data->v_offset + data->new_bytes < data->wanted_size) {
+		return t_strdup_printf("Stream is smaller than expected "
+			"(%"PRIuUOFF_T" < %"PRIuUOFF_T")",
+			data->v_offset + data->new_bytes, data->wanted_size);
+	} else {
+		return t_strdup_printf("Stream is larger than expected "
+			"(%"PRIuUOFF_T" > %"PRIuUOFF_T", eof=%d)",
+			data->v_offset + data->new_bytes, data->wanted_size,
+			data->eof);
+	}
+}
+
 static ssize_t i_stream_sized_read(struct istream_private *stream)
 {
 	struct sized_istream *sstream =
 		(struct sized_istream *)stream;
+	struct istream_sized_error_data data;
+	const char *error;
 	uoff_t left;
 	ssize_t ret;
 	size_t pos;
@@ -64,15 +85,18 @@
 		stream->buffer = i_stream_get_data(stream->parent, &pos);
 	} while (pos <= stream->pos && ret > 0);
 
+	memset(&data, 0, sizeof(data));
+	data.v_offset = stream->istream.v_offset;
+	data.new_bytes = pos;
+	data.wanted_size = sstream->size;
+	data.eof = stream->istream.eof;
+
 	left = sstream->size - stream->istream.v_offset;
 	if (pos == left)
 		stream->istream.eof = TRUE;
 	else if (pos > left) {
-		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);
+		error = sstream->error_callback(&data, sstream->error_context);
+		io_stream_set_error(&stream->iostream, "%s", error);
 		i_error("read(%s) failed: %s",
 			i_stream_get_name(stream->parent),
 			stream->iostream.error);
@@ -86,10 +110,8 @@
 	} else if (stream->istream.stream_errno == ENOENT) {
 		/* lost the file */
 	} else {
-		io_stream_set_error(&stream->iostream,
-				    "Stream is smaller than expected "
-				    "(%"PRIuUOFF_T" < %"PRIuUOFF_T")",
-				    stream->istream.v_offset+pos, sstream->size);
+		error = sstream->error_callback(&data, sstream->error_context);
+		io_stream_set_error(&stream->iostream, "%s", error);
 		i_error("read(%s) failed: %s",
 			i_stream_get_name(stream->parent),
 			stream->iostream.error);
@@ -123,7 +145,8 @@
 	return 0;
 }
 
-struct istream *i_stream_create_sized(struct istream *input, uoff_t size)
+static struct sized_istream *
+i_stream_create_sized_common(struct istream *input, uoff_t size)
 {
 	struct sized_istream *sstream;
 
@@ -138,6 +161,31 @@
 	sstream->istream.istream.readable_fd = input->readable_fd;
 	sstream->istream.istream.blocking = input->blocking;
 	sstream->istream.istream.seekable = input->seekable;
-	return i_stream_create(&sstream->istream, input,
-			       i_stream_get_fd(input));
+	(void)i_stream_create(&sstream->istream, input,
+			      i_stream_get_fd(input));
+	return sstream;
 }
+
+struct istream *i_stream_create_sized(struct istream *input, uoff_t size)
+{
+	struct sized_istream *sstream;
+
+	sstream = i_stream_create_sized_common(input, size);
+	sstream->error_callback = i_stream_create_sized_default_error_callback;
+	sstream->error_context = sstream;
+	return &sstream->istream.istream;
+}
+
+#undef i_stream_create_sized_with_callback
+struct istream *
+i_stream_create_sized_with_callback(struct istream *input, uoff_t size,
+				    istream_sized_callback_t *error_callback,
+				    void *context)
+{
+	struct sized_istream *sstream;
+
+	sstream = i_stream_create_sized_common(input, size);
+	sstream->error_callback = error_callback;
+	sstream->error_context = context;
+	return &sstream->istream.istream;
+}
diff -r ea56193d05b3 -r 5fa5cbdf65a3 src/lib/istream-sized.h
--- a/src/lib/istream-sized.h	Mon Sep 28 14:41:15 2015 +0300
+++ b/src/lib/istream-sized.h	Mon Sep 28 14:59:04 2015 +0300
@@ -1,8 +1,34 @@
 #ifndef ISTREAM_SIZED_H
 #define ISTREAM_SIZED_H
 
+struct istream_sized_error_data {
+	/* Stream's current v_offset */
+	uoff_t v_offset;
+	/* How many more bytes are being added within this read() */
+	size_t new_bytes;
+	/* What's the original wanted size. */
+	uoff_t wanted_size;
+	/* TRUE if we're at EOF now */
+	bool eof;
+};
+
+typedef const char *
+istream_sized_callback_t(const struct istream_sized_error_data *data,
+			 void *context);
+
 /* Assume that input is exactly the given size. If it's smaller, log an error
    and fail with EINVAL error. If it's larger, log an error but don't fail. */
 struct istream *i_stream_create_sized(struct istream *input, uoff_t size);
+/* Same as i_stream_create_sized(), but set the error message via the
+   callback. */
+struct istream *
+i_stream_create_sized_with_callback(struct istream *input, uoff_t size,
+				    istream_sized_callback_t *error_callback,
+				    void *context);
+#define i_stream_create_sized_with_callback(input, size, error_callback, context) \
+	i_stream_create_sized_with_callback(input, size + \
+		CALLBACK_TYPECHECK(error_callback, \
+			const char *(*)(const struct istream_sized_error_data *, typeof(context))), \
+		(istream_sized_callback_t *)error_callback, context)
 
 #endif


More information about the dovecot-cvs mailing list