tools/nolibc: add %m printf format

The %m format can be used to format the current errno.
It is non-standard but supported by other commonly used libcs like glibc and
musl, so applications do rely on them.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://lore.kernel.org/r/20250428-nolibc-misc-v2-2-3c043eeab06c@linutronix.de
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
This commit is contained in:
Thomas Weißschuh
2025-05-21 15:32:01 +02:00
committed by Thomas Weißschuh
parent 05b6b2a9ef
commit 7a7cd445d9
2 changed files with 25 additions and 0 deletions
+7
View File
@@ -20,6 +20,8 @@
#include "string.h"
#include "compiler.h"
static const char *strerror(int errnum);
#ifndef EOF
#define EOF (-1)
#endif
@@ -292,6 +294,11 @@ int __nolibc_printf(__nolibc_printf_cb cb, intptr_t state, size_t n, const char
if (!outstr)
outstr="(null)";
}
#ifndef NOLIBC_IGNORE_ERRNO
else if (c == 'm') {
outstr = strerror(errno);
}
#endif /* NOLIBC_IGNORE_ERRNO */
else if (c == '%') {
/* queue it verbatim */
continue;
@@ -1393,6 +1393,23 @@ static int test_scanf(void)
return 0;
}
int test_strerror(void)
{
char buf[100];
ssize_t ret;
memset(buf, 'A', sizeof(buf));
errno = EINVAL;
ret = snprintf(buf, sizeof(buf), "%m");
if (is_nolibc) {
if (ret < 6 || memcmp(buf, "errno=", 6))
return 1;
}
return 0;
}
static int run_printf(int min, int max)
{
int test;
@@ -1421,6 +1438,7 @@ static int run_printf(int min, int max)
CASE_TEST(number_width); EXPECT_VFPRINTF(10, " 1", "%10d", 1); break;
CASE_TEST(width_trunc); EXPECT_VFPRINTF(25, " ", "%25d", 1); break;
CASE_TEST(scanf); EXPECT_ZR(1, test_scanf()); break;
CASE_TEST(strerror); EXPECT_ZR(1, test_strerror()); break;
case __LINE__:
return ret; /* must be last */
/* note: do not set any defaults so as to permit holes above */