From: Timo Sirainen Date: Tue, 22 Dec 2009 19:19:40 +0000 (-0500) Subject: istream-seekable: If we're immediately at EOF after copying buffer to file, don't... X-Git-Tag: 2.0.beta2~96 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7bcb308d0e13dfa48b483b0addccd889a77bb598;p=thirdparty%2Fdovecot%2Fcore.git istream-seekable: If we're immediately at EOF after copying buffer to file, don't corrupt the buffer. --HG-- branch : HEAD --- diff --git a/src/lib/istream-seekable.c b/src/lib/istream-seekable.c index 4bb1cfbde1..3d82ea35a1 100644 --- a/src/lib/istream-seekable.c +++ b/src/lib/istream-seekable.c @@ -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); diff --git a/src/lib/test-istream-seekable.c b/src/lib/test-istream-seekable.c index fa3f106135..f80e39efad 100644 --- a/src/lib/test-istream-seekable.c +++ b/src/lib/test-istream-seekable.c @@ -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(); }