예제 #1
0
static int exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
  char *new_file;	
  FILE *f_out;
  const struct exfat_dir_struct *ls=(const struct exfat_dir_struct*)dir_data->private_dir_data;
  const struct exfat_super_block *exfat_header=ls->boot_sector;
  const unsigned int cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits;
  unsigned char *buffer_file=(unsigned char *)MALLOC(1<<cluster_shift);
  unsigned int cluster;
  uint64_t file_size=file->st_size;
  exfat_method_t exfat_meth=exFAT_FOLLOW_CLUSTER;
  uint64_t start_exfat1,clus_blocknr;
  unsigned long int total_clusters;
  f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory);
  if(!f_out)
  {
    log_critical("Can't create file %s: \n",new_file);
    free(new_file);
    free(buffer_file);
    return -1;
  }
  cluster = file->st_ino;
  start_exfat1=le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits;
  clus_blocknr=le32(exfat_header->clus_blocknr);
  total_clusters=le32(exfat_header->total_clusters);
  log_trace("exfat_copy dst=%s first_cluster=%u (%llu) size=%lu\n", new_file,
      cluster,
      (long long unsigned)(((cluster-2) << exfat_header->block_per_clus_bits) + clus_blocknr),
      (long unsigned)file_size);

  while(cluster>=2 && cluster<=total_clusters && file_size>0)
  {
    unsigned int toread = 1 << cluster_shift;
    if (toread > file_size)
      toread = file_size;
    if((unsigned)exfat_read_cluster(disk, partition, exfat_header, buffer_file, cluster) < toread)
    {
      log_error("exfat_copy: Can't read cluster %u.\n", cluster);
    }
    if(fwrite(buffer_file, 1, toread, f_out) != toread)
    {
      log_error("exfat_copy: no space left on destination.\n");
      fclose(f_out);
      set_date(new_file, file->td_atime, file->td_mtime);
      free(new_file);
      free(buffer_file);
      return -1;
    }
    file_size -= toread;
    if(file_size>0)
    {
      if(exfat_meth==exFAT_FOLLOW_CLUSTER)
      {
	const unsigned int next_cluster=exfat_get_next_cluster(disk, partition, start_exfat1, cluster);
	if(next_cluster>=2 && next_cluster<=total_clusters)
	  cluster=next_cluster;
	else if(cluster==file->st_ino && next_cluster==0)
	  exfat_meth=exFAT_NEXT_FREE_CLUSTER;	/* Recovery of a deleted file */
	else
	  exfat_meth=exFAT_NEXT_CLUSTER;		/* exFAT is corrupted, don't trust it */
      }
      if(exfat_meth==exFAT_NEXT_CLUSTER)
	cluster++;
      else if(exfat_meth==exFAT_NEXT_FREE_CLUSTER)
      {	/* Deleted file are composed of "free" clusters */
	while(++cluster<total_clusters &&
	    exfat_get_next_cluster(disk, partition, start_exfat1, cluster)!=0);
      }
    }
  }
  fclose(f_out);
  set_date(new_file, file->td_atime, file->td_mtime);
  free(new_file);
  free(buffer_file);
  return 0;
}
예제 #2
0
unsigned int exfat_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space)
{
  struct exfat_super_block *exfat_header;
  unsigned int cluster_shift;
  /* Load boot sector */
  exfat_header=(struct exfat_super_block *)MALLOC(0x200);
  if(disk->pread(disk, exfat_header, 0x200, partition->part_offset) != 0x200)
  {
    log_error("Can't read exFAT boot sector.\n");
    free(exfat_header);
    return 0;
  }
  cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits;
  /* Load bitmap information */
  {
    const struct exfat_alloc_bitmap_entry *bitmap;
    const uint64_t start=partition->part_offset +
      exfat_cluster_to_offset(exfat_header, le32(exfat_header->rootdir_clusnr));
    unsigned char *buffer_rootdir=(unsigned char *)MALLOC(1<<cluster_shift);
    unsigned char *buffer;
    unsigned int i;
    unsigned int cluster_bitmap;
    const uint64_t start_exfat1=(uint64_t)le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits;
    uint64_t start_free=0;
    uint64_t end_free=0;
    if(disk->pread(disk, buffer_rootdir, 1 << cluster_shift, start) != (1<<cluster_shift))
    {
      log_error("exFAT: Can't root directory cluster.\n");
      free(buffer_rootdir);
      free(exfat_header);
      return 0; 
    }
    bitmap=exfat_get_bitmap(buffer_rootdir, 1<<cluster_shift);
    if(bitmap==NULL)
    {
      log_error("exFAT: Can't find bitmap.\n");
      free(buffer_rootdir);
      free(exfat_header);
      return 0; 
    }
    cluster_bitmap=le32(bitmap->first_cluster);
    log_trace("exfat_remove_used_space\n");
    buffer=(unsigned char *)MALLOC(1<<cluster_shift);
    for(i=2; i<le32(exfat_header->total_clusters)+2; i++)
    {
      const unsigned int offset_o=(i-2)%(8<<cluster_shift);
      if(offset_o==0)
      {
	exfat_read_cluster(disk, partition, exfat_header, buffer, cluster_bitmap);
	cluster_bitmap=get_next_cluster(disk, partition, UP_FAT32, start_exfat1, cluster_bitmap);
      }
      if(((buffer[offset_o/8]>>(offset_o%8))&1) != 0)
      {
	/* Not free */
	if(end_free+1==partition->part_offset + exfat_cluster_to_offset(exfat_header, i))
	  end_free+=(1<<cluster_shift);
	else
	{
	  if(start_free != end_free)
	    del_search_space(list_search_space, start_free, end_free);
	  start_free=partition->part_offset + exfat_cluster_to_offset(exfat_header, i);
	  end_free=start_free + (1<<cluster_shift) - 1;
	}
      }
    }
    free(buffer);
    if(start_free != end_free)
      del_search_space(list_search_space, start_free, end_free);
    free(buffer_rootdir);
    free(exfat_header);
  }
  return (1<<cluster_shift);
}
예제 #3
0
static int exfat_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_cluster, file_info_t *dir_list)
{
  const struct exfat_dir_struct *ls=(const struct exfat_dir_struct*)dir_data->private_dir_data;
  const struct exfat_super_block*exfat_header=ls->boot_sector;
  const unsigned int cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits;
  unsigned int cluster;
  unsigned char *buffer_dir=(unsigned char *)MALLOC(NBR_CLUSTER_MAX << cluster_shift);
  unsigned int nbr_cluster;
  const unsigned int total_clusters=le32(exfat_header->total_clusters);
  exfat_method_t exfat_meth=exFAT_FOLLOW_CLUSTER;
  int stop=0;
  const uint64_t start_exfat1=le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits;
  if(first_cluster<2)
    cluster=le32(exfat_header->rootdir_clusnr);
  else
    cluster=first_cluster;
  memset(buffer_dir, 0, NBR_CLUSTER_MAX<<cluster_shift);
  nbr_cluster=0;
  while(!is_EOC(cluster) && cluster>=2 && nbr_cluster<NBR_CLUSTER_MAX && stop==0)
  {
    if(exfat_read_cluster(disk, partition, exfat_header, buffer_dir + ((uint64_t) nbr_cluster << cluster_shift), cluster) != (1<<cluster_shift))
    {
      log_error("exFAT: Can't read directory cluster.\n");
      stop=1;
    }
    if(stop==0)
    {
      if(exfat_meth==exFAT_FOLLOW_CLUSTER)
      {
	const unsigned int next_cluster=exfat_get_next_cluster(disk, partition, start_exfat1, cluster);
	if((next_cluster>=2 && next_cluster<=total_clusters) ||
	    is_EOC(next_cluster))
	  cluster=next_cluster;
	else if(next_cluster==0)
	{
#if 0
	  /* FIXME: experimental */
	  if(cluster==first_cluster && (dir_data->param & FLAG_LIST_DELETED)==FLAG_LIST_DELETED)
	    exfat_meth=exFAT_NEXT_FREE_CLUSTER;	/* Recovery of a deleted directory */
	  else
	    cluster=0;			/* Stop directory listing */
#else
	  cluster=0;			/* Stop directory listing */
#endif
	}
	else
	  exfat_meth=exFAT_NEXT_CLUSTER;		/* exFAT is corrupted, don't trust it */
      }
      if(exfat_meth==exFAT_NEXT_CLUSTER)
	cluster++;
      else if(exfat_meth==exFAT_NEXT_FREE_CLUSTER)
      {	/* Deleted directories are composed of "free" clusters */
#if 0
	while(++cluster<total_clusters &&
	    exfat_get_next_cluster(disk, partition, start_exfat1, cluster)!=0);
#endif
      }
      nbr_cluster++;
    }
  }
  if(nbr_cluster>0)
    dir_exfat_aux(buffer_dir, nbr_cluster<<cluster_shift, dir_data, dir_list);
  free(buffer_dir);
  return 0;
}