Annotation of 3BSD/cmd/diffdir.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.