feat(libs): global shared path resolver in libc
This commit is contained in:
parent
f66a8fc5c4
commit
7c44d13b3a
|
|
@ -2,6 +2,7 @@
|
|||
#define CORE_LIBS_PRX_LIBC_INCLUDE_GENERAL_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <filesystem>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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<std::FILE, decltype(&std::fclose)> 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<std::FILE, decltype(&std::fclose)> 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);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef CORE_LIBS_PRX_LIBKERNEL_FILE_PATH_HPP
|
||||
#define CORE_LIBS_PRX_LIBKERNEL_FILE_PATH_HPP
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
namespace File {
|
||||
|
||||
std::filesystem::path ResolvePath(const char* path);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -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<std::int64_t>(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<std::int64_t>(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::int64_t>(std::numeric_limits<int>::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<int>(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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
#include "prx/libkernel/File/include/Path.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue