Exemplo n.º 1
0
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);
  }
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
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++;
	}
      }
    }
Exemplo n.º 4
0
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;
  }
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}