Port: handle 'size_t' / 'off_t' on Solaris
[babeltrace.git] / include / babeltrace / compat / memstream-internal.h
CommitLineData
f8370579
MD
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 *
eb31c5e6
MD
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:
f8370579 17 *
eb31c5e6
MD
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
c462e188
MD
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.
f8370579
MD
28 */
29
f8370579
MD
30#ifdef BABELTRACE_HAVE_FMEMOPEN
31#include <stdio.h>
32
33static inline
0cbbc8b8 34FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
f8370579
MD
35{
36 return fmemopen(buf, size, mode);
37}
38
39#else /* BABELTRACE_HAVE_FMEMOPEN */
40
41#include <stdlib.h>
42#include <stdio.h>
b776eaa4
MJ
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>
f8370579
MD
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 */
56static inline
0cbbc8b8 57FILE *bt_fmemopen(void *buf, size_t size, const char *mode)
f8370579 58{
b776eaa4 59 char *tmpname;
f8370579
MD
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 }
b776eaa4
MJ
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
102error_close:
103 ret = fclose(fp);
104 if (ret < 0) {
105 perror("close");
106 }
107error_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 */
118static inline
119FILE *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);
f8370579
MD
134 ret = mkstemp(tmpname);
135 if (ret < 0) {
b776eaa4 136 g_free(tmpname);
f8370579
MD
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 }
b776eaa4 161 g_free(tmpname);
f8370579
MD
162 return fp;
163
164error_close:
165 ret = fclose(fp);
166 if (ret < 0) {
167 perror("close");
168 }
169error_unlink:
170 ret = unlink(tmpname);
171 if (ret < 0) {
172 perror("unlink");
173 }
b776eaa4 174 g_free(tmpname);
f8370579
MD
175 return NULL;
176}
177
b776eaa4
MJ
178#endif /* __MINGW32__ */
179
f8370579
MD
180#endif /* BABELTRACE_HAVE_FMEMOPEN */
181
b776eaa4 182
f8370579
MD
183#ifdef BABELTRACE_HAVE_OPEN_MEMSTREAM
184
185#include <stdio.h>
186
187static inline
0cbbc8b8 188FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
f8370579
MD
189{
190 return open_memstream(ptr, sizeloc);
191}
192
193static inline
0cbbc8b8 194int bt_close_memstream(char **buf, size_t *size, FILE *fp)
f8370579
MD
195{
196 return fclose(fp);
197}
198
199#else /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
200
201#include <stdlib.h>
202#include <stdio.h>
b776eaa4
MJ
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 */
213static inline
214FILE *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
237error_free:
238 g_free(tmpname);
239 return NULL;
240}
241
242#else /* __MINGW32__ */
f8370579
MD
243
244/*
245 * Fallback for systems which don't have open_memstream. Create FILE *
0cbbc8b8
MJ
246 * with bt_open_memstream, but require call to
247 * bt_close_memstream to flush all data written to the FILE *
f8370579
MD
248 * into the buffer (which we allocate).
249 */
250static inline
0cbbc8b8 251FILE *bt_open_memstream(char **ptr, size_t *sizeloc)
f8370579 252{
b776eaa4 253 char *tmpname;
f8370579
MD
254 int ret;
255 FILE *fp;
256
b776eaa4
MJ
257 tmpname = g_build_filename(g_get_tmp_dir(), "babeltrace-tmp-XXXXXX", NULL);
258
f8370579
MD
259 ret = mkstemp(tmpname);
260 if (ret < 0) {
b776eaa4
MJ
261 perror("mkstemp");
262 g_free(tmpname);
f8370579
MD
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 }
b776eaa4 278 g_free(tmpname);
f8370579
MD
279 return fp;
280
281error_unlink:
282 ret = unlink(tmpname);
283 if (ret < 0) {
284 perror("unlink");
285 }
b776eaa4 286 g_free(tmpname);
f8370579
MD
287 return NULL;
288}
289
b776eaa4
MJ
290#endif /* __MINGW32__ */
291
f8370579
MD
292/* Get file size, allocate buffer, copy. */
293static inline
0cbbc8b8 294int bt_close_memstream(char **buf, size_t *size, FILE *fp)
f8370579
MD
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
344error_close:
345 ret = fclose(fp);
346 if (ret < 0) {
347 perror("fclose");
348 }
349error_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.058245 seconds and 4 git commands to generate.