1 /*
2  * BabelTrace - Common Trace Format (CTF)
3  *
4  * CTF Metadata Dump.
5  *
6  * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
7  *
8  * Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to deal
12  * in the Software without restriction, including without limitation the rights
13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26  * SOFTWARE.
27  */
28 
29 #include <babeltrace/format.h>
30 #include <babeltrace/ctf-text/types.h>
31 #include <babeltrace/babeltrace-internal.h>
32 #include <babeltrace/ctf/events-internal.h>
33 #include <inttypes.h>
34 #include <sys/mman.h>
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <dirent.h>
40 #include <glib.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 
44 static
45 struct bt_trace_descriptor *ctf_metadata_open_trace(const char *path, int flags,
46 		void (*packet_seek)(struct bt_stream_pos *pos, size_t index,
47 			int whence), FILE *metadata_fp);
48 static
49 int ctf_metadata_close_trace(struct bt_trace_descriptor *descriptor);
50 
51 static
52 struct bt_format ctf_metadata_format = {
53 	.open_trace = ctf_metadata_open_trace,
54 	.close_trace = ctf_metadata_close_trace,
55 };
56 
bt_ctf_metadata_hook(void)57 void bt_ctf_metadata_hook(void)
58 {
59 	/*
60 	 * Dummy function to prevent the linker from discarding this format as
61 	 * "unused" in static builds.
62 	 */
63 }
64 
65 static
ctf_metadata_trace_pre_handler(struct bt_stream_pos * ppos,struct bt_trace_descriptor * td)66 int ctf_metadata_trace_pre_handler(struct bt_stream_pos *ppos,
67 			struct bt_trace_descriptor *td)
68 {
69 	struct ctf_text_stream_pos *pos =
70 		container_of(ppos, struct ctf_text_stream_pos, parent);
71 	struct ctf_trace *trace;
72 
73 	trace = container_of(td, struct ctf_trace, parent);
74 	if (!trace->metadata_string)
75 		return -EINVAL;
76 	if (trace->metadata_packetized) {
77 		fprintf(pos->fp, "/* CTF %u.%u */\n",
78 			BT_CTF_MAJOR, BT_CTF_MINOR);
79 	}
80 	fprintf(pos->fp, "%s", trace->metadata_string);
81 	return 0;
82 }
83 
84 static
ctf_metadata_open_trace(const char * path,int flags,void (* packet_seek)(struct bt_stream_pos * pos,size_t index,int whence),FILE * metadata_fp)85 struct bt_trace_descriptor *ctf_metadata_open_trace(const char *path, int flags,
86 		void (*packet_seek)(struct bt_stream_pos *pos, size_t index,
87 			int whence), FILE *metadata_fp)
88 {
89 	struct ctf_text_stream_pos *pos;
90 	FILE *fp;
91 
92 	pos = g_new0(struct ctf_text_stream_pos, 1);
93 
94 	pos->last_real_timestamp = -1ULL;
95 	pos->last_cycles_timestamp = -1ULL;
96 	switch (flags & O_ACCMODE) {
97 	case O_RDWR:
98 		if (!path)
99 			fp = stdout;
100 		else
101 			fp = fopen(path, "w");
102 		if (!fp)
103 			goto error;
104 		pos->fp = fp;
105 		pos->parent.pre_trace_cb = ctf_metadata_trace_pre_handler;
106 		pos->parent.trace = &pos->trace_descriptor;
107 		pos->print_names = 0;
108 		break;
109 	case O_RDONLY:
110 	default:
111 		fprintf(stderr, "[error] Incorrect open flags.\n");
112 		goto error;
113 	}
114 
115 	return &pos->trace_descriptor;
116 error:
117 	g_free(pos);
118 	return NULL;
119 }
120 
121 static
ctf_metadata_close_trace(struct bt_trace_descriptor * td)122 int ctf_metadata_close_trace(struct bt_trace_descriptor *td)
123 {
124 	int ret;
125 	struct ctf_text_stream_pos *pos =
126 		container_of(td, struct ctf_text_stream_pos, trace_descriptor);
127 	if (pos->fp != stdout) {
128 		ret = fclose(pos->fp);
129 		if (ret) {
130 			perror("Error on fclose");
131 			return -1;
132 		}
133 	}
134 	g_free(pos);
135 	return 0;
136 }
137 
138 static
ctf_metadata_init(void)139 void __attribute__((constructor)) ctf_metadata_init(void)
140 {
141 	int ret;
142 
143 	ctf_metadata_format.name = g_quark_from_static_string("ctf-metadata");
144 	ret = bt_register_format(&ctf_metadata_format);
145 	assert(!ret);
146 }
147 
148 static
ctf_metadata_exit(void)149 void __attribute__((destructor)) ctf_metadata_exit(void)
150 {
151 	bt_unregister_format(&ctf_metadata_format);
152 }
153