Ejemplo n.º 1
0
static int check_part_gpt(disk_t *disk, const int verbose,partition_t *partition, const int saveheader)
{
  int ret=0;
  unsigned int old_levels;
  old_levels=log_set_levels(0);
  if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MS_BASIC_DATA)==0 ||
      guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MS_RESERVED)==0)
  {
    ret=check_FAT(disk,partition,verbose);
    if(ret!=0)
      ret=check_EXFAT(disk, partition);
    if(ret!=0)
      ret=check_NTFS(disk,partition,verbose,0);
    if(ret!=0)
      ret=check_ReFS(disk, partition);
    if(ret!=0)
      ret=check_linux(disk, partition, verbose);
    if(ret!=0)
      screen_buffer_add("No FAT, NTFS, ext2, JFS, Reiser, cramfs or XFS marker\n"); 
  }
  else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_LINUX_RAID)==0)
  {
    ret=check_MD(disk, partition, verbose);
    if(ret!=0)
      screen_buffer_add("Invalid RAID superblock\n");
  }
  else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_LINUX_LVM)==0)
  {
    ret=check_LVM(disk, partition, verbose);
    if(ret!=0)
      ret=check_LVM2(disk, partition, verbose);
    if(ret!=0)
      screen_buffer_add("No LVM or LVM2 structure\n");
  }
  else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MAC_HFS)==0)
  {
    ret=check_HFS(disk, partition, verbose);
    if(ret!=0)
      ret=check_HFSP(disk, partition, verbose);
    if(ret!=0)
      screen_buffer_add("No HFS or HFS+ structure\n");
  }
  log_set_levels(old_levels);
  if(ret!=0)
  {
    log_error("check_part_gpt failed for partition\n");
    log_partition(disk, partition);
    aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk,partition);
    if(saveheader>0)
    {
      save_header(disk, partition, verbose);
    }
  }
  return ret;
}
Ejemplo n.º 2
0
int repair_MFT(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int expert, char **current_cmd)
{
  struct ntfs_boot_sector *ntfs_header;
  unsigned char *buffer_mft;
  unsigned char *buffer_mftmirr;
  unsigned int cluster_size;
  unsigned int mft_record_size;
  unsigned int mftmirr_size_bytes;
  unsigned int use_MFT=0;
  /* 0: do nothing
   * 1: fix MFT mirror using MFT
   * 2: fix MFT using MFT mirror */
  uint64_t mft_pos;
  uint64_t mftmirr_pos;
  log_trace("repair_MFT\n");
  if(check_NTFS(disk_car, partition, verbose, 0)!=0)
  {
    display_message("Boot sector not valid, can't repair MFT.\n");
    return -1;
  }
  ntfs_header=(struct ntfs_boot_sector *)MALLOC(DEFAULT_SECTOR_SIZE);
  if(disk_car->pread(disk_car, ntfs_header, DEFAULT_SECTOR_SIZE, partition->part_offset) != DEFAULT_SECTOR_SIZE)
  {
    free(ntfs_header);
    display_message("Can't read NTFS boot sector.\n");
    return -1;
  }
  mft_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mft_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header);
  mftmirr_pos=partition->part_offset+(uint64_t)(le16(ntfs_header->reserved)+le64(ntfs_header->mftmirr_lcn)*ntfs_header->sectors_per_cluster)*ntfs_sector_size(ntfs_header);
  if(ntfs_header->clusters_per_mft_record>0)
    mft_record_size=ntfs_header->sectors_per_cluster*ntfs_header->clusters_per_mft_record;
  else
    mft_record_size=1<<(-ntfs_header->clusters_per_mft_record);

  cluster_size=ntfs_header->sectors_per_cluster;

  mftmirr_size_bytes = (cluster_size <= 4 * mft_record_size ? 4 * mft_record_size : cluster_size) * ntfs_sector_size(ntfs_header);
