static int ctf_metadata_decoder_packetized_file_stream_to_buf_with_mdec( struct ctf_metadata_decoder *mdec, FILE *fp, char **buf, int byte_order) { FILE *out_fp; size_t size; int ret = 0; int tret; size_t packet_index = 0; out_fp = bt_open_memstream(buf, &size); if (out_fp == NULL) { BT_LOGE("Cannot open memory stream: %s: mdec-addr=%p", strerror(errno), mdec); goto error; } for (;;) { if (feof(fp) != 0) { break; } tret = decode_packet(mdec, fp, out_fp, byte_order); if (tret) { BT_LOGE("Cannot decode packet: index=%zu, mdec-addr=%p", packet_index, mdec); goto error; } packet_index++; } /* Make sure the whole string ends with a null character */ tret = fputc('\0', out_fp); if (tret == EOF) { BT_LOGE("Cannot append '\\0' to the decoded metadata buffer: " "mdec-addr=%p", mdec); goto error; } /* Close stream, which also flushes the buffer */ ret = bt_close_memstream(buf, &size, out_fp); /* * See fclose(3). Further access to out_fp after both success * and error, even through another bt_close_memstream(), results * in undefined behavior. Nullify out_fp to ensure we don't * fclose it twice on error. */ out_fp = NULL; if (ret < 0) { BT_LOGE("Cannot close memory stream: %s: mdec-addr=%p", strerror(errno), mdec); goto error; } goto end; error: ret = -1; if (out_fp) { if (bt_close_memstream(buf, &size, out_fp)) { BT_LOGE("Cannot close memory stream: %s: mdec-addr=%p", strerror(errno), mdec); } } if (*buf) { free(*buf); *buf = NULL; } end: return ret; }
BT_HIDDEN enum lttng_live_iterator_status lttng_live_metadata_update( struct lttng_live_trace *trace) { struct lttng_live_session *session = trace->session; struct lttng_live_metadata *metadata = trace->metadata; struct lttng_live_component *lttng_live = session->lttng_live_msg_iter->lttng_live_comp; ssize_t ret = 0; size_t size, len_read = 0; char *metadata_buf = NULL; FILE *fp = NULL; enum ctf_metadata_decoder_status decoder_status; enum lttng_live_iterator_status status = LTTNG_LIVE_ITERATOR_STATUS_OK; /* No metadata stream yet. */ if (!metadata) { if (session->new_streams_needed) { status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN; } else { session->new_streams_needed = true; status = LTTNG_LIVE_ITERATOR_STATUS_CONTINUE; } goto end; } if (!metadata->trace) { trace->new_metadata_needed = false; } if (!trace->new_metadata_needed) { goto end; } /* Open for writing */ fp = bt_open_memstream(&metadata_buf, &size); if (!fp) { BT_LOGE("Metadata open_memstream: %s", strerror(errno)); goto error; } /* Grab all available metadata. */ do { /* * get_one_metadata_packet returns the number of bytes * received, 0 when we have received everything, a * negative value on error. */ ret = lttng_live_get_one_metadata_packet(trace, fp); if (ret > 0) { len_read += ret; } } while (ret > 0); /* * Consider metadata closed as soon as we get an error reading * it (e.g. cannot be found). */ if (ret < 0) { if (!metadata->closed) { metadata->closed = true; /* * Release our reference on the trace as soon as * we know the metadata stream is not available * anymore. This won't necessarily teardown the * metadata objects immediately, but only when * the data streams are done. */ metadata->trace = NULL; } if (errno == EINTR) { if (lttng_live_graph_is_canceled(lttng_live)) { status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN; goto end; } } } if (bt_close_memstream(&metadata_buf, &size, fp)) { BT_LOGE("bt_close_memstream: %s", strerror(errno)); } ret = 0; fp = NULL; if (len_read == 0) { if (!trace->trace) { status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN; goto end; } trace->new_metadata_needed = false; goto end; } fp = bt_fmemopen(metadata_buf, len_read, "rb"); if (!fp) { BT_LOGE("Cannot memory-open metadata buffer: %s", strerror(errno)); goto error; } /* * The call to ctf_metadata_decoder_decode will append new metadata to * our current trace class. */ decoder_status = ctf_metadata_decoder_decode(metadata->decoder, fp); switch (decoder_status) { case CTF_METADATA_DECODER_STATUS_OK: if (!trace->trace_class) { trace->trace_class = ctf_metadata_decoder_get_ir_trace_class( metadata->decoder); trace->trace = bt_trace_create(trace->trace_class); if (!stream_classes_all_have_default_clock_class( trace->trace_class)) { /* Error logged in function. */ goto error; } trace->clock_class = borrow_any_clock_class(trace->trace_class); } trace->new_metadata_needed = false; break; case CTF_METADATA_DECODER_STATUS_INCOMPLETE: status = LTTNG_LIVE_ITERATOR_STATUS_AGAIN; break; case CTF_METADATA_DECODER_STATUS_ERROR: case CTF_METADATA_DECODER_STATUS_INVAL_VERSION: case CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR: goto error; } goto end; error: status = LTTNG_LIVE_ITERATOR_STATUS_ERROR; end: if (fp) { int closeret; closeret = fclose(fp); if (closeret) { BT_LOGE("Error on fclose"); } } free(metadata_buf); return status; }