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