From 3cc56bf84ce03dc049baa200a10a449ca84afe2d Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:43:30 -0500 Subject: [PATCH] More verbose errors for file opening failures (#4173) * Verbose errors for file opening failures These can be pretty helpful, and games don't usually spam them outside loading screens. * oops --- src/core/libraries/kernel/file_system.cpp | 14 +++++++++++++- .../libraries/libc_internal/libc_internal_io.cpp | 6 +++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 184343801..085e18b9f 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -87,11 +87,13 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { if (!read && !write && !rdwr) { // Start by checking for invalid flags. *__Error() = POSIX_EINVAL; + LOG_ERROR(Kernel_Fs, "Opening path {} failed, invalid flags {:#x}", raw_path, flags); return -1; } if (strlen(raw_path) > 255) { *__Error() = POSIX_ENAMETOOLONG; + LOG_ERROR(Kernel_Fs, "Opening path {} failed, path is too long", raw_path); return -1; } @@ -137,6 +139,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Error if file exists h->DeleteHandle(handle); *__Error() = POSIX_EEXIST; + LOG_ERROR(Kernel_Fs, "Creating {} failed, file already exists", raw_path); return -1; } @@ -145,6 +148,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Can't create files in a read only directory h->DeleteHandle(handle); *__Error() = POSIX_EROFS; + LOG_ERROR(Kernel_Fs, "Creating {} failed, path is read-only", raw_path); return -1; } // Create a file if it doesn't exist @@ -154,6 +158,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // If we're not creating a file, and it doesn't exist, return ENOENT h->DeleteHandle(handle); *__Error() = POSIX_ENOENT; + LOG_ERROR(Kernel_Fs, "Opening path {} failed, file does not exist", raw_path); return -1; } @@ -169,6 +174,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // This will trigger when create & directory is specified, this is expected. h->DeleteHandle(handle); *__Error() = POSIX_ENOTDIR; + LOG_ERROR(Kernel_Fs, "Opening directory {} failed, file is not a directory", raw_path); return -1; } @@ -176,6 +182,8 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Cannot open directories with any type of write access h->DeleteHandle(handle); *__Error() = POSIX_EISDIR; + LOG_ERROR(Kernel_Fs, "Opening directory {} failed, cannot open directories for writing", + raw_path); return -1; } @@ -183,6 +191,8 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Cannot open directories with truncate h->DeleteHandle(handle); *__Error() = POSIX_EISDIR; + LOG_ERROR(Kernel_Fs, "Opening directory {} failed, cannot truncate directories", + raw_path); return -1; } @@ -201,6 +211,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Can't open files with truncate flag in a read only directory h->DeleteHandle(handle); *__Error() = POSIX_EROFS; + LOG_ERROR(Kernel_Fs, "Truncating {} failed, path is read-only", raw_path); return -1; } else if (truncate) { // Open the file as read-write so we can truncate regardless of flags. @@ -219,6 +230,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Can't open files with write/read-write access in a read only directory h->DeleteHandle(handle); *__Error() = POSIX_EROFS; + LOG_ERROR(Kernel_Fs, "Opening {} for writing failed, path is read-only", raw_path); return -1; } else if (write) { if (append) { @@ -244,6 +256,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) { // Open failed in platform-specific code, errno needs to be converted. h->DeleteHandle(handle); SetPosixErrno(e); + LOG_ERROR(Kernel_Fs, "Opening {} failed, error = {}", raw_path, *__Error()); return -1; } @@ -258,7 +271,6 @@ s32 PS4_SYSV_ABI posix_open(const char* filename, s32 flags, u16 mode) { s32 PS4_SYSV_ABI sceKernelOpen(const char* path, s32 flags, /* SceKernelMode*/ u16 mode) { s32 result = open(path, flags, mode); if (result < 0) { - LOG_ERROR(Kernel_Fs, "error = {}", *__Error()); return ErrnoToSceKernelError(*__Error()); } return result; diff --git a/src/core/libraries/libc_internal/libc_internal_io.cpp b/src/core/libraries/libc_internal/libc_internal_io.cpp index 504ba5b48..0bb23eb78 100644 --- a/src/core/libraries/libc_internal/libc_internal_io.cpp +++ b/src/core/libraries/libc_internal/libc_internal_io.cpp @@ -199,7 +199,11 @@ OrbisFILE* PS4_SYSV_ABI internal_fopen(const char* path, const char* mode) { std::scoped_lock lk{g_file_mtx}; LOG_INFO(Lib_LibcInternal, "called, path {}, mode {}", path, mode); OrbisFILE* file = internal__Fofind(); - return internal__Foprep(path, mode, file, -1, 0, 0); + OrbisFILE* ret_file = internal__Foprep(path, mode, file, -1, 0, 0); + if (ret_file == nullptr) { + LOG_ERROR(Lib_LibcInternal, "failed to open file {}", path); + } + return ret_file; } s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* file) {