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 long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, file_data_t*dir_list, const unsigned long int inode, const unsigned int depth) { /* Return value * -1: quit * 1: back * other: new inode * */ int quit=0; WINDOW *window=(WINDOW*)dir_data->display; do { int offset=0; int pos_num=0; file_data_t *pos=dir_list; int old_LINES=LINES; unsigned int status=FILE_STATUS_MARKED; aff_copy(window); wmove(window,3,0); aff_part(window, AFF_PART_ORDER|AFF_PART_STATUS, disk, partition); wmove(window,4,0); wprintw(window,"Directory %s\n",dir_data->current_directory); do { int i; int car; const file_data_t *current_file; for(i=0,current_file=dir_list;(current_file!=NULL) && (i<offset);current_file=current_file->next,i++); for(i=offset;(current_file!=NULL) &&((i-offset)<INTER_DIR);i++,current_file=current_file->next) { char str[11]; char datestr[80]; wmove(window, 6+i-offset, 0); wclrtoeol(window); /* before addstr for BSD compatibility */ if(current_file==pos) { wattrset(window, A_REVERSE); waddstr(window, ">"); } else waddstr(window, " "); if((current_file->status&FILE_STATUS_DELETED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(1)); else if((current_file->status&FILE_STATUS_MARKED)!=0 && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(2)); if(current_file->td_mtime!=0) { struct tm *tm_p; tm_p = localtime(¤t_file->td_mtime); snprintf(datestr, sizeof(datestr),"%2d-%s-%4d %02d:%02d", tm_p->tm_mday, monstr[tm_p->tm_mon], 1900 + tm_p->tm_year, tm_p->tm_hour, tm_p->tm_min); /* May have to use %d instead of %e */ } else { strncpy(datestr, " ",sizeof(datestr)); } mode_string(current_file->st_mode, str); wprintw(window, "%s %5u %5u ", str, (unsigned int)current_file->st_uid, (unsigned int)current_file->st_gid); wprintw(window, "%9llu", (long long unsigned int)current_file->st_size); /* screen may overlap due to long filename */ wprintw(window, " %s %s", datestr, current_file->name); if(((current_file->status&FILE_STATUS_DELETED)!=0 || (current_file->status&FILE_STATUS_MARKED)!=0) && has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if(current_file==pos) wattroff(window, A_REVERSE); } wmove(window, 6-1, 51); wclrtoeol(window); if(offset>0) wprintw(window, "Previous"); /* Clear the last line, useful if overlapping */ wmove(window,6+i-offset,0); wclrtoeol(window); wmove(window, 6+INTER_DIR, 51); wclrtoeol(window); if(current_file!=NULL) wprintw(window, "Next"); if(dir_list==NULL) { wmove(window,6,0); wprintw(window,"No file found, filesystem may be damaged."); } /* Redraw the bottom of the screen everytime because very long filenames may have corrupt it*/ mvwaddstr(window,LINES-3,0,"Use "); if(depth>0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window, "Left"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," arrow to go back, "); } if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"Right"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to change directory"); if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"h"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((dir_data->param&FLAG_LIST_DELETED)==0) waddstr(window," to unhide deleted files"); else waddstr(window," to hide deleted files"); } wmove(window,LINES-2,4); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"q"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to quit"); if(dir_data->copy_file!=NULL) { waddstr(window,", "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,":"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to select the current file, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"a"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED) waddstr(window," to select all files "); else waddstr(window," to deselect all files"); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); mvwaddstr(window,LINES-1,4,"C"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the selected files, "); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0)); waddstr(window,"c"); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); waddstr(window," to copy the current file"); } wrefresh(window); /* Using gnome terminal under FC3, TERM=xterm, the screen is not always correct */ wredrawln(window,0,getmaxy(window)); /* redrawwin def is boggus in pdcur24 */ car=wgetch(window); wmove(window,5,0); wclrtoeol(window); switch(car) { case key_ESC: case 'q': case 'M': quit=1; break; case '-': case KEY_LEFT: case '4': if(depth>0) return 1; break; case 'h': if((dir_data->capabilities&CAPA_LIST_DELETED)!=0) dir_data->param^=FLAG_LIST_DELETED; return inode; } if(dir_list!=NULL) { switch(car) { case KEY_UP: case '8': if(pos->prev!=NULL) { pos=pos->prev; pos_num--; } break; case KEY_DOWN: case '2': if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case ':': if(!(pos->name[0]=='.' && pos->name[1]=='\0') && !(pos->name[0]=='.' && pos->name[1]=='.' && pos->name[2]=='\0')) pos->status^=FILE_STATUS_MARKED; if(pos->next!=NULL) { pos=pos->next; pos_num++; } break; case 'a': { file_data_t *tmp; for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->name[0]=='.' && tmp->name[1]=='\0') || (tmp->name[0]=='.' && tmp->name[1]=='.' && tmp->name[2]=='\0')) { tmp->status&=~FILE_STATUS_MARKED; } else { if((tmp->status & FILE_STATUS_MARKED)!=status) tmp->status^=FILE_STATUS_MARKED; } } status^=FILE_STATUS_MARKED; } break; case 'p': case 'P': case '+': case ' ': case KEY_RIGHT: case '\r': case '\n': case '6': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif if((pos!=NULL) && (LINUX_S_ISDIR(pos->st_mode)!=0)) { unsigned long int new_inode=pos->st_ino; if((new_inode!=inode) &&(strcmp(pos->name,".")!=0)) { if(strcmp(pos->name,"..")==0) return 1; if(strlen(dir_data->current_directory)+1+strlen(pos->name)+1<=sizeof(dir_data->current_directory)) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); strcat(dir_data->current_directory,pos->name); return (long int)new_inode; } } } break; case KEY_PPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->prev!=NULL);i++) { pos=pos->prev; pos_num--; } break; case KEY_NPAGE: for(i=0;(i<INTER_DIR-1)&&(pos->next!=NULL);i++) { pos=pos->next; pos_num++; } break; case 'c': if(dir_data->copy_file!=NULL) { const unsigned int current_directory_namelength=strlen(dir_data->current_directory); if(strcmp(pos->name,"..")!=0 && current_directory_namelength+1+strlen(pos->name)<sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(pos->name,".")!=0) strcat(dir_data->current_directory,pos->name); if(dir_data->local_dir==NULL) { if(LINUX_S_ISDIR(pos->st_mode)!=0) dir_data->local_dir=ask_location("Please select a destination where %s and any files below will be copied.", dir_data->current_directory, NULL); else dir_data->local_dir=ask_location("Please select a destination where %s will be copied.", dir_data->current_directory, NULL); } if(dir_data->local_dir!=NULL) { int res=-1; wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); if(LINUX_S_ISDIR(pos->st_mode)!=0) { res=copy_dir(disk, partition, dir_data, pos); } else if(LINUX_S_ISREG(pos->st_mode)!=0) { res=dir_data->copy_file(disk, partition, dir_data, pos); } wmove(window,5,0); wclrtoeol(window); if(res < -1) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(res < 0) wprintw(window,"Copy done! (Failed to copy some files)"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } dir_data->current_directory[current_directory_namelength]='\0'; } } break; case 'C': if(dir_data->copy_file!=NULL) { if(dir_data->local_dir==NULL) { dir_data->local_dir=ask_location("Please select a destination where the marked files will be copied.", NULL, NULL); } if(dir_data->local_dir!=NULL) { file_data_t *tmp; int copy_bad=0; int copy_ok=0; const unsigned int current_directory_namelength=strlen(dir_data->current_directory); wmove(window,5,0); wclrtoeol(window); if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copying, please wait..."); if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); wrefresh(window); for(tmp=dir_list; tmp!=NULL; tmp=tmp->next) { if((tmp->status&FILE_STATUS_MARKED)!=0 && current_directory_namelength + 1 + strlen(tmp->name) < sizeof(dir_data->current_directory)-1) { if(strcmp(dir_data->current_directory,"/")) strcat(dir_data->current_directory,"/"); if(strcmp(tmp->name,".")!=0) strcat(dir_data->current_directory,tmp->name); if(LINUX_S_ISDIR(tmp->st_mode)!=0) { const int res=copy_dir(disk, partition, dir_data, tmp); if(res >=-1) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else if(res < 0) copy_bad=1; } else if(LINUX_S_ISREG(tmp->st_mode)!=0) { if(dir_data->copy_file(disk, partition, dir_data, tmp) == 0) { tmp->status&=~FILE_STATUS_MARKED; copy_ok=1; } else copy_bad=1; } } dir_data->current_directory[current_directory_namelength]='\0'; } wmove(window,5,0); wclrtoeol(window); if(copy_bad > 0 && copy_ok==0) { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(1)); wprintw(window,"Copy failed!"); } else { if(has_colors()) wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(2)); if(copy_bad > 0) wprintw(window,"Copy done! (Failed to copy some files)"); else if(copy_ok == 0) wprintw(window,"No file selected"); else wprintw(window,"Copy done!"); } if(has_colors()) wbkgdset(window,' ' | COLOR_PAIR(0)); } } break; case 'f': { const char *needle=ask_string_ncurses("Filename to find ? "); if(needle!=NULL && needle[0]!='\0') { file_data_t *pos_org=pos; const int pos_num_org=pos_num; while(strcmp(pos->name, needle)!=0 && pos->next!=NULL) { pos=pos->next; pos_num++; } if(strcmp(pos->name, needle)!=0) { pos=pos_org; pos_num=pos_num_org; } } } break; } if(pos_num<offset) offset=pos_num; if(pos_num>=offset+INTER_DIR) offset=pos_num-INTER_DIR+1; } } while(quit==0 && old_LINES==LINES); } while(quit==0); return -1; }
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); }
void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const unsigned int expert, char**current_cmd) { #ifdef HAVE_NCURSES int offset=0; int current_element_num=0; int old_LINES=LINES; #endif int rewrite=1; unsigned int menu=0; list_part_t *element; list_part_t *list_part; list_part_t *current_element; log_info("\nInterface Advanced\n"); list_part=disk_car->arch->read_part(disk_car,verbose,0); current_element=list_part; log_all_partitions(disk_car, list_part); while(1) { const char *options; static struct MenuItem menuAdv[]= { {'t',"Type","Change type, this setting will not be saved on disk"}, {'b',"Boot","Boot sector recovery"}, {'s',"Superblock",NULL}, {'l',"List", "List and copy files"}, {'u',"Undelete", "File undelete"}, {'c',"Image Creation", "Create an image"}, // {'a',"Add", "Add temporary partition (Expert only)"}, {'q',"Quit","Return to main menu"}, {0,NULL,NULL} }; int command; #ifdef HAVE_NCURSES int i; if(old_LINES!=LINES) { old_LINES=LINES; rewrite=1; } if(rewrite!=0) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); if(list_part!=NULL) mvwaddstr(stdscr,6,0,msg_PART_HEADER_LONG); rewrite=0; } for(i=0,element=list_part; element!=NULL && i<offset+INTER_ADV; 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,disk_car,element->part); wattroff(stdscr, A_REVERSE); } else { waddstr(stdscr, " "); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,element->part); } } wmove(stdscr,7+INTER_ADV,5); wclrtoeol(stdscr); if(element!=NULL) wprintw(stdscr, "Next"); #endif if(current_element==NULL) { options="q"; #ifdef HAVE_NCURSES wmove(stdscr,7,0); wattrset(stdscr, A_REVERSE); wprintw(stdscr,"No partition available."); wattroff(stdscr, A_REVERSE); #endif } else { const partition_t *partition=current_element->part; if(menu==0 && (disk_car->arch!=&arch_none || partition->upart_type!=UP_UNK)) menu=1; if(is_part_fat(partition)) { options="tubcq"; menu=(partition->upart_type==UP_UNK?1:4); } else if(is_part_ntfs(partition)) options="tlubcq"; else if(is_part_linux(partition)) { if(partition->upart_type==UP_EXT2) options="tuscq"; else options="tlscq"; menuAdv[2].desc="Locate ext2/ext3/ext4 backup superblock"; } else if(is_part_hfs(partition) || is_part_hfsp(partition)) { options="tscq"; menuAdv[2].desc="Locate HFS/HFS+ backup volume header"; } else if(is_fat(partition)) options="tubcq"; else if(is_ntfs(partition)) options="tlubcq"; else if(is_exfat(partition)) options="tlubcq"; else if(is_linux(partition)) { if(partition->upart_type==UP_EXT2) options="tluscq"; else options="tlscq"; menuAdv[2].desc="Locate ext2/ext3/ext4 backup superblock"; } else if(is_hfs(partition) || is_hfsp(partition)) { options="tscq"; menuAdv[2].desc="Locate HFS/HFS+ backup volume header"; } else options="tcq"; } if(*current_cmd!=NULL) { int keep_asking; command='q'; do { keep_asking=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"type",4)==0) { (*current_cmd)+=4; command='t'; } else if(strncmp(*current_cmd,"addpart",7)==0) { (*current_cmd)+=7; command='a'; } else if(strncmp(*current_cmd,"boot",4)==0) { (*current_cmd)+=4; command='b'; } else if(strncmp(*current_cmd,"copy",4)==0) { (*current_cmd)+=4; command='c'; } else if(strncmp(*current_cmd,"list",4)==0) { (*current_cmd)+=4; command='l'; } else if(strncmp(*current_cmd,"undelete",8)==0) { (*current_cmd)+=8; command='u'; } else if(strncmp(*current_cmd,"superblock",10)==0) { (*current_cmd)+=10; command='s'; } else if(isdigit(*current_cmd[0])) { const unsigned int order= atoi(*current_cmd); while(*current_cmd[0]!=',' && *current_cmd[0]!='\0') (*current_cmd)++; for(element=list_part; element!=NULL && element->part->order!=order; element=element->next); if(element!=NULL) { current_element=element; keep_asking=1; } } } while(keep_asking>0); } else { #ifdef HAVE_NCURSES command = wmenuSelect_ext(stdscr, INTER_ADV_Y+1, INTER_ADV_Y, INTER_ADV_X, menuAdv, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, &menu, NULL); #else command = 'q'; #endif } switch(command) { case 'q': case 'Q': part_free_list(list_part); return; #ifdef HAVE_NCURSES case 'a': case 'A': if(disk_car->arch!=&arch_none) { if(*current_cmd!=NULL) list_part=add_partition_cli(disk_car, list_part, current_cmd); else list_part=add_partition_ncurses(disk_car, list_part); current_element=list_part; rewrite=1; } break; #endif } #ifdef HAVE_NCURSES if(current_element!=NULL) { switch(command) { case 'p': case 'P': case KEY_UP: if(current_element->prev!=NULL) { current_element=current_element->prev; current_element_num--; } break; case 'n': case 'N': case KEY_DOWN: if(current_element->next!=NULL) { current_element=current_element->next; current_element_num++; } break; case KEY_PPAGE: for(i=0; i<INTER_ADV-1 && current_element->prev!=NULL; i++) { current_element=current_element->prev; current_element_num--; } break; case KEY_NPAGE: for(i=0; i<INTER_ADV-1 && current_element->next!=NULL; i++) { current_element=current_element->next; current_element_num++; } break; case 'b': case 'B': { partition_t *partition=current_element->part; if(is_part_fat32(partition)) { fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); rewrite=1; } else if(is_part_fat12(partition) || is_part_fat16(partition)) { fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); rewrite=1; } else if(is_part_ntfs(partition)) { if(partition->upart_type==UP_EXFAT) exFAT_boot_sector(disk_car, partition, verbose, current_cmd); else ntfs_boot_sector(disk_car, partition, verbose, expert, current_cmd); rewrite=1; } else if(partition->upart_type==UP_FAT32) { fat32_boot_sector(disk_car, partition, verbose, dump_ind, expert,current_cmd); rewrite=1; } else if(partition->upart_type==UP_FAT12 || partition->upart_type==UP_FAT16) { fat1x_boot_sector(disk_car, partition, verbose, dump_ind,expert,current_cmd); rewrite=1; } else if(partition->upart_type==UP_NTFS) { ntfs_boot_sector(disk_car, partition, verbose, expert, current_cmd); rewrite=1; } else if(partition->upart_type==UP_EXFAT) { exFAT_boot_sector(disk_car, partition, verbose, current_cmd); rewrite=1; } } break; case 'c': case 'C': { char *dst_path; #ifdef HAVE_NCURSES if(*current_cmd!=NULL) dst_path=get_default_location(); else { char msg[256]; snprintf(msg, sizeof(msg), "Please select where to store the file image.dd (%u MB), an image of the partition", (unsigned int)(current_element->part->part_size/1000/1000)); dst_path=ask_location(msg, "", NULL); } #else dst_path=get_default_location(); #endif if(dst_path!=NULL) { char *filename=(char *)MALLOC(strlen(dst_path) + 1 + strlen(DEFAULT_IMAGE_NAME) + 1); strcpy(filename, dst_path); strcat(filename, "/"); strcat(filename, DEFAULT_IMAGE_NAME); disk_image(disk_car, current_element->part, filename); free(filename); free(dst_path); } } rewrite=1; break; case 'u': case 'U': { partition_t *partition=current_element->part; if(partition->sb_offset!=0 && partition->sb_size>0) { io_redir_add_redir(disk_car, partition->part_offset+partition->sborg_offset, partition->sb_size, partition->part_offset+partition->sb_offset, NULL); if(partition->upart_type==UP_NTFS || (is_part_ntfs(partition) && partition->upart_type!=UP_EXFAT)) ntfs_undelete_part(disk_car, partition, verbose, current_cmd); else dir_partition(disk_car, partition, 0, current_cmd); io_redir_del_redir(disk_car, partition->part_offset+partition->sborg_offset); } else { if(partition->upart_type==UP_NTFS || (is_part_ntfs(partition) && partition->upart_type!=UP_EXFAT)) ntfs_undelete_part(disk_car, partition, verbose, current_cmd); else dir_partition(disk_car, partition, 0, current_cmd); } } rewrite=1; break; case 'l': case 'L': { partition_t *partition=current_element->part; if(partition->sb_offset!=0 && partition->sb_size>0) { 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); } else dir_partition(disk_car,partition,verbose, current_cmd); } rewrite=1; break; case 's': case 'S': { if(is_linux(current_element->part)) { list_part_t *list_sb=search_superblock(disk_car,current_element->part,verbose,dump_ind,1); interface_superblock(disk_car,list_sb,current_cmd); part_free_list(list_sb); } if(is_hfs(current_element->part) || is_hfsp(current_element->part)) { HFS_HFSP_boot_sector(disk_car, current_element->part, verbose, current_cmd); } rewrite=1; } break; case 't': case 'T': if(*current_cmd!=NULL) change_part_type_cli(disk_car, current_element->part, current_cmd); else change_part_type_ncurses(disk_car, current_element->part); rewrite=1; break; } if(current_element_num<offset) offset=current_element_num; if(current_element_num>=offset+INTER_ADV) offset=current_element_num-INTER_ADV+1; } #endif } }