Пример #1
0
static void init_structure_gpt(const disk_t *disk_car,list_part_t *list_part, const int verbose)
{
  list_part_t *element;
  list_part_t *new_list_part=NULL;
  /* Create new list */
  for(element=list_part;element!=NULL;element=element->next)
    element->to_be_removed=0;
  for(element=list_part;element!=NULL;element=element->next)
  {
    int insert_error=0;
    list_part_t *element2;
    for(element2=element->next;element2!=NULL;element2=element2->next)
    {
      if(element->part->part_offset+element->part->part_size-1 >= element2->part->part_offset)
      {
        element->to_be_removed=1;
        element2->to_be_removed=1;
      }
    }
    if(element->to_be_removed==0)
      new_list_part=insert_new_partition(new_list_part, element->part, 0, &insert_error);
  }
    for(element=new_list_part;element!=NULL;element=element->next)
      element->part->status=STATUS_PRIM;
  if(disk_car->arch->test_structure(new_list_part))
  {
    for(element=new_list_part;element!=NULL;element=element->next)
      element->part->status=STATUS_DELETED;
  }
  part_free_list_only(new_list_part);
}
Пример #2
0
list_part_t *gen_sorted_partition_list(const list_part_t *list_part)
{
  list_part_t *new_list_part=NULL;
  const list_part_t *element;
  for(element=list_part;element!=NULL;element=element->next)
  {
    int insert_error=0;
    if(element->part->status!=STATUS_DELETED)
      new_list_part=insert_new_partition(new_list_part, element->part, 1, &insert_error);
  }
  return new_list_part;
}
Пример #3
0
list_part_t *sort_partition_list(list_part_t *list_part)
{
  list_part_t *new_list_part=NULL;
  list_part_t *element;
  list_part_t *next;
  for(element=list_part;element!=NULL;element=next)
  {
    int insert_error=0;
    next=element->next;
    new_list_part=insert_new_partition(new_list_part, element->part, 0, &insert_error);
    if(insert_error>0)
      free(element->part);
    free(element);
  }
  return new_list_part;
}
Пример #4
0
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);
}
Пример #5
0
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;
    }
  }
}
Пример #6
0
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;
}
Пример #7
0
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++;
	}
      }
    }
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
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;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}