diff options
| author | 2014-12-29 19:47:41 -0800 | |
|---|---|---|
| committer | 2014-12-29 19:47:41 -0800 | |
| commit | 8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch) | |
| tree | f1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/file_sys | |
| parent | Add comment regarding __WIN32__ in SkyEye code (diff) | |
| parent | Merge pull request #367 from bunnei/usat_ssat (diff) | |
| download | yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip | |
Fix merge conflicts
Diffstat (limited to 'src/core/file_sys')
22 files changed, 793 insertions, 946 deletions
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h deleted file mode 100644 index 2e79bb883..000000000 --- a/src/core/file_sys/archive.h +++ /dev/null | |||
| @@ -1,246 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/string_util.h" | ||
| 11 | #include "common/bit_field.h" | ||
| 12 | |||
| 13 | #include "core/file_sys/file.h" | ||
| 14 | #include "core/file_sys/directory.h" | ||
| 15 | |||
| 16 | #include "core/mem_map.h" | ||
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | |||
| 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 20 | // FileSys namespace | ||
| 21 | |||
| 22 | namespace FileSys { | ||
| 23 | |||
| 24 | // Path string type | ||
| 25 | enum LowPathType : u32 { | ||
| 26 | Invalid = 0, | ||
| 27 | Empty = 1, | ||
| 28 | Binary = 2, | ||
| 29 | Char = 3, | ||
| 30 | Wchar = 4 | ||
| 31 | }; | ||
| 32 | |||
| 33 | union Mode { | ||
| 34 | u32 hex; | ||
| 35 | BitField<0, 1, u32> read_flag; | ||
| 36 | BitField<1, 1, u32> write_flag; | ||
| 37 | BitField<2, 1, u32> create_flag; | ||
| 38 | }; | ||
| 39 | |||
| 40 | class Path { | ||
| 41 | public: | ||
| 42 | |||
| 43 | Path(): | ||
| 44 | type(Invalid) | ||
| 45 | { | ||
| 46 | } | ||
| 47 | |||
| 48 | Path(LowPathType type, u32 size, u32 pointer): | ||
| 49 | type(type) | ||
| 50 | { | ||
| 51 | switch (type) { | ||
| 52 | case Binary: | ||
| 53 | { | ||
| 54 | u8* data = Memory::GetPointer(pointer); | ||
| 55 | binary = std::vector<u8>(data, data + size); | ||
| 56 | break; | ||
| 57 | } | ||
| 58 | case Char: | ||
| 59 | { | ||
| 60 | const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); | ||
| 61 | string = std::string(data, size - 1); // Data is always null-terminated. | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | case Wchar: | ||
| 65 | { | ||
| 66 | const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); | ||
| 67 | u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | LowPathType GetType() const { | ||
| 74 | return type; | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Gets the string representation of the path for debugging | ||
| 79 | * @return String representation of the path for debugging | ||
| 80 | */ | ||
| 81 | const std::string DebugStr() const { | ||
| 82 | switch (GetType()) { | ||
| 83 | case Invalid: | ||
| 84 | return "[Invalid]"; | ||
| 85 | case Empty: | ||
| 86 | return "[Empty]"; | ||
| 87 | case Binary: | ||
| 88 | { | ||
| 89 | std::stringstream res; | ||
| 90 | res << "[Binary: "; | ||
| 91 | for (unsigned byte : binary) | ||
| 92 | res << std::hex << std::setw(2) << std::setfill('0') << byte; | ||
| 93 | res << ']'; | ||
| 94 | return res.str(); | ||
| 95 | } | ||
| 96 | case Char: | ||
| 97 | return "[Char: " + AsString() + ']'; | ||
| 98 | case Wchar: | ||
| 99 | return "[Wchar: " + AsString() + ']'; | ||
| 100 | default: | ||
| 101 | ERROR_LOG(KERNEL, "LowPathType cannot be converted to string!"); | ||
| 102 | return {}; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | const std::string AsString() const { | ||
| 107 | switch (GetType()) { | ||
| 108 | case Char: | ||
| 109 | return string; | ||
| 110 | case Wchar: | ||
| 111 | return Common::UTF16ToUTF8(u16str); | ||
| 112 | case Empty: | ||
| 113 | return {}; | ||
| 114 | default: | ||
| 115 | ERROR_LOG(KERNEL, "LowPathType cannot be converted to string!"); | ||
| 116 | return {}; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | const std::u16string AsU16Str() const { | ||
| 121 | switch (GetType()) { | ||
| 122 | case Char: | ||
| 123 | return Common::UTF8ToUTF16(string); | ||
| 124 | case Wchar: | ||
| 125 | return u16str; | ||
| 126 | case Empty: | ||
| 127 | return {}; | ||
| 128 | default: | ||
| 129 | ERROR_LOG(KERNEL, "LowPathType cannot be converted to u16string!"); | ||
| 130 | return {}; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | const std::vector<u8> AsBinary() const { | ||
| 135 | switch (GetType()) { | ||
| 136 | case Binary: | ||
| 137 | return binary; | ||
| 138 | case Char: | ||
| 139 | return std::vector<u8>(string.begin(), string.end()); | ||
| 140 | case Wchar: | ||
| 141 | return std::vector<u8>(u16str.begin(), u16str.end()); | ||
| 142 | case Empty: | ||
| 143 | return {}; | ||
| 144 | default: | ||
| 145 | ERROR_LOG(KERNEL, "LowPathType cannot be converted to binary!"); | ||
| 146 | return {}; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | private: | ||
| 151 | LowPathType type; | ||
| 152 | std::vector<u8> binary; | ||
| 153 | std::string string; | ||
| 154 | std::u16string u16str; | ||
| 155 | }; | ||
| 156 | |||
| 157 | class Archive : NonCopyable { | ||
| 158 | public: | ||
| 159 | /// Supported archive types | ||
| 160 | enum class IdCode : u32 { | ||
| 161 | RomFS = 0x00000003, | ||
| 162 | SaveData = 0x00000004, | ||
| 163 | ExtSaveData = 0x00000006, | ||
| 164 | SharedExtSaveData = 0x00000007, | ||
| 165 | SystemSaveData = 0x00000008, | ||
| 166 | SDMC = 0x00000009, | ||
| 167 | SDMCWriteOnly = 0x0000000A, | ||
| 168 | }; | ||
| 169 | |||
| 170 | Archive() { } | ||
| 171 | virtual ~Archive() { } | ||
| 172 | |||
| 173 | /** | ||
| 174 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 175 | * @return IdCode of the archive | ||
| 176 | */ | ||
| 177 | virtual IdCode GetIdCode() const = 0; | ||
| 178 | |||
| 179 | /** | ||
| 180 | * Open a file specified by its path, using the specified mode | ||
| 181 | * @param path Path relative to the archive | ||
| 182 | * @param mode Mode to open the file with | ||
| 183 | * @return Opened file, or nullptr | ||
| 184 | */ | ||
| 185 | virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0; | ||
| 186 | |||
| 187 | /** | ||
| 188 | * Delete a file specified by its path | ||
| 189 | * @param path Path relative to the archive | ||
| 190 | * @return Whether the file could be deleted | ||
| 191 | */ | ||
| 192 | virtual bool DeleteFile(const FileSys::Path& path) const = 0; | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Delete a directory specified by its path | ||
| 196 | * @param path Path relative to the archive | ||
| 197 | * @return Whether the directory could be deleted | ||
| 198 | */ | ||
| 199 | virtual bool DeleteDirectory(const FileSys::Path& path) const = 0; | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Create a directory specified by its path | ||
| 203 | * @param path Path relative to the archive | ||
| 204 | * @return Whether the directory could be created | ||
| 205 | */ | ||
| 206 | virtual bool CreateDirectory(const Path& path) const = 0; | ||
| 207 | |||
| 208 | /** | ||
| 209 | * Open a directory specified by its path | ||
| 210 | * @param path Path relative to the archive | ||
| 211 | * @return Opened directory, or nullptr | ||
| 212 | */ | ||
| 213 | virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0; | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Read data from the archive | ||
| 217 | * @param offset Offset in bytes to start reading data from | ||
| 218 | * @param length Length in bytes of data to read from archive | ||
| 219 | * @param buffer Buffer to read data into | ||
| 220 | * @return Number of bytes read | ||
| 221 | */ | ||
| 222 | virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0; | ||
| 223 | |||
| 224 | /** | ||
| 225 | * Write data to the archive | ||
| 226 | * @param offset Offset in bytes to start writing data to | ||
| 227 | * @param length Length in bytes of data to write to archive | ||
| 228 | * @param buffer Buffer to write data from | ||
| 229 | * @param flush The flush parameters (0 == do not flush) | ||
| 230 | * @return Number of bytes written | ||
| 231 | */ | ||
| 232 | virtual size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) = 0; | ||
| 233 | |||
| 234 | /** | ||
| 235 | * Get the size of the archive in bytes | ||
| 236 | * @return Size of the archive in bytes | ||
| 237 | */ | ||
| 238 | virtual size_t GetSize() const = 0; | ||
| 239 | |||
| 240 | /** | ||
| 241 | * Set the size of the archive in bytes | ||
| 242 | */ | ||
| 243 | virtual void SetSize(const u64 size) = 0; | ||
| 244 | }; | ||
| 245 | |||
| 246 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h new file mode 100644 index 000000000..e153917ea --- /dev/null +++ b/src/core/file_sys/archive_backend.h | |||
| @@ -0,0 +1,243 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | |||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/string_util.h" | ||
| 11 | #include "common/bit_field.h" | ||
| 12 | |||
| 13 | #include "core/file_sys/file_backend.h" | ||
| 14 | #include "core/file_sys/directory_backend.h" | ||
| 15 | |||
| 16 | #include "core/mem_map.h" | ||
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | |||
| 19 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 20 | // FileSys namespace | ||
| 21 | |||
| 22 | namespace FileSys { | ||
| 23 | |||
| 24 | // Path string type | ||
| 25 | enum LowPathType : u32 { | ||
| 26 | Invalid = 0, | ||
| 27 | Empty = 1, | ||
| 28 | Binary = 2, | ||
| 29 | Char = 3, | ||
| 30 | Wchar = 4 | ||
| 31 | }; | ||
| 32 | |||
| 33 | union Mode { | ||
| 34 | u32 hex; | ||
| 35 | BitField<0, 1, u32> read_flag; | ||
| 36 | BitField<1, 1, u32> write_flag; | ||
| 37 | BitField<2, 1, u32> create_flag; | ||
| 38 | }; | ||
| 39 | |||
| 40 | class Path { | ||
| 41 | public: | ||
| 42 | |||
| 43 | Path() : type(Invalid) { | ||
| 44 | } | ||
| 45 | |||
| 46 | Path(const char* path) : type(Char), string(path) { | ||
| 47 | } | ||
| 48 | |||
| 49 | Path(LowPathType type, u32 size, u32 pointer) : type(type) { | ||
| 50 | switch (type) { | ||
| 51 | case Binary: | ||
| 52 | { | ||
| 53 | u8* data = Memory::GetPointer(pointer); | ||
| 54 | binary = std::vector<u8>(data, data + size); | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | |||
| 58 | case Char: | ||
| 59 | { | ||
| 60 | const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); | ||
| 61 | string = std::string(data, size - 1); // Data is always null-terminated. | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | |||
| 65 | case Wchar: | ||
| 66 | { | ||
| 67 | const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); | ||
| 68 | u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. | ||
| 69 | break; | ||
| 70 | } | ||
| 71 | |||
| 72 | default: | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | LowPathType GetType() const { | ||
| 78 | return type; | ||
| 79 | } | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Gets the string representation of the path for debugging | ||
| 83 | * @return String representation of the path for debugging | ||
| 84 | */ | ||
| 85 | const std::string DebugStr() const { | ||
| 86 | switch (GetType()) { | ||
| 87 | case Invalid: | ||
| 88 | return "[Invalid]"; | ||
| 89 | case Empty: | ||
| 90 | return "[Empty]"; | ||
| 91 | case Binary: | ||
| 92 | { | ||
| 93 | std::stringstream res; | ||
| 94 | res << "[Binary: "; | ||
| 95 | for (unsigned byte : binary) | ||
| 96 | res << std::hex << std::setw(2) << std::setfill('0') << byte; | ||
| 97 | res << ']'; | ||
| 98 | return res.str(); | ||
| 99 | } | ||
| 100 | case Char: | ||
| 101 | return "[Char: " + AsString() + ']'; | ||
| 102 | case Wchar: | ||
| 103 | return "[Wchar: " + AsString() + ']'; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | const std::string AsString() const { | ||
| 108 | switch (GetType()) { | ||
| 109 | case Char: | ||
| 110 | return string; | ||
| 111 | case Wchar: | ||
| 112 | return Common::UTF16ToUTF8(u16str); | ||
| 113 | case Empty: | ||
| 114 | return {}; | ||
| 115 | case Invalid: | ||
| 116 | case Binary: | ||
| 117 | // TODO(yuriks): Add assert | ||
| 118 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); | ||
| 119 | return {}; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | const std::u16string AsU16Str() const { | ||
| 124 | switch (GetType()) { | ||
| 125 | case Char: | ||
| 126 | return Common::UTF8ToUTF16(string); | ||
| 127 | case Wchar: | ||
| 128 | return u16str; | ||
| 129 | case Empty: | ||
| 130 | return {}; | ||
| 131 | case Invalid: | ||
| 132 | case Binary: | ||
| 133 | // TODO(yuriks): Add assert | ||
| 134 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); | ||
| 135 | return {}; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | const std::vector<u8> AsBinary() const { | ||
| 140 | switch (GetType()) { | ||
| 141 | case Binary: | ||
| 142 | return binary; | ||
| 143 | case Char: | ||
| 144 | return std::vector<u8>(string.begin(), string.end()); | ||
| 145 | case Wchar: | ||
| 146 | { | ||
| 147 | // use two u8 for each character of u16str | ||
| 148 | std::vector<u8> to_return(u16str.size() * 2); | ||
| 149 | for (size_t i = 0; i < u16str.size(); ++i) { | ||
| 150 | u16 tmp_char = u16str.at(i); | ||
| 151 | to_return[i*2] = (tmp_char & 0xFF00) >> 8; | ||
| 152 | to_return[i*2 + 1] = (tmp_char & 0x00FF); | ||
| 153 | } | ||
| 154 | return to_return; | ||
| 155 | } | ||
| 156 | case Empty: | ||
| 157 | return {}; | ||
| 158 | case Invalid: | ||
| 159 | // TODO(yuriks): Add assert | ||
| 160 | LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); | ||
| 161 | return {}; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | private: | ||
| 166 | LowPathType type; | ||
| 167 | std::vector<u8> binary; | ||
| 168 | std::string string; | ||
| 169 | std::u16string u16str; | ||
| 170 | }; | ||
| 171 | |||
| 172 | class ArchiveBackend : NonCopyable { | ||
| 173 | public: | ||
| 174 | virtual ~ArchiveBackend() { | ||
| 175 | } | ||
| 176 | |||
| 177 | /** | ||
| 178 | * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) | ||
| 179 | */ | ||
| 180 | virtual std::string GetName() const = 0; | ||
| 181 | |||
| 182 | /** | ||
| 183 | * Open a file specified by its path, using the specified mode | ||
| 184 | * @param path Path relative to the archive | ||
| 185 | * @param mode Mode to open the file with | ||
| 186 | * @return Opened file, or nullptr | ||
| 187 | */ | ||
| 188 | virtual std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const = 0; | ||
| 189 | |||
| 190 | /** | ||
| 191 | * Delete a file specified by its path | ||
| 192 | * @param path Path relative to the archive | ||
| 193 | * @return Whether the file could be deleted | ||
| 194 | */ | ||
| 195 | virtual bool DeleteFile(const Path& path) const = 0; | ||
| 196 | |||
| 197 | /** | ||
| 198 | * Rename a File specified by its path | ||
| 199 | * @param src_path Source path relative to the archive | ||
| 200 | * @param dest_path Destination path relative to the archive | ||
| 201 | * @return Whether rename succeeded | ||
| 202 | */ | ||
| 203 | virtual bool RenameFile(const Path& src_path, const Path& dest_path) const = 0; | ||
| 204 | |||
| 205 | /** | ||
| 206 | * Delete a directory specified by its path | ||
| 207 | * @param path Path relative to the archive | ||
| 208 | * @return Whether the directory could be deleted | ||
| 209 | */ | ||
| 210 | virtual bool DeleteDirectory(const Path& path) const = 0; | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Create a file specified by its path | ||
| 214 | * @param path Path relative to the Archive | ||
| 215 | * @param size The size of the new file, filled with zeroes | ||
| 216 | * @return File creation result code | ||
| 217 | */ | ||
| 218 | virtual ResultCode CreateFile(const Path& path, u32 size) const = 0; | ||
| 219 | |||
| 220 | /** | ||
| 221 | * Create a directory specified by its path | ||
| 222 | * @param path Path relative to the archive | ||
| 223 | * @return Whether the directory could be created | ||
| 224 | */ | ||
| 225 | virtual bool CreateDirectory(const Path& path) const = 0; | ||
| 226 | |||
| 227 | /** | ||
| 228 | * Rename a Directory specified by its path | ||
| 229 | * @param src_path Source path relative to the archive | ||
| 230 | * @param dest_path Destination path relative to the archive | ||
| 231 | * @return Whether rename succeeded | ||
| 232 | */ | ||
| 233 | virtual bool RenameDirectory(const Path& src_path, const Path& dest_path) const = 0; | ||
| 234 | |||
| 235 | /** | ||
| 236 | * Open a directory specified by its path | ||
| 237 | * @param path Path relative to the archive | ||
| 238 | * @return Opened directory, or nullptr | ||
| 239 | */ | ||
| 240 | virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0; | ||
| 241 | }; | ||
| 242 | |||
| 243 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp index 53dc57954..fdaf73179 100644 --- a/src/core/file_sys/archive_romfs.cpp +++ b/src/core/file_sys/archive_romfs.cpp | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <memory> | ||
| 6 | |||
| 5 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/make_unique.h" | ||
| 6 | 9 | ||
| 7 | #include "core/file_sys/archive_romfs.h" | 10 | #include "core/file_sys/archive_romfs.h" |
| 8 | #include "core/file_sys/directory_romfs.h" | 11 | #include "core/file_sys/directory_romfs.h" |
| @@ -16,101 +19,47 @@ namespace FileSys { | |||
| 16 | Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { | 19 | Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) { |
| 17 | // Load the RomFS from the app | 20 | // Load the RomFS from the app |
| 18 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(raw_data)) { | 21 | if (Loader::ResultStatus::Success != app_loader.ReadRomFS(raw_data)) { |
| 19 | WARN_LOG(FILESYS, "Unable to read RomFS!"); | 22 | LOG_ERROR(Service_FS, "Unable to read RomFS!"); |
| 20 | } | 23 | } |
| 21 | } | 24 | } |
| 22 | 25 | ||
| 23 | Archive_RomFS::~Archive_RomFS() { | 26 | std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { |
| 24 | } | 27 | return Common::make_unique<File_RomFS>(this); |
| 25 | |||
| 26 | /** | ||
| 27 | * Open a file specified by its path, using the specified mode | ||
| 28 | * @param path Path relative to the archive | ||
| 29 | * @param mode Mode to open the file with | ||
| 30 | * @return Opened file, or nullptr | ||
| 31 | */ | ||
| 32 | std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { | ||
| 33 | return std::unique_ptr<File>(new File_RomFS); | ||
| 34 | } | 28 | } |
| 35 | 29 | ||
| 36 | /** | 30 | bool Archive_RomFS::DeleteFile(const Path& path) const { |
| 37 | * Delete a file specified by its path | 31 | LOG_WARNING(Service_FS, "Attempted to delete a file from ROMFS."); |
| 38 | * @param path Path relative to the archive | ||
| 39 | * @return Whether the file could be deleted | ||
| 40 | */ | ||
| 41 | bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const { | ||
| 42 | ERROR_LOG(FILESYS, "Attempted to delete a file from ROMFS."); | ||
| 43 | return false; | 32 | return false; |
| 44 | } | 33 | } |
| 45 | 34 | ||
| 46 | /** | 35 | bool Archive_RomFS::RenameFile(const Path& src_path, const Path& dest_path) const { |
| 47 | * Delete a directory specified by its path | 36 | LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); |
| 48 | * @param path Path relative to the archive | ||
| 49 | * @return Whether the directory could be deleted | ||
| 50 | */ | ||
| 51 | bool Archive_RomFS::DeleteDirectory(const FileSys::Path& path) const { | ||
| 52 | ERROR_LOG(FILESYS, "Attempted to delete a directory from ROMFS."); | ||
| 53 | return false; | 37 | return false; |
| 54 | } | 38 | } |
| 55 | 39 | ||
| 56 | /** | 40 | bool Archive_RomFS::DeleteDirectory(const Path& path) const { |
| 57 | * Create a directory specified by its path | 41 | LOG_WARNING(Service_FS, "Attempted to delete a directory from ROMFS."); |
| 58 | * @param path Path relative to the archive | ||
| 59 | * @return Whether the directory could be created | ||
| 60 | */ | ||
| 61 | bool Archive_RomFS::CreateDirectory(const Path& path) const { | ||
| 62 | ERROR_LOG(FILESYS, "Attempted to create a directory in ROMFS."); | ||
| 63 | return false; | 42 | return false; |
| 64 | } | 43 | } |
| 65 | 44 | ||
| 66 | /** | 45 | ResultCode Archive_RomFS::CreateFile(const Path& path, u32 size) const { |
| 67 | * Open a directory specified by its path | 46 | LOG_WARNING(Service_FS, "Attempted to create a file in ROMFS."); |
| 68 | * @param path Path relative to the archive | 47 | // TODO: Verify error code |
| 69 | * @return Opened directory, or nullptr | 48 | return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); |
| 70 | */ | ||
| 71 | std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const { | ||
| 72 | return std::unique_ptr<Directory>(new Directory_RomFS); | ||
| 73 | } | 49 | } |
| 74 | 50 | ||
| 75 | /** | 51 | bool Archive_RomFS::CreateDirectory(const Path& path) const { |
| 76 | * Read data from the archive | 52 | LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS."); |
| 77 | * @param offset Offset in bytes to start reading data from | 53 | return false; |
| 78 | * @param length Length in bytes of data to read from archive | ||
| 79 | * @param buffer Buffer to read data into | ||
| 80 | * @return Number of bytes read | ||
| 81 | */ | ||
| 82 | size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 83 | DEBUG_LOG(FILESYS, "called offset=%llu, length=%d", offset, length); | ||
| 84 | memcpy(buffer, &raw_data[(u32)offset], length); | ||
| 85 | return length; | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Write data to the archive | ||
| 90 | * @param offset Offset in bytes to start writing data to | ||
| 91 | * @param length Length in bytes of data to write to archive | ||
| 92 | * @param buffer Buffer to write data from | ||
| 93 | * @param flush The flush parameters (0 == do not flush) | ||
| 94 | * @return Number of bytes written | ||
| 95 | */ | ||
| 96 | size_t Archive_RomFS::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 97 | ERROR_LOG(FILESYS, "Attempted to write to ROMFS."); | ||
| 98 | return 0; | ||
| 99 | } | 54 | } |
| 100 | 55 | ||
| 101 | /** | 56 | bool Archive_RomFS::RenameDirectory(const Path& src_path, const Path& dest_path) const { |
| 102 | * Get the size of the archive in bytes | 57 | LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); |
| 103 | * @return Size of the archive in bytes | 58 | return false; |
| 104 | */ | ||
| 105 | size_t Archive_RomFS::GetSize() const { | ||
| 106 | return sizeof(u8) * raw_data.size(); | ||
| 107 | } | 59 | } |
| 108 | 60 | ||
| 109 | /** | 61 | std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const { |
| 110 | * Set the size of the archive in bytes | 62 | return Common::make_unique<Directory_RomFS>(); |
| 111 | */ | ||
| 112 | void Archive_RomFS::SetSize(const u64 size) { | ||
| 113 | ERROR_LOG(FILESYS, "Attempted to set the size of ROMFS"); | ||
| 114 | } | 63 | } |
| 115 | 64 | ||
| 116 | } // namespace FileSys | 65 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h index 0649dde99..5e918f92d 100644 --- a/src/core/file_sys/archive_romfs.h +++ b/src/core/file_sys/archive_romfs.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | 10 | ||
| 11 | #include "core/file_sys/archive.h" | 11 | #include "core/file_sys/archive_backend.h" |
| 12 | #include "core/loader/loader.h" | 12 | #include "core/loader/loader.h" |
| 13 | 13 | ||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -17,16 +17,11 @@ | |||
| 17 | namespace FileSys { | 17 | namespace FileSys { |
| 18 | 18 | ||
| 19 | /// File system interface to the RomFS archive | 19 | /// File system interface to the RomFS archive |
| 20 | class Archive_RomFS final : public Archive { | 20 | class Archive_RomFS final : public ArchiveBackend { |
| 21 | public: | 21 | public: |
| 22 | Archive_RomFS(const Loader::AppLoader& app_loader); | 22 | Archive_RomFS(const Loader::AppLoader& app_loader); |
| 23 | ~Archive_RomFS() override; | ||
| 24 | 23 | ||
| 25 | /** | 24 | std::string GetName() const override { return "RomFS"; } |
| 26 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 27 | * @return IdCode of the archive | ||
| 28 | */ | ||
| 29 | IdCode GetIdCode() const override { return IdCode::RomFS; } | ||
| 30 | 25 | ||
| 31 | /** | 26 | /** |
| 32 | * Open a file specified by its path, using the specified mode | 27 | * Open a file specified by its path, using the specified mode |
| @@ -34,67 +29,63 @@ public: | |||
| 34 | * @param mode Mode to open the file with | 29 | * @param mode Mode to open the file with |
| 35 | * @return Opened file, or nullptr | 30 | * @return Opened file, or nullptr |
| 36 | */ | 31 | */ |
| 37 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | 32 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; |
| 38 | 33 | ||
| 39 | /** | 34 | /** |
| 40 | * Delete a file specified by its path | 35 | * Delete a file specified by its path |
| 41 | * @param path Path relative to the archive | 36 | * @param path Path relative to the archive |
| 42 | * @return Whether the file could be deleted | 37 | * @return Whether the file could be deleted |
| 43 | */ | 38 | */ |
| 44 | bool DeleteFile(const FileSys::Path& path) const override; | 39 | bool DeleteFile(const Path& path) const override; |
| 45 | |||
| 46 | /** | ||
| 47 | * Delete a directory specified by its path | ||
| 48 | * @param path Path relative to the archive | ||
| 49 | * @return Whether the directory could be deleted | ||
| 50 | */ | ||
| 51 | bool DeleteDirectory(const FileSys::Path& path) const override; | ||
| 52 | 40 | ||
| 53 | /** | 41 | /** |
| 54 | * Create a directory specified by its path | 42 | * Rename a File specified by its path |
| 55 | * @param path Path relative to the archive | 43 | * @param src_path Source path relative to the archive |
| 56 | * @return Whether the directory could be created | 44 | * @param dest_path Destination path relative to the archive |
| 45 | * @return Whether rename succeeded | ||
| 57 | */ | 46 | */ |
| 58 | bool CreateDirectory(const Path& path) const override; | 47 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; |
| 59 | 48 | ||
| 60 | /** | 49 | /** |
| 61 | * Open a directory specified by its path | 50 | * Delete a directory specified by its path |
| 62 | * @param path Path relative to the archive | 51 | * @param path Path relative to the archive |
| 63 | * @return Opened directory, or nullptr | 52 | * @return Whether the directory could be deleted |
| 64 | */ | 53 | */ |
| 65 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; | 54 | bool DeleteDirectory(const Path& path) const override; |
| 66 | 55 | ||
| 67 | /** | 56 | /** |
| 68 | * Read data from the archive | 57 | * Create a file specified by its path |
| 69 | * @param offset Offset in bytes to start reading data from | 58 | * @param path Path relative to the Archive |
| 70 | * @param length Length in bytes of data to read from archive | 59 | * @param size The size of the new file, filled with zeroes |
| 71 | * @param buffer Buffer to read data into | 60 | * @return File creation result code |
| 72 | * @return Number of bytes read | ||
| 73 | */ | 61 | */ |
| 74 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | 62 | ResultCode CreateFile(const Path& path, u32 size) const override; |
| 75 | 63 | ||
| 76 | /** | 64 | /** |
| 77 | * Write data to the archive | 65 | * Create a directory specified by its path |
| 78 | * @param offset Offset in bytes to start writing data to | 66 | * @param path Path relative to the archive |
| 79 | * @param length Length in bytes of data to write to archive | 67 | * @return Whether the directory could be created |
| 80 | * @param buffer Buffer to write data from | ||
| 81 | * @param flush The flush parameters (0 == do not flush) | ||
| 82 | * @return Number of bytes written | ||
| 83 | */ | 68 | */ |
| 84 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | 69 | bool CreateDirectory(const Path& path) const override; |
| 85 | 70 | ||
| 86 | /** | 71 | /** |
| 87 | * Get the size of the archive in bytes | 72 | * Rename a Directory specified by its path |
| 88 | * @return Size of the archive in bytes | 73 | * @param src_path Source path relative to the archive |
| 74 | * @param dest_path Destination path relative to the archive | ||
| 75 | * @return Whether rename succeeded | ||
| 89 | */ | 76 | */ |
| 90 | size_t GetSize() const override; | 77 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; |
| 91 | 78 | ||
| 92 | /** | 79 | /** |
| 93 | * Set the size of the archive in bytes | 80 | * Open a directory specified by its path |
| 81 | * @param path Path relative to the archive | ||
| 82 | * @return Opened directory, or nullptr | ||
| 94 | */ | 83 | */ |
| 95 | void SetSize(const u64 size) override; | 84 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; |
| 96 | 85 | ||
| 97 | private: | 86 | private: |
| 87 | friend class File_RomFS; | ||
| 88 | |||
| 98 | std::vector<u8> raw_data; | 89 | std::vector<u8> raw_data; |
| 99 | }; | 90 | }; |
| 100 | 91 | ||
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp new file mode 100644 index 000000000..97853567c --- /dev/null +++ b/src/core/file_sys/archive_savedata.cpp | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/archive_savedata.h" | ||
| 11 | #include "core/file_sys/disk_archive.h" | ||
| 12 | #include "core/settings.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | Archive_SaveData::Archive_SaveData(const std::string& mount_point, u64 program_id) | ||
| 20 | : DiskArchive(mount_point + Common::StringFromFormat("%016X", program_id) + DIR_SEP) { | ||
| 21 | LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); | ||
| 22 | } | ||
| 23 | |||
| 24 | bool Archive_SaveData::Initialize() { | ||
| 25 | if (!FileUtil::CreateFullPath(mount_point)) { | ||
| 26 | LOG_ERROR(Service_FS, "Unable to create SaveData path."); | ||
| 27 | return false; | ||
| 28 | } | ||
| 29 | |||
| 30 | return true; | ||
| 31 | } | ||
| 32 | |||
| 33 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h new file mode 100644 index 000000000..5b0ce29e6 --- /dev/null +++ b/src/core/file_sys/archive_savedata.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/disk_archive.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | /// File system interface to the SaveData archive | ||
| 18 | class Archive_SaveData final : public DiskArchive { | ||
| 19 | public: | ||
| 20 | Archive_SaveData(const std::string& mount_point, u64 program_id); | ||
| 21 | |||
| 22 | /** | ||
| 23 | * Initialize the archive. | ||
| 24 | * @return true if it initialized successfully | ||
| 25 | */ | ||
| 26 | bool Initialize(); | ||
| 27 | |||
| 28 | std::string GetName() const override { return "SaveData"; } | ||
| 29 | }; | ||
| 30 | |||
| 31 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp index c2ffcd40d..1c1c170b6 100644 --- a/src/core/file_sys/archive_sdmc.cpp +++ b/src/core/file_sys/archive_sdmc.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <sys/stat.h> | 5 | #include <sys/stat.h> |
| @@ -8,8 +8,7 @@ | |||
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | 9 | ||
| 10 | #include "core/file_sys/archive_sdmc.h" | 10 | #include "core/file_sys/archive_sdmc.h" |
| 11 | #include "core/file_sys/directory_sdmc.h" | 11 | #include "core/file_sys/disk_archive.h" |
| 12 | #include "core/file_sys/file_sdmc.h" | ||
| 13 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 14 | 13 | ||
| 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -17,131 +16,22 @@ | |||
| 17 | 16 | ||
| 18 | namespace FileSys { | 17 | namespace FileSys { |
| 19 | 18 | ||
| 20 | Archive_SDMC::Archive_SDMC(const std::string& mount_point) { | 19 | Archive_SDMC::Archive_SDMC(const std::string& mount_point) : DiskArchive(mount_point) { |
| 21 | this->mount_point = mount_point; | 20 | LOG_INFO(Service_FS, "Directory %s set as SDMC.", mount_point.c_str()); |
| 22 | DEBUG_LOG(FILESYS, "Directory %s set as SDMC.", mount_point.c_str()); | ||
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | Archive_SDMC::~Archive_SDMC() { | ||
| 26 | } | ||
| 27 | |||
| 28 | /** | ||
| 29 | * Initialize the archive. | ||
| 30 | * @return true if it initialized successfully | ||
| 31 | */ | ||
| 32 | bool Archive_SDMC::Initialize() { | 23 | bool Archive_SDMC::Initialize() { |
| 33 | if (!Settings::values.use_virtual_sd) { | 24 | if (!Settings::values.use_virtual_sd) { |
| 34 | WARN_LOG(FILESYS, "SDMC disabled by config."); | 25 | LOG_WARNING(Service_FS, "SDMC disabled by config."); |
| 35 | return false; | 26 | return false; |
| 36 | } | 27 | } |
| 37 | 28 | ||
| 38 | if (!FileUtil::CreateFullPath(mount_point)) { | 29 | if (!FileUtil::CreateFullPath(mount_point)) { |
| 39 | WARN_LOG(FILESYS, "Unable to create SDMC path."); | 30 | LOG_ERROR(Service_FS, "Unable to create SDMC path."); |
| 40 | return false; | 31 | return false; |
| 41 | } | 32 | } |
| 42 | 33 | ||
| 43 | return true; | 34 | return true; |
| 44 | } | 35 | } |
| 45 | 36 | ||
| 46 | /** | ||
| 47 | * Open a file specified by its path, using the specified mode | ||
| 48 | * @param path Path relative to the archive | ||
| 49 | * @param mode Mode to open the file with | ||
| 50 | * @return Opened file, or nullptr | ||
| 51 | */ | ||
| 52 | std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const { | ||
| 53 | DEBUG_LOG(FILESYS, "called path=%s mode=%d", path.DebugStr().c_str(), mode); | ||
| 54 | File_SDMC* file = new File_SDMC(this, path, mode); | ||
| 55 | if (!file->Open()) | ||
| 56 | return nullptr; | ||
| 57 | return std::unique_ptr<File>(file); | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * Delete a file specified by its path | ||
| 62 | * @param path Path relative to the archive | ||
| 63 | * @return Whether the file could be deleted | ||
| 64 | */ | ||
| 65 | bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const { | ||
| 66 | return FileUtil::Delete(GetMountPoint() + path.AsString()); | ||
| 67 | } | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Delete a directory specified by its path | ||
| 71 | * @param path Path relative to the archive | ||
| 72 | * @return Whether the directory could be deleted | ||
| 73 | */ | ||
| 74 | bool Archive_SDMC::DeleteDirectory(const FileSys::Path& path) const { | ||
| 75 | return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Create a directory specified by its path | ||
| 80 | * @param path Path relative to the archive | ||
| 81 | * @return Whether the directory could be created | ||
| 82 | */ | ||
| 83 | bool Archive_SDMC::CreateDirectory(const Path& path) const { | ||
| 84 | return FileUtil::CreateDir(GetMountPoint() + path.AsString()); | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Open a directory specified by its path | ||
| 89 | * @param path Path relative to the archive | ||
| 90 | * @return Opened directory, or nullptr | ||
| 91 | */ | ||
| 92 | std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const { | ||
| 93 | DEBUG_LOG(FILESYS, "called path=%s", path.DebugStr().c_str()); | ||
| 94 | Directory_SDMC* directory = new Directory_SDMC(this, path); | ||
| 95 | return std::unique_ptr<Directory>(directory); | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Read data from the archive | ||
| 100 | * @param offset Offset in bytes to start reading archive from | ||
| 101 | * @param length Length in bytes to read data from archive | ||
| 102 | * @param buffer Buffer to read data into | ||
| 103 | * @return Number of bytes read | ||
| 104 | */ | ||
| 105 | size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 106 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 107 | return -1; | ||
| 108 | } | ||
| 109 | |||
| 110 | /** | ||
| 111 | * Write data to the archive | ||
| 112 | * @param offset Offset in bytes to start writing data to | ||
| 113 | * @param length Length in bytes of data to write to archive | ||
| 114 | * @param buffer Buffer to write data from | ||
| 115 | * @param flush The flush parameters (0 == do not flush) | ||
| 116 | * @return Number of bytes written | ||
| 117 | */ | ||
| 118 | size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) { | ||
| 119 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 120 | return -1; | ||
| 121 | } | ||
| 122 | |||
| 123 | /** | ||
| 124 | * Get the size of the archive in bytes | ||
| 125 | * @return Size of the archive in bytes | ||
| 126 | */ | ||
| 127 | size_t Archive_SDMC::GetSize() const { | ||
| 128 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Set the size of the archive in bytes | ||
| 134 | */ | ||
| 135 | void Archive_SDMC::SetSize(const u64 size) { | ||
| 136 | ERROR_LOG(FILESYS, "(UNIMPLEMENTED)"); | ||
| 137 | } | ||
| 138 | |||
| 139 | /** | ||
| 140 | * Getter for the path used for this Archive | ||
| 141 | * @return Mount point of that passthrough archive | ||
| 142 | */ | ||
| 143 | std::string Archive_SDMC::GetMountPoint() const { | ||
| 144 | return mount_point; | ||
| 145 | } | ||
| 146 | |||
| 147 | } // namespace FileSys | 37 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h index 74ce29c0d..1b801f217 100644 --- a/src/core/file_sys/archive_sdmc.h +++ b/src/core/file_sys/archive_sdmc.h | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/disk_archive.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -15,10 +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 Archive { | 18 | class Archive_SDMC final : public DiskArchive { |
| 19 | public: | 19 | public: |
| 20 | Archive_SDMC(const std::string& mount_point); | 20 | Archive_SDMC(const std::string& mount_point); |
| 21 | ~Archive_SDMC() override; | ||
| 22 | 21 | ||
| 23 | /** | 22 | /** |
| 24 | * Initialize the archive. | 23 | * Initialize the archive. |
| @@ -26,86 +25,7 @@ public: | |||
| 26 | */ | 25 | */ |
| 27 | bool Initialize(); | 26 | bool Initialize(); |
| 28 | 27 | ||
| 29 | /** | 28 | std::string GetName() const override { return "SDMC"; } |
| 30 | * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.) | ||
| 31 | * @return IdCode of the archive | ||
| 32 | */ | ||
| 33 | IdCode GetIdCode() const override { return IdCode::SDMC; } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Open a file specified by its path, using the specified mode | ||
| 37 | * @param path Path relative to the archive | ||
| 38 | * @param mode Mode to open the file with | ||
| 39 | * @return Opened file, or nullptr | ||
| 40 | */ | ||
| 41 | std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Delete a file specified by its path | ||
| 45 | * @param path Path relative to the archive | ||
| 46 | * @return Whether the file could be deleted | ||
| 47 | */ | ||
| 48 | bool DeleteFile(const FileSys::Path& path) const override; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Delete a directory specified by its path | ||
| 52 | * @param path Path relative to the archive | ||
| 53 | * @return Whether the directory could be deleted | ||
| 54 | */ | ||
| 55 | bool DeleteDirectory(const FileSys::Path& path) const override; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Create a directory specified by its path | ||
| 59 | * @param path Path relative to the archive | ||
| 60 | * @return Whether the directory could be created | ||
| 61 | */ | ||
| 62 | bool CreateDirectory(const Path& path) const override; | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Open a directory specified by its path | ||
| 66 | * @param path Path relative to the archive | ||
| 67 | * @return Opened directory, or nullptr | ||
| 68 | */ | ||
| 69 | std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Read data from the archive | ||
| 73 | * @param offset Offset in bytes to start reading archive from | ||
| 74 | * @param length Length in bytes to read data from archive | ||
| 75 | * @param buffer Buffer to read data into | ||
| 76 | * @return Number of bytes read | ||
| 77 | */ | ||
| 78 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Write data to the archive | ||
| 82 | * @param offset Offset in bytes to start writing data to | ||
| 83 | * @param length Length in bytes of data to write to archive | ||
| 84 | * @param buffer Buffer to write data from | ||
| 85 | * @param flush The flush parameters (0 == do not flush) | ||
| 86 | * @return Number of bytes written | ||
| 87 | */ | ||
| 88 | size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Get the size of the archive in bytes | ||
| 92 | * @return Size of the archive in bytes | ||
| 93 | */ | ||
| 94 | size_t GetSize() const override; | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Set the size of the archive in bytes | ||
| 98 | */ | ||
| 99 | void SetSize(const u64 size) override; | ||
| 100 | |||
| 101 | /** | ||
| 102 | * Getter for the path used for this Archive | ||
| 103 | * @return Mount point of that passthrough archive | ||
| 104 | */ | ||
| 105 | std::string GetMountPoint() const; | ||
| 106 | |||
| 107 | private: | ||
| 108 | std::string mount_point; | ||
| 109 | }; | 29 | }; |
| 110 | 30 | ||
| 111 | } // namespace FileSys | 31 | } // namespace FileSys |
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp new file mode 100644 index 000000000..0da32d510 --- /dev/null +++ b/src/core/file_sys/archive_systemsavedata.cpp | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/archive_systemsavedata.h" | ||
| 11 | #include "core/file_sys/disk_archive.h" | ||
| 12 | #include "core/settings.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | static std::string GetSystemSaveDataPath(const std::string& mount_point, u64 save_id) { | ||
| 20 | u32 save_high = static_cast<u32>((save_id >> 32) & 0xFFFFFFFF); | ||
| 21 | u32 save_low = static_cast<u32>(save_id & 0xFFFFFFFF); | ||
| 22 | return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high); | ||
| 23 | } | ||
| 24 | |||
| 25 | Archive_SystemSaveData::Archive_SystemSaveData(const std::string& mount_point, u64 save_id) | ||
| 26 | : DiskArchive(GetSystemSaveDataPath(mount_point, save_id)) { | ||
| 27 | LOG_INFO(Service_FS, "Directory %s set as SystemSaveData.", this->mount_point.c_str()); | ||
| 28 | } | ||
| 29 | |||
| 30 | bool Archive_SystemSaveData::Initialize() { | ||
| 31 | if (!FileUtil::CreateFullPath(mount_point)) { | ||
| 32 | LOG_ERROR(Service_FS, "Unable to create SystemSaveData path."); | ||
| 33 | return false; | ||
| 34 | } | ||
| 35 | |||
| 36 | return true; | ||
| 37 | } | ||
| 38 | |||
| 39 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h new file mode 100644 index 000000000..55d85193c --- /dev/null +++ b/src/core/file_sys/archive_systemsavedata.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | #include "core/file_sys/disk_archive.h" | ||
| 10 | #include "core/loader/loader.h" | ||
| 11 | |||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 13 | // FileSys namespace | ||
| 14 | |||
| 15 | namespace FileSys { | ||
| 16 | |||
| 17 | /// File system interface to the SystemSaveData archive | ||
| 18 | /// TODO(Subv): This archive should point to a location in the NAND, | ||
| 19 | /// specifically nand:/data/<ID0>/sysdata/<SaveID-Low>/<SaveID-High> | ||
| 20 | class Archive_SystemSaveData final : public DiskArchive { | ||
| 21 | public: | ||
| 22 | Archive_SystemSaveData(const std::string& mount_point, u64 save_id); | ||
| 23 | |||
| 24 | /** | ||
| 25 | * Initialize the archive. | ||
| 26 | * @return true if it initialized successfully | ||
| 27 | */ | ||
| 28 | bool Initialize(); | ||
| 29 | |||
| 30 | std::string GetName() const override { return "SystemSaveData"; } | ||
| 31 | }; | ||
| 32 | |||
| 33 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory_backend.h index e10431337..7f327dc42 100644 --- a/src/core/file_sys/directory.h +++ b/src/core/file_sys/directory_backend.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| @@ -36,10 +36,16 @@ static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension i | |||
| 36 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); | 36 | static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); |
| 37 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); | 37 | static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); |
| 38 | 38 | ||
| 39 | class Directory : NonCopyable { | 39 | class DirectoryBackend : NonCopyable { |
| 40 | public: | 40 | public: |
| 41 | Directory() { } | 41 | DirectoryBackend() { } |
| 42 | virtual ~Directory() { } | 42 | virtual ~DirectoryBackend() { } |
| 43 | |||
| 44 | /** | ||
| 45 | * Open the directory | ||
| 46 | * @return true if the directory opened correctly | ||
| 47 | */ | ||
| 48 | virtual bool Open() = 0; | ||
| 43 | 49 | ||
| 44 | /** | 50 | /** |
| 45 | * List files contained in the directory | 51 | * List files contained in the directory |
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp index 4e8f4c04d..e130aca17 100644 --- a/src/core/file_sys/directory_romfs.cpp +++ b/src/core/file_sys/directory_romfs.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| @@ -17,20 +17,14 @@ Directory_RomFS::Directory_RomFS() { | |||
| 17 | Directory_RomFS::~Directory_RomFS() { | 17 | Directory_RomFS::~Directory_RomFS() { |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | /** | 20 | bool Directory_RomFS::Open() { |
| 21 | * List files contained in the directory | 21 | return false; |
| 22 | * @param count Number of entries to return at once in entries | 22 | } |
| 23 | * @param entries Buffer to read data into | 23 | |
| 24 | * @return Number of entries listed | ||
| 25 | */ | ||
| 26 | u32 Directory_RomFS::Read(const u32 count, Entry* entries) { | 24 | u32 Directory_RomFS::Read(const u32 count, Entry* entries) { |
| 27 | return 0; | 25 | return 0; |
| 28 | } | 26 | } |
| 29 | 27 | ||
| 30 | /** | ||
| 31 | * Close the directory | ||
| 32 | * @return true if the directory closed correctly | ||
| 33 | */ | ||
| 34 | bool Directory_RomFS::Close() const { | 28 | bool Directory_RomFS::Close() const { |
| 35 | return false; | 29 | return false; |
| 36 | } | 30 | } |
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h index 4b71c4b13..2297f1645 100644 --- a/src/core/file_sys/directory_romfs.h +++ b/src/core/file_sys/directory_romfs.h | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/directory.h" | 9 | #include "core/file_sys/directory_backend.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -14,12 +14,18 @@ | |||
| 14 | 14 | ||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | class Directory_RomFS final : public Directory { | 17 | class Directory_RomFS final : public DirectoryBackend { |
| 18 | public: | 18 | public: |
| 19 | Directory_RomFS(); | 19 | Directory_RomFS(); |
| 20 | ~Directory_RomFS() override; | 20 | ~Directory_RomFS() override; |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * Open the directory | ||
| 24 | * @return true if the directory opened correctly | ||
| 25 | */ | ||
| 26 | bool Open() override; | ||
| 27 | |||
| 28 | /** | ||
| 23 | * List files contained in the directory | 29 | * List files contained in the directory |
| 24 | * @param count Number of entries to return at once in entries | 30 | * @param count Number of entries to return at once in entries |
| 25 | * @param entries Buffer to read data into | 31 | * @param entries Buffer to read data into |
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp deleted file mode 100644 index 60a197ce9..000000000 --- a/src/core/file_sys/directory_sdmc.cpp +++ /dev/null | |||
| @@ -1,81 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const Path& path) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | ||
| 22 | std::string absolute_path = archive->GetMountPoint() + path.AsString(); | ||
| 23 | FileUtil::ScanDirectoryTree(absolute_path, directory); | ||
| 24 | children_iterator = directory.children.begin(); | ||
| 25 | } | ||
| 26 | |||
| 27 | Directory_SDMC::~Directory_SDMC() { | ||
| 28 | Close(); | ||
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * List files contained in the directory | ||
| 33 | * @param count Number of entries to return at once in entries | ||
| 34 | * @param entries Buffer to read data into | ||
| 35 | * @return Number of entries listed | ||
| 36 | */ | ||
| 37 | u32 Directory_SDMC::Read(const u32 count, Entry* entries) { | ||
| 38 | u32 entries_read = 0; | ||
| 39 | |||
| 40 | while (entries_read < count && children_iterator != directory.children.cend()) { | ||
| 41 | const FileUtil::FSTEntry& file = *children_iterator; | ||
| 42 | const std::string& filename = file.virtualName; | ||
| 43 | Entry& entry = entries[entries_read]; | ||
| 44 | |||
| 45 | WARN_LOG(FILESYS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); | ||
| 46 | |||
| 47 | // TODO(Link Mauve): use a proper conversion to UTF-16. | ||
| 48 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { | ||
| 49 | entry.filename[j] = filename[j]; | ||
| 50 | if (!filename[j]) | ||
| 51 | break; | ||
| 52 | } | ||
| 53 | |||
| 54 | FileUtil::SplitFilename83(filename, entry.short_name, entry.extension); | ||
| 55 | |||
| 56 | entry.is_directory = file.isDirectory; | ||
| 57 | entry.is_hidden = (filename[0] == '.'); | ||
| 58 | entry.is_read_only = 0; | ||
| 59 | entry.file_size = file.size; | ||
| 60 | |||
| 61 | // We emulate a SD card where the archive bit has never been cleared, as it would be on | ||
| 62 | // most user SD cards. | ||
| 63 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | ||
| 64 | // file bit. | ||
| 65 | entry.is_archive = !file.isDirectory; | ||
| 66 | |||
| 67 | ++entries_read; | ||
| 68 | ++children_iterator; | ||
| 69 | } | ||
| 70 | return entries_read; | ||
| 71 | } | ||
| 72 | |||
| 73 | /** | ||
| 74 | * Close the directory | ||
| 75 | * @return true if the directory closed correctly | ||
| 76 | */ | ||
| 77 | bool Directory_SDMC::Close() const { | ||
| 78 | return true; | ||
| 79 | } | ||
| 80 | |||
| 81 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h deleted file mode 100644 index 4520d0401..000000000 --- a/src/core/file_sys/directory_sdmc.h +++ /dev/null | |||
| @@ -1,48 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/directory.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class Directory_SDMC final : public Directory { | ||
| 20 | public: | ||
| 21 | Directory_SDMC(); | ||
| 22 | Directory_SDMC(const Archive_SDMC* archive, const Path& path); | ||
| 23 | ~Directory_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * List files contained in the directory | ||
| 27 | * @param count Number of entries to return at once in entries | ||
| 28 | * @param entries Buffer to read data into | ||
| 29 | * @return Number of entries listed | ||
| 30 | */ | ||
| 31 | u32 Read(const u32 count, Entry* entries) override; | ||
| 32 | |||
| 33 | /** | ||
| 34 | * Close the directory | ||
| 35 | * @return true if the directory closed correctly | ||
| 36 | */ | ||
| 37 | bool Close() const override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | u32 total_entries_in_directory; | ||
| 41 | FileUtil::FSTEntry directory; | ||
| 42 | |||
| 43 | // We need to remember the last entry we returned, so a subsequent call to Read will continue | ||
| 44 | // from the next one. This iterator will always point to the next unread entry. | ||
| 45 | std::vector<FileUtil::FSTEntry>::iterator children_iterator; | ||
| 46 | }; | ||
| 47 | |||
| 48 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp new file mode 100644 index 000000000..0197f727d --- /dev/null +++ b/src/core/file_sys/disk_archive.cpp | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/disk_archive.h" | ||
| 11 | #include "core/settings.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const { | ||
| 19 | LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); | ||
| 20 | DiskFile* file = new DiskFile(this, path, mode); | ||
| 21 | if (!file->Open()) | ||
| 22 | return nullptr; | ||
| 23 | return std::unique_ptr<FileBackend>(file); | ||
| 24 | } | ||
| 25 | |||
| 26 | bool DiskArchive::DeleteFile(const Path& path) const { | ||
| 27 | return FileUtil::Delete(GetMountPoint() + path.AsString()); | ||
| 28 | } | ||
| 29 | |||
| 30 | bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { | ||
| 31 | return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); | ||
| 32 | } | ||
| 33 | |||
| 34 | bool DiskArchive::DeleteDirectory(const Path& path) const { | ||
| 35 | return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); | ||
| 36 | } | ||
| 37 | |||
| 38 | ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const { | ||
| 39 | std::string full_path = GetMountPoint() + path.AsString(); | ||
| 40 | |||
| 41 | if (FileUtil::Exists(full_path)) | ||
| 42 | return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info); | ||
| 43 | |||
| 44 | if (size == 0) { | ||
| 45 | FileUtil::CreateEmptyFile(full_path); | ||
| 46 | return RESULT_SUCCESS; | ||
| 47 | } | ||
| 48 | |||
| 49 | FileUtil::IOFile file(full_path, "wb"); | ||
| 50 | // Creates a sparse file (or a normal file on filesystems without the concept of sparse files) | ||
| 51 | // We do this by seeking to the right size, then writing a single null byte. | ||
| 52 | if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) | ||
| 53 | return RESULT_SUCCESS; | ||
| 54 | |||
| 55 | return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, ErrorLevel::Info); | ||
| 56 | } | ||
| 57 | |||
| 58 | |||
| 59 | bool DiskArchive::CreateDirectory(const Path& path) const { | ||
| 60 | return FileUtil::CreateDir(GetMountPoint() + path.AsString()); | ||
| 61 | } | ||
| 62 | |||
| 63 | bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { | ||
| 64 | return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); | ||
| 65 | } | ||
| 66 | |||
| 67 | std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const { | ||
| 68 | LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str()); | ||
| 69 | DiskDirectory* directory = new DiskDirectory(this, path); | ||
| 70 | if (!directory->Open()) | ||
| 71 | return nullptr; | ||
| 72 | return std::unique_ptr<DirectoryBackend>(directory); | ||
| 73 | } | ||
| 74 | |||
| 75 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 76 | |||
| 77 | DiskFile::DiskFile(const DiskArchive* archive, const Path& path, const Mode mode) { | ||
| 78 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 79 | // the root directory we set while opening the archive. | ||
| 80 | // For example, opening /../../etc/passwd can give the emulated program your users list. | ||
| 81 | this->path = archive->GetMountPoint() + path.AsString(); | ||
| 82 | this->mode.hex = mode.hex; | ||
| 83 | this->archive = archive; | ||
| 84 | } | ||
| 85 | |||
| 86 | bool DiskFile::Open() { | ||
| 87 | if (!mode.create_flag && !FileUtil::Exists(path)) { | ||
| 88 | LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str()); | ||
| 89 | return false; | ||
| 90 | } | ||
| 91 | |||
| 92 | std::string mode_string; | ||
| 93 | if (mode.create_flag) | ||
| 94 | mode_string = "w+"; | ||
| 95 | else if (mode.write_flag) | ||
| 96 | mode_string = "r+"; // Files opened with Write access can be read from | ||
| 97 | else if (mode.read_flag) | ||
| 98 | mode_string = "r"; | ||
| 99 | |||
| 100 | // Open the file in binary mode, to avoid problems with CR/LF on Windows systems | ||
| 101 | mode_string += "b"; | ||
| 102 | |||
| 103 | file = new FileUtil::IOFile(path, mode_string.c_str()); | ||
| 104 | return true; | ||
| 105 | } | ||
| 106 | |||
| 107 | size_t DiskFile::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 108 | file->Seek(offset, SEEK_SET); | ||
| 109 | return file->ReadBytes(buffer, length); | ||
| 110 | } | ||
| 111 | |||
| 112 | size_t DiskFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 113 | file->Seek(offset, SEEK_SET); | ||
| 114 | size_t written = file->WriteBytes(buffer, length); | ||
| 115 | if (flush) | ||
| 116 | file->Flush(); | ||
| 117 | return written; | ||
| 118 | } | ||
| 119 | |||
| 120 | size_t DiskFile::GetSize() const { | ||
| 121 | return static_cast<size_t>(file->GetSize()); | ||
| 122 | } | ||
| 123 | |||
| 124 | bool DiskFile::SetSize(const u64 size) const { | ||
| 125 | file->Resize(size); | ||
| 126 | file->Flush(); | ||
| 127 | return true; | ||
| 128 | } | ||
| 129 | |||
| 130 | bool DiskFile::Close() const { | ||
| 131 | return file->Close(); | ||
| 132 | } | ||
| 133 | |||
| 134 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 135 | |||
| 136 | DiskDirectory::DiskDirectory(const DiskArchive* archive, const Path& path) { | ||
| 137 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 138 | // the root directory we set while opening the archive. | ||
| 139 | // For example, opening /../../usr/bin can give the emulated program your installed programs. | ||
| 140 | this->path = archive->GetMountPoint() + path.AsString(); | ||
| 141 | this->archive = archive; | ||
| 142 | } | ||
| 143 | |||
| 144 | bool DiskDirectory::Open() { | ||
| 145 | if (!FileUtil::IsDirectory(path)) | ||
| 146 | return false; | ||
| 147 | FileUtil::ScanDirectoryTree(path, directory); | ||
| 148 | children_iterator = directory.children.begin(); | ||
| 149 | return true; | ||
| 150 | } | ||
| 151 | |||
| 152 | u32 DiskDirectory::Read(const u32 count, Entry* entries) { | ||
| 153 | u32 entries_read = 0; | ||
| 154 | |||
| 155 | while (entries_read < count && children_iterator != directory.children.cend()) { | ||
| 156 | const FileUtil::FSTEntry& file = *children_iterator; | ||
| 157 | const std::string& filename = file.virtualName; | ||
| 158 | Entry& entry = entries[entries_read]; | ||
| 159 | |||
| 160 | LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); | ||
| 161 | |||
| 162 | // TODO(Link Mauve): use a proper conversion to UTF-16. | ||
| 163 | for (size_t j = 0; j < FILENAME_LENGTH; ++j) { | ||
| 164 | entry.filename[j] = filename[j]; | ||
| 165 | if (!filename[j]) | ||
| 166 | break; | ||
| 167 | } | ||
| 168 | |||
| 169 | FileUtil::SplitFilename83(filename, entry.short_name, entry.extension); | ||
| 170 | |||
| 171 | entry.is_directory = file.isDirectory; | ||
| 172 | entry.is_hidden = (filename[0] == '.'); | ||
| 173 | entry.is_read_only = 0; | ||
| 174 | entry.file_size = file.size; | ||
| 175 | |||
| 176 | // We emulate a SD card where the archive bit has never been cleared, as it would be on | ||
| 177 | // most user SD cards. | ||
| 178 | // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a | ||
| 179 | // file bit. | ||
| 180 | entry.is_archive = !file.isDirectory; | ||
| 181 | |||
| 182 | ++entries_read; | ||
| 183 | ++children_iterator; | ||
| 184 | } | ||
| 185 | return entries_read; | ||
| 186 | } | ||
| 187 | |||
| 188 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h new file mode 100644 index 000000000..018ebd2ed --- /dev/null +++ b/src/core/file_sys/disk_archive.h | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/archive_backend.h" | ||
| 11 | #include "core/loader/loader.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | /** | ||
| 19 | * Helper which implements a backend accessing the host machine's filesystem. | ||
| 20 | * This should be subclassed by concrete archive types, which will provide the | ||
| 21 | * base directory on the host filesystem and override any required functionality. | ||
| 22 | */ | ||
| 23 | class DiskArchive : public ArchiveBackend { | ||
| 24 | public: | ||
| 25 | DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} | ||
| 26 | |||
| 27 | virtual std::string GetName() const = 0; | ||
| 28 | std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; | ||
| 29 | bool DeleteFile(const Path& path) const override; | ||
| 30 | bool RenameFile(const Path& src_path, const Path& dest_path) const override; | ||
| 31 | bool DeleteDirectory(const Path& path) const override; | ||
| 32 | ResultCode CreateFile(const Path& path, u32 size) const override; | ||
| 33 | bool CreateDirectory(const Path& path) const override; | ||
| 34 | bool RenameDirectory(const Path& src_path, const Path& dest_path) const override; | ||
| 35 | std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override; | ||
| 36 | |||
| 37 | /** | ||
| 38 | * Getter for the path used for this Archive | ||
| 39 | * @return Mount point of that passthrough archive | ||
| 40 | */ | ||
| 41 | const std::string& GetMountPoint() const { | ||
| 42 | return mount_point; | ||
| 43 | } | ||
| 44 | |||
| 45 | protected: | ||
| 46 | std::string mount_point; | ||
| 47 | }; | ||
| 48 | |||
| 49 | class DiskFile : public FileBackend { | ||
| 50 | public: | ||
| 51 | DiskFile(); | ||
| 52 | DiskFile(const DiskArchive* archive, const Path& path, const Mode mode); | ||
| 53 | |||
| 54 | ~DiskFile() override { | ||
| 55 | Close(); | ||
| 56 | } | ||
| 57 | |||
| 58 | bool Open() override; | ||
| 59 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 60 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 61 | size_t GetSize() const override; | ||
| 62 | bool SetSize(const u64 size) const override; | ||
| 63 | bool Close() const override; | ||
| 64 | |||
| 65 | void Flush() const override { | ||
| 66 | file->Flush(); | ||
| 67 | } | ||
| 68 | |||
| 69 | protected: | ||
| 70 | const DiskArchive* archive; | ||
| 71 | std::string path; | ||
| 72 | Mode mode; | ||
| 73 | FileUtil::IOFile* file; | ||
| 74 | }; | ||
| 75 | |||
| 76 | class DiskDirectory : public DirectoryBackend { | ||
| 77 | public: | ||
| 78 | DiskDirectory(); | ||
| 79 | DiskDirectory(const DiskArchive* archive, const Path& path); | ||
| 80 | |||
| 81 | ~DiskDirectory() override { | ||
| 82 | Close(); | ||
| 83 | } | ||
| 84 | |||
| 85 | bool Open() override; | ||
| 86 | u32 Read(const u32 count, Entry* entries) override; | ||
| 87 | |||
| 88 | bool Close() const override { | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | |||
| 92 | protected: | ||
| 93 | const DiskArchive* archive; | ||
| 94 | std::string path; | ||
| 95 | u32 total_entries_in_directory; | ||
| 96 | FileUtil::FSTEntry directory; | ||
| 97 | |||
| 98 | // We need to remember the last entry we returned, so a subsequent call to Read will continue | ||
| 99 | // from the next one. This iterator will always point to the next unread entry. | ||
| 100 | std::vector<FileUtil::FSTEntry>::iterator children_iterator; | ||
| 101 | }; | ||
| 102 | |||
| 103 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file_backend.h index 4013b6c3e..35890af1f 100644 --- a/src/core/file_sys/file.h +++ b/src/core/file_sys/file_backend.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| @@ -13,10 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | namespace FileSys { | 14 | namespace FileSys { |
| 15 | 15 | ||
| 16 | class File : NonCopyable { | 16 | class FileBackend : NonCopyable { |
| 17 | public: | 17 | public: |
| 18 | File() { } | 18 | FileBackend() { } |
| 19 | virtual ~File() { } | 19 | virtual ~FileBackend() { } |
| 20 | 20 | ||
| 21 | /** | 21 | /** |
| 22 | * Open the file | 22 | * Open the file |
| @@ -61,6 +61,11 @@ public: | |||
| 61 | * @return true if the file closed correctly | 61 | * @return true if the file closed correctly |
| 62 | */ | 62 | */ |
| 63 | virtual bool Close() const = 0; | 63 | virtual bool Close() const = 0; |
| 64 | |||
| 65 | /** | ||
| 66 | * Flushes the file | ||
| 67 | */ | ||
| 68 | virtual void Flush() const = 0; | ||
| 64 | }; | 69 | }; |
| 65 | 70 | ||
| 66 | } // namespace FileSys | 71 | } // namespace FileSys |
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp index b55708df4..7467d6d31 100644 --- a/src/core/file_sys/file_romfs.cpp +++ b/src/core/file_sys/file_romfs.cpp | |||
| @@ -1,74 +1,41 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "common/common_types.h" | 5 | #include "common/common_types.h" |
| 6 | 6 | ||
| 7 | #include "core/file_sys/file_romfs.h" | 7 | #include "core/file_sys/file_romfs.h" |
| 8 | #include "core/file_sys/archive_romfs.h" | ||
| 8 | 9 | ||
| 9 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 10 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 10 | // FileSys namespace | 11 | // FileSys namespace |
| 11 | 12 | ||
| 12 | namespace FileSys { | 13 | namespace FileSys { |
| 13 | 14 | ||
| 14 | File_RomFS::File_RomFS() { | ||
| 15 | } | ||
| 16 | |||
| 17 | File_RomFS::~File_RomFS() { | ||
| 18 | } | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Open the file | ||
| 22 | * @return true if the file opened correctly | ||
| 23 | */ | ||
| 24 | bool File_RomFS::Open() { | 15 | bool File_RomFS::Open() { |
| 25 | return false; | 16 | return true; |
| 26 | } | 17 | } |
| 27 | 18 | ||
| 28 | /** | ||
| 29 | * Read data from the file | ||
| 30 | * @param offset Offset in bytes to start reading data from | ||
| 31 | * @param length Length in bytes of data to read from file | ||
| 32 | * @param buffer Buffer to read data into | ||
| 33 | * @return Number of bytes read | ||
| 34 | */ | ||
| 35 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { | 19 | size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { |
| 36 | return -1; | 20 | LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); |
| 21 | memcpy(buffer, &archive->raw_data[(u32)offset], length); | ||
| 22 | return length; | ||
| 37 | } | 23 | } |
| 38 | 24 | ||
| 39 | /** | ||
| 40 | * Write data to the file | ||
| 41 | * @param offset Offset in bytes to start writing data to | ||
| 42 | * @param length Length in bytes of data to write to file | ||
| 43 | * @param flush The flush parameters (0 == do not flush) | ||
| 44 | * @param buffer Buffer to read data from | ||
| 45 | * @return Number of bytes written | ||
| 46 | */ | ||
| 47 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | 25 | size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { |
| 48 | return -1; | 26 | LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); |
| 27 | return 0; | ||
| 49 | } | 28 | } |
| 50 | 29 | ||
| 51 | /** | ||
| 52 | * Get the size of the file in bytes | ||
| 53 | * @return Size of the file in bytes | ||
| 54 | */ | ||
| 55 | size_t File_RomFS::GetSize() const { | 30 | size_t File_RomFS::GetSize() const { |
| 56 | return -1; | 31 | return sizeof(u8) * archive->raw_data.size(); |
| 57 | } | 32 | } |
| 58 | 33 | ||
| 59 | /** | ||
| 60 | * Set the size of the file in bytes | ||
| 61 | * @param size New size of the file | ||
| 62 | * @return true if successful | ||
| 63 | */ | ||
| 64 | bool File_RomFS::SetSize(const u64 size) const { | 34 | bool File_RomFS::SetSize(const u64 size) const { |
| 35 | LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); | ||
| 65 | return false; | 36 | return false; |
| 66 | } | 37 | } |
| 67 | 38 | ||
| 68 | /** | ||
| 69 | * Close the file | ||
| 70 | * @return true if the file closed correctly | ||
| 71 | */ | ||
| 72 | bool File_RomFS::Close() const { | 39 | bool File_RomFS::Close() const { |
| 73 | return false; | 40 | return false; |
| 74 | } | 41 | } |
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h index 5196701d3..04d8a16a2 100644 --- a/src/core/file_sys/file_romfs.h +++ b/src/core/file_sys/file_romfs.h | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | 8 | ||
| 9 | #include "core/file_sys/file.h" | 9 | #include "core/file_sys/file_backend.h" |
| 10 | #include "core/loader/loader.h" | 10 | #include "core/loader/loader.h" |
| 11 | 11 | ||
| 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 12 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -14,10 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | namespace FileSys { | 15 | namespace FileSys { |
| 16 | 16 | ||
| 17 | class File_RomFS final : public File { | 17 | class Archive_RomFS; |
| 18 | |||
| 19 | class File_RomFS final : public FileBackend { | ||
| 18 | public: | 20 | public: |
| 19 | File_RomFS(); | 21 | File_RomFS(const Archive_RomFS* archive) : archive(archive) {} |
| 20 | ~File_RomFS() override; | ||
| 21 | 22 | ||
| 22 | /** | 23 | /** |
| 23 | * Open the file | 24 | * Open the file |
| @@ -62,6 +63,11 @@ public: | |||
| 62 | * @return true if the file closed correctly | 63 | * @return true if the file closed correctly |
| 63 | */ | 64 | */ |
| 64 | bool Close() const override; | 65 | bool Close() const override; |
| 66 | |||
| 67 | void Flush() const override { } | ||
| 68 | |||
| 69 | private: | ||
| 70 | const Archive_RomFS* archive; | ||
| 65 | }; | 71 | }; |
| 66 | 72 | ||
| 67 | } // namespace FileSys | 73 | } // namespace FileSys |
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp deleted file mode 100644 index a4b90670a..000000000 --- a/src/core/file_sys/file_sdmc.cpp +++ /dev/null | |||
| @@ -1,107 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <sys/stat.h> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file_sdmc.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | |||
| 13 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 14 | // FileSys namespace | ||
| 15 | |||
| 16 | namespace FileSys { | ||
| 17 | |||
| 18 | File_SDMC::File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode) { | ||
| 19 | // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass | ||
| 20 | // the root directory we set while opening the archive. | ||
| 21 | // For example, opening /../../etc/passwd can give the emulated program your users list. | ||
| 22 | this->path = archive->GetMountPoint() + path.AsString(); | ||
| 23 | this->mode.hex = mode.hex; | ||
| 24 | } | ||
| 25 | |||
| 26 | File_SDMC::~File_SDMC() { | ||
| 27 | Close(); | ||
| 28 | } | ||
| 29 | |||
| 30 | /** | ||
| 31 | * Open the file | ||
| 32 | * @return true if the file opened correctly | ||
| 33 | */ | ||
| 34 | bool File_SDMC::Open() { | ||
| 35 | if (!mode.create_flag && !FileUtil::Exists(path)) { | ||
| 36 | ERROR_LOG(FILESYS, "Non-existing file %s can’t be open without mode create.", path.c_str()); | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | |||
| 40 | std::string mode_string; | ||
| 41 | if (mode.read_flag && mode.write_flag) | ||
| 42 | mode_string = "w+"; | ||
| 43 | else if (mode.read_flag) | ||
| 44 | mode_string = "r"; | ||
| 45 | else if (mode.write_flag) | ||
| 46 | mode_string = "w"; | ||
| 47 | |||
| 48 | file = new FileUtil::IOFile(path, mode_string.c_str()); | ||
| 49 | return true; | ||
| 50 | } | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Read data from the file | ||
| 54 | * @param offset Offset in bytes to start reading data from | ||
| 55 | * @param length Length in bytes of data to read from file | ||
| 56 | * @param buffer Buffer to read data into | ||
| 57 | * @return Number of bytes read | ||
| 58 | */ | ||
| 59 | size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const { | ||
| 60 | file->Seek(offset, SEEK_SET); | ||
| 61 | return file->ReadBytes(buffer, length); | ||
| 62 | } | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Write data to the file | ||
| 66 | * @param offset Offset in bytes to start writing data to | ||
| 67 | * @param length Length in bytes of data to write to file | ||
| 68 | * @param flush The flush parameters (0 == do not flush) | ||
| 69 | * @param buffer Buffer to read data from | ||
| 70 | * @return Number of bytes written | ||
| 71 | */ | ||
| 72 | size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { | ||
| 73 | file->Seek(offset, SEEK_SET); | ||
| 74 | size_t written = file->WriteBytes(buffer, length); | ||
| 75 | if (flush) | ||
| 76 | file->Flush(); | ||
| 77 | return written; | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Get the size of the file in bytes | ||
| 82 | * @return Size of the file in bytes | ||
| 83 | */ | ||
| 84 | size_t File_SDMC::GetSize() const { | ||
| 85 | return static_cast<size_t>(file->GetSize()); | ||
| 86 | } | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Set the size of the file in bytes | ||
| 90 | * @param size New size of the file | ||
| 91 | * @return true if successful | ||
| 92 | */ | ||
| 93 | bool File_SDMC::SetSize(const u64 size) const { | ||
| 94 | file->Resize(size); | ||
| 95 | file->Flush(); | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | |||
| 99 | /** | ||
| 100 | * Close the file | ||
| 101 | * @return true if the file closed correctly | ||
| 102 | */ | ||
| 103 | bool File_SDMC::Close() const { | ||
| 104 | return file->Close(); | ||
| 105 | } | ||
| 106 | |||
| 107 | } // namespace FileSys | ||
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h deleted file mode 100644 index 80b445968..000000000 --- a/src/core/file_sys/file_sdmc.h +++ /dev/null | |||
| @@ -1,75 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/file_util.h" | ||
| 9 | |||
| 10 | #include "core/file_sys/file.h" | ||
| 11 | #include "core/file_sys/archive_sdmc.h" | ||
| 12 | #include "core/loader/loader.h" | ||
| 13 | |||
| 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 15 | // FileSys namespace | ||
| 16 | |||
| 17 | namespace FileSys { | ||
| 18 | |||
| 19 | class File_SDMC final : public File { | ||
| 20 | public: | ||
| 21 | File_SDMC(); | ||
| 22 | File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode); | ||
| 23 | ~File_SDMC() override; | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Open the file | ||
| 27 | * @return true if the file opened correctly | ||
| 28 | */ | ||
| 29 | bool Open() override; | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Read data from the file | ||
| 33 | * @param offset Offset in bytes to start reading data from | ||
| 34 | * @param length Length in bytes of data to read from file | ||
| 35 | * @param buffer Buffer to read data into | ||
| 36 | * @return Number of bytes read | ||
| 37 | */ | ||
| 38 | size_t Read(const u64 offset, const u32 length, u8* buffer) const override; | ||
| 39 | |||
| 40 | /** | ||
| 41 | * Write data to the file | ||
| 42 | * @param offset Offset in bytes to start writing data to | ||
| 43 | * @param length Length in bytes of data to write to file | ||
| 44 | * @param flush The flush parameters (0 == do not flush) | ||
| 45 | * @param buffer Buffer to read data from | ||
| 46 | * @return Number of bytes written | ||
| 47 | */ | ||
| 48 | size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Get the size of the file in bytes | ||
| 52 | * @return Size of the file in bytes | ||
| 53 | */ | ||
| 54 | size_t GetSize() const override; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Set the size of the file in bytes | ||
| 58 | * @param size New size of the file | ||
| 59 | * @return true if successful | ||
| 60 | */ | ||
| 61 | bool SetSize(const u64 size) const override; | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Close the file | ||
| 65 | * @return true if the file closed correctly | ||
| 66 | */ | ||
| 67 | bool Close() const override; | ||
| 68 | |||
| 69 | private: | ||
| 70 | std::string path; | ||
| 71 | Mode mode; | ||
| 72 | FileUtil::IOFile* file; | ||
| 73 | }; | ||
| 74 | |||
| 75 | } // namespace FileSys | ||