sceKernelGetdents,sceKernelGetdirentries and some directory support
This commit is contained in:
parent
4c0e24b076
commit
b30bedd0ae
|
@ -28,15 +28,13 @@ void MntPoints::UnmountAll() {
|
||||||
std::string MntPoints::GetHostDirectory(const std::string& guest_directory) {
|
std::string MntPoints::GetHostDirectory(const std::string& guest_directory) {
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
for (auto& pair : m_mnt_pairs) {
|
for (auto& pair : m_mnt_pairs) {
|
||||||
if (pair.guest_path.starts_with(guest_directory)) {
|
// horrible code but it works :D
|
||||||
return pair.host_path + guest_directory;
|
int find = guest_directory.find(pair.guest_path);
|
||||||
}
|
if (find == 0) {
|
||||||
}
|
std::string npath =
|
||||||
// hack for relative path , get app0 and assuming it goes from there
|
guest_directory.substr(pair.guest_path.size(), guest_directory.size() - 1);
|
||||||
for (auto& pair : m_mnt_pairs) {
|
|
||||||
if (pair.guest_path.starts_with("/app0")) {
|
|
||||||
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
|
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
|
||||||
return pair.host_path + guest_directory;
|
return pair.host_path + npath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
@ -97,4 +95,5 @@ File* HandleTable::getFile(const std::string& host_name) {
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::FileSys
|
} // namespace Core::FileSys
|
||||||
|
|
|
@ -32,13 +32,18 @@ private:
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DirEntry {
|
||||||
|
std::string name;
|
||||||
|
bool isFile;
|
||||||
|
};
|
||||||
|
|
||||||
struct File {
|
struct File {
|
||||||
std::atomic_bool is_opened{};
|
std::atomic_bool is_opened{};
|
||||||
std::atomic_bool is_directory{};
|
std::atomic_bool is_directory{};
|
||||||
std::string m_host_name;
|
std::string m_host_name;
|
||||||
std::string m_guest_name;
|
std::string m_guest_name;
|
||||||
Common::FS::IOFile f;
|
Common::FS::IOFile f;
|
||||||
// std::vector<Common::FS::DirEntry> dirents;
|
std::vector<DirEntry> dirents;
|
||||||
u32 dirents_index;
|
u32 dirents_index;
|
||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,29 @@
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
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) {
|
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
||||||
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode);
|
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode);
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
|
@ -31,11 +54,23 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
||||||
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
||||||
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
||||||
|
|
||||||
if (directory) {
|
|
||||||
UNREACHABLE(); // not supported yet
|
|
||||||
} else {
|
|
||||||
u32 handle = h->CreateHandle();
|
u32 handle = h->CreateHandle();
|
||||||
auto* file = h->GetFile(handle);
|
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_guest_name = path;
|
||||||
file->m_host_name = mnt->GetHostFile(file->m_guest_name);
|
file->m_host_name = mnt->GetHostFile(file->m_guest_name);
|
||||||
if (read) {
|
if (read) {
|
||||||
|
@ -57,10 +92,62 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
||||||
h->DeleteHandle(handle);
|
h->DeleteHandle(handle);
|
||||||
return SCE_KERNEL_ERROR_EACCES;
|
return SCE_KERNEL_ERROR_EACCES;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
file->is_opened = true;
|
file->is_opened = true;
|
||||||
return handle;
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) {
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
return -1; // dummy
|
|
||||||
|
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) {
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
|
int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
|
||||||
|
@ -277,6 +364,9 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir);
|
LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir);
|
||||||
LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat);
|
LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat);
|
||||||
LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFStat);
|
LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFStat);
|
||||||
|
LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents);
|
||||||
|
LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries);
|
||||||
|
|
||||||
|
|
||||||
LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat);
|
LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat);
|
||||||
LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
|
LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread);
|
||||||
|
|
|
@ -12,6 +12,8 @@ class SymbolsResolver;
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
constexpr int ORBIS_MAX_PATH = 255;
|
||||||
|
|
||||||
struct SceKernelIovec {
|
struct SceKernelIovec {
|
||||||
void* iov_base;
|
void* iov_base;
|
||||||
std::size_t iov_len;
|
std::size_t iov_len;
|
||||||
|
@ -39,6 +41,14 @@ struct OrbisKernelStat {
|
||||||
unsigned int : (8 / 2) * (16 - static_cast<int>(sizeof(SceKernelTimespec)));
|
unsigned int : (8 / 2) * (16 - static_cast<int>(sizeof(SceKernelTimespec)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
// flags for Open
|
||||||
constexpr int ORBIS_KERNEL_O_RDONLY = 0x0000;
|
constexpr int ORBIS_KERNEL_O_RDONLY = 0x0000;
|
||||||
constexpr int ORBIS_KERNEL_O_WRONLY = 0x0001;
|
constexpr int ORBIS_KERNEL_O_WRONLY = 0x0001;
|
||||||
|
|
|
@ -113,12 +113,16 @@ s32 PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool enable) {
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePadGetHandle(s32 userId, int32_t type, int32_t index) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void padSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void padSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("hv1luiJrqQM", "libScePad", 1, "libScePad", 1, 1, scePadInit);
|
LIB_FUNCTION("hv1luiJrqQM", "libScePad", 1, "libScePad", 1, 1, scePadInit);
|
||||||
LIB_FUNCTION("xk0AcarP3V4", "libScePad", 1, "libScePad", 1, 1, scePadOpen);
|
LIB_FUNCTION("xk0AcarP3V4", "libScePad", 1, "libScePad", 1, 1, scePadOpen);
|
||||||
LIB_FUNCTION("YndgXqQVV7c", "libScePad", 1, "libScePad", 1, 1, scePadReadState);
|
LIB_FUNCTION("YndgXqQVV7c", "libScePad", 1, "libScePad", 1, 1, scePadReadState);
|
||||||
LIB_FUNCTION("q1cHNfGycLI", "libScePad", 1, "libScePad", 1, 1, scePadRead);
|
LIB_FUNCTION("q1cHNfGycLI", "libScePad", 1, "libScePad", 1, 1, scePadRead);
|
||||||
|
LIB_FUNCTION("u1GRHp+oWoY", "libScePad", 1, "libScePad", 1, 1, scePadGetHandle);
|
||||||
LIB_FUNCTION("gjP9-KQzoUk", "libScePad", 1, "libScePad", 1, 1, scePadGetControllerInformation);
|
LIB_FUNCTION("gjP9-KQzoUk", "libScePad", 1, "libScePad", 1, 1, scePadGetControllerInformation);
|
||||||
LIB_FUNCTION("clVvL4ZDntw", "libScePad", 1, "libScePad", 1, 1, scePadSetMotionSensorState);
|
LIB_FUNCTION("clVvL4ZDntw", "libScePad", 1, "libScePad", 1, 1, scePadSetMotionSensorState);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue