📄 imager.cpp
字号:
*/ if(((direction==1) && (last_read_short==false)) || ((direction==-1) && (valid_reverse_data==true))){ write_data(buf,data_offset,bytes_to_read); bad_sectors_read += sectors_to_read; // I'm giving up on them... hash_invalid = true; } if(++consecutive_read_error_regions<retry_count){ // /* Just skip to the next area */ int sectors_to_bump = readsectors / 2; if(sectors_to_bump==0) sectors_to_bump = 1; // need to bump by a positive amount /* Is there room left? */ if(low_water_mark + sectors_to_bump > high_water_mark){ break; // no more room. } if(direction == 1){ low_water_mark += sectors_to_bump; // give a little bump } else { high_water_mark -= sectors_to_bump; } } else { /* Retry count in this directory exceeded. Either reverse * direction or give up... */ if(direction == 1){ consecutive_read_errors = 0; // reset count consecutive_read_error_regions = 0; direction = -1; continue; } if(direction == -1){ /* That's it. Give up */ break; } errx(1,"imager: Unknown direction: %d\n",direction); } } } if(error_mask==1){ /* Stop reading at the first error and write the incomplete buffer */ if(bytes_read>0){ write_data(buf,data_offset,bytes_read); } break; } } imaging = false; free(buf); buf = 0; // no longer valid free(badflag); badflag = 0;}/* Returns 0 if okay, -1 if failure. */int imager::set_input_fd(int ifd){ in = ifd; /* Make sure infile is actually a device, and not a file */ struct stat so; if(fstat(ifd,&so)){ perror("fstat"); return -1; } int mode = so.st_mode & S_IFMT; struct af_figure_media_buf afb; memset(&afb,0,sizeof(afb)); /* Now figure out how many input blocks we have */ if(mode==S_IFBLK || mode==S_IFCHR){ if (af_figure_media(in,&afb)){ return -1; } sector_size = afb.sector_size; total_sectors = afb.total_sectors; maxreadblocks = afb.max_read_blocks; return 0; } if(mode==S_IFREG){ // regular file if(allow_regular==false){ fprintf(stderr,"input is a regular file.\n"); fprintf(stderr,"Use afconvert or aimage -E to convert regular files to AFF.\n"); return -1; } /* Just got with the file size... */ sector_size = 512; // default total_sectors= so.st_size / sector_size; maxreadblocks = 0; return 0; } /* Okay. We don't know how big it will be, so just get what we can... */ sector_size = 512; // it's a good guess total_sectors = 0; // we don't know maxreadblocks = 0; // no limit return 0;}int imager::set_input(const char *name){ /* Set the input given a "name" * * First, try to open the input file. * If the name specified by the user can be opened, use it. * If the name cannot be opened work, see if it is a operating system * specific filename such as "ide0" or "ata0", in which the * operating system-specific code will attempt to attach the * device. */ /* Check for '-' which is stdin */ if(strcmp(name,"-")==0){ strcpy(infile,name); // make a local copy return set_input_fd(0); // file descriptor 0 is stdin } /* Check for 'listen:%d' which means listen for a TCP connection */ int port; if(sscanf(name,"listen:%d",&port)==1){ if(socket_listen(port)) return -1; // sets infile sector_size = 512; // no rationale for picking anything else return 0; } /* The name must be a file. See if we can open it... */ int ifd = open(name,O_RDONLY); if(ifd>0){ strcpy(infile,name); // make a local copy return set_input_fd(ifd); } /* Attempt to open infile failed; check for a special * device name... */ ifd = open_dev(name); if(ifd>0){ return set_input_fd(ifd); } /* If we haven't been able to open the something by this point, give up. */ perror(name); return -1;}void imager::hash_setup(){ /* Set up the MD5 & SHA1 machinery */ MD5_Init(&md5); SHA1_Init(&sha);}/* start_recover_scan(): * Do a recover scan... * Try to read all of the pages that are not in the image */void imager::start_recover_scan(){ if(total_sectors==0){ err(1,"total_sectors not set. Cannot proceed with recover_scan"); } if(af->image_sectorsize==0){ err(1,"af->image_sectorsize not set. Cannot proceed with recover_scan"); } if(af->image_pagesize==0){ err(1,"af->image_pagesize not set. Cannot proceed with recover_scan"); } int64 sectors_per_page = af->image_pagesize / af->image_sectorsize; int64 num_pages = (total_sectors+sectors_per_page-1) / sectors_per_page; int *pages = (int *)calloc(sizeof(int *),num_pages); printf("There are %qd pages... Checking to see which are in image...\n"); /* Now figure out which pages we have. * This only works with true AFF files, because we go directly to the TOC cache. */ for(int64 i=0;i<num_pages;i++){ char segname[AF_MAX_NAME_LEN]; snprintf(segname,sizeof(segname),AF_PAGE,i); if(af_toc(af,segname)){ printf("Page %qd is in the image...\r",i); pages[i]=1; // note that we have this page } } /* Print the missing pages: */ int missing_pages = 0; printf("Missing pages:\n"); for(int64 i=0;i<num_pages;i++){ if(pages[i]==0){ printf("%qd ",i); missing_pages++; } } printf("\n"); printf("Total missing pages: %d\n",missing_pages); /* Now randomly try to get each of the missing pages */#ifdef HAVE_SRANDOMDEV srandomdev();#endif while(missing_pages>0){ int random_page = random() % num_pages; while(pages[random_page]!=0) random_page = (++random_page) % num_pages; printf("*** try for page %d\n",random_page); uint64 start_sector = random_page * sectors_per_page; uint64 end_sector = start_sector + sectors_per_page; image_loop(start_sector,end_sector,1,opt_readsectors,1); pages[random_page] = 1; // did that page missing_pages--; } free(pages); exit(0);}/* start_imaging2(): * Actually run the imaging */void imager::start_imaging2(){ retry_count = opt_retry_count; /* See if the skipping makes sense */ if(!opt_skip_sectors){ if(opt_skip % sector_size != 0){ fprintf(stderr, "Skipping must be an integral multiple of sector size " "(%d bytes)\n",sector_size); imaging_failed = true; return; } opt_skip /= sector_size; // get the actuall offset } int starting_direction = 1; if(opt_reverse) starting_direction = -1; /**************************************************************** *** Start imaging ****************************************************************/ signal(SIGINT,sig_intr); // set the signal handler hash_setup(); // get ready... image_loop(opt_skip, total_sectors,starting_direction, opt_readsectors,opt_error_mode); // start the process signal(SIGINT,0); // unset the handler /**************************************************************** *** Finished imaging ****************************************************************/ /* Calculate the final MD5 and SHA1 */ MD5_Final(final_md5,&md5); SHA1_Final(final_sha1,&sha);}/* Start the imaging. * If files are specified, opens them. * then does the imaging. * Then closes the files. */int imager::start_imaging(){ output_ident = new class ident(fname_aff[0] ? fname_aff : fname_raw); /* If the user is imaging to an AFF file, * open it and try to ident the drive. * Drive ident is not done if writing to a raw file, because * there is no place to store the ident information. This will be changed * when we can write an XML log. */ if(af){ af->tag = (void *)this; // remember me! /* If the segment size hasn't been set, then set it */ if(opt_append){ /* Make sure that the AFF file is for this drive, and set it up */ } else { ident(); // ident the drive if possible af_update_seg(af,AF_ACQUISITION_COMMAND_LINE,0,command_line,strlen(command_line)); af_update_seg(af,AF_ACQUISITION_DEVICE,0,infile,strlen(infile)); af_set_sectorsize(af,sector_size); af_set_pagesize(af,opt_pagesize); // sets current page size if(opt_maxsize){ if(af_set_maxsize(af,opt_maxsize)){ exit(-1); } } if(total_sectors>0){ af_update_segq(af,AF_DEVICE_SECTORS,(int64)total_sectors); } if(opt_no_ifconfig==0){ char *macs = ident::mac_addresses(); if(macs){ af_update_seg(af,AF_ACQUISITION_MACADDR,0,macs,strlen(macs)); free(macs); } } if(opt_no_dmesg==0){ char *dmesg = ident::dmesg(); if(dmesg && strlen(dmesg)){ af_update_seg(af,AF_ACQUISITION_DMESG,0,dmesg,strlen(dmesg)); free(dmesg); } } if(af_get_seg(af,AF_IMAGE_GID,0,0,0)!=0){ unsigned char bit128[16]; RAND_pseudo_bytes(bit128,sizeof(bit128)); af_update_seg(af,AF_IMAGE_GID,0,bit128,sizeof(bit128)); } } af_set_callback(af,segwrite_callback); char timeseg[65536]; size_t datalen = sizeof(timeseg); memset(timeseg,0,sizeof(timeseg)); af_get_seg(af,AF_ACQUISITION_DATE,0, (unsigned char *)timeseg,&datalen); time_t t = time(0); char timebuf[64]; strftime(timebuf,sizeof(timebuf),"%Y-%m-%d %H:%M:%S\n",localtime(&t)); strlcat(timeseg,timebuf,sizeof(timeseg)); af_update_seg(af,AF_ACQUISITION_DATE,0,timeseg,strlen(timeseg)); } /* Here is where the imaging takes place. * Do it unless ifd==FD_IDENT, which is the fictitious FD. */ if(logfile){ fprintf(logfile,"aimage infile=%s ",infile); if(fname_raw[0]) fprintf(logfile,"outfile_raw=%s ",fname_raw); if(fname_aff[0]) fprintf(logfile,"outfile_aff=%s ",fname_aff); fprintf(logfile,"\n"); } if(in!=FD_IDENT){ imaging_timer.start(); if(opt_recover_scan){ start_recover_scan(); } else{ start_imaging2(); } imaging_timer.stop(); } /* AFF Cleanup... */ if(af){ if(hash_invalid==false){ if(af_update_seg(af,AF_MD5,0,final_md5,16)){ if(errno!=ENOTSUP) perror("Could not update AF_MD5"); } if(af_update_seg(af,AF_SHA1,0,final_sha1,20)){ if(errno!=ENOTSUP) perror("Could not update AF_SHA1"); } } else { af_del_seg(af,AF_MD5); // because it is not valid af_del_seg(af,AF_SHA1); } if(af_update_segq(af,AF_BADSECTORS, (int64)bad_sectors_read)){ if(errno!=ENOTSUP) perror("Could not update AF_BADSECTORS"); } if(af_update_segq(af,AF_BLANKSECTORS, (int64)total_blank_sectors)){ if(errno!=ENOTSUP) perror("Could not update AF_BLANKSECTORS"); } unsigned long elapsed_seconds = (unsigned long)imaging_timer.elapsed_seconds(); if(af_update_seg(af,AF_ACQUISITION_SECONDS,elapsed_seconds,0,0)){ if(errno!=ENOTSUP) perror("Could not update AF_ACQUISITION_SECONDS"); } } return 0;}/* Listen for a local socket connection and return the * file descriptor... */int imager::socket_listen(int port){ struct sockaddr_in local; struct sockaddr_in remote; socklen_t rsize = sizeof(remote); int sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP); /* Open a listening socket ... */ memset(&local,0,sizeof(local)); memset(&remote,0,sizeof(remote));#ifdef HAVE_SOCKADDR_SIN_LEN local.sin_len = sizeof(sockaddr_in);#endif local.sin_family = AF_INET; local.sin_port = htons(port); // listen on requested port. if(bind(sock,(sockaddr *)&local,sizeof(local))) err(1,"bind"); if(listen(sock,0)) err(1,"listen"); // listen, and only accept one printf("Listening for connection on port %d...\n",port); in = accept(sock,(sockaddr *)&remote,&rsize); if(in<0){ perror("accept"); in = 0; return -1; } strcpy(infile,inet_ntoa(remote.sin_addr)); printf("Connection accepted from %s\n",infile); return 0;}/* final_report(): * Let's make the user feel good... */void imager::final_report(){ bold("****************************** IMAGING REPORT ******************************"); putchar('\n'); printf("Input: "); bold(infile); putchar('\n'); if(device_model[0]){ printf(" Model: "); bold(device_model); } if(serial_number[0]){ printf(" S/N: "); bold(serial_number); } putchar('\n'); if(fname_aff[0]){ printf(" AFF Output file: "); bold(fname_aff); } if(fname_raw[0]){ printf(" Raw Output file: "); bold(fname_raw); } putchar('\n'); char buf[64]; printf(" Bytes read: %s\n", af_commas(buf,total_bytes_read)); printf(" Bytes written: %s\n", af_commas(buf,callback_bytes_written)); char print_buf[256]; printf("\n"); if(hash_invalid==false){ printf("raw image md5: %s\n", af_hexbuf(print_buf,sizeof(print_buf),final_md5,16,opt_hexbuf)); printf("raw image sha1: %s\n", af_hexbuf(print_buf,sizeof(print_buf),final_sha1,20,opt_hexbuf)); } if(imaging_failed){ printf("\nTHIS DRIVE COULD NOT BE IMAGED DUE TO A HARDWARE FAILURE.\n"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -