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 8struct cookie { 9 char *s; 10 size_t n; 11}; 12 13#define MIN(a, b) ((a) < (b) ? (a) : (b)) 14 15static 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 36int 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