dovecot-2.0: zlib: Several fixes to zlib/bzlib istreams.

dovecot at dovecot.org dovecot at dovecot.org
Mon Mar 8 15:41:06 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/681e1c702899
changeset: 10855:681e1c702899
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Mar 08 15:41:02 2010 +0200
description:
zlib: Several fixes to zlib/bzlib istreams.

diffstat:

 src/plugins/zlib/istream-bzlib.c |  30 +++++++++++++++++++++++++++---
 src/plugins/zlib/istream-zlib.c  |  28 ++++++++++++++++++++++++++--
 2 files changed, 53 insertions(+), 5 deletions(-)

diffs (170 lines):

diff -r d49913d2d75a -r 681e1c702899 src/plugins/zlib/istream-bzlib.c
--- a/src/plugins/zlib/istream-bzlib.c	Mon Mar 08 15:29:41 2010 +0200
+++ b/src/plugins/zlib/istream-bzlib.c	Mon Mar 08 15:41:02 2010 +0200
@@ -15,7 +15,7 @@
 
 	bz_stream zs;
 	uoff_t eof_offset;
-	size_t prev_size;
+	size_t prev_size, high_pos;
 
 	unsigned int log_errors:1;
 	unsigned int marked:1;
@@ -50,10 +50,27 @@
 
 	high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
 	if (zstream->eof_offset == high_offset) {
+		i_assert(zstream->high_pos == 0);
 		stream->istream.eof = TRUE;
 		return -1;
 	}
 
+	if (stream->pos < zstream->high_pos) {
+		/* we're here because we seeked back within the read buffer. */
+		ret = zstream->high_pos - stream->pos;
+		stream->pos = zstream->high_pos;
+		zstream->high_pos = 0;
+
+		if (zstream->eof_offset != (uoff_t)-1) {
+			high_offset = stream->istream.v_offset +
+				(stream->pos - stream->skip);
+			i_assert(zstream->eof_offset == high_offset);
+			stream->istream.eof = TRUE;
+		}
+		return ret;
+	}
+	zstream->high_pos = 0;
+
 	if (stream->pos + CHUNK_SIZE > stream->buffer_size) {
 		/* try to keep at least CHUNK_SIZE available */
 		if (!zstream->marked && stream->skip > 0) {
@@ -110,7 +127,7 @@
 	zstream->zs.avail_out = size;
 	ret = BZ2_bzDecompress(&zstream->zs);
 
-	size -= zstream->zs.avail_in;
+	size -= zstream->zs.avail_out;
 	stream->pos += size;
 
 	switch (ret) {
@@ -173,13 +190,15 @@
 {
 	struct istream_private *stream = &zstream->istream;
 
-	i_stream_seek(stream->parent, 0);
+	i_stream_seek(stream->parent, stream->parent_start_offset);
 	zstream->eof_offset = (uoff_t)-1;
 	zstream->zs.next_in = NULL;
 	zstream->zs.avail_in = 0;
 
 	stream->skip = stream->pos = 0;
 	stream->istream.v_offset = 0;
+	zstream->high_pos = 0;
+	zstream->prev_size = 0;
 
 	(void)BZ2_bzDecompressEnd(&zstream->zs);
 	i_stream_bzlib_init(zstream);
@@ -195,12 +214,17 @@
 		/* have to seek backwards */
 		i_stream_bzlib_reset(zstream);
 		start_offset = 0;
+	} else if (zstream->high_pos != 0) {
+		stream->pos = zstream->high_pos;
+		zstream->high_pos = 0;
 	}
 
 	if (v_offset <= start_offset + stream->pos) {
 		/* seeking backwards within what's already cached */
 		stream->skip = v_offset - start_offset;
 		stream->istream.v_offset = v_offset;
+		zstream->high_pos = stream->pos;
+		stream->pos = stream->skip;
 	} else {
 		/* read and cache forward */
 		do {
diff -r d49913d2d75a -r 681e1c702899 src/plugins/zlib/istream-zlib.c
--- a/src/plugins/zlib/istream-zlib.c	Mon Mar 08 15:29:41 2010 +0200
+++ b/src/plugins/zlib/istream-zlib.c	Mon Mar 08 15:41:02 2010 +0200
@@ -26,7 +26,7 @@
 
 	z_stream zs;
 	uoff_t eof_offset;
-	size_t prev_size;
+	size_t prev_size, high_pos;
 	uint32_t crc32;
 
 	unsigned int gz:1;
@@ -170,6 +170,7 @@
 
 	high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
 	if (zstream->eof_offset == high_offset) {
+		i_assert(zstream->high_pos == 0);
 		if (!zstream->trailer_read) {
 			do {
 				ret = i_stream_zlib_read_trailer(zstream);
@@ -182,6 +183,7 @@
 	}
 
 	if (!zstream->header_read) {
+		i_assert(zstream->high_pos == 0);
 		do {
 			ret = i_stream_zlib_read_header(stream);
 		} while (ret == 0 && stream->istream.blocking);
@@ -191,6 +193,21 @@
 		zstream->prev_size = 0;
 	}
 
+	if (stream->pos < zstream->high_pos) {
+		/* we're here because we seeked back within the read buffer. */
+		ret = zstream->high_pos - stream->pos;
+		stream->pos = zstream->high_pos;
+		zstream->high_pos = 0;
+		if (zstream->trailer_read) {
+			high_offset = stream->istream.v_offset +
+				(stream->pos - stream->skip);
+			i_assert(zstream->eof_offset == high_offset);
+			stream->istream.eof = TRUE;
+		}
+		return ret;
+	}
+	zstream->high_pos = 0;
+
 	if (stream->pos + CHUNK_SIZE > stream->buffer_size) {
 		/* try to keep at least CHUNK_SIZE available */
 		if (!zstream->marked && stream->skip > 0) {
@@ -317,7 +334,7 @@
 {
 	struct istream_private *stream = &zstream->istream;
 
-	i_stream_seek(stream->parent, 0);
+	i_stream_seek(stream->parent, stream->parent_start_offset);
 	zstream->eof_offset = (uoff_t)-1;
 	zstream->crc32 = 0;
 
@@ -326,6 +343,8 @@
 
 	stream->skip = stream->pos = 0;
 	stream->istream.v_offset = 0;
+	zstream->high_pos = 0;
+	zstream->prev_size = 0;
 
 	(void)inflateEnd(&zstream->zs);
 	i_stream_zlib_init(zstream);
@@ -341,12 +360,17 @@
 		/* have to seek backwards */
 		i_stream_zlib_reset(zstream);
 		start_offset = 0;
+	} else if (zstream->high_pos != 0) {
+		stream->pos = zstream->high_pos;
+		zstream->high_pos = 0;
 	}
 
 	if (v_offset <= start_offset + stream->pos) {
 		/* seeking backwards within what's already cached */
 		stream->skip = v_offset - start_offset;
 		stream->istream.v_offset = v_offset;
+		zstream->high_pos = stream->pos;
+		stream->pos = stream->skip;
 	} else {
 		/* read and cache forward */
 		do {


More information about the dovecot-cvs mailing list