From 008b61d28d5da089ed3550b52910a5a96e2149a5 Mon Sep 17 00:00:00 2001 From: Marek Ledworowski Date: Fri, 21 Nov 2025 00:06:56 +0100 Subject: [PATCH] lseek on devices fixed dirents not updating when RefreshDirents is called too fast after lseek --- src/core/file_sys/devices/console_device.h | 1 - src/core/file_sys/devices/deci_tty6_device.h | 1 - src/core/file_sys/devices/logger.h | 1 - src/core/file_sys/devices/nop_device.h | 1 - src/core/file_sys/devices/null_device.h | 1 - src/core/file_sys/devices/random_device.h | 1 - src/core/file_sys/devices/rng_device.h | 1 - src/core/file_sys/devices/srandom_device.h | 1 - src/core/file_sys/devices/zero_device.h | 1 - src/core/file_sys/quasifs/quasifs_inode_quasi_device.h | 1 + src/core/file_sys/quasifs/quasifs_inode_quasi_directory.h | 2 +- .../file_sys/quasifs/src/quasifs_inode_quasi_device.cpp | 7 +++++++ .../quasifs/src/quasifs_inode_quasi_directory.cpp | 7 ++++--- .../quasifs/src/quasifs_inode_quasi_directory_pfs.cpp | 8 ++++---- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/core/file_sys/devices/console_device.h b/src/core/file_sys/devices/console_device.h index d1be2e9a2..76369872f 100644 --- a/src/core/file_sys/devices/console_device.h +++ b/src/core/file_sys/devices/console_device.h @@ -30,7 +30,6 @@ public: s64 read(void* buf, u64 count) override { DEVICE_STUB(); }; s64 write(const void* buf, u64 count) override { DEVICE_STUB(); }; s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }; - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }; s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }; s32 fsync() override { DEVICE_STUB(); }; s32 ftruncate(s64 length) override { DEVICE_STUB(); }; diff --git a/src/core/file_sys/devices/deci_tty6_device.h b/src/core/file_sys/devices/deci_tty6_device.h index 7bbe5b955..f5c3f9002 100644 --- a/src/core/file_sys/devices/deci_tty6_device.h +++ b/src/core/file_sys/devices/deci_tty6_device.h @@ -30,7 +30,6 @@ public: s64 read(void* buf, u64 count) override { DEVICE_STUB(); }; s64 write(const void* buf, u64 count) override { DEVICE_STUB(); }; s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); }; - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); }; s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); }; s32 fsync() override { DEVICE_STUB(); }; s32 ftruncate(s64 length) override { DEVICE_STUB(); }; diff --git a/src/core/file_sys/devices/logger.h b/src/core/file_sys/devices/logger.h index 3815e66ce..2ead3a117 100644 --- a/src/core/file_sys/devices/logger.h +++ b/src/core/file_sys/devices/logger.h @@ -40,7 +40,6 @@ public: // clang-format off s64 read(void* buf, u64 count) override { DEVICE_STUB(); }; s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 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 offset, s64* basep) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/devices/nop_device.h b/src/core/file_sys/devices/nop_device.h index d3a61c4d3..b2fe9de31 100644 --- a/src/core/file_sys/devices/nop_device.h +++ b/src/core/file_sys/devices/nop_device.h @@ -23,7 +23,6 @@ public: s64 read(void* buf, u64 count) override { return 0; }; s64 write(const void* buf, u64 count) override { return 0; }; s32 ioctl(u64 cmd, Common::VaCtx* args) override { return 0; }; - s64 lseek(s64 current, s64 offset, s32 whence) override { return 0; }; s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { return 0; }; s32 fsync() override { return 0; }; s32 ftruncate(s64 length) override { return 0; }; diff --git a/src/core/file_sys/devices/null_device.h b/src/core/file_sys/devices/null_device.h index 114a60dfa..7302f2181 100644 --- a/src/core/file_sys/devices/null_device.h +++ b/src/core/file_sys/devices/null_device.h @@ -30,7 +30,6 @@ public: // clang-format off s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); } s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); } s32 fsync() override { DEVICE_STUB(); } s32 ftruncate(s64 length) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/devices/random_device.h b/src/core/file_sys/devices/random_device.h index 87c1fb45f..8af3ee042 100644 --- a/src/core/file_sys/devices/random_device.h +++ b/src/core/file_sys/devices/random_device.h @@ -29,7 +29,6 @@ public: // clang-format off s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); } s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); } s32 fsync() override { DEVICE_STUB(); } s32 ftruncate(s64 length) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/devices/rng_device.h b/src/core/file_sys/devices/rng_device.h index 97b73fefb..ed13ec320 100644 --- a/src/core/file_sys/devices/rng_device.h +++ b/src/core/file_sys/devices/rng_device.h @@ -30,7 +30,6 @@ public: // clang-format off s64 read(void* buf, u64 count) override { DEVICE_STUB(); } s64 write(const void* buf, u64 count) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); } s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); } s32 fsync() override { DEVICE_STUB(); } s32 ftruncate(s64 length) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/devices/srandom_device.h b/src/core/file_sys/devices/srandom_device.h index 87956f7af..67562bc79 100644 --- a/src/core/file_sys/devices/srandom_device.h +++ b/src/core/file_sys/devices/srandom_device.h @@ -30,7 +30,6 @@ public: // clang-format off s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); } s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); } s32 fsync() override { DEVICE_STUB(); } s32 ftruncate(s64 length) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/devices/zero_device.h b/src/core/file_sys/devices/zero_device.h index 529de06d6..8b15e3423 100644 --- a/src/core/file_sys/devices/zero_device.h +++ b/src/core/file_sys/devices/zero_device.h @@ -30,7 +30,6 @@ public: // clang-format off s32 ioctl(u64 cmd, Common::VaCtx* args) override { DEVICE_STUB(); } - s64 lseek(s64 current, s64 offset, s32 whence) override { DEVICE_STUB(); } s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override { DEVICE_STUB(); } s32 fsync() override { DEVICE_STUB(); } s32 ftruncate(s64 length) override { DEVICE_STUB(); } diff --git a/src/core/file_sys/quasifs/quasifs_inode_quasi_device.h b/src/core/file_sys/quasifs/quasifs_inode_quasi_device.h index fcdae686a..a538d10ff 100644 --- a/src/core/file_sys/quasifs/quasifs_inode_quasi_device.h +++ b/src/core/file_sys/quasifs/quasifs_inode_quasi_device.h @@ -24,6 +24,7 @@ public: s64 pread(void* buf, u64 count, s64 offset) final override; s64 pwrite(const void* buf, u64 count, s64 offset) final override; + s64 lseek(s64 current, s64 offset, s32 whence) final override; }; } // namespace QuasiFS \ No newline at end of file diff --git a/src/core/file_sys/quasifs/quasifs_inode_quasi_directory.h b/src/core/file_sys/quasifs/quasifs_inode_quasi_directory.h index 2ddf5d727..4557976cc 100644 --- a/src/core/file_sys/quasifs/quasifs_inode_quasi_directory.h +++ b/src/core/file_sys/quasifs/quasifs_inode_quasi_directory.h @@ -30,7 +30,7 @@ protected: std::map entries{}; void RebuildDirents(void); - time_t last_dirent_rebuild_time{0}; + bool dirents_changed{false}; std::vector dirent_cache_bin{}; public: diff --git a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_device.cpp b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_device.cpp index 77534c1c6..f667e59f9 100644 --- a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_device.cpp +++ b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_device.cpp @@ -31,4 +31,11 @@ s64 Device::pwrite(const void* buf, u64 count, s64 offset) { return write(buf, count); } +s64 Device::lseek(s64 current, s64 offset, s32 whence) { + return ((QuasiFS::SeekOrigin::ORIGIN == whence) * offset) + + ((QuasiFS::SeekOrigin::CURRENT == whence) * (current + offset)) + + ((QuasiFS::SeekOrigin::END == whence) * ((offset > 0) * offset)); + // ::END is pro-forma +} + } // namespace QuasiFS \ No newline at end of file diff --git a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory.cpp b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory.cpp index c1ce2db0b..72a2a9c54 100644 --- a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory.cpp +++ b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory.cpp @@ -26,6 +26,7 @@ s64 QuasiDirectory::pread(void* buf, u64 count, s64 offset) { s64 QuasiDirectory::lseek(s64 current, s64 offset, s32 whence) { RebuildDirents(); + this->dirents_changed = false; return Inode::lseek(current, offset, whence); } @@ -41,6 +42,7 @@ s32 QuasiDirectory::ftruncate(s64 length) { s64 QuasiDirectory::getdents(void* buf, u32 count, s64 offset, s64* basep) { RebuildDirents(); + st.st_atim.tv_sec = time(0); // at this point count is ALWAYS >512 (checked in VIO Driver) // always returns up to 512 bytes @@ -122,10 +124,9 @@ std::vector QuasiDirectory::list() { } void QuasiDirectory::RebuildDirents(void) { - // adding/removing entries changes mtime - if (this->st.st_mtim.tv_sec == this->last_dirent_rebuild_time) + if (this->dirents_changed) return; - this->last_dirent_rebuild_time = this->st.st_mtim.tv_sec; + this->dirents_changed = false; constexpr u32 dirent_meta_size = sizeof(dirent_t::d_fileno) + sizeof(dirent_t::d_type) + sizeof(dirent_t::d_namlen) + sizeof(dirent_t::d_reclen); diff --git a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory_pfs.cpp b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory_pfs.cpp index def2cf504..8780604d6 100644 --- a/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory_pfs.cpp +++ b/src/core/file_sys/quasifs/src/quasifs_inode_quasi_directory_pfs.cpp @@ -22,6 +22,7 @@ DirectoryPFS::~DirectoryPFS() = default; s64 DirectoryPFS::pread(void* buf, u64 count, s64 offset) { RebuildDirents(); + st.st_atim.tv_sec = time(0); // data is contiguous. i think that's how it's said // anyway, everything goes raw @@ -67,6 +68,7 @@ s64 DirectoryPFS::lseek(s64 current, s64 offset, s32 whence) { // future s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) { RebuildDirents(); + st.st_atim.tv_sec = time(0); if (count != 65536) LOG_CRITICAL(Kernel_Fs, "PFS dirents read with count={} (which is not 65536) (report this)", @@ -123,11 +125,9 @@ s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) { } void DirectoryPFS::RebuildDirents(void) { - - // adding/removing entries changes mtime - if (this->st.st_mtim.tv_sec == this->last_dirent_rebuild_time) + if (this->dirents_changed) return; - this->last_dirent_rebuild_time = this->st.st_mtim.tv_sec; + this->dirents_changed = false; constexpr u32 dirent_meta_size = sizeof(dirent_pfs_t::d_fileno) + sizeof(dirent_pfs_t::d_type) + sizeof(dirent_pfs_t::d_namlen) +