aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/diff/diffdir.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-11-23 18:03:02 +0000
committerrsc <devnull@localhost>2003-11-23 18:03:02 +0000
commit5993a8f2756bc455101a8c9ce95347d5050e7883 (patch)
treedf94fe66c46612af899e6622c808d42a52542b8c /src/cmd/diff/diffdir.c
parentcfabc3ed1638efc186ebd26bdaa3dfb5663dff17 (diff)
the one true diff.
at least it can handle "diff file1 file2 dir".
Diffstat (limited to 'src/cmd/diff/diffdir.c')
-rw-r--r--src/cmd/diff/diffdir.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/cmd/diff/diffdir.c b/src/cmd/diff/diffdir.c
new file mode 100644
index 00000000..41e4fbf4
--- /dev/null
+++ b/src/cmd/diff/diffdir.c
@@ -0,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "diff.h"
+
+static int
+itemcmp(void *v1, void *v2)
+{
+ char **d1 = v1, **d2 = v2;
+
+ return strcmp(*d1, *d2);
+}
+
+static char **
+scandir(char *name)
+{
+ char **cp;
+ Dir *db;
+ int nitems;
+ int fd, n;
+
+ if ((fd = open(name, OREAD)) < 0)
+ panic(2, "can't open %s\n", name);
+ cp = 0;
+ nitems = 0;
+ if((n = dirreadall(fd, &db)) > 0){
+ while (n--) {
+ cp = REALLOC(cp, char *, (nitems+1));
+ cp[nitems] = MALLOC(char, strlen((db+n)->name)+1);
+ strcpy(cp[nitems], (db+n)->name);
+ nitems++;
+ }
+ free(db);
+ }
+ cp = REALLOC(cp, char*, (nitems+1));
+ cp[nitems] = 0;
+ close(fd);
+ qsort((char *)cp, nitems, sizeof(char*), itemcmp);
+ return cp;
+}
+
+static int
+isdotordotdot(char *p)
+{
+ if (*p == '.') {
+ if (!p[1])
+ return 1;
+ if (p[1] == '.' && !p[2])
+ return 1;
+ }
+ return 0;
+}
+
+void
+diffdir(char *f, char *t, int level)
+{
+ char **df, **dt, **dirf, **dirt;
+ char *from, *to;
+ int res;
+ char fb[MAXPATHLEN+1], tb[MAXPATHLEN+1];
+
+ df = scandir(f);
+ dt = scandir(t);
+ dirf = df;
+ dirt = dt;
+ while (*df || *dt) {
+ from = *df;
+ to = *dt;
+ if (from && isdotordotdot(from)) {
+ df++;
+ continue;
+ }
+ if (to && isdotordotdot(to)) {
+ dt++;
+ continue;
+ }
+ if (!from)
+ res = 1;
+ else if (!to)
+ res = -1;
+ else
+ res = strcmp(from, to);
+ if (res < 0) {
+ if (mode == 0 || mode == 'n')
+ Bprint(&stdout, "Only in %s: %s\n", f, from);
+ df++;
+ continue;
+ }
+ if (res > 0) {
+ if (mode == 0 || mode == 'n')
+ Bprint(&stdout, "Only in %s: %s\n", t, to);
+ dt++;
+ continue;
+ }
+ if (mkpathname(fb, f, from))
+ continue;
+ if (mkpathname(tb, t, to))
+ continue;
+ diff(fb, tb, level+1);
+ df++; dt++;
+ }
+ for (df = dirf; *df; df++)
+ FREE(*df);
+ for (dt = dirt; *dt; dt++)
+ FREE(*dt);
+ FREE(dirf);
+ FREE(dirt);
+}