mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=368692
|
@ -46,6 +46,7 @@ typedef struct _xlocale *locale_t;
|
||||||
* POSIX2008 functions
|
* POSIX2008 functions
|
||||||
*/
|
*/
|
||||||
int strcoll_l(const char *, const char *, locale_t);
|
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);
|
size_t strxfrm_l(char *, const char *, size_t, locale_t);
|
||||||
#endif /* _XLOCALE_STRING1_H */
|
#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);
|
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_ */
|
#endif /* _LIBC_PRIVATE_H_ */
|
||||||
|
|
|
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||||
#include "un-namespace.h"
|
#include "un-namespace.h"
|
||||||
|
|
||||||
#include "../locale/xlocale_private.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:" \
|
#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:" \
|
||||||
_PATH_LOCALBASE "/share/nls/%L/%N.cat:" \
|
_PATH_LOCALBASE "/share/nls/%L/%N.cat:" \
|
||||||
|
@ -121,6 +122,12 @@ SLIST_HEAD(listhead, catentry) cache =
|
||||||
|
|
||||||
nl_catd
|
nl_catd
|
||||||
catopen(const char *name, int type)
|
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 stat sbuf;
|
||||||
struct catentry *np;
|
struct catentry *np;
|
||||||
|
@ -139,7 +146,7 @@ catopen(const char *name, int type)
|
||||||
lang = NULL;
|
lang = NULL;
|
||||||
else {
|
else {
|
||||||
if (type == NL_CAT_LOCALE)
|
if (type == NL_CAT_LOCALE)
|
||||||
lang = querylocale(LC_MESSAGES_MASK, __get_locale());
|
lang = querylocale(LC_MESSAGES_MASK, locale);
|
||||||
else
|
else
|
||||||
lang = getenv("LANG");
|
lang = getenv("LANG");
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ MLINKS+=strcpy.3 stpcpy.3 \
|
||||||
strcpy.3 strncpy.3
|
strcpy.3 strncpy.3
|
||||||
MLINKS+=strdup.3 strndup.3
|
MLINKS+=strdup.3 strndup.3
|
||||||
MLINKS+=strerror.3 perror.3 \
|
MLINKS+=strerror.3 perror.3 \
|
||||||
|
strerror.3 strerror_l.3 \
|
||||||
strerror.3 strerror_r.3 \
|
strerror.3 strerror_r.3 \
|
||||||
strerror.3 sys_errlist.3 \
|
strerror.3 sys_errlist.3 \
|
||||||
strerror.3 sys_nerr.3
|
strerror.3 sys_nerr.3
|
||||||
|
|
|
@ -110,6 +110,10 @@ FBSD_1.5 {
|
||||||
timingsafe_memcmp;
|
timingsafe_memcmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FBSD_1.6 {
|
||||||
|
strerror_l;
|
||||||
|
};
|
||||||
|
|
||||||
FBSDprivate_1.0 {
|
FBSDprivate_1.0 {
|
||||||
__strtok_r;
|
__strtok_r;
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,12 +32,13 @@
|
||||||
.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
|
.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd April 5, 2011
|
.Dd December 7, 2020
|
||||||
.Dt STRERROR 3
|
.Dt STRERROR 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm perror ,
|
.Nm perror ,
|
||||||
.Nm strerror ,
|
.Nm strerror ,
|
||||||
|
.Nm strerror_l ,
|
||||||
.Nm strerror_r ,
|
.Nm strerror_r ,
|
||||||
.Nm sys_errlist ,
|
.Nm sys_errlist ,
|
||||||
.Nm sys_nerr
|
.Nm sys_nerr
|
||||||
|
@ -53,12 +54,15 @@
|
||||||
.In string.h
|
.In string.h
|
||||||
.Ft "char *"
|
.Ft "char *"
|
||||||
.Fn strerror "int errnum"
|
.Fn strerror "int errnum"
|
||||||
|
.Ft "char *"
|
||||||
|
.Fn strerror_l "int errnum" "locale_t"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
|
.Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Fn strerror ,
|
.Fn strerror ,
|
||||||
.Fn strerror_r
|
.Fn strerror_l ,
|
||||||
|
.Fn strerror_r ,
|
||||||
and
|
and
|
||||||
.Fn perror
|
.Fn perror
|
||||||
functions look up the error message string corresponding to an
|
functions look up the error message string corresponding to an
|
||||||
|
@ -68,8 +72,28 @@ The
|
||||||
.Fn strerror
|
.Fn strerror
|
||||||
function accepts an error number argument
|
function accepts an error number argument
|
||||||
.Fa errnum
|
.Fa errnum
|
||||||
and returns a pointer to the corresponding
|
and returns a pointer to the corresponding message string
|
||||||
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
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn strerror_r
|
.Fn strerror_r
|
||||||
|
@ -141,7 +165,8 @@ The external value
|
||||||
contains a count of the messages in
|
contains a count of the messages in
|
||||||
.Va sys_errlist .
|
.Va sys_errlist .
|
||||||
The use of these variables is deprecated;
|
The use of these variables is deprecated;
|
||||||
.Fn strerror
|
.Fn strerror ,
|
||||||
|
.Fn strerror_l ,
|
||||||
or
|
or
|
||||||
.Fn strerror_r
|
.Fn strerror_r
|
||||||
should be used instead.
|
should be used instead.
|
||||||
|
@ -160,6 +185,10 @@ The
|
||||||
.Fn strerror_r
|
.Fn strerror_r
|
||||||
function conforms to
|
function conforms to
|
||||||
.St -p1003.1-2001 .
|
.St -p1003.1-2001 .
|
||||||
|
The
|
||||||
|
.Fn strerror_l
|
||||||
|
function conforms to
|
||||||
|
.St -p1003.1-2008 .
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Fn strerror
|
.Fn strerror
|
||||||
|
@ -173,18 +202,21 @@ function was implemented in
|
||||||
.Fx 4.4
|
.Fx 4.4
|
||||||
by
|
by
|
||||||
.An Wes Peters Aq Mt wes@FreeBSD.org .
|
.An Wes Peters Aq Mt wes@FreeBSD.org .
|
||||||
|
The
|
||||||
|
.Fn strerror_l
|
||||||
|
function was added in
|
||||||
|
.Fx 13.0 .
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
The
|
The
|
||||||
.Fn strerror
|
.Fn strerror
|
||||||
function returns its result in a static buffer which
|
function returns its result in a static buffer which
|
||||||
will be overwritten by subsequent calls.
|
will be overwritten by subsequent calls.
|
||||||
.Pp
|
.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
|
Programs that use the deprecated
|
||||||
.Va sys_errlist
|
.Va sys_errlist
|
||||||
variable often fail to compile because they declare it
|
variable often fail to compile because they declare it
|
||||||
inconsistently.
|
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 <stdio.h>
|
||||||
|
|
||||||
#include "errlst.h"
|
#include "errlst.h"
|
||||||
|
#include "../locale/xlocale_private.h"
|
||||||
|
#include "libc_private.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define buffer big enough to contain delimiter (": ", 2 bytes),
|
* 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);
|
strlcat(buf, t, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
strerror_r(int errnum, char *strerrbuf, size_t buflen)
|
strerror_rl(int errnum, char *strerrbuf, size_t buflen, locale_t locale)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
#if defined(NLS)
|
#if defined(NLS)
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
nl_catd catd;
|
nl_catd catd;
|
||||||
catd = catopen("libc", NL_CAT_LOCALE);
|
|
||||||
|
catd = __catopen_l("libc", NL_CAT_LOCALE, locale);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (errnum < 0 || errnum >= __hidden_sys_nerr) {
|
if (errnum < 0 || errnum >= __hidden_sys_nerr) {
|
||||||
errstr(errnum,
|
errstr(errnum,
|
||||||
#if defined(NLS)
|
#if defined(NLS)
|
||||||
catgets(catd, 1, 0xffff, __uprefix),
|
catgets(catd, 1, 0xffff, __uprefix),
|
||||||
#else
|
#else
|
||||||
__uprefix,
|
__uprefix,
|
||||||
#endif
|
#endif
|
||||||
strerrbuf, buflen);
|
strerrbuf, buflen);
|
||||||
retval = EINVAL;
|
retval = EINVAL;
|
||||||
} else {
|
} else {
|
||||||
if (strlcpy(strerrbuf,
|
if (strlcpy(strerrbuf,
|
||||||
#if defined(NLS)
|
#if defined(NLS)
|
||||||
catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]),
|
catgets(catd, 1, errnum, __hidden_sys_errlist[errnum]),
|
||||||
#else
|
#else
|
||||||
__hidden_sys_errlist[errnum],
|
__hidden_sys_errlist[errnum],
|
||||||
#endif
|
#endif
|
||||||
buflen) >= buflen)
|
buflen) >= buflen)
|
||||||
retval = ERANGE;
|
retval = ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(NLS)
|
#if defined(NLS)
|
||||||
|
@ -116,12 +119,33 @@ strerror_r(int errnum, char *strerrbuf, size_t buflen)
|
||||||
return (retval);
|
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 *
|
char *
|
||||||
strerror(int num)
|
strerror(int num)
|
||||||
{
|
{
|
||||||
static char ebuf[NL_TEXTMAX];
|
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;
|
errno = EINVAL;
|
||||||
return (ebuf);
|
return (ebuf);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue