diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-21 14:04:43 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-21 14:04:43 +0200 | 
| commit | 4ff2b4f689f4e530b6c6f3eed17a595f7ccf56fb (patch) | |
| tree | 1e453c616d34a1547eb8e62949337e8361c6b31e /difftool | |
| parent | 5cbc1267e5dc42149eeb07883f5f6239d22388e9 (diff) | |
Isolate sqfsdiff global state and split off option processing
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'difftool')
| -rw-r--r-- | difftool/Makemodule.am | 2 | ||||
| -rw-r--r-- | difftool/compare_files.c | 33 | ||||
| -rw-r--r-- | difftool/extract.c | 11 | ||||
| -rw-r--r-- | difftool/node_compare.c | 14 | ||||
| -rw-r--r-- | difftool/options.c | 130 | ||||
| -rw-r--r-- | difftool/sqfsdiff.c | 162 | ||||
| -rw-r--r-- | difftool/sqfsdiff.h | 28 | 
7 files changed, 195 insertions, 185 deletions
| diff --git a/difftool/Makemodule.am b/difftool/Makemodule.am index e687cb0..9b6e713 100644 --- a/difftool/Makemodule.am +++ b/difftool/Makemodule.am @@ -1,7 +1,7 @@  sqfsdiff_SOURCES = difftool/sqfsdiff.c difftool/sqfsdiff.h difftool/util.c  sqfsdiff_SOURCES += difftool/compare_dir.c difftool/node_compare.c  sqfsdiff_SOURCES += difftool/compare_files.c difftool/super.c -sqfsdiff_SOURCES += difftool/extract.c +sqfsdiff_SOURCES += difftool/extract.c difftool/options.c  sqfsdiff_LDADD = libsquashfs.a libfstree.a libcompress.a libutil.a  sqfsdiff_LDADD += $(XZ_LIBS) $(ZLIB_LIBS) $(LZO_LIBS) $(LZ4_LIBS) $(ZSTD_LIBS) diff --git a/difftool/compare_files.c b/difftool/compare_files.c index 46e170b..605df84 100644 --- a/difftool/compare_files.c +++ b/difftool/compare_files.c @@ -9,10 +9,11 @@  static unsigned char old_buf[MAX_WINDOW_SIZE];  static unsigned char new_buf[MAX_WINDOW_SIZE]; -int compare_files(file_info_t *old, file_info_t *new, const char *path) +int compare_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new, +		  const char *path)  { -	char new_name[strlen(new_path) + strlen(path) + 2]; -	char old_name[strlen(old_path) + strlen(path) + 2]; +	char new_name[strlen(sd->new_path) + strlen(path) + 2]; +	char old_name[strlen(sd->old_path) + strlen(path) + 2];  	int old_fd = -1, new_fd = -1, status = 0;  	uint64_t offset, diff;  	ssize_t ret; @@ -20,11 +21,11 @@ int compare_files(file_info_t *old, file_info_t *new, const char *path)  	if (old->size != new->size)  		goto out_different; -	if (compare_flags & COMPARE_NO_CONTENTS) +	if (sd->compare_flags & COMPARE_NO_CONTENTS)  		return 0; -	if (old_is_dir) { -		sprintf(old_name, "%s/%s", old_path, path); +	if (sd->old_is_dir) { +		sprintf(old_name, "%s/%s", sd->old_path, path);  		old_fd = open(old_name, O_RDONLY);  		if (old_fd < 0) { @@ -33,8 +34,8 @@ int compare_files(file_info_t *old, file_info_t *new, const char *path)  		}  	} -	if (new_is_dir) { -		sprintf(new_name, "%s/%s", new_path, path); +	if (sd->new_is_dir) { +		sprintf(new_name, "%s/%s", sd->new_path, path);  		new_fd = open(new_name, O_RDONLY);  		if (new_fd < 0) { @@ -49,30 +50,30 @@ int compare_files(file_info_t *old, file_info_t *new, const char *path)  		if (diff > MAX_WINDOW_SIZE)  			diff = MAX_WINDOW_SIZE; -		if (old_is_dir) { +		if (sd->old_is_dir) {  			if (read_data_at(old_name, offset, old_fd,  					 old_buf, diff))  				goto out;  		} else { -			ret = data_reader_read(sqfs_old.data, old, offset, +			ret = data_reader_read(sd->sqfs_old.data, old, offset,  					       old_buf, diff);  			if (ret < 0 || (size_t)ret < diff) {  				fprintf(stderr, "Failed to read %s from %s\n", -					path, old_path); +					path, sd->old_path);  				return -1;  			}  		} -		if (new_is_dir) { +		if (sd->new_is_dir) {  			if (read_data_at(new_name, offset, new_fd,  					 new_buf, diff))  				goto out;  		} else { -			ret = data_reader_read(sqfs_new.data, new, offset, +			ret = data_reader_read(sd->sqfs_new.data, new, offset,  					       new_buf, diff);  			if (ret < 0 || (size_t)ret < diff) {  				fprintf(stderr, "Failed to read %s from %s\n", -					path, new_path); +					path, sd->new_path);  				return -1;  			}  		} @@ -90,8 +91,8 @@ fail:  	status = -1;  	goto out;  out_different: -	if (compare_flags & COMPARE_EXTRACT_FILES) { -		if (extract_files(old, new, path)) +	if (sd->compare_flags & COMPARE_EXTRACT_FILES) { +		if (extract_files(sd, old, new, path))  			goto fail;  	}  	status = 1; diff --git a/difftool/extract.c b/difftool/extract.c index f40de60..cefba62 100644 --- a/difftool/extract.c +++ b/difftool/extract.c @@ -37,15 +37,16 @@ static int extract(data_reader_t *data, file_info_t *fi,  	return 0;  } -int extract_files(file_info_t *old, file_info_t *new, const char *path) +int extract_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new, +		  const char *path)  { -	if (old != NULL && !old_is_dir) { -		if (extract(sqfs_old.data, old, path, 'a')) +	if (old != NULL && !sd->old_is_dir) { +		if (extract(sd->sqfs_old.data, old, path, 'a'))  			return -1;  	} -	if (new != NULL && !new_is_dir) { -		if (extract(sqfs_new.data, new, path, 'b')) +	if (new != NULL && !sd->new_is_dir) { +		if (extract(sd->sqfs_new.data, new, path, 'b'))  			return -1;  	}  	return 0; diff --git a/difftool/node_compare.c b/difftool/node_compare.c index 1c68ab2..35fd07b 100644 --- a/difftool/node_compare.c +++ b/difftool/node_compare.c @@ -6,7 +6,7 @@   */  #include "sqfsdiff.h" -int node_compare(tree_node_t *a, tree_node_t *b) +int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b)  {  	char *path = node_path(a);  	tree_node_t *ait, *bit; @@ -21,7 +21,7 @@ int node_compare(tree_node_t *a, tree_node_t *b)  		return 1;  	} -	if (!(compare_flags & COMPARE_NO_PERM)) { +	if (!(sd->compare_flags & COMPARE_NO_PERM)) {  		if ((a->mode & ~S_IFMT) != (b->mode & ~S_IFMT)) {  			fprintf(stdout, "%s has different permissions\n",  				path); @@ -29,21 +29,21 @@ int node_compare(tree_node_t *a, tree_node_t *b)  		}  	} -	if (!(compare_flags & COMPARE_NO_OWNER)) { +	if (!(sd->compare_flags & COMPARE_NO_OWNER)) {  		if (a->uid != b->uid || a->gid != b->gid) {  			fprintf(stdout, "%s has different ownership\n", path);  			status = 1;  		}  	} -	if (compare_flags & COMPARE_TIMESTAMP) { +	if (sd->compare_flags & COMPARE_TIMESTAMP) {  		if (a->mod_time != b->mod_time) {  			fprintf(stdout, "%s has a different timestamp\n", path);  			status = 1;  		}  	} -	if (compare_flags & COMPARE_INODE_NUM) { +	if (sd->compare_flags & COMPARE_INODE_NUM) {  		if (a->inode_num != b->inode_num) {  			fprintf(stdout, "%s has a different inode number\n",  				path); @@ -85,7 +85,7 @@ int node_compare(tree_node_t *a, tree_node_t *b)  		bit = b->data.dir->children;  		while (ait != NULL && bit != NULL) { -			ret = node_compare(ait, bit); +			ret = node_compare(sd, ait, bit);  			if (ret < 0)  				return -1;  			if (ret > 0) @@ -96,7 +96,7 @@ int node_compare(tree_node_t *a, tree_node_t *b)  		}  		break;  	case S_IFREG: -		ret = compare_files(a->data.file, b->data.file, path); +		ret = compare_files(sd, a->data.file, b->data.file, path);  		if (ret < 0) {  			status = -1;  		} else if (ret > 0) { diff --git a/difftool/options.c b/difftool/options.c new file mode 100644 index 0000000..8224b1d --- /dev/null +++ b/difftool/options.c @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * sqfsdiff.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "sqfsdiff.h" + +static struct option long_opts[] = { +	{ "old", required_argument, NULL, 'a' }, +	{ "new", required_argument, NULL, 'b' }, +	{ "no-owner", no_argument, NULL, 'O' }, +	{ "no-permissions", no_argument, NULL, 'P' }, +	{ "no-contents", no_argument, NULL, 'C' }, +	{ "timestamps", no_argument, NULL, 'T' }, +	{ "inode-num", no_argument, NULL, 'I' }, +	{ "super", no_argument, NULL, 'S' }, +	{ "extract", required_argument, NULL, 'e' }, +	{ "help", no_argument, NULL, 'h' }, +	{ "version", no_argument, NULL, 'V' }, +}; + +static const char *short_opts = "a:b:OPCTISe:hV"; + +static const char *usagestr = +"Usage: sqfsdiff [OPTIONS...] --old,-a <first> --new,-b <second>\n" +"\n" +"Compare two squashfs images. In contrast to doing a direct diff of the\n" +"images, this actually parses the filesystems and generates a more\n" +"meaningful difference report.\n" +"\n" +"If only contents are compared, any differences in packed file layout,\n" +"ordering, compression, inode allocation and so on is ignored and the two\n" +"images are considered equal if each directory contains the same entries,\n" +"symlink with the same paths have the same targets, device nodes the same\n" +"device number and files the same size and contents.\n" +"\n" +"A report of any difference is printed to stdout. The exit status is similar\n" +"that of diff(1): 0 means equal, 1 means different, 2 means problem.\n" +"\n" +"Possible options:\n" +"\n" +"  --old, -a <first>           The first of the two images to compare.\n" +"  --new, -b <second>          The second of the two images to compare.\n" +"\n" +"  --no-contents, -C           Do not compare file contents.\n" +"  --no-owner, -O              Do not compare file owners.\n" +"  --no-permissions, -P        Do not compare permission bits.\n" +"\n" +"  --timestamps, -T            Compare file timestamps.\n" +"  --inode-num, -I             Compare inode numbers of all files.\n" +"  --super, -S                 Also compare metadata in super blocks.\n" +"\n" +"  --extract, -e <path>        Extract files that differ to the specified\n" +"                              directory. Contents of the first image end up\n" +"                              in a subdirectory 'a' and of the second image\n" +"                              in a subdirectory 'b'.\n" +"\n" +"  --help, -h                  Print help text and exit.\n" +"  --version, -V               Print version information and exit.\n" +"\n"; + +void process_options(sqfsdiff_t *sd, int argc, char **argv) +{ +	int i; + +	for (;;) { +		i = getopt_long(argc, argv, short_opts, long_opts, NULL); +		if (i == -1) +			break; + +		switch (i) { +		case 'a': +			sd->old_path = optarg; +			break; +		case 'b': +			sd->new_path = optarg; +			break; +		case 'O': +			sd->compare_flags |= COMPARE_NO_OWNER; +			break; +		case 'P': +			sd->compare_flags |= COMPARE_NO_PERM; +			break; +		case 'C': +			sd->compare_flags |= COMPARE_NO_CONTENTS; +			break; +		case 'T': +			sd->compare_flags |= COMPARE_TIMESTAMP; +			break; +		case 'I': +			sd->compare_flags |= COMPARE_INODE_NUM; +			break; +		case 'S': +			sd->compare_super = true; +			break; +		case 'e': +			sd->compare_flags |= COMPARE_EXTRACT_FILES; +			sd->extract_dir = optarg; +			break; +		case 'h': +			fputs(usagestr, stdout); +			exit(EXIT_SUCCESS); +		case 'V': +			print_version(); +			exit(EXIT_SUCCESS); +		default: +			goto fail_arg; +		} +	} + +	if (sd->old_path == NULL) { +		fputs("Missing arguments: first filesystem\n", stderr); +		goto fail_arg; +	} + +	if (sd->new_path == NULL) { +		fputs("Missing arguments: second filesystem\n", stderr); +		goto fail_arg; +	} + +	if (optind < argc) { +		fputs("Unknown extra arguments\n", stderr); +		goto fail_arg; +	} +	return; +fail_arg: +	fprintf(stderr, "Try `sqfsdiff --help' for more information.\n"); +	exit(EXIT_FAILURE); +} diff --git a/difftool/sqfsdiff.c b/difftool/sqfsdiff.c index ddc2686..2bc733b 100644 --- a/difftool/sqfsdiff.c +++ b/difftool/sqfsdiff.c @@ -6,172 +6,42 @@   */  #include "sqfsdiff.h" -static struct option long_opts[] = { -	{ "old", required_argument, NULL, 'a' }, -	{ "new", required_argument, NULL, 'b' }, -	{ "no-owner", no_argument, NULL, 'O' }, -	{ "no-permissions", no_argument, NULL, 'P' }, -	{ "no-contents", no_argument, NULL, 'C' }, -	{ "timestamps", no_argument, NULL, 'T' }, -	{ "inode-num", no_argument, NULL, 'I' }, -	{ "super", no_argument, NULL, 'S' }, -	{ "extract", required_argument, NULL, 'e' }, -	{ "help", no_argument, NULL, 'h' }, -	{ "version", no_argument, NULL, 'V' }, -}; - -static const char *short_opts = "a:b:OPCTISe:hV"; - -static const char *usagestr = -"Usage: sqfsdiff [OPTIONS...] --old,-a <first> --new,-b <second>\n" -"\n" -"Compare two squashfs images. In contrast to doing a direct diff of the\n" -"images, this actually parses the filesystems and generates a more\n" -"meaningful difference report.\n" -"\n" -"If only contents are compared, any differences in packed file layout,\n" -"ordering, compression, inode allocation and so on is ignored and the two\n" -"images are considered equal if each directory contains the same entries,\n" -"symlink with the same paths have the same targets, device nodes the same\n" -"device number and files the same size and contents.\n" -"\n" -"A report of any difference is printed to stdout. The exit status is similar\n" -"that of diff(1): 0 means equal, 1 means different, 2 means problem.\n" -"\n" -"Possible options:\n" -"\n" -"  --old, -a <first>           The first of the two images to compare.\n" -"  --new, -b <second>          The second of the two images to compare.\n" -"\n" -"  --no-contents, -C           Do not compare file contents.\n" -"  --no-owner, -O              Do not compare file owners.\n" -"  --no-permissions, -P        Do not compare permission bits.\n" -"\n" -"  --timestamps, -T            Compare file timestamps.\n" -"  --inode-num, -I             Compare inode numbers of all files.\n" -"  --super, -S                 Also compare metadata in super blocks.\n" -"\n" -"  --extract, -e <path>        Extract files that differ to the specified\n" -"                              directory. Contents of the first image end up\n" -"                              in a subdirectory 'a' and of the second image\n" -"                              in a subdirectory 'b'.\n" -"\n" -"  --help, -h                  Print help text and exit.\n" -"  --version, -V               Print version information and exit.\n" -"\n"; - -int compare_flags = 0; -const char *old_path; -const char *new_path; -sqfs_reader_t sqfs_old; -sqfs_reader_t sqfs_new; -bool old_is_dir; -bool new_is_dir; -static bool compare_super = false; -static const char *extract_dir; - -static void process_options(int argc, char **argv) -{ -	int i; - -	for (;;) { -		i = getopt_long(argc, argv, short_opts, long_opts, NULL); -		if (i == -1) -			break; - -		switch (i) { -		case 'a': -			old_path = optarg; -			break; -		case 'b': -			new_path = optarg; -			break; -		case 'O': -			compare_flags |= COMPARE_NO_OWNER; -			break; -		case 'P': -			compare_flags |= COMPARE_NO_PERM; -			break; -		case 'C': -			compare_flags |= COMPARE_NO_CONTENTS; -			break; -		case 'T': -			compare_flags |= COMPARE_TIMESTAMP; -			break; -		case 'I': -			compare_flags |= COMPARE_INODE_NUM; -			break; -		case 'S': -			compare_super = true; -			break; -		case 'e': -			compare_flags |= COMPARE_EXTRACT_FILES; -			extract_dir = optarg; -			break; -		case 'h': -			fputs(usagestr, stdout); -			exit(EXIT_SUCCESS); -		case 'V': -			print_version(); -			exit(EXIT_SUCCESS); -		default: -			goto fail_arg; -		} -	} - -	if (old_path == NULL) { -		fputs("Missing arguments: first filesystem\n", stderr); -		goto fail_arg; -	} - -	if (new_path == NULL) { -		fputs("Missing arguments: second filesystem\n", stderr); -		goto fail_arg; -	} - -	if (optind < argc) { -		fputs("Unknown extra arguments\n", stderr); -		goto fail_arg; -	} -	return; -fail_arg: -	fprintf(stderr, "Try `sqfsdiff --help' for more information.\n"); -	exit(EXIT_FAILURE); -} -  int main(int argc, char **argv)  {  	int status, ret = 0; +	sqfsdiff_t sd; -	process_options(argc, argv); +	memset(&sd, 0, sizeof(sd)); +	process_options(&sd, argc, argv); -	if (extract_dir != NULL) { -		if (mkdir_p(extract_dir)) +	if (sd.extract_dir != NULL) { +		if (mkdir_p(sd.extract_dir))  			return EXIT_FAILURE;  	} -	if (sqfs_reader_open(&sqfs_old, old_path, 0)) +	if (sqfs_reader_open(&sd.sqfs_old, sd.old_path, 0))  		return 2; -	if (sqfs_reader_open(&sqfs_new, new_path, 0)) { +	if (sqfs_reader_open(&sd.sqfs_new, sd.new_path, 0)) {  		status = 2;  		goto out_sqfs_old;  	} -	if (extract_dir != NULL) { -		if (chdir(extract_dir)) { -			perror(extract_dir); +	if (sd.extract_dir != NULL) { +		if (chdir(sd.extract_dir)) { +			perror(sd.extract_dir);  			ret = -1;  			goto out;  		}  	} -	ret = node_compare(sqfs_old.fs.root, sqfs_new.fs.root); +	ret = node_compare(&sd, sd.sqfs_old.fs.root, sd.sqfs_new.fs.root);  	if (ret != 0)  		goto out; -	if (compare_super) { -		ret = compare_super_blocks(&sqfs_old.super, &sqfs_new.super); +	if (sd.compare_super) { +		ret = compare_super_blocks(&sd.sqfs_old.super, +					   &sd.sqfs_new.super);  		if (ret != 0)  			goto out;  	} @@ -183,8 +53,8 @@ out:  	} else {  		status = 0;  	} -	sqfs_reader_close(&sqfs_new); +	sqfs_reader_close(&sd.sqfs_new);  out_sqfs_old: -	sqfs_reader_close(&sqfs_old); +	sqfs_reader_close(&sd.sqfs_old);  	return status;  } diff --git a/difftool/sqfsdiff.h b/difftool/sqfsdiff.h index f7d5139..ce6929f 100644 --- a/difftool/sqfsdiff.h +++ b/difftool/sqfsdiff.h @@ -23,13 +23,17 @@  #define MAX_WINDOW_SIZE (1024 * 1024 * 4) -extern const char *old_path; -extern const char *new_path; -extern int compare_flags; -extern sqfs_reader_t sqfs_old; -extern sqfs_reader_t sqfs_new; -extern bool old_is_dir; -extern bool new_is_dir; +typedef struct { +	const char *old_path; +	const char *new_path; +	int compare_flags; +	sqfs_reader_t sqfs_old; +	sqfs_reader_t sqfs_new; +	bool old_is_dir; +	bool new_is_dir; +	bool compare_super; +	const char *extract_dir; +} sqfsdiff_t;  enum {  	COMPARE_NO_PERM = 0x01, @@ -44,12 +48,16 @@ int compare_dir_entries(tree_node_t *a, tree_node_t *b);  char *node_path(tree_node_t *n); -int compare_files(file_info_t *a, file_info_t *b, const char *path); +int compare_files(sqfsdiff_t *sd, file_info_t *a, file_info_t *b, +		  const char *path); -int node_compare(tree_node_t *a, tree_node_t *b); +int node_compare(sqfsdiff_t *sd, tree_node_t *a, tree_node_t *b);  int compare_super_blocks(const sqfs_super_t *a, const sqfs_super_t *b); -int extract_files(file_info_t *a, file_info_t *b, const char *path); +int extract_files(sqfsdiff_t *sd, file_info_t *old, file_info_t *new, +		  const char *path); + +void process_options(sqfsdiff_t *sd, int argc, char **argv);  #endif /* DIFFTOOL_H */ | 
