improvements in sceKernelOpen, rewrote sceKernelLseek, added sceKernelWrite, added sceKernelMkdir , partial sceKernelStat

This commit is contained in:
georgemoralis 2024-05-05 12:43:01 +03:00
parent 277e16c7ba
commit ad6724eeba
2 changed files with 156 additions and 20 deletions

View file

@ -12,25 +12,48 @@
namespace Libraries::Kernel {
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {:#x}", path, flags, mode);
ASSERT_MSG(flags == 0, "flags!=0 not supported yet");
ASSERT_MSG(mode == 0, "mode!=0 not supported yet");
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode);
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
// only open files support!
u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle);
file->m_guest_name = path;
file->m_host_name = mnt->GetHostFile(file->m_guest_name);
bool read = (flags & 0x3) == ORBIS_KERNEL_O_RDONLY;
bool write = (flags & 0x3) == ORBIS_KERNEL_O_WRONLY;
bool rdwr = (flags & 0x3) == ORBIS_KERNEL_O_RDWR;
file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
if (!file->f.IsOpen()) {
h->DeleteHandle(handle);
return SCE_KERNEL_ERROR_EACCES;
bool nonblock = (flags & ORBIS_KERNEL_O_NONBLOCK) != 0;
bool append = (flags & ORBIS_KERNEL_O_APPEND) != 0;
bool fsync = (flags & ORBIS_KERNEL_O_FSYNC) != 0;
bool sync = (flags & ORBIS_KERNEL_O_SYNC) != 0;
bool create = (flags & ORBIS_KERNEL_O_CREAT) != 0;
bool truncate = (flags & ORBIS_KERNEL_O_TRUNC) != 0;
bool excl = (flags & ORBIS_KERNEL_O_EXCL) != 0;
bool dsync = (flags & ORBIS_KERNEL_O_DSYNC) != 0;
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
if (directory) {
UNREACHABLE(); // not supported yet
} else {
// only open files support!
u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle);
file->m_guest_name = path;
file->m_host_name = mnt->GetHostFile(file->m_guest_name);
if (read) {
file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Read);
} else if (write && create && truncate) {
file->f.Open(file->m_host_name, Common::FS::FileAccessMode::Write);
} else {
UNREACHABLE();
}
if (!file->f.IsOpen()) {
h->DeleteHandle(handle);
return SCE_KERNEL_ERROR_EACCES;
}
file->is_opened = true;
return handle;
}
file->is_opened = true;
return handle;
return -1; // dummy
}
int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
@ -56,6 +79,20 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
return SCE_OK;
}
size_t PS4_SYSV_ABI sceKernelWrite(int d, void* buf, size_t nbytes) {
if (buf == nullptr) {
return SCE_KERNEL_ERROR_EFAULT;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d);
if (file == nullptr) {
return SCE_KERNEL_ERROR_EBADF;
}
file->m_mutex.lock();
u32 bytes_write = file->f.WriteRaw<u8>(buf, static_cast<u32>(nbytes));
file->m_mutex.unlock();
return bytes_write;
}
size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d);
@ -73,18 +110,19 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) {
auto* file = h->GetFile(d);
file->m_mutex.lock();
Common::FS::SeekOrigin origin;
if (whence == 0) {
origin = Common::FS::SeekOrigin::SetOrigin;
}
if (whence == 1) {
offset = static_cast<int64_t>(file->f.Tell()) + offset;
whence = 0;
origin = Common::FS::SeekOrigin::CurrentPosition;
}
if (whence == 2) {
offset = static_cast<int64_t>(file->f.GetSize()) + offset;
whence = 0;
origin = Common::FS::SeekOrigin::End;
}
file->f.Seek(offset);
file->f.Seek(offset, origin);
auto pos = static_cast<int64_t>(file->f.Tell());
file->m_mutex.unlock();
@ -111,15 +149,74 @@ s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
return bytes_read;
}
int PS4_SYSV_ABI sceKernelMkdir(const char* path, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} mode = {}", path, mode);
if (path == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
std::string dir_name = mnt->GetHostFile(path);
if (std::filesystem::exists(dir_name)) {
return SCE_KERNEL_ERROR_EEXIST;
}
if (!std::filesystem::create_directory(dir_name)) {
return SCE_KERNEL_ERROR_EIO;
}
if (!std::filesystem::exists(dir_name)) {
return SCE_KERNEL_ERROR_ENOENT;
}
return ORBIS_OK;
}
int PS4_SYSV_ABI sceKernelStat(const char* path, OrbisKernelStat* sb) {
LOG_INFO(Kernel_Fs, "(PARTIAL) path = {}", path);
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
std::string path_name = mnt->GetHostFile(path);
memset(sb, 0, sizeof(OrbisKernelStat));
bool is_dir = std::filesystem::is_directory(path_name);
bool is_file = std::filesystem::is_regular_file(path_name);
if (!is_dir && !is_file) {
return ORBIS_KERNEL_ERROR_ENOENT;
}
if (std::filesystem::is_directory(path_name)) {
sb->st_mode = 0000777u | 0040000u;
sb->st_size = 0;
sb->st_blksize = 512;
sb->st_blocks = 0;
// TODO incomplete
} else {
sb->st_mode = 0000777u | 0100000u;
sb->st_size = static_cast<int64_t>(std::filesystem::file_size(path_name));
sb->st_blksize = 512;
sb->st_blocks = (sb->st_size + 511) / 512;
// TODO incomplete
}
return ORBIS_OK;
}
int PS4_SYSV_ABI posix_stat(const char* path, OrbisKernelStat* sb) {
int result = sceKernelStat(path, sb);
if (result < 0) {
UNREACHABLE(); // TODO
}
return ORBIS_OK;
}
void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose);
LIB_FUNCTION("4wSze92BhLI", "libkernel", 1, "libkernel", 1, 1, sceKernelWrite);
LIB_FUNCTION("+WRlkKjZvag", "libkernel", 1, "libkernel", 1, 1, _readv);
LIB_FUNCTION("Oy6IpwgtYOk", "libkernel", 1, "libkernel", 1, 1, lseek);
LIB_FUNCTION("oib76F-12fk", "libkernel", 1, "libkernel", 1, 1, sceKernelLseek);
LIB_FUNCTION("Cg4srZ6TKbU", "libkernel", 1, "libkernel", 1, 1, sceKernelRead);
LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir);
LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat);
LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat);
// openOrbis (to check if it is valid out of OpenOrbis
LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1,

