From 8f0a90d24bd9eef7b8820ce09eebc2081f295f9b Mon Sep 17 00:00:00 2001 From: Ivan Chikish Date: Mon, 14 Aug 2023 23:58:28 +0300 Subject: [PATCH] [orbis-kernel] Impl sys_getdirentries/sys_getdents --- orbis-kernel/include/orbis/file.hpp | 3 ++ orbis-kernel/include/orbis/stat.hpp | 21 +++++++++++ orbis-kernel/src/sys/sys_vfs.cpp | 29 +++++++++++++-- rpcsx-os/io-device.cpp | 37 +++++++++++++++++++ rpcsx-os/orbis-kernel-config/orbis-config.hpp | 3 +- 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/orbis-kernel/include/orbis/file.hpp b/orbis-kernel/include/orbis/file.hpp index a12e985e0..d6963cd86 100644 --- a/orbis-kernel/include/orbis/file.hpp +++ b/orbis-kernel/include/orbis/file.hpp @@ -1,6 +1,8 @@ #pragma once +#include "KernelAllocator.hpp" #include "error/ErrorCode.hpp" +#include "stat.hpp" #include "utils/Rc.hpp" #include "utils/SharedMutex.hpp" #include @@ -43,5 +45,6 @@ struct File : RcBase { const FileOps *ops = nullptr; Ref device; std::uint64_t nextOff = 0; + utils::kvector dirEntries; }; } // namespace orbis diff --git a/orbis-kernel/include/orbis/stat.hpp b/orbis-kernel/include/orbis/stat.hpp index 65f32be90..c99c522c2 100644 --- a/orbis-kernel/include/orbis/stat.hpp +++ b/orbis-kernel/include/orbis/stat.hpp @@ -23,4 +23,25 @@ struct Stat { int32_t lspare; timespec birthtim; // time of file creation }; + +struct Dirent { + uint32_t fileno; + uint16_t reclen; + uint8_t type; + uint8_t namlen; + char name[256]; +}; + +enum { + kDtUnknown = 0, + kDtFifo = 1, + kDtChr = 2, + kDtDir = 4, + kDtBlk = 6, + kDtReg = 8, + kDtLnk = 10, + kDtSock = 12, + kDtWht = 14, +}; + } // namespace orbis diff --git a/orbis-kernel/src/sys/sys_vfs.cpp b/orbis-kernel/src/sys/sys_vfs.cpp index 061baa7b6..c42d78ac9 100644 --- a/orbis-kernel/src/sys/sys_vfs.cpp +++ b/orbis-kernel/src/sys/sys_vfs.cpp @@ -304,13 +304,36 @@ orbis::SysResult orbis::sys_rmdir(Thread *thread, ptr path) { orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd, ptr buf, uint count, ptr basep) { - ORBIS_LOG_ERROR(__FUNCTION__, fd, (void *)buf, count, basep); - thread->where(); + ORBIS_LOG_WARNING(__FUNCTION__, fd, (void *)buf, count, basep); + Ref file = thread->tproc->fileDescriptors.get(fd); + if (file == nullptr) { + return ErrorCode::BADF; + } + + std::lock_guard lock(file->mtx); + const orbis::Dirent *entries = file->dirEntries.data(); + auto pos = file->nextOff / sizeof(orbis::Dirent); // TODO + auto rmax = count / sizeof(orbis::Dirent); + auto next = std::min(file->dirEntries.size(), pos + rmax); + file->nextOff = next * sizeof(orbis::Dirent); + SysResult result{}; + result = uwrite((orbis::Dirent *)buf, entries + pos, next - pos); + if (result.isError()) + return result; + + if (basep) { + result = uwrite(basep, slong(file->nextOff)); + if (result.isError()) + return result; + } + + thread->retval[0] = (next - pos) * sizeof(orbis::Dirent); return {}; } orbis::SysResult orbis::sys_getdents(Thread *thread, sint fd, ptr buf, size_t count) { - return ErrorCode::NOSYS; + ORBIS_LOG_WARNING(__FUNCTION__, fd, (void *)buf, count); + return orbis::sys_getdirentries(thread, fd, buf, count, nullptr); } orbis::SysResult orbis::sys_umask(Thread *thread, sint newmask) { return ErrorCode::NOSYS; diff --git a/rpcsx-os/io-device.cpp b/rpcsx-os/io-device.cpp index dce268e63..365e1e517 100644 --- a/rpcsx-os/io-device.cpp +++ b/rpcsx-os/io-device.cpp @@ -6,6 +6,7 @@ #include "orbis/utils/Logs.hpp" #include "vm.hpp" #include +#include #include #include #include @@ -87,6 +88,9 @@ static orbis::ErrorCode convertErrno() { static orbis::ErrorCode host_read(orbis::File *file, orbis::Uio *uio, orbis::Thread *) { auto hostFile = static_cast(file); + if (!hostFile->dirEntries.empty()) + return orbis::ErrorCode::ISDIR; + std::vector vec; for (auto entry : std::span(uio->iov, uio->iovcnt)) { vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); @@ -116,6 +120,9 @@ static orbis::ErrorCode host_read(orbis::File *file, orbis::Uio *uio, static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio, orbis::Thread *) { auto hostFile = static_cast(file); + if (!hostFile->dirEntries.empty()) + return orbis::ErrorCode::ISDIR; + std::vector vec; for (auto entry : std::span(uio->iov, uio->iovcnt)) { vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); @@ -147,6 +154,8 @@ static orbis::ErrorCode host_mmap(orbis::File *file, void **address, std::int32_t flags, std::int64_t offset, orbis::Thread *thread) { auto hostFile = static_cast(file); + if (!hostFile->dirEntries.empty()) + return orbis::ErrorCode::ISDIR; auto result = rx::vm::map(*address, size, prot, flags, rx::vm::kMapInternalReserveOnly); @@ -210,6 +219,9 @@ static orbis::ErrorCode host_stat(orbis::File *file, orbis::Stat *sb, static orbis::ErrorCode host_truncate(orbis::File *file, std::uint64_t len, orbis::Thread *thread) { auto hostFile = static_cast(file); + if (!hostFile->dirEntries.empty()) + return orbis::ErrorCode::ISDIR; + // hack for audio control shared memory std::uint64_t realLen = len; if (len == 3880) { @@ -321,8 +333,33 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref *file, return error; } + // Assume the file is a directory and try to read direntries + orbis::utils::kvector dirEntries; + while (true) { + ::dirent64 hostEntry{}; + auto r = getdents64(hostFd, &hostEntry, sizeof(hostEntry)); + if (r <= 0) + break; + + auto &entry = dirEntries.emplace_back(); + entry.fileno = dirEntries.size(); // TODO + entry.reclen = sizeof(entry); + entry.namlen = std::strlen(hostEntry.d_name); + std::strncpy(entry.name, hostEntry.d_name, sizeof(entry.name)); + if (hostEntry.d_type == DT_REG) + entry.type = orbis::kDtReg; + else if (hostEntry.d_type == DT_DIR || hostEntry.d_type == DT_LNK) + entry.type = orbis::kDtDir; // Assume symlinks to be dirs + else { + ORBIS_LOG_ERROR("host_open: unknown directory entry d_type", realPath, + hostEntry.d_name, hostEntry.d_type); + dirEntries.pop_back(); + } + } + auto newFile = orbis::knew(); newFile->hostFd = hostFd; + newFile->dirEntries = std::move(dirEntries); newFile->ops = &hostOps; newFile->device = this; *file = newFile; diff --git a/rpcsx-os/orbis-kernel-config/orbis-config.hpp b/rpcsx-os/orbis-kernel-config/orbis-config.hpp index 1a44ca757..fa52bf945 100644 --- a/rpcsx-os/orbis-kernel-config/orbis-config.hpp +++ b/rpcsx-os/orbis-kernel-config/orbis-config.hpp @@ -95,7 +95,8 @@ template } template -[[nodiscard]] ErrorCode uwrite(ptr pointer, T *data, std::size_t count) { +[[nodiscard]] ErrorCode uwrite(ptr pointer, const T *data, + std::size_t count) { return uwriteRaw(pointer, &data, sizeof(T) * count); }