about summary refs log tree commit diff
path: root/src/stdio/vsnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdio/vsnprintf.c')
-rw-r--r--src/stdio/vsnprintf.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/stdio/vsnprintf.c b/src/stdio/vsnprintf.c
new file mode 100644
index 00000000..bda6b49b
--- /dev/null
+++ b/src/stdio/vsnprintf.c
@@ -0,0 +1,33 @@
+#include "stdio_impl.h"
+
+static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
+{
+	/* pretend to succeed, but discard data */
+	return l;
+}
+
+int vsnprintf(char *s, size_t n, const char *fmt, va_list ap)
+{
+	int r;
+	FILE f;
+	unsigned char buf[1];
+
+	memset(&f, 0, sizeof(FILE));
+	f.lbf = EOF;
+	f.write = sn_write;
+	f.buf_size = 1;
+	f.buf = buf;
+	if (n > INT_MAX) {
+		errno = EOVERFLOW;
+		return -1;
+	} else if (n > 0) {
+		if (n > (char *)0+SIZE_MAX-s) n = (char *)0+SIZE_MAX-s;
+		f.wpos = s;
+		f.wbase = f.wend = s+n-1;
+		f.wstop = f.wend - 1;
+	}
+	r = vfprintf(&f, fmt, ap);
+	/* wpos points just after last byte written, or to s+n-1 (wbase) */
+	*f.wpos = 0;
+	return r;
+}