diff options
Diffstat (limited to 'unpack')
| -rw-r--r-- | unpack/Makemodule.am | 3 | ||||
| -rw-r--r-- | unpack/rdsquashfs.c | 14 | ||||
| -rw-r--r-- | unpack/rdsquashfs.h | 20 | ||||
| -rw-r--r-- | unpack/read_fstree.c | 184 | ||||
| -rw-r--r-- | unpack/tree_node_from_inode.c | 143 | 
5 files changed, 14 insertions, 350 deletions
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 <stdio.h>  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; -}  | 
