From 33f93973c6b1fb17a8a1c8556d48300b4901ff4c Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Sat, 11 Feb 2017 17:30:46 -0500 Subject: [PATCH] ctf.fs source: add `get-metadata-info` query info action MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The `get-metadata-info` query info action of the ctf.fs source returns, if successful, the (possibly decoded) metadata string and if the metadata file is packetized or not. It only needs the `path` parameter which is the trace directory path (non-recursive). You can test it with the query-info command: babeltrace query-info --source ctf.fs get-metadata-info -p 'path="/path/to/trace"' Signed-off-by: Philippe Proulx Signed-off-by: Jérémie Galarneau --- plugins/ctf/fs/fs.c | 127 ++++++++++++++++++++++++++++++++++++++ plugins/ctf/fs/fs.h | 4 ++ plugins/ctf/fs/metadata.c | 87 ++++++++++++++++++-------- plugins/ctf/fs/metadata.h | 10 +++ plugins/ctf/plugin.c | 1 + 5 files changed, 203 insertions(+), 26 deletions(-) diff --git a/plugins/ctf/fs/fs.c b/plugins/ctf/fs/fs.c index b7b04956..b406ee96 100644 --- a/plugins/ctf/fs/fs.c +++ b/plugins/ctf/fs/fs.c @@ -45,6 +45,7 @@ #define PRINT_ERR_STREAM ctf_fs->error_fp #define PRINT_PREFIX "ctf-fs" #include "print.h" +#define METADATA_TEXT_SIG "/* CTF 1.8" BT_HIDDEN bool ctf_fs_debug; @@ -735,3 +736,129 @@ error: ctf_fs_destroy_data(ctf_fs); return ret; } + +BT_HIDDEN +struct bt_value *ctf_fs_query_info(struct bt_component_class *comp_class, + const char *action, struct bt_value *params) +{ + struct bt_value *results = NULL; + struct bt_value *path_value = NULL; + char *metadata_text = NULL; + FILE *metadata_fp = NULL; + GString *g_metadata_text = NULL; + + if (strcmp(action, "get-metadata-info") == 0) { + int ret; + int bo; + const char *path; + bool is_packetized; + + results = bt_value_map_create(); + if (!results) { + goto error; + } + + if (!bt_value_is_map(params)) { + fprintf(stderr, + "Query info parameters is not a map value object\n"); + goto error; + } + + path_value = bt_value_map_get(params, "path"); + ret = bt_value_string_get(path_value, &path); + if (ret) { + fprintf(stderr, + "Cannot get `path` string parameter\n"); + goto error; + } + + assert(path); + metadata_fp = ctf_fs_metadata_open_file(path); + if (!metadata_fp) { + fprintf(stderr, + "Cannot open trace at path `%s`\n", path); + goto error; + } + + is_packetized = ctf_metadata_is_packetized(metadata_fp, &bo); + + if (is_packetized) { + ret = ctf_metadata_packetized_file_to_buf(NULL, + metadata_fp, (uint8_t **) &metadata_text, bo); + if (ret) { + fprintf(stderr, + "Cannot decode packetized metadata file\n"); + goto error; + } + } else { + long filesize; + + fseek(metadata_fp, 0, SEEK_END); + filesize = ftell(metadata_fp); + rewind(metadata_fp); + metadata_text = malloc(filesize + 1); + if (!metadata_text) { + fprintf(stderr, + "Cannot allocate buffer for metadata text\n"); + goto error; + } + + if (fread(metadata_text, filesize, 1, metadata_fp) != + 1) { + fprintf(stderr, + "Cannot read metadata file\n"); + goto error; + } + + metadata_text[filesize] = '\0'; + } + + g_metadata_text = g_string_new(NULL); + if (!g_metadata_text) { + goto error; + } + + if (strncmp(metadata_text, METADATA_TEXT_SIG, + sizeof(METADATA_TEXT_SIG) - 1) != 0) { + g_string_assign(g_metadata_text, METADATA_TEXT_SIG); + g_string_append(g_metadata_text, " */\n\n"); + } + + g_string_append(g_metadata_text, metadata_text); + + ret = bt_value_map_insert_string(results, "text", + g_metadata_text->str); + if (ret) { + fprintf(stderr, "Cannot insert metadata text into results\n"); + goto error; + } + + ret = bt_value_map_insert_bool(results, "is-packetized", + is_packetized); + if (ret) { + fprintf(stderr, "Cannot insert is packetized into results\n"); + goto error; + } + } else { + fprintf(stderr, "Unknown query info action `%s`\n", action); + goto error; + } + + goto end; + +error: + BT_PUT(results); + +end: + bt_put(path_value); + free(metadata_text); + + if (g_metadata_text) { + g_string_free(g_metadata_text, TRUE); + } + + if (metadata_fp) { + fclose(metadata_fp); + } + return results; +} diff --git a/plugins/ctf/fs/fs.h b/plugins/ctf/fs/fs.h index de572cda..936cfdd0 100644 --- a/plugins/ctf/fs/fs.h +++ b/plugins/ctf/fs/fs.h @@ -126,4 +126,8 @@ enum bt_notification_iterator_status ctf_fs_iterator_next( struct bt_notification *ctf_fs_iterator_get( struct bt_notification_iterator *iterator); +BT_HIDDEN +struct bt_value *ctf_fs_query_info(struct bt_component_class *comp_class, + const char *action, struct bt_value *params); + #endif /* BABELTRACE_PLUGIN_CTF_FS_H */ diff --git a/plugins/ctf/fs/metadata.c b/plugins/ctf/fs/metadata.c index 03309dd3..e531056c 100644 --- a/plugins/ctf/fs/metadata.c +++ b/plugins/ctf/fs/metadata.c @@ -56,6 +56,35 @@ struct packet_header { uint8_t minor; } __attribute__((__packed__)); +BT_HIDDEN +FILE *ctf_fs_metadata_open_file(const char *trace_path) +{ + GString *metadata_path = g_string_new(trace_path); + FILE *fp = NULL; + + if (!metadata_path) { + goto error; + } + + g_string_append(metadata_path, "/" CTF_FS_METADATA_FILENAME); + fp = fopen(metadata_path->str, "rb"); + if (!fp) { + goto error; + } + + goto end; + +error: + if (fp) { + fclose(fp); + fp = NULL; + } + +end: + g_string_free(metadata_path, TRUE); + return fp; +} + static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs, const char *trace_path) { @@ -84,29 +113,31 @@ end: return file; } -static -bool is_packetized(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file) +BT_HIDDEN +bool ctf_metadata_is_packetized(FILE *fp, int *byte_order) { uint32_t magic; size_t len; int ret = 0; - len = fread(&magic, sizeof(magic), 1, file->fp); + len = fread(&magic, sizeof(magic), 1, fp); if (len != 1) { goto end; } - if (magic == TSDL_MAGIC) { - ret = 1; - ctf_fs->metadata->bo = BYTE_ORDER; - } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) { - ret = 1; - ctf_fs->metadata->bo = BYTE_ORDER == BIG_ENDIAN ? - LITTLE_ENDIAN : BIG_ENDIAN; + if (byte_order) { + if (magic == TSDL_MAGIC) { + ret = 1; + *byte_order = BYTE_ORDER; + } else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) { + ret = 1; + *byte_order = BYTE_ORDER == BIG_ENDIAN ? + LITTLE_ENDIAN : BIG_ENDIAN; + } } end: - rewind(file->fp); + rewind(fp); return ret; } @@ -118,7 +149,8 @@ bool is_version_valid(unsigned int major, unsigned int minor) } static -int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp) +int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp, + int byte_order) { struct packet_header header; size_t readlen, writelen, toread; @@ -133,7 +165,7 @@ int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp) goto error; } - if (ctf_fs->metadata->bo != BYTE_ORDER) { + 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); @@ -162,12 +194,14 @@ int decode_packet(struct ctf_fs_component *ctf_fs, FILE *in_fp, FILE *out_fp) } /* Set expected trace UUID if not set; otherwise validate it */ - if (!ctf_fs->metadata->is_uuid_set) { - memcpy(ctf_fs->metadata->uuid, header.uuid, sizeof(header.uuid)); - ctf_fs->metadata->is_uuid_set = true; - } else if (bt_uuid_compare(header.uuid, ctf_fs->metadata->uuid)) { - PERR("Metadata UUID mismatch between packets of the same file\n"); - goto error; + if (ctf_fs) { + if (!ctf_fs->metadata->is_uuid_set) { + memcpy(ctf_fs->metadata->uuid, header.uuid, sizeof(header.uuid)); + ctf_fs->metadata->is_uuid_set = true; + } else if (bt_uuid_compare(header.uuid, ctf_fs->metadata->uuid)) { + PERR("Metadata UUID mismatch between packets of the same file\n"); + goto error; + } } if ((header.content_size / CHAR_BIT) < sizeof(header)) { @@ -218,9 +252,9 @@ end: return ret; } -static -int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file, - uint8_t **buf) +BT_HIDDEN +int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs, + FILE *fp, uint8_t **buf, int byte_order) { FILE *out_fp; size_t size; @@ -235,11 +269,11 @@ int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file * } for (;;) { - if (feof(file->fp) != 0) { + if (feof(fp) != 0) { break; } - tret = decode_packet(ctf_fs, file->fp, out_fp); + tret = decode_packet(ctf_fs, fp, out_fp, byte_order); if (tret) { PERR("Cannot decode packet #%zu\n", packet_index); goto error; @@ -296,9 +330,10 @@ void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs) // yydebug = 1; } - if (is_packetized(ctf_fs, file)) { + if (ctf_metadata_is_packetized(file->fp, &ctf_fs->metadata->bo)) { PDBG("Metadata file \"%s\" is packetized\n", file->path->str); - ret = packetized_file_to_buf(ctf_fs, file, &buf); + ret = ctf_metadata_packetized_file_to_buf(ctf_fs, file->fp, + &buf, ctf_fs->metadata->bo); if (ret) { // log: details goto error; diff --git a/plugins/ctf/fs/metadata.h b/plugins/ctf/fs/metadata.h index 7ed7f069..a8ca942d 100644 --- a/plugins/ctf/fs/metadata.h +++ b/plugins/ctf/fs/metadata.h @@ -40,4 +40,14 @@ void ctf_fs_metadata_fini(struct ctf_fs_metadata *metadata); BT_HIDDEN void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs); +BT_HIDDEN +FILE *ctf_fs_metadata_open_file(const char *trace_path); + +BT_HIDDEN +bool ctf_metadata_is_packetized(FILE *fp, int *byte_order); + +BT_HIDDEN +int ctf_metadata_packetized_file_to_buf(struct ctf_fs_component *ctf_fs, + FILE *fp, uint8_t **buf, int byte_order); + #endif /* CTF_FS_METADATA_H */ diff --git a/plugins/ctf/plugin.c b/plugins/ctf/plugin.c index b79e5073..f91e1a1b 100644 --- a/plugins/ctf/plugin.c +++ b/plugins/ctf/plugin.c @@ -40,6 +40,7 @@ BT_PLUGIN_LICENSE("MIT"); BT_PLUGIN_SOURCE_COMPONENT_CLASS(fs, ctf_fs_iterator_get, ctf_fs_iterator_next); BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESCRIPTION(fs, CTF_FS_COMPONENT_DESCRIPTION); BT_PLUGIN_SOURCE_COMPONENT_CLASS_INIT_METHOD(fs, ctf_fs_init); +BT_PLUGIN_SOURCE_COMPONENT_CLASS_QUERY_INFO_METHOD(fs, ctf_fs_query_info); BT_PLUGIN_SOURCE_COMPONENT_CLASS_DESTROY_METHOD(fs, ctf_fs_destroy); BT_PLUGIN_SOURCE_COMPONENT_CLASS_NOTIFICATION_ITERATOR_INIT_METHOD(fs, ctf_fs_iterator_init); -- 2.34.1