• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4  *
5  */
6 #include <dirent.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <getopt.h>
11 #include <stdarg.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/wait.h>
15 #include <sys/mman.h>
16 #include <fcntl.h>
17 #include <signal.h>
18 #include <unistd.h>
19 #include <ctype.h>
20 #include <errno.h>
21 
22 #include "trace-local.h"
23 
create_output(const char * file,const char * tracing_dir,const char * kallsyms)24 static struct tracecmd_output *create_output(const char *file,
25 					     const char *tracing_dir, const char *kallsyms)
26 {
27 	struct tracecmd_output *out;
28 
29 	out = tracecmd_output_create(file);
30 	if (!out)
31 		goto error;
32 
33 	if (tracing_dir && tracecmd_output_set_trace_dir(out, tracing_dir))
34 		goto error;
35 	if (kallsyms && tracecmd_output_set_kallsyms(out, kallsyms))
36 		goto error;
37 	if (tracecmd_output_write_headers(out, NULL))
38 		goto error;
39 	return out;
40 error:
41 	if (out)
42 		tracecmd_output_close(out);
43 	unlink(file);
44 	return NULL;
45 }
46 
trace_restore(int argc,char ** argv)47 void trace_restore (int argc, char **argv)
48 {
49 	struct tracecmd_output *handle;
50 	const char *output_file = DEFAULT_INPUT_FILE;
51 	const char *output = NULL;
52 	const char *input = NULL;
53 	const char *tracing_dir = NULL;
54 	const char *kallsyms = NULL;
55 	struct stat st1;
56 	struct stat st2;
57 	int first_arg;
58 	int create_only = 0;
59 	int args;
60 	int c;
61 
62 	if (argc < 2)
63 		usage(argv);
64 
65 	if (strcmp(argv[1], "restore") != 0)
66 		usage(argv);
67 
68 	while ((c = getopt(argc-1, argv+1, "+hco:i:t:k:")) >= 0) {
69 		switch (c) {
70 		case 'h':
71 			usage(argv);
72 			break;
73 		case 'c':
74 			if (input)
75 				die("-c and -i are incompatible");
76 			create_only = 1;
77 			/* make output default to partial */
78 			output_file = "trace-partial.dat";
79 			break;
80 
81 		case 't':
82 			tracing_dir = optarg;
83 			break;
84 		case 'k':
85 			kallsyms = optarg;
86 			break;
87 		case 'o':
88 			if (output)
89 				die("only one output file allowed");
90 			output = optarg;
91 			break;
92 
93 		case 'i':
94 			if (input)
95 				die("only one input file allowed");
96 			if (create_only)
97 				die("-c and -i are incompatible");
98 			input = optarg;
99 			break;
100 
101 		default:
102 			usage(argv);
103 		}
104 	}
105 
106 	if (!output)
107 		output = output_file;
108 
109 	if ((argc - optind) <= 1) {
110 		if (!create_only) {
111 			warning("No data files found");
112 			usage(argv);
113 		}
114 
115 		handle = create_output(output, tracing_dir, kallsyms);
116 		if (!handle)
117 			die("Unabled to create output file %s", output);
118 		if (tracecmd_write_cmdlines(handle) < 0)
119 			die("Failed to write command lines");
120 		tracecmd_output_close(handle);
121 		exit(0);
122 	}
123 	first_arg = optind + 1;
124 	args = argc - first_arg;
125 	printf("first = %d %s args=%d\n", first_arg, argv[first_arg], args);
126 
127 	/* Make sure input and output are not the same file */
128 	if (input && output) {
129 		if (stat(input, &st1) < 0)
130 			die("%s:", input);
131 		/* output exists? otherwise we don't care */
132 		if (stat(output, &st2) == 0) {
133 			if (st1.st_ino == st2.st_ino &&
134 			    st1.st_dev == st2.st_dev)
135 				die("input and output file are the same");
136 		}
137 	}
138 
139 	if (input) {
140 		struct tracecmd_input *ihandle;
141 
142 		ihandle = tracecmd_alloc(input, 0);
143 		if (!ihandle)
144 			die("error reading file %s", input);
145 		/* make sure headers are ok */
146 		if (tracecmd_read_headers(ihandle, TRACECMD_FILE_CMD_LINES) < 0)
147 			die("error reading file %s headers", input);
148 
149 		handle = tracecmd_copy(ihandle, output, TRACECMD_FILE_CMD_LINES, 0, NULL);
150 		tracecmd_close(ihandle);
151 	} else {
152 		handle = tracecmd_output_create(output);
153 		tracecmd_output_write_headers(handle, NULL);
154 	}
155 
156 	if (!handle)
157 		die("error writing to %s", output);
158 
159 	if (tracecmd_append_cpu_data(handle, args, &argv[first_arg]) < 0)
160 		die("failed to append data");
161 
162 	return;
163 }
164