Changeset: 51f505078dfd for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/51f505078dfd Modified Files: cmake/monetdb-defines.cmake common/stream/stream.c gdk/gdk_posix.c gdk/gdk_posix.h monetdb_config.h.in Branch: Aug2024 Log Message:
Try to properly distinguish between two forms of strerror_r. But use strerror_s if available. diffs (131 lines): diff --git a/cmake/monetdb-defines.cmake b/cmake/monetdb-defines.cmake --- a/cmake/monetdb-defines.cmake +++ b/cmake/monetdb-defines.cmake @@ -84,6 +84,7 @@ function(monetdb_configure_defines) check_function_exists("getuid" HAVE_GETUID) check_symbol_exists("gmtime_r" "time.h" HAVE_GMTIME_R) check_symbol_exists("localtime_r" "time.h" HAVE_LOCALTIME_R) + check_symbol_exists("strerror_s" "string.h" HAVE_STRERROR_S) check_symbol_exists("strerror_r" "string.h" HAVE_STRERROR_R) check_function_exists("lockf" HAVE_LOCKF) check_symbol_exists("madvise" "sys/mman.h" HAVE_MADVISE) diff --git a/common/stream/stream.c b/common/stream/stream.c --- a/common/stream/stream.c +++ b/common/stream/stream.c @@ -426,24 +426,32 @@ mnstr_set_open_error(const char *name, i static size_t my_strerror_r(int error_nr, char *buf, size_t buflen) { - // Three cases: - // 1. no strerror_r + // Four cases: + // 1. strerror_s // 2. gnu strerror_r (returns char* and does not always fill buffer) // 3. xsi strerror_r (returns int and always fills the buffer) + // 4. no strerror_r and no strerror_s char *to_move; -#ifndef HAVE_STRERROR_R - // Hope for the best - to_move = strerror(error_nr); -#elif !defined(_GNU_SOURCE) || !_GNU_SOURCE - // standard strerror_r always writes to buf +#ifdef HAVE_STRERROR_S + int result_code = strerror_s(buf, buflen, error_nr); + if (result_code == 0) + to_move = NULL; + else + to_move = "<failed to retrieve error message>"; +#elif defined(HAVE_STRERROR_R) +#ifdef STRERROR_R_CHARP + // gnu strerror_r sometimes only returns static string, needs copy + to_move = strerror_r(error_nr, buf, buflen); +#else int result_code = strerror_r(error_nr, buf, buflen); if (result_code == 0) to_move = NULL; else to_move = "<failed to retrieve error message>"; +#endif #else - // gnu strerror_r sometimes only returns static string, needs copy - to_move = strerror_r(error_nr, buf, buflen); + // Hope for the best + to_move = strerror(error_nr); #endif if (to_move != NULL) { // move to buffer diff --git a/gdk/gdk_posix.c b/gdk/gdk_posix.c --- a/gdk/gdk_posix.c +++ b/gdk/gdk_posix.c @@ -1013,7 +1013,7 @@ ctime_r(const time_t *restrict t, char * } #endif -#ifndef HAVE_STRERROR_R +#if !defined(HAVE_STRERROR_R) && !defined(HAVE_STRERROR_S) static MT_Lock strerrlock = MT_LOCK_INITIALIZER(strerrlock); int diff --git a/gdk/gdk_posix.h b/gdk/gdk_posix.h --- a/gdk/gdk_posix.h +++ b/gdk/gdk_posix.h @@ -175,20 +175,25 @@ gdk_export char *asctime_r(const struct #ifndef HAVE_CTIME_R gdk_export char *ctime_r(const time_t *restrict, char *restrict); #endif -#ifndef HAVE_STRERROR_R +#if !defined(HAVE_STRERROR_R) && !defined(HAVE_STRERROR_S) gdk_export int strerror_r(int errnum, char *buf, size_t buflen); #endif static inline const char * GDKstrerror(int errnum, char *buf, size_t buflen) { -#if !defined(_GNU_SOURCE) || ((_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE) +#ifdef HAVE_STRERROR_S + if (strerror_s(buf, buflen, errnum) == 0) + return buf; + snprintf(buf, buflen, "Unknown error %d", errnum); + return buf; +#elif defined(STRERROR_R_CHARP) + return strerror_r(errnum, buf, buflen); +#else if (strerror_r(errnum, buf, buflen) == 0) return buf; snprintf(buf, buflen, "Unknown error %d", errnum); return buf; -#else - return strerror_r(errnum, buf, buflen); #endif } diff --git a/monetdb_config.h.in b/monetdb_config.h.in --- a/monetdb_config.h.in +++ b/monetdb_config.h.in @@ -138,6 +138,7 @@ #cmakedefine HAVE_GETUID 1 #cmakedefine HAVE_GMTIME_R 1 #cmakedefine HAVE_LOCALTIME_R 1 +#cmakedefine HAVE_STRERROR_S 1 #cmakedefine HAVE_STRERROR_R 1 #cmakedefine HAVE_LOCKF 1 #cmakedefine HAVE_MADVISE 1 @@ -367,6 +368,18 @@ typedef __uint128_t uhge; #include <strings.h> /* strcasecmp */ #endif +/* The GNU C library has two variants of strerror_r, the XSI compliant + * one which returns int and a GNU specific one which returns char *. + * According to the manual, we should check for _GNU_SOURCE to find out + * which is used (if defined, it's the char * version), but MUSL C (used + * on Alpine Linux) also defined _GNU_SOURCE but only defines the int + * version, so that won't fly. Instead we look at __USE_GNU which only + * the GNU library defines (if _GNU_SOURCE is defined) and is the one + * actually used in the GNU header file to make the distinction. */ +#if defined(__USE_GNU) && defined(HAVE_STRERROR_R) +#define STRERROR_R_CHARP 1 +#endif + #ifdef _MSC_VER #define strdup(s) _strdup(s) _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org