Mercurial > dovecot > core-2.2
changeset 10523:5d7ee047667f HEAD
istream-seekable: If we're immediately at EOF after copying buffer to file, don't corrupt the buffer.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 22 Dec 2009 14:19:40 -0500 |
parents | 19787c343ef1 |
children | 824b7072c6d9 |
files | src/lib/istream-seekable.c src/lib/test-istream-seekable.c |
diffstat | 2 files changed, 55 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/istream-seekable.c Tue Dec 22 14:19:15 2009 -0500 +++ b/src/lib/istream-seekable.c Tue Dec 22 14:19:40 2009 -0500 @@ -72,7 +72,10 @@ 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 @@ 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 @@ 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);
--- a/src/lib/test-istream-seekable.c Tue Dec 22 14:19:15 2009 -0500 +++ b/src/lib/test-istream-seekable.c Tue Dec 22 14:19:40 2009 -0500 @@ -121,6 +121,37 @@ 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 @@ test_istream_seekable_random(); } T_END; test_end(); + + test_istream_seekable_eof(); }