initial dents support

This commit is contained in:
georgemoralis 2024-06-20 18:09:40 +03:00
parent 0325e4795a
commit 49601f58ed
5 changed files with 128 additions and 24 deletions

View File

@ -28,15 +28,13 @@ void MntPoints::UnmountAll() {
std::string MntPoints::GetHostDirectory(const std::string& guest_directory) {
std::scoped_lock lock{m_mutex};
for (auto& pair : m_mnt_pairs) {
if (pair.guest_path.starts_with(guest_directory)) {
return pair.host_path + guest_directory;
}
}
// hack for relative path , get app0 and assuming it goes from there
for (auto& pair : m_mnt_pairs) {
if (pair.guest_path.starts_with("/app0")) {
// horrible code but it works :D
int find = guest_directory.find(pair.guest_path);
if (find == 0) {
std::string npath =
guest_directory.substr(pair.guest_path.size(), guest_directory.size() - 1);
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
return pair.host_path + guest_directory;
return pair.host_path + npath;
}
}
return "";

View File

@ -32,13 +32,18 @@ private:
std::mutex m_mutex;
};
struct DirEntry {
std::string name;
bool isFile;
};
struct File {
std::atomic_bool is_opened{};
std::atomic_bool is_directory{};
std::string m_host_name;
std::string m_guest_name;
Common::FS::IOFile f;
// std::vector<Common::FS::DirEntry> dirents;
std::vector<DirEntry> dirents;
u32 dirents_index;
std::mutex m_mutex;
};

View File

@ -11,6 +11,29 @@
namespace Libraries::Kernel {
std::vector<Core::FileSys::DirEntry> GetDirectoryEntries(const std::string& path) {
std::string curpath = path;
if (!curpath.ends_with("/")) {
curpath = std::string(curpath + "/");
}
std::vector<Core::FileSys::DirEntry> files;
for (const auto& entry : std::filesystem::directory_iterator(curpath)) {
Core::FileSys::DirEntry e = {};
if (std::filesystem::is_regular_file(entry.path().string())) {
e.name = entry.path().filename().string();
e.isFile = true;
} else {
Core::FileSys::DirEntry e = {};
e.name = entry.path().filename().string() +
"/"; // hmmm not sure if it has to be like this...
e.isFile = false;
}
files.push_back(e);
}
return files;
}
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode);
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
@ -34,12 +57,23 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
if (std::string_view{path} == "/dev/console" || std::string_view{path} == "/dev/deci_tty6") {
return ORBIS_OK;
}
if (directory) {
LOG_ERROR(Kernel_Fs, "called on directory");
} else {
u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle);
if (directory) {
file->is_directory = true;
file->m_guest_name = path;
file->m_host_name = mnt->GetHostDirectory(file->m_guest_name);
if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist
UNREACHABLE(); // not supported yet
} else {
if (create) {
return handle; // dir already exists
} else {
file->dirents = GetDirectoryEntries(file->m_host_name);
file->dirents_index = 0;
}
}
} else {
file->m_guest_name = path;
file->m_host_name = mnt->GetHostFile(file->m_guest_name);
if (read) {
@ -61,10 +95,9 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
h->DeleteHandle(handle);
return SCE_KERNEL_ERROR_EACCES;
}
}
file->is_opened = true;
return handle;
}
return -1; // dummy
}
int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
@ -310,6 +343,62 @@ s32 PS4_SYSV_ABI sceKernelFsync(int fd) {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) {
LOG_INFO(Kernel_Fs, "(PARTIAL) fd = {}", fd);
// TODO error codes
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(fd);
if (file->dirents_index == file->dirents.size()) {
return 0;
}
const auto& entry = file->dirents.at(file->dirents_index++);
auto str = entry.name;
auto str_size = str.size() - 1;
static int fileno = 1000; // random
OrbisKernelDirent* sce_ent = (OrbisKernelDirent*)buf;
sce_ent->d_fileno = fileno++; // TODO this should be unique but atm it changes maybe switch to a
// hash or something?
sce_ent->d_reclen = sizeof(OrbisKernelDirent);
sce_ent->d_type = (entry.isFile ? 8 : 4);
sce_ent->d_namlen = str_size;
strncpy(sce_ent->d_name, str.c_str(), ORBIS_MAX_PATH);
sce_ent->d_name[ORBIS_MAX_PATH] = '\0';
return sizeof(OrbisKernelDirent);
}
int PS4_SYSV_ABI sceKernelGetdirentries(int fd, char* buf, int nbytes, s64* basep) {
LOG_INFO(Kernel_Fs, "(PARTIAL) fd = {}", fd);
// TODO error codes
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(fd);
if (basep != nullptr) {
*basep = file->dirents_index;
}
if (file->dirents_index == file->dirents.size()) {
return 0;
}
const auto& entry = file->dirents.at(file->dirents_index++);
auto str = entry.name;
auto str_size = str.size() - 1;
static int fileno = 1000; // random
OrbisKernelDirent* sce_ent = (OrbisKernelDirent*)buf;
sce_ent->d_fileno = fileno++; // TODO this should be unique but atm it changes maybe switch to a
// hash or something?
sce_ent->d_reclen = sizeof(OrbisKernelDirent);
sce_ent->d_type = (entry.isFile ? 8 : 4);
sce_ent->d_namlen = str_size;
strncpy(sce_ent->d_name, str.c_str(), ORBIS_MAX_PATH);
sce_ent->d_name[ORBIS_MAX_PATH] = '\0';
return sizeof(OrbisKernelDirent);
}
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);
@ -333,6 +422,8 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
LIB_FUNCTION("uWyW3v98sU4", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckReachability);
LIB_FUNCTION("fTx66l5iWIA", "libkernel", 1, "libkernel", 1, 1, sceKernelFsync);
LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents);
LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries);
// openOrbis (to check if it is valid out of OpenOrbis
LIB_FUNCTION("6c3rCVE-fTU", "libkernel", 1, "libkernel", 1, 1,

View File

@ -12,6 +12,8 @@ class SymbolsResolver;
namespace Libraries::Kernel {
constexpr int ORBIS_MAX_PATH = 255;
struct SceKernelIovec {
void* iov_base;
std::size_t iov_len;
@ -39,6 +41,14 @@ struct OrbisKernelStat {
unsigned int : (8 / 2) * (16 - static_cast<int>(sizeof(OrbisKernelTimespec)));
};
struct OrbisKernelDirent {
u32 d_fileno; /* file number of entry */
u16 d_reclen; /* length of this record */
u8 d_type; /* file type, see below */
u8 d_namlen; /* length of string in d_name */
char d_name[ORBIS_MAX_PATH + 1]; /* name must be no longer than this */
};
// flags for Open
constexpr int ORBIS_KERNEL_O_RDONLY = 0x0000;
constexpr int ORBIS_KERNEL_O_WRONLY = 0x0001;