1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70: #include <errno.h>
71: #include <libio.h>
72: #include <stdio.h>
73: #include <stdlib.h>
74: #include <stdint.h>
75: #include <string.h>
76: #include <sys/types.h>
77: #include "libioP.h"
78:
79:
80: typedef struct fmemopen_cookie_struct fmemopen_cookie_t;
81: struct fmemopen_cookie_struct
82: {
83: char *buffer;
84: int mybuffer;
85: size_t size;
86: _IO_off64_t pos;
87: size_t maxpos;
88: };
89:
90:
91: static ssize_t
92: fmemopen_read (void *cookie, char *b, size_t s)
93: {
94: fmemopen_cookie_t *c;
95:
96: c = (fmemopen_cookie_t *) cookie;
97:
98: if (c->pos + s > c->size)
99: {
100: if ((size_t) c->pos == c->size)
101: return 0;
102: s = c->size - c->pos;
103: }
104:
105: memcpy (b, &(c->buffer[c->pos]), s);
106:
107: c->pos += s;
108: if ((size_t) c->pos > c->maxpos)
109: c->maxpos = c->pos;
110:
111: return s;
112: }
113:
114:
115: static ssize_t
116: fmemopen_write (void *cookie, const char *b, size_t s)
117: {
118: fmemopen_cookie_t *c;
119: int addnullc;
120:
121: c = (fmemopen_cookie_t *) cookie;
122:
123: addnullc = s == 0 || b[s - 1] != '\0';
124:
125: if (c->pos + s + addnullc > c->size)
126: {
127: if ((size_t) (c->pos + addnullc) == c->size)
128: {
129: __set_errno (ENOSPC);
130: return 0;
131: }
132: s = c->size - c->pos - addnullc;
133: }
134:
135: memcpy (&(c->buffer[c->pos]), b, s);
136:
137: c->pos += s;
138: if ((size_t) c->pos > c->maxpos)
139: {
140: c->maxpos = c->pos;
141: if (addnullc)
142: c->buffer[c->maxpos] = '\0';
143: }
144:
145: return s;
146: }
147:
148:
149: static int
150: fmemopen_seek (void *cookie, _IO_off64_t *p, int w)
151: {
152: _IO_off64_t np;
153: fmemopen_cookie_t *c;
154:
155: c = (fmemopen_cookie_t *) cookie;
156:
157: switch (w)
158: {
159: case SEEK_SET:
160: np = *p;
161: break;
162:
163: case SEEK_CUR:
164: np = c->pos + *p;
165: break;
166:
167: case SEEK_END:
168: np = c->maxpos - *p;
169: break;
170:
171: default:
172: return -1;
173: }
174:
175: if (np < 0 || (size_t) np > c->size)
176: return -1;
177:
178: *p = c->pos = np;
179:
180: return 0;
181: }
182:
183:
184: static int
185: fmemopen_close (void *cookie)
186: {
187: fmemopen_cookie_t *c;
188:
189: c = (fmemopen_cookie_t *) cookie;
190:
191: if (c->mybuffer)
192: free (c->buffer);
193: free (c);
194:
195: return 0;
196: }
197:
198:
199: FILE *
200: fmemopen (void *buf, size_t len, const char *mode)
201: {
202: cookie_io_functions_t iof;
203: fmemopen_cookie_t *c;
204:
205: if (__builtin_expect (len == 0, 0))
206: {
207: einval:
208: __set_errno (EINVAL);
209: return NULL;
210: }
211:
212: c = (fmemopen_cookie_t *) malloc (sizeof (fmemopen_cookie_t));
213: if (c == NULL)
214: return NULL;
215:
216: c->mybuffer = (buf == NULL);
217:
218: if (c->mybuffer)
219: {
220: c->buffer = (char *) malloc (len);
221: if (c->buffer == NULL)
222: {
223: free (c);
224: return NULL;
225: }
226: c->buffer[0] = '\0';
227: }
228: else
229: {
230: if (__builtin_expect ((uintptr_t) len > -(uintptr_t) buf, 0))
231: {
232: free (c);
233: goto einval;
234: }
235:
236: c->buffer = buf;
237: }
238:
239: c->size = len;
240:
241: if (mode[0] == 'w')
242: c->buffer[0] = '\0';
243:
244: c->maxpos = strlen (c->buffer);
245:
246: if (mode[0] == 'a')
247: c->pos = c->maxpos;
248: else
249: c->pos = 0;
250:
251: iof.read = fmemopen_read;
252: iof.write = fmemopen_write;
253: iof.seek = fmemopen_seek;
254: iof.close = fmemopen_close;
255:
256: return _IO_fopencookie (c, mode, iof);
257: }