static char *opt_plugin_path;
+static char *opt_input_path;
enum {
OPT_NONE = 0,
OPT_PLUGIN_PATH,
+ OPT_INPUT_PATH,
OPT_VERBOSE,
OPT_DEBUG,
OPT_HELP,
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
{ "plugin-path", 0, POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
+ { "input-path", 0, POPT_ARG_STRING, NULL, OPT_INPUT_PATH, NULL, NULL },
{ "verbose", 'v', POPT_ARG_NONE, NULL, OPT_VERBOSE, NULL, NULL },
{ "debug", 'd', POPT_ARG_NONE, NULL, OPT_DEBUG, NULL, NULL },
{ NULL, 0, 0, NULL, 0, NULL, NULL },
if (!opt_plugin_path) {
ret = -EINVAL;
goto end;
- } ;
+ }
break;
case OPT_VERBOSE:
babeltrace_verbose = 1;
case OPT_DEBUG:
babeltrace_debug = 1;
break;
+ case OPT_INPUT_PATH:
+ opt_input_path = (char *) poptGetOptArg(pc);
+ if (!opt_input_path) {
+ ret = -EINVAL;
+ goto end;
+ }
+ break;
default:
ret = -EINVAL;
goto end;
}
static
-void print_detected_component_classes(struct bt_component_factory *factory)
+void print_found_component_classes(struct bt_component_factory *factory)
{
int count, i;
}
}
-static
-void test_sink_notifications(struct bt_component *sink)
-{
- return;
-}
-
int main(int argc, char **argv)
{
int ret;
+ enum bt_value_status value_status;
struct bt_component_factory *component_factory = NULL;
- struct bt_component_class *source_class = NULL;
- struct bt_component_class *sink_class = NULL;
+ struct bt_component_class *source_class = NULL, *sink_class = NULL;
struct bt_component *source = NULL, *sink = NULL;
struct bt_value *source_params = NULL, *sink_params = NULL;
exit(EXIT_SUCCESS);
}
+ source_params = bt_value_map_create();
+ if (!source_params) {
+ fprintf(stderr, "Failed to create source parameters map, aborting...\n");
+ ret = -1;
+ goto end;
+ }
+
+ value_status = bt_value_map_insert_string(source_params, "path",
+ opt_input_path);
+ if (value_status != BT_VALUE_STATUS_OK) {
+ ret = -1;
+ goto end;
+ }
+
printf_verbose("Verbose mode active.\n");
printf_debug("Debug mode active.\n");
goto end;
}
- print_detected_component_classes(component_factory);
+ print_found_component_classes(component_factory);
+
+ source_class = bt_component_factory_get_component_class(
+ component_factory, "ctf", BT_COMPONENT_TYPE_SOURCE,
+ "fs");
+ if (!source_class) {
+ fprintf(stderr, "Could not find ctf-fs output component class. Aborting...\n");
+ ret = -1;
+ goto end;
+ }
sink_class = bt_component_factory_get_component_class(component_factory,
- NULL, BT_COMPONENT_TYPE_SINK, "text");
+ "text", BT_COMPONENT_TYPE_SINK, "text");
if (!sink_class) {
fprintf(stderr, "Could not find text output component class. Aborting...\n");
ret = -1;
goto end;
}
+ source = bt_component_create(source_class, "ctf-fs", source_params);
+ if (!source) {
+ fprintf(stderr, "Failed to instantiate source component. Aborting...\n");
+ ret = -1;
+ goto end;
+ }
+
sink = bt_component_create(sink_class, "bt_text_output", sink_params);
if (!sink) {
- fprintf(stderr, "Failed to instanciate text output. Aborting...\n");
+ fprintf(stderr, "Failed to instantiate output component. Aborting...\n");
ret = -1;
goto end;
}
- test_sink_notifications(sink);
-
/* teardown and exit */
end:
BT_PUT(component_factory);
+++ /dev/null
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
- * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
- *
- * Some functions are based on older functions written by Mathieu Desnoyers.
- *
- * 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.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <glib.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <babeltrace/ctf-ir/stream.h>
-
-#define PRINT_ERR_STREAM ctf_fs->error_fp
-#define PRINT_PREFIX "ctf-fs-data-stream"
-#include "print.h"
-
-#include "ctf-fs.h"
-#include "ctf-fs-file.h"
-#include "ctf-fs-metadata.h"
-#include "ctf-notif-iter/ctf-notif-iter.h"
-
-static void ctf_fs_stream_destroy(struct ctf_fs_stream *stream)
-{
- if (stream->file) {
- ctf_fs_file_destroy(stream->file);
- }
-
- if (stream->stream) {
- BT_PUT(stream->stream);
- }
-
- if (stream->notif_iter) {
- bt_ctf_notif_iter_destroy(stream->notif_iter);
- }
-
- g_free(stream);
-}
-
-static size_t remaining_mmap_bytes(struct ctf_fs_stream *stream)
-{
- return stream->mmap_offset + stream->mmap_len -
- stream->request_offset;
-}
-
-static int stream_munmap(struct ctf_fs_stream *stream)
-{
- struct ctf_fs *ctf_fs = stream->file->ctf_fs;
-
- if (munmap(stream->mmap_addr, stream->mmap_len)) {
- PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n",
- stream->mmap_addr, stream->mmap_len,
- stream->file->path->str, stream->file->fp,
- strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-static int mmap_next(struct ctf_fs_stream *stream)
-{
- struct ctf_fs *ctf_fs = stream->file->ctf_fs;
- int ret = 0;
-
- /* Unmap old region */
- if (stream->mmap_addr) {
- if (stream_munmap(stream)) {
- goto error;
- }
-
- stream->mmap_offset += stream->mmap_len;
- stream->request_offset = stream->mmap_offset;
- }
-
- /* Map new region */
- stream->mmap_addr = mmap((void *) 0, stream->mmap_len,
- PROT_READ, MAP_PRIVATE, fileno(stream->file->fp),
- stream->mmap_offset);
- if (stream->mmap_addr == MAP_FAILED) {
- PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n",
- stream->mmap_len, stream->file->path->str,
- stream->file->fp, stream->mmap_offset,
- strerror(errno));
- goto error;
- }
-
- goto end;
-
-error:
- stream_munmap(stream);
- ret = -1;
-
-end:
- return ret;
-}
-
-static enum bt_ctf_notif_iter_medium_status medop_request_bytes(
- size_t request_sz, uint8_t **buffer_addr,
- size_t *buffer_sz, void *data)
-{
- enum bt_ctf_notif_iter_medium_status status =
- BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
- struct ctf_fs_stream *stream = data;
- struct ctf_fs *ctf_fs = stream->file->ctf_fs;
-
- if (request_sz == 0) {
- goto end;
- }
-
- /* Check if we need an initial memory map */
- if (!stream->mmap_addr) {
- if (mmap_next(stream)) {
- PERR("Cannot memory-map initial region of file \"%s\" (%p)\n",
- stream->file->path->str, stream->file->fp);
- goto error;
- }
- }
-
- /* Check if we have at least one memory-mapped byte left */
- if (remaining_mmap_bytes(stream) == 0) {
- /* Are we at the end of the file? */
- if (stream->request_offset == stream->file->size) {
- PDBG("Reached end of file \"%s\" (%p)\n",
- stream->file->path->str, stream->file->fp);
- status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
- goto end;
- }
-
- if (mmap_next(stream)) {
- PERR("Cannot memory-map next region of file \"%s\" (%p)\n",
- stream->file->path->str, stream->file->fp);
- goto error;
- }
- }
-
- *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz);
- *buffer_addr = ((uint8_t *) stream->mmap_addr) +
- stream->request_offset - stream->mmap_offset;
- stream->request_offset += *buffer_sz;
- goto end;
-
-error:
- status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
-
-end:
- return status;
-}
-
-static struct bt_ctf_stream *medop_get_stream(
- struct bt_ctf_stream_class *stream_class, void *data)
-{
- struct ctf_fs_stream *fs_stream = data;
- struct ctf_fs *ctf_fs = fs_stream->file->ctf_fs;
-
- if (!fs_stream->stream) {
- int64_t id = bt_ctf_stream_class_get_id(stream_class);
-
- PDBG("Creating stream out of stream class %" PRId64 "\n", id);
- fs_stream->stream = bt_ctf_stream_create(stream_class,
- fs_stream->file->path->str);
- if (!fs_stream->stream) {
- PERR("Cannot create stream (stream class %" PRId64 ")\n",
- id);
- }
- }
-
- return fs_stream->stream;
-}
-
-static struct bt_ctf_notif_iter_medium_ops medops = {
- .request_bytes = medop_request_bytes,
- .get_stream = medop_get_stream,
-};
-
-static struct ctf_fs_stream *ctf_fs_stream_create(struct ctf_fs *ctf_fs,
- struct ctf_fs_file *file)
-{
- struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1);
-
- if (!stream) {
- goto error;
- }
-
- stream->file = file;
- stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata.trace,
- 12, medops, stream, ctf_fs->error_fp);
- if (!stream->notif_iter) {
- goto error;
- }
- stream->mmap_len = ctf_fs->page_size;
-
- goto end;
-
-error:
- /* Do not touch borrowed file */
- stream->file = NULL;
- ctf_fs_stream_destroy(stream);
- stream = NULL;
-
-end:
- return stream;
-}
-
-int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs)
-{
- int ret = 0;
- GError *error = NULL;
- GDir *dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
- const char *name;
-
- if (!dir) {
- PERR("Cannot open directory \"%s\": %s (code %d)\n",
- ctf_fs->trace_path->str, error->message,
- error->code);
- goto error;
- }
-
- while ((name = g_dir_read_name(dir))) {
- struct ctf_fs_file *file = NULL;
- struct ctf_fs_stream *stream = NULL;
-
- if (strcmp(name, CTF_FS_METADATA_FILENAME) == 0) {
- /* Ignore the metadata stream */
- PDBG("Ignoring metadata file \"%s\"\n",
- name);
- continue;
- }
-
- if (name[0] == '.') {
- PDBG("Ignoring hidden file \"%s\"\n",
- name);
- continue;
- }
-
- /* Create the file */
- file = ctf_fs_file_create(ctf_fs);
- if (!file) {
- PERR("Cannot create stream file object\n");
- goto error;
- }
-
- /* Create full path string */
- g_string_append(file->path, ctf_fs->trace_path->str);
- g_string_append(file->path, "/");
- g_string_append(file->path, name);
-
- if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
- PDBG("Ignoring non-regular file \"%s\"\n", name);
- ctf_fs_file_destroy(file);
- continue;
- }
-
- /* Open the file */
- if (ctf_fs_file_open(ctf_fs, file, "rb")) {
- ctf_fs_file_destroy(file);
- goto error;
- }
-
- /* Create a private stream */
- stream = ctf_fs_stream_create(ctf_fs, file);
- if (!stream) {
- ctf_fs_file_destroy(file);
- goto error;
- }
-
- /* Append file to the array of files */
- g_ptr_array_add(ctf_fs->data_stream.streams, stream);
- }
-
- goto end;
-
-error:
- ret = -1;
-
-end:
- if (dir) {
- g_dir_close(dir);
- dir = NULL;
- }
-
- if (error) {
- g_error_free(error);
- }
-
- return ret;
-}
-
-int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs,
- struct ctf_fs_data_stream *data_stream)
-{
- int ret = 0;
-
- data_stream->streams = g_ptr_array_new_with_free_func(
- (GDestroyNotify) ctf_fs_stream_destroy);
- if (!data_stream->streams) {
- PERR("Cannot allocate array of streams\n");
- goto error;
- }
-
- goto end;
-
-error:
- ret = -1;
-
-end:
- return ret;
-}
-
-void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream)
-{
- g_ptr_array_free(data_stream->streams, TRUE);
-}
-
-int ctf_fs_data_stream_get_next_notification(
- struct ctf_fs *ctf_fs,
- struct bt_ctf_notif_iter_notif **notification)
-{
- int ret = 0;
- struct ctf_fs_stream *stream = g_ptr_array_index(
- ctf_fs->data_stream.streams, 0);
- enum bt_ctf_notif_iter_status status;
-
- status = bt_ctf_notif_iter_get_next_notification(
- stream->notif_iter, notification);
- if (status != BT_CTF_NOTIF_ITER_STATUS_OK &&
- status != BT_CTF_NOTIF_ITER_STATUS_EOF) {
- goto error;
- }
- if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
- *notification = NULL;
- }
-
- goto end;
-
-error:
- ret = -1;
-
-end:
- return ret;
-}
+++ /dev/null
-#ifndef CTF_FS_DATA_STREAM_H
-#define CTF_FS_DATA_STREAM_H
-
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@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.
- */
-
-#include <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/trace.h>
-
-#include "ctf-notif-iter/ctf-notif-iter.h"
-
-struct ctf_fs_stream {
- struct ctf_fs_file *file;
- struct bt_ctf_stream *stream;
- struct bt_ctf_notif_iter *notif_iter;
- void *mmap_addr;
- size_t mmap_len;
- off_t mmap_offset;
- off_t request_offset;
-};
-
-struct ctf_fs_data_stream {
- GPtrArray *streams;
-};
-
-BT_HIDDEN
-int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs,
- struct ctf_fs_data_stream *data_stream);
-
-BT_HIDDEN
-void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream);
-
-BT_HIDDEN
-int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs);
-
-BT_HIDDEN
-int ctf_fs_data_stream_get_next_notification(
- struct ctf_fs *ctf_fs,
- struct bt_ctf_notif_iter_notif **notification);
-
-#endif /* CTF_FS_DATA_STREAM_H */
+++ /dev/null
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@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.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <glib.h>
-
-#define PRINT_ERR_STREAM ctf_fs->error_fp
-#define PRINT_PREFIX "ctf-fs-file"
-#include "print.h"
-
-#include "ctf-fs-file.h"
-
-void ctf_fs_file_destroy(struct ctf_fs_file *file)
-{
- struct ctf_fs *ctf_fs = file->ctf_fs;
-
- if (!file) {
- return;
- }
-
- if (file->fp) {
- PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp);
-
- if (fclose(file->fp)) {
- PERR("Cannot close file \"%s\": %s\n", file->path->str,
- strerror(errno));
- }
- }
-
- if (file->path) {
- g_string_free(file->path, TRUE);
- }
-
- g_free(file);
-}
-
-struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs *ctf_fs)
-{
- struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1);
-
- if (!file) {
- goto error;
- }
-
- file->ctf_fs = ctf_fs;
- file->path = g_string_new(NULL);
- if (!file->path) {
- goto error;
- }
-
- goto end;
-
-error:
- ctf_fs_file_destroy(file);
- file = NULL;
-
-end:
- return file;
-}
-
-int ctf_fs_file_open(struct ctf_fs *ctf_fs, struct ctf_fs_file *file,
- const char *mode)
-{
- int ret = 0;
- struct stat stat;
-
- PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode);
- file->fp = fopen(file->path->str, mode);
- if (!file->fp) {
- PERR("Cannot open file \"%s\" with mode \"%s\": %s",
- file->path->str, mode, strerror(errno));
- goto error;
- }
-
- PDBG("Opened file: %p\n", file->fp);
-
- if (fstat(fileno(file->fp), &stat)) {
- PERR("Cannot get file informations: %s\n", strerror(errno));
- goto error;
- }
-
- file->size = stat.st_size;
- PDBG(" File is %zu bytes\n", file->size);
- goto end;
-
-error:
- ret = -1;
-
- if (file->fp) {
- if (fclose(file->fp)) {
- PERR("Cannot close file \"%s\": %s\n", file->path->str,
- strerror(errno));
- }
- }
-
-end:
- return ret;
-}
+++ /dev/null
-#ifndef CTF_FS_FILE_H
-#define CTF_FS_FILE_H
-
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@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.
- */
-
-#include <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-
-#include "ctf-fs.h"
-
-struct ctf_fs_file {
- struct ctf_fs *ctf_fs;
- GString *path;
- FILE *fp;
- off_t size;
-};
-
-BT_HIDDEN
-void ctf_fs_file_destroy(struct ctf_fs_file *file);
-
-BT_HIDDEN
-struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs *ctf_fs);
-
-BT_HIDDEN
-int ctf_fs_file_open(struct ctf_fs *ctf_fs, struct ctf_fs_file *file,
- const char *mode);
-
-#endif /* CTF_FS_FILE_H */
+++ /dev/null
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
- * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
- *
- * Some functions are based on older functions written by Mathieu Desnoyers.
- *
- * 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.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <glib.h>
-#include <babeltrace/compat/uuid.h>
-#include <babeltrace/compat/memstream.h>
-
-#define PRINT_ERR_STREAM ctf_fs->error_fp
-#define PRINT_PREFIX "ctf-fs-metadata"
-#include "print.h"
-
-#include "ctf-fs.h"
-#include "ctf-fs-file.h"
-#include "metadata-parsing/ctf-ast.h"
-#include "metadata-parsing/ctf-scanner.h"
-
-#define TSDL_MAGIC 0x75d11d57
-
-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__));
-
-static struct ctf_fs_file *get_file(struct ctf_fs *ctf_fs,
- const char *trace_path)
-{
- struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs);
-
- if (!file) {
- goto error;
- }
-
- g_string_append(file->path, trace_path);
- g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME);
-
- if (ctf_fs_file_open(ctf_fs, file, "rb")) {
- goto error;
- }
-
- goto end;
-
-error:
- if (file) {
- ctf_fs_file_destroy(file);
- file = NULL;
- }
-
-end:
- return file;
-}
-
-static
-bool is_packetized(struct ctf_fs *ctf_fs, struct ctf_fs_file *file)
-{
- uint32_t magic;
- size_t len;
- int ret = 0;
-
- len = fread(&magic, sizeof(magic), 1, file->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;
- }
-
-end:
- rewind(file->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 *ctf_fs, FILE *in_fp, FILE *out_fp)
-{
- 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 (ctf_fs->metadata.bo != 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->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;
-}
-
-static
-int packetized_file_to_buf(struct ctf_fs *ctf_fs, struct ctf_fs_file *file,
- uint8_t **buf)
-{
- 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(file->fp) != 0) {
- break;
- }
-
- tret = decode_packet(ctf_fs, file->fp, out_fp);
- 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;
-}
-
-void ctf_fs_metadata_set_trace(struct ctf_fs *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;
-
- if (!file) {
- PERR("Cannot create metadata file object\n");
- goto error;
- }
-
- if (babeltrace_debug) {
- // yydebug = 1;
- }
-
- if (is_packetized(ctf_fs, file)) {
- PDBG("Metadata file \"%s\" is packetized\n", file->path->str);
- ret = packetized_file_to_buf(ctf_fs, file, &buf);
- 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;
- }
-
- ret = ctf_visitor_generate_ir(ctf_fs->error_fp, &scanner->ast->root,
- &ctf_fs->metadata.trace);
- if (ret) {
- PERR("Cannot create trace object from metadata AST\n");
- goto error;
- }
-
- goto end;
-
-error:
- if (ctf_fs->metadata.text) {
- free(ctf_fs->metadata.text);
- ctf_fs->metadata.text = NULL;
- }
-
-end:
- if (file) {
- ctf_fs_file_destroy(file);
- }
-
- if (scanner) {
- ctf_scanner_free(scanner);
- }
-}
-
-int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata)
-{
- /* Nothing to initialize for the moment */
- return 0;
-}
-
-void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata)
-{
- if (metadata->text) {
- free(metadata->text);
- }
-
- if (metadata->trace) {
- BT_PUT(metadata->trace);
- }
-}
+++ /dev/null
-#ifndef CTF_FS_METADATA_H
-#define CTF_FS_METADATA_H
-
-/*
- * Copyright 2016 - Philippe Proulx <pproulx@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.
- */
-
-#include <stdio.h>
-#include <glib.h>
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-ir/trace.h>
-
-#define CTF_FS_METADATA_FILENAME "metadata"
-
-struct ctf_fs;
-
-struct ctf_fs_metadata {
- struct bt_ctf_trace *trace;
- uint8_t uuid[16];
- bool is_uuid_set;
- int bo;
- char *text;
-};
-
-BT_HIDDEN
-int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata);
-
-BT_HIDDEN
-void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata);
-
-BT_HIDDEN
-void ctf_fs_metadata_set_trace(struct ctf_fs *ctf_fs);
-
-#endif /* CTF_FS_METADATA_H */
+++ /dev/null
-#ifndef CTF_FS_PRINT_H
-#define CTF_FS_PRINT_H
-
-/*
- * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file.
- *
- * Copyright (c) 2016 Philippe Proulx <pproulx@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.
- */
-
-#include <stdio.h>
-
-#include "ctf-fs.h"
-
-#define PERR(fmt, ...) \
- do { \
- if (PRINT_ERR_STREAM) { \
- fprintf(PRINT_ERR_STREAM, \
- "Error: " PRINT_PREFIX ": " fmt, \
- ##__VA_ARGS__); \
- } \
- } while (0)
-
-#define PWARN(fmt, ...) \
- do { \
- if (PRINT_ERR_STREAM) { \
- fprintf(PRINT_ERR_STREAM, \
- "Warning: " PRINT_PREFIX ": " fmt, \
- ##__VA_ARGS__); \
- } \
- } while (0)
-
-#define PDBG(fmt, ...) \
- do { \
- if (ctf_fs_debug) { \
- fprintf(stderr, \
- "Debug: " PRINT_PREFIX ": " fmt, \
- ##__VA_ARGS__); \
- } \
- } while (0)
-
-#endif /* CTF_FS_PRINT_H */
}
source = container_of(component, struct bt_component_source, parent);
- if (source->init_iterator) {
+ if (!source->init_iterator) {
ret = BT_COMPONENT_STATUS_INVALID;
goto end;
}
AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include
-noinst_HEADERS = fs-internal.h
+noinst_HEADERS = \
+ fs.h \
+ data-stream.h \
+ file.h \
+ metadata.h \
+ print.h
noinst_LTLIBRARIES = libbabeltrace-plugin-ctf-fs.la
-# Plug-in system library
-libbabeltrace_plugin_ctf_fs_la_SOURCES = fs.c
+libbabeltrace_plugin_ctf_fs_la_LIBADD = \
+ $(builddir)/../common/libbabeltrace-plugin-ctf-common.la
+libbabeltrace_plugin_ctf_fs_la_SOURCES = \
+ fs.c \
+ data-stream.c \
+ metadata.c \
+ file.c
--- /dev/null
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
+ *
+ * Some functions are based on older functions written by Mathieu Desnoyers.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <inttypes.h>
+#include <sys/mman.h>
+#include <babeltrace/ctf-ir/stream.h>
+
+#define PRINT_ERR_STREAM ctf_fs->error_fp
+#define PRINT_PREFIX "ctf-fs-data-stream"
+#include "print.h"
+
+#include "file.h"
+#include "metadata.h"
+#include "../common/notif-iter/notif-iter.h"
+
+static void ctf_fs_stream_destroy(struct ctf_fs_stream *stream)
+{
+ if (stream->file) {
+ ctf_fs_file_destroy(stream->file);
+ }
+
+ if (stream->stream) {
+ BT_PUT(stream->stream);
+ }
+
+ if (stream->notif_iter) {
+ bt_ctf_notif_iter_destroy(stream->notif_iter);
+ }
+
+ g_free(stream);
+}
+
+static size_t remaining_mmap_bytes(struct ctf_fs_stream *stream)
+{
+ return stream->mmap_offset + stream->mmap_len -
+ stream->request_offset;
+}
+
+static int stream_munmap(struct ctf_fs_stream *stream)
+{
+ struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+
+ if (munmap(stream->mmap_addr, stream->mmap_len)) {
+ PERR("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s\n",
+ stream->mmap_addr, stream->mmap_len,
+ stream->file->path->str, stream->file->fp,
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mmap_next(struct ctf_fs_stream *stream)
+{
+ struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+ int ret = 0;
+
+ /* Unmap old region */
+ if (stream->mmap_addr) {
+ if (stream_munmap(stream)) {
+ goto error;
+ }
+
+ stream->mmap_offset += stream->mmap_len;
+ stream->request_offset = stream->mmap_offset;
+ }
+
+ /* Map new region */
+ stream->mmap_addr = mmap((void *) 0, stream->mmap_len,
+ PROT_READ, MAP_PRIVATE, fileno(stream->file->fp),
+ stream->mmap_offset);
+ if (stream->mmap_addr == MAP_FAILED) {
+ PERR("Cannot memory-map address (size %zu) of file \"%s\" (%p) at offset %zu: %s\n",
+ stream->mmap_len, stream->file->path->str,
+ stream->file->fp, stream->mmap_offset,
+ strerror(errno));
+ goto error;
+ }
+
+ goto end;
+
+error:
+ stream_munmap(stream);
+ ret = -1;
+
+end:
+ return ret;
+}
+
+static enum bt_ctf_notif_iter_medium_status medop_request_bytes(
+ size_t request_sz, uint8_t **buffer_addr,
+ size_t *buffer_sz, void *data)
+{
+ enum bt_ctf_notif_iter_medium_status status =
+ BT_CTF_NOTIF_ITER_MEDIUM_STATUS_OK;
+ struct ctf_fs_stream *stream = data;
+ struct ctf_fs_component *ctf_fs = stream->file->ctf_fs;
+
+ if (request_sz == 0) {
+ goto end;
+ }
+
+ /* Check if we need an initial memory map */
+ if (!stream->mmap_addr) {
+ if (mmap_next(stream)) {
+ PERR("Cannot memory-map initial region of file \"%s\" (%p)\n",
+ stream->file->path->str, stream->file->fp);
+ goto error;
+ }
+ }
+
+ /* Check if we have at least one memory-mapped byte left */
+ if (remaining_mmap_bytes(stream) == 0) {
+ /* Are we at the end of the file? */
+ if (stream->request_offset == stream->file->size) {
+ PDBG("Reached end of file \"%s\" (%p)\n",
+ stream->file->path->str, stream->file->fp);
+ status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_EOF;
+ goto end;
+ }
+
+ if (mmap_next(stream)) {
+ PERR("Cannot memory-map next region of file \"%s\" (%p)\n",
+ stream->file->path->str, stream->file->fp);
+ goto error;
+ }
+ }
+
+ *buffer_sz = MIN(remaining_mmap_bytes(stream), request_sz);
+ *buffer_addr = ((uint8_t *) stream->mmap_addr) +
+ stream->request_offset - stream->mmap_offset;
+ stream->request_offset += *buffer_sz;
+ goto end;
+
+error:
+ status = BT_CTF_NOTIF_ITER_MEDIUM_STATUS_ERROR;
+
+end:
+ return status;
+}
+
+static struct bt_ctf_stream *medop_get_stream(
+ struct bt_ctf_stream_class *stream_class, void *data)
+{
+ struct ctf_fs_stream *fs_stream = data;
+ struct ctf_fs_component *ctf_fs = fs_stream->file->ctf_fs;
+
+ if (!fs_stream->stream) {
+ int64_t id = bt_ctf_stream_class_get_id(stream_class);
+
+ PDBG("Creating stream out of stream class %" PRId64 "\n", id);
+ fs_stream->stream = bt_ctf_stream_create(stream_class,
+ fs_stream->file->path->str);
+ if (!fs_stream->stream) {
+ PERR("Cannot create stream (stream class %" PRId64 ")\n",
+ id);
+ }
+ }
+
+ return fs_stream->stream;
+}
+
+static struct bt_ctf_notif_iter_medium_ops medops = {
+ .request_bytes = medop_request_bytes,
+ .get_stream = medop_get_stream,
+};
+
+static struct ctf_fs_stream *ctf_fs_stream_create(
+ struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file)
+{
+ struct ctf_fs_stream *stream = g_new0(struct ctf_fs_stream, 1);
+
+ if (!stream) {
+ goto error;
+ }
+
+ stream->file = file;
+ stream->notif_iter = bt_ctf_notif_iter_create(ctf_fs->metadata.trace,
+ 12, medops, stream, ctf_fs->error_fp);
+ if (!stream->notif_iter) {
+ goto error;
+ }
+ stream->mmap_len = ctf_fs->page_size;
+
+ goto end;
+
+error:
+ /* Do not touch borrowed file */
+ stream->file = NULL;
+ ctf_fs_stream_destroy(stream);
+ stream = NULL;
+
+end:
+ return stream;
+}
+
+int ctf_fs_data_stream_open_streams(struct ctf_fs_component *ctf_fs)
+{
+ int ret = 0;
+ GError *error = NULL;
+ GDir *dir = g_dir_open(ctf_fs->trace_path->str, 0, &error);
+ const char *name;
+
+ if (!dir) {
+ PERR("Cannot open directory \"%s\": %s (code %d)\n",
+ ctf_fs->trace_path->str, error->message,
+ error->code);
+ goto error;
+ }
+
+ while ((name = g_dir_read_name(dir))) {
+ struct ctf_fs_file *file = NULL;
+ struct ctf_fs_stream *stream = NULL;
+
+ if (strcmp(name, CTF_FS_METADATA_FILENAME) == 0) {
+ /* Ignore the metadata stream */
+ PDBG("Ignoring metadata file \"%s\"\n",
+ name);
+ continue;
+ }
+
+ if (name[0] == '.') {
+ PDBG("Ignoring hidden file \"%s\"\n",
+ name);
+ continue;
+ }
+
+ /* Create the file */
+ file = ctf_fs_file_create(ctf_fs);
+ if (!file) {
+ PERR("Cannot create stream file object\n");
+ goto error;
+ }
+
+ /* Create full path string */
+ g_string_append(file->path, ctf_fs->trace_path->str);
+ g_string_append(file->path, "/");
+ g_string_append(file->path, name);
+
+ if (!g_file_test(file->path->str, G_FILE_TEST_IS_REGULAR)) {
+ PDBG("Ignoring non-regular file \"%s\"\n", name);
+ ctf_fs_file_destroy(file);
+ continue;
+ }
+
+ /* Open the file */
+ if (ctf_fs_file_open(ctf_fs, file, "rb")) {
+ ctf_fs_file_destroy(file);
+ goto error;
+ }
+
+ /* Create a private stream */
+ stream = ctf_fs_stream_create(ctf_fs, file);
+ if (!stream) {
+ ctf_fs_file_destroy(file);
+ goto error;
+ }
+
+ /* Append file to the array of files */
+ g_ptr_array_add(ctf_fs->data_stream.streams, stream);
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ if (dir) {
+ g_dir_close(dir);
+ dir = NULL;
+ }
+
+ if (error) {
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+int ctf_fs_data_stream_init(struct ctf_fs_component *ctf_fs,
+ struct ctf_fs_data_stream *data_stream)
+{
+ int ret = 0;
+
+ data_stream->streams = g_ptr_array_new_with_free_func(
+ (GDestroyNotify) ctf_fs_stream_destroy);
+ if (!data_stream->streams) {
+ PERR("Cannot allocate array of streams\n");
+ goto error;
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ return ret;
+}
+
+void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream)
+{
+ g_ptr_array_free(data_stream->streams, TRUE);
+}
+
+int ctf_fs_data_stream_get_next_notification(
+ struct ctf_fs_component *ctf_fs,
+ struct bt_ctf_notif_iter_notif **notification)
+{
+ int ret = 0;
+ struct ctf_fs_stream *stream = g_ptr_array_index(
+ ctf_fs->data_stream.streams, 0);
+ enum bt_ctf_notif_iter_status status;
+
+ status = bt_ctf_notif_iter_get_next_notification(
+ stream->notif_iter, notification);
+ if (status != BT_CTF_NOTIF_ITER_STATUS_OK &&
+ status != BT_CTF_NOTIF_ITER_STATUS_EOF) {
+ goto error;
+ }
+ if (status == BT_CTF_NOTIF_ITER_STATUS_EOF) {
+ *notification = NULL;
+ }
+
+ goto end;
+
+error:
+ ret = -1;
+
+end:
+ return ret;
+}
--- /dev/null
+#ifndef CTF_FS_DATA_STREAM_H
+#define CTF_FS_DATA_STREAM_H
+
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@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.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
+
+#include "ctf-notif-iter/ctf-notif-iter.h"
+
+struct ctf_fs_stream {
+ struct ctf_fs_file *file;
+ struct bt_ctf_stream *stream;
+ struct bt_ctf_notif_iter *notif_iter;
+ void *mmap_addr;
+ size_t mmap_len;
+ off_t mmap_offset;
+ off_t request_offset;
+};
+
+struct ctf_fs_data_stream {
+ GPtrArray *streams;
+};
+
+BT_HIDDEN
+int ctf_fs_data_stream_init(struct ctf_fs *ctf_fs,
+ struct ctf_fs_data_stream *data_stream);
+
+BT_HIDDEN
+void ctf_fs_data_stream_deinit(struct ctf_fs_data_stream *data_stream);
+
+BT_HIDDEN
+int ctf_fs_data_stream_open_streams(struct ctf_fs *ctf_fs);
+
+BT_HIDDEN
+int ctf_fs_data_stream_get_next_notification(
+ struct ctf_fs *ctf_fs,
+ struct bt_ctf_notif_iter_notif **notification);
+
+#endif /* CTF_FS_DATA_STREAM_H */
--- /dev/null
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@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.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <glib.h>
+
+#define PRINT_ERR_STREAM ctf_fs->error_fp
+#define PRINT_PREFIX "ctf-fs-file"
+#include "print.h"
+
+#include "file.h"
+
+void ctf_fs_file_destroy(struct ctf_fs_file *file)
+{
+ struct ctf_fs_component *ctf_fs = file->ctf_fs;
+
+ if (!file) {
+ return;
+ }
+
+ if (file->fp) {
+ PDBG("Closing file \"%s\" (%p)\n", file->path->str, file->fp);
+
+ if (fclose(file->fp)) {
+ PERR("Cannot close file \"%s\": %s\n", file->path->str,
+ strerror(errno));
+ }
+ }
+
+ if (file->path) {
+ g_string_free(file->path, TRUE);
+ }
+
+ g_free(file);
+}
+
+struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs)
+{
+ struct ctf_fs_file *file = g_new0(struct ctf_fs_file, 1);
+
+ if (!file) {
+ goto error;
+ }
+
+ file->ctf_fs = ctf_fs;
+ file->path = g_string_new(NULL);
+ if (!file->path) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ ctf_fs_file_destroy(file);
+ file = NULL;
+
+end:
+ return file;
+}
+
+int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
+ const char *mode)
+{
+ int ret = 0;
+ struct stat stat;
+
+ PDBG("Opening file \"%s\" with mode \"%s\"\n", file->path->str, mode);
+ file->fp = fopen(file->path->str, mode);
+ if (!file->fp) {
+ PERR("Cannot open file \"%s\" with mode \"%s\": %s",
+ file->path->str, mode, strerror(errno));
+ goto error;
+ }
+
+ PDBG("Opened file: %p\n", file->fp);
+
+ if (fstat(fileno(file->fp), &stat)) {
+ PERR("Cannot get file informations: %s\n", strerror(errno));
+ goto error;
+ }
+
+ file->size = stat.st_size;
+ PDBG(" File is %zu bytes\n", file->size);
+ goto end;
+
+error:
+ ret = -1;
+
+ if (file->fp) {
+ if (fclose(file->fp)) {
+ PERR("Cannot close file \"%s\": %s\n", file->path->str,
+ strerror(errno));
+ }
+ }
+
+end:
+ return ret;
+}
--- /dev/null
+#ifndef CTF_FS_FILE_H
+#define CTF_FS_FILE_H
+
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@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.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include "fs.h"
+
+BT_HIDDEN
+void ctf_fs_file_destroy(struct ctf_fs_file *file);
+
+BT_HIDDEN
+struct ctf_fs_file *ctf_fs_file_create(struct ctf_fs_component *ctf_fs);
+
+BT_HIDDEN
+int ctf_fs_file_open(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
+ const char *mode);
+
+#endif /* CTF_FS_FILE_H */
+++ /dev/null
-#ifndef BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H
-#define BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H
-
-/*
- * BabelTrace - CTF on File System Component
- *
- * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- *
- * Author: Jérémie Galarneau <jeremie.galarneau@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.
- */
-
-#include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/plugin/component.h>
-
-#define CTF_FS_COMPONENT_NAME "ctf"
-#define CTF_FS_COMPONENT_DESCRIPTION \
- "Component used to read a CTF trace located on a file system."
-
-struct ctf_fs_iterator {
- int dummy;
-};
-
-struct ctf_fs_component_options {
- bool opt_dummy : 1;
-};
-
-struct ctf_fs_component {
- struct ctf_fs_component_options options;
-};
-
-BT_HIDDEN
-enum bt_component_status ctf_fs_init(struct bt_component *source,
- struct bt_value *params);
-
-#endif /* BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H */
#include <babeltrace/plugin/notification/iterator.h>
#include <glib.h>
#include <assert.h>
-#include "fs-internal.h"
+#include <unistd.h>
+#include "fs.h"
static bool ctf_fs_debug;
return ret;
}
-static
-struct ctf_fs_component *ctf_fs_create(struct bt_value *params)
-{
- return g_new0(struct ctf_fs_component, 1);
-}
-
static
void ctf_fs_destroy_data(struct ctf_fs_component *component)
{
+ if (component->trace_path) {
+ g_string_free(component->trace_path, TRUE);
+ }
+
+// ctf_fs_metadata_fini(&component->metadata);
+// ctf_fs_data_stream_fini(&component->data_stream);
g_free(component);
}
ctf_fs_destroy_data(data);
}
+static
+struct ctf_fs_component *ctf_fs_create(struct bt_value *params)
+{
+ struct ctf_fs_component *ctf_fs;
+ struct bt_value *value;
+ const char *path;
+ enum bt_value_status ret;
+
+ ctf_fs = g_new0(struct ctf_fs_component, 1);
+ if (!ctf_fs) {
+ goto end;
+ }
+
+ /* FIXME: should probably look for a source URI */
+ value = bt_value_map_get(params, "path");
+ if (!value || bt_value_is_null(value) || !bt_value_is_string(value)) {
+ goto error;
+ }
+
+ ret = bt_value_string_get(value, &path);
+ if (ret != BT_VALUE_STATUS_OK) {
+ goto error;
+ }
+
+ ctf_fs->trace_path = g_string_new(path);
+ if (!ctf_fs->trace_path) {
+ goto error;
+ }
+
+ ctf_fs->error_fp = stderr;
+ ctf_fs->page_size = (size_t) getpagesize();
+
+end:
+ return ctf_fs;
+error:
+ ctf_fs_destroy_data(ctf_fs);
+ return ctf_fs;
+}
+
BT_HIDDEN
enum bt_component_status ctf_fs_init(struct bt_component *source,
struct bt_value *params)
--- /dev/null
+#ifndef BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H
+#define BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H
+
+/*
+ * BabelTrace - CTF on File System Component
+ *
+ * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Author: Jérémie Galarneau <jeremie.galarneau@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.
+ */
+
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/plugin/component.h>
+
+#define CTF_FS_COMPONENT_NAME "fs"
+#define CTF_FS_COMPONENT_DESCRIPTION \
+ "Component used to read a CTF trace located on a file system."
+
+static bool ctf_fs_debug;
+
+struct ctf_fs_file {
+ struct ctf_fs_component *ctf_fs;
+ GString *path;
+ FILE *fp;
+ off_t size;
+};
+
+struct ctf_fs_metadata {
+ struct bt_ctf_trace *trace;
+ uint8_t uuid[16];
+ bool is_uuid_set;
+ int bo;
+ char *text;
+};
+
+struct ctf_fs_stream {
+ struct ctf_fs_file *file;
+ struct bt_ctf_stream *stream;
+ struct bt_ctf_notif_iter *notif_iter;
+ void *mmap_addr;
+ size_t mmap_len;
+ off_t mmap_offset;
+ off_t request_offset;
+};
+
+struct ctf_fs_data_stream {
+ GPtrArray *streams;
+};
+
+struct ctf_fs_iterator {
+ int dummy;
+};
+
+struct ctf_fs_component_options {
+ bool opt_dummy : 1;
+};
+
+struct ctf_fs_component {
+ GString *trace_path;
+ FILE *error_fp;
+ size_t page_size;
+ struct ctf_fs_metadata metadata;
+ struct ctf_fs_data_stream data_stream;
+ struct ctf_fs_component_options options;
+};
+
+BT_HIDDEN
+enum bt_component_status ctf_fs_init(struct bt_component *source,
+ struct bt_value *params);
+
+#endif /* BABELTRACE_PLUGIN_CTF_FS_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@efficios.com>
+ * Copyright 2010-2011 - EfficiOS Inc. and Linux Foundation
+ *
+ * Some functions are based on older functions written by Mathieu Desnoyers.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <babeltrace/compat/uuid.h>
+#include <babeltrace/compat/memstream.h>
+
+#define PRINT_ERR_STREAM ctf_fs->error_fp
+#define PRINT_PREFIX "ctf-fs-metadata"
+#include "print.h"
+
+#include "fs.h"
+#include "file.h"
+#include "metadata.h"
+#include "../common/metadata/ast.h"
+#include "../common/metadata/scanner.h"
+
+#define TSDL_MAGIC 0x75d11d57
+
+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__));
+
+static struct ctf_fs_file *get_file(struct ctf_fs_component *ctf_fs,
+ const char *trace_path)
+{
+ struct ctf_fs_file *file = ctf_fs_file_create(ctf_fs);
+
+ if (!file) {
+ goto error;
+ }
+
+ g_string_append(file->path, trace_path);
+ g_string_append(file->path, "/" CTF_FS_METADATA_FILENAME);
+
+ if (ctf_fs_file_open(ctf_fs, file, "rb")) {
+ goto error;
+ }
+
+ goto end;
+
+error:
+ if (file) {
+ ctf_fs_file_destroy(file);
+ file = NULL;
+ }
+
+end:
+ return file;
+}
+
+static
+bool is_packetized(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file)
+{
+ uint32_t magic;
+ size_t len;
+ int ret = 0;
+
+ len = fread(&magic, sizeof(magic), 1, file->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;
+ }
+
+end:
+ rewind(file->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)
+{
+ 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 (ctf_fs->metadata.bo != 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->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;
+}
+
+static
+int packetized_file_to_buf(struct ctf_fs_component *ctf_fs, struct ctf_fs_file *file,
+ uint8_t **buf)
+{
+ 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(file->fp) != 0) {
+ break;
+ }
+
+ tret = decode_packet(ctf_fs, file->fp, out_fp);
+ 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;
+}
+
+void 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;
+
+ if (!file) {
+ PERR("Cannot create metadata file object\n");
+ goto error;
+ }
+
+ if (babeltrace_debug) {
+ // yydebug = 1;
+ }
+
+ if (is_packetized(ctf_fs, file)) {
+ PDBG("Metadata file \"%s\" is packetized\n", file->path->str);
+ ret = packetized_file_to_buf(ctf_fs, file, &buf);
+ 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;
+ }
+
+ ret = ctf_visitor_generate_ir(ctf_fs->error_fp, &scanner->ast->root,
+ &ctf_fs->metadata.trace);
+ if (ret) {
+ PERR("Cannot create trace object from metadata AST\n");
+ goto error;
+ }
+
+ goto end;
+
+error:
+ if (ctf_fs->metadata.text) {
+ free(ctf_fs->metadata.text);
+ ctf_fs->metadata.text = NULL;
+ }
+
+end:
+ if (file) {
+ ctf_fs_file_destroy(file);
+ }
+
+ if (scanner) {
+ ctf_scanner_free(scanner);
+ }
+}
+
+int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata)
+{
+ /* Nothing to initialize for the moment */
+ return 0;
+}
+
+void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata)
+{
+ if (metadata->text) {
+ free(metadata->text);
+ }
+
+ if (metadata->trace) {
+ BT_PUT(metadata->trace);
+ }
+}
--- /dev/null
+#ifndef CTF_FS_METADATA_H
+#define CTF_FS_METADATA_H
+
+/*
+ * Copyright 2016 - Philippe Proulx <pproulx@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.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/ctf-ir/trace.h>
+#include "fs.h"
+
+#define CTF_FS_METADATA_FILENAME "metadata"
+
+BT_HIDDEN
+int ctf_fs_metadata_init(struct ctf_fs_metadata *metadata);
+
+BT_HIDDEN
+void ctf_fs_metadata_deinit(struct ctf_fs_metadata *metadata);
+
+BT_HIDDEN
+void ctf_fs_metadata_set_trace(struct ctf_fs_component *ctf_fs);
+
+#endif /* CTF_FS_METADATA_H */
--- /dev/null
+#ifndef CTF_FS_PRINT_H
+#define CTF_FS_PRINT_H
+
+/*
+ * Define PRINT_PREFIX and PRINT_ERR_STREAM, then include this file.
+ *
+ * Copyright (c) 2016 Philippe Proulx <pproulx@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.
+ */
+
+#include <stdio.h>
+
+#define PERR(fmt, ...) \
+ do { \
+ if (PRINT_ERR_STREAM) { \
+ fprintf(PRINT_ERR_STREAM, \
+ "Error: " PRINT_PREFIX ": " fmt, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PWARN(fmt, ...) \
+ do { \
+ if (PRINT_ERR_STREAM) { \
+ fprintf(PRINT_ERR_STREAM, \
+ "Warning: " PRINT_PREFIX ": " fmt, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#define PDBG(fmt, ...) \
+ do { \
+ if (ctf_fs_debug) { \
+ fprintf(stderr, \
+ "Debug: " PRINT_PREFIX ": " fmt, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+#endif /* CTF_FS_PRINT_H */
*/
#include <babeltrace/plugin/plugin-macros.h>
-#include "fs/fs-internal.h"
+#include "fs/fs.h"
#include "lttng-live/lttng-live-internal.h"
-/* Initialize plug-in entry points. */
+/* Initialize plug-in description. */
BT_PLUGIN_NAME("ctf");
-BT_PLUGIN_DESCRIPTION("Babeltrace CTF plug-in.");
+BT_PLUGIN_DESCRIPTION("Built-in Babeltrace plug-in providing CTF read support.");
BT_PLUGIN_AUTHOR("Jérémie Galarneau");
BT_PLUGIN_LICENSE("MIT");
+/* Declare component classes implemented by this plug-in. */
BT_PLUGIN_COMPONENT_CLASSES_BEGIN
BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(CTF_FS_COMPONENT_NAME,
CTF_FS_COMPONENT_DESCRIPTION, ctf_fs_init);
BT_PLUGIN_SOURCE_COMPONENT_CLASS_ENTRY(LTTNG_LIVE_COMPONENT_NAME,
LTTNG_LIVE_COMPONENT_DESCRIPTION, lttng_live_init);
BT_PLUGIN_COMPONENT_CLASSES_END
-
}
/* Initialize plug-in entry points. */
-BT_PLUGIN_NAME("ctf-text");
+BT_PLUGIN_NAME("text");
BT_PLUGIN_DESCRIPTION("Babeltrace text output plug-in.");
BT_PLUGIN_AUTHOR("Jérémie Galarneau");
BT_PLUGIN_LICENSE("MIT");