|
|
1.1 ! root 1: #include <stdio.h> ! 2: ! 3: /* ! 4: * Diffdir - a (first) directory difference program ! 5: * Bill Joy UCB March 16, 1978 ! 6: * ! 7: * This is a difference program which operates on the entire contents of ! 8: * a directory. It reports common files which are different, running ! 9: * diff if the files are ASCII files. It also reports files which are ! 10: * unique to one of the two directories. ! 11: * ! 12: * An option "h" (for header) causes diffdir to print each difference ! 13: * on a new page (using an appropriate "pr") and to summarize missing ! 14: * files and differences in binary files on a final page. ! 15: * ! 16: * Option "s" causes files which are the same to be reported also. ! 17: * ! 18: * It would be nice if this were "difftree", and if it knew a few ! 19: * more things, e.g to "size" objects which are different or some ! 20: * such or at least to not say that "directories are different" calling ! 21: * them files, i.e. "Files ex-1.1/temp and ex-1.2/temp are different". ! 22: */ ! 23: ! 24: typedef char bool; ! 25: ! 26: struct entry { ! 27: char *name; ! 28: int flags; ! 29: } *dir1, *dir2; ! 30: ! 31: #define ONLY 1 ! 32: #define DIFFER 2 ! 33: ! 34: bool eflg; ! 35: bool hflg; ! 36: bool vflg; ! 37: bool sflg; ! 38: ! 39: #define vprintf if (vflg) printf ! 40: #define diffopt() (eflg ? "-e" : "") ! 41: ! 42: main(argc, argv) ! 43: int argc; ! 44: char *argv[]; ! 45: { ! 46: register struct entry *d1, *d2; ! 47: register char *cp; ! 48: ! 49: while (argc > 1) { ! 50: cp = argv[1]; ! 51: if (*cp++ != '-') ! 52: break; ! 53: while (*cp) switch (*cp++) { ! 54: ! 55: case 'h': ! 56: hflg++; ! 57: continue; ! 58: ! 59: case 'v': ! 60: vflg++; ! 61: continue; ! 62: ! 63: case 's': ! 64: sflg++; ! 65: continue; ! 66: ! 67: case 'e': ! 68: eflg++; ! 69: printf("#\n"); ! 70: continue; ! 71: ! 72: default: ! 73: usage: ! 74: panic("Usage: diffdir [ -h ] dir1 dir2"); ! 75: } ! 76: argc--, argv++; ! 77: } ! 78: if (argc != 3) ! 79: goto usage; ! 80: setupdir(argv[1], &dir1); ! 81: setupdir(argv[2], &dir2); ! 82: d1 = dir1; d2 = dir2; ! 83: while (d1->name != 0 || d2->name != 0) { ! 84: if (useless(d1->name)) { ! 85: d1++; ! 86: continue; ! 87: } ! 88: if (useless(d2->name)) { ! 89: d2++; ! 90: continue; ! 91: } ! 92: if (d1->name != 0 && d2->name != 0) ! 93: switch (sgn(strcmp(d1->name, d2->name))) { ! 94: ! 95: case -1: ! 96: onlyin1: ! 97: if (hflg) ! 98: d1->flags =| ONLY; ! 99: else if (!eflg) ! 100: printf("Only in %s: %s\n", argv[1], d1->name); ! 101: d1++; ! 102: continue; ! 103: ! 104: case 0: ! 105: vprintf("In both: %s\n", d1->name); ! 106: compare(d1, argv[1], argv[2]); ! 107: d1++; ! 108: d2++; ! 109: continue; ! 110: ! 111: case 1: ! 112: onlyin2: if (hflg) ! 113: d2->flags =| ONLY; ! 114: else if (!eflg) ! 115: printf("Only in %s: %s\n", argv[2], d2->name); ! 116: d2++; ! 117: continue; ! 118: } ! 119: if (d1->name != 0) ! 120: goto onlyin1; ! 121: else ! 122: goto onlyin2; ! 123: } ! 124: if (hflg) { ! 125: int header = 0; ! 126: ! 127: for (d1 = dir1; d1->name; d1++) ! 128: if (d1->flags & ONLY) { ! 129: if (header == 0) { ! 130: printf("\fOnly in %s\n", argv[1]); ! 131: header = 1; ! 132: } ! 133: printf("\t%s\n", d1->name); ! 134: } ! 135: for (d2 = dir2; d2->name != 0; d2++) { ! 136: if (d2->flags & ONLY) { ! 137: if (header == 0) ! 138: printf("\f"); ! 139: if ((header & 2) == 0) { ! 140: printf("Only in %s\n", argv[2]); ! 141: header =| 2; ! 142: } ! 143: printf("\t%s\n", d2->name); ! 144: } ! 145: } ! 146: for (d1 = dir1; d1->name; d1++) ! 147: if (d1->flags & DIFFER) { ! 148: if (header == 0) { ! 149: printf("\f"); ! 150: header = 1; ! 151: } ! 152: if ((header & 4) == 0) { ! 153: printf("Non-ascii files which differ:\n"); ! 154: header =| 4; ! 155: } ! 156: printf("\t%s\n", d1->name); ! 157: } ! 158: } ! 159: exit(0); ! 160: } ! 161: ! 162: int entcmp(); ! 163: setupdir(cp, head) ! 164: char *cp; ! 165: struct entry **head; ! 166: { ! 167: int count = 1; ! 168: struct dirent0 { ! 169: short ino; ! 170: char fname[14]; ! 171: }; ! 172: ! 173: struct dirent1 { ! 174: short ino; ! 175: char fname1[16]; ! 176: } dirent; ! 177: register struct entry *hp; ! 178: ! 179: close(0); ! 180: if (open(cp, 0) < 0) { ! 181: perror(cp); ! 182: exit(1); ! 183: } ! 184: while (read(0, &dirent, sizeof (struct dirent0)) == sizeof (struct dirent0)) ! 185: if (dirent.ino) ! 186: count++; ! 187: lseek(0, (long) 0, 0); ! 188: hp = *head = Calloc(count, sizeof **head); ! 189: while (read(0, &dirent, sizeof (struct dirent0)) == sizeof (struct dirent0)) ! 190: if (dirent.ino) { ! 191: hp->name = savestr(dirent.fname); ! 192: hp++; ! 193: } ! 194: qsort(*head, count - 1, sizeof **head, entcmp); ! 195: } ! 196: ! 197: entcmp(ep, ep2) ! 198: struct entry *ep, *ep2; ! 199: { ! 200: ! 201: return (strcmp(ep->name, ep2->name)); ! 202: } ! 203: ! 204: Calloc(i, n) ! 205: int i, n; ! 206: { ! 207: register unsigned mem; ! 208: ! 209: mem = calloc(i, n); ! 210: if (mem == 0) ! 211: panic("Ran out of memory"); ! 212: return (mem); ! 213: } ! 214: ! 215: savestr(cp) ! 216: register char *cp; ! 217: { ! 218: ! 219: return (strcpy(calloc(strlen(cp)+1, sizeof (char)), cp)); ! 220: } ! 221: ! 222: panic(cp) ! 223: char *cp; ! 224: { ! 225: ! 226: fprintf(stderr, "%s\n", cp); ! 227: exit(1); ! 228: } ! 229: ! 230: sgn(i) ! 231: int i; ! 232: { ! 233: if (i > 0) ! 234: return (1); ! 235: else if (i < 0) ! 236: return (-1); ! 237: return (0); ! 238: } ! 239: ! 240: compare(dp, d1, d2) ! 241: struct entry *dp; ! 242: char *d1, *d2; ! 243: { ! 244: register int i; ! 245: char path1[100], path2[100]; ! 246: int t1, t2; ! 247: char header[250]; ! 248: char *name = dp->name; ! 249: ! 250: if (max(strlen(d1), strlen(d2)) + strlen(name) + 2 >= 100) ! 251: panic("Path names too long"); ! 252: strcat(strcat(strcpy(path1, d1), "/"), name); ! 253: strcat(strcat(strcpy(path2, d2), "/"), name); ! 254: i = callit("/usr/bin/cmp", "cmp", "-s", path1, path2, 0); ! 255: if (i == 0) { ! 256: if (sflg) ! 257: printf("Files %s and %s same\n", path1, path2); ! 258: return; ! 259: } ! 260: if (!ascii(path1) || !ascii(path2)) { ! 261: if (hflg) ! 262: dp->flags =| DIFFER; ! 263: else if (!eflg) ! 264: printf("Files %s and %s differ\n", path1, path2); ! 265: return; ! 266: } ! 267: if (hflg) { ! 268: sprintf(header, "diff %s %s %s", diffopt(), path1, path2); ! 269: prcallit(header, "/usr/bin/diff", "diff", path1, path2, 0); ! 270: } else { ! 271: if (eflg) { ! 272: printf("ed - %s << '-*-END-*-'\n", name); ! 273: callit("/usr/bin/diff", "diff", "-e", path1, path2, 0); ! 274: } else { ! 275: printf("diff %s %s\n", path1, path2); ! 276: callit("/usr/bin/diff", "diff", path1, path2, 0); ! 277: } ! 278: if (eflg) ! 279: printf("w\nq\n'-*-END-*-'\n"); ! 280: } ! 281: } ! 282: ! 283: prcallit(header, path, av) ! 284: char *header, *path; ! 285: { ! 286: int status; ! 287: int pid; ! 288: int pv[2]; ! 289: ! 290: fflush(stdout); ! 291: pipe(pv); ! 292: pid = fork(); ! 293: if (pid == -1) ! 294: panic("No more processes"); ! 295: if (pid == 0) { ! 296: close(0); ! 297: dup(pv[0]); ! 298: close(pv[0]); ! 299: close(pv[1]); ! 300: execl("/bin/pr", "pr", "-h", header, 0); ! 301: execl("/usr/bin/pr", "pr", "-h", header, 0); ! 302: perror("/usr/bin/pr"); ! 303: exit(1); ! 304: } ! 305: pid = fork(); ! 306: if (pid == -1) ! 307: panic("No more processes"); ! 308: if (pid == 0) { ! 309: close(1); ! 310: dup(pv[1]); ! 311: close(pv[0]); ! 312: close(pv[1]); ! 313: execv(path+4, &av); ! 314: execv(path, &av); ! 315: perror(path); ! 316: exit(1); ! 317: } ! 318: close(pv[0]); ! 319: close(pv[1]); ! 320: while (wait(&status) != -1) ! 321: continue; ! 322: } ! 323: ! 324: callit(path, av) ! 325: char *path; ! 326: { ! 327: int status; ! 328: int pid; ! 329: ! 330: fflush(stdout); ! 331: pid = fork(); ! 332: if (pid == -1) ! 333: panic("No more processes"); ! 334: if (pid == 0) { ! 335: execv(path+4, &av); ! 336: execv(path, &av); ! 337: perror(path); ! 338: exit(1); ! 339: } ! 340: wait(&status); ! 341: return (((status >> 8) & 0377) | (status & 0377)); ! 342: } ! 343: ! 344: max(a,b) ! 345: int a,b; ! 346: { ! 347: ! 348: return (a > b ? a : b); ! 349: } ! 350: ! 351: ascii(cp) ! 352: char *cp; ! 353: { ! 354: int f; ! 355: short w; ! 356: ! 357: f = open(cp, 0); ! 358: if (f < 0) ! 359: return (0); ! 360: if (read(f, &w, sizeof w) != sizeof w) { ! 361: close(f); ! 362: return (1); ! 363: } ! 364: close(f); ! 365: switch (w) { ! 366: ! 367: case 0405: /* Overlay executable */ ! 368: case 0407: /* Executable */ ! 369: case 0410: /* Pure executable */ ! 370: case 0411: /* Separate executable */ ! 371: case 0413: /* Demand executable */ ! 372: case 0177545: /* Archive */ ! 373: case 0177555: /* Old archive */ ! 374: return (0); ! 375: default: ! 376: if (w & 0100200) ! 377: return (0); ! 378: return (1); ! 379: } ! 380: } ! 381: ! 382: useless(cp) ! 383: char *cp; ! 384: { ! 385: ! 386: if (strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) ! 387: return (1); ! 388: if (cp[0] == '.') ! 389: return (1); /* For now */ ! 390: return (0); ! 391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.