]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
tools/nolibc: add %m printf format
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Mon, 28 Apr 2025 12:40:03 +0000 (14:40 +0200)
committerThomas Weißschuh <linux@weissschuh.net>
Wed, 21 May 2025 13:32:01 +0000 (15:32 +0200)
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>
tools/include/nolibc/stdio.h
tools/testing/selftests/nolibc/nolibc-test.c

index 8fa98abab2127c2cd175201d2f50d71b78d03559..df5717d591826c8468e3473581ac0d6e76629aa3 100644 (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;
index 3e15a25ccddf5135db1f59bce1eefdff2ffe57f6..b7440a667db6b541a2548bdf5182bee0277100ed 100644 (file)
@@ -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 */