/* file15 has the same effect as file14, but uses a more powerful comparefile() function. Programs that want to recover from errors without exiting can't use exitifdifferent(), but they can use comparefile(). The comparefile() function returns -4 if the second file is unreadable (with errno indicating the error), -3 if the first file is unreadable (with errno indicating the error), -2 if the second file is unopenable (with errno indicating the error), -1 if the first file is unopenable (with errno indicating the error), 0 if the files are the same, and a positive number if the files are different. The positive number is 1 plus the number of bytes that match before the first difference. comparefile() carefully frees all the resources consumed, and nothing but the resources consumed. Notice the fclose() operations before each return. */ #include #include #include int comparefile(char *filename1,char *filename2) { FILE *f1; FILE *f2; int bytes = 1; int d1; int d2; f1 = fopen(filename1,"r"); if (!f1) return -1; f2 = fopen(filename2,"r"); if (!f2) { fclose(f1); return -2; } do { d1 = fgetc(f1); if (d1 == -1) if (ferror(f1)) { fclose(f1); fclose(f2); return -3; } d2 = fgetc(f2); if (d2 == -1) if (ferror(f2)) { fclose(f1); fclose(f2); return -4; } if (d1 != d2) { fclose(f1); fclose(f2); return bytes; } ++bytes; } while (d1 != EOF); fclose(f1); fclose(f2); return 0; } void die(char *operation,char *filename) { fprintf(stderr,"fatal: unable to %s %s: %s\n" ,operation,filename,strerror(errno)); exit(111); } void exitifdifferent(char *filename1,char *filename2) { int result = comparefile(filename1,filename2); switch(result) { case 0: return; case -1: die("open",filename1); case -2: die("open",filename2); case -3: die("read",filename1); case -4: die("read",filename2); } printf("Files %s and %s differ after %d bytes.\n" ,filename1,filename2,result - 1); exit(0); } int main(int argc,char **argv) { if (*argv) ++argv; while (argv[0] && argv[1]) { exitifdifferent(argv[0],argv[1]); ++argv; } printf("All the files are the same.\n"); exit(0); }