xref: /plan9/sys/src/cmd/diff/diffdir.c (revision 56e2d73c64e38b03a72b5fdcfb50b0a26425b0f0)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "diff.h"
5 
6 static int
itemcmp(void * v1,void * v2)7 itemcmp(void *v1, void *v2)
8 {
9 	char **d1 = v1, **d2 = v2;
10 
11 	return strcmp(*d1, *d2);
12 }
13 
14 static char **
scandir(char * name)15 scandir(char *name)
16 {
17 	char **cp;
18 	Dir *db;
19 	int nitems;
20 	int fd, n;
21 
22 	if ((fd = open(name, OREAD)) < 0) {
23 		fprint(2, "%s: can't open %s: %r\n", argv0, name);
24 		/* fake an empty directory */
25 		cp = MALLOC(char*, 1);
26 		cp[0] = 0;
27 		return cp;
28 	}
29 	cp = 0;
30 	nitems = 0;
31 	if((n = dirreadall(fd, &db)) > 0){
32 		while (n--) {
33 			cp = REALLOC(cp, char *, (nitems+1));
34 			cp[nitems] = MALLOC(char, strlen((db+n)->name)+1);
35 			strcpy(cp[nitems], (db+n)->name);
36 			nitems++;
37 		}
38 		free(db);
39 	}
40 	cp = REALLOC(cp, char*, (nitems+1));
41 	cp[nitems] = 0;
42 	close(fd);
43 	qsort((char *)cp, nitems, sizeof(char*), itemcmp);
44 	return cp;
45 }
46 
47 static int
isdotordotdot(char * p)48 isdotordotdot(char *p)
49 {
50 	if (*p == '.') {
51 		if (!p[1])
52 			return 1;
53 		if (p[1] == '.' && !p[2])
54 			return 1;
55 	}
56 	return 0;
57 }
58 
59 void
diffdir(char * f,char * t,int level)60 diffdir(char *f, char *t, int level)
61 {
62 	char  **df, **dt, **dirf, **dirt;
63 	char *from, *to;
64 	int res;
65 	char fb[MAXPATHLEN+1], tb[MAXPATHLEN+1];
66 
67 	df = scandir(f);
68 	dt = scandir(t);
69 	dirf = df;
70 	dirt = dt;
71 	while (*df || *dt) {
72 		from = *df;
73 		to = *dt;
74 		if (from && isdotordotdot(from)) {
75 			df++;
76 			continue;
77 		}
78 		if (to && isdotordotdot(to)) {
79 			dt++;
80 			continue;
81 		}
82 		if (!from)
83 			res = 1;
84 		else if (!to)
85 			res = -1;
86 		else
87 			res = strcmp(from, to);
88 		if (res < 0) {
89 			if (mode == 0 || mode == 'n')
90 				Bprint(&stdout, "Only in %s: %s\n", f, from);
91 			df++;
92 			continue;
93 		}
94 		if (res > 0) {
95 			if (mode == 0 || mode == 'n')
96 				Bprint(&stdout, "Only in %s: %s\n", t, to);
97 			dt++;
98 			continue;
99 		}
100 		if (mkpathname(fb, f, from))
101 			continue;
102 		if (mkpathname(tb, t, to))
103 			continue;
104 		diff(fb, tb, level+1);
105 		df++; dt++;
106 	}
107 	for (df = dirf; *df; df++)
108 		FREE(*df);
109 	for (dt = dirt; *dt; dt++)
110 		FREE(*dt);
111 	FREE(dirf);
112 	FREE(dirt);
113 }
114