| 427 | } |
| 428 | |
| 429 | static copy_file_t exfat_copy(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file) |
| 430 | { |
| 431 | char *new_file; |
| 432 | FILE *f_out; |
| 433 | const struct exfat_dir_struct *ls=(const struct exfat_dir_struct*)dir_data->private_dir_data; |
| 434 | const struct exfat_super_block *exfat_header=ls->boot_sector; |
| 435 | const unsigned int cluster_shift=exfat_header->block_per_clus_bits + exfat_header->blocksize_bits; |
| 436 | unsigned char *buffer_file=(unsigned char *)MALLOC(1<<cluster_shift); |
| 437 | unsigned int cluster; |
| 438 | uint64_t file_size=file->st_size; |
| 439 | exfat_method_t exfat_meth=exFAT_FOLLOW_CLUSTER; |
| 440 | uint64_t start_exfat1; |
| 441 | unsigned long int clus_blocknr; |
| 442 | unsigned long int total_clusters; |
| 443 | f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); |
| 444 | if(!f_out) |
| 445 | { |
| 446 | log_critical("Can't create file %s: \n",new_file); |
| 447 | free(new_file); |
| 448 | free(buffer_file); |
| 449 | return CP_CREATE_FAILED; |
| 450 | } |
| 451 | cluster = file->st_ino; |
| 452 | start_exfat1=(uint64_t)le32(exfat_header->fat_blocknr) << exfat_header->blocksize_bits; |
| 453 | clus_blocknr=le32(exfat_header->clus_blocknr); |
| 454 | total_clusters=le32(exfat_header->total_clusters); |
| 455 | log_trace("exfat_copy dst=%s first_cluster=%u (%llu) size=%lu\n", new_file, |
| 456 | cluster, |
| 457 | (long long unsigned)(((cluster-2) << exfat_header->block_per_clus_bits) + clus_blocknr), |
| 458 | (long unsigned)file_size); |
| 459 | |
| 460 | while(cluster>=2 && cluster<=total_clusters && file_size>0) |
| 461 | { |
| 462 | unsigned int toread = 1 << cluster_shift; |
| 463 | if (toread > file_size) |
| 464 | toread = file_size; |
| 465 | if((unsigned)exfat_read_cluster(disk, partition, exfat_header, buffer_file, cluster) < toread) |
| 466 | { |
| 467 | log_error("exfat_copy: Can't read cluster %u.\n", cluster); |
| 468 | } |
| 469 | if(fwrite(buffer_file, 1, toread, f_out) != toread) |
| 470 | { |
| 471 | log_error("exfat_copy: no space left on destination.\n"); |
| 472 | fclose(f_out); |
| 473 | set_date(new_file, file->td_atime, file->td_mtime); |
| 474 | free(new_file); |
| 475 | free(buffer_file); |
| 476 | return CP_NOSPACE; |
| 477 | } |
| 478 | file_size -= toread; |
| 479 | if(file_size>0) |
| 480 | { |
| 481 | if(exfat_meth==exFAT_FOLLOW_CLUSTER) |
| 482 | { |
| 483 | const unsigned int next_cluster=exfat_get_next_cluster(disk, partition, start_exfat1, cluster); |
| 484 | if(next_cluster>=2 && next_cluster<=total_clusters) |
| 485 | cluster=next_cluster; |
| 486 | else if(cluster==file->st_ino && next_cluster==0) |
nothing calls this directly
no test coverage detected