cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[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(
178 char **buf __attribute__((unused)),
179 size_t *size __attribute__((unused)),
180 FILE *fp)
181 {
182 return fclose(fp);
183 }
184
185 #else /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
186
187 #include <stdlib.h>
188 #include <stdio.h>
189 #include <glib.h>
190
191 #ifdef __MINGW32__
192
193 /*
194 * Fallback for systems which don't have open_memstream. Create FILE *
195 * with bt_open_memstream, but require call to
196 * bt_close_memstream to flush all data written to the FILE *
197 * into the buffer (which we allocate).
198 */
199 static inline
200 FILE *bt_open_memstream(char **ptr __attribute__((unused)),
201 size_t *sizeloc __attribute__((unused)))
202 {
203 char *tmpname;
204 FILE *fp;
205
206 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
207
208 if (!_mktemp(tmpname)) {
209 goto error_free;
210 }
211
212 /*
213 * Open as a read/write binary temporary deleted on close file.
214 * Will be deleted when the last file pointer is closed.
215 */
216 fp = fopen(tmpname, "w+bTD");
217 if (!fp) {
218 goto error_free;
219 }
220
221 g_free(tmpname);
222 return fp;
223
224 error_free:
225 g_free(tmpname);
226 return NULL;
227 }
228
229 #else /* __MINGW32__ */
230
231 #include <unistd.h>
232
233 /*
234 * Fallback for systems which don't have open_memstream. Create FILE *
235 * with bt_open_memstream, but require call to
236 * bt_close_memstream to flush all data written to the FILE *
237 * into the buffer (which we allocate).
238 */
239 static inline
240 FILE *bt_open_memstream(char **ptr __attribute__((unused)),
241 size_t *sizeloc __attribute__((unused)))
242 {
243 char *tmpname;
244 int ret;
245 FILE *fp;
246
247 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
248
249 ret = mkstemp(tmpname);
250 if (ret < 0) {
251 perror("mkstemp");
252 g_free(tmpname);
253 return NULL;
254 }
255 fp = fdopen(ret, "wb+");
256 if (!fp) {
257 goto error_unlink;
258 }
259 /*
260 * babeltrace_flush_memstream will update the buffer content
261 * with read from fp. No need to keep the file around, just the
262 * handle.
263 */
264 ret = unlink(tmpname);
265 if (ret < 0) {
266 perror("unlink");
267 }
268 g_free(tmpname);
269 return fp;
270
271 error_unlink:
272 ret = unlink(tmpname);
273 if (ret < 0) {
274 perror("unlink");
275 }
276 g_free(tmpname);
277 return NULL;
278 }
279
280 #endif /* __MINGW32__ */
281
282 /* Get file size, allocate buffer, copy. */
283 static inline
284 int bt_close_memstream(char **buf, size_t *size, FILE *fp)
285 {
286 size_t len, n;
287 long pos;
288 int ret;
289
290 ret = fflush(fp);
291 if (ret < 0) {
292 perror("fflush");
293 return ret;
294 }
295 ret = fseek(fp, 0L, SEEK_END);
296 if (ret < 0) {
297 perror("fseek");
298 return ret;
299 }
300 pos = ftell(fp);
301 if (ret < 0) {
302 perror("ftell");
303 return ret;
304 }
305 *size = pos;
306 /* add final \0 */
307 *buf = (char *) calloc(pos + 1, sizeof(char));
308 if (!*buf) {
309 return -ENOMEM;
310 }
311 ret = fseek(fp, 0L, SEEK_SET);
312 if (ret < 0) {
313 perror("fseek");
314 goto error_free;
315 }
316 /* Copy the entire file into the buffer */
317 n = 0;
318 clearerr(fp);
319 while (!feof(fp) && !ferror(fp) && (*size - n > 0)) {
320 len = fread(*buf, sizeof(char), *size - n, fp);
321 n += len;
322 }
323 if (n != *size) {
324 ret = -1;
325 goto error_close;
326 }
327 ret = fclose(fp);
328 if (ret < 0) {
329 perror("fclose");
330 return ret;
331 }
332 return 0;
333
334 error_close:
335 ret = fclose(fp);
336 if (ret < 0) {
337 perror("fclose");
338 }
339 error_free:
340 free(*buf);
341 *buf = NULL;
342 return ret;
343 }
344
345 #endif /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
346
347 #endif /* _BABELTRACE_FORMAT_CTF_MEMSTREAM_H */
This page took 0.037729 seconds and 4 git commands to generate.