From 462146b644a7083efe817c86c3fc99c8c59fbc62 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 07:54:08 -0400 Subject: [PATCH 1/2] FileWriterWin32: Prevent implicit sign conversion within position() --- src/athena/FileWriterWin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 9a6cd43..684927d 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -89,7 +89,7 @@ atUint64 FileWriter::position() const { LARGE_INTEGER li = {}; LARGE_INTEGER res; SetFilePointerEx(m_fileHandle, li, &res, FILE_CURRENT); - return res.QuadPart; + return static_cast(res.QuadPart); } atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } From 3b1348a26a2235d192ae185609aacd6e124bc660 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 7 Sep 2019 07:55:23 -0400 Subject: [PATCH 2/2] FileWriterWin32: Handle large files within writeUBytes Handles the case where a given size exceeds the maximum value that can be contained within a DWORD. Given a DWORD is 32-bit in size and an atUint64 is 64-bits in size, this avoids errors on valid sizes, even if they're extremely unlikely to ever occur. --- src/athena/FileWriterWin32.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/athena/FileWriterWin32.cpp b/src/athena/FileWriterWin32.cpp index 684927d..7e2d117 100644 --- a/src/athena/FileWriterWin32.cpp +++ b/src/athena/FileWriterWin32.cpp @@ -1,5 +1,10 @@ #include "athena/FileWriter.hpp" -#include "win32_largefilewrapper.h" + +#include +#include + +#undef min +#undef max namespace athena::io { FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) @@ -96,19 +101,29 @@ atUint64 FileWriter::length() const { return utility::fileSize(m_filename); } void FileWriter::writeUBytes(const atUint8* data, atUint64 len) { if (!isOpen()) { - if (m_globalErr) + if (m_globalErr) { atError(fmt("File not open for writing")); + } setError(); return; } - DWORD ret = 0; - WriteFile(m_fileHandle, data, len, &ret, nullptr); - if (ret != len) { - if (m_globalErr) - atError(fmt("Unable to write to stream")); - setError(); - } + atUint64 remaining = len; + do { + const auto toWrite = static_cast(std::min(remaining, atUint64{std::numeric_limits::max()})); + DWORD written = 0; + + if (WriteFile(m_fileHandle, data, toWrite, &written, nullptr) == FALSE) { + if (m_globalErr) { + atError(fmt("Unable to write to file")); + } + setError(); + return; + } + + remaining -= written; + data += written; + } while (remaining != 0); } } // namespace athena::io