static void change_part_type_ncurses(const disk_t *disk_car,partition_t *partition) { partition_t *new_partition; char response[100]; int size=0; int i; unsigned int last[3], done = 0, next = 0; struct part_name_struct part_name[0x100]; struct MenuItem menuType[]= { { 'P', "Previous",""}, { 'N', "Next","" }, { 'Q', "Proceed","Go set the partition type"}, { 0, NULL, NULL } }; if(partition->arch->set_part_type==NULL) return ; /* Create an index of all partition type except Intel extended */ new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); for(i=0;i<=0xFF;i++) { if(partition->arch->set_part_type(new_partition,i)==0) { part_name[size].name=new_partition->arch->get_partition_typename(new_partition); if(part_name[size].name!=NULL) part_name[size++].index=i; } } free(new_partition); /* Display the list of partition type in 3 columns */ screen_buffer_reset(); screen_buffer_add("List of partition type\n"); for (i = 2; i >= 0; i--) last[2 - i] = done += (size + i - done) / (i + 1); i = done = 0; while (done < last[0]) { screen_buffer_add( "%02x %-20s%c", part_name[next].index, part_name[next].name,(i==2 ? '\n' : ' ')); next = last[i++] + done; if (i > 2 || next >= last[i]) { i = 0; next = ++done; } } /* Ask for the new partition type*/ aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); screen_buffer_display(stdscr,"",menuType); wmove(stdscr,LINES-2,0); wclrtoeol(stdscr); wprintw(stdscr,"New partition type [current %02x] ? ",partition->arch->get_part_type(partition)); if (get_string(stdscr, response, sizeof(response), NULL) > 0) { int tmp_val = strtol(response, NULL, 16); partition->arch->set_part_type(partition,tmp_val); } }
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; }
// quick sort new void quicksort_new(int *niz, int n) { int pi; if (n < 2) return; pi = partition_new(niz, n); quicksort_new(niz, pi); quicksort_new(niz + pi + 1, n - pi - 1); }
static void search_NTFS_from_backup(disk_t *disk_car, list_part_t *list_part, const int verbose, const int dump_ind, const uint64_t min_location, const uint64_t search_location_max) { unsigned char *buffer_disk; const list_part_t *element; partition_t *partition; buffer_disk=(unsigned char*)MALLOC(16*DEFAULT_SECTOR_SIZE); partition=partition_new(disk_car->arch); for(element=list_part;element!=NULL;element=element->next) { if(element->part->upart_type==UP_NTFS && element->part->sb_offset!=0) { unsigned int i; for(i=32;i>0;i--) { partition->part_size=(uint64_t)0; partition->part_offset=element->part->part_offset - i * disk_car->sector_size; if(disk_car->pread(disk_car, buffer_disk, DEFAULT_SECTOR_SIZE, partition->part_offset)==DEFAULT_SECTOR_SIZE) { if(recover_NTFS(disk_car, (const struct ntfs_boot_sector*)buffer_disk, partition, verbose, dump_ind, 0)==0) { partition->status=STATUS_DELETED; if(disk_car->arch->is_part_known(partition)!=0 && partition->part_size>1 && partition->part_offset >= min_location && partition->part_offset+partition->part_size-1 <= 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); } partition_reset(partition, disk_car->arch); } } } } } free(partition); free(buffer_disk); }
list_part_t *add_partition_gpt_cli(disk_t *disk_car,list_part_t *list_part, char **current_cmd) { partition_t *new_partition=partition_new(&arch_gpt); new_partition->part_offset=disk_car->sector_size; new_partition->part_size=disk_car->disk_size-new_partition->part_offset; while(*current_cmd[0]==',') (*current_cmd)++; while(1) { if(strncmp(*current_cmd,"s,",2)==0) { uint64_t part_offset; (*current_cmd)+=2; part_offset=new_partition->part_offset; new_partition->part_offset=(uint64_t)ask_number_cli( current_cmd, new_partition->part_offset/disk_car->sector_size, 1, (disk_car->disk_size-1)/disk_car->sector_size, "Enter the starting sector ") * (uint64_t)disk_car->sector_size; new_partition->part_size=new_partition->part_size + part_offset - new_partition->part_offset; } else if(strncmp(*current_cmd,"S,",2)==0) { (*current_cmd)+=2; new_partition->part_size=(uint64_t)ask_number_cli( current_cmd, (new_partition->part_offset+new_partition->part_size-1)/disk_car->sector_size, new_partition->part_offset/disk_car->sector_size, (disk_car->disk_size-1)/disk_car->sector_size, "Enter the ending sector ") * (uint64_t)disk_car->sector_size + disk_car->sector_size - new_partition->part_offset; } else if(strncmp(*current_cmd,"T,",2)==0) { (*current_cmd)+=2; change_part_type_cli(disk_car,new_partition,current_cmd); } else if(new_partition->part_size>0 && guid_cmp(new_partition->part_type_gpt, GPT_ENT_TYPE_UNUSED)!=0) { int insert_error=0; list_part_t *new_list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); if(insert_error>0) { free(new_partition); return new_list_part; } new_partition->status=STATUS_PRIM; if(test_structure_gpt(list_part)!=0) new_partition->status=STATUS_DELETED; return new_list_part; } else { free(new_partition); return list_part; } } }
list_part_t *read_part_gpt(disk_t *disk_car, const int verbose, const int saveheader) { struct gpt_hdr *gpt; struct gpt_ent* gpt_entries; list_part_t *new_list_part=NULL; unsigned int i; uint32_t gpt_entries_size; uint64_t gpt_entries_offset; gpt=(struct gpt_hdr*)MALLOC(disk_car->sector_size); screen_buffer_reset(); if((unsigned)disk_car->pread(disk_car, gpt, disk_car->sector_size, disk_car->sector_size) != disk_car->sector_size) { free(gpt); return NULL; } if(memcmp(gpt->hdr_sig, GPT_HDR_SIG, 8)!=0) { screen_buffer_add("Bad GPT partition, invalid signature.\n"); free(gpt); return NULL; } if(verbose>0) { log_info("hdr_size=%llu\n", (long long unsigned)le32(gpt->hdr_size)); log_info("hdr_lba_self=%llu\n", (long long unsigned)le64(gpt->hdr_lba_self)); log_info("hdr_lba_alt=%llu (expected %llu)\n", (long long unsigned)le64(gpt->hdr_lba_alt), (long long unsigned)((disk_car->disk_size-1)/disk_car->sector_size)); log_info("hdr_lba_start=%llu\n", (long long unsigned)le64(gpt->hdr_lba_start)); log_info("hdr_lba_end=%llu\n", (long long unsigned)le64(gpt->hdr_lba_end)); log_info("hdr_lba_table=%llu\n", (long long unsigned)le64(gpt->hdr_lba_table)); log_info("hdr_entries=%llu\n", (long long unsigned)le32(gpt->hdr_entries)); log_info("hdr_entsz=%llu\n", (long long unsigned)le32(gpt->hdr_entsz)); } /* Check header size */ if(le32(gpt->hdr_size)<92 || le32(gpt->hdr_size) > disk_car->sector_size) { screen_buffer_add("GPT: invalid header size.\n"); free(gpt); return NULL; } { /* CRC check */ uint32_t crc; uint32_t origcrc; origcrc=le32(gpt->hdr_crc_self); gpt->hdr_crc_self=le32(0); crc=get_crc32(gpt, le32(gpt->hdr_size), 0xFFFFFFFF)^0xFFFFFFFF; if(crc!=origcrc) { screen_buffer_add("Bad GPT partition, invalid header checksum.\n"); free(gpt); return NULL; } gpt->hdr_crc_self=le32(origcrc); } if(le64(gpt->hdr_lba_self)!=1) { screen_buffer_add("Bad GPT partition, invalid LBA self location.\n"); free(gpt); return NULL; } if(le64(gpt->hdr_lba_start) >= le64(gpt->hdr_lba_end)) { screen_buffer_add("Bad GPT partition, invalid LBA start/end location.\n"); free(gpt); return NULL; } if(le32(gpt->hdr_revision)!=GPT_HDR_REVISION) { screen_buffer_add("GPT: Warning - not revision 1.0\n"); } if(le32(gpt->__reserved)!=0) { screen_buffer_add("GPT: Warning - __reserved!=0\n"); } if(le32(gpt->hdr_entries)==0 || le32(gpt->hdr_entries)>4096) { screen_buffer_add("GPT: invalid number (%u) of partition entries.\n", (unsigned int)le32(gpt->hdr_entries)); free(gpt); return NULL; } /* le32(gpt->hdr_entsz)==128 */ if(le32(gpt->hdr_entsz)%8!=0 || le32(gpt->hdr_entsz)<128 || le32(gpt->hdr_entsz)>4096) { screen_buffer_add("GPT: invalid partition entry size.\n"); free(gpt); return NULL; } gpt_entries_size=le32(gpt->hdr_entries) * le32(gpt->hdr_entsz); if(gpt_entries_size<16384) { screen_buffer_add("GPT: A minimum of 16,384 bytes of space must be reserved for the GUID Partition Entry array.\n"); free(gpt); return NULL; } gpt_entries_offset=(uint64_t)le64(gpt->hdr_lba_table) * disk_car->sector_size; if((uint64_t) le64(gpt->hdr_lba_self) + le32(gpt->hdr_size) - 1 >= gpt_entries_offset || gpt_entries_offset >= le64(gpt->hdr_lba_start) * disk_car->sector_size) { screen_buffer_add( "GPT: The primary GUID Partition Entry array must be located after the primary GUID Partition Table Header and end before the FirstUsableLBA.\n"); free(gpt); return NULL; } gpt_entries=(struct gpt_ent*)MALLOC(gpt_entries_size); if((unsigned)disk_car->pread(disk_car, gpt_entries, gpt_entries_size, gpt_entries_offset) != gpt_entries_size) { free(gpt_entries); free(gpt); return new_list_part; } { /* CRC check */ uint32_t crc; crc=get_crc32(gpt_entries, gpt_entries_size, 0xFFFFFFFF)^0xFFFFFFFF; if(crc!=le32(gpt->hdr_crc_table)) { screen_buffer_add("Bad GPT partition entries, invalid checksum.\n"); free(gpt_entries); free(gpt); return NULL; } } for(i=0;i<le32(gpt->hdr_entries);i++) { const struct gpt_ent* gpt_entry; gpt_entry=(const struct gpt_ent*)((const char*)gpt_entries + (unsigned long)i*le32(gpt->hdr_entsz)); if(guid_cmp(gpt_entry->ent_type, GPT_ENT_TYPE_UNUSED)!=0 && le64(gpt_entry->ent_lba_start) < le64(gpt_entry->ent_lba_end)) { int insert_error=0; partition_t *new_partition=partition_new(&arch_gpt); new_partition->order=i+1; guid_cpy(&new_partition->part_uuid, &gpt_entry->ent_uuid); guid_cpy(&new_partition->part_type_gpt, &gpt_entry->ent_type); new_partition->part_offset=(uint64_t)le64(gpt_entry->ent_lba_start)*disk_car->sector_size; new_partition->part_size=(uint64_t)(le64(gpt_entry->ent_lba_end) - le64(gpt_entry->ent_lba_start)+1) * disk_car->sector_size; new_partition->status=STATUS_PRIM; UCSle2str(new_partition->partname, (const uint16_t *)&gpt_entry->ent_name, sizeof(gpt_entry->ent_name)/2); new_partition->arch->check_part(disk_car,verbose,new_partition,saveheader); /* log_debug("%u ent_attr %08llx\n", new_partition->order, (long long unsigned)le64(gpt_entry->ent_attr)); */ aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk_car,new_partition); new_list_part=insert_new_partition(new_list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } } /* TODO: The backup GUID Partition Entry array must be located after the LastUsableLBA and end before the backup GUID Partition Table Header. */ free(gpt_entries); free(gpt); return new_list_part; }
list_part_t *search_superblock(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, const int interface) { unsigned char *buffer=(unsigned char *)MALLOC(2*0x200); uint64_t hd_offset; int nbr_sb=0; list_part_t *list_part=NULL; int ind_stop=0; #ifdef HAVE_NCURSES unsigned long int old_percent=0; #endif struct ext2_super_block *sb=(struct ext2_super_block *)buffer; partition_t *new_partition=partition_new(disk_car->arch); log_trace("search_superblock\n"); #ifdef HAVE_NCURSES if(interface>0) { aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG); wmove(stdscr,6,0); aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr," Stop "); wattroff(stdscr, A_REVERSE); } #endif for(hd_offset=0;hd_offset<partition->part_size && nbr_sb<10 && ind_stop==0;hd_offset=next_sb(hd_offset)) { #ifdef HAVE_NCURSES unsigned long int percent; percent=hd_offset*100/partition->part_size; if(interface>0 && percent!=old_percent) { wmove(stdscr,9,0); wclrtoeol(stdscr); wprintw(stdscr,"Search ext2/ext3/ext4 superblock %10lu/%lu %lu%%", (long unsigned)(hd_offset/disk_car->sector_size), (long unsigned)(partition->part_size/disk_car->sector_size),percent); wrefresh(stdscr); ind_stop|=check_enter_key_or_s(stdscr); old_percent=percent; } #endif if(disk_car->pread(disk_car, buffer, 1024, partition->part_offset + hd_offset) == 1024) { /* ext2/ext3/ext4 */ if(le16(sb->s_magic)==EXT2_SUPER_MAGIC) { dup_partition_t(new_partition,partition); new_partition->part_offset+=hd_offset; if(recover_EXT2(disk_car,sb,new_partition,verbose,dump_ind)==0) { int insert_error=0; if(hd_offset<=(EXT2_MIN_BLOCK_SIZE<<2)) new_partition->part_offset-=hd_offset; if(partition->blocksize==0) { partition->sborg_offset=new_partition->sborg_offset; partition->sb_offset =new_partition->sb_offset; partition->sb_size =new_partition->sb_size; partition->blocksize =new_partition->blocksize; } log_info("Ext2 superblock found at sector %llu (block=%llu, blocksize=%u)\n", (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE, (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)), EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size)); #ifdef HAVE_NCURSES wmove(stdscr,10+nbr_sb,0); wprintw(stdscr,"Ext2 superblock found at sector %llu (block=%llu, blocksize=%u) \n", (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE, (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)), EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size)); #endif list_part=insert_new_partition(list_part, new_partition, 1, &insert_error); new_partition=partition_new(disk_car->arch); nbr_sb++; } } }
static list_part_t *read_part_none(disk_t *disk, const int verbose, const int saveheader) { int insert_error=0; unsigned char *buffer_disk; list_part_t *list_part; partition_t *partition; int res=0; partition=partition_new(&arch_none); buffer_disk=(unsigned char *)MALLOC(16*DEFAULT_SECTOR_SIZE); partition->part_size=disk->disk_size; if(recover_MD_from_partition(disk, partition, verbose)==0) res=1; else partition_reset(partition,&arch_none); if(res<=0) { if(disk->pread(disk, buffer_disk, 16 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 16 * DEFAULT_SECTOR_SIZE) res=search_type_2(buffer_disk, disk, partition,verbose,0); } if(res<=0) { res=search_type_1(buffer_disk, disk, partition,verbose,0); } if(res<=0) { res=search_type_0(buffer_disk, disk, partition,verbose,0); } if(res<=0) { res=search_type_8(buffer_disk, disk, partition,verbose,0); } if(res<=0) { if(disk->pread(disk, buffer_disk, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 16 * 512) == 3 * DEFAULT_SECTOR_SIZE) res=search_type_16(buffer_disk, disk, partition,verbose,0); } if(res<=0) { if(disk->pread(disk, buffer_disk, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 63 * 512) == 3 * DEFAULT_SECTOR_SIZE) res=search_type_64(buffer_disk, disk, partition,verbose,0); } if(res<=0) res=(recover_ISO((const struct iso_primary_descriptor*)(buffer_disk+0x200), partition)==0); if(res<=0) { /* 64k offset */ if(disk->pread(disk, buffer_disk, 11 * DEFAULT_SECTOR_SIZE, partition->part_offset + 126 * 512) == 11 * DEFAULT_SECTOR_SIZE) res=search_type_128(buffer_disk, disk, partition,verbose,0); } if(res<=0) { res=search_type_2048(buffer_disk, disk, partition,verbose,0); } if(res<=0) { /* Search FAT32 backup */ partition->part_offset = 6*512; res=search_FAT_backup(buffer_disk, disk, partition, verbose, 0); } if(res<=0) { /* Search exFAT backup */ partition->part_offset = 12 * disk->sector_size; res=search_EXFAT_backup(buffer_disk, disk, partition); } if(res<=0) { /* Search NTFS backup */ if(disk->disk_size > disk->sector_size) { partition->part_offset = disk->disk_size - disk->sector_size; res=search_NTFS_backup(buffer_disk, disk, partition, verbose, 0); if(res>0 && partition->part_offset!=0) res=0; } } if(res<=0) { int s_log_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(disk->pread(disk, buffer_disk, 1024, hd_offset)==1024) { const struct ext2_super_block *sb=(const struct ext2_super_block*)buffer_disk; partition->part_offset = hd_offset; if(le16(sb->s_block_group_nr)>0 && le16(sb->s_magic)==EXT2_SUPER_MAGIC && recover_EXT2(disk, sb, partition, 0, 0)==0) res=1; if(res>0 && partition->part_offset!=0) res=0; } } } free(buffer_disk); if(res<=0) partition_reset(partition,&arch_none); partition->part_offset=0; partition->part_size=disk->disk_size; partition->order=NO_ORDER; partition->status=STATUS_PRIM; screen_buffer_reset(); disk->arch->check_part(disk, verbose,partition,saveheader); aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk, partition); list_part=insert_new_partition(NULL, partition, 0, &insert_error); if(insert_error>0) free(partition); return list_part; }
/***************************************************** * Thread function that will attempt to sort locally */ void *parallel_qsort(void *arg_struct) { int st_idx, en_idx, rc; double median = 0; struct thread_data index_left, index_right; void *status; pthread_t first_thread; pthread_t second_thread; /* * Extract the thread args from the structure passed in */ struct thread_data *args; args = (struct thread_data *) arg_struct; st_idx = args->st_idx; en_idx = args->en_idx; if (en_idx > st_idx) { int N = en_idx - st_idx + 1; // Get number of // elements in // this array if (floor_log2(thread_count) < MAXDEPTH && N > floor_log2(MAXLEN)) { // If /* * 1. Pivot Selection Strategy */ median = select_pivot(st_idx, en_idx); // printf("Median chosen ---> %ld\n", median); /* * 2. Partition the data into subarrays lesser and greater * than pivot */ int pivot_index = partition_new(st_idx, en_idx, median); // partition_new( /* * Update the thread counter */ pthread_mutex_lock(&mutexthread); /* Lock Mutex */ thread_count += 2; ++real_thread_count; pthread_mutex_unlock(&mutexthread); /* Unlock Mutex */ /* * Fire the thread to sort the lesser than sub-array */ index_left.st_idx = st_idx; index_left.en_idx = pivot_index - 1; /* * Re-use current thread to sort the greater array ... so no * new thread creation */ index_right.st_idx = pivot_index + 1; index_right.en_idx = en_idx; // printf("****** Parallel Sorting now (%d,%d) and (%d,%d) N = // %d depth = %d\n", st_idx, pivot_index - 1, pivot_index + 1, // en_idx, N, floor_log2( thread_count ) ); /* * Now we have called a new thread to sort the lesser array */ rc = pthread_create(&first_thread, NULL, parallel_qsort, (void *) &index_left); rc = pthread_create(&second_thread, NULL, parallel_qsort, (void *) &index_right); pthread_join(first_thread, NULL); pthread_join(second_thread, NULL); } else { // printf("****** Serial Sorting now (%d,%d) N = %d depth = // %d\n", st_idx, en_idx, N, floor_log2( thread_count ) ); serial_quickSort(st_idx, en_idx); // Sort Serially the list } /* * void *pquick(void *arg){ ... pthread_t leftthr,rightthr; ... * * if (right > left){ if (recursionlev<MAXLEVELS) { ... * pthread_create(&leftthr, NULL, pquick, (void *) &leftarg); * pthread_create(&rightthr, NULL, pquick, (void *) &rightarg); * pthread_join(leftthr, NULL); pthread_join(rightthr, NULL); } * else { quicksort(left); // Serial quicksort quicksort(right); } * * } } */ } // End of main if /* * And... EXIT */ pthread_exit(NULL); }
static void change_part_type_ncurses2(const disk_t *disk_car, partition_t *partition) { partition_t *new_partition; unsigned int intr_nbr_line=0; unsigned int offset=0; unsigned int i; unsigned int current_element_num=0; struct part_name_struct part_name[0x100]; if(partition->arch->set_part_type==NULL) return ; aff_copy(stdscr); wmove(stdscr,4,0); aff_part(stdscr, AFF_PART_ORDER|AFF_PART_STATUS, disk_car, partition); wmove(stdscr,INTER_CHGTYPE_Y, INTER_CHGTYPE_X); wattrset(stdscr, A_REVERSE); wprintw(stdscr, "[ Proceed ]"); wattroff(stdscr, A_REVERSE); /* Create an index of all partition type except Intel extended */ new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); for(i=0;i<=0xFF;i++) { if(partition->arch->set_part_type(new_partition,i)==0) { part_name[intr_nbr_line].name=new_partition->arch->get_partition_typename(new_partition); if(part_name[intr_nbr_line].name!=NULL) { if(partition->arch->get_part_type(partition)==i) current_element_num=intr_nbr_line; part_name[intr_nbr_line++].index=i; } } } free(new_partition); while(1) { wmove(stdscr,5,0); wprintw(stdscr, "Please choose the partition type, press Enter when done."); wmove(stdscr,5+1,1); wclrtoeol(stdscr); if(offset>0) wprintw(stdscr, "Previous"); for(i=offset;i<intr_nbr_line && (i-offset)<3*INTER_CHGTYPE;i++) { if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,0); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,26); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,52); wclrtoeol(stdscr); /* before addstr for BSD compatibility */ if(i==current_element_num) { wattrset(stdscr, A_REVERSE); wprintw(stdscr,">%s", part_name[i].name); wattroff(stdscr, A_REVERSE); } else { wprintw(stdscr," %s", part_name[i].name); } } if(i-offset<INTER_CHGTYPE) wmove(stdscr,5+2+i-offset,1); else if(i-offset<2*INTER_CHGTYPE) wmove(stdscr,5+2+i-offset-INTER_CHGTYPE,27); else wmove(stdscr,5+2+i-offset-2*INTER_CHGTYPE,53); wclrtoeol(stdscr); if(i<intr_nbr_line) wprintw(stdscr, "Next"); switch(wgetch(stdscr)) { case 'p': case 'P': case KEY_UP: if(current_element_num>0) current_element_num--; break; case 'n': case 'N': case KEY_DOWN: if(current_element_num < intr_nbr_line-1) current_element_num++; break; case KEY_LEFT: if(current_element_num > INTER_CHGTYPE) current_element_num-=INTER_CHGTYPE; else current_element_num=0; break; case KEY_PPAGE: if(current_element_num > 3*INTER_CHGTYPE-1) current_element_num-=3*INTER_CHGTYPE-1; else current_element_num=0; break; case KEY_RIGHT: if(current_element_num+INTER_CHGTYPE < intr_nbr_line-1) current_element_num+=INTER_CHGTYPE; else current_element_num=intr_nbr_line-1; break; case KEY_NPAGE: if(current_element_num+3*INTER_CHGTYPE-1 < intr_nbr_line-1) current_element_num+=3*INTER_CHGTYPE-1; else current_element_num=intr_nbr_line-1; break; case 'Q': case 'q': case key_CR: #ifdef PADENTER case PADENTER: #endif partition->arch->set_part_type(partition, part_name[current_element_num].index); return; } if(current_element_num < offset) offset=current_element_num; if(current_element_num >= offset+3*INTER_CHGTYPE) offset=current_element_num-3*INTER_CHGTYPE+1; } }
static int write_part_gpt_i386(disk_t *disk_car, const list_part_t *list_part) { /* The Protective MBR has the same format as a legacy MBR. */ const list_part_t *element; list_part_t *list_part_i386=NULL; uint64_t efi_psize=disk_car->disk_size; partition_t *part_mac=NULL; partition_t *part_linux=NULL; partition_t *part_windows=NULL; for(element=list_part;element!=NULL;element=element->next) { if(part_mac==NULL && element->part->part_type_i386==P_HFS) part_mac=element->part; else if(part_linux==NULL && element->part->part_type_i386==P_LINUX) part_linux=element->part; else if(part_windows==NULL && element->part->part_type_i386==P_NTFS) part_windows=element->part; } if(part_mac!=NULL && (part_linux!=NULL || part_windows!=NULL)) { /* For bootcamp, the layout should be * 1 EFI * 2 MacOS X * 3 Linux if any * 4 Windows */ { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition, part_mac); new_partition->arch=&arch_i386; new_partition->status=STATUS_PRIM; new_partition->order=2; list_part_i386=insert_new_partition(list_part_i386, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); else if(efi_psize > new_partition->part_offset) efi_psize=new_partition->part_offset; } if(part_linux!=NULL) { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition, part_linux); new_partition->arch=&arch_i386; new_partition->status=STATUS_PRIM; new_partition->order=3; list_part_i386=insert_new_partition(list_part_i386, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); else if(efi_psize > new_partition->part_offset) efi_psize=new_partition->part_offset; } if(part_windows!=NULL) { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition, part_windows); new_partition->arch=&arch_i386; new_partition->status=STATUS_PRIM; new_partition->order=4; list_part_i386=insert_new_partition(list_part_i386, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); else if(efi_psize > new_partition->part_offset) efi_psize=new_partition->part_offset; } { int insert_error=0; partition_t *new_partition=partition_new(&arch_i386); new_partition->status=STATUS_PRIM; new_partition->order=1; new_partition->part_type_i386=0xee; new_partition->part_offset=disk_car->sector_size; new_partition->part_size=efi_psize - new_partition->part_offset; list_part_i386=insert_new_partition(list_part_i386, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } } else { /* The Protective MBR contains one partition entry of OS type 0xEE and * reserves the entire space used on the disk by the GPT partitions, * including all headers. */ int insert_error=0; partition_t *new_partition=partition_new(&arch_i386); new_partition->status=STATUS_PRIM; new_partition->order=1; new_partition->part_type_i386=0xee; new_partition->part_offset=disk_car->sector_size; new_partition->part_size=disk_car->disk_size - new_partition->part_offset; list_part_i386=insert_new_partition(list_part_i386, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } arch_i386.write_part(disk_car, list_part_i386, 0, 0); part_free_list(list_part_i386); return 0; }
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; }
static list_part_t *add_ext_part_i386(disk_t *disk, list_part_t *list_part, const int max_ext, const int verbose) { /* list_part need to be sorted! */ /* All extended partitions of an P_EXTENDX are P_EXTENDED */ int insert_error=0; list_part_t *element; list_part_t *deb=NULL; list_part_t *fin=NULL; int nbr_entries=0; partition_t *new_partition; unsigned int order=0; uint64_t part_extended_offset=0; uint64_t part_extended_end=0; for(element=list_part;element!=NULL;) { if(element->part->status==STATUS_EXT) { /* remove already existing extended partition */ list_part_t *next=element->next; if(element->prev!=NULL) element->prev->next=element->next; if(element->next!=NULL) element->next->prev=element->prev; order=element->part->order; if(element==list_part) list_part=next; free(element->part); free(element); element=next; } else { if(element->part->status==STATUS_LOG) { if(deb==NULL) { deb=element; nbr_entries++; } fin=element; } else nbr_entries++; element=element->next; } } if(deb==NULL) return list_part; if(nbr_entries==4 || max_ext!=0) { if(verbose>0) { log_info("add_ext_part_i386: max\n"); } if(deb->prev==NULL) { uint64_t tmp; part_extended_offset=deb->part->part_offset - disk->sector_size; if(deb->part->part_offset%(1024*1024)==0) tmp=1024*1024; else tmp=(uint64_t)disk->geom.sectors_per_head * disk->sector_size; if(tmp < part_extended_offset) part_extended_offset=tmp; } else { uint64_t tmp; part_extended_offset=deb->prev->part->part_offset + deb->prev->part->part_size; /* round up part_extended_offset */ if(deb->part->part_offset%(1024*1024)==0) { tmp=(part_extended_offset+1024*1024-1)/(1024*1024)*(1024*1024); } else { CHS_t start; start.cylinder=offset2cylinder(disk, part_extended_offset-1)+1; start.head=0; start.sector=1; tmp=CHS2offset_inline(disk, &start); } if(tmp < deb->part->part_offset && (deb->prev==NULL || tmp >= deb->prev->part->part_offset + deb->prev->part->part_size)) part_extended_offset=tmp; } if(fin->next==NULL) { part_extended_end=fin->part->part_offset + fin->part->part_size - disk->sector_size; /* In some weird cases, a partition may end after the end of the disk */ if(part_extended_end < disk->disk_size - disk->sector_size) part_extended_end=disk->disk_size - disk->sector_size; } else part_extended_end=fin->next->part->part_offset - disk->sector_size; /* round down part_extended_end */ if(part_extended_offset%(1024*1024)==0) { const uint64_t tmp=part_extended_end/(1024*1024)*(1024*1024) - disk->sector_size; if(fin->part->part_offset + fin->part->part_size - disk->sector_size <= tmp) part_extended_end=tmp; } else { uint64_t tmp; CHS_t end; end.cylinder=offset2cylinder(disk, part_extended_end)-1; end.head=disk->geom.heads_per_cylinder-1; end.sector=disk->geom.sectors_per_head; tmp=CHS2offset_inline(disk, &end); if(fin->part->part_offset + fin->part->part_size - disk->sector_size <= tmp) part_extended_end=tmp; } } else { uint64_t tmp; if(verbose>0) { log_info("add_ext_part_i386: min\n"); } part_extended_offset=deb->part->part_offset - disk->sector_size; /* round down part_extended_offset */ if(deb->part->part_offset%(1024*1024)==0) { tmp=part_extended_offset/(1024*1024)*(1024*1024); } else { CHS_t start; start.cylinder=offset2cylinder(disk, part_extended_offset); if(start.cylinder==0) start.head=1; else start.head=0; start.sector=1; tmp=CHS2offset_inline(disk, &start); } if(tmp > 0 && tmp < deb->part->part_offset && (deb->prev==NULL || tmp >= deb->prev->part->part_offset + deb->prev->part->part_size)) part_extended_offset=tmp; part_extended_end=fin->part->part_offset + fin->part->part_size - disk->sector_size; /* round up part_extended_end */ if(part_extended_offset%(1024*1024)==0) { tmp=(part_extended_end+1024*1024-1)/(1024*1024)*(1024*1024) - disk->sector_size; } else { CHS_t end; offset2CHS_inline(disk, part_extended_end, &end); end.head=disk->geom.heads_per_cylinder-1; end.sector=disk->geom.sectors_per_head; tmp=CHS2offset_inline(disk, &end); } if(tmp < disk->disk_size) part_extended_end=tmp; } new_partition=partition_new(disk->arch); new_partition->order=order; new_partition->part_type_i386=(offset2cylinder(disk, part_extended_end) > 1023?P_EXTENDX:P_EXTENDED); new_partition->status=STATUS_EXT; new_partition->part_offset=part_extended_offset; new_partition->part_size=part_extended_end - new_partition->part_offset + disk->sector_size; list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); return list_part; }
backup_disk_t *partition_load(const disk_t *disk_car, const int verbose) { FILE *f_backup; char *buffer; char *pos=NULL; int taille; backup_disk_t *new_backup=NULL; backup_disk_t *list_backup; list_backup=(backup_disk_t*)MALLOC(sizeof(*list_backup)); list_backup->list.prev= &list_backup->list; list_backup->list.next = &list_backup->list; if(verbose>1) { log_trace("partition_load\n"); } f_backup=fopen("backup.log","r"); if(!f_backup) { log_error("Can't open backup.log file: %s\n",strerror(errno)); return list_backup; } buffer=(char *)MALLOC(BACKUP_MAXSIZE); taille=fread(buffer,1,BACKUP_MAXSIZE,f_backup); buffer[(taille<BACKUP_MAXSIZE?taille:BACKUP_MAXSIZE-1)]='\0'; if(verbose>1) { log_info("partition_load backup.log size=%d\n",taille); } for(pos=buffer;pos<buffer+taille;pos++) { if(*pos=='\n') { *pos='\0'; } } pos=buffer; while(pos!=NULL && pos<buffer+taille) { if(*pos=='#') { pos++; if(verbose>1) { log_verbose("new disk: %s\n",pos); } if(new_backup!=NULL) td_list_add_tail(&new_backup->list,&list_backup->list); new_backup=(backup_disk_t*)MALLOC(sizeof(*new_backup)); new_backup->description[0]='\0'; new_backup->list_part=NULL; new_backup->my_time=strtol(pos,&pos,10); if(pos!=NULL) { strncpy(new_backup->description,++pos,sizeof(new_backup->description)); new_backup->description[sizeof(new_backup->description)-1]='\0'; } } else if(new_backup!=NULL) { partition_t *new_partition=partition_new(disk_car->arch); char status; unsigned int part_type; unsigned long part_size; unsigned long part_offset; if(verbose>1) { log_verbose("new partition\n"); } if(sscanf(pos,"%2u : start=%10lu, size=%10lu, Id=%02X, %c\n", &new_partition->order, &part_offset, &part_size,&part_type,&status)==5) { new_partition->part_offset=(uint64_t)part_offset*disk_car->sector_size; new_partition->part_size=(uint64_t)part_size*disk_car->sector_size; if(disk_car->arch->set_part_type!=NULL) disk_car->arch->set_part_type(new_partition,part_type); switch(status) { case 'P': new_partition->status=STATUS_PRIM; break; case '*': new_partition->status=STATUS_PRIM_BOOT; break; case 'L': new_partition->status=STATUS_LOG; break; default: new_partition->status=STATUS_DELETED; break; } { int insert_error=0; new_backup->list_part=insert_new_partition(new_backup->list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } } else { log_critical("partition_load: sscanf failed\n"); free(new_partition); pos=NULL; } } if(pos!=NULL) { while(*pos!='\0' && pos<buffer+taille) pos++; pos++; } } if(new_backup!=NULL) td_list_add_tail(&new_backup->list,&list_backup->list); fclose(f_backup); free(buffer); return list_backup; }
list_part_t *add_partition_gpt_ncurses(disk_t *disk_car,list_part_t *list_part, char **current_cmd) { int position=0; int done = FALSE; partition_t *new_partition=partition_new(&arch_gpt); new_partition->part_offset=disk_car->sector_size; new_partition->part_size=disk_car->disk_size-disk_car->sector_size; while (done==FALSE) { int command; static struct MenuItem menuGeometry[]= { { 's', "Sector", "Change starting sector" }, { 'S', "Sector", "Change ending sector" }, { 'T' ,"Type", "Change partition type"}, { 'd', "Done", "" }, { 0, NULL, NULL } }; aff_copy(stdscr); wmove(stdscr,4,0); wprintw(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,10, 0); wclrtoeol(stdscr); aff_part(stdscr, AFF_PART_BASE, disk_car, new_partition); wmove(stdscr,INTER_GEOM_Y, INTER_GEOM_X); wclrtoeol(stdscr); wrefresh(stdscr); command=wmenuSimple(stdscr,menuGeometry, position); switch (command) { case 's': { uint64_t part_offset; part_offset=new_partition->part_offset; wmove(stdscr, INTER_GEOM_Y, INTER_GEOM_X); new_partition->part_offset=(uint64_t)ask_number( new_partition->part_offset/disk_car->sector_size, 1, (disk_car->disk_size-1)/disk_car->sector_size, "Enter the starting sector ") * (uint64_t)disk_car->sector_size; new_partition->part_size=new_partition->part_size + part_offset - new_partition->part_offset; position=1; } break; case 'S': wmove(stdscr, INTER_GEOM_Y, INTER_GEOM_X); new_partition->part_size=(uint64_t)ask_number( (new_partition->part_offset+new_partition->part_size-1)/disk_car->sector_size, new_partition->part_offset/disk_car->sector_size, (disk_car->disk_size-1)/disk_car->sector_size, "Enter the ending sector ") * (uint64_t)disk_car->sector_size + disk_car->sector_size - new_partition->part_offset; position=2; break; case 'T': case 't': change_part_type(disk_car,new_partition, current_cmd); position=3; break; case key_ESC: case 'd': case 'D': case 'q': case 'Q': done = TRUE; break; } } if(new_partition->part_size>0 && guid_cmp(new_partition->part_type_gpt, GPT_ENT_TYPE_UNUSED)!=0) { int insert_error=0; list_part_t *new_list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); if(insert_error>0) { free(new_partition); return new_list_part; } new_partition->status=STATUS_PRIM; if(arch_gpt.test_structure(list_part)!=0) new_partition->status=STATUS_DELETED; return new_list_part; } free(new_partition); return list_part; }