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; }
fx_rtn fx_init(void) { boot_sector_t *bs; info_sector_t *info; mbr_t *mbr; u32_t start, size; assert(fx_buf); assert(! ms_read_blk(0, fx_buf)); /* First sector is either an MBR or the boot_sector of the partition. It * had better have the 2 byte signature at the end. ie. 0xaa55. * * Start by looking for a boot sector rather than the MBR. */ bs = fx_buf; if (bs->sig != CT_LE_16(BOOT_SIG)) return(FX_BAD_BOOT_SIG); start = fx_data_start = 0; if ( ! fat32_boot_sector(bs)) { /* * something doesn't look right. Look at the sector as an MBR and see * if it makes sense. We only look at partition 1. */ mbr = fx_buf; start = (mbr->p1.start4[3] << 24) | (mbr->p1.start4[2] << 16) | (mbr->p1.start4[1] << 8) | mbr->p1.start4[0]; size = (mbr->p1.size4[3] << 24) | (mbr->p1.size4[2] << 16) | (mbr->p1.size4[1] << 8 ) | mbr->p1.size4[0]; /* check for reasonableness, boot_ind can be 0x00 or 0x80 */ if ((mbr->p1.boot_ind != 0 && mbr->p1.boot_ind != 0x80) || !fat32_part(mbr->p1.part_type) || /* reasonable fat32 partition? */ start == 0 || /* can't start at 0 */ size == 0) /* zero means nothing, bail */ return(FX_NO_PARTITION); assert(! ms_read_blk(start, fx_buf)); bs = fx_buf; if (CF_LE_16(bs->sig) != BOOT_SIG) return(FX_BAD_BOOT_SIG); if (!fat32_boot_sector(bs)) /* make sure what we got is good */ return(FX_NO_PARTITION); /* check mbr partition size vs. total_sect entry in the file system header only accept if the same or if file system size is one less than the partition header */ if (size != CF_LE_32(bs->total_sect)) { /* and partition size should match internal */ if (debug) printf("*** mbr/fs size mismatch: mbr: %lu (%lx), fs: %lu (%lx)\n", size, size, CF_LE_32(bs->total_sect), CF_LE_32(bs->total_sect)); if (size != CF_LE_32(bs->total_sect) + 1) return(FX_SIZE_MISMATCH); } fx_data_start = start; } if (debug) printf("Partition start: %lx, size: %lx\n", (u32_t) fx_data_start, CF_LE_32(bs->total_sect)); /* buf contains the boot_sector. compute total data sectors and make sure that it conforms to FAT32. */ fx_cluster_size = bs->cluster_size; /* u8 */ fx_reserved = CF_LE_16(bs->reserved); fx_num_fats = bs->fats; /* u8 */ fx_total_sectors = CF_LE_32(bs->total_sect); fx_fat_size = CF_LE_32(bs->fat32_length); fx_info_sector = start + CF_LE_16(bs->info_sector); fx_data_end = fx_data_start + fx_total_sectors - 1; fx_fat_start = fx_data_start + fx_reserved; fx_fat_end = fx_fat_start + fx_fat_size - 1; fx_data_start = fx_fat_start + fx_fat_size * FX_NUM_FATS; size = fx_total_sectors; size -= (fx_reserved + (fx_fat_size * fx_num_fats)); fx_max_cluster = size/fx_cluster_size; /* last cluster */ if (debug) printf("phys data sectors: %lx, phys clusters: %lx, unused sectors: %lx\n", size, fx_max_cluster, size - fx_max_cluster * fx_cluster_size); if (fx_max_cluster < 65525) /* if less, not FAT32 */ return(FX_NOT_FAT32); fx_max_cluster++; /* make into cluster id */ fx_data_end = clu2sec(fx_max_cluster + 1) - 1; /* get last usable data sector */ if (fx_cluster_size != FX_CLUSTER_SIZE) fprintf(stderr, "*** bad fx_cluster_size (%u) should be (%u)\n", fx_cluster_size, FX_CLUSTER_SIZE); if (fx_num_fats != FX_NUM_FATS) fprintf(stderr, "*** wrong number of FATS: (%u) should be (%u)\n", fx_num_fats, FX_NUM_FATS); f32_get_chain(CF_LE_32(bs->root_cluster), &fx_rdir_start, &fx_rdir_end); assert(fx_rdir_start && fx_rdir_end); assert(!ms_read_blk(fx_info_sector, fx_buf)); info = fx_buf; if (info->boot_sig == CT_LE_16(BOOT_SIG) && IS_FSINFO(info)) { fx_free_clusters = CF_LE_32(info->free_clusters); fx_next_cluster = CF_LE_32(info->next_cluster); } else { fx_info_sector = 0; fx_free_clusters = (u32_t) -1; fx_next_cluster = (u32_t) -1; } if (debug) { printf("ts: %lx, r: %x, fat_s: %lx, n: %d, ds: %lx\n", fx_total_sectors, fx_reserved, fx_fat_size, fx_num_fats, fx_total_sectors-fx_reserved-(fx_num_fats*fx_fat_size)); printf("fat_size (secs): %lx, (clus) %lx, %lx bytes\n", fx_fat_size, fx_fat_size * SECTOR_SIZE / sizeof(u32_t), fx_fat_size * SECTOR_SIZE); printf("data_start: %lx, end: %lx, usable sectors: %lx, last phys sector: %lx\n", fx_data_start, fx_data_end, fx_data_end - fx_data_start + 1, /* usable */ fx_data_start + (fx_total_sectors - fx_reserved - (fx_num_fats * fx_fat_size)) - 1); printf("unused fat entries: %lx, cluster ids: 2 - %lx\n", (fx_fat_end - fx_fat_start + 1) * FAT32_CPB - (fx_max_cluster + 1), fx_max_cluster); printf("Last cluster: %lx, sectors: %lx - %lx, fat sector: %lx, off: %lx\n", fx_max_cluster, clu2sec(fx_max_cluster), clu2sec(fx_max_cluster + 1) - 1, FAT_SECTOR(fx_max_cluster) + fx_fat_start, FAT_OFFSET(fx_max_cluster)); printf(" fat_start: %5lx, fat_end: %5lx\n", fx_fat_start, fx_fat_end); printf(" info: free %5lx, next: %5lx\n", fx_free_clusters, fx_next_cluster); } return(FX_OK); }
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 } }