musl: introduce GNU specific version of strerror_r()

musl provides XSI compliant strerror_r(), and it is slightly different
from the one by glibc.
Let's introduce a tiny wrapper to convert XSI strerror_r() to GNU one.

The wrapper also patches musl's spurious catchall error message.
This commit is contained in:
Yu Watanabe
2023-01-23 23:39:46 -08:00
parent b8ef90d6fd
commit ebb422dd2b
3 changed files with 52 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include_next <string.h>
char* strerror_r_gnu(int errnum, char *buf, size_t buflen);
#define strerror_r strerror_r_gnu

View File

@@ -6,4 +6,5 @@ endif
libc_wrapper_sources += files(
'stdio.c',
'string.c',
)

44
src/libc/musl/string.c Normal file
View File

@@ -0,0 +1,44 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <stdio.h>
#include <string.h>
/* MAX_ERRNO is defined as 4095 in linux/err.h. We use the same value here. */
#define ERRNO_MAX 4095
/* strerror(3) says that glibc uses a maximum length of 1024 bytes. */
#define ERRNO_BUF_LEN 1024
/* The header string.h overrides strerror_r with strerror_r_gnu, hence we need to undef it here. */
#undef strerror_r
char* strerror_r_gnu(int errnum, char *buf, size_t buflen) {
/* musl provides spurious catchall error message "No error information" for unknown errno
* (including errno == 0). Let's patch it to glibc style. */
if (errnum == 0)
return (char*) "Success";
if (buflen == 0)
return (char*) "Unknown error";
if (errnum < 0 || errnum > ERRNO_MAX)
goto fallback;
if (strerror_r(errnum, buf, buflen) != 0)
goto fallback;
char buf_0[ERRNO_BUF_LEN];
if (strerror_r(0, buf_0, sizeof buf_0) != 0) /* Wut?? */
goto fallback;
/* strerror_r() may truncate the result. In that case, let's not compare the trailing NUL. */
size_t n = (buflen < ERRNO_BUF_LEN ? buflen : ERRNO_BUF_LEN) - 1;
if (strncmp(buf, buf_0, n) != 0)
return buf;
fallback:
snprintf(buf, buflen, "Unknown error %i", errnum);
return buf;
}