diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-09 11:43:15 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-09 12:11:12 +0200 | 
| commit | b3c3401aee91bc2ff46ba0eab0ceb88c78cb5bbb (patch) | |
| tree | 097241e9080420385db37a3985c5beabe42cb57b /difftool | |
| parent | fd98948e840f6e67cd2d7c72f57d2fd80ed9a418 (diff) | |
Add option to sqfsdiff to extract regular files that are different
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'difftool')
| -rw-r--r-- | difftool/Makemodule.am | 1 | ||||
| -rw-r--r-- | difftool/compare_files_sqfs.c | 10 | ||||
| -rw-r--r-- | difftool/difftool.h | 3 | ||||
| -rw-r--r-- | difftool/extract.c | 52 | ||||
| -rw-r--r-- | difftool/sqfsdiff.c | 26 | 
5 files changed, 89 insertions, 3 deletions
| diff --git a/difftool/Makemodule.am b/difftool/Makemodule.am index 1b0011b..83e5f83 100644 --- a/difftool/Makemodule.am +++ b/difftool/Makemodule.am @@ -6,6 +6,7 @@ fscompare_LDADD = libfstree.a libutil.a  sqfsdiff_SOURCES = difftool/sqfsdiff.c difftool/difftool.h difftool/util.c  sqfsdiff_SOURCES += difftool/compare_dir.c difftool/node_compare.c  sqfsdiff_SOURCES += difftool/compare_files_sqfs.c difftool/super.c +sqfsdiff_SOURCES += difftool/extract.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_sqfs.c b/difftool/compare_files_sqfs.c index 76fae7a..32b97b1 100644 --- a/difftool/compare_files_sqfs.c +++ b/difftool/compare_files_sqfs.c @@ -15,7 +15,7 @@ int compare_files(file_info_t *a, file_info_t *b, const char *path)  	ssize_t ret;  	if (a->size != b->size) -		return 1; +		goto out_different;  	if (compare_flags & COMPARE_NO_CONTENTS)  		return 0; @@ -41,8 +41,14 @@ int compare_files(file_info_t *a, file_info_t *b, const char *path)  		}  		if (memcmp(a_buf, b_buf, diff) != 0) -			return 1; +			goto out_different;  	}  	return 0; +out_different: +	if (compare_flags & COMPARE_EXTRACT_FILES) { +		if (extract_files(a, b, path)) +			return -1; +	} +	return 1;  } diff --git a/difftool/difftool.h b/difftool/difftool.h index 23a161c..bd04fd2 100644 --- a/difftool/difftool.h +++ b/difftool/difftool.h @@ -35,6 +35,7 @@ enum {  	COMPARE_NO_CONTENTS = 0x04,  	COMPARE_TIMESTAMP = 0x08,  	COMPARE_INODE_NUM = 0x10, +	COMPARE_EXTRACT_FILES = 0x20,  };  int compare_dir_entries(tree_node_t *a, tree_node_t *b); @@ -47,4 +48,6 @@ int node_compare(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); +  #endif /* DIFFTOOL_H */ diff --git a/difftool/extract.c b/difftool/extract.c new file mode 100644 index 0000000..9d84265 --- /dev/null +++ b/difftool/extract.c @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * extract.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "difftool.h" + +static int extract(data_reader_t *data, file_info_t *fi, +		   const char *path, char prefix) +{ +	char *ptr, *temp = alloca(strlen(path) + 3); +	int fd; + +	temp[0] = prefix; +	temp[1] = '/'; +	strcpy(temp + 2, path); + +	ptr = strrchr(temp, '/'); +	*ptr = '\0'; +	if (mkdir_p(temp)) +		return -1; +	*ptr = '/'; + +	fd = open(temp, O_CREAT | O_EXCL | O_WRONLY, 0600); +	if (fd < 0) { +		perror(temp); +		return -1; +	} + +	if (data_reader_dump_file(data, fi, fd, true)) { +		close(fd); +		return -1; +	} + +	close(fd); +	return 0; +} + +int extract_files(file_info_t *a, file_info_t *b, const char *path) +{ +	if (a != NULL) { +		if (extract(sqfs_a.data, a, path, 'a')) +			return -1; +	} + +	if (b != NULL) { +		if (extract(sqfs_b.data, b, path, 'b')) +			return -1; +	} +	return 0; +} diff --git a/difftool/sqfsdiff.c b/difftool/sqfsdiff.c index 8818a37..4754557 100644 --- a/difftool/sqfsdiff.c +++ b/difftool/sqfsdiff.c @@ -13,11 +13,12 @@ static struct option long_opts[] = {  	{ "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 = "OPCTIShV"; +static const char *short_opts = "OPCTISe:hV";  static const char *usagestr =  "Usage: sqfsdiff [OPTIONS...] <first> <second>\n" @@ -45,6 +46,11 @@ static const char *usagestr =  "  --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"; @@ -55,6 +61,7 @@ const char *second_path;  sqfs_reader_t sqfs_a;  sqfs_reader_t sqfs_b;  static bool compare_super = false; +static const char *extract_dir;  static void process_options(int argc, char **argv)  { @@ -84,6 +91,10 @@ static void process_options(int argc, char **argv)  		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); @@ -125,6 +136,11 @@ int main(int argc, char **argv)  	process_options(argc, argv); +	if (extract_dir != NULL) { +		if (mkdir_p(extract_dir)) +			return EXIT_FAILURE; +	} +  	if (sqfs_reader_open(&sqfs_a, first_path, 0))  		return 2; @@ -133,6 +149,14 @@ int main(int argc, char **argv)  		goto out_sqfs_a;  	} +	if (extract_dir != NULL) { +		if (chdir(extract_dir)) { +			perror(extract_dir); +			ret = -1; +			goto out; +		} +	} +  	ret = node_compare(sqfs_a.fs.root, sqfs_b.fs.root);  	if (ret != 0)  		goto out; | 
