[glib] More g_strerror() fixes



commit 19eb511ba4f4914c1914472132d3601069bef906
Author: Dan Winship <danw gnome org>
Date:   Wed Sep 9 11:16:30 2015 -0400

    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

 configure.ac          |    2 +-
 glib/gstrfuncs.c      |   27 +++++++++++++++------------
 glib/tests/strfuncs.c |   11 +++++++++++
 3 files changed, 27 insertions(+), 13 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 5cda0a7..ffca7a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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>
diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index 2f0cda1..7d6e8ef 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -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))
     {
diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
index ad14a3c..cbf5be7 100644
--- a/glib/tests/strfuncs.c
+++ b/glib/tests/strfuncs.c
@@ -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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]