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

Defined functions

cmp defined in line 112; used 1 times
  • in line 84
endoffile defined in line 232; used 3 times
error defined in line 212; used 6 times
main defined in line 43; never used
otoi defined in line 195; used 3 times
skip defined in line 92; used 2 times
usage defined in line 246; used 2 times

Defined variables

all defined in line 38; used 3 times
buf1 defined in line 39; used 7 times
buf2 defined in line 40; used 5 times
copyright defined in line 14; never used
fd1 defined in line 36; used 3 times
fd2 defined in line 36; used 4 times
file1 defined in line 41; used 8 times
file2 defined in line 41; used 8 times
sccsid defined in line 20; never used
silent defined in line 37; used 5 times

Defined macros

DIFF defined in line 30; used 4 times
ERR defined in line 31; used 2 times
NO defined in line 32; used 3 times
OK defined in line 33; used 1 times
YES defined in line 34; used 3 times
Last modified: 1988-07-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3917
Valid CSS Valid XHTML 1.0 Strict