diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-15 20:40:01 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-15 20:44:41 +0200 |
commit | 428aa363dd2b44756a5b16aa17e8c2030de801a0 (patch) | |
tree | 8bc507fdcc795a5c75ef7a148e66e940d4df91b9 /lib/sqfs/io.c | |
parent | 129e1758a5e2cf851f042e139fdd808a9be9ce94 (diff) |
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 <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs/io.c')
-rw-r--r-- | lib/sqfs/io.c | 66 |
1 files changed, 66 insertions, 0 deletions
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; +} |