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