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.
This commit is contained in:
Lioncash 2019-09-07 07:55:23 -04:00
parent 462146b644
commit 3b1348a26a
1 changed files with 24 additions and 9 deletions

View File

@ -1,5 +1,10 @@
#include "athena/FileWriter.hpp" #include "athena/FileWriter.hpp"
#include "win32_largefilewrapper.h"
#include <algorithm>
#include <limits>
#undef min
#undef max
namespace athena::io { namespace athena::io {
FileWriter::FileWriter(std::string_view filename, bool overwrite, bool globalErr) 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) { void FileWriter::writeUBytes(const atUint8* data, atUint64 len) {
if (!isOpen()) { if (!isOpen()) {
if (m_globalErr) if (m_globalErr) {
atError(fmt("File not open for writing")); atError(fmt("File not open for writing"));
}
setError(); setError();
return; return;
} }
DWORD ret = 0; atUint64 remaining = len;
WriteFile(m_fileHandle, data, len, &ret, nullptr); do {
if (ret != len) { const auto toWrite = static_cast<DWORD>(std::min(remaining, atUint64{std::numeric_limits<DWORD>::max()}));
if (m_globalErr) DWORD written = 0;
atError(fmt("Unable to write to stream"));
setError(); 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 } // namespace athena::io