Merge branch 'master' into bindings/python
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 29 Nov 2013 06:19:33 +0000 (07:19 +0100)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 29 Nov 2013 06:19:33 +0000 (07:19 +0100)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
19 files changed:
converter/babeltrace-log.c
formats/ctf/ctf.c
formats/ctf/types/array.c
formats/ctf/types/float.c
formats/ctf/types/integer.c
formats/ctf/types/sequence.c
formats/ctf/types/string.c
formats/ctf/types/struct.c
formats/ctf/types/variant.c
formats/ctf/writer/event-fields.c
formats/ctf/writer/event-types.c
formats/ctf/writer/stream.c
formats/ctf/writer/writer.c
include/Makefile.am
include/babeltrace/ctf-writer/event-types-internal.h
include/babeltrace/ctf/ctf-index.h [new file with mode: 0644]
include/babeltrace/ctf/types.h
lib/iterator.c
tests/lib/test_ctf_writer.c

index b6d798f797d0f86094b69c3e507dbf045ebed60f..5a8b26a8076ec4c26cdbdf3390403cf61b6f3e0f 100644 (file)
@@ -124,23 +124,36 @@ void write_packet_header(struct ctf_stream_pos *pos, unsigned char *uuid)
 
        /* magic */
        ctf_dummy_pos(pos, &dummy);
-       ctf_align_pos(&dummy, sizeof(uint32_t) * CHAR_BIT);
-       ctf_move_pos(&dummy, sizeof(uint32_t) * CHAR_BIT);
+       if (!ctf_align_pos(&dummy, sizeof(uint32_t) * CHAR_BIT))
+               goto error;
+       if (!ctf_move_pos(&dummy, sizeof(uint32_t) * CHAR_BIT))
+               goto error;
        assert(!ctf_pos_packet(&dummy));
 
-       ctf_align_pos(pos, sizeof(uint32_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint32_t) * CHAR_BIT))
+               goto error;
        *(uint32_t *) ctf_get_pos_addr(pos) = 0xC1FC1FC1;
-       ctf_move_pos(pos, sizeof(uint32_t) * CHAR_BIT);
+       if (!ctf_move_pos(pos, sizeof(uint32_t) * CHAR_BIT))
+               goto error;
 
        /* uuid */
        ctf_dummy_pos(pos, &dummy);
-       ctf_align_pos(&dummy, sizeof(uint8_t) * CHAR_BIT);
-       ctf_move_pos(&dummy, 16 * CHAR_BIT);
+       if (!ctf_align_pos(&dummy, sizeof(uint8_t) * CHAR_BIT))
+               goto error;
+       if (!ctf_move_pos(&dummy, 16 * CHAR_BIT))
+               goto error;
        assert(!ctf_pos_packet(&dummy));
 
-       ctf_align_pos(pos, sizeof(uint8_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint8_t) * CHAR_BIT))
+               goto error;
        memcpy(ctf_get_pos_addr(pos), uuid, BABELTRACE_UUID_LEN);
-       ctf_move_pos(pos, BABELTRACE_UUID_LEN * CHAR_BIT);
+       if (!ctf_move_pos(pos, BABELTRACE_UUID_LEN * CHAR_BIT))
+               goto error;
+       return;
+
+error:
+       fprintf(stderr, "[error] Out of packet bounds when writing packet header\n");
+       abort();
 }
 
 static
@@ -150,24 +163,37 @@ void write_packet_context(struct ctf_stream_pos *pos)
 
        /* content_size */
        ctf_dummy_pos(pos, &dummy);
-       ctf_align_pos(&dummy, sizeof(uint64_t) * CHAR_BIT);
-       ctf_move_pos(&dummy, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_align_pos(&dummy, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
+       if (!ctf_move_pos(&dummy, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
        assert(!ctf_pos_packet(&dummy));
 
-       ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
        *(uint64_t *) ctf_get_pos_addr(pos) = ~0ULL;    /* Not known yet */
        pos->content_size_loc = (uint64_t *) ctf_get_pos_addr(pos);
-       ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
 
        /* packet_size */
        ctf_dummy_pos(pos, &dummy);
-       ctf_align_pos(&dummy, sizeof(uint64_t) * CHAR_BIT);
-       ctf_move_pos(&dummy, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_align_pos(&dummy, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
+       if (!ctf_move_pos(&dummy, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
        assert(!ctf_pos_packet(&dummy));
 
-       ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
        *(uint64_t *) ctf_get_pos_addr(pos) = pos->packet_size;
-       ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
+       return;
+
+error:
+       fprintf(stderr, "[error] Out of packet bounds when writing packet context\n");
+       abort();
 }
 
 static
@@ -225,10 +251,17 @@ void write_event_header(struct ctf_stream_pos *pos, char *line,
                }
        }
        /* timestamp */
-       ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
        if (!pos->dummy)
                *(uint64_t *) ctf_get_pos_addr(pos) = *ts;
-       ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT);
+       if (!ctf_move_pos(pos, sizeof(uint64_t) * CHAR_BIT))
+               goto error;
+       return;
+
+error:
+       fprintf(stderr, "[error] Out of packet bounds when writing event header\n");
+       abort();
 }
 
 static
@@ -245,8 +278,10 @@ void trace_string(char *line, struct ctf_stream_pos *pos, size_t len)
        for (;;) {
                ctf_dummy_pos(pos, &dummy);
                write_event_header(&dummy, line, &tline, len, &tlen, &ts);
-               ctf_align_pos(&dummy, sizeof(uint8_t) * CHAR_BIT);
-               ctf_move_pos(&dummy, tlen * CHAR_BIT);
+               if (!ctf_align_pos(&dummy, sizeof(uint8_t) * CHAR_BIT))
+                       goto error;
+               if (!ctf_move_pos(&dummy, tlen * CHAR_BIT))
+                       goto error;
                if (ctf_pos_packet(&dummy)) {
                        ctf_pos_pad_packet(pos);
                        write_packet_header(pos, s_uuid);
@@ -263,9 +298,16 @@ void trace_string(char *line, struct ctf_stream_pos *pos, size_t len)
        }
 
        write_event_header(pos, line, &tline, len, &tlen, &ts);
-       ctf_align_pos(pos, sizeof(uint8_t) * CHAR_BIT);
+       if (!ctf_align_pos(pos, sizeof(uint8_t) * CHAR_BIT))
+               goto error;
        memcpy(ctf_get_pos_addr(pos), tline, tlen);
-       ctf_move_pos(pos, tlen * CHAR_BIT);
+       if (!ctf_move_pos(pos, tlen * CHAR_BIT))
+               goto error;
+       return;
+
+error:
+       fprintf(stderr, "[error] Out of packet bounds when writing event payload\n");
+       abort();
 }
 
 static
index 60d9c9f9459d159b7627c9e76927409eccd55272..5cf8097ce709892580c49957cf4751f9bc2e753b 100644 (file)
@@ -35,6 +35,7 @@
 #include <babeltrace/context-internal.h>
 #include <babeltrace/compat/uuid.h>
 #include <babeltrace/endian.h>
+#include <babeltrace/ctf/ctf-index.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <sys/mman.h>
@@ -71,6 +72,8 @@
 
 #define NSEC_PER_SEC 1000000000ULL
 
+#define INDEX_PATH "./index/%s.idx"
+
 int opt_clock_cycles,
        opt_clock_seconds,
        opt_clock_date,
@@ -468,6 +471,15 @@ int ctf_read_event(struct bt_stream_pos *ppos, struct ctf_stream_definition *str
         */
        if (unlikely(pos->offset == EOF))
                return EOF;
+
+       if (pos->content_size == 0) {
+               /* Stream is inactive for now (live reading). */
+               return EAGAIN;
+       }
+       /* Packet only contains headers */
+       if (pos->offset == pos->content_size)
+               return EAGAIN;
+
        assert(pos->offset < pos->content_size);
 
        /* Read event header */
@@ -548,10 +560,15 @@ int ctf_read_event(struct bt_stream_pos *ppos, struct ctf_stream_definition *str
                        goto error;
        }
 
+       if (pos->last_offset == pos->offset) {
+               fprintf(stderr, "[error] Invalid 0 byte event encountered.\n");
+               return -EINVAL;
+       }
+
        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");
+       fprintf(stderr, "[error] Unexpected end of packet. Either the trace data stream is corrupted or metadata description does not match data layout.\n");
        return ret;
 }
 
@@ -1481,28 +1498,28 @@ begin:
                        fprintf(stderr, "[error] Unable to read packet context: %s\n", strerror(-ret));
                        return ret;
                }
-               /* read content size from header */
-               len_index = bt_struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("content_size"));
+               /* read packet size from header */
+               len_index = bt_struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("packet_size"));
                if (len_index >= 0) {
                        struct bt_definition *field;
 
                        field = bt_struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
-                       packet_index.content_size = bt_get_unsigned_int(field);
+                       packet_index.packet_size = bt_get_unsigned_int(field);
                } else {
                        /* Use file size for packet size */
-                       packet_index.content_size = filesize * CHAR_BIT;
+                       packet_index.packet_size = filesize * CHAR_BIT;
                }
 
-               /* read packet size from header */
-               len_index = bt_struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("packet_size"));
+               /* read content size from header */
+               len_index = bt_struct_declaration_lookup_field_index(file_stream->parent.stream_packet_context->declaration, g_quark_from_static_string("content_size"));
                if (len_index >= 0) {
                        struct bt_definition *field;
 
                        field = bt_struct_definition_get_field_from_index(file_stream->parent.stream_packet_context, len_index);
-                       packet_index.packet_size = bt_get_unsigned_int(field);
+                       packet_index.content_size = bt_get_unsigned_int(field);
                } else {
-                       /* Use content size if non-zero, else file size */
-                       packet_index.packet_size = packet_index.content_size ? : filesize * CHAR_BIT;
+                       /* Use packet size if non-zero, else file size */
+                       packet_index.content_size = packet_index.packet_size ? : filesize * CHAR_BIT;
                }
 
                /* read timestamp begin from header */
@@ -1546,9 +1563,9 @@ begin:
                }
        } else {
                /* Use file size for packet size */
-               packet_index.content_size = filesize * CHAR_BIT;
-               /* Use content size if non-zero, else file size */
-               packet_index.packet_size = packet_index.content_size ? : filesize * CHAR_BIT;
+               packet_index.packet_size = filesize * CHAR_BIT;
+               /* Use packet size if non-zero, else file size */
+               packet_index.content_size = packet_index.packet_size ? : filesize * CHAR_BIT;
        }
 
        /* Validate content size and packet size values */
@@ -1564,6 +1581,16 @@ begin:
                return -EINVAL;
        }
 
+       if (packet_index.content_size < pos->offset) {
+               fprintf(stderr, "[error] Invalid CTF stream: content size is smaller than packet headers.\n");
+               return -EINVAL;
+       }
+
+       if ((packet_index.packet_size >> LOG2_CHAR_BIT) == 0) {
+               fprintf(stderr, "[error] Invalid CTF stream: packet size needs to be at least one byte\n");
+               return -EINVAL;
+       }
+
        /* Save position after header and context */
        packet_index.data_offset = pos->offset;
 
@@ -1666,6 +1693,93 @@ error:
        return ret;
 }
 
+static
+int import_stream_packet_index(struct ctf_trace *td,
+               struct ctf_file_stream *file_stream)
+{
+       struct ctf_stream_declaration *stream;
+       struct ctf_stream_pos *pos;
+       struct ctf_packet_index ctf_index;
+       struct ctf_packet_index_file_hdr index_hdr;
+       struct packet_index index;
+       int index_read;
+       int ret = 0;
+       int first_packet = 1;
+       size_t len;
+
+       pos = &file_stream->pos;
+
+       len = fread(&index_hdr, sizeof(index_hdr), 1, pos->index_fp);
+       if (len != 1) {
+               perror("read index file header");
+               goto error;
+       }
+
+       /* Check the index header */
+       if (be32toh(index_hdr.magic) != CTF_INDEX_MAGIC) {
+               fprintf(stderr, "[error] wrong index magic\n");
+               ret = -1;
+               goto error;
+       }
+       if (be32toh(index_hdr.index_major) != CTF_INDEX_MAJOR) {
+               fprintf(stderr, "[error] Incompatible index file %" PRIu64
+                               ".%" PRIu64 ", supported %d.%d\n",
+                               be64toh(index_hdr.index_major),
+                               be64toh(index_hdr.index_minor), CTF_INDEX_MAJOR,
+                               CTF_INDEX_MINOR);
+               ret = -1;
+               goto error;
+       }
+       if (index_hdr.packet_index_len == 0) {
+               fprintf(stderr, "[error] Packet index length cannot be 0.\n");
+               ret = -1;
+               goto error;
+       }
+
+       while ((index_read = fread(&ctf_index, index_hdr.packet_index_len, 1,
+                                       pos->index_fp)) == 1) {
+               uint64_t stream_id;
+
+               memset(&index, 0, sizeof(index));
+               index.offset = be64toh(ctf_index.offset);
+               index.packet_size = be64toh(ctf_index.packet_size);
+               index.content_size = be64toh(ctf_index.content_size);
+               index.timestamp_begin = be64toh(ctf_index.timestamp_begin);
+               index.timestamp_end = be64toh(ctf_index.timestamp_end);
+               index.events_discarded = be64toh(ctf_index.events_discarded);
+               index.events_discarded_len = 64;
+               stream_id = be64toh(ctf_index.stream_id);
+
+               if (!first_packet) {
+                       /* add index to packet array */
+                       g_array_append_val(file_stream->pos.packet_cycles_index, index);
+                       continue;
+               }
+
+               file_stream->parent.stream_id = stream_id;
+               stream = g_ptr_array_index(td->streams, stream_id);
+               if (!stream) {
+                       fprintf(stderr, "[error] Stream %" PRIu64
+                                       " is not declared in metadata.\n",
+                                       stream_id);
+                       ret = -EINVAL;
+                       goto error;
+               }
+               file_stream->parent.stream_class = stream;
+               ret = create_stream_definitions(td, &file_stream->parent);
+               if (ret)
+                       goto error;
+               first_packet = 0;
+               /* add index to packet array */
+               g_array_append_val(file_stream->pos.packet_cycles_index, index);
+       }
+
+       ret = 0;
+
+error:
+       return ret;
+}
+
 /*
  * Note: many file streams can inherit from the same stream class
  * description (metadata).
@@ -1678,6 +1792,7 @@ int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags,
        int ret, fd, closeret;
        struct ctf_file_stream *file_stream;
        struct stat statbuf;
+       char *index_name;
 
        fd = openat(td->dirfd, path, flags);
        if (fd < 0) {
@@ -1693,13 +1808,18 @@ int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags,
                goto fstat_error;
        }
        if (S_ISDIR(statbuf.st_mode)) {
-               fprintf(stderr, "[warning] Skipping directory '%s' found in trace\n", path);
+               if (strncmp(path, "index", 5) != 0) {
+                       fprintf(stderr, "[warning] Skipping directory '%s' "
+                                       "found in trace\n", path);
+               }
                ret = 0;
                goto fd_is_dir_ok;
        }
 
        file_stream = g_new0(struct ctf_file_stream, 1);
        file_stream->pos.last_offset = LAST_OFFSET_POISON;
+       file_stream->pos.fd = -1;
+       file_stream->pos.index_fp = NULL;
 
        strncpy(file_stream->parent.path, path, PATH_MAX);
        file_stream->parent.path[PATH_MAX - 1] = '\0';
@@ -1722,19 +1842,65 @@ int ctf_open_file_stream_read(struct ctf_trace *td, const char *path, int flags,
         * For now, only a single clock per trace is supported.
         */
        file_stream->parent.current_clock = td->parent.single_clock;
