Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Dec 2020 09:02:10 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r368692 - in head: include/xlocale lib/libc/include lib/libc/nls lib/libc/string
Message-ID:  <202012160902.0BG92A19072702@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 wes@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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202012160902.0BG92A19072702>