diff options
Diffstat (limited to 'src/core/hle/kernel/archive.cpp')
| -rw-r--r-- | src/core/hle/kernel/archive.cpp | 176 |
1 files changed, 64 insertions, 112 deletions
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp index 900f484c7..e273444c9 100644 --- a/src/core/hle/kernel/archive.cpp +++ b/src/core/hle/kernel/archive.cpp | |||
| @@ -9,8 +9,9 @@ | |||
| 9 | #include "core/file_sys/archive.h" | 9 | #include "core/file_sys/archive.h" |
| 10 | #include "core/file_sys/archive_sdmc.h" | 10 | #include "core/file_sys/archive_sdmc.h" |
| 11 | #include "core/file_sys/directory.h" | 11 | #include "core/file_sys/directory.h" |
| 12 | #include "core/hle/service/service.h" | ||
| 13 | #include "core/hle/kernel/archive.h" | 12 | #include "core/hle/kernel/archive.h" |
| 13 | #include "core/hle/result.h" | ||
| 14 | #include "core/hle/service/service.h" | ||
| 14 | 15 | ||
| 15 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 16 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 16 | // Kernel namespace | 17 | // Kernel namespace |
| @@ -51,12 +52,7 @@ public: | |||
| 51 | std::string name; ///< Name of archive (optional) | 52 | std::string name; ///< Name of archive (optional) |
| 52 | FileSys::Archive* backend; ///< Archive backend interface | 53 | FileSys::Archive* backend; ///< Archive backend interface |
| 53 | 54 | ||
| 54 | /** | 55 | ResultVal<bool> SyncRequest() override { |
| 55 | * Synchronize kernel object | ||
| 56 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 57 | * @return Result of operation, 0 on success, otherwise error code | ||
| 58 | */ | ||
| 59 | Result SyncRequest(bool* wait) override { | ||
| 60 | u32* cmd_buff = Service::GetCommandBuffer(); | 56 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 61 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 57 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 62 | 58 | ||
| @@ -106,22 +102,17 @@ public: | |||
| 106 | default: | 102 | default: |
| 107 | { | 103 | { |
| 108 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 104 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 109 | return -1; | 105 | return UnimplementedFunction(ErrorModule::FS); |
| 110 | } | 106 | } |
| 111 | } | 107 | } |
| 112 | cmd_buff[1] = 0; // No error | 108 | cmd_buff[1] = 0; // No error |
| 113 | return 0; | 109 | return MakeResult<bool>(false); |
| 114 | } | 110 | } |
| 115 | 111 | ||
| 116 | /** | 112 | ResultVal<bool> WaitSynchronization() override { |
| 117 | * Wait for kernel object to synchronize | ||
| 118 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 119 | * @return Result of operation, 0 on success, otherwise error code | ||
| 120 | */ | ||
| 121 | Result WaitSynchronization(bool* wait) override { | ||
| 122 | // TODO(bunnei): ImplementMe | 113 | // TODO(bunnei): ImplementMe |
| 123 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 114 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 124 | return 0; | 115 | return UnimplementedFunction(ErrorModule::FS); |
| 125 | } | 116 | } |
| 126 | }; | 117 | }; |
| 127 | 118 | ||
| @@ -136,12 +127,7 @@ public: | |||
| 136 | FileSys::Path path; ///< Path of the file | 127 | FileSys::Path path; ///< Path of the file |
| 137 | std::unique_ptr<FileSys::File> backend; ///< File backend interface | 128 | std::unique_ptr<FileSys::File> backend; ///< File backend interface |
| 138 | 129 | ||
| 139 | /** | 130 | ResultVal<bool> SyncRequest() override { |
| 140 | * Synchronize kernel object | ||
| 141 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 142 | * @return Result of operation, 0 on success, otherwise error code | ||
| 143 | */ | ||
| 144 | Result SyncRequest(bool* wait) override { | ||
| 145 | u32* cmd_buff = Service::GetCommandBuffer(); | 131 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 146 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); | 132 | FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); |
| 147 | switch (cmd) { | 133 | switch (cmd) { |
| @@ -183,7 +169,8 @@ public: | |||
| 183 | case FileCommand::SetSize: | 169 | case FileCommand::SetSize: |
| 184 | { | 170 | { |
| 185 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); | 171 | u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); |
| 186 | DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(), size); | 172 | DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu", |
| 173 | GetTypeName().c_str(), GetName().c_str(), size); | ||
| 187 | backend->SetSize(size); | 174 | backend->SetSize(size); |
| 188 | break; | 175 | break; |
| 189 | } | 176 | } |
| @@ -198,22 +185,18 @@ public: | |||
| 198 | // Unknown command... | 185 | // Unknown command... |
| 199 | default: | 186 | default: |
| 200 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 187 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 201 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 188 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 202 | return -1; | 189 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 190 | return error; | ||
| 203 | } | 191 | } |
| 204 | cmd_buff[1] = 0; // No error | 192 | cmd_buff[1] = 0; // No error |
| 205 | return 0; | 193 | return MakeResult<bool>(false); |
| 206 | } | 194 | } |
| 207 | 195 | ||
| 208 | /** | 196 | ResultVal<bool> WaitSynchronization() override { |
| 209 | * Wait for kernel object to synchronize | ||
| 210 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 211 | * @return Result of operation, 0 on success, otherwise error code | ||
| 212 | */ | ||
| 213 | Result WaitSynchronization(bool* wait) override { | ||
| 214 | // TODO(bunnei): ImplementMe | 197 | // TODO(bunnei): ImplementMe |
| 215 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 198 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 216 | return 0; | 199 | return UnimplementedFunction(ErrorModule::FS); |
| 217 | } | 200 | } |
| 218 | }; | 201 | }; |
| 219 | 202 | ||
| @@ -228,12 +211,7 @@ public: | |||
| 228 | FileSys::Path path; ///< Path of the directory | 211 | FileSys::Path path; ///< Path of the directory |
| 229 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface | 212 | std::unique_ptr<FileSys::Directory> backend; ///< File backend interface |
| 230 | 213 | ||
| 231 | /** | 214 | ResultVal<bool> SyncRequest() override { |
| 232 | * Synchronize kernel object | ||
| 233 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 234 | * @return Result of operation, 0 on success, otherwise error code | ||
| 235 | */ | ||
| 236 | Result SyncRequest(bool* wait) override { | ||
| 237 | u32* cmd_buff = Service::GetCommandBuffer(); | 215 | u32* cmd_buff = Service::GetCommandBuffer(); |
| 238 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); | 216 | DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); |
| 239 | switch (cmd) { | 217 | switch (cmd) { |
| @@ -243,8 +221,9 @@ public: | |||
| 243 | { | 221 | { |
| 244 | u32 count = cmd_buff[1]; | 222 | u32 count = cmd_buff[1]; |
| 245 | u32 address = cmd_buff[3]; | 223 | u32 address = cmd_buff[3]; |
| 246 | FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 224 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); |
| 247 | DEBUG_LOG(KERNEL, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); | 225 | DEBUG_LOG(KERNEL, "Read %s %s: count=%d", |
| 226 | GetTypeName().c_str(), GetName().c_str(), count); | ||
| 248 | 227 | ||
| 249 | // Number of entries actually read | 228 | // Number of entries actually read |
| 250 | cmd_buff[2] = backend->Read(count, entries); | 229 | cmd_buff[2] = backend->Read(count, entries); |
| @@ -261,22 +240,18 @@ public: | |||
| 261 | // Unknown command... | 240 | // Unknown command... |
| 262 | default: | 241 | default: |
| 263 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); | 242 | ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); |
| 264 | cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. | 243 | ResultCode error = UnimplementedFunction(ErrorModule::FS); |
| 265 | return -1; | 244 | cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. |
| 245 | return error; | ||
| 266 | } | 246 | } |
| 267 | cmd_buff[1] = 0; // No error | 247 | cmd_buff[1] = 0; // No error |
| 268 | return 0; | 248 | return MakeResult<bool>(false); |
| 269 | } | 249 | } |
| 270 | 250 | ||
| 271 | /** | 251 | ResultVal<bool> WaitSynchronization() override { |
| 272 | * Wait for kernel object to synchronize | ||
| 273 | * @param wait Boolean wait set if current thread should wait as a result of sync operation | ||
| 274 | * @return Result of operation, 0 on success, otherwise error code | ||
| 275 | */ | ||
| 276 | Result WaitSynchronization(bool* wait) override { | ||
| 277 | // TODO(bunnei): ImplementMe | 252 | // TODO(bunnei): ImplementMe |
| 278 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); | 253 | ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); |
| 279 | return 0; | 254 | return UnimplementedFunction(ErrorModule::FS); |
| 280 | } | 255 | } |
| 281 | }; | 256 | }; |
| 282 | 257 | ||
| @@ -284,89 +259,58 @@ public: | |||
| 284 | 259 | ||
| 285 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode | 260 | std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode |
| 286 | 261 | ||
| 287 | /** | 262 | ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) { |
| 288 | * Opens an archive | ||
| 289 | * @param id_code IdCode of the archive to open | ||
| 290 | * @return Handle to archive if it exists, otherwise a null handle (0) | ||
| 291 | */ | ||
| 292 | Handle OpenArchive(FileSys::Archive::IdCode id_code) { | ||
| 293 | auto itr = g_archive_map.find(id_code); | 263 | auto itr = g_archive_map.find(id_code); |
| 294 | if (itr == g_archive_map.end()) { | 264 | if (itr == g_archive_map.end()) { |
| 295 | return 0; | 265 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 266 | ErrorSummary::NotFound, ErrorLevel::Permanent); | ||
| 296 | } | 267 | } |
| 297 | return itr->second; | 268 | |
| 269 | return MakeResult<Handle>(itr->second); | ||
| 298 | } | 270 | } |
| 299 | 271 | ||
| 300 | /** | 272 | ResultCode CloseArchive(FileSys::Archive::IdCode id_code) { |
| 301 | * Closes an archive | ||
| 302 | * @param id_code IdCode of the archive to open | ||
| 303 | * @return Result of operation, 0 on success, otherwise error code | ||
| 304 | */ | ||
| 305 | Result CloseArchive(FileSys::Archive::IdCode id_code) { | ||
| 306 | auto itr = g_archive_map.find(id_code); | 273 | auto itr = g_archive_map.find(id_code); |
| 307 | if (itr == g_archive_map.end()) { | 274 | if (itr == g_archive_map.end()) { |
| 308 | ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); | 275 | ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); |
| 309 | return -1; | 276 | return InvalidHandle(ErrorModule::FS); |
| 310 | } | 277 | } |
| 311 | 278 | ||
| 312 | INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); | 279 | INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); |
| 313 | return 0; | 280 | return RESULT_SUCCESS; |
| 314 | } | 281 | } |
| 315 | 282 | ||
| 316 | /** | 283 | /** |
| 317 | * Mounts an archive | 284 | * Mounts an archive |
| 318 | * @param archive Pointer to the archive to mount | 285 | * @param archive Pointer to the archive to mount |
| 319 | * @return Result of operation, 0 on success, otherwise error code | ||
| 320 | */ | 286 | */ |
| 321 | Result MountArchive(Archive* archive) { | 287 | ResultCode MountArchive(Archive* archive) { |
| 322 | FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); | 288 | FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); |
| 323 | if (0 != OpenArchive(id_code)) { | 289 | ResultVal<Handle> archive_handle = OpenArchive(id_code); |
| 290 | if (archive_handle.Succeeded()) { | ||
| 324 | ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); | 291 | ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); |
| 325 | return -1; | 292 | return archive_handle.Code(); |
| 326 | } | 293 | } |
| 327 | g_archive_map[id_code] = archive->GetHandle(); | 294 | g_archive_map[id_code] = archive->GetHandle(); |
| 328 | INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); | 295 | INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); |
| 329 | return 0; | 296 | return RESULT_SUCCESS; |
| 330 | } | 297 | } |
| 331 | 298 | ||
| 332 | /** | 299 | ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) { |
| 333 | * Creates an Archive | ||
| 334 | * @param handle Handle to newly created archive object | ||
| 335 | * @param backend File system backend interface to the archive | ||
| 336 | * @param name Optional name of Archive | ||
| 337 | * @return Newly created Archive object | ||
| 338 | */ | ||
| 339 | Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) { | ||
| 340 | Archive* archive = new Archive; | 300 | Archive* archive = new Archive; |
| 341 | handle = Kernel::g_object_pool.Create(archive); | 301 | Handle handle = Kernel::g_object_pool.Create(archive); |
| 342 | archive->name = name; | 302 | archive->name = name; |
| 343 | archive->backend = backend; | 303 | archive->backend = backend; |
| 344 | 304 | ||
| 345 | MountArchive(archive); | 305 | ResultCode result = MountArchive(archive); |
| 346 | 306 | if (result.IsError()) { | |
| 347 | return archive; | 307 | return result; |
| 348 | } | 308 | } |
| 349 | 309 | ||
| 350 | /** | 310 | return RESULT_SUCCESS; |
| 351 | * Creates an Archive | ||
| 352 | * @param backend File system backend interface to the archive | ||
| 353 | * @param name Optional name of Archive | ||
| 354 | * @return Handle to newly created Archive object | ||
| 355 | */ | ||
| 356 | Handle CreateArchive(FileSys::Archive* backend, const std::string& name) { | ||
| 357 | Handle handle; | ||
| 358 | CreateArchive(handle, backend, name); | ||
| 359 | return handle; | ||
| 360 | } | 311 | } |
| 361 | 312 | ||
| 362 | /** | 313 | ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { |
| 363 | * Open a File from an Archive | ||
| 364 | * @param archive_handle Handle to an open Archive object | ||
| 365 | * @param path Path to the File inside of the Archive | ||
| 366 | * @param mode Mode under which to open the File | ||
| 367 | * @return Opened File object | ||
| 368 | */ | ||
| 369 | Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { | ||
| 370 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create | 314 | // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create |
| 371 | // the archive file handles at app loading, and then keep them persistent throughout execution. | 315 | // the archive file handles at app loading, and then keep them persistent throughout execution. |
| 372 | // Archives file handles are just reused and not actually freed until emulation shut down. | 316 | // Archives file handles are just reused and not actually freed until emulation shut down. |
| @@ -376,19 +320,24 @@ Handle OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, con | |||
| 376 | // design. While the functionally of this is OK, our implementation decision to separate | 320 | // design. While the functionally of this is OK, our implementation decision to separate |
| 377 | // normal files from archive file pointers is very likely wrong. | 321 | // normal files from archive file pointers is very likely wrong. |
| 378 | // See https://github.com/citra-emu/citra/issues/205 | 322 | // See https://github.com/citra-emu/citra/issues/205 |
| 379 | return archive_handle; | 323 | return MakeResult<Handle>(archive_handle); |
| 380 | 324 | ||
| 381 | File* file = new File; | 325 | File* file = new File; |
| 382 | Handle handle = Kernel::g_object_pool.Create(file); | 326 | Handle handle = Kernel::g_object_pool.Create(file); |
| 383 | 327 | ||
| 384 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 328 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |
| 329 | if (archive == nullptr) { | ||
| 330 | return InvalidHandle(ErrorModule::FS); | ||
| 331 | } | ||
| 385 | file->path = path; | 332 | file->path = path; |
| 386 | file->backend = archive->backend->OpenFile(path, mode); | 333 | file->backend = archive->backend->OpenFile(path, mode); |
| 387 | 334 | ||
| 388 | if (!file->backend) | 335 | if (!file->backend) { |
| 389 | return 0; | 336 | return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, |
| 337 | ErrorSummary::NotFound, ErrorLevel::Permanent); | ||
| 338 | } | ||
| 390 | 339 | ||
| 391 | return handle; | 340 | return MakeResult<Handle>(handle); |
| 392 | } | 341 | } |
| 393 | 342 | ||
| 394 | /** | 343 | /** |
| @@ -442,15 +391,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa | |||
| 442 | * @param path Path to the Directory inside of the Archive | 391 | * @param path Path to the Directory inside of the Archive |
| 443 | * @return Opened Directory object | 392 | * @return Opened Directory object |
| 444 | */ | 393 | */ |
| 445 | Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { | 394 | ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { |
| 446 | Directory* directory = new Directory; | 395 | Directory* directory = new Directory; |
| 447 | Handle handle = Kernel::g_object_pool.Create(directory); | 396 | Handle handle = Kernel::g_object_pool.Create(directory); |
| 448 | 397 | ||
| 449 | Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); | 398 | Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle); |
| 399 | if (archive == nullptr) { | ||
| 400 | return InvalidHandle(ErrorModule::FS); | ||
| 401 | } | ||
| 450 | directory->path = path; | 402 | directory->path = path; |
| 451 | directory->backend = archive->backend->OpenDirectory(path); | 403 | directory->backend = archive->backend->OpenDirectory(path); |
| 452 | 404 | ||
| 453 | return handle; | 405 | return MakeResult<Handle>(handle); |
| 454 | } | 406 | } |
| 455 | 407 | ||
| 456 | /// Initialize archives | 408 | /// Initialize archives |