9b2f0fbf65dc195b426433de7596f6c18850aba2
[babeltrace.git] / formats / ctf / ctf.c
1 /*
2 * BabelTrace - Common Trace Format (CTF)
3 *
4 * Format registration.
5 *
6 * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 */
18
19 #include <babeltrace/format.h>
20 #include <babeltrace/ctf/types.h>
21 #include <babeltrace/ctf/metadata.h>
22 #include <babeltrace/babeltrace.h>
23 #include <errno.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <dirent.h>
28 #include <glib.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31
32
33 #include "metadata/ctf-scanner.h"
34 #include "metadata/ctf-parser.h"
35 #include "metadata/ctf-ast.h"
36
37 extern int yydebug;
38
39 struct trace_descriptor {
40 struct ctf_trace ctf_trace;
41 };
42
43 struct trace_descriptor *ctf_open_trace(const char *path, int flags);
44 void ctf_close_trace(struct trace_descriptor *descriptor);
45
46 static struct format ctf_format = {
47 .uint_read = ctf_uint_read,
48 .int_read = ctf_int_read,
49 .uint_write = ctf_uint_write,
50 .int_write = ctf_int_write,
51 .double_read = ctf_double_read,
52 .double_write = ctf_double_write,
53 .float_copy = ctf_float_copy,
54 .string_copy = ctf_string_copy,
55 .string_read = ctf_string_read,
56 .string_write = ctf_string_write,
57 .string_free_temp = ctf_string_free_temp,
58 .enum_read = ctf_enum_read,
59 .enum_write = ctf_enum_write,
60 .struct_begin = ctf_struct_begin,
61 .struct_end = ctf_struct_end,
62 .variant_begin = ctf_variant_begin,
63 .variant_end = ctf_variant_end,
64 .array_begin = ctf_array_begin,
65 .array_end = ctf_array_end,
66 .sequence_begin = ctf_sequence_begin,
67 .sequence_end = ctf_sequence_end,
68 .open_trace = ctf_open_trace,
69 .close_trace = ctf_close_trace,
70 };
71
72 /*
73 * TODO: for now, we treat the metadata file as a simple text file
74 * (without any header nor packets nor padding).
75 */
76 static
77 int ctf_open_trace_metadata_read(struct trace_descriptor *td)
78 {
79 struct ctf_scanner *scanner;
80 FILE *fp;
81 int ret = 0;
82
83 td->ctf_trace.metadata.fd = openat(td->ctf_trace.dirfd,
84 "metadata", O_RDONLY);
85 if (td->ctf_trace.metadata.fd < 0) {
86 fprintf(stdout, "Unable to open metadata.\n");
87 return td->ctf_trace.metadata.fd;
88 }
89
90 if (babeltrace_debug)
91 yydebug = 1;
92
93 fp = fdopen(td->ctf_trace.metadata.fd, "r");
94 if (!fp) {
95 fprintf(stdout, "Unable to open metadata stream.\n");
96 ret = -errno;
97 goto end_stream;
98 }
99
100 scanner = ctf_scanner_alloc(fp);
101 if (!scanner) {
102 fprintf(stdout, "Error allocating scanner\n");
103 ret = -ENOMEM;
104 goto end_scanner_alloc;
105 }
106 ret = ctf_scanner_append_ast(scanner);
107 if (ret) {
108 fprintf(stdout, "Error creating AST\n");
109 goto end;
110 }
111
112 if (babeltrace_debug) {
113 ret = ctf_visitor_print_xml(stdout, 0, &scanner->ast->root);
114 if (ret) {
115 fprintf(stdout, "Error visiting AST for XML output\n");
116 goto end;
117 }
118 }
119
120 ret = ctf_visitor_semantic_check(stdout, 0, &scanner->ast->root);
121 if (ret) {
122 fprintf(stdout, "Error in CTF semantic validation %d\n", ret);
123 goto end;
124 }
125 ret = ctf_visitor_construct_metadata(stdout, 0, &scanner->ast->root,
126 &td->ctf_trace, BYTE_ORDER);
127 if (ret) {
128 fprintf(stdout, "Error in CTF metadata constructor %d\n", ret);
129 goto end;
130 }
131 end:
132 ctf_scanner_free(scanner);
133 end_scanner_alloc:
134 fclose(fp);
135 end_stream:
136 close(td->ctf_trace.metadata.fd);
137 return ret;
138 }
139
140 static
141 int ctf_open_trace_read(struct trace_descriptor *td, const char *path, int flags)
142 {
143 int ret;
144 struct dirent *dirent;
145 struct dirent *diriter;
146 size_t dirent_len;
147
148 td->ctf_trace.flags = flags;
149
150 /* Open trace directory */
151 td->ctf_trace.dir = opendir(path);
152 if (!td->ctf_trace.dir) {
153 fprintf(stdout, "Unable to open trace directory.\n");
154 ret = -ENOENT;
155 goto error;
156 }
157
158 td->ctf_trace.dirfd = open(path, 0);
159 if (td->ctf_trace.dirfd < 0) {
160 fprintf(stdout, "Unable to open trace directory file descriptor.\n");
161 ret = -ENOENT;
162 goto error_dirfd;
163 }
164 /*
165 * Keep the metadata file separate.
166 */
167
168 ret = ctf_open_trace_metadata_read(td);
169 if (ret) {
170 goto error_metadata;
171 }
172
173 /*
174 * Open each stream: for each file, try to open, check magic
175 * number, and get the stream ID to add to the right location in
176 * the stream array.
177 */
178
179 dirent_len = offsetof(struct dirent, d_name) +
180 fpathconf(td->ctf_trace.dirfd, _PC_NAME_MAX) + 1;
181
182 dirent = malloc(dirent_len);
183
184 for (;;) {
185 ret = readdir_r(td->ctf_trace.dir, dirent, &diriter);
186 if (ret) {
187 fprintf(stdout, "Readdir error.\n");
188 goto readdir_error;
189
190 }
191 if (!diriter)
192 break;
193 if (!strcmp(diriter->d_name, ".")
194 || !strcmp(diriter->d_name, "..")
195 || !strcmp(diriter->d_name, "metadata"))
196 continue;
197 }
198
199 free(dirent);
200 return 0;
201
202 readdir_error:
203 free(dirent);
204 error_metadata:
205 close(td->ctf_trace.dirfd);
206 error_dirfd:
207 closedir(td->ctf_trace.dir);
208 error:
209 return ret;
210 }
211
212 static
213 int ctf_open_trace_write(struct trace_descriptor *td, const char *path, int flags)
214 {
215 int ret;
216
217 ret = mkdir(path, S_IRWXU|S_IRWXG);
218 if (ret)
219 return ret;
220
221 /* Open trace directory */
222 td->ctf_trace.dir = opendir(path);
223 if (!td->ctf_trace.dir) {
224 fprintf(stdout, "Unable to open trace directory.\n");
225 ret = -ENOENT;
226 goto error;
227 }
228
229
230 return 0;
231
232 error:
233 return ret;
234 }
235
236 struct trace_descriptor *ctf_open_trace(const char *path, int flags)
237 {
238 struct trace_descriptor *td;
239 int ret;
240
241 td = g_new0(struct trace_descriptor, 1);
242
243 switch (flags) {
244 case O_RDONLY:
245 ret = ctf_open_trace_read(td, path, flags);
246 if (ret)
247 goto error;
248 break;
249 case O_WRONLY:
250 ret = ctf_open_trace_write(td, path, flags);
251 if (ret)
252 goto error;
253 break;
254 default:
255 fprintf(stdout, "Incorrect open flags.\n");
256 goto error;
257 }
258
259 return td;
260 error:
261 g_free(td);
262 return NULL;
263 }
264
265 void ctf_close_trace(struct trace_descriptor *td)
266 {
267 closedir(td->ctf_trace.dir);
268 g_free(td);
269 }
270
271 void __attribute__((constructor)) ctf_init(void)
272 {
273 int ret;
274
275 ctf_format.name = g_quark_from_static_string("ctf");
276 ret = bt_register_format(&ctf_format);
277 assert(!ret);
278 }
279
280 /* TODO: finalize */
This page took 0.033298 seconds and 3 git commands to generate.