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