diff options
| author | 2024-01-05 05:23:58 +0100 | |
|---|---|---|
| committer | 2024-01-25 16:40:42 -0500 | |
| commit | 06fb7f90da0b465e723a562134c12b513aa77dff (patch) | |
| tree | a256bbe22aa4c2a6704f41eb22b3d2cfba0fed72 /src/core | |
| parent | Merge pull request #12759 from liamwhite/mp-misc (diff) | |
| download | yuzu-06fb7f90da0b465e723a562134c12b513aa77dff.tar.gz yuzu-06fb7f90da0b465e723a562134c12b513aa77dff.tar.xz yuzu-06fb7f90da0b465e723a562134c12b513aa77dff.zip | |
fs: Move fsp_srv subclasses to separate files
fs: Move additional files to the fsp directory
Diffstat (limited to 'src/core')
17 files changed, 687 insertions, 542 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 45a0d8746..68c430a65 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -488,16 +488,25 @@ add_library(core STATIC | |||
| 488 | hle/service/fatal/fatal_u.h | 488 | hle/service/fatal/fatal_u.h |
| 489 | hle/service/filesystem/filesystem.cpp | 489 | hle/service/filesystem/filesystem.cpp |
| 490 | hle/service/filesystem/filesystem.h | 490 | hle/service/filesystem/filesystem.h |
| 491 | hle/service/filesystem/fsp/fs_i_directory.cpp | ||
| 492 | hle/service/filesystem/fsp/fs_i_directory.h | ||
| 493 | hle/service/filesystem/fsp/fs_i_file.cpp | ||
| 494 | hle/service/filesystem/fsp/fs_i_file.h | ||
| 495 | hle/service/filesystem/fsp/fs_i_filesystem.cpp | ||
| 496 | hle/service/filesystem/fsp/fs_i_filesystem.h | ||
| 497 | hle/service/filesystem/fsp/fs_i_storage.cpp | ||
| 498 | hle/service/filesystem/fsp/fs_i_storage.h | ||
| 499 | hle/service/filesystem/fsp/fsp_srv.cpp | ||
| 500 | hle/service/filesystem/fsp/fsp_srv.h | ||
| 491 | hle/service/filesystem/fsp_ldr.cpp | 501 | hle/service/filesystem/fsp_ldr.cpp |
| 492 | hle/service/filesystem/fsp_ldr.h | 502 | hle/service/filesystem/fsp_ldr.h |
| 493 | hle/service/filesystem/fsp_pr.cpp | 503 | hle/service/filesystem/fsp_pr.cpp |
| 494 | hle/service/filesystem/fsp_pr.h | 504 | hle/service/filesystem/fsp_pr.h |
| 495 | hle/service/filesystem/fsp_srv.cpp | ||
| 496 | hle/service/filesystem/fsp_srv.h | ||
| 497 | hle/service/filesystem/romfs_controller.cpp | 505 | hle/service/filesystem/romfs_controller.cpp |
| 498 | hle/service/filesystem/romfs_controller.h | 506 | hle/service/filesystem/romfs_controller.h |
| 499 | hle/service/filesystem/save_data_controller.cpp | 507 | hle/service/filesystem/save_data_controller.cpp |
| 500 | hle/service/filesystem/save_data_controller.h | 508 | hle/service/filesystem/save_data_controller.h |
| 509 | hle/service/filesystem/fsp_util.h | ||
| 501 | hle/service/fgm/fgm.cpp | 510 | hle/service/fgm/fgm.cpp |
| 502 | hle/service/fgm/fgm.h | 511 | hle/service/fgm/fgm.h |
| 503 | hle/service/friend/friend.cpp | 512 | hle/service/friend/friend.cpp |
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index ca6d8d607..ab4974ac5 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -21,9 +21,9 @@ | |||
| 21 | #include "core/file_sys/vfs.h" | 21 | #include "core/file_sys/vfs.h" |
| 22 | #include "core/file_sys/vfs_offset.h" | 22 | #include "core/file_sys/vfs_offset.h" |
| 23 | #include "core/hle/service/filesystem/filesystem.h" | 23 | #include "core/hle/service/filesystem/filesystem.h" |
| 24 | #include "core/hle/service/filesystem/fsp_ldr.h" | 24 | #include "core/hle/service/filesystem/fsp/fsp_ldr.h" |
| 25 | #include "core/hle/service/filesystem/fsp_pr.h" | 25 | #include "core/hle/service/filesystem/fsp/fsp_pr.h" |
| 26 | #include "core/hle/service/filesystem/fsp_srv.h" | 26 | #include "core/hle/service/filesystem/fsp/fsp_srv.h" |
| 27 | #include "core/hle/service/filesystem/romfs_controller.h" | 27 | #include "core/hle/service/filesystem/romfs_controller.h" |
| 28 | #include "core/hle/service/filesystem/save_data_controller.h" | 28 | #include "core/hle/service/filesystem/save_data_controller.h" |
| 29 | #include "core/hle/service/server_manager.h" | 29 | #include "core/hle/service/server_manager.h" |
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..62512ad0f --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.cpp | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "core/file_sys/savedata_factory.h" | ||
| 5 | #include "core/hle/service/filesystem/fsp/fs_i_directory.h" | ||
| 6 | #include "core/hle/service/ipc_helpers.h" | ||
| 7 | |||
| 8 | namespace Service::FileSystem { | ||
| 9 | |||
| 10 | template <typename T> | ||
| 11 | static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data, | ||
| 12 | FileSys::EntryType type) { | ||
| 13 | entries.reserve(entries.size() + new_data.size()); | ||
| 14 | |||
| 15 | for (const auto& new_entry : new_data) { | ||
| 16 | auto name = new_entry->GetName(); | ||
| 17 | |||
| 18 | if (type == FileSys::EntryType::File && name == FileSys::GetSaveDataSizeFileName()) { | ||
| 19 | continue; | ||
| 20 | } | ||
| 21 | |||
| 22 | entries.emplace_back(name, type, | ||
| 23 | type == FileSys::EntryType::Directory ? 0 : new_entry->GetSize()); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | IDirectory::IDirectory(Core::System& system_, FileSys::VirtualDir backend_, OpenDirectoryMode mode) | ||
| 28 | : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) { | ||
| 29 | static const FunctionInfo functions[] = { | ||
| 30 | {0, &IDirectory::Read, "Read"}, | ||
| 31 | {1, &IDirectory::GetEntryCount, "GetEntryCount"}, | ||
| 32 | }; | ||
| 33 | RegisterHandlers(functions); | ||
| 34 | |||
| 35 | // TODO(DarkLordZach): Verify that this is the correct behavior. | ||
| 36 | // Build entry index now to save time later. | ||
| 37 | if (True(mode & OpenDirectoryMode::Directory)) { | ||
| 38 | BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::EntryType::Directory); | ||
| 39 | } | ||
| 40 | if (True(mode & OpenDirectoryMode::File)) { | ||
| 41 | BuildEntryIndex(entries, backend->GetFiles(), FileSys::EntryType::File); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | void IDirectory::Read(HLERequestContext& ctx) { | ||
| 46 | LOG_DEBUG(Service_FS, "called."); | ||
| 47 | |||
| 48 | // Calculate how many entries we can fit in the output buffer | ||
| 49 | const u64 count_entries = ctx.GetWriteBufferNumElements<FileSys::Entry>(); | ||
| 50 | |||
| 51 | // Cap at total number of entries. | ||
| 52 | const u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); | ||
| 53 | |||
| 54 | // Determine data start and end | ||
| 55 | const auto* begin = reinterpret_cast<u8*>(entries.data() + next_entry_index); | ||
| 56 | const auto* end = reinterpret_cast<u8*>(entries.data() + next_entry_index + actual_entries); | ||
| 57 | const auto range_size = static_cast<std::size_t>(std::distance(begin, end)); | ||
| 58 | |||
| 59 | next_entry_index += actual_entries; | ||
| 60 | |||
| 61 | // Write the data to memory | ||
| 62 | ctx.WriteBuffer(begin, range_size); | ||
| 63 | |||
| 64 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 65 | rb.Push(ResultSuccess); | ||
| 66 | rb.Push(actual_entries); | ||
| 67 | } | ||
| 68 | |||
| 69 | void IDirectory::GetEntryCount(HLERequestContext& ctx) { | ||
| 70 | LOG_DEBUG(Service_FS, "called"); | ||
| 71 | |||
| 72 | u64 count = entries.size() - next_entry_index; | ||
| 73 | |||
| 74 | IPC::ResponseBuilder rb{ctx, 4}; | ||
| 75 | rb.Push(ResultSuccess); | ||
| 76 | rb.Push(count); | ||
| 77 | } | ||
| 78 | |||
| 79 | } // 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..2a28ee496 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_directory.h | |||
| @@ -0,0 +1,27 @@ | |||
| 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.h" | ||
| 7 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 8 | #include "core/hle/service/filesystem/fsp_util.h" | ||
| 9 | #include "core/hle/service/service.h" | ||
| 10 | |||
| 11 | namespace Service::FileSystem { | ||
| 12 | |||
| 13 | class IDirectory final : public ServiceFramework<IDirectory> { | ||
| 14 | public: | ||
| 15 | explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, | ||
| 16 | OpenDirectoryMode mode); | ||
| 17 | |||
| 18 | private: | ||
| 19 | FileSys::VirtualDir backend; | ||
| 20 | std::vector<FileSys::Entry> entries; | ||
| 21 | u64 next_entry_index = 0; | ||
| 22 | |||
| 23 | void Read(HLERequestContext& ctx); | ||
| 24 | void GetEntryCount(HLERequestContext& ctx); | ||
| 25 | }; | ||
| 26 | |||
| 27 | } // 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..7e0c90a89 --- /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::ERROR_INVALID_SIZE); | ||
| 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::ERROR_INVALID_OFFSET); | ||
| 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::ERROR_INVALID_SIZE); | ||
| 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::ERROR_INVALID_OFFSET); | ||
| 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..a7eb1a1e9 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_file.h | |||
| @@ -0,0 +1,26 @@ | |||
| 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.h" | ||
| 7 | #include "core/hle/service/filesystem/filesystem.h" | ||
| 8 | #include "core/hle/service/service.h" | ||
| 9 | |||
| 10 | namespace Service::FileSystem { | ||
| 11 | |||
| 12 | class IFile final : public ServiceFramework<IFile> { | ||
| 13 | public: | ||
| 14 | explicit IFile(Core::System& system_, FileSys::VirtualFile backend_); | ||
| 15 | |||
| 16 | private: | ||
| 17 | FileSys::VirtualFile backend; | ||
| 18 | |||
| 19 | void Read(HLERequestContext& ctx); | ||
| 20 | void Write(HLERequestContext& ctx); | ||
| 21 | void Flush(HLERequestContext& ctx); | ||
| 22 | void SetSize(HLERequestContext& ctx); | ||
| 23 | void GetSize(HLERequestContext& ctx); | ||
| 24 | }; | ||
| 25 | |||
| 26 | } // 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..3e72101a4 --- /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_)}, | ||
| 14 | size{std::move(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::Mode>(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<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::EntryType 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..c9e94c911 --- /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.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..9fe36f31a --- /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::ERROR_INVALID_SIZE); | ||
| 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::ERROR_INVALID_OFFSET); | ||
| 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..48d059874 --- /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.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..85ab75517 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp | |||
| @@ -26,7 +26,9 @@ | |||
| 26 | #include "core/file_sys/vfs.h" | 26 | #include "core/file_sys/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,532 +47,13 @@ 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_, |
| 583 | std::shared_ptr<SaveDataController> save_data_controller_, | 53 | std::shared_ptr<SaveDataController> save_data_controller_, |
| 584 | FileSys::SaveDataSpaceId space) | 54 | FileSys::SaveDataSpaceId space) |
| 585 | : ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{ | 55 | : ServiceFramework{system_, "ISaveDataInfoReader"}, |
| 586 | save_data_controller_} { | 56 | save_data_controller{save_data_controller_} { |
| 587 | static const FunctionInfo functions[] = { | 57 | static const FunctionInfo functions[] = { |
| 588 | {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, | 58 | {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, |
| 589 | }; | 59 | }; |
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 | ||