lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20170426203028.13900-2-federico.vaga@vaga.pv.it>
Date:   Wed, 26 Apr 2017 22:30:27 +0200
From:   Federico Vaga <federico.vaga@...a.pv.it>
To:     Steven Rostedt <rostedt@...dmis.org>
Cc:     LKML <linux-kernel@...r.kernel.org>,
        Federico Vaga <federico.vaga@...a.pv.it>
Subject: [PATCH 1/2] trace-cmd: uniform command implementation

Most of the commands have the implementation in a dedicated file.
Those commands without a dedicated file are implemented in the
`main()` function. This patch uniform the code by moving the commands
implemented in the `main()` function to dedicated files.

Signed-off-by: Federico Vaga <federico.vaga@...a.pv.it>
---
 Makefile             |   3 +-
 trace-check-events.c |  66 ++++++
 trace-cmd.c          | 631 +--------------------------------------------------
 trace-list.c         | 486 +++++++++++++++++++++++++++++++++++++++
 trace-local.h        |   7 +
 trace-show.c         | 176 ++++++++++++++
 6 files changed, 741 insertions(+), 628 deletions(-)
 create mode 100644 trace-check-events.c
 create mode 100644 trace-list.c
 create mode 100644 trace-show.c

diff --git a/Makefile b/Makefile
index a3c6bfa..2be2754 100644
--- a/Makefile
+++ b/Makefile
@@ -341,7 +341,8 @@ TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-filter-hash.o trace-dialog.
 		trace-xml.o
 TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \
 	 trace-stack.o trace-hist.o trace-mem.o trace-snapshot.o trace-stat.o \
-	 trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o
+	 trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o \
+	 trace-check-events.o trace-show.o trace-list.o
 TRACE_VIEW_OBJS = trace-view.o trace-view-store.o
 TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o
 TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS)
diff --git a/trace-check-events.c b/trace-check-events.c
new file mode 100644
index 0000000..c5a0127
--- /dev/null
+++ b/trace-check-events.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@...hat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "trace-local.h"
+
+void trace_check_events(int argc, char **argv)
+{
+	const char *tracing;
+	int ret, c;
+	struct pevent *pevent = NULL;
+	struct plugin_list *list = NULL;
+
+	while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) {
+		switch (c) {
+		case 'h':
+		default:
+			usage(argv);
+			break;
+		case 'N':
+			tracecmd_disable_plugins = 1;
+			break;
+		}
+	}
+	tracing = tracecmd_get_tracing_dir();
+
+	if (!tracing) {
+		printf("Can not find or mount tracing directory!\n"
+		       "Either tracing is not configured for this "
+		       "kernel\n"
+		       "or you do not have the proper permissions to "
+		       "mount the directory");
+		exit(EINVAL);
+	}
+
+	pevent = pevent_alloc();
+	if (!pevent)
+		exit(EINVAL);
+	list = tracecmd_load_plugins(pevent);
+	ret = tracecmd_fill_local_events(tracing, pevent);
+	if (ret || pevent->parsing_failures)
+		ret = EINVAL;
+	tracecmd_unload_plugins(list, pevent);
+	pevent_free(pevent);
+
+	return;
+}
diff --git a/trace-cmd.c b/trace-cmd.c
index 6a023e8..39bcc06 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -75,346 +75,9 @@ void *malloc_or_die(unsigned int size)
 	return data;
 }
 
