mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-02-25 09:04:47 +01:00
[orbis-kernel] Impl sys_getdirentries/sys_getdents
This commit is contained in:
parent
8179a638ad
commit
8f0a90d24b
|
|
@ -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 <cstdint>
|
||||
|
|
@ -43,5 +45,6 @@ struct File : RcBase {
|
|||
const FileOps *ops = nullptr;
|
||||
Ref<RcBase> device;
|
||||
std::uint64_t nextOff = 0;
|
||||
utils::kvector<Dirent> dirEntries;
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -304,13 +304,36 @@ orbis::SysResult orbis::sys_rmdir(Thread *thread, ptr<char> path) {
|
|||
orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd,
|
||||
ptr<char> buf, uint count,
|
||||
ptr<slong> basep) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, fd, (void *)buf, count, basep);
|
||||
thread->where();
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, fd, (void *)buf, count, basep);
|
||||
Ref<File> 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<uint64_t>(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<char> 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;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "orbis/utils/Logs.hpp"
|
||||
#include "vm.hpp"
|
||||
#include <cerrno>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
|
@ -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<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
std::vector<iovec> 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<HostFile *>(file);
|
||||
if (!hostFile->dirEntries.empty())
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
|
||||
std::vector<iovec> 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<HostFile *>(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<HostFile *>(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<orbis::File> *file,
|
|||
return error;
|
||||
}
|
||||
|
||||
// Assume the file is a directory and try to read direntries
|
||||
orbis::utils::kvector<orbis::Dirent> 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<HostFile>();
|
||||
newFile->hostFd = hostFd;
|
||||
newFile->dirEntries = std::move(dirEntries);
|
||||
newFile->ops = &hostOps;
|
||||
newFile->device = this;
|
||||
*file = newFile;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ template <typename T>
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] ErrorCode uwrite(ptr<T> pointer, T *data, std::size_t count) {
|
||||
[[nodiscard]] ErrorCode uwrite(ptr<T> pointer, const T *data,
|
||||
std::size_t count) {
|
||||
return uwriteRaw(pointer, &data, sizeof(T) * count);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue