diff options
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/Makemodule.am | 5 | ||||
| -rw-r--r-- | extras/list_files.c | 145 | 
2 files changed, 149 insertions, 1 deletions
| diff --git a/extras/Makemodule.am b/extras/Makemodule.am index 77d734e..b7882eb 100644 --- a/extras/Makemodule.am +++ b/extras/Makemodule.am @@ -4,4 +4,7 @@ mknastyfs_LDADD = libsquashfs.la  mk42sqfs_SOURCES = extras/mk42sqfs.c  mk42sqfs_LDADD = libsquashfs.la -noinst_PROGRAMS += mknastyfs mk42sqfs +list_files_SOURCES = extras/list_files.c +list_files_LDADD = libsquashfs.la + +noinst_PROGRAMS += mknastyfs mk42sqfs list_files diff --git a/extras/list_files.c b/extras/list_files.c new file mode 100644 index 0000000..3f6725a --- /dev/null +++ b/extras/list_files.c @@ -0,0 +1,145 @@ +#include "sqfs/compressor.h" +#include "sqfs/dir_reader.h" +#include "sqfs/id_table.h" +#include "sqfs/inode.h" +#include "sqfs/super.h" +#include "sqfs/io.h" + +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> + +static void write_tree_dfs(const sqfs_tree_node_t *n) +{ +	const sqfs_tree_node_t *p; +	unsigned int mask, level; +	int i; + +	for (n = n->children; n != NULL; n = n->next) { +		level = 0; +		mask = 0; + +		for (p = n->parent; p->parent != NULL; p = p->parent) { +			if (p->next != NULL) +				mask |= 1 << level; +			++level; +		} + +		for (i = level - 1; i >= 0; --i) +			fputs(mask & (1 << i) ? "│  " : "   ", stdout); + +		fputs(n->next == NULL ? "└─ " : "├─ ", stdout); +		fputs((const char *)n->name, stdout); + +		if (n->inode->base.type == SQFS_INODE_SLINK) { +			printf(" ⭢ %.*s", n->inode->data.slink.target_size, +			       n->inode->slink_target); +		} else if (n->inode->base.type == SQFS_INODE_EXT_SLINK) { +			printf(" ⭢ %.*s", n->inode->data.slink_ext.target_size, +			       n->inode->slink_target); +		} + +		fputc('\n', stdout); +		write_tree_dfs(n); +	} +} + +int main(int argc, char **argv) +{ +	sqfs_compressor_config_t cfg; +	sqfs_compressor_t *cmp; +	sqfs_tree_node_t *root = NULL; +	sqfs_id_table_t *idtbl; +	sqfs_dir_reader_t *dr; +	sqfs_file_t *file; +	sqfs_super_t super; +	int status = EXIT_FAILURE; + +	/* open the SquashFS file we want to read */ +	if (argc != 2) { +		fputs("Usage: list_files <squashfs-file>\n", stderr); +		return EXIT_FAILURE; +	} + +	file = sqfs_open_file(argv[1], SQFS_FILE_OPEN_READ_ONLY); +	if (file == NULL) { +		perror(argv[1]); +		return EXIT_FAILURE; +	} + +	/* read the super block, create a compressor and +	   process the compressor options */ +	if (sqfs_super_read(&super, file)) { +		fprintf(stderr, "%s: error reading super block.\n", argv[1]); +		goto out_fd; +	} + +	if (!sqfs_compressor_exists(super.compression_id)) { +		fprintf(stderr, "%s: unknown compressor used.\n", argv[1]); +		goto out_fd; +	} + +	sqfs_compressor_config_init(&cfg, super.compression_id, +				    super.block_size, +				    SQFS_COMP_FLAG_UNCOMPRESS); + +	cmp = sqfs_compressor_create(&cfg); +	if (cmp == NULL) { +		fprintf(stderr, "%s: error creating compressor.\n", argv[1]); +		goto out_fd; +	} + +	if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { +		if (cmp->read_options(cmp, file)) { +			fprintf(stderr, +				"%s: error reading compressor options.\n", +				argv[1]); +			goto out_cmp; +		} +	} + +	/* Create and read the UID/GID mapping table */ +	idtbl = sqfs_id_table_create(); +	if (idtbl == NULL) { +		fputs("Error creating ID table.\n", stderr); +		goto out_cmp; +	} + +	if (sqfs_id_table_read(idtbl, file, &super, cmp)) { +		fprintf(stderr, "%s: error loading ID table.\n", argv[1]); +		goto out_id; +	} + +	/* create a directory reader and scan the entire directory hiearchy */ +	dr = sqfs_dir_reader_create(&super, cmp, file); +	if (dr == NULL) { +		fprintf(stderr, "%s: error creating directory reader.\n", +			argv[1]); +		goto out_id; +	} + +	if (sqfs_dir_reader_get_full_hierarchy(dr, idtbl, NULL, 0, &root)) { +		fprintf(stderr, "%s: error loading directory tree.\n", +			argv[1]); +		goto out; +	} + +	/* fancy print the hierarchy */ +	printf("/\n"); +	write_tree_dfs(root); + +	/* cleanup */ +	status = EXIT_SUCCESS; +out: +	if (root != NULL) +		sqfs_dir_tree_destroy(root); +	sqfs_dir_reader_destroy(dr); +out_id: +	sqfs_id_table_destroy(idtbl); +out_cmp: +	cmp->destroy(cmp); +out_fd: +	file->destroy(file); +	return status; +} | 
