diff options
Diffstat (limited to 'lib/sqfs/data_reader.c')
-rw-r--r-- | lib/sqfs/data_reader.c | 116 |
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; } |