Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/string/strerror.c
Show All 39 Lines | |||||
#endif | #endif | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <string.h> | #include <string.h> | ||||
#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), | ||||
* 64-bit signed integer converted to ASCII decimal (19 bytes) with | * 64-bit signed integer converted to ASCII decimal (19 bytes) with | ||||
* optional leading sign (1 byte), and a trailing NUL. | * optional leading sign (1 byte), and a trailing NUL. | ||||
*/ | */ | ||||
#define EBUFSIZE (2 + 19 + 1 + 1) | #define EBUFSIZE (2 + 19 + 1 + 1) | ||||
Show All 17 Lines | errstr(int num, const char *uprefix, char *buf, size_t len) | ||||
if (num < 0) | if (num < 0) | ||||
*--t = '-'; | *--t = '-'; | ||||
*--t = ' '; | *--t = ' '; | ||||
*--t = ':'; | *--t = ':'; | ||||
strlcpy(buf, uprefix, len); | strlcpy(buf, uprefix, 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) | ||||
catclose(catd); | catclose(catd); | ||||
errno = saved_errno; | errno = saved_errno; | ||||
#endif | #endif | ||||
return (retval); | return (retval); | ||||
} | } | ||||
int | |||||
strerror_r(int errnum, char *strerrbuf, size_t buflen) | |||||
{ | |||||
return (strerror_rl(errnum, strerrbuf, buflen, __get_locale())); | |||||
} | |||||
char * | char * | ||||
strerror_l(int num, locale_t locale) | |||||
{ | |||||
#ifndef __NO_TLS | |||||
static _Thread_local char ebuf[NL_TEXTMAX]; | |||||
jilles: This assumes that this function will be used commonly, which seems reasonable. | |||||
if (strerror_rl(num, ebuf, sizeof(ebuf), __get_locale()) != 0) | |||||
errno = EINVAL; | |||||
return (ebuf); | |||||
#else | |||||
errno = ENOTSUP; | |||||
return (NULL); | |||||
jillesUnsubmitted Done Inline ActionsA good encouragement for architectures to implement proper TLS :) However, do we want to leave this error completely undocumented? jilles: A good encouragement for architectures to implement proper TLS :)
However, do we want to leave… | |||||
kibAuthorUnsubmitted Done Inline ActionsI think arch(7) should list arches which do not implement static thread-local storage, then we can reference ENOTSUP from there. But from what I see, there is no arches left that define NO_TLS. Still I think that maintaining NO_TLS in some form is advantageous because it easier port to the new architectires. We got 2 or 3 in recent times (depends on how to calculate, arm64, riscv, powerc elfv2). kib: I think arch(7) should list arches which do not implement static thread-local storage, then we… | |||||
#endif | |||||
} | |||||
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); | ||||
} | } |
This assumes that this function will be used commonly, which seems reasonable.