lttd mkdir ok
[lttv.git] / ltt / branches / poly / lttctl / lttctl.c
CommitLineData
2cdb6fcb 1/* lttctl
2 *
3 * Linux Trace Toolkit Control
4 *
5 * Small program that controls LTT through libltt.
6 *
7 * Copyright 2005 -
8 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
9 */
10
4e4d11b3 11#ifdef HAVE_CONFIG_H
12#include <config.h>
13#endif
14
5adba60f 15#include <libltt/libltt.h>
16#include <errno.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <unistd.h>
21#include <signal.h>
d5fbdb60 22#include <dirent.h>
23#include <string.h>
24#include <sys/stat.h>
25
26/* Buffer for file copy : 4k seems optimal. */
27#define BUF_SIZE 4194304
2cdb6fcb 28
5adba60f 29enum trace_ctl_op {
30 CTL_OP_CREATE,
31 CTL_OP_DESTROY,
32 CTL_OP_START,
33 CTL_OP_STOP,
34 CTL_OP_DAEMON,
129fd24a 35 CTL_OP_DESCRIPTION,
5adba60f 36 CTL_OP_NONE
37};
2cdb6fcb 38
5adba60f 39static char *trace_name = NULL;
40static char *mode_name = NULL;
988614ed 41static unsigned subbuf_size = 0;
42static unsigned n_subbufs = 0;
5adba60f 43static enum trace_mode mode = LTT_TRACE_NORMAL;
44static enum trace_ctl_op op = CTL_OP_NONE;
45static char *channel_root = NULL;
46static char *trace_root = NULL;
47
ada84671 48static int sigio_received = 0;
49
5adba60f 50void handler(int signo)
51{
52 printf("signal %d received\n", signo);
ada84671 53 sigio_received = 1;
5adba60f 54}
55
56
57/* Args :
58 *
59 */
60void show_arguments(void)
61{
62 printf("Please use the following arguments :\n");
63 printf("\n");
64 printf("-n name Name of the trace.\n");
65 printf("-c mode Create trace channels in mode normal or flight recorder.\n");
66 printf(" Mode values : normal (default) or flight.\n");
67 printf("-r Destroy trace channels.\n");
68 printf("-s Start tracing.\n");
69 //printf(" Note : will automatically create a normal trace if "
70 // "none exists.\n");
71 printf("-q Stop tracing.\n");
72 printf("-d Create trace, spawn a lttd daemon, start tracing.\n");
d5fbdb60 73 printf(" (optionnaly, you can set LTT_DAEMON\n");
74 printf(" and the LTT_FACILITIES env. vars.)\n");
5adba60f 75 printf("-t Trace root path. (ex. /root/traces/example_trace)\n");
76 printf("-l LTT channels root path. (ex. /mnt/relayfs/ltt)\n");
4085af66 77 printf("-z Size of the subbuffers (will be rounded to next page size)\n");
988614ed 78 printf("-x Number of subbuffers\n");
129fd24a 79 printf("-e Get XML facilities description\n");
5adba60f 80 printf("\n");
81}
82
83
84/* parse_arguments
85 *
86 * Parses the command line arguments.
87 *
88 * Returns 1 if the arguments were correct, but doesn't ask for program
89 * continuation. Returns -1 if the arguments are incorrect, or 0 if OK.
90 */
91int parse_arguments(int argc, char **argv)
92{
93 int ret = 0;
94 int argn = 1;
95
96 if(argc == 2) {
97 if(strcmp(argv[1], "-h") == 0) {
98 return 1;
99 }
100 }
101
102 while(argn < argc) {
103
104 switch(argv[argn][0]) {
105 case '-':
106 switch(argv[argn][1]) {
107 case 'n':
108 if(argn+1 < argc) {
109 trace_name = argv[argn+1];
110 argn++;
111 } else {
112 printf("Specify a trace name after -n.\n", argv[argn]);
113 printf("\n");
114 ret = -1;
115 }
116
117 break;
118 case 'c':
119 op = CTL_OP_CREATE;
120 if(argn+1 < argc) {
121 mode_name = argv[argn+1];
122 argn++;
123 if(strcmp(mode_name, "normal") == 0)
124 mode = LTT_TRACE_NORMAL;
125 else if(strcmp(mode_name, "flight") == 0)
126 mode = LTT_TRACE_FLIGHT;
127 else {
128 printf("Invalid mode '%s'.\n", argv[argn]);
129 printf("\n");
130 ret = -1;
131 }
132 } else {
988614ed 133 printf("Specify a mode after -c.\n");
5adba60f 134 printf("\n");
135 ret = -1;
136 }
137 break;
138 case 'r':
139 op = CTL_OP_DESTROY;
140 break;
141 case 's':
142 op = CTL_OP_START;
143 break;
144 case 'q':
145 op = CTL_OP_STOP;
146 break;
988614ed 147 case 'z':
148 if(argn+1 < argc) {
149 subbuf_size = (unsigned)atoi(argv[argn+1]);
150 argn++;
151 } else {
152 printf("Specify a number of subbuffers after -z.\n");
153 printf("\n");
154 ret = -1;
155 }
156 break;
157 case 'x':
158 if(argn+1 < argc) {
159 n_subbufs = (unsigned)atoi(argv[argn+1]);
160 argn++;
161 } else {
162 printf("Specify a subbuffer size after -x.\n");
163 printf("\n");
164 ret = -1;
165 }
166 break;
5adba60f 167 case 'd':
168 op = CTL_OP_DAEMON;
169 break;
129fd24a 170 case 'e':
171 op = CTL_OP_DESCRIPTION;
172 break;
5adba60f 173 case 't':
174 if(argn+1 < argc) {
175 trace_root = argv[argn+1];
176 argn++;
177 } else {
988614ed 178 printf("Specify a trace root path after -t.\n");
5adba60f 179 printf("\n");
180 ret = -1;
181 }
182 break;
183 case 'l':
184 if(argn+1 < argc) {
185 channel_root = argv[argn+1];
186 argn++;
187 } else {
988614ed 188 printf("Specify a channel root path after -l.\n");
5adba60f 189 printf("\n");
190 ret = -1;
191 }
192 break;
193 default:
194 printf("Invalid argument '%s'.\n", argv[argn]);
195 printf("\n");
196 ret = -1;
197 }
198 break;
199 default:
200 printf("Invalid argument '%s'.\n", argv[argn]);
201 printf("\n");
202 ret = -1;
203 }
204 argn++;
205 }
206
129fd24a 207 if(op != CTL_OP_DESCRIPTION && trace_name == NULL) {
5adba60f 208 printf("Please specify a trace name.\n");
209 printf("\n");
210 ret = -1;
211 }
212
213 if(op == CTL_OP_NONE) {
214 printf("Please specify an operation.\n");
215 printf("\n");
216 ret = -1;
217 }
218
219 if(op == CTL_OP_DAEMON) {
220 if(trace_root == NULL) {
221 printf("Please specify -t trace_root_path with the -d option.\n");
222 printf("\n");
223 ret = -1;
224 }
225 if(channel_root == NULL) {
226 printf("Please specify -l ltt_root_path with the -d option.\n");
227 printf("\n");
228 ret = -1;
229 }
230 }
231
129fd24a 232 if(op == CTL_OP_DESCRIPTION) {
233 if(trace_root == NULL) {
234 printf("Please specify -t trace_root_path with the -e option.\n");
235 printf("\n");
236 ret = -1;
237 }
238 }
239
5adba60f 240 return ret;
241}
242
243void show_info(void)
244{
245 printf("Linux Trace Toolkit Trace Control\n");
246 printf("\n");
129fd24a 247 if(trace_name != NULL) {
248 printf("Controlling trace : %s\n", trace_name);
249 printf("\n");
250 }
251}
252
253int create_eventdefs(void)
254{
255 int ret = 0;
256 char eventdefs_path[PATH_MAX];
257 char eventdefs_file[PATH_MAX];
258 char facilities_file[PATH_MAX];
259 char read_buf[BUF_SIZE];
260 struct dirent *entry;
261 char *facilities_path = getenv("LTT_FACILITIES");
262 if(facilities_path == NULL) facilities_path =
263 "/usr/share/LinuxTraceToolkitViewer/facilities";
264
265 ret = mkdir(trace_root, S_IRWXU|S_IRWXG|S_IRWXO);
266 if(ret == -1 && errno != EEXIST) {
267 perror("Cannot create trace_root directory");
268 printf("trace_root is %s\n", trace_root);
269 goto error;
270 }
271
272 size_t trace_root_len = strlen(trace_root);
273 strncpy(eventdefs_path, trace_root, PATH_MAX);
274 strncat(eventdefs_path, "/eventdefs/", PATH_MAX - trace_root_len);
275 size_t eventdefs_path_len = strlen(eventdefs_path);
276 ret = mkdir(eventdefs_path, S_IRWXU|S_IRWXG|S_IRWXO);
277 if(ret == -1 && errno != EEXIST) {
278 perror("Cannot create eventdefs directory");
279 goto error;
280 }
281
282 DIR *facilities_dir = opendir(facilities_path);
283
284 while((entry = readdir(facilities_dir)) != NULL) {
285 if(entry->d_name[0] == '.') continue;
286
287 printf("Appending facility file %s\n", entry->d_name);
288 strncpy(eventdefs_file, eventdefs_path, PATH_MAX);
289 strncat(eventdefs_file, entry->d_name, PATH_MAX - eventdefs_path_len);
290 /* Append to the file */
291 FILE *dest = fopen(eventdefs_file, "a");
292 if(!dest) {
293 perror("Cannot create eventdefs file");
294 continue;
295 }
296 strncpy(facilities_file, facilities_path, PATH_MAX);
297 size_t facilities_dir_len = strlen(facilities_path);
298 strncat(facilities_file, "/", PATH_MAX - facilities_dir_len);
299 strncat(facilities_file, entry->d_name, PATH_MAX - facilities_dir_len-1);
300 FILE *src = fopen(facilities_file, "r");
301 if(!src) {
302 perror("Cannot open eventdefs file for reading");
303 goto close_dest;
304 }
305
306 do {
307 size_t read_size, write_size;
308 read_size = fread(read_buf, sizeof(char), BUF_SIZE, src);
309 if(ferror(src)) {
310 perror("Cannot read eventdefs file");
311 goto close_src;
312 }
313 write_size = fwrite(read_buf, sizeof(char), read_size, dest);
314 if(ferror(dest)) {
315 perror("Cannot write eventdefs file");
316 goto close_src;
317 }
318 } while(!feof(src));
319
320 /* Add spacing between facilities */
321 fwrite("\n", 1, 1, dest);
322
323close_src:
324 fclose(src);
325close_dest:
326 fclose(dest);
327 }
328
329 closedir(facilities_dir);
330
331 error:
332 return ret;
333
5adba60f 334}
335
129fd24a 336
5adba60f 337int lttctl_daemon(struct lttctl_handle *handle, char *trace_name)
338{
339 char channel_path[PATH_MAX] = "";
340 pid_t pid;
341 int ret;
342 char *lttd_path = getenv("LTT_DAEMON");
343 struct sigaction act;
344
345 if(lttd_path == NULL) lttd_path = "lttd";
346
347 strcat(channel_path, channel_root);
348 strcat(channel_path, "/");
349 strcat(channel_path, trace_name);
350
351
988614ed 352 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size, n_subbufs);
5adba60f 353 if(ret != 0) goto create_error;
354
355 act.sa_handler = handler;
356 sigemptyset(&(act.sa_mask));
357 sigaddset(&(act.sa_mask), SIGIO);
358 sigaction(SIGIO, &act, NULL);
359
ada84671 360 sigio_received = 0;
361
5adba60f 362 pid = fork();
363
364 if(pid > 0) {
5adba60f 365 /* parent */
ada84671 366 while(!sigio_received) pause();
5adba60f 367
368 /* Now the trace is created, go on and create the supplementary files... */
d5fbdb60 369
5adba60f 370 printf("Creating supplementary trace files\n");
129fd24a 371 ret = create_eventdefs();
372 if(ret) goto start_error;
5adba60f 373
374 } else if(pid == 0) {
375 /* child */
376 int ret =
377 execlp(lttd_path, lttd_path, "-t", trace_root, "-c", channel_path, "-s", NULL);
378 if(ret) {
379 perror("Error in executing the lttd daemon");
380 exit(-1);
381 }
382 } else {
383 /* error */
384 perror("Error in forking for lttd daemon");
385
386 }
387
388 ret = lttctl_start(handle, trace_name);
389 if(ret != 0) goto start_error;
390
391 return 0;
392
393 /* error handling */
394start_error:
395 ret |= lttctl_destroy_trace(handle, trace_name);
396create_error:
397 return ret;
398}
399
400int main(int argc, char ** argv)
401{
402 int ret;
403 struct lttctl_handle *handle;
404
405 ret = parse_arguments(argc, argv);
406
407 if(ret != 0) show_arguments();
408 if(ret < 0) return EINVAL;
409 if(ret > 0) return 0;
410
411 show_info();
412
413 handle = lttctl_create_handle();
414
415 if(handle == NULL) return -1;
416
417 switch(op) {
418 case CTL_OP_CREATE:
988614ed 419 ret = lttctl_create_trace(handle, trace_name, mode, subbuf_size,
420 n_subbufs);
5adba60f 421 case CTL_OP_DESTROY:
422 ret = lttctl_destroy_trace(handle, trace_name);
423 break;
424 case CTL_OP_START:
425 ret = lttctl_start(handle, trace_name);
426 break;
427 case CTL_OP_STOP:
428 ret = lttctl_stop(handle, trace_name);
429 break;
430 case CTL_OP_DAEMON:
431 ret = lttctl_daemon(handle, trace_name);
432 break;
129fd24a 433 case CTL_OP_DESCRIPTION:
434 ret = create_eventdefs();
435 break;
5adba60f 436 case CTL_OP_NONE:
437 break;
438 }
439
440 ret |= lttctl_destroy_handle(handle);
441
442 return ret;
443}
This page took 0.041867 seconds and 4 git commands to generate.