static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file) { const unsigned long int first_inode=file->st_ino; ntfs_inode *inode; struct ntfs_dir_struct *ls=(struct ntfs_dir_struct*)dir_data->private_dir_data; inode = ntfs_inode_open (ls->vol, first_inode); if (!inode) { log_error("ntfs_copy: ntfs_inode_open failed for %s\n", dir_data->current_directory); return -1; } { char *buffer; char *new_file; ntfs_attr *attr=NULL; FILE *f_out; char *stream_name; s64 offset; u32 block_size; buffer = (char *)MALLOC(bufsize); if (!buffer) { ntfs_inode_close(inode); return -2; } stream_name=strrchr(dir_data->current_directory, ':'); if(stream_name) stream_name++; if(stream_name != NULL) { ntfschar *stream_name_ucs=NULL; #ifdef NTFS_MBSTOUCS_HAVE_TWO_ARGUMENTS const int len=ntfs_mbstoucs(stream_name, &stream_name_ucs); #else const int len=ntfs_mbstoucs(stream_name, &stream_name_ucs, 0); #endif if(len < 0) log_error("ntfs_mbstoucs failed\n"); else attr = ntfs_attr_open(inode, AT_DATA, stream_name_ucs, len); } else attr = ntfs_attr_open(inode, AT_DATA, NULL, 0); if (!attr) { log_error("Cannot find attribute type 0x%lx.\n", (long) AT_DATA); free(buffer); ntfs_inode_close(inode); return -3; } if ((inode->mft_no < 2) && (attr->type == AT_DATA)) block_size = ls->vol->mft_record_size; else if (attr->type == AT_INDEX_ALLOCATION) block_size = index_get_size(inode); else block_size = 0; #if defined(__CYGWIN__) || defined(__MINGW32__) if(stream_name) { /* fopen() create normal files instead of ADS with ':' replaced by an UTF char * replace ':' by '_' instead */ stream_name--; *stream_name='_'; f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); } else f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); #else f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); #endif if(!f_out) { log_critical("Can't create file %s: %s\n",new_file, strerror(errno)); free(new_file); ntfs_attr_close(attr); free(buffer); ntfs_inode_close(inode); return -4; } offset = 0; for (;;) { s64 bytes_read, written; if (block_size > 0) { // These types have fixup bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer); bytes_read *= block_size; } else { bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer); } //ntfs_log_info("read %lld bytes\n", bytes_read); if (bytes_read < 0) { log_error("ERROR: Couldn't read file"); break; } if (!bytes_read) break; written = fwrite(buffer, 1, bytes_read, f_out); if (written != bytes_read) { log_error("ERROR: Couldn't output all data!"); break; } offset += bytes_read; } fclose(f_out); set_date(new_file, file->td_atime, file->td_mtime); free(new_file); ntfs_attr_close(attr); free(buffer); } /* Finished with the inode; release it. */ ntfs_inode_close(inode); return 0; }
static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file) { int error=0; FILE *f_out; const struct ext2_dir_struct *ls = (const struct ext2_dir_struct *)dir_data->private_dir_data; char *new_file; f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); if(!f_out) { log_critical("Can't create file %s: %s\n", new_file, strerror(errno)); free(new_file); return -4; } { errcode_t retval; struct ext2_inode inode; char buffer[8192]; ext2_file_t e2_file; if (ext2fs_read_inode(ls->current_fs, file->st_ino, &inode)!=0) { free(new_file); fclose(f_out); return -1; } retval = ext2fs_file_open(ls->current_fs, file->st_ino, 0, &e2_file); if (retval) { log_error("Error while opening ext2 file %s\n", dir_data->current_directory); free(new_file); fclose(f_out); return -2; } while (1) { int nbytes; unsigned int got; retval = ext2fs_file_read(e2_file, buffer, sizeof(buffer), &got); if (retval) { log_error("Error while reading ext2 file %s\n", dir_data->current_directory); error = -3; } if (got == 0) break; nbytes = fwrite(buffer, 1, got, f_out); if ((unsigned) nbytes != got) { log_error("Error while writing file %s\n", new_file); error = -5; } } retval = ext2fs_file_close(e2_file); if (retval) { log_error("Error while closing ext2 file\n"); error = -6; } fclose(f_out); set_date(new_file, file->td_atime, file->td_mtime); (void)set_mode(new_file, file->st_mode); } free(new_file); return error; }
static int reiser_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_data_t *file) { reiserfs_file_t *in; FILE *f_out; char *new_file; struct rfs_dir_struct *ls=(struct rfs_dir_struct*)dir_data->private_dir_data; int error=0; uint64_t file_size; f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory); if(!f_out) { log_critical("Can't create file %s: %s\n", new_file, strerror(errno)); free(new_file); return -4; } log_error("Try to open rfs file %s\n", dir_data->current_directory); log_flush(); in=reiserfs_file_open(ls->current_fs, dir_data->current_directory, O_RDONLY); if (in==NULL) { log_error("Error while opening rfs file %s\n", dir_data->current_directory); free(new_file); fclose(f_out); return -1; } log_error("open rfs file %s done\n", dir_data->current_directory); log_flush(); file_size = reiserfs_file_size(in); #if 0 /* TODO: do not use so much memory */ { void *buf=MALLOC(file_size+1); if (reiserfs_file_read(in, buf, file_size) != file_size) { log_error("Error while reading rfs file %s\n", dir_data->current_directory); error = -3; } else if (fwrite(buf, file_size, 1, f_out) != 1) { log_error("Error while writing file %s\n", new_file); error = -5; } free(buf); } #else { /* require progsreiserfs-file-read.patch */ char buf[4096]; uint64_t offset=0; while(file_size > 0) { int read_size=(file_size < sizeof(buf) ? file_size : sizeof(buf)); if (reiserfs_file_read(in, buf, read_size) == 0) { log_error("Error while reading rfs file %s\n", dir_data->current_directory); error = -3; } else if (fwrite(buf, read_size, 1, f_out) != 1) { log_error("Error while writing file %s\n", new_file); error = -5; } file_size -= read_size; offset += read_size; } } #endif reiserfs_file_close(in); fclose(f_out); set_date(new_file, file->td_atime, file->td_mtime); set_mode(new_file, file->st_mode); free(new_file); return error; }
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; }