summaryrefslogtreecommitdiff
path: root/difftool/node_compare.c
diff options
context:
space:
mode:
Diffstat (limited to 'difftool/node_compare.c')
-rw-r--r--difftool/node_compare.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/difftool/node_compare.c b/difftool/node_compare.c
new file mode 100644
index 0000000..fae35ab
--- /dev/null
+++ b/difftool/node_compare.c
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * node_compare.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "difftool.h"
+
+int node_compare(tree_node_t *a, tree_node_t *b)
+{
+ char *path = node_path(a);
+ tree_node_t *ait, *bit;
+ int ret, status = 0;
+
+ if (path == NULL)
+ return -1;
+
+ if ((a->mode & S_IFMT) != (b->mode & S_IFMT)) {
+ fprintf(stdout, "%s has a different type\n", path);
+ free(path);
+ return 1;
+ }
+
+ if (!(compare_flags & COMPARE_NO_PERM)) {
+ if ((a->mode & ~S_IFMT) != (b->mode & ~S_IFMT)) {
+ fprintf(stdout, "%s has different permissions\n",
+ path);
+ status = 1;
+ }
+ }
+
+ if (!(compare_flags & COMPARE_NO_OWNER)) {
+ if (a->uid != b->uid || a->gid != b->gid) {
+ fprintf(stdout, "%s has different ownership\n", path);
+ status = 1;
+ }
+ }
+
+ switch (a->mode & S_IFMT) {
+ case S_IFSOCK:
+ case S_IFIFO:
+ break;
+ case S_IFBLK:
+ case S_IFCHR:
+ if (a->data.devno != b->data.devno) {
+ fprintf(stdout, "%s has different device number\n",
+ path);
+ status = 1;
+ }
+ break;
+ case S_IFLNK:
+ if (strcmp(a->data.slink_target, b->data.slink_target) != 0) {
+ fprintf(stdout, "%s has a different link target\n",
+ path);
+ }
+ break;
+ case S_IFDIR:
+ ret = compare_dir_entries(a, b);
+ if (ret < 0) {
+ status = -1;
+ break;
+ }
+ if (ret > 0)
+ status = 1;
+
+ free(path);
+ path = NULL;
+
+ ait = a->data.dir->children;
+ bit = b->data.dir->children;
+
+ while (ait != NULL && bit != NULL) {
+ ret = node_compare(ait, bit);
+ if (ret < 0)
+ return -1;
+ if (ret > 0)
+ status = 1;
+
+ ait = ait->next;
+ bit = bit->next;
+ }
+ break;
+ case S_IFREG:
+ ret = compare_files(a->data.file, b->data.file, path);
+ if (ret < 0) {
+ status = -1;
+ } else if (ret > 0) {
+ fprintf(stdout, "regular file %s differs\n", path);
+ status = 1;
+ }
+ break;
+ default:
+ fprintf(stdout, "%s has unknown type, ignoring\n", path);
+ break;
+ }
+
+ free(path);
+ return status;
+}