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