From 9895acb9809cab5812277464a3c94a821d3c3af8 Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Sat, 23 Sep 2017 04:31:42 +0200 Subject: Transparently handle GNU/XSI strerror_r. Closes #36. --- c-api/compat-5.3.c | 65 +++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 45 deletions(-) diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index e87808c..eb62009 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -24,38 +24,15 @@ #endif /* No-lock fopen_s usage if possible */ #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK -#include +# include #endif /* VC++ _fsopen for share-allowed file read */ #ifndef COMPAT53_HAVE_STRERROR_R # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \ (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) # define COMPAT53_HAVE_STRERROR_R 1 -# if ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ - (defined(_XOPEN_SOURCE) || _XOPEN_SOURCE >= 600)) && \ - (!defined(_GNU_SOURCE) || !_GNU_SOURCE) -# ifndef COMPAT53_HAVE_STRERROR_R_XSI -# define COMPAT53_HAVE_STRERROR_R_XSI 1 -# endif /* XSI-Compliant strerror_r */ -# ifndef COMPAT53_HAVE_STRERROR_R_GNU -# define COMPAT53_HAVE_STRERROR_R_GNU 0 -# endif /* GNU strerror_r */ -# else /* XSI/Posix vs. GNU strerror_r */ -# ifndef COMPAT53_HAVE_STRERROR_R_GNU -# define COMPAT53_HAVE_STRERROR_R_GNU 1 -# endif /* GNU variant strerror_r */ -# ifndef COMPAT53_HAVE_STRERROR_R_XSI -# define COMPAT53_HAVE_STRERROR_R_XSI 0 -# endif /* XSI strerror_r */ -# endif /* XSI/Posix vs. GNU strerror_r */ # else /* none of the defines matched: define to 0 */ # define COMPAT53_HAVE_STRERROR_R 0 -# ifndef COMPAT53_HAVE_STRERROR_R_XSI -# define COMPAT53_HAVE_STRERROR_R_XSI 0 -# endif /* XSI strerror_r */ -# ifndef COMPAT53_HAVE_STRERROR_R_GNU -# define COMPAT53_HAVE_STRERROR_R_GNU 0 -# endif /* GNU strerror_r */ # endif /* have strerror_r of some form */ #endif /* strerror_r */ @@ -69,34 +46,34 @@ #endif /* strerror_s */ #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE -#define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 +# define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 #endif /* Lua File Buffer Size */ static char* compat53_strerror (int en, char* buff, size_t sz) { #if COMPAT53_HAVE_STRERROR_R /* use strerror_r here, because it's available on these specific platforms */ -#if COMPAT53_HAVE_STRERROR_R_XSI - /* XSI Compliant */ + if (sz > 0) + buff[0] = '\0'; + /* we don't care whether the GNU version or the XSI version is used: */ strerror_r(en, buff, sz); - return buff; -#else - /* GNU-specific which returns const char* */ - return strerror_r(en, buff, sz); -#endif + if (sz == 0 || buff[0] != '\0') + return buff; /* strerror_r wrote into the buffer */ + else + /* buffer is unchanged, so we probably have called GNU strerror_r which + * returned a static constant string. Chances are that strerror will + * return the same static constant string and therefore be thread-safe. */ + return strerror(en); #elif COMPAT53_HAVE_STRERROR_S - /* for MSVC and other C11 implementations, use strerror_s - * since it's provided by default by the libraries - */ + /* for MSVC and other C11 implementations, use strerror_s since it's + * provided by default by the libraries */ strerror_s(buff, sz, en); return buff; #else - /* fallback, but - * strerror is not guaranteed to be threadsafe due to modifying - * errno itself and some impls not locking a static buffer for it - * ... but most known systems have threadsafe errno: this might only change - * if the locale is changed out from under someone while this function is being called - */ + /* fallback, but strerror is not guaranteed to be threadsafe due to modifying + * errno itself and some impls not locking a static buffer for it ... but most + * known systems have threadsafe errno: this might only change if the locale + * is changed out from under someone while this function is being called */ (void)buff; (void)sz; return strerror(en); @@ -579,12 +556,10 @@ COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char * dictate this to the user. A quick check shows that fopen_s this * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, * possibly even before that so we don't need to do any version - * number checks, since this has been there since forever. - */ + * number checks, since this has been there since forever. */ /* TO USER: if you want the behavior of typical fopen_s/fopen, - * which does lock the file on VC++, define the macro used below to 0 - */ + * which does lock the file on VC++, define the macro used below to 0 */ #if COMPAT53_FOPEN_NO_LOCK lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ if (lf.f == NULL) -- cgit v1.2.3-55-g6feb From b7829017581164c3e5dda24e3b187c0833b37dbf Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Sat, 23 Sep 2017 10:58:47 +0200 Subject: Do less stuff when sz is 0 in compat53_strerror(). --- c-api/compat-5.3.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index eb62009..9b304c1 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -53,17 +53,17 @@ static char* compat53_strerror (int en, char* buff, size_t sz) { #if COMPAT53_HAVE_STRERROR_R /* use strerror_r here, because it's available on these specific platforms */ - if (sz > 0) + if (sz > 0) { buff[0] = '\0'; - /* we don't care whether the GNU version or the XSI version is used: */ - strerror_r(en, buff, sz); - if (sz == 0 || buff[0] != '\0') - return buff; /* strerror_r wrote into the buffer */ - else - /* buffer is unchanged, so we probably have called GNU strerror_r which - * returned a static constant string. Chances are that strerror will - * return the same static constant string and therefore be thread-safe. */ - return strerror(en); + /* we don't care whether the GNU version or the XSI version is used: */ + strerror_r(en, buff, sz); + if (buff[0] == '\0') + /* buffer is unchanged, so we probably have called GNU strerror_r which + * returned a static constant string. Chances are that strerror will + * return the same static constant string and therefore be thread-safe. */ + return strerror(en); + } + return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ #elif COMPAT53_HAVE_STRERROR_S /* for MSVC and other C11 implementations, use strerror_s since it's * provided by default by the libraries */ -- cgit v1.2.3-55-g6feb From 447decaaf902ad9c461a6df2bbe702481f3d7786 Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Sun, 24 Sep 2017 14:36:58 +0200 Subject: Add braces and suppress warning. --- c-api/compat-5.3.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index 9b304c1..09c60dd 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -56,12 +56,16 @@ static char* compat53_strerror (int en, char* buff, size_t sz) { if (sz > 0) { buff[0] = '\0'; /* we don't care whether the GNU version or the XSI version is used: */ - strerror_r(en, buff, sz); - if (buff[0] == '\0') - /* buffer is unchanged, so we probably have called GNU strerror_r which + if (strerror_r(en, buff, sz)) { + /* Yes, we really DO want to ignore the return value! + * GCC makes that extra hard, not even a (void) cast will do. */ + } + if (buff[0] == '\0') { + /* Buffer is unchanged, so we probably have called GNU strerror_r which * returned a static constant string. Chances are that strerror will * return the same static constant string and therefore be thread-safe. */ return strerror(en); + } } return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ #elif COMPAT53_HAVE_STRERROR_S -- cgit v1.2.3-55-g6feb