Author: kib
Date: Wed Dec 16 09:02:09 2020
New Revision: 368692
URL: https://svnweb.freebsd.org/changeset/base/368692

Log:
  Implement strerror_l().
  
  Only for the arches that provide user-mode TLS.
  
  PR: 251651
  Requested by: yuri
  Discussed with:       emaste, jilles, tijl
  Sponsored by: The FreeBSD Foundation
  Differential revision:        https://reviews.freebsd.org/D27495
  MFC after:    2 weeks

Modified:
  head/include/xlocale/_string.h
  head/lib/libc/include/libc_private.h
  head/lib/libc/nls/msgcat.c
  head/lib/libc/string/Makefile.inc
  head/lib/libc/string/Symbol.map
  head/lib/libc/string/strerror.3
  head/lib/libc/string/strerror.c

Modified: head/include/xlocale/_string.h
==============================================================================
--- head/include/xlocale/_string.h      Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/include/xlocale/_string.h      Wed Dec 16 09:02:09 2020        
(r368692)
@@ -46,6 +46,7 @@ typedef struct        _xlocale *locale_t;
  * POSIX2008 functions
  */
 int     strcoll_l(const char *, const char *, locale_t);
+char   *strerror_l(int num, locale_t);
 size_t  strxfrm_l(char *, const char *, size_t, locale_t);
 #endif /* _XLOCALE_STRING1_H */
 

Modified: head/lib/libc/include/libc_private.h
==============================================================================
--- head/lib/libc/include/libc_private.h        Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/lib/libc/include/libc_private.h        Wed Dec 16 09:02:09 2020        
(r368692)
@@ -431,4 +431,9 @@ void        ___pthread_cleanup_pop_imp(int);
 
 void __throw_constraint_handler_s(const char * restrict msg, int error);
 
+struct __nl_cat_d;
+struct _xlocale;
+struct __nl_cat_d *__catopen_l(const char *name, int type,
+           struct _xlocale *locale);
+
 #endif /* _LIBC_PRIVATE_H_ */

Modified: head/lib/libc/nls/msgcat.c
==============================================================================
--- head/lib/libc/nls/msgcat.c  Wed Dec 16 08:43:38 2020        (r368691)
+++ head/lib/libc/nls/msgcat.c  Wed Dec 16 09:02:09 2020        (r368692)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include "un-namespace.h"
 
 #include "../locale/xlocale_private.h"
+#include "libc_private.h"
 
 #define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:"     
\
                                _PATH_LOCALBASE "/share/nls/%L/%N.cat:"         
