summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-12 01:47:41 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-12 01:47:41 +0100
commit3f6ba6056c5c63249022e52b3c6000e337856d1a (patch)
treecba43d1379aa917ac446d0cb6525bc860afcc4d0
parentff7828727b8967e10f020836a4876da294cb379a (diff)
call strerror before errno gets clobbered
-rw-r--r--serialize/json-helper.cpp19
-rw-r--r--serialize/world-reader.cpp28
-rw-r--r--serialize/world-writer.cpp18
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