1 #include "stdio_impl.h"
2 #include <limits.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <stdint.h>
6
7 struct cookie {
8 char *s;
9 size_t n;
10 };
11
12 #ifndef MIN
13 #define MIN(a, b) ((a) < (b) ? (a) : (b))
14 #endif
15
sn_write(FILE * f,const unsigned char * s,size_t l)16 static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
17 {
18 struct cookie *c = f->cookie;
19 size_t k = MIN(c->n, f->wpos - f->wbase);
20 if (k) {
21 memcpy(c->s, f->wbase, k);
22 c->s += k;
23 c->n -= k;
24 }
25 k = MIN(c->n, l);
26 if (k) {
27 memcpy(c->s, s, k);
28 c->s += k;
29 c->n -= k;
30 }
31 *c->s = 0;
32 f->wpos = f->wbase = f->buf;
33 /* pretend to succeed, even if we discarded extra data */
34 return l;
35 }
36
vsnprintf(char * restrict s,size_t n,const char * restrict fmt,va_list ap)37 int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
38 {
39 unsigned char buf[1];
40 char dummy[1];
41 struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 };
42 FILE f = {
43 .lbf = EOF,
44 .write = sn_write,
45 .lock = -1,
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_unfiltered(&f, fmt, ap);
57 }
58
vsnprintf_filtered(char * restrict s,size_t n,const char * restrict fmt,va_list ap)59 int vsnprintf_filtered(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
60 {
61 unsigned char buf[1];
62 char placeholder[1];
63 struct cookie c = { .s = n ? s : placeholder, .n = n ? n-1 : 0 };
64 FILE f = {
65 .lbf = EOF,
66 .write = sn_write,
67 .lock = -1,
68 .buf = buf,
69 .cookie = &c,
70 };
71
72 if (n > INT_MAX) {
73 errno = EOVERFLOW;
74 return -1;
75 }
76
77 *c.s = 0;
78 return vfprintf(&f, fmt, ap);
79 }
80