github.com/afumu/libc@v0.0.6/musl/src/stdio/open_memstream.c (about) 1 #include "stdio_impl.h" 2 #include <errno.h> 3 #include <limits.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include "libc.h" 7 8 struct cookie { 9 char **bufp; 10 size_t *sizep; 11 size_t pos; 12 char *buf; 13 size_t len; 14 size_t space; 15 }; 16 17 struct ms_FILE { 18 FILE f; 19 struct cookie c; 20 unsigned char buf[BUFSIZ]; 21 }; 22 23 static off_t ms_seek(FILE *f, off_t off, int whence) 24 { 25 ssize_t base; 26 struct cookie *c = f->cookie; 27 if (whence>2U) { 28 fail: 29 errno = EINVAL; 30 return -1; 31 } 32 base = (size_t [3]){0, c->pos, c->len}[whence]; 33 if (off < -base || off > SSIZE_MAX-base) goto fail; 34 return c->pos = base+off; 35 } 36 37 static size_t ms_write(FILE *f, const unsigned char *buf, size_t len) 38 { 39 struct cookie *c = f->cookie; 40 size_t len2 = f->wpos - f->wbase; 41 char *newbuf; 42 if (len2) { 43 f->wpos = f->wbase; 44 if (ms_write(f, f->wbase, len2) < len2) return 0; 45 } 46 if (len + c->pos >= c->space) { 47 len2 = 2*c->space+1 | c->pos+len+1; 48 newbuf = realloc(c->buf, len2); 49 if (!newbuf) return 0; 50 *c->bufp = c->buf = newbuf; 51 memset(c->buf + c->space, 0, len2 - c->space); 52 c->space = len2; 53 } 54 memcpy(c->buf+c->pos, buf, len); 55 c->pos += len; 56 if (c->pos >= c->len) c->len = c->pos; 57 *c->sizep = c->pos; 58 return len; 59 } 60 61 static int ms_close(FILE *f) 62 { 63 return 0; 64 } 65 66 FILE *open_memstream(char **bufp, size_t *sizep) 67 { 68 struct ms_FILE *f; 69 char *buf; 70 71 if (!(f=malloc(sizeof *f))) return 0; 72 if (!(buf=malloc(sizeof *buf))) { 73 free(f); 74 return 0; 75 } 76 memset(&f->f, 0, sizeof f->f); 77 memset(&f->c, 0, sizeof f->c); 78 f->f.cookie = &f->c; 79 80 f->c.bufp = bufp; 81 f->c.sizep = sizep; 82 f->c.pos = f->c.len = f->c.space = *sizep = 0; 83 f->c.buf = *bufp = buf; 84 *buf = 0; 85 86 f->f.flags = F_NORD; 87 f->f.fd = -1; 88 f->f.buf = f->buf; 89 f->f.buf_size = sizeof f->buf; 90 f->f.lbf = EOF; 91 f->f.write = ms_write; 92 f->f.seek = ms_seek; 93 f->f.close = ms_close; 94 f->f.mode = -1; 95 96 if (!libc.threaded) f->f.lock = -1; 97 98 return __ofl_add(&f->f); 99 }