#include #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(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; }