b7ae97e86cc89d3d680afe21dfa8b857be7b44b4
[babeltrace.git] / include / babeltrace / compat / memstream-internal.h
1 #ifndef _BABELTRACE_FORMAT_CTF_MEMSTREAM_H
2 #define _BABELTRACE_FORMAT_CTF_MEMSTREAM_H
3
4 /*
5 * format/ctf/memstream.h
6 *
7 * Copyright 2012 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 *
9 * memstream compatibility layer.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #ifdef BABELTRACE_HAVE_FMEMOPEN
31 #include <stdio.h>
32
33 static inline
34 FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
35 {
36 return fmemopen(buf, size, mode);
37 }
38
39 #else /* BABELTRACE_HAVE_FMEMOPEN */
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <errno.h>
45 #include <babeltrace/endian-internal.h>
46
47 #ifdef __MINGW32__
48
49 #include <io.h>
50 #include <glib.h>
51
52 /*
53 * Fallback for systems which don't have fmemopen. Copy buffer to a
54 * temporary file, and use that file as FILE * input.
55 */
56 static inline
57 FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
58 {
59 char *tmpname;
60 size_t len;
61 FILE *fp;
62 int ret;
63
64 /*
65 * Support reading only.
66 */
67 if (strcmp(mode, "rb") != 0) {
68 return NULL;
69 }
70
71 /* Build a temporary filename */
72 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
73 if (_mktemp(tmpname) == NULL) {
74 goto error_free;
75 }
76
77 /*
78 * Open as a read/write binary temporary deleted on close file.
79 * Will be deleted when the last file pointer is closed.
80 */
81 fp = fopen(tmpname, "w+bTD");
82 if (!fp) {
83 goto error_free;
84 }
85
86 /* Copy the entire buffer to the file */
87 len = fwrite(buf, sizeof(char), size, fp);
88 if (len != size) {
89 goto error_close;
90 }
91
92 /* Set the file pointer to the start of file */
93 ret = fseek(fp, 0L, SEEK_SET);
94 if (ret < 0) {
95 perror("fseek");
96 goto error_close;
97 }
98
99 g_free(tmpname);
100 return fp;
101
102 error_close:
103 ret = fclose(fp);
104 if (ret < 0) {
105 perror("close");
106 }
107 error_free:
108 g_free(tmpname);
109 return NULL;
110 }
111
112 #else /* __MINGW32__ */
113
114 /*
115 * Fallback for systems which don't have fmemopen. Copy buffer to a
116 * temporary file, and use that file as FILE * input.
117 */
118 static inline
119 FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
120 {
121 char *tmpname;
122 size_t len;
123 FILE *fp;
124 int ret;
125
126 /*
127 * Support reading only.
128 */
129 if (strcmp(mode, "rb") != 0) {
130 return NULL;
131 }
132
133 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
134 ret = mkstemp(tmpname);
135 if (ret < 0) {
136 g_free(tmpname);
137 return NULL;
138 }
139 /*
140 * We need to write to the file.
141 */
142 fp = fdopen(ret, "w+");
143 if (!fp) {
144 goto error_unlink;
145 }
146 /* Copy the entire buffer to the file */
147 len = fwrite(buf, sizeof(char), size, fp);
148 if (len != size) {
149 goto error_close;
150 }
151 ret = fseek(fp, 0L, SEEK_SET);
152 if (ret < 0) {
153 perror("fseek");
154 goto error_close;
155 }
156 /* We keep the handle open, but can unlink the file on the VFS. */
157 ret = unlink(tmpname);
158 if (ret < 0) {
159 perror("unlink");
160 }
161 g_free(tmpname);
162 return fp;
163
164 error_close:
165 ret = fclose(fp);
166 if (ret < 0) {
167 perror("close");
168 }
169 error_unlink:
170 ret = unlink(tmpname);
171 if (ret < 0) {
172 perror("unlink");
173 }
174 g_free(tmpname);
175 return NULL;
176 }
177
178 #endif /* __MINGW32__ */
179
180 #endif /* BABELTRACE_HAVE_FMEMOPEN */
181
182
183 #ifdef BABELTRACE_HAVE_OPEN_MEMSTREAM
184
185 #include <stdio.h>
186
187 static inline
188 FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
189 {
190 return open_memstream(ptr, sizeloc);
191 }
192
193 static inline
194 int bt_close_memstream(char **buf, size_t *size, FILE *fp)
195 {
196 return fclose(fp);
197 }
198
199 #else /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
200
201 #include <stdlib.h>
202 #include <stdio.h>
203 #include <glib.h>
204
205 #ifdef __MINGW32__
206
207 /*
208 * Fallback for systems which don't have open_memstream. Create FILE *
209 * with bt_open_memstream, but require call to
210 * bt_close_memstream to flush all data written to the FILE *
211 * into the buffer (which we allocate).
212 */
213 static inline
214 FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
215 {
216 char *tmpname;
217 FILE *fp;
218
219 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
220
221 if (_mktemp(tmpname) == NULL) {
222 goto error_free;
223 }
224
225 /*
226 * Open as a read/write binary temporary deleted on close file.
227 * Will be deleted when the last file pointer is closed.
228 */
229 fp = fopen(tmpname, "w+bTD");
230 if (!fp) {
231 goto error_free;
232 }
233
234 g_free(tmpname);
235 return fp;
236
237 error_free:
238 g_free(tmpname);
239 return NULL;
240 }
241
242 #else /* __MINGW32__ */
243
244 /*
245 * Fallback for systems which don't have open_memstream. Create FILE *
246 * with bt_open_memstream, but require call to
247 * bt_close_memstream to flush all data written to the FILE *
248 * into the buffer (which we allocate).
249 */
250 static inline
251 FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
252 {
253 char *tmpname;
254 int ret;
255 FILE *fp;
256
257 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
258
259 ret = mkstemp(tmpname);
260 if (ret < 0) {
261 perror("mkstemp");
262 g_free(tmpname);
263 return NULL;
264 }
265 fp = fdopen(ret, "w+");
266 if (!fp) {
267 goto error_unlink;
268 }
269 /*
270 * babeltrace_flush_memstream will update the buffer content
271 * with read from fp. No need to keep the file around, just the
272 * handle.
273 */
274 ret = unlink(tmpname);
275 if (ret < 0) {
276 perror("unlink");
277 }
278 g_free(tmpname);
279 return fp;
280
281 error_unlink:
282 ret = unlink(tmpname);
283 if (ret < 0) {
284 perror("unlink");
285 }
286 g_free(tmpname);
287 return NULL;
288 }
289
290 #endif /* __MINGW32__ */
291
292 /* Get file size, allocate buffer, copy. */
293 static inline
294 int bt_close_memstream(char **buf, size_t *size, FILE *fp)
295 {
296 size_t len, n;
297 long pos;
298 int ret;
299
300 ret = fflush(fp);
301 if (ret < 0) {
302 perror("fflush");
303 return ret;
304 }
305 ret = fseek(fp, 0L, SEEK_END);
306 if (ret < 0) {
307 perror("fseek");
308 return ret;
309 }
310 pos = ftell(fp);
311 if (ret < 0) {
312 perror("ftell");
313 return ret;
314 }
315 *size = pos;
316 /* add final \0 */
317 *buf = calloc(pos + 1, sizeof(char));
318 if (!*buf) {
319 return -ENOMEM;
320 }
321 ret = fseek(fp, 0L, SEEK_SET);
322 if (ret < 0) {
323 perror("fseek");
324 goto error_free;
325 }
326 /* Copy the entire file into the buffer */
327 n = 0;
328 clearerr(fp);
329 while (!feof(fp) && !ferror(fp) && (*size - n > 0)) {
330 len = fread(*buf, sizeof(char), *size - n, fp);
331 n += len;
332 }
333 if (n != *size) {
334 ret = -1;
335 goto error_close;
336 }
337 ret = fclose(fp);
338 if (ret < 0) {
339 perror("fclose");
340 return ret;
341 }
342 return 0;
343
344 error_close:
345 ret = fclose(fp);
346 if (ret < 0) {
347 perror("fclose");
348 }
349 error_free:
350 free(*buf);
351 *buf = NULL;
352 return ret;
353 }
354
355 #endif /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
356
357 #endif /* _BABELTRACE_FORMAT_CTF_MEMSTREAM_H */
This page took 0.039384 seconds and 3 git commands to generate.