]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Added i_stream_create_min_sized*()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 1 Nov 2016 16:35:48 +0000 (18:35 +0200)
committerGitLab <gitlab@git.dovecot.net>
Wed, 22 Feb 2017 18:10:48 +0000 (20:10 +0200)
src/lib/istream-sized.c
src/lib/istream-sized.h
src/lib/test-istream-sized.c

index 5dd35e0526e13e4b73ded54025554fb004f55852..705a195f9d6d1cf84e1251843f29709c173c87b0 100644 (file)
@@ -11,6 +11,7 @@ struct sized_istream {
        void *error_context;
 
        uoff_t size;
+       bool min_size_only;
 };
 
 static void i_stream_sized_destroy(struct iostream_private *stream)
@@ -101,10 +102,17 @@ static ssize_t i_stream_sized_read(struct istream_private *stream)
                   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) {
@@ -186,6 +194,25 @@ struct istream *i_stream_create_sized_range(struct istream *input,
        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,
index 1fe3b9207e30c9d802fd47e7ed70708b70ec8437..b0c2dc14628b8306295bba53148a20cb0d8d6560 100644 (file)
@@ -22,6 +22,10 @@ istream_sized_callback_t(const struct istream_sized_error_data *data,
 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 *
index 5afdb72fb2374ea7ff68f647102e9af6cf2afc4d..681eddb6e2eb53bc588cea147928a82d22054188 100644 (file)
@@ -1,8 +1,7 @@
 /* Copyright (c) 2016-2017 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 @@ run_test(const char *sized_input, uoff_t sized_size, int stream_errno)
        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 @@ void test_istream_sized(void)
                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();
 }