static int use_backup(disk_t *disk_car, const list_part_t *list_part, const int verbose,const int dump_ind, const unsigned int expert, char**current_cmd) { const list_part_t *element; if(verbose>1) { log_trace("use_backup\n"); } for(element=list_part;element!=NULL;element=element->next) { if(element->part->sb_offset!=0) { switch(element->part->upart_type) { case UP_FAT32: fat32_boot_sector(disk_car, element->part, verbose, dump_ind, expert,current_cmd); break; case UP_NTFS: ntfs_boot_sector(disk_car, element->part, verbose, expert, current_cmd); break; case UP_HFS: case UP_HFSP: case UP_HFSX: HFS_HFSP_boot_sector(disk_car, element->part, verbose, current_cmd); break; default: log_warning("Need to fix\n"); log_partition(disk_car,element->part); break; } } } return 0; }
int check_FAT(disk_t *disk_car,partition_t *partition,const int verbose) { unsigned char *buffer; buffer=(unsigned char *)MALLOC(3*disk_car->sector_size); if((unsigned)disk_car->pread(disk_car, buffer, 3 * disk_car->sector_size, partition->part_offset) != 3 * disk_car->sector_size) { screen_buffer_add("check_FAT: can't read FAT boot sector\n"); log_error("check_FAT: can't read FAT boot sector\n"); free(buffer); return 1; } if(test_FAT(disk_car,(const struct fat_boot_sector *)buffer,partition,verbose,0)!=0) { if(verbose>0) { log_error("\n\ntest_FAT()\n"); log_partition(disk_car,partition); log_fat_info((const struct fat_boot_sector*)buffer, partition->upart_type,disk_car->sector_size); } free(buffer); return 1; } set_FAT_info(disk_car,(const struct fat_boot_sector *)buffer,partition); /* screen_buffer_add("Ok\n"); */ free(buffer); return 0; }
void QPhotorec::qphotorec_search() { if(selected_disk==NULL || selected_partition==NULL) return; alloc_data_t list_search_space; TD_INIT_LIST_HEAD(&list_search_space.list); QByteArray byteArray = (directoryLabel->text() + "/" + DEFAULT_RECUP_DIR).toUtf8(); params->recup_dir=strdup(byteArray.constData()); params->carve_free_space_only=qfreeRadioButton->isChecked(); params->disk=selected_disk; params->partition=selected_partition; log_partition(selected_disk, selected_partition); options->mode_ext2=qextRadioButton->isChecked(); qphotorec_search_setupUI(); 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); } photorec(&list_search_space); free(params->recup_dir); params->recup_dir=NULL; }
static int test_sun_i386(const disk_t *disk_car, const sun_partition_i386 *sunlabel, const partition_t *partition, const int verbose) { if ((le16(sunlabel->magic) != SUN_LABEL_MAGIC) || (le32(sunlabel->magic_start) != SUN_LABEL_MAGIC_START)) return 1; if(verbose>0) log_info("\nSUN Marker at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset), offset2head(disk_car,partition->part_offset), offset2sector(disk_car,partition->part_offset)); { int i; partition_t *new_partition=partition_new(NULL); for(i=0;i<16;i++) { if (sunlabel->partitions[i].num_sectors > 0 && sunlabel->partitions[i].id > 0) // && sunlabel->partitions[i].id != WHOLE_DISK) { partition_reset(new_partition, &arch_sun); new_partition->order=i; new_partition->part_type_sun=sunlabel->partitions[i].id; new_partition->part_offset=partition->part_offset+(uint64_t)le32(sunlabel->partitions[i].start_sector) * le16(sunlabel->sector_size); new_partition->part_size=(uint64_t)le32(sunlabel->partitions[i].num_sectors) * le16(sunlabel->sector_size); new_partition->status=STATUS_PRIM; log_partition(disk_car,new_partition); } } free(new_partition); } 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"; }
static int check_part_gpt(disk_t *disk, const int verbose,partition_t *partition, const int saveheader) { int ret=0; unsigned int old_levels; old_levels=log_set_levels(0); if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MS_BASIC_DATA)==0 || guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MS_RESERVED)==0) { ret=check_FAT(disk,partition,verbose); if(ret!=0) ret=check_EXFAT(disk, partition); if(ret!=0) ret=check_NTFS(disk,partition,verbose,0); if(ret!=0) ret=check_ReFS(disk, partition); if(ret!=0) ret=check_linux(disk, partition, verbose); if(ret!=0) screen_buffer_add("No FAT, NTFS, ext2, JFS, Reiser, cramfs or XFS marker\n"); } else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_LINUX_RAID)==0) { ret=check_MD(disk, partition, verbose); if(ret!=0) screen_buffer_add("Invalid RAID superblock\n"); } else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_LINUX_LVM)==0) { ret=check_LVM(disk, partition, verbose); if(ret!=0) ret=check_LVM2(disk, partition, verbose); if(ret!=0) screen_buffer_add("No LVM or LVM2 structure\n"); } else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MAC_HFS)==0) { ret=check_HFS(disk, partition, verbose); if(ret!=0) ret=check_HFSP(disk, partition, verbose); if(ret!=0) screen_buffer_add("No HFS or HFS+ structure\n"); } log_set_levels(old_levels); if(ret!=0) { log_error("check_part_gpt failed for partition\n"); log_partition(disk, partition); aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); if(saveheader>0) { save_header(disk, partition, verbose); } } return ret; }
static int dir_partition_aux(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const unsigned long int inode, const unsigned int depth, char**current_cmd) { #define MAX_DIR_NBR 256 static unsigned long int inode_known[MAX_DIR_NBR]; if(depth==MAX_DIR_NBR) return 1; /* subdirectories depth is too high => Back */ if(dir_data->verbose>0) { log_info("\ndir_partition inode=%lu\n",inode); log_partition(disk, partition); } while(1) { const unsigned int current_directory_namelength=strlen(dir_data->current_directory); long int new_inode=-1; /* Quit */ file_data_t *dir_list; /* Not perfect for FAT32 root cluster */ inode_known[depth]=inode; dir_list=dir_data->get_dir(disk, partition, dir_data, inode); dir_aff_log(dir_data, dir_list); if(*current_cmd!=NULL) { /* TODO: handle copy_files */ dir_data->current_directory[current_directory_namelength]='\0'; delete_list_file(dir_list); return -1; /* Quit */ } new_inode=dir_aff_ncurses(disk, partition, dir_data,dir_list,inode,depth); if(new_inode==-1 || new_inode==1) /* -1:Quit or 1:Back */ { delete_list_file(dir_list); return new_inode; } if(new_inode>=2) { unsigned int new_inode_ok=1; unsigned int i; for(i=0;i<=depth && new_inode_ok!=0;i++) if((unsigned)new_inode==inode_known[i]) /* Avoid loop */ new_inode_ok=0; if(new_inode_ok>0) { dir_partition_aux(disk, partition, dir_data, (unsigned long int)new_inode, depth+1, current_cmd); } } /* restore current_directory name */ dir_data->current_directory[current_directory_namelength]='\0'; delete_list_file(dir_list); } }
void change_part_type(const disk_t *disk_car,partition_t *partition, char **current_cmd) { if(*current_cmd!=NULL) { change_part_type_cli(disk_car, partition, current_cmd); return; } if(partition->arch==NULL) { log_error("change_part_type arch==NULL\n"); return; } if(partition->arch==&arch_gpt) { gpt_change_part_type(disk_car, partition); log_info("Change partition type:\n"); log_partition(disk_car,partition); partition->arch=&arch_none; change_part_type_ncurses2(disk_car, partition); log_info("Change partition type:\n"); log_partition(disk_car,partition); partition->arch=&arch_gpt; return ; } if(partition->arch->set_part_type==NULL) { log_error("change_part_type set_part_type==NULL\n"); return; } if(partition->arch==&arch_i386 || partition->arch==&arch_sun) change_part_type_ncurses(disk_car, partition); else change_part_type_ncurses2(disk_car, partition); log_info("Change partition type:\n"); log_partition(disk_car,partition); }
static int interface_part_bad_log(disk_t *disk_car, list_part_t *list_part) { uint64_t disk_size=disk_car->disk_size; 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; } } log_warning("%s\n",disk_car->description(disk_car)); log_warning("Check the harddisk size: HD jumper settings, BIOS detection...\n"); #if defined(__CYGWIN__) || defined(__MINGW32__) if(disk_car->disk_size<=((uint64_t)1<<(28-1)) && disk_size>=((uint64_t)1<<(28-1))) { log_warning("Hint: update Windows to support LBA48 (minimum: W2K SP4 or XP SP1)\n"); } #endif { 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); log_warning("The harddisk (%s) seems too small! (< %s)\n", buffer_disk_size, buffer_disk_size_found); } if(list_part->next==NULL) { log_warning("The following partition can't be recovered:\n"); } else { log_warning("The following partitions can't be recovered:\n"); } { list_part_t *parts; for(parts=list_part;parts!=NULL;parts=parts->next) log_partition(disk_car,parts->part); } return 0; }
int check_HPFS(disk_t *disk_car,partition_t *partition,const int verbose) { unsigned char buffer[disk_car->sector_size]; if((unsigned)disk_car->pread(disk_car, &buffer, disk_car->sector_size, partition->part_offset) != disk_car->sector_size) { screen_buffer_add("check_HPFS: Read error\n"); log_error("check_HPFS: Read error\n"); return 1; } if(test_HPFS(disk_car,(const struct fat_boot_sector *)buffer,partition,verbose,0)!=0) { if(verbose>0) { log_info("\n\ntest_HPFS()\n"); log_partition(disk_car,partition); } return 1; } return 0; }
static unsigned int get_geometry_from_list_part_aux(const disk_t *disk_car, const list_part_t *list_part, const int verbose) { const list_part_t *element; unsigned int nbr=0; for(element=list_part;element!=NULL;element=element->next) { CHS_t start; CHS_t end; offset2CHS(disk_car,element->part->part_offset,&start); offset2CHS(disk_car,element->part->part_offset+element->part->part_size-1,&end); if(start.sector==1 && start.head<=1) { nbr++; if(end.head==disk_car->geom.heads_per_cylinder-1) { nbr++; /* Doesn't check if end.sector==disk_car->CHS.sector */ } } } if(nbr>0) { log_info("get_geometry_from_list_part_aux head=%u nbr=%u\n", disk_car->geom.heads_per_cylinder, nbr); if(verbose>1) { for(element=list_part;element!=NULL;element=element->next) { CHS_t start; CHS_t end; offset2CHS(disk_car,element->part->part_offset,&start); offset2CHS(disk_car,element->part->part_offset+element->part->part_size-1,&end); if(start.sector==1 && start.head<=1 && end.head==disk_car->geom.heads_per_cylinder-1) { log_partition(disk_car,element->part); } } } } return nbr; }
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 dir_partition(disk_t *disk_car, const partition_t *partition, const int verbose, char **current_cmd) { dir_data_t dir_data; #ifdef HAVE_NCURSES WINDOW *window; #endif int res=-3; fflush(stderr); dir_data.local_dir=NULL; if(is_part_fat(partition)) res=dir_partition_fat_init(disk_car,partition,&dir_data,verbose); else if(is_part_ntfs(partition)) { res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); if(res!=0) res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose); } else if(is_part_linux(partition)) { res=dir_partition_ext2_init(disk_car,partition,&dir_data,verbose); if(res!=0) res=dir_partition_reiser_init(disk_car,partition,&dir_data,verbose); } if(res!=0) { switch(partition->upart_type) { case UP_FAT12: case UP_FAT16: case UP_FAT32: res=dir_partition_fat_init(disk_car,partition,&dir_data,verbose); break; case UP_EXT4: case UP_EXT3: case UP_EXT2: res=dir_partition_ext2_init(disk_car,partition,&dir_data,verbose); break; case UP_RFS: case UP_RFS2: case UP_RFS3: res=dir_partition_reiser_init(disk_car,partition,&dir_data,verbose); break; case UP_NTFS: res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose); break; case UP_EXFAT: res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose); break; default: return res; } } #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 -2: screen_buffer_reset(); #ifdef HAVE_NCURSES aff_copy(window); wmove(window,4,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); #endif log_partition(disk_car,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 -1: screen_buffer_reset(); #ifdef HAVE_NCURSES aff_copy(window); wmove(window,4,0); aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); #endif log_partition(disk_car,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; default: { 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_car,partition,&dir_data,dir_data.current_inode); else { #ifdef HAVE_NCURSES dir_partition_aff(disk_car, partition, &dir_data, dir_data.current_inode, current_cmd); #else { file_data_t *dir_list; dir_list=dir_data.get_dir(disk_car, partition, &dir_data, dir_data.current_inode); 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; }
static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_org, const int verbose, const int dump_ind, const int fast_mode, char **current_cmd) { unsigned char *buffer_disk; unsigned char *buffer_disk0; /* TODO use circular buffer for try_offset and try_offset_raid */ uint64_t try_offset[MAX_SEARCH_LOCATION]; uint64_t try_offset_raid[MAX_SEARCH_LOCATION]; const uint64_t min_location=get_min_location(disk_car); uint64_t search_location; unsigned int try_offset_nbr=0; unsigned int try_offset_raid_nbr=0; #ifdef HAVE_NCURSES unsigned int old_cylinder=0; #endif const unsigned int location_boundary=get_location_boundary(disk_car); indstop_t ind_stop=INDSTOP_CONTINUE; list_part_t *list_part=NULL; list_part_t *list_part_bad=NULL; partition_t *partition; /* It's not a problem to read a little bit more than necessary */ const uint64_t search_location_max=td_max((disk_car->disk_size / ((uint64_t) disk_car->geom.heads_per_cylinder * disk_car->geom.sectors_per_head * disk_car->sector_size) + 1 ) * ((uint64_t) disk_car->geom.heads_per_cylinder * disk_car->geom.sectors_per_head * disk_car->sector_size), disk_car->disk_real_size); assert(disk_car->sector_size>0); partition=partition_new(disk_car->arch); buffer_disk=(unsigned char*)MALLOC(16*DEFAULT_SECTOR_SIZE); buffer_disk0=(unsigned char*)MALLOC(16*DEFAULT_SECTOR_SIZE); { /* Will search for partition at current known partition location */ const list_part_t *element; for(element=list_part_org;element!=NULL;element=element->next) { hint_insert(try_offset, element->part->part_offset, &try_offset_nbr); } } #ifdef HAVE_NCURSES wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr," Stop "); wattroff(stdscr, A_REVERSE); #endif screen_buffer_reset(); log_info("\nsearch_part()\n"); log_info("%s\n",disk_car->description(disk_car)); search_location=min_location; search_add_hints(disk_car, try_offset, &try_offset_nbr); /* Not every sector will be examined */ search_location_init(disk_car, location_boundary, fast_mode); /* Scan the disk */ while(ind_stop!=INDSTOP_QUIT && search_location < search_location_max) { CHS_t start; offset2CHS_inline(disk_car,search_location,&start); #ifdef HAVE_NCURSES if(disk_car->geom.heads_per_cylinder>1) { if(old_cylinder!=start.cylinder) { old_cylinder=start.cylinder; wmove(stdscr,ANALYSE_Y,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,"Analyse cylinder %5u/%u: %02u%%", start.cylinder, disk_car->geom.cylinders-1, (unsigned int)(search_location*100/disk_car->disk_size)); wrefresh(stdscr); switch(check_enter_key_or_s(stdscr)) { case 1: ind_stop=INDSTOP_STOP; break; case 2: ind_stop=INDSTOP_SKIP; break; } } } else if((start.cylinder & 0x7FFF)==0) { wmove(stdscr,ANALYSE_Y,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,"Analyse sector %11llu/%lu: %02u%%", search_location / disk_car->sector_size, (disk_car->disk_size-1)/disk_car->sector_size, (unsigned int)(search_location*100/disk_car->disk_size)); wrefresh(stdscr); switch(check_enter_key_or_s(stdscr)) { case 1: ind_stop=INDSTOP_STOP; break; case 2: ind_stop=INDSTOP_SKIP; break; } } #endif { unsigned int sector_inc=0; int test_nbr=0; int search_now=0; int search_now_raid=0; while(try_offset_nbr>0 && try_offset[0]<=search_location) { unsigned int j; if(try_offset[0]==search_location) search_now=1; for(j=0;j<try_offset_nbr-1;j++) try_offset[j]=try_offset[j+1]; try_offset_nbr--; } /* PC x/0/1 x/1/1 x/2/1 */ /* PC Vista 2048 sectors unit */ if(disk_car->arch==&arch_i386) search_now|= (start.sector==1 && fast_mode>1) || (start.sector==1 && start.head<=2) || search_location%(2048*512)==0; else search_now|= (search_location%location_boundary==0); while(try_offset_raid_nbr>0 && try_offset_raid[0]<=search_location) { unsigned int j; if(try_offset_raid[0]==search_location) search_now_raid=1; for(j=0;j<try_offset_raid_nbr-1;j++) try_offset_raid[j]=try_offset_raid[j+1]; try_offset_raid_nbr--; } do { int res=0; partition->part_size=(uint64_t)0; partition->part_offset=search_location; if(res<=0 && test_nbr==0) { if(search_now_raid>0 || fast_mode>1) { /* Search Linux software RAID */ if(disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, search_location) == 8 *DEFAULT_SECTOR_SIZE) { if(recover_MD(disk_car, (const struct mdp_superblock_s*)buffer_disk, partition, verbose, dump_ind)==0) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer_disk; if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC) { if(le32(sb1->major_version)==0) partition->part_offset-=(uint64_t)MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; else partition->part_offset-=le64(sb1->super_offset)*512; } else { if(be32(sb1->major_version)==0) partition->part_offset-=(uint64_t)MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; else partition->part_offset-=be64(sb1->super_offset)*512; } res=1; } else res=0; } } test_nbr++; } if(res<=0 && test_nbr==1) { if((disk_car->arch==&arch_i386 && ((start.sector==7 && (start.head<=2 || fast_mode>1)) || search_location%(2048*512)==(7-1)*512)) || (disk_car->arch!=&arch_i386 && (search_location%location_boundary==(7-1)*512)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(7-1)*512)) || (disk_car->arch==&arch_none && search_location==(7-1)*512)) res=search_FAT_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==2) { if((disk_car->arch==&arch_i386 && ((start.sector==13 && (start.head<=2 || fast_mode>1)) || search_location%(2048*512)==(13-1)*disk_car->sector_size)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(13-1)*512)) || (disk_car->arch!=&arch_i386 && (search_location%location_boundary==(13-1)*disk_car->sector_size))) res=search_EXFAT_backup(buffer_disk, disk_car, partition); test_nbr++; } if(res<=0 && test_nbr==3) { if((disk_car->arch==&arch_i386 && ((start.sector==disk_car->geom.sectors_per_head && (start.head==disk_car->geom.heads_per_cylinder-1 || fast_mode>1)) || search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch!=&arch_i386 && search_location%location_boundary==(location_boundary-512) && search_location>0)) res=search_NTFS_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==4) { if((disk_car->arch==&arch_i386 && ((start.sector==disk_car->geom.sectors_per_head && (start.head==disk_car->geom.heads_per_cylinder-1 || fast_mode>1)) || search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch!=&arch_i386 && search_location%location_boundary==(location_boundary-512) && search_location>0)) res=search_HFS_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==5) { int s_log_block_size; /* try backup superblock */ /* It must be in fast_mode>0 because it can hide otherwise other partition type */ /* Block size: 1024, 2048 or 4096 bytes (8192 bytes on Alpha systems) */ /* From e2fsprogs-1.34/lib/ext2fs/initialize.c: set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); */ /* Assumes that TestDisk is not running under Alpha and s_blocks_per_group=8 * block size */ for(s_log_block_size=0;(s_log_block_size<=2)&&(res<=0);s_log_block_size++) { /* sparse superblock feature: The groups chosen are 0, 1 and powers of 3, 5 and 7. */ /* Checking group 3 */ const uint64_t hd_offset=3*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)+(s_log_block_size==0?2*DEFAULT_SECTOR_SIZE:0); if(search_location>=hd_offset) { CHS_t start_ext2; offset2CHS_inline(disk_car,search_location-hd_offset,&start_ext2); if((disk_car->arch==&arch_i386 && start_ext2.sector==1 && (start_ext2.head<=2 || fast_mode>1)) || (disk_car->arch==&arch_i386 && (search_location-hd_offset)%(2048*512)==0) || (disk_car->arch!=&arch_i386 && (search_location-hd_offset)%location_boundary==0)) { if(disk_car->pread(disk_car, buffer_disk, 1024, search_location)==1024) { const struct ext2_super_block *sb=(const struct ext2_super_block*)buffer_disk; if(le16(sb->s_magic)==EXT2_SUPER_MAGIC && le16(sb->s_block_group_nr)>0 && recover_EXT2(disk_car, sb, partition, verbose, dump_ind)==0) res=1; } } } } test_nbr++; } if(res<=0 && test_nbr==6) { if(search_now==0) test_nbr=14; else { if(disk_car->pread(disk_car, buffer_disk0, 16 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 16 * DEFAULT_SECTOR_SIZE) res=search_type_2(buffer_disk0,disk_car,partition,verbose,dump_ind); else res=-1; test_nbr++; } } if(res<=0 && test_nbr==7) { if(res==0) res=search_type_1(buffer_disk0, disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==8) { if(res==0) res=search_type_0(buffer_disk0,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==9) { res=search_type_8(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==10) { /* Try to catch disklabel before BSD FFS partition */ res=search_type_16(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==11) { res=search_type_64(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==12) { /* read to fill the cache */ disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, partition->part_offset + (63 + 16) * 512); /* Try to catch disklabel before BSD FFS partition */ res=search_type_128(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==13) { res=search_type_2048(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(test_nbr>=14) { sector_inc=1; test_nbr=0; } if(res<0) { #ifdef HAVE_NCURSES wmove(stdscr,ANALYSE_Y+1,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,msg_READ_ERROR_AT, start.cylinder,start.head,start.sector,(unsigned long)(partition->part_offset/disk_car->sector_size)); #endif /* Stop reading after the end of the disk */ if(search_location >= disk_car->disk_real_size) search_location = search_location_max; } else if(res>0) { partition->status=STATUS_DELETED; log_partition(disk_car,partition); aff_part_buffer(AFF_PART_BASE, disk_car,partition); #ifdef HAVE_NCURSES screen_buffer_to_interface(); #endif if(disk_car->arch->is_part_known(partition)!=0 && partition->part_size>1 && partition->part_offset>=min_location) { const uint64_t pos_fin=partition->part_offset+partition->part_size-1; if(partition->upart_type!=UP_MD && partition->upart_type!=UP_MD1 && ind_stop==INDSTOP_CONTINUE) { /* Detect Linux md 0.9 software raid */ unsigned int disk_factor; for(disk_factor=6; disk_factor>=1;disk_factor--) { /* disk_factor=1, detect Raid 0/1 */ /* disk_factor>1, detect Raid 5 */ unsigned int help_factor; for(help_factor=0; help_factor<=MD_MAX_CHUNK_SIZE/MD_RESERVED_BYTES+3; help_factor++) { const uint64_t offset=(uint64_t)MD_NEW_SIZE_SECTORS((partition->part_size/disk_factor+help_factor*MD_RESERVED_BYTES-1)/MD_RESERVED_BYTES*MD_RESERVED_BYTES/512)*512; hint_insert(try_offset_raid, partition->part_offset+offset, &try_offset_raid_nbr); } } /* TODO: Detect Linux md 1.0 software raid */ } /* */ if(pos_fin <= search_location_max) { { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } { const uint64_t next_part_offset=partition->part_offset+partition->part_size-1+1; const uint64_t head_size=disk_car->geom.sectors_per_head * disk_car->sector_size; hint_insert(try_offset, next_part_offset, &try_offset_nbr); hint_insert(try_offset, next_part_offset+head_size, &try_offset_nbr); if(next_part_offset%head_size!=0) { hint_insert(try_offset, (next_part_offset+head_size-1)/head_size*head_size, &try_offset_nbr); hint_insert(try_offset, (next_part_offset+head_size-1)/head_size*head_size+head_size, &try_offset_nbr); } } if((fast_mode==0) && (partition->part_offset+partition->part_size-disk_car->sector_size > search_location)) { search_location=partition->part_offset+partition->part_size-disk_car->sector_size; test_nbr=0; sector_inc=1; } } else { { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); list_part_bad=insert_new_partition(list_part_bad, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } if(verbose>0) log_warning("This partition ends after the disk limits. (start=%llu, size=%llu, end=%llu, disk end=%llu)\n", (unsigned long long)(partition->part_offset/disk_car->sector_size), (unsigned long long)(partition->part_size/disk_car->sector_size), (unsigned long long)(pos_fin/disk_car->sector_size), (unsigned long long)(disk_car->disk_size/disk_car->sector_size)); else log_warning("This partition ends after the disk limits.\n"); } } else { if(verbose>0) { log_warning("Partition not added.\n"); } } partition_reset(partition, disk_car->arch); } } while(sector_inc==0); } if(ind_stop==INDSTOP_SKIP) { ind_stop=INDSTOP_CONTINUE; if(try_offset_nbr>0 && search_location < try_offset[0]) search_location=try_offset[0]; } else if(ind_stop==INDSTOP_STOP) { if(try_offset_nbr>0 && search_location < try_offset[0]) search_location=try_offset[0]; else ind_stop=INDSTOP_QUIT; } else { /* Optimized "search_location+=disk_car->sector_size;" */ uint64_t min=search_location_update(search_location); if(try_offset_nbr>0 && min>try_offset[0]) min=try_offset[0]; if(try_offset_raid_nbr>0 && min>try_offset_raid[0]) min=try_offset_raid[0]; if(min==(uint64_t)-1 || min<=search_location) search_location+=disk_car->sector_size; else search_location=min; } } /* Search for NTFS partition near the supposed partition beginning given by the NTFS backup boot sector */ if(fast_mode>0) search_NTFS_from_backup(disk_car, list_part, verbose, dump_ind, min_location, search_location_max); free(partition); if(ind_stop!=INDSTOP_CONTINUE) log_info("Search for partition aborted\n"); if(list_part_bad!=NULL) { interface_part_bad_log(disk_car,list_part_bad); #ifdef HAVE_NCURSES if(*current_cmd==NULL) interface_part_bad_ncurses(disk_car,list_part_bad); #endif } part_free_list(list_part_bad); free(buffer_disk0); free(buffer_disk); return list_part; }
int interface_recovery(disk_t *disk_car, const list_part_t * list_part_org, const int verbose, const int dump_ind, const int align, const int ask_part_order, const unsigned int expert, char **current_cmd) { int res_interface_write; int fast_mode=0; do { list_part_t *list_part; const list_part_t *element; unsigned int menu=0; if(fast_mode==0) menu=3; /* Search! */ #ifdef HAVE_NCURSES aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,5,0); #endif res_interface_write=0; list_part=search_part(disk_car, list_part_org, verbose, dump_ind, fast_mode, current_cmd); if(list_part!=NULL && (disk_car->arch==&arch_i386 || disk_car->arch==&arch_sun)) { /* Correct disk geometry is necessary for successfull Intel and Sun partition recovery */ const unsigned int heads_per_cylinder=get_geometry_from_list_part(disk_car, list_part, verbose); if(disk_car->geom.heads_per_cylinder!=heads_per_cylinder) { log_warning("Warning: the current number of heads per cylinder is %u but the correct value may be %u.\n", disk_car->geom.heads_per_cylinder, heads_per_cylinder); #ifdef HAVE_NCURSES if(*current_cmd==NULL) { warning_geometry_ncurses(disk_car, heads_per_cylinder); } #endif } } align_structure(list_part, disk_car, align); disk_car->arch->init_structure(disk_car,list_part,verbose); if(verbose>0) { #ifdef TARGET_LINUX unsigned int i=0; #endif /* Write found partitions in the log file */ log_info("\nResults\n"); for(element=list_part;element!=NULL;element=element->next) log_partition(disk_car,element->part); #ifdef TARGET_LINUX if(list_part!=NULL) log_info("\nHint for advanced users: dmsetup may be used if you prefer to avoid rewriting the partition table for the moment:\n"); for(element=list_part;element!=NULL;element=element->next) { const partition_t *partition=element->part; log_info("echo \"0 %llu linear %s %llu\" | dmsetup create test%u\n", (long long unsigned)(partition->part_size/512), disk_car->device, (long long unsigned)(partition->part_offset/512), i++); } #endif } do { list_part=ask_structure(disk_car,list_part,verbose,current_cmd); } while(fast_mode!=0 && list_part!=NULL && is_structure_empty(list_part) #ifdef HAVE_NCURSES && ask_confirmation("Discard the results, confirm ? (Y/N)")==0 #endif ); if(disk_car->arch->test_structure(list_part)==0) { int do_again=0; int max_ext=0; int can_ask_minmax_ext=0; int no_confirm=0; list_part=reduce_structure(list_part); /* sort list_part */ list_part=sort_partition_list(list_part); /* Create PC/Intel Extended partition */ /* if(disk_car->arch==&arch_i386) */ { list_part_t *parts; uint64_t partext_offset=0; uint64_t partext_size=0; list_part=add_ext_part_i386(disk_car, list_part, !max_ext, verbose); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status==STATUS_EXT) { partext_offset=parts->part->part_offset; partext_size=parts->part->part_size; } if(partext_offset>0) { list_part=add_ext_part_i386(disk_car, list_part, max_ext, verbose); for(parts=list_part;parts!=NULL;parts=parts->next) if(parts->part->status==STATUS_EXT) { if(partext_offset!=parts->part->part_offset || partext_size!=parts->part->part_size) can_ask_minmax_ext=1; } } } list_part=disk_car->arch->init_part_order(disk_car,list_part); if(ask_part_order!=0) { /* Demande l'ordre des entrees dans le MBR */ #ifdef HAVE_NCURSES ask_mbr_order_i386(disk_car,list_part); #endif /* Demande l'ordre des partitions etendues */ } do { do_again=0; res_interface_write=interface_write(disk_car,list_part,(fast_mode<1),can_ask_minmax_ext, &no_confirm, current_cmd,&menu); switch(res_interface_write) { case 'W': if(disk_car->arch == &arch_mac) { #ifdef HAVE_NCURSES write_part_mac_warning_ncurses(); #endif } else if(disk_car->arch == &arch_sun) { #ifdef HAVE_NCURSES not_implemented("write_part_sun"); #endif } else if(disk_car->arch == &arch_xbox) { #ifdef HAVE_NCURSES not_implemented("write_part_xbox"); #endif } else if(disk_car->arch->write_part!=NULL) { if(no_confirm!=0 #ifdef HAVE_NCURSES || ask_confirmation("Write partition table, confirm ? (Y/N)")!=0 #endif ) { log_info("write!\n"); if(disk_car->arch->write_part(disk_car, list_part, RW, verbose)) { display_message(msg_PART_WR_ERR); } else { use_backup(disk_car,list_part,verbose,dump_ind,expert,current_cmd); if(no_confirm==0) display_message("You will have to reboot for the change to take effect.\n"); } } else log_info("Don't write, no confirmation\n"); } break; case 0: if(disk_car->arch->write_part!=NULL) { log_info("simulate write!\n"); disk_car->arch->write_part(disk_car, list_part, RO, verbose); } break; case 'S': if(fast_mode<2) fast_mode++; break; case 'E': max_ext=!max_ext; list_part=add_ext_part_i386(disk_car, list_part, max_ext, verbose); do_again=1; break; } } while(do_again==1); } else { display_message("Invalid partition structure.\n"); } part_free_list(list_part); } while(res_interface_write=='S'); return 0; }
int exFAT_boot_sector(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd) { unsigned char *buffer_bs; unsigned char *buffer_backup_bs; const char *options=""; int rescan=1; #ifdef HAVE_NCURSES struct MenuItem menu_exFAT[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Quit","Return to Advanced menu"}, { 'O', "Org. BS","Copy superblock over backup sector"}, { 'B', "Backup BS","Copy backup superblock over superblock"}, { 'D', "Dump","Dump superblock and backup superblock"}, { 0, NULL, NULL } }; #endif buffer_bs=(unsigned char*)MALLOC(12 * disk->sector_size); buffer_backup_bs=(unsigned char*)MALLOC(12 * disk->sector_size); while(1) { #ifdef HAVE_NCURSES unsigned int menu=0; #endif int command; screen_buffer_reset(); if(rescan==1) { int opt_over=0; int opt_B=0; int opt_O=0; options="D"; #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, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) { screen_buffer_add("Bad: can't read exFAT boot record.\n"); memset(buffer_bs,0,12 * disk->sector_size); } else if(test_EXFAT((const struct exfat_super_block*)buffer_bs, partition)==0) { screen_buffer_add("exFAT OK\n"); opt_O=1; opt_over=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\nBackup boot record\n"); if(disk->pread(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) { screen_buffer_add("Bad: can't read exFAT backup boot record.\n"); memset(buffer_backup_bs,0,12 * disk->sector_size); } else if(test_EXFAT((const struct exfat_super_block*)buffer_backup_bs, partition)==0) { screen_buffer_add("exFAT OK\n"); opt_B=1; opt_over=1; } else screen_buffer_add("Bad\n"); screen_buffer_add("\n"); if(memcmp(buffer_bs,buffer_backup_bs,12 * disk->sector_size)==0) { screen_buffer_add("Sectors are identical.\n"); opt_over=0; } else { screen_buffer_add("Sectors are not identical.\n"); } if(opt_over!=0) { if(opt_B!=0 && opt_O!=0) options="DOB"; else if(opt_B!=0) options="DB"; else if(opt_O!=0) options="DO"; } rescan=0; } screen_buffer_to_log(); if(*current_cmd!=NULL) { command=0; while(*current_cmd[0]==',') (*current_cmd)++; if(strncmp(*current_cmd,"dump",4)==0) { (*current_cmd)+=4; command='D'; } else if(strncmp(*current_cmd,"originalexFAT",11)==0) { (*current_cmd)+=11; if(strchr(options,'O')!=NULL) command='O'; } else if(strncmp(*current_cmd,"backupexFAT",9)==0) { (*current_cmd)+=9; if(strchr(options,'B')!=NULL) command='B'; } } else { log_flush(); #ifdef HAVE_NCURSES command=screen_buffer_display_ext(stdscr, options, menu_exFAT, &menu); #else command=0; #endif } switch(command) { case 0: free(buffer_bs); free(buffer_backup_bs); return 0; case 'O': /* O : copy original superblock over backup boot */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy original exFAT boot record over backup, confirm ? (Y/N)")!=0) { log_info("copy original superblock over backup boot\n"); if(disk->pwrite(disk, buffer_bs, 12 * disk->sector_size, partition->part_offset + 12 * disk->sector_size) != 12 * disk->sector_size) { display_message("Write error: Can't overwrite exFAT backup boot record\n"); } disk->sync(disk); rescan=1; } #endif break; case 'B': /* B : copy backup superblock over main superblock */ #ifdef HAVE_NCURSES if(ask_confirmation("Copy backup exFAT boot record over main boot record, confirm ? (Y/N)")!=0) { log_info("copy backup superblock over main superblock\n"); /* Reset information about backup boot record */ partition->sb_offset=0; if(disk->pwrite(disk, buffer_backup_bs, 12 * disk->sector_size, partition->part_offset) != 12 * disk->sector_size) { display_message("Write error: Can't overwrite exFAT main boot record\n"); } disk->sync(disk); rescan=1; } #endif break; case 'D': exFAT_dump(disk, partition, buffer_bs, buffer_backup_bs, current_cmd); break; } } }
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); }
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; } } }