/* Compare two copies of a file object in as many aspects as i can imagine. To compare tree /media/dvd and /original/dir : find /media/dvd -exec compare_file '{}' /media/dvd /original/dir ';' Copyright 2008 Thomas Schmitt, Provided under GPL version 2. cc -g -o compare_file compare_file.c */ #include #include #include #include #include #include #include #include #include /* @param flag bit0= compare atime bit1= compare ctime */ int Compare_2_files(char *adr1, char *adr2, char *adrc, int flag) { struct stat s1, s2; int ret, differs= 0, r1, r2, fd1, fd2, i; char buf1[4096], buf2[4096], a[4096]; off_t r1count= 0, r2count= 0, diffcount= 0, first_diff= -1; ret= lstat(adr1, &s1); if(ret==-1) { printf("? %s : cannot lstat() : %s\n", adr1, strerror(errno)); return(0); } if(S_ISDIR(s1.st_mode)) strcpy(a, "d"); else if(S_ISREG(s1.st_mode)) strcpy(a, "-"); else if(S_ISLNK(s1.st_mode)) strcpy(a, "l"); else if(S_ISBLK(s1.st_mode)) strcpy(a, "b"); else if(S_ISCHR(s1.st_mode)) strcpy(a, "c"); else if(S_ISFIFO(s1.st_mode)) strcpy(a, "p"); else if(S_ISSOCK(s1.st_mode)) strcpy(a, "s"); else strcpy(a, "?"); strcat(a, " "); if(adrc[0]) strcat(a, adrc); else strcat(a, "."); ret= lstat(adr2, &s2); if(ret==-1) { printf("? %s : cannot lstat() : %s\n", adr2, strerror(errno)); return(0); } /* Attributes */ if(s1.st_mode != s2.st_mode) { printf("%s : st_mode : %7.7o <> %7.7o\n", a, s1.st_mode, s2.st_mode); differs= 1; } if(s1.st_uid != s2.st_uid) { printf("%s : st_uid : %d <> %d\n", a, s1.st_uid, s2.st_uid); differs= 1; } if(s1.st_gid != s2.st_gid) { printf("%s : st_gid : %d <> %d\n", a, s1.st_gid, s2.st_gid); differs= 1; } if((S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode)) || (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode))) { if(s1.st_rdev != s2.st_rdev) { printf("%s : %s st_rdev : %lu <> %lu\n", a, (S_ISCHR(s1.st_mode) ? "S_IFCHR" : "S_IFBLK"), (unsigned long) s1.st_rdev, (unsigned long) s1.st_rdev); differs= 1; } } if(S_ISREG(s2.st_mode) && s1.st_size != s2.st_size) { printf("%s : st_size : %.f <> %.f\n", a, (double) s1.st_size, (double) s2.st_size); differs= 1; } if(s1.st_mtime != s2.st_mtime) { printf("%s : st_mtime : %u <> %u\n", a, (unsigned int) s1.st_mtime, (unsigned int) s2.st_mtime); differs= 1; } if(flag&1) { if(s1.st_atime != s2.st_atime) { printf("%s : st_atime : %u <> %u\n", a, (unsigned int) s1.st_atime, (unsigned int) s2.st_atime); differs= 1; } } if(flag&2) { if(s1.st_ctime != s2.st_ctime) { printf("%s : st_ctime : %u <> %u\n", a, (unsigned int) s1.st_ctime, (unsigned int) s2.st_ctime); differs= 1; } } if(S_ISREG(s1.st_mode)) { fd1= open(adr1, O_RDONLY); if(fd1==-1) { printf("- %s : cannot open() : %s\n", adr1, strerror(errno)); return(0); } fd2= open(adr2, O_RDONLY); if(fd2==-1) { printf("- %s : cannot open() : %s\n", adr2, strerror(errno)); close(fd1); return(0); } /* Content */ while(1) { r1= read(fd1, buf1, sizeof(buf1)); r2= read(fd2, buf2, sizeof(buf2)); if((r1==EOF && r2==EOF) || (r1==0 && r2==0)) break; if(r1==EOF || r1==0) { if(r1==EOF) r1= 0; if(s1.st_size > r1count + r1) printf("- %s : early EOF after %d bytes\n", adr1, r1count); differs= 1; } r1count+= r1; if(r2==EOF || r2 r2count + r2) printf("- %s : early EOF after %d bytes\n", adr2, r2count); differs= 1; } if(r2>r1) { if(s1.st_size > r1count + r1) printf("- %s : early EOF after %d bytes\n", adr1, r1count); differs= 1; } r2count+= r2; if(r1>r2) r1= r2; for(i= 0; i0 || r1count!=r2count) { if(first_diff<0) first_diff= (r1count>r2count ? r2count : r1count); printf("%s : %s : differs by at least %.f bytes. First at %.f\n", a, (s1.st_size==s2.st_size || s1.st_mtime==s2.st_mtime ? "CONTENT":"content"), (double) (diffcount + abs(r1count-r2count)), (double) first_diff); differs= 1; } } close(fd1); close(fd2); return(!differs); } int main(int argc, char **argv) { int ret, i, with_ctime= 1; char adr1[4096], adr2[4096], adrc[4096]; if(argc<4) { fprintf(stderr, "usage: %s path prefix1 prefix2\n", argv[0]); exit(2); } for(i= 4; i