Annotation of src/usr.bin/diff/diffdir.c, Revision 1.2
1.2 ! deraadt 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (C) Caldera International Inc. 2001-2002.
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code and documentation must retain the above
! 11: * copyright notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed or owned by Caldera
! 18: * International, Inc.
! 19: * 4. Neither the name of Caldera International, Inc. nor the names of other
! 20: * contributors may be used to endorse or promote products derived from
! 21: * this software without specific prior written permission.
! 22: *
! 23: * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
! 24: * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
! 25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 26: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 27: * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
! 28: * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 29: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 30: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 32: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 33: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 34: * POSSIBILITY OF SUCH DAMAGE.
! 35: */
! 36:
1.1 deraadt 37: static char *sccsid = "@(#)diffdir.c 4.12 (Berkeley) 4/30/89";
38:
39: #include "diff.h"
40: /*
41: * diff - directory comparison
42: */
43: #define d_flags d_ino
44:
45: #define ONLY 1 /* Only in this directory */
46: #define SAME 2 /* Both places and same */
47: #define DIFFER 4 /* Both places and different */
48: #define DIRECT 8 /* Directory */
49:
50: struct dir {
51: u_long d_ino;
52: short d_reclen;
53: short d_namlen;
54: char *d_entry;
55: };
56:
57: struct dir *setupdir();
58: int header;
59: static int dirstatus; /* exit status from diffdir */
60: extern int status;
61: char title[2*BUFSIZ], *etitle;
62:
63: diffdir(argv)
64: char **argv;
65: {
66: register struct dir *d1, *d2;
67: struct dir *dir1, *dir2;
68: register int i;
69: int cmp;
70:
71: if (opt == D_IFDEF) {
72: fprintf(stderr, "diff: can't specify -I with directories\n");
73: done();
74: }
75: if (opt == D_EDIT && (sflag || lflag))
76: fprintf(stderr,
77: "diff: warning: shouldn't give -s or -l with -e\n");
78: title[0] = 0;
79: strcpy(title, "diff ");
80: for (i = 1; diffargv[i+2]; i++) {
81: if (!strcmp(diffargv[i], "-"))
82: continue; /* was -S, dont look silly */
83: strcat(title, diffargv[i]);
84: strcat(title, " ");
85: }
86: for (etitle = title; *etitle; etitle++)
87: ;
88: setfile(&file1, &efile1, file1);
89: setfile(&file2, &efile2, file2);
90: argv[0] = file1;
91: argv[1] = file2;
92: dir1 = setupdir(file1);
93: dir2 = setupdir(file2);
94: d1 = dir1; d2 = dir2;
95: while (d1->d_entry != 0 || d2->d_entry != 0) {
96: if (d1->d_entry && useless(d1->d_entry)) {
97: d1++;
98: continue;
99: }
100: if (d2->d_entry && useless(d2->d_entry)) {
101: d2++;
102: continue;
103: }
104: if (d1->d_entry == 0)
105: cmp = 1;
106: else if (d2->d_entry == 0)
107: cmp = -1;
108: else
109: cmp = strcmp(d1->d_entry, d2->d_entry);
110: if (cmp < 0) {
111: if (lflag)
112: d1->d_flags |= ONLY;
113: else if (opt == 0 || opt == 2)
114: only(d1, 1);
115: d1++;
116: dirstatus |= 1;
117: } else if (cmp == 0) {
118: compare(d1);
119: d1++;
120: d2++;
121: } else {
122: if (lflag)
123: d2->d_flags |= ONLY;
124: else if (opt == 0 || opt == 2)
125: only(d2, 2);
126: d2++;
127: dirstatus |= 1;
128: }
129: }
130: if (lflag) {
131: scanpr(dir1, ONLY, "Only in %.*s", file1, efile1, 0, 0);
132: scanpr(dir2, ONLY, "Only in %.*s", file2, efile2, 0, 0);
133: scanpr(dir1, SAME, "Common identical files in %.*s and %.*s",
134: file1, efile1, file2, efile2);
135: scanpr(dir1, DIFFER, "Binary files which differ in %.*s and %.*s",
136: file1, efile1, file2, efile2);
137: scanpr(dir1, DIRECT, "Common subdirectories of %.*s and %.*s",
138: file1, efile1, file2, efile2);
139: }
140: if (rflag) {
141: if (header && lflag)
142: printf("\f");
143: for (d1 = dir1; d1->d_entry; d1++) {
144: if ((d1->d_flags & DIRECT) == 0)
145: continue;
146: strcpy(efile1, d1->d_entry);
147: strcpy(efile2, d1->d_entry);
148: calldiff(0);
149: }
150: }
151: status = dirstatus;
152: }
153:
154: setfile(fpp, epp, file)
155: char **fpp, **epp;
156: char *file;
157: {
158: register char *cp;
159:
160: *fpp = malloc(BUFSIZ);
161: if (*fpp == 0) {
162: fprintf(stderr, "diff: ran out of memory\n");
163: exit(1);
164: }
165: strcpy(*fpp, file);
166: for (cp = *fpp; *cp; cp++)
167: continue;
168: *cp++ = '/';
169: *epp = cp;
170: }
171:
172: scanpr(dp, test, title, file1, efile1, file2, efile2)
173: register struct dir *dp;
174: int test;
175: char *title, *file1, *efile1, *file2, *efile2;
176: {
177: int titled = 0;
178:
179: for (; dp->d_entry; dp++) {
180: if ((dp->d_flags & test) == 0)
181: continue;
182: if (titled == 0) {
183: if (header == 0)
184: header = 1;
185: else
186: printf("\n");
187: printf(title,
188: efile1 - file1 - 1, file1,
189: efile2 - file2 - 1, file2);
190: printf(":\n");
191: titled = 1;
192: }
193: printf("\t%s\n", dp->d_entry);
194: }
195: }
196:
197: only(dp, which)
198: struct dir *dp;
199: int which;
200: {
201: char *file = which == 1 ? file1 : file2;
202: char *efile = which == 1 ? efile1 : efile2;
203:
204: printf("Only in %.*s: %s\n", efile - file - 1, file, dp->d_entry);
205:
206: }
207:
208: int entcmp();
209:
210: struct dir *
211: setupdir(cp)
212: char *cp;
213: {
214: register struct dir *dp, *ep;
215: register struct direct *rp;
216: register int nitems, n;
217: DIR *dirp;
218:
219: dirp = opendir(cp);
220: if (dirp == NULL) {
221: fprintf(stderr, "diff: ");
222: perror(cp);
223: done();
224: }
225: nitems = 0;
226: dp = (struct dir *)malloc(sizeof (struct dir));
227: if (dp == 0) {
228: fprintf(stderr, "diff: ran out of memory\n");
229: done();
230: }
231: while (rp = readdir(dirp)) {
232: ep = &dp[nitems++];
233: ep->d_reclen = rp->d_reclen;
234: ep->d_namlen = rp->d_namlen;
235: ep->d_entry = 0;
236: ep->d_flags = 0;
237: if (ep->d_namlen > 0) {
238: ep->d_entry = malloc(ep->d_namlen + 1);
239: if (ep->d_entry == 0) {
240: fprintf(stderr, "diff: out of memory\n");
241: done();
242: }
243: strcpy(ep->d_entry, rp->d_name);
244: }
245: dp = (struct dir *)realloc((char *)dp,
246: (nitems + 1) * sizeof (struct dir));
247: if (dp == 0) {
248: fprintf(stderr, "diff: ran out of memory\n");
249: done();
250: }
251: }
252: dp[nitems].d_entry = 0; /* delimiter */
253: closedir(dirp);
254: qsort(dp, nitems, sizeof (struct dir), entcmp);
255: return (dp);
256: }
257:
258: entcmp(d1, d2)
259: struct dir *d1, *d2;
260: {
261: return (strcmp(d1->d_entry, d2->d_entry));
262: }
263:
264: compare(dp)
265: register struct dir *dp;
266: {
267: register int i, j;
268: int f1, f2, fmt1, fmt2;
269: struct stat stb1, stb2;
270: int flag = 0;
271: char buf1[BUFSIZ], buf2[BUFSIZ];
272:
273: strcpy(efile1, dp->d_entry);
274: strcpy(efile2, dp->d_entry);
275: f1 = open(file1, 0);
276: if (f1 < 0) {
277: perror(file1);
278: return;
279: }
280: f2 = open(file2, 0);
281: if (f2 < 0) {
282: perror(file2);
283: close(f1);
284: return;
285: }
286: fstat(f1, &stb1); fstat(f2, &stb2);
287: fmt1 = stb1.st_mode & S_IFMT;
288: fmt2 = stb2.st_mode & S_IFMT;
289: if (fmt1 != S_IFREG || fmt2 != S_IFREG) {
290: if (fmt1 == fmt2) {
291: if (fmt1 != S_IFDIR && stb1.st_rdev == stb2.st_rdev)
292: goto same;
293: if (fmt1 == S_IFDIR) {
294: dp->d_flags = DIRECT;
295: if (lflag || opt == D_EDIT)
296: goto closem;
297: printf("Common subdirectories: %s and %s\n",
298: file1, file2);
299: goto closem;
300: }
301: }
302: goto notsame;
303: }
304: if (stb1.st_size != stb2.st_size)
305: goto notsame;
306: for (;;) {
307: i = read(f1, buf1, BUFSIZ);
308: j = read(f2, buf2, BUFSIZ);
309: if (i < 0 || j < 0 || i != j)
310: goto notsame;
311: if (i == 0 && j == 0)
312: goto same;
313: for (j = 0; j < i; j++)
314: if (buf1[j] != buf2[j])
315: goto notsame;
316: }
317: same:
318: if (sflag == 0)
319: goto closem;
320: if (lflag)
321: dp->d_flags = SAME;
322: else
323: printf("Files %s and %s are identical\n", file1, file2);
324: goto closem;
325: notsame:
326: dirstatus |= 1;
327: if (!ascii(f1) || !ascii(f2)) {
328: if (lflag)
329: dp->d_flags |= DIFFER;
330: else if (opt == D_NORMAL || opt == D_CONTEXT)
331: printf("Binary files %s and %s differ\n",
332: file1, file2);
333: goto closem;
334: }
335: close(f1); close(f2);
336: anychange = 1;
337: if (lflag)
338: calldiff(title);
339: else {
340: if (opt == D_EDIT) {
341: printf("ed - %s << '-*-END-*-'\n", dp->d_entry);
342: calldiff(0);
343: } else {
344: printf("%s%s %s\n", title, file1, file2);
345: calldiff(0);
346: }
347: if (opt == D_EDIT)
348: printf("w\nq\n-*-END-*-\n");
349: }
350: return;
351: closem:
352: close(f1); close(f2);
353: }
354:
355: char *prargs[] = { "pr", "-h", 0, "-f", 0, 0 };
356:
357: calldiff(wantpr)
358: char *wantpr;
359: {
360: int pid, lstatus, lstatus2, pv[2];
361:
362: prargs[2] = wantpr;
363: fflush(stdout);
364: if (wantpr) {
365: (void)sprintf(etitle, "%s %s", file1, file2);
366: pipe(pv);
367: pid = fork();
368: if (pid == -1) {
369: fprintf(stderr, "No more processes");
370: done();
371: }
372: if (pid == 0) {
373: close(0);
374: dup(pv[0]);
375: close(pv[0]);
376: close(pv[1]);
377: execv(pr+4, prargs);
378: execv(pr, prargs);
379: perror(pr);
380: done();
381: }
382: }
383: pid = fork();
384: if (pid == -1) {
385: fprintf(stderr, "diff: No more processes\n");
386: done();
387: }
388: if (pid == 0) {
389: if (wantpr) {
390: close(1);
391: dup(pv[1]);
392: close(pv[0]);
393: close(pv[1]);
394: }
395: execv(diff+4, diffargv);
396: execv(diff, diffargv);
397: perror(diff);
398: done();
399: }
400: if (wantpr) {
401: close(pv[0]);
402: close(pv[1]);
403: }
404: while (wait(&lstatus) != pid)
405: continue;
406: while (wait(&lstatus2) != -1)
407: continue;
408: /*
409: if ((lstatus >> 8) >= 2)
410: done();
411: */
412: dirstatus |= lstatus >> 8;
413: }
414:
415: #include <a.out.h>
416:
417: ascii(f)
418: int f;
419: {
420: char buf[BUFSIZ];
421: register int cnt;
422: register char *cp;
423:
424: lseek(f, (long)0, 0);
425: cnt = read(f, buf, BUFSIZ);
426: if (cnt >= sizeof (struct exec)) {
427: struct exec hdr;
428: hdr = *(struct exec *)buf;
429: if (!N_BADMAG(hdr))
430: return (0);
431: }
432: cp = buf;
433: while (--cnt >= 0)
434: if (*cp++ & 0200)
435: return (0);
436: return (1);
437: }
438:
439: /*
440: * THIS IS CRUDE.
441: */
442: useless(cp)
443: register char *cp;
444: {
445:
446: if (cp[0] == '.') {
447: if (cp[1] == '\0')
448: return (1); /* directory "." */
449: if (cp[1] == '.' && cp[2] == '\0')
450: return (1); /* directory ".." */
451: }
452: if (start && strcmp(start, cp) > 0)
453: return (1);
454: return (0);
455: }