summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sqfs/data_reader.h13
-rw-r--r--lib/common/data_reader_dump.c26
-rw-r--r--lib/sqfs/data_reader.c116
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;
}