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