diff options
| author | 2024-01-26 09:55:25 -0500 | |
|---|---|---|
| committer | 2024-01-26 09:55:25 -0500 | |
| commit | 55482ab5dce463d5014498b006c18a90d0d004e6 (patch) | |
| tree | b343faa9cadc692265efb4b6b88e157c97ef76d2 /src/core/hle | |
| parent | Merge pull request #12796 from t895/controller-optimizations (diff) | |
| parent | Address review comments and fix compilation problems (diff) | |
| download | yuzu-55482ab5dce463d5014498b006c18a90d0d004e6.tar.gz yuzu-55482ab5dce463d5014498b006c18a90d0d004e6.tar.xz yuzu-55482ab5dce463d5014498b006c18a90d0d004e6.zip | |
Merge pull request #12707 from FearlessTobi/fs-housekeeping
fs: Various cleanups & add path class for later use
Diffstat (limited to 'src/core/hle')
35 files changed, 792 insertions, 627 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 749f51f69..316370266 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -189,14 +189,14 @@ enum class ErrorModule : u32 { | |||
| 189 | union Result { | 189 | union Result { |
| 190 | u32 raw; | 190 | u32 raw; |
| 191 | 191 | ||
| 192 | BitField<0, 9, ErrorModule> module; | 192 | using Module = BitField<0, 9, ErrorModule>; |
| 193 | BitField<9, 13, u32> description; | 193 | using Description = BitField<9, 13, u32>; |
| 194 | 194 | ||
| 195 | Result() = default; | 195 | Result() = default; |
| 196 | constexpr explicit Result(u32 raw_) : raw(raw_) {} | 196 | constexpr explicit Result(u32 raw_) : raw(raw_) {} |
| 197 | 197 | ||
| 198 | constexpr Result(ErrorModule module_, u32 description_) | 198 | constexpr Result(ErrorModule module_, u32 description_) |
| 199 | : raw(module.FormatValue(module_) | description.FormatValue(description_)) {} | 199 | : raw(Module::FormatValue(module_) | Description::FormatValue(description_)) {} |
| 200 | 200 | ||
| 201 | [[nodiscard]] constexpr bool IsSuccess() const { | 201 | [[nodiscard]] constexpr bool IsSuccess() const { |
| 202 | return raw == 0; | 202 | return raw == 0; |
| @@ -211,7 +211,15 @@ union Result { | |||
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | [[nodiscard]] constexpr u32 GetInnerValue() const { | 213 | [[nodiscard]] constexpr u32 GetInnerValue() const { |
| 214 | return static_cast<u32>(module.Value()) | (description << module.bits); | 214 | return raw; |
| 215 | } | ||
| 216 | |||
| 217 | [[nodiscard]] constexpr ErrorModule GetModule() const { | ||
| 218 | return Module::ExtractValue(raw); | ||
| 219 | } | ||
| 220 | |||
| 221 | [[nodiscard]] constexpr u32 GetDescription() const { | ||
| 222 | return Description::ExtractValue(raw); | ||
| 215 | } | 223 | } |
| 216 | 224 | ||
| 217 | [[nodiscard]] constexpr bool Includes(Result result) const { | 225 | [[nodiscard]] constexpr bool Includes(Result result) const { |
| @@ -274,8 +282,9 @@ public: | |||
| 274 | } | 282 | } |
| 275 | 283 | ||
| 276 | [[nodiscard]] constexpr bool Includes(Result other) const { | 284 | [[nodiscard]] constexpr bool Includes(Result other) const { |
| 277 | return code.module == other.module && code.description <= other.description && | 285 | return code.GetModule() == other.GetModule() && |
| 278 | other.description <= description_end; | 286 | code.GetDescription() <= other.GetDescription() && |
| 287 | other.GetDescription() <= description_end; | ||
| 279 | } | 288 | } |
| 280 | 289 | ||
| 281 | private: | 290 | private: |
| @@ -330,6 +339,16 @@ constexpr bool EvaluateResultFailure(const Result& r) { | |||
| 330 | return R_FAILED(r); | 339 | return R_FAILED(r); |
| 331 | } | 340 | } |
| 332 | 341 | ||
| 342 | template <auto... R> | ||
| 343 | constexpr bool EvaluateAnyResultIncludes(const Result& r) { | ||
| 344 | return ((r == R) || ...); | ||
| 345 | } | ||
| 346 | |||
| 347 | template <auto... R> | ||
| 348 | constexpr bool EvaluateResultNotIncluded(const Result& r) { | ||
| 349 | return !EvaluateAnyResultIncludes<R...>(r); | ||
| 350 | } | ||
| 351 | |||
| 333 | template <typename T> | 352 | template <typename T> |
| 334 | constexpr void UpdateCurrentResultReference(T result_reference, Result result) = delete; | 353 | constexpr void UpdateCurrentResultReference(T result_reference, Result result) = delete; |
| 335 | // Intentionally not defined | 354 | // Intentionally not defined |
| @@ -371,6 +390,13 @@ constexpr void UpdateCurrentResultReference<const Result>(Result result_referenc | |||
| 371 | DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \ | 390 | DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \ |
| 372 | ON_RESULT_SUCCESS_2 | 391 | ON_RESULT_SUCCESS_2 |
| 373 | 392 | ||
| 393 | #define ON_RESULT_INCLUDED_2(...) \ | ||
| 394 | ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateAnyResultIncludes<__VA_ARGS__>) | ||
| 395 | |||
| 396 | #define ON_RESULT_INCLUDED(...) \ | ||
| 397 | DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__); \ | ||
| 398 | ON_RESULT_INCLUDED_2(__VA_ARGS__) | ||
| 399 | |||
| 374 | constexpr inline Result __TmpCurrentResultReference = ResultSuccess; | 400 | constexpr inline Result __TmpCurrentResultReference = ResultSuccess; |
| 375 | 401 | ||
| 376 | /// Returns a result. | 402 | /// Returns a result. |
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp index 5d17c353f..084bc138c 100644 --- a/src/core/hle/service/am/applets/applet_error.cpp +++ b/src/core/hle/service/am/applets/applet_error.cpp | |||
| @@ -27,8 +27,8 @@ struct ErrorCode { | |||
| 27 | 27 | ||
| 28 | static constexpr ErrorCode FromResult(Result result) { | 28 | static constexpr ErrorCode FromResult(Result result) { |
| 29 | return { | 29 | return { |
| 30 | .error_category{2000 + static_cast<u32>(result.module.Value())}, | 30 | .error_category{2000 + static_cast<u32>(result.GetModule())}, |
| 31 | .error_number{result.description.Value()}, | 31 | .error_number{result.GetDescription()}, |
| 32 | }; | 32 | }; |
| 33 | } | 33 | } |
| 34 | 34 | ||
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp index b0ea2b381..19057ad7b 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.cpp +++ b/src/core/hle/service/am/applets/applet_web_browser.cpp | |||
| @@ -9,13 +9,13 @@ | |||
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/file_sys/content_archive.h" | 11 | #include "core/file_sys/content_archive.h" |
| 12 | #include "core/file_sys/mode.h" | 12 | #include "core/file_sys/fs_filesystem.h" |
| 13 | #include "core/file_sys/nca_metadata.h" | 13 | #include "core/file_sys/nca_metadata.h" |
| 14 | #include "core/file_sys/patch_manager.h" | 14 | #include "core/file_sys/patch_manager.h" |
| 15 | #include "core/file_sys/registered_cache.h" | 15 | #include "core/file_sys/registered_cache.h" |
| 16 | #include "core/file_sys/romfs.h" | 16 | #include "core/file_sys/romfs.h" |
| 17 | #include "core/file_sys/system_archive/system_archive.h" | 17 | #include "core/file_sys/system_archive/system_archive.h" |
| 18 | #include "core/file_sys/vfs_vector.h" | 18 | #include "core/file_sys/vfs/vfs_vector.h" |
| 19 | #include "core/frontend/applets/web_browser.h" | 19 | #include "core/frontend/applets/web_browser.h" |
| 20 | #include "core/hle/result.h" | 20 | #include "core/hle/result.h" |
| 21 | #include "core/hle/service/am/am.h" | 21 | #include "core/hle/service/am/am.h" |
| @@ -213,7 +213,7 @@ void ExtractSharedFonts(Core::System& system) { | |||
| 213 | std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]); | 213 | std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]); |
| 214 | 214 | ||
| 215 | const auto temp_dir = system.GetFilesystem()->CreateDirectory( | 215 | const auto temp_dir = system.GetFilesystem()->CreateDirectory( |
| 216 | Common::FS::PathToUTF8String(fonts_dir), FileSys::Mode::ReadWrite); | 216 | Common::FS::PathToUTF8String(fonts_dir), FileSys::OpenMode::ReadWrite); |
| 217 | 217 | ||
| 218 | const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]); | 218 | const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]); |
| 219 | 219 | ||
| @@ -333,7 +333,7 @@ void WebBrowser::ExtractOfflineRomFS() { | |||
| 333 | const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs); | 333 | const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs); |
| 334 | 334 | ||
| 335 | const auto temp_dir = system.GetFilesystem()->CreateDirectory( | 335 | const auto temp_dir = system.GetFilesystem()->CreateDirectory( |
| 336 | Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); | 336 | Common::FS::PathToUTF8String(offline_cache_dir), FileSys::OpenMode::ReadWrite); |
| 337 | 337 | ||
| 338 | FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir); | 338 | FileSys::VfsRawCopyD(extracted_romfs_dir, temp_dir); |
| 339 | } | 339 | } |
diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h index 99fe18659..36adb2510 100644 --- a/src/core/hle/service/am/applets/applet_web_browser.h +++ b/src/core/hle/service/am/applets/applet_web_browser.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <optional> | 7 | #include <optional> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/file_sys/vfs_types.h" | 10 | #include "core/file_sys/vfs/vfs_types.h" |
| 11 | #include "core/hle/result.h" | 11 | #include "core/hle/result.h" |
| 12 | #include "core/hle/service/am/applets/applet_web_browser_types.h" | 12 | #include "core/hle/service/am/applets/applet_web_browser_types.h" |
| 13 | #include "core/hle/service/am/applets/applets.h" | 13 | #include "core/hle/service/am/applets/applets.h" |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index bd4ca753b..05581e6e0 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -139,7 +139,8 @@ private: | |||
| 139 | ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1); | 139 | ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1); |
| 140 | } | 140 | } |
| 141 | } else { | 141 | } else { |
| 142 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description); | 142 | LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", |
| 143 | result.GetDescription()); | ||
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | IPC::ResponseBuilder rb{ctx, 2}; | 146 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h index 205ed0702..aa36d29d5 100644 --- a/src/core/hle/service/bcat/backend/backend.h +++ b/src/core/hle/service/bcat/backend/backend.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/file_sys/vfs_types.h" | 11 | #include "core/file_sys/vfs/vfs_types.h" |
| 12 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 13 | #include "core/hle/service/kernel_helpers.h" | 13 | #include "core/hle/service/kernel_helpers.h" |
| 14 | 14 | ||
diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp index a6281913a..76d7bb139 100644 --- a/src/core/hle/service/bcat/bcat_module.cpp +++ b/src/core/hle/service/bcat/bcat_module.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "common/settings.h" | 8 | #include "common/settings.h" |
| 9 | #include "common/string_util.h" | 9 | #include "common/string_util.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/file_sys/vfs.h" | 11 | #include "core/file_sys/vfs/vfs.h" |
| 12 | #include "core/hle/kernel/k_readable_event.h" | 12 | #include "core/hle/kernel/k_readable_event.h" |
| 13 | #include "core/hle/service/bcat/backend/backend.h" | 13 | #include "core/hle/service/bcat/backend/backend.h" |
| 14 | #include "core/hle/service/bcat/bcat.h" | 14 | #include "core/hle/service/bcat/bcat.h" |
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 9925720a3..69acb3a8b 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp | |||
| @@ -202,14 +202,14 @@ Result IAlbumAccessorService::TranslateResult(Result in_result) { | |||
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | if ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) { | 204 | if ((in_result.raw & 0x3801ff) == ResultUnknown1024.raw) { |
| 205 | if (in_result.description - 0x514 < 100) { | 205 | if (in_result.GetDescription() - 0x514 < 100) { |
| 206 | return ResultInvalidFileData; | 206 | return ResultInvalidFileData; |
| 207 | } | 207 | } |
| 208 | if (in_result.description - 0x5dc < 100) { | 208 | if (in_result.GetDescription() - 0x5dc < 100) { |
| 209 | return ResultInvalidFileData; | 209 | return ResultInvalidFileData; |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | if (in_result.description - 0x578 < 100) { | 212 | if (in_result.GetDescription() - 0x578 < 100) { |
| 213 | if (in_result == ResultFileCountLimit) { | 213 | if (in_result == ResultFileCountLimit) { |
| 214 | return ResultUnknown22; | 214 | return ResultUnknown22; |
| 215 | } | 215 | } |
| @@ -244,9 +244,10 @@ Result IAlbumAccessorService::TranslateResult(Result in_result) { | |||
| 244 | return ResultUnknown1024; | 244 | return ResultUnknown1024; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | if (in_result.module == ErrorModule::FS) { | 247 | if (in_result.GetModule() == ErrorModule::FS) { |
| 248 | if ((in_result.description >> 0xc < 0x7d) || (in_result.description - 1000 < 2000) || | 248 | if ((in_result.GetDescription() >> 0xc < 0x7d) || |
| 249 | (((in_result.description - 3000) >> 3) < 0x271)) { | 249 | (in_result.GetDescription() - 1000 < 2000) || |
| 250 | (((in_result.GetDescription() - 3000) >> 3) < 0x271)) { | ||
| 250 | // TODO: Translate FS error | 251 | // TODO: Translate FS error |
| 251 | return in_result; | 252 | return in_result; |
| 252 | } | 253 | } |
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 31da86074..dfcac1ffd 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp | |||
| @@ -73,8 +73,8 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F | |||
| 73 | "Program entry point: 0x{:16X}\n" | 73 | "Program entry point: 0x{:16X}\n" |
| 74 | "\n", | 74 | "\n", |
| 75 | Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, | 75 | Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, |
| 76 | 2000 + static_cast<u32>(error_code.module.Value()), | 76 | 2000 + static_cast<u32>(error_code.GetModule()), |
| 77 | static_cast<u32>(error_code.description.Value()), info.set_flags, info.program_entry_point); | 77 | static_cast<u32>(error_code.GetDescription()), info.set_flags, info.program_entry_point); |
| 78 | if (info.backtrace_size != 0x0) { | 78 | if (info.backtrace_size != 0x0) { |
| 79 | crash_report += "Registers:\n"; | 79 | crash_report += "Registers:\n"; |
| 80 | for (size_t i = 0; i < info.registers.size(); i++) { | 80 | for (size_t i = 0; i < info.registers.size(); i++) { |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index ca6d8d607..ae230afc0 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -12,18 +12,17 @@ | |||
| 12 | #include "core/file_sys/card_image.h" | 12 | #include "core/file_sys/card_image.h" |
| 13 | #include "core/file_sys/control_metadata.h" | 13 | #include "core/file_sys/control_metadata.h" |
| 14 | #include "core/file_sys/errors.h" | 14 | #include "core/file_sys/errors.h" |
| 15 | #include "core/file_sys/mode.h" | ||
| 16 | #include "core/file_sys/patch_manager.h" | 15 | #include "core/file_sys/patch_manager.h" |
| 17 | #include "core/file_sys/registered_cache.h" | 16 | #include "core/file_sys/registered_cache.h" |
| 18 | #include "core/file_sys/romfs_factory.h" | 17 | #include "core/file_sys/romfs_factory.h" |
| 19 | #include "core/file_sys/savedata_factory.h" | 18 | #include "core/file_sys/savedata_factory.h" |
| 20 | #include "core/file_sys/sdmc_factory.h" | 19 | #include "core/file_sys/sdmc_factory.h" |
| 21 | #include "core/file_sys/vfs.h" | 20 | #include "core/file_sys/vfs/vfs.h" |
| 22 | #include "core/file_sys/vfs_offset.h" | 21 | #include "core/file_sys/vfs/vfs_offset.h" |
| 23 | #include "core/hle/service/filesystem/filesystem.h" | 22 | #include "core/hle/service/filesystem/filesystem.h" |
| 24 | #include "core/hle/service/filesystem/fsp_ldr.h" | 23 | #include "core/hle/service/filesystem/fsp/fsp_ldr.h" |
| 25 | #include "core/hle/service/filesystem/fsp_pr.h" | 24 | #include "core/hle/service/filesystem/fsp/fsp_pr.h" |
| 26 | #include "core/hle/service/filesystem/fsp_srv.h" | 25 | #include "core/hle/service/filesystem/fsp/fsp_srv.h" |
| 27 | #include "core/hle/service/filesystem/romfs_controller.h" | 26 | #include "core/hle/service/filesystem/romfs_controller.h" |
| 28 | #include "core/hle/service/filesystem/save_data_controller.h" | 27 | #include "core/hle/service/filesystem/save_data_controller.h" |
| 29 | #include "core/hle/service/server_manager.h" | 28 | #include "core/hle/service/server_manager.h" |
| @@ -53,12 +52,12 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size | |||
| 53 | std::string path(Common::FS::SanitizePath(path_)); | 52 | std::string path(Common::FS::SanitizePath(path_)); |
| 54 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 53 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 55 | if (dir == nullptr) { | 54 | if (dir == nullptr) { |
| 56 | return FileSys::ERROR_PATH_NOT_FOUND; | 55 | return FileSys::ResultPathNotFound; |
| 57 | } | 56 | } |
| 58 | 57 | ||
| 59 | FileSys::EntryType entry_type{}; | 58 | FileSys::DirectoryEntryType entry_type{}; |
| 60 | if (GetEntryType(&entry_type, path) == ResultSuccess) { | 59 | if (GetEntryType(&entry_type, path) == ResultSuccess) { |
| 61 | return FileSys::ERROR_PATH_ALREADY_EXISTS; | 60 | return FileSys::ResultPathAlreadyExists; |
| 62 | } | 61 | } |
| 63 | 62 | ||
| 64 | auto file = dir->CreateFile(Common::FS::GetFilename(path)); | 63 | auto file = dir->CreateFile(Common::FS::GetFilename(path)); |
| @@ -82,7 +81,7 @@ Result VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const { | |||
| 82 | 81 | ||
| 83 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 82 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 84 | if (dir == nullptr || dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { | 83 | if (dir == nullptr || dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { |
| 85 | return FileSys::ERROR_PATH_NOT_FOUND; | 84 | return FileSys::ResultPathNotFound; |
| 86 | } | 85 | } |
| 87 | if (!dir->DeleteFile(Common::FS::GetFilename(path))) { | 86 | if (!dir->DeleteFile(Common::FS::GetFilename(path))) { |
| 88 | // TODO(DarkLordZach): Find a better error code for this | 87 | // TODO(DarkLordZach): Find a better error code for this |
| @@ -153,12 +152,12 @@ Result VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, | |||
| 153 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { | 152 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { |
| 154 | // Use more-optimized vfs implementation rename. | 153 | // Use more-optimized vfs implementation rename. |
| 155 | if (src == nullptr) { | 154 | if (src == nullptr) { |
| 156 | return FileSys::ERROR_PATH_NOT_FOUND; | 155 | return FileSys::ResultPathNotFound; |
| 157 | } | 156 | } |
| 158 | 157 | ||
| 159 | if (dst && Common::FS::Exists(dst->GetFullPath())) { | 158 | if (dst && Common::FS::Exists(dst->GetFullPath())) { |
| 160 | LOG_ERROR(Service_FS, "File at new_path={} already exists", dst->GetFullPath()); | 159 | LOG_ERROR(Service_FS, "File at new_path={} already exists", dst->GetFullPath()); |
| 161 | return FileSys::ERROR_PATH_ALREADY_EXISTS; | 160 | return FileSys::ResultPathAlreadyExists; |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { | 163 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { |
| @@ -195,7 +194,7 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, | |||
| 195 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { | 194 | if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { |
| 196 | // Use more-optimized vfs implementation rename. | 195 | // Use more-optimized vfs implementation rename. |
| 197 | if (src == nullptr) | 196 | if (src == nullptr) |
| 198 | return FileSys::ERROR_PATH_NOT_FOUND; | 197 | return FileSys::ResultPathNotFound; |
| 199 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { | 198 | if (!src->Rename(Common::FS::GetFilename(dest_path))) { |
| 200 | // TODO(DarkLordZach): Find a better error code for this | 199 | // TODO(DarkLordZach): Find a better error code for this |
| 201 | return ResultUnknown; | 200 | return ResultUnknown; |
| @@ -214,7 +213,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, | |||
| 214 | } | 213 | } |
| 215 | 214 | ||
| 216 | Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, | 215 | Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, |
| 217 | const std::string& path_, FileSys::Mode mode) const { | 216 | const std::string& path_, |
| 217 | FileSys::OpenMode mode) const { | ||
| 218 | const std::string path(Common::FS::SanitizePath(path_)); | 218 | const std::string path(Common::FS::SanitizePath(path_)); |
| 219 | std::string_view npath = path; | 219 | std::string_view npath = path; |
| 220 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { | 220 | while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { |
| @@ -223,10 +223,10 @@ Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, | |||
| 223 | 223 | ||
| 224 | auto file = backing->GetFileRelative(npath); | 224 | auto file = backing->GetFileRelative(npath); |
| 225 | if (file == nullptr) { | 225 | if (file == nullptr) { |
| 226 | return FileSys::ERROR_PATH_NOT_FOUND; | 226 | return FileSys::ResultPathNotFound; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | if (mode == FileSys::Mode::Append) { | 229 | if (mode == FileSys::OpenMode::AllowAppend) { |
| 230 | *out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); | 230 | *out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); |
| 231 | } else { | 231 | } else { |
| 232 | *out_file = file; | 232 | *out_file = file; |
| @@ -241,50 +241,50 @@ Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_direct | |||
| 241 | auto dir = GetDirectoryRelativeWrapped(backing, path); | 241 | auto dir = GetDirectoryRelativeWrapped(backing, path); |
| 242 | if (dir == nullptr) { | 242 | if (dir == nullptr) { |
| 243 | // TODO(DarkLordZach): Find a better error code for this | 243 | // TODO(DarkLordZach): Find a better error code for this |
| 244 | return FileSys::ERROR_PATH_NOT_FOUND; | 244 | return FileSys::ResultPathNotFound; |
| 245 | } | 245 | } |
| 246 | *out_directory = dir; | 246 | *out_directory = dir; |
| 247 | return ResultSuccess; | 247 | return ResultSuccess; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, | 250 | Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::DirectoryEntryType* out_entry_type, |
| 251 | const std::string& path_) const { | 251 | const std::string& path_) const { |
| 252 | std::string path(Common::FS::SanitizePath(path_)); | 252 | std::string path(Common::FS::SanitizePath(path_)); |
| 253 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 253 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 254 | if (dir == nullptr) { | 254 | if (dir == nullptr) { |
| 255 | return FileSys::ERROR_PATH_NOT_FOUND; | 255 | return FileSys::ResultPathNotFound; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | auto filename = Common::FS::GetFilename(path); | 258 | auto filename = Common::FS::GetFilename(path); |
| 259 | // TODO(Subv): Some games use the '/' path, find out what this means. | 259 | // TODO(Subv): Some games use the '/' path, find out what this means. |
| 260 | if (filename.empty()) { | 260 | if (filename.empty()) { |
| 261 | *out_entry_type = FileSys::EntryType::Directory; | 261 | *out_entry_type = FileSys::DirectoryEntryType::Directory; |
| 262 | return ResultSuccess; | 262 | return ResultSuccess; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | if (dir->GetFile(filename) != nullptr) { | 265 | if (dir->GetFile(filename) != nullptr) { |
| 266 | *out_entry_type = FileSys::EntryType::File; | 266 | *out_entry_type = FileSys::DirectoryEntryType::File; |
| 267 | return ResultSuccess; | 267 | return ResultSuccess; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | if (dir->GetSubdirectory(filename) != nullptr) { | 270 | if (dir->GetSubdirectory(filename) != nullptr) { |
| 271 | *out_entry_type = FileSys::EntryType::Directory; | 271 | *out_entry_type = FileSys::DirectoryEntryType::Directory; |
| 272 | return ResultSuccess; | 272 | return ResultSuccess; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | return FileSys::ERROR_PATH_NOT_FOUND; | 275 | return FileSys::ResultPathNotFound; |
| 276 | } | 276 | } |
| 277 | 277 | ||
| 278 | Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( | 278 | Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( |
| 279 | FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const { | 279 | FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const { |
| 280 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); | 280 | auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); |
| 281 | if (dir == nullptr) { | 281 | if (dir == nullptr) { |
| 282 | return FileSys::ERROR_PATH_NOT_FOUND; | 282 | return FileSys::ResultPathNotFound; |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | FileSys::EntryType entry_type; | 285 | FileSys::DirectoryEntryType entry_type; |
| 286 | if (GetEntryType(&entry_type, path) != ResultSuccess) { | 286 | if (GetEntryType(&entry_type, path) != ResultSuccess) { |
| 287 | return FileSys::ERROR_PATH_NOT_FOUND; | 287 | return FileSys::ResultPathNotFound; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | *out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path)); | 290 | *out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path)); |
| @@ -317,7 +317,7 @@ Result FileSystemController::OpenProcess( | |||
| 317 | 317 | ||
| 318 | const auto it = registrations.find(process_id); | 318 | const auto it = registrations.find(process_id); |
| 319 | if (it == registrations.end()) { | 319 | if (it == registrations.end()) { |
| 320 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 320 | return FileSys::ResultTargetNotFound; |
| 321 | } | 321 | } |
| 322 | 322 | ||
| 323 | *out_program_id = it->second.program_id; | 323 | *out_program_id = it->second.program_id; |
| @@ -347,7 +347,7 @@ std::shared_ptr<SaveDataController> FileSystemController::OpenSaveDataController | |||
| 347 | std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory( | 347 | std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory( |
| 348 | ProgramId program_id) { | 348 | ProgramId program_id) { |
| 349 | using YuzuPath = Common::FS::YuzuPath; | 349 | using YuzuPath = Common::FS::YuzuPath; |
| 350 | const auto rw_mode = FileSys::Mode::ReadWrite; | 350 | const auto rw_mode = FileSys::OpenMode::ReadWrite; |
| 351 | 351 | ||
| 352 | auto vfs = system.GetFilesystem(); | 352 | auto vfs = system.GetFilesystem(); |
| 353 | const auto nand_directory = | 353 | const auto nand_directory = |
| @@ -360,12 +360,12 @@ Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const { | |||
| 360 | LOG_TRACE(Service_FS, "Opening SDMC"); | 360 | LOG_TRACE(Service_FS, "Opening SDMC"); |
| 361 | 361 | ||
| 362 | if (sdmc_factory == nullptr) { | 362 | if (sdmc_factory == nullptr) { |
| 363 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | 363 | return FileSys::ResultPortSdCardNoDevice; |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | auto sdmc = sdmc_factory->Open(); | 366 | auto sdmc = sdmc_factory->Open(); |
| 367 | if (sdmc == nullptr) { | 367 | if (sdmc == nullptr) { |
| 368 | return FileSys::ERROR_SD_CARD_NOT_FOUND; | 368 | return FileSys::ResultPortSdCardNoDevice; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | *out_sdmc = sdmc; | 371 | *out_sdmc = sdmc; |
| @@ -377,12 +377,12 @@ Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_parti | |||
| 377 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); | 377 | LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); |
| 378 | 378 | ||
| 379 | if (bis_factory == nullptr) { | 379 | if (bis_factory == nullptr) { |
| 380 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 380 | return FileSys::ResultTargetNotFound; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | auto part = bis_factory->OpenPartition(id); | 383 | auto part = bis_factory->OpenPartition(id); |
| 384 | if (part == nullptr) { | 384 | if (part == nullptr) { |
| 385 | return FileSys::ERROR_INVALID_ARGUMENT; | 385 | return FileSys::ResultInvalidArgument; |
| 386 | } | 386 | } |
| 387 | 387 | ||
| 388 | *out_bis_partition = part; | 388 | *out_bis_partition = part; |
| @@ -394,12 +394,12 @@ Result FileSystemController::OpenBISPartitionStorage( | |||
| 394 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); | 394 | LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); |
| 395 | 395 | ||
| 396 | if (bis_factory == nullptr) { | 396 | if (bis_factory == nullptr) { |
| 397 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 397 | return FileSys::ResultTargetNotFound; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | auto part = bis_factory->OpenPartitionStorage(id, system.GetFilesystem()); | 400 | auto part = bis_factory->OpenPartitionStorage(id, system.GetFilesystem()); |
| 401 | if (part == nullptr) { | 401 | if (part == nullptr) { |
| 402 | return FileSys::ERROR_INVALID_ARGUMENT; | 402 | return FileSys::ResultInvalidArgument; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | *out_bis_partition_storage = part; | 405 | *out_bis_partition_storage = part; |
| @@ -686,15 +686,15 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove | |||
| 686 | using YuzuPath = Common::FS::YuzuPath; | 686 | using YuzuPath = Common::FS::YuzuPath; |
| 687 | const auto sdmc_dir_path = Common::FS::GetYuzuPath(YuzuPath::SDMCDir); | 687 | const auto sdmc_dir_path = Common::FS::GetYuzuPath(YuzuPath::SDMCDir); |
| 688 | const auto sdmc_load_dir_path = sdmc_dir_path / "atmosphere/contents"; | 688 | const auto sdmc_load_dir_path = sdmc_dir_path / "atmosphere/contents"; |
| 689 | const auto rw_mode = FileSys::Mode::ReadWrite; | 689 | const auto rw_mode = FileSys::OpenMode::ReadWrite; |
| 690 | 690 | ||
| 691 | auto nand_directory = | 691 | auto nand_directory = |
| 692 | vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode); | 692 | vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::NANDDir), rw_mode); |
| 693 | auto sd_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_dir_path), rw_mode); | 693 | auto sd_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_dir_path), rw_mode); |
| 694 | auto load_directory = | 694 | auto load_directory = vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), |
| 695 | vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::LoadDir), FileSys::Mode::Read); | 695 | FileSys::OpenMode::Read); |
| 696 | auto sd_load_directory = | 696 | auto sd_load_directory = vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path), |
| 697 | vfs.OpenDirectory(Common::FS::PathToUTF8String(sdmc_load_dir_path), FileSys::Mode::Read); | 697 | FileSys::OpenMode::Read); |
| 698 | auto dump_directory = | 698 | auto dump_directory = |
| 699 | vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode); | 699 | vfs.OpenDirectory(Common::FS::GetYuzuPathString(YuzuPath::DumpDir), rw_mode); |
| 700 | 700 | ||
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 48f37d289..718500385 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -4,9 +4,11 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <mutex> | ||
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 8 | #include "core/file_sys/directory.h" | 9 | #include "core/file_sys/fs_directory.h" |
| 9 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/fs_filesystem.h" |
| 11 | #include "core/file_sys/vfs/vfs.h" | ||
| 10 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 11 | 13 | ||
| 12 | namespace Core { | 14 | namespace Core { |
| @@ -26,7 +28,6 @@ class XCI; | |||
| 26 | 28 | ||
| 27 | enum class BisPartitionId : u32; | 29 | enum class BisPartitionId : u32; |
| 28 | enum class ContentRecordType : u8; | 30 | enum class ContentRecordType : u8; |
| 29 | enum class Mode : u32; | ||
| 30 | enum class SaveDataSpaceId : u8; | 31 | enum class SaveDataSpaceId : u8; |
| 31 | enum class SaveDataType : u8; | 32 | enum class SaveDataType : u8; |
| 32 | enum class StorageId : u8; | 33 | enum class StorageId : u8; |
| @@ -57,13 +58,6 @@ enum class ImageDirectoryId : u32 { | |||
| 57 | SdCard, | 58 | SdCard, |
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | enum class OpenDirectoryMode : u64 { | ||
| 61 | Directory = (1 << 0), | ||
| 62 | File = (1 << 1), | ||
| 63 | All = Directory | File | ||
| 64 | }; | ||
| 65 | DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode); | ||
| 66 | |||
| 67 | using ProcessId = u64; | 61 | using ProcessId = u64; |
| 68 | using ProgramId = u64; | 62 | using ProgramId = u64; |
| 69 | 63 | ||
| @@ -237,7 +231,7 @@ public: | |||
| 237 | * @return Opened file, or error code | 231 | * @return Opened file, or error code |
| 238 | */ | 232 | */ |
| 239 | Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, | 233 | Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, |
| 240 | FileSys::Mode mode) const; | 234 | FileSys::OpenMode mode) const; |
| 241 | 235 | ||
| 242 | /** | 236 | /** |
| 243 | * Open a directory specified by its path | 237 | * Open a directory specified by its path |
| @@ -250,7 +244,7 @@ public: | |||
| 250 | * Get the type of the specified path | 244 | * Get the type of the specified path |
| 251 | * @return The type of the specified path or error code | 245 | * @return The type of the specified path or error code |
| 252 | */ | 246 | */ |
| 253 | Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const; | 247 | Result GetEntryType(FileSys::DirectoryEntryType* out_entry_type, const std::string& path) const; |
| 254 | 248 | ||
| 255 | /** | 249 | /** |
| 256 | * Get the timestamp of the specified path | 250 | * Get the timestamp of the specified path |
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp b/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp new file mode 100644 index 000000000..39690018b --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/file_sys/fs_filesystem.h" | ||
| 5 | #include "core/file_sys/savedata_factory.h" | ||
| 6 | #include "core/hle/service/filesystem/fsp/fs_i_directory.h" | ||
| 7 | #include "core/hle/service/ipc_helpers.h" | ||
| 8 | |||
| 9 | namespace Service::FileSystem { | ||
| 10 | |||
| 11 | template <typename T> | ||
| 12 | static void BuildEntryIndex(std::vector<FileSys::DirectoryEntry>& entries, | ||
| 13 | const std::vector<T>& new_data, FileSys::DirectoryEntryType type) { | ||
| 14 | entries.reserve(entries.size() + new_data.size()); | ||
| 15 | |||
| 16 | for (const auto& new_entry : new_data) { | ||
| 17 | auto name = new_entry->GetName(); | ||
| 18 | |||
| 19 | if (type == FileSys::DirectoryEntryType::File && | ||
| 20 | name == FileSys::GetSaveDataSizeFileName()) { | ||
| 21 | continue; | ||
| 22 | } | ||
| 23 | |||
| 24 | entries.emplace_back(name, static_cast<s8>(type), | ||
| 25 | type == FileSys::DirectoryEntryType::Directory ? 0 | ||
| 26 | : new_entry->GetSize()); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | IDirectory::IDirectory(Core::System& system_, FileSys::VirtualDir backend_, | ||
| 31 | FileSys::OpenDirectoryMode mode) | ||
| 32 | : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { | ||
| 33 | static const FunctionInfo functions[] = { | ||
| 34 | {0, &IDirectory::Read, "Read"}, | ||
| 35 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, | ||
| 36 | }; | ||
| 37 | RegisterHandlers(functions); | ||
| 38 | |||
| 39 | // TODO(DarkLordZach): Verify that this is the correct behavior. | ||
| 40 | // Build entry index now to save time later. | ||
| 41 | if (True(mode & FileSys::OpenDirectoryMode::Directory)) { | ||
| 42 | BuildEntryIndex(entries, backend->GetSubdirectories(), | ||
| 43 | FileSys::DirectoryEntryType::Directory); | ||
| 44 | } | ||
| 45 | if (True(mode & FileSys::OpenDirectoryMode::File)) { | ||
| 46 | BuildEntryIndex(entries, backend->GetFiles(), FileSys::DirectoryEntryType::File); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void IDirectory::Read(HLERequestContext& ctx) { | ||
| 51 | LOG_DEBUG(Service_FS, "called."); | ||
| 52 | |||
| 53 | // Calculate how many entries we can fit in the output buffer | ||
| 54 | const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::DirectoryEntry>(); | ||
| 55 | |||
| 56 | // Cap at total number of entries. | ||
| 57 | const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); | ||
| 58 | |||
| 59 | // Determine data start and end | ||
| 60 | const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index); | ||
| 61 | const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries); | ||
| 62 | const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); | ||
| 63 | |||
| 64 | next_entry_index += actual_entries; | ||
| 65 | |||
| 66 | // Write the data to memory | ||
| 67 | ctx.WriteBuffer(begin, range_size); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 70 | rb.Push(ResultSuccess); | ||
| 71 | rb.Push(actual_entries); | ||
| 72 | } | ||
| 73 | |||
| 74 | void IDirectory::GetEntryCount(HLERequestContext& ctx) { | ||
| 75 | LOG_DEBUG(Service_FS, "called"); | ||
| 76 | |||
| 77 | u64 count = entries.size() - next_entry_index; | ||
| 78 | |||
| 79 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 80 | rb.Push(ResultSuccess); | ||
| 81 | rb.Push(count); | ||
| 82 | } | ||
| 83 | |||
| 84 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_directory.h b/src/core/hle/service/filesystem/fsp/fs_i_directory.h new file mode 100644 index 000000000..793ecfcd7 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/file_sys/vfs/vfs.h" | ||
| 7 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | |||
| 10 | namespace FileSys { | ||
| 11 | struct DirectoryEntry; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Service::FileSystem { | ||
| 15 | |||
| 16 | class IDirectory final : public ServiceFramework<IDirectory> { | ||
| 17 | public: | ||
| 18 | explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, | ||
| 19 | FileSys::OpenDirectoryMode mode); | ||
| 20 | |||
| 21 | private: | ||
| 22 | FileSys::VirtualDir backend; | ||
| 23 | std::vector<FileSys::DirectoryEntry> entries; | ||
| 24 | u64 next_entry_index = 0; | ||
| 25 | |||
| 26 | void Read(HLERequestContext& ctx); | ||
| 27 | void GetEntryCount(HLERequestContext& ctx); | ||
| 28 | }; | ||
| 29 | |||
| 30 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_file.cpp b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp new file mode 100644 index 000000000..9a18f6ec5 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.cpp | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/file_sys/errors.h" | ||
| 5 | #include "core/hle/service/filesystem/fsp/fs_i_file.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::FileSystem { | ||
| 9 | |||
| 10 | IFile::IFile(Core::System& system_, FileSys::VirtualFile backend_) | ||
| 11 | : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, &IFile::Read, "Read"}, | ||
| 14 | {1, &IFile::Write, "Write"}, | ||
| 15 | {2, &IFile::Flush, "Flush"}, | ||
| 16 | {3, &IFile::SetSize, "SetSize"}, | ||
| 17 | {4, &IFile::GetSize, "GetSize"}, | ||
| 18 | {5, nullptr, "OperateRange"}, | ||
| 19 | {6, nullptr, "OperateRangeWithBuffer"}, | ||
| 20 | }; | ||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | void IFile::Read(HLERequestContext& ctx) { | ||
| 25 | IPC::RequestParser rp{ctx}; | ||
| 26 | const u64 option = rp.Pop<u64>(); | ||
| 27 | const s64 offset = rp.Pop<s64>(); | ||
| 28 | const s64 length = rp.Pop<s64>(); | ||
| 29 | |||
| 30 | LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, length); | ||
| 31 | |||
| 32 | // Error checking | ||
| 33 | if (length < 0) { | ||
| 34 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 35 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 36 | rb.Push(FileSys::ResultInvalidSize); | ||
| 37 | return; | ||
| 38 | } | ||
| 39 | if (offset < 0) { | ||
| 40 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 41 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 42 | rb.Push(FileSys::ResultInvalidOffset); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | // Read the data from the Storage backend | ||
| 47 | std::vector<u8> output = backend->ReadBytes(length, offset); | ||
| 48 | |||
| 49 | // Write the data to memory | ||
| 50 | ctx.WriteBuffer(output); | ||
| 51 | |||
| 52 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 53 | rb.Push(ResultSuccess); | ||
| 54 | rb.Push(static_cast<u64>(output.size())); | ||
| 55 | } | ||
| 56 | |||
| 57 | void IFile::Write(HLERequestContext& ctx) { | ||
| 58 | IPC::RequestParser rp{ctx}; | ||
| 59 | const u64 option = rp.Pop<u64>(); | ||
| 60 | const s64 offset = rp.Pop<s64>(); | ||
| 61 | const s64 length = rp.Pop<s64>(); | ||
| 62 | |||
| 63 | LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, length); | ||
| 64 | |||
| 65 | // Error checking | ||
| 66 | if (length < 0) { | ||
| 67 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 68 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 69 | rb.Push(FileSys::ResultInvalidSize); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | if (offset < 0) { | ||
| 73 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 74 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 75 | rb.Push(FileSys::ResultInvalidOffset); | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | |||
| 79 | const auto data = ctx.ReadBuffer(); | ||
| 80 | |||
| 81 | ASSERT_MSG(static_cast<s64>(data.size()) <= length, | ||
| 82 | "Attempting to write more data than requested (requested={:016X}, actual={:016X}).", | ||
| 83 | length, data.size()); | ||
| 84 | |||
| 85 | // Write the data to the Storage backend | ||
| 86 | const auto write_size = | ||
| 87 | static_cast<std::size_t>(std::distance(data.begin(), data.begin() + length)); | ||
| 88 | const std::size_t written = backend->Write(data.data(), write_size, offset); | ||
| 89 | |||
| 90 | ASSERT_MSG(static_cast<s64>(written) == length, | ||
| 91 | "Could not write all bytes to file (requested={:016X}, actual={:016X}).", length, | ||
| 92 | written); | ||
| 93 | |||
| 94 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 95 | rb.Push(ResultSuccess); | ||
| 96 | } | ||
| 97 | |||
| 98 | void IFile::Flush(HLERequestContext& ctx) { | ||
| 99 | LOG_DEBUG(Service_FS, "called"); | ||
| 100 | |||
| 101 | // Exists for SDK compatibiltity -- No need to flush file. | ||
| 102 | |||
| 103 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 104 | rb.Push(ResultSuccess); | ||
| 105 | } | ||
| 106 | |||
| 107 | void IFile::SetSize(HLERequestContext& ctx) { | ||
| 108 | IPC::RequestParser rp{ctx}; | ||
| 109 | const u64 size = rp.Pop<u64>(); | ||
| 110 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 111 | |||
| 112 | backend->Resize(size); | ||
| 113 | |||
| 114 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 115 | rb.Push(ResultSuccess); | ||
| 116 | } | ||
| 117 | |||
| 118 | void IFile::GetSize(HLERequestContext& ctx) { | ||
| 119 | const u64 size = backend->GetSize(); | ||
| 120 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 121 | |||
| 122 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 123 | rb.Push(ResultSuccess); | ||
| 124 | rb.Push<u64>(size); | ||
| 125 | } | ||
| 126 | |||
| 127 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_file.h b/src/core/hle/service/filesystem/fsp/fs_i_file.h new file mode 100644 index 000000000..5e5430c67 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Service::FileSystem { | ||
| 10 | |||
| 11 | class IFile final : public ServiceFramework<IFile> { | ||
| 12 | public: | ||
| 13 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_); | ||
| 14 | |||
| 15 | private: | ||
| 16 | FileSys::VirtualFile backend; | ||
| 17 | |||
| 18 | void Read(HLERequestContext& ctx); | ||
| 19 | void Write(HLERequestContext& ctx); | ||
| 20 | void Flush(HLERequestContext& ctx); | ||
| 21 | void SetSize(HLERequestContext& ctx); | ||
| 22 | void GetSize(HLERequestContext& ctx); | ||
| 23 | }; | ||
| 24 | |||
| 25 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp new file mode 100644 index 000000000..efa394dd1 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/string_util.h" | ||
| 5 | #include "core/hle/service/filesystem/fsp/fs_i_directory.h" | ||
| 6 | #include "core/hle/service/filesystem/fsp/fs_i_file.h" | ||
| 7 | #include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" | ||
| 8 | #include "core/hle/service/ipc_helpers.h" | ||
| 9 | |||
| 10 | namespace Service::FileSystem { | ||
| 11 | |||
| 12 | IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) | ||
| 13 | : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( | ||
| 14 | size_)} { | ||
| 15 | static const FunctionInfo functions[] = { | ||
| 16 | {0, &IFileSystem::CreateFile, "CreateFile"}, | ||
| 17 | {1, &IFileSystem::DeleteFile, "DeleteFile"}, | ||
| 18 | {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, | ||
| 19 | {3, &IFileSystem::DeleteDirectory, "DeleteDirectory"}, | ||
| 20 | {4, &IFileSystem::DeleteDirectoryRecursively, "DeleteDirectoryRecursively"}, | ||
| 21 | {5, &IFileSystem::RenameFile, "RenameFile"}, | ||
| 22 | {6, nullptr, "RenameDirectory"}, | ||
| 23 | {7, &IFileSystem::GetEntryType, "GetEntryType"}, | ||
| 24 | {8, &IFileSystem::OpenFile, "OpenFile"}, | ||
| 25 | {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, | ||
| 26 | {10, &IFileSystem::Commit, "Commit"}, | ||
| 27 | {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, | ||
| 28 | {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, | ||
| 29 | {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, | ||
| 30 | {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, | ||
| 31 | {15, nullptr, "QueryEntry"}, | ||
| 32 | {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, | ||
| 33 | }; | ||
| 34 | RegisterHandlers(functions); | ||
| 35 | } | ||
| 36 | |||
| 37 | void IFileSystem::CreateFile(HLERequestContext& ctx) { | ||
| 38 | IPC::RequestParser rp{ctx}; | ||
| 39 | |||
| 40 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 41 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 42 | |||
| 43 | const u64 file_mode = rp.Pop<u64>(); | ||
| 44 | const u32 file_size = rp.Pop<u32>(); | ||
| 45 | |||
| 46 | LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, file_mode, | ||
| 47 | file_size); | ||
| 48 | |||
| 49 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 50 | rb.Push(backend.CreateFile(name, file_size)); | ||
| 51 | } | ||
| 52 | |||
| 53 | void IFileSystem::DeleteFile(HLERequestContext& ctx) { | ||
| 54 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 55 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 56 | |||
| 57 | LOG_DEBUG(Service_FS, "called. file={}", name); | ||
| 58 | |||
| 59 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 60 | rb.Push(backend.DeleteFile(name)); | ||
| 61 | } | ||
| 62 | |||
| 63 | void IFileSystem::CreateDirectory(HLERequestContext& ctx) { | ||
| 64 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 65 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 66 | |||
| 67 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 68 | |||
| 69 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 70 | rb.Push(backend.CreateDirectory(name)); | ||
| 71 | } | ||
| 72 | |||
| 73 | void IFileSystem::DeleteDirectory(HLERequestContext& ctx) { | ||
| 74 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 75 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 76 | |||
| 77 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 78 | |||
| 79 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 80 | rb.Push(backend.DeleteDirectory(name)); | ||
| 81 | } | ||
| 82 | |||
| 83 | void IFileSystem::DeleteDirectoryRecursively(HLERequestContext& ctx) { | ||
| 84 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 85 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 86 | |||
| 87 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 88 | |||
| 89 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 90 | rb.Push(backend.DeleteDirectoryRecursively(name)); | ||
| 91 | } | ||
| 92 | |||
| 93 | void IFileSystem::CleanDirectoryRecursively(HLERequestContext& ctx) { | ||
| 94 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 95 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 96 | |||
| 97 | LOG_DEBUG(Service_FS, "called. Directory: {}", name); | ||
| 98 | |||
| 99 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 100 | rb.Push(backend.CleanDirectoryRecursively(name)); | ||
| 101 | } | ||
| 102 | |||
| 103 | void IFileSystem::RenameFile(HLERequestContext& ctx) { | ||
| 104 | const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); | ||
| 105 | const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); | ||
| 106 | |||
| 107 | LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); | ||
| 108 | |||
| 109 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 110 | rb.Push(backend.RenameFile(src_name, dst_name)); | ||
| 111 | } | ||
| 112 | |||
| 113 | void IFileSystem::OpenFile(HLERequestContext& ctx) { | ||
| 114 | IPC::RequestParser rp{ctx}; | ||
| 115 | |||
| 116 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 117 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 118 | |||
| 119 | const auto mode = static_cast<FileSys::OpenMode>(rp.Pop<u32>()); | ||
| 120 | |||
| 121 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); | ||
| 122 | |||
| 123 | FileSys::VirtualFile vfs_file{}; | ||
| 124 | auto result = backend.OpenFile(&vfs_file, name, mode); | ||
| 125 | if (result != ResultSuccess) { | ||
| 126 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(result); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | auto file = std::make_shared<IFile>(system, vfs_file); | ||
| 132 | |||
| 133 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 134 | rb.Push(ResultSuccess); | ||
| 135 | rb.PushIpcInterface<IFile>(std::move(file)); | ||
| 136 | } | ||
| 137 | |||
| 138 | void IFileSystem::OpenDirectory(HLERequestContext& ctx) { | ||
| 139 | IPC::RequestParser rp{ctx}; | ||
| 140 | |||
| 141 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 142 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 143 | const auto mode = rp.PopRaw<FileSys::OpenDirectoryMode>(); | ||
| 144 | |||
| 145 | LOG_DEBUG(Service_FS, "called. directory={}, mode={}", name, mode); | ||
| 146 | |||
| 147 | FileSys::VirtualDir vfs_dir{}; | ||
| 148 | auto result = backend.OpenDirectory(&vfs_dir, name); | ||
| 149 | if (result != ResultSuccess) { | ||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(result); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 155 | auto directory = std::make_shared<IDirectory>(system, vfs_dir, mode); | ||
| 156 | |||
| 157 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 158 | rb.Push(ResultSuccess); | ||
| 159 | rb.PushIpcInterface<IDirectory>(std::move(directory)); | ||
| 160 | } | ||
| 161 | |||
| 162 | void IFileSystem::GetEntryType(HLERequestContext& ctx) { | ||
| 163 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 164 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 165 | |||
| 166 | LOG_DEBUG(Service_FS, "called. file={}", name); | ||
| 167 | |||
| 168 | FileSys::DirectoryEntryType vfs_entry_type{}; | ||
| 169 | auto result = backend.GetEntryType(&vfs_entry_type, name); | ||
| 170 | if (result != ResultSuccess) { | ||
| 171 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 172 | rb.Push(result); | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 177 | rb.Push(ResultSuccess); | ||
| 178 | rb.Push<u32>(static_cast<u32>(vfs_entry_type)); | ||
| 179 | } | ||
| 180 | |||
| 181 | void IFileSystem::Commit(HLERequestContext& ctx) { | ||
| 182 | LOG_WARNING(Service_FS, "(STUBBED) called"); | ||
| 183 | |||
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | rb.Push(ResultSuccess); | ||
| 186 | } | ||
| 187 | |||
| 188 | void IFileSystem::GetFreeSpaceSize(HLERequestContext& ctx) { | ||
| 189 | LOG_DEBUG(Service_FS, "called"); | ||
| 190 | |||
| 191 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 192 | rb.Push(ResultSuccess); | ||
| 193 | rb.Push(size.get_free_size()); | ||
| 194 | } | ||
| 195 | |||
| 196 | void IFileSystem::GetTotalSpaceSize(HLERequestContext& ctx) { | ||
| 197 | LOG_DEBUG(Service_FS, "called"); | ||
| 198 | |||
| 199 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 200 | rb.Push(ResultSuccess); | ||
| 201 | rb.Push(size.get_total_size()); | ||
| 202 | } | ||
| 203 | |||
| 204 | void IFileSystem::GetFileTimeStampRaw(HLERequestContext& ctx) { | ||
| 205 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 206 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 207 | |||
| 208 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); | ||
| 209 | |||
| 210 | FileSys::FileTimeStampRaw vfs_timestamp{}; | ||
| 211 | auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); | ||
| 212 | if (result != ResultSuccess) { | ||
| 213 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 214 | rb.Push(result); | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | |||
| 218 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 219 | rb.Push(ResultSuccess); | ||
| 220 | rb.PushRaw(vfs_timestamp); | ||
| 221 | } | ||
| 222 | |||
| 223 | void IFileSystem::GetFileSystemAttribute(HLERequestContext& ctx) { | ||
| 224 | LOG_WARNING(Service_FS, "(STUBBED) called"); | ||
| 225 | |||
| 226 | struct FileSystemAttribute { | ||
| 227 | u8 dir_entry_name_length_max_defined; | ||
| 228 | u8 file_entry_name_length_max_defined; | ||
| 229 | u8 dir_path_name_length_max_defined; | ||
| 230 | u8 file_path_name_length_max_defined; | ||
| 231 | INSERT_PADDING_BYTES_NOINIT(0x5); | ||
| 232 | u8 utf16_dir_entry_name_length_max_defined; | ||
| 233 | u8 utf16_file_entry_name_length_max_defined; | ||
| 234 | u8 utf16_dir_path_name_length_max_defined; | ||
| 235 | u8 utf16_file_path_name_length_max_defined; | ||
| 236 | INSERT_PADDING_BYTES_NOINIT(0x18); | ||
| 237 | s32 dir_entry_name_length_max; | ||
| 238 | s32 file_entry_name_length_max; | ||
| 239 | s32 dir_path_name_length_max; | ||
| 240 | s32 file_path_name_length_max; | ||
| 241 | INSERT_PADDING_WORDS_NOINIT(0x5); | ||
| 242 | s32 utf16_dir_entry_name_length_max; | ||
| 243 | s32 utf16_file_entry_name_length_max; | ||
| 244 | s32 utf16_dir_path_name_length_max; | ||
| 245 | s32 utf16_file_path_name_length_max; | ||
| 246 | INSERT_PADDING_WORDS_NOINIT(0x18); | ||
| 247 | INSERT_PADDING_WORDS_NOINIT(0x1); | ||
| 248 | }; | ||
| 249 | static_assert(sizeof(FileSystemAttribute) == 0xc0, "FileSystemAttribute has incorrect size"); | ||
| 250 | |||
| 251 | FileSystemAttribute savedata_attribute{}; | ||
| 252 | savedata_attribute.dir_entry_name_length_max_defined = true; | ||
| 253 | savedata_attribute.file_entry_name_length_max_defined = true; | ||
| 254 | savedata_attribute.dir_entry_name_length_max = 0x40; | ||
| 255 | savedata_attribute.file_entry_name_length_max = 0x40; | ||
| 256 | |||
| 257 | IPC::ResponseBuilder rb{ctx, 50}; | ||
| 258 | rb.Push(ResultSuccess); | ||
| 259 | rb.PushRaw(savedata_attribute); | ||
| 260 | } | ||
| 261 | |||
| 262 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h new file mode 100644 index 000000000..b06b3ef0e --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_filesystem.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/file_sys/vfs/vfs.h" | ||
| 7 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 8 | #include "core/hle/service/filesystem/fsp/fsp_util.h" | ||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Service::FileSystem { | ||
| 12 | |||
| 13 | class IFileSystem final : public ServiceFramework<IFileSystem> { | ||
| 14 | public: | ||
| 15 | explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_); | ||
| 16 | |||
| 17 | void CreateFile(HLERequestContext& ctx); | ||
| 18 | void DeleteFile(HLERequestContext& ctx); | ||
| 19 | void CreateDirectory(HLERequestContext& ctx); | ||
| 20 | void DeleteDirectory(HLERequestContext& ctx); | ||
| 21 | void DeleteDirectoryRecursively(HLERequestContext& ctx); | ||
| 22 | void CleanDirectoryRecursively(HLERequestContext& ctx); | ||
| 23 | void RenameFile(HLERequestContext& ctx); | ||
| 24 | void OpenFile(HLERequestContext& ctx); | ||
| 25 | void OpenDirectory(HLERequestContext& ctx); | ||
| 26 | void GetEntryType(HLERequestContext& ctx); | ||
| 27 | void Commit(HLERequestContext& ctx); | ||
| 28 | void GetFreeSpaceSize(HLERequestContext& ctx); | ||
| 29 | void GetTotalSpaceSize(HLERequestContext& ctx); | ||
| 30 | void GetFileTimeStampRaw(HLERequestContext& ctx); | ||
| 31 | void GetFileSystemAttribute(HLERequestContext& ctx); | ||
| 32 | |||
| 33 | private: | ||
| 34 | VfsDirectoryServiceWrapper backend; | ||
| 35 | SizeGetter size; | ||
| 36 | }; | ||
| 37 | |||
| 38 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp new file mode 100644 index 000000000..98223c1f9 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_storage.cpp | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/file_sys/errors.h" | ||
| 5 | #include "core/hle/service/filesystem/fsp/fs_i_storage.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::FileSystem { | ||
| 9 | |||
| 10 | IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_) | ||
| 11 | : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { | ||
| 12 | static const FunctionInfo functions[] = { | ||
| 13 | {0, &IStorage::Read, "Read"}, | ||
| 14 | {1, nullptr, "Write"}, | ||
| 15 | {2, nullptr, "Flush"}, | ||
| 16 | {3, nullptr, "SetSize"}, | ||
| 17 | {4, &IStorage::GetSize, "GetSize"}, | ||
| 18 | {5, nullptr, "OperateRange"}, | ||
| 19 | }; | ||
| 20 | RegisterHandlers(functions); | ||
| 21 | } | ||
| 22 | |||
| 23 | void IStorage::Read(HLERequestContext& ctx) { | ||
| 24 | IPC::RequestParser rp{ctx}; | ||
| 25 | const s64 offset = rp.Pop<s64>(); | ||
| 26 | const s64 length = rp.Pop<s64>(); | ||
| 27 | |||
| 28 | LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); | ||
| 29 | |||
| 30 | // Error checking | ||
| 31 | if (length < 0) { | ||
| 32 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 33 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 34 | rb.Push(FileSys::ResultInvalidSize); | ||
| 35 | return; | ||
| 36 | } | ||
| 37 | if (offset < 0) { | ||
| 38 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 39 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 40 | rb.Push(FileSys::ResultInvalidOffset); | ||
| 41 | return; | ||
| 42 | } | ||
| 43 | |||
| 44 | // Read the data from the Storage backend | ||
| 45 | std::vector<u8> output = backend->ReadBytes(length, offset); | ||
| 46 | // Write the data to memory | ||
| 47 | ctx.WriteBuffer(output); | ||
| 48 | |||
| 49 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 50 | rb.Push(ResultSuccess); | ||
| 51 | } | ||
| 52 | |||
| 53 | void IStorage::GetSize(HLERequestContext& ctx) { | ||
| 54 | const u64 size = backend->GetSize(); | ||
| 55 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 56 | |||
| 57 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 58 | rb.Push(ResultSuccess); | ||
| 59 | rb.Push<u64>(size); | ||
| 60 | } | ||
| 61 | |||
| 62 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_storage.h b/src/core/hle/service/filesystem/fsp/fs_i_storage.h new file mode 100644 index 000000000..cb5bebcc9 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_storage.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/file_sys/vfs/vfs.h" | ||
| 7 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | |||
| 10 | namespace Service::FileSystem { | ||
| 11 | |||
| 12 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 13 | public: | ||
| 14 | explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_); | ||
| 15 | |||
| 16 | private: | ||
| 17 | FileSys::VirtualFile backend; | ||
| 18 | |||
| 19 | void Read(HLERequestContext& ctx); | ||
| 20 | void GetSize(HLERequestContext& ctx); | ||
| 21 | }; | ||
| 22 | |||
| 23 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp/fsp_ldr.cpp index 1e3366e71..8ee733f47 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_ldr.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/filesystem/fsp_ldr.h" | 4 | #include "core/hle/service/filesystem/fsp/fsp_ldr.h" |
| 5 | 5 | ||
| 6 | namespace Service::FileSystem { | 6 | namespace Service::FileSystem { |
| 7 | 7 | ||
diff --git a/src/core/hle/service/filesystem/fsp_ldr.h b/src/core/hle/service/filesystem/fsp/fsp_ldr.h index 358739a87..358739a87 100644 --- a/src/core/hle/service/filesystem/fsp_ldr.h +++ b/src/core/hle/service/filesystem/fsp/fsp_ldr.h | |||
diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp/fsp_pr.cpp index 4ffc31977..7c03ebaea 100644 --- a/src/core/hle/service/filesystem/fsp_pr.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_pr.cpp | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "core/hle/service/filesystem/fsp_pr.h" | 4 | #include "core/hle/service/filesystem/fsp/fsp_pr.h" |
| 5 | 5 | ||
| 6 | namespace Service::FileSystem { | 6 | namespace Service::FileSystem { |
| 7 | 7 | ||
diff --git a/src/core/hle/service/filesystem/fsp_pr.h b/src/core/hle/service/filesystem/fsp/fsp_pr.h index bd4e0a730..bd4e0a730 100644 --- a/src/core/hle/service/filesystem/fsp_pr.h +++ b/src/core/hle/service/filesystem/fsp/fsp_pr.h | |||
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index a2397bec4..2be72b021 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp | |||
| @@ -15,18 +15,20 @@ | |||
| 15 | #include "common/settings.h" | 15 | #include "common/settings.h" |
| 16 | #include "common/string_util.h" | 16 | #include "common/string_util.h" |
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/file_sys/directory.h" | ||
| 19 | #include "core/file_sys/errors.h" | 18 | #include "core/file_sys/errors.h" |
| 20 | #include "core/file_sys/mode.h" | 19 | #include "core/file_sys/fs_directory.h" |
| 20 | #include "core/file_sys/fs_filesystem.h" | ||
| 21 | #include "core/file_sys/nca_metadata.h" | 21 | #include "core/file_sys/nca_metadata.h" |
| 22 | #include "core/file_sys/patch_manager.h" | 22 | #include "core/file_sys/patch_manager.h" |
| 23 | #include "core/file_sys/romfs_factory.h" | 23 | #include "core/file_sys/romfs_factory.h" |
| 24 | #include "core/file_sys/savedata_factory.h" | 24 | #include "core/file_sys/savedata_factory.h" |
| 25 | #include "core/file_sys/system_archive/system_archive.h" | 25 | #include "core/file_sys/system_archive/system_archive.h" |
| 26 | #include "core/file_sys/vfs.h" | 26 | #include "core/file_sys/vfs/vfs.h" |
| 27 | #include "core/hle/result.h" | 27 | #include "core/hle/result.h" |
| 28 | #include "core/hle/service/filesystem/filesystem.h" | 28 | #include "core/hle/service/filesystem/filesystem.h" |
| 29 | #include "core/hle/service/filesystem/fsp_srv.h" | 29 | #include "core/hle/service/filesystem/fsp/fs_i_filesystem.h" |
| 30 | #include "core/hle/service/filesystem/fsp/fs_i_storage.h" | ||
| 31 | #include "core/hle/service/filesystem/fsp/fsp_srv.h" | ||
| 30 | #include "core/hle/service/filesystem/romfs_controller.h" | 32 | #include "core/hle/service/filesystem/romfs_controller.h" |
| 31 | #include "core/hle/service/filesystem/save_data_controller.h" | 33 | #include "core/hle/service/filesystem/save_data_controller.h" |
| 32 | #include "core/hle/service/hle_ipc.h" | 34 | #include "core/hle/service/hle_ipc.h" |
| @@ -34,19 +36,6 @@ | |||
| 34 | #include "core/reporter.h" | 36 | #include "core/reporter.h" |
| 35 | 37 | ||
| 36 | namespace Service::FileSystem { | 38 | namespace Service::FileSystem { |
| 37 | |||
| 38 | struct SizeGetter { | ||
| 39 | std::function<u64()> get_free_size; | ||
| 40 | std::function<u64()> get_total_size; | ||
| 41 | |||
| 42 | static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) { | ||
| 43 | return { | ||
| 44 | [&fsc, id] { return fsc.GetFreeSpaceSize(id); }, | ||
| 45 | [&fsc, id] { return fsc.GetTotalSpaceSize(id); }, | ||
| 46 | }; | ||
| 47 | } | ||
| 48 | }; | ||
| 49 | |||
| 50 | enum class FileSystemType : u8 { | 39 | enum class FileSystemType : u8 { |
| 51 | Invalid0 = 0, | 40 | Invalid0 = 0, |
| 52 | Invalid1 = 1, | 41 | Invalid1 = 1, |
| @@ -58,525 +47,6 @@ enum class FileSystemType : u8 { | |||
| 58 | ApplicationPackage = 7, | 47 | ApplicationPackage = 7, |
| 59 | }; | 48 | }; |
| 60 | 49 | ||
| 61 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 62 | public: | ||
| 63 | explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_) | ||
| 64 | : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) { | ||
| 65 | static const FunctionInfo functions[] = { | ||
| 66 | {0, &IStorage::Read, "Read"}, | ||
| 67 | {1, nullptr, "Write"}, | ||
| 68 | {2, nullptr, "Flush"}, | ||
| 69 | {3, nullptr, "SetSize"}, | ||
| 70 | {4, &IStorage::GetSize, "GetSize"}, | ||
| 71 | {5, nullptr, "OperateRange"}, | ||
| 72 | }; | ||
| 73 | RegisterHandlers(functions); | ||
| 74 | } | ||
| 75 | |||
| 76 | private: | ||
| 77 | FileSys::VirtualFile backend; | ||
| 78 | |||
| 79 | void Read(HLERequestContext& ctx) { | ||
| 80 | IPC::RequestParser rp{ctx}; | ||
| 81 | const s64 offset = rp.Pop<s64>(); | ||
| 82 | const s64 length = rp.Pop<s64>(); | ||
| 83 | |||
| 84 | LOG_DEBUG(Service_FS, "called, offset=0x{:X}, length={}", offset, length); | ||
| 85 | |||
| 86 | // Error checking | ||
| 87 | if (length < 0) { | ||
| 88 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 89 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 90 | rb.Push(FileSys::ERROR_INVALID_SIZE); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | if (offset < 0) { | ||
| 94 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 95 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 96 | rb.Push(FileSys::ERROR_INVALID_OFFSET); | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | // Read the data from the Storage backend | ||
| 101 | std::vector<u8> output = backend->ReadBytes(length, offset); | ||
| 102 | // Write the data to memory | ||
| 103 | ctx.WriteBuffer(output); | ||
| 104 | |||
| 105 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 106 | rb.Push(ResultSuccess); | ||
| 107 | } | ||
| 108 | |||
| 109 | void GetSize(HLERequestContext& ctx) { | ||
| 110 | const u64 size = backend->GetSize(); | ||
| 111 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 112 | |||
| 113 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 114 | rb.Push(ResultSuccess); | ||
| 115 | rb.Push<u64>(size); | ||
| 116 | } | ||
| 117 | }; | ||
| 118 | |||
| 119 | class IFile final : public ServiceFramework<IFile> { | ||
| 120 | public: | ||
| 121 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_) | ||
| 122 | : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) { | ||
| 123 | static const FunctionInfo functions[] = { | ||
| 124 | {0, &IFile::Read, "Read"}, | ||
| 125 | {1, &IFile::Write, "Write"}, | ||
| 126 | {2, &IFile::Flush, "Flush"}, | ||
| 127 | {3, &IFile::SetSize, "SetSize"}, | ||
| 128 | {4, &IFile::GetSize, "GetSize"}, | ||
| 129 | {5, nullptr, "OperateRange"}, | ||
| 130 | {6, nullptr, "OperateRangeWithBuffer"}, | ||
| 131 | }; | ||
| 132 | RegisterHandlers(functions); | ||
| 133 | } | ||
| 134 | |||
| 135 | private: | ||
| 136 | FileSys::VirtualFile backend; | ||
| 137 | |||
| 138 | void Read(HLERequestContext& ctx) { | ||
| 139 | IPC::RequestParser rp{ctx}; | ||
| 140 | const u64 option = rp.Pop<u64>(); | ||
| 141 | const s64 offset = rp.Pop<s64>(); | ||
| 142 | const s64 length = rp.Pop<s64>(); | ||
| 143 | |||
| 144 | LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, | ||
| 145 | length); | ||
| 146 | |||
| 147 | // Error checking | ||
| 148 | if (length < 0) { | ||
| 149 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(FileSys::ERROR_INVALID_SIZE); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | if (offset < 0) { | ||
| 155 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 156 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 157 | rb.Push(FileSys::ERROR_INVALID_OFFSET); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | // Read the data from the Storage backend | ||
| 162 | std::vector<u8> output = backend->ReadBytes(length, offset); | ||
| 163 | |||
| 164 | // Write the data to memory | ||
| 165 | ctx.WriteBuffer(output); | ||
| 166 | |||
| 167 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 168 | rb.Push(ResultSuccess); | ||
| 169 | rb.Push(static_cast<u64>(output.size())); | ||
| 170 | } | ||
| 171 | |||
| 172 | void Write(HLERequestContext& ctx) { | ||
| 173 | IPC::RequestParser rp{ctx}; | ||
| 174 | const u64 option = rp.Pop<u64>(); | ||
| 175 | const s64 offset = rp.Pop<s64>(); | ||
| 176 | const s64 length = rp.Pop<s64>(); | ||
| 177 | |||
| 178 | LOG_DEBUG(Service_FS, "called, option={}, offset=0x{:X}, length={}", option, offset, | ||
| 179 | length); | ||
| 180 | |||
| 181 | // Error checking | ||
| 182 | if (length < 0) { | ||
| 183 | LOG_ERROR(Service_FS, "Length is less than 0, length={}", length); | ||
| 184 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 185 | rb.Push(FileSys::ERROR_INVALID_SIZE); | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | if (offset < 0) { | ||
| 189 | LOG_ERROR(Service_FS, "Offset is less than 0, offset={}", offset); | ||
| 190 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 191 | rb.Push(FileSys::ERROR_INVALID_OFFSET); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | const auto data = ctx.ReadBuffer(); | ||
| 196 | |||
| 197 | ASSERT_MSG( | ||
| 198 | static_cast<s64>(data.size()) <= length, | ||
| 199 | "Attempting to write more data than requested (requested={:016X}, actual={:016X}).", | ||
| 200 | length, data.size()); | ||
| 201 | |||
| 202 | // Write the data to the Storage backend | ||
| 203 | const auto write_size = | ||
| 204 | static_cast<std::size_t>(std::distance(data.begin(), data.begin() + length)); | ||
| 205 | const std::size_t written = backend->Write(data.data(), write_size, offset); | ||
| 206 | |||
| 207 | ASSERT_MSG(static_cast<s64>(written) == length, | ||
| 208 | "Could not write all bytes to file (requested={:016X}, actual={:016X}).", length, | ||
| 209 | written); | ||
| 210 | |||
| 211 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 212 | rb.Push(ResultSuccess); | ||
| 213 | } | ||
| 214 | |||
| 215 | void Flush(HLERequestContext& ctx) { | ||
| 216 | LOG_DEBUG(Service_FS, "called"); | ||
| 217 | |||
| 218 | // Exists for SDK compatibiltity -- No need to flush file. | ||
| 219 | |||
| 220 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 221 | rb.Push(ResultSuccess); | ||
| 222 | } | ||
| 223 | |||
| 224 | void SetSize(HLERequestContext& ctx) { | ||
| 225 | IPC::RequestParser rp{ctx}; | ||
| 226 | const u64 size = rp.Pop<u64>(); | ||
| 227 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 228 | |||
| 229 | backend->Resize(size); | ||
| 230 | |||
| 231 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 232 | rb.Push(ResultSuccess); | ||
| 233 | } | ||
| 234 | |||
| 235 | void GetSize(HLERequestContext& ctx) { | ||
| 236 | const u64 size = backend->GetSize(); | ||
| 237 | LOG_DEBUG(Service_FS, "called, size={}", size); | ||
| 238 | |||
| 239 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 240 | rb.Push(ResultSuccess); | ||
| 241 | rb.Push<u64>(size); | ||
| 242 | } | ||
| 243 | }; | ||
| 244 | |||
| 245 | template <typename T> | ||
| 246 | static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data, | ||
| 247 | FileSys::EntryType type) { | ||
| 248 | entries.reserve(entries.size() + new_data.size()); | ||
| 249 | |||
| 250 | for (const auto& new_entry : new_data) { | ||
| 251 | auto name = new_entry->GetName(); | ||
| 252 | |||
| 253 | if (type == FileSys::EntryType::File && name == FileSys::GetSaveDataSizeFileName()) { | ||
| 254 | continue; | ||
| 255 | } | ||
| 256 | |||
| 257 | entries.emplace_back(name, type, | ||
| 258 | type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize()); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | class IDirectory final : public ServiceFramework<IDirectory> { | ||
| 263 | public: | ||
| 264 | explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, OpenDirectoryMode mode) | ||
| 265 | : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { | ||
| 266 | static const FunctionInfo functions[] = { | ||
| 267 | {0, &IDirectory::Read, "Read"}, | ||
| 268 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, | ||
| 269 | }; | ||
| 270 | RegisterHandlers(functions); | ||
| 271 | |||
| 272 | // TODO(DarkLordZach): Verify that this is the correct behavior. | ||
| 273 | // Build entry index now to save time later. | ||
| 274 | if (True(mode & OpenDirectoryMode::Directory)) { | ||
| 275 | BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::EntryType::Directory); | ||
| 276 | } | ||
| 277 | if (True(mode & OpenDirectoryMode::File)) { | ||
| 278 | BuildEntryIndex(entries, backend->GetFiles(), FileSys::EntryType::File); | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | private: | ||
| 283 | FileSys::VirtualDir backend; | ||
| 284 | std::vector<FileSys::Entry> entries; | ||
| 285 | u64 next_entry_index = 0; | ||
| 286 | |||
| 287 | void Read(HLERequestContext& ctx) { | ||
| 288 | LOG_DEBUG(Service_FS, "called."); | ||
| 289 | |||
| 290 | // Calculate how many entries we can fit in the output buffer | ||
| 291 | const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::Entry>(); | ||
| 292 | |||
| 293 | // Cap at total number of entries. | ||
| 294 | const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); | ||
| 295 | |||
| 296 | // Determine data start and end | ||
| 297 | const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index); | ||
| 298 | const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries); | ||
| 299 | const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); | ||
| 300 | |||
| 301 | next_entry_index += actual_entries; | ||
| 302 | |||
| 303 | // Write the data to memory | ||
| 304 | ctx.WriteBuffer(begin, range_size); | ||
| 305 | |||
| 306 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 307 | rb.Push(ResultSuccess); | ||
| 308 | rb.Push(actual_entries); | ||
| 309 | } | ||
| 310 | |||
| 311 | void GetEntryCount(HLERequestContext& ctx) { | ||
| 312 | LOG_DEBUG(Service_FS, "called"); | ||
| 313 | |||
| 314 | u64 count = entries.size() - next_entry_index; | ||
| 315 | |||
| 316 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 317 | rb.Push(ResultSuccess); | ||
| 318 | rb.Push(count); | ||
| 319 | } | ||
| 320 | }; | ||
| 321 | |||
| 322 | class IFileSystem final : public ServiceFramework<IFileSystem> { | ||
| 323 | public: | ||
| 324 | explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) | ||
| 325 | : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move( | ||
| 326 | size_)} { | ||
| 327 | static const FunctionInfo functions[] = { | ||
| 328 | {0, &IFileSystem::CreateFile, "CreateFile"}, | ||
| 329 | {1, &IFileSystem::DeleteFile, "DeleteFile"}, | ||
| 330 | {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, | ||
| 331 | {3, &IFileSystem::DeleteDirectory, "DeleteDirectory"}, | ||
| 332 | {4, &IFileSystem::DeleteDirectoryRecursively, "DeleteDirectoryRecursively"}, | ||
| 333 | {5, &IFileSystem::RenameFile, "RenameFile"}, | ||
| 334 | {6, nullptr, "RenameDirectory"}, | ||
| 335 | {7, &IFileSystem::GetEntryType, "GetEntryType"}, | ||
| 336 | {8, &IFileSystem::OpenFile, "OpenFile"}, | ||
| 337 | {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, | ||
| 338 | {10, &IFileSystem::Commit, "Commit"}, | ||
| 339 | {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, | ||
| 340 | {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, | ||
| 341 | {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, | ||
| 342 | {14, &IFileSystem::GetFileTimeStampRaw, "GetFileTimeStampRaw"}, | ||
| 343 | {15, nullptr, "QueryEntry"}, | ||
| 344 | {16, &IFileSystem::GetFileSystemAttribute, "GetFileSystemAttribute"}, | ||
| 345 | }; | ||
| 346 | RegisterHandlers(functions); | ||
| 347 | } | ||
| 348 | |||
| 349 | void CreateFile(HLERequestContext& ctx) { | ||
| 350 | IPC::RequestParser rp{ctx}; | ||
| 351 | |||
| 352 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 353 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 354 | |||
| 355 | const u64 file_mode = rp.Pop<u64>(); | ||
| 356 | const u32 file_size = rp.Pop<u32>(); | ||
| 357 | |||
| 358 | LOG_DEBUG(Service_FS, "called. file={}, mode=0x{:X}, size=0x{:08X}", name, file_mode, | ||
| 359 | file_size); | ||
| 360 | |||
| 361 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 362 | rb.Push(backend.CreateFile(name, file_size)); | ||
| 363 | } | ||
| 364 | |||
| 365 | void DeleteFile(HLERequestContext& ctx) { | ||
| 366 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 367 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 368 | |||
| 369 | LOG_DEBUG(Service_FS, "called. file={}", name); | ||
| 370 | |||
| 371 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 372 | rb.Push(backend.DeleteFile(name)); | ||
| 373 | } | ||
| 374 | |||
| 375 | void CreateDirectory(HLERequestContext& ctx) { | ||
| 376 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 377 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 378 | |||
| 379 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 380 | |||
| 381 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 382 | rb.Push(backend.CreateDirectory(name)); | ||
| 383 | } | ||
| 384 | |||
| 385 | void DeleteDirectory(HLERequestContext& ctx) { | ||
| 386 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 387 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 388 | |||
| 389 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 390 | |||
| 391 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 392 | rb.Push(backend.DeleteDirectory(name)); | ||
| 393 | } | ||
| 394 | |||
| 395 | void DeleteDirectoryRecursively(HLERequestContext& ctx) { | ||
| 396 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 397 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 398 | |||
| 399 | LOG_DEBUG(Service_FS, "called. directory={}", name); | ||
| 400 | |||
| 401 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 402 | rb.Push(backend.DeleteDirectoryRecursively(name)); | ||
| 403 | } | ||
| 404 | |||
| 405 | void CleanDirectoryRecursively(HLERequestContext& ctx) { | ||
| 406 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 407 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 408 | |||
| 409 | LOG_DEBUG(Service_FS, "called. Directory: {}", name); | ||
| 410 | |||
| 411 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 412 | rb.Push(backend.CleanDirectoryRecursively(name)); | ||
| 413 | } | ||
| 414 | |||
| 415 | void RenameFile(HLERequestContext& ctx) { | ||
| 416 | const std::string src_name = Common::StringFromBuffer(ctx.ReadBuffer(0)); | ||
| 417 | const std::string dst_name = Common::StringFromBuffer(ctx.ReadBuffer(1)); | ||
| 418 | |||
| 419 | LOG_DEBUG(Service_FS, "called. file '{}' to file '{}'", src_name, dst_name); | ||
| 420 | |||
| 421 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 422 | rb.Push(backend.RenameFile(src_name, dst_name)); | ||
| 423 | } | ||
| 424 | |||
| 425 | void OpenFile(HLERequestContext& ctx) { | ||
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | |||
| 428 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 429 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 430 | |||
| 431 | const auto mode = static_cast<FileSys::Mode>(rp.Pop<u32>()); | ||
| 432 | |||
| 433 | LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); | ||
| 434 | |||
| 435 | FileSys::VirtualFile vfs_file{}; | ||
| 436 | auto result = backend.OpenFile(&vfs_file, name, mode); | ||
| 437 | if (result != ResultSuccess) { | ||
| 438 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 439 | rb.Push(result); | ||
| 440 | return; | ||
| 441 | } | ||
| 442 | |||
| 443 | auto file = std::make_shared<IFile>(system, vfs_file); | ||
| 444 | |||
| 445 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 446 | rb.Push(ResultSuccess); | ||
| 447 | rb.PushIpcInterface<IFile>(std::move(file)); | ||
| 448 | } | ||
| 449 | |||
| 450 | void OpenDirectory(HLERequestContext& ctx) { | ||
| 451 | IPC::RequestParser rp{ctx}; | ||
| 452 | |||
| 453 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 454 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 455 | const auto mode = rp.PopRaw<OpenDirectoryMode>(); | ||
| 456 | |||
| 457 | LOG_DEBUG(Service_FS, "called. directory={}, mode={}", name, mode); | ||
| 458 | |||
| 459 | FileSys::VirtualDir vfs_dir{}; | ||
| 460 | auto result = backend.OpenDirectory(&vfs_dir, name); | ||
| 461 | if (result != ResultSuccess) { | ||
| 462 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 463 | rb.Push(result); | ||
| 464 | return; | ||
| 465 | } | ||
| 466 | |||
| 467 | auto directory = std::make_shared<IDirectory>(system, vfs_dir, mode); | ||
| 468 | |||
| 469 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 470 | rb.Push(ResultSuccess); | ||
| 471 | rb.PushIpcInterface<IDirectory>(std::move(directory)); | ||
| 472 | } | ||
| 473 | |||
| 474 | void GetEntryType(HLERequestContext& ctx) { | ||
| 475 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 476 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 477 | |||
| 478 | LOG_DEBUG(Service_FS, "called. file={}", name); | ||
| 479 | |||
| 480 | FileSys::EntryType vfs_entry_type{}; | ||
| 481 | auto result = backend.GetEntryType(&vfs_entry_type, name); | ||
| 482 | if (result != ResultSuccess) { | ||
| 483 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 484 | rb.Push(result); | ||
| 485 | return; | ||
| 486 | } | ||
| 487 | |||
| 488 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 489 | rb.Push(ResultSuccess); | ||
| 490 | rb.Push<u32>(static_cast<u32>(vfs_entry_type)); | ||
| 491 | } | ||
| 492 | |||
| 493 | void Commit(HLERequestContext& ctx) { | ||
| 494 | LOG_WARNING(Service_FS, "(STUBBED) called"); | ||
| 495 | |||
| 496 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 497 | rb.Push(ResultSuccess); | ||
| 498 | } | ||
| 499 | |||
| 500 | void GetFreeSpaceSize(HLERequestContext& ctx) { | ||
| 501 | LOG_DEBUG(Service_FS, "called"); | ||
| 502 | |||
| 503 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 504 | rb.Push(ResultSuccess); | ||
| 505 | rb.Push(size.get_free_size()); | ||
| 506 | } | ||
| 507 | |||
| 508 | void GetTotalSpaceSize(HLERequestContext& ctx) { | ||
| 509 | LOG_DEBUG(Service_FS, "called"); | ||
| 510 | |||
| 511 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 512 | rb.Push(ResultSuccess); | ||
| 513 | rb.Push(size.get_total_size()); | ||
| 514 | } | ||
| 515 | |||
| 516 | void GetFileTimeStampRaw(HLERequestContext& ctx) { | ||
| 517 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 518 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 519 | |||
| 520 | LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); | ||
| 521 | |||
| 522 | FileSys::FileTimeStampRaw vfs_timestamp{}; | ||
| 523 | auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); | ||
| 524 | if (result != ResultSuccess) { | ||
| 525 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 526 | rb.Push(result); | ||
| 527 | return; | ||
| 528 | } | ||
| 529 | |||
| 530 | IPC::ResponseBuilder rb{ctx, 10}; | ||
| 531 | rb.Push(ResultSuccess); | ||
| 532 | rb.PushRaw(vfs_timestamp); | ||
| 533 | } | ||
| 534 | |||
| 535 | void GetFileSystemAttribute(HLERequestContext& ctx) { | ||
| 536 | LOG_WARNING(Service_FS, "(STUBBED) called"); | ||
| 537 | |||
| 538 | struct FileSystemAttribute { | ||
| 539 | u8 dir_entry_name_length_max_defined; | ||
| 540 | u8 file_entry_name_length_max_defined; | ||
| 541 | u8 dir_path_name_length_max_defined; | ||
| 542 | u8 file_path_name_length_max_defined; | ||
| 543 | INSERT_PADDING_BYTES_NOINIT(0x5); | ||
| 544 | u8 utf16_dir_entry_name_length_max_defined; | ||
| 545 | u8 utf16_file_entry_name_length_max_defined; | ||
| 546 | u8 utf16_dir_path_name_length_max_defined; | ||
| 547 | u8 utf16_file_path_name_length_max_defined; | ||
| 548 | INSERT_PADDING_BYTES_NOINIT(0x18); | ||
| 549 | s32 dir_entry_name_length_max; | ||
| 550 | s32 file_entry_name_length_max; | ||
| 551 | s32 dir_path_name_length_max; | ||
| 552 | s32 file_path_name_length_max; | ||
| 553 | INSERT_PADDING_WORDS_NOINIT(0x5); | ||
| 554 | s32 utf16_dir_entry_name_length_max; | ||
| 555 | s32 utf16_file_entry_name_length_max; | ||
| 556 | s32 utf16_dir_path_name_length_max; | ||
| 557 | s32 utf16_file_path_name_length_max; | ||
| 558 | INSERT_PADDING_WORDS_NOINIT(0x18); | ||
| 559 | INSERT_PADDING_WORDS_NOINIT(0x1); | ||
| 560 | }; | ||
| 561 | static_assert(sizeof(FileSystemAttribute) == 0xc0, | ||
| 562 | "FileSystemAttribute has incorrect size"); | ||
| 563 | |||
| 564 | FileSystemAttribute savedata_attribute{}; | ||
| 565 | savedata_attribute.dir_entry_name_length_max_defined = true; | ||
| 566 | savedata_attribute.file_entry_name_length_max_defined = true; | ||
| 567 | savedata_attribute.dir_entry_name_length_max = 0x40; | ||
| 568 | savedata_attribute.file_entry_name_length_max = 0x40; | ||
| 569 | |||
| 570 | IPC::ResponseBuilder rb{ctx, 50}; | ||
| 571 | rb.Push(ResultSuccess); | ||
| 572 | rb.PushRaw(savedata_attribute); | ||
| 573 | } | ||
| 574 | |||
| 575 | private: | ||
| 576 | VfsDirectoryServiceWrapper backend; | ||
| 577 | SizeGetter size; | ||
| 578 | }; | ||
| 579 | |||
| 580 | class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { | 50 | class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { |
| 581 | public: | 51 | public: |
| 582 | explicit ISaveDataInfoReader(Core::System& system_, | 52 | explicit ISaveDataInfoReader(Core::System& system_, |
| @@ -960,7 +430,7 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) { | |||
| 960 | save_data_controller->OpenSaveData(&dir, parameters.space_id, parameters.attribute); | 430 | save_data_controller->OpenSaveData(&dir, parameters.space_id, parameters.attribute); |
| 961 | if (result != ResultSuccess) { | 431 | if (result != ResultSuccess) { |
| 962 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; | 432 | IPC::ResponseBuilder rb{ctx, 2, 0, 0}; |
| 963 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 433 | rb.Push(FileSys::ResultTargetNotFound); |
| 964 | return; | 434 | return; |
| 965 | } | 435 | } |
| 966 | 436 | ||
| @@ -1127,7 +597,7 @@ void FSP_SRV::OpenPatchDataStorageByCurrentProcess(HLERequestContext& ctx) { | |||
| 1127 | LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", storage_id, title_id); | 597 | LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", storage_id, title_id); |
| 1128 | 598 | ||
| 1129 | IPC::ResponseBuilder rb{ctx, 2}; | 599 | IPC::ResponseBuilder rb{ctx, 2}; |
| 1130 | rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); | 600 | rb.Push(FileSys::ResultTargetNotFound); |
| 1131 | } | 601 | } |
| 1132 | 602 | ||
| 1133 | void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { | 603 | void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h index 26980af99..26980af99 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h | |||
diff --git a/src/core/hle/service/filesystem/fsp/fsp_util.h b/src/core/hle/service/filesystem/fsp/fsp_util.h new file mode 100644 index 000000000..253f866db --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fsp_util.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 7 | |||
| 8 | namespace Service::FileSystem { | ||
| 9 | |||
| 10 | struct SizeGetter { | ||
| 11 | std::function<u64()> get_free_size; | ||
| 12 | std::function<u64()> get_total_size; | ||
| 13 | |||
| 14 | static SizeGetter FromStorageId(const FileSystemController& fsc, FileSys::StorageId id) { | ||
| 15 | return { | ||
| 16 | [&fsc, id] { return fsc.GetFreeSpaceSize(id); }, | ||
| 17 | [&fsc, id] { return fsc.GetTotalSpaceSize(id); }, | ||
| 18 | }; | ||
| 19 | } | ||
| 20 | }; | ||
| 21 | |||
| 22 | } // namespace Service::FileSystem | ||
diff --git a/src/core/hle/service/filesystem/romfs_controller.h b/src/core/hle/service/filesystem/romfs_controller.h index 9a478f71d..3c3ead344 100644 --- a/src/core/hle/service/filesystem/romfs_controller.h +++ b/src/core/hle/service/filesystem/romfs_controller.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "core/file_sys/nca_metadata.h" | 6 | #include "core/file_sys/nca_metadata.h" |
| 7 | #include "core/file_sys/romfs_factory.h" | 7 | #include "core/file_sys/romfs_factory.h" |
| 8 | #include "core/file_sys/vfs_types.h" | 8 | #include "core/file_sys/vfs/vfs_types.h" |
| 9 | 9 | ||
| 10 | namespace Service::FileSystem { | 10 | namespace Service::FileSystem { |
| 11 | 11 | ||
diff --git a/src/core/hle/service/filesystem/save_data_controller.cpp b/src/core/hle/service/filesystem/save_data_controller.cpp index d19b3ea1e..03e45f7f9 100644 --- a/src/core/hle/service/filesystem/save_data_controller.cpp +++ b/src/core/hle/service/filesystem/save_data_controller.cpp | |||
| @@ -44,7 +44,7 @@ Result SaveDataController::CreateSaveData(FileSys::VirtualDir* out_save_data, | |||
| 44 | 44 | ||
| 45 | auto save_data = factory->Create(space, attribute); | 45 | auto save_data = factory->Create(space, attribute); |
| 46 | if (save_data == nullptr) { | 46 | if (save_data == nullptr) { |
| 47 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 47 | return FileSys::ResultTargetNotFound; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | *out_save_data = save_data; | 50 | *out_save_data = save_data; |
| @@ -56,7 +56,7 @@ Result SaveDataController::OpenSaveData(FileSys::VirtualDir* out_save_data, | |||
| 56 | const FileSys::SaveDataAttribute& attribute) { | 56 | const FileSys::SaveDataAttribute& attribute) { |
| 57 | auto save_data = factory->Open(space, attribute); | 57 | auto save_data = factory->Open(space, attribute); |
| 58 | if (save_data == nullptr) { | 58 | if (save_data == nullptr) { |
| 59 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 59 | return FileSys::ResultTargetNotFound; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | *out_save_data = save_data; | 62 | *out_save_data = save_data; |
| @@ -67,7 +67,7 @@ Result SaveDataController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_ | |||
| 67 | FileSys::SaveDataSpaceId space) { | 67 | FileSys::SaveDataSpaceId space) { |
| 68 | auto save_data_space = factory->GetSaveDataSpaceDirectory(space); | 68 | auto save_data_space = factory->GetSaveDataSpaceDirectory(space); |
| 69 | if (save_data_space == nullptr) { | 69 | if (save_data_space == nullptr) { |
| 70 | return FileSys::ERROR_ENTITY_NOT_FOUND; | 70 | return FileSys::ResultTargetNotFound; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | *out_save_data_space = save_data_space; | 73 | *out_save_data_space = save_data_space; |
diff --git a/src/core/hle/service/filesystem/save_data_controller.h b/src/core/hle/service/filesystem/save_data_controller.h index 863188e4c..dc9d713df 100644 --- a/src/core/hle/service/filesystem/save_data_controller.h +++ b/src/core/hle/service/filesystem/save_data_controller.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "core/file_sys/nca_metadata.h" | 6 | #include "core/file_sys/nca_metadata.h" |
| 7 | #include "core/file_sys/savedata_factory.h" | 7 | #include "core/file_sys/savedata_factory.h" |
| 8 | #include "core/file_sys/vfs_types.h" | 8 | #include "core/file_sys/vfs/vfs_types.h" |
| 9 | 9 | ||
| 10 | namespace Service::FileSystem { | 10 | namespace Service::FileSystem { |
| 11 | 11 | ||
diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index 6423e5089..b56762941 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "common/time_zone.h" | 10 | #include "common/time_zone.h" |
| 11 | #include "core/file_sys/vfs.h" | 11 | #include "core/file_sys/vfs/vfs.h" |
| 12 | #include "core/hle/kernel/svc.h" | 12 | #include "core/hle/kernel/svc.h" |
| 13 | #include "core/hle/service/glue/time/manager.h" | 13 | #include "core/hle/service/glue/time/manager.h" |
| 14 | #include "core/hle/service/glue/time/time_zone_binary.h" | 14 | #include "core/hle/service/glue/time/time_zone_binary.h" |
diff --git a/src/core/hle/service/glue/time/manager.h b/src/core/hle/service/glue/time/manager.h index a46ec6364..1de93f8f9 100644 --- a/src/core/hle/service/glue/time/manager.h +++ b/src/core/hle/service/glue/time/manager.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/file_sys/vfs_types.h" | 10 | #include "core/file_sys/vfs/vfs_types.h" |
| 11 | #include "core/hle/service/glue/time/file_timestamp_worker.h" | 11 | #include "core/hle/service/glue/time/file_timestamp_worker.h" |
| 12 | #include "core/hle/service/glue/time/standard_steady_clock_resource.h" | 12 | #include "core/hle/service/glue/time/standard_steady_clock_resource.h" |
| 13 | #include "core/hle/service/glue/time/worker.h" | 13 | #include "core/hle/service/glue/time/worker.h" |
diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp index 67969aa3f..d33f784c0 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.cpp +++ b/src/core/hle/service/glue/time/time_zone_binary.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "core/file_sys/registered_cache.h" | 7 | #include "core/file_sys/registered_cache.h" |
| 8 | #include "core/file_sys/romfs.h" | 8 | #include "core/file_sys/romfs.h" |
| 9 | #include "core/file_sys/system_archive/system_archive.h" | 9 | #include "core/file_sys/system_archive/system_archive.h" |
| 10 | #include "core/file_sys/vfs.h" | 10 | #include "core/file_sys/vfs/vfs.h" |
| 11 | #include "core/hle/service/filesystem/filesystem.h" | 11 | #include "core/hle/service/filesystem/filesystem.h" |
| 12 | #include "core/hle/service/glue/time/time_zone_binary.h" | 12 | #include "core/hle/service/glue/time/time_zone_binary.h" |
| 13 | 13 | ||
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 207ac4efe..3e2c7deab 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp | |||
| @@ -301,7 +301,7 @@ Result NfcInterface::TranslateResultToServiceError(Result result) const { | |||
| 301 | return result; | 301 | return result; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | if (result.module != ErrorModule::NFC) { | 304 | if (result.GetModule() != ErrorModule::NFC) { |
| 305 | return result; | 305 | return result; |
| 306 | } | 306 | } |
| 307 | 307 | ||
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index a25b79513..2258ee609 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/file_sys/control_metadata.h" | 7 | #include "core/file_sys/control_metadata.h" |
| 8 | #include "core/file_sys/patch_manager.h" | 8 | #include "core/file_sys/patch_manager.h" |
| 9 | #include "core/file_sys/vfs.h" | 9 | #include "core/file_sys/vfs/vfs.h" |
| 10 | #include "core/hle/service/filesystem/filesystem.h" | 10 | #include "core/hle/service/filesystem/filesystem.h" |
| 11 | #include "core/hle/service/glue/glue_manager.h" | 11 | #include "core/hle/service/glue/glue_manager.h" |
| 12 | #include "core/hle/service/ipc_helpers.h" | 12 | #include "core/hle/service/ipc_helpers.h" |
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index f40a1c8f3..b527c39a9 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp | |||
| @@ -67,13 +67,13 @@ Result GetFirmwareVersionImpl(FirmwareVersionFormat& out_firmware, Core::System& | |||
| 67 | const auto ver_file = romfs->GetFile("file"); | 67 | const auto ver_file = romfs->GetFile("file"); |
| 68 | if (ver_file == nullptr) { | 68 | if (ver_file == nullptr) { |
| 69 | return early_exit_failure("The system version archive didn't contain the file 'file'.", | 69 | return early_exit_failure("The system version archive didn't contain the file 'file'.", |
| 70 | FileSys::ERROR_INVALID_ARGUMENT); | 70 | FileSys::ResultInvalidArgument); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | auto data = ver_file->ReadAllBytes(); | 73 | auto data = ver_file->ReadAllBytes(); |
| 74 | if (data.size() != sizeof(FirmwareVersionFormat)) { | 74 | if (data.size() != sizeof(FirmwareVersionFormat)) { |
| 75 | return early_exit_failure("The system version file 'file' was not the correct size.", | 75 | return early_exit_failure("The system version file 'file' was not the correct size.", |
| 76 | FileSys::ERROR_OUT_OF_BOUNDS); | 76 | FileSys::ResultOutOfRange); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat)); | 79 | std::memcpy(&out_firmware, data.data(), sizeof(FirmwareVersionFormat)); |