Пример #1
0
static int dir_partition_aux(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const unsigned long int inode, const unsigned int depth, char**current_cmd)
{
#define MAX_DIR_NBR 256
  static unsigned long int inode_known[MAX_DIR_NBR];
  if(depth==MAX_DIR_NBR)
    return 1;	/* subdirectories depth is too high => Back */
  if(dir_data->verbose>0)
  {
    log_info("\ndir_partition inode=%lu\n",inode);
    log_partition(disk, partition);
  }
  while(1)
  {
    const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
    long int new_inode=-1;	/* Quit */
    file_data_t *dir_list;
    /* Not perfect for FAT32 root cluster */
    inode_known[depth]=inode;
    dir_list=dir_data->get_dir(disk, partition, dir_data, inode);
    dir_aff_log(dir_data, dir_list);
    if(*current_cmd!=NULL)
    {
      /* TODO: handle copy_files */
      dir_data->current_directory[current_directory_namelength]='\0';
      delete_list_file(dir_list);
      return -1;	/* Quit */
    }
    new_inode=dir_aff_ncurses(disk, partition, dir_data,dir_list,inode,depth);
    if(new_inode==-1 || new_inode==1) /* -1:Quit or 1:Back */
    {
      delete_list_file(dir_list);
      return new_inode;
    }
    if(new_inode>=2)
    {
      unsigned int new_inode_ok=1;
      unsigned int i;
      for(i=0;i<=depth && new_inode_ok!=0;i++)
	if((unsigned)new_inode==inode_known[i]) /* Avoid loop */
	  new_inode_ok=0;
      if(new_inode_ok>0)
      {
	dir_partition_aux(disk, partition, dir_data, (unsigned long int)new_inode, depth+1, current_cmd);
      }
    }
    /* restore current_directory name */
    dir_data->current_directory[current_directory_namelength]='\0';
    delete_list_file(dir_list);
  }
}
Пример #2
0
static int fat_unformat_aux(struct ph_param *params, const struct ph_options *options, const uint64_t start_offset, alloc_data_t *list_search_space)
{
  int ind_stop=0;
  uint64_t offset;
  uint64_t offset_end;
  unsigned char *buffer_start;
  unsigned char *buffer;
  time_t start_time;
  time_t previous_time;
  const unsigned int blocksize=params->blocksize;
  const unsigned int read_size=(blocksize>65536?blocksize:65536);
  alloc_data_t *current_search_space;
  file_recovery_t file_recovery;
  disk_t *disk=params->disk;
  const partition_t *partition=params->partition;

  reset_file_recovery(&file_recovery);
  file_recovery.blocksize=blocksize;
  buffer_start=(unsigned char *)MALLOC(READ_SIZE);
  buffer=buffer_start;
  start_time=time(NULL);
  previous_time=start_time;
  current_search_space=td_list_entry(list_search_space->list.prev, alloc_data_t, list);
  if(current_search_space==list_search_space)
  {
    free(buffer_start);
    return 0;
  }
  offset_end=current_search_space->end;
  current_search_space=td_list_entry(list_search_space->list.next, alloc_data_t, list);
  offset=set_search_start(params, &current_search_space, list_search_space);
  if(options->verbose>0)
    info_list_search_space(list_search_space, current_search_space, disk->sector_size, 0, options->verbose);
  disk->pread(disk, buffer, READ_SIZE, offset);
  for(;offset < offset_end; offset+=blocksize)
  {
    if(memcmp(buffer,         ".          ", 8+3)==0 &&
	memcmp(&buffer[0x20], "..         ", 8+3)==0)
    {
      file_data_t *dir_list;
      dir_list=dir_fat_aux(buffer,read_size,0,0);
      if(dir_list!=NULL)
      {
	const file_data_t *current_file;
	log_info("Sector %llu\n", (long long unsigned)offset/disk->sector_size);
	dir_aff_log(NULL, dir_list);
	del_search_space(list_search_space, offset, offset + blocksize -1);
	current_file=dir_list;
	while(current_file!=NULL)
	{
	  if(strcmp(current_file->name,".")==0 &&
	      LINUX_S_ISDIR(current_file->stat.st_mode)!=0 &&
	      current_file!=dir_list)
	    current_file=NULL;
	  else if(current_file->stat.st_ino>2 &&
	      LINUX_S_ISREG(current_file->stat.st_mode)!=0)
	  {
	    const uint64_t file_start=start_offset + (uint64_t)(current_file->stat.st_ino - 2) * blocksize;
#ifdef DJGPP
	    const uint64_t file_end=file_start+(current_file->file_size+blocksize-1)/blocksize*blocksize - 1;
#else
	    const uint64_t file_end=file_start+(current_file->stat.st_size+blocksize-1)/blocksize*blocksize - 1;
#endif
	    if(file_end < partition->part_offset + partition->part_size)
	    {
	      if(fat_copy_file(disk, partition, blocksize, start_offset, params->recup_dir, params->dir_num, current_file)==0)
	      {
		params->file_nbr++;
		del_search_space(list_search_space, file_start, file_end);
	      }
	      current_file=current_file->next;
	    }
	    else
	      current_file=NULL;
	  }
	  else
	    current_file=current_file->next;
	}
	delete_list_file(dir_list);
      }
    }
    buffer+=blocksize;
    if(buffer+read_size>buffer_start+READ_SIZE)
    {
      buffer=buffer_start;
      if(options->verbose>1)
      {
        log_verbose("Reading sector %10llu/%llu\n",
	    (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	    (unsigned long long)((partition->part_size-1)/disk->sector_size));
      }
      if(disk->pread(disk, buffer, READ_SIZE, offset) != READ_SIZE)
      {
#ifdef HAVE_NCURSES
	wmove(stdscr,11,0);
	wclrtoeol(stdscr);
	wprintw(stdscr,"Error reading sector %10lu\n",
	    (unsigned long)((offset-partition->part_offset)/disk->sector_size));
#endif
      }
#ifdef HAVE_NCURSES
      {
        time_t current_time;
        current_time=time(NULL);
        if(current_time>previous_time)
        {
	  const time_t elapsed_time=current_time - params->real_start_time;
          previous_time=current_time;
	  wmove(stdscr,9,0);
	  wclrtoeol(stdscr);
	  log_info("Reading sector %10llu/%llu, %u files found\n",
	      (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	      (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr);
	  wprintw(stdscr,"Reading sector %10llu/%llu, %u files found\n",
	      (unsigned long long)((offset-partition->part_offset)/disk->sector_size),
	      (unsigned long long)(partition->part_size/disk->sector_size), params->file_nbr);
	  wmove(stdscr,10,0);
	  wclrtoeol(stdscr);
	  wprintw(stdscr,"Elapsed time %uh%02um%02us",
	      (unsigned)(elapsed_time/60/60),
	      (unsigned)(elapsed_time/60%60),
	      (unsigned)(elapsed_time%60));
	  if(offset-partition->part_offset!=0)
	  {
	    wprintw(stdscr," - Estimated time to completion %uh%02um%02u\n",
		(unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/3600),
		(unsigned)(((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset)/60)%60),
		(unsigned)((partition->part_offset+partition->part_size-1-offset)*elapsed_time/(offset-partition->part_offset))%60);
	  }
	  wrefresh(stdscr);
	  if(check_enter_key_or_s(stdscr))
	  {
	    log_info("PhotoRec has been stopped\n");
	    params->offset=offset;
	    offset = offset_end;
	    ind_stop=1;
	  }
	}
      }
#endif
    }
  }
  free(buffer_start);
  return ind_stop;
}
Пример #3
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;
}
Пример #4
0
dir_partition_t dir_partition(disk_t *disk, const partition_t *partition, const int verbose, char **current_cmd)
{
  dir_data_t dir_data;
#ifdef HAVE_NCURSES
  WINDOW *window;
#endif
  dir_partition_t res;
  fflush(stderr);
  dir_data.local_dir=NULL;
  res=dir_partition_init(disk, partition, verbose, &dir_data);
#ifdef HAVE_NCURSES
  window=newwin(LINES, COLS, 0, 0);	/* full screen */
  dir_data.display=window;
  aff_copy(window);
#else
  dir_data.display=NULL;
#endif
  log_info("\n");
  switch(res)
  {
    case DIR_PART_ENOSYS:
      screen_buffer_reset();
#ifdef HAVE_NCURSES
      aff_copy(window);
      wmove(window,4,0);
      aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition);
#endif
      log_partition(disk,partition);
      screen_buffer_add("Support for this filesystem hasn't been enable during compilation.\n");
      screen_buffer_to_log();
      if(*current_cmd==NULL)
      {
#ifdef HAVE_NCURSES
	screen_buffer_display(window,"",NULL);
#endif
      }
      break;
    case DIR_PART_EIO:
      screen_buffer_reset();
#ifdef HAVE_NCURSES
      aff_copy(window);
      wmove(window,4,0);
      aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition);
#endif
      log_partition(disk,partition);
      screen_buffer_add("Can't open filesystem. Filesystem seems damaged.\n");
      screen_buffer_to_log();
      if(*current_cmd==NULL)
      {
#ifdef HAVE_NCURSES
	screen_buffer_display(window,"",NULL);
#endif
      }
      break;
    case DIR_PART_OK:
      {
	int recursive=0;
	if(*current_cmd!=NULL)
	{
	  int do_continue;
	  do
	  {
	    do_continue=0;
	    while(*current_cmd[0]==',')
	      (*current_cmd)++;
	    if(strncmp(*current_cmd,"recursive",9)==0)
	    {
	      (*current_cmd)+=9;
	      recursive=1;
	      do_continue=1;
	    }
	    else if(strncmp(*current_cmd,"fullpathname",12)==0)
	    {
	      (*current_cmd)+=12;
	      dir_data.param|=FLAG_LIST_PATHNAME;
	      do_continue=1;
	    }
	  } while(do_continue==1);
	}
	if(recursive>0)
	  dir_whole_partition_log(disk,partition,&dir_data,dir_data.current_inode);
	else
	{
#ifdef HAVE_NCURSES
	  dir_partition_aff(disk, partition, &dir_data, dir_data.current_inode, current_cmd);
#else
	  {
	    file_info_t dir_list = {
	      .list = TD_LIST_HEAD_INIT(dir_list.list),
	      .name = NULL
	    };
	    dir_data.get_dir(disk, partition, &dir_data, dir_data.current_inode, &dir_list);
	    dir_aff_log(&dir_data, &dir_list);
	    delete_list_file(&dir_list);
	  }
#endif
	}
	dir_data.close(&dir_data);
      }
      break;
  }
#ifdef HAVE_NCURSES
  delwin(window);
  (void) clearok(stdscr, TRUE);
#ifdef HAVE_TOUCHWIN
  touchwin(stdscr);
#endif
  wrefresh(stdscr);
#endif
  fflush(stderr);
  free(dir_data.local_dir);
  return res;
}
Пример #5
0
static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_data_t *dir)
{
  static unsigned int dir_nbr=0;
  static unsigned long int inode_known[MAX_DIR_NBR];
  file_data_t *dir_list;
  const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
  file_data_t *current_file;
  char *dir_name;
  int copy_bad=0;
  int copy_ok=0;
  if(dir_data->get_dir==NULL || dir_data->copy_file==NULL)
    return -2;
  inode_known[dir_nbr++]=dir->st_ino;
  dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory);
  dir_list=dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->st_ino);
  for(current_file=dir_list;current_file!=NULL;current_file=current_file->next)
  {
    dir_data->current_directory[current_directory_namelength]='\0';
    if(current_directory_namelength+1+strlen(current_file->name)<sizeof(dir_data->current_directory)-1)
    {
      if(strcmp(dir_data->current_directory,"/"))
	strcat(dir_data->current_directory,"/");
      strcat(dir_data->current_directory,current_file->name);
      if(LINUX_S_ISDIR(current_file->st_mode)!=0)
      {
	const unsigned long int new_inode=current_file->st_ino;
	unsigned int new_inode_ok=1;
	unsigned int i;
	if(new_inode<2)
	  new_inode_ok=0;
	if(strcmp(current_file->name,"..")==0 || strcmp(current_file->name,".")==0)
	  new_inode_ok=0;
	for(i=0;i<dir_nbr && new_inode_ok!=0;i++)
	  if(new_inode==inode_known[i]) /* Avoid loop */
	    new_inode_ok=0;
	if(new_inode_ok>0)
	{
	  int tmp;
	  tmp=copy_dir(disk, partition, dir_data, current_file);
	  if(tmp>=-1)
	    copy_ok=1;
	  if(tmp<0)
	    copy_bad=1;
	}
      }
      else if(LINUX_S_ISREG(current_file->st_mode)!=0)
      {
//	log_trace("copy_file %s\n",dir_data->current_directory);
	int tmp;
	tmp=dir_data->copy_file(disk, partition, dir_data, current_file);
	if(tmp==0)
	  copy_ok=1;
	else
	  copy_bad=1;
      }
    }
  }
  dir_data->current_directory[current_directory_namelength]='\0';
  delete_list_file(dir_list);
  set_date(dir_name, dir->td_atime, dir->td_mtime);
  free(dir_name);
  dir_nbr--;
  return (copy_bad>0?(copy_ok>0?-1:-2):0);
}
Пример #6
0
int dir_partition(disk_t *disk_car, const partition_t *partition, const int verbose, char **current_cmd)
{
  dir_data_t dir_data;
#ifdef HAVE_NCURSES
  WINDOW *window;
#endif
  int res=-3;
  fflush(stderr);
  dir_data.local_dir=NULL;
  if(is_part_fat(partition))
    res=dir_partition_fat_init(disk_car,partition,&dir_data,verbose);
  else if(is_part_ntfs(partition))
  {
    res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose);
    if(res!=0)
      res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose);
  }
  else if(is_part_linux(partition))
  {
    res=dir_partition_ext2_init(disk_car,partition,&dir_data,verbose);
    if(res!=0)
      res=dir_partition_reiser_init(disk_car,partition,&dir_data,verbose);
  }
  if(res!=0)
  {
    switch(partition->upart_type)
    {
      case UP_FAT12:
      case UP_FAT16:
      case UP_FAT32:
	res=dir_partition_fat_init(disk_car,partition,&dir_data,verbose);
	break;
      case UP_EXT4:
      case UP_EXT3:
      case UP_EXT2:
	res=dir_partition_ext2_init(disk_car,partition,&dir_data,verbose);
	break;
      case UP_RFS:
      case UP_RFS2:
      case UP_RFS3:
	res=dir_partition_reiser_init(disk_car,partition,&dir_data,verbose);
	break;
      case UP_NTFS:
	res=dir_partition_ntfs_init(disk_car,partition,&dir_data,verbose);
	break;
      case UP_EXFAT:
	res=dir_partition_exfat_init(disk_car, partition, &dir_data, verbose);
	break;
      default:
	return res;
    }
  }
