|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <bio.h> | 
|  | #include "diff.h" | 
|  |  | 
|  | static int | 
|  | itemcmp(const void *v1, const void *v2) | 
|  | { | 
|  | char *const*d1 = v1, *const*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(mflag ? 0 : 2, "can't open %s\n", name); | 
|  | return nil; | 
|  | } | 
|  | 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; | 
|  | if(df == nil || dt == nil) | 
|  | goto Out; | 
|  | 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++; | 
|  | } | 
|  | Out: | 
|  | for (df = dirf; df && *df; df++) | 
|  | FREE(*df); | 
|  | for (dt = dirt; dt && *dt; dt++) | 
|  | FREE(*dt); | 
|  | FREE(dirf); | 
|  | FREE(dirt); | 
|  | } |