📄 afcompare.cpp
字号:
char b2[16]; printf("offset=%d\n",offset); memcpy(b2,data1+offset,16); b2[15]=0; printf("=== sector %"I64d" (offset=%d) ===\n",*j,offset); printf(" %s:\n",af_filename(af1)); print_sector(af1,data1+offset); printf("-------------------------------------\n"); printf(" %s:\n",af_filename(af2)); print_sector(af2,data2+offset); printf("=====================================\n\n"); } ret = 1; } free(data1); free(data2); return ret;}/* Compare the results of two files that were preened */int compare_preen(AFFILE *af1,AFFILE *af2){ vector<int64> pages; int comp_zero=0; int comp_lzma=0; int comp_unchanged=0; uint64 bytes_old = 0; uint64 bytes_new = 0; af_rewind_seg(af1); /* Build a list of all the pages */ char segname[AF_MAX_NAME_LEN]; while(af_get_next_seg(af1,segname,sizeof(segname),0,0,0)==0){ int64 pagenumber = af_segname_page_number(segname); if(pagenumber>=0) pages.push_back(pagenumber); } /* Now, compare each one */ for(vector<int64>::const_iterator i = pages.begin(); i != pages.end(); i++){ unsigned long arg1,arg2; size_t len1,len2; if(af_get_page_raw(af1,*i,&arg1,0,&len1)){ err(1,"Could not read page %"I64d" in file %s\n",*i,af_filename(af1)); } if(af_get_page_raw(af2,*i,&arg2,0,&len2)){ err(1,"Page %"I64d" is in file %s but not in %s\n",*i,af_filename(af1), af_filename(af2)); } if(arg1==arg2 && len1==len2){ comp_unchanged++; continue; } if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_ZERO){ comp_zero++; continue; } if((arg2 & AF_PAGE_COMP_ALG_MASK)==AF_PAGE_COMP_ALG_LZMA){ comp_lzma++; bytes_old += len1; bytes_new += len2; continue; } } printf("%s -> %s Nochg: %d NUL: %d LZMA: %d old: %"I64d" new: %"I64d" LZred: %6.2f%%\n", af_filename(af1), af_filename(af2), comp_unchanged,comp_zero,comp_lzma,bytes_old,bytes_new,(bytes_old-bytes_new)*100.0/bytes_old); return 0;}/* Compare two AFF files. * Return 0 if they are equal. */int compare_aff_aff(const char *file1,const char *file2){ bool no_data_segments = false; int ret = 0; current_source = file1; if(opt_all) printf("compare %s and %s:\n",file1,file2); AFFILE *af1 = af_open(file1,O_RDONLY,0); if(!af1) err(1,"af_open(%s)",file1); AFFILE *af2 = af_open(file2,O_RDONLY,0); if(!af2) err(1,"af_open(%s)",file2); af_vnode_info vni1,vni2; if(af_vstat(af1,&vni1) || af_vstat(af2,&vni2)){ err(1,"af_vstat failed?"); } if(af1->image_pagesize != af2->image_pagesize){ fprintf(stderr,"Currently, %s requires that both images have the " "same image datsegsize.\n" "pagesize(%s)=%ld\n" "pagesize(%s)=%ld\n", progname,file1,af1->image_pagesize, file2,af2->image_pagesize); fprintf(stderr,"Data segments will be ignored.\n"); no_data_segments = true; } if(af1->image_pagesize != af2->image_pagesize){ fprintf(stderr,"Currently, %s requires that both images have the " "same image sectorsize.\n" "sectorsize(%s)=%ld\n" "sectorsize(%s)=%ld\n", progname,file1,af1->image_sectorsize, file2,af2->image_sectorsize); fprintf(stderr,"Data segments will be ignored.\n"); no_data_segments = true; } if(opt_preen){ compare_preen(af1,af2); af_close(af1); af_close(af2); return 0; } if(opt_s3){ printf("bypass\n"); seglist list1; seglist list2; if(get_seglist(af1,&list1)) err(1,"get_seglist(%s) failed",af_filename(af1)); if(get_seglist(af2,&list2)) err(1,"get_seglist(%s) failed",af_filename(af2)); /* Just compare the presence/absence of each segment */ char title[1024]; snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af1),af_filename(af2)); for(seglist::const_iterator i=list1.begin(); i!=list1.end(); i++){ if(find(list2.begin(),list2.end(),*i)==list2.end()){ print_title(title); printf(" %s\n",(*i).name.c_str()); } } snprintf(title,sizeof(title),"\nPresent in %s but not %s:",af_filename(af2),af_filename(af1)); for(seglist::const_iterator i=list2.begin(); i!=list2.end(); i++){ if(find(list1.begin(),list1.end(),*i)==list1.end()){ print_title(title); printf(" %s\n",(*i).name.c_str()); } } return 0; } /* Compare all of the metadata segments in af1 with a2. * Report those that are missing or different. Then report * all of the segments in a2 but not in af1 */ /* First build a list of the segments in each */ vector <string> segs_with_dups; AFFILE *af[2] = {af1,af2}; for(int i=0;i<2;i++){ af_rewind_seg(af[i]); char segname[AF_MAX_NAME_LEN]; while(af_get_next_seg(af[i],segname,sizeof(segname),0,0,0)==0){ if(segname[0]){ string s; s = segname; segs_with_dups.push_back(s); // may give duplicates } } } sort(segs_with_dups.begin(),segs_with_dups.end()); vector<string>segs; /* Make a list of segs without duplicates */ string last; for(vector<string>::iterator i = segs_with_dups.begin(); i != segs_with_dups.end(); i++){ if(last != *i){ segs.push_back(*i); } last = *i; } int lowest_page = -1; int highest_page = -1; /* Scan for the lowest and highest numbers */ for(vector<string>::iterator i = segs.begin();i != segs.end(); i++){ int num = af_segname_page_number(i->c_str()); if(num!=-1){ if(num<lowest_page ||lowest_page==-1) lowest_page = num; if(num>highest_page||highest_page==-1) highest_page = num; } } if(opt_page != -1){ lowest_page = opt_page; highest_page = opt_page; } if(opt_page == -1 && vni1.supports_metadata && vni2.supports_metadata && opt_ignore_metadata==0 ){ if(opt_all) puts("Inspecting metadata..."); for(int mode=1;mode<=3;mode++){ char *title = "Metadata segments "; char mode_title[1024]; switch(mode){ case 1: snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n", title,af_filename(af1)); break; case 2: snprintf(mode_title,sizeof(mode_title)," %s only in %s:\n", title,af_filename(af2)); break; case 3: snprintf(mode_title,sizeof(mode_title)," %s in both files:\n",title); break; } for(vector<string>::iterator i = segs.begin();i != segs.end();i++){ int num = af_segname_page_number(i->c_str()); if(num==-1){ int r = compare_aff_metadata_segments(mode_title, af1,af2, i->c_str(),mode); if(r!=0) ret = r; } } } } if(opt_all) puts("Inspecting data..."); for(int mode=1;mode<=3;mode++){ char mode_title[1024]; switch(mode){ case 1: snprintf(mode_title,sizeof(mode_title), " Pages only in %s:\n", af_filename(af1));break; case 2: snprintf(mode_title,sizeof(mode_title), " Pages only in %s:\n", af_filename(af2));break; case 3: snprintf(mode_title,sizeof(mode_title)," Pages in both files:\n");break; } for(int i=lowest_page;i<=highest_page;i++){ int r = compare_aff_data_segments(mode_title,af1,af2,i,mode); if(r!=0) ret = r; } } current_source = 0; return ret;}int recurse(const char *dir1,const char *dir2){ vector<string> only_in_dir1; DIR *dirp = opendir(dir1); struct dirent *dp; if(!dirp) err(1,"opendir: %s",dir1); while ((dp = readdir(dirp)) != NULL){ char fn1[MAXPATHLEN+1]; memset(fn1,0,sizeof(fn1)); char fn2[MAXPATHLEN+1]; memset(fn2,0,sizeof(fn2)); strlcpy(fn1,dir1,sizeof(fn1)); if(fn1[strlen(fn1)-1]!='/') strlcat(fn1,"/",sizeof(fn1)); strlcat(fn1,dp->d_name,sizeof(fn1)); current_source = fn1; if(opt_verbose) printf("%s...\n",fn1); switch(af_identify_file_type(fn1,1)){ case AF_IDENTIFY_ERR: case AF_IDENTIFY_NOEXIST: only_in_dir1.push_back(fn1); break; case AF_IDENTIFY_AFF: case AF_IDENTIFY_AFD: case AF_IDENTIFY_AFM: strlcpy(fn2,dir2,sizeof(fn2)); if(fn2[strlen(fn2)-1]!='/') strlcat(fn2,"/",sizeof(fn2)); strlcat(fn2,dp->d_name,sizeof(fn2)); if(af_identify_file_type(fn2,1)<0){ char buf[1024]; snprintf(buf,sizeof(buf),"%s not in %s\n",dp->d_name,dir2); errors.push_back(buf); break; } if(opt_exist==0){ compare_aff_aff(fn1,fn2); } break; default: break; } } closedir(dirp); printf("========================\n"); printf("Only in %s\n",dir1); for(vector<string>::const_iterator i = only_in_dir1.begin(); i != only_in_dir1.end(); i++){ printf("%s\n",i->c_str()); } return 0;}int main(int argc,char **argv){ int bflag, ch; int opt_recurse=0;#ifdef SIGINFO signal(SIGINFO,sig_info);#endif bflag = 0; while ((ch = getopt(argc, argv, "P:Vabcempqrsh?v")) != -1) { switch (ch) { case 'P': opt_page = atoi(optarg); break; case 'V': printf("%s version %s\n",progname,PACKAGE_VERSION); exit(0); case 'a': opt_all++; break; case 'b': opt_print_sectors=1; break; case 'c': opt_print_sector_contents=1; break; case 'e': opt_exist++; break; case 'm': opt_ignore_metadata++; break; case 'p': opt_preen++; break; case 'q': opt_quiet++; break; case 'r': opt_recurse++; break; case 's': opt_s3++;break; case 'v': opt_verbose++;break; case 'h': case '?': default: usage(); } } argc -= optind; argv += optind; if(opt_recurse){ if(argc!=2) usage(); char *dir1 = *argv++; char *dir2 = *argv++; recurse(dir1,dir2); if(errors.size()>0){ fprintf(stderr,"================================\n"); fprintf(stderr,"%zd afcompare errors:\n",errors.size()); for(vector<string>::const_iterator i=errors.begin(); i!=errors.end(); i++){ fputs(i->c_str(),stderr); } exit(1); } exit(0); } if(argc>1){ char *last = argv[argc-1]; if(last[strlen(last)-1]=='/'){ while(argc>1){ char *file1 = *argv; char *name1 = file1; char *cc; cc = strrchr(file1,'/'); if(cc) name1 = cc+1; char file2[MAXPATHLEN+1]; strlcpy(file2,last,sizeof(file2)); strlcat(file2,name1,sizeof(file2)); int e_code = compare_aff_aff(file1,file2); if(e_code) exit(e_code); argv++; argc--; } } } if(argc!=2) usage(); // if just 2, compare them char *file1 = *argv++; char *file2 = *argv++; if(opt_verbose) printf("%s...\n",file1); int e_code = compare_aff_aff(file1,file2); exit(e_code);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -