diff options
Diffstat (limited to 'src')
| -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/result.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 191 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.h | 45 | ||||
| -rw-r--r-- | src/core/hle/service/fs/fs_user.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/ptm_u.cpp | 35 | ||||
| -rw-r--r-- | src/core/loader/loader.cpp | 2 |
21 files changed, 304 insertions, 277 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/result.h b/src/core/hle/result.h index 948b9e38e..9c6ca29e5 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -307,14 +307,14 @@ public: | |||
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | ResultVal& operator=(const ResultVal& o) { | 309 | ResultVal& operator=(const ResultVal& o) { |
| 310 | if (*this) { | 310 | if (!empty()) { |
| 311 | if (o) { | 311 | if (!o.empty()) { |
| 312 | *GetPointer() = *o.GetPointer(); | 312 | *GetPointer() = *o.GetPointer(); |
| 313 | } else { | 313 | } else { |
| 314 | GetPointer()->~T(); | 314 | GetPointer()->~T(); |
| 315 | } | 315 | } |
| 316 | } else { | 316 | } else { |
| 317 | if (o) { | 317 | if (!o.empty()) { |
| 318 | new (&storage) T(*o.GetPointer()); | 318 | new (&storage) T(*o.GetPointer()); |
| 319 | } | 319 | } |
| 320 | } | 320 | } |
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index ccf132f31..e197d3599 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" |
| @@ -18,7 +20,6 @@ | |||
| 18 | #include "core/file_sys/archive_sdmc.h" | 20 | #include "core/file_sys/archive_sdmc.h" |
| 19 | #include "core/file_sys/directory_backend.h" | 21 | #include "core/file_sys/directory_backend.h" |
| 20 | #include "core/hle/service/fs/archive.h" | 22 | #include "core/hle/service/fs/archive.h" |
| 21 | #include "core/hle/kernel/session.h" | ||
| 22 | #include "core/hle/result.h" | 23 | #include "core/hle/result.h" |
| 23 | 24 | ||
| 24 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. | 25 | // Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. |
| @@ -74,43 +75,19 @@ enum class DirectoryCommand : u32 { | |||
| 74 | Close = 0x08020000, | 75 | Close = 0x08020000, |
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | class Archive { | 78 | ResultVal<bool> File::SyncRequest() { |
| 78 | public: | 79 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 79 | Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) | 80 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 80 | : id_code(id_code), backend(std::move(backend)) { | 81 | switch (cmd) { |
| 81 | } | ||
| 82 | |||
| 83 | std::string GetName() const { return "Archive: " + backend->GetName(); } | ||
| 84 | |||
| 85 | ArchiveIdCode id_code; ///< Id code of the archive | ||
| 86 | std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface | ||
| 87 | }; | ||
| 88 | |||
| 89 | class File : public Kernel::Session { | ||
| 90 | public: | ||
| 91 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||
| 92 | : path(path), priority(0), backend(std::move(backend)) { | ||
| 93 | } | ||
| 94 | |||
| 95 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||
| 96 | |||
| 97 | FileSys::Path path; ///< Path of the file | ||
| 98 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | ||
| 99 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | ||
| 100 | |||
| 101 | ResultVal<bool> SyncRequest() override { | ||
| 102 | u32* cmd_buff = Kernel::GetCommandBuffer(); | ||
| 103 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | ||
| 104 | switch (cmd) { | ||
| 105 | 82 | ||
| 106 | // Read from file... | 83 | // Read from file... |
| 107 | case FileCommand::Read: | 84 | case FileCommand::Read: |
| 108 | { | 85 | { |
| 109 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | 86 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 110 | u32 length = cmd_buff[3]; | 87 | u32 length = cmd_buff[3]; |
| 111 | u32 address = cmd_buff[5]; | 88 | u32 address = cmd_buff[5]; |
| 112 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", | 89 | LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", |
| 113 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); | 90 | GetTypeName().c_str(), GetName().c_str(), offset, length, address); |
| 114 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); | 91 | cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address)); |
| 115 | break; | 92 | break; |
| 116 | } | 93 | } |
| @@ -118,12 +95,12 @@ public: | |||
| 118 | // Write to file... | 95 | // Write to file... |
| 119 | case FileCommand::Write: | 96 | case FileCommand::Write: |
| 120 | { | 97 | { |
| 121 | u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32; | 98 | u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; |
| 122 | u32 length = cmd_buff[3]; | 99 | u32 length = cmd_buff[3]; |
| 123 | u32 flush = cmd_buff[4]; | 100 | u32 flush = cmd_buff[4]; |
| 124 | u32 address = cmd_buff[6]; | 101 | u32 address = cmd_buff[6]; |
| 125 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", | 102 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", |
| 126 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | 103 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); |
| 127 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); | 104 | cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address)); |
| 128 | break; | 105 | break; |
| 129 | } | 106 | } |
| @@ -141,7 +118,7 @@ public: | |||
| 141 | { | 118 | { |
| 142 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 119 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 143 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", | 120 | LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", |
| 144 | GetTypeName().c_str(), GetName().c_str(), size); | 121 | GetTypeName().c_str(), GetName().c_str(), size); |
| 145 | backend->SetSize(size); | 122 | backend->SetSize(size); |
| 146 | break; | 123 | break; |
| 147 | } | 124 | } |
| @@ -187,27 +164,15 @@ public: | |||
| 187 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 164 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 188 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 165 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 189 | return error; | 166 | return error; |
| 190 | } | ||
| 191 | cmd_buff[1] = 0; // No error | ||
| 192 | return MakeResult<bool>(false); | ||
| 193 | } | 167 | } |
| 194 | }; | 168 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 195 | 169 | return MakeResult<bool>(false); | |
| 196 | class Directory : public Kernel::Session { | 170 | } |
| 197 | public: | ||
| 198 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||
| 199 | : path(path), backend(std::move(backend)) { | ||
| 200 | } | ||
| 201 | |||
| 202 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||
| 203 | |||
| 204 | FileSys::Path path; ///< Path of the directory | ||
| 205 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | ||
| 206 | 171 | ||
| 207 | ResultVal<bool> SyncRequest() override { | 172 | ResultVal<bool> Directory::SyncRequest() { |
| 208 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 173 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 209 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 174 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 210 | switch (cmd) { | 175 | switch (cmd) { |
| 211 | 176 | ||
| 212 | // Read from directory... | 177 | // Read from directory... |
| 213 | case DirectoryCommand::Read: | 178 | case DirectoryCommand::Read: |
| @@ -216,7 +181,7 @@ public: | |||
| 216 | u32 address = cmd_buff[3]; | 181 | u32 address = cmd_buff[3]; |
| 217 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 182 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); |
| 218 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", | 183 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", |
| 219 | GetTypeName().c_str(), GetName().c_str(), count); | 184 | GetTypeName().c_str(), GetName().c_str(), count); |
| 220 | 185 | ||
| 221 | // Number of entries actually read | 186 | // Number of entries actually read |
| 222 | cmd_buff[2] = backend->Read(count, entries); | 187 | cmd_buff[2] = backend->Read(count, entries); |
| @@ -236,29 +201,31 @@ public: | |||
| 236 | ResultCode error = UnimplementedFunction(ErrorModule::FS); | 201 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 237 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. | 202 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 238 | return MakeResult<bool>(false); | 203 | return MakeResult<bool>(false); |
| 239 | } | ||
| 240 | cmd_buff[1] = 0; // No error | ||
| 241 | return MakeResult<bool>(false); | ||
| 242 | } | 204 | } |
| 243 | }; | 205 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 206 | return MakeResult<bool>(false); | ||
| 207 | } | ||
| 244 | 208 | ||
| 245 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 209 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 246 | 210 | ||
| 211 | using FileSys::ArchiveBackend; | ||
| 212 | using FileSys::ArchiveFactory; | ||
| 213 | |||
| 247 | /** | 214 | /** |
| 248 | * Map of registered archives, identified by id code. Once an archive is registered here, it is | 215 | * Map of registered archives, identified by id code. Once an archive is registered here, it is |
| 249 | * never removed until the FS service is shut down. | 216 | * never removed until the FS service is shut down. |
| 250 | */ | 217 | */ |
| 251 | static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map; | 218 | static boost::container::flat_map<ArchiveIdCode, std::unique_ptr<ArchiveFactory>> id_code_map; |
| 252 | 219 | ||
| 253 | /** | 220 | /** |
| 254 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. | 221 | * Map of active archive handles. Values are pointers to the archives in `idcode_map`. |
| 255 | */ | 222 | */ |
| 256 | static std::unordered_map<ArchiveHandle, Archive*> handle_map; | 223 | static std::unordered_map<ArchiveHandle, std::unique_ptr<ArchiveBackend>> handle_map; |
| 257 | static ArchiveHandle next_handle; | 224 | static ArchiveHandle next_handle; |
| 258 | 225 | ||
| 259 | static Archive* GetArchive(ArchiveHandle handle) { | 226 | static ArchiveBackend* GetArchive(ArchiveHandle handle) { |
| 260 | auto itr = handle_map.find(handle); | 227 | auto itr = handle_map.find(handle); |
| 261 | return (itr == handle_map.end()) ? nullptr : itr->second; | 228 | return (itr == handle_map.end()) ? nullptr : itr->second.get(); |
| 262 | } | 229 | } |
| 263 | 230 | ||
| 264 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { | 231 | ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archive_path) { |
| @@ -271,15 +238,13 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 271 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 238 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 272 | } | 239 | } |
| 273 | 240 | ||
| 274 | ResultCode res = itr->second->backend->Open(archive_path); | 241 | CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); |
| 275 | if (!res.IsSuccess()) | ||
| 276 | return res; | ||
| 277 | 242 | ||
| 278 | // This should never even happen in the first place with 64-bit handles, | 243 | // This should never even happen in the first place with 64-bit handles, |
| 279 | while (handle_map.count(next_handle) != 0) { | 244 | while (handle_map.count(next_handle) != 0) { |
| 280 | ++next_handle; | 245 | ++next_handle; |
| 281 | } | 246 | } |
| 282 | handle_map.emplace(next_handle, itr->second.get()); | 247 | handle_map.emplace(next_handle, std::move(res)); |
| 283 | return MakeResult<ArchiveHandle>(next_handle++); | 248 | return MakeResult<ArchiveHandle>(next_handle++); |
| 284 | } | 249 | } |
| 285 | 250 | ||
| @@ -292,39 +257,39 @@ ResultCode CloseArchive(ArchiveHandle handle) { | |||
| 292 | 257 | ||
| 293 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in | 258 | // TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in |
| 294 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 | 259 | // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 |
| 295 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { | 260 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { |
| 296 | auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code)); | 261 | auto result = id_code_map.emplace(id_code, std::move(factory)); |
| 297 | 262 | ||
| 298 | bool inserted = result.second; | 263 | bool inserted = result.second; |
| 299 | _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); | 264 | _assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); |
| 300 | 265 | ||
| 301 | auto& archive = result.first->second; | 266 | auto& archive = result.first->second; |
| 302 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); | 267 | LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); |
| 303 | return RESULT_SUCCESS; | 268 | return RESULT_SUCCESS; |
| 304 | } | 269 | } |
| 305 | 270 | ||
| 306 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, | 271 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 307 | const FileSys::Path& path, const FileSys::Mode mode) { | 272 | const FileSys::Path& path, const FileSys::Mode mode) { |
| 308 | Archive* archive = GetArchive(archive_handle); | 273 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 309 | if (archive == nullptr) | 274 | if (archive == nullptr) |
| 310 | return ERR_INVALID_HANDLE; | 275 | return ERR_INVALID_HANDLE; |
| 311 | 276 | ||
| 312 | std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); | 277 | std::unique_ptr<FileSys::FileBackend> backend = archive->OpenFile(path, mode); |
| 313 | if (backend == nullptr) { | 278 | if (backend == nullptr) { |
| 314 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, | 279 | return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, |
| 315 | ErrorSummary::NotFound, ErrorLevel::Status); | 280 | ErrorSummary::NotFound, ErrorLevel::Status); |
| 316 | } | 281 | } |
| 317 | 282 | ||
| 318 | auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); | 283 | auto file = Kernel::SharedPtr<File>(new File(std::move(backend), path)); |
| 319 | return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(file)); | 284 | return MakeResult<Kernel::SharedPtr<File>>(std::move(file)); |
| 320 | } | 285 | } |
| 321 | 286 | ||
| 322 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 287 | ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 323 | Archive* archive = GetArchive(archive_handle); | 288 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 324 | if (archive == nullptr) | 289 | if (archive == nullptr) |
| 325 | return ERR_INVALID_HANDLE; | 290 | return ERR_INVALID_HANDLE; |
| 326 | 291 | ||
| 327 | if (archive->backend->DeleteFile(path)) | 292 | if (archive->DeleteFile(path)) |
| 328 | return RESULT_SUCCESS; | 293 | return RESULT_SUCCESS; |
| 329 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 294 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 330 | ErrorSummary::Canceled, ErrorLevel::Status); | 295 | ErrorSummary::Canceled, ErrorLevel::Status); |
| @@ -332,13 +297,13 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa | |||
| 332 | 297 | ||
| 333 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 298 | ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 334 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 299 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 335 | Archive* src_archive = GetArchive(src_archive_handle); | 300 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 336 | Archive* dest_archive = GetArchive(dest_archive_handle); | 301 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 337 | if (src_archive == nullptr || dest_archive == nullptr) | 302 | if (src_archive == nullptr || dest_archive == nullptr) |
| 338 | return ERR_INVALID_HANDLE; | 303 | return ERR_INVALID_HANDLE; |
| 339 | 304 | ||
| 340 | if (src_archive == dest_archive) { | 305 | if (src_archive == dest_archive) { |
| 341 | if (src_archive->backend->RenameFile(src_path, dest_path)) | 306 | if (src_archive->RenameFile(src_path, dest_path)) |
| 342 | return RESULT_SUCCESS; | 307 | return RESULT_SUCCESS; |
| 343 | } else { | 308 | } else { |
| 344 | // TODO: Implement renaming across archives | 309 | // TODO: Implement renaming across archives |
| @@ -352,30 +317,30 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil | |||
| 352 | } | 317 | } |
| 353 | 318 | ||
| 354 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 319 | ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 355 | Archive* archive = GetArchive(archive_handle); | 320 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 356 | if (archive == nullptr) | 321 | if (archive == nullptr) |
| 357 | return ERR_INVALID_HANDLE; | 322 | return ERR_INVALID_HANDLE; |
| 358 | 323 | ||
| 359 | if (archive->backend->DeleteDirectory(path)) | 324 | if (archive->DeleteDirectory(path)) |
| 360 | return RESULT_SUCCESS; | 325 | return RESULT_SUCCESS; |
| 361 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 326 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 362 | ErrorSummary::Canceled, ErrorLevel::Status); | 327 | ErrorSummary::Canceled, ErrorLevel::Status); |
| 363 | } | 328 | } |
| 364 | 329 | ||
| 365 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { | 330 | ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { |
| 366 | Archive* archive = GetArchive(archive_handle); | 331 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 367 | if (archive == nullptr) | 332 | if (archive == nullptr) |
| 368 | return ERR_INVALID_HANDLE; | 333 | return ERR_INVALID_HANDLE; |
| 369 | 334 | ||
| 370 | return archive->backend->CreateFile(path, file_size); | 335 | return archive->CreateFile(path, file_size); |
| 371 | } | 336 | } |
| 372 | 337 | ||
| 373 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { | 338 | ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { |
| 374 | Archive* archive = GetArchive(archive_handle); | 339 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 375 | if (archive == nullptr) | 340 | if (archive == nullptr) |
| 376 | return ERR_INVALID_HANDLE; | 341 | return ERR_INVALID_HANDLE; |
| 377 | 342 | ||
| 378 | if (archive->backend->CreateDirectory(path)) | 343 | if (archive->CreateDirectory(path)) |
| 379 | return RESULT_SUCCESS; | 344 | return RESULT_SUCCESS; |
| 380 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description | 345 | return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description |
| 381 | ErrorSummary::Canceled, ErrorLevel::Status); | 346 | ErrorSummary::Canceled, ErrorLevel::Status); |
| @@ -383,13 +348,13 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy | |||
| 383 | 348 | ||
| 384 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, | 349 | ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, |
| 385 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { | 350 | ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { |
| 386 | Archive* src_archive = GetArchive(src_archive_handle); | 351 | ArchiveBackend* src_archive = GetArchive(src_archive_handle); |
| 387 | Archive* dest_archive = GetArchive(dest_archive_handle); | 352 | ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); |
| 388 | if (src_archive == nullptr || dest_archive == nullptr) | 353 | if (src_archive == nullptr || dest_archive == nullptr) |
| 389 | return ERR_INVALID_HANDLE; | 354 | return ERR_INVALID_HANDLE; |
| 390 | 355 | ||
| 391 | if (src_archive == dest_archive) { | 356 | if (src_archive == dest_archive) { |
| 392 | if (src_archive->backend->RenameDirectory(src_path, dest_path)) | 357 | if (src_archive->RenameDirectory(src_path, dest_path)) |
| 393 | return RESULT_SUCCESS; | 358 | return RESULT_SUCCESS; |
| 394 | } else { | 359 | } else { |
| 395 | // TODO: Implement renaming across archives | 360 | // TODO: Implement renaming across archives |
| @@ -402,31 +367,29 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 402 | ErrorSummary::NothingHappened, ErrorLevel::Status); | 367 | ErrorSummary::NothingHappened, ErrorLevel::Status); |
| 403 | } | 368 | } |
| 404 | 369 | ||
| 405 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 370 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 406 | const FileSys::Path& path) { | 371 | const FileSys::Path& path) { |
| 407 | Archive* archive = GetArchive(archive_handle); | 372 | ArchiveBackend* archive = GetArchive(archive_handle); |
| 408 | if (archive == nullptr) | 373 | if (archive == nullptr) |
| 409 | return ERR_INVALID_HANDLE; | 374 | return ERR_INVALID_HANDLE; |
| 410 | 375 | ||
| 411 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); | 376 | std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); |
| 412 | if (backend == nullptr) { | 377 | if (backend == nullptr) { |
| 413 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, | 378 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 414 | ErrorSummary::NotFound, ErrorLevel::Permanent); | 379 | ErrorSummary::NotFound, ErrorLevel::Permanent); |
| 415 | } | 380 | } |
| 416 | 381 | ||
| 417 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); | 382 | auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); |
| 418 | return MakeResult<Kernel::SharedPtr<Kernel::Session>>(std::move(directory)); | 383 | return MakeResult<Kernel::SharedPtr<Directory>>(std::move(directory)); |
| 419 | } | 384 | } |
| 420 | 385 | ||
| 421 | ResultCode FormatSaveData() { | 386 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path) { |
| 422 | // Do not create the archive again if it already exists | 387 | auto archive_itr = id_code_map.find(id_code); |
| 423 | auto archive_itr = id_code_map.find(ArchiveIdCode::SaveData); | ||
| 424 | if (archive_itr == id_code_map.end()) { | 388 | if (archive_itr == id_code_map.end()) { |
| 425 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error | 389 | return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error |
| 426 | } | 390 | } |
| 427 | 391 | ||
| 428 | // Use an empty path, we do not use it when formatting the savedata | 392 | return archive_itr->second->Format(path); |
| 429 | return archive_itr->second->backend->Format(FileSys::Path()); | ||
| 430 | } | 393 | } |
| 431 | 394 | ||
| 432 | ResultCode CreateExtSaveData(u32 high, u32 low) { | 395 | ResultCode CreateExtSaveData(u32 high, u32 low) { |
| @@ -460,32 +423,32 @@ void ArchiveInit() { | |||
| 460 | 423 | ||
| 461 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); | 424 | std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX); |
| 462 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | 425 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); |
| 463 | auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory); | 426 | auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory); |
| 464 | if (sdmc_archive->Initialize()) | 427 | if (sdmc_factory->Initialize()) |
| 465 | CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC); | 428 | RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); |
| 466 | else | 429 | else |
| 467 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); | 430 | LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); |
| 468 | 431 | ||
| 469 | // Create the SaveData archive | 432 | // Create the SaveData archive |
| 470 | auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(sdmc_directory); | 433 | auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); |
| 471 | CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData); | 434 | RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); |
| 472 | 435 | ||
| 473 | auto extsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(sdmc_directory, false); | 436 | auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); |
| 474 | if (extsavedata_archive->Initialize()) | 437 | if (extsavedata_factory->Initialize()) |
| 475 | CreateArchive(std::move(extsavedata_archive), ArchiveIdCode::ExtSaveData); | 438 | RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); |
| 476 | else | 439 | else |
| 477 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_archive->GetMountPoint().c_str()); | 440 | LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); |
| 478 | 441 | ||
| 479 | auto sharedextsavedata_archive = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); | 442 | auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); |
| 480 | if (sharedextsavedata_archive->Initialize()) | 443 | if (sharedextsavedata_factory->Initialize()) |
| 481 | CreateArchive(std::move(sharedextsavedata_archive), ArchiveIdCode::SharedExtSaveData); | 444 | RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); |
| 482 | else | 445 | else |
| 483 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", | 446 | LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", |
| 484 | sharedextsavedata_archive->GetMountPoint().c_str()); | 447 | sharedextsavedata_factory->GetMountPoint().c_str()); |
| 485 | 448 | ||
| 486 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive | 449 | // Create the SaveDataCheck archive, basically a small variation of the RomFS archive |
| 487 | auto savedatacheck_archive = Common::make_unique<FileSys::Archive_SaveDataCheck>(nand_directory); | 450 | auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); |
| 488 | CreateArchive(std::move(savedatacheck_archive), ArchiveIdCode::SaveDataCheck); | 451 | RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); |
| 489 | } | 452 | } |
| 490 | 453 | ||
| 491 | /// Shutdown archives | 454 | /// Shutdown archives |
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h index ab5ea4da8..c490327d0 100644 --- a/src/core/hle/service/fs/archive.h +++ b/src/core/hle/service/fs/archive.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "core/file_sys/archive_backend.h" | 9 | #include "core/file_sys/archive_backend.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/session.h" | ||
| 11 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 12 | 13 | ||
| 13 | /// The unique system identifier hash, also known as ID0 | 14 | /// The unique system identifier hash, also known as ID0 |
| @@ -36,6 +37,35 @@ enum class ArchiveIdCode : u32 { | |||
| 36 | 37 | ||
| 37 | typedef u64 ArchiveHandle; | 38 | typedef u64 ArchiveHandle; |
| 38 | 39 | ||
| 40 | class File : public Kernel::Session { | ||
| 41 | public: | ||
| 42 | File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path) | ||
| 43 | : path(path), priority(0), backend(std::move(backend)) { | ||
| 44 | } | ||
| 45 | |||
| 46 | std::string GetName() const override { return "Path: " + path.DebugStr(); } | ||
| 47 | |||
| 48 | FileSys::Path path; ///< Path of the file | ||
| 49 | u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means | ||
| 50 | std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface | ||
| 51 | |||
| 52 | ResultVal<bool> SyncRequest() override; | ||
| 53 | }; | ||
| 54 | |||
| 55 | class Directory : public Kernel::Session { | ||
| 56 | public: | ||
| 57 | Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path) | ||
| 58 | : path(path), backend(std::move(backend)) { | ||
| 59 | } | ||
| 60 | |||
| 61 | std::string GetName() const override { return "Directory: " + path.DebugStr(); } | ||
| 62 | |||
| 63 | FileSys::Path path; ///< Path of the directory | ||
| 64 | std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface | ||
| 65 | |||
| 66 | ResultVal<bool> SyncRequest() override; | ||
| 67 | }; | ||
| 68 | |||
| 39 | /** | 69 | /** |
| 40 | * Opens an archive | 70 | * Opens an archive |
| 41 | * @param id_code IdCode of the archive to open | 71 | * @param id_code IdCode of the archive to open |
| @@ -51,11 +81,11 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi | |||
| 51 | ResultCode CloseArchive(ArchiveHandle handle); | 81 | ResultCode CloseArchive(ArchiveHandle handle); |
| 52 | 82 | ||
| 53 | /** | 83 | /** |
| 54 | * Creates an Archive | 84 | * Registers an Archive type, instances of which can later be opened using its IdCode. |
| 55 | * @param backend File system backend interface to the archive | 85 | * @param backend File system backend interface to the archive |
| 56 | * @param id_code Id code used to access this type of archive | 86 | * @param id_code Id code used to access this type of archive |
| 57 | */ | 87 | */ |
| 58 | ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code); | 88 | ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); |
| 59 | 89 | ||
| 60 | /** | 90 | /** |
| 61 | * Open a File from an Archive | 91 | * Open a File from an Archive |
| @@ -64,7 +94,7 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc | |||
| 64 | * @param mode Mode under which to open the File | 94 | * @param mode Mode under which to open the File |
| 65 | * @return The opened File object as a Session | 95 | * @return The opened File object as a Session |
| 66 | */ | 96 | */ |
| 67 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenFileFromArchive(ArchiveHandle archive_handle, | 97 | ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, |
| 68 | const FileSys::Path& path, const FileSys::Mode mode); | 98 | const FileSys::Path& path, const FileSys::Mode mode); |
| 69 | 99 | ||
| 70 | /** | 100 | /** |
| @@ -128,14 +158,17 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons | |||
| 128 | * @param path Path to the Directory inside of the Archive | 158 | * @param path Path to the Directory inside of the Archive |
| 129 | * @return The opened Directory object as a Session | 159 | * @return The opened Directory object as a Session |
| 130 | */ | 160 | */ |
| 131 | ResultVal<Kernel::SharedPtr<Kernel::Session>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, | 161 | ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, |
| 132 | const FileSys::Path& path); | 162 | const FileSys::Path& path); |
| 133 | 163 | ||
| 134 | /** | 164 | /** |
| 135 | * Creates a blank SaveData archive. | 165 | * Erases the contents of the physical folder that contains the archive |
| 166 | * identified by the specified id code and path | ||
| 167 | * @param id_code The id of the archive to format | ||
| 168 | * @param path The path to the archive, if relevant. | ||
| 136 | * @return ResultCode 0 on success or the corresponding code on error | 169 | * @return ResultCode 0 on success or the corresponding code on error |
| 137 | */ | 170 | */ |
| 138 | ResultCode FormatSaveData(); | 171 | ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::Path& path = FileSys::Path()); |
| 139 | 172 | ||
| 140 | /** | 173 | /** |
| 141 | * Creates a blank SharedExtSaveData archive for the specified extdata ID | 174 | * Creates a blank SharedExtSaveData archive for the specified extdata ID |
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 94a3a31c8..71ee4ff55 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp | |||
| @@ -61,7 +61,7 @@ static void OpenFile(Service::Interface* self) { | |||
| 61 | 61 | ||
| 62 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); | 62 | LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); |
| 63 | 63 | ||
| 64 | ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); | 64 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); |
| 65 | cmd_buff[1] = file_res.Code().raw; | 65 | cmd_buff[1] = file_res.Code().raw; |
| 66 | if (file_res.Succeeded()) { | 66 | if (file_res.Succeeded()) { |
| 67 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 67 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); |
| @@ -117,7 +117,7 @@ static void OpenFileDirectly(Service::Interface* self) { | |||
| 117 | } | 117 | } |
| 118 | SCOPE_EXIT({ CloseArchive(*archive_handle); }); | 118 | SCOPE_EXIT({ CloseArchive(*archive_handle); }); |
| 119 | 119 | ||
| 120 | ResultVal<SharedPtr<Session>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); | 120 | ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(*archive_handle, file_path, mode); |
| 121 | cmd_buff[1] = file_res.Code().raw; | 121 | cmd_buff[1] = file_res.Code().raw; |
| 122 | if (file_res.Succeeded()) { | 122 | if (file_res.Succeeded()) { |
| 123 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); | 123 | cmd_buff[3] = Kernel::g_handle_table.Create(*file_res).MoveFrom(); |
| @@ -337,7 +337,7 @@ static void OpenDirectory(Service::Interface* self) { | |||
| 337 | 337 | ||
| 338 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); | 338 | LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); |
| 339 | 339 | ||
| 340 | ResultVal<SharedPtr<Session>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); | 340 | ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); |
| 341 | cmd_buff[1] = dir_res.Code().raw; | 341 | cmd_buff[1] = dir_res.Code().raw; |
| 342 | if (dir_res.Succeeded()) { | 342 | if (dir_res.Succeeded()) { |
| 343 | cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); | 343 | cmd_buff[3] = Kernel::g_handle_table.Create(*dir_res).MoveFrom(); |
| @@ -468,7 +468,7 @@ static void FormatSaveData(Service::Interface* self) { | |||
| 468 | return; | 468 | return; |
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | cmd_buff[1] = FormatSaveData().raw; | 471 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | /** | 474 | /** |
| @@ -484,7 +484,7 @@ static void FormatThisUserSaveData(Service::Interface* self) { | |||
| 484 | 484 | ||
| 485 | // TODO(Subv): Find out what the inputs and outputs of this function are | 485 | // TODO(Subv): Find out what the inputs and outputs of this function are |
| 486 | 486 | ||
| 487 | cmd_buff[1] = FormatSaveData().raw; | 487 | cmd_buff[1] = FormatArchive(ArchiveIdCode::SaveData).raw; |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | static void CreateExtSaveData(Service::Interface* self) { | 490 | static void CreateExtSaveData(Service::Interface* self) { |
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index 7b465a348..7c8d9ce8c 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,31 +138,28 @@ const Interface::FunctionInfo FunctionTable[] = { | |||
| 138 | 138 | ||
| 139 | Interface::Interface() { | 139 | Interface::Interface() { |
| 140 | Register(FunctionTable); | 140 | Register(FunctionTable); |
| 141 | // Create the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file | 141 | |
| 142 | // TODO(Subv): In the future we should use the FS service to query this archive | 142 | // Open the SharedExtSaveData archive 0xF000000B and the gamecoin.dat file |
| 143 | std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); | ||
| 144 | ptm_shared_extsavedata = Common::make_unique<FileSys::Archive_ExtSaveData>(nand_directory, true); | ||
| 145 | if (!ptm_shared_extsavedata->Initialize()) { | ||
| 146 | LOG_CRITICAL(Service_PTM, "Could not initialize SharedExtSaveData archive for the PTM:U service"); | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | FileSys::Path archive_path(ptm_shared_extdata_id); | 143 | FileSys::Path archive_path(ptm_shared_extdata_id); |
| 150 | ResultCode result = ptm_shared_extsavedata->Open(archive_path); | 144 | auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 151 | // If the archive didn't exist, create the files inside | 145 | // If the archive didn't exist, create the files inside |
| 152 | if (result.description == ErrorDescription::FS_NotFormatted) { | 146 | if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { |
| 153 | // Format the archive to clear the directories | 147 | // Format the archive to create the directories |
| 154 | ptm_shared_extsavedata->Format(archive_path); | 148 | Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 155 | // Open it again to get a valid archive now that the folder exists | 149 | // Open it again to get a valid archive now that the folder exists |
| 156 | ptm_shared_extsavedata->Open(archive_path); | 150 | archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); |
| 151 | _assert_msg_(Service_PTM, archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); | ||
| 152 | |||
| 157 | FileSys::Path gamecoin_path("gamecoin.dat"); | 153 | FileSys::Path gamecoin_path("gamecoin.dat"); |
| 158 | FileSys::Mode open_mode = {}; | 154 | FileSys::Mode open_mode = {}; |
| 159 | open_mode.write_flag = 1; | 155 | open_mode.write_flag = 1; |
| 160 | open_mode.create_flag = 1; | 156 | open_mode.create_flag = 1; |
| 161 | // Open the file and write the default gamecoin information | 157 | // Open the file and write the default gamecoin information |
| 162 | auto gamecoin = ptm_shared_extsavedata->OpenFile(gamecoin_path, open_mode); | 158 | auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); |
| 163 | if (gamecoin != nullptr) { | 159 | if (gamecoin_result.Succeeded()) { |
| 164 | gamecoin->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); | 160 | auto gamecoin = gamecoin_result.MoveFrom(); |
| 165 | gamecoin->Close(); | 161 | gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); |
| 162 | gamecoin->backend->Close(); | ||
| 166 | } | 163 | } |
| 167 | } | 164 | } |
| 168 | } | 165 | } |
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; |