+ enum_definition = lookup_enum(&stream->stream_event_header->p, "id", FALSE);
+ if (enum_definition) {
+ id = enum_definition->integer->value._unsigned;
+ }
+ }
+
+ variant = lookup_variant(&stream->stream_event_header->p, "v");
+ if (variant) {
+ integer_definition = lookup_integer(variant, "id", FALSE);
+ if (integer_definition) {
+ id = integer_definition->value._unsigned;
+ }
+ }
+ stream->event_id = id;
+
+ /* lookup timestamp */
+ stream->has_timestamp = 0;
+ integer_definition = lookup_integer(&stream->stream_event_header->p, "timestamp", FALSE);
+ if (integer_definition) {
+ ctf_update_timestamp(stream, integer_definition);
+ stream->has_timestamp = 1;
+ } else {
+ if (variant) {
+ integer_definition = lookup_integer(variant, "timestamp", FALSE);
+ if (integer_definition) {
+ ctf_update_timestamp(stream, integer_definition);
+ stream->has_timestamp = 1;
+ }
+ }
+ }
+ }
+
+ /* Read stream-declared event context */
+ if (stream->stream_event_context) {
+ ret = generic_rw(ppos, &stream->stream_event_context->p);
+ if (ret)
+ goto error;
+ }
+
+ if (unlikely(id >= stream_class->events_by_id->len)) {
+ fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
+ return -EINVAL;
+ }
+ event = g_ptr_array_index(stream->events_by_id, id);
+ if (unlikely(!event)) {
+ fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
+ return -EINVAL;
+ }
+
+ /* Read event-declared event context */
+ if (event->event_context) {
+ ret = generic_rw(ppos, &event->event_context->p);
+ if (ret)
+ goto error;
+ }
+
+ /* Read event payload */
+ if (likely(event->event_fields)) {
+ ret = generic_rw(ppos, &event->event_fields->p);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
+ return ret;
+}
+
+static
+int ctf_write_event(struct stream_pos *pos, struct ctf_stream *stream)
+{
+ struct ctf_stream_class *stream_class = stream->stream_class;
+ struct ctf_stream_event *event;
+ uint64_t id;
+ int ret;
+
+ id = stream->event_id;
+
+ /* print event header */
+ if (likely(stream->stream_event_header)) {
+ ret = generic_rw(pos, &stream->stream_event_header->p);
+ if (ret)
+ goto error;
+ }
+
+ /* print stream-declared event context */
+ if (stream->stream_event_context) {
+ ret = generic_rw(pos, &stream->stream_event_context->p);
+ if (ret)
+ goto error;
+ }
+
+ if (unlikely(id >= stream_class->events_by_id->len)) {
+ fprintf(stderr, "[error] Event id %" PRIu64 " is outside range.\n", id);
+ return -EINVAL;
+ }
+ event = g_ptr_array_index(stream->events_by_id, id);
+ if (unlikely(!event)) {
+ fprintf(stderr, "[error] Event id %" PRIu64 " is unknown.\n", id);
+ return -EINVAL;
+ }
+
+ /* print event-declared event context */
+ if (event->event_context) {
+ ret = generic_rw(pos, &event->event_context->p);
+ if (ret)
+ goto error;
+ }
+
+ /* Read and print event payload */
+ if (likely(event->event_fields)) {
+ ret = generic_rw(pos, &event->event_fields->p);
+ if (ret)
+ goto error;
+ }
+
+ return 0;
+
+error:
+ fprintf(stderr, "[error] Unexpected end of stream. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
+ return ret;
+}
+
+void ctf_init_pos(struct ctf_stream_pos *pos, int fd, int open_flags)
+{
+ pos->fd = fd;
+ pos->mmap_offset = 0;
+ pos->packet_size = 0;
+ pos->content_size = 0;
+ pos->content_size_loc = NULL;
+ pos->base = NULL;
+ pos->offset = 0;
+ pos->dummy = false;
+ pos->cur_index = 0;
+ if (fd >= 0)
+ pos->packet_index = g_array_new(FALSE, TRUE,
+ sizeof(struct packet_index));
+ else
+ pos->packet_index = NULL;
+ switch (open_flags & O_ACCMODE) {
+ case O_RDONLY:
+ pos->prot = PROT_READ;
+ pos->flags = MAP_PRIVATE;
+ pos->parent.rw_table = read_dispatch_table;
+ pos->parent.event_cb = ctf_read_event;
+ break;
+ case O_RDWR:
+ pos->prot = PROT_WRITE; /* Write has priority */
+ pos->flags = MAP_SHARED;
+ pos->parent.rw_table = write_dispatch_table;
+ pos->parent.event_cb = ctf_write_event;
+ if (fd >= 0)
+ ctf_packet_seek(&pos->parent, 0, SEEK_SET); /* position for write */
+ break;
+ default:
+ assert(0);
+ }
+}
+
+void ctf_fini_pos(struct ctf_stream_pos *pos)
+{
+ int ret;
+
+ if (pos->prot == PROT_WRITE && pos->content_size_loc)
+ *pos->content_size_loc = pos->offset;