# libSceFios2 technical debt ### Functional - [libSceFios2 prototypes](../../../core/libs/prx/libSceFios2/include/Api.hpp) (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](../../../core/libs/prx/libSceFios2/include/Api.hpp) (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](../../../core/libs/prx/libSceFios2/src/Runtime.cpp) (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](../../../core/libs/prx/libSceFios2/src/Runtime.cpp) (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](../../../core/libs/prx/libSceFios2/src/PathQueries.cpp) (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](../../../core/libs/prx/libSceFios2/src/PathOperations.cpp) (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](../../../core/libs/prx/libSceFios2/src/PathOperations.cpp) (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](../../../core/libs/prx/libSceFios2/src/FileHandles.cpp) (libSceFios2) - a file handle owns one kernel descriptor, and `sceFiosFHRead`, `sceFiosFHWrite`, `sceFiosFHSeek` and `sceFiosFHTell` use its kernel position. - [File handle errors and lifetime](../../../core/libs/prx/libSceFios2/src/FileHandles.cpp) (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](../../../core/libs/prx/libSceFios2/src/FileHandles.cpp) (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](../../../core/libs/prx/libSceFios2/src/DirectoryHandles.cpp) (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](../../../core/libs/prx/libSceFios2/src/DirectoryHandles.cpp) (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](../../../core/libs/prx/libSceFios2/src/Time.cpp) (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](../../../core/libs/prx/libSceFios2/src/Runtime.cpp) (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](../../../core/libs/prx/libSceFios2/src/Runtime.cpp) (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 - [sceFiosInitialize, sceFiosUpdateParameters and sceFiosIsInitialized](../../../core/libs/prx/libSceFios2/src/Control.cpp) (libSceFios2) - init accepts null/arbitrary sizes and stores raw parameters; updates replace the whole block. PS4 libSceFios2.sprx (init banner SDK 0x10710001), disassembly only: Initialize takes const SceFiosParams* and returns int32_t. Null returns BAD_PTR; size other than 0xb0, nonzero reserved fields or extraFlags beyond quiet return BAD_SIZE; schedulerAlgorithm >= 4 returns BAD_FLAGS. Repeated init returns 0 after UpdateParameters, which ignores calls before init or with another size, otherwise copying only maxChunk, pVprintf, pMemcpy, priorities and affinities. IsInitialized returns the init state and copies 0xb0 bytes to a non-null output only after successful init. PS5 and console behaviour remain unverified - [SceFiosParams](../../../core/libs/prx/libSceFios2/include/Types.hpp) (libSceFios2) - forward-declared without a layout; the implementation does not apply the defaults below. The same module uses every offset of sonny-tel's 0xb0-byte layout and applies these defaults: `pathMax` 0 or above 1024 becomes 1024; `ioThreadCount` 0 becomes 1 and above 2 becomes 2; `threadsPerScheduler` 0 becomes 1 and above 3 becomes 3; `maxChunk` 0 becomes 0x80000; `maxDecompressorThreadCount` 0 becomes 2 and above 3 becomes 3; a null `pVprintf` or `pMemcpy` selects the library's own; a priority of -1 becomes 260, 700 and 260; stack sizes below 0x14000, 0x4000 and 0x4000 are raised to them. The op, FH and DH pools take elements of `pathMax` plus 0x100, 0x70 and 0x68 bytes, rounded up to 8 - [Kernel errors](../../../core/libs/prx/libSceFios2/src/Runtime.cpp) (libSceFios2) - FromKernelError differs from PS4: EFAULT becomes BAD_PTR, EINVAL BAD_OFFSET, ENOTDIR BAD_PATH, ENFILE/EMFILE (23/24) CANT_ALLOCATE_FH, ENAMETOOLONG (63) PATH_TOO_LONG, and unlisted errors UNKNOWN. The same module has no pre-init guard; file calls reach the kernel. Its shared mapper returns ACCESS for EPERM/EACCES/ENOTEMPTY; BAD_PATH for ENOENT/EINVAL/EOPNOTSUPP/ENAMETOOLONG/89; BAD_FH for EBADF; BUSY for EBUSY; ALREADY_EXISTS for EEXIST; MEDIA_GONE for ENODEV/ENOSYS; NOT_A_DIRECTORY for ENOTDIR; NOT_A_FILE for EISDIR; READ_ONLY for EROFS; EOF for ERANGE; TIMEOUT for ETIMEDOUT. Other kernel codes, including EFAULT (0x8002000e), ENFILE and EMFILE, return unchanged. This is PS4 disassembly evidence; PS5 parity is unverified - [Error codes](../../../core/libs/prx/libSceFios2/include/Types.hpp) (libSceFios2) - Types.hpp declares the subset used by the implementation; the source for the full name table is the PS4 module below. The same module's name table gives these `SCE_FIOS_ERROR_` names to 0x80820000 plus: 0x00 UNIMPLEMENTED, 0x01 to 0x04 CANT_ALLOCATE_OP, _FH, _DH and _CHUNK, 0x05 BAD_PATH, 0x06 BAD_PTR, 0x07 BAD_OFFSET, 0x08 BAD_SIZE, 0x09 BAD_IOVCNT, 0x0a BAD_OP, 0x0b BAD_FH, 0x0c BAD_DH, 0x0d BAD_ALIGNMENT, 0x0e NOT_A_FILE, 0x0f NOT_A_DIRECTORY, 0x10 EOF, 0x11 TIMEOUT, 0x12 CANCELLED, 0x13 ACCESS, 0x14 DECOMPRESSION, 0x15 READ_ONLY, 0x16 WRITE_ONLY, 0x17 MEDIA_GONE, 0x18 PATH_TOO_LONG, 0x19 TOO_MANY_OVERLAYS, 0x1a BAD_OVERLAY, 0x1b BAD_ORDER, 0x1c BAD_INDEX, 0x1d EVENT_NOT_HANDLED, 0x1e BUSY, 0x1f BAD_ARCHIVE, 0x21 BAD_FLAGS, 0x22 UNKNOWN, 0x23 ALREADY_EXISTS and 0x24 IN_CALLBACK. 0x20 has no name, 0 is `SCE_FIOS_OK` and 1 is `SCE_FIOS_IN_PROGRESS` ### Unknown function info - [sceFiosArchiveGetDecompressorThreadCount, sceFiosArchiveGetMountBufferSize, sceFiosArchiveGetMountBufferSizeSync, sceFiosArchiveMount, sceFiosArchiveMountSync, sceFiosArchiveMountWithOrder, sceFiosArchiveMountWithOrderSync, sceFiosArchiveSetDecompressorThreadCount, sceFiosArchiveUnmount, sceFiosArchiveUnmountSync, sceFiosCacheContainsFileRangeSync, sceFiosCacheContainsFileSync, sceFiosCacheFlushFileRangeSync, sceFiosCacheFlushFileSync, sceFiosCacheFlushSync, sceFiosCachePrefetchFH, sceFiosCachePrefetchFHRange, sceFiosCachePrefetchFHRangeSync, sceFiosCachePrefetchFHSync, sceFiosCachePrefetchFile, sceFiosCachePrefetchFileRange, sceFiosCachePrefetchFileRangeSync, sceFiosCachePrefetchFileSync, sceFiosClearTimeStamps, sceFiosDLLInitialize, sceFiosDLLTerminate, sceFiosDeallocatePassthruFH, sceFiosDebugDumpDH, sceFiosDebugDumpDate, sceFiosDebugDumpError, sceFiosDebugDumpFH, sceFiosDebugDumpOp, sceFiosDirectoryCreateWithMode, sceFiosDirectoryCreateWithModeSync, sceFiosFHToFileno, sceFiosFilenoToFH, sceFiosIOFilterAdd, sceFiosIOFilterCache, sceFiosIOFilterGetInfo, sceFiosIOFilterPsarcDearchiver, sceFiosIOFilterRemove, sceFiosOpReschedule, sceFiosOpRescheduleWithPriority, sceFiosOpSetBuffer, sceFiosOpWaitUntil, sceFiosOverlayAdd, sceFiosOverlayGetInfo, sceFiosOverlayGetList, sceFiosOverlayModify, sceFiosOverlayRemove, sceFiosOverlayResolveSync, sceFiosPathNormalize, sceFiosPathcmp, sceFiosPathncmp, sceFiosPrintTimeStamps, sceFiosPrintf, sceFiosResolve, sceFiosResolveSync, sceFiosSaveTimeStamp, sceFiosTimeGetCurrent, sceFiosTraceTimestamp and sceFiosVprintf](../../../core/libs/prx/libSceFios2/Export.cpp) (libSceFios2) - names and NIDs are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceFios2.c), but no credible prototypes were found. The declarations have no parameters solely to resolve known imports; this is not an ABI claim and callers must not call them until signatures are verified