diff options
-rw-r--r-- | include/sqfs/data_reader.h | 13 | ||||
-rw-r--r-- | lib/common/data_reader_dump.c | 26 | ||||
-rw-r--r-- | lib/sqfs/data_reader.c | 116 |
3 files changed, 75 insertions, 80 deletions
diff --git a/include/sqfs/data_reader.h b/include/sqfs/data_reader.h index bf29417..0c4918c 100644 --- a/include/sqfs/data_reader.h +++ b/include/sqfs/data_reader.h @@ -97,13 +97,15 @@ SQFS_API int sqfs_data_reader_load_fragment_table(sqfs_data_reader_t *data, * * @param data A pointer to a data reader object. * @param inode A pointer to the inode describing the file. - * @param out Returns a pointer to the tail block of the file. + * @param size Returns the size of the data read. + * @param out Returns a pointer to the raw data that must be + * released using free. * * @return Zero on succcess, an @ref E_SQFS_ERROR value on failure. */ SQFS_API 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); /** * @brief Get a full sized data block of a file by block index. @@ -113,13 +115,16 @@ SQFS_API int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data, * @param data A pointer to a data reader object. * @param inode A pointer to the inode describing the file. * @param index The block index in the inodes block list. - * @param out Returns a pointer to the data block. + * @param size Returns the size of the data read. + * @param out Returns a pointer to the raw data that must be + * released using free. * * @return Zero on succcess, an @ref E_SQFS_ERROR value on failure. */ SQFS_API 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); /** * @brief A simple UNIX-read-like function to read data from a file. diff --git a/lib/common/data_reader_dump.c b/lib/common/data_reader_dump.c index bf418c6..33bfc4f 100644 --- a/lib/common/data_reader_dump.c +++ b/lib/common/data_reader_dump.c @@ -11,10 +11,10 @@ #include <stdio.h> #include <errno.h> -static int append_block(FILE *fp, const sqfs_block_t *blk) +static int append_block(FILE *fp, const sqfs_u8 *data, size_t size) { - const unsigned char *ptr = blk->data; - size_t ret, size = blk->size; + const sqfs_u8 *ptr = data; + size_t ret; while (size > 0) { if (ferror(fp)) { @@ -39,9 +39,9 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, FILE *fp, size_t block_size, bool allow_sparse) { - sqfs_block_t *blk; + size_t i, diff, chunk_size; sqfs_u64 filesz; - size_t i, diff; + sqfs_u8 *chunk; int err; sqfs_inode_get_file_size(inode, &filesz); @@ -64,14 +64,15 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, if (fseek(fp, diff, SEEK_CUR) < 0) goto fail_sparse; } else { - err = sqfs_data_reader_get_block(data, inode, i, &blk); + err = sqfs_data_reader_get_block(data, inode, i, + &chunk_size, &chunk); if (err) { sqfs_perror(name, "reading data block", err); return -1; } - err = append_block(fp, blk); - free(blk); + err = append_block(fp, chunk, chunk_size); + free(chunk); if (err) return -1; @@ -81,18 +82,19 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, } if (filesz > 0) { - err = sqfs_data_reader_get_fragment(data, inode, &blk); + err = sqfs_data_reader_get_fragment(data, inode, + &chunk_size, &chunk); if (err) { sqfs_perror(name, "reading fragment block", err); return -1; } - if (append_block(fp, blk)) { - free(blk); + if (append_block(fp, chunk, chunk_size)) { + free(chunk); return -1; } - free(blk); + free(chunk); } return 0; 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; } |