Commit | Line | Data |
---|---|---|
fc93b2bd MD |
1 | /* |
2 | * BabelTrace - Common Trace Format (CTF) | |
3 | * | |
4 | * Format registration. | |
5 | * | |
c054553d | 6 | * Copyright 2010, 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
fc93b2bd | 7 | * |
ccd7e1c8 MD |
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: | |
fc93b2bd | 14 | * |
ccd7e1c8 MD |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. | |
fc93b2bd MD |
17 | */ |
18 | ||
19 | #include <babeltrace/format.h> | |
20 | #include <babeltrace/ctf/types.h> | |
bbefb8dd | 21 | #include <babeltrace/ctf/metadata.h> |
65102a8c | 22 | #include <babeltrace/babeltrace.h> |
bbefb8dd | 23 | #include <errno.h> |
bbefb8dd | 24 | #include <sys/types.h> |
65102a8c | 25 | #include <sys/stat.h> |
bbefb8dd | 26 | #include <fcntl.h> |
65102a8c | 27 | #include <dirent.h> |
bbefb8dd | 28 | #include <glib.h> |
65102a8c MD |
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; | |
bbefb8dd MD |
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); | |
fc93b2bd | 45 | |
4c8bfb7e | 46 | static struct format ctf_format = { |
fc93b2bd MD |
47 | .uint_read = ctf_uint_read, |
48 | .int_read = ctf_int_read, | |
49 | .uint_write = ctf_uint_write, | |
50 | .int_write = ctf_int_write, | |
0a46062b MD |
51 | .double_read = ctf_double_read, |
52 | .double_write = ctf_double_write, | |
fc93b2bd MD |
53 | .float_copy = ctf_float_copy, |
54 | .string_copy = ctf_string_copy, | |
a52d7f6a MD |
55 | .string_read = ctf_string_read, |
56 | .string_write = ctf_string_write, | |
57 | .string_free_temp = ctf_string_free_temp, | |
448d3cc7 MD |
58 | .enum_read = ctf_enum_read, |
59 | .enum_write = ctf_enum_write, | |
11796b96 MD |
60 | .struct_begin = ctf_struct_begin, |
61 | .struct_end = ctf_struct_end, | |
c054553d MD |
62 | .variant_begin = ctf_variant_begin, |
63 | .variant_end = ctf_variant_end, | |
d06d03db MD |
64 | .array_begin = ctf_array_begin, |
65 | .array_end = ctf_array_end, | |
66 | .sequence_begin = ctf_sequence_begin, | |
67 | .sequence_end = ctf_sequence_end, | |
bbefb8dd MD |
68 | .open_trace = ctf_open_trace, |
69 | .close_trace = ctf_close_trace, | |
fc93b2bd MD |
70 | }; |
71 | ||
65102a8c MD |
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 | ||
bbefb8dd MD |
140 | static |
141 | int ctf_open_trace_read(struct trace_descriptor *td, const char *path, int flags) | |
142 | { | |
143 | int ret; | |
65102a8c MD |
144 | struct dirent *dirent; |
145 | struct dirent *diriter; | |
146 | size_t dirent_len; | |
bbefb8dd MD |
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 | ||
65102a8c MD |
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 | */ | |
bbefb8dd | 167 | |
65102a8c MD |
168 | ret = ctf_open_trace_metadata_read(td); |
169 | if (ret) { | |
170 | goto error_metadata; | |
171 | } | |
bbefb8dd MD |
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. | |
bbefb8dd MD |
177 | */ |
178 | ||
65102a8c MD |
179 | dirent_len = offsetof(struct dirent, d_name) + |
180 | fpathconf(td->ctf_trace.dirfd, _PC_NAME_MAX) + 1; | |
bbefb8dd | 181 | |
65102a8c | 182 | dirent = malloc(dirent_len); |
bbefb8dd | 183 | |
65102a8c MD |
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 | } | |
bbefb8dd | 198 | |
65102a8c | 199 | free(dirent); |
bbefb8dd | 200 | return 0; |
65102a8c MD |
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); | |
bbefb8dd MD |
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 | ||
65102a8c MD |
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 | ||
bbefb8dd | 230 | return 0; |
65102a8c MD |
231 | |
232 | error: | |
233 | return ret; | |
bbefb8dd MD |
234 | } |
235 | ||
236 | struct trace_descriptor *ctf_open_trace(const char *path, int flags) | |
237 | { | |
238 | struct trace_descriptor *td; | |
239 | int ret; | |
240 | ||
65102a8c | 241 | td = g_new0(struct trace_descriptor, 1); |
bbefb8dd MD |
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 | ||
7fb21036 | 271 | void __attribute__((constructor)) ctf_init(void) |
fc93b2bd MD |
272 | { |
273 | int ret; | |
274 | ||
4c8bfb7e | 275 | ctf_format.name = g_quark_from_static_string("ctf"); |
fc93b2bd MD |
276 | ret = bt_register_format(&ctf_format); |
277 | assert(!ret); | |
278 | } | |
698f0fe4 MD |
279 | |
280 | /* TODO: finalize */ |