diff options
Diffstat (limited to 'lib/sqfs')
-rw-r--r-- | lib/sqfs/block_writer.c | 93 |
1 files changed, 42 insertions, 51 deletions
diff --git a/lib/sqfs/block_writer.c b/lib/sqfs/block_writer.c index 7709fb3..7302736 100644 --- a/lib/sqfs/block_writer.c +++ b/lib/sqfs/block_writer.c @@ -38,7 +38,6 @@ typedef struct { array_t blocks; size_t devblksz; - sqfs_u64 start; size_t file_start; sqfs_u32 flags; @@ -54,14 +53,24 @@ static int store_block_location(block_writer_default_t *wr, sqfs_u64 offset, return array_append(&(wr->blocks), &info); } -static int deduplicate_blocks(block_writer_default_t *wr, size_t count, - size_t *out) +static int deduplicate_blocks(block_writer_default_t *wr, sqfs_u32 flags, sqfs_u64 *out) { const blk_info_t *blocks = wr->blocks.data; sqfs_u64 loc_a, loc_b, sz; - size_t i, j; + size_t i, j, count; int ret; + count = wr->blocks.used - wr->file_start; + if (count == 0) { + *out = 0; + return 0; + } + + if (flags & SQFS_BLK_DONT_DEDUPLICATE) { + *out = blocks[wr->file_start].offset; + return 0; + } + sz = 0; loc_a = blocks[wr->file_start].offset; @@ -94,17 +103,32 @@ static int deduplicate_blocks(block_writer_default_t *wr, size_t count, return ret; } - *out = i; - return 0; + *out = blocks[i].offset; + if (i >= wr->file_start) + return 0; + + if (count >= (wr->file_start - i)) { + wr->blocks.used = i + count; + } else { + wr->blocks.used = wr->file_start; + } + + sz = blocks[wr->blocks.used - 1].offset + + SIZE_FROM_HASH(blocks[wr->blocks.used - 1].hash); + + return wr->file->truncate(wr->file, sz); } -static int align_file(block_writer_default_t *wr) +static int align_file(block_writer_default_t *wr, sqfs_u32 flags) { void *padding; sqfs_u64 size; size_t diff; int ret; + if (!(flags & SQFS_BLK_ALIGN)) + return 0; + size = wr->file->get_size(wr->file); diff = size % wr->devblksz; if (diff == 0) @@ -133,28 +157,22 @@ static int write_data_block(sqfs_block_writer_t *base, void *user, const sqfs_u8 *data, sqfs_u64 *location) { block_writer_default_t *wr = (block_writer_default_t *)base; - size_t start, count; - sqfs_u32 out; int err; (void)user; if (flags & (SQFS_BLK_FIRST_BLOCK | SQFS_BLK_FRAGMENT_BLOCK)) { - if (flags & SQFS_BLK_ALIGN) { - err = align_file(wr); - if (err) - return err; - } + err = align_file(wr, flags); + if (err) + return err; - if (flags & SQFS_BLK_FIRST_BLOCK) { - wr->start = wr->file->get_size(wr->file); + if (flags & SQFS_BLK_FIRST_BLOCK) wr->file_start = wr->blocks.used; - } } *location = wr->file->get_size(wr->file); if (size != 0 && !(flags & SQFS_BLK_IS_SPARSE)) { - out = size; + sqfs_u32 out = size; if (!(flags & SQFS_BLK_IS_COMPRESSED)) out |= 1 << 24; @@ -167,40 +185,13 @@ static int write_data_block(sqfs_block_writer_t *base, void *user, return err; } - if (flags & SQFS_BLK_ALIGN) { - if (flags & (SQFS_BLK_LAST_BLOCK | SQFS_BLK_FRAGMENT_BLOCK)) { - err = align_file(wr); - if (err) - return err; - } - } - - if (flags & SQFS_BLK_LAST_BLOCK) { - count = wr->blocks.used - wr->file_start; - - if (count == 0) { - *location = 0; - } else if (!(flags & SQFS_BLK_DONT_DEDUPLICATE)) { - err = deduplicate_blocks(wr, count, &start); - if (err) - return err; - - *location = ((blk_info_t *) - wr->blocks.data)[start].offset; - - if (start >= wr->file_start) - return 0; - - if (count >= (wr->file_start - start)) { - wr->blocks.used = start + count; - } else { - wr->blocks.used = wr->file_start; - } + if (flags & (SQFS_BLK_LAST_BLOCK | SQFS_BLK_FRAGMENT_BLOCK)) { + err = align_file(wr, flags); + if (err) + return err; - err = wr->file->truncate(wr->file, wr->start); - if (err) - return err; - } + if (flags & SQFS_BLK_LAST_BLOCK) + return deduplicate_blocks(wr, flags, location); } return 0; |