iowatcher: Merge trace dumping functions into one

Now that combine_blktrace_devs() takes a list of traces it's fairly
generic so we might as well merge blktrace_to_dump() into it. The latter
can be replaced with a call using a list with a single entry.

combine_blktrace_devs() is renamed dump_traces() because that's what it
does.

Also eradicate the big global char array 'line' that was being used in a
bunch of places along with some more unnecessary strdup()s.

Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/iowatcher/blkparse.c b/iowatcher/blkparse.c
index bf58b45..1555845 100644
--- a/iowatcher/blkparse.c
+++ b/iowatcher/blkparse.c
@@ -49,9 +49,6 @@
 extern int plot_io_action;
 extern int io_per_process;
 
-static const int line_len = 1024;
-static char line[1024];
-
 /*
  * Trace categories
  */
@@ -736,27 +733,29 @@
 {
 	int count = 0;
 	struct tracelist *traces = NULL;
+	int dlen = strlen(dir_name);
 	DIR *dir = opendir(dir_name);
 	if (!dir)
 		return NULL;
 
 	while (1) {
-		int len;
+		int n = 0;
 		struct tracelist *tl;
 		struct dirent *d = readdir(dir);
 		if (!d)
 			break;
 
-		if (!match_trace(d->d_name, &len))
+		if (!match_trace(d->d_name, &n))
 			continue;
 
+		n += dlen + 1; /* dir + '/' + file */
 		/* Allocate space for tracelist + filename */
-		tl = calloc(1, sizeof(struct tracelist) + (sizeof(char) * (len + 1)));
+		tl = calloc(1, sizeof(struct tracelist) + (sizeof(char) * (n + 1)));
 		if (!tl)
 			return NULL;
 		tl->next = traces;
 		tl->name = (char *)(tl + 1);
-		strncpy(tl->name, d->d_name, len);
+		snprintf(tl->name, n, "%s/%s", dir_name, d->d_name);
 		traces = tl;
 		count++;
 	}
@@ -778,35 +777,23 @@
 	}
 }
 
-static char *combine_blktrace_devs(char *dir_name)
+static int dump_traces(struct tracelist *traces, int count, char *dumpfile)
 {
-	struct tracelist *traces = NULL;
 	struct tracelist *tl;
-	char *ret = NULL;
 	char **argv = NULL;
-	char *dumpfile;
 	int argc = 0;
 	int i;
-	int err;
+	int err = 0;
 
-	if (!asprintf(&dumpfile, "%s.dump", dir_name))
-		goto out;
-
-	traces = traces_list(dir_name, &argc);
-	if (!traces)
-		goto out;
-
-	argc *= 2; /* {"-i", trace } */
-	argc += 6; /* See below */
+	argc = count * 2; /* {"-i", trace } */
+	argc += 4; /* See below */
 	argv = calloc(argc + 1, sizeof(char *));
 	if (!argv)
-		goto out;
+		return -errno;
 
 	i = 0;
 	argv[i++] = "blkparse";
 	argv[i++] = "-O";
-	argv[i++] = "-D";
-	argv[i++] = dir_name;
 	argv[i++] = "-d";
 	argv[i++] = dumpfile;
 	for (tl = traces; tl != NULL; tl = tl->next) {
@@ -816,14 +803,7 @@
 
 	err = run_program2(argc, argv);
 	free(argv);
-	if (err) {
-		fprintf(stderr, "blkparse failed with exit code %d\n", err);
-		exit(1);
-	}
-	ret = dumpfile;
-out:
-	traces_free(traces);
-	return ret;
+	return err;
 }
 
 static char *find_trace_file(char *filename)
@@ -831,8 +811,9 @@
 	int ret;
 	struct stat st;
 	char *dot;
-	char *try;
 	int found_dir = 0;
+	char *dumpfile;
+	int len = strlen(filename);
 
 	/* look for an exact match of whatever they pass in.
 	 * If it is a file, assume it is the dump file.
@@ -851,7 +832,7 @@
 	if (found_dir) {
 		int i;
 		/* Eat up trailing '/'s */
-		for (i = strlen(filename) - 1; filename[i] == '/'; i--)
+		for (i = len - 1; filename[i] == '/'; i--)
 			filename[i] = '\0';
 	}
 
