summaryrefslogtreecommitdiff
path: root/Source/Core/Common/CommonFuncs.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2017-12-16 13:08:50 +0100
committerJosJuice <josjuice@gmail.com>2017-12-18 22:09:02 +0100
commitbd5da5cfd60d2d2321579800ed62471a4a663e88 (patch)
tree8e04fe4a43badfb244829bf6ab587e9d8349a924 /Source/Core/Common/CommonFuncs.cpp
parentba01642dc78a44126b334d7ff4d3ceae5fec7902 (diff)
Handle both the XSI and GNU versions of strerror_r
Trying to force the XSI version by undefining _GNU_SOURCE can lead to compilation errors on some systems because of headers expecting that _GNU_SOURCE is defined. This commit uses define checks to detect which version we have. I tried making an overloaded function (int and const char*) instead, but that led to a warning about one of the variants being unused.
Diffstat (limited to 'Source/Core/Common/CommonFuncs.cpp')
-rw-r--r--Source/Core/Common/CommonFuncs.cpp36
1 files changed, 16 insertions, 20 deletions
diff --git a/Source/Core/Common/CommonFuncs.cpp b/Source/Core/Common/CommonFuncs.cpp
index ef370672d2..86b9c93e40 100644
--- a/Source/Core/Common/CommonFuncs.cpp
+++ b/Source/Core/Common/CommonFuncs.cpp
@@ -2,21 +2,10 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-// The code in GetErrorMessage can't handle some systems having the
-// GNU version of strerror_r and other systems having the XSI version,
-// so we undefine _GNU_SOURCE here in an attempt to always get the XSI version.
-// We include cstring before all other headers in case cstring is included
-// indirectly (without undefining _GNU_SOURCE) by some other header.
-#ifdef _GNU_SOURCE
-#undef _GNU_SOURCE
-#include <cstring>
-#define _GNU_SOURCE
-#else
-#include <cstring>
-#endif
-
#include <cstddef>
+#include <cstring>
#include <errno.h>
+#include <type_traits>
#include "Common/CommonFuncs.h"
@@ -33,13 +22,20 @@ std::string LastStrerrorString()
{
char error_message[BUFFER_SIZE];
- // We assume that the XSI-compliant version of strerror_r (returns int) is used
- // rather than the GNU version (returns char*). The returned value is stored to
- // an int variable to get a compile-time check that the return type is not char*.
- const int result = strerror_r(errno, error_message, BUFFER_SIZE);
- if (result != 0)
- return "";
- return std::string(error_message);
+// There are two variants of strerror_r. The XSI version stores the message to the passed-in
+// buffer and returns an int (0 on success). The GNU version returns a pointer to the message,
+// which might have been stored in the passed-in buffer or might be a static string.
+
+// We check defines in order to figure out variant is in use, and we store the returned value
+// to a variable so that we'll get a compile-time check that our assumption was correct.
+
+#if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
+ const char* str = strerror_r(errno, error_message, BUFFER_SIZE);
+ return std::string(str);
+#else
+ int error_code = strerror_r(errno, error_message, BUFFER_SIZE);
+ return error_code == 0 ? std::string(error_message) : "";
+#endif
}
#ifdef _WIN32