#ifdef DEBUG_REPAIR_MFT
  log_debug("mft_pos %lu\n",(unsigned long)(mft_pos/disk_car->sector_size));
  log_debug("mftmirr_pos %lu\n",(unsigned long)(mftmirr_pos/disk_car->sector_size));
  log_debug("cluster_size %u\n", cluster_size);
  log_debug("mft_record_size    %u\n", mft_record_size);
  log_debug("ntfs_sector_size   %u\n", ntfs_sector_size(ntfs_header));
  log_debug("mftmirr_size_bytes %u\n", mftmirr_size_bytes);
#endif
  if(mftmirr_size_bytes==0)
  {
    display_message("Invalid NTFS MFT size.\n");
    log_error("Invalid NTFS MFT size.\n");
    free(ntfs_header);
    return -1;
  }
  /* Check if MFT mirror is identical to the beginning of MFT */
  buffer_mft=(unsigned char *)MALLOC(mftmirr_size_bytes);
  if((unsigned)disk_car->pread(disk_car, buffer_mft, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes)
  {
    display_message("Can't read NTFS MFT.\n");
    log_error("Can't read NTFS MFT.\n");
    free(buffer_mft);
    free(ntfs_header);
    return -1;
  }
  buffer_mftmirr=(unsigned char *)MALLOC(mftmirr_size_bytes);
  if((unsigned)disk_car->pread(disk_car, buffer_mftmirr, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes)
  {
    display_message("Can't read NTFS MFT mirror.\n");
    log_error("Can't read NTFS MFT mirror.\n");
    free(buffer_mftmirr);
    free(buffer_mft);
    free(ntfs_header);
    return -1;
  }
  if(memcmp(buffer_mft, buffer_mftmirr, mftmirr_size_bytes)==0)
  {
    log_info("MFT and MFT mirror match perfectly.\n");
    if(*current_cmd==NULL)
      display_message("MFT and MFT mirror match perfectly.\n");
    free(buffer_mftmirr);
    free(buffer_mft);
    free(ntfs_header);
    return 0;
  }
  if(partition->sb_offset!=0)
  {
    log_info("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n");
    display_message("Please quit TestDisk and reboot your computer before trying to fix the MFT.\n");
    free(buffer_mftmirr);
    free(buffer_mft);
    free(ntfs_header);
    return -1;
  }
/*
  log_debug("MFT\n");
  dump_log(buffer_mft, mftmirr_size_bytes);
  log_debug("MFT mirror\n");
  dump_log(buffer_mftmirr, mftmirr_size_bytes);
  */
  /*
  The idea is to use the internal IO redirector built-in TestDisk
  to redirect read access to the MFT to the MFT backup instead (or
  vice-versa) when listing the NTFS files. If TestDisk can get
  a file listing, it also knows which MFT to use.
  */
  {
    int res1,res2;
    dir_data_t dir_data;
    /* Use MFT */
    io_redir_add_redir(disk_car, mftmirr_pos, mftmirr_size_bytes, 0, buffer_mft);
    res1=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose);
    if(res1==DIR_PART_ENOSYS)
    {
	display_message("Can't determine which MFT is correct, ntfslib is missing.\n");
	log_error("Can't determine which MFT is correct, ntfslib is missing.\n");
	free(buffer_mftmirr);
	free(buffer_mft);
	free(ntfs_header);
	io_redir_del_redir(disk_car,mftmirr_pos);
	return 0;
    }
    if(res1==DIR_PART_OK)
    {
      file_info_t dir_list;
      TD_INIT_LIST_HEAD(&dir_list.list);
      dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list);
      if(!td_list_empty(&dir_list.list))
      {
	log_info("NTFS listing using MFT:\n");
	dir_aff_log(&dir_data, &dir_list);
	if(delete_list_file(&dir_list)>2)
	  res1++;
      }
      dir_data.close(&dir_data);
    }
    io_redir_del_redir(disk_car,mftmirr_pos);
    /* Use MFT mirror */
    io_redir_add_redir(disk_car, mft_pos, mftmirr_size_bytes, 0, buffer_mftmirr);
    res2=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose);
    if(res2==DIR_PART_OK)
    {
      file_info_t dir_list;
      TD_INIT_LIST_HEAD(&dir_list.list);
      dir_data.get_dir(disk_car,partition,&dir_data,dir_data.current_inode, &dir_list);
      if(!td_list_empty(&dir_list.list))
      {
	log_info("NTFS listing using MFT mirror:\n");
	dir_aff_log(&dir_data, &dir_list);
	if(delete_list_file(&dir_list)>2)
	  res2++;
      }
      dir_data.close(&dir_data);
    }
    io_redir_del_redir(disk_car,mft_pos);
    /* */
    if(res1>res2 && res1>DIR_PART_OK)
    {
      /* Use MFT */
#ifdef HAVE_NCURSES
      if(ask_confirmation("Fix MFT mirror using MFT ? (Y/N)")!=0)
	use_MFT=1;
      else
#endif
	log_info("Don't fix MFT mirror.\n");
    }
    else if(res1<res2 && res2>DIR_PART_OK)
    {
      /* Use MFT mirror */
#ifdef HAVE_NCURSES
      if(ask_confirmation("Fix MFT using its mirror ? (Y/N) - DANGEROUS NON REVERSIBLE OPERATION\nUse it ONLY IF Windows failed to access this filesystem.")!=0)
	use_MFT=2;
      else
#endif
	log_info("Don't fix MFT.\n");
    }
    else
    { /* res1==res2 */
      if(res1>DIR_PART_OK && res2>DIR_PART_OK)
	log_error("Both MFT seems ok but they don't match, use chkdsk.\n");
      else
	log_error("MFT and MFT mirror are bad. Failed to repair them.\n");
      if(expert==0)
      {
	if(res1>DIR_PART_OK && res2>DIR_PART_OK)
	  display_message("Both MFT seems ok but they don't match, use chkdsk.\n");
	else
	  display_message("MFT and MFT mirror are bad. Failed to repair them.\n");
      }
      else
      {
#ifdef HAVE_NCURSES
	unsigned int menu=2;
	int real_key;
	int command;
	static const struct MenuItem menuMFT[]=
	{
	  {'B',"MFT",		"Fix MFT using MFT mirror"},
	  {'M',"MFT Mirror",	"Fix MFT mirror using MFT"},
	  {'Q',"Quit","Return to NTFS functions"},
	  {0,NULL,NULL}
	};
	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,8,0);
	if(res1>0 && res2>0)
	  wprintw(stdscr, "Both MFT seem ok but they don't match.\n");
	else
	  wprintw(stdscr, "MFT and MFT mirror are bad.\n");
	command=wmenuSelect_ext(stdscr, 23, INTER_MFT_Y, INTER_MFT_X, menuMFT, 10, "MBQ",
	    MENU_VERT | MENU_VERT_WARN | MENU_BUTTON, &menu, &real_key);
	switch(command)
	{
	  case 'b':
	  case 'B':
	    use_MFT=2;
	    break;
	  case 'm':
	  case 'M':
	    use_MFT=1;
	    break;
	  default:
	    use_MFT=0;
	    break;
	}
#endif
      }
    }
  }
  if(use_MFT==2)
  {
    if((unsigned)disk_car->pwrite(disk_car, buffer_mftmirr, mftmirr_size_bytes, mft_pos) != mftmirr_size_bytes)
    {
      display_message("Failed to fix MFT: write error.\n");
    }
    else
    {
      disk_car->sync(disk_car);
      display_message("MFT fixed.\n");
    }
  }
  else if(use_MFT==1)
  {
    if((unsigned)disk_car->pwrite(disk_car, buffer_mft, mftmirr_size_bytes, mftmirr_pos) != mftmirr_size_bytes)
    {
      display_message("Failed to fix MFT mirror: write error.\n");
    }
    else
    {
      disk_car->sync(disk_car);
      display_message("MFT mirror fixed.\n");
    }
  }
  free(buffer_mftmirr);
  free(buffer_mft);
  free(ntfs_header);
  return 0;
}
Ejemplo n.º 3
0
static int check_part_none(disk_t *disk_car,const int verbose,partition_t *partition, const int saveheader)
{
  int ret=0;
  switch(partition->upart_type)
  {
    case UP_BEOS:
      ret=check_BeFS(disk_car,partition);
      break;
    case UP_BTRFS:
      ret=check_btrfs(disk_car, partition);
      break;
    case UP_CRAMFS:
      ret=check_cramfs(disk_car,partition,verbose);
      break;
    case UP_EXT2:
    case UP_EXT3:
    case UP_EXT4:
      ret=check_EXT2(disk_car,partition,verbose);
      break;
    case UP_EXTENDED:
      break;
    case UP_EXFAT:
      ret=check_EXFAT(disk_car, partition);
      break;
    case UP_FAT12:
    case UP_FAT16:
    case UP_FAT32:
      ret=check_FAT(disk_car,partition,verbose);
      break;
    case UP_FATX:
      ret=check_FATX(disk_car, partition);
      break;
    case UP_FREEBSD:
      ret=check_BSD(disk_car,partition,verbose,BSD_MAXPARTITIONS);
      break;
    case UP_GFS2:
      ret=check_gfs2(disk_car, partition);
      break;
    case UP_HFS:
      ret=check_HFS(disk_car,partition,verbose);
      break;
    case UP_HFSP:
    case UP_HFSX:
      ret=check_HFSP(disk_car,partition,verbose);
      break;
    case UP_HPFS:
      ret=check_HPFS(disk_car,partition,verbose);
      break;
    case UP_ISO:
      ret=check_ISO(disk_car, partition);
      break;
    case UP_JFS:
      ret=check_JFS(disk_car, partition);
      break;
    case UP_LINSWAP:
    case UP_LINSWAP2:
    case UP_LINSWAP_8K:
    case UP_LINSWAP2_8K:
    case UP_LINSWAP2_8KBE:
      ret=check_Linux_SWAP(disk_car, partition);
      break;
    case UP_LUKS:
    ret=check_LUKS(disk_car, partition);
      break;
    case UP_LVM:
      ret=check_LVM(disk_car,partition,verbose);
      break;
    case UP_LVM2:
      ret=check_LVM2(disk_car,partition,verbose);
      break;
    case UP_NETWARE:
      ret=check_netware(disk_car, partition);
      break;
    case UP_NTFS:
      ret=check_NTFS(disk_car,partition,verbose,0);
      if(ret!=0)
      { screen_buffer_add("Invalid NTFS boot\n"); }
      break;
    case UP_OPENBSD:
      ret=check_BSD(disk_car,partition,verbose,OPENBSD_MAXPARTITIONS);
      break;
    case UP_OS2MB:
      ret=check_OS2MB(disk_car,partition,verbose);
      break;
    case UP_MD:
    case UP_MD1:
      ret=check_MD(disk_car,partition,verbose);
      if(ret!=0)
      { screen_buffer_add("Invalid RAID superblock\n"); }
      break;
    case UP_RFS:
    case UP_RFS2:
    case UP_RFS3:
    case UP_RFS4:
      ret=check_rfs(disk_car,partition,verbose);
      break;
    case UP_SUN:
      ret=check_sun_i386(disk_car,partition,verbose);
      break;
    case UP_SYSV4:
      ret=check_sysv(disk_car,partition,verbose);
      break;
    case UP_UFS:
    case UP_UFS2:
    case UP_UFS_LE:
    case UP_UFS2_LE:
      ret=check_ufs(disk_car,partition,verbose);
      break;
    case UP_VMFS:
      ret=check_VMFS(disk_car, partition);
      break;
    case UP_WBFS:
      ret=check_WBFS(disk_car, partition);
      break;
    case UP_XFS:
    case UP_XFS2:
    case UP_XFS3:
    case UP_XFS4:
      ret=check_xfs(disk_car,partition,verbose);
      break;
    case UP_ZFS:
      ret=check_ZFS(disk_car, partition);
      break;
    case UP_UNK:
      break;
  }
  return ret;
}