summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/archive.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-11-24 15:31:53 -0500
committerGravatar bunnei2014-11-24 15:31:53 -0500
commitbb730855e58d18d8964d158a55822c40503d548f (patch)
tree9c3ff113839583d1deca837e9888d81f25d485a0 /src/core/hle/kernel/archive.cpp
parentMerge pull request #191 from archshift/deletexyz (diff)
parentUse pointers instead of passing handles around in some functions. (diff)
downloadyuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.gz
yuzu-bb730855e58d18d8964d158a55822c40503d548f.tar.xz
yuzu-bb730855e58d18d8964d158a55822c40503d548f.zip
Merge pull request #147 from yuriks/error-codes
Error codes
Diffstat (limited to 'src/core/hle/kernel/archive.cpp')
-rw-r--r--src/core/hle/kernel/archive.cpp176
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
285std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode 260std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
286 261
287/** 262ResultVal<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); 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/** 272ResultCode 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); 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 */
321Result MountArchive(Archive* archive) { 287ResultCode 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/** 299ResultCode 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; 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 */
356Handle CreateArchive(FileSys::Archive* backend, const std::string& name) {
357 Handle handle;
358 CreateArchive(handle, backend, name);
359 return handle;
360} 311}
361 312
362/** 313ResultVal<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 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 */
445Handle OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) { 394ResultVal<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