diff options
author | bunnei <bunneidev@gmail.com> | 2018-07-08 05:24:51 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2018-07-08 05:24:51 +0200 |
commit | 913896cbd99e414c325c9d47a987376ed6d9fffd (patch) | |
tree | b660920a49f538f0ee00486c50a0d153d53c423d /src/core/hle | |
parent | Merge pull request #632 from FearlessTobi/add-discord-link (diff) | |
download | yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar.gz yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar.bz2 yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar.lz yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar.xz yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.tar.zst yuzu-913896cbd99e414c325c9d47a987376ed6d9fffd.zip |
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/service/am/am.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 225 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/filesystem.h | 133 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 114 | ||||
-rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.h | 2 |
5 files changed, 71 insertions, 405 deletions
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7bb13c735..a871b3eaa 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -621,7 +621,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; FileSys::Path unused; - auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData); + auto savedata = FileSystem::OpenFileSystem(FileSystem::Type::SaveData, unused); if (savedata.Failed()) { // Create the save data and return an error indicating that the operation was performed. FileSystem::FormatFileSystem(FileSystem::Type::SaveData); diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 25810c165..f58b518b6 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -2,221 +2,36 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "boost/container/flat_map.hpp" -#include "common/assert.h" -#include "common/common_paths.h" +#include <boost/container/flat_map.hpp> #include "common/file_util.h" -#include "core/core.h" -#include "core/file_sys/errors.h" #include "core/file_sys/filesystem.h" -#include "core/file_sys/vfs.h" -#include "core/file_sys/vfs_offset.h" -#include "core/file_sys/vfs_real.h" -#include "core/hle/kernel/process.h" +#include "core/file_sys/savedata_factory.h" +#include "core/file_sys/sdmc_factory.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" namespace Service::FileSystem { -// Size of emulated sd card free space, reported in bytes. -// Just using 32GB because thats reasonable -// TODO(DarkLordZach): Eventually make this configurable in settings. -constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000; - -static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, - const std::string& dir_name) { - if (dir_name == "." || dir_name == "" || dir_name == "/" || dir_name == "\\") - return base; - - return base->GetDirectoryRelative(dir_name); -} - -VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_) - : backing(backing_) {} - -std::string VfsDirectoryServiceWrapper::GetName() const { - return backing->GetName(); -} - -ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path, u64 size) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - auto file = dir->CreateFile(FileUtil::GetFilename(path)); - if (file == nullptr) - return ResultCode(-1); - if (!file->Resize(size)) - return ResultCode(-1); - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - if (!backing->DeleteFile(FileUtil::GetFilename(path))) - return ResultCode(-1); - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - if (dir == nullptr && FileUtil::GetFilename(FileUtil::GetParentPath(path)).empty()) - dir = backing; - auto new_dir = dir->CreateSubdirectory(FileUtil::GetFilename(path)); - if (new_dir == nullptr) - return ResultCode(-1); - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - if (!dir->DeleteSubdirectory(FileUtil::GetFilename(path))) - return ResultCode(-1); - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - if (!dir->DeleteSubdirectoryRecursive(FileUtil::GetFilename(path))) - return ResultCode(-1); - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path, - const std::string& dest_path) const { - auto src = backing->GetFileRelative(src_path); - if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { - // Use more-optimized vfs implementation rename. - if (src == nullptr) - return FileSys::ERROR_PATH_NOT_FOUND; - if (!src->Rename(FileUtil::GetFilename(dest_path))) - return ResultCode(-1); - return RESULT_SUCCESS; - } - - // Move by hand -- TODO(DarkLordZach): Optimize - auto c_res = CreateFile(dest_path, src->GetSize()); - if (c_res != RESULT_SUCCESS) - return c_res; - - auto dest = backing->GetFileRelative(dest_path); - ASSERT_MSG(dest != nullptr, "Newly created file with success cannot be found."); - - ASSERT_MSG(dest->WriteBytes(src->ReadAllBytes()) == src->GetSize(), - "Could not write all of the bytes but everything else has succeded."); - - if (!src->GetContainingDirectory()->DeleteFile(FileUtil::GetFilename(src_path))) - return ResultCode(-1); - - return RESULT_SUCCESS; -} - -ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path, - const std::string& dest_path) const { - auto src = GetDirectoryRelativeWrapped(backing, src_path); - if (FileUtil::GetParentPath(src_path) == FileUtil::GetParentPath(dest_path)) { - // Use more-optimized vfs implementation rename. - if (src == nullptr) - return FileSys::ERROR_PATH_NOT_FOUND; - if (!src->Rename(FileUtil::GetFilename(dest_path))) - return ResultCode(-1); - return RESULT_SUCCESS; - } - - // TODO(DarkLordZach): Implement renaming across the tree (move). - ASSERT_MSG(false, - "Could not rename directory with path \"{}\" to new path \"{}\" because parent dirs " - "don't match -- UNIMPLEMENTED", - src_path, dest_path); - - return ResultCode(-1); -} - -ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path, - FileSys::Mode mode) const { - auto file = backing->GetFileRelative(path); - if (file == nullptr) - return FileSys::ERROR_PATH_NOT_FOUND; - - if ((static_cast<u32>(mode) & static_cast<u32>(FileSys::Mode::Append)) != 0) { - return MakeResult<FileSys::VirtualFile>( - std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize())); - } - - return MakeResult<FileSys::VirtualFile>(file); -} - -ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path) { - auto dir = GetDirectoryRelativeWrapped(backing, path); - if (dir == nullptr) - return ResultCode(-1); - return MakeResult(dir); -} - -u64 VfsDirectoryServiceWrapper::GetFreeSpaceSize() const { - if (backing->IsWritable()) - return EMULATED_SD_REPORTED_SIZE; - - return 0; -} - -ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType( - const std::string& path) const { - auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path)); - if (dir == nullptr) - return ResultCode(-1); - auto filename = FileUtil::GetFilename(path); - if (dir->GetFile(filename) != nullptr) - return MakeResult(FileSys::EntryType::File); - if (dir->GetSubdirectory(filename) != nullptr) - return MakeResult(FileSys::EntryType::Directory); - return ResultCode(-1); -} - -// A deferred filesystem for nand save data. -// This must be deferred because the directory is dependent on title id, which is not set at -// registration time. -struct SaveDataDeferredFilesystem : DeferredFilesystem { -protected: - FileSys::VirtualDir CreateFilesystem() override { - u64 title_id = Core::CurrentProcess()->program_id; - // TODO(DarkLordZach): Users - u32 user_id = 0; - std::string nand_directory = fmt::format( - "{}save/{:016X}/{:08X}/", FileUtil::GetUserPath(D_NAND_IDX), title_id, user_id); - - auto savedata = - std::make_shared<FileSys::RealVfsDirectory>(nand_directory, FileSys::Mode::Write); - return savedata; - } -}; - /** * Map of registered file systems, identified by type. Once an file system is registered here, it * is never removed until UnregisterFileSystems is called. */ -static boost::container::flat_map<Type, std::unique_ptr<DeferredFilesystem>> filesystem_map; -static FileSys::VirtualFile filesystem_romfs = nullptr; +static boost::container::flat_map<Type, std::unique_ptr<FileSys::FileSystemFactory>> filesystem_map; -ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& factory, Type type) { +ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type) { auto result = filesystem_map.emplace(type, std::move(factory)); bool inserted = result.second; ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); auto& filesystem = result.first->second; - LOG_DEBUG(Service_FS, "Registered file system with id code 0x{:08X}", static_cast<u32>(type)); - return RESULT_SUCCESS; -} - -ResultCode RegisterRomFS(FileSys::VirtualFile filesystem) { - ASSERT_MSG(filesystem_romfs == nullptr, - "Tried to register more than one system with same id code"); - - filesystem_romfs = filesystem; LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(), - static_cast<u32>(Type::RomFS)); + static_cast<u32>(type)); return RESULT_SUCCESS; } -ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) { +ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, + FileSys::Path& path) { LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast<u32>(type)); auto itr = filesystem_map.find(type); @@ -225,13 +40,7 @@ ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type) { return ResultCode(-1); } - return MakeResult(itr->second->Get()); -} - -ResultVal<FileSys::VirtualFile> OpenRomFS() { - if (filesystem_romfs == nullptr) - return ResultCode(-1); - return MakeResult(filesystem_romfs); + return itr->second->Open(path); } ResultCode FormatFileSystem(Type type) { @@ -243,21 +52,21 @@ ResultCode FormatFileSystem(Type type) { return ResultCode(-1); } - return itr->second->Get()->GetParentDirectory()->DeleteSubdirectory( - itr->second->Get()->GetName()) - ? RESULT_SUCCESS - : ResultCode(-1); + FileSys::Path unused; + return itr->second->Format(unused); } void RegisterFileSystems() { filesystem_map.clear(); - filesystem_romfs = nullptr; + std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); - auto sdcard = std::make_shared<FileSys::RealVfsDirectory>(sd_directory, FileSys::Mode::Write); - RegisterFileSystem(std::make_unique<DeferredFilesystem>(sdcard), Type::SDMC); - RegisterFileSystem(std::make_unique<SaveDataDeferredFilesystem>(), Type::SaveData); + auto savedata = std::make_unique<FileSys::SaveData_Factory>(std::move(nand_directory)); + RegisterFileSystem(std::move(savedata), Type::SaveData); + + auto sdcard = std::make_unique<FileSys::SDMC_Factory>(std::move(sd_directory)); + RegisterFileSystem(std::move(sdcard), Type::SDMC); } void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index d3de797f1..56d26146e 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -6,8 +6,6 @@ #include <memory> #include "common/common_types.h" -#include "core/file_sys/filesystem.h" -#include "core/file_sys/vfs.h" #include "core/hle/result.h" namespace FileSys { @@ -31,136 +29,12 @@ enum class Type { SDMC = 3, }; -// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of -// pointers and booleans. This makes using a VfsDirectory with switch services much easier and -// avoids repetitive code. -class VfsDirectoryServiceWrapper { -public: - explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing); - - /** - * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) - */ - std::string GetName() const; - - /** - * Create a file specified by its path - * @param path Path relative to the Archive - * @param size The size of the new file, filled with zeroes - * @return Result of the operation - */ - ResultCode CreateFile(const std::string& path, u64 size) const; - - /** - * Delete a file specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - ResultCode DeleteFile(const std::string& path) const; - - /** - * Create a directory specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - ResultCode CreateDirectory(const std::string& path) const; - - /** - * Delete a directory specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - ResultCode DeleteDirectory(const std::string& path) const; - - /** - * Delete a directory specified by its path and anything under it - * @param path Path relative to the archive - * @return Result of the operation - */ - ResultCode DeleteDirectoryRecursively(const std::string& path) const; - - /** - * Rename a File specified by its path - * @param src_path Source path relative to the archive - * @param dest_path Destination path relative to the archive - * @return Result of the operation - */ - ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const; - - /** - * Rename a Directory specified by its path - * @param src_path Source path relative to the archive - * @param dest_path Destination path relative to the archive - * @return Result of the operation - */ - ResultCode RenameDirectory(const std::string& src_path, const std::string& dest_path) const; - - /** - * Open a file specified by its path, using the specified mode - * @param path Path relative to the archive - * @param mode Mode to open the file with - * @return Opened file, or error code - */ - ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const; - - /** - * Open a directory specified by its path - * @param path Path relative to the archive - * @return Opened directory, or error code - */ - ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path); - - /** - * Get the free space - * @return The number of free bytes in the archive - */ - u64 GetFreeSpaceSize() const; - - /** - * Get the type of the specified path - * @return The type of the specified path or error code - */ - ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const; - -private: - FileSys::VirtualDir backing; -}; - -// A class that deferres the creation of a filesystem until a later time. -// This is useful if construction depends on a variable not known when the filesystem is registered. -// Construct this with a filesystem (VirtualDir) to avoid the deferrence feature or override the -// CreateFilesystem method which will be called on first use. -struct DeferredFilesystem { - DeferredFilesystem() = default; - - explicit DeferredFilesystem(FileSys::VirtualDir vfs_directory) : fs(std::move(vfs_directory)) {} - - FileSys::VirtualDir Get() { - if (fs == nullptr) - fs = CreateFilesystem(); - - return fs; - } - - virtual ~DeferredFilesystem() = default; - -protected: - virtual FileSys::VirtualDir CreateFilesystem() { - return fs; - } - -private: - FileSys::VirtualDir fs; -}; - /** * Registers a FileSystem, instances of which can later be opened using its IdCode. * @param factory FileSystem backend interface to use * @param type Type used to access this type of FileSystem */ -ResultCode RegisterFileSystem(std::unique_ptr<DeferredFilesystem>&& fs, Type type); - -ResultCode RegisterRomFS(FileSys::VirtualFile fs); +ResultCode RegisterFileSystem(std::unique_ptr<FileSys::FileSystemFactory>&& factory, Type type); /** * Opens a file system @@ -168,9 +42,8 @@ ResultCode RegisterRomFS(FileSys::VirtualFile fs); * @param path Path to the file system, used with Binary paths * @return FileSys::FileSystemBackend interface to the file system */ -ResultVal<FileSys::VirtualDir> OpenFileSystem(Type type); - -ResultVal<FileSys::VirtualFile> OpenRomFS(); +ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenFileSystem(Type type, + FileSys::Path& path); /** * Formats a file system diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 26e8a8c88..216bfea0a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -19,8 +19,8 @@ namespace Service::FileSystem { class IStorage final : public ServiceFramework<IStorage> { public: - IStorage(FileSys::VirtualFile backend_) - : ServiceFramework("IStorage"), backend(std::move(backend_)) { + IStorage(std::unique_ptr<FileSys::StorageBackend>&& backend) + : ServiceFramework("IStorage"), backend(std::move(backend)) { static const FunctionInfo functions[] = { {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"}, {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, {5, nullptr, "OperateRange"}, @@ -29,7 +29,7 @@ public: } private: - FileSys::VirtualFile backend; + std::unique_ptr<FileSys::StorageBackend> backend; void Read(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -51,8 +51,8 @@ private: } // Read the data from the Storage backend - std::vector<u8> output = backend->ReadBytes(length, offset); - auto res = MakeResult<size_t>(output.size()); + std::vector<u8> output(length); + ResultVal<size_t> res = backend->Read(offset, length, output.data()); if (res.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); @@ -69,8 +69,8 @@ private: class IFile final : public ServiceFramework<IFile> { public: - explicit IFile(FileSys::VirtualFile backend_) - : ServiceFramework("IFile"), backend(std::move(backend_)) { + explicit IFile(std::unique_ptr<FileSys::StorageBackend>&& backend) + : ServiceFramework("IFile"), backend(std::move(backend)) { static const FunctionInfo functions[] = { {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"}, @@ -80,7 +80,7 @@ public: } private: - FileSys::VirtualFile backend; + std::unique_ptr<FileSys::StorageBackend> backend; void Read(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -103,8 +103,8 @@ private: } // Read the data from the Storage backend - std::vector<u8> output = backend->ReadBytes(length, offset); - auto res = MakeResult<size_t>(output.size()); + std::vector<u8> output(length); + ResultVal<size_t> res = backend->Read(offset, length, output.data()); if (res.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); @@ -139,10 +139,9 @@ private: return; } - std::vector<u8> data = ctx.ReadBuffer(); - data.resize(length); // Write the data to the Storage backend - auto res = MakeResult<size_t>(backend->WriteBytes(data, offset)); + std::vector<u8> data = ctx.ReadBuffer(); + ResultVal<size_t> res = backend->Write(offset, length, true, data.data()); if (res.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(res.Code()); @@ -155,8 +154,7 @@ private: void Flush(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - - // Exists for SDK compatibiltity -- No need to flush file. + backend->Flush(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -165,7 +163,7 @@ private: void SetSize(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u64 size = rp.Pop<u64>(); - backend->Resize(size); + backend->SetSize(size); LOG_DEBUG(Service_FS, "called, size={}", size); IPC::ResponseBuilder rb{ctx, 2}; @@ -182,38 +180,19 @@ private: } }; -template <typename T> -static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data, - FileSys::EntryType type) { - for (const auto& new_entry : new_data) { - FileSys::Entry entry; - entry.filename[0] = '\0'; - std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1); - entry.type = type; - entry.file_size = new_entry->GetSize(); - entries.emplace_back(std::move(entry)); - } -} - class IDirectory final : public ServiceFramework<IDirectory> { public: - explicit IDirectory(FileSys::VirtualDir backend_) - : ServiceFramework("IDirectory"), backend(std::move(backend_)) { + explicit IDirectory(std::unique_ptr<FileSys::DirectoryBackend>&& backend) + : ServiceFramework("IDirectory"), backend(std::move(backend)) { static const FunctionInfo functions[] = { {0, &IDirectory::Read, "Read"}, {1, &IDirectory::GetEntryCount, "GetEntryCount"}, }; RegisterHandlers(functions); - - // Build entry index now to save time later. - BuildEntryIndex(entries, backend->GetFiles(), FileSys::File); - BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::Directory); } private: - FileSys::VirtualDir backend; - std::vector<FileSys::Entry> entries; - u64 next_entry_index = 0; + std::unique_ptr<FileSys::DirectoryBackend> backend; void Read(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; @@ -224,31 +203,26 @@ private: // Calculate how many entries we can fit in the output buffer u64 count_entries = ctx.GetWriteBufferSize() / sizeof(FileSys::Entry); - // Cap at total number of entries. - u64 actual_entries = std::min(count_entries, entries.size() - next_entry_index); - // Read the data from the Directory backend - std::vector<FileSys::Entry> entry_data(entries.begin() + next_entry_index, - entries.begin() + next_entry_index + actual_entries); - - next_entry_index += actual_entries; + std::vector<FileSys::Entry> entries(count_entries); + u64 read_entries = backend->Read(count_entries, entries.data()); // Convert the data into a byte array - std::vector<u8> output(entry_data.size() * sizeof(FileSys::Entry)); - std::memcpy(output.data(), entry_data.data(), output.size()); + std::vector<u8> output(entries.size() * sizeof(FileSys::Entry)); + std::memcpy(output.data(), entries.data(), output.size()); // Write the data to memory ctx.WriteBuffer(output); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(actual_entries); + rb.Push(read_entries); } void GetEntryCount(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - u64 count = entries.size() - next_entry_index; + u64 count = backend->GetEntryCount(); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -258,7 +232,7 @@ private: class IFileSystem final : public ServiceFramework<IFileSystem> { public: - explicit IFileSystem(FileSys::VirtualDir backend) + explicit IFileSystem(std::unique_ptr<FileSys::FileSystemBackend>&& backend) : ServiceFramework("IFileSystem"), backend(std::move(backend)) { static const FunctionInfo functions[] = { {0, &IFileSystem::CreateFile, "CreateFile"}, @@ -293,7 +267,7 @@ public: LOG_DEBUG(Service_FS, "called file {} mode 0x{:X} size 0x{:08X}", name, mode, size); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(backend.CreateFile(name, size)); + rb.Push(backend->CreateFile(name, size)); } void DeleteFile(Kernel::HLERequestContext& ctx) { @@ -305,7 +279,7 @@ public: LOG_DEBUG(Service_FS, "called file {}", name); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(backend.DeleteFile(name)); + rb.Push(backend->DeleteFile(name)); } void CreateDirectory(Kernel::HLERequestContext& ctx) { @@ -317,7 +291,7 @@ public: LOG_DEBUG(Service_FS, "called directory {}", name); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(backend.CreateDirectory(name)); + rb.Push(backend->CreateDirectory(name)); } void RenameFile(Kernel::HLERequestContext& ctx) { @@ -335,7 +309,7 @@ public: LOG_DEBUG(Service_FS, "called file '{}' to file '{}'", src_name, dst_name); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(backend.RenameFile(src_name, dst_name)); + rb.Push(backend->RenameFile(src_name, dst_name)); } void OpenFile(Kernel::HLERequestContext& ctx) { @@ -348,14 +322,14 @@ public: LOG_DEBUG(Service_FS, "called file {} mode {}", name, static_cast<u32>(mode)); - auto result = backend.OpenFile(name, mode); + auto result = backend->OpenFile(name, mode); if (result.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result.Code()); return; } - IFile file(result.Unwrap()); + auto file = std::move(result.Unwrap()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -373,14 +347,14 @@ public: LOG_DEBUG(Service_FS, "called directory {} filter {}", name, filter_flags); - auto result = backend.OpenDirectory(name); + auto result = backend->OpenDirectory(name); if (result.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result.Code()); return; } - IDirectory directory(result.Unwrap()); + auto directory = std::move(result.Unwrap()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -395,7 +369,7 @@ public: LOG_DEBUG(Service_FS, "called file {}", name); - auto result = backend.GetEntryType(name); + auto result = backend->GetEntryType(name); if (result.Failed()) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(result.Code()); @@ -415,7 +389,7 @@ public: } private: - VfsDirectoryServiceWrapper backend; + std::unique_ptr<FileSys::FileSystemBackend> backend; }; FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { @@ -516,7 +490,8 @@ void FSP_SRV::TryLoadRomFS() { if (romfs) { return; } - auto res = OpenRomFS(); + FileSys::Path unused; + auto res = OpenFileSystem(Type::RomFS, unused); if (res.Succeeded()) { romfs = std::move(res.Unwrap()); } @@ -532,7 +507,8 @@ void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - IFileSystem filesystem(OpenFileSystem(Type::SDMC).Unwrap()); + FileSys::Path unused; + auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -555,7 +531,8 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); - IFileSystem filesystem(OpenFileSystem(Type::SaveData).Unwrap()); + FileSys::Path unused; + auto filesystem = OpenFileSystem(Type::SaveData, unused).Unwrap(); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -582,11 +559,18 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { return; } - IStorage storage(romfs); + // Attempt to open a StorageBackend interface to the RomFS + auto storage = romfs->OpenFile({}, {}); + if (storage.Failed()) { + LOG_CRITICAL(Service_FS, "no storage interface available!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(storage.Code()); + return; + } IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IStorage>(std::move(storage)); + rb.PushIpcInterface<IStorage>(std::move(storage.Unwrap())); } void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index b1ef6397f..acb78fac1 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -29,7 +29,7 @@ private: void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OpenRomStorage(Kernel::HLERequestContext& ctx); - FileSys::VirtualFile romfs; + std::unique_ptr<FileSys::FileSystemBackend> romfs; }; } // namespace Service::FileSystem |