-       ret = create_stream_packet_index(td, file_stream);
-       if (ret) {
-               fprintf(stderr, "[error] Stream index creation error.\n");
-               goto error_index;
+
+       /*
+        * Allocate the index name for this stream and try to open it.
+        */
+       index_name = malloc((strlen(path) + sizeof(INDEX_PATH)) * sizeof(char));
+       if (!index_name) {
+               fprintf(stderr, "[error] Cannot allocate index filename\n");
+               goto error_def;
        }
+       snprintf(index_name, strlen(path) + sizeof(INDEX_PATH),
+                       INDEX_PATH, path);
+
+       if (faccessat(td->dirfd, index_name, O_RDONLY, flags) < 0) {
+               ret = create_stream_packet_index(td, file_stream);
+               if (ret) {
+                       fprintf(stderr, "[error] Stream index creation error.\n");
+                       goto error_index;
+               }
+       } else {
+               ret = openat(td->dirfd, index_name, flags);
+               if (ret < 0) {
+                       perror("Index file openat()");
+                       ret = -1;
+                       goto error_free;
+               }
+               file_stream->pos.index_fp = fdopen(ret, "r");
+               if (!file_stream->pos.index_fp) {
+                       perror("fdopen() error");
+                       goto error_free;
+               }
+               ret = import_stream_packet_index(td, file_stream);
+               if (ret) {
+                       ret = -1;
+                       goto error_index;
+               }
+               ret = fclose(file_stream->pos.index_fp);
+               if (ret < 0) {
+                       perror("close index");
+                       goto error_free;
+               }
+       }
+       free(index_name);
+
        /* Add stream file to stream class */
        g_ptr_array_add(file_stream->parent.stream_class->streams,
                        &file_stream->parent);
        return 0;
 
 error_index:
+       if (file_stream->pos.index_fp) {
+               ret = fclose(file_stream->pos.index_fp);
+               if (ret < 0) {
+                       perror("close index");
+               }
+       }
        if (file_stream->parent.trace_packet_header)
                bt_definition_unref(&file_stream->parent.trace_packet_header->p);
+error_free:
+       free(index_name);
 error_def:
        closeret = ctf_fini_pos(&file_stream->pos);
        if (closeret) {
@@ -1761,6 +1927,7 @@ int ctf_open_trace_read(struct ctf_trace *td,
        struct dirent *dirent;
        struct dirent *diriter;
        size_t dirent_len;
+       char *ext;
 
        td->flags = flags;
 
@@ -1816,6 +1983,13 @@ int ctf_open_trace_read(struct ctf_trace *td,
                                || !strcmp(diriter->d_name, "..")
                                || !strcmp(diriter->d_name, "metadata"))
                        continue;
+
+               /* Ignore index files : *.idx */
+               ext = strrchr(diriter->d_name, '.');
+               if (ext && (!strcmp(ext, ".idx"))) {
+                       continue;
+               }
+
                ret = ctf_open_file_stream_read(td, diriter->d_name,
                                        flags, packet_seek);
                if (ret) {
index 04801d4f05455df71160f85b4cd0ed6d58c9d180..979f7a3dc313895d29085e6de09e7ad904b675c0 100644 (file)
@@ -48,7 +48,8 @@ int ctf_array_read(struct bt_stream_pos *ppos, struct bt_definition *definition)
                        if (integer_declaration->len == CHAR_BIT
                            && integer_declaration->p.alignment == CHAR_BIT) {
 
-                               ctf_align_pos(pos, integer_declaration->p.alignment);
+                               if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+                                       return -EFAULT;
                                if (!ctf_pos_access_ok(pos, array_declaration->len * CHAR_BIT))
                                        return -EFAULT;
 
@@ -56,6 +57,11 @@ int ctf_array_read(struct bt_stream_pos *ppos, struct bt_definition *definition)
                                g_string_insert_len(array_definition->string,
                                        0, (char *) ctf_get_pos_addr(pos),
                                        array_declaration->len);
+                               /*
+                                * We want to populate both the string
+                                * and the underlying values, so carry
+                                * on calling bt_array_rw().
+                                */
                        }
                }
        }
@@ -82,14 +88,16 @@ int ctf_array_write(struct bt_stream_pos *ppos, struct bt_definition *definition
                        if (integer_declaration->len == CHAR_BIT
                            && integer_declaration->p.alignment == CHAR_BIT) {
 
-                               ctf_align_pos(pos, integer_declaration->p.alignment);
+                               if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+                                       return -EFAULT;
                                if (!ctf_pos_access_ok(pos, array_declaration->len * CHAR_BIT))
                                        return -EFAULT;
 
                                memcpy((char *) ctf_get_pos_addr(pos),
                                        array_definition->string->str,
                                        array_declaration->len);
-                               ctf_move_pos(pos, array_declaration->len * CHAR_BIT);
+                               if (!ctf_move_pos(pos, array_declaration->len * CHAR_BIT))
+                                       return -EFAULT;
                                return 0;
                        }
                }
index 9c60b737815ab587444a8a46b9ae12a63d003e3d..b82f68db91fbd901859ee3a8004ed6794c07b3a1 100644 (file)
@@ -200,8 +200,11 @@ int ctf_float_read(struct bt_stream_pos *ppos, struct bt_definition *definition)
        ctf_init_pos(&destp, NULL, -1, O_RDWR);
        mmap_align_set_addr(&mma, (char *) u.bits);
        destp.base_mma = &mma;
-       destp.packet_size = sizeof(u) * CHAR_BIT;
-       ctf_align_pos(pos, float_declaration->p.alignment);
+       destp.content_size = destp.packet_size = sizeof(u) * CHAR_BIT;
+       if (!ctf_align_pos(pos, float_declaration->p.alignment)) {
+               ret = -EFAULT;
+               goto end_unref;
+       }
        ret = _ctf_float_copy(&destp.parent, tmpfloat, ppos, float_definition);
        switch (float_declaration->mantissa->len + 1) {
        case FLT_MANT_DIG:
@@ -256,7 +259,7 @@ int ctf_float_write(struct bt_stream_pos *ppos, struct bt_definition *definition
        ctf_init_pos(&srcp, NULL, -1, O_RDONLY);
        mmap_align_set_addr(&mma, (char *) u.bits);
        srcp.base_mma = &mma;
-       srcp.packet_size = sizeof(u) * CHAR_BIT;
+       srcp.content_size = srcp.packet_size = sizeof(u) * CHAR_BIT;
        switch (float_declaration->mantissa->len + 1) {
        case FLT_MANT_DIG:
                u.vf = float_definition->value;
@@ -268,7 +271,10 @@ int ctf_float_write(struct bt_stream_pos *ppos, struct bt_definition *definition
                ret = -EINVAL;
                goto end_unref;
        }
-       ctf_align_pos(pos, float_declaration->p.alignment);
+       if (!ctf_align_pos(pos, float_declaration->p.alignment)) {
+               ret = -EFAULT;
+               goto end_unref;
+       }
        ret = _ctf_float_copy(ppos, float_definition, &srcp.parent, tmpfloat);
 
 end_unref:
index 257341adfa41ce6320a68a00e04cf6bc4d43490f..189943e6052438bc4b6e3cb2895dcbfc54005562 100644 (file)
@@ -49,7 +49,8 @@ int _aligned_integer_read(struct bt_stream_pos *ppos,
        struct ctf_stream_pos *pos = ctf_pos(ppos);
        int rbo = (integer_declaration->byte_order != BYTE_ORDER);      /* reverse byte order */
 
-       ctf_align_pos(pos, integer_declaration->p.alignment);
+       if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+               return -EFAULT;
 
        if (!ctf_pos_access_ok(pos, integer_declaration->len))
                return -EFAULT;
@@ -136,7 +137,8 @@ int _aligned_integer_read(struct bt_stream_pos *ppos,
                        assert(0);
                }
        }
-       ctf_move_pos(pos, integer_declaration->len);
+       if (!ctf_move_pos(pos, integer_declaration->len))
+               return -EFAULT;
        return 0;
 }
 
@@ -151,7 +153,8 @@ int _aligned_integer_write(struct bt_stream_pos *ppos,
        struct ctf_stream_pos *pos = ctf_pos(ppos);
        int rbo = (integer_declaration->byte_order != BYTE_ORDER);      /* reverse byte order */
 
-       ctf_align_pos(pos, integer_declaration->p.alignment);
+       if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+               return -EFAULT;
 
        if (!ctf_pos_access_ok(pos, integer_declaration->len))
                return -EFAULT;
@@ -207,7 +210,8 @@ int _aligned_integer_write(struct bt_stream_pos *ppos,
                }
        }
 end:
-       ctf_move_pos(pos, integer_declaration->len);
+       if (!ctf_move_pos(pos, integer_declaration->len))
+               return -EFAULT;
        return 0;
 }
 
@@ -224,7 +228,8 @@ int ctf_integer_read(struct bt_stream_pos *ppos, struct bt_definition *definitio
                return _aligned_integer_read(ppos, definition);
        }
 
-       ctf_align_pos(pos, integer_declaration->p.alignment);
+       if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+               return -EFAULT;
 
        if (!ctf_pos_access_ok(pos, integer_declaration->len))
                return -EFAULT;
@@ -252,7 +257,8 @@ int ctf_integer_read(struct bt_stream_pos *ppos, struct bt_definition *definitio
                                pos->offset, integer_declaration->len,
                                &integer_definition->value._signed);
        }
-       ctf_move_pos(pos, integer_declaration->len);
+       if (!ctf_move_pos(pos, integer_declaration->len))
+               return -EFAULT;
        return 0;
 }
 
@@ -269,7 +275,8 @@ int ctf_integer_write(struct bt_stream_pos *ppos, struct bt_definition *definiti
                return _aligned_integer_write(ppos, definition);
        }
 
-       ctf_align_pos(pos, integer_declaration->p.alignment);
+       if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+               return -EFAULT;
 
        if (!ctf_pos_access_ok(pos, integer_declaration->len))
                return -EFAULT;
@@ -300,6 +307,7 @@ int ctf_integer_write(struct bt_stream_pos *ppos, struct bt_definition *definiti
                                integer_definition->value._signed);
        }
 end:
