aboutsummaryrefslogtreecommitdiff
path: root/difftool
diff options
context:
space:
mode:
Diffstat (limited to 'difftool')
-rw-r--r--difftool/Makemodule.am2
-rw-r--r--difftool/compare_files.c33
-rw-r--r--difftool/extract.c11
-rw-r--r--difftool/node_compare.c14
-rw-r--r--difftool/options.c130
-rw-r--r--difftool/sqfsdiff.c162
-rw-r--r--difftool/sqfsdiff.h28
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 */