[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:
gibbed 2020-04-20 00:44:19 -05:00 committed by Rick Gibbed
parent 725f3ce17f
commit 1c2d6753bb
9 changed files with 33 additions and 60 deletions

View File

@ -90,6 +90,8 @@ dword_result_t NtCreateFile(lpdword_t handle_out, dword_t desired_access,
auto object_name =
kernel_memory()->TranslateVirtual<X_ANSI_STRING*>(object_attrs->name_ptr);
vfs::Entry* root_entry = nullptr;
// Compute path, possibly attrs relative.
auto target_path = util::TranslateAnsiString(kernel_memory(), object_name);
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_true(root_file->type() == XObject::Type::kTypeFile);
// Resolve the file using the device the root directory is part of.
auto device = root_file->device();
target_path = xe::utf8::join_guest_paths(
{device->mount_path(), root_file->path(), target_path});
root_entry = root_file->entry();
}
// Attempt open (or create).
vfs::File* vfs_file;
vfs::FileAction file_action;
X_STATUS result = kernel_state()->file_system()->OpenFile(
target_path, vfs::FileDisposition((uint32_t)creation_disposition),
desired_access,
root_entry, target_path,
vfs::FileDisposition((uint32_t)creation_disposition), desired_access,
(create_options & CreateOptions::FILE_DIRECTORY_FILE) != 0, &vfs_file,
&file_action);
object_ref<XFile> file = nullptr;

View File

@ -263,8 +263,8 @@ object_ref<XFile> XFile::Restore(KernelState* kernel_state,
vfs::File* vfs_file = nullptr;
vfs::FileAction action;
auto res = kernel_state->file_system()->OpenFile(
abs_path, vfs::FileDisposition::kOpen, access, is_directory, &vfs_file,
&action);
nullptr, abs_path, vfs::FileDisposition::kOpen, access, is_directory,
&vfs_file, &action);
if (XFAILED(res)) {
XELOGE("Failed to open XFile: error {:08X}", res);
return object_ref<XFile>(file);

View 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
// be in the form:
// some\PATH.foo
XELOGFS("DiscImageDevice::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;
return root_entry_->ResolvePath(path);
}
DiscImageDevice::Error DiscImageDevice::Verify(ParseState* state) {

View File

@ -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
// be in the form:
// some\PATH.foo
XELOGFS("HostPathDevice::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;
return root_entry_->ResolvePath(path);
}
void HostPathDevice::PopulateEntry(HostPathEntry* parent_entry) {

View File

@ -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
// be in the form:
// some\PATH.foo
XELOGFS("StfsContainerDevice::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;
return root_entry_->ResolvePath(path);
}
StfsContainerDevice::Error StfsContainerDevice::ReadPackageType(

View File

@ -58,6 +58,19 @@ Entry* Entry::GetChild(const std::string_view name) {
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,
size_t* current_index) {
auto global_lock = global_critical_region_.Acquire();

View File

@ -97,6 +97,7 @@ class Entry {
bool is_read_only() const;
Entry* GetChild(const std::string_view name);
Entry* ResolvePath(const std::string_view path);
const std::vector<std::unique_ptr<Entry>>& children() const {
return children_;

View File

@ -126,11 +126,6 @@ Entry* VirtualFileSystem::ResolvePath(const std::string_view 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,
uint32_t attributes) {
// Create all required directories recursively.
@ -173,7 +168,8 @@ bool VirtualFileSystem::DeletePath(const std::string_view path) {
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,
uint32_t desired_access, bool is_directory,
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.
Entry* parent_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) {
*out_action = FileAction::kDoesNotExist;
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);
entry = parent_entry->GetChild(file_name);
} 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).

View File

@ -37,12 +37,11 @@ class VirtualFileSystem {
bool FindSymbolicLink(const std::string_view path, std::string& target);
Entry* ResolvePath(const std::string_view path);
Entry* ResolveBasePath(const std::string_view path);
Entry* CreatePath(const std::string_view path, uint32_t attributes);
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,
uint32_t desired_access, bool is_directory, File** out_file,
FileAction* out_action);