diff options
| author | 2015-02-06 11:53:14 -0200 | |
|---|---|---|
| committer | 2015-02-10 13:43:44 -0200 | |
| commit | 3f1a3952d707bce7851652ce54701ca14334f314 (patch) | |
| tree | 04c79ff9887f0074813276cdf989e6814901e943 /src/core | |
| parent | FS: Get rid of completely useless Archive class (diff) | |
| download | yuzu-3f1a3952d707bce7851652ce54701ca14334f314.tar.gz yuzu-3f1a3952d707bce7851652ce54701ca14334f314.tar.xz yuzu-3f1a3952d707bce7851652ce54701ca14334f314.zip | |
FS: Allow multiple instances of the same archive type to be open at once
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/file_sys/archive_backend.h | 39 | ||||
| -rw-r--r-- | src/core/file_sys/archive_extsavedata.cpp | 15 | ||||
| -rw-r--r-- | src/core/file_sys/archive_extsavedata.h | 21 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.cpp | 17 | ||||
| -rw-r--r-- | src/core/file_sys/archive_romfs.h | 11 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedata.cpp | 23 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedata.h | 17 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedatacheck.cpp | 28 | ||||
| -rw-r--r-- | src/core/file_sys/archive_savedatacheck.h | 8 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.cpp | 17 | ||||
| -rw-r--r-- | src/core/file_sys/archive_sdmc.h | 10 | ||||
| -rw-r--r-- | src/core/file_sys/disk_archive.cpp | 26 | ||||
| -rw-r--r-- | src/core/file_sys/disk_archive.h | 25 | ||||
| -rw-r--r-- | src/core/file_sys/ivfc_archive.cpp | 22 | ||||
| -rw-r--r-- | src/core/file_sys/ivfc_archive.h | 13 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 51 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/ptm_u.cpp | 9 | ||||
| -rw-r--r-- | src/core/loader/loader.cpp | 2 |
19 files changed, 199 insertions, 159 deletions
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h index 390178f67..43a106549 100644 --- a/src/core/file_sys/archive_backend.h +++ b/src/core/file_sys/archive_backend.h | |||
| @@ -181,20 +181,6 @@ public: | |||
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | /** | 183 | /** |
| 184 | * Tries to open the archive of this type with the specified path | ||
| 185 | * @param path Path to the archive | ||
| 186 | * @return ResultCode of the operation | ||
| 187 | */ | ||
| 188 | virtual ResultCode Open(const Path& path) = 0; | ||
| 189 | |||
| 190 | /** | ||
| 191 | * Deletes the archive contents and then re-creates the base folder | ||
| 192 | * @param path Path to the archive | ||
| 193 | * @return ResultCode of the operation, 0 on success | ||
| 194 | */ | ||
| 195 | virtual ResultCode Format(const Path& path) const = 0; | ||
| 196 | |||
| 197 | /** | ||
| 198 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | 184 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) |
| 199 | */ | 185 | */ |
| 200 | virtual std::string GetName() const = 0; | 186 | virtual std::string GetName() const = 0; |
| @@ -260,4 +246,29 @@ public: | |||
| 260 | virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; | 246 | virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; |
| 261 | }; | 247 | }; |
| 262 | 248 | ||
| 249 | class ArchiveFactory : NonCopyable { | ||
| 250 | public: | ||
| 251 | virtual ~ArchiveFactory() { | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | ||
| 256 | */ | ||
| 257 | virtual std::string GetName() const = 0; | ||
| 258 | |||
| 259 | /** | ||
| 260 | * Tries to open the archive of this type with the specified path | ||
| 261 | * @param path Path to the archive | ||
| 262 | * @return An ArchiveBackend corresponding operating specified archive path. | ||
| 263 | */ | ||
| 264 | virtual ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) = 0; | ||
| 265 | |||
| 266 | /** | ||
| 267 | * Deletes the archive contents and then re-creates the base folder | ||
| 268 | * @param path Path to the archive | ||
| 269 | * @return ResultCode of the operation, 0 on success | ||
| 270 | */ | ||
| 271 | virtual ResultCode Format(const Path& path) = 0; | ||
| 272 | }; | ||
| 273 | |||
| 263 | } // namespace FileSys | 274 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 33e4e76f8..0363c9771 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/make_unique.h" | ||
| 9 | 10 | ||
| 10 | #include "core/file_sys/archive_extsavedata.h" | 11 | #include "core/file_sys/archive_extsavedata.h" |
| 11 | #include "core/file_sys/disk_archive.h" | 12 | #include "core/file_sys/disk_archive.h" |
| @@ -33,12 +34,12 @@ std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) | |||
| 33 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); | 34 | SYSTEM_ID.c_str(), SDCARD_ID.c_str()); |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | Archive_ExtSaveData::Archive_ExtSaveData(const std::string& mount_location, bool shared) | 37 | ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) |
| 37 | : DiskArchive(GetExtDataContainerPath(mount_location, shared)) { | 38 | : mount_point(GetExtDataContainerPath(mount_location, shared)) { |
| 38 | LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); | 39 | LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | bool Archive_ExtSaveData::Initialize() { | 42 | bool ArchiveFactory_ExtSaveData::Initialize() { |
| 42 | if (!FileUtil::CreateFullPath(mount_point)) { | 43 | if (!FileUtil::CreateFullPath(mount_point)) { |
| 43 | LOG_ERROR(Service_FS, "Unable to create ExtSaveData base path."); | 44 | LOG_ERROR(Service_FS, "Unable to create ExtSaveData base path."); |
| 44 | return false; | 45 | return false; |
| @@ -47,18 +48,18 @@ bool Archive_ExtSaveData::Initialize() { | |||
| 47 | return true; | 48 | return true; |
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | ResultCode Archive_ExtSaveData::Open(const Path& path) { | 51 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(const Path& path) { |
| 51 | std::string fullpath = GetExtSaveDataPath(mount_point, path); | 52 | std::string fullpath = GetExtSaveDataPath(mount_point, path); |
| 52 | if (!FileUtil::Exists(fullpath)) { | 53 | if (!FileUtil::Exists(fullpath)) { |
| 53 | // TODO(Subv): Check error code, this one is probably wrong | 54 | // TODO(Subv): Check error code, this one is probably wrong |
| 54 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | 55 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 55 | ErrorSummary::InvalidState, ErrorLevel::Status); | 56 | ErrorSummary::InvalidState, ErrorLevel::Status); |
| 56 | } | 57 | } |
| 57 | concrete_mount_point = fullpath; | 58 | auto archive = Common::make_unique<DiskArchive>(fullpath); |
| 58 | return RESULT_SUCCESS; | 59 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | ResultCode Archive_ExtSaveData::Format(const Path& path) const { | 62 | ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path) { |
| 62 | std::string fullpath = GetExtSaveDataPath(mount_point, path); | 63 | std::string fullpath = GetExtSaveDataPath(mount_point, path); |
| 63 | FileUtil::CreateFullPath(fullpath); | 64 | FileUtil::CreateFullPath(fullpath); |
| 64 | return RESULT_SUCCESS; | 65 | return RESULT_SUCCESS; |
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h index 802a11b5f..83c6b0291 100644 --- a/src/core/file_sys/archive_extsavedata.h +++ b/src/core/file_sys/archive_extsavedata.h | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | /// File system interface to the ExtSaveData archive | 17 | /// File system interface to the ExtSaveData archive |
| 18 | class Archive_ExtSaveData final : public DiskArchive { | 18 | class ArchiveFactory_ExtSaveData final : public ArchiveFactory { |
| 19 | public: | 19 | public: |
| 20 | Archive_ExtSaveData(const std::string& mount_point, bool shared); | 20 | ArchiveFactory_ExtSaveData(const std::string& mount_point, bool shared); |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * Initialize the archive. | 23 | * Initialize the archive. |
| @@ -25,21 +25,20 @@ public: | |||
| 25 | */ | 25 | */ |
| 26 | bool Initialize(); | 26 | bool Initialize(); |
| 27 | 27 | ||
| 28 | ResultCode Open(const Path& path) override; | ||
| 29 | ResultCode Format(const Path& path) const override; | ||
| 30 | std::string GetName() const override { return "ExtSaveData"; } | 28 | std::string GetName() const override { return "ExtSaveData"; } |
| 31 | 29 | ||
| 32 | const std::string& GetMountPoint() const override { | 30 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 33 | return concrete_mount_point; | 31 | ResultCode Format(const Path& path) override; |
| 34 | } | ||
| 35 | 32 | ||
| 36 | protected: | 33 | const std::string& GetMountPoint() const { return mount_point; } |
| 34 | |||
| 35 | private: | ||
| 37 | /** | 36 | /** |
| 38 | * This holds the full directory path for this archive, it is only set after a successful call to Open, | 37 | * This holds the full directory path for this archive, it is only set after a successful call |
| 39 | * this is formed as <base extsavedatapath>/<type>/<high>/<low>. | 38 | * to Open, this is formed as <base extsavedatapath>/<type>/<high>/<low>. |
| 40 | * See GetExtSaveDataPath for the code that extracts this data from an archive path. | 39 | * See GetExtSaveDataPath for the code that extracts this data from an archive path. |
| 41 | */ | 40 | */ |
| 42 | std::string concrete_mount_point; | 41 | std::string mount_point; |
| 43 | }; | 42 | }; |
| 44 | 43 | ||
| 45 | /** | 44 | /** |
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index a30f73d0e..bf54a3866 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -15,11 +15,24 @@ | |||
| 15 | 15 | ||
| 16 | namespace FileSys { | 16 | namespace FileSys { |
| 17 | 17 | ||
| 18 | Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { | 18 | ArchiveFactory_RomFS::ArchiveFactory_RomFS(const Loader::AppLoader& app_loader) |
| 19 | : romfs_data(std::make_shared<std::vector<u8>>()) { | ||
| 19 | // Load the RomFS from the app | 20 | // Load the RomFS from the app |
| 20 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(raw_data)) { | 21 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(*romfs_data)) { |
| 21 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); | 22 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); |
| 22 | } | 23 | } |
| 23 | } | 24 | } |
| 24 | 25 | ||
| 26 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path& path) { | ||
| 27 | auto archive = Common::make_unique<IVFCArchive>(romfs_data); | ||
| 28 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||
| 29 | } | ||
| 30 | |||
| 31 | ResultCode ArchiveFactory_RomFS::Format(const Path& path) { | ||
| 32 | LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); | ||
| 33 | // TODO: Verify error code | ||
| 34 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | ||
| 35 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 36 | } | ||
| 37 | |||
| 25 | } // namespace FileSys | 38 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 5cb75e04d..409bc670a 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -17,12 +18,16 @@ | |||
| 17 | namespace FileSys { | 18 | namespace FileSys { |
| 18 | 19 | ||
| 19 | /// File system interface to the RomFS archive | 20 | /// File system interface to the RomFS archive |
| 20 | class Archive_RomFS final : public IVFCArchive { | 21 | class ArchiveFactory_RomFS final : public ArchiveFactory { |
| 21 | public: | 22 | public: |
| 22 | Archive_RomFS(const Loader::AppLoader& app_loader); | 23 | ArchiveFactory_RomFS(const Loader::AppLoader& app_loader); |
| 23 | 24 | ||
| 24 | std::string GetName() const override { return "RomFS"; } | 25 | std::string GetName() const override { return "RomFS"; } |
| 25 | ResultCode Open(const Path& path) override { return RESULT_SUCCESS; } | 26 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 27 | ResultCode Format(const Path& path) override; | ||
| 28 | |||
| 29 | private: | ||
| 30 | std::shared_ptr<std::vector<u8>> romfs_data; | ||
| 26 | }; | 31 | }; |
| 27 | 32 | ||
| 28 | } // namespace FileSys | 33 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp index 3baee5294..8496e06f3 100644 --- a/src/core/file_sys/archive_savedata.cpp +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/make_unique.h" | ||
| 9 | 10 | ||
| 10 | #include "core/file_sys/archive_savedata.h" | 11 | #include "core/file_sys/archive_savedata.h" |
| 11 | #include "core/file_sys/disk_archive.h" | 12 | #include "core/file_sys/disk_archive.h" |
| @@ -28,26 +29,28 @@ static std::string GetSaveDataPath(const std::string& mount_location, u64 progra | |||
| 28 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); | 29 | return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | Archive_SaveData::Archive_SaveData(const std::string& sdmc_directory) | 32 | ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) |
| 32 | : DiskArchive(GetSaveDataContainerPath(sdmc_directory)) { | 33 | : mount_point(GetSaveDataContainerPath(sdmc_directory)) { |
| 33 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); | 34 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | ResultCode Archive_SaveData::Open(const Path& path) { | 37 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { |
| 37 | if (concrete_mount_point.empty()) | 38 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); |
| 38 | concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); | ||
| 39 | if (!FileUtil::Exists(concrete_mount_point)) { | 39 | if (!FileUtil::Exists(concrete_mount_point)) { |
| 40 | // When a SaveData archive is created for the first time, it is not yet formatted | 40 | // When a SaveData archive is created for the first time, it is not yet formatted |
| 41 | // and the save file/directory structure expected by the game has not yet been initialized. | 41 | // and the save file/directory structure expected by the game has not yet been initialized. |
| 42 | // Returning the NotFormatted error code will signal the game to provision the SaveData archive | 42 | // Returning the NotFormatted error code will signal the game to provision the SaveData archive |
| 43 | // with the files and folders that it expects. | 43 | // with the files and folders that it expects. |
| 44 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, | 44 | return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, |
| 45 | ErrorSummary::InvalidState, ErrorLevel::Status); | 45 | ErrorSummary::InvalidState, ErrorLevel::Status); |
| 46 | } | 46 | } |
| 47 | return RESULT_SUCCESS; | 47 | |
| 48 | auto archive = Common::make_unique<DiskArchive>(std::move(concrete_mount_point)); | ||
| 49 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | ResultCode Archive_SaveData::Format(const Path& path) const { | 52 | ResultCode ArchiveFactory_SaveData::Format(const Path& path) { |
| 53 | std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_program_id); | ||
| 51 | FileUtil::DeleteDirRecursively(concrete_mount_point); | 54 | FileUtil::DeleteDirRecursively(concrete_mount_point); |
| 52 | FileUtil::CreateFullPath(concrete_mount_point); | 55 | FileUtil::CreateFullPath(concrete_mount_point); |
| 53 | return RESULT_SUCCESS; | 56 | return RESULT_SUCCESS; |
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h index 07c7f7eff..db17afc92 100644 --- a/src/core/file_sys/archive_savedata.h +++ b/src/core/file_sys/archive_savedata.h | |||
| @@ -15,22 +15,17 @@ | |||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | /// File system interface to the SaveData archive | 17 | /// File system interface to the SaveData archive |
| 18 | class Archive_SaveData final : public DiskArchive { | 18 | class ArchiveFactory_SaveData final : public ArchiveFactory { |
| 19 | public: | 19 | public: |
| 20 | Archive_SaveData(const std::string& mount_point); | 20 | ArchiveFactory_SaveData(const std::string& mount_point); |
| 21 | 21 | ||
| 22 | std::string GetName() const override { return "SaveData"; } | 22 | std::string GetName() const override { return "SaveData"; } |
| 23 | 23 | ||
| 24 | ResultCode Open(const Path& path) override; | 24 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; |
| 25 | ResultCode Format(const Path& path) override; | ||
| 25 | 26 | ||
| 26 | ResultCode Format(const Path& path) const override; | 27 | private: |
| 27 | 28 | std::string mount_point; | |
| 28 | const std::string& GetMountPoint() const override { | ||
| 29 | return concrete_mount_point; | ||
| 30 | } | ||
| 31 | |||
| 32 | protected: | ||
| 33 | std::string concrete_mount_point; | ||
| 34 | }; | 29 | }; |
| 35 | 30 | ||
| 36 | } // namespace FileSys | 31 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp index a7a507536..47d8a9d25 100644 --- a/src/core/file_sys/archive_savedatacheck.cpp +++ b/src/core/file_sys/archive_savedatacheck.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/file_util.h" | 5 | #include "common/file_util.h" |
| 6 | #include "common/make_unique.h" | ||
| 6 | 7 | ||
| 7 | #include "core/file_sys/archive_savedatacheck.h" | 8 | #include "core/file_sys/archive_savedatacheck.h" |
| 8 | #include "core/hle/service/fs/archive.h" | 9 | #include "core/hle/service/fs/archive.h" |
| @@ -21,32 +22,33 @@ static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high | |||
| 21 | mount_point.c_str(), high, low); | 22 | mount_point.c_str(), high, low); |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 24 | Archive_SaveDataCheck::Archive_SaveDataCheck(const std::string& nand_directory) : | 25 | ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) : |
| 25 | mount_point(GetSaveDataCheckContainerPath(nand_directory)) { | 26 | mount_point(GetSaveDataCheckContainerPath(nand_directory)) { |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | ResultCode Archive_SaveDataCheck::Open(const Path& path) { | 29 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) { |
| 29 | // TODO(Subv): We should not be overwriting raw_data everytime this function is called, | ||
| 30 | // but until we use factory classes to create the archives at runtime instead of creating them beforehand | ||
| 31 | // and allow multiple archives of the same type to be open at the same time without clobbering each other, | ||
| 32 | // we won't be able to maintain the state of each archive, hence we overwrite it every time it's needed. | ||
| 33 | // There are a number of problems with this, for example opening a file in this archive, then opening | ||
| 34 | // this archive again with a different path, will corrupt the previously open file. | ||
| 35 | auto vec = path.AsBinary(); | 30 | auto vec = path.AsBinary(); |
| 36 | const u32* data = reinterpret_cast<u32*>(vec.data()); | 31 | const u32* data = reinterpret_cast<u32*>(vec.data()); |
| 37 | std::string file_path = GetSaveDataCheckPath(mount_point, data[1], data[0]); | 32 | std::string file_path = GetSaveDataCheckPath(mount_point, data[1], data[0]); |
| 38 | FileUtil::IOFile file(file_path, "rb"); | 33 | FileUtil::IOFile file(file_path, "rb"); |
| 39 | 34 | ||
| 40 | std::fill(raw_data.begin(), raw_data.end(), 0); | ||
| 41 | |||
| 42 | if (!file.IsOpen()) { | 35 | if (!file.IsOpen()) { |
| 43 | return ResultCode(-1); // TODO(Subv): Find the right error code | 36 | return ResultCode(-1); // TODO(Subv): Find the right error code |
| 44 | } | 37 | } |
| 45 | auto size = file.GetSize(); | 38 | auto size = file.GetSize(); |
| 46 | raw_data.resize(size); | 39 | auto raw_data = std::make_shared<std::vector<u8>>(size); |
| 47 | file.ReadBytes(raw_data.data(), size); | 40 | file.ReadBytes(raw_data->data(), size); |
| 48 | file.Close(); | 41 | file.Close(); |
| 49 | return RESULT_SUCCESS; | 42 | |
| 43 | auto archive = Common::make_unique<IVFCArchive>(std::move(raw_data)); | ||
| 44 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||
| 45 | } | ||
| 46 | |||
| 47 | ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path) { | ||
| 48 | LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); | ||
| 49 | // TODO: Verify error code | ||
| 50 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, | ||
| 51 | ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 50 | } | 52 | } |
| 51 | 53 | ||
| 52 | } // namespace FileSys | 54 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h index f6e73e803..f78a6f02e 100644 --- a/src/core/file_sys/archive_savedatacheck.h +++ b/src/core/file_sys/archive_savedatacheck.h | |||
| @@ -17,12 +17,14 @@ | |||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | /// File system interface to the SaveDataCheck archive | 19 | /// File system interface to the SaveDataCheck archive |
| 20 | class Archive_SaveDataCheck final : public IVFCArchive { | 20 | class ArchiveFactory_SaveDataCheck final : public ArchiveFactory { |
| 21 | public: | 21 | public: |
| 22 | Archive_SaveDataCheck(const std::string& mount_point); | 22 | ArchiveFactory_SaveDataCheck(const std::string& mount_point); |
| 23 | 23 | ||
| 24 | std::string GetName() const override { return "SaveDataCheck"; } | 24 | std::string GetName() const override { return "SaveDataCheck"; } |
| 25 | ResultCode Open(const Path& path) override; | 25 | |
| 26 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | ||
| 27 | ResultCode Format(const Path& path) override; | ||
| 26 | 28 | ||
| 27 | private: | 29 | private: |
| 28 | std::string mount_point; | 30 | std::string mount_point; |
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index 26b03e82f..92b20c7f6 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/make_unique.h" | ||
| 9 | 10 | ||
| 10 | #include "core/file_sys/archive_sdmc.h" | 11 | #include "core/file_sys/archive_sdmc.h" |
| 11 | #include "core/file_sys/disk_archive.h" | 12 | #include "core/file_sys/disk_archive.h" |
| @@ -16,17 +17,17 @@ | |||
| 16 | 17 | ||
| 17 | namespace FileSys { | 18 | namespace FileSys { |
| 18 | 19 | ||
| 19 | Archive_SDMC::Archive_SDMC(const std::string& sdmc_directory) : DiskArchive(sdmc_directory) { | 20 | ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) : sdmc_directory(sdmc_directory) { |
| 20 | LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); | 21 | LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | bool Archive_SDMC::Initialize() { | 24 | bool ArchiveFactory_SDMC::Initialize() { |
| 24 | if (!Settings::values.use_virtual_sd) { | 25 | if (!Settings::values.use_virtual_sd) { |
| 25 | LOG_WARNING(Service_FS, "SDMC disabled by config."); | 26 | LOG_WARNING(Service_FS, "SDMC disabled by config."); |
| 26 | return false; | 27 | return false; |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | if (!FileUtil::CreateFullPath(mount_point)) { | 30 | if (!FileUtil::CreateFullPath(sdmc_directory)) { |
| 30 | LOG_ERROR(Service_FS, "Unable to create SDMC path."); | 31 | LOG_ERROR(Service_FS, "Unable to create SDMC path."); |
| 31 | return false; | 32 | return false; |
| 32 | } | 33 | } |
| @@ -34,4 +35,14 @@ bool Archive_SDMC::Initialize() { | |||
| 34 | return true; | 35 | return true; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 38 | ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path) { | ||
| 39 | auto archive = Common::make_unique<DiskArchive>(sdmc_directory); | ||
| 40 | return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); | ||
| 41 | } | ||
| 42 | |||
| 43 | ResultCode ArchiveFactory_SDMC::Format(const Path& path) { | ||
| 44 | // This is kind of an undesirable operation, so let's just ignore it. :) | ||
| 45 | return RESULT_SUCCESS; | ||
| 46 | } | ||
| 47 | |||
| 37 | } // namespace FileSys | 48 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 1b801f217..1becf6c0f 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | /// File system interface to the SDMC archive | 17 | /// File system interface to the SDMC archive |
| 18 | class Archive_SDMC final : public DiskArchive { | 18 | class ArchiveFactory_SDMC final : public ArchiveFactory { |
| 19 | public: | 19 | public: |
| 20 | Archive_SDMC(const std::string& mount_point); | 20 | ArchiveFactory_SDMC(const std::string& mount_point); |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * Initialize the archive. | 23 | * Initialize the archive. |
| @@ -26,6 +26,12 @@ public: | |||
| 26 | bool Initialize(); | 26 | bool Initialize(); |
| 27 | 27 | ||
| 28 | std::string GetName() const override { return "SDMC"; } | 28 | std::string GetName() const override { return "SDMC"; } |
| 29 | |||
| 30 | ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; | ||
| 31 | ResultCode Format(const Path& path) override; | ||
| 32 | |||
| 33 | private: | ||
| 34 | std::string sdmc_directory; | ||
| 29 | }; | 35 | }; |
| 30 | 36 | ||
| 31 | } // namespace FileSys | 37 | } // namespace FileSys |
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index c6e033fcd..f53fd57db 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp | |||
| @@ -18,26 +18,26 @@ namespace FileSys { | |||
| 18 | 18 | ||
| 19 | std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const { | 19 | std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const { |
| 20 | LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); | 20 | LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); |
| 21 | auto file = Common::make_unique<DiskFile>(this, path, mode); | 21 | auto file = Common::make_unique<DiskFile>(*this, path, mode); |
| 22 | if (!file->Open()) | 22 | if (!file->Open()) |
| 23 | return nullptr; | 23 | return nullptr; |
| 24 | return std::move(file); | 24 | return std::move(file); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | bool DiskArchive::DeleteFile(const Path& path) const { | 27 | bool DiskArchive::DeleteFile(const Path& path) const { |
| 28 | return FileUtil::Delete(GetMountPoint() + path.AsString()); | 28 | return FileUtil::Delete(mount_point + path.AsString()); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { | 31 | bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { |
| 32 | return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); | 32 | return FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString()); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | bool DiskArchive::DeleteDirectory(const Path& path) const { | 35 | bool DiskArchive::DeleteDirectory(const Path& path) const { |
| 36 | return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); | 36 | return FileUtil::DeleteDir(mount_point + path.AsString()); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const { | 39 | ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const { |
| 40 | std::string full_path = GetMountPoint() + path.AsString(); | 40 | std::string full_path = mount_point + path.AsString(); |
| 41 | 41 | ||
| 42 | if (FileUtil::Exists(full_path)) | 42 | if (FileUtil::Exists(full_path)) |
| 43 | return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info); | 43 | return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info); |
| @@ -58,16 +58,16 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const { | |||
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | bool DiskArchive::CreateDirectory(const Path& path) const { | 60 | bool DiskArchive::CreateDirectory(const Path& path) const { |
| 61 | return FileUtil::CreateDir(GetMountPoint() + path.AsString()); | 61 | return FileUtil::CreateDir(mount_point + path.AsString()); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { | 64 | bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { |
| 65 | return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); | 65 | return FileUtil::Rename(mount_point + src_path.AsString(), mount_point + dest_path.AsString()); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const { | 68 | std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const { |
| 69 | LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); | 69 | LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); |
| 70 | auto directory = Common::make_unique<DiskDirectory>(this, path); | 70 | auto directory = Common::make_unique<DiskDirectory>(*this, path); |
| 71 | if (!directory->Open()) | 71 | if (!directory->Open()) |
| 72 | return nullptr; | 72 | return nullptr; |
| 73 | return std::move(directory); | 73 | return std::move(directory); |
| @@ -75,13 +75,12 @@ std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) c | |||
| 75 | 75 | ||
| 76 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 76 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 77 | 77 | ||
| 78 | DiskFile::DiskFile(const DiskArchive* archive, const Path& path, const Mode mode) { | 78 | DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode) { |
| 79 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | 79 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass |
| 80 | // the root directory we set while opening the archive. | 80 | // the root directory we set while opening the archive. |
| 81 | // For example, opening /../../etc/passwd can give the emulated program your users list. | 81 | // For example, opening /../../etc/passwd can give the emulated program your users list. |
| 82 | this->path = archive->GetMountPoint() + path.AsString(); | 82 | this->path = archive.mount_point + path.AsString(); |
| 83 | this->mode.hex = mode.hex; | 83 | this->mode.hex = mode.hex; |
| 84 | this->archive = archive; | ||
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | bool DiskFile::Open() { | 86 | bool DiskFile::Open() { |
| @@ -134,12 +133,11 @@ bool DiskFile::Close() const { | |||
| 134 | 133 | ||
| 135 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 134 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 136 | 135 | ||
| 137 | DiskDirectory::DiskDirectory(const DiskArchive* archive, const Path& path) { | 136 | DiskDirectory::DiskDirectory(const DiskArchive& archive, const Path& path) { |
| 138 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | 137 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass |
| 139 | // the root directory we set while opening the archive. | 138 | // the root directory we set while opening the archive. |
| 140 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | 139 | // For example, opening /../../usr/bin can give the emulated program your installed programs. |
| 141 | this->path = archive->GetMountPoint() + path.AsString(); | 140 | this->path = archive.mount_point + path.AsString(); |
| 142 | this->archive = archive; | ||
| 143 | } | 141 | } |
| 144 | 142 | ||
| 145 | bool DiskDirectory::Open() { | 143 | bool DiskDirectory::Open() { |
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h index 3472f6874..dbbdced74 100644 --- a/src/core/file_sys/disk_archive.h +++ b/src/core/file_sys/disk_archive.h | |||
| @@ -24,8 +24,8 @@ class DiskArchive : public ArchiveBackend { | |||
| 24 | public: | 24 | public: |
| 25 | DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} | 25 | DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} |
| 26 | 26 | ||
| 27 | virtual std::string GetName() const = 0; | 27 | virtual std::string GetName() const { return "DiskArchive: " + mount_point; } |
| 28 | virtual ResultCode Format(const Path& path) const { return RESULT_SUCCESS; } | 28 | |
| 29 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | 29 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
| 30 | bool DeleteFile(const Path& path) const override; | 30 | bool DeleteFile(const Path& path) const override; |
| 31 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; | 31 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; |
| @@ -35,26 +35,17 @@ public: | |||
| 35 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; | 35 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; |
| 36 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | 36 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
| 37 | 37 | ||
| 38 | virtual ResultCode Open(const Path& path) override { | ||
| 39 | return RESULT_SUCCESS; | ||
| 40 | } | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Getter for the path used for this Archive | ||
| 44 | * @return Mount point of that passthrough archive | ||
| 45 | */ | ||
| 46 | virtual const std::string& GetMountPoint() const { | ||
| 47 | return mount_point; | ||
| 48 | } | ||
| 49 | |||
| 50 | protected: | 38 | protected: |
| 39 | friend class DiskFile; | ||
| 40 | friend class DiskDirectory; | ||
| 41 | |||
| 51 | std::string mount_point; | 42 | std::string mount_point; |
| 52 | }; | 43 | }; |
| 53 | 44 | ||
| 54 | class DiskFile : public FileBackend { | 45 | class DiskFile : public FileBackend { |
| 55 | public: | 46 | public: |
| 56 | DiskFile(); | 47 | DiskFile(); |
| 57 | DiskFile(const DiskArchive* archive, const Path& path, const Mode mode); | 48 | DiskFile(const DiskArchive& archive, const Path& path, const Mode mode); |
| 58 | 49 | ||
| 59 | bool Open() override; | 50 | bool Open() override; |
| 60 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | 51 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; |
| @@ -68,7 +59,6 @@ public: | |||
| 68 | } | 59 | } |
| 69 | 60 | ||
| 70 | protected: | 61 | protected: |
| 71 | const DiskArchive* archive; | ||
| 72 | std::string path; | 62 | std::string path; |
| 73 | Mode mode; | 63 | Mode mode; |
| 74 | std::unique_ptr<FileUtil::IOFile> file; | 64 | std::unique_ptr<FileUtil::IOFile> file; |
| @@ -77,7 +67,7 @@ protected: | |||
| 77 | class DiskDirectory : public DirectoryBackend { | 67 | class DiskDirectory : public DirectoryBackend { |
| 78 | public: | 68 | public: |
| 79 | DiskDirectory(); | 69 | DiskDirectory(); |
| 80 | DiskDirectory(const DiskArchive* archive, const Path& path); | 70 | DiskDirectory(const DiskArchive& archive, const Path& path); |
| 81 | 71 | ||
| 82 | ~DiskDirectory() override { | 72 | ~DiskDirectory() override { |
| 83 | Close(); | 73 | Close(); |
| @@ -91,7 +81,6 @@ public: | |||
| 91 | } | 81 | } |
| 92 | 82 | ||
| 93 | protected: | 83 | protected: |
| 94 | const DiskArchive* archive; | ||
| 95 | std::string path; | 84 | std::string path; |
| 96 | u32 total_entries_in_directory; | 85 | u32 total_entries_in_directory; |
| 97 | FileUtil::FSTEntry directory; | 86 | FileUtil::FSTEntry directory; |
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index 68c3c8b81..35aca54fa 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp | |||
| @@ -15,11 +15,15 @@ | |||
| 15 | 15 | ||
| 16 | namespace FileSys { | 16 | namespace FileSys { |
| 17 | 17 | ||
| 18 | IVFCArchive::IVFCArchive() { | 18 | IVFCArchive::IVFCArchive(std::shared_ptr<const std::vector<u8>> data) : data(data) { |
| 19 | } | ||
| 20 | |||
| 21 | std::string IVFCArchive::GetName() const { | ||
| 22 | return "IVFC"; | ||
| 19 | } | 23 | } |
| 20 | 24 | ||
| 21 | std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { | 25 | std::unique_ptr<FileBackend> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { |
| 22 | return Common::make_unique<IVFCFile>(this); | 26 | return Common::make_unique<IVFCFile>(data); |
| 23 | } | 27 | } |
| 24 | 28 | ||
| 25 | bool IVFCArchive::DeleteFile(const Path& path) const { | 29 | bool IVFCArchive::DeleteFile(const Path& path) const { |
| @@ -57,31 +61,25 @@ std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) c | |||
| 57 | return Common::make_unique<IVFCDirectory>(); | 61 | return Common::make_unique<IVFCDirectory>(); |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | ResultCode IVFCArchive::Format(const Path& path) const { | ||
| 61 | LOG_CRITICAL(Service_FS, "Attempted to format an IVFC archive (%s).", GetName().c_str()); | ||
| 62 | // TODO: Verify error code | ||
| 63 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); | ||
| 64 | } | ||
| 65 | |||
| 66 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 64 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 67 | 65 | ||
| 68 | size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { | 66 | size_t IVFCFile::Read(const u64 offset, const u32 length, u8* buffer) const { |
| 69 | LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); | 67 | LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |
| 70 | memcpy(buffer, &archive->raw_data[(u32)offset], length); | 68 | memcpy(buffer, data->data() + offset, length); |
| 71 | return length; | 69 | return length; |
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | 72 | size_t IVFCFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
| 75 | LOG_CRITICAL(Service_FS, "Attempted to write to IVFC file in archive %s.", archive->GetName().c_str()); | 73 | LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); |
| 76 | return 0; | 74 | return 0; |
| 77 | } | 75 | } |
| 78 | 76 | ||
| 79 | size_t IVFCFile::GetSize() const { | 77 | size_t IVFCFile::GetSize() const { |
| 80 | return sizeof(u8) * archive->raw_data.size(); | 78 | return sizeof(u8) * data->size(); |
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | bool IVFCFile::SetSize(const u64 size) const { | 81 | bool IVFCFile::SetSize(const u64 size) const { |
| 84 | LOG_CRITICAL(Service_FS, "Attempted to set the size of an IVFC file in archive %s", archive->GetName().c_str()); | 82 | LOG_ERROR(Service_FS, "Attempted to set the size of an IVFC file"); |
| 85 | return false; | 83 | return false; |
| 86 | } | 84 | } |
| 87 | 85 | ||
diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h index 6f4cc86df..1aff9e0a4 100644 --- a/src/core/file_sys/ivfc_archive.h +++ b/src/core/file_sys/ivfc_archive.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 7 | #include <vector> | 8 | #include <vector> |
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| @@ -23,7 +24,9 @@ namespace FileSys { | |||
| 23 | */ | 24 | */ |
| 24 | class IVFCArchive : public ArchiveBackend { | 25 | class IVFCArchive : public ArchiveBackend { |
| 25 | public: | 26 | public: |
| 26 | IVFCArchive(); | 27 | IVFCArchive(std::shared_ptr<const std::vector<u8>> data); |
| 28 | |||
| 29 | std::string GetName() const override; | ||
| 27 | 30 | ||
| 28 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | 31 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
| 29 | bool DeleteFile(const Path& path) const override; | 32 | bool DeleteFile(const Path& path) const override; |
| @@ -33,16 +36,14 @@ public: | |||
| 33 | bool CreateDirectory(const Path& path) const override; | 36 | bool CreateDirectory(const Path& path) const override; |
| 34 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; | 37 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; |
| 35 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | 38 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
| 36 | ResultCode Format(const Path& path) const override; | ||
| 37 | 39 | ||
| 38 | protected: | 40 | protected: |
| 39 | friend class IVFCFile; | 41 | std::shared_ptr<const std::vector<u8>> data; |
| 40 | std::vector<u8> raw_data; | ||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | class IVFCFile : public FileBackend { | 44 | class IVFCFile : public FileBackend { |
| 44 | public: | 45 | public: |
| 45 | IVFCFile(const IVFCArchive* archive) : archive(archive) {} | 46 | IVFCFile(std::shared_ptr<const std::vector<u8>> data) : data(data) {} |
| 46 | 47 | ||
| 47 | bool Open() override { return true; } | 48 | bool Open() override { return true; } |
| 48 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | 49 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; |
| @@ -53,7 +54,7 @@ public: | |||
| 53 | void Flush() const override { } | 54 | void Flush() const override { } |
| 54 | 55 | ||
| 55 | private: | 56 | private: |
| 56 | const IVFCArchive* archive; | 57 | std::shared_ptr<const std::vector<u8>> data; |
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 59 | class IVFCDirectory : public DirectoryBackend { | 60 | class IVFCDirectory : public DirectoryBackend { |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 6030e05e0..6c6a59e47 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <unordered_map> | 6 | #include <unordered_map> |
| 7 | 7 | ||
| 8 | #include <boost/container/flat_map.hpp> | ||
| 9 | |||
| 8 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 9 | #include "common/file_util.h" | 11 | #include "common/file_util.h" |
| 10 | #include "common/make_unique.h" | 12 | #include "common/make_unique.h" |
| @@ -233,22 +235,23 @@ public: | |||
| 233 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 235 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 234 | 236 | ||
| 235 | using FileSys::ArchiveBackend; | 237 | using FileSys::ArchiveBackend; |
| 238 | using FileSys::ArchiveFactory; | ||
| 236 | 239 | ||
| 237 | /** | 240 | /** |
| 238 | * Map of registered archives, identified by id code. Once an archive is registered here, it is | 241 | * Map of registered archives, identified by id code. Once an archive is registered here, it is |
| 239 | * never removed until the FS service is shut down. | 242 | * never removed until the FS service is shut down. |
| 240 | */ | 243 | */ |
| 241 | static std::unordered_map<ArchiveIdCode, std::unique_ptr<ArchiveBackend>> id_code_map; | 244 | static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map; |
| 242 | 245 | ||
| 243 | /** | 246 | /** |
| 244 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. | 247 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. |
| 245 | */ | 248 | */ |
| 246 | static std::unordered_map<ArchiveHandle, ArchiveBackend*> handle_map; | 249 | static std::unordered_map<ArchiveHandle, std::unique_ptr<ArchiveBackend>> handle_map; |
| 247 | static ArchiveHandle next_handle; | 250 | static ArchiveHandle next_handle; |
| 248 | 251 | ||
| 249 | static ArchiveBackend* GetArchive(ArchiveHandle handle) { | 252 | static ArchiveBackend* GetArchive(ArchiveHandle handle) { |
| 250 | auto itr = handle_map.find(handle); | 253 | auto itr = handle_map.find(handle); |
| 251 | return (itr == handle_map.end()) ? nullptr : itr->second; | 254 | return (itr == handle_map.end()) ? nullptr : itr->second.get(); |
| 252 | } | 255 | } |
| 253 | 256 | ||
| 254 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { | 257 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { |
| @@ -261,15 +264,13 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 261 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 264 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 262 | } | 265 | } |
| 263 | 266 | ||
| 264 | ResultCode res = itr->second->Open(archive_path); | 267 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); |
| 265 | if (!res.IsSuccess()) | ||
| 266 | return res; | ||
| 267 | 268 | ||
| 268 | // This should never even happen in the first place with 64-bit handles, | 269 | // This should never even happen in the first place with 64-bit handles, |
| 269 | while (handle_map.count(next_handle) != 0) { | 270 | while (handle_map.count(next_handle) != 0) { |
| 270 | ++next_handle; | 271 | ++next_handle; |
| 271 | } | 272 | } |
| 272 | handle_map.emplace(next_handle, itr->second.get()); | 273 | handle_map.emplace(next_handle, std::move(res)); |
| 273 | return MakeResult<ArchiveHandle>(next_handle++); | 274 | return MakeResult<ArchiveHandle>(next_handle++); |
| 274 | } | 275 | } |
| 275 | 276 | ||
| @@ -282,11 +283,11 @@ ResultCode CloseArchive(ArchiveHandle handle) { | |||
| 282 | 283 | ||
| 283 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in | 284 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in |
| 284 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 | 285 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 |
| 285 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { | 286 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { |
| 286 | auto result = id_code_map.emplace(id_code, std::move(backend)); | 287 | auto result = id_code_map.emplace(id_code, std::move(factory)); |
| 287 | 288 | ||
| 288 | bool inserted = result.second; | 289 | bool inserted = result.second; |
| 289 | _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); | 290 | _assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); |
| 290 | 291 | ||
| 291 | auto& archive = result.first->second; | 292 | auto& archive = result.first->second; |
| 292 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); | 293 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); |
| @@ -450,32 +451,32 @@ void ArchiveInit() { | |||
| 450 | 451 | ||
| 451 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 452 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 452 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | 453 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); |
| 453 | auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory); | 454 | auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory); |
| 454 | if (sdmc_archive->Initialize()) | 455 | if (sdmc_factory->Initialize()) |
| 455 | CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); | 456 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); |
| 456 | else | 457 | else |
| 457 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 458 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 458 | 459 | ||
| 459 | // Create the SaveData archive | 460 | // Create the SaveData archive |
| 460 | auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(sdmc_directory); | 461 | auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); |
| 461 | CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); | 462 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); |
| 462 | 463 | ||
| 463 | auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sdmc_directory, false); | 464 | auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); |
| 464 | if (extsavedata_archive->Initialize()) | 465 | if (extsavedata_factory->Initialize()) |
| 465 | CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); | 466 | RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); |
| 466 | else | 467 | else |
| 467 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_archive->GetMountPoint().c_str()); | 468 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); |
| 468 | 469 | ||
| 469 | auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); | 470 | auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); |
| 470 | if (sharedextsavedata_archive->Initialize()) | 471 | if (sharedextsavedata_factory->Initialize()) |
| 471 | CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); | 472 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); |
| 472 | else | 473 | else |
| 473 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", | 474 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", |
| 474 | sharedextsavedata_archive->GetMountPoint().c_str()); | 475 | sharedextsavedata_factory->GetMountPoint().c_str()); |
| 475 | 476 | ||
| 476 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | 477 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive |
| 477 | auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(nand_directory); | 478 | auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); |
| 478 | CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); | 479 | RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); |
| 479 | } | 480 | } |
| 480 | 481 | ||
| 481 | /// Shutdown archives | 482 | /// Shutdown archives |
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index ab5ea4da8..3d9b8a761 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -51,11 +51,11 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 51 | ResultCode CloseArchive(ArchiveHandle handle); | 51 | ResultCode CloseArchive(ArchiveHandle handle); |
| 52 | 52 | ||
| 53 | /** | 53 | /** |
| 54 | * Creates an Archive | 54 | * Registers an Archive type, instances of which can later be opened using its IdCode. |
| 55 | * @param backend File system backend interface to the archive | 55 | * @param backend File system backend interface to the archive |
| 56 | * @param id_code Id code used to access this type of archive | 56 | * @param id_code Id code used to access this type of archive |
| 57 | */ | 57 | */ |
| 58 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); | 58 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); |
| 59 | 59 | ||
| 60 | /** | 60 | /** |
| 61 | * Open a File from an Archive | 61 | * Open a File from an Archive |
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 7b465a348..561849f32 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/log.h" | 5 | #include "common/log.h" |
| 6 | #include "common/make_unique.h" | 6 | #include "common/make_unique.h" |
| 7 | #include "core/file_sys/archive_extsavedata.h" | 7 | |
| 8 | #include "core/hle/hle.h" | 8 | #include "core/hle/hle.h" |
| 9 | #include "core/hle/service/fs/archive.h" | ||
| 9 | #include "core/hle/service/ptm_u.h" | 10 | #include "core/hle/service/ptm_u.h" |
| 10 | 11 | ||
| 11 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -28,7 +29,6 @@ struct GameCoin { | |||
| 28 | u8 day; | 29 | u8 day; |
| 29 | }; | 30 | }; |
| 30 | static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; | 31 | static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; |
| 31 | static std::unique_ptr<FileSys::Archive_ExtSaveData> ptm_shared_extsavedata; | ||
| 32 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; | 32 | static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; |
| 33 | 33 | ||
| 34 | /// Charge levels used by PTM functions | 34 | /// Charge levels used by PTM functions |
| @@ -138,6 +138,10 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 138 | 138 | ||
| 139 | Interface::Interface() { | 139 | Interface::Interface() { |
| 140 | Register(FunctionTable); | 140 | Register(FunctionTable); |
| 141 | |||
| 142 | // TODO(Subv): This code needs to be updated to not directly create archives and use the | ||
| 143 | // standard archive.h interfaces. | ||
| 144 | #if 0 | ||
| 141 | // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file | 145 | // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file |
| 142 | // TODO(Subv): In the future we should use the FS service to query this archive | 146 | // TODO(Subv): In the future we should use the FS service to query this archive |
| 143 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | 147 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); |
| @@ -165,6 +169,7 @@ Interface::Interface() { | |||
| 165 | gamecoin->Close(); | 169 | gamecoin->Close(); |
| 166 | } | 170 | } |
| 167 | } | 171 | } |
| 172 | #endif | ||
| 168 | } | 173 | } |
| 169 | 174 | ||
| 170 | } // namespace | 175 | } // namespace |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 52730a7b4..94dcc50f9 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -127,7 +127,7 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 127 | // Load application and RomFS | 127 | // Load application and RomFS |
| 128 | if (ResultStatus::Success == app_loader.Load()) { | 128 | if (ResultStatus::Success == app_loader.Load()) { |
| 129 | Kernel::g_program_id = app_loader.GetProgramId(); | 129 | Kernel::g_program_id = app_loader.GetProgramId(); |
| 130 | Service::FS::CreateArchive(Common::make_unique<FileSys::Archive_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); | 130 | Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS); |
| 131 | return ResultStatus::Success; | 131 | return ResultStatus::Success; |
| 132 | } | 132 | } |
| 133 | break; | 133 | break; |