diff options
author | bunnei <bunneidev@gmail.com> | 2017-10-13 03:21:49 +0200 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2017-10-13 03:21:49 +0200 |
commit | 72b03025ac4ef0d8633c2f3e55b513cd149c59e5 (patch) | |
tree | f1fbeb915a0b3df8e4e988a6a562a763e18ea666 /src/core/file_sys | |
parent | hle: Remove a large amount of 3ds-specific service code. (diff) | |
download | yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar.gz yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar.bz2 yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar.lz yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar.xz yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.tar.zst yuzu-72b03025ac4ef0d8633c2f3e55b513cd149c59e5.zip |
Diffstat (limited to 'src/core/file_sys')
-rw-r--r-- | src/core/file_sys/archive_extsavedata.cpp | 245 | ||||
-rw-r--r-- | src/core/file_sys/archive_extsavedata.h | 89 | ||||
-rw-r--r-- | src/core/file_sys/archive_ncch.cpp | 114 | ||||
-rw-r--r-- | src/core/file_sys/archive_ncch.h | 34 | ||||
-rw-r--r-- | src/core/file_sys/archive_other_savedata.cpp | 145 | ||||
-rw-r--r-- | src/core/file_sys/archive_other_savedata.h | 52 | ||||
-rw-r--r-- | src/core/file_sys/archive_savedata.cpp | 33 | ||||
-rw-r--r-- | src/core/file_sys/archive_savedata.h | 33 | ||||
-rw-r--r-- | src/core/file_sys/archive_sdmc.cpp | 379 | ||||
-rw-r--r-- | src/core/file_sys/archive_sdmc.h | 66 | ||||
-rw-r--r-- | src/core/file_sys/archive_sdmcwriteonly.cpp | 70 | ||||
-rw-r--r-- | src/core/file_sys/archive_sdmcwriteonly.h | 57 | ||||
-rw-r--r-- | src/core/file_sys/archive_selfncch.cpp | 297 | ||||
-rw-r--r-- | src/core/file_sys/archive_selfncch.h | 54 | ||||
-rw-r--r-- | src/core/file_sys/archive_source_sd_savedata.cpp | 97 | ||||
-rw-r--r-- | src/core/file_sys/archive_source_sd_savedata.h | 32 | ||||
-rw-r--r-- | src/core/file_sys/archive_systemsavedata.cpp | 77 | ||||
-rw-r--r-- | src/core/file_sys/archive_systemsavedata.h | 61 |
18 files changed, 0 insertions, 1935 deletions
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp deleted file mode 100644 index 4867c9d17..000000000 --- a/src/core/file_sys/archive_extsavedata.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <memory> -#include <vector> -#include "common/common_types.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/file_sys/archive_extsavedata.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" -#include "core/hle/service/fs/archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/** - * A modified version of DiskFile for fixed-size file used by ExtSaveData - * The file size can't be changed by SetSize or Write. - */ -class FixSizeDiskFile : public DiskFile { -public: - FixSizeDiskFile(FileUtil::IOFile&& file, const Mode& mode) : DiskFile(std::move(file), mode) { - size = GetSize(); - } - - bool SetSize(u64 size) const override { - return false; - } - - ResultVal<size_t> Write(u64 offset, size_t length, bool flush, - const u8* buffer) const override { - if (offset > size) { - return ERR_WRITE_BEYOND_END; - } else if (offset == size) { - return MakeResult<size_t>(0); - } - - if (offset + length > size) { - length = size - offset; - } - - return DiskFile::Write(offset, length, flush, buffer); - } - -private: - u64 size{}; -}; - -/** - * Archive backend for general extsave data archive type. - * The behaviour of ExtSaveDataArchive is almost the same as SaveDataArchive, except for - * - file size can't be changed once created (thus creating zero-size file and openning with create - * flag are prohibited); - * - always open a file with read+write permission. - */ -class ExtSaveDataArchive : public SaveDataArchive { -public: - explicit ExtSaveDataArchive(const std::string& mount_point) : SaveDataArchive(mount_point) {} - - std::string GetName() const override { - return "ExtSaveDataArchive: " + mount_point; - } - - ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, - const Mode& mode) const override { - 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) { - LOG_ERROR(Service_FS, "Create flag is not supported"); - 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: - LOG_ERROR(Service_FS, "%s not found", full_path.c_str()); - return ERROR_FILE_NOT_FOUND; - case PathParser::FileFound: - break; // Expected 'success' case - } - - FileUtil::IOFile file(full_path, "r+b"); - if (!file.IsOpen()) { - LOG_CRITICAL(Service_FS, "(unreachable) Unknown error opening %s", full_path.c_str()); - return ERROR_FILE_NOT_FOUND; - } - - Mode rwmode; - rwmode.write_flag.Assign(1); - rwmode.read_flag.Assign(1); - auto disk_file = std::make_unique<FixSizeDiskFile>(std::move(file), rwmode); - return MakeResult<std::unique_ptr<FileBackend>>(std::move(disk_file)); - } - - ResultCode CreateFile(const Path& path, u64 size) const override { - if (size == 0) { - LOG_ERROR(Service_FS, "Zero-size file is not supported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - return SaveDataArchive::CreateFile(path, size); - } -}; - -std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path) { - std::vector<u8> vec_data = path.AsBinary(); - const u32* data = reinterpret_cast<const u32*>(vec_data.data()); - u32 save_low = data[1]; - u32 save_high = data[2]; - return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_high, save_low); -} - -std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { - if (shared) - return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID); - - return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), SYSTEM_ID, - SDCARD_ID); -} - -Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { - std::vector<u8> binary_path; - binary_path.reserve(12); - - // Append each word byte by byte - - // The first word is the media type - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((media_type >> (8 * i)) & 0xFF); - - // Next is the low word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((low >> (8 * i)) & 0xFF); - - // Next is the high word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((high >> (8 * i)) & 0xFF); - - return {binary_path}; -} - -ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, - bool shared) - : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { - LOG_DEBUG(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); -} - -bool ArchiveFactory_ExtSaveData::Initialize() { - if (!FileUtil::CreateFullPath(mount_point)) { - LOG_ERROR(Service_FS, "Unable to create ExtSaveData base path."); - return false; - } - - return true; -} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) { - std::string fullpath = GetExtSaveDataPath(mount_point, path) + "user/"; - if (!FileUtil::Exists(fullpath)) { - // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData. - // ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist. - if (!shared) { - return ERR_NOT_FOUND_INVALID_STATE; - } else { - return ERR_NOT_FORMATTED; - } - } - auto archive = std::make_unique<ExtSaveDataArchive>(fullpath); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - // These folders are always created with the ExtSaveData - std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; - std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; - FileUtil::CreateFullPath(user_path); - FileUtil::CreateFullPath(boss_path); - - // Write the format metadata - std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; - FileUtil::IOFile file(metadata_path, "wb"); - - if (!file.IsOpen()) { - // TODO(Subv): Find the correct error code - return ResultCode(-1); - } - - file.WriteBytes(&format_info, sizeof(format_info)); - return RESULT_SUCCESS; -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Path& path) const { - std::string metadata_path = GetExtSaveDataPath(mount_point, path) + "metadata"; - FileUtil::IOFile file(metadata_path, "rb"); - - if (!file.IsOpen()) { - LOG_ERROR(Service_FS, "Could not open metadata information for archive"); - // TODO(Subv): Verify error code - return ERR_NOT_FORMATTED; - } - - ArchiveFormatInfo info = {}; - file.ReadBytes(&info, sizeof(info)); - return MakeResult<ArchiveFormatInfo>(info); -} - -void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, - size_t icon_size) { - std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); - FileUtil::IOFile icon_file(game_path + "icon", "wb"); - icon_file.WriteBytes(icon_data, icon_size); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h deleted file mode 100644 index f705ade1c..000000000 --- a/src/core/file_sys/archive_extsavedata.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include "common/common_types.h" -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// File system interface to the ExtSaveData archive -class ArchiveFactory_ExtSaveData final : public ArchiveFactory { -public: - ArchiveFactory_ExtSaveData(const std::string& mount_point, bool shared); - - /** - * Initialize the archive. - * @return true if it initialized successfully - */ - bool Initialize(); - - std::string GetName() const override { - return "ExtSaveData"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - - const std::string& GetMountPoint() const { - return mount_point; - } - - /** - * Writes the SMDH icon of the ExtSaveData to file - * @param path Path of this ExtSaveData - * @param icon_data Binary data of the icon - * @param icon_size Size of the icon data - */ - void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); - -private: - bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData - /// archive - - /** - * This holds the full directory path for this archive, it is only set after a successful call - * to Open, this is formed as `<base extsavedatapath>/<type>/<high>/<low>`. - * See GetExtSaveDataPath for the code that extracts this data from an archive path. - */ - std::string mount_point; -}; - -/** - * Constructs a path to the concrete ExtData archive in the host filesystem based on the - * input Path and base mount point. - * @param mount_point The base mount point of the ExtSaveData archives. - * @param path The path that identifies the requested concrete ExtSaveData archive. - * @returns The complete path to the specified extdata archive in the host filesystem - */ -std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path); - -/** - * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file - * system. - * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. - * @param shared Whether this ExtSaveData container is for SharedExtSaveDatas or not. - * @returns The path to the base ExtSaveData archives' folder in the host file system - */ -std::string GetExtDataContainerPath(const std::string& mount_point, bool shared); - -/** - * Constructs a FileSys::Path object that refers to the ExtData archive identified by - * the specified media type, high save id and low save id. - * @param media_type The media type where the archive is located (NAND / SDMC) - * @param high The high word of the save id for the archive - * @param low The low word of the save id for the archive - * @returns A FileSys::Path to the wanted archive - */ -Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low); - -} // namespace FileSys diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp deleted file mode 100644 index e8c5be983..000000000 --- a/src/core/file_sys/archive_ncch.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <memory> -#include <vector> -#include "common/common_types.h" -#include "common/file_util.h" -#include "common/logging/log.h" -#include "common/string_util.h" -#include "core/core.h" -#include "core/file_sys/archive_ncch.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/ivfc_archive.h" -#include "core/file_sys/ncch_container.h" -#include "core/file_sys/title_metadata.h" -#include "core/hle/service/fs/archive.h" -#include "core/loader/loader.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -static std::string GetNCCHContainerPath(const std::string& nand_directory) { - return Common::StringFromFormat("%s%s/title/", nand_directory.c_str(), SYSTEM_ID); -} - -static std::string GetNCCHPath(const std::string& mount_point, u32 high, u32 low) { - u32 content_id = 0; - - // TODO(shinyquagsire23): Title database should be doing this path lookup - std::string content_path = - Common::StringFromFormat("%s%08x/%08x/content/", mount_point.c_str(), high, low); - std::string tmd_path = content_path + "00000000.tmd"; - TitleMetadata tmd(tmd_path); - if (tmd.Load() == Loader::ResultStatus::Success) { - content_id = tmd.GetBootContentID(); - } - - return Common::StringFromFormat("%s%08x.app", content_path.c_str(), content_id); -} - -ArchiveFactory_NCCH::ArchiveFactory_NCCH(const std::string& nand_directory) - : mount_point(GetNCCHContainerPath(nand_directory)) {} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_NCCH::Open(const Path& path) { - auto vec = path.AsBinary(); - const u32* data = reinterpret_cast<u32*>(vec.data()); - u32 high = data[1]; - u32 low = data[0]; - std::string file_path = GetNCCHPath(mount_point, high, low); - - std::shared_ptr<FileUtil::IOFile> romfs_file; - u64 romfs_offset = 0; - u64 romfs_size = 0; - auto ncch_container = NCCHContainer(file_path); - - if (ncch_container.ReadRomFS(romfs_file, romfs_offset, romfs_size) != - Loader::ResultStatus::Success) { - // High Title ID of the archive: The category (https://3dbrew.org/wiki/Title_list). - constexpr u32 shared_data_archive = 0x0004009B; - constexpr u32 system_data_archive = 0x000400DB; - - // Low Title IDs. - constexpr u32 mii_data = 0x00010202; - constexpr u32 region_manifest = 0x00010402; - constexpr u32 ng_word_list = 0x00010302; - - LOG_DEBUG(Service_FS, "Full Path: %s. Category: 0x%X. Path: 0x%X.", path.DebugStr().c_str(), - high, low); - - if (high == shared_data_archive) { - if (low == mii_data) { - LOG_ERROR(Service_FS, "Failed to get a handle for shared data archive: Mii data. "); - Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles, - "Mii data"); - } else if (low == region_manifest) { - LOG_ERROR(Service_FS, - "Failed to get a handle for shared data archive: region manifest."); - Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles, - "Region manifest"); - } - } else if (high == system_data_archive) { - if (low == ng_word_list) { - LOG_ERROR(Service_FS, - "Failed to get a handle for system data archive: NG bad word list."); - Core::System::GetInstance().SetStatus(Core::System::ResultStatus::ErrorSystemFiles, - "NG bad word list"); - } - } - return ERROR_NOT_FOUND; - } - - auto archive = std::make_unique<IVFCArchive>(romfs_file, romfs_offset, romfs_size); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveFactory_NCCH::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - LOG_ERROR(Service_FS, "Attempted to format a NCCH archive."); - // TODO: Verify error code - return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, - ErrorLevel::Permanent); -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_NCCH::GetFormatInfo(const Path& path) const { - // TODO(Subv): Implement - LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); - return ResultCode(-1); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_ncch.h b/src/core/file_sys/archive_ncch.h deleted file mode 100644 index 753b91f96..000000000 --- a/src/core/file_sys/archive_ncch.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// File system interface to the NCCH archive -class ArchiveFactory_NCCH final : public ArchiveFactory { -public: - explicit ArchiveFactory_NCCH(const std::string& mount_point); - - std::string GetName() const override { - return "NCCH"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string mount_point; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_other_savedata.cpp b/src/core/file_sys/archive_other_savedata.cpp deleted file mode 100644 index d3cf080da..000000000 --- a/src/core/file_sys/archive_other_savedata.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <tuple> -#include "core/file_sys/archive_other_savedata.h" -#include "core/file_sys/errors.h" -#include "core/hle/kernel/process.h" -#include "core/hle/service/fs/archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -// TODO(wwylele): The storage info in exheader should be checked before accessing these archives - -using Service::FS::MediaType; - -namespace { - -template <typename T> -ResultVal<std::tuple<MediaType, u64>> ParsePath(const Path& path, T program_id_reader) { - if (path.GetType() != Binary) { - LOG_ERROR(Service_FS, "Wrong path type %d", static_cast<int>(path.GetType())); - return ERROR_INVALID_PATH; - } - - std::vector<u8> vec_data = path.AsBinary(); - - if (vec_data.size() != 12) { - LOG_ERROR(Service_FS, "Wrong path length %zu", vec_data.size()); - return ERROR_INVALID_PATH; - } - - const u32* data = reinterpret_cast<const u32*>(vec_data.data()); - auto media_type = static_cast<MediaType>(data[0]); - - if (media_type != MediaType::SDMC && media_type != MediaType::GameCard) { - LOG_ERROR(Service_FS, "Unsupported media type %u", static_cast<u32>(media_type)); - - // Note: this is strange, but the error code was verified with a real 3DS - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - return MakeResult<std::tuple<MediaType, u64>>(media_type, program_id_reader(data)); -} - -ResultVal<std::tuple<MediaType, u64>> ParsePathPermitted(const Path& path) { - return ParsePath(path, - [](const u32* data) -> u64 { return (data[1] << 8) | 0x0004000000000000ULL; }); -} - -ResultVal<std::tuple<MediaType, u64>> ParsePathGeneral(const Path& path) { - return ParsePath( - path, [](const u32* data) -> u64 { return data[1] | (static_cast<u64>(data[2]) << 32); }); -} - -} // namespace - -ArchiveFactory_OtherSaveDataPermitted::ArchiveFactory_OtherSaveDataPermitted( - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) - : sd_savedata_source(sd_savedata) {} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataPermitted::Open( - const Path& path) { - MediaType media_type; - u64 program_id; - CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path)); - - if (media_type == MediaType::GameCard) { - LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); - return ERROR_GAMECARD_NOT_INSERTED; - } - - return sd_savedata_source->Open(program_id); -} - -ResultCode ArchiveFactory_OtherSaveDataPermitted::Format( - const Path& path, const FileSys::ArchiveFormatInfo& format_info) { - LOG_ERROR(Service_FS, "Attempted to format a OtherSaveDataPermitted archive."); - return ERROR_INVALID_PATH; -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataPermitted::GetFormatInfo( - const Path& path) const { - MediaType media_type; - u64 program_id; - CASCADE_RESULT(std::tie(media_type, program_id), ParsePathPermitted(path)); - - if (media_type == MediaType::GameCard) { - LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); - return ERROR_GAMECARD_NOT_INSERTED; - } - - return sd_savedata_source->GetFormatInfo(program_id); -} - -ArchiveFactory_OtherSaveDataGeneral::ArchiveFactory_OtherSaveDataGeneral( - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) - : sd_savedata_source(sd_savedata) {} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_OtherSaveDataGeneral::Open( - const Path& path) { - MediaType media_type; - u64 program_id; - CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); - - if (media_type == MediaType::GameCard) { - LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); - return ERROR_GAMECARD_NOT_INSERTED; - } - - return sd_savedata_source->Open(program_id); -} - -ResultCode ArchiveFactory_OtherSaveDataGeneral::Format( - const Path& path, const FileSys::ArchiveFormatInfo& format_info) { - MediaType media_type; - u64 program_id; - CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); - - if (media_type == MediaType::GameCard) { - LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); - return ERROR_GAMECARD_NOT_INSERTED; - } - - return sd_savedata_source->Format(program_id, format_info); -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_OtherSaveDataGeneral::GetFormatInfo( - const Path& path) const { - MediaType media_type; - u64 program_id; - CASCADE_RESULT(std::tie(media_type, program_id), ParsePathGeneral(path)); - - if (media_type == MediaType::GameCard) { - LOG_WARNING(Service_FS, "(stubbed) Unimplemented media type GameCard"); - return ERROR_GAMECARD_NOT_INSERTED; - } - - return sd_savedata_source->GetFormatInfo(program_id); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_other_savedata.h b/src/core/file_sys/archive_other_savedata.h deleted file mode 100644 index d80725158..000000000 --- a/src/core/file_sys/archive_other_savedata.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/file_sys/archive_source_sd_savedata.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// File system interface to the OtherSaveDataPermitted archive -class ArchiveFactory_OtherSaveDataPermitted final : public ArchiveFactory { -public: - explicit ArchiveFactory_OtherSaveDataPermitted( - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); - - std::string GetName() const override { - return "OtherSaveDataPermitted"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string mount_point; - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; -}; - -/// File system interface to the OtherSaveDataGeneral archive -class ArchiveFactory_OtherSaveDataGeneral final : public ArchiveFactory { -public: - explicit ArchiveFactory_OtherSaveDataGeneral( - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); - - std::string GetName() const override { - return "OtherSaveDataGeneral"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string mount_point; - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp deleted file mode 100644 index 67076c73f..000000000 --- a/src/core/file_sys/archive_savedata.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/file_sys/archive_savedata.h" -#include "core/hle/kernel/process.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -ArchiveFactory_SaveData::ArchiveFactory_SaveData( - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata) - : sd_savedata_source(sd_savedata) {} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { - UNIMPLEMENTED(); - return {}; //sd_savedata_source->Open(Kernel::g_current_process->codeset->program_id); -} - -ResultCode ArchiveFactory_SaveData::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - UNIMPLEMENTED(); - return RESULT_SUCCESS; //sd_savedata_source->Format(Kernel::g_current_process->codeset->program_id, format_info); -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { - UNIMPLEMENTED(); - return {}; //sd_savedata_source->GetFormatInfo(Kernel::g_current_process->codeset->program_id); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h deleted file mode 100644 index 41aa6f189..000000000 --- a/src/core/file_sys/archive_savedata.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/file_sys/archive_source_sd_savedata.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// File system interface to the SaveData archive -class ArchiveFactory_SaveData final : public ArchiveFactory { -public: - explicit ArchiveFactory_SaveData(std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source); - - std::string GetName() const override { - return "SaveData"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string mount_point; - std::shared_ptr<ArchiveSource_SDSaveData> sd_savedata_source; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp deleted file mode 100644 index fe3dce5d4..000000000 --- a/src/core/file_sys/archive_sdmc.cpp +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <memory> -#include "common/file_util.h" -#include "common/logging/log.h" -#include "core/file_sys/archive_sdmc.h" -#include "core/file_sys/disk_archive.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/path_parser.h" -#include "core/settings.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFile(const Path& path, - const Mode& mode) const { - Mode modified_mode; - modified_mode.hex = mode.hex; - - // SDMC archive always opens a file with at least read permission - modified_mode.read_flag.Assign(1); - - return OpenFileBase(path, modified_mode); -} - -ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFileBase(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_INVALID_OPEN_FLAGS; - } - - if (mode.create_flag && !mode.write_flag) { - LOG_ERROR(Service_FS, "Create flag set but write flag not set"); - return ERROR_INVALID_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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_NOT_FOUND; - case PathParser::DirectoryFound: - LOG_ERROR(Service_FS, "%s is not a file", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC; - 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_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_NOT_FOUND; - } - - auto disk_file = std::make_unique<DiskFile>(std::move(file), mode); - return MakeResult<std::unique_ptr<FileBackend>>(std::move(disk_file)); -} - -ResultCode SDMCArchive::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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::FileInPath: - case PathParser::NotFound: - LOG_ERROR(Service_FS, "%s not found", full_path.c_str()); - return ERROR_NOT_FOUND; - case PathParser::DirectoryFound: - LOG_ERROR(Service_FS, "%s is not a file", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC; - 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_NOT_FOUND; -} - -ResultCode SDMCArchive::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(yuriks): This code probably isn't right, it'll return a Status even if the file didn't - // exist or similar. Verify. - return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description - ErrorSummary::NothingHappened, ErrorLevel::Status); -} - -template <typename T> -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_NOT_FOUND; - - 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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::NotFound: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_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_SDMC; - 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_UNEXPECTED_FILE_OR_DIRECTORY_SDMC; -} - -ResultCode SDMCArchive::DeleteDirectory(const Path& path) const { - return DeleteDirectoryHelper(path, mount_point, FileUtil::DeleteDir); -} - -ResultCode SDMCArchive::DeleteDirectoryRecursively(const Path& path) const { - return DeleteDirectoryHelper( - path, mount_point, [](const std::string& p) { return FileUtil::DeleteDirRecursively(p); }); -} - -ResultCode SDMCArchive::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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_NOT_FOUND; - case PathParser::DirectoryFound: - LOG_ERROR(Service_FS, "%s already exists", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC; - case PathParser::FileFound: - LOG_ERROR(Service_FS, "%s already exists", full_path.c_str()); - return ERROR_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"); - return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, - ErrorLevel::Info); -} - -ResultCode SDMCArchive::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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Path not found %s", full_path.c_str()); - return ERROR_NOT_FOUND; - case PathParser::DirectoryFound: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "%s already exists", full_path.c_str()); - return ERROR_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()); - return ResultCode(ErrorDescription::NoData, ErrorModule::FS, ErrorSummary::Canceled, - ErrorLevel::Status); -} - -ResultCode SDMCArchive::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(yuriks): This code probably isn't right, it'll return a Status even if the file didn't - // exist or similar. Verify. - return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description - ErrorSummary::NothingHappened, ErrorLevel::Status); -} - -ResultVal<std::unique_ptr<DirectoryBackend>> SDMCArchive::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_NOT_FOUND; - case PathParser::PathNotFound: - case PathParser::NotFound: - case PathParser::FileFound: - LOG_ERROR(Service_FS, "%s not found", full_path.c_str()); - return ERROR_NOT_FOUND; - case PathParser::FileInPath: - LOG_ERROR(Service_FS, "Unexpected file in path %s", full_path.c_str()); - return ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC; - case PathParser::DirectoryFound: - break; // Expected 'success' case - } - - auto directory = std::make_unique<DiskDirectory>(full_path); - return MakeResult<std::unique_ptr<DirectoryBackend>>(std::move(directory)); -} - -u64 SDMCArchive::GetFreeBytes() const { - // TODO: Stubbed to return 1GiB - return 1024 * 1024 * 1024; -} - -ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) - : sdmc_directory(sdmc_directory) { - LOG_DEBUG(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); -} - -bool ArchiveFactory_SDMC::Initialize() { - if (!Settings::values.use_virtual_sd) { - LOG_WARNING(Service_FS, "SDMC disabled by config."); - return false; - } - - if (!FileUtil::CreateFullPath(sdmc_directory)) { - LOG_ERROR(Service_FS, "Unable to create SDMC path."); - return false; - } - - return true; -} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path) { - auto archive = std::make_unique<SDMCArchive>(sdmc_directory); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveFactory_SDMC::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - // This is kind of an undesirable operation, so let's just ignore it. :) - return RESULT_SUCCESS; -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMC::GetFormatInfo(const Path& path) const { - // TODO(Subv): Implement - LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); - return ResultCode(-1); -} -} // namespace FileSys diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h deleted file mode 100644 index f6c70bfcc..000000000 --- a/src/core/file_sys/archive_sdmc.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 <memory> -#include <string> -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// Archive backend for SDMC archive -class SDMCArchive : public ArchiveBackend { -public: - explicit SDMCArchive(const std::string& mount_point_) : mount_point(mount_point_) {} - - std::string GetName() const override { - return "SDMCArchive: " + mount_point; - } - - ResultVal<std::unique_ptr<FileBackend>> 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<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; - u64 GetFreeBytes() const override; - -protected: - ResultVal<std::unique_ptr<FileBackend>> OpenFileBase(const Path& path, const Mode& mode) const; - std::string mount_point; -}; - -/// File system interface to the SDMC archive -class ArchiveFactory_SDMC final : public ArchiveFactory { -public: - explicit ArchiveFactory_SDMC(const std::string& mount_point); - - /** - * Initialize the archive. - * @return true if it initialized successfully - */ - bool Initialize(); - - std::string GetName() const override { - return "SDMC"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string sdmc_directory; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_sdmcwriteonly.cpp b/src/core/file_sys/archive_sdmcwriteonly.cpp deleted file mode 100644 index 244aef48a..000000000 --- a/src/core/file_sys/archive_sdmcwriteonly.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <memory> -#include "common/file_util.h" -#include "core/file_sys/archive_sdmcwriteonly.h" -#include "core/file_sys/directory_backend.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/file_backend.h" -#include "core/settings.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -ResultVal<std::unique_ptr<FileBackend>> SDMCWriteOnlyArchive::OpenFile(const Path& path, - const Mode& mode) const { - if (mode.read_flag) { - LOG_ERROR(Service_FS, "Read flag is not supported"); - return ERROR_INVALID_READ_FLAG; - } - return SDMCArchive::OpenFileBase(path, mode); -} - -ResultVal<std::unique_ptr<DirectoryBackend>> SDMCWriteOnlyArchive::OpenDirectory( - const Path& path) const { - LOG_ERROR(Service_FS, "Not supported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; -} - -ArchiveFactory_SDMCWriteOnly::ArchiveFactory_SDMCWriteOnly(const std::string& mount_point) - : sdmc_directory(mount_point) { - LOG_DEBUG(Service_FS, "Directory %s set as SDMCWriteOnly.", sdmc_directory.c_str()); -} - -bool ArchiveFactory_SDMCWriteOnly::Initialize() { - if (!Settings::values.use_virtual_sd) { - LOG_WARNING(Service_FS, "SDMC disabled by config."); - return false; - } - - if (!FileUtil::CreateFullPath(sdmc_directory)) { - LOG_ERROR(Service_FS, "Unable to create SDMC path."); - return false; - } - - return true; -} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMCWriteOnly::Open(const Path& path) { - auto archive = std::make_unique<SDMCWriteOnlyArchive>(sdmc_directory); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveFactory_SDMCWriteOnly::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - // TODO(wwylele): hwtest this - LOG_ERROR(Service_FS, "Attempted to format a SDMC write-only archive."); - return ResultCode(-1); -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_SDMCWriteOnly::GetFormatInfo(const Path& path) const { - // TODO(Subv): Implement - LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); - return ResultCode(-1); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_sdmcwriteonly.h b/src/core/file_sys/archive_sdmcwriteonly.h deleted file mode 100644 index 9cd38d96f..000000000 --- a/src/core/file_sys/archive_sdmcwriteonly.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/file_sys/archive_sdmc.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/** - * Archive backend for SDMC write-only archive. - * The behaviour of SDMCWriteOnlyArchive is almost the same as SDMCArchive, except for - * - OpenDirectory is unsupported; - * - OpenFile with read flag is unsupported. - */ -class SDMCWriteOnlyArchive : public SDMCArchive { -public: - explicit SDMCWriteOnlyArchive(const std::string& mount_point) : SDMCArchive(mount_point) {} - - std::string GetName() const override { - return "SDMCWriteOnlyArchive: " + mount_point; - } - - ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, - const Mode& mode) const override; - - ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override; -}; - -/// File system interface to the SDMC write-only archive -class ArchiveFactory_SDMCWriteOnly final : public ArchiveFactory { -public: - explicit ArchiveFactory_SDMCWriteOnly(const std::string& mount_point); - - /** - * Initialize the archive. - * @return true if it initialized successfully - */ - bool Initialize(); - - std::string GetName() const override { - return "SDMCWriteOnly"; - } - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - std::string sdmc_directory; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_selfncch.cpp b/src/core/file_sys/archive_selfncch.cpp deleted file mode 100644 index 3222000cf..000000000 --- a/src/core/file_sys/archive_selfncch.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <array> -#include <cinttypes> -#include "common/common_types.h" -#include "common/logging/log.h" -#include "common/swap.h" -#include "core/file_sys/archive_selfncch.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/ivfc_archive.h" -#include "core/hle/kernel/process.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -enum class SelfNCCHFilePathType : u32 { - RomFS = 0, - Code = 1, // This is not supported by SelfNCCHArchive but by archive 0x2345678E - ExeFS = 2, - UpdateRomFS = 5, // This is presumably for accessing the RomFS of the update patch. -}; - -struct SelfNCCHFilePath { - u32_le type; - std::array<char, 8> exefs_filename; -}; -static_assert(sizeof(SelfNCCHFilePath) == 12, "NCCHFilePath has wrong size!"); - -// A read-only file created from a block of data. It only allows you to read the entire file at -// once, in a single read operation. -class ExeFSSectionFile final : public FileBackend { -public: - explicit ExeFSSectionFile(std::shared_ptr<std::vector<u8>> data_) : data(std::move(data_)) {} - - ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override { - if (offset != 0) { - LOG_ERROR(Service_FS, "offset must be zero!"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - if (length != data->size()) { - LOG_ERROR(Service_FS, "size must match the file size!"); - return ERROR_INCORRECT_EXEFS_READ_SIZE; - } - - std::memcpy(buffer, data->data(), data->size()); - return MakeResult<size_t>(data->size()); - } - - ResultVal<size_t> Write(u64 offset, size_t length, bool flush, - const u8* buffer) const override { - LOG_ERROR(Service_FS, "The file is read-only!"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - u64 GetSize() const override { - return data->size(); - } - - bool SetSize(u64 size) const override { - return false; - } - - bool Close() const override { - return true; - } - - void Flush() const override {} - -private: - std::shared_ptr<std::vector<u8>> data; -}; - -// SelfNCCHArchive represents the running application itself. From this archive the application can -// open RomFS and ExeFS, excluding the .code section. -class SelfNCCHArchive final : public ArchiveBackend { -public: - explicit SelfNCCHArchive(const NCCHData& ncch_data_) : ncch_data(ncch_data_) {} - - std::string GetName() const override { - return "SelfNCCHArchive"; - } - - ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode&) const override { - // Note: SelfNCCHArchive doesn't check the open mode. - - if (path.GetType() != LowPathType::Binary) { - LOG_ERROR(Service_FS, "Path need to be Binary"); - return ERROR_INVALID_PATH; - } - - std::vector<u8> binary = path.AsBinary(); - if (binary.size() != sizeof(SelfNCCHFilePath)) { - LOG_ERROR(Service_FS, "Wrong path size %zu", binary.size()); - return ERROR_INVALID_PATH; - } - - SelfNCCHFilePath file_path; - std::memcpy(&file_path, binary.data(), sizeof(SelfNCCHFilePath)); - - switch (static_cast<SelfNCCHFilePathType>(file_path.type)) { - case SelfNCCHFilePathType::UpdateRomFS: - return OpenUpdateRomFS(); - - case SelfNCCHFilePathType::RomFS: - return OpenRomFS(); - - case SelfNCCHFilePathType::Code: - LOG_ERROR(Service_FS, "Reading the code section is not supported!"); - return ERROR_COMMAND_NOT_ALLOWED; - - case SelfNCCHFilePathType::ExeFS: { - const auto& raw = file_path.exefs_filename; - auto end = std::find(raw.begin(), raw.end(), '\0'); - std::string filename(raw.begin(), end); - return OpenExeFS(filename); - } - default: - LOG_ERROR(Service_FS, "Unknown file type %u!", static_cast<u32>(file_path.type)); - return ERROR_INVALID_PATH; - } - } - - ResultCode DeleteFile(const Path& path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode DeleteDirectory(const Path& path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode DeleteDirectoryRecursively(const Path& path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode CreateFile(const Path& path, u64 size) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode CreateDirectory(const Path& path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultCode RenameDirectory(const Path& src_path, const Path& dest_path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - ResultVal<std::unique_ptr<DirectoryBackend>> OpenDirectory(const Path& path) const override { - LOG_ERROR(Service_FS, "Unsupported"); - return ERROR_UNSUPPORTED_OPEN_FLAGS; - } - - u64 GetFreeBytes() const override { - return 0; - } - -private: - ResultVal<std::unique_ptr<FileBackend>> OpenRomFS() const { - if (ncch_data.romfs_file) { - return MakeResult<std::unique_ptr<FileBackend>>(std::make_unique<IVFCFile>( - ncch_data.romfs_file, ncch_data.romfs_offset, ncch_data.romfs_size)); - } else { - LOG_INFO(Service_FS, "Unable to read RomFS"); - return ERROR_ROMFS_NOT_FOUND; - } - } - - ResultVal<std::unique_ptr<FileBackend>> OpenUpdateRomFS() const { - if (ncch_data.update_romfs_file) { - return MakeResult<std::unique_ptr<FileBackend>>(std::make_unique<IVFCFile>( - ncch_data.update_romfs_file, ncch_data.update_romfs_offset, - ncch_data.update_romfs_size)); - } else { - LOG_INFO(Service_FS, "Unable to read update RomFS"); - return ERROR_ROMFS_NOT_FOUND; - } - } - - ResultVal<std::unique_ptr<FileBackend>> OpenExeFS(const std::string& filename) const { - if (filename == "icon") { - if (ncch_data.icon) { - return MakeResult<std::unique_ptr<FileBackend>>( - std::make_unique<ExeFSSectionFile>(ncch_data.icon)); - } - - LOG_WARNING(Service_FS, "Unable to read icon"); - return ERROR_EXEFS_SECTION_NOT_FOUND; - } - - if (filename == "logo") { - if (ncch_data.logo) { - return MakeResult<std::unique_ptr<FileBackend>>( - std::make_unique<ExeFSSectionFile>(ncch_data.logo)); - } - - LOG_WARNING(Service_FS, "Unable to read logo"); - return ERROR_EXEFS_SECTION_NOT_FOUND; - } - - if (filename == "banner") { - if (ncch_data.banner) { - return MakeResult<std::unique_ptr<FileBackend>>( - std::make_unique<ExeFSSectionFile>(ncch_data.banner)); - } - - LOG_WARNING(Service_FS, "Unable to read banner"); - return ERROR_EXEFS_SECTION_NOT_FOUND; - } - - LOG_ERROR(Service_FS, "Unknown ExeFS section %s!", filename.c_str()); - return ERROR_INVALID_PATH; - } - - NCCHData ncch_data; -}; - -void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) { - u64 program_id = 0; - if (app_loader.ReadProgramId(program_id) != Loader::ResultStatus::Success) { - LOG_WARNING( - Service_FS, - "Could not read program id when registering with SelfNCCH, this might be a 3dsx file"); - } - - LOG_DEBUG(Service_FS, "Registering program %016" PRIX64 " with the SelfNCCH archive factory", - program_id); - - if (ncch_data.find(program_id) != ncch_data.end()) { - LOG_WARNING(Service_FS, "Registering program %016" PRIX64 - " with SelfNCCH will override existing mapping", - program_id); - } - - NCCHData& data = ncch_data[program_id]; - - std::shared_ptr<FileUtil::IOFile> romfs_file_; - if (Loader::ResultStatus::Success == - app_loader.ReadRomFS(romfs_file_, data.romfs_offset, data.romfs_size)) { - - data.romfs_file = std::move(romfs_file_); - } - - std::shared_ptr<FileUtil::IOFile> update_romfs_file; - if (Loader::ResultStatus::Success == - app_loader.ReadUpdateRomFS(update_romfs_file, data.update_romfs_offset, - data.update_romfs_size)) { - - data.update_romfs_file = std::move(update_romfs_file); - } - - std::vector<u8> buffer; - - if (Loader::ResultStatus::Success == app_loader.ReadIcon(buffer)) - data.icon = std::make_shared<std::vector<u8>>(std::move(buffer)); - - buffer.clear(); - if (Loader::ResultStatus::Success == app_loader.ReadLogo(buffer)) - data.logo = std::make_shared<std::vector<u8>>(std::move(buffer)); - - buffer.clear(); - if (Loader::ResultStatus::Success == app_loader.ReadBanner(buffer)) - data.banner = std::make_shared<std::vector<u8>>(std::move(buffer)); -} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) { - //auto archive = std::make_unique<SelfNCCHArchive>( - // ncch_data[Kernel::g_current_process->codeset->program_id]); - //return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); - return {}; -} - -ResultCode ArchiveFactory_SelfNCCH::Format(const Path&, const FileSys::ArchiveFormatInfo&) { - LOG_ERROR(Service_FS, "Attempted to format a SelfNCCH archive."); - return ERROR_INVALID_PATH; -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_SelfNCCH::GetFormatInfo(const Path&) const { - LOG_ERROR(Service_FS, "Attempted to get format info of a SelfNCCH archive"); - return ERROR_INVALID_PATH; -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_selfncch.h b/src/core/file_sys/archive_selfncch.h deleted file mode 100644 index 0d6d6766e..000000000 --- a/src/core/file_sys/archive_selfncch.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include <unordered_map> -#include <vector> -#include "common/common_types.h" -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" -#include "core/loader/loader.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -struct NCCHData { - std::shared_ptr<std::vector<u8>> icon; - std::shared_ptr<std::vector<u8>> logo; - std::shared_ptr<std::vector<u8>> banner; - std::shared_ptr<FileUtil::IOFile> romfs_file; - u64 romfs_offset = 0; - u64 romfs_size = 0; - - std::shared_ptr<FileUtil::IOFile> update_romfs_file; - u64 update_romfs_offset = 0; - u64 update_romfs_size = 0; -}; - -/// File system interface to the SelfNCCH archive -class ArchiveFactory_SelfNCCH final : public ArchiveFactory { -public: - ArchiveFactory_SelfNCCH() = default; - - /// Registers a loaded application so that we can open its SelfNCCH archive when requested. - void Register(Loader::AppLoader& app_loader); - - std::string GetName() const override { - return "SelfNCCH"; - } - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - -private: - /// Mapping of ProgramId -> NCCHData - std::unordered_map<u64, NCCHData> ncch_data; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_source_sd_savedata.cpp b/src/core/file_sys/archive_source_sd_savedata.cpp deleted file mode 100644 index a7e331724..000000000 --- a/src/core/file_sys/archive_source_sd_savedata.cpp +++ /dev/null @@ -1,97 +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 "common/logging/log.h" -#include "common/string_util.h" -#include "core/file_sys/archive_source_sd_savedata.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/savedata_archive.h" -#include "core/hle/service/fs/archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -namespace { - -std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { - return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), - SYSTEM_ID, SDCARD_ID); -} - -std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { - u32 high = static_cast<u32>(program_id >> 32); - u32 low = static_cast<u32>(program_id & 0xFFFFFFFF); - return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, - low); -} - -std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { - u32 high = static_cast<u32>(program_id >> 32); - u32 low = static_cast<u32>(program_id & 0xFFFFFFFF); - return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), - high, low); -} - -} // namespace - -ArchiveSource_SDSaveData::ArchiveSource_SDSaveData(const std::string& sdmc_directory) - : mount_point(GetSaveDataContainerPath(sdmc_directory)) { - LOG_DEBUG(Service_FS, "Directory %s set as SaveData.", mount_point.c_str()); -} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveSource_SDSaveData::Open(u64 program_id) { - std::string concrete_mount_point = GetSaveDataPath(mount_point, program_id); - if (!FileUtil::Exists(concrete_mount_point)) { - // When a SaveData archive is created for the first time, it is not yet formatted and the - // save file/directory structure expected by the game has not yet been initialized. - // Returning the NotFormatted error code will signal the game to provision the SaveData - // archive with the files and folders that it expects. - return ERR_NOT_FORMATTED; - } - - auto archive = std::make_unique<SaveDataArchive>(std::move(concrete_mount_point)); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveSource_SDSaveData::Format(u64 program_id, - const FileSys::ArchiveFormatInfo& format_info) { - std::string concrete_mount_point = GetSaveDataPath(mount_point, program_id); - FileUtil::DeleteDirRecursively(concrete_mount_point); - FileUtil::CreateFullPath(concrete_mount_point); - - // Write the format metadata - std::string metadata_path = GetSaveDataMetadataPath(mount_point, program_id); - FileUtil::IOFile file(metadata_path, "wb"); - - if (file.IsOpen()) { - file.WriteBytes(&format_info, sizeof(format_info)); - return RESULT_SUCCESS; - } - return RESULT_SUCCESS; -} - -ResultVal<ArchiveFormatInfo> ArchiveSource_SDSaveData::GetFormatInfo(u64 program_id) const { - std::string metadata_path = GetSaveDataMetadataPath(mount_point, program_id); - FileUtil::IOFile file(metadata_path, "rb"); - - if (!file.IsOpen()) { - LOG_ERROR(Service_FS, "Could not open metadata information for archive"); - // TODO(Subv): Verify error code - return ERR_NOT_FORMATTED; - } - - ArchiveFormatInfo info = {}; - file.ReadBytes(&info, sizeof(info)); - return MakeResult<ArchiveFormatInfo>(info); -} - -std::string ArchiveSource_SDSaveData::GetSaveDataPathFor(const std::string& mount_point, - u64 program_id) { - return GetSaveDataPath(GetSaveDataContainerPath(mount_point), program_id); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_source_sd_savedata.h b/src/core/file_sys/archive_source_sd_savedata.h deleted file mode 100644 index b5fe43cc1..000000000 --- a/src/core/file_sys/archive_source_sd_savedata.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// A common source of SD save data archive -class ArchiveSource_SDSaveData { -public: - explicit ArchiveSource_SDSaveData(const std::string& mount_point); - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(u64 program_id); - ResultCode Format(u64 program_id, const FileSys::ArchiveFormatInfo& format_info); - ResultVal<ArchiveFormatInfo> GetFormatInfo(u64 program_id) const; - - static std::string GetSaveDataPathFor(const std::string& mount_point, u64 program_id); - -private: - std::string mount_point; -}; - -} // namespace FileSys diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp deleted file mode 100644 index 81423bffd..000000000 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <memory> -#include <vector> -#include "common/common_types.h" -#include "common/file_util.h" -#include "common/string_util.h" -#include "core/file_sys/archive_systemsavedata.h" -#include "core/file_sys/errors.h" -#include "core/file_sys/savedata_archive.h" -#include "core/hle/service/fs/archive.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path) { - std::vector<u8> vec_data = path.AsBinary(); - const u32* data = reinterpret_cast<const u32*>(vec_data.data()); - u32 save_low = data[1]; - u32 save_high = data[0]; - return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high); -} - -std::string GetSystemSaveDataContainerPath(const std::string& mount_point) { - return Common::StringFromFormat("%sdata/%s/sysdata/", mount_point.c_str(), SYSTEM_ID); -} - -Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) { - std::vector<u8> binary_path; - binary_path.reserve(8); - - // Append each word byte by byte - - // First is the high word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((high >> (8 * i)) & 0xFF); - - // Next is the low word - for (unsigned i = 0; i < 4; ++i) - binary_path.push_back((low >> (8 * i)) & 0xFF); - - return {binary_path}; -} - -ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) - : base_path(GetSystemSaveDataContainerPath(nand_path)) {} - -ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { - std::string fullpath = GetSystemSaveDataPath(base_path, path); - if (!FileUtil::Exists(fullpath)) { - // TODO(Subv): Check error code, this one is probably wrong - return ERR_NOT_FORMATTED; - } - auto archive = std::make_unique<SaveDataArchive>(fullpath); - return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); -} - -ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, - const FileSys::ArchiveFormatInfo& format_info) { - std::string fullpath = GetSystemSaveDataPath(base_path, path); - FileUtil::DeleteDirRecursively(fullpath); - FileUtil::CreateFullPath(fullpath); - return RESULT_SUCCESS; -} - -ResultVal<ArchiveFormatInfo> ArchiveFactory_SystemSaveData::GetFormatInfo(const Path& path) const { - // TODO(Subv): Implement - LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive %s", GetName().c_str()); - return ResultCode(-1); -} - -} // namespace FileSys diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h deleted file mode 100644 index 52eb6c630..000000000 --- a/src/core/file_sys/archive_systemsavedata.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <memory> -#include <string> -#include "common/common_types.h" -#include "core/file_sys/archive_backend.h" -#include "core/hle/result.h" - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// FileSys namespace - -namespace FileSys { - -/// File system interface to the SystemSaveData archive -class ArchiveFactory_SystemSaveData final : public ArchiveFactory { -public: - explicit ArchiveFactory_SystemSaveData(const std::string& mount_point); - - ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; - ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; - ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; - - std::string GetName() const override { - return "SystemSaveData"; - } - -private: - std::string base_path; -}; - -/** - * Constructs a path to the concrete SystemSaveData archive in the host filesystem based on the - * input Path and base mount point. - * @param mount_point The base mount point of the SystemSaveData archives. - * @param path The path that identifies the requested concrete SystemSaveData archive. - * @returns The complete path to the specified SystemSaveData archive in the host filesystem - */ -std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path); - -/** - * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file - * system. - * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. - * @returns The path to the base SystemSaveData archives' folder in the host file system - */ -std::string GetSystemSaveDataContainerPath(const std::string& mount_point); - -/** - * Constructs a FileSys::Path object that refers to the SystemSaveData archive identified by - * the specified high save id and low save id. - * @param high The high word of the save id for the archive - * @param low The low word of the save id for the archive - * @returns A FileSys::Path to the wanted archive - */ -Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low); - -} // namespace FileSys |