summaryrefslogtreecommitdiff
path: root/difftool/compare_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'difftool/compare_file.c')
-rw-r--r--difftool/compare_file.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/difftool/compare_file.c b/difftool/compare_file.c
new file mode 100644
index 0000000..c424220
--- /dev/null
+++ b/difftool/compare_file.c
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * compare_file.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "difftool.h"
+
+int compare_files(file_info_t *a, file_info_t *b, const char *path)
+{
+ uint64_t offset, size, diff;
+ int ret = 0, afd, bfd;
+ void *aptr, *bptr;
+
+ if (a->size != b->size)
+ return 1;
+
+ if (pushd(first_path))
+ return -1;
+ afd = open(path, O_RDONLY);
+ if (afd < 0) {
+ fprintf(stderr, "%s/%s: %s\n", first_path, path,
+ strerror(errno));
+ return -1;
+ }
+ if (popd())
+ goto fail_afd;
+
+ if (pushd(second_path))
+ goto fail_afd;
+ bfd = open(path, O_RDONLY);
+ if (bfd < 0) {
+ fprintf(stderr, "%s/%s: %s\n", second_path, path,
+ strerror(errno));
+ goto fail_afd;
+ }
+ if (popd())
+ goto fail_bfd;
+
+ size = a->size;
+
+ for (offset = 0; offset < size; offset += diff) {
+ diff = size - offset;
+ if (diff > MAX_WINDOW_SIZE)
+ diff = MAX_WINDOW_SIZE;
+
+ aptr = mmap(NULL, diff, PROT_READ, MAP_SHARED, afd, offset);
+ if (aptr == MAP_FAILED) {
+ fprintf(stderr, "mmap %s/%s: %s\n", first_path, path,
+ strerror(errno));
+ goto fail_bfd;
+ }
+
+ bptr = mmap(NULL, diff, PROT_READ, MAP_SHARED, bfd, offset);
+ if (bptr == MAP_FAILED) {
+ fprintf(stderr, "mmap %s/%s: %s\n", second_path, path,
+ strerror(errno));
+ goto fail_bfd;
+ }
+
+ ret = memcmp(aptr, bptr, diff);
+ munmap(aptr, diff);
+ munmap(bptr, diff);
+
+ if (ret != 0)
+ break;
+ }
+
+ close(afd);
+ close(bfd);
+ return ret;
+fail_bfd:
+ close(bfd);
+fail_afd:
+ close(afd);
+ return -1;
+}