static void warning_geometry_ncurses(disk_t *disk_car, const unsigned int recommanded_heads_per_cylinder) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,6,0); wprintw(stdscr, "Warning: the current number of heads per cylinder is %u", disk_car->geom.heads_per_cylinder); wmove(stdscr,7,0); wprintw(stdscr,"but the correct value may be %u.",recommanded_heads_per_cylinder); wmove(stdscr,8,0); wprintw(stdscr,"You can use the Geometry menu to change this value."); wmove(stdscr,9,0); wprintw(stdscr,"It's something to try if"); wmove(stdscr,10,0); wprintw(stdscr,"- some partitions are not found by TestDisk"); wmove(stdscr,11,0); wprintw(stdscr,"- or the partition table can not be written because partitions overlap."); wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); wprintw(stdscr,"[ Continue ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); while(wgetch(stdscr)==ERR); }
static void change_part_type_ncurses(const disk_t *disk_car,partition_t *partition) { partition_t *new_partition; char response[100]; int size=0; int i; unsigned int last[3], done = 0, next = 0; struct part_name_struct part_name[0x100]; struct MenuItem menuType[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Proceed","Go set the partition type"}, { 0, NULL, NULL } }; if(partition->arch->set_part_type==NULL) return ; /* Create an index of all partition type except Intel extended */ new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); for(i=0;i<=0xFF;i++) { if(partition->arch->set_part_type(new_partition,i)==0) { part_name[size].name=new_partition->arch->get_partition_typename(new_partition); if(part_name[size].name!=NULL) part_name[size++].index=i; } } free(new_partition); /* Display the list of partition type in 3 columns */ screen_buffer_reset(); screen_buffer_add("List of partition type\n"); for (i = 2; i >= 0; i--) last[2 - i] = done += (size + i - done) / (i + 1); i = done = 0; while (done < last[0]) { screen_buffer_add( "%02x %-20s%c", part_name[next].index, part_name[next].name,(i==2 ? '\n' : ' ')); next = last[i++] + done; if (i > 2 || next >= last[i]) { i = 0; next = ++done; } } /* Ask for the new partition type*/ aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); screen_buffer_display(stdscr,"",menuType); wmove(stdscr,LINES-2,0); wclrtoeol(stdscr); wprintw(stdscr,"New partition type [current %02x] ? ",partition->arch->get_part_type(partition)); if (get_string(stdscr, response, sizeof(response), NULL) > 0) { int tmp_val = strtol(response, NULL, 16); partition->arch->set_part_type(partition,tmp_val); } }
int interface_superblock(disk_t *disk_car,list_part_t *list_part, char**current_cmd) { const list_part_t *parts; const partition_t *old_part=NULL; #ifdef HAVE_NCURSES struct MenuItem menuSuperblock[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quit","Return to Advanced menu"}, { 0, NULL, NULL } }; #endif screen_buffer_reset(); #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,5,0); mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); #endif for(parts=list_part;parts!=NULL;parts=parts->next) { const partition_t *partition=parts->part; if(old_part==NULL || old_part->part_offset!=partition->part_offset || old_part->part_size!=partition->part_size || guid_cmp(old_part->part_type_gpt, partition->part_type_gpt)!=0 || old_part->part_type_i386!=partition->part_type_i386 || old_part->part_type_sun!=partition->part_type_sun || old_part->part_type_mac!=partition->part_type_mac || old_part->upart_type!=partition->upart_type) { aff_part_buffer(AFF_PART_BASE, disk_car, partition); old_part=partition; } if(partition->blocksize!=0) screen_buffer_add("superblock %lu, blocksize=%u [%s]\n", (long unsigned)(partition->sb_offset/partition->blocksize), partition->blocksize, partition->fsname); } if(list_part!=NULL) { const partition_t *partition=list_part->part; screen_buffer_add("\n"); screen_buffer_add("To repair the filesystem using alternate superblock, run\n"); screen_buffer_add("fsck.ext%u -p -b superblock -B blocksize device\n", (partition->upart_type==UP_EXT2?2: (partition->upart_type==UP_EXT3?3:4))); } screen_buffer_to_log(); if(*current_cmd==NULL) { log_flush(); #ifdef HAVE_NCURSES screen_buffer_display(stdscr,"",menuSuperblock); #endif } return 0; }
static const char *exFAT_boot_sector_rescan(disk_t *disk, partition_t *partition, unsigned char *buffer_bs, unsigned char *buffer_backup_bs) { const int size_bs=12 * disk->sector_size; int opt_B=0; int opt_O=0; #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk->description(disk)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); #endif log_info("\nexFAT_boot_sector\n"); log_partition(disk,partition); screen_buffer_add("Boot sector\n"); if(disk->pread(disk, buffer_bs, size_bs, partition->part_offset) != size_bs) { screen_buffer_add("Bad: can't read exFAT boot record.\n"); memset(buffer_bs,0,size_bs); } else if(test_exFAT((const struct exfat_super_block*)buffer_bs)==0) { screen_buffer_add("exFAT OK\n"); opt_O=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\nBackup boot record\n"); if(disk->pread(disk, buffer_backup_bs, size_bs, partition->part_offset + size_bs) != size_bs) { screen_buffer_add("Bad: can't read exFAT backup boot record.\n"); memset(buffer_backup_bs,0,size_bs); } else if(test_exFAT((const struct exfat_super_block*)buffer_backup_bs)==0) { screen_buffer_add("exFAT OK\n"); opt_B=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\n"); if(memcmp(buffer_bs, buffer_backup_bs, size_bs)==0) { screen_buffer_add("Sectors are identical.\n"); return "D"; } else { screen_buffer_add("Sectors are not identical.\n"); } if(opt_B!=0 && opt_O!=0) return "DOB"; else if(opt_B!=0) return "DB"; else if(opt_O!=0) return "DO"; return "D"; }
int intrf_no_disk_ncurses(const char *prog_name) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr," %s is free software, and",prog_name); wmove(stdscr,5,0); wprintw(stdscr,"comes with ABSOLUTELY NO WARRANTY."); wmove(stdscr,7,0); wprintw(stdscr,"No harddisk found\n"); #if defined(__CYGWIN__) || defined(__MINGW32__) wmove(stdscr,8,0); wprintw(stdscr,"You need to be administrator to use %s.\n", prog_name); wmove(stdscr,9,0); wprintw(stdscr,"Under Win9x, use the DOS version instead.\n"); wmove(stdscr,10,0); wprintw(stdscr,"Under Vista or later, select %s, right-click and\n", prog_name); wmove(stdscr,11,0); wprintw(stdscr,"choose \"Run as administrator\".\n"); #elif defined(DJGPP) #else #ifdef HAVE_GETEUID if(geteuid()!=0) { wmove(stdscr,8,0); wprintw(stdscr,"You need to be root to use %s.\n", prog_name); #ifdef SUDO_BIN { static const struct MenuItem menuSudo[]= { {'S',"Sudo","Use the sudo command to restart as root"}, {'Q',"Quit",""}, {0,NULL,NULL} }; unsigned int menu=0; int command; command = wmenuSelect_ext(stdscr,23, 20, 0, menuSudo, 8, "SQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu,NULL); if(command=='s' || command=='S') return 1; return 0; } #endif } #endif #endif wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr,"[ Quit ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); while(wgetch(stdscr)==ERR); return 0; }
void dump_ncurses(const void *nom_dump, unsigned int lng) { WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */ keypad(window, TRUE); /* Need it to get arrow key */ aff_copy(window); dump(window, nom_dump, lng); dump_log(nom_dump,lng); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif }
static void exFAT_dump_ncurses(disk_t *disk, const partition_t *partition, const unsigned char *buffer_bs, const unsigned char *buffer_backup_bs) { WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */ keypad(window, TRUE); /* Need it to get arrow key */ aff_copy(window); wmove(window,4,0); wprintw(window,"%s",disk->description(disk)); wmove(window,5,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); mvwaddstr(window,6,0, "Boot sector Backup boot record"); dump2(window, buffer_bs, buffer_backup_bs, 12 * disk->sector_size); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif }
int ask_confirmation(const char*_format, ...) { va_list ap; int res; WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */ aff_copy(window); va_start(ap,_format); vaff_txt(4, window, _format, ap); va_end(ap); res=ask_YN(window); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif return res; }
void display_message(const char*msg) { static const struct MenuItem menuGeometry[]= { { 'Q', "Ok", "" }, { 0, NULL, NULL } }; WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */ log_info("%s",msg); aff_copy(window); mvwaddstr(window,5,0,msg); wmenuSimple(window,menuGeometry, 0); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif }
void not_implemented(const char *msg) { WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */ aff_copy(window); wmove(window,7,0); wprintw(window,"Function %s not implemented",msg); log_warning("Function %s not implemented\n",msg); wmove(window,22,0); wattrset(window, A_REVERSE); wprintw(window,"[ Abort ]"); wattroff(window, A_REVERSE); wrefresh(window); while(wgetch(window)==ERR); delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif }
char *ask_log_location(const char*filename, const int errsv) { static char response[128]; aff_copy(stdscr); if(filename!=NULL) { wmove(stdscr,6,0); wprintw(stdscr,"Cannot open %s: %s\n",filename, strerror(errsv)); } wmove(stdscr,8,0); wprintw(stdscr,"Please enter the full log filename or press "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); wprintw(stdscr,"Enter"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); wmove(stdscr,9,0); wprintw(stdscr,"to abort log file creation.\n"); wclrtoeol(stdscr); if (get_string(stdscr, response, sizeof(response), NULL) > 0) return response; return NULL; }
int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd) { int ind_stop=0; uint64_t nbr_read_error=0; uint64_t src_offset=partition->part_offset; uint64_t src_offset_old; uint64_t dst_offset=0; const uint64_t src_offset_end=partition->part_offset+partition->part_size; const uint64_t offset_inc=(src_offset_end-src_offset)/10000; uint64_t src_offset_next=src_offset; struct stat stat_buf; unsigned char *buffer=(unsigned char *)MALLOC(READ_SIZE); unsigned int readsize=READ_SIZE; int disk_dst; #ifdef HAVE_NCURSES WINDOW *window; #endif if((disk_dst=open(image_dd, O_CREAT|O_LARGEFILE|O_RDWR|O_BINARY, 0644)) < 0) { log_error("Can't create file %s.\n",image_dd); display_message("Can't create file!\n"); free(buffer); return -1; } if(fstat(disk_dst, &stat_buf)==0) { int res=1; #ifdef HAVE_NCURSES if(stat_buf.st_size > 0) res=ask_confirmation("Append to existing file ? (Y/N)"); #endif if(res>0) { dst_offset=stat_buf.st_size; src_offset+=dst_offset; } } src_offset_old=src_offset; #ifdef HAVE_NCURSES window=newwin(LINES, COLS, 0, 0); /* full screen */ aff_copy(window); wmove(window,5,0); wprintw(window,"%s\n",disk->description_short(disk)); wmove(window,6,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); wmove(window,10,0); waddstr(window, "Disk images are mainly used "); wmove(window,11,0); waddstr(window, "- for forensics purpose"); wmove(window,12,0); waddstr(window, "- or to deal with media with bad sectors"); #ifdef WIN32 wmove(window,14,0); waddstr(window, "To use TestDisk or PhotoRec with this disk image, go in command line and run"); wmove(window,15,0); waddstr(window, " testdisk_win.exe image.dd"); wmove(window,16,0); waddstr(window, "or photorec_win.exe image.dd"); #else wmove(window,14,0); waddstr(window, "To use TestDisk or PhotoRec with this disk image, start a Terminal and run"); wmove(window,15,0); waddstr(window, " testdisk image.dd"); wmove(window,16,0); waddstr(window, "or photorec image.dd"); #endif wmove(window,22,0); wattrset(window, A_REVERSE); waddstr(window," Stop "); wattroff(window, A_REVERSE); #endif while(ind_stop==0 && src_offset < src_offset_end) { ssize_t pread_res; int update=0; if(src_offset_end-src_offset < readsize) readsize=src_offset_end-src_offset; pread_res=disk->pread(disk, buffer, readsize, src_offset); if(pread_res > 0) { #if defined(HAVE_PWRITE) if(pwrite(disk_dst, buffer, pread_res, dst_offset)<0) { ind_stop=2; } #else if(lseek(disk_dst, dst_offset, SEEK_SET)<0) { ind_stop=2; } if(write(disk_dst, buffer, pread_res) != pread_res) { ind_stop=2; } #endif if(src_offset_old + SKIP_SIZE==src_offset) { disk_image_backward(disk_dst, disk, src_offset_old, src_offset, dst_offset); } } src_offset_old=src_offset; if((unsigned)pread_res == readsize) { src_offset+=readsize; dst_offset+=readsize; readsize=READ_SIZE; } else { update=1; nbr_read_error++; readsize=disk->sector_size; src_offset+=SKIP_SIZE; dst_offset+=SKIP_SIZE; } if(src_offset>src_offset_next) { update=1; src_offset_next=src_offset+offset_inc; } if(update) { #ifdef HAVE_NCURSES unsigned int i; const float percent=(src_offset-partition->part_offset)*100.00/partition->part_size; wmove(window,7,0); wprintw(window,"%3.2f %% ", percent); for(i=0;i<percent*3/5;i++) wprintw(window,"="); wprintw(window,">"); wrefresh(window); ind_stop=check_enter_key_or_s(window); #endif } } close(disk_dst); #ifdef HAVE_NCURSES delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif #endif if(ind_stop==2) { display_message("No space left for the file image.\n"); free(buffer); return -2; } if(ind_stop) { if(nbr_read_error==0) display_message("Incomplete image created.\n"); else display_message("Incomplete image created: read errors have occured.\n"); free(buffer); return 0; } if(nbr_read_error==0) display_message("Image created successfully.\n"); else display_message("Image created successfully but read errors have occured.\n"); free(buffer); return 0; }
int start_ncurses(const char *prog_name, const char *real_prog_name) { #if defined(DJGPP) || defined(__MINGW32__) if(initscr()==NULL) { log_critical("initscr() has failed. Exiting\n"); printf("initscr() has failed. Exiting\n"); printf("Press Enter key to quit.\n"); getchar(); return 1; } #else { int term_overwrite; char *terminfo=filename_to_directory(real_prog_name); for(term_overwrite=0;screenp==NULL && term_overwrite<=1;term_overwrite++) { #ifdef HAVE_SETENV #if defined(TARGET_BSD) setenv("TERM","cons25",term_overwrite); #elif defined(TARGET_LINUX) setenv("TERM","linux",term_overwrite); #elif defined(__CYGWIN__) setenv("TERM","cygwin",term_overwrite); #elif defined(__OS2__) setenv("TERM","ansi",term_overwrite); #elif defined(__APPLE__) setenv("TERM","xterm-color",term_overwrite); #endif #endif screenp=newterm(NULL,stdout,stdin); #ifdef HAVE_SETENV if(screenp==NULL && terminfo!=NULL && terminfo[0]!='\0') { setenv("TERMINFO", terminfo, 1); screenp=newterm(NULL,stdout,stdin); } if(screenp==NULL) { setenv("TERMINFO",".",1); screenp=newterm(NULL,stdout,stdin); } if(screenp==NULL) unsetenv("TERMINFO"); #endif } if(screenp==NULL) { log_critical("Terminfo file is missing.\n"); #if defined(__CYGWIN__) printf("The terminfo file '%s\\63\\cygwin' is missing.\n", terminfo); #else printf("Terminfo file is missing.\n"); #endif printf("Extract all files and subdirectories before running the program.\n"); printf("Press Enter key to quit.\n"); getchar(); free(terminfo); return 1; } free(terminfo); } #endif noecho(); #ifndef DJGPP nonl(); /*don't use for Dos version but enter will work with it... dilema */ #endif /* intrflush(stdscr, FALSE); */ cbreak(); /* Should solve a problem with users who redefined the colors */ if(has_colors()) { start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); } curs_set(0); { int quit=0; while(LINES>=8 && LINES<MINIMUM_LINES && quit==0) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s need %d lines to work.", prog_name, MINIMUM_LINES); wmove(stdscr,5,0); wprintw(stdscr,"Please enlarge the terminal."); wmove(stdscr,LINES-2,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr,"[ Quit ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); switch(wgetch(stdscr)) { case 'q': case 'Q': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': quit=1; break; } } } if(LINES < MINIMUM_LINES) { end_ncurses(); printf("%s need %d lines to work.\nPlease enlarge the terminal and restart %s.\n", prog_name, MINIMUM_LINES, prog_name); log_critical("Terminal has only %d lines\n",LINES); return 1; } return 0; }
unsigned int menu_choose_blocksize(unsigned int blocksize, const unsigned int sector_size, uint64_t *offset) { int command; unsigned int menu=0; const char *optionsBlocksize="BS51248736"; static const struct MenuItem menuBlocksize[]= { {'B',"1",""}, {'S',"256",""}, {'5',"512",""}, {'1',"1024",""}, {'2',"2048",""}, {'4',"4096",""}, {'8',"8192",""}, {'7',"16384",""}, {'3',"32768",""}, {'6',"65536",""}, {0,NULL,NULL} }; switch(sector_size) { case 256: optionsBlocksize+=1; break; case 512: optionsBlocksize+=2; break; case 1024: optionsBlocksize+=3; break; case 2048: optionsBlocksize+=4; break; case 4096: optionsBlocksize+=5; break; case 8192: optionsBlocksize+=6; break; case 16384: optionsBlocksize+=7;break; case 32768: optionsBlocksize+=8; break; case 65536: optionsBlocksize+=9; break; } switch(blocksize) { case 1: menu=0; break; case 256: menu=1; break; case 512: menu=2; break; case 1024: menu=3; break; case 2048: menu=4; break; case 4096: menu=5; break; case 8192: menu=6; break; case 16384: menu=7; break; case 32768: menu=8; break; case 65536: menu=9; break; } aff_copy(stdscr); wmove(stdscr,INTER_PARTITION_Y-1,0); wprintw(stdscr,"Please select the block size, press Enter when done."); command = wmenuSelect_ext(stdscr, 23, INTER_PARTITION_Y, INTER_PARTITION_X, menuBlocksize, 7, optionsBlocksize, MENU_VERT| MENU_BUTTON|MENU_VERT_WARN, &menu,NULL); switch(command) { case 'B': blocksize=1; break; case 'S': blocksize=256; break; case '5': blocksize=512; break; case '1': blocksize=1024; break; case '2': blocksize=2048; break; case '4': blocksize=4096; break; case '8': blocksize=8192; break; case '7': blocksize=16384; break; case '3': blocksize=32768; break; case '6': blocksize=65536; break; } *offset=*offset % blocksize; if(*offset%sector_size!=0) *offset=0; if(sector_size < blocksize) { unsigned int quit=0; aff_copy(stdscr); wmove(stdscr,INTER_PARTITION_Y-2,0); wprintw(stdscr,"Please select the offset (0 - %u). Press Up/Down to increase/decrease it,",blocksize-sector_size); wmove(stdscr,INTER_PARTITION_Y-1,0); wprintw(stdscr,"Enter when done."); do { wmove(stdscr,INTER_PARTITION_Y,0); wclrtoeol(stdscr); wprintw(stdscr,"Offset %u",(unsigned int)(*offset)); switch(wgetch(stdscr)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': quit=1; break; case KEY_PPAGE: case KEY_UP: case KEY_RIGHT: case '+': if(*offset + sector_size < blocksize) *offset+=sector_size; break; case KEY_NPAGE: case KEY_DOWN: case KEY_LEFT: case '-': if(*offset >= sector_size) *offset-=sector_size; break; } } while(quit==0); } return blocksize; }
void menu_photorec(struct ph_param *params, struct ph_options *options, alloc_data_t*list_search_space) { list_part_t *list_part; #ifdef HAVE_NCURSES list_part_t *current_element; unsigned int current_element_num; int done=0; int command; unsigned int offset=0; unsigned int menu=0; static const struct MenuItem menuMain[]= { {'S',"Search","Start file recovery"}, {'O',"Options","Modify options"}, {'F',"File Opt","Modify file options"}, {'G',"Geometry", "Change disk geometry" }, {'Q',"Quit","Return to disk selection"}, {0,NULL,NULL} }; #endif params->blocksize=0; list_part=init_list_part(params->disk, options); if(list_part==NULL) return; log_all_partitions(params->disk, list_part); if(params->cmd_run!=NULL) { if(menu_photorec_cli(list_part, params, options, list_search_space) > 0) { if(params->recup_dir==NULL) { char *res; #ifdef HAVE_NCURSES res=ask_location("Please select a destination to save the recovered files.\nDo not choose to write the files to the same partition they were stored on.", "", NULL); #else res=get_default_location(); #endif if(res!=NULL) { params->recup_dir=(char *)MALLOC(strlen(res)+1+strlen(DEFAULT_RECUP_DIR)+1); strcpy(params->recup_dir,res); strcat(params->recup_dir,"/"); strcat(params->recup_dir,DEFAULT_RECUP_DIR); free(res); } } if(params->recup_dir!=NULL) photorec(params, options, list_search_space); } } if(params->cmd_run!=NULL) { part_free_list(list_part); return; } #ifdef HAVE_NCURSES if(list_part->next!=NULL) { current_element_num=1; current_element=list_part->next; } else { current_element_num=0; current_element=list_part; } while(done==0) { /* ncurses interface */ list_part_t *element; unsigned int i; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",params->disk->description_short(params->disk)); mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) mousemask(ALL_MOUSE_EVENTS, NULL); #endif for(i=0,element=list_part; element!=NULL && i<offset+INTER_SELECT;element=element->next,i++) { if(i<offset) continue; wmove(stdscr,7+i-offset,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(element==current_element) { wattrset(stdscr, A_REVERSE); waddstr(stdscr, ">"); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,params->disk,element->part); wattroff(stdscr, A_REVERSE); } else { waddstr(stdscr, " "); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,params->disk,element->part); } } wmove(stdscr,7+INTER_SELECT,5); wclrtoeol(stdscr); if(element!=NULL) wprintw(stdscr, "Next"); command = wmenuSelect(stdscr, INTER_SELECT_Y+1, INTER_SELECT_Y, INTER_SELECT_X, menuMain, 8, (options->expert==0?"SOFQ":"SOFGQ"), MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) if(command == KEY_MOUSE) { MEVENT event; if(getmouse(&event) == OK) { /* When the user clicks left mouse button */ if((event.bstate & BUTTON1_CLICKED) || (event.bstate & BUTTON1_DOUBLE_CLICKED)) { if(event.y >=7 && event.y<7+INTER_SELECT) { /* Disk selection */ while(current_element_num > event.y-(7-offset) && current_element->prev!=NULL) { current_element=current_element->prev; current_element_num--; } while(current_element_num < event.y-(7-offset) && current_element->next!=NULL) { current_element=current_element->next; current_element_num++; } if(event.bstate & BUTTON1_DOUBLE_CLICKED) command='S'; } else command = menu_to_command(INTER_SELECT_Y+1, INTER_SELECT_Y, INTER_SELECT_X, menuMain, 8, (options->expert==0?"SOFQ":"SOFGQ"), MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, event.y, event.x); } } } #endif switch(command) { case KEY_UP: if(current_element!=NULL && current_element->prev!=NULL) { current_element=current_element->prev; current_element_num--; } break; case KEY_PPAGE: for(i=0; (signed)i<INTER_SELECT && current_element->prev!=NULL; i++) { current_element=current_element->prev; current_element_num--; } break; case KEY_DOWN: if(current_element->next!=NULL) { current_element=current_element->next; current_element_num++; } break; case KEY_NPAGE: for(i=0; (signed)i<INTER_SELECT && current_element->next!=NULL; i++) { current_element=current_element->next; current_element_num++; } break; case 's': case 'S': if(current_element!=NULL) { params->partition=current_element->part; ask_mode_ext2(params->disk, params->partition, &options->mode_ext2, ¶ms->carve_free_space_only); menu=0; if(params->recup_dir==NULL) { char *res; res=ask_location("Please select a destination to save the recovered files.\nDo not choose to write the files to the same partition they were stored on.", "", NULL); if(res!=NULL) { params->recup_dir=(char *)MALLOC(strlen(res)+1+strlen(DEFAULT_RECUP_DIR)+1); strcpy(params->recup_dir,res); strcat(params->recup_dir,"/"); strcat(params->recup_dir,DEFAULT_RECUP_DIR); free(res); } } if(params->recup_dir!=NULL) { if(td_list_empty(&list_search_space->list)) { init_search_space(list_search_space, params->disk, params->partition); } if(params->carve_free_space_only>0) { aff_copy(stdscr); wmove(stdscr,5,0); wprintw(stdscr, "Filesystem analysis, please wait...\n"); wrefresh(stdscr); params->blocksize=remove_used_space(params->disk, params->partition, list_search_space); /* Only free space is carved, list_search_space is modified. * To carve the whole space, need to quit and reselect the params->partition */ done = 1; } photorec(params, options, list_search_space); } } break; case 'o': case 'O': { interface_options_photorec_ncurses(options); menu=1; } break; case 'f': case 'F': interface_file_select_ncurses(options->list_file_format); menu=2; break; case 'g': case 'G': if(options->expert!=0) if(change_geometry_ncurses(params->disk)) done=1; break; case 'a': case 'A': if(params->disk->arch != &arch_none) { list_part=add_partition_ncurses(params->disk, list_part); current_element=list_part; current_element_num=0; } break; case 'q': case 'Q': done = 1; break; } if(current_element_num<offset) offset=current_element_num; if(current_element_num>=offset+INTER_SELECT) offset=current_element_num-INTER_SELECT+1; } #endif log_info("\n"); part_free_list(list_part); }
static int testdisk_disk_selection_ncurses(int verbose,int dump_ind, const list_disk_t *list_disk, const int saveheader, char **current_cmd) { int command='Q'; unsigned int menu=0; int offset=0; int pos_num=0; int use_sudo=0; const list_disk_t *element_disk; const list_disk_t *current_disk; static struct MenuItem menuMain[]= { { 'P', "Previous", ""}, { 'N', "Next", "" }, { 'O', "Proceed", ""}, { 'S', "Sudo", "Use the sudo command to restart as root"}, { 'Q', "Quit", "Quit program"}, { 0, NULL, NULL} }; if(list_disk==NULL) { log_critical("No disk found\n"); return intrf_no_disk_ncurses("TestDisk"); } current_disk=list_disk; /* ncurses interface */ while(1) { const char *options; int i; #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr," TestDisk is free software, and"); wmove(stdscr,5,0); wprintw(stdscr,"comes with ABSOLUTELY NO WARRANTY."); wmove(stdscr,7,0); wprintw(stdscr,"Select a media (use Arrow keys, then press Enter):"); #endif for(i=0,element_disk=list_disk; element_disk!=NULL && i<offset+NBR_DISK_MAX; i++, element_disk=element_disk->next) { if(i<offset) continue; wmove(stdscr,8+i-offset,0); if(element_disk!=current_disk) wprintw(stdscr," %s\n",element_disk->disk->description_short(element_disk->disk)); else { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s\n",element_disk->disk->description_short(element_disk->disk)); wattroff(stdscr, A_REVERSE); } } { int line=INTER_NOTE_Y; mvwaddstr(stdscr,line++,0,"Note: "); #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) #else #ifdef HAVE_GETEUID if(geteuid()!=0) { if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1)); waddstr(stdscr,"Some disks won't appear unless you are root user."); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); wmove(stdscr,line++,0); #ifdef SUDO_BIN use_sudo=1; #endif } #endif #endif waddstr(stdscr,"Disk capacity must be correctly detected for a successful recovery."); wmove(stdscr,line++,0); wprintw(stdscr,"If a disk listed above has incorrect size, check HD jumper settings, BIOS"); wmove(stdscr,line,0); wprintw(stdscr,"detection, and install the latest OS patches and disk drivers."); } if(use_sudo > 0) { if(i<=NBR_DISK_MAX && element_disk==NULL) options="OSQ"; else options="PNOSQ"; } else { if(i<=NBR_DISK_MAX && element_disk==NULL) options="OQ"; else options="PNOQ"; } command = wmenuSelect_ext(stdscr, INTER_NOTE_Y-1, INTER_DISK_Y, INTER_DISK_X, menuMain, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,NULL); switch(command) { case 'p': case 'P': case KEY_UP: if(current_disk->prev!=NULL) { current_disk=current_disk->prev; pos_num--; } break; case 'n': case 'N': case KEY_DOWN: if(current_disk->next!=NULL) { current_disk=current_disk->next; pos_num++; } break; case KEY_PPAGE: for(i=0;i<NBR_DISK_MAX-1 && current_disk->prev!=NULL;i++) { current_disk=current_disk->prev; pos_num--; } break; case KEY_NPAGE: for(i=0;i<NBR_DISK_MAX-1 && current_disk->next!=NULL;i++) { current_disk=current_disk->next; pos_num++; } break; case 'o': case 'O': { disk_t *disk=current_disk->disk; const int hpa_dco=is_hpa_or_dco(disk); autodetect_arch(disk, NULL); autoset_unit(disk); if(interface_check_disk_capacity(disk)==0 && interface_check_disk_access(disk, current_cmd)==0 && (hpa_dco==0 || interface_check_hidden_ncurses(disk, hpa_dco)==0) && interface_partition_type(disk, verbose, current_cmd)==0) { if(menu_disk(disk, verbose, dump_ind, saveheader, current_cmd)) return 0; } } break; case 's': case 'S': return 1; case 'q': case 'Q': return 0; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+NBR_DISK_MAX) offset=pos_num-NBR_DISK_MAX+1; } }
static void gpt_change_part_type(const disk_t *disk_car, partition_t *partition) { unsigned int offset=0; unsigned int i,j; unsigned int current_element_num=0; log_info("gpt_change_part_type\n"); aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition); wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X); wattrset(stdscr, A_REVERSE); wprintw(stdscr, "[ Proceed ]"); wattroff(stdscr, A_REVERSE); /* By default, select the current type */ for(i=0;gpt_sys_types[i].name!=NULL;i++) { if(guid_cmp(partition->part_type_gpt, gpt_sys_types[i].part_type)==0) { current_element_num=i; while(current_element_num >= offset+3*INTER_CHGTYPE) offset++; } } while(1) { wmove(stdscr,5,0); wprintw(stdscr, "Please choose the partition type, press Enter when done."); wmove(stdscr,5+1,1); wclrtoeol(stdscr); if(offset>0) wprintw(stdscr, "Previous"); for(i=offset;gpt_sys_types[i].name!=NULL && (i-offset)<3*INTER_CHGTYPE;i++) { if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,0); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(i==current_element_num) { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s", gpt_sys_types[i].name); wattroff(stdscr, A_REVERSE); } else { wprintw(stdscr," %s", gpt_sys_types[i].name); } } if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,1); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53); wclrtoeol(stdscr); if(gpt_sys_types[i].name!=NULL) wprintw(stdscr, "Next"); switch(wgetch(stdscr)) { case 'p': case 'P': case KEY_UP: if(current_element_num>0) current_element_num--; break; case 'n': case 'N': case KEY_DOWN: if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; break; case KEY_RIGHT: for(j=0;j<INTER_CHGTYPE;j++) { if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; } break; case KEY_NPAGE: for(j=0;j<3*INTER_CHGTYPE;j++) { if(gpt_sys_types[current_element_num].name!=NULL && gpt_sys_types[current_element_num+1].name!=NULL) current_element_num++; } break; case 'Q': case 'q': case key_CR: #ifdef PADENTER case PADENTER: #endif guid_cpy(&partition->part_type_gpt, &gpt_sys_types[current_element_num].part_type); return; } if(current_element_num<offset) offset=current_element_num; if(current_element_num >= offset+3*INTER_CHGTYPE) offset=current_element_num-3*INTER_CHGTYPE+1; } }
dir_partition_t dir_partition(disk_t *disk, const partition_t *partition, const int verbose, char **current_cmd) { dir_data_t dir_data; #ifdef HAVE_NCURSES WINDOW *window; #endif dir_partition_t res; fflush(stderr); dir_data.local_dir=NULL; res=dir_partition_init(disk, partition, verbose, &dir_data); #ifdef HAVE_NCURSES window=newwin(LINES, COLS, 0, 0); /* full screen */ dir_data.display=window; aff_copy(window); #else dir_data.display=NULL; #endif log_info("\n"); switch(res) { case DIR_PART_ENOSYS: screen_buffer_reset(); #ifdef HAVE_NCURSES aff_copy(window); wmove(window,4,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); #endif log_partition(disk,partition); screen_buffer_add("Support for this filesystem hasn't been enable during compilation.\n"); screen_buffer_to_log(); if(*current_cmd==NULL) { #ifdef HAVE_NCURSES screen_buffer_display(window,"",NULL); #endif } break; case DIR_PART_EIO: screen_buffer_reset(); #ifdef HAVE_NCURSES aff_copy(window); wmove(window,4,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); #endif log_partition(disk,partition); screen_buffer_add("Can't open filesystem. Filesystem seems damaged.\n"); screen_buffer_to_log(); if(*current_cmd==NULL) { #ifdef HAVE_NCURSES screen_buffer_display(window,"",NULL); #endif } break; case DIR_PART_OK: { int recursive=0; if(*current_cmd!=NULL) { int do_continue; do { do_continue=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"recursive",9)==0) { (*current_cmd)+=9; recursive=1; do_continue=1; } else if(strncmp(*current_cmd,"fullpathname",12)==0) { (*current_cmd)+=12; dir_data.param|=FLAG_LIST_PATHNAME; do_continue=1; } } while(do_continue==1); } if(recursive>0) dir_whole_partition_log(disk,partition,&dir_data,dir_data.current_inode); else { #ifdef HAVE_NCURSES dir_partition_aff(disk, partition, &dir_data, dir_data.current_inode, current_cmd); #else { file_info_t dir_list = { .list = TD_LIST_HEAD_INIT(dir_list.list), .name = NULL }; dir_data.get_dir(disk, partition, &dir_data, dir_data.current_inode, &dir_list); dir_aff_log(&dir_data, &dir_list); delete_list_file(&dir_list); } #endif } dir_data.close(&dir_data); } break; } #ifdef HAVE_NCURSES delwin(window); (void) clearok(stdscr, TRUE); #ifdef HAVE_TOUCHWIN touchwin(stdscr); #endif wrefresh(stdscr); #endif fflush(stderr); free(dir_data.local_dir); return res; }
int main( int argc, char **argv ) { int i; int use_sudo=0; int create_log=TD_LOG_NONE; int run_setlocale=1; int testdisk_mode=TESTDISK_O_RDONLY|TESTDISK_O_READAHEAD_32K; list_disk_t *list_disk=NULL; list_disk_t *element_disk; const char *logfile="photorec.log"; FILE *log_handle=NULL; int log_errno=0; struct ph_options options={ .paranoid=1, .keep_corrupted_file=0, .mode_ext2=0, .expert=0, .lowmem=0, .verbose=0, .list_file_format=list_file_enable }; struct ph_param params; params.recup_dir=NULL; params.cmd_device=NULL; params.cmd_run=NULL; params.carve_free_space_only=0; /* random (weak is ok) is need fot GPT */ srand(time(NULL)); #ifdef HAVE_SIGACTION /* set up the signal handler for SIGINT & SIGHUP */ sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGINT); sigaddset(&action.sa_mask, SIGHUP); action.sa_handler = sighup_hdlr; action.sa_flags = 0; if(sigaction(SIGINT, &action, NULL)==-1) { printf("Error on SIGACTION call\n"); return -1; } if(sigaction(SIGHUP, &action, NULL)==-1) { printf("Error on SIGACTION call\n"); return -1; } #endif printf("PhotoRec %s, Data Recovery Utility, %s\nChristophe GRENIER <*****@*****.**>\nhttp://www.cgsecurity.org\n",VERSION,TESTDISKDATE); for(i=1;i<argc;i++) { if((strcmp(argv[i],"/logname")==0) ||(strcmp(argv[i],"-logname")==0)) { if(i+2>=argc) { display_help(); free(params.recup_dir); return 1; } logfile=argv[++i]; } else if((strcmp(argv[i],"/log")==0) ||(strcmp(argv[i],"-log")==0)) { if(create_log==TD_LOG_NONE) create_log=TD_LOG_APPEND; } else if((strcmp(argv[i],"/debug")==0) || (strcmp(argv[i],"-debug")==0)) { options.verbose++; if(create_log==TD_LOG_NONE) create_log=TD_LOG_APPEND; } else if(((strcmp(argv[i],"/d")==0)||(strcmp(argv[i],"-d")==0)) &&(i+1<argc)) { int len=strlen(argv[i+1]); if(argv[i+1][len-1]=='\\' || argv[i+1][len-1]=='/') { params.recup_dir=(char *)MALLOC(len + strlen(DEFAULT_RECUP_DIR) + 1); strcpy(params.recup_dir,argv[i+1]); strcat(params.recup_dir,DEFAULT_RECUP_DIR); } else params.recup_dir=strdup(argv[i+1]); i++; } else if((strcmp(argv[i],"/all")==0) || (strcmp(argv[i],"-all")==0)) testdisk_mode|=TESTDISK_O_ALL; else if((strcmp(argv[i],"/direct")==0) || (strcmp(argv[i],"-direct")==0)) testdisk_mode|=TESTDISK_O_DIRECT; else if((strcmp(argv[i],"/help")==0) || (strcmp(argv[i],"-help")==0) || (strcmp(argv[i],"--help")==0) || (strcmp(argv[i],"/h")==0) || (strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"/?")==0) || (strcmp(argv[i],"-?")==0)) { display_help(); free(params.recup_dir); return 0; } else if((strcmp(argv[i],"/version")==0) || (strcmp(argv[i],"-version")==0) || (strcmp(argv[i],"--version")==0) || (strcmp(argv[i],"/v")==0) || (strcmp(argv[i],"-v")==0)) { display_version(); free(params.recup_dir); return 0; } else if((strcmp(argv[i],"/nosetlocale")==0) || (strcmp(argv[i],"-nosetlocale")==0)) run_setlocale=0; else if(strcmp(argv[i],"/cmd")==0) { if(i+2>=argc) { display_help(); free(params.recup_dir); return 1; } { disk_t *disk_car; params.cmd_device=argv[++i]; params.cmd_run=argv[++i]; /* There is no log currently */ disk_car=file_test_availability(params.cmd_device, options.verbose, testdisk_mode); if(disk_car==NULL) { printf("\nUnable to open file or device %s: %s\n", params.cmd_device, strerror(errno)); free(params.recup_dir); return 1; } list_disk=insert_new_disk(list_disk,disk_car); } } else { disk_t *disk_car=file_test_availability(argv[i], options.verbose, testdisk_mode); if(disk_car==NULL) { printf("\nUnable to open file or device %s: %s\n", argv[i], strerror(errno)); free(params.recup_dir); return 1; } list_disk=insert_new_disk(list_disk,disk_car); } } #ifdef ENABLE_DFXML xml_set_command_line(argc, argv); #endif if(create_log!=TD_LOG_NONE) log_handle=log_open(logfile, create_log, &log_errno); #ifdef HAVE_SETLOCALE if(run_setlocale>0) { const char *locale; locale = setlocale (LC_ALL, ""); if (locale==NULL) { locale = setlocale (LC_ALL, NULL); log_error("Failed to set locale, using default '%s'.\n", locale); } else { log_info("Using locale '%s'.\n", locale); } } #endif if(create_log!=TD_LOG_NONE && log_handle==NULL) log_handle=log_open_default(logfile, create_log, &log_errno); #ifdef HAVE_NCURSES /* ncurses need locale for correct unicode support */ if(start_ncurses("PhotoRec", argv[0])) { free(params.recup_dir); return 1; } { const char*filename=logfile; while(create_log!=TD_LOG_NONE && log_handle==NULL) { filename=ask_log_location(filename, log_errno); if(filename!=NULL) log_handle=log_open(filename, create_log, &log_errno); else create_log=TD_LOG_NONE; } } aff_copy(stdscr); wmove(stdscr,5,0); wprintw(stdscr, "Disk identification, please wait...\n"); wrefresh(stdscr); #endif if(log_handle!=NULL) { time_t my_time; #ifdef HAVE_DUP2 dup2(fileno(log_handle),2); #endif my_time=time(NULL); log_info("\n\n%s",ctime(&my_time)); log_info("Command line: PhotoRec"); for(i=1;i<argc;i++) log_info(" %s", argv[i]); log_info("\n\n"); } log_info("PhotoRec %s, Data Recovery Utility, %s\nChristophe GRENIER <*****@*****.**>\nhttp://www.cgsecurity.org\n", VERSION, TESTDISKDATE); log_info("OS: %s\n" , get_os()); log_info("Compiler: %s\n", get_compiler()); log_info("Compilation date: %s\n", get_compilation_date()); log_info("ext2fs lib: %s, ntfs lib: %s, ewf lib: %s, libjpeg: %s\n", td_ext2fs_version(), td_ntfs_version(), td_ewf_version(), td_jpeg_version()); #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) #else #ifdef HAVE_GETEUID if(geteuid()!=0) { log_warning("User is not root!\n"); } #endif #endif log_flush(); screen_buffer_reset(); /* Scan for available device only if no device or image has been supplied in parameter */ if(list_disk==NULL) list_disk=hd_parse(list_disk, options.verbose, testdisk_mode); hd_update_all_geometry(list_disk, options.verbose); /* Activate the cache, even if photorec has its own */ for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next) { element_disk->disk=new_diskcache(element_disk->disk, testdisk_mode); } log_disk_list(list_disk); reset_list_file_enable(options.list_file_format); file_options_load(options.list_file_format); #ifdef SUDO_BIN if(list_disk==NULL) { #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(DJGPP) #else #ifdef HAVE_GETEUID if(geteuid()!=0) use_sudo=2; #endif #endif } #endif if(use_sudo==0) use_sudo=do_curses_photorec(¶ms, &options, list_disk); #ifdef HAVE_NCURSES end_ncurses(); #endif log_info("PhotoRec exited normally.\n"); if(log_close()!=0) { printf("PhotoRec: Log file corrupted!\n"); } else if(params.cmd_run!=NULL && params.cmd_run[0]!='\0') { printf("PhotoRec syntax error: %s\n", params.cmd_run); } #ifdef SUDO_BIN if(use_sudo>0) { printf("\n"); if(use_sudo>1) printf("No disk found.\n"); printf("PhotoRec will try to restart itself using the sudo command to get\n"); printf("root (superuser) privileges.\n"); printf("\n"); run_sudo(argc, argv); } #endif delete_list_disk(list_disk); free(params.recup_dir); #ifdef ENABLE_DFXML xml_clear_command_line(); #endif return 0; }
int start_ncurses(const char *prog_name, const char *real_prog_name) { #if defined(DJGPP) || defined(__MINGW32__) if(initscr()==NULL) { log_critical("initscr() has failed. Exiting\n"); printf("initscr() has failed. Exiting\n"); printf("Press Enter key to quit.\n"); (void)getchar(); return 1; } #else get_newterm(real_prog_name); if(screenp==NULL) { log_critical("Terminfo file is missing.\n"); #if defined(__CYGWIN__) printf("The terminfo file '63\\cygwin' is missing.\n"); #else printf("Terminfo file is missing.\n"); #endif printf("Extract all files and subdirectories before running the program.\n"); printf("Press Enter key to quit.\n"); (void)getchar(); return 1; } #endif /* Should solve a problem with users who redefined the colors */ if(has_colors()) { start_color(); #ifdef HAVE_ASSUME_DEFAULT_COLORS assume_default_colors(COLOR_WHITE,COLOR_BLACK); #endif init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); } noecho(); #ifndef DJGPP nonl(); /*don't use for Dos version but enter will work with it... dilema */ #endif /* intrflush(stdscr, FALSE); */ cbreak(); curs_set(0); { int quit=0; while(LINES>=8 && LINES<MINIMUM_LINES && quit==0) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s need %d lines to work.", prog_name, MINIMUM_LINES); wmove(stdscr,5,0); wprintw(stdscr,"Please enlarge the terminal."); wmove(stdscr,LINES-2,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr,"[ Quit ]"); wattroff(stdscr, A_REVERSE); wrefresh(stdscr); switch(wgetch(stdscr)) { case 'q': case 'Q': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': quit=1; break; } } } if(LINES < MINIMUM_LINES) { end_ncurses(); printf("%s need %d lines to work.\nPlease enlarge the terminal and restart %s.\n", prog_name, MINIMUM_LINES, prog_name); log_critical("Terminal has only %d lines\n",LINES); return 1; } return 0; }
static int photorec_disk_selection_ncurses(struct ph_param *params, struct ph_options *options, const list_disk_t *list_disk, alloc_data_t *list_search_space) { int command; int real_key; unsigned int menu=0; int offset=0; int pos_num=0; int use_sudo=0; const list_disk_t *element_disk; const list_disk_t *current_disk=list_disk; static const struct MenuItem menuMain[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'O',"Proceed",""}, { 'S', "Sudo", "Use the sudo command to restart as root"}, { 'Q',"Quit","Quit program"}, { 0,NULL,NULL} }; if(list_disk==NULL) { log_critical("No disk found\n"); return intrf_no_disk_ncurses("PhotoRec"); } /* ncurses interface */ while(1) { const char *menu_options; int i; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr," PhotoRec is free software, and"); wmove(stdscr,5,0); wprintw(stdscr,"comes with ABSOLUTELY NO WARRANTY."); wmove(stdscr,7,0); wprintw(stdscr,"Select a media (use Arrow keys, then press Enter):"); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) mousemask(ALL_MOUSE_EVENTS, NULL); #endif for(i=0,element_disk=list_disk; element_disk!=NULL && i<offset+NBR_DISK_MAX; i++, element_disk=element_disk->next) { if(i<offset) continue; wmove(stdscr,8+i-offset,0); if(element_disk!=current_disk) wprintw(stdscr," %s\n",element_disk->disk->description_short(element_disk->disk)); else { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s\n",element_disk->disk->description_short(element_disk->disk)); wattroff(stdscr, A_REVERSE); } } { mvwaddstr(stdscr, INTER_NOTE_Y,0,"Note: "); #if defined(__CYGWIN__) || defined(__MINGW32__) #else #ifndef DJGPP #ifdef HAVE_GETEUID if(geteuid()!=0) { if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(stdscr,"Some disks won't appear unless you're root user."); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); #ifdef SUDO_BIN use_sudo=1; #endif } #endif #endif #endif wmove(stdscr, INTER_NOTE_Y+1, 0); wprintw(stdscr,"Disk capacity must be correctly detected for a successful recovery."); wmove(stdscr, INTER_NOTE_Y+2, 0); wprintw(stdscr,"If a disk listed above has incorrect size, check HD jumper settings, BIOS"); wmove(stdscr, INTER_NOTE_Y+3, 0); wprintw(stdscr,"detection, and install the latest OS patches and disk drivers."); } if(use_sudo > 0) { if(i<=NBR_DISK_MAX && element_disk==NULL) menu_options="OSQ"; else menu_options="PNOSQ"; } else { if(i<=NBR_DISK_MAX && element_disk==NULL) menu_options="OQ"; else menu_options="PNOQ"; } command = wmenuSelect_ext(stdscr, INTER_NOTE_Y-1, INTER_DISK_Y, INTER_DISK_X, menuMain, 8, menu_options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu,&real_key); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) if(command == KEY_MOUSE) { MEVENT event; if(getmouse(&event) == OK) { /* When the user clicks left mouse button */ if((event.bstate & BUTTON1_CLICKED) || (event.bstate & BUTTON1_DOUBLE_CLICKED)) { if(event.y >=8 && event.y<8+NBR_DISK_MAX) { const int pos_num_old=pos_num; /* Disk selection */ while(pos_num > event.y-(8-offset) && current_disk->prev!=NULL) { current_disk=current_disk->prev; pos_num--; } while(pos_num < event.y-(8-offset) && current_disk->next!=NULL) { current_disk=current_disk->next; pos_num++; } if(((event.bstate & BUTTON1_CLICKED) && pos_num==pos_num_old) || (event.bstate & BUTTON1_DOUBLE_CLICKED)) command='O'; } else command = menu_to_command(INTER_NOTE_Y-1, INTER_DISK_Y, INTER_DISK_X, menuMain, 8, menu_options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, event.y, event.x); } } } #endif switch(command) { case KEY_UP: case 'P': if(current_disk->prev!=NULL) { current_disk=current_disk->prev; pos_num--; } break; case KEY_DOWN: case 'N': if(current_disk->next!=NULL) { current_disk=current_disk->next; pos_num++; } break; case KEY_PPAGE: for(i=0;i<NBR_DISK_MAX-1 && current_disk->prev!=NULL;i++) { current_disk=current_disk->prev; pos_num--; } break; case KEY_NPAGE: for(i=0;i<NBR_DISK_MAX-1 && current_disk->next!=NULL;i++) { current_disk=current_disk->next; pos_num++; } break; case 'o': case 'O': { disk_t *disk=current_disk->disk; const int hpa_dco=is_hpa_or_dco(disk); autodetect_arch(disk, &arch_none); params->disk=disk; if((hpa_dco==0 || interface_check_hidden_ncurses(disk, hpa_dco)==0) && (options->expert == 0 || change_arch_type_ncurses(disk, options->verbose)==0)) menu_photorec(params, options, list_search_space); } break; case 's': case 'S': return 1; case 'q': case 'Q': return 0; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+NBR_DISK_MAX) offset=pos_num-NBR_DISK_MAX+1; } }
static void interface_editor_ncurses(disk_t *disk) { int done = 0; uint64_t hd_offset=0; unsigned char *buffer=(unsigned char *)MALLOC(disk->sector_size); log_info("%s\n",disk->description(disk)); aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s", disk->description_short(disk)); while (done==0) { static const struct MenuItem menuEditor[]= { { 'C', "Change location", "" }, { 'D', "Dump", "Dump sector" }, { 'Q', "Quit",""}, { 0, NULL, NULL } }; switch ( wmenuSelect(stdscr, INTER_EDIT_Y+1, INTER_EDIT_Y, INTER_EDIT_X, menuEditor, 8, "CDQ", MENU_HORIZ | MENU_BUTTON, 0)) { case 'c': case 'C': interface_editor_location(disk,&hd_offset); break; case 'd': case 'D': { int menu_pos=KEY_DOWN; while(done==0) { wmove(stdscr,5,0); wclrtoeol(stdscr); wprintw(stdscr,"%lu ", (unsigned long)(hd_offset/disk->sector_size)); aff_LBA2CHS(disk, hd_offset/disk->sector_size); if((unsigned)disk->pread(disk, buffer, disk->sector_size, hd_offset) != disk->sector_size) { wprintw(stdscr,msg_PART_RD_ERR); } { menu_pos=dump_editor(buffer, disk->sector_size, menu_pos); switch(menu_pos) { case KEY_UP: if(hd_offset>0) hd_offset-=disk->sector_size; else menu_pos=KEY_DOWN; break; case KEY_DOWN: if(hd_offset<disk->disk_size) hd_offset+=disk->sector_size; else menu_pos=KEY_UP; break; default: done = 1; break; } } } done = 0; } break; case key_ESC: case 'q': case 'Q': done = 1; break; } } free(buffer); }
static void ask_mbr_order_i386(disk_t *disk_car,list_part_t *list_part) { partition_t *table[4]; int nbr_prim=0; int i,pos=0; int res; int quit=0; list_part_t *element; /* Initialisation */ aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_MBR_ORDER); mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); for(element=list_part;element!=NULL;element=element->next) { if((element->part->order>0) && (element->part->order<5)) table[nbr_prim++]=element->part; } /* */ log_info("\nSelect primary partition\n"); for(i=0;i<nbr_prim;i++) log_partition(disk_car,table[i]); /* */ do { partition_t *table2[4]; int car; unsigned int order; /* sort table into table2 */ int part=0; res=0; for(order=1;order<=4;order++) { int nbr=0; for(i=0;i<nbr_prim;i++) if(table[i]->order==order) { table2[part++]=table[i]; nbr++; } res|=(nbr>1); } if(part!=nbr_prim) { log_critical("\nBUG part %d, nbr_prim %d\n", part, nbr_prim); } for(i=0;i<nbr_prim;i++) { wmove(stdscr,5+2+i,0); wclrtoeol(stdscr); if(i==pos) standout(); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,table2[i]); if(i==pos) standend(); } wmove(stdscr,20,0); if(res) wprintw(stdscr,msg_MBR_ORDER_BAD); else wprintw(stdscr,msg_MBR_ORDER_GOOD); wrefresh(stdscr); car=wgetch(stdscr); quit=0; switch(car) { case KEY_UP: if(--pos<0) pos=nbr_prim-1; break; case KEY_DOWN: if(++pos>=nbr_prim) pos=0; break; case KEY_PPAGE: pos=0; break; case KEY_NPAGE: pos=nbr_prim-1; break; case '1': case '2': case '3': case '4': table2[pos]->order=car-'0'; break; case KEY_RIGHT: case ' ': case '+': if(++table2[pos]->order>4) table2[pos]->order=1; break; case KEY_LEFT: case '-': if(--table2[pos]->order<1) table2[pos]->order=4; break; case 'q': case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case 'M': quit=1; break; } wrefresh(stdscr); } while(res!=0 || quit==0); }
static void change_part_type_ncurses2(const disk_t *disk_car, partition_t *partition) { partition_t *new_partition; unsigned int intr_nbr_line=0; unsigned int offset=0; unsigned int i; unsigned int current_element_num=0; struct part_name_struct part_name[0x100]; if(partition->arch->set_part_type==NULL) return ; aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition); wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X); wattrset(stdscr, A_REVERSE); wprintw(stdscr, "[ Proceed ]"); wattroff(stdscr, A_REVERSE); /* Create an index of all partition type except Intel extended */ new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); for(i=0;i<=0xFF;i++) { if(partition->arch->set_part_type(new_partition,i)==0) { part_name[intr_nbr_line].name=new_partition->arch->get_partition_typename(new_partition); if(part_name[intr_nbr_line].name!=NULL) { if(partition->arch->get_part_type(partition)==i) current_element_num=intr_nbr_line; part_name[intr_nbr_line++].index=i; } } } free(new_partition); while(1) { wmove(stdscr,5,0); wprintw(stdscr, "Please choose the partition type, press Enter when done."); wmove(stdscr,5+1,1); wclrtoeol(stdscr); if(offset>0) wprintw(stdscr, "Previous"); for(i=offset;i<intr_nbr_line && (i-offset)<3*INTER_CHGTYPE;i++) { if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,0); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(i==current_element_num) { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s", part_name[i].name); wattroff(stdscr, A_REVERSE); } else { wprintw(stdscr," %s", part_name[i].name); } } if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,1); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53); wclrtoeol(stdscr); if(i<intr_nbr_line) wprintw(stdscr, "Next"); switch(wgetch(stdscr)) { case 'p': case 'P': case KEY_UP: if(current_element_num>0) current_element_num--; break; case 'n': case 'N': case KEY_DOWN: if(current_element_num < intr_nbr_line-1) current_element_num++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; break; case KEY_RIGHT: if(current_element_num+INTER_CHGTYPE < intr_nbr_line-1) current_element_num+=INTER_CHGTYPE; else current_element_num=intr_nbr_line-1; break; case KEY_NPAGE: if(current_element_num+3*INTER_CHGTYPE-1 < intr_nbr_line-1) current_element_num+=3*INTER_CHGTYPE-1; else current_element_num=intr_nbr_line-1; break; case 'Q': case 'q': case key_CR: #ifdef PADENTER case PADENTER: #endif partition->arch->set_part_type(partition, part_name[current_element_num].index); return; } if(current_element_num < offset) offset=current_element_num; if(current_element_num >= offset+3*INTER_CHGTYPE) offset=current_element_num-3*INTER_CHGTYPE+1; } }
list_part_t *search_superblock(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, const int interface) { unsigned char *buffer=(unsigned char *)MALLOC(2*0x200); uint64_t hd_offset; int nbr_sb=0; list_part_t *list_part=NULL; int ind_stop=0; #ifdef HAVE_NCURSES unsigned long int old_percent=0; #endif struct ext2_super_block *sb=(struct ext2_super_block *)buffer; partition_t *new_partition=partition_new(disk_car->arch); log_trace("search_superblock\n"); #ifdef HAVE_NCURSES if(interface>0) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr," Stop "); wattroff(stdscr, A_REVERSE); } #endif for(hd_offset=0;hd_offset<partition->part_size && nbr_sb<10 && ind_stop==0;hd_offset=next_sb(hd_offset)) { #ifdef HAVE_NCURSES unsigned long int percent; percent=hd_offset*100/partition->part_size; if(interface>0 && percent!=old_percent) { wmove(stdscr,9,0); wclrtoeol(stdscr); wprintw(stdscr,"Search ext2/ext3/ext4 superblock %10lu/%lu %lu%%", (long unsigned)(hd_offset/disk_car->sector_size), (long unsigned)(partition->part_size/disk_car->sector_size),percent); wrefresh(stdscr); ind_stop|=check_enter_key_or_s(stdscr); old_percent=percent; } #endif if(disk_car->pread(disk_car, buffer, 1024, partition->part_offset + hd_offset) == 1024) { /* ext2/ext3/ext4 */ if(le16(sb->s_magic)==EXT2_SUPER_MAGIC) { dup_partition_t(new_partition,partition); new_partition->part_offset+=hd_offset; if(recover_EXT2(disk_car,sb,new_partition,verbose,dump_ind)==0) { int insert_error=0; if(hd_offset<=(EXT2_MIN_BLOCK_SIZE<<2)) new_partition->part_offset-=hd_offset; if(partition->blocksize==0) { partition->sborg_offset=new_partition->sborg_offset; partition->sb_offset =new_partition->sb_offset; partition->sb_size =new_partition->sb_size; partition->blocksize =new_partition->blocksize; } log_info("Ext2 superblock found at sector %llu (block=%llu, blocksize=%u)\n", (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE, (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)), EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size)); #ifdef HAVE_NCURSES wmove(stdscr,10+nbr_sb,0); wprintw(stdscr,"Ext2 superblock found at sector %llu (block=%llu, blocksize=%u) \n", (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE, (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)), EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size)); #endif list_part=insert_new_partition(list_part, new_partition, 1, &insert_error); new_partition=partition_new(disk_car->arch); nbr_sb++; } } }
static list_part_t *interface_analyse_ncurses(disk_t *disk_car, const int verbose, const int saveheader, char**current_cmd) { list_part_t *list_part; int command; #ifdef HAVE_NCURSES const struct MenuItem menuAnalyse[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q',"Quick Search","Try to locate partition"}, { 'B', "Backup","Save current partition list to backup.log file and proceed"}, { 0, NULL, NULL } }; #endif screen_buffer_reset(); /* ncurses interface */ #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s\n",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,"Checking current partition structure"); wrefresh(stdscr); #endif list_part=disk_car->arch->read_part(disk_car,verbose,saveheader); log_info("Current partition structure:\n"); screen_buffer_to_log(); #ifdef HAVE_NCURSES wmove(stdscr,5,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ waddstr(stdscr,"Current partition structure:"); wmove(stdscr,6,0); wprintw(stdscr,msg_PART_HEADER_LONG); if(disk_car->arch->msg_part_type!=NULL) mvwaddstr(stdscr,LINES-3,0,disk_car->arch->msg_part_type); #endif command='Q'; if(*current_cmd!=NULL) { while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"backup",6)==0) { (*current_cmd)+=6; if(list_part!=NULL) command='B'; } } else { log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display(stdscr, (list_part!=NULL && disk_car->arch != &arch_none?"QB":"Q"), menuAnalyse); #endif } if(command=='B') { log_info("Backup partition structure\n"); if(partition_save(disk_car,list_part,verbose)<0) { display_message("Can't create backup.log.\n"); } } return list_part; }
static list_part_t *ask_structure_ncurses(disk_t *disk_car,list_part_t *list_part, const int verbose, char **current_cmd) { int offset=0; int pos_num=0; list_part_t *pos=list_part; int rewrite=1; int old_LINES=LINES; while(1) { int i; int command; list_part_t *parts; int structure_status; if(old_LINES!=LINES) { rewrite=1; old_LINES=LINES; } if(rewrite) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER); rewrite=0; } structure_status=disk_car->arch->test_structure(list_part); for(i=0,parts=list_part; parts!=NULL && i<offset+INTER_STRUCTURE; i++, parts=parts->next) { if(i<offset) continue; wmove(stdscr,6+i-offset,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(parts==pos) wattrset(stdscr, A_REVERSE); if(structure_status==0 && parts->part->status!=STATUS_DELETED && has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(2)); if(parts==pos) waddstr(stdscr, ">"); else waddstr(stdscr, " "); aff_part(stdscr, AFF_PART_STATUS, disk_car, parts->part); if(structure_status==0 && parts->part->status!=STATUS_DELETED && has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); if(parts==pos) { char buffer_part_size[100]; wattroff(stdscr, A_REVERSE); wmove(stdscr,LINES-1,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(parts->part->info[0]!='\0') { wprintw(stdscr,"%s, ",parts->part->info); } size_to_unit(parts->part->part_size, buffer_part_size); wprintw(stdscr,"%s", buffer_part_size); } } if(structure_status==0) { if(list_part!=NULL) mvwaddstr(stdscr,LINES-6,0,msg_STRUCT_OK); } else { if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(1)); mvwaddstr(stdscr,LINES-6,0,msg_STRUCT_BAD); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); } if(list_part!=NULL && disk_car->arch->msg_part_type!=NULL) { mvwaddstr(stdscr,LINES-6,16,"Use "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"Up"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,"/"); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"Down"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr," Arrow keys to select partition."); mvwaddstr(stdscr,LINES-5,0,"Use "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"Left"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,"/"); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"Right"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr," Arrow keys to CHANGE partition characteristics:"); mvwaddstr(stdscr,LINES-4,0,disk_car->arch->msg_part_type); } wmove(stdscr,LINES-3,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ waddstr(stdscr,"Keys "); /* If the disk can't be partionned, there is no partition to add and no partition to save */ if(disk_car->arch != &arch_none) { if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"A"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,": add partition, "); if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"L"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,": load backup, "); } if(list_part==NULL) { waddstr(stdscr,"Enter: to continue"); } else { if(pos->part->arch==NULL || pos->part->arch==disk_car->arch) { if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"T"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,": change type, "); } switch(pos->part->upart_type) { case UP_EXFAT: case UP_EXT2: case UP_EXT3: case UP_EXT4: case UP_RFS: case UP_RFS2: case UP_RFS3: case UP_FAT12: case UP_FAT16: case UP_FAT32: case UP_NTFS: if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(stdscr,"P"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,": list files, "); break; default: break; } if(has_colors()) wbkgdset(stdscr,' ' | A_BOLD | COLOR_PAIR(0)); mvwaddstr(stdscr,LINES-2,5, "Enter"); if(has_colors()) wbkgdset(stdscr,' ' | COLOR_PAIR(0)); waddstr(stdscr,": to continue"); } wrefresh(stdscr); command=wgetch(stdscr); switch(command) { case KEY_UP: if(list_part!=NULL) { only_one_bootable(list_part,pos); if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } } break; case KEY_DOWN: if(list_part!=NULL) { only_one_bootable(list_part,pos); if(pos->next!=NULL) { pos=pos->next; pos_num++; } } break; case KEY_PPAGE: if(list_part!=NULL) { only_one_bootable(list_part,pos); for(i=0; i<INTER_STRUCTURE && pos->prev!=NULL; i++) { pos=pos->prev; pos_num--; } } break; case KEY_NPAGE: if(list_part!=NULL) { only_one_bootable(list_part,pos); for(i=0; i<INTER_STRUCTURE && pos->next!=NULL; i++) { pos=pos->next; pos_num++; } } break; case KEY_RIGHT: case '+': case ' ': if(list_part!=NULL) { if(pos->part->arch==NULL || pos->part->arch==disk_car->arch) disk_car->arch->set_next_status(disk_car,pos->part); } break; case KEY_LEFT: case '-': if(list_part!=NULL) { if(pos->part->arch==NULL || pos->part->arch==disk_car->arch) disk_car->arch->set_prev_status(disk_car,pos->part); } break; case 'a': case 'A': if(disk_car->arch != &arch_none) { list_part=add_partition_ncurses(disk_car, list_part); rewrite=1; offset=0; pos_num=0; pos=list_part; } break; case 't': case 'T': if(list_part!=NULL) { rewrite=1; change_part_type_ncurses(disk_car, pos->part); } break; case 'p': case 'P': if(list_part!=NULL) { const partition_t *partition=pos->part; if(partition->sb_offset==0 || partition->sb_size==0) dir_partition(disk_car,partition,verbose, current_cmd); else { io_redir_add_redir(disk_car, partition->part_offset+partition->sborg_offset, partition->sb_size, partition->part_offset+partition->sb_offset, NULL); dir_partition(disk_car,partition,verbose, current_cmd); io_redir_del_redir(disk_car, partition->part_offset+partition->sborg_offset); } rewrite=1; } break; case 'b': case 'B': if(partition_save(disk_car,list_part,verbose)<0) display_message("Can't create backup.log.\n"); else display_message("Results saved in backup.log.\n"); rewrite=1; break; case 'l': case 'L': if(disk_car->arch != &arch_none) { list_part=interface_load(disk_car,list_part,verbose); rewrite=1; offset=0; pos_num=0; pos=list_part; } break; case 'q': case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case 'M': return list_part; default: /* log_trace("ask_structure command=%x\n",command); */ break; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+INTER_STRUCTURE) offset=pos_num-INTER_STRUCTURE+1; } }
int repair_MFT(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int expert, char **current_cmd) { struct ntfs_boot_sector *ntfs_header; unsigned char *buffer_mft; unsigned char *buffer_mftmirr; unsigned int cluster_size; unsigned int mft_record_size; unsigned int mftmirr_size_bytes; unsigned int use_MFT=0; /* 0: do nothing * 1: fix MFT mirror using MFT * 2: fix MFT using MFT mirror */ uint64_t mft_pos; uint64_t mftmirr_pos; log_trace("repair_MFT\n"); if(check_NTFS(disk_car, partition, verbose, 0)!=0) { display_message("Boot sector not valid, can't repair MFT.\n"); return -1; } ntfs_header=(struct ntfs_boot_sector *)MALLOC(DEFAULT_SECTOR_SIZE); if(disk_car->pread(disk_car, ntfs_header, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE) { free(ntfs_header); display_message("Can't read NTFS boot sector.\n"); return -1; } mft_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mft_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header); mftmirr_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mftmirr_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header); if(ntfs_header->clusters_per_mft_record>0) mft_record_size=ntfs_header->sectors_per_cluster*ntfs_header->clusters_per_mft_record; else mft_record_size=1<<(-ntfs_header->clusters_per_mft_record); cluster_size=ntfs_header->sectors_per_cluster; mftmirr_size_bytes = (cluster_size <= 4 * mft_record_size ? 4 * mft_record_size : cluster_size) * ntfs_sector_size(ntfs_header); #ifdef DEBUG_REPAIR_MFT log_debug("mft_pos %lu\n",(unsigned long)(mft_pos/disk_car->sector_size)); log_debug("mftmirr_pos %lu\n",(unsigned long)(mftmirr_pos/disk_car->sector_size)); log_debug("cluster_size %u\n", cluster_size); log_debug("mft_record_size %u\n", mft_record_size); log_debug("ntfs_sector_size %u\n", ntfs_sector_size(ntfs_header)); log_debug("mftmirr_size_bytes %u\n", mftmirr_size_bytes); #endif if(mftmirr_size_bytes==0) { display_message("Invalid NTFS MFT size.\n"); log_error("Invalid NTFS MFT size.\n"); free(ntfs_header); return -1; } /* Check if MFT mirror is identical to the beginning of MFT */ buffer_mft=(unsigned char *)MALLOC(mftmirr_size_bytes); if((unsigned)disk_car->pread(disk_car, buffer_mft, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes) { display_message("Can't read NTFS MFT.\n"); log_error("Can't read NTFS MFT.\n"); free(buffer_mft); free(ntfs_header); return -1; } buffer_mftmirr=(unsigned char *)MALLOC(mftmirr_size_bytes); if((unsigned)disk_car->pread(disk_car, buffer_mftmirr, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes) { display_message("Can't read NTFS MFT mirror.\n"); log_error("Can't read NTFS MFT mirror.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return -1; } if(memcmp(buffer_mft, buffer_mftmirr, mftmirr_size_bytes)==0) { log_info("MFT and MFT mirror match perfectly.\n"); if(*current_cmd==NULL) display_message("MFT and MFT mirror match perfectly.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return 0; } if(partition->sb_offset!=0) { log_info("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n"); display_message("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return -1; } /* log_debug("MFT\n"); dump_log(buffer_mft, mftmirr_size_bytes); log_debug("MFT mirror\n"); dump_log(buffer_mftmirr, mftmirr_size_bytes); */ /* The idea is to use the internal IO redirector built-in TestDisk to redirect read access to the MFT to the MFT backup instead (or vice-versa) when listing the NTFS files. If TestDisk can get a file listing, it also knows which MFT to use. */ { int res1,res2; dir_data_t dir_data; /* Use MFT */ io_redir_add_redir(disk_car, mftmirr_pos, mftmirr_size_bytes, 0, buffer_mft); res1=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); if(res1==DIR_PART_ENOSYS) { display_message("Can't determine which MFT is correct, ntfslib is missing.\n"); log_error("Can't determine which MFT is correct, ntfslib is missing.\n"); free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); io_redir_del_redir(disk_car,mftmirr_pos); return 0; } if(res1==DIR_PART_OK) { file_info_t dir_list; TD_INIT_LIST_HEAD(&dir_list.list); dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list); if(!td_list_empty(&dir_list.list)) { log_info("NTFS listing using MFT:\n"); dir_aff_log(&dir_data, &dir_list); if(delete_list_file(&dir_list)>2) res1++; } dir_data.close(&dir_data); } io_redir_del_redir(disk_car,mftmirr_pos); /* Use MFT mirror */ io_redir_add_redir(disk_car, mft_pos, mftmirr_size_bytes, 0, buffer_mftmirr); res2=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); if(res2==DIR_PART_OK) { file_info_t dir_list; TD_INIT_LIST_HEAD(&dir_list.list); dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list); if(!td_list_empty(&dir_list.list)) { log_info("NTFS listing using MFT mirror:\n"); dir_aff_log(&dir_data, &dir_list); if(delete_list_file(&dir_list)>2) res2++; } dir_data.close(&dir_data); } io_redir_del_redir(disk_car,mft_pos); /* */ if(res1>res2 && res1>DIR_PART_OK) { /* Use MFT */ #ifdef HAVE_NCURSES if(ask_confirmation("Fix MFT mirror using MFT ? (Y/N)")!=0) use_MFT=1; else #endif log_info("Don't fix MFT mirror.\n"); } else if(res1<res2 && res2>DIR_PART_OK) { /* Use MFT mirror */ #ifdef HAVE_NCURSES if(ask_confirmation("Fix MFT using its mirror ? (Y/N) - DANGEROUS NON REVERSIBLE OPERATION\nUse it ONLY IF Windows failed to access this filesystem.")!=0) use_MFT=2; else #endif log_info("Don't fix MFT.\n"); } else { /* res1==res2 */ if(res1>DIR_PART_OK && res2>DIR_PART_OK) log_error("Both MFT seems ok but they don't match, use chkdsk.\n"); else log_error("MFT and MFT mirror are bad. Failed to repair them.\n"); if(expert==0) { if(res1>DIR_PART_OK && res2>DIR_PART_OK) display_message("Both MFT seems ok but they don't match, use chkdsk.\n"); else display_message("MFT and MFT mirror are bad. Failed to repair them.\n"); } else { #ifdef HAVE_NCURSES unsigned int menu=2; int real_key; int command; static const struct MenuItem menuMFT[]= { {'B',"MFT", "Fix MFT using MFT mirror"}, {'M',"MFT Mirror", "Fix MFT mirror using MFT"}, {'Q',"Quit","Return to NTFS functions"}, {0,NULL,NULL} }; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); wmove(stdscr,8,0); if(res1>0 && res2>0) wprintw(stdscr, "Both MFT seem ok but they don't match.\n"); else wprintw(stdscr, "MFT and MFT mirror are bad.\n"); command=wmenuSelect_ext(stdscr, 23, INTER_MFT_Y, INTER_MFT_X, menuMFT, 10, "MBQ", MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu, &real_key); switch(command) { case 'b': case 'B': use_MFT=2; break; case 'm': case 'M': use_MFT=1; break; default: use_MFT=0; break; } #endif } } } if(use_MFT==2) { if((unsigned)disk_car->pwrite(disk_car, buffer_mftmirr, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes) { display_message("Failed to fix MFT: write error.\n"); } else { disk_car->sync(disk_car); display_message("MFT fixed.\n"); } } else if(use_MFT==1) { if((unsigned)disk_car->pwrite(disk_car, buffer_mft, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes) { display_message("Failed to fix MFT mirror: write error.\n"); } else { disk_car->sync(disk_car); display_message("MFT mirror fixed.\n"); } } free(buffer_mftmirr); free(buffer_mft); free(ntfs_header); return 0; }
void menu_photorec(struct ph_param *params, struct ph_options *options, alloc_data_t*list_search_space) { list_part_t *list_part; list_part_t *current_element; unsigned int current_element_num; unsigned int user_blocksize=0; int done=0; init_mode_t mode_init_space=(td_list_empty(&list_search_space->list)?INIT_SPACE_WHOLE:INIT_SPACE_PREINIT); #ifdef HAVE_NCURSES int command; unsigned int offset=0; unsigned int menu=0; static const struct MenuItem menuMain[]= { {'S',"Search","Start file recovery"}, {'O',"Options","Modify options"}, {'F',"File Opt","Modify file options"}, {'G',"Geometry", "Change disk geometry" }, {'Q',"Quit","Return to disk selection"}, {0,NULL,NULL} }; #endif params->blocksize=0; list_part=init_list_part(params->disk, options); if(list_part==NULL) return; log_all_partitions(params->disk, list_part); if(list_part->next!=NULL) { current_element_num=1; current_element=list_part->next; } else { current_element_num=0; current_element=list_part; } while(done==0) { if(params->cmd_run!=NULL) { while(params->cmd_run[0]==',') params->cmd_run++; if(params->cmd_run[0]=='\0') { part_free_list(list_part); return; } if(strncmp(params->cmd_run,"search",6)==0) { params->cmd_run+=6; if(params->recup_dir==NULL) { char *res; #ifdef HAVE_NCURSES res=ask_location("Please select a destination to save the recovered files.\nDo not choose to write the files to the same partition they were stored on.", "", NULL); #else res=get_default_location(); #endif if(res!=NULL) { params->recup_dir=(char *)MALLOC(strlen(res)+1+strlen(DEFAULT_RECUP_DIR)+1); strcpy(params->recup_dir,res); strcat(params->recup_dir,"/"); strcat(params->recup_dir,DEFAULT_RECUP_DIR); free(res); } } if(params->recup_dir!=NULL) { params->partition=current_element->part; if(mode_init_space==INIT_SPACE_EXT2_GROUP) { params->blocksize=ext2_fix_group(list_search_space, params->disk, params->partition); if(params->blocksize==0) display_message("Not a valid ext2/ext3/ext4 filesystem"); } else if(mode_init_space==INIT_SPACE_EXT2_INODE) { params->blocksize=ext2_fix_inode(list_search_space, params->disk, params->partition); if(params->blocksize==0) display_message("Not a valid ext2/ext3/ext4 filesystem"); } if(td_list_empty(&list_search_space->list)) { init_search_space(list_search_space, params->disk, params->partition); } if(params->carve_free_space_only>0) { params->blocksize=remove_used_space(params->disk, params->partition, list_search_space); } if(user_blocksize > 0) params->blocksize=user_blocksize; photorec(params, options, list_search_space); } } else if(strncmp(params->cmd_run,"options",7)==0) { params->cmd_run+=7; interface_options_photorec_cli(options, ¶ms->cmd_run); } else if(strncmp(params->cmd_run,"fileopt",7)==0) { params->cmd_run+=7; interface_file_select(options->list_file_format, ¶ms->cmd_run); } else if(strncmp(params->cmd_run,"blocksize,",10)==0) { params->cmd_run+=10; user_blocksize=atoi(params->cmd_run); while(params->cmd_run[0]!=',' && params->cmd_run[0]!='\0') params->cmd_run++; } else if(strncmp(params->cmd_run,"geometry,",9)==0) { params->cmd_run+=9; change_geometry_cli(params->disk, ¶ms->cmd_run); } else if(strncmp(params->cmd_run,"inter",5)==0) { /* Start interactive mode */ params->cmd_run=NULL; } else if(strncmp(params->cmd_run,"wholespace",10)==0) { params->cmd_run+=10; params->carve_free_space_only=0; } else if(strncmp(params->cmd_run,"freespace",9)==0) { params->cmd_run+=9; params->carve_free_space_only=1; } else if(strncmp(params->cmd_run,"ext2_group,",11)==0) { unsigned int groupnr; params->cmd_run+=11; options->mode_ext2=1; groupnr=atoi(params->cmd_run); while(params->cmd_run[0]!=',' && params->cmd_run[0]!='\0') params->cmd_run++; if(mode_init_space==INIT_SPACE_WHOLE) mode_init_space=INIT_SPACE_EXT2_GROUP; if(mode_init_space==INIT_SPACE_EXT2_GROUP) { alloc_data_t *new_free_space; new_free_space=(alloc_data_t*)MALLOC(sizeof(*new_free_space)); /* Temporary storage, values need to be multiplied by group size and aligned */ new_free_space->start=groupnr; new_free_space->end=groupnr; new_free_space->file_stat=NULL; new_free_space->data=1; if(td_list_add_sorted_uniq(&new_free_space->list, &list_search_space->list, spacerange_cmp)) free(new_free_space); } } else if(strncmp(params->cmd_run,"ext2_inode,",11)==0) { unsigned int inodenr; params->cmd_run+=11; options->mode_ext2=1; inodenr=atoi(params->cmd_run); while(params->cmd_run[0]!=',' && params->cmd_run[0]!='\0') params->cmd_run++; if(mode_init_space==INIT_SPACE_WHOLE) mode_init_space=INIT_SPACE_EXT2_INODE; if(mode_init_space==INIT_SPACE_EXT2_INODE) { alloc_data_t *new_free_space; new_free_space=(alloc_data_t*)MALLOC(sizeof(*new_free_space)); /* Temporary storage, values need to be multiplied by group size and aligned */ new_free_space->start=inodenr; new_free_space->end=inodenr; new_free_space->file_stat=NULL; new_free_space->data=1; if(td_list_add_sorted_uniq(&new_free_space->list, &list_search_space->list, spacerange_cmp)) free(new_free_space); } } else if(isdigit(params->cmd_run[0])) { list_part_t *element; unsigned int order; order= atoi(params->cmd_run); while(params->cmd_run[0]!=',' && params->cmd_run[0]!='\0') params->cmd_run++; for(element=list_part;element!=NULL && element->part->order!=order;element=element->next); if(element!=NULL) current_element=element; } else { log_critical("Syntax error in command line: %s\n", params->cmd_run); part_free_list(list_part); return; } } #ifdef HAVE_NCURSES else { /* ncurses interface */ list_part_t *element; unsigned int i; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",params->disk->description_short(params->disk)); mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) mousemask(ALL_MOUSE_EVENTS, NULL); #endif for(i=0,element=list_part; element!=NULL && i<offset+INTER_SELECT;element=element->next,i++) { if(i<offset) continue; wmove(stdscr,7+i-offset,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(element==current_element) { wattrset(stdscr, A_REVERSE); waddstr(stdscr, ">"); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,params->disk,element->part); wattroff(stdscr, A_REVERSE); } else { waddstr(stdscr, " "); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,params->disk,element->part); } } wmove(stdscr,7+INTER_SELECT,5); wclrtoeol(stdscr); if(element!=NULL) wprintw(stdscr, "Next"); command = wmenuSelect(stdscr, INTER_SELECT_Y+1, INTER_SELECT_Y, INTER_SELECT_X, menuMain, 8, (options->expert==0?"SOFQ":"SOFGQ"), MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu); #if defined(KEY_MOUSE) && defined(ENABLE_MOUSE) if(command == KEY_MOUSE) { MEVENT event; if(getmouse(&event) == OK) { /* When the user clicks left mouse button */ if((event.bstate & BUTTON1_CLICKED) || (event.bstate & BUTTON1_DOUBLE_CLICKED)) { if(event.y >=7 && event.y<7+INTER_SELECT) { /* Disk selection */ while(current_element_num > event.y-(7-offset) && current_element->prev!=NULL) { current_element=current_element->prev; current_element_num--; } while(current_element_num < event.y-(7-offset) && current_element->next!=NULL) { current_element=current_element->next; current_element_num++; } if(event.bstate & BUTTON1_DOUBLE_CLICKED) command='S'; } else command = menu_to_command(INTER_SELECT_Y+1, INTER_SELECT_Y, INTER_SELECT_X, menuMain, 8, (options->expert==0?"SOFQ":"SOFGQ"), MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, event.y, event.x); } } } #endif switch(command) { case KEY_UP: if(current_element!=NULL && current_element->prev!=NULL) { current_element=current_element->prev; current_element_num--; } break; case KEY_PPAGE: for(i=0; (signed)i<INTER_SELECT && current_element->prev!=NULL; i++) { current_element=current_element->prev; current_element_num--; } break; case KEY_DOWN: if(current_element->next!=NULL) { current_element=current_element->next; current_element_num++; } break; case KEY_NPAGE: for(i=0; (signed)i<INTER_SELECT && current_element->next!=NULL; i++) { current_element=current_element->next; current_element_num++; } break; case 's': case 'S': if(current_element!=NULL) { params->partition=current_element->part; ask_mode_ext2(params->disk, params->partition, &options->mode_ext2, ¶ms->carve_free_space_only); menu=0; if(params->recup_dir==NULL) { char *res; res=ask_location("Please select a destination to save the recovered files.\nDo not choose to write the files to the same partition they were stored on.", "", NULL); if(res!=NULL) { params->recup_dir=(char *)MALLOC(strlen(res)+1+strlen(DEFAULT_RECUP_DIR)+1); strcpy(params->recup_dir,res); strcat(params->recup_dir,"/"); strcat(params->recup_dir,DEFAULT_RECUP_DIR); free(res); } } if(params->recup_dir!=NULL) { if(td_list_empty(&list_search_space->list)) { init_search_space(list_search_space, params->disk, params->partition); } if(params->carve_free_space_only>0) { aff_copy(stdscr); wmove(stdscr,5,0); wprintw(stdscr, "Filesystem analysis, please wait...\n"); wrefresh(stdscr); params->blocksize=remove_used_space(params->disk, params->partition, list_search_space); /* Only free space is carved, list_search_space is modified. * To carve the whole space, need to quit and reselect the params->partition */ done = 1; } photorec(params, options, list_search_space); } } break; case 'o': case 'O': { interface_options_photorec_ncurses(options); menu=1; } break; case 'f': case 'F': interface_file_select(options->list_file_format, ¶ms->cmd_run); menu=2; break; case 'g': case 'G': if(options->expert!=0) if(change_geometry_ncurses(params->disk)) done=1; break; case 'a': case 'A': if(params->disk->arch != &arch_none) { list_part=add_partition_ncurses(params->disk, list_part); current_element=list_part; current_element_num=0; } break; case 'q': case 'Q': done = 1; break; } if(current_element_num<offset) offset=current_element_num; if(current_element_num>=offset+INTER_SELECT) offset=current_element_num-INTER_SELECT+1; } #endif } log_info("\n"); part_free_list(list_part); }
static int interface_part_bad_ncurses(disk_t *disk_car, list_part_t *list_part) { int quit=0; int offset=0; int pos_num=0; uint64_t disk_size=disk_car->disk_size; list_part_t *pos=list_part; if(list_part==NULL) return 1; { list_part_t *parts; for(parts=list_part;parts!=NULL;parts=parts->next) { if(disk_size<parts->part->part_offset+parts->part->part_size-1) disk_size=parts->part->part_offset+parts->part->part_size-1; } } aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,6,0); { char buffer_disk_size[100]; char buffer_disk_size_found[100]; size_to_unit(disk_car->disk_size, buffer_disk_size); size_to_unit(disk_size, buffer_disk_size_found); wprintw(stdscr,"The harddisk (%s) seems too small! (< %s)", buffer_disk_size, buffer_disk_size_found); } wmove(stdscr,7,0); wprintw(stdscr,"Check the harddisk size: HD jumper settings, BIOS detection..."); #if defined(__CYGWIN__) || defined(__MINGW32__) if(disk_car->disk_size<=((uint64_t)1<<(28-1)) && disk_size>=((uint64_t)1<<(28-1))) { wmove(stdscr,8,0); wprintw(stdscr,"Hint: update Windows to support LBA48 (minimum: W2K SP4 or XP SP1)"); } #endif wmove(stdscr,9,0); if(list_part->next==NULL) { wprintw(stdscr,"The following partition can't be recovered:"); } else { wprintw(stdscr,"The following partitions can't be recovered:"); } mvwaddstr(stdscr,10,0,msg_PART_HEADER); wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); wprintw(stdscr,"[ Continue ]"); wattroff(stdscr, A_REVERSE); do { int i; int car; list_part_t *parts; for(i=0,parts=list_part;(parts!=NULL) && (i<offset);parts=parts->next,i++); for(i=offset;(parts!=NULL) &&((i-offset)<INTER_BAD_PART);i++,parts=parts->next) { wmove(stdscr,11+i-offset,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(parts==pos) { char buffer_part_size[100]; wattrset(stdscr, A_REVERSE); waddstr(stdscr, ">"); aff_part(stdscr, AFF_PART_BASE, disk_car, parts->part); wattroff(stdscr, A_REVERSE); wmove(stdscr,23,0); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(parts->part->info[0]!='\0') { wprintw(stdscr,"%s, ",parts->part->info); } size_to_unit(parts->part->part_size, buffer_part_size); wprintw(stdscr,"%s", buffer_part_size); } else { waddstr(stdscr, " "); aff_part(stdscr, AFF_PART_BASE, disk_car, parts->part); } } wrefresh(stdscr); car=wgetch(stdscr); switch(car) { case 'q': case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case 'M': quit=1; break; case KEY_UP: if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } break; case KEY_DOWN: if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case KEY_PPAGE: for(i=0; i<INTER_BAD_PART && pos->prev!=NULL; i++) { pos=pos->prev; pos_num--; } break; case KEY_NPAGE: for(i=0; i<INTER_BAD_PART && pos->next!=NULL; i++) { pos=pos->next; pos_num++; } break; default: break; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+INTER_BAD_PART) offset=pos_num-INTER_BAD_PART+1; } while(quit==0); return 0; }