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
This commit is contained in:
parent
30dc473697
commit
c6e1ca1c22
@ -21,8 +21,7 @@
|
|||||||
#include "FlacIOHandle.hxx"
|
#include "FlacIOHandle.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
#include "system/Error.hxx"
|
||||||
#include <system_error>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -49,7 +48,7 @@ FlacIORead(void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle)
|
|||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
} catch (const std::system_error &e) {
|
} catch (const std::system_error &e) {
|
||||||
errno = e.code().category() == std::system_category()
|
errno = e.code().category() == ErrnoCategory()
|
||||||
? e.code().value()
|
? e.code().value()
|
||||||
/* just some random non-zero errno
|
/* just some random non-zero errno
|
||||||
value */
|
value */
|
||||||
|
@ -95,10 +95,32 @@ FormatLastError(const char *fmt, Args&&... args)
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.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
|
static inline std::system_error
|
||||||
MakeErrno(int code, const char *msg)
|
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);
|
msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +155,7 @@ IsFileNotFound(const std::system_error &e)
|
|||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == std::system_category() &&
|
||||||
e.code().value() == ERROR_FILE_NOT_FOUND;
|
e.code().value() == ERROR_FILE_NOT_FOUND;
|
||||||
#else
|
#else
|
||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == ErrnoCategory() &&
|
||||||
e.code().value() == ENOENT;
|
e.code().value() == ENOENT;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -146,7 +168,7 @@ IsPathNotFound(const std::system_error &e)
|
|||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == std::system_category() &&
|
||||||
e.code().value() == ERROR_PATH_NOT_FOUND;
|
e.code().value() == ERROR_PATH_NOT_FOUND;
|
||||||
#else
|
#else
|
||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == ErrnoCategory() &&
|
||||||
e.code().value() == ENOTDIR;
|
e.code().value() == ENOTDIR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -159,7 +181,7 @@ IsAccessDenied(const std::system_error &e)
|
|||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == std::system_category() &&
|
||||||
e.code().value() == ERROR_ACCESS_DENIED;
|
e.code().value() == ERROR_ACCESS_DENIED;
|
||||||
#else
|
#else
|
||||||
return e.code().category() == std::system_category() &&
|
return e.code().category() == ErrnoCategory() &&
|
||||||
e.code().value() == EACCES;
|
e.code().value() == EACCES;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user