static list_part_t *ask_structure_cli(disk_t *disk_car,list_part_t *list_part, const int verbose, char **current_cmd) { const list_part_t *pos=list_part; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"list",4)==0) { (*current_cmd)+=4; if(pos!=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); } } } 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 ntfs_boot_sector(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int expert, char **current_cmd) { unsigned char *buffer_bs; unsigned char *buffer_backup_bs; const char *options=""; #ifdef HAVE_NCURSES struct MenuItem menu_ntfs[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Quit","Return to Advanced menu"}, { 'L', "List", "List directories and files, copy data from NTFS" }, { 'O', "Org. BS","Copy boot sector over backup sector"}, { 'B', "Backup BS","Copy backup boot sector over boot sector"}, { 'R', "Rebuild BS","Rebuild boot sector"}, { 'M', "Repair MFT","Check MFT"}, { 'D', "Dump","Dump boot sector and backup boot sector"}, { 0, NULL, NULL } }; #endif buffer_bs=(unsigned char*)MALLOC(NTFS_BOOT_SECTOR_SIZE); buffer_backup_bs=(unsigned char*)MALLOC(NTFS_BOOT_SECTOR_SIZE); while(1) { unsigned int menu=0; int command; screen_buffer_reset(); { int identical_sectors=0; int opt_B=0; int opt_O=0; #ifdef HAVE_NCURSES 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); #endif log_info("\nntfs_boot_sector\n"); log_partition(disk_car,partition); screen_buffer_add("Boot sector\n"); if(disk_car->pread(disk_car, buffer_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset) != NTFS_BOOT_SECTOR_SIZE) { screen_buffer_add("ntfs_boot_sector: Can't read boot sector.\n"); memset(buffer_bs,0,NTFS_BOOT_SECTOR_SIZE); } if(test_NTFS(disk_car,(struct ntfs_boot_sector*)buffer_bs,partition,verbose,0)==0) { screen_buffer_add("Status: OK\n"); opt_O=1; } else { screen_buffer_add("Status: Bad\n"); } screen_buffer_add("\nBackup boot sector\n"); if(disk_car->pread(disk_car, buffer_backup_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset + partition->part_size - disk_car->sector_size) != NTFS_BOOT_SECTOR_SIZE) { screen_buffer_add("ntfs_boot_sector: Can't read backup boot sector.\n"); memset(buffer_backup_bs,0,NTFS_BOOT_SECTOR_SIZE); } if(test_NTFS(disk_car,(struct ntfs_boot_sector*)buffer_backup_bs,partition,verbose,0)==0) { screen_buffer_add("Status: OK\n"); opt_B=1; } else { screen_buffer_add("Status: Bad\n"); } screen_buffer_add("\n"); if(memcmp(buffer_bs,buffer_backup_bs,NTFS_BOOT_SECTOR_SIZE)==0) { log_ntfs_info((const struct ntfs_boot_sector *)buffer_bs); screen_buffer_add("Sectors are identical.\n"); identical_sectors=1; } else { log_ntfs2_info((const struct ntfs_boot_sector *)buffer_bs, (const struct ntfs_boot_sector *)buffer_backup_bs); screen_buffer_add("Sectors are not identical.\n"); identical_sectors=0; } screen_buffer_add("\n"); screen_buffer_add("A valid NTFS Boot sector must be present in order to access\n"); screen_buffer_add("any data; even if the partition is not bootable.\n"); if(opt_B!=0 && opt_O!=0) { if(identical_sectors==0) options="DOBRL"; else options="DRML"; } else if(opt_B!=0) { menu=5; if(expert>0) options="DBRML"; else options="DBRL"; } else if(opt_O!=0) { menu=4; options="DORL"; } else options="DR"; } screen_buffer_to_log(); if(*current_cmd!=NULL) { command=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"rebuildbs",9)==0) { (*current_cmd)+=9; command='R'; } else if(strncmp(*current_cmd,"dump",4)==0) { (*current_cmd)+=4; command='D'; } else if(strncmp(*current_cmd,"list",4)==0) { (*current_cmd)+=4; command='L'; } else if(strncmp(*current_cmd,"originalntfs",11)==0) { (*current_cmd)+=11; if(strchr(options,'O')!=NULL) command='O'; } else if(strncmp(*current_cmd,"backupntfs",9)==0) { (*current_cmd)+=9; if(strchr(options,'B')!=NULL) command='B'; } else if(strncmp(*current_cmd,"repairmft",9)==0) { (*current_cmd)+=9; if(strchr(options,'M')!=NULL) command='M'; } } else { log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display_ext(stdscr, options, menu_ntfs, &menu); #else command=0; #endif } switch(command) { case 0: free(buffer_bs); free(buffer_backup_bs); return 0; case 'O': /* O : copy original boot sector over backup boot */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy original NTFS boot sector over backup boot, confirm ? (Y/N)")!=0) { log_info("copy original boot sector over backup boot\n"); if(disk_car->pwrite(disk_car, buffer_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset + partition->part_size - disk_car->sector_size) != NTFS_BOOT_SECTOR_SIZE) { display_message("Write error: Can't overwrite NTFS backup boot sector\n"); } disk_car->sync(disk_car); } #endif break; case 'B': /* B : copy backup boot sector over boot sector */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy backup NTFS boot sector over boot sector, confirm ? (Y/N)")!=0) { log_info("copy backup boot sector over boot sector\n"); /* Reset information about backup boot sector */ partition->sb_offset=0; if(disk_car->pwrite(disk_car, buffer_backup_bs, NTFS_BOOT_SECTOR_SIZE, partition->part_offset) != NTFS_BOOT_SECTOR_SIZE) { display_message("Write error: Can't overwrite NTFS boot sector\n"); } disk_car->sync(disk_car); } #endif break; case 'L': if(strchr(options,'O')==NULL && strchr(options,'B')!=NULL) { io_redir_add_redir(disk_car,partition->part_offset,NTFS_BOOT_SECTOR_SIZE,0,buffer_backup_bs); dir_partition(disk_car, partition, 0,current_cmd); io_redir_del_redir(disk_car,partition->part_offset); } else dir_partition(disk_car, partition, 0,current_cmd); break; case 'M': repair_MFT(disk_car, partition, verbose, expert, current_cmd); break; case 'R': /* R : rebuild boot sector */ rebuild_NTFS_BS(disk_car, partition, verbose, 1, expert, current_cmd); break; case 'D': dump_NTFS(disk_car, partition, buffer_bs, buffer_backup_bs); break; } } }
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 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 } }