summaryrefslogtreecommitdiffstats
path: root/src/bfstd.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-10-05 12:56:36 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-10-05 13:22:57 -0400
commit428cf9c206beee3407ea3c5480b00f4cfbea95f5 (patch)
treeb5abbb4ad7fc8ee450ea0abfdb7419ca89b8a8ca /src/bfstd.c
parent634359bb169311646f6369b21f0c90a9819fe2ce (diff)
downloadbfs-428cf9c206beee3407ea3c5480b00f4cfbea95f5.tar.xz
bfstd: Add a thread-safe wrapper for strerror()
Diffstat (limited to 'src/bfstd.c')
-rw-r--r--src/bfstd.c43
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, "----------");