|  | #include "stdio_impl.h" | 
|  | #include <limits.h> | 
|  | #include <string.h> | 
|  | #include <errno.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | static size_t sn_write(FILE *f, const unsigned char *s, size_t l) | 
|  | { | 
|  | size_t k = f->wend - f->wpos; | 
|  | if (k > l) k = l; | 
|  | memcpy(f->wpos, s, k); | 
|  | f->wpos += k; | 
|  | /* pretend to succeed, but discard extra data */ | 
|  | return l; | 
|  | } | 
|  |  | 
|  | int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap) | 
|  | { | 
|  | int r; | 
|  | char b; | 
|  | FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 }; | 
|  |  | 
|  | if (n-1 > INT_MAX-1) { | 
|  | if (n) { | 
|  | errno = EOVERFLOW; | 
|  | return -1; | 
|  | } | 
|  | s = &b; | 
|  | n = 1; | 
|  | } | 
|  |  | 
|  | /* Ensure pointers don't wrap if "infinite" n is passed in */ | 
|  | if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1; | 
|  | f.buf_size = n; | 
|  | f.buf = f.wpos = (void *)s; | 
|  | f.wbase = f.wend = (void *)(s+n); | 
|  | r = vfprintf(&f, fmt, ap); | 
|  |  | 
|  | /* Null-terminate, overwriting last char if dest buffer is full */ | 
|  | if (n) f.wpos[-(f.wpos == f.wend)] = 0; | 
|  | return r; | 
|  | } |