static char *sccsid = "@(#)diffdir.c 4.5 (Berkeley) 81/02/28"; #include "diff.h" /* * diff - directory comparison */ #define d_flags d_ino #define ONLY 1 /* Only in this directory */ #define SAME 2 /* Both places and same */ #define DIFFER 4 /* Both places and different */ #define DIRECT 8 /* Directory */ struct direct *setupdir(); int header; char title[2*BUFSIZ], *etitle; diffdir(argv) char **argv; { register struct direct *d1, *d2; struct direct *dir1, *dir2; register int i; int cmp; if (opt == D_EDIT && sflag) fprintf(stderr, "diff: warning: shouldn't give -s with -e\n"); title[0] = 0; strcpy(title, "diff "); for (i = 1; diffargv[i+2]; i++) { if (strcmp(diffargv[i], "-") == 0) continue; /* was -S, dont look silly */ strcat(title, diffargv[i]); strcat(title, " "); } for (etitle = title; *etitle; etitle++) ; setfile(&file1, &efile1, file1); setfile(&file2, &efile2, file2); argv[0] = file1; argv[1] = file2; dir1 = setupdir(file1); dir2 = setupdir(file2); d1 = dir1; d2 = dir2; while (d1->d_name[0] != 0 || d2->d_name[0] != 0) { if (d1->d_name[0] && isdotordotdot(d1->d_name)) { d1++; continue; } if (d2->d_name[0] && isdotordotdot(d2->d_name)) { d2++; continue; } if (d1->d_name[0] == 0) cmp = 1; else if (d2->d_name[0] == 0) cmp = -1; else cmp = strncmp(d1->d_name, d2->d_name, DIRSIZ); if (cmp < 0) { if (opt == 0 || opt == 2) { only(d1, 1); printf(": %.*s\n", DIRSIZ, d1->d_name); } d1++; } else if (cmp == 0) { compare(d1); d1++; d2++; } else { if (opt == 0 || opt == 2) { only(d2, 2); printf(": %.*s\n", DIRSIZ, d2->d_name); } d2++; } } if (rflag) { for (d1 = dir1; d1->d_name[0]; d1++) { if ((d1->d_flags & DIRECT) == 0) continue; strncpy(efile1, d1->d_name, DIRSIZ); strncpy(efile2, d1->d_name, DIRSIZ); calldiff(); } } } setfile(fpp, epp, file) char **fpp, **epp; char *file; { register char *cp; *fpp = malloc(BUFSIZ); if (*fpp == 0) { fprintf(stderr, "diff: ran out of memory\n"); exit(1); } strcpy(*fpp, file); for (cp = *fpp; *cp; cp++) continue; *cp++ = '/'; *epp = cp; } only(dp, which) struct direct *dp; int which; { char *file = which == 1 ? file1 : file2; char *efile = which == 1 ? efile1 : efile2; printf("Only in %.*s", efile - file - 1, file, DIRSIZ, dp->d_name); } ptname(dp) struct direct *dp; { printf("\t%.*s\n", DIRSIZ, dp->d_name); } int entcmp(); struct direct * setupdir(cp) char *cp; { struct stat stb; register struct direct *dp, *ep; close(0); if (open(cp, 0) < 0) { fprintf(stderr, "diff: "); perror(cp); done(); } fstat(0, &stb); dp = (struct direct *)malloc((unsigned) stb.st_size + sizeof (struct direct)); if (dp == 0) { fprintf(stderr, "diff: ran out of memory\n"); done(); } if (read(0, (char *)dp, (int)stb.st_size) != (int)stb.st_size) { fprintf(stderr, "diff: "); perror(cp); done(); } qsort(dp, (int) stb.st_size / sizeof (struct direct), sizeof (struct direct), entcmp); ep = &dp[stb.st_size / sizeof (struct direct)]; ep->d_name[0] = 0; while (--ep >= dp && ep->d_ino == 0) ep->d_name[0] = 0; for (; ep >= dp; ep--) ep->d_flags = 0; return (dp); } entcmp(d1, d2) struct direct *d1, *d2; { if (d1->d_ino == 0) return (1); if (d2->d_ino == 0) return (-1); return (strncmp(d1->d_name, d2->d_name, DIRSIZ)); } compare(dp) register struct direct *dp; { register int i, j; int f1, f2, fmt1, fmt2; struct stat stb1, stb2; int flag = 0; char buf1[BUFSIZ], buf2[BUFSIZ]; strncpy(efile1, dp->d_name, DIRSIZ); strncpy(efile2, dp->d_name, DIRSIZ); f1 = open(file1, 0); if (f1 < 0) { perror(file1); return; } f2 = open(file2, 0); if (f2 < 0) { perror(file2); close(f1); return; } fstat(f1, &stb1); fstat(f2, &stb2); fmt1 = stb1.st_mode & S_IFMT; fmt2 = stb2.st_mode & S_IFMT; if (fmt1 != S_IFREG || fmt2 != S_IFREG) { if (fmt1 == fmt2) { if (fmt1 != S_IFDIR && stb1.st_rdev == stb2.st_rdev) goto same; if (fmt1 == S_IFDIR) { dp->d_flags = DIRECT; if (opt == D_EDIT) goto closem; printf("Common subdirectories: %s and %s\n", file1, file2); goto closem; } } goto notsame; } if (stb1.st_size != stb2.st_size) goto notsame; for (;;) { i = read(f1, buf1, BUFSIZ); j = read(f2, buf2, BUFSIZ); if (i < 0 || j < 0 || i != j) goto notsame; if (i == 0 && j == 0) goto same; for (j = 0; j < i; j++) if (buf1[j] != buf2[j]) goto notsame; } same: if (sflag == 0) goto closem; printf("Files %s and %s are identical\n", file1, file2); goto closem; notsame: if (!ascii(f1) || !ascii(f2)) { if (opt == D_NORMAL || opt == D_CONTEXT) printf("Binary files %s and %s differ\n", file1, file2); goto closem; } close(f1); close(f2); anychange = 1; if (opt == D_EDIT) { printf("ed - %.*s << '-*-END-*-'\n", DIRSIZ, dp->d_name); calldiff(); } else { printf("%s%s %s\n", title, file1, file2); calldiff(); } if (opt == D_EDIT) printf("w\nq\n-*-END-*-\n"); return; closem: close(f1); close(f2); } calldiff() { int pid, status, status2, pv[2]; fflush(stdout); pid = fork(); if (pid == -1) { fprintf(stderr, "diff: No more processes\n"); done(); } if (pid == 0) { execv(diff+4, diffargv); execv(diff, diffargv); perror(diff); done(); } close(pv[0]); close(pv[1]); while (wait(&status) != pid) continue; while (wait(&status2) != -1) continue; } #include <a.out.h> ascii(f) int f; { char buf[BUFSIZ]; register int cnt; register char *cp; lseek(f, (long)0, 0); cnt = read(f, buf, BUFSIZ); if (cnt >= sizeof (struct exec)) { struct exec hdr; hdr = *(struct exec *)buf; if (!N_BADMAG(hdr)) return (0); } cp = buf; while (--cnt >= 0) if (*cp++ & 0200) return (0); return (1); } isdotordotdot(p) register char *p; { if (*p == '.') { if (*(p+1) == '\0') return 1; if (*(p+1) == '.' && *(p+2) == '\0') return 1; } return 0; }