Files
AnyPS5/docs/dev/debt/libSceFios2.md
T
MarcZX10 dddc4fd030 docs(libSceFios2): cite the call-site source by title ID and record gaps
Cite the PC port that supplied PS4 call-site evidence by owner, commit
and title IDs instead of its repository name, split the file handle
entry under the length the conventions check expects, and record the
operation threading and guest input handling in the technical debt.
2026-10-28 07:27:23 +00:00

13 KiB

libSceFios2 technical debt

Functional

  • libSceFios2 prototypes (libSceFios2) - the implemented exports take the prototypes of RPCS3's Vita FIOS2 module (Emu/ARMv7/Modules/sceFios.h and sceFios.cpp, jacquesjk/RPCS-DX12 at 9b8b7c9eea446095f24af19182032013837e6ca5, 64-bit types substituted), checked against the PS4 headers and call sites of kalaposfos13/fios2 (src/fios2.h, ae6ca1d78e7a822c2528f7660959167b9b3d8b63), sonny-tel/libSceFios2 (sceFios2.h, 5d44f9e7a80ae00557af80fad335e4c74ef35d22), Inori/GPCS4 (SceFios2/sce_fios2.cpp) and SonicMastr/SceLibcPosix (src/internal/fios2.h, Vita, c2cd5e880a8770bdbfb58de761de11f396c1a2e7).
  • Layouts (libSceFios2) - The SceFiosOpAttr, SceFiosOpenParams, SceFiosStat and SceFiosDirEntry layouts and the SCE_FIOS_ERROR_* values (0x80820000 plus the enumeration order) come from the same sources; vascon-es, a PC port of a PS4 title (CUSA01176 and CUSA00935 version 01.24), at 57c3c202975ea48e574df2d1e4a620b4e18b7701, confirms the SceFiosStat and SceFiosDirEntry offsets and the fileSize, statFlags bit 0 (directory) and offsetToName reads from the call sites of a PS4 title. None of it was measured on a PS5. The SceFiosOpenParams buffer sits at offset 8 in kalaposfos13 and sonny-tel and at offset 0x10 in vascon-es; only openFlags is read
  • Operations (libSceFios2) - there are no I/O or decompressor threads. An operation runs on the calling thread and is complete when the export returns, and its callback fires there with SCE_FIOS_OPEVENT_COMPLETE; while sceFiosSuspend is in effect new operations queue and run on the thread whose sceFiosResume ends the suspension. deadline, priority, opflags, userTag, userPtr and the scheduler fields are stored and returned but have no effect, and SCE_FIOS_OPEVENT_START is never sent. The *Sync exports are the asynchronous export followed by sceFiosOpSyncWait, so they also fire the completion and SCE_FIOS_OPEVENT_DELETE callbacks.
  • Completion values and parameters (libSceFios2) - sceFiosOpSyncWait returns the error or the low 32 bits of the result (1 or 0 for the existence queries, as in kalaposfos13/fios2), sceFiosOpGetActualCount returns the result (the size for sceFiosFileGetSize) also for a failed operation, and sceFiosOpGetError returns 1 while an operation is queued; none of these is measured. Handles of operations, files and directories share one number space that starts at 1. Nothing requires sceFiosInitialize first, and SceFiosParams is stored as paramsSize bytes (the 15 bits at bit 1 of the first word) without interpretation, so the storage buffers, pathMax (1024 is used), thread and scheduler settings are ignored
  • sceFiosExists, sceFiosFileExists, sceFiosDirectoryExists, sceFiosFileGetSize, sceFiosStat and their Sync forms (libSceFios2) - paths go to sceKernelStat, so archive and alias mapping is the kernel's. A missing path is not an error for the existence queries. SceFiosStat carries only the sizes, the nanosecond dates as seconds since 1970 times 10^9 plus nanoseconds (the epoch and unit are not measured), statFlags bit 0 for a directory, and the kernel st_uid, st_gid, st_dev, st_ino and st_mode; other statFlags bits are 0. sceFiosFileExists and sceFiosDirectoryExists take the pOutExists argument of RPCS3's prototype, which kalaposfos13/fios2 omits, and sceFiosFileGetSize has no output pointer as in kalaposfos13/fios2 and sonny-tel (RPCS3 declares one)
  • sceFiosDelete, sceFiosFileDelete, sceFiosDirectoryCreate, sceFiosDirectoryDelete, sceFiosRename, sceFiosFileRead, sceFiosFileWrite, sceFiosFileTruncate and their Sync forms (libSceFios2) - behaviour is inferred from the export names; none of it is measured. They run on sceKernelStat, sceKernelOpen, sceKernelPread, sceKernelPwrite, sceKernelFtruncate, sceKernelMkdir, sceKernelRmdir, sceKernelUnlink and sceKernelRename, so guest path mapping and the read-only application directory are the kernel's. sceFiosFileWrite opens the file write-only with creation and no truncation, sceFiosFileTruncate does not create it, directories are created with mode 0777 and files with 0666, sceFiosDelete removes a file or an empty directory, and a negative length returns SCE_FIOS_ERROR_BAD_SIZE, a negative offset SCE_FIOS_ERROR_BAD_OFFSET.
  • Error mapping (libSceFios2) - A read stops at the end of the file and returns the bytes read. The mapping of kernel errors to SCE_FIOS_ERROR_* is chosen here: ENOENT and ENOTDIR to BAD_PATH, EPERM, EACCES and ENOTEMPTY to ACCESS, EROFS to READ_ONLY, EEXIST to ALREADY_EXISTS, EISDIR to NOT_A_FILE, EINVAL to BAD_OFFSET, ENFILE and EMFILE to CANT_ALLOCATE_FH, ENAMETOOLONG to PATH_TOO_LONG, EFAULT to BAD_PTR, and anything else to UNKNOWN. The prototypes follow RPCS3 (sceFios.cpp sceFiosFileWrite, sceFiosFileTruncate, sceFiosRename, sceFiosDelete) and kalaposfos13/fios2 (sceFiosFileRead)
  • sceFiosFHOpen, sceFiosFHOpenWithMode, sceFiosFHClose, sceFiosFHStat, sceFiosFHTruncate, sceFiosFHSync, sceFiosFHRead, sceFiosFHWrite, sceFiosFHPread, sceFiosFHPwrite, the vectored forms with their Sync forms, sceFiosFHSeek, sceFiosFHTell, sceFiosFHGetSize, sceFiosFHGetPath and sceFiosFHGetOpenParams (libSceFios2) - a file handle owns one kernel descriptor, and sceFiosFHRead, sceFiosFHWrite, sceFiosFHSeek and sceFiosFHTell use its kernel position.
  • File handle errors and lifetime (libSceFios2) - openFlags map as SCE_FIOS_O_READ 1, SCE_FIOS_O_WRITE 2, SCE_FIOS_O_APPEND 4, SCE_FIOS_O_CREAT 8 and SCE_FIOS_O_TRUNC 16 (sonny-tel/libSceFios2, SonicMastr/SceLibcPosix); SCE_FIOS_O_DIRECT (1 << 12) is ignored, no flags or null parameters open read-only, and the handle returns SCE_FIOS_ERROR_WRITE_ONLY or SCE_FIOS_ERROR_READ_ONLY for a transfer its flags exclude (the console result is not measured). The creation mode is 0777 unless sceFiosFHOpenWithMode is given one (-1 means the default, as in kalaposfos13/fios2).
  • Open flags and offsets (libSceFios2) - Opening a directory returns SCE_FIOS_ERROR_NOT_A_FILE. An invalid whence or a negative resulting position returns SCE_FIOS_ERROR_BAD_OFFSET, a vector count outside 1 to 1024 SCE_FIOS_ERROR_BAD_IOVCNT. The Readv and Writev exports transfer the vectors in order and stop at the first short one. sceFiosFHGetPath and sceFiosFHGetOpenParams return pointers that stay valid until the handle is closed; the stored SceFiosOpenParams has no buffer. The handle prototypes follow RPCS3's sceFios.cpp and kalaposfos13/fios2; sceFiosFHToFileno and sceFiosFilenoToFH have no source and keep throwing
  • sceFiosDHOpen, sceFiosDHRead, sceFiosDHClose, their Sync forms and sceFiosDHGetPath (libSceFios2) - the prototypes follow RPCS3 and kalaposfos13/fios2, with the SceFiosBuffer passed by value in two registers as in vascon-es. Opening reads the whole listing through sceKernelGetdirentries into host memory; the caller's buffer is never written. A title that opens with a null or too small buffer gets SCE_FIOS_ERROR_BAD_SIZE and the required size from sceFiosOpGetActualCount, the probe that vascon-es observes at the call sites of a PS4 title.
  • Required directory buffer size (libSceFios2) - The required size, 16 plus the name lengths plus one each, is chosen here and is not what the console reports, so a title that sizes its buffer from another source can get a false BAD_SIZE. . and .. are not listed (unverified), entries come in kernel order, the end of the listing returns SCE_FIOS_ERROR_EOF and sceFiosDHRead fills fileSize, statFlags bit 0, nameLength, fullPathLength, offsetToName and fullPath as vascon-es reads them, with fullPath the opened path, a slash and the name
  • sceFiosDateGetCurrent, sceFiosDateFromComponents, sceFiosDateToComponents, sceFiosTimeIntervalFromNanoseconds and sceFiosTimeIntervalToNanoseconds (libSceFios2) - a SceFiosDate is taken as nanoseconds since 1970-01-01 UTC and a SceFiosTimeInterval as nanoseconds (identity conversions), as in kalaposfos13/fios2 (src/fios2.cpp, time(nullptr) * 1000000000) and RPCS3 (sceFios.cpp, 64-bit unsigned date); neither is measured, and both may descend from one Vita SDK. kalaposfos13/fios2 converts components through local time, here they are UTC (sceFiosDateFromComponents normalizes out-of-range fields like timegm and returns 0 before 1970). Only the nine leading int fields of struct tm are read and written, so tm_gmtoff and tm_zone are left untouched. sceFiosTimeGetCurrent has no source for its clock and keeps throwing
  • Operation threading (libSceFios2) - an operation and its SCE_FIOS_OPEVENT_COMPLETE callback run inside the call that issues the operation, whereas on the console the callback runs on a FIOS I/O thread. A title that issues an operation while holding a lock its own callback takes deadlocks on its own thread, and a title that expects the output pointers (pOutFH, pOutExists, pOutStatus) to be written only after sceFiosOpWait is not tested. A worker thread was not added: guest callbacks need a guest thread (scePthreadCreate, as libSceJobManager uses) with its TLS and stack, the *Sync forms must stay synchronous on the caller, and moving completion to another thread changes every output-pointer, callback and teardown ordering in the library and its tests, which could not be validated here against a title or a console
  • Guest inputs (libSceFios2) - SceFiosOpAttr, SceFiosOpenParams, SceFiosParams, the vector arrays and struct tm are copied with GuestCopyIn_nid_no_patch; a failed copy returns SCE_FIOS_ERROR_BAD_PTR (the operation handle value itself for an unreadable SceFiosOpAttr), or is ignored by the void exports. That the console returns SCE_FIOS_ERROR_BAD_PTR for an unreadable pointer is not measured

Unknown function info