diff options
author | Max Kellermann <max@musicpd.org> | 2016-12-04 19:50:21 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2016-12-04 20:07:11 +0100 |
commit | c6e1ca1c22ff236544f97aa982d4cbd2dce64456 (patch) | |
tree | 3a7bfb164979d9d52f58ec4f3c4d8b4160622146 /src/system | |
parent | 30dc473697ac6ca7f89c9bd0ad831622fc87b224 (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.hxx | 30 |
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 } |