-       ctf_move_pos(pos, integer_declaration->len);
+       if (!ctf_move_pos(pos, integer_declaration->len))
+               return -EFAULT;
        return 0;
 }
index 898c36725672c8e4b01084e1850e4c27050634d6..5dae7d0281d4610c586d00b2ee487e8ddb5a063d 100644 (file)
@@ -48,14 +48,16 @@ int ctf_sequence_read(struct bt_stream_pos *ppos, struct bt_definition *definiti
                            && integer_declaration->p.alignment == CHAR_BIT) {
                                uint64_t len = bt_sequence_len(sequence_definition);
 
-                               ctf_align_pos(pos, integer_declaration->p.alignment);
+                               if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+                                       return -EFAULT;
                                if (!ctf_pos_access_ok(pos, len * CHAR_BIT))
                                        return -EFAULT;
 
                                g_string_assign(sequence_definition->string, "");
                                g_string_insert_len(sequence_definition->string,
                                        0, (char *) ctf_get_pos_addr(pos), len);
-                               ctf_move_pos(pos, len * CHAR_BIT);
+                               if (!ctf_move_pos(pos, len * CHAR_BIT))
+                                       return -EFAULT;
                                return 0;
                        }
                }
@@ -83,13 +85,15 @@ int ctf_sequence_write(struct bt_stream_pos *ppos, struct bt_definition *definit
                            && integer_declaration->p.alignment == CHAR_BIT) {
                                uint64_t len = bt_sequence_len(sequence_definition);
 
-                               ctf_align_pos(pos, integer_declaration->p.alignment);
+                               if (!ctf_align_pos(pos, integer_declaration->p.alignment))
+                                       return -EFAULT;
                                if (!ctf_pos_access_ok(pos, len * CHAR_BIT))
                                        return -EFAULT;
 
                                memcpy((char *) ctf_get_pos_addr(pos),
                                        sequence_definition->string->str, len);
-                               ctf_move_pos(pos, len * CHAR_BIT);
+                               if (!ctf_move_pos(pos, len * CHAR_BIT))
+                                       return -EFAULT;
                                return 0;
                        }
                }
