Minix1.5/commands/cmp.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);
}