@@ -859,43 +840,58 @@
 	 * try tacking .dump onto the end and see if that already
 	 * has been generated
 	 */
-	snprintf(line, line_len, "%s.%s", filename, "dump");
-	ret = stat(line, &st);
+	ret = asprintf(&dumpfile, "%s.dump", filename);
+	if (ret == -1) {
+		perror("Error building dump file name");
+		return NULL;
+	}
+	ret = stat(dumpfile, &st);
 	if (ret == 0)
-		return strdup(line);
+		return dumpfile;
 
 	/*
 	 * try to generate the .dump from all the traces in
 	 * a single dir.
 	 */
 	if (found_dir) {
-		try = combine_blktrace_devs(filename);
-		if (try)
-			return try;
+		int count;
+		struct tracelist *traces = traces_list(filename, &count);
+		if (traces) {
+			ret = dump_traces(traces, count, dumpfile);
+			traces_free(traces);
+			if (ret == 0)
+				return dumpfile;
+		}
 	}
+	free(dumpfile);
 
 	/*
 	 * try to generate the .dump from all the blktrace
 	 * files for a named trace
 	 */
-	try = strdup(filename);
-	dot = strrchr(try, '.');
+	dot = strrchr(filename, '.');
 	if (!dot || strcmp(".dump", dot) != 0) {
-		if (dot && dot != try)
-			*dot = '\0';
-		snprintf(line, line_len, "%s%s", try, ".blktrace.0");
-		ret = stat(line, &st);
-		if (ret == 0) {
-			blktrace_to_dump(try);
-			snprintf(line, line_len, "%s.%s", try, "dump");
-			ret = stat(line, &st);
-			if (ret == 0) {
-				free(try);
-				return strdup(line);
-			}
+		struct tracelist trace = {0};
+		if (dot && dot != filename)
+			len = dot - filename;
+
+		ret = asprintf(&trace.name, "%*s.blktrace.0", len, filename);
+		if (ret == -1)
+			return NULL;
+		ret = asprintf(&dumpfile, "%*s.dump", len, filename);
+		if (ret == -1) {
+			free(trace.name);
+			return NULL;
 		}
+
+		ret = dump_traces(&trace, 1, dumpfile);
+		if (ret == 0) {
+			free(trace.name);
+			return dumpfile;
+		}
+		free(trace.name);
+		free(dumpfile);
 	}
-	free(try);
 	return NULL;
 }
 struct trace *open_trace(char *filename)
diff --git a/iowatcher/tracers.c b/iowatcher/tracers.c
index ed5efa1..f42958b 100644
--- a/iowatcher/tracers.c
+++ b/iowatcher/tracers.c
@@ -223,22 +223,6 @@
 	return 0;
 }
 
-int blktrace_to_dump(char *trace_name)
-{
-	char *argv[] = {
-		"blkparse", "-O",
-		"-i", NULL,
-		"-d", NULL,
-		NULL
-	};
-
-	argv[3] = trace_name;
-	snprintf(line, line_len, "%s.dump", trace_name);
-	argv[5] = line;
-
-	return run_program2(6, argv);
-}
-
 int start_mpstat(char *trace_name)
 {
 	int fd;
diff --git a/iowatcher/tracers.h b/iowatcher/tracers.h
index 48eec45..92f349a 100644
--- a/iowatcher/tracers.h
+++ b/iowatcher/tracers.h
@@ -23,7 +23,6 @@
 int start_blktrace(char **devices, int num_devices, char *trace_name, char *dest);
 int start_mpstat(char *trace_name);
 int wait_for_tracers(void);
-int blktrace_to_dump(char *trace_name);
 int start_mpstat(char *trace_name);