diff --git a/core/libs/prx/libc/src/FileAndHeap.cpp b/core/libs/prx/libc/src/FileAndHeap.cpp index aba269af5..e8c483b25 100644 --- a/core/libs/prx/libc/src/FileAndHeap.cpp +++ b/core/libs/prx/libc/src/FileAndHeap.cpp @@ -30,6 +30,7 @@ struct GuestFileMode { std::string native; bool writes = false; bool exclusive = false; + bool append = false; }; static std::optional ParseFileMode(const char* mode) { @@ -42,7 +43,7 @@ static std::optional ParseFileMode(const char* mode) { if (*flag == 'x') exclusive = true; } if (exclusive && access == 'r' && !update) return std::nullopt; - GuestFileMode result{std::string(1, access), access != 'r' || update, exclusive}; + GuestFileMode result{std::string(1, access), access != 'r' || update, exclusive, access == 'a'}; if (update) result.native += '+'; #ifdef _WIN32 result.native += 'b'; @@ -123,6 +124,7 @@ FileStream* APS5_VABI freopen_nid_postfix(const char* filename, const char* mode } } if (stream->Reopen(path, parsed->native.c_str())) { + if (parsed->append) static_cast(std::fseek(stream->GetHandle(), 0, SEEK_END)); if (!path.empty() && parsed->writes) RecordWrittenPath_nid_no_patch(path); return stream; } @@ -168,6 +170,7 @@ FileStream* APS5_VABI fopen_nid_postfix(const char* filename, const char* mode) throw std::runtime_error(std::string(__func__) + ": " + FOPEN_MSG_OPEN_FAILED + ": \"" + abs_path + "\": " + reason); } // APS5_LOG_OUT("success: \"%s\"", abs_path.c_str()); + if (parsed->append) static_cast(std::fseek(handle.get(), 0, SEEK_END)); if (parsed->writes) RecordWrittenPath_nid_no_patch(fpath); auto stream = std::make_unique(handle.get(), true); handle.release(); diff --git a/core/libs/tests/GuestStandardStreams.cpp b/core/libs/tests/GuestStandardStreams.cpp index 67a4a57b3..b970dccaf 100644 --- a/core/libs/tests/GuestStandardStreams.cpp +++ b/core/libs/tests/GuestStandardStreams.cpp @@ -295,6 +295,12 @@ static bool CheckBinaryModes() { FileStream* stream = reopen ? freopen_nid_postfix(filename.c_str(), mode, &redirected) : fopen_nid_postfix(filename.c_str(), mode); Require(stream != nullptr); const bool update = std::strchr(mode, '+') != nullptr; + if (*mode == 'a') { + const bool atEnd = ftello_nid_postfix(stream) == static_cast(original.size()) && + (!update || fgetc_nid_postfix(stream) == EOF); + if (!atEnd) std::fprintf(stderr, "%s %s: the append stream does not start at the end of the file\n", reopen ? "freopen" : "fopen", mode); + correct &= atEnd; + } if (*mode == 'r' || (*mode == 'a' && update)) { Require(fseeko_nid_postfix(stream, 0, SEEK_SET) == 0); char bytes[16]{};