diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-06 16:46:49 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-07 11:26:32 +0200 | 
| commit | da2dbf9f9bd1a244a618b9dc141a9fcb19b23427 (patch) | |
| tree | 599a97af826d4f8d863b955b02ed1b6922515877 /difftool | |
| parent | 28a99ec109637a92f78a24f0eed64cb8a078f356 (diff) | |
Add flag to sqfsdiff to compare the fields in the super block
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/difftool.h | 2 | ||||
| -rw-r--r-- | difftool/sqfsdiff.c | 35 | ||||
| -rw-r--r-- | difftool/super.c | 124 | 
4 files changed, 155 insertions, 8 deletions
| diff --git a/difftool/Makemodule.am b/difftool/Makemodule.am index 62c9197..1b0011b 100644 --- a/difftool/Makemodule.am +++ b/difftool/Makemodule.am @@ -5,7 +5,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 +sqfsdiff_SOURCES += difftool/compare_files_sqfs.c difftool/super.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/difftool.h b/difftool/difftool.h index 4b6173a..23a161c 100644 --- a/difftool/difftool.h +++ b/difftool/difftool.h @@ -45,4 +45,6 @@ int compare_files(file_info_t *a, file_info_t *b, const char *path);  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); +  #endif /* DIFFTOOL_H */ diff --git a/difftool/sqfsdiff.c b/difftool/sqfsdiff.c index 96a8f31..8818a37 100644 --- a/difftool/sqfsdiff.c +++ b/difftool/sqfsdiff.c @@ -12,11 +12,12 @@ static struct option long_opts[] = {  	{ "no-contents", no_argument, NULL, 'C' },  	{ "timestamps", no_argument, NULL, 'T' },  	{ "inode-num", no_argument, NULL, 'I' }, +	{ "super", no_argument, NULL, 'S' },  	{ "help", no_argument, NULL, 'h' },  	{ "version", no_argument, NULL, 'V' },  }; -static const char *short_opts = "OPCTIhV"; +static const char *short_opts = "OPCTIShV";  static const char *usagestr =  "Usage: sqfsdiff [OPTIONS...] <first> <second>\n" @@ -42,6 +43,7 @@ static const char *usagestr =  "\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"  "  --help, -h                  Print help text and exit.\n"  "  --version, -V               Print version information and exit.\n" @@ -52,6 +54,7 @@ const char *first_path;  const char *second_path;  sqfs_reader_t sqfs_a;  sqfs_reader_t sqfs_b; +static bool compare_super = false;  static void process_options(int argc, char **argv)  { @@ -78,6 +81,9 @@ static void process_options(int argc, char **argv)  		case 'I':  			compare_flags |= COMPARE_INODE_NUM;  			break; +		case 'S': +			compare_super = true; +			break;  		case 'h':  			fputs(usagestr, stdout);  			exit(EXIT_SUCCESS); @@ -115,22 +121,37 @@ fail_arg:  int main(int argc, char **argv)  { -	int ret = EXIT_FAILURE; +	int status, ret = 0;  	process_options(argc, argv);  	if (sqfs_reader_open(&sqfs_a, first_path, 0)) -		return EXIT_FAILURE; +		return 2; -	if (sqfs_reader_open(&sqfs_b, second_path, 0)) +	if (sqfs_reader_open(&sqfs_b, second_path, 0)) { +		status = 2;  		goto out_sqfs_a; +	}  	ret = node_compare(sqfs_a.fs.root, sqfs_b.fs.root); -	if (ret < 0) -		ret = 2; +	if (ret != 0) +		goto out; +	if (compare_super) { +		ret = compare_super_blocks(&sqfs_a.super, &sqfs_b.super); +		if (ret != 0) +			goto out; +	} +out: +	if (ret < 0) { +		status = 2; +	} else if (ret > 0) { +		status = 1; +	} else { +		status = 0; +	}  	sqfs_reader_close(&sqfs_b);  out_sqfs_a:  	sqfs_reader_close(&sqfs_a); -	return ret; +	return status;  } diff --git a/difftool/super.c b/difftool/super.c new file mode 100644 index 0000000..7bda728 --- /dev/null +++ b/difftool/super.c @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * super.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#include "difftool.h" + +static const struct { +	uint16_t mask; +	const char *name; +} sqfs_flags[] = { +	{ SQFS_FLAG_UNCOMPRESSED_INODES, "uncompressed inodes" }, +	{ SQFS_FLAG_UNCOMPRESSED_DATA, "uncompressed data" }, +	{ SQFS_FLAG_UNCOMPRESSED_FRAGMENTS, "uncompressed fragments" }, +	{ SQFS_FLAG_NO_FRAGMENTS, "no fragments" }, +	{ SQFS_FLAG_ALWAYS_FRAGMENTS, "always fragments" }, +	{ SQFS_FLAG_DUPLICATES, "duplicates" }, +	{ SQFS_FLAG_EXPORTABLE, "exportable" }, +	{ SQFS_FLAG_UNCOMPRESSED_XATTRS, "uncompressed xattrs" }, +	{ SQFS_FLAG_NO_XATTRS, "no xattrs" }, +	{ SQFS_FLAG_COMPRESSOR_OPTIONS, "compressor options" }, +	{ SQFS_FLAG_UNCOMPRESSED_IDS, "uncompressed ids" }, +}; + +static void print_value_difference(const char *name, uint64_t a, uint64_t b) +{ +	uint64_t diff; +	char c; + +	if (a != b) { +		if (a < b) { +			c = '+'; +			diff = b - a; +		} else { +			c = '-'; +			diff = a - b; +		} +		fprintf(stdout, "%s: %c%lu\n", name, c, diff); +	} +} + +static void print_offset_diff(const char *name, uint64_t a, uint64_t b) +{ +	if (a != b) +		fprintf(stdout, "Location of %s differs\n", name); +} + +static void print_flag_diff(uint16_t a, uint16_t b) +{ +	uint16_t diff = a ^ b, mask; +	size_t i; +	char c; + +	if (diff == 0) +		return; + +	fputs("flags:\n", stdout); + +	for (i = 0; i < sizeof(sqfs_flags) / sizeof(sqfs_flags[0]); ++i) { +		if (diff & sqfs_flags[i].mask) { +			c = a & sqfs_flags[i].mask ? '<' : '>'; + +			fprintf(stdout, "\t%c%s\n", c, sqfs_flags[i].name); +		} + +		a &= ~sqfs_flags[i].mask; +		b &= ~sqfs_flags[i].mask; +		diff &= ~sqfs_flags[i].mask; +	} + +	for (i = 0, mask = 0x01; i < 16; ++i, mask <<= 1) { +		if (diff & mask) { +			fprintf(stdout, "\t%c additional unknown\n", +				a & mask ? '<' : '>'); +		} +	} +} + +int compare_super_blocks(const sqfs_super_t *a, const sqfs_super_t *b) +{ +	if (memcmp(a, b, sizeof(*a)) == 0) +		return 0; + +	fputs("======== super blocks are different ========\n", stdout); + +	/* TODO: if a new magic number or squashfs version is introduced, +	   compare them. */ + +	print_value_difference("inode count", a->inode_count, b->inode_count); +	print_value_difference("modification time", a->modification_time, +			       b->modification_time); +	print_value_difference("block size", a->block_size, b->block_size); +	print_value_difference("block log", a->block_log, b->block_log); +	print_value_difference("fragment table entries", +			       a->fragment_entry_count, +			       b->fragment_entry_count); +	print_value_difference("ID table entries", a->id_count, b->id_count); + +	if (a->compression_id != b->compression_id) { +		fprintf(stdout, "compressor: %s vs %s\n", +			compressor_name_from_id(a->compression_id), +			compressor_name_from_id(b->compression_id)); +	} + +	print_flag_diff(a->flags, b->flags); + +	print_value_difference("total bytes used", a->bytes_used, +			       b->bytes_used); + +	print_offset_diff("root inode", a->root_inode_ref, b->root_inode_ref); +	print_offset_diff("ID table", a->id_table_start, b->id_table_start); +	print_offset_diff("xattr ID table", a->xattr_id_table_start, +			  b->xattr_id_table_start); +	print_offset_diff("inode table", a->inode_table_start, +			  b->inode_table_start); +	print_offset_diff("directory table", a->directory_table_start, +			  b->directory_table_start); +	print_offset_diff("fragment table", a->fragment_table_start, +			  b->fragment_table_start); +	print_offset_diff("export table", a->export_table_start, +			  b->export_table_start); +	return 1; +} | 
