#define _LARGEFILE64_SOURCE 1 #include #include #include #include static FILE * open_file (const char *filename) { FILE *retval; if (strcmp (filename, "-") == 0) return stdin; retval = fopen (filename, "r"); if (retval == NULL) { fprintf (stderr, "Error opening \"%s\": %m\n", filename); exit (2); } return retval; } static void close_file (FILE *f, const char *filename) { if (f == stdin) return; if (fclose (f) != 0) { fprintf (stderr, "Error closing \"%s\": %m\n", filename); exit(2); } } static int get_character (FILE *f, const char *filename) { int retval; retval = fgetc (f); if (ferror (f)) { fprintf (stderr, "Error reading \"%s\": %m\n", filename); exit(2); } return retval; } static void dump_character (int c) { /*_(0xXX YYY 'C') */ /*_EOF */ if (c == EOF) fputs (" EOF ", stdout); else { printf (" (0x%02x %3d ", c, c); if (isprint (c)) printf ("'%c'", c); else fputs (" ", stdout); putchar (')'); } } int main (int argc, char **argv) { int exit_code = 0; int argi; if (argc < 3) { fputs ("Syntax: cmpx [...]\n", stderr); exit (2); } for (argi = 1; argi <= argc - 2; argi++) { FILE *f1, *f2; int c1, c2; off_t offset; char *f1_filename, *f2_filename; int need_header = argc > 3; f1_filename = argv[argi + 0]; f2_filename = argv[argi + 1]; f1 = open_file (f1_filename); f2 = open_file (f2_filename); for (offset = 0 ;; offset++) { c1 = get_character (f1, f1_filename); c2 = get_character (f2, f2_filename); if (c1 == EOF && c2 == EOF) break; if (c1 == c2) continue; if (need_header) { printf ("%s\t%s\n", f1_filename, f2_filename); need_header = 0; } printf ("0x%08llx", (unsigned long long) offset); dump_character (c1); dump_character (c2); putchar ('\n'); exit_code = 1; } close_file (f1, f1_filename); close_file (f2, f2_filename); } return exit_code; }