Implemented vector rw in virtual and posix

Reverted Partition::Format (stupid idea)
Minor removals
This commit is contained in:
Marek Ledworowski 2025-11-06 21:53:30 +01:00
parent 21748acf46
commit 89b91c6f30
19 changed files with 439 additions and 212 deletions

View File

@ -13,6 +13,11 @@
namespace HostIODriver {
static_assert(std::is_same_v<decltype(OrbisKernelIovec::iov_base), decltype(iovec::iov_base)>,
"IOV base pointer is incompatible with native call");
static_assert(std::is_same_v<decltype(OrbisKernelIovec::iov_len), decltype(iovec::iov_len)>,
"IOV length specifier is incompatible with native call");
/**
* This driver bends time and space a bit, because it conforms to POSIX-like returns,
* i.e. -1 for error, 0 for success
@ -95,17 +100,21 @@ public:
s32 Truncate(const fs::path& path, u64 size) override;
s32 FTruncate(const s32 fd, u64 size) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 Read(const s32 fd, void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
s64 ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s32 MKDir(const fs::path& path, u16 mode = 0755) override;
s32 RMDir(const fs::path& path) override;
s32 Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) override;
s32 FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) override;
s32 Stat(const fs::path& path, OrbisKernelStat* statbuf) override;
s32 FStat(const s32 fd, OrbisKernelStat* statbuf) override;
s32 Chmod(const fs::path& path, u16 mode) override;
s32 FChmod(const s32 fd, u16 mode) override;

View File

@ -61,17 +61,21 @@ public:
s32 Truncate(const fs::path& path, u64 size) override;
s32 FTruncate(const s32 fd, u64 size) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 Read(const s32 fd, void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
s64 ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s32 MKDir(const fs::path& path, u16 mode = 0755) override;
s32 RMDir(const fs::path& path) override;
s32 Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) override;
s32 FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) override;
s32 Stat(const fs::path& path, OrbisKernelStat* statbuf) override;
s32 FStat(const s32 fd, OrbisKernelStat* statbuf) override;
s32 Chmod(const fs::path& path, u16 mode) override;
s32 FChmod(const s32 fd, u16 mode) override;

View File

@ -91,17 +91,21 @@ public:
s32 Truncate(const fs::path& path, u64 size) override;
s32 FTruncate(const s32 fd, u64 size) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 Read(const s32 fd, void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
s64 ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset) override;
s32 MKDir(const fs::path& path, u16 mode = 0755) override;
s32 RMDir(const fs::path& path) override;
// s32 Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) override;
// s32 FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) override;
// s32 Stat(const fs::path& path, OrbisKernelStat* statbuf) override;
// s32 FStat(const s32 fd, OrbisKernelStat* statbuf) override;
// s32 Chmod(const fs::path& path, u16 mode) override;
// s32 FChmod(const s32 fd, u16 mode) override;

View File

@ -17,37 +17,45 @@ HostIO_Base::~HostIO_Base() = default;
// clang-format off
s32 HostIO_Base::Open(const fs::path& path, int flags, u16 mode) { STUB(); }
s32 HostIO_Base::Creat(const fs::path& path, u16 mode) { STUB() }
s32 HostIO_Base::Close(const s32 fd) { STUB() }
s32 HostIO_Base::Creat(const fs::path& path, u16 mode) { STUB(); }
s32 HostIO_Base::Close(const s32 fd) { STUB(); }
s32 HostIO_Base::Link(const fs::path& src, const fs::path& dst) { STUB() }
s32 HostIO_Base::Unlink(const fs::path& path) { STUB() }
s32 HostIO_Base::LinkSymbolic(const fs::path& src, const fs::path& dst) { STUB() }
s32 HostIO_Base::Link(const fs::path& src, const fs::path& dst) { STUB(); }
s32 HostIO_Base::Unlink(const fs::path& path) { STUB(); }
s32 HostIO_Base::LinkSymbolic(const fs::path& src, const fs::path& dst) { STUB(); }
s32 HostIO_Base::Flush(const s32 fd) { STUB() }
s32 HostIO_Base::FSync(const s32 fd) { STUB() }
s64 HostIO_Base::LSeek(const s32 fd, u64 offset, QuasiFS::SeekOrigin origin) { STUB() }
s64 HostIO_Base::Tell(const s32 fd) { STUB() }
s32 HostIO_Base::Flush(const s32 fd) { STUB(); }
s32 HostIO_Base::FSync(const s32 fd) { STUB(); }
s64 HostIO_Base::LSeek(const s32 fd, u64 offset, QuasiFS::SeekOrigin origin) { STUB(); }
s64 HostIO_Base::Tell(const s32 fd) { STUB(); }
s32 HostIO_Base::Truncate(const fs::path& path, u64 size) { STUB() }
s32 HostIO_Base::FTruncate(const s32 fd, u64 size) { STUB() }
s32 HostIO_Base::Truncate(const fs::path& path, u64 size) { STUB(); }
s32 HostIO_Base::FTruncate(const s32 fd, u64 size) { STUB(); }
s64 HostIO_Base::Write(const s32 fd, const void* buf, u64 count) { STUB() }
s64 HostIO_Base::Read(const s32 fd, void* buf, u64 count) { STUB() }
s64 HostIO_Base::Read(const s32 fd, void* buf, u64 count) { STUB(); }
s64 HostIO_Base::PRead(const s32 fd, void* buf, u64 count, u64 offset) { STUB(); }
s64 HostIO_Base::ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) { STUB(); }
s64 HostIO_Base::PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt,
s64 offset) { STUB(); }
s64 HostIO_Base::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) { STUB() }
s64 HostIO_Base::PRead(const s32 fd, void* buf, u64 count, u64 offset) { STUB() }
s64 HostIO_Base::Write(const s32 fd, const void* buf, u64 count) { STUB(); }
s64 HostIO_Base::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) { STUB(); }
s64 HostIO_Base::WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) { STUB(); }
s64 HostIO_Base::PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt,
s64 offset) { STUB(); }
s32 HostIO_Base::MKDir(const fs::path& path, u16 mode) { STUB() }
s32 HostIO_Base::RMDir(const fs::path& path) { STUB() }
s32 HostIO_Base::MKDir(const fs::path& path, u16 mode) { STUB(); }
s32 HostIO_Base::RMDir(const fs::path& path) { STUB(); }
s32 HostIO_Base::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) { STUB() }
s32 HostIO_Base::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) { STUB() }
s32 HostIO_Base::Stat(const fs::path& path, OrbisKernelStat* statbuf) { STUB(); }
s32 HostIO_Base::FStat(const s32 fd, OrbisKernelStat* statbuf) { STUB(); }
s32 HostIO_Base::Chmod(const fs::path& path, u16 mode) { STUB() }
s32 HostIO_Base::FChmod(const s32 fd, u16 mode) { STUB() }
s32 HostIO_Base::Chmod(const fs::path& path, u16 mode) { STUB(); }
s32 HostIO_Base::FChmod(const s32 fd, u16 mode) { STUB(); }
s64 HostIO_Base::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) { STUB() }
s64 HostIO_Base::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
STUB()
}
// clang-format on
} // namespace HostIODriver

View File

@ -12,10 +12,9 @@
namespace HostIODriver {
namespace fs = std::filesystem;
using namespace QuasiFS;
using namespace Libraries::Kernel;
class HostIO_Base {
protected:
public:
HostIO_Base();
~HostIO_Base();
@ -37,15 +36,22 @@ public:
virtual s32 FTruncate(const s32 fd, u64 size);
virtual s64 LSeek(const s32 fd, u64 offset, QuasiFS::SeekOrigin origin);
virtual s64 Tell(const s32 fd);
virtual s64 Write(const s32 fd, const void* buf, u64 count);
virtual s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset);
virtual s64 Read(const s32 fd, void* buf, u64 count);
virtual s64 PRead(const s32 fd, void* buf, u64 count, u64 offset);
virtual s64 ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt);
virtual s64 PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset);
virtual s64 Write(const s32 fd, const void* buf, u64 count);
virtual s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset);
virtual s64 WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt);
virtual s64 PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset);
virtual s32 MKDir(const fs::path& path, u16 mode = 0755);
virtual s32 RMDir(const fs::path& path);
virtual s32 Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf);
virtual s32 FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf);
virtual s32 Stat(const fs::path& path, OrbisKernelStat* statbuf);
virtual s32 FStat(const s32 fd, OrbisKernelStat* statbuf);
virtual s32 Chmod(const fs::path& path, u16 mode);
virtual s32 FChmod(const s32 fd, u16 mode);

View File

@ -6,6 +6,7 @@
#include <dirent.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/unistd.h>
#include "core/file_sys/hostio/host_io_posix.h"
@ -89,28 +90,80 @@ s32 HostIO_POSIX::FTruncate(const s32 fd, u64 size) {
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::Write(const s32 fd, const void* buf, u64 count) {
errno = 0;
s32 status = write(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::Read(const s32 fd, void* buf, u64 count) {
errno = 0;
s32 status = read(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
errno = 0;
s32 status = pread(fd, buf, count, offset);
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) {
errno = 0;
iovec* iov_native = new iovec[iovcnt];
for (s32 idx = 0; idx < iovcnt; idx++)
iov_native[idx] = {.iov_base = iov[idx].iov_base, .iov_len = iov[idx].iov_len};
s64 ret = readv(fd, iov_native, iovcnt);
delete[] iov_native;
return ret;
}
s64 HostIO_POSIX::PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
errno = 0;
iovec* iov_native = new iovec[iovcnt];
for (s32 idx = 0; idx < iovcnt; idx++)
iov_native[idx] = {.iov_base = iov[idx].iov_base, .iov_len = iov[idx].iov_len};
s64 ret = preadv(fd, iov_native, iovcnt, offset);
delete[] iov_native;
return ret;
}
s64 HostIO_POSIX::Write(const s32 fd, const void* buf, u64 count) {
errno = 0;
s32 status = write(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
errno = 0;
s32 status = pwrite(fd, buf, count, offset);
return status >= 0 ? status : -errno;
}
s64 HostIO_POSIX::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
s64 HostIO_POSIX::WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) {
errno = 0;
s32 status = pread(fd, buf, count, offset);
return status >= 0 ? status : -errno;
iovec* iov_native = new iovec[iovcnt];
for (s32 idx = 0; idx < iovcnt; idx++)
iov_native[idx] = {.iov_base = iov[idx].iov_base, .iov_len = iov[idx].iov_len};
s64 ret = writev(fd, iov_native, iovcnt);
delete[] iov_native;
return ret;
}
s64 HostIO_POSIX::PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
errno = 0;
iovec* iov_native = new iovec[iovcnt];
for (s32 idx = 0; idx < iovcnt; idx++)
iov_native[idx] = {.iov_base = iov[idx].iov_base, .iov_len = iov[idx].iov_len};
s64 ret = pwritev(fd, iov_native, iovcnt, offset);
delete[] iov_native;
return ret;
}
s32 HostIO_POSIX::MKDir(const fs::path& path, u16 mode) {
@ -125,7 +178,7 @@ s32 HostIO_POSIX::RMDir(const fs::path& path) {
return 0 == status ? status : -errno;
}
s32 HostIO_POSIX::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) {
s32 HostIO_POSIX::Stat(const fs::path& path, OrbisKernelStat* statbuf) {
errno = 0;
struct stat st;
@ -158,7 +211,7 @@ s32 HostIO_POSIX::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat*
return 0;
}
s32 HostIO_POSIX::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) {
s32 HostIO_POSIX::FStat(const s32 fd, OrbisKernelStat* statbuf) {
errno = 0;
struct stat st;

View File

@ -200,24 +200,9 @@ s32 HostIO_Virtual::FTruncate(const s32 fd, u64 size) {
if (nullptr == node)
return -QUASI_EBADF;
// if (node->is_dir())
// return -QUASI_EISDIR;
// if (!node->is_file())
// return -QUASI_EINVAL;
return handle->node->ftruncate(size);
}
s64 HostIO_Virtual::Write(const s32 fd, const void* buf, u64 count) {
s64 bw = this->PWrite(fd, buf, count, handle->pos);
if (bw > 0)
handle->pos += bw;
return bw;
}
s64 HostIO_Virtual::Read(const s32 fd, void* buf, u64 count) {
s64 br = PRead(fd, buf, count, handle->pos);
@ -227,6 +212,51 @@ s64 HostIO_Virtual::Read(const s32 fd, void* buf, u64 count) {
return br;
}
s64 HostIO_Virtual::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
if (nullptr == handle)
return -QUASI_EINVAL;
inode_ptr node = handle->node;
if (nullptr == node)
return -QUASI_EBADF;
return node->pread(buf, count, offset);
}
s64 HostIO_Virtual::ReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt) {
s64 br = PReadV(fd, iov, iovcnt, handle->pos);
if (br > 0)
handle->pos += br;
return br;
}
s64 HostIO_Virtual::PReadV(const s32 fd, OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
if (nullptr == handle)
return -QUASI_EBADF;
inode_ptr node = handle->node;
if (nullptr == node)
return -QUASI_EBADF;
if (handle->append)
offset = node->st.st_size;
return node->preadv(iov, iovcnt, offset);
}
s64 HostIO_Virtual::Write(const s32 fd, const void* buf, u64 count) {
s64 bw = this->PWrite(fd, buf, count, handle->pos);
if (bw > 0)
handle->pos += bw;
return bw;
}
s64 HostIO_Virtual::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
if (nullptr == handle)
return -QUASI_EBADF;
@ -242,16 +272,28 @@ s64 HostIO_Virtual::PWrite(const s32 fd, const void* buf, u64 count, u64 offset)
return node->pwrite(buf, count, offset);
}
s64 HostIO_Virtual::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
s64 HostIO_Virtual::WriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt) {
s64 bw = this->PWriteV(fd, iov, iovcnt, handle->pos);
if (bw > 0)
handle->pos += bw;
return bw;
}
s64 HostIO_Virtual::PWriteV(const s32 fd, const OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
if (nullptr == handle)
return -QUASI_EINVAL;
return -QUASI_EBADF;
inode_ptr node = handle->node;
if (nullptr == node)
return -QUASI_EBADF;
return node->pread(buf, count, offset);
if (handle->append)
offset = node->st.st_size;
return node->pwritev(iov, iovcnt, offset);
}
s32 HostIO_Virtual::MKDir(const fs::path& path, u16 mode) {
@ -286,7 +328,7 @@ s32 HostIO_Virtual::RMDir(const fs::path& path) {
return 0;
}
s32 HostIO_Virtual::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) {
s32 HostIO_Virtual::Stat(const fs::path& path, OrbisKernelStat* statbuf) {
if (nullptr == this->res)
return -QUASI_EINVAL;
@ -295,12 +337,12 @@ s32 HostIO_Virtual::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelSta
if (nullptr == node)
return -QUASI_ENOENT;
memcpy(statbuf, &node->st, sizeof(Libraries::Kernel::OrbisKernelStat));
memcpy(statbuf, &node->st, sizeof(OrbisKernelStat));
return 0;
}
s32 HostIO_Virtual::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) {
s32 HostIO_Virtual::FStat(const s32 fd, OrbisKernelStat* statbuf) {
if (nullptr == this->handle)
return -QUASI_EINVAL;
@ -309,7 +351,7 @@ s32 HostIO_Virtual::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* stat
if (nullptr == node)
return -QUASI_EBADF;
memcpy(statbuf, &node->st, sizeof(Libraries::Kernel::OrbisKernelStat));
memcpy(statbuf, &node->st, sizeof(OrbisKernelStat));
return 0;
}
@ -350,7 +392,7 @@ s64 HostIO_Virtual::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
if (nullptr != basep)
*basep = handle->pos;
s64 br = node->getdents(buf + handle->pos, nbytes, basep);
s64 br = node->getdents(static_cast<char*>(buf) + handle->pos, nbytes, basep);
if (br > 0)
handle->pos += br;

View File

@ -84,31 +84,12 @@ int HostIO_Win32::FTruncate(const s32 fd, u64 size) {
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::Write(const s32 fd, const void* buf, u64 count) {
errno = 0;
s32 status = _write(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::Read(const s32 fd, void* buf, u64 count) {
errno = 0;
s32 status = _read(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
errno = 0;
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
if (bak < 0)
return -errno;
LSeek(fd, offset, SeekOrigin::ORIGIN);
s32 status = _write(fd, buf, count);
LSeek(fd, bak, SeekOrigin::ORIGIN);
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
errno = 0;
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
@ -122,6 +103,25 @@ s64 HostIO_Win32::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::Write(const s32 fd, const void* buf, u64 count) {
errno = 0;
s32 status = _write(fd, buf, count);
return status >= 0 ? status : -errno;
}
s64 HostIO_Win32::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
errno = 0;
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
if (bak < 0)
return -errno;
LSeek(fd, offset, SeekOrigin::ORIGIN);
s32 status = _write(fd, buf, count);
LSeek(fd, bak, SeekOrigin::ORIGIN);
return status >= 0 ? status : -errno;
}
s32 HostIO_Win32::MKDir(const fs::path& path, u16 mode) {
errno = 0;
s32 status = _wmkdir(path.c_str());

View File

@ -108,4 +108,5 @@ typedef struct mount_t {
dir_ptr parentdir;
unsigned int options;
} mount_t;
} // namespace QuasiFS

View File

@ -73,10 +73,20 @@ private:
s32 FTruncate(const s32 fd, u64 size) override;
s64 LSeek(const s32 fd, u64 offset, SeekOrigin origin) override;
s64 Tell(const s32 fd) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 Read(const s32 fd, void* buf, u64 count) override;
s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
s64 ReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt) override;
s64 PReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt,
s64 offset) override;
s64 Write(const s32 fd, const void* buf, u64 count) override;
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
s64 WriteV(const s32 fd, const Libraries::Kernel::OrbisKernelIovec* iov,
u32 iovcnt) override;
s64 PWriteV(const s32 fd, const Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt,
s64 offset) override;
s32 MKDir(const fs::path& path, u16 mode = 0755) override;
s32 RMDir(const fs::path& path) override;

View File

@ -16,6 +16,8 @@
namespace QuasiFS {
static_assert(sizeof(time_t) == 8, "Time is not stored in 64 bits");
class Inode {
public:
Inode() {
@ -24,8 +26,6 @@ public:
st.st_uid = 0;
st.st_gid = 0;
static_assert(sizeof(time_t) == 8, "Time is not stored in 64 bits");
st.st_birthtim.tv_sec = time(0);
st.st_birthtim.tv_nsec = 0;
st.st_ctim.tv_sec = time(0);
@ -42,17 +42,6 @@ public:
return -QUASI_ENOTTY;
}
// these don't make sense with anything that's not a device
// kept here to verify
virtual s64 read(void* buf, u64 count) {
return -QUASI_EBADF;
}
virtual s64 write(const void* buf, u64 count) {
return -QUASI_EBADF;
}
// these 4 make sense everywhere
virtual s64 pread(void* buf, u64 count, s64 offset) {
return -QUASI_EBADF;
}
@ -61,29 +50,7 @@ public:
return -QUASI_EBADF;
}
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
u64 tb = 0;
for (unsigned int idx = 0; idx < iovcnt; idx++) {
int status = this->read(iov[idx].iov_base, iov[idx].iov_len);
if (status < 0)
return status;
tb += status;
}
return tb;
}
virtual s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
u64 tb = 0;
for (unsigned int idx = 0; idx < iovcnt; idx++) {
int status = this->write(iov[idx].iov_base, iov[idx].iov_len);
if (status < 0)
return status;
tb += status;
}
return tb;
}
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, s64 offset) {
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
u64 tb = 0;
for (unsigned int idx = 0; idx < iovcnt; idx++) {
int status = this->pread(iov[idx].iov_base, iov[idx].iov_len, offset);
@ -94,7 +61,7 @@ public:
return tb;
}
virtual s64 pwritev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, s64 offset) {
virtual s64 pwritev(const Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt, s64 offset) {
u64 tb = 0;
for (unsigned int idx = 0; idx < iovcnt; idx++) {
int status = this->pwrite(iov[idx].iov_base, iov[idx].iov_len, offset);

View File

@ -22,8 +22,11 @@ public:
UNREACHABLE();
}
s64 pread(void* buf, u64 count, s64 offset) override;
s64 pwrite(const void* buf, u64 count, s64 offset) override;
virtual s64 read(void* buf, u64 count);
virtual s64 write(const void* buf, u64 count);
s64 pread(void* buf, u64 count, s64 offset) final override;
s64 pwrite(const void* buf, u64 count, s64 offset) final override;
};
} // namespace QuasiFS

View File

@ -33,7 +33,6 @@ private:
public:
DirectoryPFS() = default;
~DirectoryPFS() = default;
};
} // namespace QuasiFS

View File

@ -30,22 +30,19 @@ private:
const fs::path host_root{};
// IO block size, allocation unit (multiples of 512)
u32 ioblock_size{4096};
const u32 ioblock_size{4096};
// amount of raw on-disk blocks per io block
// this is pretty much so we don't recalculate it over and over and over
// and
u32 block_size{512};
u8 filesystem_format = FileSystem::NORMAL;
const u32 block_size{512};
public:
// host-bound directory, permissions for root directory
Partition(const fs::path& host_root = "");
Partition();
Partition(const fs::path& host_root = "", const int root_permissions = 0755,
const u32 block_size = 512, const u32 ioblock_size = 4096);
~Partition() = default;
void Format(const int root_permissions = 0755, u8 format = FileSystem::NORMAL,
const u32 block_size = 512, const u32 ioblock_size = 4096);
template <typename... Args>
static partition_ptr Create(Args&&... args) {
return std::make_shared<Partition>(std::forward<Args>(args)...);

View File

@ -5,10 +5,10 @@
#include "core/file_sys/quasifs/quasi_errno.h"
#include "core/file_sys/quasifs/quasi_types.h"
#include "core/file_sys/quasifs/quasifs.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_file_virtual.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory_pfs.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_file.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_file_virtual.h"
#include "core/file_sys/quasifs/quasifs_inode_symlink.h"
#include "core/file_sys/quasifs/quasifs_partition.h"

View File

@ -15,6 +15,14 @@ Device::Device() {
Device::~Device() = default;
s64 Device::read(void* buf, u64 count) {
return -QUASI_EBADF;
}
s64 Device::write(const void* buf, u64 count) {
return -QUASI_EBADF;
}
s64 Device::pread(void* buf, u64 count, s64 offset) {
return read(buf, count);
}

View File

@ -12,28 +12,14 @@
namespace QuasiFS {
Partition::Partition(const fs::path& host_root)
: block_id(next_block_id++), host_root(host_root.lexically_normal()) {}
void Partition::Format(const int root_permissions, u8 format, const u32 block_size,
const u32 ioblock_size) {
this->inode_table.clear();
this->next_fileno = 2;
this->ioblock_size = ioblock_size;
this->block_size = block_size;
this->filesystem_format = format;
switch (format) {
default:
LOG_ERROR(Kernel_Fs, "Unknown target partition type. Defaulting to normal");
case FileSystem::NORMAL:
this->root = Directory::Create<Directory>();
break;
case FileSystem::PFS:
this->root = Directory::Create<DirectoryPFS>();
break;
}
Partition::Partition() : Partition("", 0755, 512, 4096) {}
Partition::Partition(const fs::path& host_root, const int root_permissions, const u32 block_size,
const u32 ioblock_size)
: block_id(next_block_id++), host_root(host_root.lexically_normal()), block_size(block_size),
ioblock_size(ioblock_size) {
this->root = Directory::Create<Directory>();
// clear defaults, write
chmod(this->root, root_permissions);
IndexInode(this->root);
mkrelative(this->root, this->root);

View File

@ -512,6 +512,143 @@ void UpdateStatFromHost(Libraries::Kernel::OrbisKernelStat* vfs,
vfs->st_ctim = host->st_ctim;
}
s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
return -QUASI_EBADF;
bool host_used = false;
int hio_status = 0;
int vio_status = 0;
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.Read(host_fd, buf, count); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.Read(fd, buf, count);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
return vio_status;
}
s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
return -QUASI_EBADF;
bool host_used = false;
int hio_status = 0;
int vio_status = 0;
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.PRead(host_fd, buf, count, offset); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.PRead(fd, buf, count, offset);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
return vio_status;
};
s64 QFS::OperationImpl::ReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
return -QUASI_EBADF;
bool host_used = false;
int hio_status = 0;
int vio_status = 0;
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.ReadV(host_fd, iov, iovcnt); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.ReadV(fd, iov, iovcnt);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
return vio_status;
}
s64 QFS::OperationImpl::PReadV(const s32 fd, Libraries::Kernel::OrbisKernelIovec* iov, u32 iovcnt,
s64 offset) {
if (fd < 0)
return -QUASI_EBADF;
fd_handle_ptr handle = qfs.GetHandle(fd);
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
return -QUASI_EBADF;
bool host_used = false;
int hio_status = 0;
int vio_status = 0;
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.PReadV(host_fd, iov, iovcnt, offset); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.PReadV(fd, iov, iovcnt, offset);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
LOG_ERROR(Kernel_Fs, "Host returned {}, but virtual driver returned {}", hio_status,
vio_status);
return vio_status;
}
s64 QFS::OperationImpl::Write(const s32 fd, const void* buf, u64 count) {
if (fd < 0)
return -QUASI_EBADF;
@ -580,7 +717,8 @@ s64 QFS::OperationImpl::PWrite(const s32 fd, const void* buf, u64 count, u64 off
return vio_status;
};
s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
s64 QFS::OperationImpl::WriteV(const s32 fd, const Libraries::Kernel::OrbisKernelIovec* iov,
u32 iovcnt) {
if (fd < 0)
return -QUASI_EBADF;
@ -588,7 +726,7 @@ s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
if (!handle->write)
return -QUASI_EBADF;
bool host_used = false;
@ -597,14 +735,14 @@ s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.Read(host_fd, buf, count); hio_status < 0)
if (hio_status = qfs.hio_driver.WriteV(host_fd, iov, iovcnt); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.Read(fd, buf, count);
vio_status = qfs.vio_driver.WriteV(fd, iov, iovcnt);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
@ -614,7 +752,8 @@ s64 QFS::OperationImpl::Read(const s32 fd, void* buf, u64 count) {
return vio_status;
}
s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
s64 QFS::OperationImpl::PWriteV(const s32 fd, const Libraries::Kernel::OrbisKernelIovec* iov,
u32 iovcnt, s64 offset) {
if (fd < 0)
return -QUASI_EBADF;
@ -622,7 +761,7 @@ s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
if (nullptr == handle)
return -QUASI_EBADF;
if (!handle->read)
if (!handle->write)
return -QUASI_EBADF;
bool host_used = false;
@ -631,14 +770,14 @@ s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
if (handle->IsHostBound()) {
int host_fd = handle->host_fd;
if (hio_status = qfs.hio_driver.PRead(host_fd, buf, count, offset); hio_status < 0)
if (hio_status = qfs.hio_driver.PWriteV(host_fd, iov, iovcnt, offset); hio_status < 0)
// hosts operation must succeed in order to continue
return hio_status;
host_used = true;
}
qfs.vio_driver.SetCtx(nullptr, host_used, handle);
vio_status = qfs.vio_driver.PRead(fd, buf, count, offset);
vio_status = qfs.vio_driver.PWriteV(fd, iov, iovcnt, offset);
qfs.vio_driver.ClearCtx();
if (host_used && (hio_status != vio_status))
@ -646,7 +785,7 @@ s64 QFS::OperationImpl::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
vio_status);
return vio_status;
};
}
s32 QFS::OperationImpl::MKDir(const fs::path& path, u16 mode) {
Resolved res;

View File

@ -93,27 +93,15 @@ Emulator::~Emulator() {}
void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
auto* qfs = Common::Singleton<qfs::QFS>::Instance();
qfs->Operation.MKDir("/app0", 0555);
qfs->Operation.MKDir("/hostapp", 0555);
qfs::partition_ptr partition_app0 = qfs::Partition::Create(game_folder);
partition_app0->Format(0555, qfs::FileSystem::PFS, 512, 65536);
qfs->Mount("/app0", partition_app0, qfs::MountOptions::MOUNT_NOOPT);
qfs->Mount("/hostapp", partition_app0,
qfs::MountOptions::MOUNT_NOOPT | qfs::MountOptions::MOUNT_BIND);
qfs->Operation.Chmod("/", 0777);
qfs::partition_ptr partition_app0 = qfs::Partition::Create(game_folder, 0555, 512, 65536);
qfs::partition_ptr partition_av_contents = qfs::Partition::Create("", 0775, 512, 16384);
qfs::partition_ptr partition_av_contents_photo = qfs::Partition::Create("", 0755, 4096, 32768);
qfs::partition_ptr partition_av_contents_thumbs = qfs::Partition::Create("", 0755, 4096, 32768);
qfs::partition_ptr partition_av_contents_video = qfs::Partition::Create("", 0755, 4096, 32768);
qfs::partition_ptr partition_dev = qfs::Partition::Create("", 0755, 16384, 16384);
partition_app0->Format(0555, qfs::FileSystem::PFS, 512, 65536);
partition_app0->Format(0555, qfs::FileSystem::PFS, 512, 65536);
partition_app0->Format(0555, qfs::FileSystem::PFS, 512, 65536);
partition_app0->Format(0555, qfs::FileSystem::PFS, 512, 65536);
qfs->Operation.MKDir("/app0", 0555);
qfs->Operation.MKDir("/hostapp", 0555);
qfs->Operation.MKDir("/av_contents", 0775);
qfs->Operation.MKDir("/av_contents/photo", 0755);
qfs->Operation.MKDir("/av_contents/thumbnails", 0755);
@ -125,6 +113,7 @@ void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
qfs->Operation.MKDir("/temp", 0777);
qfs->Operation.MKDir("/temp0", 0777);
qfs->Mount("/app0", partition_app0, qfs::MountOptions::MOUNT_NOOPT);
qfs->Mount("/av_contents", partition_av_contents, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/av_contents/photo", partition_av_contents_photo, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/av_contents/thumbnails", partition_av_contents_thumbs,
@ -132,6 +121,8 @@ void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
qfs->Mount("/av_contents/video", partition_av_contents_video, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/dev", partition_dev, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/hostapp", partition_app0,
qfs::MountOptions::MOUNT_NOOPT | qfs::MountOptions::MOUNT_BIND);
//
// Setup /dev
@ -286,7 +277,7 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
qfs->Mount("/temp0", partition_temp,
qfs::MountOptions::MOUNT_RW | qfs::MountOptions::MOUNT_BIND);
qfs->SyncHost("/data");
qfs->SyncHost("/donwload0");
qfs->SyncHost("/download0");
qfs->SyncHost("/temp");
qfs->SyncHost("/temp0");
@ -430,34 +421,34 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
g_window = window.get();
// const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
if (!std::filesystem::exists(mount_data_dir)) {
std::filesystem::create_directory(mount_data_dir);
}
mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial
// if (!std::filesystem::exists(mount_data_dir)) {
// std::filesystem::create_directory(mount_data_dir);
// }
// mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial
// Mounting temp folders
// const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
if (std::filesystem::exists(mount_temp_dir)) {
// Temp folder should be cleared on each boot.
std::filesystem::remove_all(mount_temp_dir);
}
std::filesystem::create_directory(mount_temp_dir);
mnt->Mount(mount_temp_dir, "/temp0");
mnt->Mount(mount_temp_dir, "/temp");
// if (std::filesystem::exists(mount_temp_dir)) {
// // Temp folder should be cleared on each boot.
// std::filesystem::remove_all(mount_temp_dir);
// }
// std::filesystem::create_directory(mount_temp_dir);
// mnt->Mount(mount_temp_dir, "/temp0");
// mnt->Mount(mount_temp_dir, "/temp");
// const auto& mount_download_dir =
// Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
if (!std::filesystem::exists(mount_download_dir)) {
std::filesystem::create_directory(mount_download_dir);
}
mnt->Mount(mount_download_dir, "/download0");
// if (!std::filesystem::exists(mount_download_dir)) {
// std::filesystem::create_directory(mount_download_dir);
// }
// mnt->Mount(mount_download_dir, "/download0");
// const auto& mount_captures_dir =
// Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
if (!std::filesystem::exists(mount_captures_dir)) {
std::filesystem::create_directory(mount_captures_dir);
}
VideoCore::SetOutputDir(mount_captures_dir, id);
// if (!std::filesystem::exists(mount_captures_dir)) {
// std::filesystem::create_directory(mount_captures_dir);
// }
// VideoCore::SetOutputDir(mount_captures_dir, id);
// Initialize kernel and library facilities.
Libraries::InitHLELibs(&linker->GetHLESymbols());