index a2433bf5922d2013e80f19a1e1897842657de535..002f1b4fb335f5bb34d776fa79d36b5f9bf83c35 100644 (file)
@@ -39,19 +39,21 @@ int ctf_string_read(struct bt_stream_pos *ppos, struct bt_definition *definition
                string_definition->declaration;
        struct ctf_stream_pos *pos = ctf_pos(ppos);
        size_t len;
-       ssize_t max_len;
+       ssize_t max_len_bits;
        char *srcaddr;
 
-       ctf_align_pos(pos, string_declaration->p.alignment);
+       if (!ctf_align_pos(pos, string_declaration->p.alignment))
+               return -EFAULT;
 
        srcaddr = ctf_get_pos_addr(pos);
        if (pos->offset == EOF)
                return -EFAULT;
-       /* Not counting \0 */
-       max_len = pos->packet_size - pos->offset - 1;
-       if (max_len < 0)
+       /* Not counting \0. Counting in bits. */
+       max_len_bits = pos->packet_size - pos->offset - CHAR_BIT;
+       if (max_len_bits < 0)
                return -EFAULT;
-       len = strnlen(srcaddr, max_len) + 1;    /* Add \0 */
+       /* Add \0, counting in bytes. */
+       len = strnlen(srcaddr, (size_t) max_len_bits / CHAR_BIT) + 1;
        /* Truncated string, unexpected. Trace probably corrupted. */
        if (srcaddr[len - 1] != '\0')
                return -EFAULT;
@@ -64,7 +66,8 @@ int ctf_string_read(struct bt_stream_pos *ppos, struct bt_definition *definition
        printf_debug("CTF string read %s\n", srcaddr);
        memcpy(string_definition->value, srcaddr, len);
        string_definition->len = len;
-       ctf_move_pos(pos, len * CHAR_BIT);
+       if (!ctf_move_pos(pos, len * CHAR_BIT))
+               return -EFAULT;
        return 0;
 }
 
@@ -79,7 +82,8 @@ int ctf_string_write(struct bt_stream_pos *ppos,
        size_t len;
        char *destaddr;
 
-       ctf_align_pos(pos, string_declaration->p.alignment);
+       if (!ctf_align_pos(pos, string_declaration->p.alignment))
+               return -EFAULT;
        assert(string_definition->value != NULL);
        len = string_definition->len;
 
@@ -91,6 +95,7 @@ int ctf_string_write(struct bt_stream_pos *ppos,
        destaddr = ctf_get_pos_addr(pos);
        memcpy(destaddr, string_definition->value, len);
 end:
-       ctf_move_pos(pos, len * CHAR_BIT);
+       if (!ctf_move_pos(pos, len * CHAR_BIT))
+               return -EFAULT;
        return 0;
 }
index 106f682c8ee2d886a9daded1bb32d027e20a7abc..cbf53c1edb58a9d29a03ff449a7c7d16b8401d14 100644 (file)
@@ -33,6 +33,7 @@ int ctf_struct_rw(struct bt_stream_pos *ppos, struct bt_definition *definition)
        struct bt_declaration *declaration = definition->declaration;
        struct ctf_stream_pos *pos = ctf_pos(ppos);
 
-       ctf_align_pos(pos, declaration->alignment);
+       if (!ctf_align_pos(pos, declaration->alignment))
+               return -EFAULT;
        return bt_struct_rw(ppos, definition);
 }
index b3d6396a6f9f075f21be4fd71e871a55c2c038f6..fc7b7ad449d935ea4dcf9e32afda839463250141 100644 (file)
@@ -33,6 +33,7 @@ int ctf_variant_rw(struct bt_stream_pos *ppos, struct bt_definition *definition)
        struct bt_declaration *declaration = definition->declaration;
        struct ctf_stream_pos *pos = ctf_pos(ppos);
 
-       ctf_align_pos(pos, declaration->alignment);
+       if (!ctf_align_pos(pos, declaration->alignment))
+               return -EFAULT;
        return bt_variant_rw(ppos, definition);
 }
index 7a37aaf989f4bd92607863b6b91b469662f50175..c4d1b968587e33f00f24f8efe0c0658c201e6ba6 100644 (file)
@@ -179,8 +179,8 @@ struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type)
        }
 
        type_id = bt_ctf_field_type_get_type_id(type);
-       if (type_id <= CTF_TYPE_UNKNOWN ||
-               type_id >= NR_CTF_TYPES) {
+       if (type_id <= CTF_TYPE_UNKNOWN || type_id >= NR_CTF_TYPES ||
+               bt_ctf_field_type_validate(type)) {
                goto error;
        }
 
@@ -247,13 +247,14 @@ int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field,
                bt_ctf_field_put(sequence->length);
        }
 
-       sequence->elements = g_ptr_array_new_full((size_t)sequence_length,
-               (GDestroyNotify)bt_ctf_field_put);
+       sequence->elements = g_ptr_array_sized_new((size_t)sequence_length);
        if (!sequence->elements) {
                ret = -1;
                goto end;
        }
 
+       g_ptr_array_set_free_func(sequence->elements,
+               (GDestroyNotify)bt_ctf_field_put);
        g_ptr_array_set_size(sequence->elements, (size_t)sequence_length);
        bt_ctf_field_get(length_field);
        sequence->length = length_field;
@@ -768,12 +769,13 @@ struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type)
 
        array_type = container_of(type, struct bt_ctf_field_type_array, parent);
        array_length = array_type->length;
-       array->elements = g_ptr_array_new_full(array_length,
-               (GDestroyNotify)bt_ctf_field_put);
+       array->elements = g_ptr_array_sized_new(array_length);
        if (!array->elements) {
                goto error;
        }
 
+       g_ptr_array_set_free_func(array->elements,
+               (GDestroyNotify)bt_ctf_field_put);
        g_ptr_array_set_size(array->elements, array_length);
        return &array->parent;
 error:
@@ -1123,10 +1125,16 @@ int bt_ctf_field_structure_serialize(struct bt_ctf_field *field,
        while (!ctf_pos_access_ok(pos,
                offset_align(pos->offset,
                        field->type->declaration->alignment))) {
-               increase_packet_size(pos);
+               ret = increase_packet_size(pos);
+               if (ret) {
+                       goto end;
+               }
        }
 
-       ctf_align_pos(pos, field->type->declaration->alignment);
+       if (!ctf_align_pos(pos, field->type->declaration->alignment)) {
+               ret = -1;
+               goto end;
+       }
 
        for (i = 0; i < structure->fields->len; i++) {
                struct bt_ctf_field *field = g_ptr_array_index(
@@ -1137,7 +1145,7 @@ int bt_ctf_field_structure_serialize(struct bt_ctf_field *field,
                        break;
                }
        }
-
+end:
        return ret;
 }
 
index 091b3209eff8261d4526de6042ce08f8b933086e..7f7fa7622247abb3e09288960429722d3f9cf8a1 100644 (file)
@@ -33,6 +33,7 @@
 #include <babeltrace/endian.h>
 #include <float.h>
 #include <inttypes.h>
+#include <stdlib.h>
 
 struct range_overlap_query {
        int64_t range_start, range_end;
@@ -214,8 +215,8 @@ int add_structure_field(GPtrArray *fields,
        struct structure_field *field;
 
        /* Make sure structure does not contain a field of the same name */
-       if (g_hash_table_contains(field_name_to_index,
-                       GUINT_TO_POINTER(name_quark))) {
+       if (g_hash_table_lookup_extended(field_name_to_index,
+               GUINT_TO_POINTER(name_quark), NULL, NULL)) {
                ret = -1;
                goto end;
        }
@@ -238,6 +239,27 @@ end:
        return ret;
 }
 
+BT_HIDDEN
+int bt_ctf_field_type_validate(struct bt_ctf_field_type *type)
+{
+       int ret = 0;
+
+       if (!type) {
+               ret = -1;
+               goto end;
+       }
+
+       if (type->declaration->id == CTF_TYPE_ENUM) {
+               struct bt_ctf_field_type_enumeration *enumeration =
+                       container_of(type, struct bt_ctf_field_type_enumeration,
+                       parent);
+
+               ret = enumeration->entries->len ? 0 : -1;
+       }
+end:
+       return ret;
+}
+
 struct bt_ctf_field_type *bt_ctf_field_type_integer_create(unsigned int size)
 {
        struct bt_ctf_field_type_integer *integer =
@@ -364,6 +386,7 @@ int bt_ctf_field_type_enumeration_add_mapping(
        struct enumeration_mapping *mapping;
        struct bt_ctf_field_type_enumeration *enumeration;
        struct range_overlap_query query;
+       char *escaped_string;
 
        if (!type || (type->declaration->id != CTF_TYPE_ENUM) ||
                type->frozen ||
@@ -372,12 +395,18 @@ int bt_ctf_field_type_enumeration_add_mapping(
                goto end;
        }
 
-       if (validate_identifier(string)) {
+       if (!string || strlen(string) == 0) {
                ret = -1;
                goto end;
        }
 
-       mapping_name = g_quark_from_string(string);
+       escaped_string = g_strescape(string, NULL);
+       if (!escaped_string) {
+               ret = -1;
+               goto end;
+       }
+
+       mapping_name = g_quark_from_string(escaped_string);
        query = (struct range_overlap_query) { .range_start = range_start,
                .range_end = range_end,
                .mapping_name = mapping_name,
@@ -389,18 +418,20 @@ int bt_ctf_field_type_enumeration_add_mapping(
        g_ptr_array_foreach(enumeration->entries, check_ranges_overlap, &query);
        if (query.overlaps) {
                ret = -1;
-               goto end;
+               goto error_free;
        }
 
        mapping = g_new(struct enumeration_mapping, 1);
        if (!mapping) {
                ret = -1;
-               goto end;
+               goto error_free;
        }
 
        *mapping = (struct enumeration_mapping) {.range_start = range_start,
                .range_end = range_end, .string = mapping_name};
        g_ptr_array_add(enumeration->entries, mapping);
+error_free:
+       free(escaped_string);
 end:
        return ret;
 }
@@ -517,7 +548,8 @@ int bt_ctf_field_type_structure_add_field(struct bt_ctf_field_type *type,
 
        if (!type || !field_type || type->frozen ||
                validate_identifier(field_name) ||
-               (type->declaration->id != CTF_TYPE_STRUCT)) {
+               (type->declaration->id != CTF_TYPE_STRUCT) ||
+               bt_ctf_field_type_validate(field_type)) {
                goto end;
        }
 
@@ -579,7 +611,8 @@ int bt_ctf_field_type_variant_add_field(struct bt_ctf_field_type *type,
 
        if (!type || !field_type || type->frozen ||
                validate_identifier(field_name) ||
-               (type->declaration->id != CTF_TYPE_VARIANT)) {
+               (type->declaration->id != CTF_TYPE_VARIANT) ||
+               bt_ctf_field_type_validate(field_type)) {
                ret = -1;
                goto end;
        }
@@ -611,7 +644,8 @@ struct bt_ctf_field_type *bt_ctf_field_type_array_create(
 {
        struct bt_ctf_field_type_array *array = NULL;
 
-       if (!element_type || length == 0) {
+       if (!element_type || length == 0 ||
+               bt_ctf_field_type_validate(element_type)) {
                goto error;
        }
 
@@ -639,7 +673,8 @@ struct bt_ctf_field_type *bt_ctf_field_type_sequence_create(
 {
        struct bt_ctf_field_type_sequence *sequence = NULL;
 
-       if (!element_type || validate_identifier(length_field_name)) {
+       if (!element_type || validate_identifier(length_field_name) ||
+               bt_ctf_field_type_validate(element_type)) {
                goto error;
        }
 
@@ -1154,10 +1189,15 @@ int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type *type,
                struct metadata_context *context)
 {
        size_t entry;
-       int ret = 0;
+       int ret;
        struct bt_ctf_field_type_enumeration *enumeration = container_of(type,
                struct bt_ctf_field_type_enumeration, parent);
 
+       ret = bt_ctf_field_type_validate(type);
+       if (ret) {
+               goto end;
+       }
+
        g_string_append(context->string, "enum : ");
        ret = bt_ctf_field_type_serialize(enumeration->container, context);
        if (ret) {
@@ -1170,12 +1210,13 @@ int bt_ctf_field_type_enumeration_serialize(struct bt_ctf_field_type *type,
                        enumeration->entries->pdata[entry];
 
                if (mapping->range_start == mapping->range_end) {
-                       g_string_append_printf(context->string, "%s = %" PRId64,
+                       g_string_append_printf(context->string,
+                               "\"%s\" = %" PRId64,
                                g_quark_to_string(mapping->string),
                                mapping->range_start);
                } else {
                        g_string_append_printf(context->string,
-                               "%s = %" PRId64 " ... %" PRId64,
+                               "\"%s\" = %" PRId64 " ... %" PRId64,
                                g_quark_to_string(mapping->string),
                                mapping->range_start, mapping->range_end);
                }
index f03f170d6a5ff7c09744149b4f4f2f9181eaa1f6..ac8942972ef71e71678b85f41e953f117eb1b9be 100644 (file)
@@ -368,7 +368,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        int ret = 0;
        size_t i;
        uint64_t timestamp_begin, timestamp_end;
-       struct bt_ctf_stream_class *stream_class = stream->stream_class;
+       struct bt_ctf_stream_class *stream_class;
        struct bt_ctf_field *integer = NULL;
        struct ctf_stream_pos packet_context_pos;
 
@@ -385,6 +385,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                stream->flush.func(stream, stream->flush.data);
        }
 
+       stream_class = stream->stream_class;
        timestamp_begin = ((struct bt_ctf_event *) g_ptr_array_index(
                stream->events, 0))->timestamp;
        timestamp_end = ((struct bt_ctf_event *) g_ptr_array_index(
@@ -518,7 +519,9 @@ void bt_ctf_stream_destroy(struct bt_ctf_ref *ref)
 
        stream = container_of(ref, struct bt_ctf_stream, ref_count);
        ctf_fini_pos(&stream->pos);
-       close(stream->pos.fd);
+       if (close(stream->pos.fd)) {
+               perror("close");
+       }
        bt_ctf_stream_class_put(stream->stream_class);
        g_ptr_array_free(stream->events, TRUE);
        g_free(stream);
index 5600a92a0a1debd22cfed2066edf5ee16bfae825..a3ca263adeca7a9eb934ea6dd74432262e7e02b9 100644 (file)
@@ -560,8 +560,9 @@ int validate_identifier(const char *input_string)
 
        token = strtok_r(string, " ", &save_ptr);
        while (token) {
-               if (g_hash_table_contains(reserved_keywords_set,
-                       GINT_TO_POINTER(g_quark_from_string(token)))) {
+               if (g_hash_table_lookup_extended(reserved_keywords_set,
+                       GINT_TO_POINTER(g_quark_from_string(token)),
+                       NULL, NULL)) {
                        ret = -1;
                        goto end;
                }
@@ -737,8 +738,10 @@ void writer_init(void)
 
        reserved_keywords_set = g_hash_table_new(g_direct_hash, g_direct_equal);
        for (i = 0; i < reserved_keywords_count; i++) {
-               g_hash_table_add(reserved_keywords_set,
-               GINT_TO_POINTER(g_quark_from_string(reserved_keywords_str[i])));
+               gpointer quark = GINT_TO_POINTER(g_quark_from_string(
+                       reserved_keywords_str[i]));
+
+               g_hash_table_insert(reserved_keywords_set, quark, quark);
        }
 
        init_done = 1;
index ec927b9173ffa21f9a9557c157e80f5e38ba5d77..d9996a7b4cf93b679cb1133e4ba80b106bd611fe 100644 (file)
@@ -38,6 +38,7 @@ noinst_HEADERS = \
        babeltrace/ctf-text/types.h \
        babeltrace/ctf/types.h \
        babeltrace/ctf/callbacks-internal.h \
+       babeltrace/ctf/ctf-index.h \
        babeltrace/ctf-writer/ref-internal.h \
        babeltrace/ctf-writer/writer-internal.h \
        babeltrace/ctf-writer/event-types-internal.h \
index d9acdd350cad7aa52323cdb62ae035b795ae721b..a937c7803ee889612632f67836a3acaa8edfd092 100644 (file)
@@ -147,4 +147,7 @@ BT_HIDDEN
 int bt_ctf_field_type_serialize(struct bt_ctf_field_type *type,
                struct metadata_context *context);
 
+BT_HIDDEN
+int bt_ctf_field_type_validate(struct bt_ctf_field_type *type);
+
 #endif /* BABELTRACE_CTF_WRITER_EVENT_TYPES_INTERNAL_H */
diff --git a/include/babeltrace/ctf/ctf-index.h b/include/babeltrace/ctf/ctf-index.h
new file mode 100644 (file)
index 0000000..0efa888
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2013 - Julien Desfossez <jdesfossez@efficios.com>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *                      David Goulet <dgoulet@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef LTTNG_INDEX_H
+#define LTTNG_INDEX_H
+
+#include <limits.h>
+
+#define CTF_INDEX_MAGIC 0xC1F1DCC1
+#define CTF_INDEX_MAJOR 1
+#define CTF_INDEX_MINOR 0
+
+/*
+ * Header at the beginning of each index file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index_file_hdr {
+       uint32_t magic;
+       uint32_t index_major;
+       uint32_t index_minor;
+       /* struct packet_index_len, in bytes */
+       uint32_t packet_index_len;
+} __attribute__((__packed__));
+
+/*
+ * Packet index generated for each trace packet store in a trace file.
+ * All integer fields are stored in big endian.
+ */
+struct ctf_packet_index {
+       uint64_t offset;                /* offset of the packet in the file, in bytes */
+       uint64_t packet_size;           /* packet size, in bits */
+       uint64_t content_size;          /* content size, in bits */
+       uint64_t timestamp_begin;
+       uint64_t timestamp_end;
+       uint64_t events_discarded;
+       uint64_t stream_id;
+} __attribute__((__packed__));
+
+#endif /* LTTNG_INDEX_H */
index 96c5083c2b7d5eea1e0154aa5954073353017139..e90464dc76243e02a0c1d250ae973cd48cb45fa0 100644 (file)
@@ -61,6 +61,7 @@ struct packet_index {
 struct ctf_stream_pos {
        struct bt_stream_pos parent;
        int fd;                 /* backing file fd. -1 if unset. */
+       FILE *index_fp;         /* backing index file fp. NULL if unset. */
        GArray *packet_cycles_index;    /* contains struct packet_index in cycles */
        GArray *packet_real_index;      /* contains struct packet_index in ns */
        int prot;               /* mmap protection */
@@ -128,28 +129,41 @@ int ctf_fini_pos(struct ctf_stream_pos *pos);
 /*
  * move_pos - move position of a relative bit offset
  *
+ * Return 1 if OK, 0 if out-of-bound.
+ *
  * TODO: allow larger files by updating base too.
  */
 static inline
-void ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
+int ctf_move_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
 {
+       uint64_t max_len;
+
        printf_debug("ctf_move_pos test EOF: %" PRId64 "\n", pos->offset);
        if (unlikely(pos->offset == EOF))
-               return;
+               return 0;
+       if (pos->prot == PROT_READ)
+               max_len = pos->content_size;
+       else
+               max_len = pos->packet_size;
+       if (unlikely(pos->offset + bit_offset > max_len))
+               return 0;
 
        pos->offset += bit_offset;
        printf_debug("ctf_move_pos after increment: %" PRId64 "\n", pos->offset);
+       return 1;
 }
 
 /*
  * align_pos - align position on a bit offset (> 0)
  *
+ * Return 1 if OK, 0 if out-of-bound.
+ *
  * TODO: allow larger files by updating base too.
  */
 static inline
-void ctf_align_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
+int ctf_align_pos(struct ctf_stream_pos *pos, uint64_t bit_offset)
 {
-       ctf_move_pos(pos, offset_align(pos->offset, bit_offset));
+       return ctf_move_pos(pos, offset_align(pos->offset, bit_offset));
 }
 
 static inline
@@ -190,15 +204,21 @@ void ctf_pos_pad_packet(struct ctf_stream_pos *pos)
 static inline
 int ctf_pos_access_ok(struct ctf_stream_pos *pos, uint64_t bit_len)
 {
+       uint64_t max_len;
+
        if (unlikely(pos->offset == EOF))
                return 0;
-       if (unlikely(pos->offset + bit_len > pos->packet_size))
+       if (pos->prot == PROT_READ)
+               max_len = pos->content_size;
+       else
+               max_len = pos->packet_size;
+       if (unlikely(pos->offset + bit_len > max_len))
                return 0;
        return 1;
 }
 
 /*
- * Update the stream position for to the current event. This moves to
+ * Update the stream position to the current event. This moves to
  * the next packet if we are located at the end of the current packet.
  */
 static inline
index 966a00010e3e82a8393987f72f78b9e4d820c70f..a2a7bb578adca29313b9bda620382bfe67b8248c 100644 (file)
@@ -65,6 +65,9 @@ static int stream_read_event(struct ctf_file_stream *sin)
        ret = sin->pos.parent.event_cb(&sin->pos.parent, &sin->parent);
        if (ret == EOF)
                return EOF;
+       else if (ret == EAGAIN)
+               /* Stream is inactive for now (live reading). */
+               return EAGAIN;
        else if (ret) {
                fprintf(stderr, "[error] Reading event failed.\n");
                return ret;
@@ -716,7 +719,7 @@ int bt_iter_init(struct bt_iter *iter,
                                if (ret == EOF) {
                                        ret = 0;
                                        continue;
-                               } else if (ret) {
+                               } else if (ret != 0 && ret != EAGAIN) {
                                        goto error;
                                }
                                /* Add to heap */
@@ -801,13 +804,28 @@ int bt_iter_next(struct bt_iter *iter)
                assert(removed == file_stream);
                ret = 0;
                goto end;
+       } else if (ret == EAGAIN) {
+               /*
+                * The stream is inactive for now, we just updated the timestamp_end
+                * to skip over this stream up to a certain point in time.
+                */
+               goto reinsert;
        } else if (ret) {
                goto end;
        }
+
+reinsert:
        /* Reinsert the file stream into the heap, and rebalance. */
        removed = bt_heap_replace_max(iter->stream_heap, file_stream);
        assert(removed == file_stream);
 
+       file_stream = bt_heap_maximum(iter->stream_heap);
+       if (file_stream->pos.content_size == 0) {
+               ret = EAGAIN;
+       } else {
+               ret = 0;
+       }
+
 end:
        return ret;
 }
index d55c6297b20e70dd2646563794ec681b12ee6aaf..0927a325cc0a06ab7b071b554d760ff5a4e8aa2b 100644 (file)
@@ -254,13 +254,30 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
                bt_ctf_field_type_integer_create(12);
        struct bt_ctf_field_type *float_type =
                bt_ctf_field_type_floating_point_create();
+       struct bt_ctf_field_type *enum_type =
+               bt_ctf_field_type_enumeration_create(uint_12_type);
        struct bt_ctf_event *simple_event;
        struct bt_ctf_field *integer_field;
        struct bt_ctf_field *float_field;
+       struct bt_ctf_field *enum_field;
+       struct bt_ctf_field *enum_container_field;
 
        bt_ctf_field_type_set_alignment(float_type, 32);
        bt_ctf_field_type_floating_point_set_exponent_digits(float_type, 11);
        bt_ctf_field_type_floating_point_set_mantissa_digits(float_type, 53);
+
+       ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
+               "escaping; \"test\"", 0, 0) == 0,
+               "Accept enumeration mapping strings containing quotes");
+       ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
+               "\tanother \'escaping\'\n test\"", 1, 4) == 0,
+               "Accept enumeration mapping strings containing special characters");
+       ok(bt_ctf_field_type_enumeration_add_mapping(enum_type,
+               "event clock int float", 5, 22) == 0,
+               "Accept enumeration mapping strings containing reserved keywords");
+       ok(bt_ctf_event_class_add_field(simple_event_class, enum_type,
+               "enum_field") == 0, "Add enumeration field to event");
+
        ok(uint_12_type, "Create an unsigned integer type");
        bt_ctf_event_class_add_field(simple_event_class, uint_12_type,
                "integer_field");
@@ -281,6 +298,13 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
 
        float_field = bt_ctf_event_get_payload(simple_event, "float_field");
        bt_ctf_field_floating_point_set_value(float_field, 3.1415);
+       enum_field = bt_ctf_field_create(enum_type);
+       enum_container_field = bt_ctf_field_enumeration_get_container(
+               enum_field);
+       ok(bt_ctf_field_unsigned_integer_set_value(
+               enum_container_field, 1) == 0,
+               "Set enumeration container value");
+       bt_ctf_event_set_payload(simple_event, "enum_field", enum_field);
 
        ok(bt_ctf_clock_set_time(clock, current_time) == 0, "Set clock time");
 
@@ -294,8 +318,11 @@ void append_simple_event(struct bt_ctf_stream_class *stream_class,
        bt_ctf_event_put(simple_event);
        bt_ctf_field_type_put(uint_12_type);
        bt_ctf_field_type_put(float_type);
+       bt_ctf_field_type_put(enum_type);
        bt_ctf_field_put(integer_field);
        bt_ctf_field_put(float_field);
+       bt_ctf_field_put(enum_field);
+       bt_ctf_field_put(enum_container_field);
 }
 
 void append_complex_event(struct bt_ctf_stream_class *stream_class,
@@ -469,6 +496,7 @@ void type_field_tests()
        struct bt_ctf_field *uint_12;
        struct bt_ctf_field *int_16;
        struct bt_ctf_field *string;
+       struct bt_ctf_field *enumeration;
        struct bt_ctf_field_type *composite_structure_type;
        struct bt_ctf_field_type *structure_seq_type;
        struct bt_ctf_field_type *string_type;
@@ -477,6 +505,9 @@ void type_field_tests()
        struct bt_ctf_field_type *int_16_type;
        struct bt_ctf_field_type *uint_12_type =
                bt_ctf_field_type_integer_create(12);
+       struct bt_ctf_field_type *enumeration_type;
+       struct bt_ctf_field_type *enumeration_sequence_type;
+       struct bt_ctf_field_type *enumeration_array_type;
 
        ok(uint_12_type, "Create an unsigned integer type");
        ok(bt_ctf_field_type_integer_set_base(uint_12_type,
@@ -578,9 +609,28 @@ void type_field_tests()
        ok(bt_ctf_field_string_set_value(string, "A value") == 0,
                "Set a string's value");
 
+       enumeration_type = bt_ctf_field_type_enumeration_create(uint_12_type);
+       ok(enumeration_type,
+               "Create an enumeration type with an unsigned 12-bit integer as container");
+       enumeration_sequence_type = bt_ctf_field_type_sequence_create(
+               enumeration_type, "count");
+       ok(!enumeration_sequence_type,
+               "Check enumeration types are validated when creating a sequence");
+       enumeration_array_type = bt_ctf_field_type_array_create(
+               enumeration_type, 10);
+       ok(!enumeration_array_type,
+               "Check enumeration types are validated when creating an array");
+       ok(bt_ctf_field_type_structure_add_field(composite_structure_type,
+               enumeration_type, "enumeration") == 0,
+               "Check enumeration types are validated when adding them as structure members");
+       enumeration = bt_ctf_field_create(enumeration_type);
+       ok(!enumeration,
+               "Check enumeration types are validated before instantiation");
+
        bt_ctf_field_put(string);
        bt_ctf_field_put(uint_12);
        bt_ctf_field_put(int_16);
+       bt_ctf_field_put(enumeration);
        bt_ctf_field_type_put(composite_structure_type);
        bt_ctf_field_type_put(structure_seq_type);
        bt_ctf_field_type_put(string_type);
@@ -588,6 +638,9 @@ void type_field_tests()
        bt_ctf_field_type_put(uint_8_type);
        bt_ctf_field_type_put(int_16_type);
        bt_ctf_field_type_put(uint_12_type);
+       bt_ctf_field_type_put(enumeration_type);
+       bt_ctf_field_type_put(enumeration_sequence_type);
+       bt_ctf_field_type_put(enumeration_array_type);
 }
 
 void packet_resize_test(struct bt_ctf_stream_class *stream_class,
This page took 0.049206 seconds and 4 git commands to generate.