Annotation of 43BSDTahoe/bin/cmp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1987 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that the above copyright notice and this paragraph are
                      7:  * duplicated in all such forms and that any documentation,
                      8:  * advertising materials, and other materials related to such
                      9:  * distribution and use acknowledge that the software was developed
                     10:  * by the University of California, Berkeley.  The name of the
                     11:  * University may not be used to endorse or promote products derived
                     12:  * from this software without specific prior written permission.
                     13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     15:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     16:  */
                     17: 
                     18: #ifndef lint
                     19: char copyright[] =
                     20: "@(#) Copyright (c) 1987 Regents of the University of California.\n\
                     21:  All rights reserved.\n";
                     22: #endif /* not lint */
                     23: 
                     24: #ifndef lint
                     25: static char sccsid[] = "@(#)cmp.c      4.9 (Berkeley) 6/18/88";
                     26: #endif /* not lint */
                     27: 
                     28: #include <sys/param.h>
                     29: #include <sys/file.h>
                     30: #include <sys/stat.h>
                     31: #include <stdio.h>
                     32: #include <ctype.h>
                     33: #include <errno.h>
                     34: 
                     35: #define DIFF   1                       /* found differences */
                     36: #define ERR    2                       /* error during run */
                     37: #define NO     0                       /* no/false */
                     38: #define OK     0                       /* didn't find differences */
                     39: #define YES    1                       /* yes/true */
                     40: 
                     41: static int     fd1, fd2,               /* file descriptors */
                     42:                silent = NO;            /* if silent run */
                     43: static short   all = NO;               /* if report all differences */
                     44: static u_char  buf1[MAXBSIZE],         /* read buffers */
                     45:                buf2[MAXBSIZE];
                     46: static char    *file1, *file2;         /* file names */
                     47: 
                     48: main(argc, argv)
                     49:        int     argc;
                     50:        char    **argv;
                     51: {
                     52:        extern char     *optarg;
                     53:        extern int      optind;
                     54:        int     ch;
                     55:        u_long  otoi();
                     56: 
                     57:        while ((ch = getopt(argc, argv, "ls")) != EOF)
                     58:                switch(ch) {
                     59:                case 'l':               /* print all differences */
                     60:                        all = YES;
                     61:                        break;
                     62:                case 's':               /* silent run */
                     63:                        silent = YES;
                     64:                        break;
                     65:                case '?':
                     66:                default:
                     67:                        usage();
                     68:                }
                     69:        argv += optind;
                     70:        argc -= optind;
                     71: 
                     72:        if (argc < 2 || argc > 4)
                     73:                usage();
                     74: 
                     75:        /* open up files; "-" is stdin */
                     76:        file1 = argv[0];
                     77:        if (strcmp(file1, "-") && (fd1 = open(file1, O_RDONLY, 0)) < 0)
                     78:                error(file1);
                     79:        file2 = argv[1];
                     80:        if ((fd2 = open(file2, O_RDONLY, 0)) < 0)
                     81:                error(file2);
                     82: 
                     83:        /* handle skip arguments */
                     84:        if (argc > 2) {
                     85:                skip(otoi(argv[2]), fd1, file1);
                     86:                if (argc == 4)
                     87:                        skip(otoi(argv[3]), fd2, file2);
                     88:        }
                     89:        cmp();
                     90:        /*NOTREACHED*/
                     91: }
                     92: 
                     93: /*
                     94:  * skip --
                     95:  *     skip first part of file
                     96:  */
                     97: static
                     98: skip(dist, fd, fname)
                     99:        register u_long dist;           /* length in bytes, to skip */
                    100:        register int    fd;             /* file descriptor */
                    101:        char    *fname;                 /* file name for error */
                    102: {
                    103:        register int    rlen;           /* read length */
                    104:        register int    nread;
                    105: 
                    106:        for (; dist; dist -= rlen) {
                    107:                rlen = MIN(dist, sizeof(buf1));
                    108:                if ((nread = read(fd, buf1, rlen)) != rlen) {
                    109:                        if (nread < 0)
                    110:                                error(fname);
                    111:                        else
                    112:                                endoffile(fname);
                    113:                }
                    114:        }
                    115: }
                    116: 
                    117: static
                    118: cmp()
                    119: {
                    120:        register u_char *C1, *C2;       /* traveling pointers */
                    121:        register int    cnt,            /* counter */
                    122:                        len1, len2;     /* read lengths */
                    123:        register long   byte,           /* byte count */
                    124:                        line;           /* line count */
                    125:        short   dfound = NO;            /* if difference found */
                    126: 
                    127:        for (byte = 0, line = 1;;) {
                    128:                switch(len1 = read(fd1, buf1, MAXBSIZE)) {
                    129:                case -1:
                    130:                        error(file1);
                    131:                case 0:
                    132:                        /*
                    133:                         * read of file 1 just failed, find out
                    134:                         * if there's anything left in file 2
                    135:                         */
                    136:                        switch(read(fd2, buf2, 1)) {
                    137:                                case -1:
                    138:                                        error(file2);
                    139:                                case 0:
                    140:                                        exit(dfound ? DIFF : OK);
                    141:                                default:
                    142:                                        endoffile(file1);
                    143:                        }
                    144:                }
                    145:                /*
                    146:                 * file1 might be stdio, which means that a read of less than
                    147:                 * MAXBSIZE might not mean an EOF.  So, read whatever we read
                    148:                 * from file1 from file2.
                    149:                 */
                    150:                if ((len2 = read(fd2, buf2, len1)) == -1)
                    151:                        error(file2);
                    152:                if (bcmp(buf1, buf2, len2)) {
                    153:                        if (silent)
                    154:                                exit(DIFF);
                    155:                        if (all) {
                    156:                                dfound = YES;
                    157:                                for (C1 = buf1, C2 = buf2, cnt = len2; cnt--; ++C1, ++C2) {
                    158:                                        ++byte;
                    159:                                        if (*C1 != *C2)
                    160:                                                printf("%6ld %3o %3o\n", byte, *C1, *C2);
                    161:                                }
                    162:                        }
                    163:                        else for (C1 = buf1, C2 = buf2;; ++C1, ++C2) {
                    164:                                ++byte;
                    165:                                if (*C1 != *C2) {
                    166:                                        printf("%s %s differ: char %ld, line %ld\n", file1, file2, byte, line);
                    167:                                        exit(DIFF);
                    168:                                }
                    169:                                if (*C1 == '\n')
                    170:                                        ++line;
                    171:                        }
                    172:                }
                    173:                else {
                    174:                        byte += len2;
                    175:                        /*
                    176:                         * here's the real performance problem, we've got to
                    177:                         * count the stupid lines, which means that -l is a
                    178:                         * *much* faster version, i.e., unless you really
                    179:                         * *want* to know the line number, run -s or -l.
                    180:                         */
                    181:                        if (!silent && !all)
                    182:                                for (C1 = buf1, cnt = len2; cnt--;)
                    183:                                        if (*C1++ == '\n')
                    184:                                                ++line;
                    185:                }
                    186:                /*
                    187:                 * couldn't read as much from file2 as from file1; checked
                    188:                 * here because there might be a difference before we got
                    189:                 * to this point, which would have precedence.
                    190:                 */
                    191:                if (len2 < len1)
                    192:                        endoffile(file2);
                    193:        }
                    194: }
                    195: 
                    196: /*
                    197:  * otoi --
                    198:  *     octal/decimal string to u_long
                    199:  */
                    200: static u_long
                    201: otoi(C)
                    202:        register char   *C;             /* argument string */
                    203: {
                    204:        register u_long val;            /* return value */
                    205:        register int    base;           /* number base */
                    206: 
                    207:        base = (*C == '0') ? 8 : 10;
                    208:        for (val = 0; isdigit(*C); ++C)
                    209:                val = val * base + *C - '0';
                    210:        return(val);
                    211: }
                    212: 
                    213: /*
                    214:  * error --
                    215:  *     print I/O error message and die
                    216:  */
                    217: static
                    218: error(filename)
                    219:        char *filename;
                    220: {
                    221:        extern int errno;
                    222:        int sverrno;
                    223: 
                    224:        if (!silent) {
                    225:                sverrno = errno;
                    226:                (void)fprintf(stderr, "cmp: %s: ", filename);
                    227:                errno = sverrno;
                    228:                perror((char *)NULL);
                    229:        }
                    230:        exit(ERR);
                    231: }
                    232: 
                    233: /*
                    234:  * endoffile --
                    235:  *     print end-of-file message and exit indicating the files were different
                    236:  */
                    237: static
                    238: endoffile(filename)
                    239:        char *filename;
                    240: {
                    241:        /* 32V put this message on stdout, S5 does it on stderr. */
                    242:        if (!silent)
                    243:                (void)fprintf(stderr, "cmp: EOF on %s\n", filename);
                    244:        exit(DIFF);
                    245: }
                    246: 
                    247: /*
                    248:  * usage --
                    249:  *     print usage and die
                    250:  */
                    251: static
                    252: usage()
                    253: {
                    254:        fputs("usage: cmp [-ls] file1 file2 [skip1] [skip2]\n", stderr);
                    255:        exit(ERR);
                    256: }

unix.superglobalmegacorp.com

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