From 7c44d13b3a80de887d63f24695f95e5a5c5e3b30 Mon Sep 17 00:00:00 2001 From: boykopovar Date: Sun, 13 Sep 2026 12:45:50 +0300 Subject: [PATCH] feat(libs): global shared path resolver in libc --- core/libs/prx/libc/include/General.hpp | 3 ++ core/libs/prx/libc/src/FileAndHeap.cpp | 19 +++++----- core/libs/prx/libc/src/General.cpp | 16 ++++++++ core/libs/prx/libkernel/CMakeLists.txt | 1 - core/libs/prx/libkernel/File/include/Path.hpp | 13 ------- core/libs/prx/libkernel/File/src/Open.cpp | 37 +++++++++---------- core/libs/prx/libkernel/File/src/Path.cpp | 20 ---------- 7 files changed, 46 insertions(+), 63 deletions(-) delete mode 100644 core/libs/prx/libkernel/File/include/Path.hpp delete mode 100644 core/libs/prx/libkernel/File/src/Path.cpp diff --git a/core/libs/prx/libc/include/General.hpp b/core/libs/prx/libc/include/General.hpp index 6fa5b99ab..987d0af45 100644 --- a/core/libs/prx/libc/include/General.hpp +++ b/core/libs/prx/libc/include/General.hpp @@ -2,6 +2,7 @@ #define CORE_LIBS_PRX_LIBC_INCLUDE_GENERAL_HPP #include +#include #include "general/LogMacros.hpp" #include "general/VabiMacros.hpp" @@ -9,6 +10,8 @@ extern "C" void NotImplemented_nid_no_patch(const char* funcName); +extern "C" std::filesystem::path ResolvePath_nid_no_patch(const char* path); + #define APS5_INVALID_ARG_EX throw std::invalid_argument(std::string(__func__) + ": invalid argument") #endif diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index 8d724f2a0..017283fca 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -14,21 +14,22 @@ extern "C" { FileStream* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode) { if (!filename || !mode) throw std::runtime_error(std::string(__func__) + ": " + FOPEN_MSG_NULL_ARG); - std::unique_ptr handle(std::fopen(filename, mode), std::fclose); - const auto abs_path = std::filesystem::absolute(filename).string(); + const std::filesystem::path fpath = ResolvePath_nid_no_patch(filename); + const auto abs_path = fpath.string(); + std::unique_ptr handle(std::fopen(abs_path.c_str(), mode), std::fclose); if (!handle) { const auto reason = std::strerror(errno); - const std::filesystem::path fpath(filename); - bool sibling_exists = false; std::error_code ec; - for (const auto& entry : std::filesystem::directory_iterator(std::filesystem::absolute(fpath.parent_path()), ec)) { - if (!ec && entry.path().stem() == fpath.stem() && entry.path().extension() != fpath.extension()) { - sibling_exists = true; + std::filesystem::path sibling; + for (const auto& entry : std::filesystem::directory_iterator(fpath.parent_path(), ec)) { + if (ec) break; + if (entry.path().stem() == fpath.stem() && entry.path().extension() != fpath.extension()) { + sibling = std::filesystem::absolute(entry.path()); break; } } - if (sibling_exists) { - APS5_LOG_OUT("%s: \"%s\": %s", FOPEN_MSG_NOT_FOUND, abs_path.c_str(), reason); + if (!sibling.empty()) { + APS5_LOG_OUT("%s: \"%s\": %s. Sibling: \"%s\"", FOPEN_MSG_NOT_FOUND, abs_path.c_str(), reason, sibling.string().c_str()); return nullptr; } throw std::runtime_error(std::string(__func__) + ": " + FOPEN_MSG_OPEN_FAILED + ": \"" + abs_path + "\": " + reason); diff --git a/core/libs/prx/libc/src/General.cpp b/core/libs/prx/libc/src/General.cpp index e70f3d513..b15c746eb 100644 --- a/core/libs/prx/libc/src/General.cpp +++ b/core/libs/prx/libc/src/General.cpp @@ -1,5 +1,21 @@ #include #include +#include + +#include "prx/libc/include/General.hpp" + +extern "C" std::filesystem::path ResolvePath_nid_no_patch(const char* path) { + if (path == nullptr) { + APS5_INVALID_ARG_EX; + } + std::string s(path); + std::size_t start = 0; + while (start < s.size() && (s[start] == '/' || s[start] == '\\')) { + ++start; + } + std::filesystem::path result = std::filesystem::current_path() / std::filesystem::path(s.substr(start)); + return result; +} extern "C" void NotImplemented_nid_no_patch(const char* funcName) { throw std::runtime_error(std::string(funcName) + " not implemented"); diff --git a/core/libs/prx/libkernel/CMakeLists.txt b/core/libs/prx/libkernel/CMakeLists.txt index 93b969f2d..aedaf3317 100644 --- a/core/libs/prx/libkernel/CMakeLists.txt +++ b/core/libs/prx/libkernel/CMakeLists.txt @@ -3,7 +3,6 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/Equeue/Equeue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/File/src/NativeStat.cpp ${CMAKE_CURRENT_SOURCE_DIR}/File/src/Open.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/File/src/Path.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Semaphore/src/Semaphore.cpp ${CMAKE_CURRENT_SOURCE_DIR}/DirectMemory/Export.cpp ${CMAKE_CURRENT_SOURCE_DIR}/DirectMemory/DirectMemory.cpp diff --git a/core/libs/prx/libkernel/File/include/Path.hpp b/core/libs/prx/libkernel/File/include/Path.hpp deleted file mode 100644 index de105d94d..000000000 --- a/core/libs/prx/libkernel/File/include/Path.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef CORE_LIBS_PRX_LIBKERNEL_FILE_PATH_HPP -#define CORE_LIBS_PRX_LIBKERNEL_FILE_PATH_HPP - -#include - - -namespace File { - -std::filesystem::path ResolvePath(const char* path); - -} - -#endif diff --git a/core/libs/prx/libkernel/File/src/Open.cpp b/core/libs/prx/libkernel/File/src/Open.cpp index 301307f30..5a8c065dc 100644 --- a/core/libs/prx/libkernel/File/src/Open.cpp +++ b/core/libs/prx/libkernel/File/src/Open.cpp @@ -1,6 +1,6 @@ #include "prx/libkernel/File/include/FileFlags.hpp" #include "prx/libkernel/File/include/NativeStat.hpp" -#include "prx/libkernel/File/include/Path.hpp" +#include "prx/libc/include/General.hpp" #include "prx/libkernel/File/include/File.hpp" #include "SceTypes.hpp" @@ -88,78 +88,75 @@ static int MapFlags(int sceFlags) { extern "C" { int APS5_VABI sceKernelOpen(const char* path, int flags, std::uint16_t mode) { - if (path == nullptr) { - throw std::invalid_argument("sceKernelOpen: path is null"); - } - auto native = File::ResolvePath(path); + auto native = ResolvePath_nid_no_patch(path); int fd = NativeOpen(native, MapFlags(flags), mode); if (fd < 0) { - throw std::runtime_error("sceKernelOpen: failed to open " + native.string() + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": failed to open " + native.string() + ", errno=" + std::to_string(errno)); } return fd; } int APS5_VABI sceKernelClose(int d) { if (NativeClose(d) != 0) { - throw std::runtime_error("sceKernelClose: close failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": close failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); } return 0; } std::int64_t APS5_VABI sceKernelRead(int d, void* buf, std::size_t nbytes) { if (buf == nullptr) { - throw std::invalid_argument("sceKernelRead: buf is null"); + throw std::invalid_argument(std::string(__func__) + ": buf is null"); } auto n = NativeRead(d, buf, nbytes); if (n < 0) { - throw std::runtime_error("sceKernelRead: read failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": read failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); } return static_cast(n); } std::int64_t APS5_VABI sceKernelWrite(int d, const void* buf, std::size_t nbytes) { if (buf == nullptr) { - throw std::invalid_argument("sceKernelWrite: buf is null"); + throw std::invalid_argument(std::string(__func__) + ": buf is null"); } auto n = NativeWrite(d, buf, nbytes); if (n < 0) { - throw std::runtime_error("sceKernelWrite: write failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": write failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); } return static_cast(n); } int APS5_VABI sceKernelLseek(int d, std::int64_t offset, int whence) { if (whence < 0 || whence > 2) { - throw std::invalid_argument("sceKernelLseek: invalid whence=" + std::to_string(whence)); + throw std::invalid_argument(std::string(__func__) + ": invalid whence=" + std::to_string(whence)); } std::int64_t result = NativeLseek(d, offset, whence); if (result < 0) { - throw std::runtime_error("sceKernelLseek: lseek failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": lseek failed, fd=" + std::to_string(d) + ", errno=" + std::to_string(errno)); } if (result > static_cast(std::numeric_limits::max())) { - throw std::overflow_error("sceKernelLseek: result " + std::to_string(result) + " overflows int return type"); + throw std::overflow_error(std::string(__func__) + ": result " + std::to_string(result) + " overflows int return type"); } return static_cast(result); } int APS5_VABI sceKernelStat(const char* path, FileStat* sb) { if (path == nullptr) { - throw std::invalid_argument("sceKernelStat: path is null"); + throw std::invalid_argument(std::string(__func__) + ": path is null"); } if (sb == nullptr) { - throw std::invalid_argument("sceKernelStat: sb is null"); + throw std::invalid_argument(std::string(__func__) + ": sb is null"); } - File::FillFileStat(File::ResolvePath(path), sb); + File::FillFileStat(ResolvePath_nid_no_patch(path), sb); return 0; } int APS5_VABI sceKernelUnlink(const char* path) { if (path == nullptr) { - throw std::invalid_argument("sceKernelUnlink: path is null"); + throw std::invalid_argument(std::string(__func__) + ": path is null"); } - auto native = File::ResolvePath(path); + auto native = ResolvePath_nid_no_patch(path); if (NativeUnlink(native) != 0) { - throw std::runtime_error("sceKernelUnlink: unlink failed for " + native.string() + ", errno=" + std::to_string(errno)); + throw std::runtime_error(std::string(__func__) + ": unlink failed for " + native.string() + ", errno=" + std::to_string(errno)); } return 0; } diff --git a/core/libs/prx/libkernel/File/src/Path.cpp b/core/libs/prx/libkernel/File/src/Path.cpp deleted file mode 100644 index fb378849e..000000000 --- a/core/libs/prx/libkernel/File/src/Path.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "prx/libkernel/File/include/Path.hpp" - -#include -#include - -namespace File { - -std::filesystem::path ResolvePath(const char* path) { - if (path == nullptr) { - throw std::invalid_argument("ResolvePath: path is null"); - } - std::filesystem::path p(path); - if (p.is_absolute()) { - auto rel = p.relative_path(); - return std::filesystem::current_path() / rel; - } - return std::filesystem::current_path() / p; -} - -}