Move NtCreateFile/NtOpenFile to VFS, implement (mostly) for real.

Progress on #305.
This commit is contained in:
Ben Vanik
2015-06-29 10:33:36 -07:00
parent 0104a2290f
commit cc08e9019a
25 changed files with 459 additions and 159 deletions

View File

@@ -12,6 +12,7 @@
#include <string>
#include "xenia/base/filesystem.h"
#include "xenia/base/string.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/xobject.h"
#include "xenia/vfs/devices/host_path_device.h"

View File

@@ -16,10 +16,10 @@
namespace xe {
namespace kernel {
XFile::XFile(KernelState* kernel_state, vfs::Mode mode, vfs::Entry* entry)
XFile::XFile(KernelState* kernel_state, uint32_t file_access, vfs::Entry* entry)
: XObject(kernel_state, kTypeFile),
entry_(entry),
mode_(mode),
file_access_(file_access),
position_(0),
find_index_(0) {
async_event_ = new XEvent(kernel_state);

View File

@@ -81,6 +81,7 @@ class XFile : public XObject {
vfs::Device* device() const { return entry_->device(); }
vfs::Entry* entry() const { return entry_; }
uint32_t file_access() const { return file_access_; }
const std::string& path() const { return entry_->path(); }
const std::string& name() const { return entry_->name(); }
@@ -102,7 +103,7 @@ class XFile : public XObject {
virtual void* GetWaitHandle();
protected:
XFile(KernelState* kernel_state, vfs::Mode mode, vfs::Entry* entry);
XFile(KernelState* kernel_state, uint32_t file_access, vfs::Entry* entry);
virtual X_STATUS ReadSync(void* buffer, size_t buffer_length,
size_t byte_offset, size_t* out_bytes_read) = 0;
virtual X_STATUS WriteSync(const void* buffer, size_t buffer_length,
@@ -112,7 +113,7 @@ class XFile : public XObject {
private:
vfs::Entry* entry_;
vfs::Mode mode_;
uint32_t file_access_;
XEvent* async_event_;
// TODO(benvanik): create flags, open state, etc.

View File

@@ -57,9 +57,9 @@ X_STATUS XUserModule::LoadFromFile(std::string path) {
std::vector<uint8_t> buffer(fs_entry->size());
// Open file for reading.
XFile* file_ptr = nullptr;
result = fs_entry->Open(kernel_state(), vfs::Mode::READ, false, &file_ptr);
object_ref<XFile> file(file_ptr);
object_ref<XFile> file;
result =
fs_entry->Open(kernel_state(), vfs::FileAccess::kGenericRead, &file);
if (result) {
return result;
}

View File

@@ -152,98 +152,45 @@ class X_FILE_FS_ATTRIBUTE_INFORMATION {
};
static_assert_size(X_FILE_FS_ATTRIBUTE_INFORMATION, 16);
struct FileDisposition {
static const uint32_t X_FILE_SUPERSEDE = 0x00000000;
static const uint32_t X_FILE_OPEN = 0x00000001;
static const uint32_t X_FILE_CREATE = 0x00000002;
static const uint32_t X_FILE_OPEN_IF = 0x00000003;
static const uint32_t X_FILE_OVERWRITE = 0x00000004;
static const uint32_t X_FILE_OVERWRITE_IF = 0x00000005;
};
struct FileAccess {
static const uint32_t X_GENERIC_READ = 0x80000000;
static const uint32_t X_GENERIC_WRITE = 0x40000000;
static const uint32_t X_GENERIC_EXECUTE = 0x20000000;
static const uint32_t X_GENERIC_ALL = 0x10000000;
static const uint32_t X_FILE_READ_DATA = 0x00000001;
static const uint32_t X_FILE_WRITE_DATA = 0x00000002;
static const uint32_t X_FILE_APPEND_DATA = 0x00000004;
};
X_STATUS NtCreateFile(PPCContext* ppc_context, KernelState* kernel_state,
uint32_t handle_ptr, uint32_t desired_access,
X_OBJECT_ATTRIBUTES* object_attrs,
const char* object_name, uint32_t io_status_block_ptr,
uint32_t allocation_size_ptr, uint32_t file_attributes,
uint32_t share_access, uint32_t creation_disposition) {
uint32_t share_access,
FileDisposition creation_disposition) {
uint64_t allocation_size = 0; // is this correct???
if (allocation_size_ptr != 0) {
allocation_size = SHIM_MEM_64(allocation_size_ptr);
}
X_STATUS result = X_STATUS_NO_SUCH_FILE;
uint32_t info = X_FILE_DOES_NOT_EXIST;
uint32_t handle;
auto fs = kernel_state->file_system();
Entry* entry;
object_ref<XFile> root_file;
// Compute path, possibly attrs relative.
std::string target_path = object_name;
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
object_attrs->root_directory != 0) {
root_file = kernel_state->object_table()->LookupObject<XFile>(
auto root_file = kernel_state->object_table()->LookupObject<XFile>(
object_attrs->root_directory);
assert_not_null(root_file);
assert_true(root_file->type() == XObject::Type::kTypeFile);
// Resolve the file using the device the root directory is part of.
auto device = root_file->device();
auto target_path = xe::join_paths(root_file->path(), object_name);
entry = device->ResolvePath(target_path.c_str());
} else {
// Resolve the file using the virtual file system.
entry = fs->ResolvePath(object_name);
}
bool wants_write = desired_access & FileAccess::X_GENERIC_WRITE ||
desired_access & FileAccess::X_GENERIC_ALL ||
desired_access & FileAccess::X_FILE_WRITE_DATA ||
desired_access & FileAccess::X_FILE_APPEND_DATA;
if (wants_write) {
if (entry && entry->is_read_only()) {
// We don't support any write modes.
XELOGW("Attempted to open the file/dir for create/write");
desired_access = FileAccess::X_GENERIC_READ;
}
target_path = xe::join_paths(
device->mount_path(), xe::join_paths(root_file->path(), object_name));
}
// Attempt open (or create).
object_ref<XFile> file;
if (!entry) {
result = X_STATUS_NO_SUCH_FILE;
info = X_FILE_DOES_NOT_EXIST;
} else {
// Open the file/directory.
vfs::Mode mode;
if (desired_access & FileAccess::X_FILE_APPEND_DATA) {
mode = vfs::Mode::READ_APPEND;
} else if (wants_write) {
mode = vfs::Mode::READ_WRITE;
} else {
mode = vfs::Mode::READ;
}
XFile* file_ptr = nullptr;
result = entry->Open(kernel_state, mode,
false, // TODO(benvanik): pick async mode, if needed.
&file_ptr);
file = object_ref<XFile>(file_ptr);
}
FileAction file_action;
X_STATUS result = kernel_state->file_system()->OpenFile(
kernel_state, target_path, creation_disposition, desired_access, &file,
&file_action);
uint32_t info = uint32_t(file_action);
X_HANDLE handle = X_INVALID_HANDLE_VALUE;
if (XSUCCEEDED(result)) {
// Handle ref is incremented, so return that.
handle = file->handle();
result = X_STATUS_SUCCESS;
info = X_FILE_OPENED;
}
if (io_status_block_ptr) {
@@ -282,7 +229,7 @@ SHIM_CALL NtCreateFile_shim(PPCContext* ppc_context,
auto result = NtCreateFile(
ppc_context, kernel_state, handle_ptr, desired_access, &object_attrs,
object_name, io_status_block_ptr, allocation_size_ptr, file_attributes,
share_access, creation_disposition);
share_access, FileDisposition(creation_disposition));
free(object_name);
SHIM_SET_RETURN_32(result);
@@ -305,7 +252,7 @@ SHIM_CALL NtOpenFile_shim(PPCContext* ppc_context, KernelState* kernel_state) {
auto result = NtCreateFile(
ppc_context, kernel_state, handle_ptr, desired_access, &object_attrs,
object_name, io_status_block_ptr, 0, 0, 0, FileDisposition::X_FILE_OPEN);
object_name, io_status_block_ptr, 0, 0, 0, FileDisposition::kOpen);
free(object_name);
SHIM_SET_RETURN_32(result);
@@ -451,7 +398,7 @@ SHIM_CALL NtWriteFile_shim(PPCContext* ppc_context, KernelState* kernel_state) {
// Grab file.
auto file = kernel_state->object_table()->LookupObject<XFile>(file_handle);
if (!ev) {
if (!file) {
result = X_STATUS_INVALID_HANDLE;
}