#ifdef HAVE_NCURSES
  window=newwin(LINES, COLS, 0, 0);	/* full screen */
  dir_data.display=window;
  aff_copy(window);
#else
  dir_data.display=NULL;
#endif
  log_info("\n");
  switch(res)
  {
    case -2:
      screen_buffer_reset();
#ifdef HAVE_NCURSES
      aff_copy(window);
      wmove(window,4,0);
      aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
#endif
      log_partition(disk_car,partition);
      screen_buffer_add("Support for this filesystem hasn't been enable during compilation.\n");
      screen_buffer_to_log();
      if(*current_cmd==NULL)
      {
#ifdef HAVE_NCURSES
	screen_buffer_display(window,"",NULL);
#endif
      }
      break;
    case -1:
      screen_buffer_reset();
#ifdef HAVE_NCURSES
      aff_copy(window);
      wmove(window,4,0);
      aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
#endif
      log_partition(disk_car,partition);
      screen_buffer_add("Can't open filesystem. Filesystem seems damaged.\n");
      screen_buffer_to_log();
      if(*current_cmd==NULL)
      {
#ifdef HAVE_NCURSES
	screen_buffer_display(window,"",NULL);
#endif
      }
      break;
    default:
      {
	int recursive=0;
	if(*current_cmd!=NULL)
	{
	  int do_continue;
	  do
	  {
	    do_continue=0;
	    while(*current_cmd[0]==',')
	      (*current_cmd)++;
	    if(strncmp(*current_cmd,"recursive",9)==0)
	    {
	      (*current_cmd)+=9;
	      recursive=1;
	      do_continue=1;
	    }
	    else if(strncmp(*current_cmd,"fullpathname",12)==0)
	    {
	      (*current_cmd)+=12;
	      dir_data.param|=FLAG_LIST_PATHNAME;
	      do_continue=1;
	    }
	  } while(do_continue==1);
	}
	if(recursive>0)
	  dir_whole_partition_log(disk_car,partition,&dir_data,dir_data.current_inode);
	else
	{
#ifdef HAVE_NCURSES
	  dir_partition_aff(disk_car, partition, &dir_data, dir_data.current_inode, current_cmd);
#else
	  {
	    file_data_t *dir_list;
	    dir_list=dir_data.get_dir(disk_car, partition, &dir_data, dir_data.current_inode);
	    dir_aff_log(&dir_data, dir_list);
	    delete_list_file(dir_list);
	  }
#endif
	}
	dir_data.close(&dir_data);
      }
      break;
  }
#ifdef HAVE_NCURSES
  delwin(window);
  (void) clearok(stdscr, TRUE);
#ifdef HAVE_TOUCHWIN
  touchwin(stdscr);
#endif
  wrefresh(stdscr);
#endif
  fflush(stderr);
  free(dir_data.local_dir);
  return res;
}