View file

@ -4,6 +4,7 @@
#pragma once
#include "common/types.h"
#include "thread_management.h"
namespace Core::Loader {
class SymbolsResolver;
@ -16,6 +17,44 @@ struct SceKernelIovec {
std::size_t iov_len;
};
struct OrbisKernelStat {
u32 st_dev;
u32 st_ino;
u16 st_mode;
u16 st_nlink;
u32 st_uid;
u32 st_gid;
u32 st_rdev;
SceKernelTimespec st_atim;
SceKernelTimespec st_mtim;
SceKernelTimespec st_ctim;
s64 st_size;
s64 st_blocks;
u32 st_blksize;
u32 st_flags;
u32 st_gen;
s32 st_lspare;
SceKernelTimespec st_birthtim;
unsigned int : (8 / 2) * (16 - static_cast<int>(sizeof(SceKernelTimespec)));
unsigned int : (8 / 2) * (16 - static_cast<int>(sizeof(SceKernelTimespec)));
};
// flags for Open
constexpr int ORBIS_KERNEL_O_RDONLY = 0x0000;
constexpr int ORBIS_KERNEL_O_WRONLY = 0x0001;
constexpr int ORBIS_KERNEL_O_RDWR = 0x0002;
constexpr int ORBIS_KERNEL_O_NONBLOCK = 0x0004;
constexpr int ORBIS_KERNEL_O_APPEND = 0x0008;
constexpr int ORBIS_KERNEL_O_FSYNC = 0x0080;
constexpr int ORBIS_KERNEL_O_SYNC = 0x0080;
constexpr int ORBIS_KERNEL_O_CREAT = 0x0200;
constexpr int ORBIS_KERNEL_O_TRUNC = 0x0400;
constexpr int ORBIS_KERNEL_O_EXCL = 0x0800;
constexpr int ORBIS_KERNEL_O_DSYNC = 0x1000;
constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000;
constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, /* SceKernelMode*/ u16 mode);
int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode);