aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/io.c')
-rw-r--r--lib/sqfs/io.c66
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;
+}