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