size_t size, out_size;
int ret;
- high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
- if (zstream->eof_offset == high_offset) {
- stream->istream.eof = TRUE;
- return -1;
- }
-
- if (!zstream->marked) {
- if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
- return -2; /* buffer full */
- } else {
- /* try to avoid compressing, so we can quickly seek backwards */
- if (!i_stream_try_alloc_avoid_compress(stream, CHUNK_SIZE, &out_size))
- return -2; /* buffer full */
- }
+ for (;;) {
+ high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
+ if (zstream->eof_offset == high_offset) {
+ stream->istream.eof = TRUE;
+ return -1;
+ }
- if (i_stream_read_more(stream->parent, &data, &size) < 0) {
- if (stream->parent->stream_errno != 0) {
- stream->istream.stream_errno =
- stream->parent->stream_errno;
+ if (!zstream->marked) {
+ if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
+ return -2; /* buffer full */
} else {
- i_assert(stream->parent->eof);
- bzlib_read_error(zstream, "unexpected EOF");
- if (!zstream->hdr_read)
- stream->istream.stream_errno = EINVAL;
- else
- stream->istream.stream_errno = EPIPE;
+ /* try to avoid compressing, so we can quickly seek backwards */
+ if (!i_stream_try_alloc_avoid_compress(stream, CHUNK_SIZE, &out_size))
+ return -2; /* buffer full */
}
- return -1;
- }
- if (size == 0) {
- /* no more input */
- i_assert(!stream->istream.blocking);
- return 0;
- }
- zstream->zs.next_in = (char *)data;
- zstream->zs.avail_in = size;
+ if (i_stream_read_more(stream->parent, &data, &size) < 0) {
+ if (stream->parent->stream_errno != 0) {
+ stream->istream.stream_errno =
+ stream->parent->stream_errno;
+ } else {
+ i_assert(stream->parent->eof);
+ bzlib_read_error(zstream, "unexpected EOF");
+ if (!zstream->hdr_read)
+ stream->istream.stream_errno = EINVAL;
+ else
+ stream->istream.stream_errno = EPIPE;
+ }
+ return -1;
+ }
+ if (size == 0) {
+ /* no more input */
+ i_assert(!stream->istream.blocking);
+ return 0;
+ }
- zstream->zs.next_out = (char *)stream->w_buffer + stream->pos;
- zstream->zs.avail_out = out_size;
- ret = BZ2_bzDecompress(&zstream->zs);
- zstream->hdr_read = TRUE;
+ zstream->zs.next_in = (char *)data;
+ zstream->zs.avail_in = size;
- out_size -= zstream->zs.avail_out;
- stream->pos += out_size;
+ zstream->zs.next_out = (char *)stream->w_buffer + stream->pos;
+ zstream->zs.avail_out = out_size;
+ ret = BZ2_bzDecompress(&zstream->zs);
+ zstream->hdr_read = TRUE;
- i_stream_skip(stream->parent, size - zstream->zs.avail_in);
+ out_size -= zstream->zs.avail_out;
+ stream->pos += out_size;
- switch (ret) {
- case BZ_OK:
- break;
- case BZ_PARAM_ERROR:
- i_unreached();
- case BZ_DATA_ERROR:
- bzlib_read_error(zstream, "corrupted data");
- stream->istream.stream_errno = EINVAL;
- return -1;
- case BZ_DATA_ERROR_MAGIC:
- bzlib_read_error(zstream,
- "wrong magic in header (not bz2 file?)");
- stream->istream.stream_errno = EINVAL;
- return -1;
- case BZ_MEM_ERROR:
- i_fatal_status(FATAL_OUTOFMEM, "bzlib.read(%s): Out of memory",
- i_stream_get_name(&stream->istream));
- case BZ_STREAM_END:
- zstream->eof_offset = stream->istream.v_offset +
- (stream->pos - stream->skip);
- stream->cached_stream_size = zstream->eof_offset;
- if (out_size == 0) {
- stream->istream.eof = TRUE;
+ i_stream_skip(stream->parent, size - zstream->zs.avail_in);
+
+ switch (ret) {
+ case BZ_OK:
+ break;
+ case BZ_PARAM_ERROR:
+ i_unreached();
+ case BZ_DATA_ERROR:
+ bzlib_read_error(zstream, "corrupted data");
+ stream->istream.stream_errno = EINVAL;
return -1;
+ case BZ_DATA_ERROR_MAGIC:
+ bzlib_read_error(zstream,
+ "wrong magic in header (not bz2 file?)");
+ stream->istream.stream_errno = EINVAL;
+ return -1;
+ case BZ_MEM_ERROR:
+ i_fatal_status(FATAL_OUTOFMEM, "bzlib.read(%s): Out of memory",
+ i_stream_get_name(&stream->istream));
+ case BZ_STREAM_END:
+ zstream->eof_offset = stream->istream.v_offset +
+ (stream->pos - stream->skip);
+ stream->cached_stream_size = zstream->eof_offset;
+ if (out_size == 0) {
+ stream->istream.eof = TRUE;
+ return -1;
+ }
+ break;
+ default:
+ i_fatal("BZ2_bzDecompress() failed with %d", ret);
}
- break;
- default:
- i_fatal("BZ2_bzDecompress() failed with %d", ret);
- }
- if (out_size == 0) {
- /* read more input */
- return i_stream_bzlib_read(stream);
+ if (out_size == 0) {
+ /* read more input */
+ return i_stream_bzlib_read(stream);
+ }
+ return out_size;
}
- return out_size;
}
static void i_stream_bzlib_init(struct bzlib_istream *zstream)
zstream->header_read = TRUE;
}
- if (zstream->chunk_left == 0) {
- while ((ret = i_stream_lz4_read_chunk_header(zstream)) == 0) {
- if (!stream->istream.blocking)
- return 0;
+ for (;;) {
+ if (zstream->chunk_left == 0) {
+ while ((ret = i_stream_lz4_read_chunk_header(zstream)) == 0) {
+ if (!stream->istream.blocking)
+ return 0;
+ }
+ if (ret < 0)
+ return ret;
}
- if (ret < 0)
- return ret;
- }
- /* read the whole compressed chunk into memory */
- while (zstream->chunk_left > 0 &&
- (ret = i_stream_read_more(zstream->istream.parent, &data, &size)) > 0) {
- if (size > zstream->chunk_left)
- size = zstream->chunk_left;
- buffer_append(zstream->chunk_buf, data, size);
- i_stream_skip(zstream->istream.parent, size);
- zstream->chunk_left -= size;
- }
- if (zstream->chunk_left > 0) {
- if (ret == -1 && zstream->istream.parent->stream_errno == 0) {
- lz4_read_error(zstream, "truncated lz4 chunk");
- stream->istream.stream_errno = EPIPE;
- return -1;
+ /* read the whole compressed chunk into memory */
+ while (zstream->chunk_left > 0 &&
+ (ret = i_stream_read_more(zstream->istream.parent, &data, &size)) > 0) {
+ if (size > zstream->chunk_left)
+ size = zstream->chunk_left;
+ buffer_append(zstream->chunk_buf, data, size);
+ i_stream_skip(zstream->istream.parent, size);
+ zstream->chunk_left -= size;
+ }
+ if (zstream->chunk_left > 0) {
+ if (ret == -1 && zstream->istream.parent->stream_errno == 0) {
+ lz4_read_error(zstream, "truncated lz4 chunk");
+ stream->istream.stream_errno = EPIPE;
+ return -1;
+ }
+ zstream->istream.istream.stream_errno =
+ zstream->istream.parent->stream_errno;
+ i_assert(ret != 0 || !stream->istream.blocking);
+ return ret;
}
- zstream->istream.istream.stream_errno =
- zstream->istream.parent->stream_errno;
- i_assert(ret != 0 || !stream->istream.blocking);
+ /* if we already have max_buffer_size amount of data, fail here */
+ if (stream->pos - stream->skip >= i_stream_get_max_buffer_size(&stream->istream))
+ return -2;
+ if (i_stream_get_data_size(zstream->istream.parent) > 0) {
+ /* Parent stream was only partially consumed. Set the stream's
+ IO as pending to avoid hangs. */
+ i_stream_set_input_pending(&zstream->istream.istream, TRUE);
+ }
+ /* allocate enough space for the old data and the new
+ decompressed chunk. we don't know the original compressed size,
+ so just allocate the max amount of memory. */
+ void *dest = i_stream_alloc(stream, zstream->max_uncompressed_chunk_size);
+ ret = LZ4_decompress_safe(zstream->chunk_buf->data, dest,
+ zstream->chunk_buf->used,
+ zstream->max_uncompressed_chunk_size);
+ i_assert(ret <= (int)zstream->max_uncompressed_chunk_size);
+ if (ret < 0) {
+ lz4_read_error(zstream, "corrupted lz4 chunk");
+ stream->istream.stream_errno = EINVAL;
+ return -1;
+ } else if (ret == 0)
+ return i_stream_lz4_read(stream);
+ i_assert(ret > 0);
+ stream->pos += ret;
+ i_assert(stream->pos <= stream->buffer_size);
+
+ /* we are going to get next chunk after this, so reset here
+ so we can reuse the chunk buf for reading next buffer prefix */
+ if (zstream->chunk_left == 0)
+ buffer_set_used_size(zstream->chunk_buf, 0);
+
return ret;
}
- /* if we already have max_buffer_size amount of data, fail here */
- if (stream->pos - stream->skip >= i_stream_get_max_buffer_size(&stream->istream))
- return -2;
- if (i_stream_get_data_size(zstream->istream.parent) > 0) {
- /* Parent stream was only partially consumed. Set the stream's
- IO as pending to avoid hangs. */
- i_stream_set_input_pending(&zstream->istream.istream, TRUE);
- }
- /* allocate enough space for the old data and the new
- decompressed chunk. we don't know the original compressed size,
- so just allocate the max amount of memory. */
- void *dest = i_stream_alloc(stream, zstream->max_uncompressed_chunk_size);
- ret = LZ4_decompress_safe(zstream->chunk_buf->data, dest,
- zstream->chunk_buf->used,
- zstream->max_uncompressed_chunk_size);
- i_assert(ret <= (int)zstream->max_uncompressed_chunk_size);
- if (ret < 0) {
- lz4_read_error(zstream, "corrupted lz4 chunk");
- stream->istream.stream_errno = EINVAL;
- return -1;
- } else if (ret == 0)
- return i_stream_lz4_read(stream);
- i_assert(ret > 0);
- stream->pos += ret;
- i_assert(stream->pos <= stream->buffer_size);
-
- /* we are going to get next chunk after this, so reset here
- so we can reuse the chunk buf for reading next buffer prefix */
- if (zstream->chunk_left == 0)
- buffer_set_used_size(zstream->chunk_buf, 0);
-
- return ret;
}
static void i_stream_lz4_reset(struct lz4_istream *zstream)
size_t size, out_size;
int ret;
- high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
- if (zstream->eof_offset == high_offset) {
- /* zlib library returned EOF. */
- if (!zstream->gz) {
- /* deflate - ignore if there's still more data */
- stream->istream.eof = TRUE;
- return -1;
+ for (;;) {
+ high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
+ if (zstream->eof_offset == high_offset) {
+ /* zlib library returned EOF. */
+ if (!zstream->gz) {
+ /* deflate - ignore if there's still more data */
+ stream->istream.eof = TRUE;
+ return -1;
+ }
+ /* gz format - read the trailer */
+ if (!zstream->trailer_read) {
+ do {
+ ret = i_stream_zlib_read_trailer(zstream);
+ } while (ret == 0 && stream->istream.blocking);
+ if (ret <= 0)
+ return ret;
+ }
+ /* See if there's another concatenated gz stream. */
+ if (i_stream_read_eof(stream->parent)) {
+ /* EOF or error */
+ stream->istream.stream_errno =
+ stream->parent->stream_errno;
+ stream->istream.eof = TRUE;
+ return -1;
+ }
+ /* Multiple gz streams concatenated together */
+ zstream->starting_concatenated_output = TRUE;
}
- /* gz format - read the trailer */
- if (!zstream->trailer_read) {
+ if (zstream->starting_concatenated_output) {
+ /* make sure there actually is something in parent stream.
+ we don't want to reset the stream unless we actually see
+ some concatenated output. */
+ ret = i_stream_read_more(stream->parent, &data, &size);
+ if (ret <= 0) {
+ if (ret == 0)
+ return 0;
+ if (stream->parent->stream_errno != 0) {
+ stream->istream.stream_errno =
+ stream->parent->stream_errno;
+ }
+ stream->istream.eof = TRUE;
+ return -1;
+ }
+
+ /* gzip file with concatenated content */
+ stream->cached_stream_size = UOFF_T_MAX;
+ zstream->eof_offset = UOFF_T_MAX;
+ zstream->header_read = FALSE;
+ zstream->trailer_read = FALSE;
+ zstream->crc32 = 0;
+ zstream->starting_concatenated_output = FALSE;
+
+ (void)inflateEnd(&zstream->zs);
+ i_stream_zlib_init(zstream);
+ }
+
+ if (!zstream->header_read) {
do {
- ret = i_stream_zlib_read_trailer(zstream);
+ ret = i_stream_zlib_read_header(stream);
} while (ret == 0 && stream->istream.blocking);
if (ret <= 0)
return ret;
+ zstream->header_read = TRUE;
}
- /* See if there's another concatenated gz stream. */
- if (i_stream_read_eof(stream->parent)) {
- /* EOF or error */
- stream->istream.stream_errno =
- stream->parent->stream_errno;
- stream->istream.eof = TRUE;
- return -1;
+
+ if (!zstream->marked) {
+ if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
+ return -2; /* buffer full */
+ } else {
+ /* try to avoid compressing, so we can quickly seek backwards */
+ if (!i_stream_try_alloc_avoid_compress(stream, CHUNK_SIZE, &out_size))
+ return -2; /* buffer full */
}
- /* Multiple gz streams concatenated together */
- zstream->starting_concatenated_output = TRUE;
- }
- if (zstream->starting_concatenated_output) {
- /* make sure there actually is something in parent stream.
- we don't want to reset the stream unless we actually see
- some concatenated output. */
- ret = i_stream_read_more(stream->parent, &data, &size);
- if (ret <= 0) {
- if (ret == 0)
- return 0;
+
+ if (i_stream_read_more(stream->parent, &data, &size) < 0) {
if (stream->parent->stream_errno != 0) {
stream->istream.stream_errno =
stream->parent->stream_errno;
+ } else {
+ i_assert(stream->parent->eof);
+ zlib_read_error(zstream, "unexpected EOF");
+ stream->istream.stream_errno = EPIPE;
}
- stream->istream.eof = TRUE;
return -1;
}
-
- /* gzip file with concatenated content */
- stream->cached_stream_size = UOFF_T_MAX;
- zstream->eof_offset = UOFF_T_MAX;
- zstream->header_read = FALSE;
- zstream->trailer_read = FALSE;
- zstream->crc32 = 0;
- zstream->starting_concatenated_output = FALSE;
-
- (void)inflateEnd(&zstream->zs);
- i_stream_zlib_init(zstream);
- }
-
- if (!zstream->header_read) {
- do {
- ret = i_stream_zlib_read_header(stream);
- } while (ret == 0 && stream->istream.blocking);
- if (ret <= 0)
- return ret;
- zstream->header_read = TRUE;
- }
-
- if (!zstream->marked) {
- if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
- return -2; /* buffer full */
- } else {
- /* try to avoid compressing, so we can quickly seek backwards */
- if (!i_stream_try_alloc_avoid_compress(stream, CHUNK_SIZE, &out_size))
- return -2; /* buffer full */
- }
-
- if (i_stream_read_more(stream->parent, &data, &size) < 0) {
- if (stream->parent->stream_errno != 0) {
- stream->istream.stream_errno =
- stream->parent->stream_errno;
- } else {
- i_assert(stream->parent->eof);
- zlib_read_error(zstream, "unexpected EOF");
- stream->istream.stream_errno = EPIPE;
+ if (size == 0) {
+ /* no more input */
+ i_assert(!stream->istream.blocking);
+ return 0;
}
- return -1;
- }
- if (size == 0) {
- /* no more input */
- i_assert(!stream->istream.blocking);
- return 0;
- }
- zstream->zs.next_in = (void *)data;
- zstream->zs.avail_in = size;
-
- zstream->zs.next_out = stream->w_buffer + stream->pos;
- zstream->zs.avail_out = out_size;
- ret = inflate(&zstream->zs, Z_SYNC_FLUSH);
-
- out_size -= zstream->zs.avail_out;
- /* CRC32 is only needed for GZ trailer. */
- if (zstream->gz)
- zstream->crc32 = crc32_data_more(zstream->crc32,
- stream->w_buffer + stream->pos,
- out_size);
- stream->pos += out_size;
-
- size_t bytes_consumed = size - zstream->zs.avail_in;
- i_stream_skip(stream->parent, bytes_consumed);
- if (i_stream_get_data_size(stream->parent) > 0 &&
- (bytes_consumed > 0 || out_size > 0)) {
- /* Parent stream was only partially consumed. Set the stream's
- IO as pending to avoid hangs. */
- i_stream_set_input_pending(&stream->istream, TRUE);
- }
+ zstream->zs.next_in = (void *)data;
+ zstream->zs.avail_in = size;
+
+ zstream->zs.next_out = stream->w_buffer + stream->pos;
+ zstream->zs.avail_out = out_size;
+ ret = inflate(&zstream->zs, Z_SYNC_FLUSH);
+
+ out_size -= zstream->zs.avail_out;
+ /* CRC32 is only needed for GZ trailer. */
+ if (zstream->gz)
+ zstream->crc32 = crc32_data_more(zstream->crc32,
+ stream->w_buffer + stream->pos,
+ out_size);
+ stream->pos += out_size;
+
+ size_t bytes_consumed = size - zstream->zs.avail_in;
+ i_stream_skip(stream->parent, bytes_consumed);
+ if (i_stream_get_data_size(stream->parent) > 0 &&
+ (bytes_consumed > 0 || out_size > 0)) {
+ /* Parent stream was only partially consumed. Set the stream's
+ IO as pending to avoid hangs. */
+ i_stream_set_input_pending(&stream->istream, TRUE);
+ }
- switch (ret) {
- case Z_OK:
- break;
- case Z_NEED_DICT:
- zlib_read_error(zstream, "can't read file without dict");
- stream->istream.stream_errno = EIO;
- return -1;
- case Z_DATA_ERROR:
- zlib_read_error(zstream, "corrupted data");
- stream->istream.stream_errno = EINVAL;
- return -1;
- case Z_MEM_ERROR:
- i_fatal_status(FATAL_OUTOFMEM, "zlib.read(%s): Out of memory",
- i_stream_get_name(&stream->istream));
- case Z_STREAM_END:
- zstream->eof_offset = stream->istream.v_offset +
- (stream->pos - stream->skip);
- stream->cached_stream_size = zstream->eof_offset;
- zstream->zs.avail_in = 0;
-
- if (!zstream->trailer_read) {
- /* try to read and verify the trailer, we might not
- be called again. */
- if (i_stream_zlib_read_trailer(zstream) < 0)
- return -1;
+ switch (ret) {
+ case Z_OK:
+ break;
+ case Z_NEED_DICT:
+ zlib_read_error(zstream, "can't read file without dict");
+ stream->istream.stream_errno = EIO;
+ return -1;
+ case Z_DATA_ERROR:
+ zlib_read_error(zstream, "corrupted data");
+ stream->istream.stream_errno = EINVAL;
+ return -1;
+ case Z_MEM_ERROR:
+ i_fatal_status(FATAL_OUTOFMEM, "zlib.read(%s): Out of memory",
+ i_stream_get_name(&stream->istream));
+ case Z_STREAM_END:
+ zstream->eof_offset = stream->istream.v_offset +
+ (stream->pos - stream->skip);
+ stream->cached_stream_size = zstream->eof_offset;
+ zstream->zs.avail_in = 0;
+
+ if (!zstream->trailer_read) {
+ /* try to read and verify the trailer, we might not
+ be called again. */
+ if (i_stream_zlib_read_trailer(zstream) < 0)
+ return -1;
+ }
+ break;
+ default:
+ i_fatal("inflate() failed with %d", ret);
}
- break;
- default:
- i_fatal("inflate() failed with %d", ret);
- }
- if (out_size == 0) {
- /* read more input */
- return i_stream_zlib_read(stream);
+ if (out_size == 0) {
+ /* read more input */
+ return i_stream_zlib_read(stream);
+ }
+ return out_size;
}
- return out_size;
}
static void i_stream_zlib_init(struct zlib_istream *zstream)