1: static char *sccsid = "@(#)diffdir.c 4.5 (Berkeley) 81/02/28";
2:
3: #include "diff.h"
4: /*
5: * diff - directory comparison
6: */
7: #define d_flags d_ino
8:
9: #define ONLY 1 /* Only in this directory */
10: #define SAME 2 /* Both places and same */
11: #define DIFFER 4 /* Both places and different */
12: #define DIRECT 8 /* Directory */
13:
14: struct direct *setupdir();
15: int ;
16: char title[2*BUFSIZ], *etitle;
17:
18: diffdir(argv)
19: char **argv;
20: {
21: register struct direct *d1, *d2;
22: struct direct *dir1, *dir2;
23: register int i;
24: int cmp;
25:
26: if (opt == D_IFDEF) {
27: fprintf(stderr, "diff: can't specify -I with directories\n");
28: done();
29: }
30: if (opt == D_EDIT && (sflag || lflag))
31: fprintf(stderr,
32: "diff: warning: shouldn't give -s or -l with -e\n");
33: title[0] = 0;
34: strcpy(title, "diff ");
35: for (i = 1; diffargv[i+2]; i++) {
36: if (!strcmp(diffargv[i], "-"))
37: continue; /* was -S, dont look silly */
38: strcat(title, diffargv[i]);
39: strcat(title, " ");
40: }
41: for (etitle = title; *etitle; etitle++)
42: ;
43: setfile(&file1, &efile1, file1);
44: setfile(&file2, &efile2, file2);
45: argv[0] = file1;
46: argv[1] = file2;
47: dir1 = setupdir(file1);
48: dir2 = setupdir(file2);
49: d1 = dir1; d2 = dir2;
50: while (d1->d_name[0] != 0 || d2->d_name[0] != 0) {
51: if (d1->d_name[0] && useless(d1->d_name)) {
52: d1++;
53: continue;
54: }
55: if (d2->d_name[0] && useless(d2->d_name)) {
56: d2++;
57: continue;
58: }
59: if (d1->d_name[0] == 0)
60: cmp = 1;
61: else if (d2->d_name[0] == 0)
62: cmp = -1;
63: else
64: cmp = strncmp(d1->d_name, d2->d_name, DIRSIZ);
65: if (cmp < 0) {
66: if (lflag)
67: d1->d_flags |= ONLY;
68: else if (opt == 0 || opt == 2) {
69: only(d1, 1);
70: printf(": %.*s\n", DIRSIZ, d1->d_name);
71: }
72: d1++;
73: } else if (cmp == 0) {
74: compare(d1);
75: d1++;
76: d2++;
77: } else {
78: if (lflag)
79: d2->d_flags |= ONLY;
80: else if (opt == 0 || opt == 2) {
81: only(d2, 2);
82: printf(": %.*s\n", DIRSIZ, d2->d_name);
83: }
84: d2++;
85: }
86: }
87: if (lflag) {
88: scanpr(dir1, ONLY, "Only in %.*s", file1, efile1);
89: scanpr(dir2, ONLY, "Only in %.*s", file2, efile2);
90: scanpr(dir1, SAME, "Common identical files", 0, 0);
91: scanpr(dir1, DIFFER, "Binary files which differ", 0, 0);
92: scanpr(dir1, DIRECT, "Common subdirectories", 0, 0);
93: }
94: if (rflag) {
95: if (header && lflag)
96: printf("\f");
97: for (d1 = dir1; d1->d_name[0]; d1++) {
98: if ((d1->d_flags & DIRECT) == 0)
99: continue;
100: strncpy(efile1, d1->d_name, DIRSIZ);
101: strncpy(efile2, d1->d_name, DIRSIZ);
102: /*
103: if (opt != D_EDIT) {
104: *etitle = 0;
105: printf("%s%s %s\n", title, file1, file2);
106: }
107: */
108: calldiff(0);
109: }
110: }
111: }
112:
113: setfile(fpp, epp, file)
114: char **fpp, **epp;
115: char *file;
116: {
117: register char *cp;
118:
119: *fpp = malloc(BUFSIZ);
120: if (*fpp == 0) {
121: fprintf(stderr, "diff: ran out of memory\n");
122: exit(1);
123: }
124: strcpy(*fpp, file);
125: for (cp = *fpp; *cp; cp++)
126: continue;
127: *cp++ = '/';
128: *epp = cp;
129: }
130:
131: scanpr(dp, test, title, file, efile)
132: register struct direct *dp;
133: int test;
134: char *title, *file, *efile;
135: {
136: int titled = 0;
137:
138: for (; dp->d_name[0]; dp++)
139: if (dp->d_flags & test) {
140: if (titled == 0) {
141: if (header == 0) {
142: if (anychange)
143: printf("\f");
144: header = 1;
145: } else
146: printf("\n");
147: printf(title, efile - file - 1, file);
148: printf(":\n");
149: titled = 1;
150: }
151: ptname(dp);
152: }
153: }
154:
155: only(dp, which)
156: struct direct *dp;
157: int which;
158: {
159: char *file = which == 1 ? file1 : file2;
160: char *efile = which == 1 ? efile1 : efile2;
161:
162: printf("Only in %.*s", efile - file - 1, file, DIRSIZ, dp->d_name);
163: }
164:
165: ptname(dp)
166: struct direct *dp;
167: {
168:
169: printf("\t%.*s\n", DIRSIZ, dp->d_name);
170: }
171:
172: int entcmp();
173:
174: struct direct *
175: setupdir(cp)
176: char *cp;
177: {
178: struct stat stb;
179: register struct direct *dp, *ep;
180:
181: close(0);
182: if (open(cp, 0) < 0) {
183: fprintf(stderr, "diff: ");
184: perror(cp);
185: done();
186: }
187: fstat(0, &stb);
188: dp = (struct direct *)malloc((unsigned) stb.st_size + sizeof (struct direct));
189: if (dp == 0) {
190: fprintf(stderr, "diff: ran out of memory\n");
191: done();
192: }
193: if (read(0, (char *)dp, (int)stb.st_size) != (int)stb.st_size) {
194: fprintf(stderr, "diff: ");
195: perror(cp);
196: done();
197: }
198: qsort(dp, (int) stb.st_size / sizeof (struct direct),
199: sizeof (struct direct), entcmp);
200: ep = &dp[stb.st_size / sizeof (struct direct)];
201: ep->d_name[0] = 0;
202: while (--ep >= dp && ep->d_ino == 0)
203: ep->d_name[0] = 0;
204: for (; ep >= dp; ep--)
205: ep->d_flags = 0;
206: return (dp);
207: }
208:
209: entcmp(d1, d2)
210: struct direct *d1, *d2;
211: {
212:
213: if (d1->d_ino == 0)
214: return (1);
215: if (d2->d_ino == 0)
216: return (-1);
217: return (strncmp(d1->d_name, d2->d_name, DIRSIZ));
218: }
219:
220: compare(dp)
221: register struct direct *dp;
222: {
223: register int i, j;
224: int f1, f2, fmt1, fmt2;
225: struct stat stb1, stb2;
226: int flag = 0;
227: char buf1[BUFSIZ], buf2[BUFSIZ];
228:
229: strncpy(efile1, dp->d_name, DIRSIZ);
230: strncpy(efile2, dp->d_name, DIRSIZ);
231: f1 = open(file1, 0);
232: if (f1 < 0) {
233: perror(file1);
234: return;
235: }
236: f2 = open(file2, 0);
237: if (f2 < 0) {
238: perror(file2);
239: close(f1);
240: return;
241: }
242: fstat(f1, &stb1); fstat(f2, &stb2);
243: fmt1 = stb1.st_mode & S_IFMT;
244: fmt2 = stb2.st_mode & S_IFMT;
245: if (fmt1 != S_IFREG || fmt2 != S_IFREG) {
246: if (fmt1 == fmt2) {
247: if (fmt1 != S_IFDIR && stb1.st_rdev == stb2.st_rdev)
248: goto same;
249: if (fmt1 == S_IFDIR) {
250: dp->d_flags = DIRECT;
251: if (lflag || opt == D_EDIT)
252: goto closem;
253: printf("Common subdirectories: %s and %s\n",
254: file1, file2);
255: goto closem;
256: }
257: }
258: goto notsame;
259: }
260: if (stb1.st_size != stb2.st_size)
261: goto notsame;
262: for (;;) {
263: i = read(f1, buf1, BUFSIZ);
264: j = read(f2, buf2, BUFSIZ);
265: if (i < 0 || j < 0 || i != j)
266: goto notsame;
267: if (i == 0 && j == 0)
268: goto same;
269: for (j = 0; j < i; j++)
270: if (buf1[j] != buf2[j])
271: goto notsame;
272: }
273: same:
274: if (sflag == 0)
275: goto closem;
276: if (lflag)
277: dp->d_flags = SAME;
278: else
279: printf("Files %s and %s are identical\n", file1, file2);
280: goto closem;
281: notsame:
282: if (!ascii(f1) || !ascii(f2)) {
283: if (lflag)
284: dp->d_flags |= DIFFER;
285: else if (opt == D_NORMAL || opt == D_CONTEXT)
286: printf("Binary files %s and %s differ\n",
287: file1, file2);
288: goto closem;
289: }
290: close(f1); close(f2);
291: anychange = 1;
292: if (lflag)
293: calldiff(title);
294: else {
295: if (opt == D_EDIT) {
296: printf("ed - %.*s << '-*-END-*-'\n",
297: DIRSIZ, dp->d_name);
298: calldiff(0);
299: } else {
300: printf("%s%s %s\n", title, file1, file2);
301: calldiff(0);
302: }
303: if (opt == D_EDIT)
304: printf("w\nq\n-*-END-*-\n");
305: }
306: return;
307: closem:
308: close(f1); close(f2);
309: }
310:
311: char *prargs[] = { "pr", "-h", 0, "-f", 0, 0 };
312:
313: calldiff(wantpr)
314: char *wantpr;
315: {
316: int pid, status, status2, pv[2];
317:
318: prargs[2] = wantpr;
319: fflush(stdout);
320: if (wantpr) {
321: sprintf(etitle, "%s %s", file1, file2);
322: pipe(pv);
323: pid = fork();
324: if (pid == -1) {
325: fprintf(stderr, "No more processes");
326: done();
327: }
328: if (pid == 0) {
329: close(0);
330: dup(pv[0]);
331: close(pv[0]);
332: close(pv[1]);
333: execv(pr+4, prargs);
334: execv(pr, prargs);
335: perror(pr);
336: done();
337: }
338: }
339: pid = fork();
340: if (pid == -1) {
341: fprintf(stderr, "diff: No more processes\n");
342: done();
343: }
344: if (pid == 0) {
345: if (wantpr) {
346: close(1);
347: dup(pv[1]);
348: close(pv[0]);
349: close(pv[1]);
350: }
351: execv(diff+4, diffargv);
352: execv(diff, diffargv);
353: perror(diff);
354: done();
355: }
356: close(pv[0]);
357: close(pv[1]);
358: while (wait(&status) != pid)
359: continue;
360: while (wait(&status2) != -1)
361: continue;
362: /*
363: if ((status >> 8) >= 2)
364: done();
365: */
366: }
367:
368: #include <a.out.h>
369:
370: ascii(f)
371: int f;
372: {
373: char buf[BUFSIZ];
374: register int cnt;
375: register char *cp;
376:
377: lseek(f, (long)0, 0);
378: cnt = read(f, buf, BUFSIZ);
379: if (cnt >= sizeof (struct exec)) {
380: struct exec hdr;
381: hdr = *(struct exec *)buf;
382: if (!N_BADMAG(hdr))
383: return (0);
384: }
385: cp = buf;
386: while (--cnt >= 0)
387: if (*cp++ & 0200)
388: return (0);
389: return (1);
390: }
391:
392: /*
393: * THIS IS CRUDE.
394: */
395: useless(cp)
396: register char *cp;
397: {
398:
399: if (cp[0] == '.')
400: return (1);
401: if (start && strcmp(start, cp) > 0)
402: return (1);
403: return (0);
404: }