/** * cat */ static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int namelen) { const int bufsize = 4096; char *buffer; ntfs_attr *attr; s64 bytes_read, written; s64 offset; u32 block_size; buffer = malloc(bufsize); if (!buffer) return 1; attr = ntfs_attr_open(inode, type, name, namelen); if (!attr) { ntfs_log_error("Cannot find attribute type 0x%x.\n", le32_to_cpu(type)); free(buffer); return 1; } if ((inode->mft_no < 2) && (attr->type == AT_DATA)) block_size = vol->mft_record_size; else if (attr->type == AT_INDEX_ALLOCATION) block_size = index_get_size(inode); else block_size = 0; offset = 0; for (;;) { if (!opts.raw && block_size > 0) { // These types have fixup bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer); if (bytes_read > 0) 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 == -1) { ntfs_log_perror("ERROR: Couldn't read file"); break; } if (!bytes_read) break; written = fwrite(buffer, 1, bytes_read, stdout); if (written != bytes_read) { ntfs_log_perror("ERROR: Couldn't output all data!"); break; } offset += bytes_read; } ntfs_attr_close(attr); free(buffer); return 0; }
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; }