diff options
| author | 2018-07-06 10:51:32 -0400 | |
|---|---|---|
| committer | 2018-07-06 10:51:32 -0400 | |
| commit | 77c684c1140f6bf3fb7d4560d06d2efb1a2ee5e2 (patch) | |
| tree | 38ef6451732c5eecb0efdd198f3db4d33848453c /src/core/hle | |
| parent | Merge pull request #629 from Subv/depth_test (diff) | |
| download | yuzu-77c684c1140f6bf3fb7d4560d06d2efb1a2ee5e2.tar.gz yuzu-77c684c1140f6bf3fb7d4560d06d2efb1a2ee5e2.tar.xz yuzu-77c684c1140f6bf3fb7d4560d06d2efb1a2ee5e2.zip | |
Virtual Filesystem (#597)
* Add VfsFile and VfsDirectory classes
* Finish abstract Vfs classes
* Implement RealVfsFile (computer fs backend)
* Finish RealVfsFile and RealVfsDirectory
* Finished OffsetVfsFile
* More changes
* Fix import paths
* Major refactor
* Remove double const
* Use experimental/filesystem or filesystem depending on compiler
* Port partition_filesystem
* More changes
* More Overhaul
* FSP_SRV fixes
* Fixes and testing
* Try to get filesystem to compile
* Filesystem on linux
* Remove std::filesystem and document/test
* Compile fixes
* Missing include
* Bug fixes
* Fixes
* Rename v_file and v_dir
* clang-format fix
* Rename NGLOG_* to LOG_*
* Most review changes
* Fix TODO
* Guess 'main' to be Directory by filename
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 225 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 133 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 114 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.h | 2 |
5 files changed, 405 insertions, 71 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a871b3eaa..7bb13c735 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -621,7 +621,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { | |||
| 621 | IPC::ResponseBuilder rb{ctx, 4}; | 621 | IPC::ResponseBuilder rb{ctx, 4}; |
| 622 | 622 | ||
| 623 | FileSys::Path unused; | 623 | FileSys::Path unused; |
| 624 | auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused); | 624 | auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData); |
| 625 | if (savedata.Failed()) { | 625 | if (savedata.Failed()) { |
| 626 | // Create the save data and return an error indicating that the operation was performed. | 626 | // Create the save data and return an error indicating that the operation was performed. |
| 627 | FileSystem::FormatFileSystem(FileSystem::Type::SaveData); | 627 | FileSystem::FormatFileSystem(FileSystem::Type::SaveData); |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index f58b518b6..25810c165 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -2,36 +2,221 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <boost/container/flat_map.hpp> | 5 | #include "boost/container/flat_map.hpp" |
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/common_paths.h" | ||
| 6 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "core/core.h" | ||
| 10 | #include "core/file_sys/errors.h" | ||
| 7 | #include "core/file_sys/filesystem.h" | 11 | #include "core/file_sys/filesystem.h" |
| 8 | #include "core/file_sys/savedata_factory.h" | 12 | #include "core/file_sys/vfs.h" |
| 9 | #include "core/file_sys/sdmc_factory.h" | 13 | #include "core/file_sys/vfs_offset.h" |
| 14 | #include "core/file_sys/vfs_real.h" | ||
| 15 | #include "core/hle/kernel/process.h" | ||
| 10 | #include "core/hle/service/filesystem/filesystem.h" | 16 | #include "core/hle/service/filesystem/filesystem.h" |
| 11 | #include "core/hle/service/filesystem/fsp_srv.h" | 17 | #include "core/hle/service/filesystem/fsp_srv.h" |
| 12 | 18 | ||
| 13 | namespace Service::FileSystem { | 19 | namespace Service::FileSystem { |
| 14 | 20 | ||
| 21 | // Size of emulated sd card free space, reported in bytes. | ||
| 22 | // Just using 32GB because thats reasonable | ||
| 23 | // TODO(DarkLordZach): Eventually make this configurable in settings. | ||
| 24 | constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000; | ||
| 25 | |||
| 26 | static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, | ||
| 27 | const std::string& dir_name) { | ||
| 28 | if (dir_name == "." || dir_name == "" || dir_name == "/" || dir_name == "\\") | ||
| 29 | return base; | ||
| 30 | |||
| 31 | return base->GetDirectoryRelative(dir_name); | ||
| 32 | } | ||
| 33 | |||
| 34 | VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_) | ||
| 35 | : backing(backing_) {} | ||
| 36 | |||
| 37 | std::string VfsDirectoryServiceWrapper::GetName() const { | ||
| 38 | return backing->GetName(); | ||
| 39 | } | ||
| 40 | |||
| 41 | ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const { | ||
| 42 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 43 | auto file = dir->CreateFile(FileUtil::GetFilename(path)); | ||
| 44 | if (file == nullptr) | ||
| 45 | return ResultCode(-1); | ||
| 46 | if (!file->Resize(size)) | ||
| 47 | return ResultCode(-1); | ||
| 48 | return RESULT_SUCCESS; | ||
| 49 | } | ||
| 50 | |||
| 51 | ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const { | ||
| 52 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 53 | if (!backing->DeleteFile(FileUtil::GetFilename(path))) | ||
| 54 | return ResultCode(-1); | ||
| 55 | return RESULT_SUCCESS; | ||
| 56 | } | ||
| 57 | |||
| 58 | ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const { | ||
| 59 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 60 | if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty()) | ||
| 61 | dir = backing; | ||
| 62 | auto new_dir = dir->CreateSubdirectory(FileUtil::GetFilename(path)); | ||
| 63 | if (new_dir == nullptr) | ||
| 64 | return ResultCode(-1); | ||
| 65 | return RESULT_SUCCESS; | ||
| 66 | } | ||
| 67 | |||
| 68 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const { | ||
| 69 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 70 | if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) | ||
| 71 | return ResultCode(-1); | ||
| 72 | return RESULT_SUCCESS; | ||
| 73 | } | ||
| 74 | |||
| 75 | ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const { | ||
| 76 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 77 | if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) | ||
| 78 | return ResultCode(-1); | ||
| 79 | return RESULT_SUCCESS; | ||
| 80 | } | ||
| 81 | |||
| 82 | ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, | ||
| 83 | const std::string& dest_path) const { | ||
| 84 | auto src = backing->GetFileRelative(src_path); | ||
| 85 | if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { | ||
| 86 | // Use more-optimized vfs implementation rename. | ||
| 87 | if (src == nullptr) | ||
| 88 | return FileSys::ERROR_PATH_NOT_FOUND; | ||
| 89 | if (!src->Rename(FileUtil::GetFilename(dest_path))) | ||
| 90 | return ResultCode(-1); | ||
| 91 | return RESULT_SUCCESS; | ||
| 92 | } | ||
| 93 | |||
| 94 | // Move by hand -- TODO(DarkLordZach): Optimize | ||
| 95 | auto c_res = CreateFile(dest_path, src->GetSize()); | ||
| 96 | if (c_res != RESULT_SUCCESS) | ||
| 97 | return c_res; | ||
| 98 | |||
| 99 | auto dest = backing->GetFileRelative(dest_path); | ||
| 100 | ASSERT_MSG(dest != nullptr, "Newly created file with success cannot be found."); | ||
| 101 | |||
| 102 | ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(), | ||
| 103 | "Could not write all of the bytes but everything else has succeded."); | ||
| 104 | |||
| 105 | if (!src->GetContainingDirectory()->DeleteFile(FileUtil::GetFilename(src_path))) | ||
| 106 | return ResultCode(-1); | ||
| 107 | |||
| 108 | return RESULT_SUCCESS; | ||
| 109 | } | ||
| 110 | |||
| 111 | ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, | ||
| 112 | const std::string& dest_path) const { | ||
| 113 | auto src = GetDirectoryRelativeWrapped(backing, src_path); | ||
| 114 | if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { | ||
| 115 | // Use more-optimized vfs implementation rename. | ||
| 116 | if (src == nullptr) | ||
| 117 | return FileSys::ERROR_PATH_NOT_FOUND; | ||
| 118 | if (!src->Rename(FileUtil::GetFilename(dest_path))) | ||
| 119 | return ResultCode(-1); | ||
| 120 | return RESULT_SUCCESS; | ||
| 121 | } | ||
| 122 | |||
| 123 | // TODO(DarkLordZach): Implement renaming across the tree (move). | ||
| 124 | ASSERT_MSG(false, | ||
| 125 | "Could not rename directory with path \"{}\" to new path \"{}\" because parent dirs " | ||
| 126 | "don't match -- UNIMPLEMENTED", | ||
| 127 | src_path, dest_path); | ||
| 128 | |||
| 129 | return ResultCode(-1); | ||
| 130 | } | ||
| 131 | |||
| 132 | ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path, | ||
| 133 | FileSys::Mode mode) const { | ||
| 134 | auto file = backing->GetFileRelative(path); | ||
| 135 | if (file == nullptr) | ||
| 136 | return FileSys::ERROR_PATH_NOT_FOUND; | ||
| 137 | |||
| 138 | if ((static_cast<u32>(mode) & static_cast<u32>(FileSys::Mode::Append)) != 0) { | ||
| 139 | return MakeResult<FileSys::VirtualFile>( | ||
| 140 | std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize())); | ||
| 141 | } | ||
| 142 | |||
| 143 | return MakeResult<FileSys::VirtualFile>(file); | ||
| 144 | } | ||
| 145 | |||
| 146 | ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) { | ||
| 147 | auto dir = GetDirectoryRelativeWrapped(backing, path); | ||
| 148 | if (dir == nullptr) | ||
| 149 | return ResultCode(-1); | ||
| 150 | return MakeResult(dir); | ||
| 151 | } | ||
| 152 | |||
| 153 | u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const { | ||
| 154 | if (backing->IsWritable()) | ||
| 155 | return EMULATED_SD_REPORTED_SIZE; | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( | ||
| 161 | const std::string& path) const { | ||
| 162 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); | ||
| 163 | if (dir == nullptr) | ||
| 164 | return ResultCode(-1); | ||
| 165 | auto filename = FileUtil::GetFilename(path); | ||
| 166 | if (dir->GetFile(filename) != nullptr) | ||
| 167 | return MakeResult(FileSys::EntryType::File); | ||
| 168 | if (dir->GetSubdirectory(filename) != nullptr) | ||
| 169 | return MakeResult(FileSys::EntryType::Directory); | ||
| 170 | return ResultCode(-1); | ||
| 171 | } | ||
| 172 | |||
| 173 | // A deferred filesystem for nand save data. | ||
| 174 | // This must be deferred because the directory is dependent on title id, which is not set at | ||
| 175 | // registration time. | ||
| 176 | struct SaveDataDeferredFilesystem : DeferredFilesystem { | ||
| 177 | protected: | ||
| 178 | FileSys::VirtualDir CreateFilesystem() override { | ||
| 179 | u64 title_id = Core::CurrentProcess()->program_id; | ||
| 180 | // TODO(DarkLordZach): Users | ||
| 181 | u32 user_id = 0; | ||
| 182 | std::string nand_directory = fmt::format( | ||
| 183 | "{}save/{:016X}/{:08X}/", FileUtil::GetUserPath(D_NAND_IDX), title_id, user_id); | ||
| 184 | |||
| 185 | auto savedata = | ||
| 186 | std::make_shared<FileSys::RealVfsDirectory>(nand_directory, FileSys::Mode::Write); | ||
| 187 | return savedata; | ||
| 188 | } | ||
| 189 | }; | ||
| 190 | |||
| 15 | /** | 191 | /** |
| 16 | * Map of registered file systems, identified by type. Once an file system is registered here, it | 192 | * Map of registered file systems, identified by type. Once an file system is registered here, it |
| 17 | * is never removed until UnregisterFileSystems is called. | 193 | * is never removed until UnregisterFileSystems is called. |
| 18 | */ | 194 | */ |
| 19 | static boost::container::flat_map<Type, std::unique_ptr<FileSys::FileSystemFactory>> filesystem_map; | 195 | static boost::container::flat_map<Type, std::unique_ptr<DeferredFilesystem>> filesystem_map; |
| 196 | static FileSys::VirtualFile filesystem_romfs = nullptr; | ||
| 20 | 197 | ||
| 21 | ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type) { | 198 | ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& factory, Type type) { |
| 22 | auto result = filesystem_map.emplace(type, std::move(factory)); | 199 | auto result = filesystem_map.emplace(type, std::move(factory)); |
| 23 | 200 | ||
| 24 | bool inserted = result.second; | 201 | bool inserted = result.second; |
| 25 | ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); | 202 | ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); |
| 26 | 203 | ||
| 27 | auto& filesystem = result.first->second; | 204 | auto& filesystem = result.first->second; |
| 205 | LOG_DEBUG(Service_FS, "Registered file system with id code 0x{:08X}", static_cast<u32>(type)); | ||
| 206 | return RESULT_SUCCESS; | ||
| 207 | } | ||
| 208 | |||
| 209 | ResultCode RegisterRomFS(FileSys::VirtualFile filesystem) { | ||
| 210 | ASSERT_MSG(filesystem_romfs == nullptr, | ||
| 211 | "Tried to register more than one system with same id code"); | ||
| 212 | |||
| 213 | filesystem_romfs = filesystem; | ||
| 28 | LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(), | 214 | LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(), |
| 29 | static_cast<u32>(type)); | 215 | static_cast<u32>(Type::RomFS)); |
| 30 | return RESULT_SUCCESS; | 216 | return RESULT_SUCCESS; |
| 31 | } | 217 | } |
| 32 | 218 | ||
| 33 | ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, | 219 | ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) { |
| 34 | FileSys::Path& path) { | ||
| 35 | LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type)); | 220 | LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type)); |
| 36 | 221 | ||
| 37 | auto itr = filesystem_map.find(type); | 222 | auto itr = filesystem_map.find(type); |
| @@ -40,7 +225,13 @@ ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, | |||
| 40 | return ResultCode(-1); | 225 | return ResultCode(-1); |
| 41 | } | 226 | } |
| 42 | 227 | ||
| 43 | return itr->second->Open(path); | 228 | return MakeResult(itr->second->Get()); |
| 229 | } | ||
| 230 | |||
| 231 | ResultVal<FileSys::VirtualFile> OpenRomFS() { | ||
| 232 | if (filesystem_romfs == nullptr) | ||
| 233 | return ResultCode(-1); | ||
| 234 | return MakeResult(filesystem_romfs); | ||
| 44 | } | 235 | } |
| 45 | 236 | ||
| 46 | ResultCode FormatFileSystem(Type type) { | 237 | ResultCode FormatFileSystem(Type type) { |
| @@ -52,21 +243,21 @@ ResultCode FormatFileSystem(Type type) { | |||
| 52 | return ResultCode(-1); | 243 | return ResultCode(-1); |
| 53 | } | 244 | } |
| 54 | 245 | ||
| 55 | FileSys::Path unused; | 246 | return itr->second->Get()->GetParentDirectory()->DeleteSubdirectory( |
| 56 | return itr->second->Format(unused); | 247 | itr->second->Get()->GetName()) |
| 248 | ? RESULT_SUCCESS | ||
| 249 | : ResultCode(-1); | ||
| 57 | } | 250 | } |
| 58 | 251 | ||
| 59 | void RegisterFileSystems() { | 252 | void RegisterFileSystems() { |
| 60 | filesystem_map.clear(); | 253 | filesystem_map.clear(); |
| 254 | filesystem_romfs = nullptr; | ||
| 61 | 255 | ||
| 62 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | ||
| 63 | std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 256 | std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 257 | auto sdcard = std::make_shared<FileSys::RealVfsDirectory>(sd_directory, FileSys::Mode::Write); | ||
| 258 | RegisterFileSystem(std::make_unique<DeferredFilesystem>(sdcard), Type::SDMC); | ||
| 64 | 259 | ||
| 65 | auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory)); | 260 | RegisterFileSystem(std::make_unique<SaveDataDeferredFilesystem>(), Type::SaveData); |
| 66 | RegisterFileSystem(std::move(savedata), Type::SaveData); | ||
| 67 | |||
| 68 | auto sdcard = std::make_unique<FileSys::SDMC_Factory>(std::move(sd_directory)); | ||
| 69 | RegisterFileSystem(std::move(sdcard), Type::SDMC); | ||
| 70 | } | 261 | } |
| 71 | 262 | ||
| 72 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 263 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 56d26146e..d3de797f1 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "core/file_sys/filesystem.h" | ||
| 10 | #include "core/file_sys/vfs.h" | ||
| 9 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 10 | 12 | ||
| 11 | namespace FileSys { | 13 | namespace FileSys { |
| @@ -29,12 +31,136 @@ enum class Type { | |||
| 29 | SDMC = 3, | 31 | SDMC = 3, |
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| 34 | // A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of | ||
| 35 | // pointers and booleans. This makes using a VfsDirectory with switch services much easier and | ||
| 36 | // avoids repetitive code. | ||
| 37 | class VfsDirectoryServiceWrapper { | ||
| 38 | public: | ||
| 39 | explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing); | ||
| 40 | |||
| 41 | /** | ||
| 42 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | ||
| 43 | */ | ||
| 44 | std::string GetName() const; | ||
| 45 | |||
| 46 | /** | ||
| 47 | * Create a file specified by its path | ||
| 48 | * @param path Path relative to the Archive | ||
| 49 | * @param size The size of the new file, filled with zeroes | ||
| 50 | * @return Result of the operation | ||
| 51 | */ | ||
| 52 | ResultCode CreateFile(const std::string& path, u64 size) const; | ||
| 53 | |||
| 54 | /** | ||
| 55 | * Delete a file specified by its path | ||
| 56 | * @param path Path relative to the archive | ||
| 57 | * @return Result of the operation | ||
| 58 | */ | ||
| 59 | ResultCode DeleteFile(const std::string& path) const; | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Create a directory specified by its path | ||
| 63 | * @param path Path relative to the archive | ||
| 64 | * @return Result of the operation | ||
| 65 | */ | ||
| 66 | ResultCode CreateDirectory(const std::string& path) const; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Delete a directory specified by its path | ||
| 70 | * @param path Path relative to the archive | ||
| 71 | * @return Result of the operation | ||
| 72 | */ | ||
| 73 | ResultCode DeleteDirectory(const std::string& path) const; | ||
| 74 | |||
| 75 | /** | ||
| 76 | * Delete a directory specified by its path and anything under it | ||
| 77 | * @param path Path relative to the archive | ||
| 78 | * @return Result of the operation | ||
| 79 | */ | ||
| 80 | ResultCode DeleteDirectoryRecursively(const std::string& path) const; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Rename a File specified by its path | ||
| 84 | * @param src_path Source path relative to the archive | ||
| 85 | * @param dest_path Destination path relative to the archive | ||
| 86 | * @return Result of the operation | ||
| 87 | */ | ||
| 88 | ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Rename a Directory specified by its path | ||
| 92 | * @param src_path Source path relative to the archive | ||
| 93 | * @param dest_path Destination path relative to the archive | ||
| 94 | * @return Result of the operation | ||
| 95 | */ | ||
| 96 | ResultCode RenameDirectory(const std::string& src_path, const std::string& dest_path) const; | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Open a file specified by its path, using the specified mode | ||
| 100 | * @param path Path relative to the archive | ||
| 101 | * @param mode Mode to open the file with | ||
| 102 | * @return Opened file, or error code | ||
| 103 | */ | ||
| 104 | ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const; | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Open a directory specified by its path | ||
| 108 | * @param path Path relative to the archive | ||
| 109 | * @return Opened directory, or error code | ||
| 110 | */ | ||
| 111 | ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path); | ||
| 112 | |||
| 113 | /** | ||
| 114 | * Get the free space | ||
| 115 | * @return The number of free bytes in the archive | ||
| 116 | */ | ||
| 117 | u64 GetFreeSpaceSize() const; | ||
| 118 | |||
| 119 | /** | ||
| 120 | * Get the type of the specified path | ||
| 121 | * @return The type of the specified path or error code | ||
| 122 | */ | ||
| 123 | ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const; | ||
| 124 | |||
| 125 | private: | ||
| 126 | FileSys::VirtualDir backing; | ||
| 127 | }; | ||
| 128 | |||
| 129 | // A class that deferres the creation of a filesystem until a later time. | ||
| 130 | // This is useful if construction depends on a variable not known when the filesystem is registered. | ||
| 131 | // Construct this with a filesystem (VirtualDir) to avoid the deferrence feature or override the | ||
| 132 | // CreateFilesystem method which will be called on first use. | ||
| 133 | struct DeferredFilesystem { | ||
| 134 | DeferredFilesystem() = default; | ||
| 135 | |||
| 136 | explicit DeferredFilesystem(FileSys::VirtualDir vfs_directory) : fs(std::move(vfs_directory)) {} | ||
| 137 | |||
| 138 | FileSys::VirtualDir Get() { | ||
| 139 | if (fs == nullptr) | ||
| 140 | fs = CreateFilesystem(); | ||
| 141 | |||
| 142 | return fs; | ||
| 143 | } | ||
| 144 | |||
| 145 | virtual ~DeferredFilesystem() = default; | ||
| 146 | |||
| 147 | protected: | ||
| 148 | virtual FileSys::VirtualDir CreateFilesystem() { | ||
| 149 | return fs; | ||
| 150 | } | ||
| 151 | |||
| 152 | private: | ||
| 153 | FileSys::VirtualDir fs; | ||
| 154 | }; | ||
| 155 | |||
| 32 | /** | 156 | /** |
| 33 | * Registers a FileSystem, instances of which can later be opened using its IdCode. | 157 | * Registers a FileSystem, instances of which can later be opened using its IdCode. |
| 34 | * @param factory FileSystem backend interface to use | 158 | * @param factory FileSystem backend interface to use |
| 35 | * @param type Type used to access this type of FileSystem | 159 | * @param type Type used to access this type of FileSystem |
| 36 | */ | 160 | */ |
| 37 | ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type); | 161 | ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& fs, Type type); |
| 162 | |||
| 163 | ResultCode RegisterRomFS(FileSys::VirtualFile fs); | ||
| 38 | 164 | ||
| 39 | /** | 165 | /** |
| 40 | * Opens a file system | 166 | * Opens a file system |
| @@ -42,8 +168,9 @@ ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& fact | |||
| 42 | * @param path Path to the file system, used with Binary paths | 168 | * @param path Path to the file system, used with Binary paths |
| 43 | * @return FileSys::FileSystemBackend interface to the file system | 169 | * @return FileSys::FileSystemBackend interface to the file system |
| 44 | */ | 170 | */ |
| 45 | ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, | 171 | ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type); |
| 46 | FileSys::Path& path); | 172 | |
| 173 | ResultVal<FileSys::VirtualFile> OpenRomFS(); | ||
| 47 | 174 | ||
| 48 | /** | 175 | /** |
| 49 | * Formats a file system | 176 | * Formats a file system |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 216bfea0a..26e8a8c88 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -19,8 +19,8 @@ namespace Service::FileSystem { | |||
| 19 | 19 | ||
| 20 | class IStorage final : public ServiceFramework<IStorage> { | 20 | class IStorage final : public ServiceFramework<IStorage> { |
| 21 | public: | 21 | public: |
| 22 | IStorage(std::unique_ptr<FileSys::StorageBackend>&& backend) | 22 | IStorage(FileSys::VirtualFile backend_) |
| 23 | : ServiceFramework("IStorage"), backend(std::move(backend)) { | 23 | : ServiceFramework("IStorage"), backend(std::move(backend_)) { |
| 24 | static const FunctionInfo functions[] = { | 24 | static const FunctionInfo functions[] = { |
| 25 | {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"}, | 25 | {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"}, |
| 26 | {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"}, | 26 | {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"}, |
| @@ -29,7 +29,7 @@ public: | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | private: | 31 | private: |
| 32 | std::unique_ptr<FileSys::StorageBackend> backend; | 32 | FileSys::VirtualFile backend; |
| 33 | 33 | ||
| 34 | void Read(Kernel::HLERequestContext& ctx) { | 34 | void Read(Kernel::HLERequestContext& ctx) { |
| 35 | IPC::RequestParser rp{ctx}; | 35 | IPC::RequestParser rp{ctx}; |
| @@ -51,8 +51,8 @@ private: | |||
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | // Read the data from the Storage backend | 53 | // Read the data from the Storage backend |
| 54 | std::vector<u8> output(length); | 54 | std::vector<u8> output = backend->ReadBytes(length, offset); |
| 55 | ResultVal<size_t> res = backend->Read(offset, length, output.data()); | 55 | auto res = MakeResult<size_t>(output.size()); |
| 56 | if (res.Failed()) { | 56 | if (res.Failed()) { |
| 57 | IPC::ResponseBuilder rb{ctx, 2}; | 57 | IPC::ResponseBuilder rb{ctx, 2}; |
| 58 | rb.Push(res.Code()); | 58 | rb.Push(res.Code()); |
| @@ -69,8 +69,8 @@ private: | |||
| 69 | 69 | ||
| 70 | class IFile final : public ServiceFramework<IFile> { | 70 | class IFile final : public ServiceFramework<IFile> { |
| 71 | public: | 71 | public: |
| 72 | explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend) | 72 | explicit IFile(FileSys::VirtualFile backend_) |
| 73 | : ServiceFramework("IFile"), backend(std::move(backend)) { | 73 | : ServiceFramework("IFile"), backend(std::move(backend_)) { |
| 74 | static const FunctionInfo functions[] = { | 74 | static const FunctionInfo functions[] = { |
| 75 | {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, | 75 | {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, |
| 76 | {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, | 76 | {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, |
| @@ -80,7 +80,7 @@ public: | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | private: | 82 | private: |
| 83 | std::unique_ptr<FileSys::StorageBackend> backend; | 83 | FileSys::VirtualFile backend; |
| 84 | 84 | ||
| 85 | void Read(Kernel::HLERequestContext& ctx) { | 85 | void Read(Kernel::HLERequestContext& ctx) { |
| 86 | IPC::RequestParser rp{ctx}; | 86 | IPC::RequestParser rp{ctx}; |
| @@ -103,8 +103,8 @@ private: | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | // Read the data from the Storage backend | 105 | // Read the data from the Storage backend |
| 106 | std::vector<u8> output(length); | 106 | std::vector<u8> output = backend->ReadBytes(length, offset); |
| 107 | ResultVal<size_t> res = backend->Read(offset, length, output.data()); | 107 | auto res = MakeResult<size_t>(output.size()); |
| 108 | if (res.Failed()) { | 108 | if (res.Failed()) { |
| 109 | IPC::ResponseBuilder rb{ctx, 2}; | 109 | IPC::ResponseBuilder rb{ctx, 2}; |
| 110 | rb.Push(res.Code()); | 110 | rb.Push(res.Code()); |
| @@ -139,9 +139,10 @@ private: | |||
| 139 | return; | 139 | return; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | // Write the data to the Storage backend | ||
| 143 | std::vector<u8> data = ctx.ReadBuffer(); | 142 | std::vector<u8> data = ctx.ReadBuffer(); |
| 144 | ResultVal<size_t> res = backend->Write(offset, length, true, data.data()); | 143 | data.resize(length); |
| 144 | // Write the data to the Storage backend | ||
| 145 | auto res = MakeResult<size_t>(backend->WriteBytes(data, offset)); | ||
| 145 | if (res.Failed()) { | 146 | if (res.Failed()) { |
| 146 | IPC::ResponseBuilder rb{ctx, 2}; | 147 | IPC::ResponseBuilder rb{ctx, 2}; |
| 147 | rb.Push(res.Code()); | 148 | rb.Push(res.Code()); |
| @@ -154,7 +155,8 @@ private: | |||
| 154 | 155 | ||
| 155 | void Flush(Kernel::HLERequestContext& ctx) { | 156 | void Flush(Kernel::HLERequestContext& ctx) { |
| 156 | LOG_DEBUG(Service_FS, "called"); | 157 | LOG_DEBUG(Service_FS, "called"); |
| 157 | backend->Flush(); | 158 | |
| 159 | // Exists for SDK compatibiltity -- No need to flush file. | ||
| 158 | 160 | ||
| 159 | IPC::ResponseBuilder rb{ctx, 2}; | 161 | IPC::ResponseBuilder rb{ctx, 2}; |
| 160 | rb.Push(RESULT_SUCCESS); | 162 | rb.Push(RESULT_SUCCESS); |
| @@ -163,7 +165,7 @@ private: | |||
| 163 | void SetSize(Kernel::HLERequestContext& ctx) { | 165 | void SetSize(Kernel::HLERequestContext& ctx) { |
| 164 | IPC::RequestParser rp{ctx}; | 166 | IPC::RequestParser rp{ctx}; |
| 165 | const u64 size = rp.Pop<u64>(); | 167 | const u64 size = rp.Pop<u64>(); |
| 166 | backend->SetSize(size); | 168 | backend->Resize(size); |
| 167 | LOG_DEBUG(Service_FS, "called, size={}", size); | 169 | LOG_DEBUG(Service_FS, "called, size={}", size); |
| 168 | 170 | ||
| 169 | IPC::ResponseBuilder rb{ctx, 2}; | 171 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -180,19 +182,38 @@ private: | |||
| 180 | } | 182 | } |
| 181 | }; | 183 | }; |
| 182 | 184 | ||
| 185 | template <typename T> | ||
| 186 | static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data, | ||
| 187 | FileSys::EntryType type) { | ||
| 188 | for (const auto& new_entry : new_data) { | ||
| 189 | FileSys::Entry entry; | ||
| 190 | entry.filename[0] = '\0'; | ||
| 191 | std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1); | ||
| 192 | entry.type = type; | ||
| 193 | entry.file_size = new_entry->GetSize(); | ||
| 194 | entries.emplace_back(std::move(entry)); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 183 | class IDirectory final : public ServiceFramework<IDirectory> { | 198 | class IDirectory final : public ServiceFramework<IDirectory> { |
| 184 | public: | 199 | public: |
| 185 | explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend) | 200 | explicit IDirectory(FileSys::VirtualDir backend_) |
| 186 | : ServiceFramework("IDirectory"), backend(std::move(backend)) { | 201 | : ServiceFramework("IDirectory"), backend(std::move(backend_)) { |
| 187 | static const FunctionInfo functions[] = { | 202 | static const FunctionInfo functions[] = { |
| 188 | {0, &IDirectory::Read, "Read"}, | 203 | {0, &IDirectory::Read, "Read"}, |
| 189 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, | 204 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, |
| 190 | }; | 205 | }; |
| 191 | RegisterHandlers(functions); | 206 | RegisterHandlers(functions); |
| 207 | |||
| 208 | // Build entry index now to save time later. | ||
| 209 | BuildEntryIndex(entries, backend->GetFiles(), FileSys::File); | ||
| 210 | BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::Directory); | ||
| 192 | } | 211 | } |
| 193 | 212 | ||
| 194 | private: | 213 | private: |
| 195 | std::unique_ptr<FileSys::DirectoryBackend> backend; | 214 | FileSys::VirtualDir backend; |
| 215 | std::vector<FileSys::Entry> entries; | ||
| 216 | u64 next_entry_index = 0; | ||
| 196 | 217 | ||
| 197 | void Read(Kernel::HLERequestContext& ctx) { | 218 | void Read(Kernel::HLERequestContext& ctx) { |
| 198 | IPC::RequestParser rp{ctx}; | 219 | IPC::RequestParser rp{ctx}; |
| @@ -203,26 +224,31 @@ private: | |||
| 203 | // Calculate how many entries we can fit in the output buffer | 224 | // Calculate how many entries we can fit in the output buffer |
| 204 | u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); | 225 | u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); |
| 205 | 226 | ||
| 227 | // Cap at total number of entries. | ||
| 228 | u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); | ||
| 229 | |||
| 206 | // Read the data from the Directory backend | 230 | // Read the data from the Directory backend |
| 207 | std::vector<FileSys::Entry> entries(count_entries); | 231 | std::vector<FileSys::Entry> entry_data(entries.begin() + next_entry_index, |
| 208 | u64 read_entries = backend->Read(count_entries, entries.data()); | 232 | entries.begin() + next_entry_index + actual_entries); |
| 233 | |||
| 234 | next_entry_index += actual_entries; | ||
| 209 | 235 | ||
| 210 | // Convert the data into a byte array | 236 | // Convert the data into a byte array |
| 211 | std::vector<u8> output(entries.size() * sizeof(FileSys::Entry)); | 237 | std::vector<u8> output(entry_data.size() * sizeof(FileSys::Entry)); |
| 212 | std::memcpy(output.data(), entries.data(), output.size()); | 238 | std::memcpy(output.data(), entry_data.data(), output.size()); |
| 213 | 239 | ||
| 214 | // Write the data to memory | 240 | // Write the data to memory |
| 215 | ctx.WriteBuffer(output); | 241 | ctx.WriteBuffer(output); |
| 216 | 242 | ||
| 217 | IPC::ResponseBuilder rb{ctx, 4}; | 243 | IPC::ResponseBuilder rb{ctx, 4}; |
| 218 | rb.Push(RESULT_SUCCESS); | 244 | rb.Push(RESULT_SUCCESS); |
| 219 | rb.Push(read_entries); | 245 | rb.Push(actual_entries); |
| 220 | } | 246 | } |
| 221 | 247 | ||
| 222 | void GetEntryCount(Kernel::HLERequestContext& ctx) { | 248 | void GetEntryCount(Kernel::HLERequestContext& ctx) { |
| 223 | LOG_DEBUG(Service_FS, "called"); | 249 | LOG_DEBUG(Service_FS, "called"); |
| 224 | 250 | ||
| 225 | u64 count = backend->GetEntryCount(); | 251 | u64 count = entries.size() - next_entry_index; |
| 226 | 252 | ||
| 227 | IPC::ResponseBuilder rb{ctx, 4}; | 253 | IPC::ResponseBuilder rb{ctx, 4}; |
| 228 | rb.Push(RESULT_SUCCESS); | 254 | rb.Push(RESULT_SUCCESS); |
| @@ -232,7 +258,7 @@ private: | |||
| 232 | 258 | ||
| 233 | class IFileSystem final : public ServiceFramework<IFileSystem> { | 259 | class IFileSystem final : public ServiceFramework<IFileSystem> { |
| 234 | public: | 260 | public: |
| 235 | explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend) | 261 | explicit IFileSystem(FileSys::VirtualDir backend) |
| 236 | : ServiceFramework("IFileSystem"), backend(std::move(backend)) { | 262 | : ServiceFramework("IFileSystem"), backend(std::move(backend)) { |
| 237 | static const FunctionInfo functions[] = { | 263 | static const FunctionInfo functions[] = { |
| 238 | {0, &IFileSystem::CreateFile, "CreateFile"}, | 264 | {0, &IFileSystem::CreateFile, "CreateFile"}, |
| @@ -267,7 +293,7 @@ public: | |||
| 267 | LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size); | 293 | LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size); |
| 268 | 294 | ||
| 269 | IPC::ResponseBuilder rb{ctx, 2}; | 295 | IPC::ResponseBuilder rb{ctx, 2}; |
| 270 | rb.Push(backend->CreateFile(name, size)); | 296 | rb.Push(backend.CreateFile(name, size)); |
| 271 | } | 297 | } |
| 272 | 298 | ||
| 273 | void DeleteFile(Kernel::HLERequestContext& ctx) { | 299 | void DeleteFile(Kernel::HLERequestContext& ctx) { |
| @@ -279,7 +305,7 @@ public: | |||
| 279 | LOG_DEBUG(Service_FS, "called file {}", name); | 305 | LOG_DEBUG(Service_FS, "called file {}", name); |
| 280 | 306 | ||
| 281 | IPC::ResponseBuilder rb{ctx, 2}; | 307 | IPC::ResponseBuilder rb{ctx, 2}; |
| 282 | rb.Push(backend->DeleteFile(name)); | 308 | rb.Push(backend.DeleteFile(name)); |
| 283 | } | 309 | } |
| 284 | 310 | ||
| 285 | void CreateDirectory(Kernel::HLERequestContext& ctx) { | 311 | void CreateDirectory(Kernel::HLERequestContext& ctx) { |
| @@ -291,7 +317,7 @@ public: | |||
| 291 | LOG_DEBUG(Service_FS, "called directory {}", name); | 317 | LOG_DEBUG(Service_FS, "called directory {}", name); |
| 292 | 318 | ||
| 293 | IPC::ResponseBuilder rb{ctx, 2}; | 319 | IPC::ResponseBuilder rb{ctx, 2}; |
| 294 | rb.Push(backend->CreateDirectory(name)); | 320 | rb.Push(backend.CreateDirectory(name)); |
| 295 | } | 321 | } |
| 296 | 322 | ||
| 297 | void RenameFile(Kernel::HLERequestContext& ctx) { | 323 | void RenameFile(Kernel::HLERequestContext& ctx) { |
| @@ -309,7 +335,7 @@ public: | |||
| 309 | LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name); | 335 | LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name); |
| 310 | 336 | ||
| 311 | IPC::ResponseBuilder rb{ctx, 2}; | 337 | IPC::ResponseBuilder rb{ctx, 2}; |
| 312 | rb.Push(backend->RenameFile(src_name, dst_name)); | 338 | rb.Push(backend.RenameFile(src_name, dst_name)); |
| 313 | } | 339 | } |
| 314 | 340 | ||
| 315 | void OpenFile(Kernel::HLERequestContext& ctx) { | 341 | void OpenFile(Kernel::HLERequestContext& ctx) { |
| @@ -322,14 +348,14 @@ public: | |||
| 322 | 348 | ||
| 323 | LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode)); | 349 | LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode)); |
| 324 | 350 | ||
| 325 | auto result = backend->OpenFile(name, mode); | 351 | auto result = backend.OpenFile(name, mode); |
| 326 | if (result.Failed()) { | 352 | if (result.Failed()) { |
| 327 | IPC::ResponseBuilder rb{ctx, 2}; | 353 | IPC::ResponseBuilder rb{ctx, 2}; |
| 328 | rb.Push(result.Code()); | 354 | rb.Push(result.Code()); |
| 329 | return; | 355 | return; |
| 330 | } | 356 | } |
| 331 | 357 | ||
| 332 | auto file = std::move(result.Unwrap()); | 358 | IFile file(result.Unwrap()); |
| 333 | 359 | ||
| 334 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 360 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 335 | rb.Push(RESULT_SUCCESS); | 361 | rb.Push(RESULT_SUCCESS); |
| @@ -347,14 +373,14 @@ public: | |||
| 347 | 373 | ||
| 348 | LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags); | 374 | LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags); |
| 349 | 375 | ||
| 350 | auto result = backend->OpenDirectory(name); | 376 | auto result = backend.OpenDirectory(name); |
| 351 | if (result.Failed()) { | 377 | if (result.Failed()) { |
| 352 | IPC::ResponseBuilder rb{ctx, 2}; | 378 | IPC::ResponseBuilder rb{ctx, 2}; |
| 353 | rb.Push(result.Code()); | 379 | rb.Push(result.Code()); |
| 354 | return; | 380 | return; |
| 355 | } | 381 | } |
| 356 | 382 | ||
| 357 | auto directory = std::move(result.Unwrap()); | 383 | IDirectory directory(result.Unwrap()); |
| 358 | 384 | ||
| 359 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 385 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 360 | rb.Push(RESULT_SUCCESS); | 386 | rb.Push(RESULT_SUCCESS); |
| @@ -369,7 +395,7 @@ public: | |||
| 369 | 395 | ||
| 370 | LOG_DEBUG(Service_FS, "called file {}", name); | 396 | LOG_DEBUG(Service_FS, "called file {}", name); |
| 371 | 397 | ||
| 372 | auto result = backend->GetEntryType(name); | 398 | auto result = backend.GetEntryType(name); |
| 373 | if (result.Failed()) { | 399 | if (result.Failed()) { |
| 374 | IPC::ResponseBuilder rb{ctx, 2}; | 400 | IPC::ResponseBuilder rb{ctx, 2}; |
| 375 | rb.Push(result.Code()); | 401 | rb.Push(result.Code()); |
| @@ -389,7 +415,7 @@ public: | |||
| 389 | } | 415 | } |
| 390 | 416 | ||
| 391 | private: | 417 | private: |
| 392 | std::unique_ptr<FileSys::FileSystemBackend> backend; | 418 | VfsDirectoryServiceWrapper backend; |
| 393 | }; | 419 | }; |
| 394 | 420 | ||
| 395 | FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | 421 | FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { |
| @@ -490,8 +516,7 @@ void FSP_SRV::TryLoadRomFS() { | |||
| 490 | if (romfs) { | 516 | if (romfs) { |
| 491 | return; | 517 | return; |
| 492 | } | 518 | } |
| 493 | FileSys::Path unused; | 519 | auto res = OpenRomFS(); |
| 494 | auto res = OpenFileSystem(Type::RomFS, unused); | ||
| 495 | if (res.Succeeded()) { | 520 | if (res.Succeeded()) { |
| 496 | romfs = std::move(res.Unwrap()); | 521 | romfs = std::move(res.Unwrap()); |
| 497 | } | 522 | } |
| @@ -507,8 +532,7 @@ void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { | |||
| 507 | void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { | 532 | void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { |
| 508 | LOG_DEBUG(Service_FS, "called"); | 533 | LOG_DEBUG(Service_FS, "called"); |
| 509 | 534 | ||
| 510 | FileSys::Path unused; | 535 | IFileSystem filesystem(OpenFileSystem(Type::SDMC).Unwrap()); |
| 511 | auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); | ||
| 512 | 536 | ||
| 513 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 537 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 514 | rb.Push(RESULT_SUCCESS); | 538 | rb.Push(RESULT_SUCCESS); |
| @@ -531,8 +555,7 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { | |||
| 531 | void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { | 555 | void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { |
| 532 | LOG_WARNING(Service_FS, "(STUBBED) called"); | 556 | LOG_WARNING(Service_FS, "(STUBBED) called"); |
| 533 | 557 | ||
| 534 | FileSys::Path unused; | 558 | IFileSystem filesystem(OpenFileSystem(Type::SaveData).Unwrap()); |
| 535 | auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap(); | ||
| 536 | 559 | ||
| 537 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 560 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 538 | rb.Push(RESULT_SUCCESS); | 561 | rb.Push(RESULT_SUCCESS); |
| @@ -559,18 +582,11 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | |||
| 559 | return; | 582 | return; |
| 560 | } | 583 | } |
| 561 | 584 | ||
| 562 | // Attempt to open a StorageBackend interface to the RomFS | 585 | IStorage storage(romfs); |
| 563 | auto storage = romfs->OpenFile({}, {}); | ||
| 564 | if (storage.Failed()) { | ||
| 565 | LOG_CRITICAL(Service_FS, "no storage interface available!"); | ||
| 566 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 567 | rb.Push(storage.Code()); | ||
| 568 | return; | ||
| 569 | } | ||
| 570 | 586 | ||
| 571 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 587 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 572 | rb.Push(RESULT_SUCCESS); | 588 | rb.Push(RESULT_SUCCESS); |
| 573 | rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap())); | 589 | rb.PushIpcInterface<IStorage>(std::move(storage)); |
| 574 | } | 590 | } |
| 575 | 591 | ||
| 576 | void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { | 592 | void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index acb78fac1..b1ef6397f 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h | |||
| @@ -29,7 +29,7 @@ private: | |||
| 29 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); | 29 | void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); |
| 30 | void OpenRomStorage(Kernel::HLERequestContext& ctx); | 30 | void OpenRomStorage(Kernel::HLERequestContext& ctx); |
| 31 | 31 | ||
| 32 | std::unique_ptr<FileSys::FileSystemBackend> romfs; | 32 | FileSys::VirtualFile romfs; |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | } // namespace Service::FileSystem | 35 | } // namespace Service::FileSystem |