📄 fileio.c
字号:
/* * 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 + -