diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-10-05 12:56:36 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-10-05 13:22:57 -0400 |
commit | 428cf9c206beee3407ea3c5480b00f4cfbea95f5 (patch) | |
tree | b5abbb4ad7fc8ee450ea0abfdb7419ca89b8a8ca /src/bfstd.c | |
parent | 634359bb169311646f6369b21f0c90a9819fe2ce (diff) | |
download | bfs-428cf9c206beee3407ea3c5480b00f4cfbea95f5.tar.xz |
bfstd: Add a thread-safe wrapper for strerror()
Diffstat (limited to 'src/bfstd.c')
-rw-r--r-- | src/bfstd.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/bfstd.c b/src/bfstd.c index fcf4a6d..e9214d4 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -12,6 +12,7 @@ #include <errno.h> #include <fcntl.h> #include <langinfo.h> +#include <locale.h> #include <nl_types.h> #include <stdint.h> #include <stdio.h> @@ -276,6 +277,48 @@ char *xstpencpy(char *dest, char *end, const char *src, size_t n) { } } +const char *xstrerror(int errnum) { + int saved = errno; + const char *ret = NULL; + static thread_local char buf[256]; + +#if __APPLE__ + // No strerror_l() on macOS + if (strerror_r(errnum, buf, sizeof(buf)) == 0) { + ret = buf; + } +#else +# if __NetBSD__ + // NetBSD has no thread-specific locales + locale_t loc = LC_GLOBAL_LOCALE; +# else + locale_t loc = uselocale((locale_t)0); +# endif + + locale_t copy = loc; + if (copy == LC_GLOBAL_LOCALE) { + copy = duplocale(copy); + } + + if (copy != (locale_t)0) { + ret = strerror_l(errnum, loc); + } + + if (loc == LC_GLOBAL_LOCALE) { + freelocale(copy); + } +#endif + + if (!ret) { + // Fallback for strerror_[lr]() or duplocale() failures + snprintf(buf, sizeof(buf), "Unknown error %d", errnum); + ret = buf; + } + + errno = saved; + return ret; +} + void xstrmode(mode_t mode, char str[11]) { strcpy(str, "----------"); |