From 6f7ee71165b30272a4f18bca361c324c7671680c Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 3 May 2019 23:33:41 +0200 Subject: unsquashfs: add flags to filter what file types to unpack This allows the user to skip stuff like device special files (which non-root can't create anyway) or to not create symlinks/fifos etc... Signed-off-by: David Oberhollenzer --- unpack/read_fstree.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 6 deletions(-) (limited to 'unpack/read_fstree.c') diff --git a/unpack/read_fstree.c b/unpack/read_fstree.c index a6903b0..f200243 100644 --- a/unpack/read_fstree.c +++ b/unpack/read_fstree.c @@ -2,15 +2,36 @@ #include "unsquashfs.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) + 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; - tree_node_t *n; uint32_t i; block_start = root->data.dir->start_block; @@ -35,6 +56,11 @@ static int fill_dir(meta_reader_t *ir, meta_reader_t *dr, tree_node_t *root, 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); @@ -58,17 +84,38 @@ static int fill_dir(meta_reader_t *ir, meta_reader_t *dr, tree_node_t *root, } } - for (n = root->data.dir->children; n != NULL; n = n->next) { + n = root->data.dir->children; + prev = NULL; + + while (n != NULL) { if (S_ISDIR(n->mode)) { - if (fill_dir(ir, dr, n, super, idtbl)) + 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, int fd, sqfs_super_t *super, compressor_t *cmp) +int read_fstree(fstree_t *out, int fd, sqfs_super_t *super, compressor_t *cmp, + int flags) { sqfs_inode_generic_t *root; meta_reader_t *ir, *dr; @@ -119,7 +166,7 @@ int read_fstree(fstree_t *out, int fd, sqfs_super_t *super, compressor_t *cmp) if (out->root == NULL) goto out_id; - if (fill_dir(ir, dr, out->root, super, &idtbl)) + if (fill_dir(ir, dr, out->root, super, &idtbl, flags)) goto fail_fs; fstree_sort(out); -- cgit v1.2.3