remove stale document from malloc src directory
[oweals/musl.git] / src / stdio / open_memstream.c
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 }