• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "stdio_impl.h"
2 #include <limits.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <stdint.h>
6 #include <pthread.h>
7 
8 struct cookie {
9 	char *s;
10 	size_t n;
11 };
12 
13 #define MIN(a, b) ((a) < (b) ? (a) : (b))
14 
sn_write(FILE * f,const unsigned char * s,size_t l)15 static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
16 {
17 	struct cookie *c = f->cookie;
18 	size_t k = MIN(c->n, f->wpos - f->wbase);
19 	if (k) {
20 		memcpy(c->s, f->wbase, k);
21 		c->s += k;
22 		c->n -= k;
23 	}
24 	k = MIN(c->n, l);
25 	if (k) {
26 		memcpy(c->s, s, k);
27 		c->s += k;
28 		c->n -= k;
29 	}
30 	*c->s = 0;
31 	f->wpos = f->wbase = f->buf;
32 	/* pretend to succeed, even if we discarded extra data */
33 	return l;
34 }
35 
vsnprintf(char * restrict s,size_t n,const char * restrict fmt,va_list ap)36 int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
37 {
38 	unsigned char buf[1];
39 	char dummy[1];
40 	struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 };
41 	pthread_mutex_t locallock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
42 	FILE f = {
43 		.lbf = EOF,
44 		.write = sn_write,
45 		.lock = &locallock,
46 		.buf = buf,
47 		.cookie = &c,
48 	};
49 
50 	if (n > INT_MAX) {
51 		errno = EOVERFLOW;
52 		return -1;
53 	}
54 
55 	*c.s = 0;
56 	return vfprintf(&f, fmt, ap);
57 }
58