2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/credentials.h>
9 #include <common/error.h>
10 #include <common/hashtable/hashtable.h>
11 #include <common/hashtable/utils.h>
12 #include <common/macros.h>
13 #include <common/mi-lttng.h>
14 #include <common/optional.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
17 #include <common/runas.h>
18 #include <common/string-utils/string-utils.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/user-tracepoint-internal.h>
21 #include <lttng/event.h>
22 #include <lttng/log-level-rule.h>
24 #define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
27 static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule
*rule
)
29 struct lttng_event_rule_user_tracepoint
*tracepoint
;
35 tracepoint
= container_of(
36 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
38 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
39 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
40 free(tracepoint
->pattern
);
41 free(tracepoint
->filter_expression
);
42 free(tracepoint
->internal_filter
.filter
);
43 free(tracepoint
->internal_filter
.bytecode
);
47 static bool lttng_event_rule_user_tracepoint_validate(
48 const struct lttng_event_rule
*rule
)
51 struct lttng_event_rule_user_tracepoint
*tracepoint
;
57 tracepoint
= container_of(
58 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
61 if (!tracepoint
->pattern
) {
62 ERR("Invalid user tracepoint event rule: a pattern must be set.");
71 static int lttng_event_rule_user_tracepoint_serialize(
72 const struct lttng_event_rule
*rule
,
73 struct lttng_payload
*payload
)
76 size_t pattern_len
, filter_expression_len
, exclusions_len
, header_offset
;
77 size_t size_before_log_level_rule
;
78 struct lttng_event_rule_user_tracepoint
*tracepoint
;
79 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm
;
80 enum lttng_event_rule_status status
;
81 unsigned int exclusion_count
;
82 size_t exclusions_appended_len
= 0;
83 struct lttng_event_rule_user_tracepoint_comm
*header
;
85 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
90 header_offset
= payload
->buffer
.size
;
92 DBG("Serializing user tracepoint event rule.");
93 tracepoint
= container_of(
94 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
96 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
, &exclusion_count
);
97 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
99 pattern_len
= strlen(tracepoint
->pattern
) + 1;
101 if (tracepoint
->filter_expression
!= NULL
) {
102 filter_expression_len
=
103 strlen(tracepoint
->filter_expression
) + 1;
105 filter_expression_len
= 0;
109 for (i
= 0; i
< exclusion_count
; i
++) {
110 const char *exclusion
;
112 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
113 rule
, i
, &exclusion
);
114 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
117 exclusions_len
+= sizeof(uint32_t);
118 /* Payload (null terminated). */
119 exclusions_len
+= strlen(exclusion
) + 1;
122 tracepoint_comm
.pattern_len
= pattern_len
;
123 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
124 tracepoint_comm
.exclusions_count
= exclusion_count
;
125 tracepoint_comm
.exclusions_len
= exclusions_len
;
127 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
128 sizeof(tracepoint_comm
));
133 ret
= lttng_dynamic_buffer_append(
134 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
139 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
140 filter_expression_len
);
145 size_before_log_level_rule
= payload
->buffer
.size
;
147 ret
= lttng_log_level_rule_serialize(tracepoint
->log_level_rule
, payload
);
152 header
= (typeof(header
)) ((char *) payload
->buffer
.data
+ header_offset
);
153 header
->log_level_rule_len
=
154 payload
->buffer
.size
- size_before_log_level_rule
;
156 for (i
= 0; i
< exclusion_count
; i
++) {
158 const char *exclusion
;
160 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
161 rule
, i
, &exclusion
);
162 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
164 len
= strlen(exclusion
) + 1;
165 /* Append exclusion length, includes the null terminator. */
166 ret
= lttng_dynamic_buffer_append(
167 &payload
->buffer
, &len
, sizeof(uint32_t));
172 exclusions_appended_len
+= sizeof(uint32_t);
174 /* Include the '\0' in the payload. */
175 ret
= lttng_dynamic_buffer_append(
176 &payload
->buffer
, exclusion
, len
);
181 exclusions_appended_len
+= len
;
184 LTTNG_ASSERT(exclusions_len
== exclusions_appended_len
);
190 static bool lttng_event_rule_user_tracepoint_is_equal(
191 const struct lttng_event_rule
*_a
,
192 const struct lttng_event_rule
*_b
)
195 bool is_equal
= false;
196 struct lttng_event_rule_user_tracepoint
*a
, *b
;
197 unsigned int count_a
, count_b
;
198 enum lttng_event_rule_status status
;
200 a
= container_of(_a
, struct lttng_event_rule_user_tracepoint
, parent
);
201 b
= container_of(_b
, struct lttng_event_rule_user_tracepoint
, parent
);
203 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a
, &count_a
);
204 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
205 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b
, &count_b
);
206 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
209 if (count_a
!= count_b
) {
213 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
218 LTTNG_ASSERT(a
->pattern
);
219 LTTNG_ASSERT(b
->pattern
);
220 if (strcmp(a
->pattern
, b
->pattern
)) {
224 if (a
->filter_expression
&& b
->filter_expression
) {
225 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
228 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
229 /* One is set; not the other. */
233 if (!lttng_log_level_rule_is_equal(
234 a
->log_level_rule
, b
->log_level_rule
)) {
238 for (i
= 0; i
< count_a
; i
++) {
239 const char *exclusion_a
, *exclusion_b
;
241 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
242 _a
, i
, &exclusion_a
);
243 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
244 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
245 _b
, i
, &exclusion_b
);
246 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
247 if (strcmp(exclusion_a
, exclusion_b
)) {
257 static enum lttng_error_code
258 lttng_event_rule_user_tracepoint_generate_filter_bytecode(
259 struct lttng_event_rule
*rule
,
260 const struct lttng_credentials
*creds
)
263 enum lttng_error_code ret_code
;
264 struct lttng_event_rule_user_tracepoint
*tracepoint
;
265 enum lttng_event_rule_status status
;
267 struct lttng_bytecode
*bytecode
= NULL
;
271 tracepoint
= container_of(
272 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
274 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
275 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
277 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
278 ret_code
= LTTNG_ERR_FILTER_INVAL
;
282 if (filter
&& filter
[0] == '\0') {
283 ret_code
= LTTNG_ERR_FILTER_INVAL
;
288 tracepoint
->internal_filter
.filter
= strdup(filter
);
289 if (tracepoint
->internal_filter
.filter
== NULL
) {
290 ret_code
= LTTNG_ERR_NOMEM
;
294 tracepoint
->internal_filter
.filter
= NULL
;
297 if (tracepoint
->internal_filter
.filter
== NULL
) {
302 ret
= run_as_generate_filter_bytecode(
303 tracepoint
->internal_filter
.filter
, creds
,
306 ret_code
= LTTNG_ERR_FILTER_INVAL
;
310 tracepoint
->internal_filter
.bytecode
= bytecode
;
320 static const char *lttng_event_rule_user_tracepoint_get_internal_filter(
321 const struct lttng_event_rule
*rule
)
323 struct lttng_event_rule_user_tracepoint
*tracepoint
;
326 tracepoint
= container_of(
327 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
328 return tracepoint
->internal_filter
.filter
;
331 static const struct lttng_bytecode
*
332 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(
333 const struct lttng_event_rule
*rule
)
335 struct lttng_event_rule_user_tracepoint
*tracepoint
;
338 tracepoint
= container_of(
339 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
340 return tracepoint
->internal_filter
.bytecode
;
343 static enum lttng_event_rule_generate_exclusions_status
344 lttng_event_rule_user_tracepoint_generate_exclusions(
345 const struct lttng_event_rule
*rule
,
346 struct lttng_event_exclusion
**_exclusions
)
348 unsigned int nb_exclusions
= 0, i
;
349 struct lttng_event_exclusion
*exclusions
;
350 enum lttng_event_rule_status event_rule_status
;
351 enum lttng_event_rule_generate_exclusions_status ret_status
;
353 LTTNG_ASSERT(_exclusions
);
355 event_rule_status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
356 rule
, &nb_exclusions
);
357 LTTNG_ASSERT(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
358 if (nb_exclusions
== 0) {
361 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
365 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
366 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
368 PERROR("Failed to allocate exclusions buffer");
369 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
373 exclusions
->count
= nb_exclusions
;
374 for (i
= 0; i
< nb_exclusions
; i
++) {
376 const char *exclusion_str
;
379 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
380 rule
, i
, &exclusion_str
);
381 LTTNG_ASSERT(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
383 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
384 LTTNG_SYMBOL_NAME_LEN
);
388 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
393 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
396 *_exclusions
= exclusions
;
400 static void destroy_lttng_exclusions_element(void *ptr
)
405 static unsigned long lttng_event_rule_user_tracepoint_hash(
406 const struct lttng_event_rule
*rule
)
409 unsigned int i
, exclusion_count
;
410 enum lttng_event_rule_status status
;
411 struct lttng_event_rule_user_tracepoint
*tp_rule
=
412 container_of(rule
, typeof(*tp_rule
), parent
);
414 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
,
416 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
418 if (tp_rule
->filter_expression
) {
419 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
422 if (tp_rule
->log_level_rule
) {
423 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
426 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
,
428 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
430 for (i
= 0; i
< exclusion_count
; i
++) {
431 const char *exclusion
;
433 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
434 rule
, i
, &exclusion
);
435 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
436 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
442 static enum lttng_error_code
lttng_event_rule_user_tracepoint_mi_serialize(
443 const struct lttng_event_rule
*rule
, struct mi_writer
*writer
)
446 enum lttng_error_code ret_code
;
447 enum lttng_event_rule_status status
;
448 const char *filter
= NULL
;
449 const char *name_pattern
= NULL
;
450 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
451 unsigned int exclusion_count
= 0;
454 LTTNG_ASSERT(writer
);
455 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule
));
457 status
= lttng_event_rule_user_tracepoint_get_name_pattern(
458 rule
, &name_pattern
);
459 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
460 LTTNG_ASSERT(name_pattern
);
462 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
463 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
464 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
466 status
= lttng_event_rule_user_tracepoint_get_log_level_rule(
467 rule
, &log_level_rule
);
468 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
469 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
471 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
472 rule
, &exclusion_count
);
473 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
475 /* Open event rule user tracepoint element. */
476 ret
= mi_lttng_writer_open_element(
477 writer
, mi_lttng_element_event_rule_user_tracepoint
);
483 ret
= mi_lttng_writer_write_element_string(writer
,
484 mi_lttng_element_event_rule_name_pattern
, name_pattern
);
489 /* Filter expression. */
490 if (filter
!= NULL
) {
491 ret
= mi_lttng_writer_write_element_string(writer
,
492 mi_lttng_element_event_rule_filter_expression
,
499 /* Log level rule. */
500 if (log_level_rule
) {
501 ret_code
= lttng_log_level_rule_mi_serialize(
502 log_level_rule
, writer
);
503 if (ret_code
!= LTTNG_OK
) {
508 if (exclusion_count
!= 0) {
511 /* Open the exclusion list. */
512 ret
= mi_lttng_writer_open_element(writer
,
513 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions
);
518 for (i
= 0; i
< exclusion_count
; i
++) {
519 const char *exclusion
;
521 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
522 rule
, i
, &exclusion
);
523 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
525 ret
= mi_lttng_writer_write_element_string(writer
,
526 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion
,
533 /* Close the list. */
534 ret
= mi_lttng_writer_close_element(writer
);
540 /* Close event rule user tracepoint element. */
541 ret
= mi_lttng_writer_close_element(writer
);
550 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
555 struct lttng_event_rule
*lttng_event_rule_user_tracepoint_create(void)
557 struct lttng_event_rule
*rule
= NULL
;
558 struct lttng_event_rule_user_tracepoint
*tp_rule
;
559 enum lttng_event_rule_status status
;
561 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_user_tracepoint
));
566 rule
= &tp_rule
->parent
;
567 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
);
568 tp_rule
->parent
.validate
= lttng_event_rule_user_tracepoint_validate
;
569 tp_rule
->parent
.serialize
= lttng_event_rule_user_tracepoint_serialize
;
570 tp_rule
->parent
.equal
= lttng_event_rule_user_tracepoint_is_equal
;
571 tp_rule
->parent
.destroy
= lttng_event_rule_user_tracepoint_destroy
;
572 tp_rule
->parent
.generate_filter_bytecode
=
573 lttng_event_rule_user_tracepoint_generate_filter_bytecode
;
574 tp_rule
->parent
.get_filter
=
575 lttng_event_rule_user_tracepoint_get_internal_filter
;
576 tp_rule
->parent
.get_filter_bytecode
=
577 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode
;
578 tp_rule
->parent
.generate_exclusions
=
579 lttng_event_rule_user_tracepoint_generate_exclusions
;
580 tp_rule
->parent
.hash
= lttng_event_rule_user_tracepoint_hash
;
581 tp_rule
->parent
.mi_serialize
= lttng_event_rule_user_tracepoint_mi_serialize
;
583 /* Not necessary for now. */
584 tp_rule
->parent
.generate_lttng_event
= NULL
;
586 tp_rule
->log_level_rule
= NULL
;
588 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
589 destroy_lttng_exclusions_element
);
591 /* Default pattern is '*'. */
592 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, "*");
593 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
594 lttng_event_rule_destroy(rule
);
602 ssize_t
lttng_event_rule_user_tracepoint_create_from_payload(
603 struct lttng_payload_view
*view
,
604 struct lttng_event_rule
**_event_rule
)
606 ssize_t ret
, offset
= 0;
608 enum lttng_event_rule_status status
;
609 const struct lttng_event_rule_user_tracepoint_comm
*tracepoint_comm
;
611 const char *filter_expression
= NULL
;
612 const char **exclusions
= NULL
;
613 const uint32_t *exclusion_len
;
614 const char *exclusion
;
615 struct lttng_buffer_view current_buffer_view
;
616 struct lttng_event_rule
*rule
= NULL
;
617 struct lttng_log_level_rule
*log_level_rule
= NULL
;
624 current_buffer_view
= lttng_buffer_view_from_view(
625 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
626 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
627 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
632 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
634 rule
= lttng_event_rule_user_tracepoint_create();
636 ERR("Failed to create event rule user tracepoint.");
641 /* Skip to payload. */
642 offset
+= current_buffer_view
.size
;
644 /* Map the pattern. */
645 current_buffer_view
= lttng_buffer_view_from_view(
646 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
648 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
653 pattern
= current_buffer_view
.data
;
654 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
655 tracepoint_comm
->pattern_len
)) {
660 /* Skip after the pattern. */
661 offset
+= tracepoint_comm
->pattern_len
;
663 if (!tracepoint_comm
->filter_expression_len
) {
664 goto skip_filter_expression
;
667 /* Map the filter_expression. */
668 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
669 tracepoint_comm
->filter_expression_len
);
670 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
675 filter_expression
= current_buffer_view
.data
;
676 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
678 tracepoint_comm
->filter_expression_len
)) {
683 /* Skip after the pattern. */
684 offset
+= tracepoint_comm
->filter_expression_len
;
686 skip_filter_expression
:
687 if (!tracepoint_comm
->log_level_rule_len
) {
688 goto skip_log_level_rule
;
692 /* Map the log level rule. */
693 struct lttng_payload_view current_payload_view
=
694 lttng_payload_view_from_view(view
, offset
,
695 tracepoint_comm
->log_level_rule_len
);
697 ret
= lttng_log_level_rule_create_from_payload(
698 ¤t_payload_view
, &log_level_rule
);
704 LTTNG_ASSERT(ret
== tracepoint_comm
->log_level_rule_len
);
707 /* Skip after the log level rule. */
708 offset
+= tracepoint_comm
->log_level_rule_len
;
711 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
712 current_buffer_view
= lttng_buffer_view_from_view(
713 &view
->buffer
, offset
, sizeof(*exclusion_len
));
714 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
719 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
720 offset
+= sizeof(*exclusion_len
);
722 current_buffer_view
= lttng_buffer_view_from_view(
723 &view
->buffer
, offset
, *exclusion_len
);
724 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
729 exclusion
= current_buffer_view
.data
;
730 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
731 exclusion
, *exclusion_len
)) {
736 status
= lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule
, exclusion
);
737 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
738 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
744 /* Skip to next exclusion. */
745 offset
+= *exclusion_len
;
748 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, pattern
);
749 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
750 ERR("Failed to set event rule user tracepoint pattern.");
755 if (filter_expression
) {
756 status
= lttng_event_rule_user_tracepoint_set_filter(
757 rule
, filter_expression
);
758 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
759 ERR("Failed to set event rule user tracepoint pattern.");
765 if (log_level_rule
) {
766 status
= lttng_event_rule_user_tracepoint_set_log_level_rule(
767 rule
, log_level_rule
);
768 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
769 ERR("Failed to set event rule user tracepoint log level rule.");
780 lttng_log_level_rule_destroy(log_level_rule
);
781 lttng_event_rule_destroy(rule
);
785 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_name_pattern(
786 struct lttng_event_rule
*rule
, const char *pattern
)
788 char *pattern_copy
= NULL
;
789 struct lttng_event_rule_user_tracepoint
*tracepoint
;
790 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
792 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
793 strlen(pattern
) == 0) {
794 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
798 tracepoint
= container_of(
799 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
800 pattern_copy
= strdup(pattern
);
802 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
806 /* Normalize the pattern. */
807 strutils_normalize_star_glob_pattern(pattern_copy
);
809 free(tracepoint
->pattern
);
811 tracepoint
->pattern
= pattern_copy
;
817 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern(
818 const struct lttng_event_rule
*rule
, const char **pattern
)
820 struct lttng_event_rule_user_tracepoint
*tracepoint
;
821 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
823 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
824 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
828 tracepoint
= container_of(
829 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
830 if (!tracepoint
->pattern
) {
831 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
835 *pattern
= tracepoint
->pattern
;
840 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_filter(
841 struct lttng_event_rule
*rule
, const char *expression
)
843 char *expression_copy
= NULL
;
844 struct lttng_event_rule_user_tracepoint
*tracepoint
;
845 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
847 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
848 strlen(expression
) == 0) {
849 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
853 tracepoint
= container_of(
854 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
855 expression_copy
= strdup(expression
);
856 if (!expression_copy
) {
857 PERROR("Failed to copy filter expression");
858 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
862 if (tracepoint
->filter_expression
) {
863 free(tracepoint
->filter_expression
);
866 tracepoint
->filter_expression
= expression_copy
;
867 expression_copy
= NULL
;
872 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_filter(
873 const struct lttng_event_rule
*rule
, const char **expression
)
875 struct lttng_event_rule_user_tracepoint
*tracepoint
;
876 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
878 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
879 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
883 tracepoint
= container_of(
884 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
885 if (!tracepoint
->filter_expression
) {
886 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
890 *expression
= tracepoint
->filter_expression
;
895 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
)
898 enum lttng_log_level_rule_status status
;
901 switch (lttng_log_level_rule_get_type(rule
)) {
902 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
903 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
905 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
906 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
913 LTTNG_ASSERT(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
915 if (level
< LTTNG_LOGLEVEL_EMERG
) {
919 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
930 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_log_level_rule(
931 struct lttng_event_rule
*rule
,
932 const struct lttng_log_level_rule
*log_level_rule
)
934 struct lttng_event_rule_user_tracepoint
*tracepoint
;
935 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
936 struct lttng_log_level_rule
*copy
= NULL
;
938 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
939 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
943 tracepoint
= container_of(
944 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
946 if (!log_level_rule_valid(log_level_rule
)) {
947 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
951 copy
= lttng_log_level_rule_copy(log_level_rule
);
953 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
957 if (tracepoint
->log_level_rule
) {
958 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
961 tracepoint
->log_level_rule
= copy
;
967 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_log_level_rule(
968 const struct lttng_event_rule
*rule
,
969 const struct lttng_log_level_rule
**log_level_rule
972 struct lttng_event_rule_user_tracepoint
*tracepoint
;
973 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
975 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
976 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
980 tracepoint
= container_of(
981 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
982 if (tracepoint
->log_level_rule
== NULL
) {
983 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
987 *log_level_rule
= tracepoint
->log_level_rule
;
992 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
993 struct lttng_event_rule
*rule
,
994 const char *exclusion
)
997 char *exclusion_copy
= NULL
;
998 struct lttng_event_rule_user_tracepoint
*tracepoint
;
999 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1001 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) ||
1003 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1007 tracepoint
= container_of(
1008 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1010 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1011 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1015 exclusion_copy
= strdup(exclusion
);
1016 if (!exclusion_copy
) {
1017 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1021 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1024 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1028 exclusion_copy
= NULL
;
1030 free(exclusion_copy
);
1034 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1035 const struct lttng_event_rule
*rule
, unsigned int *count
)
1037 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1038 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1040 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1041 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1045 tracepoint
= container_of(
1046 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1047 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1052 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1053 const struct lttng_event_rule
*rule
,
1055 const char **exclusion
)
1058 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1059 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1061 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1062 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1066 tracepoint
= container_of(
1067 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1068 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
, &count
) !=
1069 LTTNG_EVENT_RULE_STATUS_OK
) {
1073 if (index
>= count
) {
1077 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1078 &tracepoint
->exclusions
, index
);