diff options
Diffstat (limited to 'lib/sqfs/write_table.c')
-rw-r--r-- | lib/sqfs/write_table.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/lib/sqfs/write_table.c b/lib/sqfs/write_table.c index fc90a3f..23ba5a8 100644 --- a/lib/sqfs/write_table.c +++ b/lib/sqfs/write_table.c @@ -6,56 +6,69 @@ #include "util.h" #include <endian.h> +#include <stdlib.h> #include <stdio.h> -int sqfs_write_table(int outfd, sqfs_super_t *super, const void *data, - size_t entsize, size_t count, uint64_t *startblock, - compressor_t *cmp) +int sqfs_write_table(int outfd, sqfs_super_t *super, compressor_t *cmp, + const void *data, size_t table_size, uint64_t *start) { - size_t ent_per_blocks = SQFS_META_BLOCK_SIZE / entsize; - uint64_t blocks[count / ent_per_blocks + 1], block; - size_t i, blkidx = 0, tblsize; + size_t block_count, list_size, diff, blkidx = 0; + uint64_t block, *locations; meta_writer_t *m; uint32_t offset; + int ret = -1; - /* Write actual data. Whenever we cross a block boundary, remember - the block start offset */ + block_count = table_size / SQFS_META_BLOCK_SIZE; + if ((table_size % SQFS_META_BLOCK_SIZE) != 0) + ++block_count; + + list_size = sizeof(uint64_t) * block_count; + locations = malloc(list_size); + + if (locations == NULL) { + perror("writing table"); + return -1; + } + + /* Write actual data */ m = meta_writer_create(outfd, cmp, false); if (m == NULL) - return -1; + goto out_idx; - for (i = 0; i < count; ++i) { + while (table_size > 0) { meta_writer_get_position(m, &block, &offset); + locations[blkidx++] = htole64(super->bytes_used + block); - if (blkidx == 0 || block > blocks[blkidx - 1]) - blocks[blkidx++] = block; + diff = SQFS_META_BLOCK_SIZE; + if (diff > table_size) + diff = table_size; - if (meta_writer_append(m, data, entsize)) - goto fail; + if (meta_writer_append(m, data, diff)) + goto out; - data = (const char *)data + entsize; + data = (const char *)data + diff; + table_size -= diff; } if (meta_writer_flush(m)) - goto fail; - - for (i = 0; i < blkidx; ++i) - blocks[i] = htole64(blocks[i] + super->bytes_used); + goto out; meta_writer_get_position(m, &block, &offset); super->bytes_used += block; - meta_writer_destroy(m); - /* write new index table */ - *startblock = super->bytes_used; - tblsize = sizeof(blocks[0]) * blkidx; + /* write location list */ + *start = super->bytes_used; - if (write_data("writing table index", outfd, blocks, tblsize)) - return -1; + if (write_data("writing table locations", outfd, locations, list_size)) + goto out; + + super->bytes_used += list_size; - super->bytes_used += tblsize; - return 0; -fail: + /* cleanup */ + ret = 0; +out: meta_writer_destroy(m); - return -1; +out_idx: + free(locations); + return ret; } |