#include #include #include #include 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(const int argc, const char **argv) { int i; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; else if (!strcmp(argv[i], "-s")) s_flag = 1; else if (!strcmp(argv[i], "--help")) { printf("cmp [-s silent] FILE1 FILE2 [SKIP1] [SKIP2]\n"); return 0; } } long skip1 = 0; long skip2 = 0; FILE *fp1 = NULL; FILE *fp2 = stdin; switch (argc - i) { case 4: skip2 = parse_int(argv[i + 3]); /* fallthrough */ case 3: skip1 = parse_int(argv[i + 2]); /* fallthrough */ case 2: fp2 = file_open(argv[i + 1]); /* fallthrough */ case 1: fp1 = file_open(argv[i]); break; default: 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; }