More g_strerror() fixes

Add a check to configure.ac for strerror_r, since we don't currently
require POSIX.1-2001 conformance in general. Add back a
plain-strerror() case as a fallback, and rearrange the glibc-vs-POSIX
strerror_r() branches.

Update the docs to not claim that "not all platforms support the
strerror() function" (we require C90), but still mention the UTF-8 and
always-valid-string benefits. (And make test_strerror() check that
last part.)

https://bugzilla.gnome.org/show_bug.cgi?id=754788
This commit is contained in:
Dan Winship 2015-09-09 11:16:30 -04:00
parent ee6740aa78
commit 19eb511ba4
3 changed files with 27 additions and 13 deletions

View File

@ -525,7 +525,7 @@ AM_CONDITIONAL(OS_WIN32_AND_DLL_COMPILATION, [test x$glib_native_win32 = xyes -a
# Checks for library functions.
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(mmap posix_memalign memalign valloc fsync pipe2 issetugid)
AC_CHECK_FUNCS(timegm gmtime_r)
AC_CHECK_FUNCS(timegm gmtime_r strerror_r)
AC_CACHE_CHECK([for __libc_enable_secure], glib_cv_have_libc_enable_secure,
[AC_TRY_LINK([#include <unistd.h>

View File

@ -1238,13 +1238,15 @@ g_ascii_strtoll (const gchar *nptr,
* @errnum: the system error number. See the standard C %errno
* documentation
*
* Returns a string corresponding to the given error code, e.g.
* "no such process". You should use this function in preference to
* strerror(), because it returns a string in UTF-8 encoding, and since
* not all platforms support the strerror() function.
* Returns a string corresponding to the given error code, e.g. "no
* such process". Unlike strerror(), this always returns a string in
* UTF-8 encoding, and the pointer is guaranteed to remain valid for
* the lifetime of the process.
*
* Note that the string may be translated according to the current locale.
*
* The value of %errno will not be changed by this function.
*
* Returns: a UTF-8 string describing the error code. If the error code
* is unknown, it returns a string like "unknown error (<code>)".
*/
@ -1258,19 +1260,20 @@ g_strerror (gint errnum)
gint saved_errno = errno;
GError *error = NULL;
#ifdef G_OS_WIN32
#if defined(G_OS_WIN32)
strerror_s (buf, sizeof (buf), errnum);
msg = buf;
/* If we're using glibc, since we are building with _GNU_SOURCE, we
* expect to get the GNU variant of strerror_r. However, use the
* provided check from man strerror_r(3) in case we ever stop using
* _GNU_SOURCE (admittedly unlikely).
*/
#elif (defined __GLIBC__) && !((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)
#elif defined(HAVE_STRERROR_R)
/* Match the condition in strerror_r(3) for glibc */
# if defined(__GLIBC__) && !((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE)
msg = strerror_r (errnum, buf, sizeof (buf));
#else
# else
strerror_r (errnum, buf, sizeof (buf));
msg = buf;
# endif /* HAVE_STRERROR_R */
#else
g_strlcpy (buf, strerror (errnum), sizeof (buf));
msg = buf;
#endif
if (!g_get_charset (NULL))
{

View File

@ -1317,17 +1317,28 @@ test_strip_context (void)
static void
test_strerror (void)
{
GHashTable *strs;
gint i;
const gchar *str;
GHashTableIter iter;
setlocale (LC_ALL, "C");
strs = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 1; i < 200; i++)
{
str = g_strerror (i);
g_assert (str != NULL);
g_assert (g_utf8_validate (str, -1, NULL));
g_assert_false (g_hash_table_contains (strs, str));
g_hash_table_add (strs, (char *)str);
}
g_hash_table_iter_init (&iter, strs);
while (g_hash_table_iter_next (&iter, (gpointer *)&str, NULL))
g_assert (g_utf8_validate (str, -1, NULL));
g_hash_table_unref (strs);
}
static void