From afc865cc6925f28e427312dda2a08f3aced3e85a Mon Sep 17 00:00:00 2001 From: DH Date: Sat, 11 Nov 2023 17:52:27 +0300 Subject: [PATCH] [orbis-kernel] implement unlink, nmount/unmount nullfs --- .../include/orbis/thread/ProcessOps.hpp | 5 ++ orbis-kernel/src/sys/sys_vfs.cpp | 3 + orbis-kernel/src/sys/sys_vfs_mount.cpp | 24 ++++---- rpcsx-os/io-device.cpp | 30 +++++++++- rpcsx-os/io-device.hpp | 13 ++++- rpcsx-os/ops.cpp | 55 ++++++++++++++++++- rpcsx-os/vfs.cpp | 45 ++++++++++++++- rpcsx-os/vfs.hpp | 8 ++- 8 files changed, 161 insertions(+), 22 deletions(-) diff --git a/orbis-kernel/include/orbis/thread/ProcessOps.hpp b/orbis-kernel/include/orbis/thread/ProcessOps.hpp index 7cb62fcba..dba815821 100644 --- a/orbis-kernel/include/orbis/thread/ProcessOps.hpp +++ b/orbis-kernel/include/orbis/thread/ProcessOps.hpp @@ -11,6 +11,7 @@ struct Module; struct timespec; struct File; struct MemoryProtection; +struct IoVec; struct ProcessOps { SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot, @@ -40,6 +41,7 @@ struct ProcessOps { Ref *file); SysResult (*shm_open)(Thread *thread, const char *path, sint flags, sint mode, Ref *file); + SysResult (*unlink)(Thread *thread, ptr path); SysResult (*mkdir)(Thread *thread, ptr path, sint mode); SysResult (*rmdir)(Thread *thread, ptr path); SysResult (*rename)(Thread *thread, ptr from, ptr to); @@ -70,6 +72,9 @@ struct ProcessOps { SysResult (*thr_wake)(Thread *thread, slong id); SysResult (*thr_set_name)(Thread *thread, slong id, ptr name); + SysResult (*unmount)(Thread *thread, ptr path, sint flags); + SysResult (*nmount)(Thread *thread, ptr iovp, uint iovcnt, sint flags); + SysResult (*fork)(Thread *thread, slong status); SysResult (*execve)(Thread *thread, ptr fname, ptr> argv, ptr> envv); diff --git a/orbis-kernel/src/sys/sys_vfs.cpp b/orbis-kernel/src/sys/sys_vfs.cpp index 3b42bbac4..f1c54ec06 100644 --- a/orbis-kernel/src/sys/sys_vfs.cpp +++ b/orbis-kernel/src/sys/sys_vfs.cpp @@ -84,6 +84,9 @@ orbis::SysResult orbis::sys_undelete(Thread *thread, ptr path) { return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_unlink(Thread *thread, ptr path) { + if (auto unlink = thread->tproc->ops->unlink) { + return unlink(thread, path); + } return ErrorCode::NOSYS; } orbis::SysResult orbis::sys_unlinkat(Thread *thread, sint fd, ptr path, diff --git a/orbis-kernel/src/sys/sys_vfs_mount.cpp b/orbis-kernel/src/sys/sys_vfs_mount.cpp index 0d94f3511..6797f34b6 100644 --- a/orbis-kernel/src/sys/sys_vfs_mount.cpp +++ b/orbis-kernel/src/sys/sys_vfs_mount.cpp @@ -1,28 +1,24 @@ #include "sys/sysproto.hpp" -#include "uio.hpp" -#include "utils/Logs.hpp" orbis::SysResult orbis::sys_mount(Thread *thread, ptr type, ptr path, sint flags, caddr_t data) { return ErrorCode::NOSYS; } + orbis::SysResult orbis::sys_unmount(Thread *thread, ptr path, sint flags) { + if (auto unmount = thread->tproc->ops->unmount) { + return unmount(thread, path, flags); + } + return ErrorCode::NOSYS; } + orbis::SysResult orbis::sys_nmount(Thread *thread, ptr iovp, uint iovcnt, sint flags) { - ORBIS_LOG_ERROR(__FUNCTION__, iovp, iovcnt, flags); - - for (auto it = iovp; it < iovp + iovcnt; it += 2) { - IoVec a{}, b{}; - uread(a, it); - uread(b, it + 1); - - std::string aSv((char *)a.base, a.len); - std::string bSv((char *)b.base, b.len); - - std::fprintf(stderr, "%s: '%s':'%s'\n", __FUNCTION__, aSv.c_str(), bSv.c_str()); + if (auto nmount = thread->tproc->ops->nmount) { + return nmount(thread, iovp, iovcnt, flags); } - return {}; + + return ErrorCode::NOSYS; } diff --git a/rpcsx-os/io-device.cpp b/rpcsx-os/io-device.cpp index 5ba10f0b3..2ab2421dc 100644 --- a/rpcsx-os/io-device.cpp +++ b/rpcsx-os/io-device.cpp @@ -47,6 +47,10 @@ struct HostFsDevice : IoDevice { orbis::ErrorCode open(orbis::Ref *file, const char *path, std::uint32_t flags, std::uint32_t mode, orbis::Thread *thread) override; + orbis::ErrorCode unlink(const char *path, bool recursive, + orbis::Thread *thread) override; + orbis::ErrorCode createSymlink(const char *target, const char *linkPath, + orbis::Thread *thread) override; orbis::ErrorCode mkdir(const char *path, int mode, orbis::Thread *thread) override; orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) override; @@ -291,7 +295,8 @@ static orbis::ErrorCode host_write(orbis::File *file, orbis::Uio *uio, vec.push_back({.iov_base = entry.base, .iov_len = entry.len}); } - ssize_t cnt = ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset); + ssize_t cnt = + ::pwritev(hostFile->hostFd, vec.data(), vec.size(), uio->offset); if (cnt < 0) { for (auto io : vec) { @@ -538,6 +543,29 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref *file, return {}; } +orbis::ErrorCode HostFsDevice::unlink(const char *path, bool recursive, + orbis::Thread *thread) { + std::error_code ec; + + if (recursive) { + std::filesystem::remove_all(hostPath + "/" + path, ec); + } else { + std::filesystem::remove(hostPath + "/" + path, ec); + } + + return convertErrorCode(ec); +} + +orbis::ErrorCode HostFsDevice::createSymlink(const char *linkPath, + const char *target, + orbis::Thread *thread) { + std::error_code ec; + std::filesystem::create_symlink( + std::filesystem::absolute(hostPath + "/" + linkPath), + hostPath + "/" + target, ec); + return convertErrorCode(ec); +} + orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode, orbis::Thread *thread) { std::error_code ec; diff --git a/rpcsx-os/io-device.hpp b/rpcsx-os/io-device.hpp index 4f877c21a..f0f948575 100644 --- a/rpcsx-os/io-device.hpp +++ b/rpcsx-os/io-device.hpp @@ -27,16 +27,23 @@ struct IoDevice : orbis::RcBase { virtual orbis::ErrorCode open(orbis::Ref *file, const char *path, std::uint32_t flags, std::uint32_t mode, orbis::Thread *thread) = 0; - virtual orbis::ErrorCode unlink(const char *path, orbis::Thread *thread) { + virtual orbis::ErrorCode unlink(const char *path, bool recursive, + orbis::Thread *thread) { return orbis::ErrorCode::NOTSUP; } - virtual orbis::ErrorCode mkdir(const char *path, int mode, orbis::Thread *thread) { + virtual orbis::ErrorCode createSymlink(const char *target, const char *linkPath, + orbis::Thread *thread) { + return orbis::ErrorCode::NOTSUP; + } + virtual orbis::ErrorCode mkdir(const char *path, int mode, + orbis::Thread *thread) { return orbis::ErrorCode::NOTSUP; } virtual orbis::ErrorCode rmdir(const char *path, orbis::Thread *thread) { return orbis::ErrorCode::NOTSUP; } - virtual orbis::ErrorCode rename(const char *from, const char *to, orbis::Thread *thread) { + virtual orbis::ErrorCode rename(const char *from, const char *to, + orbis::Thread *thread) { return orbis::ErrorCode::NOTSUP; } }; diff --git a/rpcsx-os/ops.cpp b/rpcsx-os/ops.cpp index 4334cfd21..ff6a2657b 100644 --- a/rpcsx-os/ops.cpp +++ b/rpcsx-os/ops.cpp @@ -12,6 +12,7 @@ #include "orbis/module/ModuleHandle.hpp" #include "orbis/thread/Process.hpp" #include "orbis/thread/Thread.hpp" +#include "orbis/uio.hpp" #include "orbis/umtx.hpp" #include "orbis/utils/Logs.hpp" #include "orbis/utils/Rc.hpp" @@ -30,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -287,7 +289,9 @@ orbis::SysResult shm_open(orbis::Thread *thread, const char *path, auto dev = static_cast(orbis::g_context.shmDevice.get()); return dev->open(file, path, flags, mode, thread); } - +orbis::SysResult unlink(orbis::Thread *thread, orbis::ptr path) { + return rx::vfs::unlink(path, thread); +} orbis::SysResult mkdir(Thread *thread, ptr path, sint mode) { ORBIS_LOG_TODO(__FUNCTION__, path, mode); return rx::vfs::mkdir(path, mode, thread); @@ -337,7 +341,7 @@ orbis::SysResult socket(orbis::Thread *thread, orbis::ptr name, orbis::SysResult shm_unlink(orbis::Thread *thread, const char *path) { auto dev = static_cast(orbis::g_context.shmDevice.get()); - return dev->unlink(path, thread); + return dev->unlink(path, false, thread); } orbis::SysResult dynlib_get_obj_member(orbis::Thread *thread, @@ -572,6 +576,50 @@ SysResult thr_set_name(orbis::Thread *thread, orbis::slong id, ORBIS_LOG_WARNING(__FUNCTION__, name, id, thread->tid); return {}; } + +orbis::SysResult unmount(orbis::Thread *thread, orbis::ptr path, + orbis::sint flags) { + // TODO: support other that nullfs + return rx::vfs::unlink(path, thread); +} +orbis::SysResult nmount(orbis::Thread *thread, orbis::ptr iovp, + orbis::uint iovcnt, orbis::sint flags) { + ORBIS_LOG_ERROR(__FUNCTION__, iovp, iovcnt, flags); + + std::string_view fstype; + std::string_view fspath; + std::string_view target; + + for (auto it = iovp; it < iovp + iovcnt; it += 2) { + IoVec a; + IoVec b; + ORBIS_RET_ON_ERROR(uread(a, it)); + ORBIS_RET_ON_ERROR(uread(b, it + 1)); + + std::string_view key((char *)a.base, a.len - 1); + std::string_view value((char *)b.base, b.len - 1); + + if (key == "fstype") { + fstype = value; + } else if (key == "fspath") { + fspath = value; + } else if (key == "target") { + target = value; + } + + std::fprintf(stderr, "%s: '%s':'%s'\n", __FUNCTION__, key.data(), + value.data()); + } + + if (fstype == "nullfs") { + ORBIS_RET_ON_ERROR(rx::vfs::unlink(fspath, thread)); + return rx::vfs::createSymlink(target, fspath, thread); + } + + // TODO + return {}; +} + orbis::SysResult exit(orbis::Thread *thread, orbis::sint status) { std::printf("Requested exit with status %d\n", status); std::exit(status); @@ -794,6 +842,7 @@ ProcessOps rx::procOpsTable = { .query_memory_protection = query_memory_protection, .open = open, .shm_open = shm_open, + .unlink = unlink, .mkdir = mkdir, .rmdir = rmdir, .rename = rename, @@ -815,6 +864,8 @@ ProcessOps rx::procOpsTable = { .thr_suspend = thr_suspend, .thr_wake = thr_wake, .thr_set_name = thr_set_name, + .unmount = unmount, + .nmount = nmount, .fork = fork, .execve = execve, .exit = exit, diff --git a/rpcsx-os/vfs.cpp b/rpcsx-os/vfs.cpp index c84ac3395..dc5baeecc 100644 --- a/rpcsx-os/vfs.cpp +++ b/rpcsx-os/vfs.cpp @@ -21,7 +21,8 @@ struct DevFs : IoDevice { devPath.remove_prefix(pos + 1); if (auto it = devices.find(deviceName); it != devices.end()) { - return it->second->open(file, std::string(devPath).c_str(), flags, mode, thread); + return it->second->open(file, std::string(devPath).c_str(), flags, mode, + thread); } } else { if (auto it = devices.find(devPath); it != devices.end()) { @@ -170,3 +171,45 @@ orbis::SysResult rx::vfs::rename(std::string_view from, std::string_view to, return fromDevice->rename(fromDevPath.c_str(), toDevPath.c_str(), thread); } + +orbis::ErrorCode rx::vfs::unlink(std::string_view path, orbis::Thread *thread) { + auto [device, devPath] = get(path); + if (device == nullptr) { + return orbis::ErrorCode::NOENT; + } + + return device->unlink(devPath.c_str(), false, thread); +} + +orbis::ErrorCode rx::vfs::unlinkAll(std::string_view path, + orbis::Thread *thread) { + auto [device, devPath] = get(path); + if (device == nullptr) { + return orbis::ErrorCode::NOENT; + } + + return device->unlink(devPath.c_str(), true, thread); +} + +orbis::ErrorCode rx::vfs::createSymlink(std::string_view target, + std::string_view linkPath, + orbis::Thread *thread) { + auto [fromDevice, fromDevPath] = get(target); + if (fromDevice == nullptr) { + return orbis::ErrorCode::NOENT; + } + + auto [targetDevice, toDevPath] = get(linkPath); + if (targetDevice == nullptr) { + return orbis::ErrorCode::NOENT; + } + + if (fromDevice != targetDevice) { + std::fprintf(stderr, "cross fs operation: %s -> %s\n", + std::string(target).c_str(), std::string(linkPath).c_str()); + std::abort(); + } + + return fromDevice->createSymlink(fromDevPath.c_str(), toDevPath.c_str(), + thread); +} diff --git a/rpcsx-os/vfs.hpp b/rpcsx-os/vfs.hpp index b342a77d2..873a51137 100644 --- a/rpcsx-os/vfs.hpp +++ b/rpcsx-os/vfs.hpp @@ -17,5 +17,11 @@ orbis::SysResult open(std::string_view path, int flags, int mode, orbis::Ref *file, orbis::Thread *thread); orbis::SysResult mkdir(std::string_view path, int mode, orbis::Thread *thread); orbis::SysResult rmdir(std::string_view path, orbis::Thread *thread); -orbis::SysResult rename(std::string_view from, std::string_view to, orbis::Thread *thread); +orbis::SysResult rename(std::string_view from, std::string_view to, + orbis::Thread *thread); +orbis::ErrorCode unlink(std::string_view path, orbis::Thread *thread); +orbis::ErrorCode unlinkAll(std::string_view path, orbis::Thread *thread); +orbis::ErrorCode createSymlink(std::string_view target, + std::string_view linkPath, + orbis::Thread *thread); } // namespace rx::vfs