⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileio.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This source code is a part of coLinux source package. * * Dan Aloni <da-x@colinux.org>, 2003 (c) * * The code is licensed under the GPL. See the COPYING file at * the root directory. * */ #include "ddk.h"#include <ddk/ntifs.h>#include <ddk/ntdddisk.h>#include <colinux/os/alloc.h>#include <colinux/common/libc.h>#include <colinux/common/unicode.h>#include <colinux/kernel/transfer.h>#include <colinux/kernel/fileblock.h>#include <colinux/kernel/monitor.h>#include <colinux/kernel/filesystem.h>#include <colinux/os/kernel/time.h>#include <colinux/os/kernel/filesystem.h>#include "time.h"#include "fileio.h"#define FILE_SHARE_DIRECTORY (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)co_rc_t co_winnt_utf8_to_unicode(const char *src, UNICODE_STRING *unicode_str){	co_rc_t rc;	co_wchar_t *wstring;	unsigned long size;	unicode_str->Buffer = NULL;	rc = co_utf8_dup_to_wc(src, &wstring, &size);	if (!CO_OK(rc))		return rc;	unicode_str->Length = size * sizeof(WCHAR);	unicode_str->MaximumLength = (size + 1) * sizeof(WCHAR);	unicode_str->Buffer = wstring;	return CO_RC(OK);}void co_winnt_free_unicode(UNICODE_STRING *unicode_str){	if (!unicode_str->Buffer)		return;	co_utf8_free_wc(unicode_str->Buffer);	unicode_str->Buffer = NULL;}static co_rc_t status_convert(NTSTATUS status){	switch (status) {	case STATUS_NO_SUCH_FILE: 	case STATUS_OBJECT_NAME_NOT_FOUND: return CO_RC(NOT_FOUND);	case STATUS_CANNOT_DELETE:	case STATUS_ACCESS_DENIED: return CO_RC(ACCESS_DENIED);	case STATUS_INVALID_PARAMETER: return CO_RC(INVALID_PARAMETER);	}	if (status != STATUS_SUCCESS) {		return CO_RC(ERROR);	}	return CO_RC(OK);}co_rc_t co_os_file_create(char *pathname, PHANDLE FileHandle, unsigned long open_flags,			  unsigned long file_attribute, unsigned long create_disposition,			  unsigned long options){    	NTSTATUS status;	OBJECT_ATTRIBUTES ObjectAttributes;	IO_STATUS_BLOCK IoStatusBlock;	UNICODE_STRING unipath;	co_rc_t rc;	rc = co_winnt_utf8_to_unicode(pathname, &unipath);	if (!CO_OK(rc))		return rc;	InitializeObjectAttributes(&ObjectAttributes, 				   &unipath,				   OBJ_CASE_INSENSITIVE,				   NULL,				   NULL);	status = ZwCreateFile(FileHandle, 			      open_flags | SYNCHRONIZE,			      &ObjectAttributes,			      &IoStatusBlock,			      NULL,			      file_attribute,			      (open_flags == FILE_LIST_DIRECTORY) ?				 FILE_SHARE_DIRECTORY : 0,			      create_disposition,			      options | FILE_SYNCHRONOUS_IO_NONALERT,			      NULL,			      0);	if (status != STATUS_SUCCESS)		co_debug_lvl(filesystem, 5, "error %x ZwOpenFile('%s')", (int)status, pathname);	co_winnt_free_unicode(&unipath);	return status_convert(status);}co_rc_t co_os_file_open(char *pathname, PHANDLE FileHandle, unsigned long open_flags){   	return co_os_file_create(pathname, FileHandle, open_flags, 0, FILE_OPEN, 0);}co_rc_t co_os_file_close(PHANDLE FileHandle){    	NTSTATUS status;	status = ZwClose(FileHandle);	return status_convert(status);}typedef struct {	LARGE_INTEGER offset;	HANDLE file_handle;} co_os_transfer_file_block_data_t;static co_rc_t transfer_file_block(co_monitor_t *cmon, 				  void *host_data, void *linuxvm, 				  unsigned long size, 				  co_monitor_transfer_dir_t dir){	IO_STATUS_BLOCK isb;	NTSTATUS status;	co_os_transfer_file_block_data_t *data;	co_rc_t rc = CO_RC_OK;	HANDLE FileHandle;	data = (co_os_transfer_file_block_data_t *)host_data;	FileHandle = data->file_handle;	if (CO_MONITOR_TRANSFER_FROM_HOST == dir) {		status = ZwReadFile(FileHandle,				    NULL,				    NULL,				    NULL, 				    &isb,				    linuxvm,				    size,				    &data->offset,				    NULL);	}	else {		status = ZwWriteFile(FileHandle,				     NULL,				     NULL,				     NULL, 				     &isb,				     linuxvm,				     size,				     &data->offset,				     NULL);	}	if (status != STATUS_SUCCESS) {		co_debug_error("block io failed: %p %lx (reason: %x)",				linuxvm, size, (int)status);		rc = status_convert(status);	}	data->offset.QuadPart += size;	return rc;}co_rc_t co_os_file_block_read_write(co_monitor_t *linuxvm,				    HANDLE file_handle,				    unsigned long long offset,				    vm_ptr_t address,				    unsigned long size,				    bool_t read){	co_rc_t rc;	co_os_transfer_file_block_data_t data;		data.offset.QuadPart = offset;	data.file_handle = file_handle;	rc = co_monitor_host_linuxvm_transfer(linuxvm, 					      &data, 					      transfer_file_block,					      address,					      size,					      (read ? CO_MONITOR_TRANSFER_FROM_HOST : 					       CO_MONITOR_TRANSFER_FROM_LINUX));	return rc;}typedef void (*co_os_change_file_info_func_t)(void *data, VOID *buffer, ULONG len);co_rc_t co_os_change_file_information(char *filename,				      IO_STATUS_BLOCK *io_status,				      VOID *buffer,				      ULONG len,				      FILE_INFORMATION_CLASS info_class,				      co_os_change_file_info_func_t func,				      void *data){	NTSTATUS status;	HANDLE handle;	co_rc_t rc;	rc = co_os_file_open(filename, &handle, FILE_READ_DATA | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES);	if (!CO_OK(rc)) {		rc = co_os_file_open(filename, &handle, FILE_WRITE_ATTRIBUTES);		if (!CO_OK(rc))			return rc;	}	status = ZwQueryInformationFile(handle, io_status, buffer, len, info_class);	if (status == STATUS_SUCCESS) {		if (func) {			func(data, buffer, len);		}		status = ZwSetInformationFile(handle, io_status, buffer, len, info_class);	}	co_os_file_close(handle);	return status_convert(status);}co_rc_t co_os_set_file_information(char *filename,				   IO_STATUS_BLOCK *io_status,				   VOID *buffer,				   ULONG len,				   FILE_INFORMATION_CLASS info_class){	HANDLE handle;	NTSTATUS status;	co_rc_t rc;	rc = co_os_file_open(filename, &handle, FILE_READ_DATA | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES);	if (!CO_OK(rc))		return rc;	status = ZwSetInformationFile(handle, io_status, buffer, len, info_class);	co_os_file_close(handle);	return status_convert(status);}co_rc_t co_os_file_read_write(co_monitor_t *linuxvm, char *filename, 			      unsigned long long offset, unsigned long size,			      vm_ptr_t src_buffer, bool_t read){	co_rc_t rc;	HANDLE handle;	rc = co_os_file_open(filename, &handle, read ? FILE_READ_DATA : FILE_WRITE_DATA);	if (!CO_OK(rc))		return rc;	rc = co_os_file_block_read_write(linuxvm,					 handle,					 offset,					 src_buffer,					 size,					 read);	co_os_file_close(handle);	return rc;}static void change_file_info_func(void *data, VOID *buffer, ULONG len){	struct fuse_attr *attr = (struct fuse_attr *)data;	FILE_BASIC_INFORMATION *fbi = (FILE_BASIC_INFORMATION *)buffer;	fbi->LastAccessTime = unix_time_to_windows_time(attr->mtime);	fbi->LastWriteTime = unix_time_to_windows_time(attr->atime);	KeQuerySystemTime(&fbi->ChangeTime);}co_rc_t co_os_file_set_attr(char *filename, unsigned long valid, struct fuse_attr *attr){	IO_STATUS_BLOCK io_status;	co_rc_t rc = CO_RC(OK);	/* FIXME: make return codes not to overwrite each other */	if (valid & FATTR_MODE) {		rc = CO_RC(OK); /* TODO */	}	if (valid & FATTR_UID) {		rc = CO_RC(OK); /* TODO */	}	if (valid & FATTR_GID) {		rc = CO_RC(OK); /* TODO */	}	if (valid & FATTR_UTIME) {		FILE_BASIC_INFORMATION fbi;		rc = co_os_change_file_information(filename, &io_status, &fbi,						   sizeof(fbi), FileBasicInformation,						   change_file_info_func,						   attr);	}	if (valid & FATTR_SIZE) {		FILE_END_OF_FILE_INFORMATION feofi;				feofi.EndOfFile.QuadPart = attr->size;		rc = co_os_set_file_information(filename, &io_status, &feofi,						sizeof(feofi), FileEndOfFileInformation);	} 	return rc;} co_rc_t co_os_file_get_attr(char *fullname, struct fuse_attr *attr){	char * dirname;	char * filename;	UNICODE_STRING dirname_unicode;	UNICODE_STRING filename_unicode;	OBJECT_ATTRIBUTES attributes;	NTSTATUS status;	HANDLE handle;	struct {		union {			FILE_FULL_DIRECTORY_INFORMATION entry;			FILE_BOTH_DIRECTORY_INFORMATION entry2;		};		WCHAR name_filler[sizeof(co_pathname_t)];	} entry_buffer;	IO_STATUS_BLOCK io_status;	co_rc_t rc;	int len, len1;	LARGE_INTEGER LastAccessTime;	LARGE_INTEGER LastWriteTime;	LARGE_INTEGER ChangeTime;	LARGE_INTEGER EndOfFile;	ULONG FileAttributes; 	len = co_strlen(fullname);	len1 = len;		while (len > 0 && fullname[len-1] != '\\') {		if (fullname[len-1] == '?' || fullname[len-1] == '*') {			co_debug_lvl(filesystem, 5, "error: Wildcard in filename ('%s')", fullname);			return CO_RC(NOT_FOUND);		}		len--;	}	dirname = co_os_malloc(len+1);	if (!dirname) {		co_debug_lvl(filesystem, 5, "no memory");		return CO_RC(OUT_OF_MEMORY);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -