Implemented dirents (normal)

Minor movements
This commit is contained in:
Marek Ledworowski 2025-11-09 23:40:56 +01:00
parent 4e07f5c2e1
commit 5abfa01ccd
32 changed files with 263 additions and 101 deletions

View File

@ -659,6 +659,7 @@ set(QUASIFS src/core/file_sys/quasifs/src/quasifs.cpp
src/core/file_sys/quasifs/src/quasifs_vdriver.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_device.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory_pfs.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_file.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_socket.cpp
src/core/file_sys/quasifs/src/quasifs_inode_quasi_file_virtual.cpp

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); };
s32 fsync() override { DEVICE_STUB(); };
s32 ftruncate(s64 length) override { DEVICE_STUB(); };
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); };
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); };
// clang-format on
};

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); };
s32 fsync() override { DEVICE_STUB(); };
s32 ftruncate(s64 length) override { DEVICE_STUB(); };
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); };
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); };
// clang-format on
};

View File

@ -39,7 +39,7 @@ public:
s64 lseek(s64 offset, int whence) override { DEVICE_STUB(); }
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
private:

View File

@ -23,7 +23,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { return 0; };
s32 fsync() override { return 0; };
s32 ftruncate(s64 length) override { return 0; };
s64 getdents(void* buf, u32 nbytes, s64* basep) override { return 0; };
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { return 0; };
// clang-format on
};

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
};

View File

@ -29,7 +29,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
};

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
private:

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
};

View File

@ -30,7 +30,7 @@ public:
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }
s32 fsync() override { DEVICE_STUB(); }
s32 ftruncate(s64 length) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64* basep) override { DEVICE_STUB(); }
s64 getdents(void* buf, u32 nbytes, s64 offset, s64* basep) override { DEVICE_STUB(); }
// clang-format on
};

View File

@ -18,13 +18,13 @@ public:
explicit NormalDirectory(std::string_view guest_path);
~NormalDirectory() override = default;
virtual s64 read(void* buf, u64 nbytes) override;
virtual s64 read(void* buf, u64 count) override;
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt,
s64 offset) override;
virtual s64 lseek(s64 offset, s32 whence) override;
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) override;
virtual s64 getdents(void* buf, u64 nbytes, s64* basep) override;
virtual s64 getdents(void* buf, u64 count, s64* basep) override;
private:
static constexpr s32 MAX_LENGTH = 255;

View File

@ -80,7 +80,7 @@ public:
s32 Chmod(const fs::path& path, u16 mode) override;
s32 FChmod(const s32 fd, u16 mode) override;
s64 GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) override;
s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep) override;
//
// Derived, complex functions are to be handled by main FS class
//

View File

@ -53,9 +53,7 @@ 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(); }
s64 HostIO_Base::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
STUB()
}
s64 HostIO_Base::GetDents(const s32 fd, void* buf, u64 count, s64* basep) { STUB(); }
// clang-format on
} // namespace HostIODriver

View File

@ -56,7 +56,7 @@ public:
virtual s32 Chmod(const fs::path& path, u16 mode);
virtual s32 FChmod(const s32 fd, u16 mode);
virtual s64 GetDents(s32 fd, void* buf, u32 nbytes, s64* basep);
virtual s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep);
//
// Derived, complex functions are to be handled by main FS class
//

View File

@ -259,6 +259,6 @@ s32 HostIO_POSIX::FChmod(const s32 fd, u16 mode) {
return 0 == status ? status : -errno;
}
// s64 HostIO_POSIX::GetDents(void* buf, u32 nbytes, s64* basep) { return -QUASI_ENOSYS; }
// s32 HostIO_POSIX::GetDents(void* buf, u32 count, s64* basep) { return -QUASI_ENOSYS; }
} // namespace HostIODriver

View File

@ -380,7 +380,7 @@ s32 HostIO_Virtual::FChmod(const s32 fd, u16 mode) {
return Partition::chmod(node, mode);
}
s64 HostIO_Virtual::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
s64 HostIO_Virtual::GetDents(const s32 fd, void* buf, u64 count, s64* basep) {
if (nullptr == this->handle)
return -QUASI_EINVAL;
@ -389,10 +389,8 @@ s64 HostIO_Virtual::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
if (nullptr == node)
return -QUASI_EBADF;
if (nullptr != basep)
*basep = handle->pos;
s64 br = node->getdents(buf, count, handle->pos, basep);
s64 br = node->getdents(static_cast<char*>(buf) + handle->pos, nbytes, basep);
if (br > 0)
handle->pos += br;

View File

@ -20,4 +20,7 @@
#define __QUASI_O_ALLFLAGS_AT_ONCE \
(QUASI_O_RDONLY | QUASI_O_WRONLY | QUASI_O_RDWR | QUASI_O_NONBLOCK | QUASI_O_APPEND | \
QUASI_O_FSYNC | QUASI_O_SYNC | QUASI_O_CREAT | QUASI_O_TRUNC | QUASI_O_EXCL | QUASI_O_DSYNC | \
QUASI_O_DIRECT | QUASI_O_DIRECTORY)
QUASI_O_DIRECT | QUASI_O_DIRECTORY)
// not implemented
#define QUASI_O_CLOEXEC 0x100000

View File

@ -58,12 +58,12 @@ using fd_handle_ptr = std::shared_ptr<File>;
struct File {
File() = default;
~File() = default;
int host_fd{-1}; // fd if opened with HostIO
s32 host_fd{-1}; // fd if opened with HostIO
inode_ptr node{nullptr}; // inode
bool read{false}; // read permission
bool write{false}; // write permission
bool append{false}; // append
u64 pos{0}; // cursor offset
s64 pos{0}; // cursor offset
static fd_handle_ptr Create() {
return std::shared_ptr<File>(new File());

View File

@ -96,7 +96,7 @@ private:
s32 Chmod(const fs::path& path, u16 mode) override;
s32 FChmod(const s32 fd, u16 mode) override;
s64 GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) override;
s64 GetDents(const s32 fd, void* buf, u64 count, s64* basep) override;
};
public:

View File

