diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-12 01:47:41 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-12 01:47:41 +0100 |
commit | 3f6ba6056c5c63249022e52b3c6000e337856d1a (patch) | |
tree | cba43d1379aa917ac446d0cb6525bc860afcc4d0 | |
parent | ff7828727b8967e10f020836a4876da294cb379a (diff) |
call strerror before errno gets clobbered
-rw-r--r-- | serialize/json-helper.cpp | 19 | ||||
-rw-r--r-- | serialize/world-reader.cpp | 28 | ||||
-rw-r--r-- | serialize/world-writer.cpp | 18 |
3 files changed, 52 insertions, 13 deletions
diff --git a/serialize/json-helper.cpp b/serialize/json-helper.cpp index 5504ff52..325d4d12 100644 --- a/serialize/json-helper.cpp +++ b/serialize/json-helper.cpp @@ -1,4 +1,6 @@ #include "json-helper.hpp" +#include <cerrno> +#include <cstring> #include <fstream> namespace floormat { @@ -7,8 +9,23 @@ template<typename T, std::ios_base::openmode mode> static T open_stream(StringView filename) { T s; - s.exceptions(s.exceptions() | std::ios::failbit | std::ios::badbit); s.open(filename.data(), mode); + if (!s.good()) + { + char errbuf[128]; + constexpr auto get_error_string = []<std::size_t N> (char (&buf)[N]) + { + buf[0] = '\0'; +#ifndef _WIN32 + (void)::strerror_r(errno, errbuf, std::size(errbuf)); +#else + (void)::strerror_s(buf, std::size(buf), errno); +#endif + }; + const char* mode_str = mode & std::ios_base::out ? "writing" : "reading"; + (void)get_error_string(errbuf); + fm_error("can't open file '%s' for %s: %s", filename.data(), mode_str, errbuf); + } return s; } diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp index 615aba0d..602eabf5 100644 --- a/serialize/world-reader.cpp +++ b/serialize/world-reader.cpp @@ -117,32 +117,46 @@ namespace floormat { world world::deserialize(StringView filename) { char errbuf[128]; - constexpr auto strerror = []<std::size_t N> (char (&buf)[N]) -> const char* { + constexpr auto get_error_string = []<std::size_t N> (char (&buf)[N]) { buf[0] = '\0'; #ifndef _WIN32 (void)::strerror_r(errno, buf, std::size(buf)); #else (void)::strerror_s(buf, std::size(buf), errno); #endif - return buf; }; fm_assert(filename.flags() & StringViewFlag::NullTerminated); FILE_raii f = ::fopen(filename.data(), "rb"); if (!f) - fm_abort("fopen(\"%s\", \"r\"): %s", filename.data(), strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fopen(\"%s\", \"r\"): %s", filename.data(), errbuf); + } if (int ret = ::fseek(f, 0, SEEK_END); ret != 0) - fm_abort("fseek(SEEK_END): %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fseek(SEEK_END): %s", errbuf); + } std::size_t len; if (auto len_ = ::ftell(f); len_ >= 0) len = (std::size_t)len_; else - fm_abort("ftell: %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("ftell: %s", errbuf); + } if (int ret = ::fseek(f, 0, SEEK_SET); ret != 0) - fm_abort("fseek(SEEK_SET): %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fseek(SEEK_SET): %s", errbuf); + } auto buf_ = std::make_unique<char[]>(len); if (auto ret = ::fread(&buf_[0], 1, len, f); ret != len) - fm_abort("fread short read: %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fread short read: %s", errbuf); + } world w; Serialize::reader_state s{w}; diff --git a/serialize/world-writer.cpp b/serialize/world-writer.cpp index 5e6c07fe..747610c1 100644 --- a/serialize/world-writer.cpp +++ b/serialize/world-writer.cpp @@ -252,27 +252,35 @@ void world::serialize(StringView filename) { collect(true); char errbuf[128]; - constexpr auto strerror = []<std::size_t N> (char (&buf)[N]) -> const char* { + constexpr auto get_error_string = []<std::size_t N> (char (&buf)[N]) { buf[0] = '\0'; #ifndef _WIN32 (void)::strerror_r(errno, buf, std::size(buf)); #else (void)::strerror_s(buf, std::size(buf), errno); #endif - return buf; }; fm_assert(filename.flags() & StringViewFlag::NullTerminated); if (Path::exists(filename)) Path::remove(filename); FILE_raii file = ::fopen(filename.data(), "wb"); if (!file) - fm_abort("fopen(\"%s\", \"w\"): %s", filename.data(), strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fopen(\"%s\", \"w\"): %s", filename.data(), errbuf); + } Serialize::writer_state s{*this}; const auto array = s.serialize_world(); if (auto len = ::fwrite(array.data(), array.size(), 1, file); len != 1) - fm_abort("fwrite: %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fwrite: %s", errbuf); + } if (int ret = ::fflush(file); ret != 0) - fm_abort("fflush: %s", strerror(errbuf)); + { + get_error_string(errbuf); + fm_abort("fflush: %s", errbuf); + } } } // namespace floormat |