#include <babeltrace/format.h>
#include <babeltrace/ctf/types.h>
#include <babeltrace/ctf/metadata.h>
+#include <babeltrace/babeltrace.h>
#include <errno.h>
-#include <sys/stat.h>
#include <sys/types.h>
-#include <dirent.h>
+#include <sys/stat.h>
#include <fcntl.h>
+#include <dirent.h>
#include <glib.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+
+#include "metadata/ctf-scanner.h"
+#include "metadata/ctf-parser.h"
+#include "metadata/ctf-ast.h"
+
+extern int yydebug;
struct trace_descriptor {
struct ctf_trace ctf_trace;
.close_trace = ctf_close_trace,
};
+/*
+ * TODO: for now, we treat the metadata file as a simple text file
+ * (without any header nor packets nor padding).
+ */
+static
+int ctf_open_trace_metadata_read(struct trace_descriptor *td)
+{
+ struct ctf_scanner *scanner;
+ FILE *fp;
+ int ret = 0;
+
+ td->ctf_trace.metadata.fd = openat(td->ctf_trace.dirfd,
+ "metadata", O_RDONLY);
+ if (td->ctf_trace.metadata.fd < 0) {
+ fprintf(stdout, "Unable to open metadata.\n");
+ return td->ctf_trace.metadata.fd;
+ }
+
+ if (babeltrace_debug)
+ yydebug = 1;
+
+ fp = fdopen(td->ctf_trace.metadata.fd, "r");
+ if (!fp) {
+ fprintf(stdout, "Unable to open metadata stream.\n");
+ ret = -errno;
+ goto end_stream;
+ }
+
+ scanner = ctf_scanner_alloc(fp);
+ if (!scanner) {
+ fprintf(stdout, "Error allocating scanner\n");
+ ret = -ENOMEM;
+ goto end_scanner_alloc;
+ }
+ ret = ctf_scanner_append_ast(scanner);
+ if (ret) {
+ fprintf(stdout, "Error creating AST\n");
+ goto end;
+ }
+
+ if (babeltrace_debug) {
+ ret = ctf_visitor_print_xml(stdout, 0, &scanner->ast->root);
+ if (ret) {
+ fprintf(stdout, "Error visiting AST for XML output\n");
+ goto end;
+ }
+ }
+
+ ret = ctf_visitor_semantic_check(stdout, 0, &scanner->ast->root);
+ if (ret) {
+ fprintf(stdout, "Error in CTF semantic validation %d\n", ret);
+ goto end;
+ }
+ ret = ctf_visitor_construct_metadata(stdout, 0, &scanner->ast->root,
+ &td->ctf_trace, BYTE_ORDER);
+ if (ret) {
+ fprintf(stdout, "Error in CTF metadata constructor %d\n", ret);
+ goto end;
+ }
+end:
+ ctf_scanner_free(scanner);
+end_scanner_alloc:
+ fclose(fp);
+end_stream:
+ close(td->ctf_trace.metadata.fd);
+ return ret;
+}
+
static
int ctf_open_trace_read(struct trace_descriptor *td, const char *path, int flags)
{
int ret;
+ struct dirent *dirent;
+ struct dirent *diriter;
+ size_t dirent_len;
td->ctf_trace.flags = flags;
goto error;
}
+ td->ctf_trace.dirfd = open(path, 0);
+ if (td->ctf_trace.dirfd < 0) {
+ fprintf(stdout, "Unable to open trace directory file descriptor.\n");
+ ret = -ENOENT;
+ goto error_dirfd;
+ }
+ /*
+ * Keep the metadata file separate.
+ */
+ ret = ctf_open_trace_metadata_read(td);
+ if (ret) {
+ goto error_metadata;
+ }
/*
* Open each stream: for each file, try to open, check magic
* number, and get the stream ID to add to the right location in
* the stream array.
- *
- * Keep the metadata file separate.
*/
+ dirent_len = offsetof(struct dirent, d_name) +
+ fpathconf(td->ctf_trace.dirfd, _PC_NAME_MAX) + 1;
+ dirent = malloc(dirent_len);
- /*
- * Use the metadata file to populate the trace metadata.
- */
-
+ for (;;) {
+ ret = readdir_r(td->ctf_trace.dir, dirent, &diriter);
+ if (ret) {
+ fprintf(stdout, "Readdir error.\n");
+ goto readdir_error;
+
+ }
+ if (!diriter)
+ break;
+ if (!strcmp(diriter->d_name, ".")
+ || !strcmp(diriter->d_name, "..")
+ || !strcmp(diriter->d_name, "metadata"))
+ continue;
+ }
+ free(dirent);
return 0;
+
+readdir_error:
+ free(dirent);
+error_metadata:
+ close(td->ctf_trace.dirfd);
+error_dirfd:
+ closedir(td->ctf_trace.dir);
error:
return ret;
}
if (ret)
return ret;
+ /* Open trace directory */
+ td->ctf_trace.dir = opendir(path);
+ if (!td->ctf_trace.dir) {
+ fprintf(stdout, "Unable to open trace directory.\n");
+ ret = -ENOENT;
+ goto error;
+ }
+
+
return 0;
+
+error:
+ return ret;
}
struct trace_descriptor *ctf_open_trace(const char *path, int flags)
struct trace_descriptor *td;
int ret;
- td = g_new(struct trace_descriptor, 1);
+ td = g_new0(struct trace_descriptor, 1);
switch (flags) {
case O_RDONLY:
int yylex(union YYSTYPE *yyval, struct ctf_scanner *scanner);
int yylex_init_extra(struct ctf_scanner *scanner, yyscan_t * ptr_yy_globals);
int yylex_destroy(yyscan_t yyscanner);
-void yyset_in(FILE * in_str, yyscan_t scanner);
+void yyrestart(FILE * in_str, yyscan_t scanner);
int yydebug;
fprintf(stderr, "yylex_init error\n");
goto cleanup_scanner;
}
- yyset_in(input, scanner);
+ /* Start processing new stream */
+ yyrestart(input, scanner->scanner);
scanner->ast = ctf_ast_alloc();
if (!scanner->ast)
scanner->cs = &scanner->root_scope;
CDS_INIT_LIST_HEAD(&scanner->allocated_strings);
+ if (yydebug)
+ fprintf(stdout, "Scanner input is a%s.\n",
+ isatty(fileno(input)) ? "n interactive tty" :
+ " noninteractive file");
+
return scanner;
cleanup_lexer:
struct ctf_stream;
struct ctf_event;
+struct ctf_stream_file {
+ /* Information about stream backing file */
+ int fd;
+ char *mmap; /* current stream mmap */
+ struct stream_pos pos; /* current stream position */
+};
+
#define CTF_TRACE_SET_FIELD(ctf_trace, field) \
do { \
(ctf_trace)->field_mask |= CTF_TRACE_ ## field; \
struct declaration_scope *declaration_scope;
GPtrArray *streams; /* Array of struct ctf_stream pointers*/
+ struct ctf_stream_file metadata;
uint64_t major;
uint64_t minor;
/* Information about trace backing directory and files */
DIR *dir;
+ int dirfd;
int flags; /* open flags */
};
CTF_STREAM_stream_id = (1 << 0),
} field_mask;
- /* Information about stream backing file */
- int fd;
- char *mmap; /* current stream mmap */
- struct stream_pos pos; /* current stream position */
+ struct ctf_stream_file file; /* Backing file */
};
#define CTF_EVENT_SET_FIELD(ctf_event, field) \