]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
istream-seekable: If we're immediately at EOF after copying buffer to file, don't...
authorTimo Sirainen <tss@iki.fi>
Tue, 22 Dec 2009 19:19:40 +0000 (14:19 -0500)
committerTimo Sirainen <tss@iki.fi>
Tue, 22 Dec 2009 19:19:40 +0000 (14:19 -0500)
--HG--
branch : HEAD

src/lib/istream-seekable.c
src/lib/test-istream-seekable.c

index 4bb1cfbde1fd426b89bb1d64c06ca2415c56f50d..3d82ea35a1569320bbead7d3556b2626cceadcc1 100644 (file)
@@ -72,7 +72,10 @@ i_stream_seekable_set_max_buffer_size(struct iostream_private *stream,
 
 static int copy_to_temp_file(struct seekable_istream *sstream)
 {
+       struct istream_private *stream = &sstream->istream;
        const char *path;
+       const unsigned char *buffer;
+       size_t size;
        int fd;
 
        fd = sstream->fd_callback(&path, sstream->context);
@@ -89,11 +92,27 @@ static int copy_to_temp_file(struct seekable_istream *sstream)
        sstream->temp_path = i_strdup(path);
        sstream->write_peak = sstream->buffer->used;
 
-       buffer_free(&sstream->buffer);
-
        sstream->fd = fd;
        sstream->fd_input =
                i_stream_create_fd(fd, sstream->istream.max_buffer_size, TRUE);
+
+       /* read back the data we just had in our buffer */
+       i_stream_seek(sstream->fd_input, stream->istream.v_offset);
+       for (;;) {
+               buffer = i_stream_get_data(sstream->fd_input, &size);
+               if (size >= stream->pos)
+                       break;
+
+               if (i_stream_read(sstream->fd_input) <= 0) {
+                       i_error("istream-seekable: Couldn't read back "
+                               "in-memory input");
+                       i_stream_destroy(&sstream->fd_input);
+                       return -1;
+               }
+       }
+       stream->buffer = buffer;
+       stream->pos = size;
+       buffer_free(&sstream->buffer);
        return 0;
 }
 
@@ -341,6 +360,7 @@ i_stream_create_seekable(struct istream *input[],
        sstream->context = context;
        sstream->buffer = buffer_create_dynamic(default_pool, BUF_INITIAL_SIZE);
         sstream->istream.max_buffer_size = max_buffer_size;
+       sstream->fd = -1;
 
        sstream->input = i_new(struct istream *, count + 1);
        memcpy(sstream->input, input, sizeof(*input) * count);
index fa3f1061357f440104c32b69f7f14399eed81be2..f80e39efad1877a365b468662f7ba7a767c80a6f 100644 (file)
@@ -121,6 +121,37 @@ static void test_istream_seekable_random(void)
        i_stream_unref(&input);
 }
 
+static void test_istream_seekable_eof(void)
+{
+       static const char *in_str = "foo";
+       unsigned int in_str_len = strlen(in_str);
+       struct istream *streams[2], *input;
+       const unsigned char *data;
+       size_t size;
+
+       test_begin("istream seekable eof");
+
+       streams[0] = i_stream_create_from_data(in_str, in_str_len);
+       streams[0]->seekable = FALSE;
+       streams[1] = NULL;
+
+       input = i_stream_create_seekable(streams, in_str_len, fd_callback, NULL);
+       i_stream_unref(&streams[0]);
+
+       test_assert(i_stream_read(input) == (ssize_t)in_str_len);
+       data = i_stream_get_data(input, &size);
+       test_assert(size == in_str_len);
+       test_assert(memcmp(data, in_str, in_str_len) == 0);
+
+       test_assert(i_stream_read(input) == -1);
+       data = i_stream_get_data(input, &size);
+       test_assert(size == in_str_len);
+       test_assert(memcmp(data, in_str, in_str_len) == 0);
+
+       i_stream_unref(&input);
+       test_end();
+}
+
 void test_istream_seekable(void)
 {
        unsigned int i;
@@ -135,4 +166,6 @@ void test_istream_seekable(void)
                test_istream_seekable_random();
        } T_END;
        test_end();
+
+       test_istream_seekable_eof();
 }