add normalizepath_cstr()
[rofl0r-libulz.git] / examples / find_identical_files.c
blob69ff480237fa6145f622907bc0c74be1b63cb6f2
1 #include "../include/filelist.h"
2 #include "../include/filelib.h"
3 #include "../include/logger.h"
4 #include <string.h>
5 #include <stdio.h>
7 static int stringptr_endswithchar(stringptr* s, int ch) {
8 if(stringptr_getsize(s) == 0) return 0;
9 return stringptr_get(s)[stringptr_getsize(s)-1] == ch;
12 static int compare_files(stringptr* fn1, stringptr* fn2) {
13 FILE *f1 = fopen(stringptr_get(fn1), "r");
14 FILE *f2 = fopen(stringptr_get(fn2), "r");
15 int ret = 1;
16 size_t n;
17 while(1) {
18 unsigned char buf1[16*1024];
19 unsigned char buf2[16*1024];
20 n = fread(buf1, 1, sizeof buf1, f1);
21 if(n == 0) { ret = 0; break; }
22 if(n != fread(buf2, 1, sizeof buf2, f2)) break;
23 if(memcmp(buf1, buf2, n)) break;
25 fclose(f1);
26 fclose(f2);
27 return ret;
30 static int mode = 0; /* 0: identical, 1: not identical */
32 static int process_path(stringptr* dir1, stringptr* dir2) {
33 filelist fl1, fl2;
34 int ret;
35 ret = filelist_search(&fl1, dir1, SPL("*"), FLF_EXCLUDE_PATH|FLF_INCLUDE_HIDDEN);
36 if(ret) return ret;
37 ret = filelist_search(&fl2, dir2, SPL("*"), FLF_EXCLUDE_PATH|FLF_INCLUDE_HIDDEN);
38 if(ret) return ret;
39 size_t i, j;
40 for(i=0; i < stringptrlist_getsize(fl1.files); ++i) {
41 stringptr *f1 = stringptrlist_get(fl1.files, i);
42 if(!stringptrlist_contains(fl2.files, f1)) continue;
43 stringptr* full1 = stringptr_concat(dir1, stringptr_endswithchar(dir1, '/') ? SPL("") : SPL("/"), f1, NULL);
44 stringptr* full2 = stringptr_concat(dir2, stringptr_endswithchar(dir1, '/') ? SPL("") : SPL("/"), f1, NULL);
45 if(stringptr_endswithchar(f1, '/')) {
46 ret = process_path(full1, full2);
47 if(ret) return ret;
48 goto next;
50 if(getfilesize(stringptr_get(full1)) != getfilesize(stringptr_get(full2)))
51 if(mode) goto print;
52 else goto next;
53 if(compare_files(full1, full2) == mode) {
54 print:
55 log_puts(1, full1);
56 log_putln(1);
58 next:
59 stringptr_free(full1);
60 stringptr_free(full2);
62 filelist_free(&fl1);
63 filelist_free(&fl2);
66 static int usage() {
67 log_puts(2, SPL(
68 "usage: PROG MODE DIR1 DIR2\n"
69 "MODE: i - identical or n - not identical\n"
70 "finds all (not) identical files in DIR1/2 and its subdirs.\n"
71 "prints filenames of DIR1 that match MODE.\n"
72 "files that exist only in DIR1 or DIR2 are excluded.\n"
73 ));
74 return 1;
77 int main(int argc, char** argv) {
78 if(argc != 4) return usage();
79 mode = argv[1][0] == 'i' ? 0 : 1;
80 SPDECLAREC(dir1, argv[2]);
81 SPDECLAREC(dir2, argv[3]);
82 int ret = process_path(dir1, dir2);
83 return ret;