diff --git a/sys/fmt/fmt.c b/sys/fmt/fmt.c index 74fb79c016..19955416dc 100644 --- a/sys/fmt/fmt.c +++ b/sys/fmt/fmt.c @@ -21,15 +21,9 @@ #include #include #include -#include +#include #include - -#if defined(__WITH_AVRLIBC__) || defined(__mips__) -#include /* for fwrite() */ -#else -/* work around broken sys/posix/unistd.h */ -ssize_t write(int fildes, const void *buf, size_t nbyte); -#endif +#include #include "kernel_defines.h" #include "fmt.h" @@ -505,19 +499,28 @@ uint32_t scn_u32_hex(const char *str, size_t n) void print(const char *s, size_t n) { -#ifdef __WITH_AVRLIBC__ - /* AVR's libc doesn't offer write(), so use fwrite() instead */ - fwrite(s, n, 1, stdout); -#else while (n > 0) { - ssize_t written = write(STDOUT_FILENO, s, n); + ssize_t written; + if (IS_USED(MODULE_STDIO_NATIVE)) { + /* for native fwrite is not wrapped and would use the system's + * write directly, resulting in corrupted output. Instead, use the + * stdio_write wrapper directly here to force all output from + * puts() / printf() and fmt to be handled the same. */ + extern ssize_t stdio_write(const void* buffer, size_t len); + written = stdio_write(s, n); + } + else { + /* For all but native: Use fwrite rather than the cheaper unbuffered + * write() to avoid corrupted output when mixing stdio and fmt + * for C libs that use buffered output */ + written = fwrite(s, 1, n, stdout); + } if (written < 0) { break; } n -= written; s += written; } -#endif /* __WITH_AVRLIBC__ */ } void print_u32_dec(uint32_t val)