diff options
| author | 2018-07-17 15:42:15 -0400 | |
|---|---|---|
| committer | 2018-07-17 12:42:15 -0700 | |
| commit | 69bfe075b5c3f6b17ce269950d1f8c9aab18e2de (patch) | |
| tree | 8fca65bb5b3a0a8fb2b0772020d5b8d47749c3b3 /src/core/file_sys | |
| parent | Merge pull request #671 from MerryMage/clear-exclusive-state (diff) | |
| download | yuzu-69bfe075b5c3f6b17ce269950d1f8c9aab18e2de.tar.gz yuzu-69bfe075b5c3f6b17ce269950d1f8c9aab18e2de.tar.xz yuzu-69bfe075b5c3f6b17ce269950d1f8c9aab18e2de.zip | |
General Filesystem and Save Data Fixes (#670)
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/errors.h | 2 | ||||
| -rw-r--r-- | src/core/file_sys/filesystem.h | 31 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_factory.cpp | 17 | ||||
| -rw-r--r-- | src/core/file_sys/romfs_factory.h | 11 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.cpp | 95 | ||||
| -rw-r--r-- | src/core/file_sys/savedata_factory.h | 46 | ||||
| -rw-r--r-- | src/core/file_sys/sdmc_factory.cpp | 16 | ||||
| -rw-r--r-- | src/core/file_sys/sdmc_factory.h | 11 |
8 files changed, 123 insertions, 106 deletions
diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index d3e9a3829..1f3b8fa84 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h | |||
| @@ -12,6 +12,8 @@ namespace ErrCodes { | |||
| 12 | enum { | 12 | enum { |
| 13 | NotFound = 1, | 13 | NotFound = 1, |
| 14 | SaveDataNotFound = 1002, | 14 | SaveDataNotFound = 1002, |
| 15 | SdCardNotFound = 2001, | ||
| 16 | RomFSNotFound = 2520, | ||
| 15 | }; | 17 | }; |
| 16 | } | 18 | } |
| 17 | 19 | ||
diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h index 295a3133e..1a32a373b 100644 --- a/src/core/file_sys/filesystem.h +++ b/src/core/file_sys/filesystem.h | |||
| @@ -167,35 +167,4 @@ public: | |||
| 167 | virtual ResultVal<EntryType> GetEntryType(const std::string& path) const = 0; | 167 | virtual ResultVal<EntryType> GetEntryType(const std::string& path) const = 0; |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | class FileSystemFactory : NonCopyable { | ||
| 171 | public: | ||
| 172 | virtual ~FileSystemFactory() {} | ||
| 173 | |||
| 174 | /** | ||
| 175 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | ||
| 176 | */ | ||
| 177 | virtual std::string GetName() const = 0; | ||
| 178 | |||
| 179 | /** | ||
| 180 | * Tries to open the archive of this type with the specified path | ||
| 181 | * @param path Path to the archive | ||
| 182 | * @return An ArchiveBackend corresponding operating specified archive path. | ||
| 183 | */ | ||
| 184 | virtual ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) = 0; | ||
| 185 | |||
| 186 | /** | ||
| 187 | * Deletes the archive contents and then re-creates the base folder | ||
| 188 | * @param path Path to the archive | ||
| 189 | * @return ResultCode of the operation, 0 on success | ||
| 190 | */ | ||
| 191 | virtual ResultCode Format(const Path& path) = 0; | ||
| 192 | |||
| 193 | /** | ||
| 194 | * Retrieves the format info about the archive with the specified path | ||
| 195 | * @param path Path to the archive | ||
| 196 | * @return Format information about the archive or error code | ||
| 197 | */ | ||
| 198 | virtual ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const = 0; | ||
| 199 | }; | ||
| 200 | |||
| 201 | } // namespace FileSys | 170 | } // namespace FileSys |
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index 84ae0d99b..946fc0452 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -11,28 +11,17 @@ | |||
| 11 | 11 | ||
| 12 | namespace FileSys { | 12 | namespace FileSys { |
| 13 | 13 | ||
| 14 | RomFS_Factory::RomFS_Factory(Loader::AppLoader& app_loader) { | 14 | RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) { |
| 15 | // Load the RomFS from the app | 15 | // Load the RomFS from the app |
| 16 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) { | 16 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(romfs_file, data_offset, data_size)) { |
| 17 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); | 17 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); |
| 18 | } | 18 | } |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | ResultVal<std::unique_ptr<FileSystemBackend>> RomFS_Factory::Open(const Path& path) { | 21 | ResultVal<std::unique_ptr<FileSystemBackend>> RomFSFactory::Open(u64 title_id) { |
| 22 | // TODO(DarkLordZach): Use title id. | ||
| 22 | auto archive = std::make_unique<RomFS_FileSystem>(romfs_file, data_offset, data_size); | 23 | auto archive = std::make_unique<RomFS_FileSystem>(romfs_file, data_offset, data_size); |
| 23 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); | 24 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | ResultCode RomFS_Factory::Format(const Path& path) { | ||
| 27 | LOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName()); | ||
| 28 | // TODO(bunnei): Find the right error code for this | ||
| 29 | return ResultCode(-1); | ||
| 30 | } | ||
| 31 | |||
| 32 | ResultVal<ArchiveFormatInfo> RomFS_Factory::GetFormatInfo(const Path& path) const { | ||
| 33 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); | ||
| 34 | // TODO(bunnei): Find the right error code for this | ||
| 35 | return ResultCode(-1); | ||
| 36 | } | ||
| 37 | |||
| 38 | } // namespace FileSys | 27 | } // namespace FileSys |
diff --git a/src/core/file_sys/romfs_factory.h b/src/core/file_sys/romfs_factory.h index e0698e642..c9e20c3ab 100644 --- a/src/core/file_sys/romfs_factory.h +++ b/src/core/file_sys/romfs_factory.h | |||
| @@ -15,16 +15,11 @@ | |||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | /// File system interface to the RomFS archive | 17 | /// File system interface to the RomFS archive |
| 18 | class RomFS_Factory final : public FileSystemFactory { | 18 | class RomFSFactory { |
| 19 | public: | 19 | public: |
| 20 | explicit RomFS_Factory(Loader::AppLoader& app_loader); | 20 | explicit RomFSFactory(Loader::AppLoader& app_loader); |
| 21 | 21 | ||
| 22 | std::string GetName() const override { | 22 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(u64 title_id); |
| 23 | return "ArchiveFactory_RomFS"; | ||
| 24 | } | ||
| 25 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override; | ||
| 26 | ResultCode Format(const Path& path) override; | ||
| 27 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 28 | 23 | ||
| 29 | private: | 24 | private: |
| 30 | std::shared_ptr<FileUtil::IOFile> romfs_file; | 25 | std::shared_ptr<FileUtil::IOFile> romfs_file; |
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp index f3aa213af..3ad37b28c 100644 --- a/src/core/file_sys/savedata_factory.cpp +++ b/src/core/file_sys/savedata_factory.cpp | |||
| @@ -12,11 +12,49 @@ | |||
| 12 | 12 | ||
| 13 | namespace FileSys { | 13 | namespace FileSys { |
| 14 | 14 | ||
| 15 | SaveData_Factory::SaveData_Factory(std::string nand_directory) | 15 | std::string SaveDataDescriptor::DebugInfo() { |
| 16 | return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}]", | ||
| 17 | static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id); | ||
| 18 | } | ||
| 19 | |||
| 20 | SaveDataFactory::SaveDataFactory(std::string nand_directory) | ||
| 16 | : nand_directory(std::move(nand_directory)) {} | 21 | : nand_directory(std::move(nand_directory)) {} |
| 17 | 22 | ||
| 18 | ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path& path) { | 23 | ResultVal<std::unique_ptr<FileSystemBackend>> SaveDataFactory::Open(SaveDataSpaceId space, |
| 19 | std::string save_directory = GetFullPath(); | 24 | SaveDataDescriptor meta) { |
| 25 | if (meta.type == SaveDataType::SystemSaveData || meta.type == SaveDataType::SaveData) { | ||
| 26 | if (meta.zero_1 != 0) { | ||
| 27 | LOG_WARNING(Service_FS, | ||
| 28 | "Possibly incorrect SaveDataDescriptor, type is " | ||
| 29 | "SystemSaveData||SaveData but offset 0x28 is non-zero ({:016X}).", | ||
| 30 | meta.zero_1); | ||
| 31 | } | ||
| 32 | if (meta.zero_2 != 0) { | ||
| 33 | LOG_WARNING(Service_FS, | ||
| 34 | "Possibly incorrect SaveDataDescriptor, type is " | ||
| 35 | "SystemSaveData||SaveData but offset 0x30 is non-zero ({:016X}).", | ||
| 36 | meta.zero_2); | ||
| 37 | } | ||
| 38 | if (meta.zero_3 != 0) { | ||
| 39 | LOG_WARNING(Service_FS, | ||
| 40 | "Possibly incorrect SaveDataDescriptor, type is " | ||
| 41 | "SystemSaveData||SaveData but offset 0x38 is non-zero ({:016X}).", | ||
| 42 | meta.zero_3); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | if (meta.type == SaveDataType::SystemSaveData && meta.title_id != 0) { | ||
| 47 | LOG_WARNING(Service_FS, | ||
| 48 | "Possibly incorrect SaveDataDescriptor, type is SystemSaveData but title_id is " | ||
| 49 | "non-zero ({:016X}).", | ||
| 50 | meta.title_id); | ||
| 51 | } | ||
| 52 | |||
| 53 | std::string save_directory = | ||
| 54 | GetFullPath(space, meta.type, meta.title_id, meta.user_id, meta.save_id); | ||
| 55 | |||
| 56 | // TODO(DarkLordZach): Try to not create when opening, there are dedicated create save methods. | ||
| 57 | // But, user_ids don't match so this works for now. | ||
| 20 | 58 | ||
| 21 | if (!FileUtil::Exists(save_directory)) { | 59 | if (!FileUtil::Exists(save_directory)) { |
| 22 | // TODO(bunnei): This is a work-around to always create a save data directory if it does not | 60 | // TODO(bunnei): This is a work-around to always create a save data directory if it does not |
| @@ -26,6 +64,12 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path& | |||
| 26 | FileUtil::CreateFullPath(save_directory); | 64 | FileUtil::CreateFullPath(save_directory); |
| 27 | } | 65 | } |
| 28 | 66 | ||
| 67 | // TODO(DarkLordZach): For some reason, CreateFullPath doesn't create the last bit. Should be | ||
| 68 | // fixed with VFS. | ||
| 69 | if (!FileUtil::IsDirectory(save_directory)) { | ||
| 70 | FileUtil::CreateDir(save_directory); | ||
| 71 | } | ||
| 72 | |||
| 29 | // Return an error if the save data doesn't actually exist. | 73 | // Return an error if the save data doesn't actually exist. |
| 30 | if (!FileUtil::IsDirectory(save_directory)) { | 74 | if (!FileUtil::IsDirectory(save_directory)) { |
| 31 | // TODO(Subv): Find out correct error code. | 75 | // TODO(Subv): Find out correct error code. |
| @@ -36,28 +80,35 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SaveData_Factory::Open(const Path& | |||
| 36 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); | 80 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); |
| 37 | } | 81 | } |
| 38 | 82 | ||
| 39 | ResultCode SaveData_Factory::Format(const Path& path) { | 83 | std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, |
| 40 | LOG_WARNING(Service_FS, "Format archive {}", GetName()); | 84 | u128 user_id, u64 save_id) const { |
| 41 | // Create the save data directory. | 85 | // According to switchbrew, if a save is of type SaveData and the title id field is 0, it should |
| 42 | if (!FileUtil::CreateFullPath(GetFullPath())) { | 86 | // be interpreted as the title id of the current process. |
| 43 | // TODO(Subv): Find the correct error code. | 87 | if (type == SaveDataType::SaveData && title_id == 0) |
| 44 | return ResultCode(-1); | 88 | title_id = Core::CurrentProcess()->program_id; |
| 45 | } | ||
| 46 | 89 | ||
| 47 | return RESULT_SUCCESS; | 90 | std::string prefix; |
| 48 | } | ||
| 49 | 91 | ||
| 50 | ResultVal<ArchiveFormatInfo> SaveData_Factory::GetFormatInfo(const Path& path) const { | 92 | switch (space) { |
| 51 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); | 93 | case SaveDataSpaceId::NandSystem: |
| 52 | // TODO(bunnei): Find the right error code for this | 94 | prefix = nand_directory + "system/save/"; |
| 53 | return ResultCode(-1); | 95 | break; |
| 54 | } | 96 | case SaveDataSpaceId::NandUser: |
| 97 | prefix = nand_directory + "user/save/"; | ||
| 98 | break; | ||
| 99 | default: | ||
| 100 | ASSERT_MSG(false, "Unrecognized SaveDataSpaceId: {:02X}", static_cast<u8>(space)); | ||
| 101 | } | ||
| 55 | 102 | ||
| 56 | std::string SaveData_Factory::GetFullPath() const { | 103 | switch (type) { |
| 57 | u64 title_id = Core::CurrentProcess()->program_id; | 104 | case SaveDataType::SystemSaveData: |
| 58 | // TODO(Subv): Somehow obtain this value. | 105 | return fmt::format("{}{:016X}/{:016X}{:016X}", prefix, save_id, user_id[1], user_id[0]); |
| 59 | u32 user = 0; | 106 | case SaveDataType::SaveData: |
| 60 | return fmt::format("{}save/{:016X}/{:08X}/", nand_directory, title_id, user); | 107 | return fmt::format("{}{:016X}/{:016X}{:016X}/{:016X}", prefix, 0, user_id[1], user_id[0], |
| 108 | title_id); | ||
| 109 | default: | ||
| 110 | ASSERT_MSG(false, "Unrecognized SaveDataType: {:02X}", static_cast<u8>(type)); | ||
| 111 | } | ||
| 61 | } | 112 | } |
| 62 | 113 | ||
| 63 | } // namespace FileSys | 114 | } // namespace FileSys |
diff --git a/src/core/file_sys/savedata_factory.h b/src/core/file_sys/savedata_factory.h index 73a42aab6..b96721ac0 100644 --- a/src/core/file_sys/savedata_factory.h +++ b/src/core/file_sys/savedata_factory.h | |||
| @@ -12,22 +12,50 @@ | |||
| 12 | 12 | ||
| 13 | namespace FileSys { | 13 | namespace FileSys { |
| 14 | 14 | ||
| 15 | enum class SaveDataSpaceId : u8 { | ||
| 16 | NandSystem = 0, | ||
| 17 | NandUser = 1, | ||
| 18 | SdCard = 2, | ||
| 19 | TemporaryStorage = 3, | ||
| 20 | }; | ||
| 21 | |||
| 22 | enum class SaveDataType : u8 { | ||
| 23 | SystemSaveData = 0, | ||
| 24 | SaveData = 1, | ||
| 25 | BcatDeliveryCacheStorage = 2, | ||
| 26 | DeviceSaveData = 3, | ||
| 27 | TemporaryStorage = 4, | ||
| 28 | CacheStorage = 5, | ||
| 29 | }; | ||
| 30 | |||
| 31 | struct SaveDataDescriptor { | ||
| 32 | u64_le title_id; | ||
| 33 | u128 user_id; | ||
| 34 | u64_le save_id; | ||
| 35 | SaveDataType type; | ||
| 36 | INSERT_PADDING_BYTES(7); | ||
| 37 | u64_le zero_1; | ||
| 38 | u64_le zero_2; | ||
| 39 | u64_le zero_3; | ||
| 40 | |||
| 41 | std::string DebugInfo(); | ||
| 42 | }; | ||
| 43 | static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size."); | ||
| 44 | |||
| 15 | /// File system interface to the SaveData archive | 45 | /// File system interface to the SaveData archive |
| 16 | class SaveData_Factory final : public FileSystemFactory { | 46 | class SaveDataFactory { |
| 17 | public: | 47 | public: |
| 18 | explicit SaveData_Factory(std::string nand_directory); | 48 | explicit SaveDataFactory(std::string nand_directory); |
| 19 | 49 | ||
| 20 | std::string GetName() const override { | 50 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(SaveDataSpaceId space, |
| 21 | return "SaveData_Factory"; | 51 | SaveDataDescriptor meta); |
| 22 | } | ||
| 23 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override; | ||
| 24 | ResultCode Format(const Path& path) override; | ||
| 25 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 26 | 52 | ||
| 27 | private: | 53 | private: |
| 28 | std::string nand_directory; | 54 | std::string nand_directory; |
| 55 | std::string sd_directory; | ||
| 29 | 56 | ||
| 30 | std::string GetFullPath() const; | 57 | std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id, u128 user_id, |
| 58 | u64 save_id) const; | ||
| 31 | }; | 59 | }; |
| 32 | 60 | ||
| 33 | } // namespace FileSys | 61 | } // namespace FileSys |
diff --git a/src/core/file_sys/sdmc_factory.cpp b/src/core/file_sys/sdmc_factory.cpp index 2e5ffb764..ac6f2f971 100644 --- a/src/core/file_sys/sdmc_factory.cpp +++ b/src/core/file_sys/sdmc_factory.cpp | |||
| @@ -12,9 +12,9 @@ | |||
| 12 | 12 | ||
| 13 | namespace FileSys { | 13 | namespace FileSys { |
| 14 | 14 | ||
| 15 | SDMC_Factory::SDMC_Factory(std::string sd_directory) : sd_directory(std::move(sd_directory)) {} | 15 | SDMCFactory::SDMCFactory(std::string sd_directory) : sd_directory(std::move(sd_directory)) {} |
| 16 | 16 | ||
| 17 | ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& path) { | 17 | ResultVal<std::unique_ptr<FileSystemBackend>> SDMCFactory::Open() { |
| 18 | // Create the SD Card directory if it doesn't already exist. | 18 | // Create the SD Card directory if it doesn't already exist. |
| 19 | if (!FileUtil::IsDirectory(sd_directory)) { | 19 | if (!FileUtil::IsDirectory(sd_directory)) { |
| 20 | FileUtil::CreateFullPath(sd_directory); | 20 | FileUtil::CreateFullPath(sd_directory); |
| @@ -24,16 +24,4 @@ ResultVal<std::unique_ptr<FileSystemBackend>> SDMC_Factory::Open(const Path& pat | |||
| 24 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); | 24 | return MakeResult<std::unique_ptr<FileSystemBackend>>(std::move(archive)); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | ResultCode SDMC_Factory::Format(const Path& path) { | ||
| 28 | LOG_ERROR(Service_FS, "Unimplemented Format archive {}", GetName()); | ||
| 29 | // TODO(Subv): Find the right error code for this | ||
| 30 | return ResultCode(-1); | ||
| 31 | } | ||
| 32 | |||
| 33 | ResultVal<ArchiveFormatInfo> SDMC_Factory::GetFormatInfo(const Path& path) const { | ||
| 34 | LOG_ERROR(Service_FS, "Unimplemented GetFormatInfo archive {}", GetName()); | ||
| 35 | // TODO(bunnei): Find the right error code for this | ||
| 36 | return ResultCode(-1); | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace FileSys | 27 | } // namespace FileSys |
diff --git a/src/core/file_sys/sdmc_factory.h b/src/core/file_sys/sdmc_factory.h index 93becda25..09bec7fce 100644 --- a/src/core/file_sys/sdmc_factory.h +++ b/src/core/file_sys/sdmc_factory.h | |||
| @@ -13,16 +13,11 @@ | |||
| 13 | namespace FileSys { | 13 | namespace FileSys { |
| 14 | 14 | ||
| 15 | /// File system interface to the SDCard archive | 15 | /// File system interface to the SDCard archive |
| 16 | class SDMC_Factory final : public FileSystemFactory { | 16 | class SDMCFactory { |
| 17 | public: | 17 | public: |
| 18 | explicit SDMC_Factory(std::string sd_directory); | 18 | explicit SDMCFactory(std::string sd_directory); |
| 19 | 19 | ||
| 20 | std::string GetName() const override { | 20 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(); |
| 21 | return "SDMC_Factory"; | ||
| 22 | } | ||
| 23 | ResultVal<std::unique_ptr<FileSystemBackend>> Open(const Path& path) override; | ||
| 24 | ResultCode Format(const Path& path) override; | ||
| 25 | ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; | ||
| 26 | 21 | ||
| 27 | private: | 22 | private: |
| 28 | std::string sd_directory; | 23 | std::string sd_directory; |