diff options
Diffstat (limited to 'lib/sqfs/block_processor/block.c')
-rw-r--r-- | lib/sqfs/block_processor/block.c | 155 |
1 files changed, 12 insertions, 143 deletions
diff --git a/lib/sqfs/block_processor/block.c b/lib/sqfs/block_processor/block.c index 49892be..e88456a 100644 --- a/lib/sqfs/block_processor/block.c +++ b/lib/sqfs/block_processor/block.c @@ -9,164 +9,33 @@ #include <string.h> -static int store_block_location(sqfs_block_processor_t *proc, sqfs_u64 offset, - sqfs_u32 size, sqfs_u32 chksum) -{ - size_t new_sz; - void *new; - - if (proc->num_blocks == proc->max_blocks) { - new_sz = proc->max_blocks * 2; - new = realloc(proc->blocks, sizeof(proc->blocks[0]) * new_sz); - - if (new == NULL) - return SQFS_ERROR_ALLOC; - - proc->blocks = new; - proc->max_blocks = new_sz; - } - - proc->blocks[proc->num_blocks].offset = offset; - proc->blocks[proc->num_blocks].hash = MK_BLK_HASH(chksum, size); - proc->num_blocks += 1; - return 0; -} - -static size_t deduplicate_blocks(sqfs_block_processor_t *proc, size_t count) -{ - size_t i, j; - - for (i = 0; i < proc->file_start; ++i) { - for (j = 0; j < count; ++j) { - if (proc->blocks[i + j].hash != - proc->blocks[proc->file_start + j].hash) - break; - } - - if (j == count) - break; - } - - return i; -} - -static int align_file(sqfs_block_processor_t *proc, sqfs_block_t *blk) -{ - sqfs_u32 chksum; - void *padding; - sqfs_u64 size; - size_t diff; - int ret; - - if (!(blk->flags & SQFS_BLK_ALIGN)) - return 0; - - size = proc->file->get_size(proc->file); - diff = size % proc->devblksz; - if (diff == 0) - return 0; - - padding = calloc(1, diff); - if (padding == 0) - return SQFS_ERROR_ALLOC; - - if (proc->hooks != NULL && proc->hooks->prepare_padding != NULL) - proc->hooks->prepare_padding(proc->user_ptr, padding, diff); - - chksum = crc32(0, padding, diff); - - ret = proc->file->write_at(proc->file, size, padding, diff); - free(padding); - if (ret) - return ret; - - return store_block_location(proc, size, diff | (1 << 24), chksum); -} - int process_completed_block(sqfs_block_processor_t *proc, sqfs_block_t *blk) { - sqfs_u64 offset, bytes; - size_t start, count; - sqfs_u32 out; + sqfs_u64 location; + sqfs_u32 size; int err; - if (proc->hooks != NULL && proc->hooks->pre_block_write != NULL) { - proc->hooks->pre_block_write(proc->user_ptr, blk, proc->file); - } - - if (blk->flags & SQFS_BLK_FIRST_BLOCK) { - proc->start = proc->file->get_size(proc->file); - proc->file_start = proc->num_blocks; + size = blk->size; + if (!(blk->flags & SQFS_BLK_IS_COMPRESSED)) + size |= 1 << 24; - err = align_file(proc, blk); - if (err) - return err; - } + err = sqfs_block_writer_write(proc->wr, blk, &location); + if (err) + return err; if (blk->size != 0) { - out = blk->size; - if (!(blk->flags & SQFS_BLK_IS_COMPRESSED)) - out |= 1 << 24; - - offset = proc->file->get_size(proc->file); - if (blk->flags & SQFS_BLK_FRAGMENT_BLOCK) { err = sqfs_frag_table_set(proc->frag_tbl, blk->index, - offset, out); + location, size); if (err) return err; } else { - blk->inode->extra[blk->index] = out; + blk->inode->extra[blk->index] = size; } - - err = store_block_location(proc, offset, out, blk->checksum); - if (err) - return err; - - err = proc->file->write_at(proc->file, offset, - blk->data, blk->size); - if (err) - return err; - } - - if (proc->hooks != NULL && proc->hooks->post_block_write != NULL) { - proc->hooks->post_block_write(proc->user_ptr, blk, proc->file); } - if (blk->flags & SQFS_BLK_LAST_BLOCK) { - err = align_file(proc, blk); - if (err) - return err; - - count = proc->num_blocks - proc->file_start; - start = deduplicate_blocks(proc, count); - offset = proc->blocks[start].offset; - - sqfs_inode_set_file_block_start(blk->inode, offset); - - if (start >= proc->file_start) - return 0; - - offset = start + count; - if (offset >= proc->file_start) { - count = proc->num_blocks - offset; - proc->num_blocks = offset; - } else { - proc->num_blocks = proc->file_start; - } - - if (proc->hooks != NULL && - proc->hooks->notify_blocks_erased != NULL) { - bytes = proc->file->get_size(proc->file) - proc->start; - - proc->hooks->notify_blocks_erased(proc->user_ptr, - count, bytes); - } - - err = proc->file->truncate(proc->file, proc->start); - if (err) - return err; - } + if (blk->flags & SQFS_BLK_LAST_BLOCK) + sqfs_inode_set_file_block_start(blk->inode, location); return 0; } |