From d7c39cc7190019796c3cbad5b3f1781b4755c894 Mon Sep 17 00:00:00 2001 From: DH Date: Fri, 14 Mar 2025 14:54:18 +0300 Subject: [PATCH] FIle: add write_at --- rpcs3/Utilities/File.cpp | 47 ++++++++++++++++++++++++++++++++++++++++ rpcs3/Utilities/File.h | 33 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/rpcs3/Utilities/File.cpp b/rpcs3/Utilities/File.cpp index c5fecc9d1..45c4b1256 100644 --- a/rpcs3/Utilities/File.cpp +++ b/rpcs3/Utilities/File.cpp @@ -539,6 +539,34 @@ namespace fs return nwritten_sum; } + u64 write_at(u64 offset, const void* buffer, u64 count) override + { + u64 nwritten_sum = 0; + + for (const char* data = static_cast(buffer); count;) + { + const DWORD size = static_cast(std::min(count, DWORD{umax} & -4096)); + + DWORD nwritten = 0; + OVERLAPPED ovl{}; + ovl.Offset = DWORD(offset); + ovl.OffsetHigh = DWORD(offset >> 32); + ensure(WriteFile(m_handle, data, size, &nwritten, &ovl)); // "file::write" + ensure(nwritten == size); + nwritten_sum += nwritten; + + if (nwritten < size) + { + break; + } + + count -= size; + data += size; + } + + return nwritten_sum; + } + u64 seek(s64 offset, seek_mode whence) override { if (whence > seek_end) @@ -710,6 +738,25 @@ namespace fs return result; } + u64 write_at(u64 offset, const void* buffer, u64 count) override + { + u64 result = 0; + + // For safety; see read() + while (auto r = ::pwrite(m_fd, buffer, count, offset)) + { + ensure(r > 0); // "file::write" + count -= r; + offset += r; + result += r; + buffer = static_cast(buffer) + r; + if (!count) + break; + } + + return result; + } + u64 seek(s64 offset, seek_mode whence) override { if (whence > seek_end) diff --git a/rpcs3/Utilities/File.h b/rpcs3/Utilities/File.h index a5a4c53d7..8c1b0b585 100644 --- a/rpcs3/Utilities/File.h +++ b/rpcs3/Utilities/File.h @@ -109,6 +109,10 @@ namespace fs virtual u64 read(void* buffer, u64 size) = 0; virtual u64 read_at(u64 offset, void* buffer, u64 size) = 0; virtual u64 write(const void* buffer, u64 size) = 0; + virtual u64 write_at([[maybe_unused]] u64 offset, [[maybe_unused]] const void* buffer, [[maybe_unused]] u64 size) + { + return 0; + } virtual u64 seek(s64 offset, seek_mode whence) = 0; virtual u64 size() = 0; virtual native_handle get_handle(); @@ -343,6 +347,12 @@ namespace fs return m_file->write(buffer, count); } + u64 write_at(u64 offset, const void* buffer, u64 count, std::source_location src_loc = std::source_location::current()) const + { + if (!m_file) xnull(src_loc); + return m_file->write_at(offset, buffer, count); + } + // Change current position, returns resulting position u64 seek(s64 offset, seek_mode whence = seek_set, std::source_location src_loc = std::source_location::current()) const { @@ -611,6 +621,29 @@ namespace fs } }; + class virtual_dir final : public fs::dir_base + { + std::vector m_entries; + std::size_t m_offset = 0; + + public: + virtual_dir(std::vector entries) + : m_entries(std::move(entries)) {} + + bool read(fs::dir_entry &entry) override + { + if (m_offset < m_entries.size()) + { + entry = m_entries[m_offset++]; + return true; + } + + return false; + } + + void rewind() override { m_offset = 0; } + }; + // Get executable path std::string get_executable_path();