Index: common/include/printf_core.h
===================================================================
--- common/include/printf_core.h	(revision 97f6b71fdbc9535de15d3b4ae8be377be2040150)
+++ common/include/printf_core.h	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
@@ -36,15 +36,17 @@
 #define _LIBC_PRINTF_CORE_H_
 
+#include <errno.h>
+#include <stdarg.h>
 #include <stddef.h>
-#include <stdarg.h>
 #include <uchar.h>
 
 /** Structure for specifying output methods for different printf clones. */
 typedef struct {
-	/* String output function, returns number of printed characters or EOF */
-	int (*str_write)(const char *, size_t, void *);
-
-	/* Wide string output function, returns number of printed characters or EOF */
-	int (*wstr_write)(const char32_t *, size_t, void *);
+	/*
+	 * String output function, returns EOK on success.
+	 * Only returns an error when an irrecoverable failure occurs and
+	 * the string cannot be fully output.
+	 */
+	errno_t (*write)(const char *, size_t, void *);
 
 	/* User data - output stream specification, state, locks, etc. */
Index: common/printf/printf_core.c
===================================================================
--- common/printf/printf_core.c	(revision 97f6b71fdbc9535de15d3b4ae8be377be2040150)
+++ common/printf/printf_core.c	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
@@ -201,15 +201,10 @@
     size_t *written_bytes)
 {
-	int written = ps->str_write(buf, n, ps->data);
-	if (written < 0)
-		return EIO;
+	errno_t rc = ps->write(buf, n, ps->data);
+	if (rc != EOK)
+		return rc;
+
 	_saturating_add(written_bytes, n);
 	return EOK;
-
-	#if 0
-	errno_t rc = ps->write(buf, &n, ps->data);
-	_saturating_add(written_bytes, n);
-	return rc;
-	#endif
 }
 
@@ -1466,6 +1461,4 @@
 
 		rc = _format_number(number, width, precision, base, flags, ps, &counter);
-		if (rc != EOK)
-			continue;
 	}
 
Index: common/stdc/snprintf.c
===================================================================
--- common/stdc/snprintf.c	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
+++ common/stdc/snprintf.c	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+/** Print formatted to the given buffer with limited size.
+ *
+ * @param str  Buffer
+ * @param size Buffer size
+ * @param fmt  Format string
+ *
+ * \see For more details about format string see printf_core.
+ *
+ */
+int snprintf(char *str, size_t size, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+
+	int ret = vsnprintf(str, size, fmt, args);
+
+	va_end(args);
+
+	return ret;
+}
+
+/** @}
+ */
Index: common/stdc/vsnprintf.c
===================================================================
--- common/stdc/vsnprintf.c	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
+++ common/stdc/vsnprintf.c	(revision 163e34ce66d8952017bc5a812affc2f72443b230)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2025 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#include <errno.h>
+#include <macros.h>
+#include <printf_core.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <str.h>
+
+typedef struct {
+	char *dst;      /* Destination */
+	size_t left;
+} vsnprintf_data_t;
+
+static int vsnprintf_str_write(const char *str, size_t size, void *data)
+{
+	vsnprintf_data_t *d = data;
+	size_t left = min(size, d->left);
+	if (left > 0) {
+		memcpy(d->dst, str, left);
+		d->dst += left;
+		d->left -= left;
+	}
+	return EOK;
+}
+
+int vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
+{
+	vsnprintf_data_t data = {
+		.dst = str,
+		.left = size ? size - 1 : 0,
+	};
+
+	printf_spec_t ps = {
+		vsnprintf_str_write,
+		&data
+	};
+
+	int written = printf_core(fmt, &ps, ap);
+	if (written < 0)
+		return written;
+
+	/* Write the terminating NUL character. */
+	if (size > 0)
+		data.dst[0] = 0;
+
+	return written;
+}
+
+/** @}
+ */
