From 576e195ba5476ebf428bac51365d829d713e6907 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Mon, 10 Jun 2019 23:16:34 +0200 Subject: cleanup: move tree deserialization to libsqfs.a Signed-off-by: David Oberhollenzer --- include/highlevel.h | 27 ++++++ lib/Makemodule.am | 2 + lib/sqfs/deserialize_fstree.c | 189 ++++++++++++++++++++++++++++++++++++++++ lib/sqfs/tree_node_from_inode.c | 147 +++++++++++++++++++++++++++++++ unpack/Makemodule.am | 3 +- unpack/rdsquashfs.c | 14 +-- unpack/rdsquashfs.h | 20 ++--- unpack/read_fstree.c | 184 -------------------------------------- unpack/tree_node_from_inode.c | 143 ------------------------------ 9 files changed, 379 insertions(+), 350 deletions(-) create mode 100644 lib/sqfs/deserialize_fstree.c create mode 100644 lib/sqfs/tree_node_from_inode.c delete mode 100644 unpack/read_fstree.c delete mode 100644 unpack/tree_node_from_inode.c diff --git a/include/highlevel.h b/include/highlevel.h index e69e337..f61ad0b 100644 --- a/include/highlevel.h +++ b/include/highlevel.h @@ -10,6 +10,14 @@ #include #include +enum RDTREE_FLAGS { + RDTREE_NO_DEVICES = 0x01, + RDTREE_NO_SOCKETS = 0x02, + RDTREE_NO_FIFO = 0x04, + RDTREE_NO_SLINKS = 0x08, + RDTREE_NO_EMPTY = 0x10, +}; + /* Convenience function for writing meta data to a SquashFS image @@ -40,4 +48,23 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, const void *data, int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, compressor_t *cmp, id_table_t *idtbl); +/* + Convert a generic squashfs tree node to an fstree_t node. + + Prints error messages to stderr on failure. + */ +tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, + const id_table_t *idtbl, + const char *name, + size_t block_size); + +/* + Restore a file system tree from a squashfs image. The given flags are a + combination of RDTREE_FLAGS. + + Returns 0 on success. Prints error messages to stderr on failure. + */ +int deserialize_fstree(fstree_t *out, sqfs_super_t *super, compressor_t *cmp, + int fd, int flags); + #endif /* HIGHLEVEL_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index ff63a7f..9496a9d 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -20,6 +20,8 @@ libsquashfs_a_SOURCES += lib/sqfs/id_table_read.c lib/sqfs/read_inode.c libsquashfs_a_SOURCES += lib/sqfs/readdir.c lib/sqfs/frag_reader.c libsquashfs_a_SOURCES += lib/sqfs/write_dir.c lib/sqfs/write_inode.c libsquashfs_a_SOURCES += lib/sqfs/serialize_fstree.c +libsquashfs_a_SOURCES += lib/sqfs/tree_node_from_inode.c +libsquashfs_a_SOURCES += lib/sqfs/deserialize_fstree.c libsquashfs_a_SOURCES += include/frag_reader.h libutil_a_SOURCES = lib/util/canonicalize_name.c lib/util/write_retry.c diff --git a/lib/sqfs/deserialize_fstree.c b/lib/sqfs/deserialize_fstree.c new file mode 100644 index 0000000..95dce98 --- /dev/null +++ b/lib/sqfs/deserialize_fstree.c @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "meta_reader.h" +#include "highlevel.h" + +#include +#include +#include + +static int should_skip(int type, int flags) +{ + switch (type) { + case SQFS_INODE_BDEV: + case SQFS_INODE_CDEV: + case SQFS_INODE_EXT_CDEV: + case SQFS_INODE_EXT_BDEV: + return (flags & RDTREE_NO_DEVICES); + case SQFS_INODE_SLINK: + case SQFS_INODE_EXT_SLINK: + return (flags & RDTREE_NO_SLINKS); + case SQFS_INODE_SOCKET: + case SQFS_INODE_EXT_SOCKET: + return(flags & RDTREE_NO_SOCKETS); + case SQFS_INODE_FIFO: + case SQFS_INODE_EXT_FIFO: + return (flags & RDTREE_NO_FIFO); + } + return 0; +} + +static int fill_dir(meta_reader_t *ir, meta_reader_t *dr, tree_node_t *root, + sqfs_super_t *super, id_table_t *idtbl, int flags) +{ + sqfs_inode_generic_t *inode; + sqfs_dir_header_t hdr; + sqfs_dir_entry_t *ent; + tree_node_t *n, *prev; + uint64_t block_start; + size_t size, diff; + uint32_t i; + + block_start = root->data.dir->start_block; + block_start += super->directory_table_start; + + if (meta_reader_seek(dr, block_start, root->data.dir->block_offset)) + return -1; + + size = root->data.dir->size; + + while (size != 0) { + if (meta_reader_read_dir_header(dr, &hdr)) + return -1; + + size -= sizeof(hdr) > size ? size : sizeof(hdr); + + for (i = 0; i <= hdr.count; ++i) { + ent = meta_reader_read_dir_ent(dr); + if (ent == NULL) + return -1; + + diff = sizeof(*ent) + strlen((char *)ent->name); + size -= diff > size ? size : diff; + + if (should_skip(ent->type, flags)) { + free(ent); + continue; + } + + inode = meta_reader_read_inode(ir, super, + hdr.start_block, + ent->offset); + if (inode == NULL) { + free(ent); + return -1; + } + + n = tree_node_from_inode(inode, idtbl, + (char *)ent->name, + super->block_size); + free(ent); + free(inode); + + if (n == NULL) + return -1; + + n->parent = root; + n->next = root->data.dir->children; + root->data.dir->children = n; + } + } + + n = root->data.dir->children; + prev = NULL; + + while (n != NULL) { + if (S_ISDIR(n->mode)) { + if (fill_dir(ir, dr, n, super, idtbl, flags)) + return -1; + + if (n->data.dir->children == NULL && + (flags & RDTREE_NO_EMPTY)) { + if (prev == NULL) { + root->data.dir->children = n->next; + free(n); + n = root->data.dir->children; + } else { + prev->next = n->next; + free(n); + n = prev->next; + } + continue; + } + } + + prev = n; + n = n->next; + } + + return 0; +} + +int deserialize_fstree(fstree_t *out, sqfs_super_t *super, compressor_t *cmp, + int fd, int flags) +{ + sqfs_inode_generic_t *root; + meta_reader_t *ir, *dr; + uint64_t block_start; + id_table_t idtbl; + int status = -1; + size_t offset; + + ir = meta_reader_create(fd, cmp); + if (ir == NULL) + return -1; + + dr = meta_reader_create(fd, cmp); + if (dr == NULL) + goto out_ir; + + if (id_table_init(&idtbl)) + goto out_dr; + + if (id_table_read(&idtbl, fd, super, cmp)) + goto out_id; + + block_start = super->root_inode_ref >> 16; + offset = super->root_inode_ref & 0xFFFF; + root = meta_reader_read_inode(ir, super, block_start, offset); + if (root == NULL) + goto out_id; + + if (root->base.type != SQFS_INODE_DIR && + root->base.type != SQFS_INODE_EXT_DIR) { + free(root); + fputs("File system root inode is not a directory inode!\n", + stderr); + goto out_id; + } + + memset(out, 0, sizeof(*out)); + out->block_size = super->block_size; + out->default_uid = 0; + out->default_gid = 0; + out->default_mode = 0755; + out->default_mtime = super->modification_time; + + out->root = tree_node_from_inode(root, &idtbl, "", super->block_size); + free(root); + root = NULL; + + if (out->root == NULL) + goto out_id; + + if (fill_dir(ir, dr, out->root, super, &idtbl, flags)) + goto fail_fs; + + fstree_sort(out); + + status = 0; +out_id: + id_table_cleanup(&idtbl); +out_dr: + meta_reader_destroy(dr); +out_ir: + meta_reader_destroy(ir); + return status; +fail_fs: + fstree_cleanup(out); + goto out_id; +} diff --git a/lib/sqfs/tree_node_from_inode.c b/lib/sqfs/tree_node_from_inode.c new file mode 100644 index 0000000..f9a6599 --- /dev/null +++ b/lib/sqfs/tree_node_from_inode.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "highlevel.h" + +#include +#include +#include + +static size_t compute_size(sqfs_inode_generic_t *inode, const char *name, + size_t block_size) +{ + size_t size = sizeof(tree_node_t) + strlen(name) + 1; + size_t block_count = 0; + + switch (inode->base.type) { + case SQFS_INODE_DIR: + case SQFS_INODE_EXT_DIR: + size += sizeof(dir_info_t); + break; + case SQFS_INODE_FILE: + size += sizeof(file_info_t); + block_count = inode->data.file.file_size / block_size; + break; + case SQFS_INODE_EXT_FILE: + size += sizeof(file_info_t); + block_count = inode->data.file_ext.file_size / block_size; + break; + case SQFS_INODE_SLINK: + case SQFS_INODE_EXT_SLINK: + size += strlen(inode->slink_target) + 1; + break; + default: + break; + } + + return size + block_count * sizeof(uint32_t); +} + +static void copy_block_sizes(sqfs_inode_generic_t *inode, tree_node_t *out, + size_t block_size) +{ + size_t block_count = out->data.file->size / block_size; + + out->name += block_count * sizeof(uint32_t); + + if (block_count) { + memcpy(out->data.file->blocksizes, inode->block_sizes, + block_count * sizeof(uint32_t)); + } +} + +tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, + const id_table_t *idtbl, + const char *name, + size_t block_size) +{ + tree_node_t *out; + + if (inode->base.uid_idx >= idtbl->num_ids) { + fputs("converting inode to fs tree node: UID out of range\n", + stderr); + return NULL; + } + + if (inode->base.gid_idx >= idtbl->num_ids) { + fputs("converting inode to fs tree node: GID out of range\n", + stderr); + return NULL; + } + + out = calloc(1, compute_size(inode, name, block_size)); + if (out == NULL) { + perror("converting inode to fs tree node"); + return NULL; + } + + out->uid = idtbl->ids[inode->base.uid_idx]; + out->gid = idtbl->ids[inode->base.gid_idx]; + out->mode = inode->base.mode; + out->inode_num = inode->base.inode_number; + out->name = (char *)out->payload; + + switch (inode->base.type) { + case SQFS_INODE_DIR: + out->data.dir = (dir_info_t *)out->payload; + out->name += sizeof(dir_info_t); + + out->data.dir->size = inode->data.dir.size; + out->data.dir->start_block = inode->data.dir.start_block; + out->data.dir->block_offset = inode->data.dir.offset; + break; + case SQFS_INODE_EXT_DIR: + out->data.dir = (dir_info_t *)out->payload; + out->name += sizeof(dir_info_t); + + out->data.dir->size = inode->data.dir_ext.size; + out->data.dir->start_block = inode->data.dir_ext.start_block; + out->data.dir->block_offset = inode->data.dir_ext.offset; + break; + case SQFS_INODE_FILE: + out->data.file = (file_info_t *)out->payload; + out->name += sizeof(file_info_t); + + out->data.file->size = inode->data.file.file_size; + out->data.file->startblock = inode->data.file.blocks_start; + out->data.file->fragment = inode->data.file.fragment_index; + out->data.file->fragment_offset = + inode->data.file.fragment_offset; + + copy_block_sizes(inode, out, block_size); + break; + case SQFS_INODE_EXT_FILE: + out->data.file = (file_info_t *)out->payload; + out->name += sizeof(file_info_t); + + out->data.file->size = inode->data.file_ext.file_size; + out->data.file->startblock = inode->data.file_ext.blocks_start; + out->data.file->fragment = inode->data.file_ext.fragment_idx; + out->data.file->fragment_offset = + inode->data.file_ext.fragment_offset; + + copy_block_sizes(inode, out, block_size); + break; + case SQFS_INODE_SLINK: + case SQFS_INODE_EXT_SLINK: + out->data.slink_target = (char *)out->payload; + strcpy(out->data.slink_target, inode->slink_target); + + out->name = (char *)out->payload + + strlen(inode->slink_target) + 1; + break; + case SQFS_INODE_BDEV: + case SQFS_INODE_CDEV: + out->name = (char *)out->payload; + out->data.devno = inode->data.dev.devno; + break; + case SQFS_INODE_EXT_BDEV: + case SQFS_INODE_EXT_CDEV: + out->name = (char *)out->payload; + out->data.devno = inode->data.dev_ext.devno; + break; + default: + break; + } + + strcpy(out->name, name); + return out; +} diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am index 6829681..5f4269e 100644 --- a/unpack/Makemodule.am +++ b/unpack/Makemodule.am @@ -1,5 +1,4 @@ -rdsquashfs_SOURCES = unpack/rdsquashfs.c unpack/tree_node_from_inode.c -rdsquashfs_SOURCES += unpack/rdsquashfs.h unpack/read_fstree.c +rdsquashfs_SOURCES = unpack/rdsquashfs.c unpack/rdsquashfs.h rdsquashfs_SOURCES += unpack/list_files.c unpack/extract_file.c rdsquashfs_SOURCES += unpack/restore_fstree.c unpack/describe.c rdsquashfs_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index 11f0a32..81da226 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -177,16 +177,16 @@ int main(int argc, char **argv) switch (i) { case 'D': - info.flags |= UNPACK_NO_DEVICES; + info.rdtree_flags |= RDTREE_NO_DEVICES; break; case 'S': - info.flags |= UNPACK_NO_SOCKETS; + info.rdtree_flags |= RDTREE_NO_SOCKETS; break; case 'F': - info.flags |= UNPACK_NO_FIFO; + info.rdtree_flags |= RDTREE_NO_FIFO; break; case 'L': - info.flags |= UNPACK_NO_SLINKS; + info.rdtree_flags |= RDTREE_NO_SLINKS; break; case 'C': info.flags |= UNPACK_CHMOD; @@ -195,7 +195,7 @@ int main(int argc, char **argv) info.flags |= UNPACK_CHOWN; break; case 'E': - info.flags |= UNPACK_NO_EMPTY; + info.rdtree_flags |= RDTREE_NO_EMPTY; break; case 'c': op = OP_CAT; @@ -276,8 +276,10 @@ int main(int argc, char **argv) goto out_cmp; } - if (read_fstree(&fs, &super, &info)) + if (deserialize_fstree(&fs, &super, info.cmp, + info.sqfsfd, info.rdtree_flags)) { goto out_cmp; + } info.block_size = super.block_size; diff --git a/unpack/rdsquashfs.h b/unpack/rdsquashfs.h index f1cd131..a615bb5 100644 --- a/unpack/rdsquashfs.h +++ b/unpack/rdsquashfs.h @@ -4,6 +4,7 @@ #include "meta_reader.h" #include "frag_reader.h" +#include "highlevel.h" #include "squashfs.h" #include "compress.h" #include "id_table.h" @@ -20,20 +21,16 @@ #include enum UNPACK_FLAGS { - UNPACK_NO_DEVICES = 0x01, - UNPACK_NO_SOCKETS = 0x02, - UNPACK_NO_FIFO = 0x04, - UNPACK_NO_SLINKS = 0x08, - UNPACK_NO_EMPTY = 0x10, - UNPACK_CHMOD = 0x20, - UNPACK_CHOWN = 0x40, - UNPACK_QUIET = 0x80, + UNPACK_CHMOD = 0x01, + UNPACK_CHOWN = 0x02, + UNPACK_QUIET = 0x04, }; typedef struct { compressor_t *cmp; size_t block_size; frag_reader_t *frag; + int rdtree_flags; int sqfsfd; int flags; @@ -41,13 +38,6 @@ typedef struct { void *scratch; } unsqfs_info_t; -tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, - const id_table_t *idtbl, - const char *name, - size_t block_size); - -int read_fstree(fstree_t *out, sqfs_super_t *super, unsqfs_info_t *info); - void list_files(tree_node_t *node); int extract_file(file_info_t *fi, unsqfs_info_t *info, int outfd); diff --git a/unpack/read_fstree.c b/unpack/read_fstree.c deleted file mode 100644 index 544af83..0000000 --- a/unpack/read_fstree.c +++ /dev/null @@ -1,184 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -#include "rdsquashfs.h" - - -static int should_skip(int type, int flags) -{ - switch (type) { - case SQFS_INODE_BDEV: - case SQFS_INODE_CDEV: - case SQFS_INODE_EXT_CDEV: - case SQFS_INODE_EXT_BDEV: - return (flags & UNPACK_NO_DEVICES); - case SQFS_INODE_SLINK: - case SQFS_INODE_EXT_SLINK: - return (flags & UNPACK_NO_SLINKS); - case SQFS_INODE_SOCKET: - case SQFS_INODE_EXT_SOCKET: - return(flags & UNPACK_NO_SOCKETS); - case SQFS_INODE_FIFO: - case SQFS_INODE_EXT_FIFO: - return (flags & UNPACK_NO_FIFO); - } - return 0; -} - -static int fill_dir(meta_reader_t *ir, meta_reader_t *dr, tree_node_t *root, - sqfs_super_t *super, id_table_t *idtbl, int flags) -{ - sqfs_inode_generic_t *inode; - sqfs_dir_header_t hdr; - sqfs_dir_entry_t *ent; - tree_node_t *n, *prev; - uint64_t block_start; - size_t size, diff; - uint32_t i; - - block_start = root->data.dir->start_block; - block_start += super->directory_table_start; - - if (meta_reader_seek(dr, block_start, root->data.dir->block_offset)) - return -1; - - size = root->data.dir->size; - - while (size != 0) { - if (meta_reader_read_dir_header(dr, &hdr)) - return -1; - - size -= sizeof(hdr) > size ? size : sizeof(hdr); - - for (i = 0; i <= hdr.count; ++i) { - ent = meta_reader_read_dir_ent(dr); - if (ent == NULL) - return -1; - - diff = sizeof(*ent) + strlen((char *)ent->name); - size -= diff > size ? size : diff; - - if (should_skip(ent->type, flags)) { - free(ent); - continue; - } - - inode = meta_reader_read_inode(ir, super, - hdr.start_block, - ent->offset); - if (inode == NULL) { - free(ent); - return -1; - } - - n = tree_node_from_inode(inode, idtbl, - (char *)ent->name, - super->block_size); - free(ent); - free(inode); - - if (n == NULL) - return -1; - - n->parent = root; - n->next = root->data.dir->children; - root->data.dir->children = n; - } - } - - n = root->data.dir->children; - prev = NULL; - - while (n != NULL) { - if (S_ISDIR(n->mode)) { - if (fill_dir(ir, dr, n, super, idtbl, flags)) - return -1; - - if (n->data.dir->children == NULL && - (flags & UNPACK_NO_EMPTY)) { - if (prev == NULL) { - root->data.dir->children = n->next; - free(n); - n = root->data.dir->children; - } else { - prev->next = n->next; - free(n); - n = prev->next; - } - continue; - } - } - - prev = n; - n = n->next; - } - - return 0; -} - -int read_fstree(fstree_t *out, sqfs_super_t *super, unsqfs_info_t *info) -{ - sqfs_inode_generic_t *root; - meta_reader_t *ir, *dr; - uint64_t block_start; - id_table_t idtbl; - int status = -1; - size_t offset; - - ir = meta_reader_create(info->sqfsfd, info->cmp); - if (ir == NULL) - return -1; - - dr = meta_reader_create(info->sqfsfd, info->cmp); - if (dr == NULL) - goto out_ir; - - if (id_table_init(&idtbl)) - goto out_dr; - - if (id_table_read(&idtbl, info->sqfsfd, super, info->cmp)) - goto out_id; - - block_start = super->root_inode_ref >> 16; - offset = super->root_inode_ref & 0xFFFF; - root = meta_reader_read_inode(ir, super, block_start, offset); - if (root == NULL) - goto out_id; - - if (root->base.type != SQFS_INODE_DIR && - root->base.type != SQFS_INODE_EXT_DIR) { - free(root); - fputs("File system root inode is not a directory inode!\n", - stderr); - goto out_id; - } - - memset(out, 0, sizeof(*out)); - out->block_size = super->block_size; - out->default_uid = 0; - out->default_gid = 0; - out->default_mode = 0755; - out->default_mtime = super->modification_time; - - out->root = tree_node_from_inode(root, &idtbl, "", super->block_size); - free(root); - root = NULL; - - if (out->root == NULL) - goto out_id; - - if (fill_dir(ir, dr, out->root, super, &idtbl, info->flags)) - goto fail_fs; - - fstree_sort(out); - - status = 0; -out_id: - id_table_cleanup(&idtbl); -out_dr: - meta_reader_destroy(dr); -out_ir: - meta_reader_destroy(ir); - return status; -fail_fs: - fstree_cleanup(out); - goto out_id; -} diff --git a/unpack/tree_node_from_inode.c b/unpack/tree_node_from_inode.c deleted file mode 100644 index 0fd7da1..0000000 --- a/unpack/tree_node_from_inode.c +++ /dev/null @@ -1,143 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-or-later */ -#include "rdsquashfs.h" - -static size_t compute_size(sqfs_inode_generic_t *inode, const char *name, - size_t block_size) -{ - size_t size = sizeof(tree_node_t) + strlen(name) + 1; - size_t block_count = 0; - - switch (inode->base.type) { - case SQFS_INODE_DIR: - case SQFS_INODE_EXT_DIR: - size += sizeof(dir_info_t); - break; - case SQFS_INODE_FILE: - size += sizeof(file_info_t); - block_count = inode->data.file.file_size / block_size; - break; - case SQFS_INODE_EXT_FILE: - size += sizeof(file_info_t); - block_count = inode->data.file_ext.file_size / block_size; - break; - case SQFS_INODE_SLINK: - case SQFS_INODE_EXT_SLINK: - size += strlen(inode->slink_target) + 1; - break; - default: - break; - } - - return size + block_count * sizeof(uint32_t); -} - -static void copy_block_sizes(sqfs_inode_generic_t *inode, tree_node_t *out, - size_t block_size) -{ - size_t block_count = out->data.file->size / block_size; - - out->name += block_count * sizeof(uint32_t); - - if (block_count) { - memcpy(out->data.file->blocksizes, inode->block_sizes, - block_count * sizeof(uint32_t)); - } -} - -tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, - const id_table_t *idtbl, - const char *name, - size_t block_size) -{ - tree_node_t *out; - - if (inode->base.uid_idx >= idtbl->num_ids) { - fputs("converting inode to fs tree node: UID out of range\n", - stderr); - return NULL; - } - - if (inode->base.gid_idx >= idtbl->num_ids) { - fputs("converting inode to fs tree node: GID out of range\n", - stderr); - return NULL; - } - - out = calloc(1, compute_size(inode, name, block_size)); - if (out == NULL) { - perror("converting inode to fs tree node"); - return NULL; - } - - out->uid = idtbl->ids[inode->base.uid_idx]; - out->gid = idtbl->ids[inode->base.gid_idx]; - out->mode = inode->base.mode; - out->inode_num = inode->base.inode_number; - out->name = (char *)out->payload; - - switch (inode->base.type) { - case SQFS_INODE_DIR: - out->data.dir = (dir_info_t *)out->payload; - out->name += sizeof(dir_info_t); - - out->data.dir->size = inode->data.dir.size; - out->data.dir->start_block = inode->data.dir.start_block; - out->data.dir->block_offset = inode->data.dir.offset; - break; - case SQFS_INODE_EXT_DIR: - out->data.dir = (dir_info_t *)out->payload; - out->name += sizeof(dir_info_t); - - out->data.dir->size = inode->data.dir_ext.size; - out->data.dir->start_block = inode->data.dir_ext.start_block; - out->data.dir->block_offset = inode->data.dir_ext.offset; - break; - case SQFS_INODE_FILE: - out->data.file = (file_info_t *)out->payload; - out->name += sizeof(file_info_t); - - out->data.file->size = inode->data.file.file_size; - out->data.file->startblock = inode->data.file.blocks_start; - out->data.file->fragment = inode->data.file.fragment_index; - out->data.file->fragment_offset = - inode->data.file.fragment_offset; - - copy_block_sizes(inode, out, block_size); - break; - case SQFS_INODE_EXT_FILE: - out->data.file = (file_info_t *)out->payload; - out->name += sizeof(file_info_t); - - out->data.file->size = inode->data.file_ext.file_size; - out->data.file->startblock = inode->data.file_ext.blocks_start; - out->data.file->fragment = inode->data.file_ext.fragment_idx; - out->data.file->fragment_offset = - inode->data.file_ext.fragment_offset; - - copy_block_sizes(inode, out, block_size); - break; - case SQFS_INODE_SLINK: - case SQFS_INODE_EXT_SLINK: - out->data.slink_target = (char *)out->payload; - strcpy(out->data.slink_target, inode->slink_target); - - out->name = (char *)out->payload + - strlen(inode->slink_target) + 1; - break; - case SQFS_INODE_BDEV: - case SQFS_INODE_CDEV: - out->name = (char *)out->payload; - out->data.devno = inode->data.dev.devno; - break; - case SQFS_INODE_EXT_BDEV: - case SQFS_INODE_EXT_CDEV: - out->name = (char *)out->payload; - out->data.devno = inode->data.dev_ext.devno; - break; - default: - break; - } - - strcpy(out->name, name); - return out; -} -- cgit v1.2.3