diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/sqfshelper/data_reader.c | 104 |
1 files changed, 36 insertions, 68 deletions
diff --git a/lib/sqfshelper/data_reader.c b/lib/sqfshelper/data_reader.c index 929b7ee..9a31fa4 100644 --- a/lib/sqfshelper/data_reader.c +++ b/lib/sqfshelper/data_reader.c @@ -20,19 +20,19 @@ struct data_reader_t { sqfs_fragment_t *frag; - size_t num_fragments; - size_t current_frag_index; - size_t frag_used; + sqfs_compressor_t *cmp; + sqfs_block_t *data_block; + sqfs_block_t *frag_block; - off_t current_block; + uint64_t current_block; - sqfs_compressor_t *cmp; - size_t block_size; sqfs_file_t *file; - void *block; - void *scratch; - void *frag_block; + uint32_t num_fragments; + uint32_t current_frag_index; + uint32_t block_size; + + uint8_t scratch[]; }; static int get_block(data_reader_t *data, uint64_t off, uint32_t size, @@ -84,53 +84,23 @@ static int get_block(data_reader_t *data, uint64_t off, uint32_t size, return 0; } -static ssize_t read_block(data_reader_t *data, off_t offset, uint32_t size, - void *dst) -{ - bool compressed = SQFS_IS_BLOCK_COMPRESSED(size); - void *ptr = compressed ? data->scratch : dst; - ssize_t ret; - - size = SQFS_ON_DISK_BLOCK_SIZE(size); - - if (size > data->block_size) - goto fail_bs; - - if (data->file->read_at(data->file, offset, ptr, size)) { - fputs("error reading data block from input file\n", stderr); - return -1; - } - - if (compressed) { - ret = data->cmp->do_block(data->cmp, data->scratch, size, - dst, data->block_size); - if (ret <= 0) { - fputs("extracting block failed\n", stderr); - return -1; - } - size = ret; - } - - return size; -fail_bs: - fputs("found compressed block larger than block size\n", stderr); - return -1; -} - -static int precache_data_block(data_reader_t *data, off_t location, +static int precache_data_block(data_reader_t *data, uint64_t location, uint32_t size) { - ssize_t ret; + int ret; - if (data->current_block == location) + if (data->data_block != NULL && data->current_block == location) return 0; - ret = read_block(data, location, size, data->block); - if (ret < 0) - return -1; + free(data->data_block); - if ((size_t)ret < data->block_size) - memset((char *)data->block + ret, 0, data->block_size - ret); + ret = get_block(data, location, size, data->block_size, + &data->data_block); + + if (ret < 0) { + data->data_block = NULL; + return -1; + } data->current_block = location; return 0; @@ -138,9 +108,9 @@ static int precache_data_block(data_reader_t *data, off_t location, static int precache_fragment_block(data_reader_t *data, size_t idx) { - ssize_t ret; + int ret; - if (idx == data->current_frag_index) + if (data->frag_block != NULL && idx == data->current_frag_index) return 0; if (idx >= data->num_fragments) { @@ -148,20 +118,22 @@ static int precache_fragment_block(data_reader_t *data, size_t idx) return -1; } - ret = read_block(data, data->frag[idx].start_offset, - data->frag[idx].size, data->frag_block); + free(data->frag_block); + + ret = get_block(data, data->frag[idx].start_offset, + data->frag[idx].size, data->block_size, + &data->frag_block); if (ret < 0) return -1; data->current_frag_index = idx; - data->frag_used = ret; return 0; } data_reader_t *data_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp) { - data_reader_t *data = alloc_flex(sizeof(*data), super->block_size, 3); + data_reader_t *data = alloc_flex(sizeof(*data), 1, super->block_size); size_t i, size; void *raw_frag; int ret; @@ -173,10 +145,6 @@ data_reader_t *data_reader_create(sqfs_file_t *file, sqfs_super_t *super, data->num_fragments = super->fragment_entry_count; data->current_frag_index = super->fragment_entry_count; - data->block = (char *)data + sizeof(*data); - data->scratch = (char *)data->block + super->block_size; - data->frag_block = (char *)data->scratch + super->block_size; - data->current_block = -1; data->file = file; data->block_size = super->block_size; data->cmp = cmp; @@ -220,6 +188,8 @@ data_reader_t *data_reader_create(sqfs_file_t *file, sqfs_super_t *super, void data_reader_destroy(data_reader_t *data) { + free(data->data_block); + free(data->frag_block); free(data->frag); free(data); } @@ -285,7 +255,7 @@ int data_reader_get_fragment(data_reader_t *data, if (precache_fragment_block(data, frag_idx)) return -1; - if (frag_off + frag_sz > data->frag_used) + if (frag_off + frag_sz > data->block_size) return -1; blk = alloc_flex(sizeof(*blk), 1, frag_sz); @@ -293,7 +263,7 @@ int data_reader_get_fragment(data_reader_t *data, return -1; blk->size = frag_sz; - memcpy(blk->data, (char *)data->frag_block + frag_off, frag_sz); + memcpy(blk->data, (char *)data->frag_block->data + frag_off, frag_sz); *out = blk; return 0; @@ -349,7 +319,8 @@ ssize_t data_reader_read(data_reader_t *data, return -1; } - memcpy(buffer, (char *)data->block + offset, diff); + memcpy(buffer, (char *)data->data_block->data + offset, + diff); off += SQFS_ON_DISK_BLOCK_SIZE(inode->block_sizes[i]); } @@ -371,10 +342,7 @@ ssize_t data_reader_read(data_reader_t *data, if (precache_fragment_block(data, frag_idx)) return -1; - if (frag_off >= data->frag_used) - goto fail_range; - - if (frag_off + filesz > data->frag_used) + if (frag_off + filesz > data->block_size) goto fail_range; if (offset >= filesz) @@ -386,7 +354,7 @@ ssize_t data_reader_read(data_reader_t *data, if (size == 0) return total; - ptr = (char *)data->frag_block + frag_off + offset; + ptr = (char *)data->frag_block->data + frag_off + offset; memcpy(buffer, ptr, size); total += size; } |