xref: /plan9/sys/src/cmd/diff/diffdir.c (revision 56e2d73c64e38b03a72b5fdcfb50b0a26425b0f0)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include "diff.h"
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier static int
itemcmp(void * v1,void * v2)77dd7cddfSDavid du Colombier itemcmp(void *v1, void *v2)
83e12c5d1SDavid du Colombier {
97dd7cddfSDavid du Colombier 	char **d1 = v1, **d2 = v2;
107dd7cddfSDavid du Colombier 
11bd389b36SDavid du Colombier 	return strcmp(*d1, *d2);
123e12c5d1SDavid du Colombier }
133e12c5d1SDavid du Colombier 
143e12c5d1SDavid du Colombier static char **
scandir(char * name)153e12c5d1SDavid du Colombier scandir(char *name)
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier 	char **cp;
189a747e4fSDavid du Colombier 	Dir *db;
193e12c5d1SDavid du Colombier 	int nitems;
203e12c5d1SDavid du Colombier 	int fd, n;
213e12c5d1SDavid du Colombier 
22*56e2d73cSDavid du Colombier 	if ((fd = open(name, OREAD)) < 0) {
23*56e2d73cSDavid du Colombier 		fprint(2, "%s: can't open %s: %r\n", argv0, name);
24*56e2d73cSDavid du Colombier 		/* fake an empty directory */
25*56e2d73cSDavid du Colombier 		cp = MALLOC(char*, 1);
26*56e2d73cSDavid du Colombier 		cp[0] = 0;
27*56e2d73cSDavid du Colombier 		return cp;
28*56e2d73cSDavid du Colombier 	}
293e12c5d1SDavid du Colombier 	cp = 0;
303e12c5d1SDavid du Colombier 	nitems = 0;
319a747e4fSDavid du Colombier 	if((n = dirreadall(fd, &db)) > 0){
323e12c5d1SDavid du Colombier 		while (n--) {
333e12c5d1SDavid du Colombier 			cp = REALLOC(cp, char *, (nitems+1));
349a747e4fSDavid du Colombier 			cp[nitems] = MALLOC(char, strlen((db+n)->name)+1);
359a747e4fSDavid du Colombier 			strcpy(cp[nitems], (db+n)->name);
363e12c5d1SDavid du Colombier 			nitems++;
373e12c5d1SDavid du Colombier 		}
389a747e4fSDavid du Colombier 		free(db);
393e12c5d1SDavid du Colombier 	}
403e12c5d1SDavid du Colombier 	cp = REALLOC(cp, char*, (nitems+1));
413e12c5d1SDavid du Colombier 	cp[nitems] = 0;
423e12c5d1SDavid du Colombier 	close(fd);
433e12c5d1SDavid du Colombier 	qsort((char *)cp, nitems, sizeof(char*), itemcmp);
443e12c5d1SDavid du Colombier 	return cp;
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier static int
isdotordotdot(char * p)483e12c5d1SDavid du Colombier isdotordotdot(char *p)
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	if (*p == '.') {
513e12c5d1SDavid du Colombier 		if (!p[1])
523e12c5d1SDavid du Colombier 			return 1;
533e12c5d1SDavid du Colombier 		if (p[1] == '.' && !p[2])
543e12c5d1SDavid du Colombier 			return 1;
553e12c5d1SDavid du Colombier 	}
563e12c5d1SDavid du Colombier 	return 0;
573e12c5d1SDavid du Colombier }
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier void
diffdir(char * f,char * t,int level)603e12c5d1SDavid du Colombier diffdir(char *f, char *t, int level)
613e12c5d1SDavid du Colombier {
623e12c5d1SDavid du Colombier 	char  **df, **dt, **dirf, **dirt;
633e12c5d1SDavid du Colombier 	char *from, *to;
643e12c5d1SDavid du Colombier 	int res;
653e12c5d1SDavid du Colombier 	char fb[MAXPATHLEN+1], tb[MAXPATHLEN+1];
663e12c5d1SDavid du Colombier 
67bd389b36SDavid du Colombier 	df = scandir(f);
68bd389b36SDavid du Colombier 	dt = scandir(t);
69bd389b36SDavid du Colombier 	dirf = df;
70bd389b36SDavid du Colombier 	dirt = dt;
713e12c5d1SDavid du Colombier 	while (*df || *dt) {
72bd389b36SDavid du Colombier 		from = *df;
73bd389b36SDavid du Colombier 		to = *dt;
74bd389b36SDavid du Colombier 		if (from && isdotordotdot(from)) {
75bd389b36SDavid du Colombier 			df++;
763e12c5d1SDavid du Colombier 			continue;
77bd389b36SDavid du Colombier 		}
78bd389b36SDavid du Colombier 		if (to && isdotordotdot(to)) {
79bd389b36SDavid du Colombier 			dt++;
803e12c5d1SDavid du Colombier 			continue;
81bd389b36SDavid du Colombier 		}
823e12c5d1SDavid du Colombier 		if (!from)
833e12c5d1SDavid du Colombier 			res = 1;
843e12c5d1SDavid du Colombier 		else if (!to)
853e12c5d1SDavid du Colombier 			res = -1;
863e12c5d1SDavid du Colombier 		else
873e12c5d1SDavid du Colombier 			res = strcmp(from, to);
883e12c5d1SDavid du Colombier 		if (res < 0) {
897dd7cddfSDavid du Colombier 			if (mode == 0 || mode == 'n')
903e12c5d1SDavid du Colombier 				Bprint(&stdout, "Only in %s: %s\n", f, from);
91bd389b36SDavid du Colombier 			df++;
923e12c5d1SDavid du Colombier 			continue;
933e12c5d1SDavid du Colombier 		}
943e12c5d1SDavid du Colombier 		if (res > 0) {
957dd7cddfSDavid du Colombier 			if (mode == 0 || mode == 'n')
963e12c5d1SDavid du Colombier 				Bprint(&stdout, "Only in %s: %s\n", t, to);
97bd389b36SDavid du Colombier 			dt++;
983e12c5d1SDavid du Colombier 			continue;
993e12c5d1SDavid du Colombier 		}
1003e12c5d1SDavid du Colombier 		if (mkpathname(fb, f, from))
1013e12c5d1SDavid du Colombier 			continue;
1023e12c5d1SDavid du Colombier 		if (mkpathname(tb, t, to))
1033e12c5d1SDavid du Colombier 			continue;
1043e12c5d1SDavid du Colombier 		diff(fb, tb, level+1);
105bd389b36SDavid du Colombier 		df++; dt++;
1063e12c5d1SDavid du Colombier 	}
1073e12c5d1SDavid du Colombier 	for (df = dirf; *df; df++)
1083e12c5d1SDavid du Colombier 		FREE(*df);
1093e12c5d1SDavid du Colombier 	for (dt = dirt; *dt; dt++)
1103e12c5d1SDavid du Colombier 		FREE(*dt);
1113e12c5d1SDavid du Colombier 	FREE(dirf);
1123e12c5d1SDavid du Colombier 	FREE(dirt);
1133e12c5d1SDavid du Colombier }
114