From 98ec0d073ef46f02225f77d1df3029ddc8852154 Mon Sep 17 00:00:00 2001 From: Marek Ledworowski Date: Sun, 16 Nov 2025 19:48:31 +0100 Subject: [PATCH] Cleanse --- .../file_sys/directories/base_directory.cpp | 15 -- .../file_sys/directories/base_directory.h | 52 ----- .../file_sys/directories/normal_directory.cpp | 140 ----------- .../file_sys/directories/normal_directory.h | 45 ---- .../file_sys/directories/pfs_directory.cpp | 220 ------------------ src/core/file_sys/directories/pfs_directory.h | 53 ----- src/core/file_sys/fs.h | 1 - src/core/libraries/kernel/file_system.cpp | 2 - src/core/memory.cpp | 25 +- 9 files changed, 17 insertions(+), 536 deletions(-) delete mode 100644 src/core/file_sys/directories/base_directory.cpp delete mode 100644 src/core/file_sys/directories/base_directory.h delete mode 100644 src/core/file_sys/directories/normal_directory.cpp delete mode 100644 src/core/file_sys/directories/normal_directory.h delete mode 100644 src/core/file_sys/directories/pfs_directory.cpp delete mode 100644 src/core/file_sys/directories/pfs_directory.h diff --git a/src/core/file_sys/directories/base_directory.cpp b/src/core/file_sys/directories/base_directory.cpp deleted file mode 100644 index c709da6a2..000000000 --- a/src/core/file_sys/directories/base_directory.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/logging/log.h" -#include "common/singleton.h" -#include "core/file_sys/directories/base_directory.h" -#include "core/file_sys/fs.h" - -namespace Core::Directories { - -BaseDirectory::BaseDirectory() = default; - -BaseDirectory::~BaseDirectory() = default; - -} // namespace Core::Directories \ No newline at end of file diff --git a/src/core/file_sys/directories/base_directory.h b/src/core/file_sys/directories/base_directory.h deleted file mode 100644 index 8900ac32b..000000000 --- a/src/core/file_sys/directories/base_directory.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include "common/types.h" -#include "common/va_ctx.h" -#include "core/libraries/kernel/file_system.h" -#include "core/libraries/kernel/orbis_error.h" - -namespace Libraries::Kernel { -struct OrbisKernelStat; -struct OrbisKernelIovec; -struct OrbisKernelDirent; -} // namespace Libraries::Kernel - -namespace Core::Directories { - -class BaseDirectory { -public: - explicit BaseDirectory(); - - virtual ~BaseDirectory() = 0; - - virtual s64 read(void* buf, u64 nbytes) { - return ORBIS_KERNEL_ERROR_EBADF; - } - - virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) { - return ORBIS_KERNEL_ERROR_EBADF; - } - - virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) { - return ORBIS_KERNEL_ERROR_EBADF; - } - - virtual s64 lseek(s64 offset, s32 whence) { - return ORBIS_KERNEL_ERROR_EBADF; - } - - virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* stat) { - return ORBIS_KERNEL_ERROR_EBADF; - } - - virtual s64 getdents(void* buf, u64 nbytes, s64* basep) { - return ORBIS_KERNEL_ERROR_EBADF; - } -}; - -} // namespace Core::Directories \ No newline at end of file diff --git a/src/core/file_sys/directories/normal_directory.cpp b/src/core/file_sys/directories/normal_directory.cpp deleted file mode 100644 index a7d76074a..000000000 --- a/src/core/file_sys/directories/normal_directory.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/alignment.h" -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/singleton.h" -#include "core/file_sys/directories/normal_directory.h" -#include "core/file_sys/fs.h" - -namespace Core::Directories { - -std::shared_ptr NormalDirectory::Create(std::string_view guest_directory) { - return std::static_pointer_cast( - std::make_shared(guest_directory)); -} - -NormalDirectory::NormalDirectory(std::string_view guest_directory) { - auto* mnt = Common::Singleton::Instance(); - - static s32 fileno = 0; - mnt->IterateDirectory(guest_directory, [this](const auto& ent_path, const auto ent_is_file) { - auto& dirent = dirents.emplace_back(); - dirent.d_fileno = ++fileno; - dirent.d_type = (ent_is_file ? 8 : 4); - strncpy(dirent.d_name, ent_path.filename().string().data(), MAX_LENGTH + 1); - dirent.d_namlen = ent_path.filename().string().size(); - - // Calculate the appropriate length for this dirent. - // Account for the null terminator in d_name too. - dirent.d_reclen = Common::AlignUp(sizeof(dirent.d_fileno) + sizeof(dirent.d_type) + - sizeof(dirent.d_namlen) + sizeof(dirent.d_reclen) + - (dirent.d_namlen + 1), - 4); - - directory_size += dirent.d_reclen; - }); - - // The last entry of a normal directory should have d_reclen covering the remaining data. - // Since the dirents of a folder are constant by this point, we can modify the last dirent - // before creating the emulated file buffer. - const u64 filler_count = Common::AlignUp(directory_size, DIRECTORY_ALIGNMENT) - directory_size; - dirents[dirents.size() - 1].d_reclen += filler_count; - - // Reading from standard directories seems to be based around file pointer logic. - // Keep an internal buffer representing the raw contents of this file descriptor, - // then emulate the various read functions with that. - directory_size = Common::AlignUp(directory_size, DIRECTORY_ALIGNMENT); - data_buffer.reserve(directory_size); - memset(data_buffer.data(), 0, directory_size); - - u8* current_dirent = data_buffer.data(); - for (const NormalDirectoryDirent& dirent : dirents) { - NormalDirectoryDirent* dirent_to_write = - reinterpret_cast(current_dirent); - dirent_to_write->d_fileno = dirent.d_fileno; - - // Using size d_namlen + 1 to account for null terminator. - strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1); - dirent_to_write->d_namlen = dirent.d_namlen; - dirent_to_write->d_reclen = dirent.d_reclen; - dirent_to_write->d_type = dirent.d_type; - - current_dirent += dirent.d_reclen; - } -} - -s64 NormalDirectory::read(void* buf, u64 nbytes) { - // Nothing left to read. - if (file_offset >= directory_size) { - return ORBIS_OK; - } - - const s64 remaining_data = directory_size - file_offset; - const s64 bytes = nbytes > remaining_data ? remaining_data : nbytes; - - std::memcpy(buf, data_buffer.data() + file_offset, bytes); - - file_offset += bytes; - return bytes; -} - -s64 NormalDirectory::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) { - s64 bytes_read = 0; - for (s32 i = 0; i < iovcnt; i++) { - const s64 result = read(iov[i].iov_base, iov[i].iov_len); - if (result < 0) { - return result; - } - bytes_read += result; - } - return bytes_read; -} - -s64 NormalDirectory::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, - s64 offset) { - const u64 old_file_pointer = file_offset; - file_offset = offset; - const s64 bytes_read = readv(iov, iovcnt); - file_offset = old_file_pointer; - return bytes_read; -} - -s64 NormalDirectory::lseek(s64 offset, s32 whence) { - switch (whence) { - case 0: { - file_offset = offset; - break; - } - case 1: { - file_offset += offset; - break; - } - case 2: { - file_offset = directory_size + offset; - break; - } - default: { - UNREACHABLE_MSG("lseek with unknown whence {}", whence); - } - } - return file_offset; -} - -s32 NormalDirectory::fstat(Libraries::Kernel::OrbisKernelStat* stat) { - stat->st_mode = 0000777u | 0040000u; - stat->st_size = directory_size; - stat->st_blksize = 0x8000; - stat->st_blocks = 8; - return ORBIS_OK; -} - -s64 NormalDirectory::getdents(void* buf, u64 nbytes, s64* basep) { - if (basep != nullptr) { - *basep = file_offset; - } - // read behaves identically to getdents for normal directories. - return read(buf, nbytes); -} -} // namespace Core::Directories \ No newline at end of file diff --git a/src/core/file_sys/directories/normal_directory.h b/src/core/file_sys/directories/normal_directory.h deleted file mode 100644 index 0cd8a8f8d..000000000 --- a/src/core/file_sys/directories/normal_directory.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include "common/types.h" -#include "core/file_sys/directories/base_directory.h" -#include "core/libraries/kernel/orbis_error.h" - -namespace Core::Directories { - -class NormalDirectory final : public BaseDirectory { -public: - static std::shared_ptr Create(std::string_view guest_path); - explicit NormalDirectory(std::string_view guest_path); - ~NormalDirectory() override = default; - - 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 count, s64* basep) override; - -private: - static constexpr s32 MAX_LENGTH = 255; - static constexpr s64 DIRECTORY_ALIGNMENT = 0x200; - struct NormalDirectoryDirent { - u32 d_fileno; - u16 d_reclen; - u8 d_type; - u8 d_namlen; - char d_name[MAX_LENGTH + 1]; - }; - - u64 directory_size = 0; - s64 file_offset = 0; - std::vector data_buffer; - std::vector dirents; -}; -} // namespace Core::Directories diff --git a/src/core/file_sys/directories/pfs_directory.cpp b/src/core/file_sys/directories/pfs_directory.cpp deleted file mode 100644 index fbd97c019..000000000 --- a/src/core/file_sys/directories/pfs_directory.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/alignment.h" -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/singleton.h" -#include "core/file_sys/directories/pfs_directory.h" -#include "core/file_sys/fs.h" - -namespace Core::Directories { - -std::shared_ptr PfsDirectory::Create(std::string_view guest_directory) { - return std::static_pointer_cast(std::make_shared(guest_directory)); -} - -PfsDirectory::PfsDirectory(std::string_view guest_directory) { - auto* mnt = Common::Singleton::Instance(); - - static s32 fileno = 0; - mnt->IterateDirectory(guest_directory, [this](const auto& ent_path, const auto ent_is_file) { - auto& dirent = dirents.emplace_back(); - dirent.d_fileno = ++fileno; - dirent.d_type = (ent_is_file ? 8 : 4); - strncpy(dirent.d_name, ent_path.filename().string().data(), MAX_LENGTH + 1); - dirent.d_namlen = ent_path.filename().string().size(); - - // Calculate the appropriate length for this dirent. - // Account for the null terminator in d_name too. - dirent.d_reclen = Common::AlignUp(sizeof(dirent.d_fileno) + sizeof(dirent.d_type) + - sizeof(dirent.d_namlen) + sizeof(dirent.d_reclen) + - (dirent.d_namlen + 1), - 8); - - // To handle some obscure dirents_index behavior, - // keep track of the "actual" length of this directory. - directory_content_size += dirent.d_reclen; - }); - - directory_size = Common::AlignUp(directory_content_size, DIRECTORY_ALIGNMENT); -} - -s64 PfsDirectory::read(void* buf, u64 nbytes) { - if (dirents_index >= dirents.size()) { - if (dirents_index < directory_content_size) { - // We need to find the appropriate dirents_index to start from. - s64 data_to_skip = dirents_index; - u64 corrected_index = 0; - while (data_to_skip > 0) { - const auto dirent = dirents[corrected_index++]; - data_to_skip -= dirent.d_reclen; - } - dirents_index = corrected_index; - } else { - // Nothing left to read. - return ORBIS_OK; - } - } - - s64 bytes_remaining = nbytes > directory_size ? directory_size : nbytes; - // read on PfsDirectories will always return the maximum possible value. - const u64 bytes_written = bytes_remaining; - memset(buf, 0, bytes_remaining); - - char* current_dirent = static_cast(buf); - PfsDirectoryDirent dirent = dirents[dirents_index]; - while (bytes_remaining > dirent.d_reclen) { - PfsDirectoryDirent* dirent_to_write = reinterpret_cast(current_dirent); - dirent_to_write->d_fileno = dirent.d_fileno; - - // Using size d_namlen + 1 to account for null terminator. - strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1); - dirent_to_write->d_namlen = dirent.d_namlen; - dirent_to_write->d_reclen = dirent.d_reclen; - dirent_to_write->d_type = dirent.d_type; - - current_dirent += dirent.d_reclen; - bytes_remaining -= dirent.d_reclen; - - if (dirents_index == dirents.size() - 1) { - // Currently at the last dirent, so break out of the loop. - dirents_index++; - break; - } - dirent = dirents[++dirents_index]; - } - - return bytes_written; -} - -s64 PfsDirectory::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) { - s64 bytes_read = 0; - for (s32 i = 0; i < iovcnt; i++) { - const s64 result = read(iov[i].iov_base, iov[i].iov_len); - if (result < 0) { - return result; - } - bytes_read += result; - } - return bytes_read; -} - -s64 PfsDirectory::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) { - const u64 old_dirent_index = dirents_index; - dirents_index = 0; - s64 data_to_skip = offset; - // If offset is part-way through one dirent, that dirent is skipped. - while (data_to_skip > 0) { - const auto dirent = dirents[dirents_index++]; - data_to_skip -= dirent.d_reclen; - if (dirents_index == dirents.size()) { - // We've reached the end of the dirents, nothing more can be skipped. - break; - } - } - - const s64 bytes_read = readv(iov, iovcnt); - dirents_index = old_dirent_index; - return bytes_read; -} - -s64 PfsDirectory::lseek(s64 offset, s32 whence) { - switch (whence) { - // Seek start - case 0: { - dirents_index = 0; - } - case 1: { - // There aren't any dirents left to pass through. - if (dirents_index >= dirents.size()) { - dirents_index = dirents_index + offset; - break; - } - s64 data_to_skip = offset; - while (data_to_skip > 0) { - const auto dirent = dirents[dirents_index++]; - data_to_skip -= dirent.d_reclen; - if (dirents_index == dirents.size()) { - // We've passed through all file dirents. - // Set dirents_index to directory_size + remaining_offset instead. - dirents_index = directory_content_size + data_to_skip; - break; - } - } - break; - } - case 2: { - // Seems like real hardware gives up on tracking dirents_index if you go this route. - dirents_index = directory_size + offset; - break; - } - default: { - UNREACHABLE_MSG("lseek with unknown whence {}", whence); - } - } - - return dirents_index; -} - -s32 PfsDirectory::fstat(Libraries::Kernel::OrbisKernelStat* stat) { - stat->st_mode = 0000777u | 0040000u; - stat->st_size = directory_size; - stat->st_blksize = 0x10000; - stat->st_blocks = 0x80; - return ORBIS_OK; -} - -s64 PfsDirectory::getdents(void* buf, u64 nbytes, s64* basep) { - // basep is set at the start of the function. - if (basep != nullptr) { - *basep = dirents_index; - } - - if (dirents_index >= dirents.size()) { - if (dirents_index < directory_content_size) { - // We need to find the appropriate dirents_index to start from. - s64 data_to_skip = dirents_index; - u64 corrected_index = 0; - while (data_to_skip > 0) { - const auto dirent = dirents[corrected_index++]; - data_to_skip -= dirent.d_reclen; - } - dirents_index = corrected_index; - } else { - // Nothing left to read. - return ORBIS_OK; - } - } - - s64 bytes_remaining = nbytes > directory_size ? directory_size : nbytes; - memset(buf, 0, bytes_remaining); - - u64 bytes_written = 0; - char* current_dirent = static_cast(buf); - // getdents has to convert pfs dirents to normal dirents - PfsDirectoryDirent dirent = dirents[dirents_index]; - while (bytes_remaining > dirent.d_reclen) { - NormalDirectoryDirent* dirent_to_write = - reinterpret_cast(current_dirent); - dirent_to_write->d_fileno = dirent.d_fileno; - strncpy(dirent_to_write->d_name, dirent.d_name, dirent.d_namlen + 1); - dirent_to_write->d_namlen = dirent.d_namlen; - dirent_to_write->d_reclen = dirent.d_reclen; - dirent_to_write->d_type = dirent.d_type; - - current_dirent += dirent.d_reclen; - bytes_remaining -= dirent.d_reclen; - bytes_written += dirent.d_reclen; - - if (dirents_index == dirents.size() - 1) { - // Currently at the last dirent, so set dirents_index appropriately and break. - dirents_index = directory_size; - break; - } - dirent = dirents[++dirents_index]; - } - - return bytes_written; -} -} // namespace Core::Directories \ No newline at end of file diff --git a/src/core/file_sys/directories/pfs_directory.h b/src/core/file_sys/directories/pfs_directory.h deleted file mode 100644 index 8f3e8d1f5..000000000 --- a/src/core/file_sys/directories/pfs_directory.h +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include "common/types.h" -#include "core/file_sys/directories/base_directory.h" -#include "core/libraries/kernel/orbis_error.h" - -namespace Core::Directories { - -class PfsDirectory final : public BaseDirectory { -public: - static std::shared_ptr Create(std::string_view guest_path); - explicit PfsDirectory(std::string_view guest_path); - ~PfsDirectory() override = default; - - virtual s64 read(void* buf, u64 nbytes) 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; - -private: - static constexpr s32 MAX_LENGTH = 255; - static constexpr s32 DIRECTORY_ALIGNMENT = 0x10000; - struct PfsDirectoryDirent { - u32 d_fileno; - u32 d_type; - u32 d_namlen; - u32 d_reclen; - char d_name[MAX_LENGTH + 1]; - }; - - struct NormalDirectoryDirent { - u32 d_fileno; - u16 d_reclen; - u8 d_type; - u8 d_namlen; - char d_name[MAX_LENGTH + 1]; - }; - - u64 directory_size = 0; - u64 directory_content_size = 0; - s64 dirents_index = 0; - std::vector dirents; -}; -} // namespace Core::Directories diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index e8a3a75b2..a686295ec 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -10,7 +10,6 @@ #include #include "common/io_file.h" #include "common/logging/formatter.h" -#include "core/file_sys/directories/base_directory.h" namespace Libraries::Net { struct Socket; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 25b1c4d8e..892a6eb16 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -18,8 +18,6 @@ #include "core/file_sys/devices/random_device.h" #include "core/file_sys/devices/rng_device.h" #include "core/file_sys/devices/srandom_device.h" -#include "core/file_sys/directories/normal_directory.h" -#include "core/file_sys/directories/pfs_directory.h" #include "core/file_sys/fs.h" #include "core/libraries/kernel/file_system.h" diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 7db25391a..b84a4b254 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -5,7 +5,7 @@ #include "common/assert.h" #include "common/config.h" #include "common/debug.h" -#include "core/file_sys/fs.h" +#include "core/file_sys/quasifs/quasifs.h" #include "core/libraries/kernel/memory.h" #include "core/libraries/kernel/orbis_error.h" #include "core/libraries/kernel/process.h" @@ -555,14 +555,19 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory } // Get the file to map - auto* h = Common::Singleton::Instance(); - auto file = h->GetFile(fd); - if (file == nullptr) { + auto* qfs = Common::Singleton::Instance(); + auto file = qfs->GetHandle(fd); + + if (nullptr == file) { LOG_WARNING(Kernel_Vmm, "Invalid file for mmap, fd {}", fd); return ORBIS_KERNEL_ERROR_EBADF; } - if (file->type != Core::FileSys::FileType::Regular) { + if (nullptr == file->node) { + return ORBIS_KERNEL_ERROR_EBADF; + } + + if (!file->node->is_file()) { LOG_WARNING(Kernel_Vmm, "Unsupported file type for mmap, fd {}", fd); return ORBIS_KERNEL_ERROR_EBADF; } @@ -572,10 +577,14 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory prot |= MemoryProt::CpuRead; } - const auto handle = file->f.GetFileMapping(); + const auto handle = file->host_fd; - if (False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Write) || - False(file->f.GetAccessMode() & Common::FS::FileAccessMode::Append)) { + if (handle < 0) { + LOG_CRITICAL(Kernel_Vmm, "Descriptor does not have host-bound file associated for mmap"); + return ORBIS_KERNEL_ERROR_EBADF; + } + + if (0 == (file->write | file->append)) { // If the file does not have write access, ensure prot does not contain write permissions. // On real hardware, these mappings succeed, but the memory cannot be written to. prot &= ~MemoryProt::CpuWrite;