summaryrefslogtreecommitdiff
path: root/src/system
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2016-12-04 19:50:21 +0100
committerMax Kellermann <max@musicpd.org>2016-12-04 20:07:11 +0100
commitc6e1ca1c22ff236544f97aa982d4cbd2dce64456 (patch)
tree3a7bfb164979d9d52f58ec4f3c4d8b4160622146 /src/system
parent30dc473697ac6ca7f89c9bd0ad831622fc87b224 (diff)
system/Error: use std::generic_category() for errno on Windows
It's wrong to use std::system_category() for both GetLastError() and errno on Windows. Apparently, everybody uses std::generic_category() for errno values, which appears to be a safe choice. Some discussion on this confusing topic can be found here: https://stackoverflow.com/questions/28746372/system-error-categories-and-standard-system-error-codes
Diffstat (limited to 'src/system')
-rw-r--r--src/system/Error.hxx30
1 files changed, 26 insertions, 4 deletions
diff --git a/src/system/Error.hxx b/src/system/Error.hxx
index 0d42bd726..faacbe358 100644
--- a/src/system/Error.hxx
+++ b/src/system/Error.hxx
@@ -95,10 +95,32 @@ FormatLastError(const char *fmt, Args&&... args)
#include <errno.h>
#include <string.h>
+/**
+ * Returns the error_category to be used to wrap errno values. The
+ * C++ standard does not define this well, so this code is based on
+ * observations what C++ standard library implementations actually
+ * use.
+ *
+ * @see https://stackoverflow.com/questions/28746372/system-error-categories-and-standard-system-error-codes
+ */
+static inline const std::error_category &
+ErrnoCategory()
+{
+#ifdef WIN32
+ /* on Windows, the generic_category() is used for errno
+ values */
+ return std::generic_category();
+#else
+ /* on POSIX, system_category() appears to be the best
+ choice */
+ return std::system_category();
+#endif
+}
+
static inline std::system_error
MakeErrno(int code, const char *msg)
{
- return std::system_error(std::error_code(code, std::system_category()),
+ return std::system_error(std::error_code(code, ErrnoCategory()),
msg);
}
@@ -133,7 +155,7 @@ IsFileNotFound(const std::system_error &e)
return e.code().category() == std::system_category() &&
e.code().value() == ERROR_FILE_NOT_FOUND;
#else
- return e.code().category() == std::system_category() &&
+ return e.code().category() == ErrnoCategory() &&
e.code().value() == ENOENT;
#endif
}
@@ -146,7 +168,7 @@ IsPathNotFound(const std::system_error &e)
return e.code().category() == std::system_category() &&
e.code().value() == ERROR_PATH_NOT_FOUND;
#else
- return e.code().category() == std::system_category() &&
+ return e.code().category() == ErrnoCategory() &&
e.code().value() == ENOTDIR;
#endif
}
@@ -159,7 +181,7 @@ IsAccessDenied(const std::system_error &e)
return e.code().category() == std::system_category() &&
e.code().value() == ERROR_ACCESS_DENIED;
#else
- return e.code().category() == std::system_category() &&
+ return e.code().category() == ErrnoCategory() &&
e.code().value() == EACCES;
#endif
}