mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
184 lines
5.6 KiB
C++
184 lines
5.6 KiB
C++
#include "prx/libkernel/include/Api.hpp"
|
|
#include "prx/libc/include/Api.hpp"
|
|
#include "prx/libc/include/GuestDirectory.hpp"
|
|
#include "prx/libc/include/General.hpp"
|
|
#include "SceTypes.hpp"
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
|
|
namespace {
|
|
|
|
constexpr std::size_t NameCapacity = 260;
|
|
constexpr std::size_t CurrentCapacity = 256;
|
|
constexpr int NoSuchFile = 2;
|
|
constexpr int Exists = 17;
|
|
constexpr int NotDirectory = 20;
|
|
constexpr int Invalid = 22;
|
|
constexpr int NameTooLong = 63;
|
|
constexpr std::uint16_t DefaultDirectoryMode = 0777;
|
|
constexpr std::uint16_t PermissionBits = 07777;
|
|
|
|
enum FileType : int {
|
|
TypeNotFound = -1,
|
|
TypeNone = 0,
|
|
TypeRegular = 1,
|
|
TypeDirectory = 2,
|
|
TypeSymlink = 3,
|
|
TypeBlock = 4,
|
|
TypeCharacter = 5,
|
|
TypeFifo = 6,
|
|
TypeSocket = 7,
|
|
TypeUnknown = 8,
|
|
};
|
|
|
|
int& GuestErrno() {
|
|
return *__error_nid_postfix();
|
|
}
|
|
|
|
int TypeOfMode(std::uint16_t mode) {
|
|
switch (mode & 0170000) {
|
|
case 0010000: return TypeFifo;
|
|
case 0020000: return TypeCharacter;
|
|
case 0040000: return TypeDirectory;
|
|
case 0060000: return TypeBlock;
|
|
case 0100000: return TypeRegular;
|
|
case 0120000: return TypeSymlink;
|
|
case 0140000: return TypeSocket;
|
|
default: return TypeUnknown;
|
|
}
|
|
}
|
|
|
|
int StatType(const char* path, int* perms, int* error) {
|
|
GuestErrno() = 0;
|
|
FileStat status{};
|
|
int type;
|
|
if (stat_nid_postfix(path, &status) == 0) {
|
|
GuestErrno() = 0;
|
|
if (perms) *perms = status.st_mode & PermissionBits;
|
|
type = TypeOfMode(status.st_mode);
|
|
} else {
|
|
const int code = GuestErrno();
|
|
type = code == NoSuchFile || code == NotDirectory || code == Invalid || code == NameTooLong ? TypeNotFound : TypeNone;
|
|
}
|
|
if (error) *error = GuestErrno();
|
|
return type;
|
|
}
|
|
|
|
void CopyName(char* target, const char* source) {
|
|
std::size_t length = 0;
|
|
while (length < NameCapacity - 1 && source[length] != '\0') {
|
|
target[length] = source[length];
|
|
++length;
|
|
}
|
|
target[length] = '\0';
|
|
}
|
|
|
|
bool IsDotEntry(const char* name) {
|
|
return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
|
|
}
|
|
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int APS5_VABI _ZNSt10filesystem5_StatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error) {
|
|
return StatType(path, perms, error);
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem6_LstatEPKcPNS_5permsEPi_nid_postfix(const char* path, int* perms, int* error) {
|
|
return StatType(path, perms, error);
|
|
}
|
|
|
|
std::uint64_t APS5_VABI _ZNSt10filesystem10_File_sizeEPKcPi_nid_postfix(const char* path, int* error) {
|
|
FileStat status{};
|
|
if (stat_nid_postfix(path, &status) != 0) {
|
|
if (error) *error = GuestErrno();
|
|
return UINT64_MAX;
|
|
}
|
|
return static_cast<std::uint64_t>(status.st_size);
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem16_Last_write_timeEPKcPlS2__nid_postfix(const char* path, std::int64_t* seconds, std::int64_t* nanoseconds) {
|
|
FileStat status{};
|
|
if (stat_nid_postfix(path, &status) != 0) return GuestErrno();
|
|
*seconds = status.st_mtim.tv_sec;
|
|
*nanoseconds = status.st_mtim.tv_nsec;
|
|
return 0;
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem9_Make_dirEPKcS1__nid_postfix(const char* path, const char* existing) {
|
|
GuestErrno() = 0;
|
|
std::uint16_t mode = DefaultDirectoryMode;
|
|
if (existing) {
|
|
FileStat status{};
|
|
if (stat_nid_postfix(existing, &status) != 0) return -GuestErrno();
|
|
mode = status.st_mode;
|
|
}
|
|
if (mkdir_nid_postfix(path, mode) == 0) return 1;
|
|
if (GuestErrno() == Exists) return 0;
|
|
return -GuestErrno();
|
|
}
|
|
|
|
bool APS5_VABI _ZNSt10filesystem11_Remove_dirEPKc_nid_postfix(const char* path) {
|
|
return rmdir_nid_postfix(path) == 0;
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem7_UnlinkEPKc_nid_postfix(const char* path) {
|
|
GuestErrno() = 0;
|
|
return unlink_nid_postfix(path) == 0 ? 0 : GuestErrno();
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem6_ChmodEPKcNS_5permsE_nid_postfix(const char* path, int perms) {
|
|
return chmod_nid_postfix(path, static_cast<std::uint16_t>(perms));
|
|
}
|
|
|
|
bool APS5_VABI _ZNSt10filesystem12_Current_getERA260_c_nid_postfix(char* target) {
|
|
char current[CurrentCapacity];
|
|
const bool found = getcwd_nid_postfix(current, sizeof(current)) != nullptr;
|
|
if (found) CopyName(target, current);
|
|
else target[0] = '\0';
|
|
return found;
|
|
}
|
|
|
|
char* APS5_VABI _ZNSt10filesystem9_Read_dirERA260_cPvRNS_9file_typeE_nid_postfix(char* target, void* handle, int* type) {
|
|
*type = TypeUnknown;
|
|
GuestDirectoryEntry entry{};
|
|
GuestDirectoryEntry* result = nullptr;
|
|
while (readdir_r_nid_postfix(handle, &entry, &result) == 0 && result) {
|
|
if (IsDotEntry(entry.name)) continue;
|
|
CopyName(target, entry.name);
|
|
return target;
|
|
}
|
|
target[0] = '\0';
|
|
return target;
|
|
}
|
|
|
|
void* APS5_VABI _ZNSt10filesystem9_Open_dirERA260_cPKcRiRNS_9file_typeE_nid_postfix(char* target, const char* path, int* error, int* type) {
|
|
GuestErrno() = 0;
|
|
void* handle = opendir_nid_postfix(path);
|
|
if (!handle) {
|
|
*error = GuestErrno();
|
|
return nullptr;
|
|
}
|
|
*error = 0;
|
|
_ZNSt10filesystem9_Read_dirERA260_cPvRNS_9file_typeE_nid_postfix(target, handle, type);
|
|
if (target[0] != '\0') return handle;
|
|
closedir_nid_postfix(handle);
|
|
return nullptr;
|
|
}
|
|
|
|
int APS5_VABI _ZNSt10filesystem10_Close_dirEPv_nid_postfix(void* handle) {
|
|
return closedir_nid_postfix(handle);
|
|
}
|
|
|
|
void APS5_VABI _ZNSt10filesystem18_Xfilesystem_errorEPKcSt10error_code_nid_postfix() {
|
|
NotImplemented_nid_no_patch(__func__);
|
|
}
|
|
|
|
void APS5_VABI _ZNSt10filesystem18_Xfilesystem_errorEPKcRKNS_4pathESt10error_code_nid_postfix() {
|
|
NotImplemented_nid_no_patch(__func__);
|
|
}
|
|
|
|
}
|