122 lines
1.8 KiB
C
122 lines
1.8 KiB
C
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
unsigned int s_flag;
|
|
|
|
int compare(FILE *fp1, FILE *fp2) {
|
|
if (fp1 == fp2)
|
|
return 0;
|
|
|
|
int ch1;
|
|
int ch2;
|
|
|
|
size_t byte = 0;
|
|
do {
|
|
ch1 = getc(fp1);
|
|
ch2 = getc(fp2);
|
|
|
|
if (ch1 != ch2) {
|
|
if (!s_flag)
|
|
printf("files differ at byte %lu\n", byte);
|
|
|
|
return 1;
|
|
}
|
|
|
|
byte++;
|
|
} while(ch1 != EOF);
|
|
|
|
return 0;
|
|
}
|
|
|
|
long parse_int(const char *str) {
|
|
char *ptr;
|
|
long val = strtol(str, &ptr, 0);
|
|
if (*ptr || val < 0) {
|
|
fprintf(stderr, "cmp: invalid offset: %s\n", str);
|
|
exit(1);
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
FILE *file_open(const char *path) {
|
|
if (!strcmp(path, "-"))
|
|
return stdin;
|
|
|
|
FILE *fp = fopen(path, "r");
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "cmp: %s\n", strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
return fp;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
int opt;
|
|
while ((opt = getopt(argc, argv, "f")) != -1) {
|
|
switch (opt) {
|
|
case 'f':
|
|
s_flag = 1;
|
|
break;
|
|
|
|
default:
|
|
printf("cmp file1 file2 [skip1] [skip2]\n\t[-f Silent]\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
argv += optind;
|
|
argc -= optind;
|
|
|
|
long skip1 = 0;
|
|
long skip2 = 0;
|
|
FILE *fp1 = NULL;
|
|
FILE *fp2 = stdin;
|
|
|
|
switch (argc) {
|
|
case 4:
|
|
skip2 = parse_int(argv[3]);
|
|
/* fallthrough */
|
|
|
|
case 3:
|
|
skip1 = parse_int(argv[2]);
|
|
/* fallthrough */
|
|
|
|
case 2:
|
|
fp2 = file_open(argv[1]);
|
|
/* fallthrough */
|
|
|
|
case 1:
|
|
fp1 = file_open(argv[0]);
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "cmp: missing operand\n");
|
|
return 1;
|
|
}
|
|
|
|
if (skip1 && fseek(fp1, skip1, SEEK_SET) < 0) {
|
|
if (!s_flag)
|
|
fprintf(stderr, "cmp: %s\n", strerror(errno));
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (skip2 && fseek(fp2, skip2, SEEK_SET) < 0) {
|
|
if (!s_flag)
|
|
fprintf(stderr, "cmp: %s\n", strerror(errno));
|
|
|
|
return 1;
|
|
}
|
|
|
|
int ret = compare(fp1, fp2);
|
|
fclose(fp1);
|
|
fclose(fp2);
|
|
|
|
return ret;
|
|
}
|