Fix: get rid of consumed flag
[babeltrace.git] / formats / ctf / ctf.c
1 /*
2 * BabelTrace - Common Trace Format (CTF)
3 *
4 * Format registration.
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
21 #include <babeltrace/format.h>
22 #include <babeltrace/ctf/types.h>
23 #include <babeltrace/ctf/metadata.h>
24 #include <babeltrace/babeltrace-internal.h>
25 #include <babeltrace/ctf/events-internal.h>
26 #include <babeltrace/trace-handle-internal.h>
27 #include <babeltrace/context-internal.h>
28 #include <babeltrace/uuid.h>
29 #include <babeltrace/endian.h>
30 #include <inttypes.h>
31 #include <stdio.h>
32 #include <sys/mman.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <dirent.h>
38 #include <glib.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41
42 #include "metadata/ctf-scanner.h"
43 #include "metadata/ctf-parser.h"
44 #include "metadata/ctf-ast.h"
45 #include "events-private.h"
46 #include "memstream.h"
47
48 /*
49 * We currently simply map a page to read the packet header and packet
50 * context to get the packet length and content length. (in bits)
51 */
52 #define MAX_PACKET_HEADER_LEN (getpagesize() * CHAR_BIT)
53 #define WRITE_PACKET_LEN (getpagesize() * 8 * CHAR_BIT)
54
55 #ifndef min
56 #define min(a, b) (((a) < (b)) ? (a) : (b))
57 #endif
58
59 #define NSEC_PER_SEC 1000000000ULL
60
61 int opt_clock_raw,
62 opt_clock_seconds,
63 opt_clock_date,
64 opt_clock_gmt;
65
66 uint64_t opt_clock_offset;
67
68 extern int yydebug;
69
70 static
71 struct trace_descriptor *ctf_open_trace(const char *path, int flags,
72 void (*packet_seek)(struct stream_pos *pos, size_t index,
73 int whence),
74 FILE *metadata_fp);
75 static
76 struct trace_descriptor *ctf_open_mmap_trace(
77 struct mmap_stream_list *mmap_list,
78 void (*packet_seek)(struct stream_pos *pos, size_t index,
79 int whence),
80 FILE *metadata_fp);
81 static
82 void ctf_set_context(struct trace_descriptor *descriptor,
83 struct bt_context *ctx);
84 static
85 void ctf_set_handle(struct trace_descriptor *descriptor,
86 struct bt_trace_handle *handle);
87
88 static
89 void ctf_close_trace(struct trace_descriptor *descriptor);
90 static
91 uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
92 struct bt_trace_handle *handle);
93 static
94 uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
95 struct bt_trace_handle *handle);
96
97 static
98 rw_dispatch read_dispatch_table[] = {
99 [ CTF_TYPE_INTEGER ] = ctf_integer_read,
100 [ CTF_TYPE_FLOAT ] = ctf_float_read,
101 [ CTF_TYPE_ENUM ] = ctf_enum_read,
102 [ CTF_TYPE_STRING ] = ctf_string_read,
103 [ CTF_TYPE_STRUCT ] = ctf_struct_rw,
104 [ CTF_TYPE_VARIANT ] = ctf_variant_rw,
105 [ CTF_TYPE_ARRAY ] = ctf_array_read,
106 [ CTF_TYPE_SEQUENCE ] = ctf_sequence_read,
107 };
108
109 static
110 rw_dispatch write_dispatch_table[] = {
111 [ CTF_TYPE_INTEGER ] = ctf_integer_write,
112 [ CTF_TYPE_FLOAT ] = ctf_float_write,
113 [ CTF_TYPE_ENUM ] = ctf_enum_write,
114 [ CTF_TYPE_STRING ] = ctf_string_write,
115 [ CTF_TYPE_STRUCT ] = ctf_struct_rw,
116 [ CTF_TYPE_VARIANT ] = ctf_variant_rw,
117 [ CTF_TYPE_ARRAY ] = ctf_array_write,
118 [ CTF_TYPE_SEQUENCE ] = ctf_sequence_write,
119 };
120
121 static
122 struct format ctf_format = {
123 .open_trace = ctf_open_trace,
124 .open_mmap_trace = ctf_open_mmap_trace,
125 .close_trace = ctf_close_trace,
126 .set_context = ctf_set_context,
127 .set_handle = ctf_set_handle,
128 .timestamp_begin = ctf_timestamp_begin,
129 .timestamp_end = ctf_timestamp_end,
130 };
131
132 static
133 uint64_t ctf_timestamp_begin(struct trace_descriptor *descriptor,
134 struct bt_trace_handle *handle)
135 {
136 struct ctf_trace *tin;
137 uint64_t begin = ULLONG_MAX;
138 int i, j;
139
140 tin = container_of(descriptor, struct ctf_trace, parent);
141
142 if (!tin)
143 goto error;
144
145 /* for each stream_class */
146 for (i = 0; i < tin->streams->len; i++) {
147 struct ctf_stream_declaration *stream_class;
148
149 stream_class = g_ptr_array_index(tin->streams, i);
150 if (!stream_class)
151 continue;
152 /* for each file_stream */
153 for (j = 0; j < stream_class->streams->len; j++) {
154 struct ctf_stream_definition *stream;
155 struct ctf_file_stream *cfs;
156 struct ctf_stream_pos *stream_pos;
157 struct packet_index *index;
158
159 stream = g_ptr_array_index(stream_class->streams, j);
160 cfs = container_of(stream, struct ctf_file_stream,
161 parent);
162 stream_pos = &cfs->pos;
163
164 index = &g_array_index(stream_pos->packet_index,
165 struct packet_index, 0);
166 if (index->timestamp_begin < begin)
167 begin = index->timestamp_begin;
168 }
169 }
170
171 return begin;
172
173 error:
174 return -1ULL;
175 }
176
177 static
178 uint64_t ctf_timestamp_end(struct trace_descriptor *descriptor,
179 struct bt_trace_handle *handle)
180 {
181 struct ctf_trace *tin;
182 uint64_t end = 0;
183 int i, j;
184
185 tin = container_of(descriptor, struct ctf_trace, parent);
186
187 if (!tin)
188 goto error;
189
190 /* for each stream_class */
191 for (i = 0; i < tin->streams->len; i++) {
192 struct ctf_stream_declaration *stream_class;
193
194 stream_class = g_ptr_array_index(tin->streams, i);
195 if (!stream_class)
196 continue;
197 /* for each file_stream */
198 for (j = 0; j < stream_class->streams->len; j++) {
199 struct ctf_stream_definition *stream;
200 struct ctf_file_stream *cfs;
201 struct ctf_stream_pos *stream_pos;
202 struct packet_index *index;
203
204 stream = g_ptr_array_index(stream_class->streams, j);
205 cfs = container_of(stream, struct ctf_file_stream,
206 parent);
207 stream_pos = &cfs->pos;
208
209 index = &g_array_index(stream_pos->packet_index,
210 struct packet_index,
211 stream_pos->packet_index->len - 1);
212 if (index->timestamp_end > end)
213 end = index->timestamp_end;
214 }
215 }
216
217 return end;
218
219 error:
220 return -1ULL;
221 }
222
223 /*
224 * Update stream current timestamp, keep at clock frequency.
225 */
226 static
227 void ctf_update_timestamp(struct ctf_stream_definition *stream,
228 struct definition_integer *integer_definition)
229 {
230 struct declaration_integer *integer_declaration =
231 integer_definition->declaration;
232 uint64_t oldval, newval, updateval;
233
234 if (unlikely(integer_declaration->len == 64)) {
235 stream->timestamp = integer_definition->value._unsigned;
236 return;
237 }
238 /* keep low bits */
239 oldval = stream->timestamp;
240 oldval &= (1ULL << integer_declaration->len) - 1;
241 newval = integer_definition->value._unsigned;
242 /* Test for overflow by comparing low bits */
243 if (newval < oldval)
244 newval += 1ULL << integer_declaration->len;
245 /* updateval contains old high bits, and new low bits (sum) */
246 updateval = stream->timestamp;
247 updateval &= ~((1ULL << integer_declaration->len) - 1);
248 updateval += newval;
249 stream->prev_timestamp = stream->timestamp;
250 stream->timestamp = updateval;
251 }
252
253 /*
254 * Print timestamp, rescaling clock frequency to nanoseconds and
255 * applying offsets as needed (unix time).
256 */
257 void ctf_print_timestamp(FILE *fp,
258 struct ctf_stream_definition *stream,
259 uint64_t timestamp)
260 {
261 uint64_t ts_sec = 0, ts_nsec;
262
263 if (opt_clock_raw) {
264 ts_nsec = ctf_get_timestamp_raw(stream, timestamp);
265 } else {
266 ts_nsec = ctf_get_timestamp(stream, timestamp);
267 }
268
269 /* Add command-line offset */
270 ts_sec += opt_clock_offset;
271
272 ts_sec += ts_nsec / NSEC_PER_SEC;
273 ts_nsec = ts_nsec % NSEC_PER_SEC;
274
275 if (!opt_clock_seconds) {
276 struct tm tm;
277 time_t time_s = (time_t) ts_sec;
278
279 if (!opt_clock_gmt) {
280 struct tm *res;
281
282 res = localtime_r(&time_s, &tm);
283 if (!res) {
284 fprintf(stderr, "[warning] Unable to get localtime.\n");
285 goto seconds;
286 }
287 } else {
288 struct tm *res;
289
290 res = gmtime_r(&time_s, &tm);
291 if (!res) {
292 fprintf(stderr, "[warning] Unable to get gmtime.\n");
293 goto seconds;
294 }
295 }
296 if (opt_clock_date) {
297 char timestr[26];
298 size_t res;
299
300 /* Print date and time */
301 res = strftime(timestr, sizeof(timestr),
302 "%F ", &tm);
303 if (!res) {
304 fprintf(stderr, "[warning] Unable to print ascii time.\n");
305 goto seconds;
306 }
307 fprintf(fp, "%s", timestr);
308 }
309 /* Print time in HH:MM:SS.ns */
310 fprintf(fp, "%02d:%02d:%02d.%09" PRIu64,
311 tm.tm_hour, tm.tm_min, tm.tm_sec, ts_nsec);
312 goto end;
313 }
314 seconds:
315 fprintf(fp, "%3" PRIu64 ".%09" PRIu64,
316 ts_sec, ts_nsec);
317
318 end:
319 return;
320 }
321
322 static
323 int ctf_read_event(struct stream_pos *ppos, struct ctf_stream_definition *stream)
324 {
325 struct ctf_stream_pos *pos =
326 container_of(ppos, struct ctf_stream_pos, parent);
327 struct ctf_stream_declaration *stream_class = stream->stream_class;
328 struct ctf_event_definition *event;
329 uint64_t id = 0;
330 int ret;
331
332 /* We need to check for EOF here for empty files. */
333 if (unlikely(pos->offset == EOF))
334 return EOF;
335
336 ctf_pos_get_event(pos);
337
338 /* save the current position as a restore point */
339 pos->last_offset = pos->offset;
340
341 /*
342 * This is the EOF check after we've advanced the position in
343 * ctf_pos_get_event.
344 */
345 if (unlikely(pos->offset == EOF))
346 return EOF;
347 assert(pos->offset < pos->content_size);
348
349 /* Read event header */
350 if (likely(stream->stream_event_header)) {
351 struct definition_integer *integer_definition;
352 struct definition *variant;
353
354 ret = generic_rw(ppos, &stream->stream_event_header->p);
355 if (unlikely(ret))
356 goto error;
357 /* lookup event id */
358 integer_definition = lookup_integer(&stream->stream_event_header->p, "id", FALSE);
359 if (integer_definition) {
360 id = integer_definition->value._unsigned;
361 } else {
362 struct definition_enum *enum_definition;
363
364 enum_definition = lookup_enum(&stream->stream_event_header->p, "id", FALSE);
365 if (enum_definition) {
366 id = enum_definition->integer->value._unsigned;
367 }
368 }
369
370 variant = lookup_variant(&stream->stream_event_header->p, "v");
371 if (variant) {
372 integer_definition = lookup_integer(variant, "id", FALSE);
373 if (integer_definition) {
374 id = integer_definition->value._unsigned;
375 }
376 }
377 stream->event_id = id;
378
379 /* lookup timestamp */
380 stream->has_timestamp = 0;
381 integer_definition = lookup_integer(&stream->stream_event_header->p, "timestamp", FALSE);
382 if (integer_definition) {
383 ctf_update_timestamp(stream, integer_definition);
384 stream->has_timestamp = 1;
385 } else {
386 if (variant) {
387 integer_definition = lookup_integer(variant, "timestamp", FALSE);
388 if (integer_definition) {
389 ctf_update_timestamp(stream, integer_definition);
390 stream->has_timestamp = 1;
391 }
392 }
393 }
394 }
395
396 /* Read stream-declared event context */
397 if (stream->stream_event_context) {
398 ret = generic_rw(ppos, &stream->stream_event_context->p);
399 if (ret)
400 goto error;
401 }
402
403 if (unlikely(id >= stream_class->events_by_id->len)) {
404 fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
405 return -EINVAL;
406 }
407 event = g_ptr_array_index(stream->events_by_id, id);
408 if (unlikely(!event)) {
409 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
410 return -EINVAL;
411 }
412
413 /* Read event-declared event context */
414 if (event->event_context) {
415 ret = generic_rw(ppos, &event->event_context->p);
416 if (ret)
417 goto error;
418 }
419
420 /* Read event payload */
421 if (likely(event->event_fields)) {
422 ret = generic_rw(ppos, &event->event_fields->p);
423 if (ret)
424 goto error;
425 }
426
427 return 0;
428
429 error:
430 fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
431 return ret;
432 }
433
434 static
435 int ctf_write_event(struct stream_pos *pos, struct ctf_stream_definition *stream)
436 {
437 struct ctf_stream_declaration *stream_class = stream->stream_class;
438 struct ctf_event_definition *event;
439 uint64_t id;
440 int ret;
441
442 id = stream->event_id;
443
444 /* print event header */
445 if (likely(stream->stream_event_header)) {
446 ret = generic_rw(pos, &stream->stream_event_header->p);
447 if (ret)
448 goto error;
449 }
450
451 /* print stream-declared event context */
452 if (stream->stream_event_context) {
453 ret = generic_rw(pos, &stream->stream_event_context->p);
454 if (ret)
455 goto error;
456 }
457
458 if (unlikely(id >= stream_class->events_by_id->len)) {
459 fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
460 return -EINVAL;
461 }
462 event = g_ptr_array_index(stream->events_by_id, id);
463 if (unlikely(!event)) {
464 fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
465 return -EINVAL;
466 }
467
468 /* print event-declared event context */
469 if (event->event_context) {
470 ret = generic_rw(pos, &event->event_context->p);
471 if (ret)
472 goto error;
473 }
474
475 /* Read and print event payload */
476 if (likely(event->event_fields)) {
477 ret = generic_rw(pos, &event->event_fields->p);
478 if (ret)
479 goto error;
480 }
481
482 return 0;
483
484 error:
485 fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
486 return ret;
487 }
488
489 void ctf_init_pos(struct ctf_stream_pos *pos, int fd, int open_flags)
490 {
491 pos->fd = fd;
492 pos->mmap_offset = 0;
493 pos->packet_size = 0;
494 pos->content_size = 0;
495 pos->content_size_loc = NULL;
496 pos->base_mma = NULL;
497 pos->offset = 0;
498 pos->dummy = false;
499 pos->cur_index = 0;
500 if (fd >= 0)
501 pos->packet_index = g_array_new(FALSE, TRUE,
502 sizeof(struct packet_index));
503 else
504 pos->packet_index = NULL;
505 switch (open_flags & O_ACCMODE) {
506 case O_RDONLY:
507 pos->prot = PROT_READ;
508 pos->flags = MAP_PRIVATE;
509 pos->parent.rw_table = read_dispatch_table;
510 pos->parent.event_cb = ctf_read_event;
511 break;
512 case O_RDWR:
513 pos->prot = PROT_WRITE; /* Write has priority */
514 pos->flags = MAP_SHARED;
515 pos->parent.rw_table = write_dispatch_table;
516 pos->parent.event_cb = ctf_write_event;
517 if (fd >= 0)
518 ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
519 break;
520 default:
521 assert(0);
522 }
523 }
524
525 void ctf_fini_pos(struct ctf_stream_pos *pos)
526 {
527 int ret;
528
529 if (pos->prot == PROT_WRITE && pos->content_size_loc)
530 *pos->content_size_loc = pos->offset;
531 if (pos->base_mma) {
532 /* unmap old base */
533 ret = munmap_align(pos->base_mma);
534 if (ret) {
535 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
536 strerror(errno));
537 assert(0);
538 }
539 }
540 (void) g_array_free(pos->packet_index, TRUE);
541 }
542
543 /*
544 * for SEEK_CUR: go to next packet.
545 * for SEEK_POS: go to packet numer (index).
546 */
547 void ctf_packet_seek(struct stream_pos *stream_pos, size_t index, int whence)
548 {
549 struct ctf_stream_pos *pos =
550 container_of(stream_pos, struct ctf_stream_pos, parent);
551 struct ctf_file_stream *file_stream =
552 container_of(pos, struct ctf_file_stream, pos);
553 int ret;
554 off_t off;
555 struct packet_index *packet_index;
556
557 if (pos->prot == PROT_WRITE && pos->content_size_loc)
558 *pos->content_size_loc = pos->offset;
559
560 if (pos->base_mma) {
561 /* unmap old base */
562 ret = munmap_align(pos->base_mma);
563 if (ret) {
564 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
565 strerror(errno));
566 assert(0);
567 }
568 pos->base_mma = NULL;
569 }
570
571 /*
572 * The caller should never ask for ctf_move_pos across packets,
573 * except to get exactly at the beginning of the next packet.
574 */
575 if (pos->prot == PROT_WRITE) {
576 switch (whence) {
577 case SEEK_CUR:
578 /* The writer will add padding */
579 pos->mmap_offset += WRITE_PACKET_LEN / CHAR_BIT;
580 break;
581 case SEEK_SET:
582 assert(index == 0); /* only seek supported for now */
583 pos->cur_index = 0;
584 break;
585 default:
586 assert(0);
587 }
588 pos->content_size = -1U; /* Unknown at this point */
589 pos->packet_size = WRITE_PACKET_LEN;
590 off = posix_fallocate(pos->fd, pos->mmap_offset,
591 pos->packet_size / CHAR_BIT);
592 assert(off >= 0);
593 pos->offset = 0;
594 } else {
595 read_next_packet:
596 switch (whence) {
597 case SEEK_CUR:
598 {
599 uint64_t events_discarded_diff;
600
601 if (pos->offset == EOF) {
602 return;
603 }
604 /* For printing discarded event count */
605 packet_index = &g_array_index(pos->packet_index,
606 struct packet_index, pos->cur_index);
607 events_discarded_diff = packet_index->events_discarded;
608 file_stream->parent.prev_timestamp_end =
609 packet_index->timestamp_end;
610 if (pos->cur_index > 0) {
611 packet_index = &g_array_index(pos->packet_index,
612 struct packet_index,
613 pos->cur_index - 1);
614 events_discarded_diff -= packet_index->events_discarded;
615 /*
616 * Deal with 32-bit wrap-around if the
617 * tracer provided a 32-bit field.
618 */
619 if (packet_index->events_discarded_len == 32) {
620 events_discarded_diff = (uint32_t) events_discarded_diff;
621 }
622 }
623 file_stream->parent.events_discarded = events_discarded_diff;
624 file_stream->parent.prev_timestamp = file_stream->parent.timestamp;
625 /* The reader will expect us to skip padding */
626 ++pos->cur_index;
627 break;
628 }
629 case SEEK_SET:
630 pos->cur_index = index;
631 file_stream->parent.prev_timestamp = 0;
632 file_stream->parent.prev_timestamp_end = 0;
633 break;
634 default:
635 assert(0);
636 }
637 if (pos->cur_index >= pos->packet_index->len) {
638 /*
639 * When a stream reaches the end of the
640 * file, we need to show the number of
641 * events discarded ourselves, because
642 * there is no next event scheduled to
643 * be printed in the output.
644 */
645 if (file_stream->parent.events_discarded) {
646 /*
647 * We need to check if we are in trace
648 * read or called from packet indexing.
649 * In this last case, the collection is
650 * not there, so we cannot print the
651 * timestamps.
652 */
653 if ((&file_stream->parent)->stream_class->trace->collection) {
654 fflush(stdout);
655 fprintf(stderr, "[warning] Tracer discarded %" PRIu64 " events at end of stream between [",
656 file_stream->parent.events_discarded);
657 ctf_print_timestamp(stderr, &file_stream->parent,
658 file_stream->parent.prev_timestamp);
659 fprintf(stderr, "] and [");
660 ctf_print_timestamp(stderr, &file_stream->parent,
661 file_stream->parent.prev_timestamp_end);
662 fprintf(stderr, "]. You should consider recording a new trace with larger buffers or with fewer events enabled.\n");
663 fflush(stderr);
664 }
665 file_stream->parent.events_discarded = 0;
666 }
667 pos->offset = EOF;
668 return;
669 }
670 packet_index = &g_array_index(pos->packet_index, struct packet_index,
671 pos->cur_index);
672 pos->mmap_offset = packet_index->offset;
673
674 /* Lookup context/packet size in index */
675 file_stream->parent.timestamp = packet_index->timestamp_begin;
676 pos->content_size = packet_index->content_size;
677 pos->packet_size = packet_index->packet_size;
678 if (packet_index->data_offset < packet_index->content_size) {
679 pos->offset = 0; /* will read headers */
680 } else if (packet_index->data_offset == packet_index->content_size) {
681 /* empty packet */
682 pos->offset = packet_index->data_offset;
683 whence = SEEK_CUR;
684 goto read_next_packet;
685 } else {
686 pos->offset = EOF;
687 return;
688 }
689 }
690 /* map new base. Need mapping length from header. */
691 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
692 pos->flags, pos->fd, pos->mmap_offset);
693 if (pos->base_mma == MAP_FAILED) {
694 fprintf(stderr, "[error] mmap error %s.\n",
695 strerror(errno));
696 assert(0);
697 }
698
699 /* update trace_packet_header and stream_packet_context */
700 if (pos->prot != PROT_WRITE && file_stream->parent.trace_packet_header) {
701 /* Read packet header */
702 ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
703 assert(!ret);
704 }
705 if (pos->prot != PROT_WRITE && file_stream->parent.stream_packet_context) {
706 /* Read packet context */
707 ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
708 assert(!ret);
709 }
710 }
711
712 static
713 int packet_metadata(struct ctf_trace *td, FILE *fp)
714 {
715 uint32_t magic;
716 size_t len;
717 int ret = 0;
718
719 len = fread(&magic, sizeof(magic), 1, fp);
720 if (len != 1) {
721 goto end;
722 }
723 if (magic == TSDL_MAGIC) {
724 ret = 1;
725 td->byte_order = BYTE_ORDER;
726 CTF_TRACE_SET_FIELD(td, byte_order);
727 } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
728 ret = 1;
729 td->byte_order = (BYTE_ORDER == BIG_ENDIAN) ?
730 LITTLE_ENDIAN : BIG_ENDIAN;
731 CTF_TRACE_SET_FIELD(td, byte_order);
732 }
733 end:
734 rewind(fp);
735 return ret;
736 }
737
738 /*
739 * Returns 0 on success, -1 on error.
740 */
741 static
742 int check_version(unsigned int major, unsigned int minor)
743 {
744 switch (major) {
745 case 1:
746 switch (minor) {
747 case 8:
748 return 0;
749 default:
750 goto warning;
751 }
752 default:
753 goto warning;
754
755 }
756
757 /* eventually return an error instead of warning */
758 warning:
759 fprintf(stderr, "[warning] Unsupported CTF specification version %u.%u. Trying anyway.\n",
760 major, minor);
761 return 0;
762 }
763
764 static
765 int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in,
766 FILE *out)
767 {
768 struct metadata_packet_header header;
769 size_t readlen, writelen, toread;
770 char buf[4096 + 1]; /* + 1 for debug-mode \0 */
771 int ret = 0;
772
773 readlen = fread(&header, header_sizeof(header), 1, in);
774 if (readlen < 1)
775 return -EINVAL;
776
777 if (td->byte_order != BYTE_ORDER) {
778 header.magic = GUINT32_SWAP_LE_BE(header.magic);
779 header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
780 header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
781 header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
782 }
783 if (header.checksum)
784 fprintf(stderr, "[warning] checksum verification not supported yet.\n");
785 if (header.compression_scheme) {
786 fprintf(stderr, "[error] compression (%u) not supported yet.\n",
787 header.compression_scheme);
788 return -EINVAL;
789 }
790 if (header.encryption_scheme) {
791 fprintf(stderr, "[error] encryption (%u) not supported yet.\n",
792 header.encryption_scheme);
793 return -EINVAL;
794 }
795 if (header.checksum_scheme) {
796 fprintf(stderr, "[error] checksum (%u) not supported yet.\n",
797 header.checksum_scheme);
798 return -EINVAL;
799 }
800 if (check_version(header.major, header.minor) < 0)
801 return -EINVAL;
802 if (!CTF_TRACE_FIELD_IS_SET(td, uuid)) {
803 memcpy(td->uuid, header.uuid, sizeof(header.uuid));
804 CTF_TRACE_SET_FIELD(td, uuid);
805 } else {
806 if (babeltrace_uuid_compare(header.uuid, td->uuid))
807 return -EINVAL;
808 }
809
810 toread = (header.content_size / CHAR_BIT) - header_sizeof(header);
811
812 for (;;) {
813 readlen = fread(buf, sizeof(char), min(sizeof(buf) - 1, toread), in);
814 if (ferror(in)) {
815 ret = -EINVAL;
816 break;
817 }
818 if (babeltrace_debug) {
819 buf[readlen] = '\0';
820 fprintf(stderr, "[debug] metadata packet read: %s\n",
821 buf);
822 }
823
824 writelen = fwrite(buf, sizeof(char), readlen, out);
825 if (writelen < readlen) {
826 ret = -EIO;
827 break;
828 }
829 if (ferror(out)) {
830 ret = -EINVAL;
831 break;
832 }
833 toread -= readlen;
834 if (!toread) {
835 ret = 0; /* continue reading next packet */
836 goto read_padding;
837 }
838 }
839 return ret;
840
841 read_padding:
842 toread = (header.packet_size - header.content_size) / CHAR_BIT;
843 ret = fseek(in, toread, SEEK_CUR);
844 if (ret < 0) {
845 fprintf(stderr, "[warning] Missing padding at end of file\n");
846 ret = 0;
847 }
848 return ret;
849 }
850
851 static
852 int ctf_open_trace_metadata_stream_read(struct ctf_trace *td, FILE **fp,
853 char **buf)
854 {
855 FILE *in, *out;
856 size_t size;
857 int ret;
858
859 in = *fp;
860 /*
861 * Using strlen on *buf instead of size of open_memstream
862 * because its size includes garbage at the end (after final
863 * \0). This is the allocated size, not the actual string size.
864 */
865 out = babeltrace_open_memstream(buf, &size);
866 if (out == NULL) {
867 perror("Metadata open_memstream");
868 return -errno;
869 }
870 for (;;) {
871 ret = ctf_open_trace_metadata_packet_read(td, in, out);
872 if (ret) {
873 break;
874 }
875 if (feof(in)) {
876 ret = 0;
877 break;
878 }
879 }
880 /* close to flush the buffer */
881 ret = babeltrace_close_memstream(buf, &size, out);
882 if (ret < 0) {
883 perror("babeltrace_flush_memstream");
884 fclose(in);
885 return -errno;
886 }
887 fclose(in);
888 /* open for reading */
889 *fp = babeltrace_fmemopen(*buf, strlen(*buf), "rb");
890 if (!*fp) {
891 perror("Metadata fmemopen");
892 return -errno;
893 }
894 return 0;
895 }
896
897 static
898 int ctf_open_trace_metadata_read(struct ctf_trace *td,
899 void (*packet_seek)(struct stream_pos *pos, size_t index,
900 int whence), FILE *metadata_fp)
901 {
902 struct ctf_scanner *scanner;
903 struct ctf_file_stream *metadata_stream;
904 FILE *fp;
905 char *buf = NULL;
906 int ret = 0;
907
908 metadata_stream = g_new0(struct ctf_file_stream, 1);
909 metadata_stream->pos.last_offset = LAST_OFFSET_POISON;
910
911 if (packet_seek) {
912 metadata_stream->pos.packet_seek = packet_seek;
913 } else {
914 fprintf(stderr, "[error] packet_seek function undefined.\n");
915 ret = -1;
916 goto end_stream;
917 }
918
919 if (metadata_fp) {
920 fp = metadata_fp;
921 } else {
922 td->metadata = &metadata_stream->parent;
923 metadata_stream->pos.fd = openat(td->dirfd, "metadata", O_RDONLY);
924 if (metadata_stream->pos.fd < 0) {
925 fprintf(stderr, "Unable to open metadata.\n");
926 return metadata_stream->pos.fd;
927 }
928
929 fp = fdopen(metadata_stream->pos.fd, "r");
930 if (!fp) {
931 fprintf(stderr, "[error] Unable to open metadata stream.\n");
932 perror("Metadata stream open");
933 ret = -errno;
934 goto end_stream;
935 }
936 }
937 if (babeltrace_debug)
938 yydebug = 1;
939
940 if (packet_metadata(td, fp)) {
941 ret = ctf_open_trace_metadata_stream_read(td, &fp, &buf);
942 if (ret)
943 goto end_packet_read;
944 } else {
945 unsigned int major, minor;
946 ssize_t nr_items;
947
948 td->byte_order = BYTE_ORDER;
949
950 /* Check text-only metadata header and version */
951 nr_items = fscanf(fp, "/* CTF %u.%u", &major, &minor);
952 if (nr_items < 2)
953 fprintf(stderr, "[warning] Ill-shapen or missing \"/* CTF x.y\" header for text-only metadata.\n");
954 if (check_version(major, minor) < 0) {
955 ret = -EINVAL;
956 goto end_packet_read;
957 }
958 rewind(fp);
959 }
960
961 scanner = ctf_scanner_alloc(fp);
962 if (!scanner) {
963 fprintf(stderr, "[error] Error allocating scanner\n");
964 ret = -ENOMEM;
965 goto end_scanner_alloc;
966 }
967 ret = ctf_scanner_append_ast(scanner);
968 if (ret) {
969 fprintf(stderr, "[error] Error creating AST\n");
970 goto end;
971 }
972
973 if (babeltrace_debug) {
974 ret = ctf_visitor_print_xml(stderr, 0, &scanner->ast->root);
975 if (ret) {
976 fprintf(stderr, "[error] Error visiting AST for XML output\n");
977 goto end;
978 }
979 }
980
981 ret = ctf_visitor_semantic_check(stderr, 0, &scanner->ast->root);
982 if (ret) {
983 fprintf(stderr, "[error] Error in CTF semantic validation %d\n", ret);
984 goto end;
985 }
986 ret = ctf_visitor_construct_metadata(stderr, 0, &scanner->ast->root,
987 td, td->byte_order);
988 if (ret) {
989 fprintf(stderr, "[error] Error in CTF metadata constructor %d\n", ret);
990 goto end;
991 }
992 end:
993 ctf_scanner_free(scanner);
994 end_scanner_alloc:
995 end_packet_read:
996 if (fp)
997 fclose(fp);
998 free(buf);
999 end_stream:
1000 close(metadata_stream->pos.fd);
1001 if (ret)
1002 g_free(metadata_stream);
1003 return ret;
1004 }
1005
1006 static
1007 struct ctf_event_definition *create_event_definitions(struct ctf_trace *td,
1008 struct ctf_stream_definition *stream,
1009 struct ctf_event_declaration *event)
1010 {
1011 struct ctf_event_definition *stream_event = g_new0(struct ctf_event_definition, 1);
1012
1013 if (event->context_decl) {
1014 struct definition *definition =
1015 event->context_decl->p.definition_new(&event->context_decl->p,
1016 stream->parent_def_scope, 0, 0, "event.context");
1017 if (!definition) {
1018 goto error;
1019 }
1020 stream_event->event_context = container_of(definition,
1021 struct definition_struct, p);
1022 stream->parent_def_scope = stream_event->event_context->p.scope;
1023 }
1024 if (event->fields_decl) {
1025 struct definition *definition =
1026 event->fields_decl->p.definition_new(&event->fields_decl->p,
1027 stream->parent_def_scope, 0, 0, "event.fields");
1028 if (!definition) {
1029 goto error;
1030 }
1031 stream_event->event_fields = container_of(definition,
1032 struct definition_struct, p);
1033 stream->parent_def_scope = stream_event->event_fields->p.scope;
1034 }
1035 stream_event->stream = stream;
1036 return stream_event;
1037
1038 error:
1039 if (stream_event->event_fields)
1040 definition_unref(&stream_event->event_fields->p);
1041 if (stream_event->event_context)
1042 definition_unref(&stream_event->event_context->p);
1043 return NULL;
1044 }
1045
1046 static
1047 int create_stream_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
1048 {
1049 struct ctf_stream_declaration *stream_class;
1050 int ret;
1051 int i;
1052
1053 if (stream->stream_definitions_created)
1054 return 0;
1055
1056 stream_class = stream->stream_class;
1057
1058 if (stream_class->packet_context_decl) {
1059 struct definition *definition =
1060 stream_class->packet_context_decl->p.definition_new(&stream_class->packet_context_decl->p,
1061 stream->parent_def_scope, 0, 0, "stream.packet.context");
1062 if (!definition) {
1063 ret = -EINVAL;
1064 goto error;
1065 }
1066 stream->stream_packet_context = container_of(definition,
1067 struct definition_struct, p);
1068 stream->parent_def_scope = stream->stream_packet_context->p.scope;
1069 }
1070 if (stream_class->event_header_decl) {
1071 struct definition *definition =
1072 stream_class->event_header_decl->p.definition_new(&stream_class->event_header_decl->p,
1073 stream->parent_def_scope, 0, 0, "stream.event.header");
1074 if (!definition) {
1075 ret = -EINVAL;
1076 goto error;
1077 }
1078 stream->stream_event_header =
1079 container_of(definition, struct definition_struct, p);
1080 stream->parent_def_scope = stream->stream_event_header->p.scope;
1081 }
1082 if (stream_class->event_context_decl) {
1083 struct definition *definition =
1084 stream_class->event_context_decl->p.definition_new(&stream_class->event_context_decl->p,
1085 stream->parent_def_scope, 0, 0, "stream.event.context");
1086 if (!definition) {
1087 ret = -EINVAL;
1088 goto error;
1089 }
1090 stream->stream_event_context =
1091 container_of(definition, struct definition_struct, p);
1092 stream->parent_def_scope = stream->stream_event_context->p.scope;
1093 }
1094 stream->events_by_id = g_ptr_array_new();
1095 g_ptr_array_set_size(stream->events_by_id, stream_class->events_by_id->len);
1096 for (i = 0; i < stream->events_by_id->len; i++) {
1097 struct ctf_event_declaration *event = g_ptr_array_index(stream_class->events_by_id, i);
1098 struct ctf_event_definition *stream_event;
1099
1100 if (!event)
1101 continue;
1102 stream_event = create_event_definitions(td, stream, event);
1103 if (!stream_event)
1104 goto error_event;
1105 g_ptr_array_index(stream->events_by_id, i) = stream_event;
1106 }
1107 return 0;
1108
1109 error_event:
1110 for (i = 0; i < stream->events_by_id->len; i++) {
1111 struct ctf_event_definition *stream_event = g_ptr_array_index(stream->events_by_id, i);
1112 if (stream_event)
1113 g_free(stream_event);
1114 }
1115 g_ptr_array_free(stream->events_by_id, TRUE);
1116 error:
1117 if (stream->stream_event_context)
1118 definition_unref(&stream->stream_event_context->p);
1119 if (stream->stream_event_header)
1120 definition_unref(&stream->stream_event_header->p);
1121 if (stream->stream_packet_context)
1122 definition_unref(&stream->stream_packet_context->p);
1123 return ret;
1124 }
1125
1126
1127 static
1128 int create_stream_packet_index(struct ctf_trace *td,
1129 struct ctf_file_stream *file_stream)
1130 {
1131 struct ctf_stream_declaration *stream;
1132 int len_index;
1133 struct ctf_stream_pos *pos;
1134 struct stat filestats;
1135 struct packet_index packet_index;
1136 int first_packet = 1;
1137 int ret;
1138
1139 pos = &file_stream->pos;
1140
1141 ret = fstat(pos->fd, &filestats);
1142 if (ret < 0)
1143 return ret;
1144
1145 if (filestats.st_size < MAX_PACKET_HEADER_LEN / CHAR_BIT)
1146 return -EINVAL;
1147
1148 for (pos->mmap_offset = 0; pos->mmap_offset < filestats.st_size; ) {
1149 uint64_t stream_id = 0;
1150
1151 if (pos->base_mma) {
1152 /* unmap old base */
1153 ret = munmap_align(pos->base_mma);
1154 if (ret) {
1155 fprintf(stderr, "[error] Unable to unmap old base: %s.\n",
1156 strerror(errno));
1157 return ret;
1158 }
1159 pos->base_mma = NULL;
1160 }
1161 /* map new base. Need mapping length from header. */
1162 pos->base_mma = mmap_align(MAX_PACKET_HEADER_LEN / CHAR_BIT, PROT_READ,
1163 MAP_PRIVATE, pos->fd, pos->mmap_offset);
1164 assert(pos->base_mma != MAP_FAILED);
1165 pos->content_size = MAX_PACKET_HEADER_LEN; /* Unknown at this point */
1166 pos->packet_size = MAX_PACKET_HEADER_LEN; /* Unknown at this point */
1167 pos->offset = 0; /* Position of the packet header */
1168
1169 packet_index.offset = pos->mmap_offset;
1170 packet_index.content_size = 0;
1171 packet_index.packet_size = 0;
1172 packet_index.timestamp_begin = 0;
1173 packet_index.timestamp_end = 0;
1174 packet_index.events_discarded = 0;
1175
1176 /* read and check header, set stream id (and check) */
1177 if (file_stream->parent.trace_packet_header) {
1178 /* Read packet header */
1179 ret = generic_rw(&pos->parent, &file_stream->parent.trace_packet_header->p);
1180 if (ret)
1181 return ret;
1182 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("magic"));
1183 if (len_index >= 0) {
1184 struct definition *field;
1185 uint64_t magic;
1186
1187 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
1188 magic = get_unsigned_int(field);
1189 if (magic != CTF_MAGIC) {
1190 fprintf(stderr, "[error] Invalid magic number 0x%" PRIX64 " at packet %u (file offset %zd).\n",
1191 magic,
1192 file_stream->pos.packet_index->len,
1193 (ssize_t) pos->mmap_offset);
1194 return -EINVAL;
1195 }
1196 }
1197
1198 /* check uuid */
1199 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("uuid"));
1200 if (len_index >= 0) {
1201 struct definition_array *defarray;
1202 struct definition *field;
1203 uint64_t i;
1204 uint8_t uuidval[BABELTRACE_UUID_LEN];
1205
1206 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
1207 assert(field->declaration->id == CTF_TYPE_ARRAY);
1208 defarray = container_of(field, struct definition_array, p);
1209 assert(array_len(defarray) == BABELTRACE_UUID_LEN);
1210
1211 for (i = 0; i < BABELTRACE_UUID_LEN; i++) {
1212 struct definition *elem;
1213
1214 elem = array_index(defarray, i);
1215 uuidval[i] = get_unsigned_int(elem);
1216 }
1217 ret = babeltrace_uuid_compare(td->uuid, uuidval);
1218 if (ret) {
1219 fprintf(stderr, "[error] Unique Universal Identifiers do not match.\n");
1220 return -EINVAL;
1221 }
1222 }
1223
1224
1225 len_index = struct_declaration_lookup_field_index(file_stream->parent.trace_packet_header->declaration, g_quark_from_static_string("stream_id"));
1226 if (len_index >= 0) {
1227 struct definition *field;
1228
1229 field = struct_definition_get_field_from_index(file_stream->parent.trace_packet_header, len_index);
1230 stream_id = get_unsigned_int(field);
1231 }
1232 }
1233
1234 if (!first_packet && file_stream->parent.stream_id != stream_id) {
1235 fprintf(stderr, "[error] Stream ID is changing within a stream.\n");
1236 return -EINVAL;
1237 }
1238 if (first_packet) {
1239 file_stream->parent.stream_id = stream_id;
1240 if (stream_id >= td->streams->len) {
1241 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
1242 return -EINVAL;
1243 }
1244 stream = g_ptr_array_index(td->streams, stream_id);
1245 if (!stream) {
1246 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared in metadata.\n", stream_id);
1247 return -EINVAL;
1248 }
1249 file_stream->parent.stream_class = stream;
1250 ret = create_stream_definitions(td, &file_stream->parent);
1251 if (ret)
1252 return ret;
1253 }
1254 first_packet = 0;
1255
1256 if (file_stream->parent.stream_packet_context) {
1257 /* Read packet context */
1258 ret = generic_rw(&pos->parent, &file_stream->parent.stream_packet_context->p);
1259 if (ret)
1260 return ret;
1261 /* read content size from header */
1262 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("content_size"));
1263 if (len_index >= 0) {
1264 struct definition *field;
1265
1266 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1267 packet_index.content_size = get_unsigned_int(field);
1268 } else {
1269 /* Use file size for packet size */
1270 packet_index.content_size = filestats.st_size * CHAR_BIT;
1271 }
1272
1273 /* read packet size from header */
1274 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("packet_size"));
1275 if (len_index >= 0) {
1276 struct definition *field;
1277
1278 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1279 packet_index.packet_size = get_unsigned_int(field);
1280 } else {
1281 /* Use content size if non-zero, else file size */
1282 packet_index.packet_size = packet_index.content_size ? : filestats.st_size * CHAR_BIT;
1283 }
1284
1285 /* read timestamp begin from header */
1286 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("timestamp_begin"));
1287 if (len_index >= 0) {
1288 struct definition *field;
1289
1290 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1291 packet_index.timestamp_begin = get_unsigned_int(field);
1292 }
1293
1294 /* read timestamp end from header */
1295 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("timestamp_end"));
1296 if (len_index >= 0) {
1297 struct definition *field;
1298
1299 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1300 packet_index.timestamp_end = get_unsigned_int(field);
1301 }
1302
1303 /* read events discarded from header */
1304 len_index = struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("events_discarded"));
1305 if (len_index >= 0) {
1306 struct definition *field;
1307
1308 field = struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
1309 packet_index.events_discarded = get_unsigned_int(field);
1310 packet_index.events_discarded_len = get_int_len(field);
1311 }
1312 } else {
1313 /* Use file size for packet size */
1314 packet_index.content_size = filestats.st_size * CHAR_BIT;
1315 /* Use content size if non-zero, else file size */
1316 packet_index.packet_size = packet_index.content_size ? : filestats.st_size * CHAR_BIT;
1317 }
1318
1319 /* Validate content size and packet size values */
1320 if (packet_index.content_size > packet_index.packet_size) {
1321 fprintf(stderr, "[error] Content size (%" PRIu64 " bits) is larger than packet size (%" PRIu64 " bits).\n",
1322 packet_index.content_size, packet_index.packet_size);
1323 return -EINVAL;
1324 }
1325
1326 if (packet_index.packet_size > ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT) {
1327 fprintf(stderr, "[error] Packet size (%" PRIu64 " bits) is larger than remaining file size (%" PRIu64 " bits).\n",
1328 packet_index.packet_size, ((uint64_t)filestats.st_size - packet_index.offset) * CHAR_BIT);
1329 return -EINVAL;
1330 }
1331
1332 /* Save position after header and context */
1333 packet_index.data_offset = pos->offset;
1334
1335 /* add index to packet array */
1336 g_array_append_val(file_stream->pos.packet_index, packet_index);
1337
1338 pos->mmap_offset += packet_index.packet_size / CHAR_BIT;
1339 }
1340
1341 /* Move pos back to beginning of file */
1342 ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
1343
1344 return 0;
1345 }
1346
1347 static
1348 int create_trace_definitions(struct ctf_trace *td, struct ctf_stream_definition *stream)
1349 {
1350 int ret;
1351
1352 if (td->packet_header_decl) {
1353 struct definition *definition =
1354 td->packet_header_decl->p.definition_new(&td->packet_header_decl->p,
1355 stream->parent_def_scope, 0, 0, "trace.packet.header");
1356 if (!definition) {
1357 ret = -EINVAL;
1358 goto error;
1359 }
1360 stream->trace_packet_header =
1361 container_of(definition, struct definition_struct, p);
1362 stream->parent_def_scope = stream->trace_packet_header->p.scope;
1363 }
1364
1365 return 0;
1366
1367 error:
1368 return ret;
1369 }
1370
1371 /*
1372 * Note: many file streams can inherit from the same stream class
1373 * description (metadata).
1374 */
1375 static
1376 int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags,
1377 void (*packet_seek)(struct stream_pos *pos, size_t index,
1378 int whence))
1379 {
1380 int ret, fd;
1381 struct ctf_file_stream *file_stream;
1382 struct stat statbuf;
1383
1384 fd = openat(td->dirfd, path, flags);
1385 if (fd < 0) {
1386 perror("File stream openat()");
1387 ret = fd;
1388 goto error;
1389 }
1390
1391 /* Don't try to mmap subdirectories. Skip them, return success. */
1392 ret = fstat(fd, &statbuf);
1393 if (ret) {
1394 perror("File stream fstat()");
1395 goto fstat_error;
1396 }
1397 if (S_ISDIR(statbuf.st_mode)) {
1398 fprintf(stderr, "[warning] Skipping directory '%s' found in trace\n", path);
1399 ret = 0;
1400 goto fd_is_dir_ok;
1401 }
1402
1403 file_stream = g_new0(struct ctf_file_stream, 1);
1404 file_stream->pos.last_offset = LAST_OFFSET_POISON;
1405
1406 if (packet_seek) {
1407 file_stream->pos.packet_seek = packet_seek;
1408 } else {
1409 fprintf(stderr, "[error] packet_seek function undefined.\n");
1410 ret = -1;
1411 goto error_def;
1412 }
1413
1414 ctf_init_pos(&file_stream->pos, fd, flags);
1415 ret = create_trace_definitions(td, &file_stream->parent);
1416 if (ret)
1417 goto error_def;
1418 /*
1419 * For now, only a single slock is supported.
1420 */
1421 file_stream->parent.current_clock = td->single_clock;
1422 ret = create_stream_packet_index(td, file_stream);
1423 if (ret)
1424 goto error_index;
1425 /* Add stream file to stream class */
1426 g_ptr_array_add(file_stream->parent.stream_class->streams,
1427 &file_stream->parent);
1428 return 0;
1429
1430 error_index:
1431 if (file_stream->parent.trace_packet_header)
1432 definition_unref(&file_stream->parent.trace_packet_header->p);
1433 error_def:
1434 ctf_fini_pos(&file_stream->pos);
1435 g_free(file_stream);
1436 fd_is_dir_ok:
1437 fstat_error:
1438 close(fd);
1439 error:
1440 return ret;
1441 }
1442
1443 static
1444 int ctf_open_trace_read(struct ctf_trace *td,
1445 const char *path, int flags,
1446 void (*packet_seek)(struct stream_pos *pos, size_t index,
1447 int whence), FILE *metadata_fp)
1448 {
1449 int ret;
1450 struct dirent *dirent;
1451 struct dirent *diriter;
1452 size_t dirent_len;
1453
1454 td->flags = flags;
1455
1456 /* Open trace directory */
1457 td->dir = opendir(path);
1458 if (!td->dir) {
1459 fprintf(stderr, "[error] Unable to open trace directory \"%s\".\n", path);
1460 ret = -ENOENT;
1461 goto error;
1462 }
1463
1464 td->dirfd = open(path, 0);
1465 if (td->dirfd < 0) {
1466 fprintf(stderr, "[error] Unable to open trace directory file descriptor for path \"%s\".\n", path);
1467 perror("Trace directory open");
1468 ret = -errno;
1469 goto error_dirfd;
1470 }
1471 strncpy(td->path, path, sizeof(td->path));
1472 td->path[sizeof(td->path) - 1] = '\0';
1473
1474 /*
1475 * Keep the metadata file separate.
1476 */
1477
1478 ret = ctf_open_trace_metadata_read(td, packet_seek, metadata_fp);
1479 if (ret) {
1480 fprintf(stderr, "[warning] Unable to open trace metadata for path \"%s\".\n", path);
1481 goto error_metadata;
1482 }
1483
1484 /*
1485 * Open each stream: for each file, try to open, check magic
1486 * number, and get the stream ID to add to the right location in
1487 * the stream array.
1488 */
1489
1490 dirent_len = offsetof(struct dirent, d_name) +
1491 fpathconf(td->dirfd, _PC_NAME_MAX) + 1;
1492
1493 dirent = malloc(dirent_len);
1494
1495 for (;;) {
1496 ret = readdir_r(td->dir, dirent, &diriter);
1497 if (ret) {
1498 fprintf(stderr, "[error] Readdir error.\n");
1499 goto readdir_error;
1500 }
1501 if (!diriter)
1502 break;
1503 /* Ignore hidden files, ., .. and metadata. */
1504 if (!strncmp(diriter->d_name, ".", 1)
1505 || !strcmp(diriter->d_name, "..")
1506 || !strcmp(diriter->d_name, "metadata"))
1507 continue;
1508 ret = ctf_open_file_stream_read(td, diriter->d_name,
1509 flags, packet_seek);
1510 if (ret) {
1511 fprintf(stderr, "[error] Open file stream error.\n");
1512 goto readdir_error;
1513 }
1514 }
1515
1516 free(dirent);
1517 return 0;
1518
1519 readdir_error:
1520 free(dirent);
1521 error_metadata:
1522 close(td->dirfd);
1523 error_dirfd:
1524 closedir(td->dir);
1525 error:
1526 return ret;
1527 }
1528
1529 static
1530 struct trace_descriptor *ctf_open_trace(const char *path, int flags,
1531 void (*packet_seek)(struct stream_pos *pos, size_t index,
1532 int whence), FILE *metadata_fp)
1533 {
1534 struct ctf_trace *td;
1535 int ret;
1536
1537 /*
1538 * If packet_seek is NULL, we provide our default version.
1539 */
1540 if (!packet_seek)
1541 packet_seek = ctf_packet_seek;
1542
1543 td = g_new0(struct ctf_trace, 1);
1544
1545 switch (flags & O_ACCMODE) {
1546 case O_RDONLY:
1547 if (!path) {
1548 fprintf(stderr, "[error] Path missing for input CTF trace.\n");
1549 goto error;
1550 }
1551 ret = ctf_open_trace_read(td, path, flags, packet_seek, metadata_fp);
1552 if (ret)
1553 goto error;
1554 break;
1555 case O_RDWR:
1556 fprintf(stderr, "[error] Opening CTF traces for output is not supported yet.\n");
1557 goto error;
1558 default:
1559 fprintf(stderr, "[error] Incorrect open flags.\n");
1560 goto error;
1561 }
1562
1563 return &td->parent;
1564 error:
1565 g_free(td);
1566 return NULL;
1567 }
1568
1569
1570 void ctf_init_mmap_pos(struct ctf_stream_pos *pos,
1571 struct mmap_stream *mmap_info)
1572 {
1573 pos->mmap_offset = 0;
1574 pos->packet_size = 0;
1575 pos->content_size = 0;
1576 pos->content_size_loc = NULL;
1577 pos->fd = mmap_info->fd;
1578 pos->base_mma = NULL;
1579 pos->offset = 0;
1580 pos->dummy = false;
1581 pos->cur_index = 0;
1582 pos->packet_index = NULL;
1583 pos->prot = PROT_READ;
1584 pos->flags = MAP_PRIVATE;
1585 pos->parent.rw_table = read_dispatch_table;
1586 pos->parent.event_cb = ctf_read_event;
1587 }
1588
1589 static
1590 int prepare_mmap_stream_definition(struct ctf_trace *td,
1591 struct ctf_file_stream *file_stream)
1592 {
1593 struct ctf_stream_declaration *stream;
1594 uint64_t stream_id = 0;
1595 int ret;
1596
1597 file_stream->parent.stream_id = stream_id;
1598 if (stream_id >= td->streams->len) {
1599 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared "
1600 "in metadata.\n", stream_id);
1601 ret = -EINVAL;
1602 goto end;
1603 }
1604 stream = g_ptr_array_index(td->streams, stream_id);
1605 if (!stream) {
1606 fprintf(stderr, "[error] Stream %" PRIu64 " is not declared "
1607 "in metadata.\n", stream_id);
1608 ret = -EINVAL;
1609 goto end;
1610 }
1611 file_stream->parent.stream_class = stream;
1612 ret = create_stream_definitions(td, &file_stream->parent);
1613 end:
1614 return ret;
1615 }
1616
1617 static
1618 int ctf_open_mmap_stream_read(struct ctf_trace *td,
1619 struct mmap_stream *mmap_info,
1620 void (*packet_seek)(struct stream_pos *pos, size_t index,
1621 int whence))
1622 {
1623 int ret;
1624 struct ctf_file_stream *file_stream;
1625
1626 file_stream = g_new0(struct ctf_file_stream, 1);
1627 file_stream->pos.last_offset = LAST_OFFSET_POISON;
1628 ctf_init_mmap_pos(&file_stream->pos, mmap_info);
1629
1630 file_stream->pos.packet_seek = packet_seek;
1631
1632 ret = create_trace_definitions(td, &file_stream->parent);
1633 if (ret) {
1634 goto error_def;
1635 }
1636
1637 ret = prepare_mmap_stream_definition(td, file_stream);
1638 if (ret)
1639 goto error_index;
1640
1641 /* Add stream file to stream class */
1642 g_ptr_array_add(file_stream->parent.stream_class->streams,
1643 &file_stream->parent);
1644 return 0;
1645
1646 error_index:
1647 if (file_stream->parent.trace_packet_header)
1648 definition_unref(&file_stream->parent.trace_packet_header->p);
1649 error_def:
1650 g_free(file_stream);
1651 return ret;
1652 }
1653
1654 int ctf_open_mmap_trace_read(struct ctf_trace *td,
1655 struct mmap_stream_list *mmap_list,
1656 void (*packet_seek)(struct stream_pos *pos, size_t index,
1657 int whence),
1658 FILE *metadata_fp)
1659 {
1660 int ret;
1661 struct mmap_stream *mmap_info;
1662
1663 ret = ctf_open_trace_metadata_read(td, ctf_packet_seek, metadata_fp);
1664 if (ret) {
1665 goto error;
1666 }
1667
1668 /*
1669 * for each stream, try to open, check magic number, and get the
1670 * stream ID to add to the right location in the stream array.
1671 */
1672 bt_list_for_each_entry(mmap_info, &mmap_list->head, list) {
1673 ret = ctf_open_mmap_stream_read(td, mmap_info, packet_seek);
1674 if (ret) {
1675 fprintf(stderr, "[error] Open file mmap stream error.\n");
1676 goto error;
1677 }
1678 }
1679
1680 return 0;
1681
1682 error:
1683 return ret;
1684 }
1685
1686 static
1687 struct trace_descriptor *ctf_open_mmap_trace(
1688 struct mmap_stream_list *mmap_list,
1689 void (*packet_seek)(struct stream_pos *pos, size_t index,
1690 int whence),
1691 FILE *metadata_fp)
1692 {
1693 struct ctf_trace *td;
1694 int ret;
1695
1696 if (!metadata_fp) {
1697 fprintf(stderr, "[error] No metadata file pointer associated, "
1698 "required for mmap parsing\n");
1699 goto error;
1700 }
1701 if (!packet_seek) {
1702 fprintf(stderr, "[error] packet_seek function undefined.\n");
1703 goto error;
1704 }
1705 td = g_new0(struct ctf_trace, 1);
1706 ret = ctf_open_mmap_trace_read(td, mmap_list, packet_seek, metadata_fp);
1707 if (ret)
1708 goto error_free;
1709
1710 return &td->parent;
1711
1712 error_free:
1713 g_free(td);
1714 error:
1715 return NULL;
1716 }
1717
1718 static
1719 void ctf_close_file_stream(struct ctf_file_stream *file_stream)
1720 {
1721 ctf_fini_pos(&file_stream->pos);
1722 close(file_stream->pos.fd);
1723 }
1724
1725 static
1726 void ctf_close_trace(struct trace_descriptor *tdp)
1727 {
1728 struct ctf_trace *td = container_of(tdp, struct ctf_trace, parent);
1729 int i;
1730
1731 if (td->streams) {
1732 for (i = 0; i < td->streams->len; i++) {
1733 struct ctf_stream_declaration *stream;
1734 int j;
1735
1736 stream = g_ptr_array_index(td->streams, i);
1737 if (!stream)
1738 continue;
1739 for (j = 0; j < stream->streams->len; j++) {
1740 struct ctf_file_stream *file_stream;
1741 file_stream = container_of(g_ptr_array_index(stream->streams, j), struct ctf_file_stream, parent);
1742 ctf_close_file_stream(file_stream);
1743 }
1744
1745 }
1746 g_ptr_array_free(td->streams, TRUE);
1747 }
1748
1749 if (td->event_declarations) {
1750 for (i = 0; i < td->event_declarations->len; i++) {
1751 struct bt_ctf_event_decl *event;
1752
1753 event = g_ptr_array_index(td->event_declarations, i);
1754 if (event->context_decl)
1755 g_ptr_array_free(event->context_decl, TRUE);
1756 if (event->fields_decl)
1757 g_ptr_array_free(event->fields_decl, TRUE);
1758 if (event->packet_header_decl)
1759 g_ptr_array_free(event->packet_header_decl, TRUE);
1760 if (event->event_context_decl)
1761 g_ptr_array_free(event->event_context_decl, TRUE);
1762 if (event->event_header_decl)
1763 g_ptr_array_free(event->event_header_decl, TRUE);
1764 if (event->packet_context_decl)
1765 g_ptr_array_free(event->packet_context_decl, TRUE);
1766 g_free(event);
1767 }
1768 g_ptr_array_free(td->event_declarations, TRUE);
1769 }
1770 closedir(td->dir);
1771 g_free(td);
1772 }
1773
1774 static
1775 void ctf_set_context(struct trace_descriptor *descriptor,
1776 struct bt_context *ctx)
1777 {
1778 struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
1779 parent);
1780
1781 td->ctx = ctx;
1782 }
1783
1784 static
1785 void ctf_set_handle(struct trace_descriptor *descriptor,
1786 struct bt_trace_handle *handle)
1787 {
1788 struct ctf_trace *td = container_of(descriptor, struct ctf_trace,
1789 parent);
1790
1791 td->handle = handle;
1792 }
1793
1794 void __attribute__((constructor)) ctf_init(void)
1795 {
1796 int ret;
1797
1798 ctf_format.name = g_quark_from_static_string("ctf");
1799 ret = bt_register_format(&ctf_format);
1800 assert(!ret);
1801 }
1802
1803 /* TODO: finalize */
This page took 0.126726 seconds and 4 git commands to generate.