@ -89,7 +89,7 @@ public:
return -QUASI_EINVAL;
}
virtual s64 getdents(void* buf, u32 nbytes, s64* basep) {
virtual s64 getdents(void* buf, u32 count, s64 offset, s64* basep) {
return -QUASI_EINVAL;
}

View File

@ -7,6 +7,7 @@
#include <vector>
#include "common/assert.h"
#include "common/logging/log.h"
#include "quasi_types.h"
#include "quasifs_inode.h"
@ -16,23 +17,21 @@ namespace QuasiFS {
// Directory
class QuasiDirectory : public Inode {
private:
std::map<std::string, inode_ptr> entries{};
time_t last_dirent_rebuild_time{0};
void RebuildDirents(void);
static constexpr s32 MAX_LENGTH = 255;
static constexpr s64 DIRECTORY_ALIGNMENT = 0x200;
protected:
#pragma pack(push, 1)
typedef struct dirent_t {
quasi_ino_t d_ino{};
u64 d_off{};
unsigned short d_reclen{};
unsigned char d_type{};
char d_name[256]{};
u32 d_fileno;
u16 d_reclen;
u8 d_type;
u8 d_namlen;
char d_name[256];
} dirent_t;
#pragma pack(pop)
std::map<std::string, inode_ptr> entries{};
void RebuildDirents(void);
time_t last_dirent_rebuild_time{0};
std::map<s64, dirent_t> dirent_cache{};
public:
dir_ptr mounted_root = nullptr;
@ -58,17 +57,13 @@ public:
// Inode overrides
//
// s64 pread(void* buf, size_t count, u64 offset) override;
s64 pread(void* buf, u64 count, s64 offset) override;
// s64 pwrite(const void* buf, size_t count, u64 offset) override;
s32 ftruncate(s64 length) final override {
return -QUASI_EISDIR;
}
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
this->st.st_size = entries.size() * 32;
*sb = st;
return 0;
}
s32 ftruncate(s64 length) final override;
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s64 getdents(void* buf, u32 count, s64 offset, s64* basep) override;
//
// Dir-specific

View File

@ -16,23 +16,29 @@ namespace QuasiFS {
// Directory
class DirectoryPFS final : public QuasiDirectory {
private:
static constexpr s32 MAX_LENGTH = 255;
static constexpr s32 DIRECTORY_ALIGNMENT = 0x10000;
protected:
#pragma pack(push, 1)
typedef struct dirent_pfs_t {
u32 d_fileno;
u32 d_type;
u32 d_namlen;
u32 d_reclen;
char d_name[MAX_LENGTH + 1];
char d_name[256];
} dirent_pfs_t;
#pragma pack(pop)
private:
// void RebuildDirents(void);
public:
DirectoryPFS() = default;
~DirectoryPFS() = default;
DirectoryPFS();
~DirectoryPFS();
s64 pread(void* buf, u64 count, s64 offset) override;
s64 getdents(void* buf, u32 count, s64 offset, s64* basep) override;
};
} // namespace QuasiFS

View File

@ -4,6 +4,9 @@
#include <unordered_map>
#include "common/alignment.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory.h"
#include "quasi_types.h"
namespace QuasiFS {
@ -31,16 +34,15 @@ private:
// IO block size, allocation unit (multiples of 512)
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
const u32 block_size{512};
public:
// host-bound directory, permissions for root directory
Partition();
Partition(const fs::path& host_root = "", const int root_permissions = 0755,
const u32 block_size = 512, const u32 ioblock_size = 4096);
const u32 ioblock_size = 4096);
Partition(dir_ptr root_directory = Directory::Create<Directory>(),
const fs::path& host_root = "", const int root_permissions = 0755,
const u32 ioblock_size = 4096);
~Partition() = default;
template <typename... Args>
@ -62,11 +64,6 @@ public:
blkid_t GetBlkId(void) {
return this->block_id;
}
void AdjustStat(Libraries::Kernel::OrbisKernelStat* statbuf) {
auto& s = statbuf->st_size;
statbuf->st_blksize = this->block_size;
statbuf->st_blocks = (1 + (s / this->ioblock_size)) * this->ioblock_size / this->block_size;
}
inode_ptr GetInodeByFileno(fileno_t fileno);
int Resolve(fs::path& path, Resolved& res);

View File

@ -114,7 +114,7 @@ void printTree(const dir_ptr& node, const std::string& name, int depth) {
}
QFS::QFS(const fs::path& host_path) {
this->rootfs = Partition::Create(host_path);
this->rootfs = Partition::Create(Directory::Create<Directory>(), host_path);
this->root = rootfs->GetRoot();
mount_t mount_options = {
@ -435,7 +435,9 @@ void QFS::SyncHostImpl(partition_ptr part) {
LOG_ERROR(Kernel_Fs, "Cannot stat file: {}", entry_path.string());
continue;
}
part->AdjustStat(&new_inode->st);
new_inode->st.st_blocks =
Common::AlignUp(static_cast<u64>(new_inode->st.st_size), new_inode->st.st_blksize) /
512;
}
} catch (const std::exception& e) {
LOG_CRITICAL(Kernel_Fs, "An error occurred when syncing [{}]: {}", host_path.string(),

View File

@ -3,6 +3,7 @@
#include <map>
#include <string>
#include "common/alignment.h"
#include "core/file_sys/quasifs/quasi_errno.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory.h"
@ -12,11 +13,59 @@ QuasiDirectory::QuasiDirectory() {
st.st_mode |= QUASI_S_IFDIR;
}
s64 QuasiDirectory::pread(void* buf, u64 count, s64 offset) {
return getdents(buf, count, offset, nullptr);
}
s32 QuasiDirectory::ftruncate(s64 length) {
return -QUASI_EISDIR;
}
s32 QuasiDirectory::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
RebuildDirents();
*sb = st;
return 0;
}
s64 QuasiDirectory::getdents(void* buf, u32 count, s64 offset, s64* basep) {
RebuildDirents();
auto it = dirent_cache.lower_bound(offset);
if (it == dirent_cache.end())
return 0;
u64 cumulative_offset = 0;
u16 last_reclen = 0;
for (; it != dirent_cache.end(); it++) {
auto dirent = it->second;
if (dirent.d_reclen + cumulative_offset > count)
break;
memcpy(static_cast<u8*>(buf) + cumulative_offset, &dirent, dirent.d_reclen);
last_reclen = dirent.d_reclen;
cumulative_offset += last_reclen;
}
if (basep)
*basep = cumulative_offset;
// offset of the last reclen
auto _val = cumulative_offset - last_reclen + 4;
// pointer to last reclen in buffer
u8* placement = static_cast<u8*>(buf) + _val;
// casting buffer to u16 to write whole value at once (2 bytes)
u16* pos = reinterpret_cast<u16*>(placement);
*pos += Common::AlignUp(cumulative_offset, count) - cumulative_offset;
return count;
}
inode_ptr QuasiDirectory::lookup(const std::string& name) {
st.st_atim.tv_sec = time(0);
auto it = entries.find(name);
if (it == entries.end())
return nullptr;
st.st_atim.tv_sec = time(0);
return it->second;
}
@ -69,9 +118,35 @@ std::vector<std::string> QuasiDirectory::list() {
}
void QuasiDirectory::RebuildDirents(void) {
// adding/removing entries changes mtime
if (this->st.st_mtim.tv_sec == this->last_dirent_rebuild_time)
return;
this->last_dirent_rebuild_time = this->st.st_mtim.tv_sec;
u64 dirent_size = 0;
this->dirent_cache.clear();
for (auto entry = entries.begin(); entry != entries.end(); ++entry) {
dirent_t tmp{};
inode_ptr node = entry->second;
std::string name = entry->first;
tmp.d_fileno = node->fileno;
tmp.d_namlen = name.size();
strncpy(tmp.d_name, name.data(), tmp.d_namlen + 1);
tmp.d_type = node->type() >> 12;
tmp.d_reclen =
Common::AlignUp(sizeof(tmp.d_fileno) + sizeof(tmp.d_type) + sizeof(tmp.d_namlen) +
sizeof(tmp.d_reclen) + (tmp.d_namlen + 1),
4);
dirent_cache[dirent_size] = tmp;
dirent_size += tmp.d_reclen;
}
this->st.st_size = dirent_size;
return;
}
} // namespace QuasiFS

View File

@ -0,0 +1,84 @@
// INAA License @marecl 2025
#include <map>
#include <string>
#include "common/alignment.h"
#include "core/file_sys/quasifs/quasi_errno.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory_pfs.h"
namespace QuasiFS {
DirectoryPFS::DirectoryPFS() {
this->st.st_size = 65536;
}
DirectoryPFS::~DirectoryPFS() = default;
s64 DirectoryPFS::pread(void* buf, u64 count, s64 offset) {
RebuildDirents();
auto it = dirent_cache.lower_bound(offset);
if (it == dirent_cache.end())
return 0;
u64 cumulative_offset = 0;
u16 last_reclen = 0;
for (; it != dirent_cache.end(); it++) {
auto dirent = it->second;
if (dirent.d_reclen + cumulative_offset > count)
break;
memcpy(static_cast<u8*>(buf) + cumulative_offset, &dirent, dirent.d_reclen);
last_reclen = dirent.d_reclen;
cumulative_offset += last_reclen;
}
// offset of the last reclen
auto _val = cumulative_offset - last_reclen + 4;
// pointer to last reclen in buffer
u8* placement = static_cast<u8*>(buf) + _val;
// casting buffer to u16 to write whole value at once (2 bytes)
u16* pos = reinterpret_cast<u16*>(placement);
*pos += Common::AlignUp(cumulative_offset, count) - cumulative_offset;
return count;
}
s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) {
RebuildDirents();
auto it = dirent_cache.lower_bound(offset);
if (it == dirent_cache.end())
return 0;
u64 cumulative_offset = 0;
u16 last_reclen = 0;
for (; it != dirent_cache.end(); it++) {
auto dirent = it->second;
if (dirent.d_reclen + cumulative_offset > count)
break;
memcpy(static_cast<u8*>(buf) + cumulative_offset, &dirent, dirent.d_reclen);
last_reclen = dirent.d_reclen;
cumulative_offset += last_reclen;
}
if (basep)
*basep = cumulative_offset;
// offset of the last reclen
auto _val = cumulative_offset - last_reclen + 4;
// pointer to last reclen in buffer
u8* placement = static_cast<u8*>(buf) + _val;
// casting buffer to u16 to write whole value at once (2 bytes)
u16* pos = reinterpret_cast<u16*>(placement);
*pos += Common::AlignUp(cumulative_offset, count) - cumulative_offset;
return count;
}
} // namespace QuasiFS

View File

@ -12,11 +12,14 @@
namespace QuasiFS {
Partition::Partition() : Partition("", 0755, 512, 4096) {}
Partition::Partition() : Partition(Directory::Create<Directory>(), "", 0755, 4096) {}
Partition::Partition(const fs::path& host_root, const int root_permissions, const u32 block_size,
Partition::Partition(const fs::path& host_root, const int root_permissions, const u32 ioblock_size)
: Partition(Directory::Create<Directory>(), host_root, root_permissions, ioblock_size) {}
Partition::Partition(dir_ptr root_directory, const fs::path& host_root, const int root_permissions,
const u32 ioblock_size)
: block_id(next_block_id++), host_root(host_root.lexically_normal()), block_size(block_size),
: block_id(next_block_id++), host_root(host_root.lexically_normal()),
ioblock_size(ioblock_size) {
this->root = Directory::Create<Directory>();
// clear defaults, write
@ -223,15 +226,6 @@ int Partition::touch(dir_ptr parent, const std::string& name, inode_ptr child) {
if (nullptr == parent)
return -QUASI_EINVAL;
// auto* csize = &child->st.st_size;
// auto* cbsize = &child->st.st_blksize;
// auto* cblks = &child->st.st_blocks;
// *cbsize = this->ioblock_size;
// *cblks = blocks_per_io * (*csize) / (*cbsize);
child->st.st_blksize = ioblock_size;
auto ret = parent->link(name, child);
if (ret == 0)
IndexInode(child);
@ -370,6 +364,8 @@ bool Partition::IndexInode(inode_ptr node) {
node->st.st_ino = node_fileno;
node->st.st_dev = block_id;
node->st.st_blksize = ioblock_size;
node->st.st_blocks = Common::AlignUp(static_cast<u64>(node->st.st_size), ioblock_size) / 512;
return true;
}

View File

@ -936,7 +936,7 @@ s32 QFS::OperationImpl::FChmod(const s32 fd, u16 mode) {
return vio_status;
}
s64 QFS::OperationImpl::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
s64 QFS::OperationImpl::GetDents(const s32 fd, void* buf, u64 count, s64* basep) {
if (fd < 0)
return -QUASI_EBADF;
@ -948,7 +948,7 @@ s64 QFS::OperationImpl::GetDents(s32 fd, void* buf, u32 nbytes, s64* basep) {
return -QUASI_EBADF;
qfs.vio_driver.SetCtx(nullptr, false, handle);
int vio_status = qfs.vio_driver.GetDents(fd, buf, nbytes, basep);
int vio_status = qfs.vio_driver.GetDents(fd, buf, count, basep);
qfs.vio_driver.ClearCtx();
return vio_status;

View File

@ -14,12 +14,15 @@
#include "core/libraries/system/systemservice.h"
#include "core/file_sys/quasifs/quasifs.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory_pfs.h"
#include "core/file_sys/quasifs/quasifs_partition.h"
static QuasiFS::QFS* g_qfs = Common::Singleton<QuasiFS::QFS>::Instance();
namespace qfs = QuasiFS;
namespace Libraries::AppContent {
static qfs::QFS* g_qfs = Common::Singleton<qfs::QFS>::Instance();
struct AddContInfo {
char entitlement_label[ORBIS_NP_UNIFIED_ENTITLEMENT_LABEL_SIZE];
OrbisAppContentAddcontDownloadStatus status;
@ -109,11 +112,12 @@ int PS4_SYSV_ABI sceAppContentAddcontMount(u32 service_label,
// We've located the correct folder.
g_qfs->Operation.MKDir(mount_point->data, 0555 /* I think it's like /app0*/);
QuasiFS::partition_ptr partition_dlc = QuasiFS::Partition::Create(entry.path(), 0555);
g_qfs->Mount(mount_point->data, partition_dlc, QuasiFS::MountOptions::MOUNT_RW);
qfs::partition_ptr partition_dlc = qfs::Partition::Create(
qfs::Directory::Create<qfs::DirectoryPFS>(), entry.path(), 0555);
g_qfs->Mount(mount_point->data, partition_dlc, qfs::MountOptions::MOUNT_RW);
g_qfs->SyncHost(mount_point->data);
g_qfs->Mount(mount_point->data, partition_dlc,
QuasiFS::MountOptions::MOUNT_REMOUNT | QuasiFS::MountOptions::MOUNT_NOOPT);
qfs::MountOptions::MOUNT_REMOUNT | qfs::MountOptions::MOUNT_NOOPT);
return ORBIS_OK;
}

View File

@ -40,10 +40,11 @@
#endif
namespace qfs = QuasiFS;
static QuasiFS::QFS* g_qfs = Common::Singleton<QuasiFS::QFS>::Instance();
namespace Libraries::Kernel {
static QuasiFS::QFS* g_qfs = Common::Singleton<QuasiFS::QFS>::Instance();
s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {:#o}", raw_path, flags, mode);
@ -537,7 +538,7 @@ static s64 GetDents(s32 fd, char* buf, u64 nbytes, s64* basep) {
return -1;
}
return ORBIS_OK;
return result;
}
s64 PS4_SYSV_ABI posix_getdents(s32 fd, char* buf, u64 nbytes) {

View File

@ -19,10 +19,8 @@ constexpr auto OrbisSaveDataBlocksMin2 = 96; // 3MiB
constexpr auto OrbisSaveDataBlocksMax = 32768; // 1 GiB
constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save
namespace qfs = QuasiFS;
static qfs::QFS* g_qfs = Common::Singleton<qfs::QFS>::Instance();
namespace fs = std::filesystem;
namespace qfs = QuasiFS;
// clang-format off
static const std::unordered_map<int, std::string> default_title = {
@ -49,6 +47,8 @@ static const std::unordered_map<int, std::string> default_title = {
namespace Libraries::SaveData {
static qfs::QFS* g_qfs = Common::Singleton<qfs::QFS>::Instance();
fs::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id,
std::string_view game_serial) {
return Config::GetSaveDataPath() / std::to_string(user_id) / game_serial;
@ -192,7 +192,7 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor
max_blocks = static_cast<int>(GetMaxBlockFromSFO(param_sfo));
g_qfs->Operation.MKDir(mount_point);
auto part = qfs::Partition::Create(save_path);
auto part = qfs::Partition::Create(qfs::Directory::Create<qfs::Directory>(), save_path);
g_qfs->Mount(mount_point, part,
read_only ? qfs::MountOptions::MOUNT_NOOPT : qfs::MountOptions::MOUNT_RW);
g_qfs->SyncHost(mount_point);

View File

@ -47,6 +47,7 @@
#include "core/file_sys/quasifs/quasi_sys_fcntl.h"
#include "core/file_sys/quasifs/quasifs.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_device.h"
#include "core/file_sys/quasifs/quasifs_inode_quasi_directory_pfs.h"
#include "core/file_sys/quasifs/quasifs_partition.h"
#include "core/file_sys/devices/console_device.h"
@ -93,12 +94,14 @@ Emulator::~Emulator() {}
void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
auto* qfs = Common::Singleton<qfs::QFS>::Instance();
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);
qfs::partition_ptr partition_app0 = qfs::Partition::Create(game_folder, 0555, 65536);
// qfs::partition_ptr partition_app0 = qfs::Partition::Create(
// qfs::Directory::Create<qfs::DirectoryPFS>(), game_folder, 0555, 512, 65536);
qfs::partition_ptr partition_av_contents = qfs::Partition::Create("", 0775, 16384);
qfs::partition_ptr partition_av_contents_photo = qfs::Partition::Create("", 0755, 32768);
qfs::partition_ptr partition_av_contents_thumbs = qfs::Partition::Create("", 0755, 32768);
qfs::partition_ptr partition_av_contents_video = qfs::Partition::Create("", 0755, 32768);
qfs::partition_ptr partition_dev = qfs::Partition::Create("", 0755, 16384);
qfs->Operation.MKDir("/app0", 0555);
qfs->Operation.MKDir("/av_contents", 0775);
@ -264,10 +267,9 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
qfs->Operation.MKDir("/download0", 0777); // not sure about perms here
qfs->Operation.MKDir("/temp", 0777);
qfs->Operation.MKDir("/temp0", 0777);
qfs::partition_ptr partition_data = qfs::Partition::Create(mount_data_dir, 0777, 4096, 32768);
qfs::partition_ptr partition_download =
qfs::Partition::Create(mount_download_dir, 0777, 512, 65536);
qfs::partition_ptr partition_temp = qfs::Partition::Create(mount_temp_dir, 0777, 512, 16384);
qfs::partition_ptr partition_data = qfs::Partition::Create(mount_data_dir, 0777, 32768);
qfs::partition_ptr partition_download = qfs::Partition::Create(mount_download_dir, 0777, 65536);
qfs::partition_ptr partition_temp = qfs::Partition::Create(mount_temp_dir, 0777, 16384);
qfs->Mount("/data", partition_data, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/download0", partition_download, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/temp", partition_temp, qfs::MountOptions::MOUNT_RW);