summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/archive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/archive.cpp')
-rw-r--r--src/core/hle/kernel/archive.cpp147
1 files changed, 65 insertions, 82 deletions
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 900f484c7..e11dddc84 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
@@ -56,7 +57,7 @@ public:
56 * @param wait Boolean wait set if current thread should wait as a result of sync operation 57 * @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 * @return Result of operation, 0 on success, otherwise error code
58 */ 59 */
59 Result SyncRequest(bool* wait) override { 60 ResultVal<bool> SyncRequest() override {
60 u32* cmd_buff = Service::GetCommandBuffer(); 61 u32* cmd_buff = Service::GetCommandBuffer();
61 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 62 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
62 63
@@ -106,11 +107,11 @@ public:
106 default: 107 default:
107 { 108 {
108 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 109 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
109 return -1; 110 return UnimplementedFunction(ErrorModule::FS);
110 } 111 }
111 } 112 }
112 cmd_buff[1] = 0; // No error 113 cmd_buff[1] = 0; // No error
113 return 0; 114 return MakeResult<bool>(false);
114 } 115 }
115 116
116 /** 117 /**
@@ -118,10 +119,10 @@ public:
118 * @param wait Boolean wait set if current thread should wait as a result of sync operation 119 * @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 * @return Result of operation, 0 on success, otherwise error code
120 */ 121 */
121 Result WaitSynchronization(bool* wait) override { 122 ResultVal<bool> WaitSynchronization() override {
122 // TODO(bunnei): ImplementMe 123 // TODO(bunnei): ImplementMe
123 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 124 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
124 return 0; 125 return UnimplementedFunction(ErrorModule::FS);
125 } 126 }
126}; 127};
127 128
@@ -141,7 +142,7 @@ public:
141 * @param wait Boolean wait set if current thread should wait as a result of sync operation 142 * @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 * @return Result of operation, 0 on success, otherwise error code
143 */ 144 */
144 Result SyncRequest(bool* wait) override { 145 ResultVal<bool> SyncRequest() override {
145 u32* cmd_buff = Service::GetCommandBuffer(); 146 u32* cmd_buff = Service::GetCommandBuffer();
146 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 147 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
147 switch (cmd) { 148 switch (cmd) {
@@ -183,7 +184,8 @@ public:
183 case FileCommand::SetSize: 184 case FileCommand::SetSize:
184 { 185 {
185 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 186 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); 187 DEBUG_LOG(KERNEL, "SetSize %s %s size=%llu",
188 GetTypeName().c_str(), GetName().c_str(), size);
187 backend->SetSize(size); 189 backend->SetSize(size);
188 break; 190 break;
189 } 191 }
@@ -198,11 +200,12 @@ public:
198 // Unknown command... 200 // Unknown command...
199 default: 201 default:
200 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 202 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
201 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 203 ResultCode error = UnimplementedFunction(ErrorModule::FS);
202 return -1; 204 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
205 return error;
203 } 206 }
204 cmd_buff[1] = 0; // No error 207 cmd_buff[1] = 0; // No error
205 return 0; 208 return MakeResult<bool>(false);
206 } 209 }
207 210
208 /** 211 /**
@@ -210,10 +213,10 @@ public:
210 * @param wait Boolean wait set if current thread should wait as a result of sync operation 213 * @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 214 * @return Result of operation, 0 on success, otherwise error code
212 */ 215 */
213 Result WaitSynchronization(bool* wait) override { 216 ResultVal<bool> WaitSynchronization() override {
214 // TODO(bunnei): ImplementMe 217 // TODO(bunnei): ImplementMe
215 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 218 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
216 return 0; 219 return UnimplementedFunction(ErrorModule::FS);
217 } 220 }
218}; 221};
219 222
@@ -233,7 +236,7 @@ public:
233 * @param wait Boolean wait set if current thread should wait as a result of sync operation 236 * @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 237 * @return Result of operation, 0 on success, otherwise error code
235 */ 238 */
236 Result SyncRequest(bool* wait) override { 239 ResultVal<bool> SyncRequest() override {
237 u32* cmd_buff = Service::GetCommandBuffer(); 240 u32* cmd_buff = Service::GetCommandBuffer();
238 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 241 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
239 switch (cmd) { 242 switch (cmd) {
@@ -243,8 +246,9 @@ public:
243 { 246 {
244 u32 count = cmd_buff[1]; 247 u32 count = cmd_buff[1];
245 u32 address = cmd_buff[3]; 248 u32 address = cmd_buff[3];
246 FileSys::Entry* entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); 249 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); 250 DEBUG_LOG(KERNEL, "Read %s %s: count=%d",
251 GetTypeName().c_str(), GetName().c_str(), count);
248 252
249 // Number of entries actually read 253 // Number of entries actually read
250 cmd_buff[2] = backend->Read(count, entries); 254 cmd_buff[2] = backend->Read(count, entries);
@@ -261,11 +265,12 @@ public:
261 // Unknown command... 265 // Unknown command...
262 default: 266 default:
263 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd); 267 ERROR_LOG(KERNEL, "Unknown command=0x%08X!", cmd);
264 cmd_buff[1] = -1; // TODO(Link Mauve): use the correct error code for that. 268 ResultCode error = UnimplementedFunction(ErrorModule::FS);
265 return -1; 269 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
270 return error;
266 } 271 }
267 cmd_buff[1] = 0; // No error 272 cmd_buff[1] = 0; // No error
268 return 0; 273 return MakeResult<bool>(false);
269 } 274 }
270 275
271 /** 276 /**
@@ -273,10 +278,10 @@ public:
273 * @param wait Boolean wait set if current thread should wait as a result of sync operation 278 * @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 279 * @return Result of operation, 0 on success, otherwise error code
275 */ 280 */
276 Result WaitSynchronization(bool* wait) override { 281 ResultVal<bool> WaitSynchronization() override {
277 // TODO(bunnei): ImplementMe 282 // TODO(bunnei): ImplementMe
278 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)"); 283 ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
279 return 0; 284 return UnimplementedFunction(ErrorModule::FS);
280 } 285 }
281}; 286};
282 287
@@ -284,89 +289,59 @@ public:
284 289
285std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode 290std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
286 291
287/** 292ResultVal<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 */
292Handle OpenArchive(FileSys::Archive::IdCode id_code) {
293 auto itr = g_archive_map.find(id_code); 293 auto itr = g_archive_map.find(id_code);
294 if (itr == g_archive_map.end()) { 294 if (itr == g_archive_map.end()) {
295 return 0; 295 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
296 ErrorSummary::NotFound, ErrorLevel::Permanent);
296 } 297 }
297 return itr->second; 298
299 return MakeResult<Handle>(itr->second);
298} 300}
299 301
300/** 302ResultCode 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 */
305Result CloseArchive(FileSys::Archive::IdCode id_code) {
306 auto itr = g_archive_map.find(id_code); 303 auto itr = g_archive_map.find(id_code);
307 if (itr == g_archive_map.end()) { 304 if (itr == g_archive_map.end()) {
308 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code); 305 ERROR_LOG(KERNEL, "Cannot close archive %d, does not exist!", (int)id_code);
309 return -1; 306 return InvalidHandle(ErrorModule::FS);
310 } 307 }
311 308
312 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code); 309 INFO_LOG(KERNEL, "Closed archive %d", (int) id_code);
313 return 0; 310 return RESULT_SUCCESS;
314} 311}
315 312
316/** 313/**
317 * Mounts an archive 314 * Mounts an archive
318 * @param archive Pointer to the archive to mount 315 * @param archive Pointer to the archive to mount
319 * @return Result of operation, 0 on success, otherwise error code 316 * @return Result of operation
320 */ 317 */
321Result MountArchive(Archive* archive) { 318ResultCode MountArchive(Archive* archive) {
322 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode(); 319 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
323 if (0 != OpenArchive(id_code)) { 320 ResultVal<Handle> archive_handle = OpenArchive(id_code);
321 if (archive_handle.Succeeded()) {
324 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code); 322 ERROR_LOG(KERNEL, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
325 return -1; 323 return archive_handle.Code();
326 } 324 }
327 g_archive_map[id_code] = archive->GetHandle(); 325 g_archive_map[id_code] = archive->GetHandle();
328 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str()); 326 INFO_LOG(KERNEL, "Mounted archive %s", archive->GetName().c_str());
329 return 0; 327 return RESULT_SUCCESS;
330} 328}
331 329
332/** 330ResultCode 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 */
339Archive* CreateArchive(Handle& handle, FileSys::Archive* backend, const std::string& name) {
340 Archive* archive = new Archive; 331 Archive* archive = new Archive;
341 handle = Kernel::g_object_pool.Create(archive); 332 Handle handle = Kernel::g_object_pool.Create(archive);
342 archive->name = name; 333 archive->name = name;
343 archive->backend = backend; 334 archive->backend = backend;
344 335
345 MountArchive(archive); 336 ResultCode result = MountArchive(archive);
346 337 if (result.IsError()) {
347 return archive; 338 return result;
348} 339 }
349 340
350/** 341 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 */
356Handle CreateArchive(FileSys::Archive* backend, const std::string& name) {
357 Handle handle;
358 CreateArchive(handle, backend, name);
359 return handle;
360} 342}
361 343
362/** 344ResultVal<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 */
369Handle 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 345 // 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. 346 // 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. 347 // Archives file handles are just reused and not actually freed until emulation shut down.
@@ -376,19 +351,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 351 // design. While the functionally of this is OK, our implementation decision to separate
377 // normal files from archive file pointers is very likely wrong. 352 // normal files from archive file pointers is very likely wrong.
378 // See https://github.com/citra-emu/citra/issues/205 353 // See https://github.com/citra-emu/citra/issues/205
379 return archive_handle; 354 return MakeResult<Handle>(archive_handle);
380 355
381 File* file = new File; 356 File* file = new File;
382 Handle handle = Kernel::g_object_pool.Create(file); 357 Handle handle = Kernel::g_object_pool.Create(file);
383 358
384 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 359 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
360 if (archive == nullptr) {
361 return InvalidHandle(ErrorModule::FS);
362 }
385 file->path = path; 363 file->path = path;
386 file->backend = archive->backend->OpenFile(path, mode); 364 file->backend = archive->backend->OpenFile(path, mode);
387 365
388 if (!file->backend) 366 if (!file->backend) {
389 return 0; 367 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
368 ErrorSummary::NotFound, ErrorLevel::Permanent);
369 }
390 370
391 return handle; 371 return MakeResult<Handle>(handle);
392} 372}
393 373
394/** 374/**
@@ -442,15 +422,18 @@ Result CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& pa
442 * @param path Path to the Directory inside of the Archive 422 * @param path Path to the Directory inside of the Archive
443 * @return Opened Directory object 423 * @return Opened Directory object
444 */ 424 */
445Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 425ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
446 Directory* directory = new Directory; 426 Directory* directory = new Directory;
447 Handle handle = Kernel::g_object_pool.Create(directory); 427 Handle handle = Kernel::g_object_pool.Create(directory);
448 428
449 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle); 429 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
430 if (archive == nullptr) {
431 return InvalidHandle(ErrorModule::FS);
432 }
450 directory->path = path; 433 directory->path = path;
451 directory->backend = archive->backend->OpenDirectory(path); 434 directory->backend = archive->backend->OpenDirectory(path);
452 435
453 return handle; 436 return MakeResult<Handle>(handle);
454} 437}
455 438
456/// Initialize archives 439/// Initialize archives