1570af302Sopenharmony_ci#include "stdio_impl.h" 2570af302Sopenharmony_ci#include <errno.h> 3570af302Sopenharmony_ci#include <limits.h> 4570af302Sopenharmony_ci#include <string.h> 5570af302Sopenharmony_ci#include <stdlib.h> 6570af302Sopenharmony_ci#include "libc.h" 7570af302Sopenharmony_ci 8570af302Sopenharmony_cistruct cookie { 9570af302Sopenharmony_ci char **bufp; 10570af302Sopenharmony_ci size_t *sizep; 11570af302Sopenharmony_ci size_t pos; 12570af302Sopenharmony_ci char *buf; 13570af302Sopenharmony_ci size_t len; 14570af302Sopenharmony_ci size_t space; 15570af302Sopenharmony_ci}; 16570af302Sopenharmony_ci 17570af302Sopenharmony_cistruct ms_FILE { 18570af302Sopenharmony_ci FILE f; 19570af302Sopenharmony_ci struct cookie c; 20570af302Sopenharmony_ci unsigned char buf[BUFSIZ]; 21570af302Sopenharmony_ci}; 22570af302Sopenharmony_ci 23570af302Sopenharmony_cistatic off_t ms_seek(FILE *f, off_t off, int whence) 24570af302Sopenharmony_ci{ 25570af302Sopenharmony_ci ssize_t base; 26570af302Sopenharmony_ci struct cookie *c = f->cookie; 27570af302Sopenharmony_ci if (whence>2U) { 28570af302Sopenharmony_cifail: 29570af302Sopenharmony_ci errno = EINVAL; 30570af302Sopenharmony_ci return -1; 31570af302Sopenharmony_ci } 32570af302Sopenharmony_ci base = (size_t [3]){0, c->pos, c->len}[whence]; 33570af302Sopenharmony_ci if (off < -base || off > SSIZE_MAX-base) goto fail; 34570af302Sopenharmony_ci return c->pos = base+off; 35570af302Sopenharmony_ci} 36570af302Sopenharmony_ci 37570af302Sopenharmony_cistatic size_t ms_write(FILE *f, const unsigned char *buf, size_t len) 38570af302Sopenharmony_ci{ 39570af302Sopenharmony_ci struct cookie *c = f->cookie; 40570af302Sopenharmony_ci size_t len2 = f->wpos - f->wbase; 41570af302Sopenharmony_ci char *newbuf; 42570af302Sopenharmony_ci if (len2) { 43570af302Sopenharmony_ci f->wpos = f->wbase; 44570af302Sopenharmony_ci if (ms_write(f, f->wbase, len2) < len2) return 0; 45570af302Sopenharmony_ci } 46570af302Sopenharmony_ci if (len + c->pos >= c->space) { 47570af302Sopenharmony_ci len2 = 2*c->space+1 | c->pos+len+1; 48570af302Sopenharmony_ci newbuf = realloc(c->buf, len2); 49570af302Sopenharmony_ci if (!newbuf) return 0; 50570af302Sopenharmony_ci *c->bufp = c->buf = newbuf; 51570af302Sopenharmony_ci memset(c->buf + c->space, 0, len2 - c->space); 52570af302Sopenharmony_ci c->space = len2; 53570af302Sopenharmony_ci } 54570af302Sopenharmony_ci memcpy(c->buf+c->pos, buf, len); 55570af302Sopenharmony_ci c->pos += len; 56570af302Sopenharmony_ci if (c->pos >= c->len) c->len = c->pos; 57570af302Sopenharmony_ci *c->sizep = c->pos; 58570af302Sopenharmony_ci return len; 59570af302Sopenharmony_ci} 60570af302Sopenharmony_ci 61570af302Sopenharmony_cistatic int ms_close(FILE *f) 62570af302Sopenharmony_ci{ 63570af302Sopenharmony_ci return 0; 64570af302Sopenharmony_ci} 65570af302Sopenharmony_ci 66570af302Sopenharmony_ciFILE *open_memstream(char **bufp, size_t *sizep) 67570af302Sopenharmony_ci{ 68570af302Sopenharmony_ci struct ms_FILE *f; 69570af302Sopenharmony_ci char *buf; 70570af302Sopenharmony_ci 71570af302Sopenharmony_ci if (!(f=malloc(sizeof *f))) return 0; 72570af302Sopenharmony_ci if (!(buf=malloc(sizeof *buf))) { 73570af302Sopenharmony_ci free(f); 74570af302Sopenharmony_ci return 0; 75570af302Sopenharmony_ci } 76570af302Sopenharmony_ci memset(&f->f, 0, sizeof f->f); 77570af302Sopenharmony_ci memset(&f->c, 0, sizeof f->c); 78570af302Sopenharmony_ci f->f.cookie = &f->c; 79570af302Sopenharmony_ci 80570af302Sopenharmony_ci f->c.bufp = bufp; 81570af302Sopenharmony_ci f->c.sizep = sizep; 82570af302Sopenharmony_ci f->c.pos = f->c.len = f->c.space = *sizep = 0; 83570af302Sopenharmony_ci f->c.buf = *bufp = buf; 84570af302Sopenharmony_ci *buf = 0; 85570af302Sopenharmony_ci 86570af302Sopenharmony_ci f->f.flags = F_NORD; 87570af302Sopenharmony_ci f->f.fd = -1; 88570af302Sopenharmony_ci f->f.buf = f->buf; 89570af302Sopenharmony_ci f->f.buf_size = sizeof f->buf; 90570af302Sopenharmony_ci f->f.lbf = EOF; 91570af302Sopenharmony_ci f->f.write = ms_write; 92570af302Sopenharmony_ci f->f.seek = ms_seek; 93570af302Sopenharmony_ci f->f.close = ms_close; 94570af302Sopenharmony_ci f->f.mode = -1; 95570af302Sopenharmony_ci 96570af302Sopenharmony_ci if (!libc.threaded) f->f.lock = -1; 97570af302Sopenharmony_ci 98570af302Sopenharmony_ci return __ofl_add(&f->f); 99570af302Sopenharmony_ci} 100