aboutsummaryrefslogtreecommitdiff
path: root/lib/tar
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tar')
-rw-r--r--lib/tar/src/iterator.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/lib/tar/src/iterator.c b/lib/tar/src/iterator.c
index 85937c8..2914e3a 100644
--- a/lib/tar/src/iterator.c
+++ b/lib/tar/src/iterator.c
@@ -73,25 +73,6 @@ static bool is_sparse_region(const tar_iterator_t *tar, sqfs_u64 *count)
return true;
}
-static int data_available(tar_iterator_t *tar, sqfs_u64 want, sqfs_u64 *out)
-{
- if (want > tar->stream->buffer_used) {
- if (istream_precache(tar->stream)) {
- tar->state = SQFS_ERROR_IO;
- return -1;
- }
-
- if (tar->stream->buffer_used == 0 && tar->stream->eof) {
- tar->state = SQFS_ERROR_CORRUPTED;
- return -1;
- }
- }
-
- *out = tar->stream->buffer_used <= want ?
- tar->stream->buffer_used : want;
- return 0;
-}
-
/*****************************************************************************/
static const char *strm_get_filename(istream_t *strm)
@@ -108,8 +89,10 @@ static int strm_precache(istream_t *strm)
goto out_eof;
if (!tar->parent->last_sparse) {
- tar->parent->stream->buffer += tar->parent->last_chunk;
- tar->parent->stream->buffer_used -= tar->parent->last_chunk;
+ int ret = istream_advance_buffer(tar->parent->stream,
+ tar->parent->last_chunk);
+ if (ret != 0)
+ return ret;
tar->parent->record_size -= tar->parent->last_chunk;
}
@@ -118,6 +101,8 @@ static int strm_precache(istream_t *strm)
goto out_eof;
tar->parent->last_sparse = is_sparse_region(tar->parent, &diff);
+ if (diff == 0)
+ goto out_eof;
if (tar->parent->last_sparse) {
if (diff > sizeof(tar->buffer))
@@ -126,15 +111,40 @@ static int strm_precache(istream_t *strm)
strm->buffer = tar->buffer;
memset(tar->buffer, 0, diff);
} else {
- if (data_available(tar->parent, diff, &diff))
- goto out_eof;
+ const sqfs_u8 *ptr;
+ size_t avail;
+ int ret;
+
+ for (int i = 0; i < 2; ++i) {
+ ret = istream_get_buffered_data(tar->parent->stream,
+ &ptr, &avail);
+ if (ret > 0)
+ goto fail_borked;
+ if (ret < 0)
+ goto fail_io;
+
+ if (diff <= avail)
+ break;
+ ret = istream_precache(tar->parent->stream);
+ if (ret)
+ goto fail_io;
+ }
- strm->buffer = tar->parent->stream->buffer;
+ if (diff > avail)
+ diff = avail;
+
+ strm->buffer = ptr;
}
strm->buffer_used = diff;
tar->parent->last_chunk = diff;
return 0;
+fail_borked:
+ tar->parent->state = SQFS_ERROR_CORRUPTED;
+ return -1;
+fail_io:
+ tar->parent->state = SQFS_ERROR_IO;
+ return -1;
out_eof:
strm->eof = true;
strm->buffer_used = 0;
@@ -347,6 +357,8 @@ dir_iterator_t *tar_open_stream(istream_t *strm)
tar_iterator_t *tar = calloc(1, sizeof(*tar));
dir_iterator_t *it = (dir_iterator_t *)tar;
xfrm_stream_t *xfrm = NULL;
+ const sqfs_u8 *ptr;
+ size_t size;
int ret;
if (tar == NULL)
@@ -365,11 +377,15 @@ dir_iterator_t *tar_open_stream(istream_t *strm)
if (ret != 0)
goto out_strm;
- ret = tar_probe(strm->buffer, strm->buffer_used);
+ ret = istream_get_buffered_data(strm, &ptr, &size);
+ if (ret != 0)
+ goto out_strm;
+
+ ret = tar_probe(ptr, size);
if (ret > 0)
goto out_strm;
- ret = xfrm_compressor_id_from_magic(strm->buffer, strm->buffer_used);
+ ret = xfrm_compressor_id_from_magic(ptr, size);
if (ret <= 0)
goto out_strm;