BT_HIDDEN struct bt_value *bt_attributes_get_field_value(struct bt_value *attr_obj, uint64_t index) { struct bt_value *value_obj = NULL; struct bt_value *attr_field_obj = NULL; if (!attr_obj) { BT_LOGW_STR("Invalid parameter: attributes object is NULL."); goto end; } attr_field_obj = bt_value_array_get(attr_obj, index); if (!attr_field_obj) { BT_LOGE("Cannot get attributes object's array value's element by index: " "value-addr=%p, index=%" PRIu64, attr_obj, index); goto end; } value_obj = bt_value_array_get(attr_field_obj, BT_ATTR_VALUE_INDEX); if (!value_obj) { BT_LOGE("Cannot get attribute array value's element by index: " "value-addr=%p, index=%" PRIu64, attr_field_obj, (uint64_t) BT_ATTR_VALUE_INDEX); } end: BT_PUT(attr_field_obj); return value_obj; }
int bt_ctf_event_class_get_payload_type_field_by_index( struct bt_ctf_event_class *event_class, const char **field_name, struct bt_ctf_field_type **field_type, uint64_t index) { int ret; if (!event_class) { BT_LOGW_STR("Invalid parameter: event class is NULL."); ret = -1; goto end; } if (!event_class->common.payload_field_type) { BT_LOGV("Event class has no payload field type: " "addr=%p, name=\"%s\", id=%" PRId64 ", index=%" PRIu64, event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class), index); ret = -1; goto end; } BT_ASSERT(bt_ctf_field_type_common_get_type_id( event_class->common.payload_field_type) == BT_CTF_FIELD_TYPE_ID_STRUCT); ret = bt_ctf_field_type_structure_get_field_by_index( (void *) event_class->common.payload_field_type, field_name, (void *) field_type, index); end: return ret; }
int64_t bt_ctf_event_class_get_payload_type_field_count( struct bt_ctf_event_class *event_class) { int64_t ret; if (!event_class) { BT_LOGW_STR("Invalid parameter: event class is NULL."); ret = (int64_t) -1; goto end; } if (!event_class->common.payload_field_type) { BT_LOGV("Event class has no payload field type: " "addr=%p, name=\"%s\", id=%" PRId64, event_class, bt_ctf_event_class_get_name(event_class), bt_ctf_event_class_get_id(event_class)); ret = (int64_t) -1; goto end; } BT_ASSERT(bt_ctf_field_type_common_get_type_id( event_class->common.payload_field_type) == BT_CTF_FIELD_TYPE_ID_STRUCT); ret = bt_ctf_field_type_common_structure_get_field_count( event_class->common.payload_field_type); end: return ret; }
struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name) { struct bt_ctf_event_class *ctf_event_class = NULL; int ret; if (!name) { BT_LOGW_STR("Invalid parameter: name is NULL."); goto error; } BT_LOGD("Creating event class object: name=\"%s\"", name); ctf_event_class = g_new0(struct bt_ctf_event_class, 1); if (!ctf_event_class) { BT_LOGE_STR("Failed to allocate one event class."); goto error; } ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class), name, bt_ctf_event_class_destroy, (bt_ctf_field_type_structure_create_func) bt_ctf_field_type_structure_create); if (ret) { goto error; } goto end; error: bt_ctf_object_put_ref(ctf_event_class); end: return ctf_event_class; }
struct bt_stream *bt_event_get_stream(struct bt_event *event) { struct bt_stream *stream = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } /* * If the event has a parent, then this is its (writer) stream. * If the event has no parent, then if it has a packet, this * is its (non-writer) stream. */ if (event->base.parent) { stream = (struct bt_stream *) bt_object_get_parent(event); } else { if (event->packet) { stream = bt_get(event->packet->stream); } } end: return stream; }
struct bt_value *bt_value_string_create_init(const char *val) { struct bt_value_string *string_obj = NULL; if (!val) { BT_LOGW_STR("Invalid parameter: value is NULL."); goto end; } BT_LOGD("Creating string value object: val-len=%zu", strlen(val)); string_obj = g_new0(struct bt_value_string, 1); if (!string_obj) { BT_LOGE_STR("Failed to allocate one string object."); goto end; } string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING); string_obj->gstr = g_string_new(val); if (!string_obj->gstr) { BT_LOGE_STR("Failed to allocate a GString."); g_free(string_obj); string_obj = NULL; goto end; } BT_LOGD("Created string value object: addr=%p", string_obj); end: return (void *) string_obj; }
static void print_python_traceback_warn(void) { if (BT_LOG_ON_WARN && Py_IsInitialized() && PyErr_Occurred()) { BT_LOGW_STR("Exception occured: traceback: "); PyErr_Print(); } }
struct bt_event_class *bt_event_get_class(struct bt_event *event) { struct bt_event_class *event_class = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } event_class = bt_get(bt_event_borrow_event_class(event)); end: return event_class; }
bt_bool bt_port_is_connected(struct bt_port *port) { int ret; if (!port) { BT_LOGW_STR("Invalid parameter: port is NULL."); ret = -1; goto end; } ret = port->connection ? 1 : 0; end: return ret; }
struct bt_field *bt_event_get_payload_by_index( struct bt_event *event, uint64_t index) { struct bt_field *field = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } field = bt_field_structure_get_field_by_index(event->fields_payload, index); end: return field; }
BT_HIDDEN struct bt_port *bt_port_create(struct bt_component *parent_component, enum bt_port_type type, const char *name, void *user_data) { struct bt_port *port = NULL; assert(name); assert(parent_component); assert(type == BT_PORT_TYPE_INPUT || type == BT_PORT_TYPE_OUTPUT); if (strlen(name) == 0) { BT_LOGW_STR("Invalid parameter: name is an empty string."); goto end; } port = g_new0(struct bt_port, 1); if (!port) { BT_LOGE_STR("Failed to allocate one port."); goto end; } BT_LOGD("Creating port for component: " "comp-addr=%p, comp-name=\"%s\", port-type=%s, " "port-name=\"%s\"", parent_component, bt_component_get_name(parent_component), bt_port_type_string(type), name); bt_object_init(port, bt_port_destroy); port->name = g_string_new(name); if (!port->name) { BT_LOGE_STR("Failed to allocate one GString."); BT_PUT(port); goto end; } port->type = type; port->user_data = user_data; bt_object_set_parent(port, &parent_component->base); BT_LOGD("Created port for component: " "comp-addr=%p, comp-name=\"%s\", port-type=%s, " "port-name=\"%s\", port-addr=%p", parent_component, bt_component_get_name(parent_component), bt_port_type_string(type), name, port); end: return port; }
struct bt_connection *bt_port_get_connection(struct bt_port *port) { struct bt_connection *connection = NULL; if (!port) { BT_LOGW_STR("Invalid parameter: port is NULL."); goto end; } if (!port->connection) { /* Not an error: means disconnected */ goto end; } connection = bt_get(port->connection); end: return connection; }
BT_HIDDEN const char *bt_attributes_get_field_name(struct bt_value *attr_obj, uint64_t index) { int rc; const char *ret = NULL; struct bt_value *attr_field_obj = NULL; struct bt_value *attr_field_name_obj = NULL; if (!attr_obj) { BT_LOGW_STR("Invalid parameter: attributes object is NULL."); goto end; } attr_field_obj = bt_value_array_get(attr_obj, index); if (!attr_field_obj) { BT_LOGE("Cannot get attributes object's array value's element by index: " "value-addr=%p, index=%" PRIu64, attr_obj, index); goto end; } attr_field_name_obj = bt_value_array_get(attr_field_obj, BT_ATTR_NAME_INDEX); if (!attr_field_name_obj) { BT_LOGE("Cannot get attribute array value's element by index: " "value-addr=%p, index=%" PRIu64, attr_field_obj, (uint64_t) BT_ATTR_NAME_INDEX); goto end; } rc = bt_value_string_get(attr_field_name_obj, &ret); if (rc) { BT_LOGE("Cannot get raw value from string value: value-addr=%p", attr_field_name_obj); ret = NULL; } end: BT_PUT(attr_field_name_obj); BT_PUT(attr_field_obj); return ret; }
struct bt_field *bt_event_get_payload(struct bt_event *event, const char *name) { struct bt_field *field = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } if (name) { field = bt_field_structure_get_field_by_name( event->fields_payload, name); } else { field = event->fields_payload; bt_get(field); } end: return field; }
int bt_port_disconnect(struct bt_port *port) { int ret = 0; if (!port) { BT_LOGW_STR("Invalid parameter: port is NULL."); ret = -1; goto end; } if (port->connection) { bt_connection_end(port->connection, true); BT_LOGV("Disconnected port: " "port-addr=%p, port-name=\"%s\"", port, bt_port_get_name(port)); } end: return ret; }
BT_HIDDEN int bt_attributes_freeze(struct bt_value *attr_obj) { uint64_t i; int64_t count; int ret = 0; if (!attr_obj) { BT_LOGW_STR("Invalid parameter: attributes object is NULL."); ret = -1; goto end; } BT_LOGD("Freezing attributes object: value-addr=%p", attr_obj); count = bt_value_array_size(attr_obj); assert(count >= 0); /* * We do not freeze the array value object itself here, since * internal stuff could need to modify/add attributes. Each * attribute is frozen one by one. */ for (i = 0; i < count; ++i) { struct bt_value *obj = NULL; obj = bt_attributes_get_field_value(attr_obj, i); if (!obj) { BT_LOGE("Cannot get attributes object's field value by index: " "value-addr=%p, index=%" PRIu64, attr_obj, i); ret = -1; goto end; } bt_value_freeze(obj); BT_PUT(obj); } end: return ret; }
struct bt_packet *bt_event_get_packet(struct bt_event *event) { struct bt_packet *packet = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } if (!event->packet) { BT_LOGV("Event has no current packet: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); goto end; } packet = bt_get(event->packet); end: return packet; }
int bt_private_port_remove_from_component( struct bt_private_port *private_port) { int ret = 0; struct bt_port *port = bt_port_from_private(private_port); struct bt_component *comp = NULL; if (!port) { BT_LOGW_STR("Invalid parameter: private port is NULL."); ret = -1; goto end; } comp = (void *) bt_object_get_parent(port); /* bt_component_remove_port() logs details */ ret = bt_component_remove_port(comp, port); end: bt_put(comp); return ret; }
struct bt_field *bt_event_get_event_payload(struct bt_event *event) { struct bt_field *payload = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } if (!event->fields_payload) { BT_LOGV("Event has no current payload field: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); goto end; } payload = event->fields_payload; bt_get(payload); end: return payload; }
struct bt_field *bt_event_get_stream_event_context( struct bt_event *event) { struct bt_field *stream_event_context = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } if (!event->stream_event_context) { BT_LOGV("Event has no current stream event context field: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); goto end; } stream_event_context = event->stream_event_context; end: return bt_get(stream_event_context); }
struct bt_field *bt_event_get_header( struct bt_event *event) { struct bt_field *header = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); goto end; } if (!event->event_header) { BT_LOGV("Event has no current header field: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); goto end; } header = event->event_header; bt_get(header); end: return header; }
int bt_event_set_stream_event_context(struct bt_event *event, struct bt_field *stream_event_context) { int ret = 0; struct bt_field_type *field_type = NULL; struct bt_stream_class *stream_class = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } stream_class = bt_event_class_get_stream_class(event->event_class); /* * We should not have been able to create the event without associating * the event class to a stream class. */ assert(stream_class); if (stream_event_context) { field_type = bt_field_get_type(stream_event_context); if (bt_field_type_compare(field_type, stream_class->event_context_type)) { BT_LOGW("Invalid parameter: stream event context field type is different from the expected field type: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } } else { if (stream_class->event_context_type) { BT_LOGW("Invalid parameter: setting no stream event context but stream event context field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "stream-event-context-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_class->event_context_type); ret = -1; goto end; } } bt_get(stream_event_context); BT_MOVE(event->stream_event_context, stream_event_context); BT_LOGV("Set event's stream event context field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "stream-event-context-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_event_context); end: BT_PUT(stream_class); bt_put(field_type); return ret; }
struct bt_event *bt_event_create(struct bt_event_class *event_class) { int ret; enum bt_validation_flag validation_flags = BT_VALIDATION_FLAG_STREAM | BT_VALIDATION_FLAG_EVENT; struct bt_event *event = NULL; struct bt_trace *trace = NULL; struct bt_stream_class *stream_class = NULL; struct bt_field_type *packet_header_type = NULL; struct bt_field_type *packet_context_type = NULL; struct bt_field_type *event_header_type = NULL; struct bt_field_type *stream_event_ctx_type = NULL; struct bt_field_type *event_context_type = NULL; struct bt_field_type *event_payload_type = NULL; struct bt_field *event_header = NULL; struct bt_field *stream_event_context = NULL; struct bt_field *event_context = NULL; struct bt_field *event_payload = NULL; struct bt_value *environment = NULL; struct bt_validation_output validation_output = { 0 }; int trace_valid = 0; BT_LOGD("Creating event object: event-class-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event_class, bt_event_class_get_name(event_class), bt_event_class_get_id(event_class)); if (!event_class) { BT_LOGW_STR("Invalid parameter: event class is NULL."); goto error; } stream_class = bt_event_class_get_stream_class(event_class); /* * We disallow the creation of an event if its event class has not been * associated to a stream class. */ if (!stream_class) { BT_LOGW_STR("Event class is not part of a stream class."); goto error; } /* The event class was frozen when added to its stream class */ assert(event_class->frozen); /* Validate the trace (if any), the stream class, and the event class */ trace = bt_stream_class_get_trace(stream_class); if (trace) { BT_LOGD_STR("Event's class is part of a trace."); packet_header_type = bt_trace_get_packet_header_type(trace); trace_valid = trace->valid; assert(trace_valid); environment = trace->environment; } packet_context_type = bt_stream_class_get_packet_context_type( stream_class); event_header_type = bt_stream_class_get_event_header_type( stream_class); stream_event_ctx_type = bt_stream_class_get_event_context_type( stream_class); event_context_type = bt_event_class_get_context_type(event_class); event_payload_type = bt_event_class_get_payload_type(event_class); ret = bt_validate_class_types(environment, packet_header_type, packet_context_type, event_header_type, stream_event_ctx_type, event_context_type, event_payload_type, trace_valid, stream_class->valid, event_class->valid, &validation_output, validation_flags); BT_PUT(packet_header_type); BT_PUT(packet_context_type); BT_PUT(event_header_type); BT_PUT(stream_event_ctx_type); BT_PUT(event_context_type); BT_PUT(event_payload_type); if (ret) { /* * This means something went wrong during the validation * process, not that the objects are invalid. */ BT_LOGE("Failed to validate event and parents: ret=%d", ret); goto error; } if ((validation_output.valid_flags & validation_flags) != validation_flags) { /* Invalid trace/stream class/event class */ BT_LOGW("Invalid trace, stream class, or event class: " "valid-flags=0x%x", validation_output.valid_flags); goto error; } /* * At this point we know the trace (if associated to the stream * class), the stream class, and the event class, with their * current types, are valid. We may proceed with creating * the event. */ event = g_new0(struct bt_event, 1); if (!event) { BT_LOGE_STR("Failed to allocate one event."); goto error; } bt_object_init(event, bt_event_destroy); /* * event does not share a common ancestor with the event class; it has * to guarantee its existence by holding a reference. This reference * shall be released once the event is associated to a stream since, * from that point, the event and its class will share the same * lifetime. */ event->event_class = bt_get(event_class); event->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, bt_put, bt_put); if (validation_output.event_header_type) { BT_LOGD("Creating initial event header field: ft-addr=%p", validation_output.event_header_type); event_header = bt_field_create(validation_output.event_header_type); if (!event_header) { BT_LOGE_STR("Cannot create initial event header field object."); goto error; } } if (validation_output.stream_event_ctx_type) { BT_LOGD("Creating initial stream event context field: ft-addr=%p", validation_output.stream_event_ctx_type); stream_event_context = bt_field_create( validation_output.stream_event_ctx_type); if (!stream_event_context) { BT_LOGE_STR("Cannot create initial stream event context field object."); goto error; } } if (validation_output.event_context_type) { BT_LOGD("Creating initial event context field: ft-addr=%p", validation_output.event_context_type); event_context = bt_field_create( validation_output.event_context_type); if (!event_context) { BT_LOGE_STR("Cannot create initial event context field object."); goto error; } } if (validation_output.event_payload_type) { BT_LOGD("Creating initial event payload field: ft-addr=%p", validation_output.event_payload_type); event_payload = bt_field_create( validation_output.event_payload_type); if (!event_payload) { BT_LOGE_STR("Cannot create initial event payload field object."); goto error; } } /* * At this point all the fields are created, potentially from * validated copies of field types, so that the field types and * fields can be replaced in the trace, stream class, * event class, and created event. */ bt_validation_replace_types(trace, stream_class, event_class, &validation_output, validation_flags); BT_MOVE(event->event_header, event_header); BT_MOVE(event->stream_event_context, stream_event_context); BT_MOVE(event->context_payload, event_context); BT_MOVE(event->fields_payload, event_payload); /* * Put what was not moved in bt_validation_replace_types(). */ bt_validation_output_put_types(&validation_output); /* * Freeze the stream class since the event header must not be changed * anymore. */ bt_stream_class_freeze(stream_class); /* * Mark stream class, and event class as valid since * they're all frozen now. */ stream_class->valid = 1; event_class->valid = 1; /* Put stuff we borrowed from the event class */ BT_PUT(stream_class); BT_PUT(trace); BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event_class)); return event; error: bt_validation_output_put_types(&validation_output); BT_PUT(event); BT_PUT(stream_class); BT_PUT(trace); BT_PUT(event_header); BT_PUT(stream_event_context); BT_PUT(event_context); BT_PUT(event_payload); assert(!packet_header_type); assert(!packet_context_type); assert(!event_header_type); assert(!stream_event_ctx_type); assert(!event_context_type); assert(!event_payload_type); return event; }
int bt_event_set_event_context(struct bt_event *event, struct bt_field *context) { int ret = 0; struct bt_field_type *field_type = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } if (context) { field_type = bt_field_get_type(context); if (bt_field_type_compare(field_type, event->event_class->context)) { BT_LOGW("Invalid parameter: context field type is different from the expected field type: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } } else { if (event->event_class->context) { BT_LOGW("Invalid parameter: setting no event context but event context field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "event-context-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), event->event_class->context); ret = -1; goto end; } } bt_put(event->context_payload); event->context_payload = bt_get(context); BT_LOGV("Set event's context field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "context-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), context); end: bt_put(field_type); return ret; }
int bt_event_set_header(struct bt_event *event, struct bt_field *header) { int ret = 0; struct bt_field_type *field_type = NULL; struct bt_stream_class *stream_class = NULL; if (!event) { BT_LOGW_STR("Invalid parameter: event is NULL."); ret = -1; goto end; } if (event->frozen) { BT_LOGW("Invalid parameter: event is frozen: addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } stream_class = (struct bt_stream_class *) bt_object_get_parent( event->event_class); /* * Ensure the provided header's type matches the one registered to the * stream class. */ if (header) { field_type = bt_field_get_type(header); if (bt_field_type_compare(field_type, stream_class->event_header_type)) { BT_LOGW("Invalid parameter: header field type is different from the expected field type: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64, event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class)); ret = -1; goto end; } } else { if (stream_class->event_header_type) { BT_LOGW("Invalid parameter: setting no event header but event header field type is not NULL: " "event-addr=%p, event-class-name=\"%s\", " "event-class-id=%" PRId64 ", " "event-header-ft-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), stream_class->event_header_type); ret = -1; goto end; } } bt_put(event->event_header); event->event_header = bt_get(header); BT_LOGV("Set event's header field: event-addr=%p, " "event-class-name=\"%s\", event-class-id=%" PRId64 ", " "header-field-addr=%p", event, bt_event_class_get_name(event->event_class), bt_event_class_get_id(event->event_class), header); end: bt_put(stream_class); bt_put(field_type); return ret; }
static int decode_packet(struct ctf_metadata_decoder *mdec, FILE *in_fp, FILE *out_fp, int byte_order) { struct packet_header header; size_t readlen, writelen, toread; uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */ int ret = 0; const long offset = ftell(in_fp); if (offset < 0) { BT_LOGE_ERRNO("Failed to get current metadata file position", "."); goto error; } BT_LOGV("Decoding metadata packet: mdec-addr=%p, offset=%ld", mdec, offset); readlen = fread(&header, sizeof(header), 1, in_fp); if (feof(in_fp) != 0) { BT_LOGV("Reached end of file: offset=%ld", ftell(in_fp)); goto end; } if (readlen < 1) { BT_LOGV("Cannot decode metadata packet: offset=%ld", offset); goto error; } if (byte_order != BYTE_ORDER) { header.magic = GUINT32_SWAP_LE_BE(header.magic); header.checksum = GUINT32_SWAP_LE_BE(header.checksum); header.content_size = GUINT32_SWAP_LE_BE(header.content_size); header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size); } if (header.compression_scheme) { BT_LOGE("Metadata packet compression is not supported as of this version: " "compression-scheme=%u, offset=%ld", (unsigned int) header.compression_scheme, offset); goto error; } if (header.encryption_scheme) { BT_LOGE("Metadata packet encryption is not supported as of this version: " "encryption-scheme=%u, offset=%ld", (unsigned int) header.encryption_scheme, offset); goto error; } if (header.checksum || header.checksum_scheme) { BT_LOGE("Metadata packet checksum verification is not supported as of this version: " "checksum-scheme=%u, checksum=%x, offset=%ld", (unsigned int) header.checksum_scheme, header.checksum, offset); goto error; } if (!is_version_valid(header.major, header.minor)) { BT_LOGE("Invalid metadata packet version: " "version=%u.%u, offset=%ld", header.major, header.minor, offset); goto error; } /* Set expected trace UUID if not set; otherwise validate it */ if (mdec) { if (!mdec->is_uuid_set) { memcpy(mdec->uuid, header.uuid, sizeof(header.uuid)); mdec->is_uuid_set = true; } else if (bt_uuid_compare(header.uuid, mdec->uuid)) { BT_LOGE("Metadata UUID mismatch between packets of the same stream: " "packet-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", " "expected-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", " "offset=%ld", (unsigned int) header.uuid[0], (unsigned int) header.uuid[1], (unsigned int) header.uuid[2], (unsigned int) header.uuid[3], (unsigned int) header.uuid[4], (unsigned int) header.uuid[5], (unsigned int) header.uuid[6], (unsigned int) header.uuid[7], (unsigned int) header.uuid[8], (unsigned int) header.uuid[9], (unsigned int) header.uuid[10], (unsigned int) header.uuid[11], (unsigned int) header.uuid[12], (unsigned int) header.uuid[13], (unsigned int) header.uuid[14], (unsigned int) header.uuid[15], (unsigned int) mdec->uuid[0], (unsigned int) mdec->uuid[1], (unsigned int) mdec->uuid[2], (unsigned int) mdec->uuid[3], (unsigned int) mdec->uuid[4], (unsigned int) mdec->uuid[5], (unsigned int) mdec->uuid[6], (unsigned int) mdec->uuid[7], (unsigned int) mdec->uuid[8], (unsigned int) mdec->uuid[9], (unsigned int) mdec->uuid[10], (unsigned int) mdec->uuid[11], (unsigned int) mdec->uuid[12], (unsigned int) mdec->uuid[13], (unsigned int) mdec->uuid[14], (unsigned int) mdec->uuid[15], offset); goto error; } } if ((header.content_size / CHAR_BIT) < sizeof(header)) { BT_LOGE("Bad metadata packet content size: content-size=%u, " "offset=%ld", header.content_size, offset); goto error; } toread = header.content_size / CHAR_BIT - sizeof(header); for (;;) { size_t loop_read; loop_read = MIN(sizeof(buf) - 1, toread); readlen = fread(buf, sizeof(uint8_t), loop_read, in_fp); if (ferror(in_fp)) { BT_LOGE("Cannot read metadata packet buffer: " "offset=%ld, read-size=%zu", ftell(in_fp), loop_read); goto error; } if (readlen > loop_read) { BT_LOGE("fread returned more byte than expected: " "read-size-asked=%zu, read-size-returned=%zu", loop_read, readlen); goto error; } writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp); if (writelen < readlen || ferror(out_fp)) { BT_LOGE("Cannot write decoded metadata text to buffer: " "read-offset=%ld, write-size=%zu", ftell(in_fp), readlen); goto error; } toread -= readlen; if (toread == 0) { int fseek_ret; /* Read leftover padding */ toread = (header.packet_size - header.content_size) / CHAR_BIT; fseek_ret = fseek(in_fp, toread, SEEK_CUR); if (fseek_ret < 0) { BT_LOGW_STR("Missing padding at the end of the metadata stream."); } break; } } goto end; error: ret = -1; end: return ret; }