update version
[ltt-control.git] / trunk / ltt-control / lttctl / lttctl.c
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
11 #ifdef HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <liblttctl/lttctl.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <limits.h>
23 #define _GNU_SOURCE
24 #include <getopt.h>
25
26 #define OPT_MAX (1024)
27 #define OPT_NAMELEN (256)
28 #define OPT_VALSTRINGLEN (256)
29
30 enum lttcrl_option_type {
31 option_type_unknown,
32 option_type_string,
33 option_type_int,
34 option_type_uint,
35 option_type_positive,
36 option_type_bool,
37 };
38
39 struct lttctl_option {
40 char name1[OPT_NAMELEN];
41 char name2[OPT_NAMELEN];
42 char name3[OPT_NAMELEN];
43 union {
44 char v_string[OPT_VALSTRINGLEN];
45 int v_int;
46 unsigned int v_uint;
47 int v_bool:1;
48 } value;
49 };
50
51 static int opt_create;
52 static int opt_destroy;
53 static int opt_start;
54 static int opt_pause;
55 static int opt_help;
56 static const char *opt_transport;
57 static struct lttctl_option opt_options[OPT_MAX];
58 static unsigned int opt_option_n;
59 static const char *opt_write;
60 static int opt_append;
61 static unsigned int opt_dump_threads;
62 static char channel_root_default[PATH_MAX];
63 static const char *opt_channel_root;
64 static const char *opt_tracename;
65
66 /* Args :
67 *
68 */
69 static void show_arguments(void)
70 {
71 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
72 printf("\n");
73 printf("Usage: lttctl [OPTION]... [TRACENAME]\n");
74 printf("\n");
75 printf("Examples:\n");
76 printf(" lttctl -c trace1 "
77 "# Create a trace named trace1.\n");
78 printf(" lttctl -s trace1 "
79 "# start a trace named trace1.\n");
80 printf(" lttctl -p trace1 "
81 "# pause a trace named trace1.\n");
82 printf(" lttctl -d trace1 "
83 "# Destroy a trace named trace1.\n");
84 printf(" lttctl -C -w /tmp/trace1 trace1 "
85 "# Create a trace named trace1, start it and\n"
86 " "
87 "# write non-overwrite channels' data to\n"
88 " "
89 "# /tmp/trace1, debugfs must be mounted for\n"
90 " "
91 "# auto-find\n");
92 printf(" lttctl -D -w /tmp/trace1 trace1 "
93 "# Pause and destroy a trace named trace1 and\n"
94 " "
95 "# write overwrite channels' data to\n"
96 " "
97 "# /tmp/trace1, debugfs must be mounted for\n"
98 " "
99 "# auto-find\n");
100 printf("\n");
101 printf(" Basic options:\n");
102 printf(" -c, --create\n");
103 printf(" Create a trace.\n");
104 printf(" -d, --destroy\n");
105 printf(" Destroy a trace.\n");
106 printf(" -s, --start\n");
107 printf(" Start a trace.\n");
108 printf(" -p, --pause\n");
109 printf(" Pause a trace.\n");
110 printf(" -h, --help\n");
111 printf(" Show this help.\n");
112 printf("\n");
113 printf(" Advanced options:\n");
114 printf(" --transport TRANSPORT\n");
115 printf(" Set trace's transport. (ex. relay)\n");
116 printf(" -o, --option OPTION\n");
117 printf(" Set options, following operations are supported:\n");
118 printf(" channel.<channelname>.enable=\n");
119 printf(" channel.<channelname>.overwrite=\n");
120 printf(" channel.<channelname>.bufnum=\n");
121 printf(" channel.<channelname>.bufsize=\n");
122 printf(" <channelname> can be set to all for all channels\n");
123 printf("\n");
124 printf(" Integration options:\n");
125 printf(" -C, --create_start\n");
126 printf(" Create and start a trace.\n");
127 printf(" -D, --pause_destroy\n");
128 printf(" Pause and destroy a trace.\n");
129 printf(" -w, --write PATH\n");
130 printf(" Path for write trace datas.\n");
131 printf(" For -c, -C, -d, -D options\n");
132 printf(" -a, --append\n");
133 printf(" Append to trace, For -w option\n");
134 printf(" -n, --dump_threads NUMBER\n");
135 printf(" Number of lttd threads, For -w option\n");
136 printf(" --channel_root PATH\n");
137 printf(" Set channels root path, For -w option."
138 " (ex. /mnt/debugfs/ltt)\n");
139 printf("\n");
140 }
141
142 static int getdebugfsmntdir(char *mntdir)
143 {
144 char mnt_dir[PATH_MAX];
145 char mnt_type[PATH_MAX];
146
147 FILE *fp = fopen("/proc/mounts", "r");
148 if (!fp)
149 return -EINVAL;
150
151 while (1) {
152 if (fscanf(fp, "%*s %s %s %*s %*s %*s", mnt_dir, mnt_type) <= 0)
153 return -ENOENT;
154
155 if (!strcmp(mnt_type, "debugfs")) {
156 strcpy(mntdir, mnt_dir);
157 return 0;
158 }
159 }
160 }
161
162 /*
163 * Separate option name to 3 fields
164 * Ex:
165 * Input: name = channel.cpu.bufsize
166 * Output: name1 = channel
167 * name2 = cpu
168 * name3 = bufsize
169 * Ret: 0 on success
170 * 1 on fail
171 *
172 * Note:
173 * Make sure that name1~3 longer than OPT_NAMELEN.
174 * name1~3 can be NULL to discard value
175 *
176 */
177 static int separate_opt(const char *name, char *name1, char *name2, char *name3)
178 {
179 char *p;
180
181 if (!name)
182 return 1;
183
184 /* segment1 */
185 p = strchr(name, '.');
186 if (!p)
187 return 1;
188 if (p - name >= OPT_NAMELEN)
189 return 1;
190 if (name1) {
191 memcpy(name1, name, p - name);
192 name1[p - name] = 0;
193 }
194 name = p + 1;
195
196 /* segment2 */
197 p = strchr(name, '.');
198 if (!p)
199 return 1;
200 if (p - name >= OPT_NAMELEN)
201 return 1;
202 if (name2) {
203 memcpy(name2, name, p - name);
204 name2[p - name] = 0;
205 }
206 name = p + 1;
207
208 /* segment3 */
209 if (strlen(name) >= OPT_NAMELEN)
210 return 1;
211 if (name3)
212 strcpy(name3, name);
213
214 return 0;
215 }
216
217 /*
218 * get option's type by its name,
219 * can also be used to check is option exists
220 * (return option_type_unknown when not exist)
221 */
222 static enum lttcrl_option_type opt_type(const char *name1, const char *name2,
223 const char *name3)
224 {
225 if (!name1 || !name2 || !name3)
226 return option_type_unknown;
227
228 if (strlen(name1) >= OPT_NAMELEN
229 || strlen(name2) >= OPT_NAMELEN
230 || strlen(name3) >= OPT_NAMELEN)
231 return option_type_unknown;
232
233 if (strcmp(name1, "channel") == 0) {
234 /* Option is channel class */
235 if (strcmp(name3, "enable") == 0)
236 return option_type_bool;
237 if (strcmp(name3, "overwrite") == 0)
238 return option_type_bool;
239 if (strcmp(name3, "bufnum") == 0)
240 return option_type_uint;
241 if (strcmp(name3, "bufsize") == 0)
242 return option_type_uint;
243 return option_type_unknown;
244 }
245
246 /*
247 * Now we only support channel options
248 * other option class' will used in future
249 */
250
251 return option_type_unknown;
252 }
253
254 static struct lttctl_option *find_opt(const char *name1, const char *name2,
255 const char *name3)
256 {
257 int i;
258
259 if (!name1 || !name2 || !name3)
260 return NULL;
261
262 for (i = 0; i < opt_option_n; i++) {
263 if (strcmp(opt_options[i].name1, name1) == 0
264 && strcmp(opt_options[i].name2, name2) == 0
265 && strcmp(opt_options[i].name3, name3) == 0)
266 return opt_options + i;
267 }
268
269 return NULL;
270 }
271
272 static struct lttctl_option *get_opt(const char *name1, const char *name2,
273 const char *name3)
274 {
275 struct lttctl_option *opt;
276
277 if (!name1 || !name2 || !name3)
278 return NULL;
279
280 opt = find_opt(name1, name2, name3);
281 if (opt)
282 return opt;
283
284 if (opt_option_n >= OPT_MAX) {
285 fprintf(stderr, "Option number out of range\n");
286 return NULL;
287 }
288
289 if (strlen(name1) >= OPT_NAMELEN
290 || strlen(name2) >= OPT_NAMELEN
291 || strlen(name3) >= OPT_NAMELEN) {
292 fprintf(stderr, "Option name too long: %s.%s.%s\n",
293 name1, name2, name3);
294 return NULL;
295 }
296
297 opt = &opt_options[opt_option_n];
298 strcpy(opt->name1, name1);
299 strcpy(opt->name2, name2);
300 strcpy(opt->name3, name3);
301 opt_option_n++;
302
303 return opt;
304 }
305
306 static int parst_opt(const char *optarg)
307 {
308 int ret;
309 char opt_name[OPT_NAMELEN * 3];
310 char opt_valstr[OPT_VALSTRINGLEN];
311 char *p;
312
313 char name1[OPT_NAMELEN];
314 char name2[OPT_NAMELEN];
315 char name3[OPT_NAMELEN];
316
317 enum lttcrl_option_type opttype;
318 int opt_intval;
319 unsigned int opt_uintval;
320 struct lttctl_option *newopt;
321
322 if (!optarg) {
323 fprintf(stderr, "Option empty\n");
324 return -EINVAL;
325 }
326
327 /* Get option name and val_str */
328 p = strchr(optarg, '=');
329 if (!p) {
330 fprintf(stderr, "Option format error: %s\n", optarg);
331 return -EINVAL;
332 }
333
334 if (p - optarg >= sizeof(opt_name)/sizeof(opt_name[0])) {
335 fprintf(stderr, "Option name too long: %s\n", optarg);
336 return -EINVAL;
337 }
338
339 if (strlen(p+1) >= OPT_VALSTRINGLEN) {
340 fprintf(stderr, "Option value too long: %s\n", optarg);
341 return -EINVAL;
342 }
343
344 memcpy(opt_name, optarg, p - optarg);
345 opt_name[p - optarg] = 0;
346 strcpy(opt_valstr, p+1);
347
348 /* separate option name into 3 fields */
349 ret = separate_opt(opt_name, name1, name2, name3);
350 if (ret != 0) {
351 fprintf(stderr, "Option name error: %s\n", optarg);
352 return -EINVAL;
353 }
354
355 /*
356 * check and add option
357 */
358 opttype = opt_type(name1, name2, name3);
359 switch (opttype) {
360 case option_type_unknown:
361 fprintf(stderr, "Option not supported: %s\n", optarg);
362 return -EINVAL;
363 case option_type_string:
364 newopt = get_opt(name1, name2, name3);
365 if (!newopt)
366 return -EINVAL;
367 strcpy(newopt->value.v_string, opt_valstr);
368 return 0;
369 case option_type_int:
370 ret = sscanf(opt_valstr, "%d", &opt_intval);
371 if (ret != 1) {
372 fprintf(stderr, "Option format error: %s\n", optarg);
373 return -EINVAL;
374 }
375 newopt = get_opt(name1, name2, name3);
376 if (!newopt)
377 return -EINVAL;
378 newopt->value.v_int = opt_intval;
379 return 0;
380 case option_type_uint:
381 ret = sscanf(opt_valstr, "%u", &opt_uintval);
382 if (ret != 1) {
383 fprintf(stderr, "Option format error: %s\n", optarg);
384 return -EINVAL;
385 }
386 newopt = get_opt(name1, name2, name3);
387 if (!newopt)
388 return -EINVAL;
389 newopt->value.v_uint = opt_uintval;
390 return 0;
391 case option_type_positive:
392 ret = sscanf(opt_valstr, "%u", &opt_uintval);
393 if (ret != 1 || opt_uintval == 0) {
394 fprintf(stderr, "Option format error: %s\n", optarg);
395 return -EINVAL;
396 }
397 newopt = get_opt(name1, name2, name3);
398 if (!newopt)
399 return -EINVAL;
400 newopt->value.v_uint = opt_uintval;
401 return 0;
402 case option_type_bool:
403 if (opt_valstr[1] != 0) {
404 fprintf(stderr, "Option format error: %s\n", optarg);
405 return -EINVAL;
406 }
407 if (opt_valstr[0] == 'Y' || opt_valstr[0] == 'y'
408 || opt_valstr[0] == '1')
409 opt_intval = 1;
410 else if (opt_valstr[0] == 'N' || opt_valstr[0] == 'n'
411 || opt_valstr[0] == '0')
412 opt_intval = 0;
413 else {
414 fprintf(stderr, "Option format error: %s\n", optarg);
415 return -EINVAL;
416 }
417
418 newopt = get_opt(name1, name2, name3);
419 if (!newopt)
420 return -EINVAL;
421 newopt->value.v_bool = opt_intval;
422 return 0;
423 default:
424 fprintf(stderr, "Internal error on opt %s\n", optarg);
425 return -EINVAL;
426 }
427
428 return 0; /* should not run to here */
429 }
430
431 /* parse_arguments
432 *
433 * Parses the command line arguments.
434 *
435 * Returns -1 if the arguments were correct, but doesn't ask for program
436 * continuation. Returns EINVAL if the arguments are incorrect, or 0 if OK.
437 */
438 static int parse_arguments(int argc, char **argv)
439 {
440 int ret = 0;
441
442 static struct option longopts[] = {
443 {"create", no_argument, NULL, 'c'},
444 {"destroy", no_argument, NULL, 'd'},
445 {"start", no_argument, NULL, 's'},
446 {"pause", no_argument, NULL, 'p'},
447 {"help", no_argument, NULL, 'h'},
448 {"transport", required_argument, NULL, 2},
449 {"option", required_argument, NULL, 'o'},
450 {"create_start", no_argument, NULL, 'C'},
451 {"pause_destroy", no_argument, NULL, 'D'},
452 {"write", required_argument, NULL, 'w'},
453 {"append", no_argument, NULL, 'a'},
454 {"dump_threads", required_argument, NULL, 'n'},
455 {"channel_root", required_argument, NULL, 3},
456 { NULL, 0, NULL, 0 },
457 };
458
459 /*
460 * Enable all channels in default
461 * To make novice users happy
462 */
463 parst_opt("channel.all.enable=1");
464
465 opterr = 1; /* Print error message on getopt_long */
466 while (1) {
467 int c;
468 c = getopt_long(argc, argv, "cdspho:CDw:an:", longopts, NULL);
469 if (-1 == c) {
470 /* parse end */
471 break;
472 }
473 switch (c) {
474 case 'c':
475 opt_create = 1;
476 break;
477 case 'd':
478 opt_destroy = 1;
479 break;
480 case 's':
481 opt_start = 1;
482 break;
483 case 'p':
484 opt_pause = 1;
485 break;
486 case 'h':
487 opt_help = 1;
488 break;
489 case 2:
490 if (!opt_transport) {
491 opt_transport = optarg;
492 } else {
493 fprintf(stderr,
494 "Please specify only 1 transport\n");
495 return -EINVAL;
496 }
497 break;
498 case 'o':
499 ret = parst_opt(optarg);
500 if (ret)
501 return ret;
502 break;
503 case 'C':
504 opt_create = 1;
505 opt_start = 1;
506 break;
507 case 'D':
508 opt_pause = 1;
509 opt_destroy = 1;
510 break;
511 case 'w':
512 if (!opt_write) {
513 opt_write = optarg;
514 } else {
515 fprintf(stderr,
516 "Please specify only 1 write dir\n");
517 return -EINVAL;
518 }
519 break;
520 case 'a':
521 opt_append = 1;
522 break;
523 case 'n':
524 if (opt_dump_threads) {
525 fprintf(stderr,
526 "Please specify only 1 dump threads\n");
527 return -EINVAL;
528 }
529
530 ret = sscanf(optarg, "%u", &opt_dump_threads);
531 if (ret != 1) {
532 fprintf(stderr,
533 "Dump threads not positive number\n");
534 return -EINVAL;
535 }
536 break;
537 case 3:
538 if (!opt_channel_root) {
539 opt_channel_root = optarg;
540 } else {
541 fprintf(stderr,
542 "Please specify only 1 channel root\n");
543 return -EINVAL;
544 }
545 break;
546 case '?':
547 return -EINVAL;
548 default:
549 break;
550 };
551 };
552
553 /* Don't check args when user needs help */
554 if (opt_help)
555 return 0;
556
557 /* Get tracename */
558 if (optind < argc - 1) {
559 fprintf(stderr, "Please specify only 1 trace name\n");
560 return -EINVAL;
561 }
562 if (optind > argc - 1) {
563 fprintf(stderr, "Please specify trace name\n");
564 return -EINVAL;
565 }
566 opt_tracename = argv[optind];
567
568 /*
569 * Check arguments
570 */
571 if (!opt_create && !opt_start && !opt_destroy && !opt_pause) {
572 fprintf(stderr,
573 "Please specify a option of "
574 "create, destroy, start, or pause\n");
575 return -EINVAL;
576 }
577
578 if ((opt_create || opt_start) && (opt_destroy || opt_pause)) {
579 fprintf(stderr,
580 "Create and start conflict with destroy and pause\n");
581 return -EINVAL;
582 }
583
584 if (opt_create) {
585 if (!opt_transport)
586 opt_transport = "relay";
587 }
588
589 if (opt_transport) {
590 if (!opt_create) {
591 fprintf(stderr,
592 "Transport option must be combine with create"
593 " option\n");
594 return -EINVAL;
595 }
596 }
597
598 if (opt_write) {
599 if (!opt_create && !opt_destroy) {
600 fprintf(stderr,
601 "Write option must be combine with create or"
602 " destroy option\n");
603 return -EINVAL;
604 }
605
606 if (!opt_channel_root)
607 if (getdebugfsmntdir(channel_root_default) == 0) {
608 strcat(channel_root_default, "/ltt");
609 opt_channel_root = channel_root_default;
610 }
611 /* Todo:
612 * if (!opt_channel_root)
613 * if (auto_mount_debugfs_dir(channel_root_default) == 0)
614 * opt_channel_root = debugfs_dir_mnt_point;
615 */
616 if (!opt_channel_root) {
617 fprintf(stderr,
618 "Channel_root is necessary for -w option,"
619 " but neither --channel_root option\n"
620 "specified, nor debugfs's mount dir found.\n");
621 return -EINVAL;
622 }
623
624 if (opt_dump_threads == 0)
625 opt_dump_threads = 1;
626 }
627
628 if (opt_append) {
629 if (!opt_write) {
630 fprintf(stderr,
631 "Append option must be combine with write"
632 " option\n");
633 return -EINVAL;
634 }
635 }
636
637 if (opt_dump_threads) {
638 if (!opt_write) {
639 fprintf(stderr,
640 "Dump_threads option must be combine with write"
641 " option\n");
642 return -EINVAL;
643 }
644 }
645
646 if (opt_channel_root) {
647 if (!opt_write) {
648 fprintf(stderr,
649 "Channel_root option must be combine with write"
650 " option\n");
651 return -EINVAL;
652 }
653 }
654
655 return 0;
656 }
657
658 static void show_info(void)
659 {
660 printf("Linux Trace Toolkit Trace Control " VERSION"\n");
661 printf("\n");
662 if (opt_tracename != NULL) {
663 printf("Controlling trace : %s\n", opt_tracename);
664 printf("\n");
665 }
666 }
667
668 static int lttctl_create_trace(void)
669 {
670 int ret;
671 int i;
672
673 ret = lttctl_setup_trace(opt_tracename);
674 if (ret)
675 goto setup_trace_fail;
676
677 for (i = 0; i < opt_option_n; i++) {
678 if (strcmp(opt_options[i].name1, "channel") != 0)
679 continue;
680
681 if (strcmp(opt_options[i].name3, "enable") == 0) {
682 ret = lttctl_set_channel_enable(opt_tracename,
683 opt_options[i].name2,
684 opt_options[i].value.v_bool);
685 if (ret)
686 goto set_option_fail;
687 }
688
689 if (strcmp(opt_options[i].name3, "overwrite") == 0) {
690 ret = lttctl_set_channel_overwrite(opt_tracename,
691 opt_options[i].name2,
692 opt_options[i].value.v_bool);
693 if (ret)
694 goto set_option_fail;
695 }
696
697 if (strcmp(opt_options[i].name3, "bufnum") == 0) {
698 ret = lttctl_set_channel_subbuf_num(opt_tracename,
699 opt_options[i].name2,
700 opt_options[i].value.v_uint);
701 if (ret)
702 goto set_option_fail;
703 }
704
705 if (strcmp(opt_options[i].name3, "bufsize") == 0) {
706 ret = lttctl_set_channel_subbuf_size(opt_tracename,
707 opt_options[i].name2,
708 opt_options[i].value.v_uint);
709 if (ret)
710 goto set_option_fail;
711 }
712 }
713
714 ret = lttctl_set_trans(opt_tracename, opt_transport);
715 if (ret)
716 goto set_option_fail;
717
718 ret = lttctl_alloc_trace(opt_tracename);
719 if (ret)
720 goto alloc_trace_fail;
721
722 return 0;
723
724 alloc_trace_fail:
725 set_option_fail:
726 lttctl_destroy_trace(opt_tracename);
727 setup_trace_fail:
728 return ret;
729 }
730
731 /*
732 * Start a lttd daemon to write trace datas
733 * Dump overwrite channels on overwrite!=0
734 * Dump normal(non-overwrite) channels on overwrite=0
735 *
736 * ret: 0 on success
737 * !0 on fail
738 */
739 static int lttctl_daemon(int overwrite)
740 {
741 pid_t pid;
742 int status;
743
744 pid = fork();
745 if (pid < 0) {
746 perror("Error in forking for lttd daemon");
747 return errno;
748 }
749
750 if (pid == 0) {
751 /* child */
752 char *argv[16];
753 int argc = 0;
754 char channel_path[PATH_MAX];
755 char thread_num[16];
756
757 /* prog path */
758 argv[argc] = getenv("LTT_DAEMON");
759 if (argv[argc] == NULL)
760 argv[argc] = PACKAGE_BIN_DIR "/lttd";
761 argc++;
762
763 /* -t option */
764 argv[argc] = "-t";
765 argc++;
766 /*
767 * we allow modify of opt_write's content in new process
768 * for get rid of warning of assign char * to const char *
769 */
770 argv[argc] = (char *)opt_write;
771 argc++;
772
773 /* -c option */
774 strcpy(channel_path, opt_channel_root);
775 strcat(channel_path, "/");
776 strcat(channel_path, opt_tracename);
777 argv[argc] = "-c";
778 argc++;
779 argv[argc] = channel_path;
780 argc++;
781
782 /* -N option */
783 sprintf(thread_num, "%u", opt_dump_threads);
784 argv[argc] = "-N";
785 argc++;
786 argv[argc] = thread_num;
787 argc++;
788
789 /* -a option */
790 if (opt_append) {
791 argv[argc] = "-a";
792 argc++;
793 }
794
795 /* -d option */
796 argv[argc] = "-d";
797 argc++;
798
799 /* overwrite option */
800 if (overwrite) {
801 argv[argc] = "-f";
802 argc++;
803 } else {
804 argv[argc] = "-n";
805 argc++;
806 }
807
808 argv[argc] = NULL;
809
810 execvp(argv[0], argv);
811
812 perror("Error in executing the lttd daemon");
813 exit(errno);
814 }
815
816 /* parent */
817 if (waitpid(pid, &status, 0) == -1) {
818 perror("Error in waitpid\n");
819 return errno;
820 }
821
822 if (!WIFEXITED(status)) {
823 fprintf(stderr, "lttd process interrupted\n");
824 return status;
825 }
826
827 if (WEXITSTATUS(status))
828 fprintf(stderr, "lttd process running failed\n");
829
830 return WEXITSTATUS(status);
831 }
832
833 int main(int argc, char **argv)
834 {
835 int ret;
836
837 ret = parse_arguments(argc, argv);
838 /* If user needs show help, we disregard other options */
839 if (opt_help) {
840 show_arguments();
841 return 0;
842 }
843
844 /* exit program if arguments wrong */
845 if (ret)
846 return 1;
847
848 show_info();
849
850 ret = lttctl_init();
851 if (ret != 0)
852 return ret;
853
854 if (opt_create) {
855 printf("lttctl: Creating trace\n");
856 ret = lttctl_create_trace();
857 if (ret)
858 goto op_fail;
859
860 if (opt_write) {
861 printf("lttctl: Forking lttd\n");
862 ret = lttctl_daemon(0);
863 if (ret)
864 goto op_fail;
865 }
866 }
867
868 if (opt_start) {
869 printf("lttctl: Starting trace\n");
870 ret = lttctl_start(opt_tracename);
871 if (ret)
872 goto op_fail;
873 }
874
875 if (opt_pause) {
876 printf("lttctl: Pausing trace\n");
877 ret = lttctl_pause(opt_tracename);
878 if (ret)
879 goto op_fail;
880 }
881
882 if (opt_destroy) {
883 if (opt_write) {
884 printf("lttctl: Forking lttd\n");
885 ret = lttctl_daemon(1);
886 if (ret)
887 goto op_fail;
888 }
889
890 printf("lttctl: Destroying trace\n");
891 ret = lttctl_destroy_trace(opt_tracename);
892 if (ret)
893 goto op_fail;
894 }
895
896 op_fail:
897 lttctl_destroy();
898
899 return ret;
900 }
This page took 0.050269 seconds and 4 git commands to generate.