Minix1.5/commands/cmp.c

Compare this file to the similar file:
Show the results in this format:

/* 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);
}