[Kernel/VFS] Specify root entry to open from + cleanup.
[VFS] Allow specifying root entry to open from with OpenFile. [Kernel] NtCreateFile now opens from root entry when available instead of needlessly building a full path and resolving from that. [VFS] Reduce code duplication by adding Entry::ResolvePath. [VFS] Remove ResolveBasePath to avoid multiple calls to find_base_guest_path.
This commit is contained in:
parent
725f3ce17f
commit
1c2d6753bb
|
@ -90,6 +90,8 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
|
||||||
auto object_name =
|
auto object_name =
|
||||||
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
|
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
|
||||||
|
|
||||||
|
vfs::Entry* root_entry = nullptr;
|
||||||
|
|
||||||
// Compute path, possibly attrs relative.
|
// Compute path, possibly attrs relative.
|
||||||
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
|
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
|
||||||
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
|
if (object_attrs->root_directory != 0xFFFFFFFD && // ObDosDevices
|
||||||
|
@ -99,18 +101,15 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
|
||||||
assert_not_null(root_file);
|
assert_not_null(root_file);
|
||||||
assert_true(root_file->type() == XObject::Type::kTypeFile);
|
assert_true(root_file->type() == XObject::Type::kTypeFile);
|
||||||
|
|
||||||
// Resolve the file using the device the root directory is part of.
|
root_entry = root_file->entry();
|
||||||
auto device = root_file->device();
|
|
||||||
target_path = xe::utf8::join_guest_paths(
|
|
||||||
{device->mount_path(), root_file->path(), target_path});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt open (or create).
|
// Attempt open (or create).
|
||||||
vfs::File* vfs_file;
|
vfs::File* vfs_file;
|
||||||
vfs::FileAction file_action;
|
vfs::FileAction file_action;
|
||||||
X_STATUS result = kernel_state()->file_system()->OpenFile(
|
X_STATUS result = kernel_state()->file_system()->OpenFile(
|
||||||
target_path, vfs::FileDisposition((uint32_t)creation_disposition),
|
root_entry, target_path,
|
||||||
desired_access,
|
vfs::FileDisposition((uint32_t)creation_disposition), desired_access,
|
||||||
(create_options & CreateOptions::FILE_DIRECTORY_FILE) != 0, &vfs_file,
|
(create_options & CreateOptions::FILE_DIRECTORY_FILE) != 0, &vfs_file,
|
||||||
&file_action);
|
&file_action);
|
||||||
object_ref<XFile> file = nullptr;
|
object_ref<XFile> file = nullptr;
|
||||||
|
|
|
@ -263,8 +263,8 @@ object_ref<XFile> XFile::Restore(KernelState* kernel_state,
|
||||||
vfs::File* vfs_file = nullptr;
|
vfs::File* vfs_file = nullptr;
|
||||||
vfs::FileAction action;
|
vfs::FileAction action;
|
||||||
auto res = kernel_state->file_system()->OpenFile(
|
auto res = kernel_state->file_system()->OpenFile(
|
||||||
abs_path, vfs::FileDisposition::kOpen, access, is_directory, &vfs_file,
|
nullptr, abs_path, vfs::FileDisposition::kOpen, access, is_directory,
|
||||||
&action);
|
&vfs_file, &action);
|
||||||
if (XFAILED(res)) {
|
if (XFAILED(res)) {
|
||||||
XELOGE("Failed to open XFile: error {:08X}", res);
|
XELOGE("Failed to open XFile: error {:08X}", res);
|
||||||
return object_ref<XFile>(file);
|
return object_ref<XFile>(file);
|
||||||
|
|
|
@ -58,20 +58,8 @@ Entry* DiscImageDevice::ResolvePath(const std::string_view path) {
|
||||||
// The filesystem will have stripped our prefix off already, so the path will
|
// The filesystem will have stripped our prefix off already, so the path will
|
||||||
// be in the form:
|
// be in the form:
|
||||||
// some\PATH.foo
|
// some\PATH.foo
|
||||||
|
|
||||||
XELOGFS("DiscImageDevice::ResolvePath({})", path);
|
XELOGFS("DiscImageDevice::ResolvePath({})", path);
|
||||||
|
return root_entry_->ResolvePath(path);
|
||||||
// Walk the path, one separator at a time.
|
|
||||||
auto entry = root_entry_.get();
|
|
||||||
for (const auto& part : xe::utf8::split_path(path)) {
|
|
||||||
entry = entry->GetChild(part);
|
|
||||||
if (!entry) {
|
|
||||||
// Not found.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscImageDevice::Error DiscImageDevice::Verify(ParseState* state) {
|
DiscImageDevice::Error DiscImageDevice::Verify(ParseState* state) {
|
||||||
|
|
|
@ -53,21 +53,8 @@ Entry* HostPathDevice::ResolvePath(const std::string_view path) {
|
||||||
// The filesystem will have stripped our prefix off already, so the path will
|
// The filesystem will have stripped our prefix off already, so the path will
|
||||||
// be in the form:
|
// be in the form:
|
||||||
// some\PATH.foo
|
// some\PATH.foo
|
||||||
|
|
||||||
XELOGFS("HostPathDevice::ResolvePath({})", path);
|
XELOGFS("HostPathDevice::ResolvePath({})", path);
|
||||||
|
return root_entry_->ResolvePath(path);
|
||||||
// Walk the path, one separator at a time.
|
|
||||||
auto entry = root_entry_.get();
|
|
||||||
auto path_parts = xe::utf8::split_path(path);
|
|
||||||
for (auto& part : path_parts) {
|
|
||||||
entry = entry->GetChild(part);
|
|
||||||
if (!entry) {
|
|
||||||
// Not found.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostPathDevice::PopulateEntry(HostPathEntry* parent_entry) {
|
void HostPathDevice::PopulateEntry(HostPathEntry* parent_entry) {
|
||||||
|
|
|
@ -165,21 +165,8 @@ Entry* StfsContainerDevice::ResolvePath(const std::string_view path) {
|
||||||
// The filesystem will have stripped our prefix off already, so the path will
|
// The filesystem will have stripped our prefix off already, so the path will
|
||||||
// be in the form:
|
// be in the form:
|
||||||
// some\PATH.foo
|
// some\PATH.foo
|
||||||
|
|
||||||
XELOGFS("StfsContainerDevice::ResolvePath({})", path);
|
XELOGFS("StfsContainerDevice::ResolvePath({})", path);
|
||||||
|
return root_entry_->ResolvePath(path);
|
||||||
// Walk the path, one separator at a time.
|
|
||||||
auto entry = root_entry_.get();
|
|
||||||
auto path_parts = xe::utf8::split_path(path);
|
|
||||||
for (auto& part : path_parts) {
|
|
||||||
entry = entry->GetChild(part);
|
|
||||||
if (!entry) {
|
|
||||||
// Not found.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StfsContainerDevice::Error StfsContainerDevice::ReadPackageType(
|
StfsContainerDevice::Error StfsContainerDevice::ReadPackageType(
|
||||||
|
|
|
@ -58,6 +58,19 @@ Entry* Entry::GetChild(const std::string_view name) {
|
||||||
return (*it).get();
|
return (*it).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Entry* Entry::ResolvePath(const std::string_view path) {
|
||||||
|
// Walk the path, one separator at a time.
|
||||||
|
Entry* entry = this;
|
||||||
|
for (auto& part : xe::utf8::split_path(path)) {
|
||||||
|
entry = entry->GetChild(part);
|
||||||
|
if (!entry) {
|
||||||
|
// Not found.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
|
Entry* Entry::IterateChildren(const xe::filesystem::WildcardEngine& engine,
|
||||||
size_t* current_index) {
|
size_t* current_index) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
|
@ -97,6 +97,7 @@ class Entry {
|
||||||
bool is_read_only() const;
|
bool is_read_only() const;
|
||||||
|
|
||||||
Entry* GetChild(const std::string_view name);
|
Entry* GetChild(const std::string_view name);
|
||||||
|
Entry* ResolvePath(const std::string_view path);
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<Entry>>& children() const {
|
const std::vector<std::unique_ptr<Entry>>& children() const {
|
||||||
return children_;
|
return children_;
|
||||||
|
|
|
@ -126,11 +126,6 @@ Entry* VirtualFileSystem::ResolvePath(const std::string_view path) {
|
||||||
return device->ResolvePath(relative_path);
|
return device->ResolvePath(relative_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* VirtualFileSystem::ResolveBasePath(const std::string_view path) {
|
|
||||||
auto base_path = xe::utf8::find_base_guest_path(path);
|
|
||||||
return ResolvePath(base_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry* VirtualFileSystem::CreatePath(const std::string_view path,
|
Entry* VirtualFileSystem::CreatePath(const std::string_view path,
|
||||||
uint32_t attributes) {
|
uint32_t attributes) {
|
||||||
// Create all required directories recursively.
|
// Create all required directories recursively.
|
||||||
|
@ -173,7 +168,8 @@ bool VirtualFileSystem::DeletePath(const std::string_view path) {
|
||||||
return parent->Delete(entry);
|
return parent->Delete(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
X_STATUS VirtualFileSystem::OpenFile(const std::string_view path,
|
X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry,
|
||||||
|
const std::string_view path,
|
||||||
FileDisposition creation_disposition,
|
FileDisposition creation_disposition,
|
||||||
uint32_t desired_access, bool is_directory,
|
uint32_t desired_access, bool is_directory,
|
||||||
File** out_file, FileAction* out_action) {
|
File** out_file, FileAction* out_action) {
|
||||||
|
@ -195,8 +191,11 @@ X_STATUS VirtualFileSystem::OpenFile(const std::string_view path,
|
||||||
// If no device or parent, fail.
|
// If no device or parent, fail.
|
||||||
Entry* parent_entry = nullptr;
|
Entry* parent_entry = nullptr;
|
||||||
Entry* entry = nullptr;
|
Entry* entry = nullptr;
|
||||||
if (!xe::utf8::find_base_guest_path(path).empty()) {
|
|
||||||
parent_entry = ResolveBasePath(path);
|
auto base_path = xe::utf8::find_base_guest_path(path);
|
||||||
|
if (!base_path.empty()) {
|
||||||
|
parent_entry = !root_entry ? ResolvePath(base_path)
|
||||||
|
: root_entry->ResolvePath(base_path);
|
||||||
if (!parent_entry) {
|
if (!parent_entry) {
|
||||||
*out_action = FileAction::kDoesNotExist;
|
*out_action = FileAction::kDoesNotExist;
|
||||||
return X_STATUS_NO_SUCH_FILE;
|
return X_STATUS_NO_SUCH_FILE;
|
||||||
|
@ -205,7 +204,7 @@ X_STATUS VirtualFileSystem::OpenFile(const std::string_view path,
|
||||||
auto file_name = xe::utf8::find_name_from_guest_path(path);
|
auto file_name = xe::utf8::find_name_from_guest_path(path);
|
||||||
entry = parent_entry->GetChild(file_name);
|
entry = parent_entry->GetChild(file_name);
|
||||||
} else {
|
} else {
|
||||||
entry = ResolvePath(path);
|
entry = !root_entry ? ResolvePath(path) : root_entry->GetChild(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if exists (if we need it to), or that it doesn't (if it shouldn't).
|
// Check if exists (if we need it to), or that it doesn't (if it shouldn't).
|
||||||
|
|
|
@ -37,12 +37,11 @@ class VirtualFileSystem {
|
||||||
bool FindSymbolicLink(const std::string_view path, std::string& target);
|
bool FindSymbolicLink(const std::string_view path, std::string& target);
|
||||||
|
|
||||||
Entry* ResolvePath(const std::string_view path);
|
Entry* ResolvePath(const std::string_view path);
|
||||||
Entry* ResolveBasePath(const std::string_view path);
|
|
||||||
|
|
||||||
Entry* CreatePath(const std::string_view path, uint32_t attributes);
|
Entry* CreatePath(const std::string_view path, uint32_t attributes);
|
||||||
bool DeletePath(const std::string_view path);
|
bool DeletePath(const std::string_view path);
|
||||||
|
|
||||||
X_STATUS OpenFile(const std::string_view path,
|
X_STATUS OpenFile(Entry* root_entry, const std::string_view path,
|
||||||
FileDisposition creation_disposition,
|
FileDisposition creation_disposition,
|
||||||
uint32_t desired_access, bool is_directory, File** out_file,
|
uint32_t desired_access, bool is_directory, File** out_file,
|
||||||
FileAction* out_action);
|
FileAction* out_action);
|
||||||
|
|
Loading…
Reference in New Issue