* Copyright (c) 1987 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of California at Berkeley. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific written prior permission. This software
* is provided ``as is'' without express or implied warranty.
"@(#) Copyright (c) 1987 Regents of the University of California.\n\
static char sccsid
[] = "@(#)cmp.c 4.8 (Berkeley) %G%";
#define DIFF 1 /* found differences */
#define ERR 2 /* error during run */
#define NO 0 /* no/false */
#define OK 0 /* didn't find differences */
#define YES 1 /* yes/true */
static int fd1
, fd2
, /* file descriptors */
silent
= NO
; /* if silent run */
static short all
= NO
; /* if report all differences */
static u_char buf1
[MAXBSIZE
], /* read buffers */
static char *file1
, *file2
; /* file names */
while ((ch
= getopt(argc
, argv
, "ls")) != EOF
)
case 'l': /* print all differences */
case 's': /* silent run */
if (argc
< 2 || argc
> 4)
/* open up files; "-" is stdin */
if (strcmp(file1
, "-") && (fd1
= open(file1
, O_RDONLY
, 0)) < 0)
if ((fd2
= open(file2
, O_RDONLY
, 0)) < 0)
/* handle skip arguments */
skip(otoi(argv
[2]), fd1
, file1
);
skip(otoi(argv
[3]), fd2
, file2
);
* skip first part of file
register u_long dist
; /* length in bytes, to skip */
register int fd
; /* file descriptor */
char *fname
; /* file name for error */
register int rlen
; /* read length */
for (; dist
; dist
-= rlen
) {
rlen
= MIN(dist
, sizeof(buf1
));
if ((nread
= read(fd
, buf1
, rlen
)) != rlen
) {
register u_char
*C1
, *C2
; /* traveling pointers */
register int cnt
, /* counter */
len1
, len2
; /* read lengths */
register long byte
, /* byte count */
short dfound
= NO
; /* if difference found */
for (byte
= 0, line
= 1;;) {
switch(len1
= read(fd1
, buf1
, MAXBSIZE
)) {
* read of file 1 just failed, find out
* if there's anything left in file 2
switch(read(fd2
, buf2
, 1)) {
exit(dfound
? DIFF
: OK
);
* file1 might be stdio, which means that a read of less than
* MAXBSIZE might not mean an EOF. So, read whatever we read
if ((len2
= read(fd2
, buf2
, len1
)) == -1)
if (bcmp(buf1
, buf2
, len2
)) {
for (C1
= buf1
, C2
= buf2
, cnt
= len2
; cnt
--; ++C1
, ++C2
) {
printf("%6ld %3o %3o\n", byte
, *C1
, *C2
);
else for (C1
= buf1
, C2
= buf2
;; ++C1
, ++C2
) {
printf("%s %s differ: char %ld, line %ld\n", file1
, file2
, byte
, line
);
* here's the real performance problem, we've got to
* count the stupid lines, which means that -l is a
* *much* faster version, i.e., unless you really
* *want* to know the line number, run -s or -l.
for (C1
= buf1
, cnt
= len2
; cnt
--;)
* couldn't read as much from file2 as from file1; checked
* here because there might be a difference before we got
* to this point, which would have precedence.
* octal/decimal string to u_long
register char *C
; /* argument string */
register u_long val
; /* return value */
register int base
; /* number base */
base
= (*C
== '0') ? 8 : 10;
for (val
= 0; isdigit(*C
); ++C
)
val
= val
* base
+ *C
- '0';
* print I/O error message and die
(void)fprintf(stderr
, "cmp: %s: ", filename
);
* print end-of-file message and exit indicating the files were different
/* 32V put this message on stdout, S5 does it on stderr. */
(void)fprintf(stderr
, "cmp: EOF on %s\n", filename
);
fputs("usage: cmp [-ls] file1 file2 [skip1] [skip2]\n", stderr
);