From 2f71a32363ba062f42938091acdf11962cba932e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 19 Jan 2018 21:45:07 -0500 Subject: file_sys: Repurpose 3DS IVFC code for Switch ROMFS. --- src/core/CMakeLists.txt | 4 +- src/core/file_sys/ivfc_archive.cpp | 110 ------------------------------------ src/core/file_sys/ivfc_archive.h | 83 --------------------------- src/core/file_sys/romfs_archive.cpp | 105 ++++++++++++++++++++++++++++++++++ src/core/file_sys/romfs_archive.h | 80 ++++++++++++++++++++++++++ 5 files changed, 187 insertions(+), 195 deletions(-) delete mode 100644 src/core/file_sys/ivfc_archive.cpp delete mode 100644 src/core/file_sys/ivfc_archive.h create mode 100644 src/core/file_sys/romfs_archive.cpp create mode 100644 src/core/file_sys/romfs_archive.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7153c4f3f..ec25ec9cf 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,10 +13,10 @@ add_library(core STATIC file_sys/disk_archive.h file_sys/errors.h file_sys/file_backend.h - file_sys/ivfc_archive.cpp - file_sys/ivfc_archive.h file_sys/path_parser.cpp file_sys/path_parser.h + file_sys/romfs_archive.cpp + file_sys/romfs_archive.h file_sys/savedata_archive.cpp file_sys/savedata_archive.h file_sys/title_metadata.cpp diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp deleted file mode 100644 index b3c3f2c6f..000000000 --- a/src/core/file_sys/ivfc_archive.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/file_sys/ivfc_archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -std::string IVFCArchive::GetName() const { - return "IVFC"; -} - -ResultVal> IVFCArchive::OpenFile(const Path& path, - const Mode& mode) const { - return MakeResult>( - std::make_unique(romfs_file, data_offset, data_size)); -} - -ResultCode IVFCArchive::DeleteFile(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", - GetName().c_str()); - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { - LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::DeleteDirectory(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::DeleteDirectoryRecursively(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { - LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", - GetName().c_str()); - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::CreateDirectory(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { - LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultVal> IVFCArchive::OpenDirectory(const Path& path) const { - return MakeResult>(std::make_unique()); -} - -u64 IVFCArchive::GetFreeBytes() const { - LOG_WARNING(Service_FS, "Attempted to get the free space in an IVFC archive"); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -ResultVal IVFCFile::Read(const u64 offset, const size_t length, u8* buffer) const { - LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); - romfs_file->Seek(data_offset + offset, SEEK_SET); - size_t read_length = (size_t)std::min((u64)length, data_size - offset); - - return MakeResult(romfs_file->ReadBytes(buffer, read_length)); -} - -ResultVal IVFCFile::Write(const u64 offset, const size_t length, const bool flush, - const u8* buffer) const { - LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); - // TODO(Subv): Find error code - return MakeResult(0); -} - -u64 IVFCFile::GetSize() const { - return data_size; -} - -bool IVFCFile::SetSize(const u64 size) const { - LOG_ERROR(Service_FS, "Attempted to set the size of an IVFC file"); - return false; -} - -} // namespace FileSys diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h deleted file mode 100644 index e6fbdfb1f..000000000 --- a/src/core/file_sys/ivfc_archive.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include "common/common_types.h" -#include "common/file_util.h" -#include "core/file_sys/archive_backend.h" -#include "core/file_sys/directory_backend.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/** - * Helper which implements an interface to deal with IVFC images used in some archives - * This should be subclassed by concrete archive types, which will provide the - * input data (load the raw IVFC archive) and override any required methods - */ -class IVFCArchive : public ArchiveBackend { -public: - IVFCArchive(std::shared_ptr file, u64 offset, u64 size) - : romfs_file(file), data_offset(offset), data_size(size) {} - - std::string GetName() const override; - - ResultVal> OpenFile(const Path& path, - const Mode& mode) const override; - ResultCode DeleteFile(const Path& path) const override; - ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; - ResultCode DeleteDirectory(const Path& path) const override; - ResultCode DeleteDirectoryRecursively(const Path& path) const override; - ResultCode CreateFile(const Path& path, u64 size) const override; - ResultCode CreateDirectory(const Path& path) const override; - ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; - ResultVal> OpenDirectory(const Path& path) const override; - u64 GetFreeBytes() const override; - -protected: - std::shared_ptr romfs_file; - u64 data_offset; - u64 data_size; -}; - -class IVFCFile : public FileBackend { -public: - IVFCFile(std::shared_ptr file, u64 offset, u64 size) - : romfs_file(file), data_offset(offset), data_size(size) {} - - ResultVal Read(u64 offset, size_t length, u8* buffer) const override; - ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; - u64 GetSize() const override; - bool SetSize(u64 size) const override; - bool Close() const override { - return false; - } - void Flush() const override {} - -private: - std::shared_ptr romfs_file; - u64 data_offset; - u64 data_size; -}; - -class IVFCDirectory : public DirectoryBackend { -public: - u32 Read(const u32 count, Entry* entries) override { - return 0; - } - bool Close() const override { - return false; - } -}; - -} // namespace FileSys diff --git a/src/core/file_sys/romfs_archive.cpp b/src/core/file_sys/romfs_archive.cpp new file mode 100644 index 000000000..482de2220 --- /dev/null +++ b/src/core/file_sys/romfs_archive.cpp @@ -0,0 +1,105 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include "common/common_types.h" +#include "common/logging/log.h" +#include "core/file_sys/romfs_archive.h" + +namespace FileSys { + +std::string ROMFSArchive::GetName() const { + return "RomFS"; +} + +ResultVal> ROMFSArchive::OpenFile(const Path& path, + const Mode& mode) const { + return MakeResult>( + std::make_unique(romfs_file, data_offset, data_size)); +} + +ResultCode ROMFSArchive::DeleteFile(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(bunnei): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::RenameFile(const Path& src_path, const Path& dest_path) const { + LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::DeleteDirectory(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::DeleteDirectoryRecursively(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::CreateFile(const Path& path, u64 size) const { + LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", + GetName().c_str()); + // TODO(bunnei): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::CreateDirectory(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode ROMFSArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { + LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultVal> ROMFSArchive::OpenDirectory(const Path& path) const { + return MakeResult>(std::make_unique()); +} + +u64 ROMFSArchive::GetFreeBytes() const { + LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); + return 0; +} + +ResultVal ROMFSFile::Read(const u64 offset, const size_t length, u8* buffer) const { + LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); + romfs_file->Seek(data_offset + offset, SEEK_SET); + size_t read_length = (size_t)std::min((u64)length, data_size - offset); + + return MakeResult(romfs_file->ReadBytes(buffer, read_length)); +} + +ResultVal ROMFSFile::Write(const u64 offset, const size_t length, const bool flush, + const u8* buffer) const { + LOG_ERROR(Service_FS, "Attempted to write to ROMFS file"); + // TODO(Subv): Find error code + return MakeResult(0); +} + +u64 ROMFSFile::GetSize() const { + return data_size; +} + +bool ROMFSFile::SetSize(const u64 size) const { + LOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file"); + return false; +} + +} // namespace FileSys diff --git a/src/core/file_sys/romfs_archive.h b/src/core/file_sys/romfs_archive.h new file mode 100644 index 000000000..2bb13146b --- /dev/null +++ b/src/core/file_sys/romfs_archive.h @@ -0,0 +1,80 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include "common/common_types.h" +#include "common/file_util.h" +#include "core/file_sys/archive_backend.h" +#include "core/file_sys/directory_backend.h" +#include "core/file_sys/file_backend.h" +#include "core/hle/result.h" + +namespace FileSys { + +/** + * Helper which implements an interface to deal with Switch .istorage ROMFS images used in some + * archives This should be subclassed by concrete archive types, which will provide the input data + * (load the raw ROMFS archive) and override any required methods + */ +class ROMFSArchive : public ArchiveBackend { +public: + ROMFSArchive(std::shared_ptr file, u64 offset, u64 size) + : romfs_file(file), data_offset(offset), data_size(size) {} + + std::string GetName() const override; + + ResultVal> OpenFile(const Path& path, + const Mode& mode) const override; + ResultCode DeleteFile(const Path& path) const override; + ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; + ResultCode DeleteDirectory(const Path& path) const override; + ResultCode DeleteDirectoryRecursively(const Path& path) const override; + ResultCode CreateFile(const Path& path, u64 size) const override; + ResultCode CreateDirectory(const Path& path) const override; + ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; + ResultVal> OpenDirectory(const Path& path) const override; + u64 GetFreeBytes() const override; + +protected: + std::shared_ptr romfs_file; + u64 data_offset; + u64 data_size; +}; + +class ROMFSFile : public FileBackend { +public: + ROMFSFile(std::shared_ptr file, u64 offset, u64 size) + : romfs_file(file), data_offset(offset), data_size(size) {} + + ResultVal Read(u64 offset, size_t length, u8* buffer) const override; + ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; + u64 GetSize() const override; + bool SetSize(u64 size) const override; + bool Close() const override { + return false; + } + void Flush() const override {} + +private: + std::shared_ptr romfs_file; + u64 data_offset; + u64 data_size; +}; + +class ROMFSDirectory : public DirectoryBackend { +public: + u32 Read(const u32 count, Entry* entries) override { + return 0; + } + bool Close() const override { + return false; + } +}; + +} // namespace FileSys -- cgit v1.2.3 From 7988f0248959b2284ce5cc74bac6aef897627a8e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 19 Jan 2018 22:08:21 -0500 Subject: archive_backend: Minor changes to match Switch IFileSystem. --- src/core/file_sys/archive_backend.h | 44 +++++++++++++++++----------------- src/core/file_sys/romfs_archive.cpp | 2 +- src/core/file_sys/romfs_archive.h | 2 +- src/core/file_sys/savedata_archive.cpp | 2 +- src/core/file_sys/savedata_archive.h | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 58f6c150c..2255bee42 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h @@ -81,13 +81,12 @@ public: virtual std::string GetName() const = 0; /** - * 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 + * 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 */ - virtual ResultVal> OpenFile(const Path& path, - const Mode& mode) const = 0; + virtual ResultCode CreateFile(const Path& path, u64 size) const = 0; /** * Delete a file specified by its path @@ -97,12 +96,11 @@ public: virtual ResultCode DeleteFile(const Path& path) const = 0; /** - * 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 + * Create a directory specified by its path + * @param path Path relative to the archive * @return Result of the operation */ - virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; + virtual ResultCode CreateDirectory(const Path& path) const = 0; /** * Delete a directory specified by its path @@ -119,19 +117,12 @@ public: virtual ResultCode DeleteDirectoryRecursively(const Path& path) const = 0; /** - * 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 - */ - virtual ResultCode CreateFile(const Path& path, u64 size) const = 0; - - /** - * Create a directory specified by its path - * @param path Path relative to the archive + * 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 */ - virtual ResultCode CreateDirectory(const Path& path) const = 0; + virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; /** * Rename a Directory specified by its path @@ -141,6 +132,15 @@ public: */ virtual ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const = 0; + /** + * 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 + */ + virtual ResultVal> OpenFile(const Path& path, + const Mode& mode) const = 0; + /** * Open a directory specified by its path * @param path Path relative to the archive @@ -152,7 +152,7 @@ public: * Get the free space * @return The number of free bytes in the archive */ - virtual u64 GetFreeBytes() const = 0; + virtual u64 GetFreeSpaceSize() const = 0; }; class ArchiveFactory : NonCopyable { diff --git a/src/core/file_sys/romfs_archive.cpp b/src/core/file_sys/romfs_archive.cpp index 482de2220..0d93fccd4 100644 --- a/src/core/file_sys/romfs_archive.cpp +++ b/src/core/file_sys/romfs_archive.cpp @@ -73,7 +73,7 @@ ResultVal> ROMFSArchive::OpenDirectory(const P return MakeResult>(std::make_unique()); } -u64 ROMFSArchive::GetFreeBytes() const { +u64 ROMFSArchive::GetFreeSpaceSize() const { LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); return 0; } diff --git a/src/core/file_sys/romfs_archive.h b/src/core/file_sys/romfs_archive.h index 2bb13146b..2b6c573ba 100644 --- a/src/core/file_sys/romfs_archive.h +++ b/src/core/file_sys/romfs_archive.h @@ -39,7 +39,7 @@ public: ResultCode CreateDirectory(const Path& path) const override; ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; ResultVal> OpenDirectory(const Path& path) const override; - u64 GetFreeBytes() const override; + u64 GetFreeSpaceSize() const override; protected: std::shared_ptr romfs_file; diff --git a/src/core/file_sys/savedata_archive.cpp b/src/core/file_sys/savedata_archive.cpp index d7b012f6e..d12739ca7 100644 --- a/src/core/file_sys/savedata_archive.cpp +++ b/src/core/file_sys/savedata_archive.cpp @@ -322,7 +322,7 @@ ResultVal> SaveDataArchive::OpenDirectory( return MakeResult>(std::move(directory)); } -u64 SaveDataArchive::GetFreeBytes() const { +u64 SaveDataArchive::GetFreeSpaceSize() const { // TODO: Stubbed to return 1GiB return 1024 * 1024 * 1024; } diff --git a/src/core/file_sys/savedata_archive.h b/src/core/file_sys/savedata_archive.h index 176d35710..931dfb17b 100644 --- a/src/core/file_sys/savedata_archive.h +++ b/src/core/file_sys/savedata_archive.h @@ -34,7 +34,7 @@ public: ResultCode CreateDirectory(const Path& path) const override; ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; ResultVal> OpenDirectory(const Path& path) const override; - u64 GetFreeBytes() const override; + u64 GetFreeSpaceSize() const override; protected: std::string mount_point; -- cgit v1.2.3 From 1c06c918af30e4f431920c6197128524b2caee14 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 19 Jan 2018 22:18:01 -0500 Subject: file_sys: Remove disk_archive, savedata_archive, and title_metadata. --- src/core/CMakeLists.txt | 6 - src/core/file_sys/disk_archive.cpp | 99 ---------- src/core/file_sys/disk_archive.h | 68 ------- src/core/file_sys/savedata_archive.cpp | 330 --------------------------------- src/core/file_sys/savedata_archive.h | 43 ----- src/core/file_sys/title_metadata.cpp | 163 ---------------- src/core/file_sys/title_metadata.h | 126 ------------- 7 files changed, 835 deletions(-) delete mode 100644 src/core/file_sys/disk_archive.cpp delete mode 100644 src/core/file_sys/disk_archive.h delete mode 100644 src/core/file_sys/savedata_archive.cpp delete mode 100644 src/core/file_sys/savedata_archive.h delete mode 100644 src/core/file_sys/title_metadata.cpp delete mode 100644 src/core/file_sys/title_metadata.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ec25ec9cf..b2dcc039a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -9,18 +9,12 @@ add_library(core STATIC file_sys/archive_backend.cpp file_sys/archive_backend.h file_sys/directory_backend.h - file_sys/disk_archive.cpp - file_sys/disk_archive.h file_sys/errors.h file_sys/file_backend.h file_sys/path_parser.cpp file_sys/path_parser.h file_sys/romfs_archive.cpp file_sys/romfs_archive.h - file_sys/savedata_archive.cpp - file_sys/savedata_archive.h - file_sys/title_metadata.cpp - file_sys/title_metadata.h frontend/emu_window.cpp frontend/emu_window.h frontend/framebuffer_layout.cpp diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp deleted file mode 100644 index 98d80aabc..000000000 --- a/src/core/file_sys/disk_archive.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include -#include "common/common_types.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "core/file_sys/disk_archive.h" -#include "core/file_sys/errors.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -ResultVal DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { - if (!mode.read_flag) - return ERROR_INVALID_OPEN_FLAGS; - - file->Seek(offset, SEEK_SET); - return MakeResult(file->ReadBytes(buffer, length)); -} - -ResultVal DiskFile::Write(const u64 offset, const size_t length, const bool flush, - const u8* buffer) const { - if (!mode.write_flag) - return ERROR_INVALID_OPEN_FLAGS; - - file->Seek(offset, SEEK_SET); - size_t written = file->WriteBytes(buffer, length); - if (flush) - file->Flush(); - return MakeResult(written); -} - -u64 DiskFile::GetSize() const { - return file->GetSize(); -} - -bool DiskFile::SetSize(const u64 size) const { - file->Resize(size); - file->Flush(); - return true; -} - -bool DiskFile::Close() const { - return file->Close(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -DiskDirectory::DiskDirectory(const std::string& path) : directory() { - unsigned size = FileUtil::ScanDirectoryTree(path, directory); - directory.size = size; - directory.isDirectory = true; - children_iterator = directory.children.begin(); -} - -u32 DiskDirectory::Read(const u32 count, Entry* entries) { - u32 entries_read = 0; - - while (entries_read < count && children_iterator != directory.children.cend()) { - const FileUtil::FSTEntry& file = *children_iterator; - const std::string& filename = file.virtualName; - Entry& entry = entries[entries_read]; - - LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, - file.isDirectory); - - // TODO(Link Mauve): use a proper conversion to UTF-16. - for (size_t j = 0; j < FILENAME_LENGTH; ++j) { - entry.filename[j] = filename[j]; - if (!filename[j]) - break; - } - - FileUtil::SplitFilename83(filename, entry.short_name, entry.extension); - - entry.is_directory = file.isDirectory; - entry.is_hidden = (filename[0] == '.'); - entry.is_read_only = 0; - entry.file_size = file.size; - - // We emulate a SD card where the archive bit has never been cleared, as it would be on - // most user SD cards. - // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a - // file bit. - entry.is_archive = !file.isDirectory; - - ++entries_read; - ++children_iterator; - } - return entries_read; -} - -} // namespace FileSys diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h deleted file mode 100644 index eb9166df6..000000000 --- a/src/core/file_sys/disk_archive.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include "common/common_types.h" -#include "common/file_util.h" -#include "core/file_sys/archive_backend.h" -#include "core/file_sys/directory_backend.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -class DiskFile : public FileBackend { -public: - DiskFile(FileUtil::IOFile&& file_, const Mode& mode_) - : file(new FileUtil::IOFile(std::move(file_))) { - mode.hex = mode_.hex; - } - - ResultVal Read(u64 offset, size_t length, u8* buffer) const override; - ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; - u64 GetSize() const override; - bool SetSize(u64 size) const override; - bool Close() const override; - - void Flush() const override { - file->Flush(); - } - -protected: - Mode mode; - std::unique_ptr file; -}; - -class DiskDirectory : public DirectoryBackend { -public: - DiskDirectory(const std::string& path); - - ~DiskDirectory() override { - Close(); - } - - u32 Read(const u32 count, Entry* entries) override; - - bool Close() const override { - return true; - } - -protected: - u32 total_entries_in_directory; - FileUtil::FSTEntry directory; - - // We need to remember the last entry we returned, so a subsequent call to Read will continue - // from the next one. This iterator will always point to the next unread entry. - std::vector::iterator children_iterator; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/savedata_archive.cpp b/src/core/file_sys/savedata_archive.cpp deleted file mode 100644 index d12739ca7..000000000 --- a/src/core/file_sys/savedata_archive.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "common/file_util.h" -#include "core/file_sys/disk_archive.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/path_parser.h" -#include "core/file_sys/savedata_archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -ResultVal> SaveDataArchive::OpenFile(const Path& path, - const Mode& mode) const { - LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); - - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - if (mode.hex == 0) { - LOG_ERROR(Service_FS, "Empty open mode"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - if (mode.create_flag && !mode.write_flag) { - LOG_ERROR(Service_FS, "Create flag set but write flag not set"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::PathNotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - case PathParser::DirectoryFound: - LOG_ERROR(Service_FS, "Unexpected file or directory in %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY; - case PathParser::NotFound: - if (!mode.create_flag) { - LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", - full_path.c_str()); - return ERROR_FILE_NOT_FOUND; - } else { - // Create the file - FileUtil::CreateEmptyFile(full_path); - } - break; - case PathParser::FileFound: - break; // Expected 'success' case - } - - FileUtil::IOFile file(full_path, mode.write_flag ? "r+b" : "rb"); - if (!file.IsOpen()) { - LOG_CRITICAL(Service_FS, "(unreachable) Unknown error opening %s", full_path.c_str()); - return ERROR_FILE_NOT_FOUND; - } - - auto disk_file = std::make_unique(std::move(file), mode); - return MakeResult>(std::move(disk_file)); -} - -ResultCode SaveDataArchive::DeleteFile(const Path& path) const { - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::PathNotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - case PathParser::DirectoryFound: - case PathParser::NotFound: - LOG_ERROR(Service_FS, "File not found %s", full_path.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::FileFound: - break; // Expected 'success' case - } - - if (FileUtil::Delete(full_path)) { - return RESULT_SUCCESS; - } - - LOG_CRITICAL(Service_FS, "(unreachable) Unknown error deleting %s", full_path.c_str()); - return ERROR_FILE_NOT_FOUND; -} - -ResultCode SaveDataArchive::RenameFile(const Path& src_path, const Path& dest_path) const { - const PathParser path_parser_src(src_path); - - // TODO: Verify these return codes with HW - if (!path_parser_src.IsValid()) { - LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const PathParser path_parser_dest(dest_path); - - if (!path_parser_dest.IsValid()) { - LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto src_path_full = path_parser_src.BuildHostPath(mount_point); - const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); - - if (FileUtil::Rename(src_path_full, dest_path_full)) { - return RESULT_SUCCESS; - } - - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -template -static ResultCode DeleteDirectoryHelper(const Path& path, const std::string& mount_point, - T deleter) { - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - if (path_parser.IsRootDirectory()) - return ERROR_DIRECTORY_NOT_EMPTY; - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::NotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "Unexpected file or directory %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY; - case PathParser::DirectoryFound: - break; // Expected 'success' case - } - - if (deleter(full_path)) { - return RESULT_SUCCESS; - } - - LOG_ERROR(Service_FS, "Directory not empty %s", full_path.c_str()); - return ERROR_DIRECTORY_NOT_EMPTY; -} - -ResultCode SaveDataArchive::DeleteDirectory(const Path& path) const { - return DeleteDirectoryHelper(path, mount_point, FileUtil::DeleteDir); -} - -ResultCode SaveDataArchive::DeleteDirectoryRecursively(const Path& path) const { - return DeleteDirectoryHelper( - path, mount_point, [](const std::string& p) { return FileUtil::DeleteDirRecursively(p); }); -} - -ResultCode SaveDataArchive::CreateFile(const FileSys::Path& path, u64 size) const { - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::PathNotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Unexpected file in path %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY; - case PathParser::DirectoryFound: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "%s already exists", full_path.c_str()); - return ERROR_FILE_ALREADY_EXISTS; - case PathParser::NotFound: - break; // Expected 'success' case - } - - if (size == 0) { - FileUtil::CreateEmptyFile(full_path); - return RESULT_SUCCESS; - } - - FileUtil::IOFile file(full_path, "wb"); - // Creates a sparse file (or a normal file on filesystems without the concept of sparse files) - // We do this by seeking to the right size, then writing a single null byte. - if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) { - return RESULT_SUCCESS; - } - - LOG_ERROR(Service_FS, "Too large file"); - - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode SaveDataArchive::CreateDirectory(const Path& path) const { - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::PathNotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Unexpected file in path %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY; - case PathParser::DirectoryFound: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "%s already exists", full_path.c_str()); - return ERROR_DIRECTORY_ALREADY_EXISTS; - case PathParser::NotFound: - break; // Expected 'success' case - } - - if (FileUtil::CreateDir(mount_point + path.AsString())) { - return RESULT_SUCCESS; - } - - LOG_CRITICAL(Service_FS, "(unreachable) Unknown error creating %s", mount_point.c_str()); - - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode SaveDataArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { - const PathParser path_parser_src(src_path); - - // TODO: Verify these return codes with HW - if (!path_parser_src.IsValid()) { - LOG_ERROR(Service_FS, "Invalid src path %s", src_path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const PathParser path_parser_dest(dest_path); - - if (!path_parser_dest.IsValid()) { - LOG_ERROR(Service_FS, "Invalid dest path %s", dest_path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto src_path_full = path_parser_src.BuildHostPath(mount_point); - const auto dest_path_full = path_parser_dest.BuildHostPath(mount_point); - - if (FileUtil::Rename(src_path_full, dest_path_full)) { - return RESULT_SUCCESS; - } - - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultVal> SaveDataArchive::OpenDirectory( - const Path& path) const { - const PathParser path_parser(path); - - if (!path_parser.IsValid()) { - LOG_ERROR(Service_FS, "Invalid path %s", path.DebugStr().c_str()); - return ERROR_INVALID_PATH; - } - - const auto full_path = path_parser.BuildHostPath(mount_point); - - switch (path_parser.GetHostStatus(mount_point)) { - case PathParser::InvalidMountPoint: - LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point %s", mount_point.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::NotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_PATH_NOT_FOUND; - case PathParser::FileInPath: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "Unexpected file in path %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY; - case PathParser::DirectoryFound: - break; // Expected 'success' case - } - - auto directory = std::make_unique(full_path); - return MakeResult>(std::move(directory)); -} - -u64 SaveDataArchive::GetFreeSpaceSize() const { - // TODO: Stubbed to return 1GiB - return 1024 * 1024 * 1024; -} - -} // namespace FileSys diff --git a/src/core/file_sys/savedata_archive.h b/src/core/file_sys/savedata_archive.h deleted file mode 100644 index 931dfb17b..000000000 --- a/src/core/file_sys/savedata_archive.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include "core/file_sys/archive_backend.h" -#include "core/file_sys/directory_backend.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// Archive backend for general save data archive type (SaveData and SystemSaveData) -class SaveDataArchive : public ArchiveBackend { -public: - explicit SaveDataArchive(const std::string& mount_point_) : mount_point(mount_point_) {} - - std::string GetName() const override { - return "SaveDataArchive: " + mount_point; - } - - ResultVal> OpenFile(const Path& path, - const Mode& mode) const override; - ResultCode DeleteFile(const Path& path) const override; - ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; - ResultCode DeleteDirectory(const Path& path) const override; - ResultCode DeleteDirectoryRecursively(const Path& path) const override; - ResultCode CreateFile(const Path& path, u64 size) const override; - ResultCode CreateDirectory(const Path& path) const override; - ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; - ResultVal> OpenDirectory(const Path& path) const override; - u64 GetFreeSpaceSize() const override; - -protected: - std::string mount_point; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/title_metadata.cpp b/src/core/file_sys/title_metadata.cpp deleted file mode 100644 index e29ba6064..000000000 --- a/src/core/file_sys/title_metadata.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include "common/alignment.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "core/file_sys/title_metadata.h" -#include "core/loader/loader.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -static u32 GetSignatureSize(u32 signature_type) { - switch (signature_type) { - case Rsa4096Sha1: - case Rsa4096Sha256: - return 0x200; - - case Rsa2048Sha1: - case Rsa2048Sha256: - return 0x100; - - case EllipticSha1: - case EcdsaSha256: - return 0x3C; - } -} - -Loader::ResultStatus TitleMetadata::Load() { - FileUtil::IOFile file(filepath, "rb"); - if (!file.IsOpen()) - return Loader::ResultStatus::Error; - - if (!file.ReadBytes(&signature_type, sizeof(u32_be))) - return Loader::ResultStatus::Error; - - // Signature lengths are variable, and the body follows the signature - u32 signature_size = GetSignatureSize(signature_type); - - tmd_signature.resize(signature_size); - if (!file.ReadBytes(&tmd_signature[0], signature_size)) - return Loader::ResultStatus::Error; - - // The TMD body start position is rounded to the nearest 0x40 after the signature - size_t body_start = Common::AlignUp(signature_size + sizeof(u32), 0x40); - file.Seek(body_start, SEEK_SET); - - // Read our TMD body, then load the amount of ContentChunks specified - if (file.ReadBytes(&tmd_body, sizeof(TitleMetadata::Body)) != sizeof(TitleMetadata::Body)) - return Loader::ResultStatus::Error; - - for (u16 i = 0; i < tmd_body.content_count; i++) { - ContentChunk chunk; - if (file.ReadBytes(&chunk, sizeof(ContentChunk)) == sizeof(ContentChunk)) { - tmd_chunks.push_back(chunk); - } else { - LOG_ERROR(Service_FS, "Malformed TMD %s, failed to load content chunk index %u!", - filepath.c_str(), i); - return Loader::ResultStatus::ErrorInvalidFormat; - } - } - - return Loader::ResultStatus::Success; -} - -Loader::ResultStatus TitleMetadata::Save() { - UNIMPLEMENTED(); - return Loader::ResultStatus::Success; -} - -u64 TitleMetadata::GetTitleID() const { - return tmd_body.title_id; -} - -u32 TitleMetadata::GetTitleType() const { - return tmd_body.title_type; -} - -u16 TitleMetadata::GetTitleVersion() const { - return tmd_body.title_version; -} - -u64 TitleMetadata::GetSystemVersion() const { - return tmd_body.system_version; -} - -size_t TitleMetadata::GetContentCount() const { - return tmd_chunks.size(); -} - -u32 TitleMetadata::GetBootContentID() const { - return tmd_chunks[TMDContentIndex::Main].id; -} - -u32 TitleMetadata::GetManualContentID() const { - return tmd_chunks[TMDContentIndex::Manual].id; -} - -u32 TitleMetadata::GetDLPContentID() const { - return tmd_chunks[TMDContentIndex::DLP].id; -} - -void TitleMetadata::SetTitleID(u64 title_id) { - tmd_body.title_id = title_id; -} - -void TitleMetadata::SetTitleType(u32 type) { - tmd_body.title_type = type; -} - -void TitleMetadata::SetTitleVersion(u16 version) { - tmd_body.title_version = version; -} - -void TitleMetadata::SetSystemVersion(u64 version) { - tmd_body.system_version = version; -} - -void TitleMetadata::AddContentChunk(const ContentChunk& chunk) { - tmd_chunks.push_back(chunk); -} - -void TitleMetadata::Print() const { - LOG_DEBUG(Service_FS, "%s - %u chunks", filepath.c_str(), - static_cast(tmd_body.content_count)); - - // Content info describes ranges of content chunks - LOG_DEBUG(Service_FS, "Content info:"); - for (size_t i = 0; i < tmd_body.contentinfo.size(); i++) { - if (tmd_body.contentinfo[i].command_count == 0) - break; - - LOG_DEBUG(Service_FS, " Index %04X, Command Count %04X", - static_cast(tmd_body.contentinfo[i].index), - static_cast(tmd_body.contentinfo[i].command_count)); - } - - // For each content info, print their content chunk range - for (size_t i = 0; i < tmd_body.contentinfo.size(); i++) { - u16 index = static_cast(tmd_body.contentinfo[i].index); - u16 count = static_cast(tmd_body.contentinfo[i].command_count); - - if (count == 0) - continue; - - LOG_DEBUG(Service_FS, "Content chunks for content info index %zu:", i); - for (u16 j = index; j < index + count; j++) { - // Don't attempt to print content we don't have - if (j > tmd_body.content_count) - break; - - const ContentChunk& chunk = tmd_chunks[j]; - LOG_DEBUG(Service_FS, " ID %08X, Index %04X, Type %04x, Size %016" PRIX64, - static_cast(chunk.id), static_cast(chunk.index), - static_cast(chunk.type), static_cast(chunk.size)); - } - } -} -} // namespace FileSys diff --git a/src/core/file_sys/title_metadata.h b/src/core/file_sys/title_metadata.h deleted file mode 100644 index a4c7d1089..000000000 --- a/src/core/file_sys/title_metadata.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include "common/common_types.h" -#include "common/swap.h" - -namespace Loader { -enum class ResultStatus; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -enum TMDSignatureType : u32 { - Rsa4096Sha1 = 0x10000, - Rsa2048Sha1 = 0x10001, - EllipticSha1 = 0x10002, - Rsa4096Sha256 = 0x10003, - Rsa2048Sha256 = 0x10004, - EcdsaSha256 = 0x10005 -}; - -enum TMDContentTypeFlag : u16 { - Encrypted = 1 << 1, - Disc = 1 << 2, - CFM = 1 << 3, - Optional = 1 << 14, - Shared = 1 << 15 -}; - -/** - * Helper which implements an interface to read and write Title Metadata (TMD) files. - * If a file path is provided and the file exists, it can be parsed and used, otherwise - * it must be created. The TMD file can then be interpreted, modified and/or saved. - */ -class TitleMetadata { -public: - struct ContentChunk { - u32_be id; - u16_be index; - u16_be type; - u64_be size; - std::array hash; - }; - - static_assert(sizeof(ContentChunk) == 0x30, "TMD ContentChunk structure size is wrong"); - - struct ContentInfo { - u16_be index; - u16_be command_count; - std::array hash; - }; - - static_assert(sizeof(ContentInfo) == 0x24, "TMD ContentInfo structure size is wrong"); - -#pragma pack(push, 1) - - struct Body { - std::array issuer; - u8 version; - u8 ca_crl_version; - u8 signer_crl_version; - u8 reserved; - u64_be system_version; - u64_be title_id; - u32_be title_type; - u16_be group_id; - u32_be savedata_size; - u32_be srl_private_savedata_size; - std::array reserved_2; - u8 srl_flag; - std::array reserved_3; - u32_be access_rights; - u16_be title_version; - u16_be content_count; - u16_be boot_content; - std::array reserved_4; - std::array contentinfo_hash; - std::array contentinfo; - }; - - static_assert(sizeof(Body) == 0x9C4, "TMD body structure size is wrong"); - -#pragma pack(pop) - - explicit TitleMetadata(std::string& path) : filepath(std::move(path)) {} - Loader::ResultStatus Load(); - Loader::ResultStatus Save(); - - u64 GetTitleID() const; - u32 GetTitleType() const; - u16 GetTitleVersion() const; - u64 GetSystemVersion() const; - size_t GetContentCount() const; - u32 GetBootContentID() const; - u32 GetManualContentID() const; - u32 GetDLPContentID() const; - - void SetTitleID(u64 title_id); - void SetTitleType(u32 type); - void SetTitleVersion(u16 version); - void SetSystemVersion(u64 version); - void AddContentChunk(const ContentChunk& chunk); - - void Print() const; - -private: - enum TMDContentIndex { Main = 0, Manual = 1, DLP = 2 }; - - Body tmd_body; - u32_be signature_type; - std::vector tmd_signature; - std::vector tmd_chunks; - - std::string filepath; -}; - -} // namespace FileSys -- cgit v1.2.3 From 00851a5ef442947c4237f32e063c37e7751db3ed Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 19 Jan 2018 22:34:48 -0500 Subject: file_sys: Cleanup to better match Switch file system constructs. file_sys: Add factory class for RomFS file system. --- src/core/CMakeLists.txt | 14 +-- src/core/file_sys/archive_backend.cpp | 122 --------------------- src/core/file_sys/archive_backend.h | 190 --------------------------------- src/core/file_sys/directory.h | 58 ++++++++++ src/core/file_sys/directory_backend.h | 58 ---------- src/core/file_sys/file_backend.h | 66 ------------ src/core/file_sys/filesystem.cpp | 122 +++++++++++++++++++++ src/core/file_sys/filesystem.h | 190 +++++++++++++++++++++++++++++++++ src/core/file_sys/path_parser.h | 2 +- src/core/file_sys/romfs_archive.cpp | 105 ------------------ src/core/file_sys/romfs_archive.h | 80 -------------- src/core/file_sys/romfs_factory.cpp | 39 +++++++ src/core/file_sys/romfs_factory.h | 35 ++++++ src/core/file_sys/romfs_filesystem.cpp | 105 ++++++++++++++++++ src/core/file_sys/romfs_filesystem.h | 80 ++++++++++++++ src/core/file_sys/storage.h | 63 +++++++++++ 16 files changed, 701 insertions(+), 628 deletions(-) delete mode 100644 src/core/file_sys/archive_backend.cpp delete mode 100644 src/core/file_sys/archive_backend.h create mode 100644 src/core/file_sys/directory.h delete mode 100644 src/core/file_sys/directory_backend.h delete mode 100644 src/core/file_sys/file_backend.h create mode 100644 src/core/file_sys/filesystem.cpp create mode 100644 src/core/file_sys/filesystem.h delete mode 100644 src/core/file_sys/romfs_archive.cpp delete mode 100644 src/core/file_sys/romfs_archive.h create mode 100644 src/core/file_sys/romfs_factory.cpp create mode 100644 src/core/file_sys/romfs_factory.h create mode 100644 src/core/file_sys/romfs_filesystem.cpp create mode 100644 src/core/file_sys/romfs_filesystem.h create mode 100644 src/core/file_sys/storage.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b2dcc039a..5ff1311a2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -6,15 +6,17 @@ add_library(core STATIC core.h core_timing.cpp core_timing.h - file_sys/archive_backend.cpp - file_sys/archive_backend.h - file_sys/directory_backend.h + file_sys/directory.h file_sys/errors.h - file_sys/file_backend.h + file_sys/filesystem.cpp + file_sys/filesystem.h file_sys/path_parser.cpp file_sys/path_parser.h - file_sys/romfs_archive.cpp - file_sys/romfs_archive.h + file_sys/romfs_factory.cpp + file_sys/romfs_factory.h + file_sys/romfs_filesystem.cpp + file_sys/romfs_filesystem.h + file_sys/storage.h frontend/emu_window.cpp frontend/emu_window.h frontend/framebuffer_layout.cpp diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp deleted file mode 100644 index fc472b44f..000000000 --- a/src/core/file_sys/archive_backend.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/file_sys/archive_backend.h" -#include "core/memory.h" - -namespace FileSys { - -Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { - switch (type) { - case Binary: { - binary.resize(size); - Memory::ReadBlock(pointer, binary.data(), binary.size()); - break; - } - - case Char: { - string.resize(size - 1); // Data is always null-terminated. - Memory::ReadBlock(pointer, &string[0], string.size()); - break; - } - - case Wchar: { - u16str.resize(size / 2 - 1); // Data is always null-terminated. - Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); - break; - } - - default: - break; - } -} - -std::string Path::DebugStr() const { - switch (GetType()) { - case Invalid: - default: - return "[Invalid]"; - case Empty: - return "[Empty]"; - case Binary: { - std::stringstream res; - res << "[Binary: "; - for (unsigned byte : binary) - res << std::hex << std::setw(2) << std::setfill('0') << byte; - res << ']'; - return res.str(); - } - case Char: - return "[Char: " + AsString() + ']'; - case Wchar: - return "[Wchar: " + AsString() + ']'; - } -} - -std::string Path::AsString() const { - switch (GetType()) { - case Char: - return string; - case Wchar: - return Common::UTF16ToUTF8(u16str); - case Empty: - return {}; - case Invalid: - case Binary: - default: - // TODO(yuriks): Add assert - LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); - return {}; - } -} - -std::u16string Path::AsU16Str() const { - switch (GetType()) { - case Char: - return Common::UTF8ToUTF16(string); - case Wchar: - return u16str; - case Empty: - return {}; - case Invalid: - case Binary: - // TODO(yuriks): Add assert - LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); - return {}; - } - - UNREACHABLE(); -} - -std::vector Path::AsBinary() const { - switch (GetType()) { - case Binary: - return binary; - case Char: - return std::vector(string.begin(), string.end()); - case Wchar: { - // use two u8 for each character of u16str - std::vector to_return(u16str.size() * 2); - for (size_t i = 0; i < u16str.size(); ++i) { - u16 tmp_char = u16str.at(i); - to_return[i * 2] = (tmp_char & 0xFF00) >> 8; - to_return[i * 2 + 1] = (tmp_char & 0x00FF); - } - return to_return; - } - case Empty: - return {}; - case Invalid: - default: - // TODO(yuriks): Add assert - LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); - return {}; - } -} -} // namespace FileSys diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h deleted file mode 100644 index 2255bee42..000000000 --- a/src/core/file_sys/archive_backend.h +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include "common/bit_field.h" -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/result.h" - -namespace FileSys { - -class FileBackend; -class DirectoryBackend; - -// Path string type -enum LowPathType : u32 { - Invalid = 0, - Empty = 1, - Binary = 2, - Char = 3, - Wchar = 4, -}; - -union Mode { - u32 hex; - BitField<0, 1, u32> read_flag; - BitField<1, 1, u32> write_flag; - BitField<2, 1, u32> create_flag; -}; - -class Path { -public: - Path() : type(Invalid) {} - Path(const char* path) : type(Char), string(path) {} - Path(std::vector binary_data) : type(Binary), binary(std::move(binary_data)) {} - Path(LowPathType type, u32 size, u32 pointer); - - LowPathType GetType() const { - return type; - } - - /** - * Gets the string representation of the path for debugging - * @return String representation of the path for debugging - */ - std::string DebugStr() const; - - std::string AsString() const; - std::u16string AsU16Str() const; - std::vector AsBinary() const; - -private: - LowPathType type; - std::vector binary; - std::string string; - std::u16string u16str; -}; - -/// Parameters of the archive, as specified in the Create or Format call. -struct ArchiveFormatInfo { - u32_le total_size; ///< The pre-defined size of the archive. - u32_le number_directories; ///< The pre-defined number of directories in the archive. - u32_le number_files; ///< The pre-defined number of files in the archive. - u8 duplicate_data; ///< Whether the archive should duplicate the data. -}; -static_assert(std::is_pod::value, "ArchiveFormatInfo is not POD"); - -class ArchiveBackend : NonCopyable { -public: - virtual ~ArchiveBackend() {} - - /** - * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) - */ - virtual std::string GetName() const = 0; - - /** - * 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 - */ - virtual ResultCode CreateFile(const Path& path, u64 size) const = 0; - - /** - * Delete a file specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - virtual ResultCode DeleteFile(const Path& path) const = 0; - - /** - * Create a directory specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - virtual ResultCode CreateDirectory(const Path& path) const = 0; - - /** - * Delete a directory specified by its path - * @param path Path relative to the archive - * @return Result of the operation - */ - virtual ResultCode DeleteDirectory(const Path& path) const = 0; - - /** - * Delete a directory specified by its path and anything under it - * @param path Path relative to the archive - * @return Result of the operation - */ - virtual ResultCode DeleteDirectoryRecursively(const Path& path) const = 0; - - /** - * 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 - */ - virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; - - /** - * 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 - */ - virtual ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const = 0; - - /** - * 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 - */ - virtual ResultVal> OpenFile(const Path& path, - const Mode& mode) const = 0; - - /** - * Open a directory specified by its path - * @param path Path relative to the archive - * @return Opened directory, or error code - */ - virtual ResultVal> OpenDirectory(const Path& path) const = 0; - - /** - * Get the free space - * @return The number of free bytes in the archive - */ - virtual u64 GetFreeSpaceSize() const = 0; -}; - -class ArchiveFactory : NonCopyable { -public: - virtual ~ArchiveFactory() {} - - /** - * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) - */ - virtual std::string GetName() const = 0; - - /** - * Tries to open the archive of this type with the specified path - * @param path Path to the archive - * @return An ArchiveBackend corresponding operating specified archive path. - */ - virtual ResultVal> Open(const Path& path) = 0; - - /** - * Deletes the archive contents and then re-creates the base folder - * @param path Path to the archive - * @param format_info Format information for the new archive - * @return ResultCode of the operation, 0 on success - */ - virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0; - - /** - * Retrieves the format info about the archive with the specified path - * @param path Path to the archive - * @return Format information about the archive or error code - */ - virtual ResultVal GetFormatInfo(const Path& path) const = 0; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory.h new file mode 100644 index 000000000..5a40bf472 --- /dev/null +++ b/src/core/file_sys/directory.h @@ -0,0 +1,58 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include "common/common_types.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// FileSys namespace + +namespace FileSys { + +// Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format +const size_t FILENAME_LENGTH = 0x20C / 2; +struct Entry { + char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) + std::array short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) + char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) + std::array + extension; // 8.3 file extension (set to spaces for directories, null-terminated) + char unknown2; // unknown (always 0x01) + char unknown3; // unknown (0x00 or 0x08) + char is_directory; // directory flag + char is_hidden; // hidden flag + char is_archive; // archive flag + char is_read_only; // read-only flag + u64 file_size; // file size (for files only) +}; +static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); +static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); +static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); +static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); +static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); + +class DirectoryBackend : NonCopyable { +public: + DirectoryBackend() {} + virtual ~DirectoryBackend() {} + + /** + * List files contained in the directory + * @param count Number of entries to return at once in entries + * @param entries Buffer to read data into + * @return Number of entries listed + */ + virtual u32 Read(const u32 count, Entry* entries) = 0; + + /** + * Close the directory + * @return true if the directory closed correctly + */ + virtual bool Close() const = 0; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/directory_backend.h b/src/core/file_sys/directory_backend.h deleted file mode 100644 index 0c93f2074..000000000 --- a/src/core/file_sys/directory_backend.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include "common/common_types.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -// Structure of a directory entry, from http://3dbrew.org/wiki/FSDir:Read#Entry_format -const size_t FILENAME_LENGTH = 0x20C / 2; -struct Entry { - char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) - std::array short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) - char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) - std::array - extension; // 8.3 file extension (set to spaces for directories, null-terminated) - char unknown2; // unknown (always 0x01) - char unknown3; // unknown (0x00 or 0x08) - char is_directory; // directory flag - char is_hidden; // hidden flag - char is_archive; // archive flag - char is_read_only; // read-only flag - u64 file_size; // file size (for files only) -}; -static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); -static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); -static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension in Entry."); -static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); -static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); - -class DirectoryBackend : NonCopyable { -public: - DirectoryBackend() {} - virtual ~DirectoryBackend() {} - - /** - * List files contained in the directory - * @param count Number of entries to return at once in entries - * @param entries Buffer to read data into - * @return Number of entries listed - */ - virtual u32 Read(const u32 count, Entry* entries) = 0; - - /** - * Close the directory - * @return true if the directory closed correctly - */ - virtual bool Close() const = 0; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/file_backend.h b/src/core/file_sys/file_backend.h deleted file mode 100644 index 5e7c2bab4..000000000 --- a/src/core/file_sys/file_backend.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include "common/common_types.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -class FileBackend : NonCopyable { -public: - FileBackend() {} - virtual ~FileBackend() {} - - /** - * Read data from the file - * @param offset Offset in bytes to start reading data from - * @param length Length in bytes of data to read from file - * @param buffer Buffer to read data into - * @return Number of bytes read, or error code - */ - virtual ResultVal Read(u64 offset, size_t length, u8* buffer) const = 0; - - /** - * Write data to the file - * @param offset Offset in bytes to start writing data to - * @param length Length in bytes of data to write to file - * @param flush The flush parameters (0 == do not flush) - * @param buffer Buffer to read data from - * @return Number of bytes written, or error code - */ - virtual ResultVal Write(u64 offset, size_t length, bool flush, - const u8* buffer) const = 0; - - /** - * Get the size of the file in bytes - * @return Size of the file in bytes - */ - virtual u64 GetSize() const = 0; - - /** - * Set the size of the file in bytes - * @param size New size of the file - * @return true if successful - */ - virtual bool SetSize(u64 size) const = 0; - - /** - * Close the file - * @return true if the file closed correctly - */ - virtual bool Close() const = 0; - - /** - * Flushes the file - */ - virtual void Flush() const = 0; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/filesystem.cpp b/src/core/file_sys/filesystem.cpp new file mode 100644 index 000000000..82fdb3c46 --- /dev/null +++ b/src/core/file_sys/filesystem.cpp @@ -0,0 +1,122 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/file_sys/filesystem.h" +#include "core/memory.h" + +namespace FileSys { + +Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { + switch (type) { + case Binary: { + binary.resize(size); + Memory::ReadBlock(pointer, binary.data(), binary.size()); + break; + } + + case Char: { + string.resize(size - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &string[0], string.size()); + break; + } + + case Wchar: { + u16str.resize(size / 2 - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); + break; + } + + default: + break; + } +} + +std::string Path::DebugStr() const { + switch (GetType()) { + case Invalid: + default: + return "[Invalid]"; + case Empty: + return "[Empty]"; + case Binary: { + std::stringstream res; + res << "[Binary: "; + for (unsigned byte : binary) + res << std::hex << std::setw(2) << std::setfill('0') << byte; + res << ']'; + return res.str(); + } + case Char: + return "[Char: " + AsString() + ']'; + case Wchar: + return "[Wchar: " + AsString() + ']'; + } +} + +std::string Path::AsString() const { + switch (GetType()) { + case Char: + return string; + case Wchar: + return Common::UTF16ToUTF8(u16str); + case Empty: + return {}; + case Invalid: + case Binary: + default: + // TODO(yuriks): Add assert + LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); + return {}; + } +} + +std::u16string Path::AsU16Str() const { + switch (GetType()) { + case Char: + return Common::UTF8ToUTF16(string); + case Wchar: + return u16str; + case Empty: + return {}; + case Invalid: + case Binary: + // TODO(yuriks): Add assert + LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); + return {}; + } + + UNREACHABLE(); +} + +std::vector Path::AsBinary() const { + switch (GetType()) { + case Binary: + return binary; + case Char: + return std::vector(string.begin(), string.end()); + case Wchar: { + // use two u8 for each character of u16str + std::vector to_return(u16str.size() * 2); + for (size_t i = 0; i < u16str.size(); ++i) { + u16 tmp_char = u16str.at(i); + to_return[i * 2] = (tmp_char & 0xFF00) >> 8; + to_return[i * 2 + 1] = (tmp_char & 0x00FF); + } + return to_return; + } + case Empty: + return {}; + case Invalid: + default: + // TODO(yuriks): Add assert + LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); + return {}; + } +} +} // namespace FileSys diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h new file mode 100644 index 000000000..eb3d9c4d6 --- /dev/null +++ b/src/core/file_sys/filesystem.h @@ -0,0 +1,190 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include "common/bit_field.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/result.h" + +namespace FileSys { + +class StorageBackend; +class DirectoryBackend; + +// Path string type +enum LowPathType : u32 { + Invalid = 0, + Empty = 1, + Binary = 2, + Char = 3, + Wchar = 4, +}; + +union Mode { + u32 hex; + BitField<0, 1, u32> read_flag; + BitField<1, 1, u32> write_flag; + BitField<2, 1, u32> create_flag; +}; + +class Path { +public: + Path() : type(Invalid) {} + Path(const char* path) : type(Char), string(path) {} + Path(std::vector binary_data) : type(Binary), binary(std::move(binary_data)) {} + Path(LowPathType type, u32 size, u32 pointer); + + LowPathType GetType() const { + return type; + } + + /** + * Gets the string representation of the path for debugging + * @return String representation of the path for debugging + */ + std::string DebugStr() const; + + std::string AsString() const; + std::u16string AsU16Str() const; + std::vector AsBinary() const; + +private: + LowPathType type; + std::vector binary; + std::string string; + std::u16string u16str; +}; + +/// Parameters of the archive, as specified in the Create or Format call. +struct ArchiveFormatInfo { + u32_le total_size; ///< The pre-defined size of the archive. + u32_le number_directories; ///< The pre-defined number of directories in the archive. + u32_le number_files; ///< The pre-defined number of files in the archive. + u8 duplicate_data; ///< Whether the archive should duplicate the data. +}; +static_assert(std::is_pod::value, "ArchiveFormatInfo is not POD"); + +class FileSystemBackend : NonCopyable { +public: + virtual ~FileSystemBackend() {} + + /** + * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) + */ + virtual std::string GetName() const = 0; + + /** + * 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 + */ + virtual ResultCode CreateFile(const Path& path, u64 size) const = 0; + + /** + * Delete a file specified by its path + * @param path Path relative to the archive + * @return Result of the operation + */ + virtual ResultCode DeleteFile(const Path& path) const = 0; + + /** + * Create a directory specified by its path + * @param path Path relative to the archive + * @return Result of the operation + */ + virtual ResultCode CreateDirectory(const Path& path) const = 0; + + /** + * Delete a directory specified by its path + * @param path Path relative to the archive + * @return Result of the operation + */ + virtual ResultCode DeleteDirectory(const Path& path) const = 0; + + /** + * Delete a directory specified by its path and anything under it + * @param path Path relative to the archive + * @return Result of the operation + */ + virtual ResultCode DeleteDirectoryRecursively(const Path& path) const = 0; + + /** + * 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 + */ + virtual ResultCode RenameFile(const Path& src_path, const Path& dest_path) const = 0; + + /** + * 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 + */ + virtual ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const = 0; + + /** + * 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 + */ + virtual ResultVal> OpenFile(const Path& path, + const Mode& mode) const = 0; + + /** + * Open a directory specified by its path + * @param path Path relative to the archive + * @return Opened directory, or error code + */ + virtual ResultVal> OpenDirectory(const Path& path) const = 0; + + /** + * Get the free space + * @return The number of free bytes in the archive + */ + virtual u64 GetFreeSpaceSize() const = 0; +}; + +class FileSystemFactory : NonCopyable { +public: + virtual ~FileSystemFactory() {} + + /** + * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) + */ + virtual std::string GetName() const = 0; + + /** + * Tries to open the archive of this type with the specified path + * @param path Path to the archive + * @return An ArchiveBackend corresponding operating specified archive path. + */ + virtual ResultVal> Open(const Path& path) = 0; + + /** + * Deletes the archive contents and then re-creates the base folder + * @param path Path to the archive + * @param format_info Format information for the new archive + * @return ResultCode of the operation, 0 on success + */ + virtual ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) = 0; + + /** + * Retrieves the format info about the archive with the specified path + * @param path Path to the archive + * @return Format information about the archive or error code + */ + virtual ResultVal GetFormatInfo(const Path& path) const = 0; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/path_parser.h b/src/core/file_sys/path_parser.h index b9f52f65d..184f59d55 100644 --- a/src/core/file_sys/path_parser.h +++ b/src/core/file_sys/path_parser.h @@ -6,7 +6,7 @@ #include #include -#include "core/file_sys/archive_backend.h" +#include "core/file_sys/filesystem.h" namespace FileSys { diff --git a/src/core/file_sys/romfs_archive.cpp b/src/core/file_sys/romfs_archive.cpp deleted file mode 100644 index 0d93fccd4..000000000 --- a/src/core/file_sys/romfs_archive.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include "common/common_types.h" -#include "common/logging/log.h" -#include "core/file_sys/romfs_archive.h" - -namespace FileSys { - -std::string ROMFSArchive::GetName() const { - return "RomFS"; -} - -ResultVal> ROMFSArchive::OpenFile(const Path& path, - const Mode& mode) const { - return MakeResult>( - std::make_unique(romfs_file, data_offset, data_size)); -} - -ResultCode ROMFSArchive::DeleteFile(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", - GetName().c_str()); - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::RenameFile(const Path& src_path, const Path& dest_path) const { - LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::DeleteDirectory(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::DeleteDirectoryRecursively(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::CreateFile(const Path& path, u64 size) const { - LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", - GetName().c_str()); - // TODO(bunnei): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::CreateDirectory(const Path& path) const { - LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultCode ROMFSArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { - LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", - GetName().c_str()); - // TODO(wwylele): Use correct error code - return ResultCode(-1); -} - -ResultVal> ROMFSArchive::OpenDirectory(const Path& path) const { - return MakeResult>(std::make_unique()); -} - -u64 ROMFSArchive::GetFreeSpaceSize() const { - LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); - return 0; -} - -ResultVal ROMFSFile::Read(const u64 offset, const size_t length, u8* buffer) const { - LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); - romfs_file->Seek(data_offset + offset, SEEK_SET); - size_t read_length = (size_t)std::min((u64)length, data_size - offset); - - return MakeResult(romfs_file->ReadBytes(buffer, read_length)); -} - -ResultVal ROMFSFile::Write(const u64 offset, const size_t length, const bool flush, - const u8* buffer) const { - LOG_ERROR(Service_FS, "Attempted to write to ROMFS file"); - // TODO(Subv): Find error code - return MakeResult(0); -} - -u64 ROMFSFile::GetSize() const { - return data_size; -} - -bool ROMFSFile::SetSize(const u64 size) const { - LOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file"); - return false; -} - -} // namespace FileSys diff --git a/src/core/file_sys/romfs_archive.h b/src/core/file_sys/romfs_archive.h deleted file mode 100644 index 2b6c573ba..000000000 --- a/src/core/file_sys/romfs_archive.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include "common/common_types.h" -#include "common/file_util.h" -#include "core/file_sys/archive_backend.h" -#include "core/file_sys/directory_backend.h" -#include "core/file_sys/file_backend.h" -#include "core/hle/result.h" - -namespace FileSys { - -/** - * Helper which implements an interface to deal with Switch .istorage ROMFS images used in some - * archives This should be subclassed by concrete archive types, which will provide the input data - * (load the raw ROMFS archive) and override any required methods - */ -class ROMFSArchive : public ArchiveBackend { -public: - ROMFSArchive(std::shared_ptr file, u64 offset, u64 size) - : romfs_file(file), data_offset(offset), data_size(size) {} - - std::string GetName() const override; - - ResultVal> OpenFile(const Path& path, - const Mode& mode) const override; - ResultCode DeleteFile(const Path& path) const override; - ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; - ResultCode DeleteDirectory(const Path& path) const override; - ResultCode DeleteDirectoryRecursively(const Path& path) const override; - ResultCode CreateFile(const Path& path, u64 size) const override; - ResultCode CreateDirectory(const Path& path) const override; - ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; - ResultVal> OpenDirectory(const Path& path) const override; - u64 GetFreeSpaceSize() const override; - -protected: - std::shared_ptr romfs_file; - u64 data_offset; - u64 data_size; -}; - -class ROMFSFile : public FileBackend { -public: - ROMFSFile(std::shared_ptr file, u64 offset, u64 size) - : romfs_file(file), data_offset(offset), data_size(size) {} - - ResultVal Read(u64 offset, size_t length, u8* buffer) const override; - ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; - u64 GetSize() const override; - bool SetSize(u64 size) const override; - bool Close() const override { - return false; - } - void Flush() const override {} - -private: - std::shared_ptr romfs_file; - u64 data_offset; - u64 data_size; -}; - -class ROMFSDirectory : public DirectoryBackend { -public: - u32 Read(const u32 count, Entry* entries) override { - return 0; - } - bool Close() const override { - return false; - } -}; - -} // namespace FileSys diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp new file mode 100644 index 000000000..590c2acb3 --- /dev/null +++ b/src/core/file_sys/romfs_factory.cpp @@ -0,0 +1,39 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include "common/common_types.h" +#include "common/logging/log.h" +#include "core/file_sys/romfs_factory.h" +#include "core/file_sys/romfs_filesystem.h" + +namespace FileSys { + +RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) { + // Load the RomFS from the app + if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) { + LOG_ERROR(Service_FS, "Unable to read RomFS!"); + } +} + +ResultVal> RomFS_Factory::Open(const Path& path) { + auto archive = std::make_unique(romfs_file, data_offset, data_size); + return MakeResult>(std::move(archive)); +} + +ResultCode RomFS_Factory::Format(const Path& path, + const FileSys::ArchiveFormatInfo& format_info) { + LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); + // TODO(bunnei): Find the right error code for this + return ResultCode(-1); +} + +ResultVal RomFS_Factory::GetFormatInfo(const Path& path) const { + LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); + // TODO(bunnei): Find the right error code for this + return ResultCode(-1); +} + +} // namespace FileSys diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h new file mode 100644 index 000000000..10ea13966 --- /dev/null +++ b/src/core/file_sys/romfs_factory.h @@ -0,0 +1,35 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include "common/common_types.h" +#include "core/file_sys/filesystem.h" +#include "core/hle/result.h" +#include "core/loader/loader.h" + +namespace FileSys { + +/// File system interface to the RomFS archive +class RomFS_Factory final : public FileSystemFactory { +public: + explicit RomFS_Factory(Loader::AppLoader& app_loader); + + std::string GetName() const override { + return "ArchiveFactory_RomFS"; + } + ResultVal> Open(const Path& path) override; + ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; + ResultVal GetFormatInfo(const Path& path) const override; + +private: + std::shared_ptr romfs_file; + u64 data_offset; + u64 data_size; +}; + +} // namespace FileSys diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp new file mode 100644 index 000000000..5b5c5a73e --- /dev/null +++ b/src/core/file_sys/romfs_filesystem.cpp @@ -0,0 +1,105 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include "common/common_types.h" +#include "common/logging/log.h" +#include "core/file_sys/romfs_filesystem.h" + +namespace FileSys { + +std::string RomFS_FileSystem::GetName() const { + return "RomFS"; +} + +ResultVal> RomFS_FileSystem::OpenFile(const Path& path, + const Mode& mode) const { + return MakeResult>( + std::make_unique(romfs_file, data_offset, data_size)); +} + +ResultCode RomFS_FileSystem::DeleteFile(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(bunnei): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { + LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::DeleteDirectory(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::DeleteDirectoryRecursively(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::CreateFile(const Path& path, u64 size) const { + LOG_CRITICAL(Service_FS, "Attempted to create a file in an ROMFS archive (%s).", + GetName().c_str()); + // TODO(bunnei): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::CreateDirectory(const Path& path) const { + LOG_CRITICAL(Service_FS, "Attempted to create a directory in an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& dest_path) const { + LOG_CRITICAL(Service_FS, "Attempted to rename a file within an ROMFS archive (%s).", + GetName().c_str()); + // TODO(wwylele): Use correct error code + return ResultCode(-1); +} + +ResultVal> RomFS_FileSystem::OpenDirectory(const Path& path) const { + return MakeResult>(std::make_unique()); +} + +u64 RomFS_FileSystem::GetFreeSpaceSize() const { + LOG_WARNING(Service_FS, "Attempted to get the free space in an ROMFS archive"); + return 0; +} + +ResultVal RomFS_Storage::Read(const u64 offset, const size_t length, u8* buffer) const { + LOG_TRACE(Service_FS, "called offset=%llu, length=%zu", offset, length); + romfs_file->Seek(data_offset + offset, SEEK_SET); + size_t read_length = (size_t)std::min((u64)length, data_size - offset); + + return MakeResult(romfs_file->ReadBytes(buffer, read_length)); +} + +ResultVal RomFS_Storage::Write(const u64 offset, const size_t length, const bool flush, + const u8* buffer) const { + LOG_ERROR(Service_FS, "Attempted to write to ROMFS file"); + // TODO(Subv): Find error code + return MakeResult(0); +} + +u64 RomFS_Storage::GetSize() const { + return data_size; +} + +bool RomFS_Storage::SetSize(const u64 size) const { + LOG_ERROR(Service_FS, "Attempted to set the size of an ROMFS file"); + return false; +} + +} // namespace FileSys diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h new file mode 100644 index 000000000..900ea567a --- /dev/null +++ b/src/core/file_sys/romfs_filesystem.h @@ -0,0 +1,80 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include "common/common_types.h" +#include "common/file_util.h" +#include "core/file_sys/directory.h" +#include "core/file_sys/filesystem.h" +#include "core/file_sys/storage.h" +#include "core/hle/result.h" + +namespace FileSys { + +/** + * Helper which implements an interface to deal with Switch .istorage ROMFS images used in some + * archives This should be subclassed by concrete archive types, which will provide the input data + * (load the raw ROMFS archive) and override any required methods + */ +class RomFS_FileSystem : public FileSystemBackend { +public: + RomFS_FileSystem(std::shared_ptr file, u64 offset, u64 size) + : romfs_file(file), data_offset(offset), data_size(size) {} + + std::string GetName() const override; + + ResultVal> OpenFile(const Path& path, + const Mode& mode) const override; + ResultCode DeleteFile(const Path& path) const override; + ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; + ResultCode DeleteDirectory(const Path& path) const override; + ResultCode DeleteDirectoryRecursively(const Path& path) const override; + ResultCode CreateFile(const Path& path, u64 size) const override; + ResultCode CreateDirectory(const Path& path) const override; + ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override; + ResultVal> OpenDirectory(const Path& path) const override; + u64 GetFreeSpaceSize() const override; + +protected: + std::shared_ptr romfs_file; + u64 data_offset; + u64 data_size; +}; + +class RomFS_Storage : public StorageBackend { +public: + RomFS_Storage(std::shared_ptr file, u64 offset, u64 size) + : romfs_file(file), data_offset(offset), data_size(size) {} + + ResultVal Read(u64 offset, size_t length, u8* buffer) const override; + ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; + u64 GetSize() const override; + bool SetSize(u64 size) const override; + bool Close() const override { + return false; + } + void Flush() const override {} + +private: + std::shared_ptr romfs_file; + u64 data_offset; + u64 data_size; +}; + +class ROMFSDirectory : public DirectoryBackend { +public: + u32 Read(const u32 count, Entry* entries) override { + return 0; + } + bool Close() const override { + return false; + } +}; + +} // namespace FileSys diff --git a/src/core/file_sys/storage.h b/src/core/file_sys/storage.h new file mode 100644 index 000000000..2a6811831 --- /dev/null +++ b/src/core/file_sys/storage.h @@ -0,0 +1,63 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/hle/result.h" + +namespace FileSys { + +class StorageBackend : NonCopyable { +public: + StorageBackend() {} + virtual ~StorageBackend() {} + + /** + * Read data from the file + * @param offset Offset in bytes to start reading data from + * @param length Length in bytes of data to read from file + * @param buffer Buffer to read data into + * @return Number of bytes read, or error code + */ + virtual ResultVal Read(u64 offset, size_t length, u8* buffer) const = 0; + + /** + * Write data to the file + * @param offset Offset in bytes to start writing data to + * @param length Length in bytes of data to write to file + * @param flush The flush parameters (0 == do not flush) + * @param buffer Buffer to read data from + * @return Number of bytes written, or error code + */ + virtual ResultVal Write(u64 offset, size_t length, bool flush, + const u8* buffer) const = 0; + + /** + * Flushes the file + */ + virtual void Flush() const = 0; + + /** + * Set the size of the file in bytes + * @param size New size of the file + * @return true if successful + */ + virtual bool SetSize(u64 size) const = 0; + + /** + * Get the size of the file in bytes + * @return Size of the file in bytes + */ + virtual u64 GetSize() const = 0; + + /** + * Close the file + * @return true if the file closed correctly + */ + virtual bool Close() const = 0; +}; + +} // namespace FileSys -- cgit v1.2.3 From d64b7d7dfda8123cc8e0d6abaf358a4a08ba795c Mon Sep 17 00:00:00 2001 From: David Marcec Date: Tue, 16 Jan 2018 19:20:12 -0800 Subject: filesystem: Implement basic IStorage functionality. --- src/core/CMakeLists.txt | 4 + src/core/hle/service/filesystem/filesystem.cpp | 54 ++++++++++ src/core/hle/service/filesystem/filesystem.h | 41 ++++++++ src/core/hle/service/filesystem/fsp_srv.cpp | 132 +++++++++++++++++++++++++ src/core/hle/service/filesystem/fsp_srv.h | 25 +++++ src/core/hle/service/service.cpp | 2 + 6 files changed, 258 insertions(+) create mode 100644 src/core/hle/service/filesystem/filesystem.cpp create mode 100644 src/core/hle/service/filesystem/filesystem.h create mode 100644 src/core/hle/service/filesystem/fsp_srv.cpp create mode 100644 src/core/hle/service/filesystem/fsp_srv.h (limited to 'src') diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5ff1311a2..433e7e596 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -97,6 +97,10 @@ add_library(core STATIC hle/service/audio/audio.h hle/service/audio/audout_u.cpp hle/service/audio/audout_u.h + hle/service/filesystem/filesystem.cpp + hle/service/filesystem/filesystem.h + hle/service/filesystem/fsp_srv.cpp + hle/service/filesystem/fsp_srv.h hle/service/hid/hid.cpp hle/service/hid/hid.h hle/service/lm/lm.cpp diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp new file mode 100644 index 000000000..4b47548fd --- /dev/null +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -0,0 +1,54 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/file_sys/filesystem.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/fsp_srv.h" + +namespace Service { +namespace FileSystem { + +/** + * 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> filesystem_map; + +ResultCode RegisterFileSystem(std::unique_ptr&& 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 %s with id code 0x%08X", + filesystem->GetName().c_str(), static_cast(type)); + return RESULT_SUCCESS; +} + +ResultVal> OpenFileSystem(Type type, + FileSys::Path& path) { + LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type); + + auto itr = filesystem_map.find(type); + if (itr == filesystem_map.end()) { + // TODO(bunnei): Find a better error code for this + return ResultCode(-1); + } + + return itr->second->Open(path); +} + +void UnregisterFileSystems() { + filesystem_map.clear(); +} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + UnregisterFileSystems(); + std::make_shared()->InstallAsService(service_manager); +} + +} // namespace FileSystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h new file mode 100644 index 000000000..52db83e62 --- /dev/null +++ b/src/core/hle/service/filesystem/filesystem.h @@ -0,0 +1,41 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/file_sys/filesystem.h" +#include "core/hle/result.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace FileSystem { + +/// Supported FileSystem types +enum class Type { + RomFS = 1, +}; + +/** + * 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&& factory, Type type); + +/** + * Opens a file system + * @param type Type of the file system to open + * @param path Path to the file system, used with Binary paths + * @return FileSys::FileSystemBackend interface to the file system + */ +ResultVal> OpenFileSystem(Type type, + FileSys::Path& path); + +/// Registers all Filesystem services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp new file mode 100644 index 000000000..47a97f0fd --- /dev/null +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -0,0 +1,132 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/file_sys/filesystem.h" +#include "core/file_sys/storage.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/client_session.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/fsp_srv.h" + +namespace Service { +namespace FileSystem { + +class IStorage final : public ServiceFramework { +public: + IStorage(std::unique_ptr&& backend) + : ServiceFramework("IStorage"), backend(std::move(backend)) { + static const FunctionInfo functions[] = { + {0, &IStorage::Read, "Read"}, {1, &IStorage::Write, "Write"}, + {2, &IStorage::Flush, "Flush"}, {3, &IStorage::SetSize, "SetSize"}, + {4, &IStorage::GetSize, "GetSize"}, + }; + RegisterHandlers(functions); + } + +private: + std::unique_ptr backend; + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u64 offset = rp.Pop(); + u64 length = rp.Pop(); + + LOG_DEBUG(Service, "called, offset=0x%llx, length=0x%llx", offset, length); + + auto descriptor = ctx.BufferDescriptorB()[0]; + std::vector output(length); + + ResultVal res = backend->Read(offset, length, output.data()); + if (res.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size()); + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Write(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void Flush(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void SetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void GetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } +}; + +FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { + static const FunctionInfo functions[] = { + {1, &FSP_SRV::Initalize, "Initalize"}, + {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, + {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, + {1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"}, + }; + RegisterHandlers(functions); +} + +void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(5); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { + FileSys::Path path; + auto filesystem = OpenFileSystem(Type::RomFS, path); + if (filesystem.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(filesystem.Code()); + return; + } + + auto storage = filesystem.Unwrap()->OpenFile({}, {}); + if (storage.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(storage.Code()); + return; + } + + // TODO: What if already opened? + + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::move(storage.Unwrap())); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { + OpenDataStorageByCurrentProcess(ctx); +} + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h new file mode 100644 index 000000000..b41ba6bd1 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -0,0 +1,25 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace FileSystem { + +class FSP_SRV final : public ServiceFramework { +public: + FSP_SRV(); + ~FSP_SRV() = default; + +private: + void Initalize(Kernel::HLERequestContext& ctx); + void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); + void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); + void OpenRomStorage(Kernel::HLERequestContext& ctx); +}; + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 19213a2f4..3f5ce56c6 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -19,6 +19,7 @@ #include "core/hle/service/aoc/aoc_u.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/audio/audio.h" +#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/lm/lm.h" #include "core/hle/service/nvdrv/nvdrv.h" @@ -172,6 +173,7 @@ void Init() { AOC::InstallInterfaces(*SM::g_service_manager); APM::InstallInterfaces(*SM::g_service_manager); Audio::InstallInterfaces(*SM::g_service_manager); + FileSystem::InstallInterfaces(*SM::g_service_manager); HID::InstallInterfaces(*SM::g_service_manager); LM::InstallInterfaces(*SM::g_service_manager); Nvidia::InstallInterfaces(*SM::g_service_manager); -- cgit v1.2.3 From d9a91d76785da6d0fa32ce32417e12023c8f394e Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 20 Jan 2018 18:20:46 -0500 Subject: deconstructed_rom_directory: Implement istorage loading for RomFS. --- src/core/loader/deconstructed_rom_directory.cpp | 69 ++++++++++++++++++++++++- src/core/loader/deconstructed_rom_directory.h | 4 ++ 2 files changed, 71 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 4bee5fb86..37030683b 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -7,14 +7,44 @@ #include "common/file_util.h" #include "common/logging/log.h" #include "common/string_util.h" +#include "core/file_sys/romfs_factory.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" +#include "core/hle/service/filesystem/filesystem.h" #include "core/loader/deconstructed_rom_directory.h" #include "core/loader/nso.h" #include "core/memory.h" namespace Loader { +static std::string FindRomFS(const std::string& directory) { + std::string filepath_romfs; + const auto callback = [&filepath_romfs](unsigned*, const std::string& directory, + const std::string& virtual_name) -> bool { + const std::string physical_name = directory + virtual_name; + if (FileUtil::IsDirectory(physical_name)) { + // Skip directories + return true; + } + + // Verify extension + const std::string extension = physical_name.substr(physical_name.find_last_of(".") + 1); + if (Common::ToLower(extension) != "istorage") { + return true; + } + + // Found it - we are done + filepath_romfs = std::move(physical_name); + return false; + }; + + // Search the specified directory recursively, looking for the first .istorage file, which will + // be used for the RomFS + FileUtil::ForeachDirectoryEntry(nullptr, directory, callback); + + return filepath_romfs; +} + AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileUtil::IOFile&& file, std::string filepath) : AppLoader(std::move(file)), filepath(std::move(filepath)) {} @@ -79,10 +109,10 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( // Load NSO modules VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; + const std::string directory = filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP; for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { - const std::string path = - filepath.substr(0, filepath.find_last_of("/\\")) + DIR_SEP + module; + const std::string path = directory + DIR_SEP + module; const VAddr load_addr = next_load_addr; next_load_addr = AppLoader_NSO::LoadModule(path, load_addr); if (next_load_addr) { @@ -98,8 +128,43 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); + // Find the RomFS by searching for a ".istorage" file in this directory + filepath_romfs = FindRomFS(directory); + + // Register the RomFS if a ".istorage" file was found + if (!filepath_romfs.empty()) { + Service::FileSystem::RegisterFileSystem(std::make_unique(*this), + Service::FileSystem::Type::RomFS); + } + is_loaded = true; return ResultStatus::Success; } +ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS( + std::shared_ptr& romfs_file, u64& offset, u64& size) { + + if (filepath_romfs.empty()) { + LOG_DEBUG(Loader, "No RomFS available"); + return ResultStatus::ErrorNotUsed; + } + + // We reopen the file, to allow its position to be independent + romfs_file = std::make_shared(filepath_romfs, "rb"); + if (!romfs_file->IsOpen()) { + return ResultStatus::Error; + } + + offset = 0; + size = romfs_file->GetSize(); + + LOG_DEBUG(Loader, "RomFS offset: 0x%08X", offset); + LOG_DEBUG(Loader, "RomFS size: 0x%08X", size); + + // Reset read pointer + file.Seek(0, SEEK_SET); + + return ResultStatus::Success; +} + } // namespace Loader diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index 162541d54..26493de5e 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h @@ -35,7 +35,11 @@ public: ResultStatus Load(Kernel::SharedPtr& process) override; + ResultStatus ReadRomFS(std::shared_ptr& romfs_file, u64& offset, + u64& size) override; + private: + std::string filepath_romfs; std::string filepath; }; -- cgit v1.2.3 From 8e50d6002bd12dde7e4ba4fd3da1b53864c4058c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 20 Jan 2018 21:32:36 -0500 Subject: fsp_srv: Various improvements to IStorage:Read implementation. --- src/core/hle/ipc_helpers.h | 5 ++ src/core/hle/result.h | 2 + src/core/hle/service/filesystem/filesystem.h | 15 ++++- src/core/hle/service/filesystem/fsp_srv.cpp | 92 +++++++++++++++------------- src/core/hle/service/filesystem/fsp_srv.h | 13 +++- 5 files changed, 79 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 4c9b0de28..a27cfbc2d 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -304,6 +304,11 @@ inline u64 RequestParser::Pop() { return msw << 32 | lsw; } +template <> +inline s64 RequestParser::Pop() { + return static_cast(Pop()); +} + template <> inline bool RequestParser::Pop() { return Pop() != 0; diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 10ddc4feb..656e1b4a7 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -19,6 +19,8 @@ enum class ErrorDescription : u32 { Success = 0, RemoteProcessDead = 301, + InvalidOffset = 6061, + InvalidLength = 6062, }; /** diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 52db83e62..a674c9493 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -6,11 +6,20 @@ #include #include "common/common_types.h" -#include "core/file_sys/filesystem.h" #include "core/hle/result.h" -#include "core/hle/service/service.h" + +namespace FileSys { +class FileSystemBackend; +class FileSystemFactory; +class Path; +} // namespace FileSys namespace Service { + +namespace SM { +class ServiceManager; +} // namespace SM + namespace FileSystem { /// Supported FileSystem types @@ -37,5 +46,5 @@ ResultVal> OpenFileSystem(Type type, /// Registers all Filesystem services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); -} // namespace Filesystem +} // namespace FileSystem } // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 47a97f0fd..ef1915e5a 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -20,9 +20,8 @@ public: IStorage(std::unique_ptr&& backend) : ServiceFramework("IStorage"), backend(std::move(backend)) { static const FunctionInfo functions[] = { - {0, &IStorage::Read, "Read"}, {1, &IStorage::Write, "Write"}, - {2, &IStorage::Flush, "Flush"}, {3, &IStorage::SetSize, "SetSize"}, - {4, &IStorage::GetSize, "GetSize"}, + {0, &IStorage::Read, "Read"}, {1, nullptr, "Write"}, {2, nullptr, "Flush"}, + {3, nullptr, "SetSize"}, {4, nullptr, "GetSize"}, }; RegisterHandlers(functions); } @@ -32,49 +31,40 @@ private: void Read(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - u64 offset = rp.Pop(); - u64 length = rp.Pop(); + const s64 offset = rp.Pop(); + const s64 length = rp.Pop(); + const auto& descriptor = ctx.BufferDescriptorB()[0]; - LOG_DEBUG(Service, "called, offset=0x%llx, length=0x%llx", offset, length); + LOG_DEBUG(Service_FS, "called, offset=0x%llx, length=0x%llx", offset, length); - auto descriptor = ctx.BufferDescriptorB()[0]; - std::vector output(length); + // Error checking + ASSERT_MSG(length == descriptor.Size(), "unexpected size difference"); + if (length < 0) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidLength)); + return; + } + if (offset < 0) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, ErrorDescription::InvalidOffset)); + return; + } + // Read the data from the Storage backend + std::vector output(length); ResultVal res = backend->Read(offset, length, output.data()); if (res.Failed()) { IPC::RequestBuilder rb{ctx, 2}; rb.Push(res.Code()); + return; } + // Write the data to memory Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size()); IPC::RequestBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } - - void Write(Kernel::HLERequestContext& ctx) { - IPC::RequestBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); - } - - void Flush(Kernel::HLERequestContext& ctx) { - IPC::RequestBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); - } - - void SetSize(Kernel::HLERequestContext& ctx) { - IPC::RequestBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); - } - - void GetSize(Kernel::HLERequestContext& ctx) { - IPC::RequestBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); - } }; FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { @@ -87,46 +77,62 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { RegisterHandlers(functions); } +void FSP_SRV::TryLoadRomFS() { + if (romfs) { + return; + } + FileSys::Path unused; + auto res = OpenFileSystem(Type::RomFS, unused); + if (res.Succeeded()) { + romfs = std::move(res.Unwrap()); + } +} + void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + IPC::RequestBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service, "(STUBBED) called"); } void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + IPC::RequestBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push(5); - LOG_WARNING(Service, "(STUBBED) called"); } void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { - FileSys::Path path; - auto filesystem = OpenFileSystem(Type::RomFS, path); - if (filesystem.Failed()) { + LOG_DEBUG(Service_FS, "called"); + + TryLoadRomFS(); + if (!romfs) { + // TODO (bunnei): Find the right error code to use here + LOG_CRITICAL(Service_FS, "no file system interface available!"); IPC::RequestBuilder rb{ctx, 2}; - rb.Push(filesystem.Code()); + rb.Push(ResultCode(-1)); return; } - auto storage = filesystem.Unwrap()->OpenFile({}, {}); + // 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::RequestBuilder rb{ctx, 2}; rb.Push(storage.Code()); return; } - // TODO: What if already opened? - IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(std::move(storage.Unwrap())); - LOG_WARNING(Service, "(STUBBED) called"); } void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess"); OpenDataStorageByCurrentProcess(ctx); } -} // namespace Filesystem +} // namespace FileSystem } // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index b41ba6bd1..15be8edc1 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -4,22 +4,31 @@ #pragma once +#include #include "core/hle/service/service.h" +namespace FileSys { +class FileSystemBackend; +} + namespace Service { namespace FileSystem { class FSP_SRV final : public ServiceFramework { public: - FSP_SRV(); + explicit FSP_SRV(); ~FSP_SRV() = default; private: + void TryLoadRomFS(); + void Initalize(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OpenRomStorage(Kernel::HLERequestContext& ctx); + + std::unique_ptr romfs; }; -} // namespace Filesystem +} // namespace FileSystem } // namespace Service -- cgit v1.2.3 From 5035d18baaad5cee4cbc671710de472b9f25a920 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 20 Jan 2018 23:01:00 -0500 Subject: file_sys: Clang format fixes. --- src/core/file_sys/filesystem.h | 2 +- src/core/file_sys/romfs_factory.cpp | 3 +-- src/core/file_sys/romfs_filesystem.cpp | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index eb3d9c4d6..02705506b 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h @@ -139,7 +139,7 @@ public: * @return Opened file, or error code */ virtual ResultVal> OpenFile(const Path& path, - const Mode& mode) const = 0; + const Mode& mode) const = 0; /** * Open a directory specified by its path diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index 590c2acb3..e0de49f05 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp @@ -23,8 +23,7 @@ ResultVal> RomFS_Factory::Open(const Path& pa return MakeResult>(std::move(archive)); } -ResultCode RomFS_Factory::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { +ResultCode RomFS_Factory::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { LOG_ERROR(Service_FS, "Unimplemented Format archive %s", GetName().c_str()); // TODO(bunnei): Find the right error code for this return ResultCode(-1); diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp index 5b5c5a73e..ca1463d7c 100644 --- a/src/core/file_sys/romfs_filesystem.cpp +++ b/src/core/file_sys/romfs_filesystem.cpp @@ -69,7 +69,8 @@ ResultCode RomFS_FileSystem::RenameDirectory(const Path& src_path, const Path& d return ResultCode(-1); } -ResultVal> RomFS_FileSystem::OpenDirectory(const Path& path) const { +ResultVal> RomFS_FileSystem::OpenDirectory( + const Path& path) const { return MakeResult>(std::make_unique()); } -- cgit v1.2.3