bz_stream zs;
uoff_t eof_offset;
- size_t high_pos;
struct stat last_parent_statbuf;
bool log_errors:1;
high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
if (zstream->eof_offset == high_offset) {
- i_assert(zstream->high_pos == 0 ||
- zstream->high_pos == stream->pos);
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 (!zstream->marked) {
if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
return -2; /* buffer full */
stream->parent_expected_offset = stream->parent_start_offset;
stream->skip = stream->pos = 0;
stream->istream.v_offset = 0;
- zstream->high_pos = 0;
+ stream->high_pos = 0;
(void)BZ2_bzDecompressEnd(&zstream->zs);
i_stream_bzlib_init(zstream);
i_stream_bzlib_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
{
struct bzlib_istream *zstream = (struct bzlib_istream *) stream;
- uoff_t start_offset = stream->istream.v_offset - stream->skip;
-
- if (v_offset < start_offset) {
- /* 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 */
- ssize_t ret;
-
- do {
- size_t avail = stream->pos - stream->skip;
-
- if (stream->istream.v_offset + avail >= v_offset) {
- i_stream_skip(&stream->istream,
- v_offset -
- stream->istream.v_offset);
- ret = -1;
- break;
- }
-
- i_stream_skip(&stream->istream, avail);
- } while ((ret = i_stream_read(&stream->istream)) > 0);
- i_assert(ret == -1);
-
- if (stream->istream.v_offset != v_offset) {
- /* some failure, we've broken it */
- if (stream->istream.stream_errno != 0) {
- i_error("bzlib_istream.seek(%s) failed: %s",
- i_stream_get_name(&stream->istream),
- strerror(stream->istream.stream_errno));
- i_stream_close(&stream->istream);
- } else {
- /* unexpected EOF. allow it since we may just
- want to check if there's anything.. */
- i_assert(stream->istream.eof);
- }
- }
- }
+ if (i_stream_nonseekable_try_seek(stream, v_offset))
+ return;
+
+ /* have to seek backwards - reset state and retry */
+ i_stream_bzlib_reset(zstream);
+ if (!i_stream_nonseekable_try_seek(stream, v_offset))
+ i_unreached();
if (mark)
zstream->marked = TRUE;
i_stream_lz4_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
{
struct lz4_istream *zstream = (struct lz4_istream *) stream;
- uoff_t start_offset = stream->istream.v_offset - stream->skip;
- if (v_offset < start_offset) {
- /* have to seek backwards */
- i_stream_lz4_reset(zstream);
- start_offset = 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;
- stream->pos = stream->skip;
- } else {
- /* read and cache forward */
- ssize_t ret;
-
- do {
- size_t avail = stream->pos - stream->skip;
-
- if (stream->istream.v_offset + avail >= v_offset) {
- i_stream_skip(&stream->istream,
- v_offset -
- stream->istream.v_offset);
- ret = -1;
- break;
- }
+ if (i_stream_nonseekable_try_seek(stream, v_offset))
+ return;
- i_stream_skip(&stream->istream, avail);
- } while ((ret = i_stream_read(&stream->istream)) > 0);
- i_assert(ret == -1);
-
- if (stream->istream.v_offset != v_offset) {
- /* some failure, we've broken it */
- if (stream->istream.stream_errno != 0) {
- i_error("lz4_istream.seek(%s) failed: %s",
- i_stream_get_name(&stream->istream),
- strerror(stream->istream.stream_errno));
- i_stream_close(&stream->istream);
- } else {
- /* unexpected EOF. allow it since we may just
- want to check if there's anything.. */
- i_assert(stream->istream.eof);
- }
- }
- }
+ /* have to seek backwards - reset state and retry */
+ i_stream_lz4_reset(zstream);
+ if (!i_stream_nonseekable_try_seek(stream, v_offset))
+ i_unreached();
if (mark)
zstream->marked = TRUE;
lzma_stream strm;
uoff_t eof_offset;
- size_t high_pos;
struct stat last_parent_statbuf;
bool log_errors:1;
high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
if (zstream->eof_offset == high_offset) {
- i_assert(zstream->high_pos == 0 ||
- zstream->high_pos == stream->pos);
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 (!zstream->marked) {
if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
return -2; /* buffer full */
stream->parent_expected_offset = stream->parent_start_offset;
stream->skip = stream->pos = 0;
stream->istream.v_offset = 0;
- zstream->high_pos = 0;
lzma_end(&zstream->strm);
i_stream_lzma_init(zstream);
i_stream_lzma_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
{
struct lzma_istream *zstream = (struct lzma_istream *) stream;
- uoff_t start_offset = stream->istream.v_offset - stream->skip;
-
- if (v_offset < start_offset) {
- /* have to seek backwards */
- i_stream_lzma_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 */
- ssize_t ret;
-
- do {
- size_t avail = stream->pos - stream->skip;
-
- if (stream->istream.v_offset + avail >= v_offset) {
- i_stream_skip(&stream->istream,
- v_offset -
- stream->istream.v_offset);
- ret = -1;
- break;
- }
-
- i_stream_skip(&stream->istream, avail);
- } while ((ret = i_stream_read(&stream->istream)) > 0);
- i_assert(ret == -1);
-
- if (stream->istream.v_offset != v_offset) {
- /* some failure, we've broken it */
- if (stream->istream.stream_errno != 0) {
- i_error("lzma_istream.seek(%s) failed: %s",
- i_stream_get_name(&stream->istream),
- strerror(stream->istream.stream_errno));
- i_stream_close(&stream->istream);
- } else {
- /* unexpected EOF. allow it since we may just
- want to check if there's anything.. */
- i_assert(stream->istream.eof);
- }
- }
- }
+ if (i_stream_nonseekable_try_seek(stream, v_offset))
+ return;
+
+ /* have to seek backwards - reset state and retry */
+ i_stream_lzma_reset(zstream);
+ if (!i_stream_nonseekable_try_seek(stream, v_offset))
+ i_unreached();
if (mark)
zstream->marked = TRUE;
z_stream zs;
uoff_t eof_offset;
- size_t prev_size, high_pos;
+ size_t prev_size;
uint32_t crc32;
struct stat last_parent_statbuf;
high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
if (zstream->eof_offset == high_offset) {
- i_assert(zstream->high_pos == 0 ||
- zstream->high_pos == stream->pos);
if (!zstream->trailer_read) {
do {
ret = i_stream_zlib_read_trailer(zstream);
zstream->header_read = TRUE;
}
- 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 (!zstream->marked) {
if (!i_stream_try_alloc(stream, CHUNK_SIZE, &out_size))
return -2; /* buffer full */
stream->parent_expected_offset = stream->parent_start_offset;
stream->skip = stream->pos = 0;
stream->istream.v_offset = 0;
- zstream->high_pos = 0;
+ stream->high_pos = 0;
zstream->prev_size = 0;
(void)inflateEnd(&zstream->zs);
i_stream_zlib_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
{
struct zlib_istream *zstream = (struct zlib_istream *) stream;
- uoff_t start_offset = stream->istream.v_offset - stream->skip;
-
- if (v_offset < start_offset) {
- /* 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 */
- ssize_t ret;
- do {
- size_t avail = stream->pos - stream->skip;
-
- if (stream->istream.v_offset + avail >= v_offset) {
- i_stream_skip(&stream->istream,
- v_offset -
- stream->istream.v_offset);
- ret = -1;
- break;
- }
+ if (i_stream_nonseekable_try_seek(stream, v_offset))
+ return;
- i_stream_skip(&stream->istream, avail);
- } while ((ret = i_stream_read(&stream->istream)) > 0);
- i_assert(ret == -1);
-
- if (stream->istream.v_offset != v_offset) {
- /* some failure, we've broken it */
- if (stream->istream.stream_errno != 0) {
- i_error("zlib_istream.seek(%s) failed: %s",
- i_stream_get_name(&stream->istream),
- strerror(stream->istream.stream_errno));
- i_stream_close(&stream->istream);
- } else {
- /* unexpected EOF. allow it since we may just
- want to check if there's anything.. */
- i_assert(stream->istream.eof);
- }
- }
- }
+ /* have to seek backwards - reset state and retry */
+ i_stream_zlib_reset(zstream);
+ if (!i_stream_nonseekable_try_seek(stream, v_offset))
+ i_unreached();
if (mark)
zstream->marked = TRUE;
sha1_result(&sha1, output_sha1);
/* read and uncompress the data */
- sha1_init(&sha1);
file_input = i_stream_create_fd(fd, IO_BLOCK_SIZE);
input = handler->create_istream(file_input, FALSE);
test_assert(i_stream_get_size(input, TRUE, &size) == 1);
test_assert(size == uncompressed_size);
- while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
- sha1_loop(&sha1, data, size);
- i_stream_skip(input, size);
+ sha1_init(&sha1);
+ for (bool seeked = FALSE;;) {
+ sha1_init(&sha1);
+ while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
+ sha1_loop(&sha1, data, size);
+ i_stream_skip(input, size);
+ }
+ test_assert(ret == -1);
+ test_assert(input->stream_errno == 0);
+ sha1_result(&sha1, input_sha1);
+ test_assert(memcmp(input_sha1, output_sha1, sizeof(input_sha1)) == 0);
+ if (seeked)
+ break;
+ seeked = TRUE;
+ i_stream_seek(input, 0);
}
- test_assert(ret == -1);
- test_assert(input->stream_errno == 0);
i_stream_destroy(&input);
i_stream_destroy(&file_input);
- sha1_result(&sha1, input_sha1);
- test_assert(memcmp(input_sha1, output_sha1, sizeof(input_sha1)) == 0);
i_unlink(path);
i_close_fd(&fd);