-static void dump_file_content(const char *path)
-{
-	char buf[BUFSIZ];
-	ssize_t n;
-	FILE *fp;
-
-	fp = fopen(path, "r");
-	if (!fp)
-		die("reading %s", path);
-
-	do {
-		n = fread(buf, 1, BUFSIZ, fp);
-		if (n > 0)
-			fwrite(buf, 1, n, stdout);
-	} while (n > 0);
-	fclose(fp);
-}
-
-void show_file(const char *name)
-{
-	char *path;
-
-	path = tracecmd_get_tracing_file(name);
-	dump_file_content(path);
-	tracecmd_put_tracing_file(path);
-}
-
-typedef int (*process_file_func)(char *buf, int len);
-
-static void process_file_re(process_file_func func,
-			    const char *name, const char *re)
-{
-	regex_t reg;
-	char *path;
-	char *buf = NULL;
-	char *str;
-	FILE *fp;
-	ssize_t n;
-	size_t l = strlen(re);
-
-	/* Just in case :-p */
-	if (!re || l == 0) {
-		show_file(name);
-		return;
-	}
-
-	/* Handle the newline at end of names for the user */
-	str = malloc(l + 3);
-	if (!str)
-		die("Failed to allocate reg ex %s", re);
-	strcpy(str, re);
-	if (re[l-1] == '$')
-		strcpy(&str[l-1], "\n*$");
-		
-	if (regcomp(&reg, str, REG_ICASE|REG_NOSUB))
-		die("invalid function regex '%s'", re);
-
-	free(str);
-
-	path = tracecmd_get_tracing_file(name);
-	fp = fopen(path, "r");
-	if (!fp)
-		die("reading %s", path);
-	tracecmd_put_tracing_file(path);
-
-	do {
-		n = getline(&buf, &l, fp);
-		if (n > 0 && regexec(&reg, buf, 0, NULL, 0) == 0)
-			func(buf, n);
-	} while (n > 0);
-	free(buf);
-	fclose(fp);
-
-	regfree(&reg);
-}
-
-static int show_file_write(char *buf, int len)
-{
-	return fwrite(buf, 1, len, stdout);
-}
-
-static void show_file_re(const char *name, const char *re)
-{
-	process_file_re(show_file_write, name, re);
-}
-
-static char *get_event_file(const char *type, char *buf, int len)
-{
-	char *system;
-	char *event;
-	char *path;
-	char *file;
-
-	if (buf[len-1] == '\n')
-		buf[len-1] = '\0';
-
-	system = strtok(buf, ":");
-	if (!system)
-		die("no system found in %s", buf);
-
-	event = strtok(NULL, ":");
-	if (!event)
-		die("no event found in %s\n", buf);
-
-	path = tracecmd_get_tracing_file("events");
-	file = malloc(strlen(path) + strlen(system) + strlen(event) +
-		      strlen(type) + strlen("///") + 1);
-	if (!file)
-		die("Failed to allocate event file %s %s", system, event);
-	sprintf(file, "%s/%s/%s/%s", path, system, event, type);
-	tracecmd_put_tracing_file(path);
-
-	return file;
-}
-
-static int event_filter_write(char *buf, int len)
-{
-	char *file;
-
-	if (buf[len-1] == '\n')
-		buf[len-1] = '\0';
-
-	printf("%s\n", buf);
-
-	file = get_event_file("filter", buf, len);
-	dump_file_content(file);
-	free(file);
-	printf("\n");
-
-	return 0;
-}
-
-static int event_trigger_write(char *buf, int len)
-{
-	char *file;
-
-	if (buf[len-1] == '\n')
-		buf[len-1] = '\0';
-
-	printf("%s\n", buf);
-
-	file = get_event_file("trigger", buf, len);
-	dump_file_content(file);
-	free(file);
-	printf("\n");
-
-	return 0;
-}
-
-static int event_format_write(char *fbuf, int len)
-{
-	char *file = get_event_file("format", fbuf, len);
-	char *buf = NULL;
-	size_t l;
-	FILE *fp;
-	int n;
-
-	/* The get_event_file() crops system in fbuf */
-	printf("system: %s\n", fbuf);
-
-	/* Don't print the print fmt, it's ugly */
-
-	fp = fopen(file, "r");
-	if (!fp)
-		die("reading %s", file);
-
-	do {
-		n = getline(&buf, &l, fp);
-		if (n > 0) {
-			if (strncmp(buf, "print fmt", 9) == 0)
-				break;
-			fwrite(buf, 1, n, stdout);
-		}
-	} while (n > 0);
-	fclose(fp);
-	free(buf);
-	free(file);
-
-	return 0;
-}
-
-static void show_event_filter_re(const char *re)
-{
-	process_file_re(event_filter_write, "available_events", re);
-}
-
-static void show_event_trigger_re(const char *re)
-{
-	process_file_re(event_trigger_write, "available_events", re);
-}
-
-static void show_event_format_re(const char *re)
-{
-	process_file_re(event_format_write, "available_events", re);
-}
-
-void show_instance_file(struct buffer_instance *instance, const char *name)
-{
-	char *path;
-
-	path = get_instance_file(instance, name);
-	dump_file_content(path);
-	tracecmd_put_tracing_file(path);
-}
-
-enum {
-	SHOW_EVENT_FORMAT		= 1 << 0,
-	SHOW_EVENT_FILTER		= 1 << 1,
-	SHOW_EVENT_TRIGGER		= 1 << 2,
-};
-
-static void show_events(const char *eventre, int flags)
-{
-	if (flags && !eventre)
-		die("When specifying event files, an event must be named");
-
-	if (eventre) {
-		if (flags & SHOW_EVENT_FORMAT)
-			show_event_format_re(eventre);
-
-		else if (flags & SHOW_EVENT_FILTER)
-			show_event_filter_re(eventre);
-
-		else if (flags & SHOW_EVENT_TRIGGER)
-			show_event_trigger_re(eventre);
-		else
-			show_file_re("available_events", eventre);
-	} else
-		show_file("available_events");
-}
-
-static void show_tracers(void)
-{
-	show_file("available_tracers");
-}
-
-static void show_options(void)
-{
-	show_file("trace_options");
-}
-
-static void show_clocks(void)
-{
-	show_file("trace_clock");
-}
-
-static void show_functions(const char *funcre)
-{
-	if (funcre)
-		show_file_re("available_filter_functions", funcre);
-	else
-		show_file("available_filter_functions");
-}
-
-static void show_buffers(void)
-{
-	struct dirent *dent;
-	DIR *dir;
-	char *path;
-	int printed = 0;
-
-	path = tracecmd_get_tracing_file("instances");
-	dir = opendir(path);
-	tracecmd_put_tracing_file(path);
-	if (!dir)
-		die("Can not read instance directory");
-
-	while ((dent = readdir(dir))) {
-		const char *name = dent->d_name;
-
-		if (strcmp(name, ".") == 0 ||
-		    strcmp(name, "..") == 0)
-			continue;
-
-		printf("%s\n", name);
-		printed = 1;
-	}
-	closedir(dir);
-
-	if (!printed)
-		printf("No buffer instances defined\n");
-}
-
-static void show_plugins(void)
-{
-	struct pevent *pevent;
-	struct plugin_list *list;
-	struct trace_seq s;
-
-	pevent = pevent_alloc();
-	if (!pevent)
-		die("Can not allocate pevent\n");
-
-	trace_seq_init(&s);
-
-	list = tracecmd_load_plugins(pevent);
-	trace_util_print_plugins(&s, "  ", "\n", list);
-	trace_seq_do_printf(&s);
-	tracecmd_unload_plugins(list, pevent);
-	pevent_free(pevent);
-}
-
-static void show_plugin_options(void)
-{
-	struct pevent *pevent;
-	struct plugin_list *list;
-	struct trace_seq s;
-
-	tracecmd_ftrace_load_options();
-
-	pevent = pevent_alloc();
-	if (!pevent)
-		die("Can not allocate pevent\n");
-
-	trace_seq_init(&s);
-
-	list = tracecmd_load_plugins(pevent);
-	trace_util_print_plugin_options(&s);
-	trace_seq_do_printf(&s);
-	tracecmd_unload_plugins(list, pevent);
-	pevent_free(pevent);
-}
-
-enum {
-	OPT_tracing_on			= 255,
-	OPT_current_tracer		= 254,
-	OPT_buffer_size_kb		= 253,
-	OPT_buffer_total_size_kb	= 252,
-	OPT_ftrace_filter		= 251,
-	OPT_ftrace_notrace		= 250,
-	OPT_ftrace_pid			= 249,
-	OPT_graph_function		= 248,
-	OPT_graph_notrace		= 247,
-	OPT_cpumask			= 246,
-};
 
 int main (int argc, char **argv)
 {
-	int c;
-
 	errno = 0;
 
 	if (argc < 2)
@@ -445,44 +108,8 @@ int main (int argc, char **argv)
 		trace_stack(argc, argv);
 		exit(0);
 	} else if (strcmp(argv[1], "check-events") == 0) {
-		const char *tracing;
-		int ret;
-		struct pevent *pevent = NULL;
-		struct plugin_list *list = NULL;
-
-		while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) {
-			switch (c) {
-			case 'h':
-			default:
-				usage(argv);
-				break;
-			case 'N':
-				tracecmd_disable_plugins = 1;
-				break;
-			}
-		}
-		tracing = tracecmd_get_tracing_dir();
-
-		if (!tracing) {
-			printf("Can not find or mount tracing directory!\n"
-				"Either tracing is not configured for this "
-				"kernel\n"
-				"or you do not have the proper permissions to "
-				"mount the directory");
-			exit(EINVAL);
-		}
-
-		pevent = pevent_alloc();
-		if (!pevent)
-			exit(EINVAL);
-		list = tracecmd_load_plugins(pevent);
-		ret = tracecmd_fill_local_events(tracing, pevent);
-		if (ret || pevent->parsing_failures)
-			ret = EINVAL;
-		tracecmd_unload_plugins(list, pevent);
-		pevent_free(pevent);
-		exit(ret);
-
+		trace_check_events(argc, argv);
+		exit(0);
 	} else if (strcmp(argv[1], "record") == 0 ||
 		   strcmp(argv[1], "start") == 0 ||
 		   strcmp(argv[1], "extract") == 0 ||
@@ -502,261 +129,11 @@ int main (int argc, char **argv)
 		show_plugin_options();
 		exit(0);
 	} else if (strcmp(argv[1], "show") == 0) {
-		const char *buffer = NULL;
-		const char *file = "trace";
-		const char *cpu = NULL;
-		struct buffer_instance *instance = &top_instance;
-		char cpu_path[128];
-		char *path;
-		int snap = 0;
-		int pipe = 0;
-		int show_name = 0;
-		int option_index = 0;
-		int stop = 0;
-		static struct option long_options[] = {
-			{"tracing_on", no_argument, NULL, OPT_tracing_on},
-			{"current_tracer", no_argument, NULL, OPT_current_tracer},
-			{"buffer_size", no_argument, NULL, OPT_buffer_size_kb},
-			{"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb},
-			{"ftrace_filter", no_argument, NULL, OPT_ftrace_filter},
-			{"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace},
-			{"ftrace_pid", no_argument, NULL, OPT_ftrace_pid},
-			{"graph_function", no_argument, NULL, OPT_graph_function},
-			{"graph_notrace", no_argument, NULL, OPT_graph_notrace},
-			{"cpumask", no_argument, NULL, OPT_cpumask},
-			{"help", no_argument, NULL, '?'},
-			{NULL, 0, NULL, 0}
-		};
-
-		while ((c = getopt_long(argc-1, argv+1, "B:c:fsp",
-					long_options, &option_index)) >= 0) {
-			switch (c) {
-			case 'h':
-				usage(argv);
-				break;
-			case 'B':
-				if (buffer)
-					die("Can only show one buffer at a time");
-				buffer = optarg;
-				instance = create_instance(optarg);
-				if (!instance)
-					die("Failed to create instance");
-				break;
-			case 'c':
-				if (cpu)
-					die("Can only show one CPU at a time");
-				cpu = optarg;
-				break;
-			case 'f':
-				show_name = 1;
-				break;
-			case 's':
-				snap = 1;
-				if (pipe)
-					die("Can not have -s and -p together");
-				break;
-			case 'p':
-				pipe = 1;
-				if (snap)
-					die("Can not have -s and -p together");
-				break;
-			case OPT_tracing_on:
-				show_instance_file(instance, "tracing_on");
-				stop = 1;
-				break;
-			case OPT_current_tracer:
-				show_instance_file(instance, "current_tracer");
-				stop = 1;
-				break;
-			case OPT_buffer_size_kb:
-				show_instance_file(instance, "buffer_size_kb");
-				stop = 1;
-				break;
-			case OPT_buffer_total_size_kb:
-				show_instance_file(instance, "buffer_total_size_kb");
-				stop = 1;
-				break;
-			case OPT_ftrace_filter:
-				show_instance_file(instance, "set_ftrace_filter");
-				stop = 1;
-				break;
-			case OPT_ftrace_notrace:
-				show_instance_file(instance, "set_ftrace_notrace");
-				stop = 1;
-				break;
-			case OPT_ftrace_pid:
-				show_instance_file(instance, "set_ftrace_pid");
-				stop = 1;
-				break;
-			case OPT_graph_function:
-				show_instance_file(instance, "set_graph_function");
-				stop = 1;
-				break;
-			case OPT_graph_notrace:
-				show_instance_file(instance, "set_graph_notrace");
-				stop = 1;
-				break;
-			case OPT_cpumask:
-				show_instance_file(instance, "tracing_cpumask");
-				stop = 1;
-				break;
-			default:
-				usage(argv);
-			}
-		}
-		if (stop)
-			exit(0);
-		if (pipe)
-			file = "trace_pipe";
-		else if (snap)
-			file = "snapshot";
-
-		if (cpu) {
-			snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file);
-			file = cpu_path;
-		}
-			
-		if (buffer) {
-			path = malloc(strlen(buffer) + strlen("instances//") +
-				      strlen(file) + 1);
-			if (!path)
-				die("Failed to allocate instance path %s", file);
-			sprintf(path, "instances/%s/%s", buffer, file);
-			file = path;
-		}
-
-		if (show_name) {
-			char *name;
-			name = tracecmd_get_tracing_file(file);
-			printf("%s\n", name);
-			tracecmd_put_tracing_file(name);
-		}
-		show_file(file);
-		if (buffer)
-			free(path);
-
+		trace_show(argc, argv);
 		exit(0);
 	} else if (strcmp(argv[1], "list") == 0) {
-		int events = 0;
-		int tracer = 0;
-		int options = 0;
-		int funcs = 0;
-		int buffers = 0;
-		int clocks = 0;
-		int plug = 0;
-		int plug_op = 0;
-		int flags = 0;
-		int show_all = 1;
-		int i;
-		const char *arg;
-		const char *funcre = NULL;
-		const char *eventre = NULL;
-
-		for (i = 2; i < argc; i++) {
-			arg = NULL;
-			if (argv[i][0] == '-') {
-				if (i < argc - 1) {
-					if (argv[i+1][0] != '-')
-						arg = argv[i+1];
-				}
-				switch (argv[i][1]) {
-				case 'h':
-					usage(argv);
-					break;
-				case 'e':
-					events = 1;
-					eventre = arg;
-					show_all = 0;
-					break;
-				case 'B':
-					buffers = 1;
-					show_all = 0;
-					break;
-				case 'C':
-					clocks = 1;
-					show_all = 0;
-					break;
-				case 'F':
-					flags |= SHOW_EVENT_FORMAT;
-					break;
-				case 'R':
-					flags |= SHOW_EVENT_TRIGGER;
-					break;
-				case 'l':
-					flags |= SHOW_EVENT_FILTER;
-					break;
-				case 'p':
-				case 't':
-					tracer = 1;
-					show_all = 0;
-					break;
-				case 'P':
-					plug = 1;
-					show_all = 0;
-					break;
-				case 'O':
-					plug_op = 1;
-					show_all = 0;
-					break;
-				case 'o':
-					options = 1;
-					show_all = 0;
-					break;
-				case 'f':
-					funcs = 1;
-					funcre = arg;
-					show_all = 0;
-					break;
-				case '-':
-					if (strcmp(argv[i], "--debug") == 0) {
-						debug = true;
-						break;
-					}
-					fprintf(stderr, "list: invalid option -- '%s'\n",
-						argv[i]);
-				default:
-					fprintf(stderr, "list: invalid option -- '%c'\n",
-						argv[i][1]);
-					usage(argv);
-				}
-			}
-		}
-
-		if (events)
-			show_events(eventre, flags);
-
-		if (tracer)
-			show_tracers();
-
-		if (options)
-			show_options();
-
-		if (plug)
-			show_plugins();
-
-		if (plug_op)
-			show_plugin_options();
-
-		if (funcs)
-			show_functions(funcre);
-
-		if (buffers)
-			show_buffers();
-
-		if (clocks)
-			show_clocks();
-
-		if (show_all) {
-			printf("events:\n");
-			show_events(NULL, 0);
-			printf("\ntracers:\n");
-			show_tracers();
-			printf("\noptions:\n");
-			show_options();
-		}
-
+		trace_list(argc, argv);
 		exit(0);
-
 	} else if (strcmp(argv[1], "-h") == 0 ||
 		   strcmp(argv[1], "help") == 0) {
 		usage(argv);
diff --git a/trace-list.c b/trace-list.c
new file mode 100644
index 0000000..3fdca34
--- /dev/null
+++ b/trace-list.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@...hat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <stdlib.h>
+
+#include "trace-local.h"
+
+
+static void dump_file_content(const char *path)
+{
+	char buf[BUFSIZ];
+	ssize_t n;
+	FILE *fp;
+
+	fp = fopen(path, "r");
+	if (!fp)
+		die("reading %s", path);
+
+	do {
+		n = fread(buf, 1, BUFSIZ, fp);
+		if (n > 0)
+			fwrite(buf, 1, n, stdout);
+	} while (n > 0);
+	fclose(fp);
+}
+
+
+
+void show_instance_file(struct buffer_instance *instance, const char *name)
+{
+	char *path;
+
+	path = get_instance_file(instance, name);
+	dump_file_content(path);
+	tracecmd_put_tracing_file(path);
+}
+
+enum {
+	SHOW_EVENT_FORMAT		= 1 << 0,
+	SHOW_EVENT_FILTER		= 1 << 1,
+	SHOW_EVENT_TRIGGER		= 1 << 2,
+};
+
+
+void show_file(const char *name)
+{
+	char *path;
+
+	path = tracecmd_get_tracing_file(name);
+	dump_file_content(path);
+	tracecmd_put_tracing_file(path);
+}
+
+typedef int (*process_file_func)(char *buf, int len);
+
+static void process_file_re(process_file_func func,
+			    const char *name, const char *re)
+{
+	regex_t reg;
+	char *path;
+	char *buf = NULL;
+	char *str;
+	FILE *fp;
+	ssize_t n;
+	size_t l = strlen(re);
+
+	/* Just in case :-p */
+	if (!re || l == 0) {
+		show_file(name);
+		return;
+	}
+
+	/* Handle the newline at end of names for the user */
+	str = malloc(l + 3);
+	if (!str)
+		die("Failed to allocate reg ex %s", re);
+	strcpy(str, re);
+	if (re[l-1] == '$')
+		strcpy(&str[l-1], "\n*$");
+
+	if (regcomp(&reg, str, REG_ICASE|REG_NOSUB))
+		die("invalid function regex '%s'", re);
+
+	free(str);
+
+	path = tracecmd_get_tracing_file(name);
+	fp = fopen(path, "r");
+	if (!fp)
+		die("reading %s", path);
+	tracecmd_put_tracing_file(path);
+
+	do {
+		n = getline(&buf, &l, fp);
+		if (n > 0 && regexec(&reg, buf, 0, NULL, 0) == 0)
+			func(buf, n);
+	} while (n > 0);
+	free(buf);
+	fclose(fp);
+
+	regfree(&reg);
+}
+
+static int show_file_write(char *buf, int len)
+{
+	return fwrite(buf, 1, len, stdout);
+}
+
+static void show_file_re(const char *name, const char *re)
+{
+	process_file_re(show_file_write, name, re);
+}
+
+static char *get_event_file(const char *type, char *buf, int len)
+{
+	char *system;
+	char *event;
+	char *path;
+	char *file;
+
+	if (buf[len-1] == '\n')
+		buf[len-1] = '\0';
+
+	system = strtok(buf, ":");
+	if (!system)
+		die("no system found in %s", buf);
+
+	event = strtok(NULL, ":");
+	if (!event)
+		die("no event found in %s\n", buf);
+
+	path = tracecmd_get_tracing_file("events");
+	file = malloc(strlen(path) + strlen(system) + strlen(event) +
+		      strlen(type) + strlen("///") + 1);
+	if (!file)
+		die("Failed to allocate event file %s %s", system, event);
+	sprintf(file, "%s/%s/%s/%s", path, system, event, type);
+	tracecmd_put_tracing_file(path);
+
+	return file;
+}
+
+static int event_filter_write(char *buf, int len)
+{
+	char *file;
+
+	if (buf[len-1] == '\n')
+		buf[len-1] = '\0';
+
+	printf("%s\n", buf);
+
+	file = get_event_file("filter", buf, len);
+	dump_file_content(file);
+	free(file);
+	printf("\n");
+
+	return 0;
+}
+
+static int event_trigger_write(char *buf, int len)
+{
+	char *file;
+
+	if (buf[len-1] == '\n')
+		buf[len-1] = '\0';
+
+	printf("%s\n", buf);
+
+	file = get_event_file("trigger", buf, len);
+	dump_file_content(file);
+	free(file);
+	printf("\n");
+
+	return 0;
+}
+
+static int event_format_write(char *fbuf, int len)
+{
+	char *file = get_event_file("format", fbuf, len);
+	char *buf = NULL;
+	size_t l;
+	FILE *fp;
+	int n;
+
+	/* The get_event_file() crops system in fbuf */
+	printf("system: %s\n", fbuf);
+
+	/* Don't print the print fmt, it's ugly */
+
+	fp = fopen(file, "r");
+	if (!fp)
+		die("reading %s", file);
+
+	do {
+		n = getline(&buf, &l, fp);
+		if (n > 0) {
+			if (strncmp(buf, "print fmt", 9) == 0)
+				break;
+			fwrite(buf, 1, n, stdout);
+		}
+	} while (n > 0);
+	fclose(fp);
+	free(buf);
+	free(file);
+
+	return 0;
+}
+
+
+static void show_event_filter_re(const char *re)
+{
+	process_file_re(event_filter_write, "available_events", re);
+}
+
+
+static void show_event_trigger_re(const char *re)
+{
+	process_file_re(event_trigger_write, "available_events", re);
+}
+
+
+static void show_event_format_re(const char *re)
+{
+	process_file_re(event_format_write, "available_events", re);
+}
+
+
+static void show_events(const char *eventre, int flags)
+{
+	if (flags && !eventre)
+		die("When specifying event files, an event must be named");
+
+	if (eventre) {
+		if (flags & SHOW_EVENT_FORMAT)
+			show_event_format_re(eventre);
+
+		else if (flags & SHOW_EVENT_FILTER)
+			show_event_filter_re(eventre);
+
+		else if (flags & SHOW_EVENT_TRIGGER)
+			show_event_trigger_re(eventre);
+		else
+			show_file_re("available_events", eventre);
+	} else
+		show_file("available_events");
+}
+
+
+static void show_tracers(void)
+{
+	show_file("available_tracers");
+}
+
+
+static void show_options(void)
+{
+	show_file("trace_options");
+}
+
+
+static void show_clocks(void)
+{
+	show_file("trace_clock");
+}
+
+
+static void show_functions(const char *funcre)
+{
+	if (funcre)
+		show_file_re("available_filter_functions", funcre);
+	else
+		show_file("available_filter_functions");
+}
+
+
+static void show_buffers(void)
+{
+	struct dirent *dent;
+	DIR *dir;
+	char *path;
+	int printed = 0;
+
+	path = tracecmd_get_tracing_file("instances");
+	dir = opendir(path);
+	tracecmd_put_tracing_file(path);
+	if (!dir)
+		die("Can not read instance directory");
+
+	while ((dent = readdir(dir))) {
+		const char *name = dent->d_name;
+
+		if (strcmp(name, ".") == 0 ||
+		    strcmp(name, "..") == 0)
+			continue;
+
+		printf("%s\n", name);
+		printed = 1;
+	}
+	closedir(dir);
+
+	if (!printed)
+		printf("No buffer instances defined\n");
+}
+
+
+void show_plugin_options(void)
+{
+	struct pevent *pevent;
+	struct plugin_list *list;
+	struct trace_seq s;
+
+	tracecmd_ftrace_load_options();
+
+	pevent = pevent_alloc();
+	if (!pevent)
+		die("Can not allocate pevent\n");
+
+	trace_seq_init(&s);
+
+	list = tracecmd_load_plugins(pevent);
+	trace_util_print_plugin_options(&s);
+	trace_seq_do_printf(&s);
+	tracecmd_unload_plugins(list, pevent);
+	pevent_free(pevent);
+}
+
+
+static void show_plugins(void)
+{
+	struct pevent *pevent;
+	struct plugin_list *list;
+	struct trace_seq s;
+
+	pevent = pevent_alloc();
+	if (!pevent)
+		die("Can not allocate pevent\n");
+
+	trace_seq_init(&s);
+
+	list = tracecmd_load_plugins(pevent);
+	trace_util_print_plugins(&s, "  ", "\n", list);
+	trace_seq_do_printf(&s);
+	tracecmd_unload_plugins(list, pevent);
+	pevent_free(pevent);
+}
+
+
+void trace_list(int argc, char **argv)
+{
+	int events = 0;
+	int tracer = 0;
+	int options = 0;
+	int funcs = 0;
+	int buffers = 0;
+	int clocks = 0;
+	int plug = 0;
+	int plug_op = 0;
+	int flags = 0;
+	int show_all = 1;
+	int i;
+	const char *arg;
+	const char *funcre = NULL;
+	const char *eventre = NULL;
+
+	for (i = 2; i < argc; i++) {
+		arg = NULL;
+		if (argv[i][0] == '-') {
+			if (i < argc - 1) {
+				if (argv[i+1][0] != '-')
+					arg = argv[i+1];
+			}
+			switch (argv[i][1]) {
+			case 'h':
+				usage(argv);
+				break;
+			case 'e':
+				events = 1;
+				eventre = arg;
+				show_all = 0;
+				break;
+			case 'B':
+				buffers = 1;
+				show_all = 0;
+				break;
+			case 'C':
+				clocks = 1;
+				show_all = 0;
+				break;
+			case 'F':
+				flags |= SHOW_EVENT_FORMAT;
+				break;
+			case 'R':
+				flags |= SHOW_EVENT_TRIGGER;
+				break;
+			case 'l':
+				flags |= SHOW_EVENT_FILTER;
+				break;
+			case 'p':
+			case 't':
+				tracer = 1;
+				show_all = 0;
+				break;
+			case 'P':
+				plug = 1;
+				show_all = 0;
+				break;
+			case 'O':
+				plug_op = 1;
+				show_all = 0;
+				break;
+			case 'o':
+				options = 1;
+				show_all = 0;
+				break;
+			case 'f':
+				funcs = 1;
+				funcre = arg;
+				show_all = 0;
+				break;
+			case '-':
+				if (strcmp(argv[i], "--debug") == 0) {
+					debug = true;
+					break;
+				}
+				fprintf(stderr, "list: invalid option -- '%s'\n",
+					argv[i]);
+			default:
+				fprintf(stderr, "list: invalid option -- '%c'\n",
+					argv[i][1]);
+				usage(argv);
+			}
+		}
+	}
+
+	if (events)
+		show_events(eventre, flags);
+
+	if (tracer)
+		show_tracers();
+
+	if (options)
+		show_options();
+
+	if (plug)
+		show_plugins();
+
+	if (plug_op)
+		show_plugin_options();
+
+	if (funcs)
+		show_functions(funcre);
+
+	if (buffers)
+		show_buffers();
+
+	if (clocks)
+		show_clocks();
+
+	if (show_all) {
+		printf("events:\n");
+		show_events(NULL, 0);
+		printf("\ntracers:\n");
+		show_tracers();
+		printf("\noptions:\n");
+		show_options();
+	}
+
+	return;
+
+}
diff --git a/trace-local.h b/trace-local.h
index 46aa979..ee518fb 100644
--- a/trace-local.h
+++ b/trace-local.h
@@ -65,6 +65,8 @@ void trace_listen(int argc, char **argv);
 
 void trace_restore(int argc, char **argv);
 
+void trace_check_events(int argc, char **argv);
+
 void trace_stack(int argc, char **argv);
 
 void trace_option(int argc, char **argv);
@@ -77,6 +79,10 @@ void trace_mem(int argc, char **argv);
 
 void trace_stat(int argc, char **argv);
 
+void trace_show(int argc, char **argv);
+
+void trace_list(int argc, char **argv);
+
 struct hook_list;
 
 void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks,
@@ -183,6 +189,7 @@ char *get_instance_file(struct buffer_instance *instance, const char *file);
 void update_first_instance(struct buffer_instance *instance, int topt);
 
 void show_instance_file(struct buffer_instance *instance, const char *name);
+void show_plugin_options(void);
 int count_cpus(void);
 
 /* No longer in event-utils.h */
diff --git a/trace-show.c b/trace-show.c
new file mode 100644
index 0000000..14b786c
--- /dev/null
+++ b/trace-show.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@...hat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include "trace-local.h"
+
+enum {
+	OPT_tracing_on			= 255,
+	OPT_current_tracer		= 254,
+	OPT_buffer_size_kb		= 253,
+	OPT_buffer_total_size_kb	= 252,
+	OPT_ftrace_filter		= 251,
+	OPT_ftrace_notrace		= 250,
+	OPT_ftrace_pid			= 249,
+	OPT_graph_function		= 248,
+	OPT_graph_notrace		= 247,
+	OPT_cpumask			= 246,
+};
+
+void trace_show(int argc, char **argv)
+{
+	const char *buffer = NULL;
+	const char *file = "trace";
+	const char *cpu = NULL;
+	struct buffer_instance *instance = &top_instance;
+	char cpu_path[128];
+	char *path;
+	int snap = 0;
+	int pipe = 0;
+	int show_name = 0;
+	int option_index = 0;
+	int stop = 0;
+	int c;
+	static struct option long_options[] = {
+		{"tracing_on", no_argument, NULL, OPT_tracing_on},
+		{"current_tracer", no_argument, NULL, OPT_current_tracer},
+		{"buffer_size", no_argument, NULL, OPT_buffer_size_kb},
+		{"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb},
+		{"ftrace_filter", no_argument, NULL, OPT_ftrace_filter},
+		{"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace},
+		{"ftrace_pid", no_argument, NULL, OPT_ftrace_pid},
+		{"graph_function", no_argument, NULL, OPT_graph_function},
+		{"graph_notrace", no_argument, NULL, OPT_graph_notrace},
+		{"cpumask", no_argument, NULL, OPT_cpumask},
+		{"help", no_argument, NULL, '?'},
+		{NULL, 0, NULL, 0}
+	};
+
+	while ((c = getopt_long(argc-1, argv+1, "B:c:fsp",
+				long_options, &option_index)) >= 0) {
+		switch (c) {
+		case 'h':
+			usage(argv);
+			break;
+		case 'B':
+			if (buffer)
+				die("Can only show one buffer at a time");
+			buffer = optarg;
+			instance = create_instance(optarg);
+			if (!instance)
+				die("Failed to create instance");
+			break;
+		case 'c':
+			if (cpu)
+				die("Can only show one CPU at a time");
+			cpu = optarg;
+			break;
+		case 'f':
+			show_name = 1;
+			break;
+		case 's':
+			snap = 1;
+			if (pipe)
+				die("Can not have -s and -p together");
+			break;
+		case 'p':
+			pipe = 1;
+			if (snap)
+				die("Can not have -s and -p together");
+			break;
+		case OPT_tracing_on:
+			show_instance_file(instance, "tracing_on");
+			stop = 1;
+			break;
+		case OPT_current_tracer:
+			show_instance_file(instance, "current_tracer");
+			stop = 1;
+			break;
+		case OPT_buffer_size_kb:
+			show_instance_file(instance, "buffer_size_kb");
+			stop = 1;
+			break;
+		case OPT_buffer_total_size_kb:
+			show_instance_file(instance, "buffer_total_size_kb");
+			stop = 1;
+			break;
+		case OPT_ftrace_filter:
+			show_instance_file(instance, "set_ftrace_filter");
+			stop = 1;
+			break;
+		case OPT_ftrace_notrace:
+			show_instance_file(instance, "set_ftrace_notrace");
+			stop = 1;
+			break;
+		case OPT_ftrace_pid:
+			show_instance_file(instance, "set_ftrace_pid");
+			stop = 1;
+			break;
+		case OPT_graph_function:
+			show_instance_file(instance, "set_graph_function");
+			stop = 1;
+			break;
+		case OPT_graph_notrace:
+			show_instance_file(instance, "set_graph_notrace");
+			stop = 1;
+			break;
+		case OPT_cpumask:
+			show_instance_file(instance, "tracing_cpumask");
+			stop = 1;
+			break;
+		default:
+			usage(argv);
+		}
+	}
+	if (stop)
+		exit(0);
+	if (pipe)
+		file = "trace_pipe";
+	else if (snap)
+		file = "snapshot";
+
+	if (cpu) {
+		snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file);
+		file = cpu_path;
+	}
+
+	if (buffer) {
+		path = malloc(strlen(buffer) + strlen("instances//") +
+			      strlen(file) + 1);
+		if (!path)
+			die("Failed to allocate instance path %s", file);
+		sprintf(path, "instances/%s/%s", buffer, file);
+		file = path;
+	}
+
+	if (show_name) {
+		char *name;
+		name = tracecmd_get_tracing_file(file);
+		printf("%s\n", name);
+		tracecmd_put_tracing_file(name);
+	}
+	show_file(file);
+	if (buffer)
+		free(path);
+
+	return;
+}
-- 
2.9.3

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