diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-05 17:38:08 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-05 17:45:59 +0200 | 
| commit | 88f75857702bcc6a2a423570912140c125ec518a (patch) | |
| tree | a1ec54e2520e076395208872d36606f917c8ca34 | |
| parent | 3a340b12eb9b7ed86a47391345cb836fa662b2d9 (diff) | |
cleanup: unify all the code that reads squashfs images
This commit creates a new data structure called 'sqfs_reader_t' that
takes care of all the repetetive tasks like opening the file, reading
the super block, creating the compressor, deserializing an fstree and
creating a data reader.
This in turn makes it possible to remove all the duplicate code from
rdsquashfs and sqfs2tar.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
| -rw-r--r-- | include/highlevel.h | 19 | ||||
| -rw-r--r-- | lib/Makemodule.am | 1 | ||||
| -rw-r--r-- | lib/sqfs/sqfs_reader.c | 72 | ||||
| -rw-r--r-- | tar/sqfs2tar.c | 68 | ||||
| -rw-r--r-- | unpack/rdsquashfs.c | 66 | 
5 files changed, 118 insertions, 108 deletions
diff --git a/include/highlevel.h b/include/highlevel.h index e3afbd7..f8c5bfb 100644 --- a/include/highlevel.h +++ b/include/highlevel.h @@ -9,6 +9,7 @@  #include "config.h" +#include "data_reader.h"  #include "squashfs.h"  #include "compress.h"  #include "id_table.h" @@ -17,6 +18,14 @@  #include <stdint.h>  #include <stddef.h> +typedef struct { +	compressor_t *cmp; +	data_reader_t *data; +	sqfs_super_t super; +	fstree_t fs; +	int sqfsfd; +} sqfs_reader_t; +  enum RDTREE_FLAGS {  	RDTREE_NO_DEVICES = 0x01,  	RDTREE_NO_SOCKETS = 0x02, @@ -96,4 +105,14 @@ int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super,  /* Print out fancy statistics for squashfs packing tools */  void sqfs_print_statistics(fstree_t *fs, sqfs_super_t *super); +/* Open a squashfs file, extract all the information we may need and +   construct datastructures we need to access its contents. +   Returns 0 on success. Prints error messages to stderr on failure. +*/ +int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, +		     int rdtree_flags); + +/* Cleanup after a successfull sqfs_reader_open */ +void sqfs_reader_close(sqfs_reader_t *rd); +  #endif /* HIGHLEVEL_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index c3451f4..82c910c 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -39,6 +39,7 @@ libsquashfs_a_SOURCES += include/data_writer.h include/xattr_reader.h  libsquashfs_a_SOURCES += include/data_reader.h lib/sqfs/data_reader.c  libsquashfs_a_SOURCES += lib/sqfs/write_export_table.c  libsquashfs_a_SOURCES += lib/sqfs/read_table.c lib/sqfs/statistics.c +libsquashfs_a_SOURCES += lib/sqfs/sqfs_reader.c  libutil_a_SOURCES = lib/util/canonicalize_name.c lib/util/write_data.c  libutil_a_SOURCES += lib/util/read_data.c include/util.h diff --git a/lib/sqfs/sqfs_reader.c b/lib/sqfs/sqfs_reader.c new file mode 100644 index 0000000..85cf97a --- /dev/null +++ b/lib/sqfs/sqfs_reader.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * sqfs_reader.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" + +#include "highlevel.h" + +#include <string.h> +#include <unistd.h> +#include <fcntl.h> + +int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, int rdtree_flags) +{ +	memset(rd, 0, sizeof(*rd)); + +	rd->sqfsfd = open(filename, O_RDONLY); +	if (rd->sqfsfd < 0) { +		perror(filename); +		return -1; +	} + +	if (sqfs_super_read(&rd->super, rd->sqfsfd)) +		goto fail_fd; + +	if (!compressor_exists(rd->super.compression_id)) { +		fprintf(stderr, "%s: unknown compressor used.\n", filename); +		goto fail_fd; +	} + +	rd->cmp = compressor_create(rd->super.compression_id, false, +				    rd->super.block_size, NULL); +	if (rd->cmp == NULL) +		goto fail_fd; + +	if (rd->super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { +		if (rd->cmp->read_options(rd->cmp, rd->sqfsfd)) +			goto fail_cmp; +	} + +	if (deserialize_fstree(&rd->fs, &rd->super, rd->cmp, rd->sqfsfd, +			       rdtree_flags)) { +		goto fail_cmp; +	} + +	fstree_gen_file_list(&rd->fs); + +	rd->data = data_reader_create(rd->sqfsfd, &rd->super, rd->cmp); +	if (rd->data == NULL) +		goto fail_fs; + +	return 0; +fail_fs: +	fstree_cleanup(&rd->fs); +fail_cmp: +	rd->cmp->destroy(rd->cmp); +fail_fd: +	close(rd->sqfsfd); +	memset(rd, 0, sizeof(*rd)); +	return -1; +} + +void sqfs_reader_close(sqfs_reader_t *rd) +{ +	data_reader_destroy(rd->data); +	fstree_cleanup(&rd->fs); +	rd->cmp->destroy(rd->cmp); +	close(rd->sqfsfd); +	memset(rd, 0, sizeof(*rd)); +} diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c index a49efda..59e9703 100644 --- a/tar/sqfs2tar.c +++ b/tar/sqfs2tar.c @@ -302,89 +302,51 @@ skip_hdr:  int main(int argc, char **argv)  { -	int sqfsfd, rdtree_flags = 0; -	data_reader_t *data = NULL; -	int status = EXIT_FAILURE; -	sqfs_super_t super; -	compressor_t *cmp; +	int rdtree_flags = 0, status = EXIT_FAILURE; +	sqfs_reader_t sqfs;  	tree_node_t *root; -	fstree_t fs;  	size_t i;  	process_args(argc, argv); -	sqfsfd = open(filename, O_RDONLY); -	if (sqfsfd < 0) { -		perror(filename); -		return EXIT_FAILURE; -	} - -	if (sqfs_super_read(&super, sqfsfd)) -		goto out_fd; - -	if (!compressor_exists(super.compression_id)) { -		fputs("Image uses a compressor that has not been built in\n", -		      stderr); -		goto out_fd; -	} - -	cmp = compressor_create(super.compression_id, false, -				super.block_size, NULL); -	if (cmp == NULL) -		goto out_fd; - -	if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { -		if (cmp->read_options(cmp, sqfsfd)) -			goto out_cmp; -	} -  	if (!no_xattr)  		rdtree_flags |= RDTREE_READ_XATTR; -	if (deserialize_fstree(&fs, &super, cmp, sqfsfd, rdtree_flags)) -		goto out_cmp; - -	data = data_reader_create(sqfsfd, &super, cmp); -	if (data == NULL) -		goto out_fs; +	if (sqfs_reader_open(&sqfs, filename, rdtree_flags)) +		goto out_dirs;  	for (i = 0; i < num_subdirs; ++i) { -		root = fstree_node_from_path(&fs, subdirs[i]); +		root = fstree_node_from_path(&sqfs.fs, subdirs[i]);  		if (root == NULL) {  			perror(subdirs[i]); -			goto out_data; +			goto out;  		}  		if (!S_ISDIR(root->mode)) {  			fprintf(stderr, "%s is not a directory\n", subdirs[i]); -			goto out_data; +			goto out;  		}  		current_subdir = subdirs[i]; -		if (write_tree_dfs(&fs, root, data)) -			goto out_data; +		if (write_tree_dfs(&sqfs.fs, root, sqfs.data)) +			goto out;  	}  	current_subdir = NULL;  	if (num_subdirs == 0) { -		if (write_tree_dfs(&fs, fs.root, data)) -			goto out_data; +		if (write_tree_dfs(&sqfs.fs, sqfs.fs.root, sqfs.data)) +			goto out;  	}  	if (terminate_archive()) -		goto out_data; +		goto out;  	status = EXIT_SUCCESS; -out_data: -	data_reader_destroy(data); -out_fs: -	fstree_cleanup(&fs); -out_cmp: -	cmp->destroy(cmp); -out_fd: -	close(sqfsfd); +out: +	sqfs_reader_close(&sqfs); +out_dirs:  	for (i = 0; i < num_subdirs; ++i)  		free(subdirs[i]);  	free(subdirs); diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c index dc43fcd..4fb3a78 100644 --- a/unpack/rdsquashfs.c +++ b/unpack/rdsquashfs.c @@ -24,54 +24,23 @@ static void dump_xattrs(fstree_t *fs, tree_xattr_t *xattr)  int main(int argc, char **argv)  {  	int status = EXIT_FAILURE; -	data_reader_t *data = NULL; -	sqfs_super_t super; -	compressor_t *cmp; +	sqfs_reader_t sqfs;  	tree_node_t *n;  	options_t opt; -	fstree_t fs; -	int sqfsfd;  	process_command_line(&opt, argc, argv); -	sqfsfd = open(opt.image_name, O_RDONLY); -	if (sqfsfd < 0) { -		perror(opt.image_name); +	if (sqfs_reader_open(&sqfs, opt.image_name, opt.rdtree_flags))  		goto out_cmd; -	} - -	if (sqfs_super_read(&super, sqfsfd)) -		goto out_fd; - -	if (!compressor_exists(super.compression_id)) { -		fputs("Image uses a compressor that has not been built in\n", -		      stderr); -		goto out_fd; -	} - -	cmp = compressor_create(super.compression_id, false, -				super.block_size, NULL); -	if (cmp == NULL) -		goto out_fd; - -	if (super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { -		if (cmp->read_options(cmp, sqfsfd)) -			goto out_cmp; -	} - -	if (deserialize_fstree(&fs, &super, cmp, sqfsfd, opt.rdtree_flags)) -		goto out_cmp; - -	fstree_gen_file_list(&fs);  	if (opt.cmdpath != NULL) { -		n = fstree_node_from_path(&fs, opt.cmdpath); +		n = fstree_node_from_path(&sqfs.fs, opt.cmdpath);  		if (n == NULL) {  			perror(opt.cmdpath);  			goto out_fs;  		}  	} else { -		n = fs.root; +		n = sqfs.fs.root;  	}  	switch (opt.op) { @@ -85,11 +54,7 @@ int main(int argc, char **argv)  			goto out_fs;  		} -		data = data_reader_create(sqfsfd, &super, cmp); -		if (data == NULL) -			goto out_fs; - -		if (data_reader_dump_file(data, n->data.file, +		if (data_reader_dump_file(sqfs.data, n->data.file,  					  STDOUT_FILENO, false))  			goto out_fs;  		break; @@ -105,38 +70,29 @@ int main(int argc, char **argv)  		if (restore_fstree(n, opt.flags))  			goto out_fs; -		data = data_reader_create(sqfsfd, &super, cmp); -		if (data == NULL) -			goto out_fs; - -		if (fill_unpacked_files(&fs, data, opt.flags, opt.num_jobs)) +		if (fill_unpacked_files(&sqfs.fs, sqfs.data, +					opt.flags, opt.num_jobs))  			goto out_fs; -		if (update_tree_attribs(&fs, n, opt.flags)) +		if (update_tree_attribs(&sqfs.fs, n, opt.flags))  			goto out_fs;  		if (opt.unpack_root != NULL && popd() != 0)  			goto out_fs;  		break;  	case OP_DESCRIBE: -		if (describe_tree(fs.root, opt.unpack_root)) +		if (describe_tree(sqfs.fs.root, opt.unpack_root))  			goto out_fs;  		break;  	case OP_RDATTR:  		if (n->xattr != NULL) -			dump_xattrs(&fs, n->xattr); +			dump_xattrs(&sqfs.fs, n->xattr);  		break;  	}  	status = EXIT_SUCCESS;  out_fs: -	if (data != NULL) -		data_reader_destroy(data); -	fstree_cleanup(&fs); -out_cmp: -	cmp->destroy(cmp); -out_fd: -	close(sqfsfd); +	sqfs_reader_close(&sqfs);  out_cmd:  	free(opt.cmdpath);  	return status;  | 
