From 275abf35cf517d6017b4a4b84959cc73c336e402 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 25 Jun 2018 19:43:14 -0400 Subject: [PATCH] FSP_SRV fixes --- src/core/CMakeLists.txt | 3 +- src/core/file_sys/vfs.cpp | 11 ++ src/core/file_sys/vfs.h | 3 + src/core/file_sys/vfs_offset.cpp | 13 +- .../hle/service/filesystem/filesystem.cpp | 114 +++++++++++++++++- src/core/hle/service/filesystem/filesystem.h | 2 +- 6 files changed, 135 insertions(+), 11 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c627dc8544..582294a57b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -20,8 +20,7 @@ add_library(core STATIC file_sys/path_parser.h file_sys/program_metadata.cpp file_sys/program_metadata.h - file_sys/romfs.cpp - file_sys/romfs.h + file_sys/storage.h file_sys/vfs.cpp file_sys/vfs.h file_sys/vfs_offset.cpp diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index af31148430..fa513ae1a3 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp @@ -69,6 +69,17 @@ std::shared_ptr VfsDirectory::GetFileAbsolute(const filesystem::path& p return GetParentDirectory()->GetFileAbsolute(path); } +std::shared_ptr VfsDirectory::GetDirectoryRelative(const filesystem::path& path) const { + return ""; +} + +std::shared_ptr VfsDirectory::GetDirectoryAbsolute(const filesystem::path& path) const { + if (IsRoot()) + return GetDirectoryRelative(path); + + return GetParentDirectory()->GetDirectoryAbsolute(path); +} + std::shared_ptr VfsDirectory::GetFile(const std::string& name) const { const auto& files = GetFiles(); const auto& iter = std::find_if(files.begin(), files.end(), [&name](const auto& file1) { diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 637b9139b2..5aa2edd42e 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h @@ -97,6 +97,9 @@ struct VfsDirectory : NonCopyable { virtual std::shared_ptr GetFileRelative(const filesystem::path& path) const; virtual std::shared_ptr GetFileAbsolute(const filesystem::path& path) const; + virtual std::shared_ptr GetDirectoryRelative(const filesystem::path& path) const; + virtual std::shared_ptr GetDirectoryAbsolute(const filesystem::path& path) const; + virtual std::vector> GetFiles() const = 0; virtual std::shared_ptr GetFile(const std::string& name) const; diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp index b25a945202..c02a8c00d4 100644 --- a/src/core/file_sys/vfs_offset.cpp +++ b/src/core/file_sys/vfs_offset.cpp @@ -6,7 +6,7 @@ namespace FileSys { -OffsetVfsFile::OffsetVfsFile(std::shared_ptr file_, u64 size_, u64 offset_, +OffsetVfsFile::OffsetVfsFile(std::shared_ptr file_, size_t size_, size_t offset_, const std::string& name_) : file(file_), offset(offset_), size(size_), name(name_) {} @@ -14,17 +14,20 @@ std::string OffsetVfsFile::GetName() const { return name.empty() ? file->GetName() : name; } -u64 OffsetVfsFile::GetSize() const { +size_t OffsetVfsFile::GetSize() const { return size; } -bool OffsetVfsFile::Resize(u64 new_size) { +bool OffsetVfsFile::Resize(size_t new_size) { if (offset + new_size < file->GetSize()) { size = new_size; - return true; + } else { + auto res = file->Resize(offset + new_size); + if (!res) return false; + size = new_size; } - return false; + return true; } std::shared_ptr OffsetVfsFile::GetContainingDirectory() const { diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index b98ac46ae4..803cae6131 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -2,7 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include "boost/container/flat_map.hpp" +#include "common/common_paths.h" #include "common/file_util.h" #include "core/file_sys/filesystem.h" #include "core/file_sys/vfs.h" @@ -12,8 +13,110 @@ namespace Service::FileSystem { -ResultVal OpenRomFS() { - return romfs; +VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(v_dir backing_) : backing(backing_) { } + +std::string VfsDirectoryServiceWrapper::GetName() const { + return backing->GetName(); +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const { + filesystem::path s_path(path); + auto dir = backing->GetDirectoryRelative(s_path.parent_path()); + auto file = dir->CreateFile(path.filename().string()); + if (file == nullptr) return ResultCode(-1); + if (!file->Resize(size)) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const { + filesystem::path s_path(path); + auto dir = backing->GetDirectoryRelative(s_path.parent_path()); + if (!backing->DeleteFile(s_path.filename().string())) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const { + filesystem::path s_path(path); + auto dir = backing->GetDirectoryRelative(s_path.parent_path()); + auto new_dir = dir->CreateSubdirectory(path.filename().name); + if (new_dir == nullptr) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const { + filesystem::path s_path(path); + auto dir = backing->GetDirectoryRelative(s_path.parent_path()); + if (!dir->DeleteSubdirectory(path.filename().string())) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const { + filesystem::path s_path(path); + auto dir = backing->GetDirectoryRelative(s_path.parent_path()); + if (!dir->DeleteSubdirectoryRecursive(path.filename().string())) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, const std::string& dest_path) const { + filesystem::path s_path(src_path); + auto file = backing->GetFileRelative(s_path); + file->GetContainingDirectory()->DeleteFile(file->GetName()); + auto res_code = CreateFile(dest_path, file->GetSize()); + if (res_code != RESULT_SUCCESS) return res_code; + auto file2 = backing->GetFileRelative(filesystem::path(dest_path)); + if (file2->WriteBytes(file->ReadAllBytes() != file->GetSize()) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultCode +VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, const std::string& dest_path) const { + filesystem::path s_path(src_path); + auto file = backing->GetFileRelative(s_path); + file->GetContainingDirectory()->DeleteFile(file->GetName()); + auto res_code = CreateFile(dest_path, file->GetSize()); + if (res_code != RESULT_SUCCESS) return res_code; + auto file2 = backing->GetFileRelative(filesystem::path(dest_path)); + if (file2->WriteBytes(file->ReadAllBytes() != file->GetSize())) return ResultCode(-1); + return RESULT_SUCCESS; +} + +// TODO(DarkLordZach): Verify path usage. +ResultVal VfsDirectoryServiceWrapper::OpenFile(const std::string& path, FileSys::Mode mode) const { + auto file = backing->GetFileRelative(filesystem::path(path)); + if (file == nullptr) return ResultVal(-1); + if (mode == FileSys::Mode::Append) return MakeResult(std::make_shared(file, 0, file->GetSize())); + else if (mode == FileSys::Mode::Write && file->IsWritable()) return file; + else if (mode == FileSys::Mode::Read && file->IsReadable()) return file; + return ResultVal(-1); +} + +// TODO(DarkLordZach): Verify path usage. +ResultVal VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) const { + auto dir = backing->GetDirectoryRelative(filesystem::path(path)); + if (dir == nullptr) return ResultVal(-1); + return MakeResult(RESULT_SUCCESS, dir); +} + +u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const { + // TODO(DarkLordZach): Infinite? Actual? Is this actually used productively or...? + return 0; +} + +// TODO(DarkLordZach): Verify path usage. +ResultVal VfsDirectoryServiceWrapper::GetEntryType(const std::string& path) const { + filesystem::path r_path(path); + auto dir = backing->GetDirectoryRelative(r_path.parent_path()); + if (dir == nullptr) return ResultVal(-1); + if (dir->GetFile(r_path.filename().string()) != nullptr) return MakeResult(FileSys::EntryType::File); + if (dir->GetSubdirectory(r_path.filename().string()) != nullptr) return MakeResult(FileSys::EntryType::Directory); + return ResultVal(-1); } /** @@ -57,6 +160,11 @@ ResultVal OpenFileSystem(Type type) { return MakeResult(itr->second); } +ResultVal OpenRomFS() { + if (filesystem_romfs == nullptr) return ResultVal(-1); + return MakeResult(filesystem_romfs); +} + ResultCode FormatFileSystem(Type type) { LOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast(type)); diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index e3a86a54c9..4e10080e0c 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -34,7 +34,7 @@ class VfsDirectoryServiceWrapper { v_dir backing; public: - VfsDirectoryServiceWrapper(v_dir backing); + explicit VfsDirectoryServiceWrapper(v_dir backing); /** * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)