133 lines
2.6 KiB
C
133 lines
2.6 KiB
C
/* cmp - compare two files Authors: Paul Polderman & Michiel Huisjes */
|
|
|
|
/* 90-04-10 Schlenker
|
|
* Fixed incorrect handling of flags.
|
|
* Reduced buffer size to accommodate 7K pipes (Minix restriction).
|
|
* Better trapping of file reading errors.
|
|
* Considerable speedup when using -s flag.
|
|
* Buffering strategy remains seriously error prone; should be fixed.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
#define BLOCK_SIZE 6144
|
|
|
|
char *file_1, *file_2;
|
|
char buf1[BLOCK_SIZE];
|
|
char buf2[BLOCK_SIZE];
|
|
char lflag, sflag;
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
int fd1, fd2, i, exit_status;
|
|
|
|
if (argc < 3 || argc > 4) usage();
|
|
lflag = 0;
|
|
sflag = 0;
|
|
|
|
i = 1;
|
|
if (strcmp(argv[i], "-l") == 0) {
|
|
lflag++;
|
|
i++;
|
|
} else
|
|
if (strcmp(argv[i], "-s") == 0) {
|
|
sflag++;
|
|
i++;
|
|
}
|
|
|
|
if (strcmp(argv[i], "-") == 0) {
|
|
fd1 = 0;
|
|
file_1 = "<stdin>";
|
|
} else {
|
|
if ((fd1 = open(argv[i], O_RDONLY)) < 0)
|
|
cantopen(argv[i]);
|
|
file_1 = argv[i];
|
|
}
|
|
i++;
|
|
|
|
if (i == argc || (fd2 = open(argv[i], O_RDONLY)) < 0)
|
|
cantopen(argv[i]);
|
|
file_2 = argv[i];
|
|
|
|
exit_status = sflag ? fastcmp(fd1, fd2) : cmp(fd1, fd2);
|
|
|
|
close(fd1);
|
|
close(fd2);
|
|
|
|
exit(exit_status);
|
|
}
|
|
|
|
cmp(fd1, fd2)
|
|
int fd1, fd2;
|
|
{
|
|
register unsigned long char_cnt, line_cnt;
|
|
register int i;
|
|
int n1, n2, n, exit_status;
|
|
|
|
char_cnt = 1L;
|
|
line_cnt = 1L;
|
|
exit_status = 0;
|
|
do {
|
|
n1 = read(fd1, buf1, BLOCK_SIZE);
|
|
n2 = read(fd2, buf2, BLOCK_SIZE);
|
|
n = (n1 < n2) ? n1 : n2;
|
|
if (n < 0) {
|
|
printf("cmp: Error on %s\n", (n1 < 0) ? file_1 : file_2);
|
|
return(1);
|
|
}
|
|
for (i = 0; i < n; i++) { /* Check buffers for equality */
|
|
if (buf1[i] != buf2[i]) {
|
|
if (!lflag) {
|
|
printf("%s %s differ: char %ld, line %ld\n",
|
|
file_1, file_2, char_cnt, line_cnt);
|
|
return(1);
|
|
}
|
|
printf("%10lu %03o %03o\n",
|
|
char_cnt, buf1[i] & 0377, buf2[i] & 0377);
|
|
exit_status = 1;
|
|
}
|
|
if (buf1[i] == '\n') line_cnt++;
|
|
char_cnt++;
|
|
}
|
|
if (n1 != n2) { /* EOF on one of the input files. */
|
|
printf("cmp: EOF on %s\n", (n1 < n2) ? file_1 : file_2);
|
|
return(1);
|
|
}
|
|
} while (n > 0); /* While not EOF on any file */
|
|
return(exit_status);
|
|
}
|
|
|
|
fastcmp(fd1, fd2)
|
|
int fd1, fd2;
|
|
{
|
|
int n1, n2;
|
|
|
|
while (1) {
|
|
n1 = read(fd1, buf1, BLOCK_SIZE);
|
|
n2 = read(fd2, buf2, BLOCK_SIZE);
|
|
if (n1 != n2) return(1); /* Bug! - depends on buffering */
|
|
if (n1 == 0) return(0);
|
|
if (n1 < 0) return(1);
|
|
if (memcmp((void *) buf1, (void *) buf2, (size_t) n1) != 0)
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
usage()
|
|
{
|
|
fprintf(stderr, "Usage: cmp [-l | -s] file1 file2\n");
|
|
exit(2);
|
|
}
|
|
|
|
cantopen(s)
|
|
char *s;
|
|
{
|
|
fprintf(stderr, "cmp: cannot open %s\n", s);
|
|
exit(1);
|
|
}
|