summaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs')
-rw-r--r--lib/sqfs/block_processor/common.c8
-rw-r--r--lib/sqfs/data_reader.c16
-rw-r--r--lib/sqfs/dir_writer.c9
-rw-r--r--lib/sqfs/inode.c35
-rw-r--r--lib/sqfs/read_inode.c11
-rw-r--r--lib/sqfs/write_inode.c22
6 files changed, 47 insertions, 54 deletions
diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c
index d855b51..51851ae 100644
--- a/lib/sqfs/block_processor/common.c
+++ b/lib/sqfs/block_processor/common.c
@@ -10,10 +10,14 @@
static void set_block_size(sqfs_inode_generic_t *inode,
sqfs_u32 index, sqfs_u32 size)
{
+ size_t min_size = (index + 1) * sizeof(sqfs_u32);
+
inode->extra[index] = size;
- if (index >= inode->num_file_blocks)
- inode->num_file_blocks = index + 1;
+ if (min_size >= inode->payload_bytes_used) {
+ inode->payload_bytes_used = min_size;
+ inode->payload_bytes_available = min_size;
+ }
}
int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk)
diff --git a/lib/sqfs/data_reader.c b/lib/sqfs/data_reader.c
index 8c9bb2e..5e985e0 100644
--- a/lib/sqfs/data_reader.c
+++ b/lib/sqfs/data_reader.c
@@ -187,7 +187,7 @@ int sqfs_data_reader_get_block(sqfs_data_reader_t *data,
sqfs_inode_get_file_block_start(inode, &off);
sqfs_inode_get_file_size(inode, &filesz);
- if (index >= inode->num_file_blocks)
+ if (index >= sqfs_inode_get_file_block_count(inode))
return SQFS_ERROR_OUT_OF_BOUNDS;
for (i = 0; i < index; ++i) {
@@ -206,6 +206,7 @@ int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data,
size_t *size, sqfs_u8 **out)
{
sqfs_u32 frag_idx, frag_off, frag_sz;
+ size_t block_count;
sqfs_u64 filesz;
int err;
@@ -214,7 +215,9 @@ int sqfs_data_reader_get_fragment(sqfs_data_reader_t *data,
*size = 0;
*out = NULL;
- if (inode->num_file_blocks * data->block_size >= filesz)
+ block_count = sqfs_inode_get_file_block_count(inode);
+
+ if (block_count * data->block_size >= filesz)
return 0;
frag_sz = filesz % data->block_size;
@@ -240,9 +243,9 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
sqfs_u64 offset, void *buffer, sqfs_u32 size)
{
sqfs_u32 frag_idx, frag_off, diff, total = 0;
+ size_t i, block_count;
sqfs_u64 off, filesz;
char *ptr;
- size_t i;
int err;
if (size >= 0x7FFFFFFF)
@@ -252,11 +255,12 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
sqfs_inode_get_file_size(inode, &filesz);
sqfs_inode_get_frag_location(inode, &frag_idx, &frag_off);
sqfs_inode_get_file_block_start(inode, &off);
+ block_count = sqfs_inode_get_file_block_count(inode);
/* find location of the first block */
i = 0;
- while (offset > data->block_size && i < inode->num_file_blocks) {
+ while (offset > data->block_size && i < block_count) {
off += SQFS_ON_DISK_BLOCK_SIZE(inode->extra[i++]);
offset -= data->block_size;
@@ -268,7 +272,7 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
}
/* copy data from blocks */
- while (i < inode->num_file_blocks && size > 0 && filesz > 0) {
+ while (i < block_count && size > 0 && filesz > 0) {
diff = data->block_size - offset;
if (size < diff)
diff = size;
@@ -298,7 +302,7 @@ sqfs_s32 sqfs_data_reader_read(sqfs_data_reader_t *data,
}
/* copy from fragment */
- if (i == inode->num_file_blocks && size > 0 && filesz > 0) {
+ if (i == block_count && size > 0 && filesz > 0) {
err = precache_fragment_block(data, frag_idx);
if (err)
return err;
diff --git a/lib/sqfs/dir_writer.c b/lib/sqfs/dir_writer.c
index 9dd7ad2..bb3e867 100644
--- a/lib/sqfs/dir_writer.c
+++ b/lib/sqfs/dir_writer.c
@@ -392,6 +392,7 @@ sqfs_inode_generic_t
if (inode == NULL)
return NULL;
+ inode->payload_bytes_available = index_size;
start_block = writer->dir_ref >> 16;
block_offset = writer->dir_ref & 0xFFFF;
@@ -416,7 +417,7 @@ sqfs_inode_generic_t
inode->data.dir_ext.offset = block_offset;
inode->data.dir_ext.xattr_idx = xattr;
inode->data.dir_ext.inodex_count = 0;
- inode->num_dir_idx_bytes = 0;
+ inode->payload_bytes_used = 0;
for (idx = writer->idx; idx != NULL; idx = idx->next) {
memset(&ent, 0, sizeof(ent));
@@ -425,14 +426,14 @@ sqfs_inode_generic_t
ent.size = idx->ent->name_len - 1;
ptr = (sqfs_u8 *)inode->extra +
- inode->num_dir_idx_bytes;
+ inode->payload_bytes_used;
memcpy(ptr, &ent, sizeof(ent));
memcpy(ptr + sizeof(ent), idx->ent->name,
idx->ent->name_len);
inode->data.dir_ext.inodex_count += 1;
- inode->num_dir_idx_bytes += sizeof(ent);
- inode->num_dir_idx_bytes += idx->ent->name_len;
+ inode->payload_bytes_used += sizeof(ent);
+ inode->payload_bytes_used += idx->ent->name_len;
}
}
diff --git a/lib/sqfs/inode.c b/lib/sqfs/inode.c
index 815cc0f..bda244b 100644
--- a/lib/sqfs/inode.c
+++ b/lib/sqfs/inode.c
@@ -36,38 +36,9 @@ static int inverse_type[] = {
int sqfs_inode_copy(const sqfs_inode_generic_t *src,
sqfs_inode_generic_t **out)
{
- sqfs_inode_generic_t *copy;
- size_t size = sizeof(*src);
+ size_t size = sizeof(*src) + src->payload_bytes_used;
+ sqfs_inode_generic_t *copy = calloc(1, size);
- switch (src->base.type) {
- case SQFS_INODE_FILE:
- case SQFS_INODE_EXT_FILE:
- size += src->num_file_blocks;
- break;
- case SQFS_INODE_DIR:
- case SQFS_INODE_EXT_DIR:
- size += src->num_dir_idx_bytes;
- break;
- case SQFS_INODE_SLINK:
- size += src->data.slink.target_size;
- break;
- case SQFS_INODE_EXT_SLINK:
- size += src->data.slink_ext.target_size;
- break;
- case SQFS_INODE_BDEV:
- case SQFS_INODE_CDEV:
- case SQFS_INODE_FIFO:
- case SQFS_INODE_SOCKET:
- case SQFS_INODE_EXT_BDEV:
- case SQFS_INODE_EXT_CDEV:
- case SQFS_INODE_EXT_FIFO:
- case SQFS_INODE_EXT_SOCKET:
- break;
- default:
- return SQFS_ERROR_CORRUPTED;
- }
-
- copy = calloc(1, size);
if (copy == NULL)
return SQFS_ERROR_ALLOC;
@@ -406,7 +377,7 @@ int sqfs_inode_unpack_dir_index_entry(const sqfs_inode_generic_t *inode,
ptr = (char *)inode->extra;
for (;;) {
- if (offset >= inode->num_dir_idx_bytes)
+ if (offset >= inode->payload_bytes_used)
return SQFS_ERROR_OUT_OF_BOUNDS;
if (index == 0)
diff --git a/lib/sqfs/read_inode.c b/lib/sqfs/read_inode.c
index 8653928..6ca61d5 100644
--- a/lib/sqfs/read_inode.c
+++ b/lib/sqfs/read_inode.c
@@ -101,7 +101,8 @@ static int read_inode_file(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
out->base = *base;
out->data.file = file;
- out->num_file_blocks = count;
+ out->payload_bytes_available = count * sizeof(sqfs_u32);
+ out->payload_bytes_used = count * sizeof(sqfs_u32);
err = sqfs_meta_reader_read(ir, out->extra, count * sizeof(sqfs_u32));
if (err) {
@@ -147,7 +148,8 @@ static int read_inode_file_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
out->base = *base;
out->data.file_ext = file;
- out->num_file_blocks = count;
+ out->payload_bytes_available = count * sizeof(sqfs_u32);
+ out->payload_bytes_used = count * sizeof(sqfs_u32);
err = sqfs_meta_reader_read(ir, out->extra, count * sizeof(sqfs_u32));
if (err) {
@@ -186,6 +188,8 @@ static int read_inode_slink(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
if (out == NULL)
return SQFS_ERROR_ALLOC;
+ out->payload_bytes_available = size - sizeof(*out);
+ out->payload_bytes_used = size - sizeof(*out) - 1;
out->base = *base;
out->data.slink = slink;
@@ -298,7 +302,8 @@ static int read_inode_dir_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base,
index_used += ent.size + 1;
}
- out->num_dir_idx_bytes = index_used;
+ out->payload_bytes_used = index_used;
+ out->payload_bytes_available = index_used;
*result = out;
return 0;
}
diff --git a/lib/sqfs/write_inode.c b/lib/sqfs/write_inode.c
index b5ba905..86ed146 100644
--- a/lib/sqfs/write_inode.c
+++ b/lib/sqfs/write_inode.c
@@ -14,18 +14,26 @@
#include "compat.h"
#include <string.h>
+#include <alloca.h>
static int write_block_sizes(sqfs_meta_writer_t *ir,
const sqfs_inode_generic_t *n)
{
- sqfs_u32 sizes[n->num_file_blocks];
+ sqfs_u32 *sizes;
size_t i;
- for (i = 0; i < n->num_file_blocks; ++i)
+ if (n->payload_bytes_used < sizeof(sizes[0]))
+ return 0;
+
+ if ((n->payload_bytes_used % sizeof(sizes[0])) != 0)
+ return SQFS_ERROR_CORRUPTED;
+
+ sizes = alloca(n->payload_bytes_used);
+
+ for (i = 0; i < (n->payload_bytes_used / sizeof(sizes[0])); ++i)
sizes[i] = htole32(n->extra[i]);
- return sqfs_meta_writer_append(ir, sizes,
- sizeof(sqfs_u32) * n->num_file_blocks);
+ return sqfs_meta_writer_append(ir, sizes, n->payload_bytes_used);
}
static int write_dir_index(sqfs_meta_writer_t *ir, const sqfs_u8 *data,
@@ -102,7 +110,7 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir,
ret = sqfs_meta_writer_append(ir, &file, sizeof(file));
if (ret)
return ret;
- return n->num_file_blocks ? write_block_sizes(ir, n) : 0;
+ return write_block_sizes(ir, n);
}
case SQFS_INODE_SLINK: {
sqfs_inode_slink_t slink = {
@@ -144,7 +152,7 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir,
if (ret)
return ret;
return write_dir_index(ir, (const sqfs_u8 *)n->extra,
- n->num_dir_idx_bytes);
+ n->payload_bytes_used);
}
case SQFS_INODE_EXT_FILE: {
sqfs_inode_file_ext_t file = {
@@ -160,7 +168,7 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir,
ret = sqfs_meta_writer_append(ir, &file, sizeof(file));
if (ret)
return ret;
- return n->num_file_blocks ? write_block_sizes(ir, n) : 0;
+ return write_block_sizes(ir, n);
}
case SQFS_INODE_EXT_SLINK: {
sqfs_inode_slink_t slink = {