Mercurial > dovecot > core-2.2
changeset 21687:bc16d43aed49
lib: Added i_stream_create_min_sized*()
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 01 Nov 2016 18:35:48 +0200 |
parents | e33f5589923f |
children | d1788e9bd7ea |
files | src/lib/istream-sized.c src/lib/istream-sized.h src/lib/test-istream-sized.c |
diffstat | 3 files changed, 82 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/istream-sized.c Fri Dec 23 12:52:45 2016 -0500 +++ b/src/lib/istream-sized.c Tue Nov 01 18:35:48 2016 +0200 @@ -11,6 +11,7 @@ void *error_context; uoff_t size; + bool min_size_only; }; static void i_stream_sized_destroy(struct iostream_private *stream) @@ -102,10 +103,17 @@ parent is at EOF. */ } else if (pos > left) { /* parent has more data available than expected */ - error = sstream->error_callback(&data, sstream->error_context); - io_stream_set_error(&stream->iostream, "%s", error); - stream->istream.stream_errno = EINVAL; - return -1; + if (!sstream->min_size_only) { + error = sstream->error_callback(&data, sstream->error_context); + io_stream_set_error(&stream->iostream, "%s", error); + stream->istream.stream_errno = EINVAL; + return -1; + } + pos = left; + if (pos <= stream->pos) { + stream->istream.eof = TRUE; + ret = -1; + } } else if (!stream->istream.eof) { /* still more to read */ } else if (stream->istream.stream_errno == ENOENT) { @@ -187,6 +195,25 @@ return ret; } +struct istream *i_stream_create_min_sized(struct istream *input, uoff_t min_size) +{ + struct istream *ret; + + ret= i_stream_create_sized(input, min_size); + ((struct sized_istream *)ret->real_stream)->min_size_only = TRUE; + return ret; +} + +struct istream *i_stream_create_min_sized_range(struct istream *input, + uoff_t offset, uoff_t min_size) +{ + struct istream *ret; + + ret = i_stream_create_sized_range(input, offset, min_size); + ((struct sized_istream *)ret->real_stream)->min_size_only = TRUE; + return ret; +} + #undef i_stream_create_sized_with_callback struct istream * i_stream_create_sized_with_callback(struct istream *input, uoff_t size,
--- a/src/lib/istream-sized.h Fri Dec 23 12:52:45 2016 -0500 +++ b/src/lib/istream-sized.h Tue Nov 01 18:35:48 2016 +0200 @@ -22,6 +22,10 @@ struct istream *i_stream_create_sized(struct istream *input, uoff_t size); struct istream *i_stream_create_sized_range(struct istream *input, uoff_t offset, uoff_t size); +/* Like i_stream_create_sized*(), but allow input stream's size to be larger. */ +struct istream *i_stream_create_min_sized(struct istream *input, uoff_t min_size); +struct istream *i_stream_create_min_sized_range(struct istream *input, + uoff_t offset, uoff_t min_size); /* Same as i_stream_create_sized(), but set the error message via the callback. */ struct istream *
--- a/src/lib/test-istream-sized.c Fri Dec 23 12:52:45 2016 -0500 +++ b/src/lib/test-istream-sized.c Tue Nov 01 18:35:48 2016 +0200 @@ -1,8 +1,7 @@ /* Copyright (c) 2016 Dovecot authors, see the included COPYING file */ #include "test-lib.h" -#include "str.h" -#include "istream-private.h" +#include "istream.h" #include "istream-sized.h" static const struct { @@ -54,6 +53,45 @@ i_stream_unref(&input_data); } +static void test_istream_sized_full(bool exact) +{ + const unsigned char test_data[10] = "1234567890"; + struct istream *test_input, *input; + unsigned int i, j; + int expected_errno; + + for (i = 1; i < sizeof(test_data)*2; i++) { + test_input = test_istream_create_data(test_data, sizeof(test_data)); + test_istream_set_allow_eof(test_input, FALSE); + test_istream_set_size(test_input, 0); + + if (exact) + input = i_stream_create_sized(test_input, i); + else + input = i_stream_create_min_sized(test_input, i); + for (j = 1; j <= I_MIN(i, sizeof(test_data)); j++) { + test_assert_idx(i_stream_read(input) == 0, j); + test_istream_set_size(test_input, j); + test_assert_idx(i_stream_read(input) == 1, j); + } + test_assert_idx(i_stream_read(input) == 0, i); + if (j <= sizeof(test_data)) + test_istream_set_size(test_input, j); + else + test_istream_set_allow_eof(test_input, TRUE); + test_assert_idx(i_stream_read(input) == -1 && input->eof, i); + if (i > sizeof(test_data)) + expected_errno = EPIPE; + else if (i < sizeof(test_data) && exact) + expected_errno = EINVAL; + else + expected_errno = 0; + test_assert_idx(input->stream_errno == expected_errno, i); + i_stream_unref(&input); + i_stream_unref(&test_input); + } +} + void test_istream_sized(void) { unsigned int i; @@ -63,4 +101,11 @@ run_test(tests[i].input, tests[i].size, tests[i].stream_errno); test_end(); } + test_begin("istream sized"); + test_istream_sized_full(TRUE); + test_end(); + + test_begin("istream sized min"); + test_istream_sized_full(FALSE); + test_end(); }