From 62e0bb1aa023a8a55105232d83cc9ea663a22511 Mon Sep 17 00:00:00 2001 From: Marek Ledworowski Date: Thu, 13 Nov 2025 23:36:10 +0100 Subject: [PATCH] finished mid-thought --- .../src/quasifs_inode_quasi_directory.cpp | 87 +++++++------------ .../src/quasifs_inode_quasi_directory_pfs.cpp | 3 +- 2 files changed, 33 insertions(+), 57 deletions(-) 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 b0857d087..47e3802f4 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 @@ -15,27 +15,12 @@ QuasiDirectory::QuasiDirectory() { } s64 QuasiDirectory::pread(void* buf, u64 count, s64 offset) { - RebuildDirents(); - // complete dirents are divided into 512 (0-filled) byte blocks // if more than 512 bytes are read, it draws bytes from the next block // anything after last dirent is zeroed-out // reclen of last complete dirent (in aligned segment) has size filling up to the end of the // segment - if (offset >= this->dirent_cache_bin.size()) - return 0; - - s64 bytes_available = this->dirent_cache_bin.size() - offset; - // bytes_to_read but retains the same variable lmao - if (bytes_available >= count) - bytes_available = count; - - memcpy(buf, this->dirent_cache_bin.data() + offset, bytes_available); - - // always returns count - return count; - return getdents(buf, count, offset, nullptr); } @@ -68,50 +53,27 @@ s32 QuasiDirectory::ftruncate(s64 length) { s64 QuasiDirectory::getdents(void* buf, u32 count, s64 offset, s64* basep) { RebuildDirents(); - memset(buf, 0, count); // always returns 512 bytes // forces handle ptr to increment in multiples of 512 // returns each memory-aligned segment + // doesn't zero-out remaining space in buffer - if (offset >= this->st.st_size) + s64 bytes_available = this->dirent_cache_bin.size() - offset; + s64 true_end = Common::AlignUp(static_cast(offset) + count, 512); + s64 to_read = true_end - offset; + + if (bytes_available <= 0) return 0; - auto _start = std::lower_bound(dirent_offset.begin(), dirent_offset.end(), offset); - auto _end = std::lower_bound(dirent_offset.begin(), dirent_offset.end(), offset + count); + to_read = to_read > 512 ? 512 : to_read; + to_read = to_read > bytes_available ? bytes_available : to_read; - // lower_bound will *always* select an element that's NOT SMALLER than x - // so if arg lands between two values, it will always select the bigger one - if (_start != dirent_offset.begin() && *_start > offset) - _start--; - - u64 real_start = 0; - u64 real_end = 0; - - u8* dirent_data = static_cast(dirent_cache_bin.data()); - u8* buffer = static_cast(buf); - - u64 bytes_to_read = 0; - // track last reclen to update after writing - u64 reclen_offset = 0; - // there's always data left - for (auto _end_reverse = std::make_reverse_iterator(_end); _end_reverse != dirent_offset.rend(); - _end_reverse++) { - reclen_offset = *_end_reverse + 4; - bytes_to_read = *_end_reverse - *_start + - *reinterpret_cast(dirent_cache_bin.data() + reclen_offset); - if (bytes_to_read < count) - break; - } - - memcpy(reinterpret_cast(buf), dirent_cache_bin.data() + *_start, bytes_to_read); - - u8* tmp = static_cast(buf) + reclen_offset - *_start; - *(reinterpret_cast(tmp)) += count - bytes_to_read; + memcpy(this->dirent_cache_bin.data() + offset, buf, to_read); if (basep) - *basep = count; - return count; + *basep = to_read; + return to_read; } inode_ptr QuasiDirectory::lookup(const std::string& name) { @@ -179,29 +141,42 @@ void QuasiDirectory::RebuildDirents(void) { 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); + u64 next_ceiling = 512; u64 dirent_size = 0; + u64 last_reclen_offset = 4; this->dirent_cache_bin.clear(); - for (auto entry = entries.begin(); entry != entries.end(); ++entry) { dirent_t tmp{}; inode_ptr node = entry->second; std::string name = entry->first; + // prepare dirent 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(dirent_meta_size + tmp.d_namlen + 1, 4); - + tmp.d_reclen = Common::AlignUp(dirent_meta_size + tmp.d_namlen + 1, 8); auto dirent_ptr = reinterpret_cast(&tmp); + + if (dirent_size + tmp.d_reclen > next_ceiling) { + // fill rest of the sector with 0s + std::fill(dirent_cache_bin.begin() + dirent_size, + dirent_cache_bin.begin() + next_ceiling, 0); + // last reclen size to fill the void + *reinterpret_cast(dirent_cache_bin.data() + last_reclen_offset) += + next_ceiling - dirent_size; + dirent_size = next_ceiling; + } + + last_reclen_offset = dirent_size + 4; dirent_cache_bin.insert(dirent_cache_bin.end(), dirent_ptr, dirent_ptr + tmp.d_reclen); dirent_size += tmp.d_reclen; + next_ceiling = Common::AlignUp(dirent_size, 512); } - // directory size is aligned to 512 - this->st.st_size = Common::AlignUp(dirent_size, 512); - - return; + std::fill(dirent_cache_bin.begin() + dirent_size, + dirent_cache_bin.begin() + Common::AlignUp(dirent_size, 512), 0); + this->st.st_size = next_ceiling; } } // namespace QuasiFS \ No newline at end of file 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 d14e3a2c7..db032b410 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 @@ -65,6 +65,7 @@ s64 DirectoryPFS::getdents(void* buf, u32 count, s64 offset, s64* basep) { // variable sizes are same as dirent_t, but data is still aligned to 8 bytes // initial call pulls all COMPLETE dirents (like base), but returns real amount of bytes // for some reason, subsequent calls return 0 + // doesn't zero-out memory after last dirent return count; } @@ -93,8 +94,8 @@ void DirectoryPFS::RebuildDirents(void) { strncpy(tmp.d_name, name.data(), tmp.d_namlen + 1); tmp.d_type = node->type() >> 12; tmp.d_reclen = Common::AlignUp(dirent_meta_size + tmp.d_namlen + 1, 8); - auto dirent_ptr = reinterpret_cast(&tmp); + dirent_cache_bin.insert(dirent_cache_bin.end(), dirent_ptr, dirent_ptr + tmp.d_reclen); dirent_size += tmp.d_reclen; }