aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs')
-rw-r--r--lib/sqfs/block_processor/common.c44
-rw-r--r--lib/sqfs/block_processor/fileapi.c11
-rw-r--r--lib/sqfs/block_processor/serial.c38
-rw-r--r--lib/sqfs/block_writer.c35
4 files changed, 71 insertions, 57 deletions
diff --git a/lib/sqfs/block_processor/common.c b/lib/sqfs/block_processor/common.c
index 002dad4..3859916 100644
--- a/lib/sqfs/block_processor/common.c
+++ b/lib/sqfs/block_processor/common.c
@@ -13,6 +13,11 @@ int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk)
sqfs_u32 size;
int err;
+ err = sqfs_block_writer_write(proc->wr, blk->size, blk->checksum,
+ blk->flags, blk->data, &location);
+ if (err)
+ return err;
+
if (blk->flags & SQFS_BLK_IS_SPARSE) {
sqfs_inode_make_extended(blk->inode);
blk->inode->data.file_ext.sparse += blk->size;
@@ -20,19 +25,11 @@ int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk)
blk->inode->num_file_blocks += 1;
proc->stats.sparse_block_count += 1;
- return 0;
- }
-
- size = blk->size;
- if (!(blk->flags & SQFS_BLK_IS_COMPRESSED))
- size |= 1 << 24;
-
- err = sqfs_block_writer_write(proc->wr, blk->size, blk->checksum,
- blk->flags, blk->data, &location);
- if (err)
- return err;
+ } else if (blk->size != 0) {
+ size = blk->size;
+ if (!(blk->flags & SQFS_BLK_IS_COMPRESSED))
+ size |= 1 << 24;
- if (blk->size != 0) {
if (blk->flags & SQFS_BLK_FRAGMENT_BLOCK) {
err = sqfs_frag_table_set(proc->frag_tbl, blk->index,
location, size);
@@ -52,12 +49,23 @@ int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk)
return 0;
}
+static bool is_zero_block(unsigned char *ptr, size_t size)
+{
+ return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0;
+}
+
int block_processor_do_block(sqfs_block_t *block, sqfs_compressor_t *cmp,
sqfs_u8 *scratch, size_t scratch_size)
{
ssize_t ret;
- if (block->size == 0 || (block->flags & SQFS_BLK_IS_SPARSE)) {
+ if (block->size == 0) {
+ block->checksum = 0;
+ return 0;
+ }
+
+ if (is_zero_block(block->data, block->size)) {
+ block->flags |= SQFS_BLK_IS_SPARSE;
block->checksum = 0;
return 0;
}
@@ -90,6 +98,16 @@ int process_completed_fragment(sqfs_block_processor_t *proc, sqfs_block_t *frag,
size_t size;
int err;
+ if (frag->flags & SQFS_BLK_IS_SPARSE) {
+ sqfs_inode_make_extended(frag->inode);
+ frag->inode->data.file_ext.sparse += frag->size;
+ frag->inode->extra[frag->inode->num_file_blocks] = 0;
+ frag->inode->num_file_blocks += 1;
+
+ proc->stats.sparse_block_count += 1;
+ return 0;
+ }
+
proc->stats.total_frag_count += 1;
err = sqfs_frag_table_find_tail_end(proc->frag_tbl,
diff --git a/lib/sqfs/block_processor/fileapi.c b/lib/sqfs/block_processor/fileapi.c
index 7ca189e..abaf3d2 100644
--- a/lib/sqfs/block_processor/fileapi.c
+++ b/lib/sqfs/block_processor/fileapi.c
@@ -7,11 +7,6 @@
#define SQFS_BUILDING_DLL
#include "internal.h"
-static bool is_zero_block(unsigned char *ptr, size_t size)
-{
- return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0;
-}
-
static int enqueue_block(sqfs_block_processor_t *proc, sqfs_block_t *block)
{
int status;
@@ -58,10 +53,8 @@ static int flush_block(sqfs_block_processor_t *proc, sqfs_block_t *block)
block->flags = proc->blk_flags;
block->inode = proc->inode;
- if (is_zero_block(block->data, block->size)) {
- block->flags |= SQFS_BLK_IS_SPARSE;
- } else if (block->size < proc->max_block_size &&
- !(block->flags & SQFS_BLK_DONT_FRAGMENT)) {
+ if (block->size < proc->max_block_size &&
+ !(block->flags & SQFS_BLK_DONT_FRAGMENT)) {
block->flags |= SQFS_BLK_IS_FRAGMENT;
} else {
proc->blk_flags &= ~SQFS_BLK_FIRST_BLOCK;
diff --git a/lib/sqfs/block_processor/serial.c b/lib/sqfs/block_processor/serial.c
index c9ee164..1d2c2db 100644
--- a/lib/sqfs/block_processor/serial.c
+++ b/lib/sqfs/block_processor/serial.c
@@ -43,35 +43,33 @@ int append_to_work_queue(sqfs_block_processor_t *proc, sqfs_block_t *block)
{
sqfs_block_t *fragblk = NULL;
- if (proc->status != 0 || block == NULL) {
- free(block);
- return proc->status;
- }
+ if (proc->status != 0)
+ goto done;
- if (block->flags & SQFS_BLK_IS_FRAGMENT) {
- block->checksum = crc32(0, block->data, block->size);
+ proc->status = block_processor_do_block(block, proc->cmp,
+ proc->scratch,
+ proc->max_block_size);
+ if (proc->status != 0)
+ goto done;
+ if (block->flags & SQFS_BLK_IS_FRAGMENT) {
proc->status = process_completed_fragment(proc, block,
&fragblk);
- free(block);
-
- if (proc->status != 0) {
- free(fragblk);
- return proc->status;
- }
-
if (fragblk == NULL)
- return 0;
+ goto done;
+ free(block);
block = fragblk;
- }
-
- proc->status = block_processor_do_block(block, proc->cmp, proc->scratch,
- proc->max_block_size);
- if (proc->status == 0)
- proc->status = process_completed_block(proc, block);
+ proc->status = block_processor_do_block(block, proc->cmp,
+ proc->scratch,
+ proc->max_block_size);
+ if (proc->status != 0)
+ goto done;
+ }
+ proc->status = process_completed_block(proc, block);
+done:
free(block);
return proc->status;
}
diff --git a/lib/sqfs/block_writer.c b/lib/sqfs/block_writer.c
index 63f8c61..73dcb14 100644
--- a/lib/sqfs/block_writer.c
+++ b/lib/sqfs/block_writer.c
@@ -191,14 +191,14 @@ int sqfs_block_writer_write(sqfs_block_writer_t *wr, sqfs_u32 size,
}
}
- if (size != 0) {
+ offset = wr->file->get_size(wr->file);
+ *location = offset;
+
+ if (size != 0 && !(flags & SQFS_BLK_IS_SPARSE)) {
out = size;
if (!(flags & SQFS_BLK_IS_COMPRESSED))
out |= 1 << 24;
- offset = wr->file->get_size(wr->file);
- *location = offset;
-
err = store_block_location(wr, offset, out, checksum);
if (err)
return err;
@@ -226,19 +226,24 @@ int sqfs_block_writer_write(sqfs_block_writer_t *wr, sqfs_u32 size,
}
count = wr->num_blocks - wr->file_start;
- start = deduplicate_blocks(wr, count);
- offset = wr->blocks[start].offset;
-
- *location = offset;
- if (start >= wr->file_start)
- return 0;
- offset = start + count;
- if (offset >= wr->file_start) {
- count = wr->num_blocks - offset;
- wr->num_blocks = offset;
+ if (count == 0) {
+ *location = 0;
} else {
- wr->num_blocks = wr->file_start;
+ start = deduplicate_blocks(wr, count);
+ offset = wr->blocks[start].offset;
+
+ *location = offset;
+ if (start >= wr->file_start)
+ return 0;
+
+ offset = start + count;
+ if (offset >= wr->file_start) {
+ count = wr->num_blocks - offset;
+ wr->num_blocks = offset;
+ } else {
+ wr->num_blocks = wr->file_start;
+ }
}
err = wr->file->truncate(wr->file, wr->start);