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
This commit is contained in:
parent
3ab53b27e3
commit
675079b1ea
@ -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 */
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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:" \
|
||||
@ -121,6 +122,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;
|
||||
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -110,6 +110,10 @@ FBSD_1.5 {
|
||||
timingsafe_memcmp;
|
||||
};
|
||||
|
||||
FBSD_1.6 {
|
||||
strerror_l;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
__strtok_r;
|
||||
};
|
||||
|
@ -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,8 +72,28 @@ 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
|
||||
@ -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.
|
||||
|
@ -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 len)
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user