From a4f38d5dd40f853fed6c3d27ad7a9a82648ad3e8 Mon Sep 17 00:00:00 2001 From: staphen Date: Sat, 1 Feb 2025 20:27:04 -0500 Subject: [PATCH] Avoid write mode when opening save files --- Source/mpq/mpq_writer.cpp | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/Source/mpq/mpq_writer.cpp b/Source/mpq/mpq_writer.cpp index 8f2dfc7ebe3..201d502e1ac 100644 --- a/Source/mpq/mpq_writer.cpp +++ b/Source/mpq/mpq_writer.cpp @@ -93,19 +93,28 @@ MpqWriter::MpqWriter(const char *path) LogVerbose("Opening {}", path); std::string error; bool exists = FileExists(path); - const char *mode = "wbx"; - if (exists) { - mode = "r+b"; - std::uintmax_t fileSize; - if (!GetFileSize(path, &fileSize)) { - error = R"(GetFileSize failed: "{}")"; - LogError(error, path, std::strerror(errno)); - goto on_error; - } - size_ = static_cast(fileSize); - LogVerbose("GetFileSize(\"{}\") = {}", path, size_); + if (!exists) { + // FileExists() may return false in the case of an error + // so we use "ab" instead of "wb" to avoid accidentally + // truncating an existing file + stream_.Open(path, "ab"); + + // However, we cannot actually use a file handle that was + // opened in "ab" mode because we need to be able to seek + // and write to the middle of the file + stream_.Close(); } - if (!stream_.Open(path, mode)) { + + std::uintmax_t fileSize; + if (!GetFileSize(path, &fileSize)) { + error = R"(GetFileSize failed: "{}")"; + LogError(error, path, std::strerror(errno)); + goto on_error; + } + size_ = static_cast(fileSize); + LogVerbose("GetFileSize(\"{}\") = {}", path, size_); + + if (!stream_.Open(path, "r+b")) { stream_.Close(); error = "Failed to open file"; goto on_error;