📄 afconvert.cpp
字号:
struct af_vnode_info vni; af_vstat(a_out,&vni); if(vni.supports_compression){ if(opt_compression_alg){ af_enable_compression(a_out,opt_compression_alg,opt_compress_level); } else{ af_enable_compression(a_out,0,0); } } if(vni.supports_metadata){ af_update_seg(a_out,AF_MD5,0,md5_buf,16); af_update_seg(a_out,AF_SHA1,0,sha1_buf,20); } /* Get a list of all the metadata segments and the pages * (if this is a raw file, then the vnode raw driver will give us those segments) */ char segname[AF_MAX_NAME_LEN]; vector <string> metadata_segments; vector <int64> pages; af_rewind_seg(a_in); // start at the beginning int64 highest_pagenum = 0; while(af_get_next_seg(a_in,segname,sizeof(segname),0,0,0)==0){ int64 page_num = af_segname_page_number(segname); if(page_num>=0){ pages.push_back(page_num); if(page_num>highest_pagenum) highest_pagenum = page_num; } else { metadata_segments.push_back(segname); } } /* Copy over all of the metadata segments. * But don't bother if we are creating raw output */ if(opt_write_raw==0){ for(vector<string>::iterator i = metadata_segments.begin(); i != metadata_segments.end(); i++){ strlcpy(segname,i->c_str(),sizeof(segname)); size_t data_len = 0; unsigned long arg; /* First find out how big the segment is */ if(af_get_seg(a_in,segname,&arg,0,&data_len)){ warn("af_get_seg_1"); continue; } /* Now get the data */ unsigned char *data = (unsigned char *)malloc(data_len); if(af_get_seg(a_in,segname,0,data,&data_len)){ warn("af_get_seg_2"); free(data); continue; } /* Now put the data */ if(af_update_seg(a_out,segname,arg,data,data_len)){ err(1,"af_update_seg"); } free(data); } } /* Now sort the pages and copy them over. If there is no break, * we can compute the hashes... */ sort(pages.begin(),pages.end()); int64 prev_pagenum = -1; bool hash_valid = true; uint64 last_byte_in_image = 0; uint64 total_bytes_converted = 0; bool copy_by_pages = af_has_pages(a_in); if(copy_by_pages){ /* Copy over data one page at a time */ for(vector<int64>::iterator i = pages.begin(); i != pages.end(); i++){ int64 pagenum = *i; if(!opt_quiet) printf("Converting page %"I64d" of %"I64d"\r",pagenum,highest_pagenum);fflush(stdout); unsigned char *data = (unsigned char *)malloc(image_pagesize); size_t data_len = image_pagesize; if(af_get_page(a_in,pagenum,data,&data_len)){ err(1,"af_get_page(file=%s,page=%"I64d")", af_filename(a_in),pagenum); } if(af_update_page(a_out,pagenum,data,data_len)){ err(1,"af_update_page(file=%s,page=%"I64d")", af_filename(a_out),pagenum); } if(pagenum != prev_pagenum + 1) hash_valid = false; if(hash_valid){ MD5_Update(&md5,data,data_len); SHA1_Update(&sha,data,data_len); prev_pagenum = pagenum; } free(data); data = 0; last_byte_in_image = (int64)image_pagesize * pagenum + (int64)data_len; total_bytes_converted += data_len; } } else { /* No page support; Copy from beginning to end */ unsigned char *data = (unsigned char *)malloc(image_pagesize); while(!af_eof(a_in)){ int data_len = af_read(a_in,data,image_pagesize); if(data_len>0){ if(!opt_quiet){ printf("Writing to page %" I64d " with %d bytes read from input... \r", total_bytes_converted / image_pagesize,data_len); fflush(stdout); } if(af_write(a_out,data,data_len)!=data_len){ err(1,"af_write"); } MD5_Update(&md5,data,data_len); SHA1_Update(&sha,data,data_len); } if(data_len<0) err(1,"af_read"); if(data_len==0){ if(!opt_quiet) printf("af_read returned 0. Reached a sparse region or end of pipe.\n"); break; } last_byte_in_image += data_len; total_bytes_converted += data_len; } free(data); } if(!opt_quiet) printf("\n"); /* Write out the new hash if it is valid */ if(hash_valid){ MD5_Final(md5_buf,&md5); char buf[256]; if(af_update_seg(a_out,AF_MD5,0,md5_buf,16) && errno!=ENOTSUP){ err(1,"Could not update AF_MD5"); } if(!opt_quiet) printf("md5: %s\n",af_hexbuf(buf,sizeof(buf),md5_buf,16,1)); SHA1_Final(sha1_buf,&sha); if(af_update_seg(a_out,AF_SHA1,0,sha1_buf,20) && errno!=ENOTSUP){ err(1,"Could not update AF_SHA1"); } if(!opt_quiet) printf("sha1: %s\n",af_hexbuf(buf,sizeof(buf),sha1_buf,20,1)); } /* Go back and update the image size */ if(af_update_segq(a_out,AF_IMAGESIZE,last_byte_in_image) && errno!=ENOTSUP){ err(1,"Could not upate AF_IMAGESIZE"); } /* Finish the hash calculations and write to the db */ if(!opt_quiet){ printf("bytes converted: %qd \n",total_bytes_converted); /* If the vnode implementation tracked segments written, report it. */ if(a_out->pages_written || a_out->pages_compressed){ printf("Total pages: %"I64u" (%"I64u" compressed)\n", a_out->pages_written,a_out->pages_compressed); } } if(af_close(a_in)) err(1,"af_close(a_in)"); if(af_close(a_out)) err(1,"af_close(a_out)"); if(!opt_quiet){ printf("Conversion finished.\n"); printf("\n\n"); } /* Set the utime on the resulting file if we can stat it */ return(0);}int64 atoi64(const char *buf){ int64 r=0; sscanf(buf,"%"I64d,&r); return r;}int64 atoi64m(const char *optarg){ int multiplier; switch(optarg[strlen(optarg)-1]){ case 'g': case 'G': multiplier=1024*1024*1024;break; case 'm': case 'M': multiplier=1024*1024; break; case 'k': case 'K': multiplier=1024; break; case 'b': case 'B': multiplier=1;break; default: err(1,"Specify multiplier units of g, m, k or b in '%s'\n",optarg); } return atoi64(optarg) * multiplier;}int main(int argc,char **argv){ char *outfile = 0; int ch;#ifdef HAVE_LIBNCURSES setupterm((char *)0,1,(int *)0);#endif /* Figure out the command line that was used to run this program. * This information will be recorded in the AFF file. */ command_line = (char *)malloc(1); command_line[0] = 0; for(int i=0;i<argc;i++){ if(i>0) command_line = append(command_line," "); command_line = append(command_line,argv[i]); } while ((ch = getopt(argc, argv, "a:e:Lo:zqrs:xX:Zh?M:O::ydV")) != -1) { switch (ch) { case 'a': opt_aff_ext = optarg; break; case 'e': opt_write_raw++; opt_write_raw_ext = optarg; break; case 'o': outfile = optarg; break; case 'z': opt_zap ++; break; case 'q': opt_quiet++; break; case 'L': opt_compression_alg = AF_COMPRESSION_ALG_LZMA; break; case 'r': opt_write_raw++; break; case 's': image_pagesize = atoi64m(optarg); break; case 'x': opt_compression_alg=AF_COMPRESSION_ALG_NONE; break; case 'X': opt_compress_level = atoi(optarg); break; case 'Z': opt_nozprobe++; break; case 'y': opt_yes = 1; break; case 'M': opt_maxsize = atoi64m(optarg); break; case 'O': if(!optarg) err(1,"-O flag requires a directory"); opt_outdir = optarg; break; case 'd': opt_debug++; break; case 'h': case '?': default: usage(); exit(0); case 'V': printf("%s version %s\n",progname,PACKAGE_VERSION); exit(0); } } argc -= optind; argv += optind; if(argc<1){ usage(); } if(outfile){ convert(*argv,outfile); return 0; // only can convert a single file } while(*argv){ /* Come up with output file name */ char outfile[PATH_MAX]; memset(outfile,0,sizeof(outfile)); char *ext = opt_write_raw ? opt_write_raw_ext : opt_aff_ext; char *infile = *argv; argv++; argc--; /* Check for "-o filename" to specify the output arg... */ if(argc>=2 && strcmp(*argv,"-o")==0){ strlcpy(outfile,argv[1],sizeof(outfile)); argv += 2; argc -= 2; } else { /* Copy over the filename and change the extension */ strlcpy(outfile,infile,sizeof(outfile)); char *cc = rindex(outfile,'.'); // to strip off extension if(cc){ /* Found an extension; copy over mine. */ strlcpy(cc+1,ext,sizeof(outfile)-(cc-outfile)); } else { /* No extension; make one */ strlcat(outfile,".",sizeof(outfile)); strlcat(outfile,ext,sizeof(outfile)); } /* The user might want us to put things * in a different directory. Pull off the filename... */ if(opt_outdir){ cc = rindex(outfile,'/'); char filename[PATH_MAX]; if(cc){ strlcpy(filename,cc+1,sizeof(filename)); // just the filename } else{ strlcpy(filename,outfile,sizeof(filename)); // the outfile is the filename } strlcpy(outfile,opt_outdir,sizeof(outfile)); strlcat(outfile,"/",sizeof(outfile)); strlcat(outfile,filename,sizeof(outfile)); } } convert(infile,outfile); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -