ctf plugin: add CTF metadata decoder API
[babeltrace.git] / plugins / ctf / fs / metadata.c
index 5c64113c3b5d7eef3f3b9e2b478ae8151ecbd427..a728abbfba6d1b50eaa13e8724798644ec7f78d6 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <assert.h>
 #include <glib.h>
 #include <babeltrace/compat/uuid.h>
 #include <babeltrace/compat/memstream.h>
 #include "fs.h"
 #include "file.h"
 #include "metadata.h"
-#include "../common/metadata/ast.h"
-#include "../common/metadata/scanner.h"
-
-#define TSDL_MAGIC     0x75d11d57
+#include "../common/metadata/decoder.h"
 
 #define NSEC_PER_SEC 1000000000LL
 
-struct packet_header {
-       uint32_t magic;
-       uint8_t  uuid[16];
-       uint32_t checksum;
-       uint32_t content_size;
-       uint32_t packet_size;
-       uint8_t  compression_scheme;
-       uint8_t  encryption_scheme;
-       uint8_t  checksum_scheme;
-       uint8_t  major;
-       uint8_t  minor;
-} __attribute__((__packed__));
-
 BT_HIDDEN
 FILE *ctf_fs_metadata_open_file(const char *trace_path)
 {
@@ -115,318 +100,40 @@ end:
        return 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, fp);
