dovecot-2.2: lib: Added i_stream_create_failure_at() to inject E...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Jun 16 13:43:09 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/99827acc1888
changeset: 18865:99827acc1888
user: Timo Sirainen <tss at iki.fi>
date: Tue Jun 16 16:21:56 2015 +0300
description:
lib: Added i_stream_create_failure_at() to inject EIO at given offset in istream.
diffstat:
src/lib/Makefile.am | 3 +
src/lib/istream-failure-at.c | 88 +++++++++++++++++++++++++++++++++++++++
src/lib/istream-failure-at.h | 10 ++++
src/lib/test-istream-failure-at.c | 46 ++++++++++++++++++++
src/lib/test-lib.c | 1 +
src/lib/test-lib.h | 1 +
6 files changed, 149 insertions(+), 0 deletions(-)
diffs (205 lines):
diff -r 80c1be850fdc -r 99827acc1888 src/lib/Makefile.am
--- a/src/lib/Makefile.am Tue Jun 16 14:12:59 2015 +0300
+++ b/src/lib/Makefile.am Tue Jun 16 16:21:56 2015 +0300
@@ -65,6 +65,7 @@
istream-concat.c \
istream-crlf.c \
istream-data.c \
+ istream-failure-at.c \
istream-file.c \
istream-hash.c \
istream-jsonstr.c \
@@ -203,6 +204,7 @@
istream-chain.h \
istream-concat.h \
istream-crlf.h \
+ istream-failure-at.h \
istream-file-private.h \
istream-hash.h \
istream-jsonstr.h \
@@ -306,6 +308,7 @@
test-istream-base64-encoder.c \
test-istream-concat.c \
test-istream-crlf.c \
+ test-istream-failure-at.c \
test-istream-seekable.c \
test-istream-tee.c \
test-istream-unix.c \
diff -r 80c1be850fdc -r 99827acc1888 src/lib/istream-failure-at.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-failure-at.c Tue Jun 16 16:21:56 2015 +0300
@@ -0,0 +1,88 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream-private.h"
+#include "istream-failure-at.h"
+
+struct failure_at_istream {
+ struct istream_private istream;
+ char *error_string;
+ uoff_t failure_offset;
+};
+
+static void i_stream_failure_at_destroy(struct iostream_private *stream)
+{
+ struct failure_at_istream *fstream =
+ (struct failure_at_istream *)stream;
+
+ i_free(fstream->error_string);
+}
+
+static ssize_t
+i_stream_failure_at_read(struct istream_private *stream)
+{
+ struct failure_at_istream *fstream = (struct failure_at_istream *)stream;
+ uoff_t new_offset;
+ ssize_t ret;
+
+ i_stream_seek(stream->parent, stream->parent_start_offset +
+ stream->istream.v_offset);
+
+ ret = i_stream_read_copy_from_parent(&stream->istream);
+ new_offset = stream->istream.v_offset + (stream->pos - stream->skip);
+ if (ret >= 0 && new_offset >= fstream->failure_offset) {
+ if (stream->istream.v_offset >= fstream->failure_offset) {
+ /* we already passed the wanted failure offset,
+ return error immediately. */
+ stream->pos = stream->skip;
+ stream->istream.stream_errno = errno = EIO;
+ io_stream_set_error(&stream->iostream, "%s",
+ fstream->error_string);
+ ret = -1;
+ } else {
+ /* return data up to the wanted failure offset and
+ on the next read() call return failure */
+ size_t new_pos = fstream->failure_offset -
+ stream->istream.v_offset + stream->skip;
+ i_assert(new_pos >= stream->skip &&
+ stream->pos >= new_pos);
+ ret -= stream->pos - new_pos;
+ stream->pos = new_pos;
+ }
+ } else if (ret < 0 && stream->istream.stream_errno == 0 &&
+ fstream->failure_offset == (uoff_t)-1) {
+ /* failure at EOF */
+ stream->istream.stream_errno = errno = EIO;
+ io_stream_set_error(&stream->iostream, "%s",
+ fstream->error_string);
+ }
+ return ret;
+}
+
+struct istream *
+i_stream_create_failure_at(struct istream *input, uoff_t failure_offset,
+ const char *error_string)
+{
+ struct failure_at_istream *fstream;
+
+ fstream = i_new(struct failure_at_istream, 1);
+ fstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
+ fstream->istream.stream_size_passthrough = TRUE;
+
+ fstream->istream.read = i_stream_failure_at_read;
+ fstream->istream.iostream.destroy = i_stream_failure_at_destroy;
+
+ fstream->istream.istream.blocking = input->blocking;
+ fstream->istream.istream.seekable = input->seekable;
+
+ fstream->error_string = i_strdup(error_string);
+ fstream->failure_offset = failure_offset;
+ return i_stream_create(&fstream->istream, input,
+ i_stream_get_fd(input));
+}
+
+struct istream *
+i_stream_create_failure_at_eof(struct istream *input, const char *error_string)
+{
+ return i_stream_create_failure_at(input, (uoff_t)-1, error_string);
+}
diff -r 80c1be850fdc -r 99827acc1888 src/lib/istream-failure-at.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-failure-at.h Tue Jun 16 16:21:56 2015 +0300
@@ -0,0 +1,10 @@
+#ifndef ISTREAM_FAILURE_AT_H
+#define ISTREAM_FAILURE_AT_H
+
+struct istream *
+i_stream_create_failure_at(struct istream *input, uoff_t failure_offset,
+ const char *error_string);
+struct istream *
+i_stream_create_failure_at_eof(struct istream *input, const char *error_string);
+
+#endif
diff -r 80c1be850fdc -r 99827acc1888 src/lib/test-istream-failure-at.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-istream-failure-at.c Tue Jun 16 16:21:56 2015 +0300
@@ -0,0 +1,46 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "istream.h"
+#include "istream-failure-at.h"
+
+#define TEST_DATA_LENGTH 128
+#define TEST_ERRMSG "test-istream-failure-at error triggered"
+
+void test_istream_failure_at(void)
+{
+ struct istream *input, *data_input;
+ unsigned char test_data[TEST_DATA_LENGTH];
+ unsigned int i;
+ ssize_t ret;
+
+ test_begin("istream failure at");
+ for (i = 0; i < sizeof(test_data); i++)
+ test_data[i] = i;
+ data_input = i_stream_create_from_data(test_data, sizeof(test_data));
+ for (i = 0; i < TEST_DATA_LENGTH; i++) {
+ i_stream_seek(data_input, 0);
+ input = i_stream_create_failure_at(data_input, i, TEST_ERRMSG);
+ while ((ret = i_stream_read(input)) > 0)
+ i_stream_skip(input, ret);
+ test_assert_idx(ret == -1 && input->v_offset == i &&
+ input->stream_errno == EIO &&
+ strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i);
+ i_stream_destroy(&input);
+ }
+ /* shouldn't fail */
+ i_stream_seek(data_input, 0);
+ input = i_stream_create_failure_at(data_input, TEST_DATA_LENGTH, TEST_ERRMSG);
+ while ((ret = i_stream_read(input)) > 0)
+ i_stream_skip(input, ret);
+ test_assert(ret == -1 && input->stream_errno == 0);
+ /* fail at EOF */
+ i_stream_seek(data_input, 0);
+ input = i_stream_create_failure_at_eof(data_input, TEST_ERRMSG);
+ while ((ret = i_stream_read(input)) > 0)
+ i_stream_skip(input, ret);
+ test_assert_idx(ret == -1 && input->v_offset == TEST_DATA_LENGTH &&
+ input->stream_errno == EIO &&
+ strcmp(i_stream_get_error(input), TEST_ERRMSG) == 0, i);
+ test_end();
+}
diff -r 80c1be850fdc -r 99827acc1888 src/lib/test-lib.c
--- a/src/lib/test-lib.c Tue Jun 16 14:12:59 2015 +0300
+++ b/src/lib/test-lib.c Tue Jun 16 16:21:56 2015 +0300
@@ -26,6 +26,7 @@
test_istream_base64_encoder,
test_istream_concat,
test_istream_crlf,
+ test_istream_failure_at,
test_istream_seekable,
test_istream_tee,
test_istream_unix,
diff -r 80c1be850fdc -r 99827acc1888 src/lib/test-lib.h
--- a/src/lib/test-lib.h Tue Jun 16 14:12:59 2015 +0300
+++ b/src/lib/test-lib.h Tue Jun 16 16:21:56 2015 +0300
@@ -27,6 +27,7 @@
void test_istream_base64_encoder(void);
void test_istream_concat(void);
void test_istream_crlf(void);
+void test_istream_failure_at(void);
void test_istream_seekable(void);
void test_istream_tee(void);
void test_istream_unix(void);
More information about the dovecot-cvs
mailing list