]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: iostream-temp: Fixed o_stream_send_istream()
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 18 May 2016 14:41:32 +0000 (17:41 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 18 May 2016 14:47:26 +0000 (17:47 +0300)
src/lib/iostream-temp.c
src/lib/test-iostream-temp.c

index 9660361133a7694728ab5868551f88b87a01273f..f3776c6af854cd34d0a2af8caafdf669d28379ef 100644 (file)
@@ -131,8 +131,11 @@ static int o_stream_temp_dup_cancel(struct temp_ostream *tstream)
        int ret = -1;
 
        i_stream_seek(tstream->dupstream, tstream->dupstream_start_offset);
+       tstream->ostream.ostream.offset = 0;
 
        input = i_stream_create_limit(tstream->dupstream, size);
+       i_stream_unref(&tstream->dupstream);
+
        if (io_stream_copy(&tstream->ostream.ostream, input) > 0) {
                /* everything copied */
                ret = 0;
@@ -141,7 +144,6 @@ static int o_stream_temp_dup_cancel(struct temp_ostream *tstream)
                tstream->ostream.ostream.stream_errno = input->stream_errno;
        }
        i_stream_destroy(&input);
-       i_stream_unref(&tstream->dupstream);
        return ret;
 }
 
@@ -170,7 +172,12 @@ static int o_stream_temp_dup_istream(struct temp_ostream *outstream,
                        return o_stream_temp_dup_cancel(outstream);
        }
        i_stream_seek(instream, in_size);
+       /* we should be at EOF now. o_stream_send_istream() asserts if
+          eof isn't set. */
+       instream->eof = TRUE;
        outstream->dupstream_offset = instream->v_offset;
+       outstream->ostream.ostream.offset =
+               outstream->dupstream_offset - outstream->dupstream_start_offset;
        return 1;
 }
 
index 7cfae398c3217f5506880da8cd0be37d2bce9373..d2978a6e2438d6ac7166c4aa9e0ce6a33456ce60 100644 (file)
@@ -1,9 +1,13 @@
 /* Copyright (c) 2016 Dovecot authors, see the included COPYING file */
 
 #include "test-lib.h"
+#include "istream.h"
 #include "ostream.h"
 #include "iostream-temp.h"
 
+#include <unistd.h>
+#include <fcntl.h>
+
 static void test_iostream_temp_create_sized_memory(void)
 {
        struct ostream *output;
@@ -39,8 +43,60 @@ static void test_iostream_temp_create_sized_disk(void)
        test_end();
 }
 
+static void test_iostream_temp_istream(void)
+{
+       struct istream *input, *input2, *temp_input;
+       struct ostream *output;
+       int fd;
+
+       test_begin("iostream_temp istream");
+
+       fd = open(".temp.istream", O_RDWR | O_CREAT | O_TRUNC, 0600);
+       if (fd == -1)
+               i_fatal("create(.temp.istream) failed: %m");
+       test_assert(write(fd, "foobar", 6) == 6);
+       test_assert(lseek(fd, 0, SEEK_SET) == 0);
+
+       input = i_stream_create_fd(fd, 1024, TRUE);
+       /* a working fd-dup */
+       output = iostream_temp_create_sized(".nonexistent/",
+               IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 1);
+       test_assert(o_stream_send_istream(output, input) > 0);
+       temp_input = iostream_temp_finish(&output, 128);
+       test_assert(i_stream_read(temp_input) == 6);
+       i_stream_destroy(&temp_input);
+
+       /* non-working fd-dup: write data before sending istream */
+       i_stream_seek(input, 0);
+       output = iostream_temp_create_sized(".intentional-nonexistent-error/",
+               IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
+       test_assert(o_stream_send(output, "1234", 4) == 4);
+       test_expect_errors(1);
+       test_assert(o_stream_send_istream(output, input) > 0);
+       test_expect_no_more_errors();
+       o_stream_destroy(&output);
+
+       /* non-working fd-dup: send two istreams */
+       i_stream_seek(input, 0);
+       input2 = i_stream_create_limit(input, (uoff_t)-1);
+       output = iostream_temp_create_sized(".intentional-nonexistent-error/",
+               IOSTREAM_TEMP_FLAG_TRY_FD_DUP, "test", 4);
+       test_assert(o_stream_send_istream(output, input) > 0);
+       test_expect_errors(1);
+       test_assert(o_stream_send_istream(output, input2) > 0);
+       test_expect_no_more_errors();
+       o_stream_destroy(&output);
+       i_stream_unref(&input2);
+
+       i_stream_destroy(&input);
+
+       i_unlink(".temp.istream");
+       test_end();
+}
+
 void test_iostream_temp(void)
 {
        test_iostream_temp_create_sized_memory();
        test_iostream_temp_create_sized_disk();
+       test_iostream_temp_istream();
 }