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