\
@@ -122,6 +123,12 @@ SLIST_HEAD(listhead, catentry) cache =
 nl_catd
 catopen(const char *name, int type)
 {
+       return (__catopen_l(name, type, __get_locale()));
+}
+
+nl_catd
+__catopen_l(const char *name, int type, locale_t locale)
+{
        struct stat sbuf;
        struct catentry *np;
        char *base, *cptr, *cptr1, *nlspath, *pathP, *pcode;
@@ -139,7 +146,7 @@ catopen(const char *name, int type)
                lang = NULL;
        else {
                if (type == NL_CAT_LOCALE)
-                       lang = querylocale(LC_MESSAGES_MASK, __get_locale());
+                       lang = querylocale(LC_MESSAGES_MASK, locale);
                else
                        lang = getenv("LANG");
 

Modified: head/lib/libc/string/Makefile.inc
==============================================================================
--- head/lib/libc/string/Makefile.inc   Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/lib/libc/string/Makefile.inc   Wed Dec 16 09:02:09 2020        
(r368692)
@@ -64,6 +64,7 @@ MLINKS+=strcpy.3 stpcpy.3 \
        strcpy.3 strncpy.3
 MLINKS+=strdup.3 strndup.3
 MLINKS+=strerror.3 perror.3 \
+       strerror.3 strerror_l.3 \
        strerror.3 strerror_r.3 \
        strerror.3 sys_errlist.3 \
        strerror.3 sys_nerr.3

Modified: head/lib/libc/string/Symbol.map
==============================================================================
--- head/lib/libc/string/Symbol.map     Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/lib/libc/string/Symbol.map     Wed Dec 16 09:02:09 2020        
(r368692)
@@ -110,6 +110,10 @@ FBSD_1.5 {
        timingsafe_memcmp;
 };
 
+FBSD_1.6 {
+       strerror_l;
+};
+
 FBSDprivate_1.0 {
        __strtok_r;
 };

Modified: head/lib/libc/string/strerror.3
==============================================================================
--- head/lib/libc/string/strerror.3     Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/lib/libc/string/strerror.3     Wed Dec 16 09:02:09 2020        
(r368692)
@@ -32,12 +32,13 @@
 .\"     @(#)strerror.3 8.1 (Berkeley) 6/9/93
 .\" $FreeBSD$
 .\"
-.Dd April 5, 2011
+.Dd December 7, 2020
 .Dt STRERROR 3
 .Os
 .Sh NAME
 .Nm perror ,
 .Nm strerror ,
+.Nm strerror_l ,
 .Nm strerror_r ,
 .Nm sys_errlist ,
 .Nm sys_nerr
@@ -53,12 +54,15 @@
 .In string.h
 .Ft "char *"
 .Fn strerror "int errnum"
+.Ft "char *"
+.Fn strerror_l "int errnum" "locale_t"
 .Ft int
 .Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
 .Sh DESCRIPTION
 The
 .Fn strerror ,
-.Fn strerror_r
+.Fn strerror_l ,
+.Fn strerror_r ,
 and
 .Fn perror
 functions look up the error message string corresponding to an
@@ -68,10 +72,30 @@ The
 .Fn strerror
 function accepts an error number argument
 .Fa errnum
-and returns a pointer to the corresponding
-message string.
+and returns a pointer to the corresponding message string
+in the current locale.
+.Fn strerror
+is not thread-safe.
+It returns a pointer to an internal static buffer that could be
+overwritten by a
+.Fn strerror
+call from another thread.
 .Pp
 The
+.Fn strerror_l
+function accepts
+.Fa errnum
+error number and
+.Fa locale
+locale handle arguments and returns a pointer to a string
+corresponding to the specified error in the given locale.
+.Fn strerror_l
+is thread-safe, its result can be only overwritten by
+another call to
+.Fn strerror_l
+from the current thread.
+.Pp
+The
 .Fn strerror_r
 function renders the same result into
 .Fa strerrbuf
@@ -141,7 +165,8 @@ The external value
 contains a count of the messages in
 .Va sys_errlist .
 The use of these variables is deprecated;
-.Fn strerror
+.Fn strerror ,
+.Fn strerror_l ,
 or
 .Fn strerror_r
 should be used instead.
@@ -160,6 +185,10 @@ The
 .Fn strerror_r
 function conforms to
 .St -p1003.1-2001 .
+The
+.Fn strerror_l
+function conforms to
+.St -p1003.1-2008 .
 .Sh HISTORY
 The
 .Fn strerror
@@ -173,18 +202,21 @@ function was implemented in
 .Fx 4.4
 by
 .An Wes Peters Aq Mt w...@freebsd.org .
+The
+.Fn strerror_l
+function was added in
+.Fx 13.0 .
 .Sh BUGS
 The
 .Fn strerror
 function returns its result in a static buffer which
 will be overwritten by subsequent calls.
 .Pp
-The return type for
-.Fn strerror
-is missing a type-qualifier; it should actually be
-.Vt const char * .
-.Pp
 Programs that use the deprecated
 .Va sys_errlist
 variable often fail to compile because they declare it
 inconsistently.
+Size of the
+.Va sys_errlist
+object might increase during FreeBSD lifetime,
+breaking some ABI stability guarantees.

Modified: head/lib/libc/string/strerror.c
==============================================================================
--- head/lib/libc/string/strerror.c     Wed Dec 16 08:43:38 2020        
(r368691)
+++ head/lib/libc/string/strerror.c     Wed Dec 16 09:02:09 2020        
(r368692)
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
 #include <stdio.h>
 
 #include "errlst.h"
+#include "../locale/xlocale_private.h"
+#include "libc_private.h"
 
 /*
  * Define buffer big enough to contain delimiter (": ", 2 bytes),
@@ -78,34 +80,35 @@ errstr(int num, const char *uprefix, char *buf, size_t
        strlcat(buf, t, len);
 }
 
-int
-strerror_r(int errnum, char *strerrbuf, size_t buflen)
+static int
+strerror_rl(int errnum, char *strerrbuf, size_t buflen, locale_t locale)
 {
        int retval = 0;
 #if defined(NLS)
        int saved_errno = errno;
        nl_catd catd;
-       catd = catopen("libc", NL_CAT_LOCALE);
+
+       catd = __catopen_l("libc", NL_CAT_LOCALE, locale);
 #endif
 
        if (errnum < 0 || errnum >= __hidden_sys_nerr) {
                errstr(errnum,
 #if defined(NLS)
-                       catgets(catd, 1, 0xffff, __uprefix),
+                   catgets(catd, 1, 0xffff, __uprefix),
 #else
-                       __uprefix,
+                   __uprefix,
 #endif
-                       strerrbuf, buflen);
+                  strerrbuf, buflen);
                retval = EINVAL;
        } else {
                if (strlcpy(strerrbuf,
 #if defined(NLS)
-                       catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]),
+                   catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]),
 #else
-                       __hidden_sys_errlist[errnum],
+                   __hidden_sys_errlist[errnum],
 #endif
-                       buflen) >= buflen)
-               retval = ERANGE;
+                   buflen) >= buflen)
+                       retval = ERANGE;
        }
 
 #if defined(NLS)
@@ -116,12 +119,33 @@ strerror_r(int errnum, char *strerrbuf, size_t buflen)
        return (retval);
 }
 
+int
+strerror_r(int errnum, char *strerrbuf, size_t buflen)
+{
+       return (strerror_rl(errnum, strerrbuf, buflen, __get_locale()));
+}
+
 char *
+strerror_l(int num, locale_t locale)
+{
+#ifndef __NO_TLS
+       static _Thread_local char ebuf[NL_TEXTMAX];
+
+       if (strerror_rl(num, ebuf, sizeof(ebuf), locale) != 0)
+               errno = EINVAL;
+       return (ebuf);
+#else
+       errno = ENOTSUP;
+       return (NULL);
+#endif
+}
+
+char *
 strerror(int num)
 {
        static char ebuf[NL_TEXTMAX];
 
-       if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
+       if (strerror_rl(num, ebuf, sizeof(ebuf), __get_locale()) != 0)
                errno = EINVAL;
        return (ebuf);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to