From 428aa363dd2b44756a5b16aa17e8c2030de801a0 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 15 Sep 2019 20:40:01 +0200 Subject: Move condensed-sparse-file handling to libsquashfs Add another helper function for getting a blocks from a condensed sparse file, then rewrite the data writer to use that instead, using an sqfs_file_t pointer instead of direct file i/o. Signed-off-by: David Oberhollenzer --- lib/sqfs/io.c | 66 ++++++++++++++++++++++++++++++++++++ lib/sqfshelper/data_writer.c | 80 ++++---------------------------------------- 2 files changed, 73 insertions(+), 73 deletions(-) (limited to 'lib') diff --git a/lib/sqfs/io.c b/lib/sqfs/io.c index 4afb489..b41fc4a 100644 --- a/lib/sqfs/io.c +++ b/lib/sqfs/io.c @@ -37,3 +37,69 @@ int sqfs_file_create_block(sqfs_file_t *file, uint64_t offset, *out = blk; return 0; } + +int sqfs_file_create_block_dense(sqfs_file_t *file, uint64_t offset, + size_t size, void *user, uint32_t flags, + const sqfs_sparse_map_t *map, + sqfs_block_t **out) +{ + sqfs_block_t *blk = alloc_flex(sizeof(*blk), 1, size); + size_t dst_start, diff, count; + const sqfs_sparse_map_t *it; + uint64_t poffset, src_start; + int err; + + if (blk == NULL) + return SQFS_ERROR_ALLOC; + + poffset = 0; + + for (it = map; it != NULL; it = it->next) { + if (it->offset + it->count <= offset) { + poffset += it->count; + continue; + } + + if (it->offset >= offset + size) { + poffset += it->count; + continue; + } + + count = size; + + if (offset + count >= it->offset + it->count) + count = it->offset + it->count - offset; + + if (it->offset < offset) { + diff = offset - it->offset; + + src_start = poffset + diff; + dst_start = 0; + count -= diff; + } else if (it->offset > offset) { + diff = it->offset - offset; + + src_start = poffset; + dst_start = diff; + } else { + src_start = poffset; + dst_start = 0; + } + + err = file->read_at(file, src_start, + blk->data + dst_start, count); + if (err) { + free(blk); + return err; + } + + poffset += it->count; + } + + blk->user = user; + blk->size = size; + blk->flags = flags; + + *out = blk; + return 0; +} diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index a6d0297..92592c9 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -390,77 +390,15 @@ int write_data_from_file(data_writer_t *data, file_info_t *fi, return 0; } -static int check_map_valid(const sqfs_sparse_map_t *map, file_info_t *fi) -{ - const sqfs_sparse_map_t *m; - uint64_t offset; - - if (map != NULL) { - offset = map->offset; - - for (m = map; m != NULL; m = m->next) { - if (m->offset < offset) - goto fail_map; - offset = m->offset + m->count; - } - - if (offset > fi->size) - goto fail_map_size; - } - - return 0; -fail_map_size: - fprintf(stderr, "%s: sparse file map spans beyond file size\n", - fi->input_file); - return -1; -fail_map: - fprintf(stderr, - "%s: sparse file map is unordered or self overlapping\n", - fi->input_file); - return -1; -} - -static int get_sparse_block(sqfs_block_t *blk, file_info_t *fi, int infd, - sqfs_sparse_map_t **sparse_map, uint64_t offset, - size_t diff) -{ - sqfs_sparse_map_t *map = *sparse_map; - size_t start, count; - - while (map != NULL && map->offset < offset + diff) { - start = 0; - count = map->count; - - if (map->offset < offset) - count -= offset - map->offset; - - if (map->offset > offset) - start = map->offset - offset; - - if (start + count > diff) - count = diff - start; - - if (read_data(fi->input_file, infd, blk->data + start, count)) - return -1; - - map = map->next; - } - - *sparse_map = map; - return 0; -} - -int write_data_from_fd_condensed(data_writer_t *data, file_info_t *fi, - int infd, sqfs_sparse_map_t *map, int flags) +int write_data_from_file_condensed(data_writer_t *data, sqfs_file_t *file, + file_info_t *fi, + const sqfs_sparse_map_t *map, int flags) { uint32_t blk_flags = BLK_FIRST_BLOCK; size_t diff, i = 0; sqfs_block_t *blk; uint64_t offset; - if (check_map_valid(map, fi)) - return -1; - if (flags & DW_DONT_COMPRESS) blk_flags |= SQFS_BLK_DONT_COMPRESS; @@ -474,17 +412,13 @@ int write_data_from_fd_condensed(data_writer_t *data, file_info_t *fi, diff = fi->size - offset; } - blk = alloc_flex(sizeof(*blk), 1, diff); - blk->size = diff; - blk->index = i++; - blk->user = fi; - blk->flags = blk_flags; - - if (get_sparse_block(blk, fi, infd, &map, offset, diff)) { - free(blk); + if (sqfs_file_create_block_dense(file, offset, diff, fi, + blk_flags, map, &blk)) { return -1; } + blk->index = i++; + if (is_zero_block(blk->data, blk->size)) { data->stats.sparse_blocks += 1; -- cgit v1.2.3