Unref: handle null pointers
[babeltrace.git] / formats / ctf / ctf.c
CommitLineData
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
37extern int yydebug;
bbefb8dd
MD
38
39struct trace_descriptor {
40 struct ctf_trace ctf_trace;
41};
42
43struct trace_descriptor *ctf_open_trace(const char *path, int flags);
44void ctf_close_trace(struct trace_descriptor *descriptor);
fc93b2bd 45
4c8bfb7e 46static 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 */
76static
77int 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 }
131end:
132 ctf_scanner_free(scanner);
133end_scanner_alloc:
134 fclose(fp);
135end_stream:
136 close(td->ctf_trace.metadata.fd);
137 return ret;
138}
139
bbefb8dd
MD
140static
141int 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
202readdir_error:
203 free(dirent);
204error_metadata:
205 close(td->ctf_trace.dirfd);
206error_dirfd:
207 closedir(td->ctf_trace.dir);
bbefb8dd
MD
208error:
209 return ret;
210}
211
212static
213int 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
232error:
233 return ret;
bbefb8dd
MD
234}
235
236struct 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;
260error:
261 g_free(td);
262 return NULL;
263}
264
265void ctf_close_trace(struct trace_descriptor *td)
266{
267 closedir(td->ctf_trace.dir);
268 g_free(td);
269}
270
7fb21036 271void __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 */
This page took 0.033629 seconds and 4 git commands to generate.