dovecot-2.2: lib: Added o_stream_create_failure_at() to inject E...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Jun 16 13:43:20 UTC 2015
details: http://hg.dovecot.org/dovecot-2.2/rev/1c7288c054b1
changeset: 18866:1c7288c054b1
user: Timo Sirainen <tss at iki.fi>
date: Tue Jun 16 16:22:18 2015 +0300
description:
lib: Added o_stream_create_failure_at() to inject EIO at given offset in ostream
diffstat:
src/lib/Makefile.am | 3 +
src/lib/ostream-failure-at.c | 108 ++++++++++++++++++++++++++++++++++++++
src/lib/ostream-failure-at.h | 10 +++
src/lib/test-lib.c | 1 +
src/lib/test-lib.h | 1 +
src/lib/test-ostream-failure-at.c | 52 ++++++++++++++++++
6 files changed, 175 insertions(+), 0 deletions(-)
diffs (231 lines):
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/Makefile.am
--- a/src/lib/Makefile.am Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/Makefile.am Tue Jun 16 16:22:18 2015 +0300
@@ -109,6 +109,7 @@
numpack.c \
ostream.c \
ostream-buffer.c \
+ ostream-failure-at.c \
ostream-file.c \
ostream-hash.c \
ostream-rawlog.c \
@@ -237,6 +238,7 @@
nfs-workarounds.h \
numpack.h \
ostream.h \
+ ostream-failure-at.h \
ostream-hash.h \
ostream-private.h \
ostream-rawlog.h \
@@ -318,6 +320,7 @@
test-mempool-alloconly.c \
test-net.c \
test-numpack.c \
+ test-ostream-failure-at.c \
test-ostream-file.c \
test-primes.c \
test-printf-format-fix.c \
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/ostream-failure-at.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-failure-at.c Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,108 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "buffer.h"
+#include "ostream-private.h"
+#include "ostream-failure-at.h"
+
+struct failure_at_ostream {
+ struct ostream_private ostream;
+ char *error_string;
+ uoff_t failure_offset;
+ bool failed;
+};
+
+static void o_stream_failure_at_destroy(struct iostream_private *stream)
+{
+ struct failure_at_ostream *fstream =
+ (struct failure_at_ostream *)stream;
+
+ i_free(fstream->error_string);
+}
+
+static ssize_t
+o_stream_failure_at_sendv(struct ostream_private *stream,
+ const struct const_iovec *iov, unsigned int iov_count)
+{
+ struct failure_at_ostream *fstream =
+ (struct failure_at_ostream *)stream;
+ unsigned int i;
+ struct const_iovec *iov_dup;
+ unsigned int iov_dup_count;
+ uoff_t bytes_until_failure;
+ ssize_t ret;
+
+ if (fstream->failure_offset <= stream->ostream.offset) {
+ io_stream_set_error(&stream->iostream, "%s",
+ fstream->error_string);
+ stream->ostream.stream_errno = errno = EIO;
+ fstream->failed = TRUE;
+ return -1;
+ }
+ bytes_until_failure = fstream->failure_offset - stream->ostream.offset;
+
+ iov_dup = i_new(struct const_iovec, iov_count);
+ iov_dup_count = iov_count;
+ for (i = 0; i < iov_count; i++) {
+ iov_dup[i] = iov[i];
+ if (iov_dup[i].iov_len >= bytes_until_failure) {
+ iov_dup[i].iov_len = bytes_until_failure;
+ iov_dup_count = i+1;
+ break;
+ }
+ }
+ ret = o_stream_sendv(stream->parent, iov_dup, iov_dup_count);
+ i_free(iov_dup);
+
+ if (ret < 0) {
+ o_stream_copy_error_from_parent(stream);
+ return -1;
+ }
+ stream->ostream.offset += ret;
+ return ret;
+}
+
+static int
+o_stream_failure_at_flush(struct ostream_private *stream)
+{
+ struct failure_at_ostream *fstream =
+ (struct failure_at_ostream *)stream;
+
+ if (fstream->failed) {
+ io_stream_set_error(&stream->iostream, "%s",
+ fstream->error_string);
+ stream->ostream.stream_errno = errno = EIO;
+ return -1;
+ }
+ return o_stream_flush(stream->parent);
+}
+
+struct ostream *
+o_stream_create_failure_at(struct ostream *output, uoff_t failure_offset,
+ const char *error_string)
+{
+ struct failure_at_ostream *fstream;
+
+ fstream = i_new(struct failure_at_ostream, 1);
+ fstream->ostream.sendv = o_stream_failure_at_sendv;
+ fstream->ostream.flush = o_stream_failure_at_flush;
+ fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
+ fstream->failure_offset = failure_offset;
+ fstream->error_string = i_strdup(error_string);
+ return o_stream_create(&fstream->ostream, output,
+ o_stream_get_fd(output));
+}
+
+struct ostream *
+o_stream_create_failure_at_flush(struct ostream *output, const char *error_string)
+{
+ struct failure_at_ostream *fstream;
+
+ fstream = i_new(struct failure_at_ostream, 1);
+ fstream->ostream.flush = o_stream_failure_at_flush;
+ fstream->ostream.iostream.destroy = o_stream_failure_at_destroy;
+ fstream->error_string = i_strdup(error_string);
+ fstream->failed = TRUE;
+ return o_stream_create(&fstream->ostream, output,
+ o_stream_get_fd(output));
+}
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/ostream-failure-at.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/ostream-failure-at.h Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,10 @@
+#ifndef OSTREAM_FAILURE_AT_H
+#define OSTREAM_FAILURE_AT_H
+
+struct ostream *
+o_stream_create_failure_at(struct ostream *output, uoff_t failure_offset,
+ const char *error_string);
+struct ostream *
+o_stream_create_failure_at_flush(struct ostream *output, const char *error_string);
+
+#endif
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-lib.c
--- a/src/lib/test-lib.c Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/test-lib.c Tue Jun 16 16:22:18 2015 +0300
@@ -36,6 +36,7 @@
test_mempool_alloconly,
test_net,
test_numpack,
+ test_ostream_failure_at,
test_ostream_file,
test_primes,
test_printf_format_fix,
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-lib.h
--- a/src/lib/test-lib.h Tue Jun 16 16:21:56 2015 +0300
+++ b/src/lib/test-lib.h Tue Jun 16 16:22:18 2015 +0300
@@ -38,6 +38,7 @@
enum fatal_test_state fatal_mempool(int);
void test_net(void);
void test_numpack(void);
+void test_ostream_failure_at(void);
void test_ostream_file(void);
void test_primes(void);
void test_printf_format_fix(void);
diff -r 99827acc1888 -r 1c7288c054b1 src/lib/test-ostream-failure-at.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/test-ostream-failure-at.c Tue Jun 16 16:22:18 2015 +0300
@@ -0,0 +1,52 @@
+/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
+
+#include "test-lib.h"
+#include "buffer.h"
+#include "ostream.h"
+#include "ostream-failure-at.h"
+
+#define TEST_DATA_LENGTH 128
+#define TEST_ERRMSG "test-ostream-failure-at error triggered"
+
+void test_ostream_failure_at(void)
+{
+ unsigned char test_data[TEST_DATA_LENGTH];
+ struct ostream *output, *buf_output;
+ buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 256);
+ unsigned int i;
+
+ test_begin("ostream failure at");
+ for (i = 0; i < sizeof(test_data); i++)
+ test_data[i] = i;
+ for (i = 0; i < TEST_DATA_LENGTH; i++) {
+ buf_output = o_stream_create_buffer(buf);
+ output = o_stream_create_failure_at(buf_output, i, TEST_ERRMSG);
+ if (i > 0)
+ test_assert(o_stream_send(output, test_data, sizeof(test_data)) == i);
+ test_assert_idx(o_stream_send(output, test_data, sizeof(test_data)) == -1 &&
+ output->offset == i &&
+ output->stream_errno == EIO &&
+ strcmp(o_stream_get_error(output), TEST_ERRMSG) == 0, i);
+ o_stream_destroy(&output);
+ o_stream_destroy(&buf_output);
+ }
+ /* shouldn't fail */
+ buf_output = o_stream_create_buffer(buf);
+ output = o_stream_create_failure_at(buf_output, TEST_DATA_LENGTH, TEST_ERRMSG);
+ test_assert(o_stream_send(output, test_data, sizeof(test_data)) == TEST_DATA_LENGTH);
+ test_assert(o_stream_flush(output) > 0 &&
+ output->offset == TEST_DATA_LENGTH &&
+ output->stream_errno == 0);
+ o_stream_destroy(&output);
+ o_stream_destroy(&buf_output);
+
+ /* fail at flush */
+ buf_output = o_stream_create_buffer(buf);
+ output = o_stream_create_failure_at_flush(buf_output, TEST_ERRMSG);
+ test_assert(o_stream_send(output, test_data, sizeof(test_data)) == TEST_DATA_LENGTH);
+ test_assert(o_stream_flush(output) < 0 && output->stream_errno == EIO &&
+ strcmp(o_stream_get_error(output), TEST_ERRMSG) == 0);
+ o_stream_destroy(&output);
+ o_stream_destroy(&buf_output);
+ test_end();
+}
More information about the dovecot-cvs
mailing list