summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar liamwhite2024-01-26 09:55:25 -0500
committerGravatar GitHub2024-01-26 09:55:25 -0500
commit55482ab5dce463d5014498b006c18a90d0d004e6 (patch)
treeb343faa9cadc692265efb4b6b88e157c97ef76d2 /src/core/hle
parentMerge pull request #12796 from t895/controller-optimizations (diff)
parentAddress review comments and fix compilation problems (diff)
downloadyuzu-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')
-rw-r--r--src/core/hle/result.h38
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp4
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp8
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.h2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp3
-rw-r--r--src/core/hle/service/bcat/backend/backend.h2
-rw-r--r--src/core/hle/service/bcat/bcat_module.cpp2
-rw-r--r--src/core/hle/service/caps/caps_a.cpp13
-rw-r--r--src/core/hle/service/fatal/fatal.cpp4
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp78
-rw-r--r--src/core/hle/service/filesystem/filesystem.h18
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_directory.cpp84
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_directory.h30
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_file.cpp127
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_file.h25
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_filesystem.cpp262
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_filesystem.h38
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_storage.cpp62
-rw-r--r--src/core/hle/service/filesystem/fsp/fs_i_storage.h23
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_ldr.cpp (renamed from src/core/hle/service/filesystem/fsp_ldr.cpp)2
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_ldr.h (renamed from src/core/hle/service/filesystem/fsp_ldr.h)0
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_pr.cpp (renamed from src/core/hle/service/filesystem/fsp_pr.cpp)2
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_pr.h (renamed from src/core/hle/service/filesystem/fsp_pr.h)0
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.cpp (renamed from src/core/hle/service/filesystem/fsp_srv.cpp)546
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_srv.h (renamed from src/core/hle/service/filesystem/fsp_srv.h)0
-rw-r--r--src/core/hle/service/filesystem/fsp/fsp_util.h22
-rw-r--r--src/core/hle/service/filesystem/romfs_controller.h2
-rw-r--r--src/core/hle/service/filesystem/save_data_controller.cpp6
-rw-r--r--src/core/hle/service/filesystem/save_data_controller.h2
-rw-r--r--src/core/hle/service/glue/time/manager.cpp2
-rw-r--r--src/core/hle/service/glue/time/manager.h2
-rw-r--r--src/core/hle/service/glue/time/time_zone_binary.cpp2
-rw-r--r--src/core/hle/service/nfc/nfc_interface.cpp2
-rw-r--r--src/core/hle/service/ns/ns.cpp2
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp4
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 {
189union Result { 189union 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
281private: 290private:
@@ -330,6 +339,16 @@ constexpr bool EvaluateResultFailure(const Result& r) {
330 return R_FAILED(r); 339 return R_FAILED(r);
331} 340}
332 341
342template <auto... R>
343constexpr bool EvaluateAnyResultIncludes(const Result& r) {
344 return ((r == R) || ...);
345}
346
347template <auto... R>
348constexpr bool EvaluateResultNotIncluded(const Result& r) {
349 return !EvaluateAnyResultIncludes<R...>(r);
350}
351
333template <typename T> 352template <typename T>
334constexpr void UpdateCurrentResultReference(T result_reference, Result result) = delete; 353constexpr 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
374constexpr inline Result __TmpCurrentResultReference = ResultSuccess; 400constexpr 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
216Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, 215Result 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
250Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, 250Result 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
278Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( 278Result 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
347std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFactory( 347std::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
12namespace Core { 14namespace Core {
@@ -26,7 +28,6 @@ class XCI;
26 28
27enum class BisPartitionId : u32; 29enum class BisPartitionId : u32;
28enum class ContentRecordType : u8; 30enum class ContentRecordType : u8;
29enum class Mode : u32;
30enum class SaveDataSpaceId : u8; 31enum class SaveDataSpaceId : u8;
31enum class SaveDataType : u8; 32enum class SaveDataType : u8;
32enum class StorageId : u8; 33enum class StorageId : u8;
@@ -57,13 +58,6 @@ enum class ImageDirectoryId : u32 {
57 SdCard, 58 SdCard,
58}; 59};
59 60
60enum class OpenDirectoryMode : u64 {
61 Directory = (1 << 0),
62 File = (1 << 1),
63 All = Directory | File
64};
65DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode);
66
67using ProcessId = u64; 61using ProcessId = u64;
68using ProgramId = u64; 62using 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
9namespace Service::FileSystem {
10
11template <typename T>
12static 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
30IDirectory::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
50void 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
74void 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
10namespace FileSys {
11struct DirectoryEntry;
12}
13
14namespace Service::FileSystem {
15
16class IDirectory final : public ServiceFramework<IDirectory> {
17public:
18 explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_,
19 FileSys::OpenDirectoryMode mode);
20
21private:
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
8namespace Service::FileSystem {
9
10IFile::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
24void 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
57void 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
98void 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
107void 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
118void 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
9namespace Service::FileSystem {
10
11class IFile final : public ServiceFramework<IFile> {
12public:
13 explicit IFile(Core::System& system_, FileSys::VirtualFile backend_);
14
15private:
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
10namespace Service::FileSystem {
11
12IFileSystem::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
37void 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
53void 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
63void 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
73void 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
83void 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
93void 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
103void 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
113void 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
138void 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
162void 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
181void IFileSystem::Commit(HLERequestContext& ctx) {
182 LOG_WARNING(Service_FS, "(STUBBED) called");
183
184 IPC::ResponseBuilder rb{ctx, 2};
185 rb.Push(ResultSuccess);
186}
187
188void 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
196void 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
204void 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
223void 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
11namespace Service::FileSystem {
12
13class IFileSystem final : public ServiceFramework<IFileSystem> {
14public:
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
33private:
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
8namespace Service::FileSystem {
9
10IStorage::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
23void 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
53void 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
10namespace Service::FileSystem {
11
12class IStorage final : public ServiceFramework<IStorage> {
13public:
14 explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_);
15
16private:
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
6namespace Service::FileSystem { 6namespace 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
6namespace Service::FileSystem { 6namespace 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
36namespace Service::FileSystem { 38namespace Service::FileSystem {
37
38struct 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
50enum class FileSystemType : u8 { 39enum 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
61class IStorage final : public ServiceFramework<IStorage> {
62public:
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
76private:
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
119class IFile final : public ServiceFramework<IFile> {
120public:
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
135private:
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
245template <typename T>
246static 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
262class IDirectory final : public ServiceFramework<IDirectory> {
263public:
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
282private:
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
322class IFileSystem final : public ServiceFramework<IFileSystem> {
323public:
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
575private:
576 VfsDirectoryServiceWrapper backend;
577 SizeGetter size;
578};
579
580class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> { 50class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
581public: 51public:
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
1133void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) { 603void 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
8namespace Service::FileSystem {
9
10struct 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
10namespace Service::FileSystem { 10namespace 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
10namespace Service::FileSystem { 10namespace 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));