Clean-up: lttng: add-trigger: silence coverity warning
[lttng-tools.git] / src / bin / lttng / commands / add_trigger.c
1 /*
2 * Copyright (C) 2021 Simon Marchi <simon.marchi@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include <ctype.h>
9 #include <stdio.h>
10
11 #include "../command.h"
12 #include "../loglevel.h"
13 #include "../uprobe.h"
14
15 #include "common/argpar/argpar.h"
16 #include "common/dynamic-array.h"
17 #include "common/string-utils/string-utils.h"
18 #include "common/utils.h"
19 /* For lttng_event_rule_type_str(). */
20 #include <lttng/event-rule/event-rule-internal.h>
21 #include <lttng/lttng.h>
22 #include "common/filter/filter-ast.h"
23 #include "common/filter/filter-ir.h"
24 #include "common/dynamic-array.h"
25
26 #if (LTTNG_SYMBOL_NAME_LEN == 256)
27 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
28 #endif
29
30 #ifdef LTTNG_EMBED_HELP
31 static const char help_msg[] =
32 #include <lttng-add-trigger.1.h>
33 ;
34 #endif
35
36 enum {
37 OPT_HELP,
38 OPT_LIST_OPTIONS,
39
40 OPT_CONDITION,
41 OPT_ACTION,
42 OPT_ID,
43 OPT_USER_ID,
44 OPT_RATE_POLICY,
45
46 OPT_ALL,
47 OPT_FILTER,
48 OPT_EXCLUDE,
49 OPT_LOGLEVEL,
50 OPT_LOGLEVEL_ONLY,
51
52 OPT_USERSPACE,
53 OPT_KERNEL,
54 OPT_LOG4J,
55 OPT_JUL,
56 OPT_PYTHON,
57
58 OPT_FUNCTION,
59 OPT_PROBE,
60 OPT_USERSPACE_PROBE,
61 OPT_SYSCALL,
62 OPT_TRACEPOINT,
63
64 OPT_NAME,
65 OPT_MAX_SIZE,
66 OPT_DATA_URL,
67 OPT_CTRL_URL,
68 OPT_URL,
69 OPT_PATH,
70
71 OPT_CAPTURE,
72 };
73
74 static const struct argpar_opt_descr event_rule_opt_descrs[] = {
75 { OPT_ALL, 'a', "all", false },
76 { OPT_FILTER, 'f', "filter", true },
77 { OPT_EXCLUDE, 'x', "exclude", true },
78 { OPT_LOGLEVEL, '\0', "loglevel", true },
79 { OPT_LOGLEVEL_ONLY, '\0', "loglevel-only", true },
80
81 /* Domains */
82 { OPT_USERSPACE, 'u', "userspace", false },
83 { OPT_KERNEL, 'k', "kernel", false },
84 { OPT_LOG4J, 'l', "log4j", false },
85 { OPT_JUL, 'j', "jul", false },
86 { OPT_PYTHON, 'p', "python", false },
87
88 /* Event rule types */
89 { OPT_FUNCTION, '\0', "function", true },
90 { OPT_PROBE, '\0', "probe", true },
91 { OPT_USERSPACE_PROBE, '\0', "userspace-probe", true },
92 { OPT_SYSCALL, '\0', "syscall" },
93 { OPT_TRACEPOINT, '\0', "tracepoint" },
94
95 /* Capture descriptor */
96 { OPT_CAPTURE, '\0', "capture", true },
97
98 ARGPAR_OPT_DESCR_SENTINEL
99 };
100
101 static
102 bool assign_domain_type(enum lttng_domain_type *dest,
103 enum lttng_domain_type src)
104 {
105 bool ret;
106
107 if (*dest == LTTNG_DOMAIN_NONE || *dest == src) {
108 *dest = src;
109 ret = true;
110 } else {
111 ERR("Multiple domains specified.");
112 ret = false;
113 }
114
115 return ret;
116 }
117
118 static
119 bool assign_event_rule_type(enum lttng_event_rule_type *dest,
120 enum lttng_event_rule_type src)
121 {
122 bool ret;
123
124 if (*dest == LTTNG_EVENT_RULE_TYPE_UNKNOWN || *dest == src) {
125 *dest = src;
126 ret = true;
127 } else {
128 ERR("Multiple event types specified.");
129 ret = false;
130 }
131
132 return ret;
133 }
134
135 static
136 bool assign_string(char **dest, const char *src, const char *opt_name)
137 {
138 bool ret;
139
140 if (*dest) {
141 ERR("Duplicate '%s' given.", opt_name);
142 goto error;
143 }
144
145 *dest = strdup(src);
146 if (!*dest) {
147 PERROR("Failed to allocate string '%s'.", opt_name);
148 goto error;
149 }
150
151 ret = true;
152 goto end;
153
154 error:
155 ret = false;
156
157 end:
158 return ret;
159 }
160
161 /* This is defined in enable_events.c. */
162 LTTNG_HIDDEN
163 int create_exclusion_list_and_validate(const char *event_name,
164 const char *exclusions_arg,
165 char ***exclusion_list);
166
167 /*
168 * Parse `str` as a log level in domain `domain_type`. Return -1 if the string
169 * is not recognized as a valid log level.
170 */
171 static
172 int parse_loglevel_string(const char *str, enum lttng_domain_type domain_type)
173 {
174 switch (domain_type) {
175 case LTTNG_DOMAIN_UST:
176 {
177 enum lttng_loglevel loglevel;
178 const int ret = loglevel_name_to_value(str, &loglevel);
179
180 return ret == -1 ? ret : (int) loglevel;
181 }
182 case LTTNG_DOMAIN_LOG4J:
183 {
184 enum lttng_loglevel_log4j loglevel;
185 const int ret = loglevel_log4j_name_to_value(str, &loglevel);
186
187 return ret == -1 ? ret : (int) loglevel;
188 }
189 case LTTNG_DOMAIN_JUL:
190 {
191 enum lttng_loglevel_jul loglevel;
192 const int ret = loglevel_jul_name_to_value(str, &loglevel);
193
194 return ret == -1 ? ret : (int) loglevel;
195 }
196 case LTTNG_DOMAIN_PYTHON:
197 {
198 enum lttng_loglevel_python loglevel;
199 const int ret = loglevel_python_name_to_value(str, &loglevel);
200
201 return ret == -1 ? ret : (int) loglevel;
202 }
203 default:
204 /* Invalid domain type. */
205 abort();
206 }
207 }
208
209 static int parse_kernel_probe_opts(const char *source,
210 struct lttng_kernel_probe_location **location)
211 {
212 int ret = 0;
213 int match;
214 char s_hex[19];
215 char name[LTTNG_SYMBOL_NAME_LEN];
216 char *symbol_name = NULL;
217 uint64_t offset;
218
219 /* Check for symbol+offset. */
220 match = sscanf(source,
221 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
222 "[^'+']+%18s",
223 name, s_hex);
224 if (match == 2) {
225 if (*s_hex == '\0') {
226 ERR("Kernel probe symbol offset is missing.");
227 goto error;
228 }
229
230 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
231 if (!symbol_name) {
232 PERROR("Failed to copy kernel probe location symbol name.");
233 goto error;
234 }
235 offset = strtoul(s_hex, NULL, 0);
236
237 *location = lttng_kernel_probe_location_symbol_create(
238 symbol_name, offset);
239 if (!*location) {
240 ERR("Failed to create symbol kernel probe location.");
241 goto error;
242 }
243
244 goto end;
245 }
246
247 /* Check for symbol. */
248 if (isalpha(name[0]) || name[0] == '_') {
249 match = sscanf(source,
250 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
251 "s",
252 name);
253 if (match == 1) {
254 symbol_name = strndup(name, LTTNG_SYMBOL_NAME_LEN);
255 if (!symbol_name) {
256 ERR("Failed to copy kernel probe location symbol name.");
257 goto error;
258 }
259
260 *location = lttng_kernel_probe_location_symbol_create(
261 symbol_name, 0);
262 if (!*location) {
263 ERR("Failed to create symbol kernel probe location.");
264 goto error;
265 }
266
267 goto end;
268 }
269 }
270
271 /* Check for address. */
272 match = sscanf(source, "%18s", s_hex);
273 if (match > 0) {
274 uint64_t address;
275
276 if (*s_hex == '\0') {
277 ERR("Invalid kernel probe location address.");
278 goto error;
279 }
280
281 address = strtoul(s_hex, NULL, 0);
282 *location = lttng_kernel_probe_location_address_create(address);
283 if (!*location) {
284 ERR("Failed to create symbol kernel probe location.");
285 goto error;
286 }
287
288 goto end;
289 }
290
291 error:
292 /* No match */
293 ret = -1;
294 *location = NULL;
295
296 end:
297 free(symbol_name);
298 return ret;
299 }
300
301 static
302 struct lttng_event_expr *ir_op_load_expr_to_event_expr(
303 const struct ir_load_expression *load_expr,
304 const char *capture_str)
305 {
306 char *provider_name = NULL;
307 struct lttng_event_expr *event_expr = NULL;
308 const struct ir_load_expression_op *load_expr_op = load_expr->child;
309 const enum ir_load_expression_type load_expr_child_type =
310 load_expr_op->type;
311
312 switch (load_expr_child_type) {
313 case IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT:
314 case IR_LOAD_EXPRESSION_GET_CONTEXT_ROOT:
315 {
316 const char *field_name;
317
318 load_expr_op = load_expr_op->next;
319 assert(load_expr_op);
320 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
321 field_name = load_expr_op->u.symbol;
322 assert(field_name);
323
324 event_expr = load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
325 lttng_event_expr_event_payload_field_create(field_name) :
326 lttng_event_expr_channel_context_field_create(field_name);
327 if (!event_expr) {
328 ERR("Failed to create %s event expression: field name = `%s`.",
329 load_expr_child_type == IR_LOAD_EXPRESSION_GET_PAYLOAD_ROOT ?
330 "payload field" : "channel context",
331 field_name);
332 goto error;
333 }
334
335 break;
336 }
337 case IR_LOAD_EXPRESSION_GET_APP_CONTEXT_ROOT:
338 {
339 const char *colon;
340 const char *type_name;
341 const char *field_name;
342
343 load_expr_op = load_expr_op->next;
344 assert(load_expr_op);
345 assert(load_expr_op->type == IR_LOAD_EXPRESSION_GET_SYMBOL);
346 field_name = load_expr_op->u.symbol;
347 assert(field_name);
348
349 /*
350 * The field name needs to be of the form PROVIDER:TYPE. We
351 * split it here.
352 */
353 colon = strchr(field_name, ':');
354 if (!colon) {
355 ERR("Invalid app-specific context field name: missing colon in `%s`.",
356 field_name);
357 goto error;
358 }
359
360 type_name = colon + 1;
361 if (*type_name == '\0') {
362 ERR("Invalid app-specific context field name: missing type name after colon in `%s`.",
363 field_name);
364 goto error;
365 }
366
367 provider_name = strndup(field_name, colon - field_name);
368 if (!provider_name) {
369 PERROR("Failed to allocate field name string");
370 goto error;
371 }
372
373 event_expr = lttng_event_expr_app_specific_context_field_create(
374 provider_name, type_name);
375 if (!event_expr) {
376 ERR("Failed to create app-specific context field event expression: provider name = `%s`, type name = `%s`",
377 provider_name, type_name);
378 goto error;
379 }
380
381 break;
382 }
383 default:
384 ERR("%s: unexpected load expr type %d.", __func__,
385 load_expr_op->type);
386 abort();
387 }
388
389 load_expr_op = load_expr_op->next;
390
391 /* There may be a single array index after that. */
392 if (load_expr_op->type == IR_LOAD_EXPRESSION_GET_INDEX) {
393 struct lttng_event_expr *index_event_expr;
394 const uint64_t index = load_expr_op->u.index;
395
396 index_event_expr = lttng_event_expr_array_field_element_create(event_expr, index);
397 if (!index_event_expr) {
398 ERR("Failed to create array field element event expression.");
399 goto error;
400 }
401
402 event_expr = index_event_expr;
403 load_expr_op = load_expr_op->next;
404 }
405
406 switch (load_expr_op->type) {
407 case IR_LOAD_EXPRESSION_LOAD_FIELD:
408 /*
409 * This is what we expect, IR_LOAD_EXPRESSION_LOAD_FIELD is
410 * always found at the end of the chain.
411 */
412 break;
413 case IR_LOAD_EXPRESSION_GET_SYMBOL:
414 ERR("While parsing expression `%s`: Capturing subfields is not supported.",
415 capture_str);
416 goto error;
417
418 default:
419 ERR("%s: unexpected load expression operator %s.", __func__,
420 ir_load_expression_type_str(load_expr_op->type));
421 abort();
422 }
423
424 goto end;
425
426 error:
427 lttng_event_expr_destroy(event_expr);
428 event_expr = NULL;
429
430 end:
431 free(provider_name);
432
433 return event_expr;
434 }
435
436 static
437 struct lttng_event_expr *ir_op_load_to_event_expr(
438 const struct ir_op *ir, const char *capture_str)
439 {
440 struct lttng_event_expr *event_expr = NULL;
441
442 assert(ir->op == IR_OP_LOAD);
443
444 switch (ir->data_type) {
445 case IR_DATA_EXPRESSION:
446 {
447 const struct ir_load_expression *ir_load_expr =
448 ir->u.load.u.expression;
449
450 event_expr = ir_op_load_expr_to_event_expr(
451 ir_load_expr, capture_str);
452 break;
453 }
454 default:
455 ERR("%s: unexpected data type: %s.", __func__,
456 ir_data_type_str(ir->data_type));
457 abort();
458 }
459
460 return event_expr;
461 }
462
463 static
464 const char *ir_operator_type_human_str(enum ir_op_type op)
465 {
466 const char *name;
467
468 switch (op) {
469 case IR_OP_BINARY:
470 name = "Binary";
471 break;
472 case IR_OP_UNARY:
473 name = "Unary";
474 break;
475 case IR_OP_LOGICAL:
476 name = "Logical";
477 break;
478 default:
479 abort();
480 }
481
482 return name;
483 }
484
485 static
486 struct lttng_event_expr *ir_op_root_to_event_expr(const struct ir_op *ir,
487 const char *capture_str)
488 {
489 struct lttng_event_expr *event_expr = NULL;
490
491 assert(ir->op == IR_OP_ROOT);
492 ir = ir->u.root.child;
493
494 switch (ir->op) {
495 case IR_OP_LOAD:
496 event_expr = ir_op_load_to_event_expr(ir, capture_str);
497 break;
498 case IR_OP_BINARY:
499 case IR_OP_UNARY:
500 case IR_OP_LOGICAL:
501 ERR("While parsing expression `%s`: %s operators are not allowed in capture expressions.",
502 capture_str,
503 ir_operator_type_human_str(ir->op));
504 break;
505 default:
506 ERR("%s: unexpected IR op type: %s.", __func__,
507 ir_op_type_str(ir->op));
508 abort();
509 }
510
511 return event_expr;
512 }
513
514 static
515 void destroy_event_expr(void *ptr)
516 {
517 lttng_event_expr_destroy(ptr);
518 }
519
520 struct parse_event_rule_res {
521 /* Owned by this. */
522 struct lttng_event_rule *er;
523
524 /* Array of `struct lttng_event_expr *` */
525 struct lttng_dynamic_pointer_array capture_descriptors;
526 };
527
528 static
529 struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv)
530 {
531 enum lttng_domain_type domain_type = LTTNG_DOMAIN_NONE;
532 enum lttng_event_rule_type event_rule_type =
533 LTTNG_EVENT_RULE_TYPE_UNKNOWN;
534 struct argpar_state *state;
535 struct argpar_item *item = NULL;
536 char *error = NULL;
537 int consumed_args = -1;
538 struct lttng_kernel_probe_location *kernel_probe_location = NULL;
539 struct lttng_userspace_probe_location *userspace_probe_location = NULL;
540 struct parse_event_rule_res res = { 0 };
541 struct lttng_event_expr *event_expr = NULL;
542 struct filter_parser_ctx *parser_ctx = NULL;
543 struct lttng_log_level_rule *log_level_rule = NULL;
544
545 /* Was the -a/--all flag provided? */
546 bool all_events = false;
547
548 /* Tracepoint name (non-option argument). */
549 const char *tracepoint_name = NULL;
550
551 /* Holds the argument of --probe / --userspace-probe. */
552 char *source = NULL;
553
554 /* Filter. */
555 char *filter = NULL;
556
557 /* Exclude. */
558 char *exclude = NULL;
559 char **exclusion_list = NULL;
560
561 /* Log level. */
562 char *loglevel_str = NULL;
563 bool loglevel_only = false;
564
565 lttng_dynamic_pointer_array_init(&res.capture_descriptors,
566 destroy_event_expr);
567 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
568 if (!state) {
569 ERR("Failed to allocate an argpar state.");
570 goto error;
571 }
572
573 while (true) {
574 enum argpar_state_parse_next_status status;
575
576 ARGPAR_ITEM_DESTROY_AND_RESET(item);
577 status = argpar_state_parse_next(state, &item, &error);
578 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
579 ERR("%s", error);
580 goto error;
581 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
582 /* Just stop parsing here. */
583 break;
584 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
585 break;
586 }
587
588 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
589
590 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
591 const struct argpar_item_opt *item_opt =
592 (const struct argpar_item_opt *) item;
593
594 switch (item_opt->descr->id) {
595 /* Domains. */
596 case OPT_USERSPACE:
597 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_UST)) {
598 goto error;
599 }
600
601 break;
602 case OPT_KERNEL:
603 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_KERNEL)) {
604 goto error;
605 }
606
607 break;
608 case OPT_LOG4J:
609 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_LOG4J)) {
610 goto error;
611 }
612
613 break;
614 case OPT_JUL:
615 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_JUL)) {
616 goto error;
617 }
618
619 break;
620 case OPT_PYTHON:
621 if (!assign_domain_type(&domain_type, LTTNG_DOMAIN_PYTHON)) {
622 goto error;
623 }
624
625 break;
626
627 /* Event rule types */
628 case OPT_FUNCTION:
629 if (!assign_event_rule_type(&event_rule_type,
630 LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION)) {
631 goto error;
632 }
633
634 break;
635 case OPT_PROBE:
636 if (!assign_event_rule_type(&event_rule_type,
637 LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE)) {
638 goto error;
639 }
640
641 if (!assign_string(&source, item_opt->arg, "source")) {
642 goto error;
643 }
644
645 break;
646 case OPT_USERSPACE_PROBE:
647 if (!assign_event_rule_type(&event_rule_type,
648 LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE)) {
649 goto error;
650 }
651
652 if (!assign_string(&source, item_opt->arg, "source")) {
653 goto error;
654 }
655
656 break;
657 case OPT_SYSCALL:
658 if (!assign_event_rule_type(&event_rule_type,
659 LTTNG_EVENT_RULE_TYPE_SYSCALL)) {
660 goto error;
661 }
662
663 break;
664 case OPT_TRACEPOINT:
665 if (!assign_event_rule_type(&event_rule_type,
666 LTTNG_EVENT_RULE_TYPE_TRACEPOINT)) {
667 goto error;
668 }
669
670 break;
671 case OPT_ALL:
672 all_events = true;
673 break;
674 case OPT_FILTER:
675 if (!assign_string(&filter, item_opt->arg,
676 "--filter/-f")) {
677 goto error;
678 }
679
680 break;
681 case OPT_EXCLUDE:
682 if (!assign_string(&exclude, item_opt->arg,
683 "--exclude/-x")) {
684 goto error;
685 }
686
687 break;
688 case OPT_LOGLEVEL:
689 case OPT_LOGLEVEL_ONLY:
690 if (!assign_string(&loglevel_str, item_opt->arg,
691 "--loglevel/--loglevel-only")) {
692 goto error;
693 }
694
695 loglevel_only = item_opt->descr->id ==
696 OPT_LOGLEVEL_ONLY;
697 break;
698 case OPT_CAPTURE:
699 {
700 int ret;
701 const char *capture_str = item_opt->arg;
702
703 ret = filter_parser_ctx_create_from_filter_expression(
704 capture_str, &parser_ctx);
705 if (ret) {
706 ERR("Failed to parse capture expression `%s`.",
707 capture_str);
708 goto error;
709 }
710
711 event_expr = ir_op_root_to_event_expr(
712 parser_ctx->ir_root,
713 capture_str);
714 if (!event_expr) {
715 /*
716 * ir_op_root_to_event_expr has printed
717 * an error message.
718 */
719 goto error;
720 }
721
722 ret = lttng_dynamic_pointer_array_add_pointer(
723 &res.capture_descriptors,
724 event_expr);
725 if (ret) {
726 goto error;
727 }
728
729 /*
730 * The ownership of event expression was
731 * transferred to the dynamic array.
732 */
733 event_expr = NULL;
734
735 break;
736 }
737 default:
738 abort();
739 }
740 } else {
741 const struct argpar_item_non_opt *item_non_opt =
742 (const struct argpar_item_non_opt *)
743 item;
744
745 /*
746 * Don't accept two non-option arguments/tracepoint
747 * names.
748 */
749 if (tracepoint_name) {
750 ERR("Unexpected argument '%s'",
751 item_non_opt->arg);
752 goto error;
753 }
754
755 tracepoint_name = item_non_opt->arg;
756 }
757 }
758
759 if (event_rule_type == LTTNG_EVENT_RULE_TYPE_UNKNOWN) {
760 event_rule_type = LTTNG_EVENT_RULE_TYPE_TRACEPOINT;
761 }
762
763 /*
764 * Option -a is applicable to event rules of type tracepoint and
765 * syscall, and it is equivalent to using "*" as the tracepoint name.
766 */
767 if (all_events) {
768 switch (event_rule_type) {
769 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
770 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
771 break;
772 default:
773 ERR("Can't use -a/--all with %s event rules.",
774 lttng_event_rule_type_str(event_rule_type));
775 goto error;
776 }
777
778 if (tracepoint_name) {
779 ERR("Can't provide a tracepoint name with -a/--all.");
780 goto error;
781 }
782
783 /* In which case, it's equivalent to tracepoint name "*". */
784 tracepoint_name = "*";
785 }
786
787 /*
788 * A tracepoint name (or -a, for the event rule types that accept it)
789 * is required.
790 */
791 if (!tracepoint_name) {
792 ERR("Need to provide either a tracepoint name or -a/--all.");
793 goto error;
794 }
795
796 /*
797 * We don't support multiple tracepoint names for now.
798 */
799 if (strchr(tracepoint_name, ',')) {
800 ERR("Comma separated tracepoint names are not supported.");
801 goto error;
802 }
803
804 /*
805 * Update *argc and *argv so our caller can keep parsing what follows.
806 */
807 consumed_args = argpar_state_get_ingested_orig_args(state);
808 assert(consumed_args >= 0);
809 *argc -= consumed_args;
810 *argv += consumed_args;
811
812 /* Need to specify a domain. */
813 if (domain_type == LTTNG_DOMAIN_NONE) {
814 ERR("Please specify a domain (--kernel/--userspace/--jul/--log4j/--python).");
815 goto error;
816 }
817
818 /* Validate event rule type against domain. */
819 switch (event_rule_type) {
820 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
821 case LTTNG_EVENT_RULE_TYPE_KERNEL_FUNCTION:
822 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
823 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
824 if (domain_type != LTTNG_DOMAIN_KERNEL) {
825 ERR("Event type not available for user-space tracing.");
826 goto error;
827 }
828 break;
829
830 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
831 break;
832
833 default:
834 abort();
835 }
836
837 /*
838 * Adding a filter to a probe, function or userspace-probe would be
839 * denied by the kernel tracer as it's not supported at the moment. We
840 * do an early check here to warn the user.
841 */
842 if (filter && domain_type == LTTNG_DOMAIN_KERNEL) {
843 switch (event_rule_type) {
844 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
845 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
846 break;
847 default:
848 ERR("Filter expressions are not supported for %s event rules.",
849 lttng_event_rule_type_str(event_rule_type));
850 goto error;
851 }
852 }
853
854 /* If --exclude/-x was passed, split it into an exclusion list. */
855 if (exclude) {
856 if (domain_type != LTTNG_DOMAIN_UST) {
857 ERR("Event name exclusions are not yet implemented for %s event rules.",
858 get_domain_str(domain_type));
859 goto error;
860 }
861
862
863 if (create_exclusion_list_and_validate(tracepoint_name, exclude,
864 &exclusion_list) != 0) {
865 ERR("Failed to create exclusion list.");
866 goto error;
867 }
868 }
869
870 if (loglevel_str && event_rule_type != LTTNG_EVENT_RULE_TYPE_TRACEPOINT) {
871 ERR("Log levels are only applicable to tracepoint event rules.");
872 goto error;
873 }
874
875 /* Finally, create the event rule object. */
876 switch (event_rule_type) {
877 case LTTNG_EVENT_RULE_TYPE_TRACEPOINT:
878 {
879 enum lttng_event_rule_status event_rule_status;
880
881 res.er = lttng_event_rule_tracepoint_create(domain_type);
882 if (!res.er) {
883 ERR("Failed to create tracepoint event rule.");
884 goto error;
885 }
886
887 /* Set pattern. */
888 event_rule_status = lttng_event_rule_tracepoint_set_pattern(
889 res.er, tracepoint_name);
890 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
891 ERR("Failed to set tracepoint event rule's pattern to '%s'.",
892 tracepoint_name);
893 goto error;
894 }
895
896 /* Set filter. */
897 if (filter) {
898 event_rule_status = lttng_event_rule_tracepoint_set_filter(
899 res.er, filter);
900 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
901 ERR("Failed to set tracepoint event rule's filter to '%s'.",
902 filter);
903 goto error;
904 }
905 }
906
907 /* Set exclusion list. */
908 if (exclusion_list) {
909 int n;
910
911 for (n = 0; exclusion_list[n]; n++) {
912 event_rule_status = lttng_event_rule_tracepoint_add_exclusion(
913 res.er,
914 exclusion_list[n]);
915 if (event_rule_status !=
916 LTTNG_EVENT_RULE_STATUS_OK) {
917 ERR("Failed to set tracepoint exclusion list element '%s'",
918 exclusion_list[n]);
919 goto error;
920 }
921 }
922 }
923
924 if (loglevel_str) {
925 int loglevel;
926
927 if (domain_type == LTTNG_DOMAIN_KERNEL) {
928 ERR("Log levels are not supported by the kernel tracer.");
929 goto error;
930 }
931
932 loglevel = parse_loglevel_string(
933 loglevel_str, domain_type);
934 if (loglevel < 0) {
935 ERR("Failed to parse `%s` as a log level.",
936 loglevel_str);
937 goto error;
938 }
939
940 if (loglevel_only) {
941 log_level_rule = lttng_log_level_rule_exactly_create(loglevel);
942 } else {
943 log_level_rule = lttng_log_level_rule_at_least_as_severe_as_create(loglevel);
944 }
945
946 if (log_level_rule == NULL) {
947 ERR("Failed to create log level rule object.");
948 goto error;
949 }
950
951 event_rule_status =
952 lttng_event_rule_tracepoint_set_log_level_rule(
953 res.er, log_level_rule);
954
955 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
956 ERR("Failed to set log level on event fule.");
957 goto error;
958 }
959 }
960
961 break;
962 }
963 case LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE:
964 {
965 int ret;
966 enum lttng_event_rule_status event_rule_status;
967
968
969 ret = parse_kernel_probe_opts(source, &kernel_probe_location);
970 if (ret) {
971 ERR("Failed to parse kernel probe location.");
972 goto error;
973 }
974
975 assert(kernel_probe_location);
976 res.er = lttng_event_rule_kernel_probe_create(kernel_probe_location);
977 if (!res.er) {
978 ERR("Failed to create kprobe event rule.");
979 goto error;
980 }
981
982 event_rule_status = lttng_event_rule_kernel_probe_set_event_name(res.er, tracepoint_name);
983 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
984 ERR("Failed to set kprobe event rule's name to '%s'.", tracepoint_name);
985 goto error;
986 }
987
988 break;
989 }
990 case LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE:
991 {
992 int ret;
993 enum lttng_event_rule_status event_rule_status;
994
995 ret = parse_userspace_probe_opts(
996 source, &userspace_probe_location);
997 if (ret) {
998 ERR("Failed to parse user space probe location.");
999 goto error;
1000 }
1001
1002 res.er = lttng_event_rule_userspace_probe_create(userspace_probe_location);
1003 if (!res.er) {
1004 ERR("Failed to create userspace probe event rule.");
1005 goto error;
1006 }
1007
1008 event_rule_status = lttng_event_rule_userspace_probe_set_event_name(
1009 res.er, tracepoint_name);
1010 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1011 ERR("Failed to set user space probe event rule's name to '%s'.",
1012 tracepoint_name);
1013 goto error;
1014 }
1015
1016 break;
1017 }
1018 case LTTNG_EVENT_RULE_TYPE_SYSCALL:
1019 {
1020 enum lttng_event_rule_status event_rule_status;
1021
1022 res.er = lttng_event_rule_syscall_create();
1023 if (!res.er) {
1024 ERR("Failed to create syscall event rule.");
1025 goto error;
1026 }
1027
1028 event_rule_status = lttng_event_rule_syscall_set_pattern(
1029 res.er, tracepoint_name);
1030 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1031 ERR("Failed to set syscall event rule's pattern to '%s'.",
1032 tracepoint_name);
1033 goto error;
1034 }
1035
1036 if (filter) {
1037 event_rule_status = lttng_event_rule_syscall_set_filter(
1038 res.er, filter);
1039 if (event_rule_status != LTTNG_EVENT_RULE_STATUS_OK) {
1040 ERR("Failed to set syscall event rule's filter to '%s'.",
1041 filter);
1042 goto error;
1043 }
1044 }
1045
1046 break;
1047 }
1048 default:
1049 abort();
1050 goto error;
1051 }
1052
1053 goto end;
1054
1055 error:
1056 lttng_event_rule_destroy(res.er);
1057 res.er = NULL;
1058 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1059
1060 end:
1061 if (parser_ctx) {
1062 filter_parser_ctx_free(parser_ctx);
1063 }
1064
1065 lttng_event_expr_destroy(event_expr);
1066 argpar_item_destroy(item);
1067 free(error);
1068 argpar_state_destroy(state);
1069 free(filter);
1070 free(exclude);
1071 free(loglevel_str);
1072 free(source);
1073 strutils_free_null_terminated_array_of_strings(exclusion_list);
1074 lttng_kernel_probe_location_destroy(kernel_probe_location);
1075 lttng_userspace_probe_location_destroy(userspace_probe_location);
1076 lttng_log_level_rule_destroy(log_level_rule);
1077 return res;
1078 }
1079
1080 static
1081 struct lttng_condition *handle_condition_event(int *argc, const char ***argv)
1082 {
1083 struct parse_event_rule_res res;
1084 struct lttng_condition *c;
1085 size_t i;
1086
1087 res = parse_event_rule(argc, argv);
1088 if (!res.er) {
1089 c = NULL;
1090 goto error;
1091 }
1092
1093 c = lttng_condition_on_event_create(res.er);
1094 lttng_event_rule_destroy(res.er);
1095 res.er = NULL;
1096 if (!c) {
1097 goto error;
1098 }
1099
1100 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&res.capture_descriptors);
1101 i++) {
1102 enum lttng_condition_status status;
1103 struct lttng_event_expr **expr =
1104 lttng_dynamic_array_get_element(
1105 &res.capture_descriptors.array, i);
1106
1107 assert(expr);
1108 assert(*expr);
1109 status = lttng_condition_on_event_append_capture_descriptor(
1110 c, *expr);
1111 if (status != LTTNG_CONDITION_STATUS_OK) {
1112 if (status == LTTNG_CONDITION_STATUS_UNSUPPORTED) {
1113 ERR("The capture feature is unsupported by the event-rule condition type");
1114 }
1115
1116 goto error;
1117 }
1118
1119 /* Ownership of event expression moved to `c` */
1120 *expr = NULL;
1121 }
1122
1123 goto end;
1124
1125 error:
1126 lttng_condition_destroy(c);
1127 c = NULL;
1128
1129 end:
1130 lttng_dynamic_pointer_array_reset(&res.capture_descriptors);
1131 lttng_event_rule_destroy(res.er);
1132 return c;
1133 }
1134
1135 static
1136 struct lttng_condition *handle_condition_session_consumed_size(int *argc, const char ***argv)
1137 {
1138 struct lttng_condition *cond = NULL;
1139 struct argpar_state *state = NULL;
1140 struct argpar_item *item = NULL;
1141 const char *threshold_arg = NULL;
1142 const char *session_name_arg = NULL;
1143 uint64_t threshold;
1144 char *error = NULL;
1145 enum lttng_condition_status condition_status;
1146
1147 state = argpar_state_create(*argc, *argv, event_rule_opt_descrs);
1148 if (!state) {
1149 ERR("Failed to allocate an argpar state.");
1150 goto error;
1151 }
1152
1153 while (true) {
1154 enum argpar_state_parse_next_status status;
1155
1156 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1157 status = argpar_state_parse_next(state, &item, &error);
1158 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1159 ERR("%s", error);
1160 goto error;
1161 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1162 /* Just stop parsing here. */
1163 break;
1164 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1165 break;
1166 }
1167
1168 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1169
1170 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1171 const struct argpar_item_opt *item_opt =
1172 (const struct argpar_item_opt *) item;
1173
1174 switch (item_opt->descr->id) {
1175 default:
1176 abort();
1177 }
1178 } else {
1179 const struct argpar_item_non_opt *item_non_opt;
1180
1181 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1182
1183 item_non_opt = (const struct argpar_item_non_opt *) item;
1184
1185 switch (item_non_opt->non_opt_index) {
1186 case 0:
1187 session_name_arg = item_non_opt->arg;
1188 break;
1189 case 1:
1190 threshold_arg = item_non_opt->arg;
1191 break;
1192 default:
1193 ERR("Unexpected argument `%s`.",
1194 item_non_opt->arg);
1195 goto error;
1196 }
1197 }
1198 }
1199
1200 *argc -= argpar_state_get_ingested_orig_args(state);
1201 *argv += argpar_state_get_ingested_orig_args(state);
1202
1203 if (!session_name_arg) {
1204 ERR("Missing session name argument.");
1205 goto error;
1206 }
1207
1208 if (!threshold_arg) {
1209 ERR("Missing threshold argument.");
1210 goto error;
1211 }
1212
1213 if (utils_parse_size_suffix(threshold_arg, &threshold) != 0) {
1214 ERR("Failed to parse `%s` as a size.", threshold_arg);
1215 goto error;
1216 }
1217
1218 cond = lttng_condition_session_consumed_size_create();
1219 if (!cond) {
1220 ERR("Failed to allocate a session consumed size condition.");
1221 goto error;
1222 }
1223
1224 condition_status = lttng_condition_session_consumed_size_set_session_name(
1225 cond, session_name_arg);
1226 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1227 ERR("Failed to set session consumed size condition's session name to '%s'.",
1228 session_name_arg);
1229 goto error;
1230 }
1231
1232 condition_status = lttng_condition_session_consumed_size_set_threshold(
1233 cond, threshold);
1234 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1235 ERR("Failed to set session consumed size condition threshold.");
1236 goto error;
1237 }
1238
1239 goto end;
1240
1241 error:
1242 lttng_condition_destroy(cond);
1243 cond = NULL;
1244
1245 end:
1246 argpar_state_destroy(state);
1247 argpar_item_destroy(item);
1248 free(error);
1249 return cond;
1250 }
1251
1252 static
1253 struct lttng_condition *handle_condition_buffer_usage_high(int *argc, const char ***argv)
1254 {
1255 ERR("High buffer usage threshold conditions are unsupported for the moment.");
1256 return NULL;
1257 }
1258
1259 static
1260 struct lttng_condition *handle_condition_buffer_usage_low(int *argc, const char ***argv)
1261 {
1262 ERR("Low buffer usage threshold conditions are unsupported for the moment.");
1263 return NULL;
1264 }
1265
1266 static
1267 struct lttng_condition *handle_condition_session_rotation_ongoing(int *argc, const char ***argv)
1268 {
1269 ERR("Session rotation ongoing conditions are unsupported for the moment.");
1270 return NULL;
1271 }
1272
1273 static
1274 struct lttng_condition *handle_condition_session_rotation_completed(int *argc, const char ***argv)
1275 {
1276 ERR("Session rotation completed conditions are unsupported for the moment.");
1277 return NULL;
1278 }
1279
1280 struct condition_descr {
1281 const char *name;
1282 struct lttng_condition *(*handler) (int *argc, const char ***argv);
1283 };
1284
1285 static const
1286 struct condition_descr condition_descrs[] = {
1287 { "on-event", handle_condition_event },
1288 { "on-session-consumed-size", handle_condition_session_consumed_size },
1289 { "on-buffer-usage-high", handle_condition_buffer_usage_high },
1290 { "on-buffer-usage-low", handle_condition_buffer_usage_low },
1291 { "on-session-rotation-ongoing", handle_condition_session_rotation_ongoing },
1292 { "on-session-rotation-completed", handle_condition_session_rotation_completed },
1293 };
1294
1295 static
1296 struct lttng_condition *parse_condition(int *argc, const char ***argv)
1297 {
1298 int i;
1299 struct lttng_condition *cond;
1300 const char *condition_name;
1301 const struct condition_descr *descr = NULL;
1302
1303 if (*argc == 0) {
1304 ERR("Missing condition name.");
1305 goto error;
1306 }
1307
1308 condition_name = (*argv)[0];
1309
1310 (*argc)--;
1311 (*argv)++;
1312
1313 for (i = 0; i < ARRAY_SIZE(condition_descrs); i++) {
1314 if (strcmp(condition_name, condition_descrs[i].name) == 0) {
1315 descr = &condition_descrs[i];
1316 break;
1317 }
1318 }
1319
1320 if (!descr) {
1321 ERR("Unknown condition name '%s'", condition_name);
1322 goto error;
1323 }
1324
1325 cond = descr->handler(argc, argv);
1326 if (!cond) {
1327 /* The handler has already printed an error message. */
1328 goto error;
1329 }
1330
1331 goto end;
1332 error:
1333 cond = NULL;
1334 end:
1335 return cond;
1336 }
1337
1338 static struct lttng_rate_policy *parse_rate_policy(const char *policy_str)
1339 {
1340 int num_token;
1341 char **tokens = NULL;
1342 struct lttng_rate_policy *policy = NULL;
1343 enum lttng_rate_policy_type policy_type;
1344 unsigned long long value;
1345 char *policy_type_str;
1346 char *policy_value_str;
1347
1348 assert(policy_str);
1349
1350 /*
1351 * rate policy fields are separated by ':'.
1352 */
1353 tokens = strutils_split(policy_str, ':', 1);
1354 num_token = strutils_array_of_strings_len(tokens);
1355
1356 /*
1357 * Early sanity check that the number of parameter is exactly 2.
1358 * i.e : type:value
1359 */
1360 if (num_token != 2) {
1361 ERR("Rate policy format is invalid.");
1362 goto end;
1363 }
1364
1365 policy_type_str = tokens[0];
1366 policy_value_str = tokens[1];
1367
1368 /* Parse the type. */
1369 if (strcmp(policy_type_str, "once-after") == 0) {
1370 policy_type = LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N;
1371 } else if (strcmp(policy_type_str, "every") == 0) {
1372 policy_type = LTTNG_RATE_POLICY_TYPE_EVERY_N;
1373 } else {
1374 ERR("Rate policy type `%s` unknown.", policy_type_str);
1375 goto end;
1376 }
1377
1378 /* Parse the value. */
1379 if (utils_parse_unsigned_long_long(policy_value_str, &value) != 0) {
1380 ERR("Failed to parse rate policy value `%s` as an integer.",
1381 policy_value_str);
1382 goto end;
1383 }
1384
1385 if (value == 0) {
1386 ERR("Rate policy value `%s` must be > 0.", policy_value_str);
1387 goto end;
1388 }
1389
1390 switch (policy_type) {
1391 case LTTNG_RATE_POLICY_TYPE_EVERY_N:
1392 policy = lttng_rate_policy_every_n_create(value);
1393 break;
1394 case LTTNG_RATE_POLICY_TYPE_ONCE_AFTER_N:
1395 policy = lttng_rate_policy_once_after_n_create(value);
1396 break;
1397 default:
1398 abort();
1399 }
1400
1401 if (policy == NULL) {
1402 ERR("Failed to create rate policy `%s`.", policy_str);
1403 }
1404
1405 end:
1406 strutils_free_null_terminated_array_of_strings(tokens);
1407 return policy;
1408 }
1409
1410 static const struct argpar_opt_descr notify_action_opt_descrs[] = {
1411 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1412 ARGPAR_OPT_DESCR_SENTINEL
1413 };
1414
1415 static
1416 struct lttng_action *handle_action_notify(int *argc, const char ***argv)
1417 {
1418 struct lttng_action *action = NULL;
1419 struct argpar_state *state = NULL;
1420 struct argpar_item *item = NULL;
1421 char *error = NULL;
1422 struct lttng_rate_policy *policy = NULL;
1423
1424 state = argpar_state_create(*argc, *argv, notify_action_opt_descrs);
1425 if (!state) {
1426 ERR("Failed to allocate an argpar state.");
1427 goto error;
1428 }
1429
1430 while (true) {
1431 enum argpar_state_parse_next_status status;
1432
1433 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1434 status = argpar_state_parse_next(state, &item, &error);
1435 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1436 ERR("%s", error);
1437 goto error;
1438 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1439 /* Just stop parsing here. */
1440 break;
1441 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1442 break;
1443 }
1444
1445 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1446
1447 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1448 const struct argpar_item_opt *item_opt =
1449 (const struct argpar_item_opt *) item;
1450
1451 switch (item_opt->descr->id) {
1452 case OPT_RATE_POLICY:
1453 {
1454 policy = parse_rate_policy(item_opt->arg);
1455 if (!policy) {
1456 goto error;
1457 }
1458 break;
1459 }
1460 default:
1461 abort();
1462 }
1463 } else {
1464 const struct argpar_item_non_opt *item_non_opt;
1465
1466 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1467
1468 item_non_opt = (const struct argpar_item_non_opt *) item;
1469
1470 switch (item_non_opt->non_opt_index) {
1471 default:
1472 ERR("Unexpected argument `%s`.",
1473 item_non_opt->arg);
1474 goto error;
1475 }
1476 }
1477 }
1478
1479 *argc -= argpar_state_get_ingested_orig_args(state);
1480 *argv += argpar_state_get_ingested_orig_args(state);
1481
1482 action = lttng_action_notify_create();
1483 if (!action) {
1484 ERR("Failed to create notify action");
1485 goto error;
1486 }
1487
1488 if (policy) {
1489 enum lttng_action_status status;
1490 status = lttng_action_notify_set_rate_policy(action, policy);
1491 if (status != LTTNG_ACTION_STATUS_OK) {
1492 ERR("Failed to set rate policy");
1493 goto error;
1494 }
1495 }
1496
1497 goto end;
1498
1499 error:
1500 lttng_action_destroy(action);
1501 action = NULL;
1502 end:
1503 free(error);
1504 lttng_rate_policy_destroy(policy);
1505 argpar_state_destroy(state);
1506 argpar_item_destroy(item);
1507 return action;
1508 }
1509
1510 /*
1511 * Generic handler for a kind of action that takes a session name and an
1512 * optional rate policy.
1513 */
1514
1515 static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
1516 const char ***argv,
1517 struct lttng_action *(*create_action_cb)(void),
1518 enum lttng_action_status (*set_session_name_cb)(
1519 struct lttng_action *, const char *),
1520 enum lttng_action_status (*set_rate_policy_cb)(
1521 struct lttng_action *,
1522 const struct lttng_rate_policy *),
1523 const char *action_name)
1524 {
1525 struct lttng_action *action = NULL;
1526 struct argpar_state *state = NULL;
1527 struct argpar_item *item = NULL;
1528 const char *session_name_arg = NULL;
1529 char *error = NULL;
1530 enum lttng_action_status action_status;
1531 struct lttng_rate_policy *policy = NULL;
1532
1533 assert(set_session_name_cb);
1534 assert(set_rate_policy_cb);
1535
1536 const struct argpar_opt_descr rate_policy_opt_descrs[] = {
1537 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1538 ARGPAR_OPT_DESCR_SENTINEL
1539 };
1540
1541 state = argpar_state_create(*argc, *argv, rate_policy_opt_descrs);
1542 if (!state) {
1543 ERR("Failed to allocate an argpar state.");
1544 goto error;
1545 }
1546
1547 while (true) {
1548 enum argpar_state_parse_next_status status;
1549
1550 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1551 status = argpar_state_parse_next(state, &item, &error);
1552 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1553 ERR("%s", error);
1554 goto error;
1555 } else if (status ==
1556 ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1557 /* Just stop parsing here. */
1558 break;
1559 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1560 break;
1561 }
1562
1563 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1564 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1565 const struct argpar_item_opt *item_opt =
1566 (const struct argpar_item_opt *) item;
1567
1568 switch (item_opt->descr->id) {
1569 case OPT_RATE_POLICY:
1570 {
1571 policy = parse_rate_policy(item_opt->arg);
1572 if (!policy) {
1573 goto error;
1574 }
1575 break;
1576 }
1577 default:
1578 abort();
1579 }
1580 } else {
1581 const struct argpar_item_non_opt *item_non_opt;
1582 item_non_opt = (const struct argpar_item_non_opt *) item;
1583
1584 switch (item_non_opt->non_opt_index) {
1585 case 0:
1586 session_name_arg = item_non_opt->arg;
1587 break;
1588 default:
1589 ERR("Unexpected argument `%s`.",
1590 item_non_opt->arg);
1591 goto error;
1592 }
1593 }
1594 }
1595
1596 *argc -= argpar_state_get_ingested_orig_args(state);
1597 *argv += argpar_state_get_ingested_orig_args(state);
1598
1599 if (!session_name_arg) {
1600 ERR("Missing session name.");
1601 goto error;
1602 }
1603
1604 action = create_action_cb();
1605 if (!action) {
1606 ERR("Failed to allocate %s session action.", action_name);
1607 goto error;
1608 }
1609
1610 action_status = set_session_name_cb(action, session_name_arg);
1611 if (action_status != LTTNG_ACTION_STATUS_OK) {
1612 ERR("Failed to set action %s session's session name to '%s'.",
1613 action_name, session_name_arg);
1614 goto error;
1615 }
1616
1617 if (policy) {
1618 action_status = set_rate_policy_cb(action, policy);
1619 if (action_status != LTTNG_ACTION_STATUS_OK) {
1620 ERR("Failed to set rate policy");
1621 goto error;
1622 }
1623 }
1624
1625 goto end;
1626
1627 error:
1628 lttng_action_destroy(action);
1629 action = NULL;
1630 argpar_item_destroy(item);
1631 end:
1632 lttng_rate_policy_destroy(policy);
1633 free(error);
1634 argpar_state_destroy(state);
1635 return action;
1636 }
1637
1638 static
1639 struct lttng_action *handle_action_start_session(int *argc,
1640 const char ***argv)
1641 {
1642 return handle_action_simple_session_with_policy(argc, argv,
1643 lttng_action_start_session_create,
1644 lttng_action_start_session_set_session_name,
1645 lttng_action_start_session_set_rate_policy, "start");
1646 }
1647
1648 static
1649 struct lttng_action *handle_action_stop_session(int *argc,
1650 const char ***argv)
1651 {
1652 return handle_action_simple_session_with_policy(argc, argv,
1653 lttng_action_stop_session_create,
1654 lttng_action_stop_session_set_session_name,
1655 lttng_action_stop_session_set_rate_policy, "stop");
1656 }
1657
1658 static
1659 struct lttng_action *handle_action_rotate_session(int *argc,
1660 const char ***argv)
1661 {
1662 return handle_action_simple_session_with_policy(argc, argv,
1663 lttng_action_rotate_session_create,
1664 lttng_action_rotate_session_set_session_name,
1665 lttng_action_rotate_session_set_rate_policy,
1666 "rotate");
1667 }
1668
1669 static const struct argpar_opt_descr snapshot_action_opt_descrs[] = {
1670 { OPT_NAME, 'n', "name", true },
1671 { OPT_MAX_SIZE, 'm', "max-size", true },
1672 { OPT_CTRL_URL, '\0', "ctrl-url", true },
1673 { OPT_DATA_URL, '\0', "data-url", true },
1674 { OPT_URL, '\0', "url", true },
1675 { OPT_PATH, '\0', "path", true },
1676 { OPT_RATE_POLICY, '\0', "rate-policy", true },
1677 ARGPAR_OPT_DESCR_SENTINEL
1678 };
1679
1680 static
1681 struct lttng_action *handle_action_snapshot_session(int *argc,
1682 const char ***argv)
1683 {
1684 struct lttng_action *action = NULL;
1685 struct argpar_state *state = NULL;
1686 struct argpar_item *item = NULL;
1687 const char *session_name_arg = NULL;
1688 char *snapshot_name_arg = NULL;
1689 char *ctrl_url_arg = NULL;
1690 char *data_url_arg = NULL;
1691 char *max_size_arg = NULL;
1692 char *url_arg = NULL;
1693 char *path_arg = NULL;
1694 char *error = NULL;
1695 enum lttng_action_status action_status;
1696 struct lttng_snapshot_output *snapshot_output = NULL;
1697 struct lttng_rate_policy *policy = NULL;
1698 int ret;
1699 unsigned int locations_specified = 0;
1700
1701 state = argpar_state_create(*argc, *argv, snapshot_action_opt_descrs);
1702 if (!state) {
1703 ERR("Failed to allocate an argpar state.");
1704 goto error;
1705 }
1706
1707 while (true) {
1708 enum argpar_state_parse_next_status status;
1709
1710 ARGPAR_ITEM_DESTROY_AND_RESET(item);
1711 status = argpar_state_parse_next(state, &item, &error);
1712 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
1713 ERR("%s", error);
1714 goto error;
1715 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
1716 /* Just stop parsing here. */
1717 break;
1718 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
1719 break;
1720 }
1721
1722 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
1723
1724 if (item->type == ARGPAR_ITEM_TYPE_OPT) {
1725 const struct argpar_item_opt *item_opt =
1726 (const struct argpar_item_opt *) item;
1727
1728 switch (item_opt->descr->id) {
1729 case OPT_NAME:
1730 if (!assign_string(&snapshot_name_arg, item_opt->arg, "--name/-n")) {
1731 goto error;
1732 }
1733
1734 break;
1735 case OPT_MAX_SIZE:
1736 if (!assign_string(&max_size_arg, item_opt->arg, "--max-size/-m")) {
1737 goto error;
1738 }
1739
1740 break;
1741 case OPT_CTRL_URL:
1742 if (!assign_string(&ctrl_url_arg, item_opt->arg, "--ctrl-url")) {
1743 goto error;
1744 }
1745
1746 break;
1747 case OPT_DATA_URL:
1748 if (!assign_string(&data_url_arg, item_opt->arg, "--data-url")) {
1749 goto error;
1750 }
1751
1752 break;
1753 case OPT_URL:
1754 if (!assign_string(&url_arg, item_opt->arg, "--url")) {
1755 goto error;
1756 }
1757
1758 break;
1759 case OPT_PATH:
1760 if (!assign_string(&path_arg, item_opt->arg, "--path")) {
1761 goto error;
1762 }
1763
1764 break;
1765 case OPT_RATE_POLICY:
1766 {
1767 policy = parse_rate_policy(item_opt->arg);
1768 if (!policy) {
1769 goto error;
1770 }
1771 break;
1772 }
1773 default:
1774 abort();
1775 }
1776 } else {
1777 const struct argpar_item_non_opt *item_non_opt;
1778
1779 assert(item->type == ARGPAR_ITEM_TYPE_NON_OPT);
1780
1781 item_non_opt = (const struct argpar_item_non_opt *) item;
1782
1783 switch (item_non_opt->non_opt_index) {
1784 case 0:
1785 session_name_arg = item_non_opt->arg;
1786 break;
1787 default:
1788 ERR("Unexpected argument `%s`.",
1789 item_non_opt->arg);
1790 goto error;
1791 }
1792 }
1793 }
1794
1795 *argc -= argpar_state_get_ingested_orig_args(state);
1796 *argv += argpar_state_get_ingested_orig_args(state);
1797
1798 if (!session_name_arg) {
1799 ERR("Missing session name.");
1800 goto error;
1801 }
1802
1803 /* --ctrl-url and --data-url must come in pair. */
1804 if (ctrl_url_arg && !data_url_arg) {
1805 ERR("--ctrl-url is specified, but --data-url is missing.");
1806 goto error;
1807 }
1808
1809 if (!ctrl_url_arg && data_url_arg) {
1810 ERR("--data-url is specified, but --ctrl-url is missing.");
1811 goto error;
1812 }
1813
1814 locations_specified += !!(ctrl_url_arg || data_url_arg);
1815 locations_specified += !!url_arg;
1816 locations_specified += !!path_arg;
1817
1818 /* --ctrl-url/--data-url, --url and --path are mutually exclusive. */
1819 if (locations_specified > 1) {
1820 ERR("The --ctrl-url/--data-url, --url, and --path options can't be used together.");
1821 goto error;
1822 }
1823
1824 /*
1825 * Did the user specify an option that implies using a
1826 * custom/unregistered output?
1827 */
1828 if (url_arg || ctrl_url_arg || path_arg) {
1829 snapshot_output = lttng_snapshot_output_create();
1830 if (!snapshot_output) {
1831 ERR("Failed to allocate a snapshot output.");
1832 goto error;
1833 }
1834 }
1835
1836 action = lttng_action_snapshot_session_create();
1837 if (!action) {
1838 ERR("Failed to allocate snapshot session action.");
1839 goto error;
1840 }
1841
1842 action_status = lttng_action_snapshot_session_set_session_name(
1843 action, session_name_arg);
1844 if (action_status != LTTNG_ACTION_STATUS_OK) {
1845 ERR("Failed to set action snapshot session's session name to '%s'.",
1846 session_name_arg);
1847 goto error;
1848 }
1849
1850 if (snapshot_name_arg) {
1851 if (!snapshot_output) {
1852 ERR("Can't provide a snapshot output name without a snapshot output destination.");
1853 goto error;
1854 }
1855
1856 ret = lttng_snapshot_output_set_name(
1857 snapshot_name_arg, snapshot_output);
1858 if (ret != 0) {
1859 ERR("Failed to set name of snapshot output.");
1860 goto error;
1861 }
1862 }
1863
1864 if (max_size_arg) {
1865 uint64_t max_size;
1866
1867 if (!snapshot_output) {
1868 ERR("Can't provide a snapshot output max size without a snapshot output destination.");
1869 goto error;
1870 }
1871
1872 ret = utils_parse_size_suffix(max_size_arg, &max_size);
1873 if (ret != 0) {
1874 ERR("Failed to parse `%s` as a size.", max_size_arg);
1875 goto error;
1876 }
1877
1878 ret = lttng_snapshot_output_set_size(max_size, snapshot_output);
1879 if (ret != 0) {
1880 ERR("Failed to set snapshot output's max size to %" PRIu64 " bytes.",
1881 max_size);
1882 goto error;
1883 }
1884 }
1885
1886 if (url_arg) {
1887 int num_uris;
1888 struct lttng_uri *uris;
1889
1890 if (!strstr(url_arg, "://")) {
1891 ERR("Failed to parse '%s' as an URL.", url_arg);
1892 goto error;
1893 }
1894
1895 num_uris = uri_parse_str_urls(url_arg, NULL, &uris);
1896 if (num_uris < 1) {
1897 ERR("Failed to parse '%s' as an URL.", url_arg);
1898 goto error;
1899 }
1900
1901 if (uris[0].dtype == LTTNG_DST_PATH) {
1902 ret = lttng_snapshot_output_set_local_path(
1903 uris[0].dst.path, snapshot_output);
1904 free(uris);
1905 if (ret != 0) {
1906 ERR("Failed to assign '%s' as a local destination.",
1907 url_arg);
1908 goto error;
1909 }
1910 } else {
1911 ret = lttng_snapshot_output_set_network_url(
1912 url_arg, snapshot_output);
1913 free(uris);
1914 if (ret != 0) {
1915 ERR("Failed to assign '%s' as a network URL.",
1916 url_arg);
1917 goto error;
1918 }
1919 }
1920 }
1921
1922 if (path_arg) {
1923 ret = lttng_snapshot_output_set_local_path(
1924 path_arg, snapshot_output);
1925 if (ret != 0) {
1926 ERR("Failed to parse '%s' as a local path.", path_arg);
1927 goto error;
1928 }
1929 }
1930
1931 if (ctrl_url_arg) {
1932 /*
1933 * Two argument form, network output with separate control and
1934 * data URLs.
1935 */
1936 ret = lttng_snapshot_output_set_network_urls(
1937 ctrl_url_arg, data_url_arg, snapshot_output);
1938 if (ret != 0) {
1939 ERR("Failed to parse `%s` and `%s` as control and data URLs.",
1940 ctrl_url_arg, data_url_arg);
1941 goto error;
1942 }
1943 }
1944
1945 if (snapshot_output) {
1946 action_status = lttng_action_snapshot_session_set_output(
1947 action, snapshot_output);
1948 if (action_status != LTTNG_ACTION_STATUS_OK) {
1949 ERR("Failed to set snapshot session action's output.");
1950 goto error;
1951 }
1952
1953 /* Ownership of `snapshot_output` has been transferred to the action. */
1954 snapshot_output = NULL;
1955 }
1956
1957 if (policy) {
1958 enum lttng_action_status status;
1959 status = lttng_action_snapshot_session_set_rate_policy(
1960 action, policy);
1961 if (status != LTTNG_ACTION_STATUS_OK) {
1962 ERR("Failed to set rate policy");
1963 goto error;
1964 }
1965 }
1966
1967 goto end;
1968
1969 error:
1970 lttng_action_destroy(action);
1971 action = NULL;
1972 free(error);
1973 end:
1974 free(snapshot_name_arg);
1975 free(path_arg);
1976 free(url_arg);
1977 free(ctrl_url_arg);
1978 free(data_url_arg);
1979 free(snapshot_output);
1980 free(max_size_arg);
1981 lttng_rate_policy_destroy(policy);
1982 argpar_state_destroy(state);
1983 argpar_item_destroy(item);
1984 return action;
1985 }
1986
1987 struct action_descr {
1988 const char *name;
1989 struct lttng_action *(*handler) (int *argc, const char ***argv);
1990 };
1991
1992 static const
1993 struct action_descr action_descrs[] = {
1994 { "notify", handle_action_notify },
1995 { "start-session", handle_action_start_session },
1996 { "stop-session", handle_action_stop_session },
1997 { "rotate-session", handle_action_rotate_session },
1998 { "snapshot-session", handle_action_snapshot_session },
1999 };
2000
2001 static
2002 struct lttng_action *parse_action(int *argc, const char ***argv)
2003 {
2004 int i;
2005 struct lttng_action *action;
2006 const char *action_name;
2007 const struct action_descr *descr = NULL;
2008
2009 if (*argc == 0) {
2010 ERR("Missing action name.");
2011 goto error;
2012 }
2013
2014 action_name = (*argv)[0];
2015
2016 (*argc)--;
2017 (*argv)++;
2018
2019 for (i = 0; i < ARRAY_SIZE(action_descrs); i++) {
2020 if (strcmp(action_name, action_descrs[i].name) == 0) {
2021 descr = &action_descrs[i];
2022 break;
2023 }
2024 }
2025
2026 if (!descr) {
2027 ERR("Unknown action name: %s", action_name);
2028 goto error;
2029 }
2030
2031 action = descr->handler(argc, argv);
2032 if (!action) {
2033 /* The handler has already printed an error message. */
2034 goto error;
2035 }
2036
2037 goto end;
2038 error:
2039 action = NULL;
2040 end:
2041 return action;
2042 }
2043
2044 static const
2045 struct argpar_opt_descr add_trigger_options[] = {
2046 { OPT_HELP, 'h', "help", false },
2047 { OPT_LIST_OPTIONS, '\0', "list-options", false },
2048 { OPT_CONDITION, '\0', "condition", false },
2049 { OPT_ACTION, '\0', "action", false },
2050 { OPT_ID, '\0', "id", true },
2051 { OPT_USER_ID, '\0', "user-id", true },
2052 ARGPAR_OPT_DESCR_SENTINEL,
2053 };
2054
2055 static
2056 void lttng_actions_destructor(void *p)
2057 {
2058 struct lttng_action *action = p;
2059
2060 lttng_action_destroy(action);
2061 }
2062
2063 int cmd_add_trigger(int argc, const char **argv)
2064 {
2065 int ret;
2066 int my_argc = argc - 1;
2067 const char **my_argv = argv + 1;
2068 struct lttng_condition *condition = NULL;
2069 struct lttng_dynamic_pointer_array actions;
2070 struct argpar_state *argpar_state = NULL;
2071 struct argpar_item *argpar_item = NULL;
2072 struct lttng_action *action_group = NULL;
2073 struct lttng_action *action = NULL;
2074 struct lttng_trigger *trigger = NULL;
2075 char *error = NULL;
2076 char *id = NULL;
2077 int i;
2078 char *user_id = NULL;
2079
2080 lttng_dynamic_pointer_array_init(&actions, lttng_actions_destructor);
2081
2082 while (true) {
2083 enum argpar_state_parse_next_status status;
2084 const struct argpar_item_opt *item_opt;
2085 int ingested_args;
2086
2087 argpar_state_destroy(argpar_state);
2088 argpar_state = argpar_state_create(my_argc, my_argv,
2089 add_trigger_options);
2090 if (!argpar_state) {
2091 ERR("Failed to create argpar state.");
2092 goto error;
2093 }
2094
2095 ARGPAR_ITEM_DESTROY_AND_RESET(argpar_item);
2096 status = argpar_state_parse_next(argpar_state, &argpar_item, &error);
2097 if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR) {
2098 ERR("%s", error);
2099 goto error;
2100 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
2101 ERR("%s", error);
2102 goto error;
2103 } else if (status == ARGPAR_STATE_PARSE_NEXT_STATUS_END) {
2104 break;
2105 }
2106
2107 assert(status == ARGPAR_STATE_PARSE_NEXT_STATUS_OK);
2108
2109 if (argpar_item->type == ARGPAR_ITEM_TYPE_NON_OPT) {
2110 const struct argpar_item_non_opt *item_non_opt =
2111 (const struct argpar_item_non_opt *)
2112 argpar_item;
2113
2114 ERR("Unexpected argument `%s`.", item_non_opt->arg);
2115 goto error;
2116 }
2117
2118 item_opt = (const struct argpar_item_opt *) argpar_item;
2119
2120 ingested_args = argpar_state_get_ingested_orig_args(
2121 argpar_state);
2122
2123 my_argc -= ingested_args;
2124 my_argv += ingested_args;
2125
2126 switch (item_opt->descr->id) {
2127 case OPT_HELP:
2128 SHOW_HELP();
2129 ret = 0;
2130 goto end;
2131 case OPT_LIST_OPTIONS:
2132 list_cmd_options_argpar(stdout, add_trigger_options);
2133 ret = 0;
2134 goto end;
2135 case OPT_CONDITION:
2136 {
2137 if (condition) {
2138 ERR("A --condition was already given.");
2139 goto error;
2140 }
2141
2142 condition = parse_condition(&my_argc, &my_argv);
2143 if (!condition) {
2144 /*
2145 * An error message was already printed by
2146 * parse_condition.
2147 */
2148 goto error;
2149 }
2150
2151 break;
2152 }
2153 case OPT_ACTION:
2154 {
2155 action = parse_action(&my_argc, &my_argv);
2156 if (!action) {
2157 /*
2158 * An error message was already printed by
2159 * parse_condition.
2160 */
2161 goto error;
2162 }
2163
2164 ret = lttng_dynamic_pointer_array_add_pointer(
2165 &actions, action);
2166 if (ret) {
2167 ERR("Failed to add pointer to pointer array.");
2168 goto error;
2169 }
2170
2171 /* Ownership of the action was transferred to the group. */
2172 action = NULL;
2173
2174 break;
2175 }
2176 case OPT_ID:
2177 {
2178 if (!assign_string(&id, item_opt->arg, "--id")) {
2179 goto error;
2180 }
2181
2182 break;
2183 }
2184 case OPT_USER_ID:
2185 {
2186 if (!assign_string(&user_id, item_opt->arg,
2187 "--user-id")) {
2188 goto error;
2189 }
2190
2191 break;
2192 }
2193 default:
2194 abort();
2195 }
2196 }
2197
2198 if (!condition) {
2199 ERR("Missing --condition.");
2200 goto error;
2201 }
2202
2203 if (lttng_dynamic_pointer_array_get_count(&actions) == 0) {
2204 ERR("Need at least one --action.");
2205 goto error;
2206 }
2207
2208 action_group = lttng_action_group_create();
2209 if (!action_group) {
2210 goto error;
2211 }
2212
2213 for (i = 0; i < lttng_dynamic_pointer_array_get_count(&actions); i++) {
2214 enum lttng_action_status status;
2215
2216 action = lttng_dynamic_pointer_array_steal_pointer(&actions, i);
2217
2218 status = lttng_action_group_add_action(action_group, action);
2219 if (status != LTTNG_ACTION_STATUS_OK) {
2220 goto error;
2221 }
2222
2223 /*
2224 * The `lttng_action_group_add_action()` takes a reference to
2225 * the action. We can destroy ours.
2226 */
2227 lttng_action_destroy(action);
2228 action = NULL;
2229 }
2230
2231 trigger = lttng_trigger_create(condition, action_group);
2232 if (!trigger) {
2233 goto error;
2234 }
2235
2236 if (id) {
2237 enum lttng_trigger_status trigger_status =
2238 lttng_trigger_set_name(trigger, id);
2239
2240 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2241 ERR("Failed to set trigger id.");
2242 goto error;
2243 }
2244 }
2245
2246 if (user_id) {
2247 enum lttng_trigger_status trigger_status;
2248 char *end;
2249 long long uid;
2250
2251 errno = 0;
2252 uid = strtol(user_id, &end, 10);
2253 if (end == user_id || *end != '\0' || errno != 0) {
2254 ERR("Failed to parse `%s` as a user id.", user_id);
2255 }
2256
2257 trigger_status = lttng_trigger_set_owner_uid(trigger, uid);
2258 if (trigger_status != LTTNG_TRIGGER_STATUS_OK) {
2259 ERR("Failed to set trigger's user identity.");
2260 goto error;
2261 }
2262 }
2263
2264 ret = lttng_register_trigger(trigger);
2265 if (ret) {
2266 ERR("Failed to register trigger: %s.", lttng_strerror(ret));
2267 goto error;
2268 }
2269
2270 MSG("Trigger registered successfully.");
2271
2272 goto end;
2273
2274 error:
2275 ret = 1;
2276
2277 end:
2278 argpar_state_destroy(argpar_state);
2279 argpar_item_destroy(argpar_item);
2280 lttng_dynamic_pointer_array_reset(&actions);
2281 lttng_condition_destroy(condition);
2282 lttng_action_destroy(action_group);
2283 lttng_action_destroy(action);
2284 lttng_trigger_destroy(trigger);
2285 free(error);
2286 free(id);
2287 free(user_id);
2288 return ret;
2289 }
This page took 0.113978 seconds and 4 git commands to generate.