diff options
Diffstat (limited to 'lib/sqfshelper')
-rw-r--r-- | lib/sqfshelper/data_writer.c | 217 |
1 files changed, 7 insertions, 210 deletions
diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index 461cb55..f5e22f3 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -26,11 +26,6 @@ #define INIT_BLOCK_COUNT (128) typedef struct { - uint64_t offset; - uint64_t signature; -} blk_info_t; - -typedef struct { uint32_t index; uint32_t offset; uint64_t signature; @@ -38,22 +33,11 @@ typedef struct { struct data_writer_t { sqfs_block_t *frag_block; - sqfs_fragment_t *fragments; size_t num_fragments; - size_t max_fragments; - - size_t devblksz; - uint64_t start; sqfs_block_processor_t *proc; sqfs_compressor_t *cmp; sqfs_super_t *super; - sqfs_file_t *file; - - size_t file_start; - size_t num_blocks; - size_t max_blocks; - blk_info_t *blocks; size_t frag_list_num; size_t frag_list_max; @@ -62,163 +46,6 @@ struct data_writer_t { data_writer_stats_t stats; }; -static int allign_file(data_writer_t *data) -{ - return padd_sqfs(data->file, data->file->get_size(data->file), - data->devblksz); -} - -static int store_block_location(data_writer_t *data, uint64_t offset, - uint32_t size, uint32_t chksum) -{ - size_t new_sz; - void *new; - - if (data->num_blocks == data->max_blocks) { - new_sz = data->max_blocks * 2; - new = realloc(data->blocks, sizeof(data->blocks[0]) * new_sz); - - if (new == NULL) { - perror("growing data block checksum table"); - return -1; - } - - data->blocks = new; - data->max_blocks = new_sz; - } - - data->blocks[data->num_blocks].offset = offset; - data->blocks[data->num_blocks].signature = MK_BLK_SIG(chksum, size); - data->num_blocks += 1; - return 0; -} - -static size_t deduplicate_blocks(data_writer_t *data, size_t count) -{ - size_t i, j; - - for (i = 0; i < data->file_start; ++i) { - for (j = 0; j < count; ++j) { - if (data->blocks[i + j].signature != - data->blocks[data->file_start + j].signature) - break; - } - - if (j == count) - break; - } - - return i; -} - -static size_t grow_fragment_table(data_writer_t *data, size_t index) -{ - size_t newsz; - void *new; - - if (index < data->max_fragments) - return 0; - - do { - newsz = data->max_fragments ? data->max_fragments * 2 : 16; - } while (index >= newsz); - - new = realloc(data->fragments, sizeof(data->fragments[0]) * newsz); - - if (new == NULL) { - perror("appending to fragment table"); - return -1; - } - - data->max_fragments = newsz; - data->fragments = new; - return 0; -} - -static int block_callback(void *user, sqfs_block_t *blk) -{ - data_writer_t *data = user; - size_t start, count; - uint64_t offset; - uint32_t out; - - if (blk->flags & SQFS_BLK_FIRST_BLOCK) { - data->start = data->file->get_size(data->file); - data->file_start = data->num_blocks; - - if ((blk->flags & SQFS_BLK_ALLIGN) && allign_file(data) != 0) - return -1; - } - - if (blk->size != 0) { - out = blk->size; - if (!(blk->flags & SQFS_BLK_IS_COMPRESSED)) - out |= 1 << 24; - - offset = data->file->get_size(data->file); - - if (blk->flags & SQFS_BLK_FRAGMENT_BLOCK) { - if (grow_fragment_table(data, blk->index)) - return 0; - - data->fragments[blk->index].start_offset = htole64(offset); - data->fragments[blk->index].pad0 = 0; - data->fragments[blk->index].size = htole32(out); - - data->super->flags &= ~SQFS_FLAG_NO_FRAGMENTS; - data->super->flags |= SQFS_FLAG_ALWAYS_FRAGMENTS; - - data->stats.frag_blocks_written += 1; - } else { - blk->inode->block_sizes[blk->index] = htole32(out); - - data->stats.blocks_written += 1; - } - - if (store_block_location(data, offset, out, blk->checksum)) - return -1; - - if (data->file->write_at(data->file, offset, - blk->data, blk->size)) { - return -1; - } - } - - if (blk->flags & SQFS_BLK_LAST_BLOCK) { - if ((blk->flags & SQFS_BLK_ALLIGN) && allign_file(data) != 0) - return -1; - - count = data->num_blocks - data->file_start; - start = deduplicate_blocks(data, count); - offset = data->blocks[start].offset; - - sqfs_inode_set_file_block_start(blk->inode, offset); - - if (start < data->file_start) { - offset = start + count; - - if (offset >= data->file_start) { - data->num_blocks = offset; - data->stats.duplicate_blocks += - offset - data->num_blocks; - } else { - data->num_blocks = data->file_start; - data->stats.duplicate_blocks += count; - } - - if (data->file->truncate(data->file, data->start)) { - perror("truncating squashfs image after " - "file deduplication"); - return -1; - } - } - } - - return 0; -} - -/*****************************************************************************/ - static int flush_fragment_block(data_writer_t *data) { int ret; @@ -435,74 +262,44 @@ data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp, return NULL; } - data->max_blocks = INIT_BLOCK_COUNT; data->frag_list_max = INIT_BLOCK_COUNT; - - data->blocks = alloc_array(sizeof(data->blocks[0]), - data->max_blocks); - - if (data->blocks == NULL) { - perror("creating data writer"); - free(data); - return NULL; - } - data->frag_list = alloc_array(sizeof(data->frag_list[0]), data->frag_list_max); - if (data->frag_list == NULL) { perror("creating data writer"); - free(data->blocks); free(data); return NULL; } data->proc = sqfs_block_processor_create(super->block_size, cmp, - num_jobs, max_backlog, data, - block_callback); + num_jobs, max_backlog, + devblksize, file); if (data->proc == NULL) { perror("creating data block processor"); free(data->frag_list); - free(data->blocks); free(data); return NULL; } data->cmp = cmp; data->super = super; - data->file = file; - data->devblksz = devblksize; return data; } void data_writer_destroy(data_writer_t *data) { sqfs_block_processor_destroy(data->proc); - free(data->fragments); - free(data->blocks); + free(data->frag_list); free(data); } int data_writer_write_fragment_table(data_writer_t *data) { - uint64_t start; - size_t size; - int ret; - - if (data->num_fragments == 0) { - data->super->fragment_entry_count = 0; - data->super->fragment_table_start = 0xFFFFFFFFFFFFFFFFUL; - return 0; - } - - size = sizeof(data->fragments[0]) * data->num_fragments; - ret = sqfs_write_table(data->file, data->cmp, - data->fragments, size, &start); - if (ret) + if (sqfs_block_processor_write_fragment_table(data->proc, + data->super)) { + fputs("error storing fragment table\n", stderr); return -1; - - data->super->fragment_entry_count = data->num_fragments; - data->super->fragment_table_start = start; + } return 0; } |