/** * 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_ib_read(ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst) { s64 pos, ret; ntfs_log_trace("vcn: %lld\n", (long long)vcn); pos = ntfs_ib_vcn_to_pos(icx, vcn); ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst); if (ret != 1) { if (ret == -1) ntfs_log_perror("Failed to read index block"); else ntfs_log_error("Failed to read full index block at " "%lld\n", (long long)pos); return -1; } if (ntfs_ia_check(icx, dst, vcn)) return -1; 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; }
static int ntfsrec_emit_file(struct ntfsrec_copy *state, ntfs_inode *inode, const char *name) { ntfs_attr *data_attribute; char *old_path_end; if (ntfsrec_append_filename(state, name, &old_path_end) == NR_FALSE) { printf("Error: path %s and filename %s are too long.\n", state->path, name); return NR_FALSE; } data_attribute = ntfs_attr_open(inode, AT_DATA, NULL, 0); if (data_attribute != NULL) { int output_fd; unsigned int block_size = 0, retries = 0; s64 offset = 0; output_fd = open(state->path, O_WRONLY | O_CREAT); if (output_fd != -1) { if (inode->mft_no < 2) { block_size = state->volume->mft_record_size; } for(;;) { s64 bytes_read = 0; if (block_size > 0) { bytes_read = ntfs_attr_mst_pread(data_attribute, offset, 1, block_size, state->file_buffer); bytes_read *= block_size; } else { bytes_read = ntfs_attr_pread(data_attribute, offset, NR_FILE_BUFFER_SIZE, state->file_buffer); } if (bytes_read == -1) { unsigned int actual_size = block_size > 0 ? block_size : NR_FILE_BUFFER_SIZE; if (retries++ < state->opt.retries) { state->stats.retries++; continue; } state->stats.errors++; printf("Error: failed %u times to read %s, skipping %d bytes\n", retries, name, actual_size); lseek(output_fd, actual_size, SEEK_CUR); offset += actual_size; continue; } if (bytes_read == 0) { break; } if (write(output_fd, state->file_buffer, bytes_read) < 0) { printf("Error: unable to write to output file %s\n", state->path); if (retries++ < state->opt.retries) { state->stats.retries++; continue; } break; } retries = 0; offset += bytes_read; } close(output_fd); } state->stats.files++; ntfs_attr_close(data_attribute); } else { printf("Error: can't access the data for %s\n", name); } *old_path_end = '\0'; state->current_path_end = old_path_end; return NR_TRUE; }