mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-11 03:00:16 +01:00
[rpcsx-os] Initial sys_rename, sys_mkdir, sys_rmdir implementation
vfs: implement overlapped mounts
This commit is contained in:
parent
3232e57445
commit
60e11486f4
|
|
@ -41,7 +41,8 @@ struct ProcessOps {
|
|||
SysResult (*shm_open)(Thread *thread, const char *path, sint flags, sint mode,
|
||||
Ref<File> *file);
|
||||
SysResult (*mkdir)(Thread *thread, ptr<const char> path, sint mode);
|
||||
SysResult (*rmdir)(Thread *thread, ptr<const char> path) = nullptr;
|
||||
SysResult (*rmdir)(Thread *thread, ptr<const char> path);
|
||||
SysResult (*rename)(Thread *thread, ptr<const char> from, ptr<const char> to);
|
||||
SysResult (*blockpool_open)(Thread *thread, Ref<File> *file);
|
||||
SysResult (*blockpool_map)(Thread *thread, caddr_t addr, size_t len,
|
||||
sint prot, sint flags);
|
||||
|
|
|
|||
|
|
@ -285,6 +285,9 @@ orbis::SysResult orbis::sys_freebsd6_truncate(Thread *thread, ptr<char> path,
|
|||
orbis::SysResult orbis::sys_fsync(Thread *thread, sint fd) { return {}; }
|
||||
orbis::SysResult orbis::sys_rename(Thread *thread, ptr<char> from,
|
||||
ptr<char> to) {
|
||||
if (auto rename = thread->tproc->ops->rename) {
|
||||
return rename(thread, from, to);
|
||||
}
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
orbis::SysResult orbis::sys_renameat(Thread *thread, sint oldfd, ptr<char> old,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <cerrno>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <sys/mman.h>
|
||||
|
|
@ -45,8 +46,98 @@ struct HostFsDevice : IoDevice {
|
|||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
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;
|
||||
orbis::ErrorCode rename(const char *from, const char *to, orbis::Thread *thread) override;
|
||||
};
|
||||
|
||||
static orbis::ErrorCode convertErrc(std::errc errc) {
|
||||
if (errc == std::errc{}) {
|
||||
return{};
|
||||
}
|
||||
|
||||
switch (errc) {
|
||||
case std::errc::address_family_not_supported: return orbis::ErrorCode::AFNOSUPPORT;
|
||||
case std::errc::address_in_use: return orbis::ErrorCode::ADDRINUSE;
|
||||
case std::errc::address_not_available: return orbis::ErrorCode::ADDRNOTAVAIL;
|
||||
case std::errc::already_connected: return orbis::ErrorCode::ISCONN;
|
||||
case std::errc::argument_out_of_domain: return orbis::ErrorCode::DOM;
|
||||
case std::errc::bad_address: return orbis::ErrorCode::FAULT;
|
||||
case std::errc::bad_file_descriptor: return orbis::ErrorCode::BADF;
|
||||
case std::errc::bad_message: return orbis::ErrorCode::BADMSG;
|
||||
case std::errc::broken_pipe: return orbis::ErrorCode::PIPE;
|
||||
case std::errc::connection_aborted: return orbis::ErrorCode::CONNABORTED;
|
||||
case std::errc::connection_already_in_progress: return orbis::ErrorCode::ALREADY;
|
||||
case std::errc::connection_refused: return orbis::ErrorCode::CONNREFUSED;
|
||||
case std::errc::connection_reset: return orbis::ErrorCode::CONNRESET;
|
||||
case std::errc::cross_device_link: return orbis::ErrorCode::XDEV;
|
||||
case std::errc::destination_address_required: return orbis::ErrorCode::DESTADDRREQ;
|
||||
case std::errc::device_or_resource_busy: return orbis::ErrorCode::BUSY;
|
||||
case std::errc::directory_not_empty: return orbis::ErrorCode::NOTEMPTY;
|
||||
case std::errc::executable_format_error: return orbis::ErrorCode::NOEXEC;
|
||||
case std::errc::file_exists: return orbis::ErrorCode::EXIST;
|
||||
case std::errc::file_too_large: return orbis::ErrorCode::FBIG;
|
||||
case std::errc::filename_too_long: return orbis::ErrorCode::NAMETOOLONG;
|
||||
case std::errc::function_not_supported: return orbis::ErrorCode::NOSYS;
|
||||
case std::errc::host_unreachable: return orbis::ErrorCode::HOSTUNREACH;
|
||||
case std::errc::identifier_removed: return orbis::ErrorCode::IDRM;
|
||||
case std::errc::illegal_byte_sequence: return orbis::ErrorCode::ILSEQ;
|
||||
case std::errc::inappropriate_io_control_operation: return orbis::ErrorCode::NOTTY;
|
||||
case std::errc::interrupted: return orbis::ErrorCode::INTR;
|
||||
case std::errc::invalid_argument: return orbis::ErrorCode::INVAL;
|
||||
case std::errc::invalid_seek: return orbis::ErrorCode::SPIPE;
|
||||
case std::errc::io_error: return orbis::ErrorCode::IO;
|
||||
case std::errc::is_a_directory: return orbis::ErrorCode::ISDIR;
|
||||
case std::errc::message_size: return orbis::ErrorCode::MSGSIZE;
|
||||
case std::errc::network_down: return orbis::ErrorCode::NETDOWN;
|
||||
case std::errc::network_reset: return orbis::ErrorCode::NETRESET;
|
||||
case std::errc::network_unreachable: return orbis::ErrorCode::NETUNREACH;
|
||||
case std::errc::no_buffer_space: return orbis::ErrorCode::NOBUFS;
|
||||
case std::errc::no_child_process: return orbis::ErrorCode::CHILD;
|
||||
case std::errc::no_link: return orbis::ErrorCode::NOLINK;
|
||||
case std::errc::no_lock_available: return orbis::ErrorCode::NOLCK;
|
||||
case std::errc::no_message: return orbis::ErrorCode::NOMSG;
|
||||
case std::errc::no_protocol_option: return orbis::ErrorCode::NOPROTOOPT;
|
||||
case std::errc::no_space_on_device: return orbis::ErrorCode::NOSPC;
|
||||
case std::errc::no_such_device_or_address: return orbis::ErrorCode::NXIO;
|
||||
case std::errc::no_such_device: return orbis::ErrorCode::NODEV;
|
||||
case std::errc::no_such_file_or_directory: return orbis::ErrorCode::NOENT;
|
||||
case std::errc::no_such_process: return orbis::ErrorCode::SRCH;
|
||||
case std::errc::not_a_directory: return orbis::ErrorCode::NOTDIR;
|
||||
case std::errc::not_a_socket: return orbis::ErrorCode::NOTSOCK;
|
||||
case std::errc::not_connected: return orbis::ErrorCode::NOTCONN;
|
||||
case std::errc::not_enough_memory: return orbis::ErrorCode::NOMEM;
|
||||
case std::errc::not_supported: return orbis::ErrorCode::NOTSUP;
|
||||
case std::errc::operation_canceled: return orbis::ErrorCode::CANCELED;
|
||||
case std::errc::operation_in_progress: return orbis::ErrorCode::INPROGRESS;
|
||||
case std::errc::operation_not_permitted: return orbis::ErrorCode::PERM;
|
||||
case std::errc::operation_would_block: return orbis::ErrorCode::WOULDBLOCK;
|
||||
case std::errc::permission_denied: return orbis::ErrorCode::ACCES;
|
||||
case std::errc::protocol_error: return orbis::ErrorCode::PROTO;
|
||||
case std::errc::protocol_not_supported: return orbis::ErrorCode::PROTONOSUPPORT;
|
||||
case std::errc::read_only_file_system: return orbis::ErrorCode::ROFS;
|
||||
case std::errc::resource_deadlock_would_occur: return orbis::ErrorCode::DEADLK;
|
||||
case std::errc::result_out_of_range: return orbis::ErrorCode::RANGE;
|
||||
case std::errc::text_file_busy: return orbis::ErrorCode::TXTBSY;
|
||||
case std::errc::timed_out: return orbis::ErrorCode::TIMEDOUT;
|
||||
case std::errc::too_many_files_open_in_system: return orbis::ErrorCode::NFILE;
|
||||
case std::errc::too_many_files_open: return orbis::ErrorCode::MFILE;
|
||||
case std::errc::too_many_links: return orbis::ErrorCode::MLINK;
|
||||
case std::errc::too_many_symbolic_link_levels: return orbis::ErrorCode::LOOP;
|
||||
case std::errc::value_too_large: return orbis::ErrorCode::OVERFLOW;
|
||||
case std::errc::wrong_protocol_type: return orbis::ErrorCode::PROTOTYPE;
|
||||
default:
|
||||
return orbis::ErrorCode::FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static orbis::ErrorCode convertErrorCode(const std::error_code &code) {
|
||||
if (!code) {
|
||||
return{};
|
||||
}
|
||||
return convertErrc(static_cast<std::errc>(code.value()));
|
||||
}
|
||||
|
||||
static orbis::ErrorCode convertErrno() {
|
||||
switch (auto error = errno) {
|
||||
case EPERM:
|
||||
|
|
@ -254,6 +345,10 @@ static const orbis::FileOps socketOps = {
|
|||
};
|
||||
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath) {
|
||||
while (hostPath.size() > 1 && hostPath.ends_with("/")) {
|
||||
hostPath.resize(hostPath.size() - 1);
|
||||
}
|
||||
|
||||
return orbis::knew<HostFsDevice>(std::move(hostPath));
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +424,7 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
|||
|
||||
if (hostFd < 0) {
|
||||
auto error = convertErrno();
|
||||
ORBIS_LOG_ERROR("host_open failed", realPath, error);
|
||||
ORBIS_LOG_ERROR("host_open failed", path, realPath, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
@ -366,6 +461,22 @@ orbis::ErrorCode HostFsDevice::open(orbis::Ref<orbis::File> *file,
|
|||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode HostFsDevice::mkdir(const char *path, int mode, orbis::Thread *thread) {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(hostPath + "/" + path, ec);
|
||||
return convertErrorCode(ec);
|
||||
}
|
||||
orbis::ErrorCode HostFsDevice::rmdir(const char *path, orbis::Thread *thread) {
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(hostPath + "/" + path, ec);
|
||||
return convertErrorCode(ec);
|
||||
}
|
||||
orbis::ErrorCode HostFsDevice::rename(const char *from, const char *to, orbis::Thread *thread) {
|
||||
std::error_code ec;
|
||||
std::filesystem::rename(hostPath + "/" + from, hostPath + "/" + to, ec);
|
||||
return convertErrorCode(ec);
|
||||
}
|
||||
|
||||
orbis::File *createHostFile(int hostFd, orbis::Ref<IoDevice> device) {
|
||||
auto newFile = orbis::knew<HostFile>();
|
||||
newFile->hostFd = hostFd;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,15 @@ struct IoDevice : orbis::RcBase {
|
|||
virtual orbis::ErrorCode unlink(const char *path, 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) {
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
}
|
||||
};
|
||||
|
||||
IoDevice *createHostIoDevice(orbis::kstring hostPath);
|
||||
|
|
|
|||
|
|
@ -322,30 +322,30 @@ static int ps4Exec(orbis::Thread *mainThread,
|
|||
auto dmem1 = createDmemCharacterDevice(1);
|
||||
orbis::g_context.dmemDevice = dmem1;
|
||||
|
||||
rx::vfs::mount("/dev/dmem0", createDmemCharacterDevice(0));
|
||||
rx::vfs::mount("/dev/npdrm", createNpdrmCharacterDevice());
|
||||
rx::vfs::mount("/dev/icc_configuration", createIccConfigurationCharacterDevice());
|
||||
rx::vfs::mount("/dev/console", createConsoleCharacterDevice());
|
||||
rx::vfs::mount("/dev/camera", createCameraCharacterDevice());
|
||||
rx::vfs::mount("/dev/dmem1", dmem1);
|
||||
rx::vfs::mount("/dev/dmem2", createDmemCharacterDevice(2));
|
||||
rx::vfs::mount("/dev/stdout", createFdWrapDevice(STDOUT_FILENO));
|
||||
rx::vfs::mount("/dev/stderr", createFdWrapDevice(STDERR_FILENO));
|
||||
rx::vfs::mount("/dev/stdin", createFdWrapDevice(STDIN_FILENO));
|
||||
rx::vfs::mount("/dev/zero", createZeroCharacterDevice());
|
||||
rx::vfs::mount("/dev/null", createNullCharacterDevice());
|
||||
rx::vfs::mount("/dev/dipsw", createDipswCharacterDevice());
|
||||
rx::vfs::mount("/dev/dce", createDceCharacterDevice());
|
||||
rx::vfs::mount("/dev/hmd_cmd", createHmdCmdCharacterDevice());
|
||||
rx::vfs::mount("/dev/hmd_snsr", createHmdSnsrCharacterDevice());
|
||||
rx::vfs::mount("/dev/hmd_3da", createHmd3daCharacterDevice());
|
||||
rx::vfs::mount("/dev/hmd_dist", createHmdMmapCharacterDevice());
|
||||
rx::vfs::mount("/dev/hid", createHidCharacterDevice());
|
||||
rx::vfs::mount("/dev/gc", createGcCharacterDevice());
|
||||
rx::vfs::mount("/dev/rng", createRngCharacterDevice());
|
||||
rx::vfs::mount("/dev/sbl_srv", createSblSrvCharacterDevice());
|
||||
rx::vfs::mount("/dev/ajm", createAjmCharacterDevice());
|
||||
rx::vfs::mount("/dev/urandom", createUrandomCharacterDevice());
|
||||
rx::vfs::addDevice("dmem0", createDmemCharacterDevice(0));
|
||||
rx::vfs::addDevice("npdrm", createNpdrmCharacterDevice());
|
||||
rx::vfs::addDevice("icc_configuration", createIccConfigurationCharacterDevice());
|
||||
rx::vfs::addDevice("console", createConsoleCharacterDevice());
|
||||
rx::vfs::addDevice("camera", createCameraCharacterDevice());
|
||||
rx::vfs::addDevice("dmem1", dmem1);
|
||||
rx::vfs::addDevice("dmem2", createDmemCharacterDevice(2));
|
||||
rx::vfs::addDevice("stdout", createFdWrapDevice(STDOUT_FILENO));
|
||||
rx::vfs::addDevice("stderr", createFdWrapDevice(STDERR_FILENO));
|
||||
rx::vfs::addDevice("stdin", createFdWrapDevice(STDIN_FILENO));
|
||||
rx::vfs::addDevice("zero", createZeroCharacterDevice());
|
||||
rx::vfs::addDevice("null", createNullCharacterDevice());
|
||||
rx::vfs::addDevice("dipsw", createDipswCharacterDevice());
|
||||
rx::vfs::addDevice("dce", createDceCharacterDevice());
|
||||
rx::vfs::addDevice("hmd_cmd", createHmdCmdCharacterDevice());
|
||||
rx::vfs::addDevice("hmd_snsr", createHmdSnsrCharacterDevice());
|
||||
rx::vfs::addDevice("hmd_3da", createHmd3daCharacterDevice());
|
||||
rx::vfs::addDevice("hmd_dist", createHmdMmapCharacterDevice());
|
||||
rx::vfs::addDevice("hid", createHidCharacterDevice());
|
||||
rx::vfs::addDevice("gc", createGcCharacterDevice());
|
||||
rx::vfs::addDevice("rng", createRngCharacterDevice());
|
||||
rx::vfs::addDevice("sbl_srv", createSblSrvCharacterDevice());
|
||||
rx::vfs::addDevice("ajm", createAjmCharacterDevice());
|
||||
rx::vfs::addDevice("urandom", createUrandomCharacterDevice());
|
||||
|
||||
orbis::Ref<orbis::File> stdinFile;
|
||||
orbis::Ref<orbis::File> stdoutFile;
|
||||
|
|
|
|||
|
|
@ -274,6 +274,19 @@ orbis::SysResult shm_open(orbis::Thread *thread, const char *path,
|
|||
return dev->open(file, path, flags, mode, thread);
|
||||
}
|
||||
|
||||
orbis::SysResult mkdir(Thread *thread, ptr<const char> path, sint mode) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, path, mode);
|
||||
return rx::vfs::mkdir(path, mode, thread);
|
||||
}
|
||||
orbis::SysResult rmdir(Thread *thread, ptr<const char> path) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, path);
|
||||
return rx::vfs::rmdir(path, thread);
|
||||
}
|
||||
orbis::SysResult rename(Thread *thread, ptr<const char> from, ptr<const char> to) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, from, to);
|
||||
return rx::vfs::rename(from, to, thread);
|
||||
}
|
||||
|
||||
orbis::SysResult blockpool_open(orbis::Thread *thread,
|
||||
orbis::Ref<orbis::File> *file) {
|
||||
auto dev = static_cast<IoDevice *>(orbis::g_context.blockpoolDevice.get());
|
||||
|
|
@ -633,6 +646,9 @@ ProcessOps rx::procOpsTable = {
|
|||
.query_memory_protection = query_memory_protection,
|
||||
.open = open,
|
||||
.shm_open = shm_open,
|
||||
.mkdir = mkdir,
|
||||
.rmdir = rmdir,
|
||||
.rename = rename,
|
||||
.blockpool_open = blockpool_open,
|
||||
.blockpool_map = blockpool_map,
|
||||
.blockpool_unmap = blockpool_unmap,
|
||||
|
|
|
|||
147
rpcsx-os/vfs.cpp
147
rpcsx-os/vfs.cpp
|
|
@ -6,17 +6,80 @@
|
|||
#include "orbis/error/SysResult.hpp"
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
static std::map<std::string, orbis::Ref<IoDevice>> sMountsMap;
|
||||
static std::map<std::string, orbis::Ref<IoDevice>, std::greater<>> sMountsMap;
|
||||
|
||||
void rx::vfs::initialize() {}
|
||||
void rx::vfs::deinitialize() { sMountsMap.clear(); }
|
||||
struct DevFs : IoDevice {
|
||||
std::map<std::string, orbis::Ref<IoDevice>> devices;
|
||||
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
if (auto it = devices.find(path); it != devices.end()) {
|
||||
return it->second->open(file, path, flags, mode, thread);
|
||||
}
|
||||
|
||||
std::fprintf(stderr, "device %s not exists\n", path);
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
};
|
||||
static orbis::Ref<DevFs> sDevFs;
|
||||
|
||||
struct ProcFs : IoDevice {
|
||||
orbis::ErrorCode open(orbis::Ref<orbis::File> *file, const char *path,
|
||||
std::uint32_t flags, std::uint32_t mode,
|
||||
orbis::Thread *thread) override {
|
||||
std::fprintf(stderr, "procfs access: %s\n", path);
|
||||
std::abort();
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
};
|
||||
|
||||
void rx::vfs::initialize() {
|
||||
sDevFs = orbis::knew<DevFs>();
|
||||
sMountsMap.emplace("/dev/", sDevFs);
|
||||
sMountsMap.emplace("/proc/", orbis::knew<ProcFs>());
|
||||
}
|
||||
|
||||
void rx::vfs::deinitialize() {
|
||||
sDevFs = nullptr;
|
||||
sMountsMap.clear();
|
||||
}
|
||||
|
||||
void rx::vfs::addDevice(std::string name, IoDevice *device) {
|
||||
sDevFs->devices[std::move(name)] = device;
|
||||
}
|
||||
|
||||
static std::pair<orbis::Ref<IoDevice>, std::string>
|
||||
get(const std::filesystem::path &guestPath) {
|
||||
std::string normalPath = std::filesystem::path(guestPath).lexically_normal();
|
||||
std::string_view path = normalPath;
|
||||
orbis::Ref<IoDevice> device;
|
||||
std::string_view prefix;
|
||||
|
||||
for (auto &mount : sMountsMap) {
|
||||
if (!path.starts_with(mount.first)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
device = mount.second;
|
||||
path.remove_prefix(mount.first.length());
|
||||
return {mount.second, std::string(path)};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::SysResult rx::vfs::mount(const std::filesystem::path &guestPath,
|
||||
IoDevice *dev) {
|
||||
auto [it, inserted] =
|
||||
sMountsMap.emplace(guestPath.lexically_normal().string(), dev);
|
||||
auto mp = guestPath.lexically_normal().string();
|
||||
if (!mp.ends_with("/")) {
|
||||
mp += "/";
|
||||
}
|
||||
|
||||
auto [it, inserted] = sMountsMap.emplace(std::move(mp), dev);
|
||||
|
||||
if (!inserted) {
|
||||
return orbis::ErrorCode::EXIST;
|
||||
|
|
@ -28,37 +91,47 @@ orbis::SysResult rx::vfs::mount(const std::filesystem::path &guestPath,
|
|||
orbis::SysResult rx::vfs::open(std::string_view path, int flags, int mode,
|
||||
orbis::Ref<orbis::File> *file,
|
||||
orbis::Thread *thread) {
|
||||
orbis::Ref<IoDevice> device;
|
||||
bool isCharacterDevice = path.starts_with("/dev/");
|
||||
|
||||
for (auto &mount : sMountsMap) {
|
||||
if (!path.starts_with(mount.first)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
path.remove_prefix(mount.first.length());
|
||||
device = mount.second;
|
||||
break;
|
||||
auto [device, devPath] = get(path);
|
||||
if (device == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
|
||||
if (isCharacterDevice && device != nullptr) {
|
||||
if (!path.empty()) {
|
||||
std::fprintf(stderr,
|
||||
"vfs::open: access to character device subentry '%s' (%s)\n",
|
||||
path.data(), std::string(path).c_str());
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
}
|
||||
|
||||
if (device != nullptr) {
|
||||
return (orbis::ErrorCode)device->open(file, std::string(path).c_str(),
|
||||
flags, mode, thread);
|
||||
}
|
||||
|
||||
if (isCharacterDevice) {
|
||||
std::fprintf(stderr, "vfs::open: character device '%s' not found.\n",
|
||||
std::string(path).c_str());
|
||||
}
|
||||
|
||||
return orbis::ErrorCode::NOENT;
|
||||
return device->open(file, devPath.c_str(), flags, mode, thread);
|
||||
}
|
||||
|
||||
orbis::SysResult rx::vfs::mkdir(std::string_view path, int mode,
|
||||
orbis::Thread *thread) {
|
||||
auto [device, devPath] = get(path);
|
||||
if (device == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
return device->mkdir(devPath.c_str(), mode, thread);
|
||||
}
|
||||
|
||||
orbis::SysResult rx::vfs::rmdir(std::string_view path, orbis::Thread *thread) {
|
||||
auto [device, devPath] = get(path);
|
||||
if (device == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
return device->rmdir(devPath.c_str(), thread);
|
||||
}
|
||||
|
||||
orbis::SysResult rx::vfs::rename(std::string_view from, std::string_view to,
|
||||
orbis::Thread *thread) {
|
||||
auto [fromDevice, fromDevPath] = get(from);
|
||||
if (fromDevice == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
|
||||
auto [toDevice, toDevPath] = get(to);
|
||||
if (toDevice == nullptr) {
|
||||
return orbis::ErrorCode::NOENT;
|
||||
}
|
||||
|
||||
if (fromDevice != toDevice) {
|
||||
std::fprintf(stderr, "cross fs rename operation: %s -> %s\n",
|
||||
std::string(from).c_str(), std::string(to).c_str());
|
||||
std::abort();
|
||||
}
|
||||
|
||||
return fromDevice->rename(fromDevPath.c_str(), toDevPath.c_str(), thread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,11 @@ struct IoDevice;
|
|||
namespace rx::vfs {
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
void addDevice(std::string name, IoDevice *device);
|
||||
orbis::SysResult mount(const std::filesystem::path &guestPath, IoDevice *dev);
|
||||
orbis::SysResult open(std::string_view path, int flags, int mode,
|
||||
orbis::Ref<orbis::File> *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);
|
||||
} // namespace rx::vfs
|
||||
|
|
|
|||
Loading…
Reference in a new issue