📄 afcompare.cpp
字号:
/* * acompare.cpp: * * Compare the contents of an ISO file to an AFF file. * Optionally, if they are equal, delete the ISO file *//* * Copyright (c) 2005 * Simson L. Garfinkel and Basis Technology, Inc. * All rights reserved. * * This code is derrived from software contributed by * Simson L. Garfinkel * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Simson L. Garfinkel * and Basis Technology Corp. * 4. Neither the name of Simson Garfinkel, Basis Technology, or other * contributors to this program may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY SIMSON GARFINKEL, BASIS TECHNOLOGY, * AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL SIMSON GARFINKEL, BAIS TECHNOLOGy, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "config.h"#include "afflib.h"#include "afflib_i.h"#include "utils.h"#include <sys/signal.h>#include <ctype.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <fcntl.h>#include <limits.h>#include <string.h>#include <zlib.h>#include <openssl/md5.h>#include <openssl/sha.h>#include <assert.h>char *progname = "afcompare";int opt_quiet = 0;int opt_all = 0;int opt_print_sectors = 0;int opt_print_sector_contents = 0;int opt_page = -1;int opt_preen = 0;int opt_exist = 0;int opt_ignore_metadata = 0;int opt_s3 = 0;int opt_verbose = 0;char *batch_ext = "";vector<string> errors;const char *current_source = 0;void sig_info(int arg){ if(current_source){ printf("%s... ",current_source); } printf("\n"); fflush(stdout);}void print_title(char *title){ if(title[0]){ puts(title); title[0] = 0; }}void usage(){ printf("afcompare version %s\n",PACKAGE_VERSION); printf("\n"); printf("usage: afcompare [options] file1 file2\n"); printf(" compares file1 with file2\n"); printf("\n"); printf("or afcompare [options] -r dir1 dir2\n"); printf(" comparses similarly-named files in dir1 and dir2\n"); printf("\n"); printf("or afcompare [options] -s file1 file2...\n"); printf(" Reports if file was successfully copied to Amazon S3\n"); printf(" checking only for existence, not reading back the bytes.\n"); printf(" (Because all writes to S3 are validated by the MD5 of the object\n");#ifndef USE_S3 printf(" NOTE: S3 support is not provided in this version\n");#endif printf("fast options:\n"); printf("(These compare segments but not their contents.)\n"); printf(" -p --- report about the results of preening\n"); printf(" -e --- Just report about existence (use with -r)\n"); printf(" -s --- Just see if all of the segments are present, but don't\n"); printf(" validate the contents. (Primarily for use with Amazon S3)\n"); printf("other options:\n"); printf(" -V --- just print the version number and exit\n"); printf(" -v --- Verbose; each file as it is compared.\n"); printf(" -q --- Quiet. No output except for errors\n"); printf(" -a --- print what's the same (all)\n"); printf(" -b --- print the numbers of differing sectors\n"); printf(" -c --- print the contents of differing sectors\n"); printf(" -m --- Just report about the data (ignore metadata)\n"); printf(" -P ### --- Just examine the differences on page ###\n"); printf(" -q --- Quiet; no output except for errors.\n"); printf("\n"); printf("Options documented above:\n"); printf(" -r dir1 dir2 --- recursively compare what's in dir1 with dir2, and\n"); printf(" report what's in dir1 that's not in dir2\n"); printf(" -s --- Check to see if named files are on Amazon S3\n"); printf("\n"); printf(" afcompare file1.aff file2.aff --- compare file1.aff and file2.aff\n"); printf(" afcompare f1.aff f2.aff dir1/ --- compare f1.aff with dir1/f1.aff and f2.aff with dir2/f2.aff\n"); printf(" note: dir1/ must end with a slash.\n"); printf(" afcompare -b img file.aff --- compare file.aff and file.img\n"); printf(" afcompare -b img file1.aff file2.aff... --- compare file1.aff, file1.img, etc.\n"); printf(" afcompare -re dir1 dir2 --- report AFF files in dir1 but not in dir2\n"); printf(" afcompare -rse dir1 s3:/// --- report AFF files in dir1 but not on S3 (low bandwidth)\n"); printf(" afcompare -rs dir1 s3:/// --- report AFF files in dir1 but incomplete on on S3 (more bandwidth)\n"); printf("\n"); exit(0);}void print_sector(AFFILE *af,unsigned char *buf){ for(unsigned int i=0;i<af->image_sectorsize;i++){ if(isprint(buf[i])){ putchar(buf[i]); } else { putchar('.'); } if(i%64==63) putchar('\n'); }}void print_info(char dir,const char *segname,unsigned long arg,size_t len, unsigned char *data,int mcr){ printf(" %c %s arg=%lu len=%d\n",dir,segname,arg,(int)len); printf(" "); if((arg == AF_SEG_QUADWORD) && (len==8)){ printf("data=%"I64d" as a 64-bit value\n",af_decode_q(data)); return; } /* Otherwise, just print some stuff... */ for(unsigned int i=0;i<len && i<60;i++){ if(data[i]==' '){ putchar(' '); continue; } if(!isprint(data[i])){ putchar('.'); continue; } putchar(data[i]); } putchar('\n');}int compare_aff_metadata_segments(char *title,AFFILE *af1,AFFILE *af2,const char *segname,int mode){ int ret = 0; unsigned long arg1 = 0; size_t data1_len = 0; int r1 = af_get_seg(af1,segname,&arg1,0,&data1_len); unsigned long arg2 = 0; size_t data2_len = 0; int r2 = af_get_seg(af2,segname,&arg2,0,&data2_len); if(r1==0 && r2!=0){ if(mode==1){ print_title(title); printf(" %s \n",segname); } return 1; } if(r1!=0 && r2==0){ if(mode==2){ print_title(title); printf(" %s \n",segname); } return 1; } if(mode!=3) return 0; // only report differences in mode 3 /* Get the actual data... */ unsigned char *data1 = (unsigned char *)malloc(data1_len); unsigned char *data2 = (unsigned char *)malloc(data2_len); int s1 = af_get_seg(af1,segname,&arg1,data1,&data1_len); if(s1!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af1)); int s2 = af_get_seg(af2,segname,&arg2,data2,&data2_len); if(s2!=0) err(1,"Couldn't read data segment %s in %s",segname,af_filename(af2)); int mcr = 0; if(data1_len != data2_len) mcr = 1; else mcr = memcmp(data1,data2,data1_len); if(arg1!=arg2 || data1_len!=data2_len || mcr!=0){ print_title(title); print_info('<',segname,arg1,data1_len,data1,mcr); print_info('>',segname,arg2,data2_len,data2,mcr); if(mcr){ printf(" *** Metadata segment are different "); if(strcmp(segname,AF_BADFLAG)==0){ printf("(bad flags should be different!)"); } putchar('\n'); } putchar('\n'); ret = 1; } else { if(opt_all){ print_title(title); printf(" %s (same in both) \n",segname); } } free(data1); free(data2); return ret;}int compare_aff_data_segments(char *title,AFFILE *af1,AFFILE *af2,int64 pagenum,int mode){ int ret = 0; char pagename[65]; snprintf(pagename,sizeof(pagename),AF_PAGE,pagenum); char segname[65]; snprintf(segname,sizeof(segname),AF_SEG_D,pagenum); unsigned long arg1=0; size_t data1_len=0; int r1 = af_get_seg(af1,pagename,&arg1,0,&data1_len); if(r1==-1) r1=af_get_seg(af1,segname,&arg1,0,&data1_len); unsigned long arg2=0; size_t data2_len=0; int r2 = af_get_seg(af2,pagename,&arg2,0,&data2_len); if(r2 == -1) r2=af_get_seg(af2,segname,&arg2,0,&data2_len); if(r1<0 && r2<0) return 0; // no data segment in either file if(r1==0 && r2!=0){ if(mode==1){ print_title(title); printf(" %s \n",segname); } return 1; } if(r2==0 && r1!=0){ if(mode==2){ print_title(title); printf(" %s \n",segname); } return 1; } if(mode!=3) return 0; // only report differences in mode 3 /* Get the actual data... */ unsigned char *data1 = (unsigned char *)malloc(af_page_size(af1)); unsigned char *data2 = (unsigned char *)malloc(af_page_size(af2)); data1_len = af_page_size(af1); data2_len = af_page_size(af2); uint64 start_sector_number = (pagenum * data1_len) / af1->image_sectorsize; if(af_get_page(af1,pagenum,data1,&data1_len)<0) err(1,"Cannot read page %"I64d" from %s\n",pagenum,af_filename(af1)); if(af_get_page(af2,pagenum,data2,&data2_len)<0) err(1,"Cannot read page %"I64d" from %s\n",pagenum,af_filename(af2)); /* Now look at the pages sector-by-sector. */ int af1_bad=0; int af2_bad=0; int matching_bad_sectors = 0; int matching_sectors = 0; int total_sectors = 0; int no_match = 0; vector<uint64> different_sectors; for(unsigned int offset=0;offset<data1_len;offset+=af1->image_sectorsize){ uint64 this_sector = start_sector_number + offset/af1->image_sectorsize; total_sectors++; if(af_is_badsector(af1,data1+offset) && af_is_badsector(af2,data2+offset)){ matching_bad_sectors++; continue; } if(af_is_badsector(af1,data1+offset)){ af1_bad++; continue; } if(af_is_badsector(af2,data2+offset)){ af2_bad++; continue; } if(memcmp(data1+offset,data2+offset,af1->image_sectorsize)==0){ matching_sectors++; continue; } no_match++; different_sectors.push_back(this_sector); } char outline[256]; outline[0] = 0; if(opt_all || (no_match>0) || af1_bad || af2_bad){ snprintf(outline,sizeof(outline), " page%"I64d" sectors:%4d matching: %3d different:%3d", pagenum,total_sectors,matching_sectors,no_match); } if(af1_bad){ snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline), " file 1 bad: %3d ",af1_bad); } if(af2_bad){ snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline), " file 2 bad: %3d ",af2_bad); } if(matching_bad_sectors){ if(opt_all){ snprintf(outline+strlen(outline),sizeof(outline)-strlen(outline), " bad both:%3d ",matching_bad_sectors); } } if(outline[0]){ print_title(title); puts(outline); } if(opt_print_sectors && different_sectors.size()>0){ print_title(title); printf(" Sectors with differences:"); int i=0; for(vector<uint64>::iterator j = different_sectors.begin(); j != different_sectors.end(); j++){ if(i==0){ printf("\n "); } printf(" %"I64d,*j); i = (i+1) % 10; } putchar('\n'); ret = 1; } if(opt_print_sector_contents && different_sectors.size()>0){ print_title(title); printf(" Sectors with differences:"); for(vector<uint64>::iterator j = different_sectors.begin(); j != different_sectors.end(); j++){ int offset = (*j - start_sector_number)*af1->image_sectorsize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -