cpp-common/bt2c/fmt.hpp: use `wise_enum::string_type` in `EnableIfIsWiseEnum` definition
[babeltrace.git] / src / compat / memstream.h
CommitLineData
f8370579 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
f8370579 3 *
0235b0db 4 * Copyright 2012 (c) Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
f8370579 5 *
0235b0db 6 * memstream compatibility layer.
f8370579
MD
7 */
8
0235b0db
MJ
9#ifndef _BABELTRACE_FORMAT_CTF_MEMSTREAM_H
10#define _BABELTRACE_FORMAT_CTF_MEMSTREAM_H
11
f8370579
MD
12#ifdef BABELTRACE_HAVE_FMEMOPEN
13#include <stdio.h>
14
15static inline
0cbbc8b8 16FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
f8370579
MD
17{
18 return fmemopen(buf, size, mode);
19}
20
21#else /* BABELTRACE_HAVE_FMEMOPEN */
22
b8d6e1fc 23#include <unistd.h>
f8370579
MD
24#include <stdlib.h>
25#include <stdio.h>
b776eaa4
MJ
26#include <string.h>
27#include <errno.h>
578e048b 28#include "compat/endian.h"
b776eaa4
MJ
29
30#ifdef __MINGW32__
31
32#include <io.h>
33#include <glib.h>
f8370579
MD
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 */
39static inline
0cbbc8b8 40FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
f8370579 41{
b776eaa4 42 char *tmpname;
f8370579
MD
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 }
b776eaa4
MJ
53
54 /* Build a temporary filename */
55 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
5084732e 56 if (!_mktemp(tmpname)) {
b776eaa4
MJ
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
85error_close:
86 ret = fclose(fp);
87 if (ret < 0) {
88 perror("close");
89 }
90error_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 */
101static inline
102FILE *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);
f8370579
MD
117 ret = mkstemp(tmpname);
118 if (ret < 0) {
b776eaa4 119 g_free(tmpname);
f8370579
MD
120 return NULL;
121 }
122 /*
123 * We need to write to the file.
124 */
7eb22883 125 fp = fdopen(ret, "wb+");
f8370579
MD
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 }
b776eaa4 144 g_free(tmpname);
f8370579
MD
145 return fp;
146
147error_close:
148 ret = fclose(fp);
149 if (ret < 0) {
150 perror("close");
151 }
152error_unlink:
153 ret = unlink(tmpname);
154 if (ret < 0) {
155 perror("unlink");
156 }
b776eaa4 157 g_free(tmpname);
f8370579
MD
158 return NULL;
159}
160
b776eaa4
MJ
161#endif /* __MINGW32__ */
162
f8370579
MD
163#endif /* BABELTRACE_HAVE_FMEMOPEN */
164
b776eaa4 165
f8370579
MD
166#ifdef BABELTRACE_HAVE_OPEN_MEMSTREAM
167
168#include <stdio.h>
169
170static inline
0cbbc8b8 171FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
f8370579
MD
172{
173 return open_memstream(ptr, sizeloc);
174}
175
176static inline
ecd7492f
MJ
177int bt_close_memstream(
178 char **buf __attribute__((unused)),
179 size_t *size __attribute__((unused)),
180 FILE *fp)
f8370579
MD
181{
182 return fclose(fp);
183}
184
185#else /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
186
187#include <stdlib.h>
188#include <stdio.h>
b776eaa4
MJ
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 */
199static inline
ecd7492f
MJ
200FILE *bt_open_memstream(char **ptr __attribute__((unused)),
201 size_t *sizeloc __attribute__((unused)))
b776eaa4
MJ
202{
203 char *tmpname;
204 FILE *fp;
205
206 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
207
5084732e 208 if (!_mktemp(tmpname)) {
b776eaa4
MJ
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
224error_free:
225 g_free(tmpname);
226 return NULL;
227}
228
229#else /* __MINGW32__ */
f8370579 230
516bf0a7
SM
231#include <unistd.h>
232
f8370579
MD
233/*
234 * Fallback for systems which don't have open_memstream. Create FILE *
0cbbc8b8
MJ
235 * with bt_open_memstream, but require call to
236 * bt_close_memstream to flush all data written to the FILE *
f8370579
MD
237 * into the buffer (which we allocate).
238 */
239static inline
ecd7492f
MJ
240FILE *bt_open_memstream(char **ptr __attribute__((unused)),
241 size_t *sizeloc __attribute__((unused)))
f8370579 242{
b776eaa4 243 char *tmpname;
f8370579
MD
244 int ret;
245 FILE *fp;
246
b776eaa4
MJ
247 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
248
f8370579
MD
249 ret = mkstemp(tmpname);
250 if (ret < 0) {
b776eaa4
MJ
251 perror("mkstemp");
252 g_free(tmpname);
f8370579
MD
253 return NULL;
254 }
7eb22883 255 fp = fdopen(ret, "wb+");
f8370579
MD
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 }
b776eaa4 268 g_free(tmpname);
f8370579
MD
269 return fp;
270
271error_unlink:
272 ret = unlink(tmpname);
273 if (ret < 0) {
274 perror("unlink");
275 }
b776eaa4 276 g_free(tmpname);
f8370579
MD
277 return NULL;
278}
279
b776eaa4
MJ
280#endif /* __MINGW32__ */
281
f8370579
MD
282/* Get file size, allocate buffer, copy. */
283static inline
0cbbc8b8 284int bt_close_memstream(char **buf, size_t *size, FILE *fp)
f8370579
MD
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 */
087cd0f5 307 *buf = (char *) calloc(pos + 1, sizeof(char));
f8370579
MD
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
334error_close:
335 ret = fclose(fp);
336 if (ret < 0) {
337 perror("fclose");
338 }
339error_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.123856 seconds and 4 git commands to generate.