diff --git a/test/compare_file.c b/test/compare_file.c new file mode 100644 index 00000000..714213f7 --- /dev/null +++ b/test/compare_file.c @@ -0,0 +1,172 @@ +/* + 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]; + 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); + } + + 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", adrc, s1.st_mode, s2.st_mode); + differs= 1; + } + if(s1.st_uid != s2.st_uid) { + printf("%s : st_uid : %d <> %d\n", adrc, s1.st_uid, s2.st_uid); + differs= 1; + } + if(s1.st_gid != s2.st_gid) { + printf("%s : st_gid : %d <> %d\n", adrc, 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", adrc, + (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", + adrc, (double) s1.st_size, (double) s2.st_size); + differs= 1; + } + if(s1.st_mtime != s2.st_mtime) { + printf("%s : st_mtime : %u <> %u\n", + adrc, (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", + adrc, (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", + adrc, (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(adr1, 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) { + printf("%s : early EOF after %d bytes\n", adr1, r1count); + differs= 1; + break; + } + r1count+= r1; + if(r2==EOF || r2r1) { + printf("%s : early EOF after %d bytes\n", adr1, r1count); + differs= 1; + break; + } + r2count+= r2; + for(i= 0; i0) { + printf("%s : Content differs by %.f bytes. First at %.f\n", + adr1, (double) diffcount, (double) first_diff); + differs= 1; + } + } + close(fd1); + close(fd2); + return(!differs); +} + + +int main(int argc, char **argv) +{ + int ret; + char adr1[4096], adr2[4096], adrc[4096]; + + if(argc<4) { + fprintf(stderr, "usage: %s path prefix1 prefix2\n", argv[0]); + exit(2); + } + + if(strncmp(argv[1], argv[2], strlen(argv[2]))!=0) { + fprintf(stderr, "%s: path '%s' does not match prefix1 '%s'\n", + argv[0], argv[1], argv[2]); + exit(2); + } + strcpy(adr1, argv[1]); + strcpy(adrc, argv[1]+strlen(argv[2])); + sprintf(adr2, "%s%s%s", argv[3], (adrc[0]=='/' ? "" : "/"), adrc); + + ret= Compare_2_files(adr1, adr2, adrc, 2); + exit(ret<=0); +} +