aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/data_reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/data_reader.c')
-rw-r--r--lib/sqfs/data_reader.c116
1 files changed, 52 insertions, 64 deletions
diff --git a/lib/sqfs/data_reader.c b/lib/sqfs/data_reader.c
index 42f99ec..c8886c5 100644
--- a/lib/sqfs/data_reader.c
+++ b/lib/sqfs/data_reader.c
@@ -23,13 +23,14 @@
struct sqfs_data_reader_t {
sqfs_frag_table_t *frag_tbl;
sqfs_compressor_t *cmp;
- sqfs_block_t *data_block;
- sqfs_block_t *frag_block;
+ sqfs_file_t *file;
+ sqfs_u8 *data_block;
+ size_t data_blk_size;
sqfs_u64 current_block;
- sqfs_file_t *file;
-
+ sqfs_u8 *frag_block;
+ size_t frag_blk_size;
sqfs_u32 current_frag_index;
sqfs_u32 block_size;
@@ -37,77 +38,72 @@ struct sqfs_data_reader_t {
};
static int get_block(sqfs_data_reader_t *data, sqfs_u64 off, sqfs_u32 size,
- size_t unpacked_size, sqfs_block_t **out)
+ sqfs_u32 max_size, size_t *out_sz, sqfs_u8 **out)
{
- sqfs_block_t *blk = alloc_flex(sizeof(*blk), 1, unpacked_size);
sqfs_u32 on_disk_size;
sqfs_s32 ret;
int err;
- if (blk == NULL)
- return SQFS_ERROR_ALLOC;
+ *out = alloc_array(1, max_size);
+ *out_sz = max_size;
- blk->size = unpacked_size;
+ if (*out == NULL) {
+ err = SQFS_ERROR_ALLOC;
+ goto fail;
+ }
- if (SQFS_IS_SPARSE_BLOCK(size)) {
- *out = blk;
+ if (SQFS_IS_SPARSE_BLOCK(size))
return 0;
- }
on_disk_size = SQFS_ON_DISK_BLOCK_SIZE(size);
- if (on_disk_size > unpacked_size) {
- free(blk);
- return SQFS_ERROR_OVERFLOW;
+ if (on_disk_size > max_size) {
+ err = SQFS_ERROR_OVERFLOW;
+ goto fail;
}
if (SQFS_IS_BLOCK_COMPRESSED(size)) {
err = data->file->read_at(data->file, off,
data->scratch, on_disk_size);
- if (err) {
- free(blk);
- return err;
- }
+ if (err)
+ goto fail;
ret = data->cmp->do_block(data->cmp, data->scratch,
- on_disk_size, blk->data, blk->size);
- if (ret <= 0)
+ on_disk_size, *out, max_size);
+ if (ret <= 0) {
err = ret < 0 ? ret : SQFS_ERROR_OVERFLOW;
+ goto fail;
+ }
+
+ *out_sz = ret;
} else {
err = data->file->read_at(data->file, off,
- blk->data, on_disk_size);
- }
+ *out, on_disk_size);
+ if (err)
+ goto fail;
- if (err) {
- free(blk);
- return err;
+ *out_sz = on_disk_size;
}
- *out = blk;
return 0;
+fail:
+ free(*out);
+ *out = NULL;
+ *out_sz = 0;
+ return err;
}
static int precache_data_block(sqfs_data_reader_t *data, sqfs_u64 location,
sqfs_u32 size)
{
- int ret;
-
if (data->data_block != NULL && data->current_block == location)
return 0;
free(data->data_block);
- data->data_block = NULL;
-
- ret = get_block(data, location, size, data->block_size,
- &data->data_block);
-
- if (ret < 0) {
- data->data_block = NULL;
- return ret;
- }
-
data->current_block = location;
- return 0;
+
+ return get_block(data, location, size, data->block_size,
+ &data->data_blk_size, &data->data_block);
}
static int precache_fragment_block(sqfs_data_reader_t *data, size_t idx)
@@ -123,15 +119,10 @@ static int precache_fragment_block(sqfs_data_reader_t *data, size_t idx)
return ret;
free(data->frag_block);
- data->frag_block = NULL;
-
- ret = get_block(data, ent.start_offset, ent.size, data->block_size,
- &data->frag_block);
- if (ret < 0)
- return ret;
-
data->current_frag_index = idx;
- return 0;
+
+ return get_block(data, ent.start_offset, ent.size, data->block_size,
+ &data->frag_blk_size, &data->frag_block);
}
sqfs_data_reader_t *sqfs_data_reader_create(sqfs_file_t *file,
@@ -183,7 +174,7 @@ void sqfs_data_reader_destroy(sqfs_data_reader_t *data)
int sqfs_data_reader_get_block(sqfs_data_reader_t *data,
const sqfs_inode_generic_t *inode,
- size_t index, sqfs_block_t **out)
+ size_t index, size_t *size, sqfs_u8 **out)
{
size_t i, unpacked_size;
sqfs_u64 off, filesz;
@@ -201,25 +192,25 @@ int sqfs_data_reader_get_block(sqfs_data_reader_t *data,
unpacked_size = filesz < data->block_size ? filesz : data->block_size;
- return get_block(data, off, inode->extra[index], unpacked_size, out);
+ return get_block(data, off, inode->extra[index],
+ unpacked_size, size, out);
}
int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data,
const sqfs_inode_generic_t *inode,
- sqfs_block_t **out)
+ size_t *size, sqfs_u8 **out)
{
sqfs_u32 frag_idx, frag_off, frag_sz;
- sqfs_block_t *blk;
sqfs_u64 filesz;
int err;
sqfs_inode_get_file_size(inode, &filesz);
sqfs_inode_get_frag_location(inode, &frag_idx, &frag_off);
+ *size = 0;
+ *out = NULL;
- if (inode->num_file_blocks * data->block_size >= filesz) {
- *out = NULL;
+ if (inode->num_file_blocks * data->block_size >= filesz)
return 0;
- }
frag_sz = filesz % data->block_size;
@@ -230,14 +221,12 @@ int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data,
if (frag_off + frag_sz > data->block_size)
return SQFS_ERROR_OUT_OF_BOUNDS;
- blk = alloc_flex(sizeof(*blk), 1, frag_sz);
- if (blk == NULL)
+ *out = alloc_array(1, frag_sz);
+ if (*out == NULL)
return SQFS_ERROR_ALLOC;
- blk->size = frag_sz;
- memcpy(blk->data, (char *)data->frag_block->data + frag_off, frag_sz);
-
- *out = blk;
+ *size = frag_sz;
+ memcpy(*out, (char *)data->frag_block + frag_off, frag_sz);
return 0;
}
@@ -286,8 +275,7 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
if (err)
return err;
- memcpy(buffer, (char *)data->data_block->data + offset,
- diff);
+ memcpy(buffer, (char *)data->data_block + offset, diff);
off += SQFS_ON_DISK_BLOCK_SIZE(inode->extra[i]);
}
@@ -322,7 +310,7 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
if (size == 0)
return total;
- ptr = (char *)data->frag_block->data + frag_off + offset;
+ ptr = (char *)data->frag_block + frag_off + offset;
memcpy(buffer, ptr, size);
total += size;
}