-       if (len != 1) {
-               goto end;
-       }
-
-       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(fp);
-
-       return ret;
-}
-
-static
-bool is_version_valid(unsigned int major, unsigned int minor)
-{
-       return major == 1 && minor == 8;
-}
-
-static
-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;
-       uint8_t buf[512 + 1];   /* + 1 for debug-mode \0 */
-       int ret = 0;
-
-       readlen = fread(&header, sizeof(header), 1, in_fp);
-       if (feof(in_fp) != 0) {
-               goto end;
-       }
-       if (readlen < 1) {
-               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) {
-               PERR("Metadata packet compression not supported yet\n");
-               goto error;
-       }
-
-       if (header.encryption_scheme) {
-               PERR("Metadata packet encryption not supported yet\n");
-               goto error;
-       }
-
-       if (header.checksum || header.checksum_scheme) {
-               PERR("Metadata packet checksum verification not supported yet\n");
-               goto error;
-       }
-
-       if (!is_version_valid(header.major, header.minor)) {
-               PERR("Invalid metadata version: %u.%u\n", header.major,
-                       header.minor);
-               goto error;
-       }
-
-       /* Set expected trace UUID if not set; otherwise validate it */
-       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)) {
-               PERR("Bad metadata packet content size: %u\n",
-                       header.content_size);
-               goto error;
-       }
-
-       toread = header.content_size / CHAR_BIT - sizeof(header);
-
-       for (;;) {
-               readlen = fread(buf, sizeof(uint8_t),
-                       MIN(sizeof(buf) - 1, toread), in_fp);
-               if (ferror(in_fp)) {
-                       PERR("Cannot read metadata packet buffer (at position %ld)\n",
-                               ftell(in_fp));
-                       goto error;
-               }
-
-               writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp);
-               if (writelen < readlen || ferror(out_fp)) {
-                       PERR("Cannot write decoded metadata text to buffer\n");
-                       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) {
-                               PWARN("Missing padding at the end of the metadata file\n");
-                       }
-
-                       break;
-               }
-       }
-
-       goto end;
-
-error:
-       ret = -1;
-
-end:
-       return ret;
-}
-
-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;
-       int ret = 0;
-       int tret;
-       size_t packet_index = 0;
-
-       out_fp = babeltrace_open_memstream((char **) buf, &size);
-       if (out_fp == NULL) {
-               PERR("Cannot open memory stream: %s\n", strerror(errno));
-               goto error;
-       }
-
-       for (;;) {
-               if (feof(fp) != 0) {
-                       break;
-               }
-
-               tret = decode_packet(ctf_fs, fp, out_fp, byte_order);
-               if (tret) {
-                       PERR("Cannot decode packet #%zu\n", packet_index);
-                       goto error;
-               }
-
-               packet_index++;
-       }
-
-       /* Make sure the whole string ends with a null character */
-       tret = fputc('\0', out_fp);
-       if (tret == EOF) {
-               PERR("Cannot append '\\0' to the decoded metadata buffer\n");
-               goto error;
-       }
-
-       /* Close stream, which also flushes the buffer */
-       ret = babeltrace_close_memstream((char **) buf, &size, out_fp);
-       if (ret < 0) {
-               PERR("Cannot close memory stream: %s\n", strerror(errno));
-               goto error;
-       }
-
-       goto end;
-
-error:
-       ret = -1;
-
-       if (out_fp) {
-               babeltrace_close_memstream((char **) buf, &size, out_fp);
-       }
-
-       if (*buf) {
-               free(*buf);
-       }
-
-end:
-       return ret;
-}
-
 int ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs)
 {
        int ret = 0;
-       struct ctf_fs_file *file = get_file(ctf_fs, ctf_fs->trace_path->str);
-       struct ctf_scanner *scanner = NULL;
-       uint8_t *buf = NULL;
-       char *cbuf;
+       struct ctf_fs_file *file = NULL;
+       struct ctf_metadata_decoder *metadata_decoder = NULL;
 
+       file = get_file(ctf_fs, ctf_fs->trace_path->str);
        if (!file) {
                PERR("Cannot create metadata file object\n");
-               goto error;
-       }
-
-       if (babeltrace_debug) {
-               // yydebug = 1;
-       }
-
-       if (ctf_metadata_is_packetized(file->fp, &ctf_fs->metadata->bo)) {
-               PDBG("Metadata file \"%s\" is packetized\n", file->path->str);
-               ret = ctf_metadata_packetized_file_to_buf(ctf_fs, file->fp,
-                       &buf, ctf_fs->metadata->bo);
-               if (ret) {
-                       // log: details
-                       goto error;
-               }
-
-               cbuf = (char *) buf;
-               ctf_fs->metadata->text = (char *) cbuf;
-
-               /* Convert the real file pointer to a memory file pointer */
-               ret = fclose(file->fp);
-               file->fp = NULL;
-               if (ret) {
-                       PERR("Cannot close file \"%s\": %s\n", file->path->str,
-                               strerror(errno));
-                       goto error;
-               }
-
-               file->fp = babeltrace_fmemopen(cbuf, strlen(cbuf), "rb");
-               if (!file->fp) {
-                       PERR("Cannot memory-open metadata buffer: %s\n",
-                               strerror(errno));
-                       goto error;
-               }
-       } else {
-               unsigned int major, minor;
-               ssize_t nr_items;
-
-               PDBG("Metadata file \"%s\" is plain text\n", file->path->str);
-
-               /* Check text-only metadata header and version */
-               nr_items = fscanf(file->fp, "/* CTF %10u.%10u", &major, &minor);
-               if (nr_items < 2) {
-                       PWARN("Ill-shapen or missing \"/* CTF major.minor\" header in plain text metadata file\n");
-               }
-               PDBG("Metadata version: %u.%u\n", major, minor);
-
-               if (!is_version_valid(major, minor)) {
-                       PERR("Invalid metadata version: %u.%u\n", major, minor);
-                       goto error;
-               }
-
-               rewind(file->fp);
-       }
-
-       /* Allocate a scanner and append the metadata text content */
-       scanner = ctf_scanner_alloc();
-       if (!scanner) {
-               PERR("Cannot allocate a metadata lexical scanner\n");
-               goto error;
-       }
-
-       ret = ctf_scanner_append_ast(scanner, file->fp);
-       if (ret) {
-               PERR("Cannot create the metadata AST\n");
-               goto error;
-       }
-
-       ret = ctf_visitor_semantic_check(stderr, 0, &scanner->ast->root);
-       if (ret) {
-               PERR("Metadata semantic validation failed\n");
-               goto error;
+               goto end;
        }
 
-       ret = ctf_visitor_generate_ir(ctf_fs->error_fp, &scanner->ast->root,
-               &ctf_fs->metadata->trace,
+       metadata_decoder = ctf_metadata_decoder_create(ctf_fs->error_fp,
                ctf_fs->options.clock_offset * NSEC_PER_SEC +
                ctf_fs->options.clock_offset_ns);
-       if (ret) {
-               PERR("Cannot create trace object from metadata AST\n");
-               goto error;
+       if (!metadata_decoder) {
+               PERR("Cannot create metadata decoder object\n");
+               goto end;
        }
 
-       goto end;
-
-error:
-       if (ctf_fs->metadata->text) {
-               free(ctf_fs->metadata->text);
-               ctf_fs->metadata->text = NULL;
+       ret = ctf_metadata_decoder_decode(metadata_decoder, file->fp);
+       if (ret) {
+               PERR("Cannot decode metadata file\n");
+               goto end;
        }
 
+       ctf_fs->metadata->trace = ctf_metadata_decoder_get_trace(
+               metadata_decoder);
+       assert(ctf_fs->metadata->trace);
        ret = -1;
 
 end:
-       if (file) {
-               ctf_fs_file_destroy(file);
-       }
-
-       if (scanner) {
-               ctf_scanner_free(scanner);
-       }
-
+       ctf_fs_file_destroy(file);
+       ctf_metadata_decoder_destroy(metadata_decoder);
        return ret;
 }
 
This page took 0.027366 seconds and 4 git commands to generate.