Big live update, see details
[lttngtop.git] / lib / babeltrace / compat / memstream.h
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 *
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:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
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.
28 */
29
30 #define _GNU_SOURCE
31 #include <config.h>
32
33 #ifdef BABELTRACE_HAVE_FMEMOPEN
34 #include <stdio.h>
35
36 static inline
37 FILE *babeltrace_fmemopen(void *buf, size_t size, const char *mode)
38 {
39 return fmemopen(buf, size, mode);
40 }
41
42 #else /* BABELTRACE_HAVE_FMEMOPEN */
43
44 #include <stdlib.h>
45 #include <stdio.h>
46
47 /*
48 * Fallback for systems which don't have fmemopen. Copy buffer to a
49 * temporary file, and use that file as FILE * input.
50 */
51 static inline
52 FILE *babeltrace_fmemopen(void *buf, size_t size, const char *mode)
53 {
54 char tmpname[PATH_MAX];
55 size_t len;
56 FILE *fp;
57 int ret;
58
59 /*
60 * Support reading only.
61 */
62 if (strcmp(mode, "rb") != 0) {
63 return NULL;
64 }
65 strncpy(tmpname, "/tmp/babeltrace-tmp-XXXXXX", PATH_MAX);
66 ret = mkstemp(tmpname);
67 if (ret < 0) {
68 return NULL;
69 }
70 /*
71 * We need to write to the file.
72 */
73 fp = fdopen(ret, "w+");
74 if (!fp) {
75 goto error_unlink;
76 }
77 /* Copy the entire buffer to the file */
78 len = fwrite(buf, sizeof(char), size, fp);
79 if (len != size) {
80 goto error_close;
81 }
82 ret = fseek(fp, 0L, SEEK_SET);
83 if (ret < 0) {
84 perror("fseek");
85 goto error_close;
86 }
87 /* We keep the handle open, but can unlink the file on the VFS. */
88 ret = unlink(tmpname);
89 if (ret < 0) {
90 perror("unlink");
91 }
92 return fp;
93
94 error_close:
95 ret = fclose(fp);
96 if (ret < 0) {
97 perror("close");
98 }
99 error_unlink:
100 ret = unlink(tmpname);
101 if (ret < 0) {
102 perror("unlink");
103 }
104 return NULL;
105 }
106
107 #endif /* BABELTRACE_HAVE_FMEMOPEN */
108
109 #ifdef BABELTRACE_HAVE_OPEN_MEMSTREAM
110
111 #include <stdio.h>
112
113 static inline
114 FILE *babeltrace_open_memstream(char **ptr, size_t *sizeloc)
115 {
116 return open_memstream(ptr, sizeloc);
117 }
118
119 static inline
120 int babeltrace_close_memstream(char **buf, size_t *size, FILE *fp)
121 {
122 return fclose(fp);
123 }
124
125 #else /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
126
127 #include <stdlib.h>
128 #include <stdio.h>
129
130 /*
131 * Fallback for systems which don't have open_memstream. Create FILE *
132 * with babeltrace_open_memstream, but require call to
133 * babeltrace_close_memstream to flush all data written to the FILE *
134 * into the buffer (which we allocate).
135 */
136 static inline
137 FILE *babeltrace_open_memstream(char **ptr, size_t *sizeloc)
138 {
139 char tmpname[PATH_MAX];
140 int ret;
141 FILE *fp;
142
143 strncpy(tmpname, "/tmp/babeltrace-tmp-XXXXXX", PATH_MAX);
144 ret = mkstemp(tmpname);
145 if (ret < 0) {
146 return NULL;
147 }
148 fp = fdopen(ret, "w+");
149 if (!fp) {
150 goto error_unlink;
151 }
152 /*
153 * babeltrace_flush_memstream will update the buffer content
154 * with read from fp. No need to keep the file around, just the
155 * handle.
156 */
157 ret = unlink(tmpname);
158 if (ret < 0) {
159 perror("unlink");
160 }
161 return fp;
162
163 error_unlink:
164 ret = unlink(tmpname);
165 if (ret < 0) {
166 perror("unlink");
167 }
168 return NULL;
169 }
170
171 /* Get file size, allocate buffer, copy. */
172 static inline
173 int babeltrace_close_memstream(char **buf, size_t *size, FILE *fp)
174 {
175 size_t len, n;
176 long pos;
177 int ret;
178
179 ret = fflush(fp);
180 if (ret < 0) {
181 perror("fflush");
182 return ret;
183 }
184 ret = fseek(fp, 0L, SEEK_END);
185 if (ret < 0) {
186 perror("fseek");
187 return ret;
188 }
189 pos = ftell(fp);
190 if (ret < 0) {
191 perror("ftell");
192 return ret;
193 }
194 *size = pos;
195 /* add final \0 */
196 *buf = calloc(pos + 1, sizeof(char));
197 if (!*buf) {
198 return -ENOMEM;
199 }
200 ret = fseek(fp, 0L, SEEK_SET);
201 if (ret < 0) {
202 perror("fseek");
203 goto error_free;
204 }
205 /* Copy the entire file into the buffer */
206 n = 0;
207 clearerr(fp);
208 while (!feof(fp) && !ferror(fp) && (*size - n > 0)) {
209 len = fread(*buf, sizeof(char), *size - n, fp);
210 n += len;
211 }
212 if (n != *size) {
213 ret = -1;
214 goto error_close;
215 }
216 ret = fclose(fp);
217 if (ret < 0) {
218 perror("fclose");
219 return ret;
220 }
221 return 0;
222
223 error_close:
224 ret = fclose(fp);
225 if (ret < 0) {
226 perror("fclose");
227 }
228 error_free:
229 free(*buf);
230 *buf = NULL;
231 return ret;
232 }
233
234 #endif /* BABELTRACE_HAVE_OPEN_MEMSTREAM */
235
236 #endif /* _BABELTRACE_FORMAT_CTF_MEMSTREAM_H */
This page took 0.035134 seconds and 4 git commands to generate.