2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/credentials.hpp>
9 #include <common/error.hpp>
10 #include <common/hashtable/hashtable.hpp>
11 #include <common/hashtable/utils.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/optional.hpp>
15 #include <common/payload-view.hpp>
16 #include <common/payload.hpp>
17 #include <common/runas.hpp>
18 #include <common/string-utils/string-utils.hpp>
20 #include <lttng/event-rule/event-rule-internal.hpp>
21 #include <lttng/event-rule/user-tracepoint-internal.hpp>
22 #include <lttng/event.h>
23 #include <lttng/log-level-rule.h>
25 #define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
26 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
28 static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule
*rule
)
30 struct lttng_event_rule_user_tracepoint
*tracepoint
;
32 if (rule
== nullptr) {
36 tracepoint
= lttng::utils::container_of(rule
, <tng_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(const struct lttng_event_rule
*rule
)
50 struct lttng_event_rule_user_tracepoint
*tracepoint
;
56 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
59 if (!tracepoint
->pattern
) {
60 ERR("Invalid user tracepoint event rule: a pattern must be set.");
69 static int lttng_event_rule_user_tracepoint_serialize(const struct lttng_event_rule
*rule
,
70 struct lttng_payload
*payload
)
73 size_t pattern_len
, filter_expression_len
, exclusions_len
, header_offset
;
74 size_t size_before_log_level_rule
;
75 struct lttng_event_rule_user_tracepoint
*tracepoint
;
76 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm
;
77 enum lttng_event_rule_status status
;
78 unsigned int exclusion_count
;
79 size_t exclusions_appended_len
= 0;
80 struct lttng_event_rule_user_tracepoint_comm
*header
;
82 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
87 header_offset
= payload
->buffer
.size
;
89 DBG("Serializing user tracepoint event rule.");
90 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
92 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
93 rule
, &exclusion_count
);
94 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
96 pattern_len
= strlen(tracepoint
->pattern
) + 1;
98 if (tracepoint
->filter_expression
!= nullptr) {
99 filter_expression_len
= strlen(tracepoint
->filter_expression
) + 1;
101 filter_expression_len
= 0;
105 for (i
= 0; i
< exclusion_count
; i
++) {
106 const char *exclusion
;
108 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
109 rule
, i
, &exclusion
);
110 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
113 exclusions_len
+= sizeof(uint32_t);
114 /* Payload (null terminated). */
115 exclusions_len
+= strlen(exclusion
) + 1;
118 tracepoint_comm
.pattern_len
= pattern_len
;
119 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
120 tracepoint_comm
.exclusions_count
= exclusion_count
;
121 tracepoint_comm
.exclusions_len
= exclusions_len
;
123 ret
= lttng_dynamic_buffer_append(
124 &payload
->buffer
, &tracepoint_comm
, sizeof(tracepoint_comm
));
129 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->pattern
, pattern_len
);
134 ret
= lttng_dynamic_buffer_append(
135 &payload
->buffer
, tracepoint
->filter_expression
, filter_expression_len
);
140 size_before_log_level_rule
= payload
->buffer
.size
;
142 ret
= lttng_log_level_rule_serialize(tracepoint
->log_level_rule
, payload
);
147 header
= (typeof(header
)) ((char *) payload
->buffer
.data
+ header_offset
);
148 header
->log_level_rule_len
= payload
->buffer
.size
- size_before_log_level_rule
;
150 for (i
= 0; i
< exclusion_count
; i
++) {
152 uint32_t serialized_len
;
153 const char *exclusion
;
155 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
156 rule
, i
, &exclusion
);
157 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
159 len
= strlen(exclusion
) + 1;
161 serialized_len
= len
;
162 /* Append exclusion length, includes the null terminator. */
163 ret
= lttng_dynamic_buffer_append(
164 &payload
->buffer
, &serialized_len
, sizeof(serialized_len
));
169 exclusions_appended_len
+= sizeof(uint32_t);
171 /* Include the '\0' in the payload. */
172 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, exclusion
, len
);
177 exclusions_appended_len
+= len
;
180 LTTNG_ASSERT(exclusions_len
== exclusions_appended_len
);
186 static bool lttng_event_rule_user_tracepoint_is_equal(const struct lttng_event_rule
*_a
,
187 const struct lttng_event_rule
*_b
)
190 bool is_equal
= false;
191 struct lttng_event_rule_user_tracepoint
*a
, *b
;
192 unsigned int count_a
, count_b
;
193 enum lttng_event_rule_status status
;
195 a
= lttng::utils::container_of(_a
, <tng_event_rule_user_tracepoint::parent
);
196 b
= lttng::utils::container_of(_b
, <tng_event_rule_user_tracepoint::parent
);
198 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a
, &count_a
);
199 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
200 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b
, &count_b
);
201 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
204 if (count_a
!= count_b
) {
208 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
213 LTTNG_ASSERT(a
->pattern
);
214 LTTNG_ASSERT(b
->pattern
);
215 if (strcmp(a
->pattern
, b
->pattern
) != 0) {
219 if (a
->filter_expression
&& b
->filter_expression
) {
220 if (strcmp(a
->filter_expression
, b
->filter_expression
) != 0) {
223 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
224 /* One is set; not the other. */
228 if (!lttng_log_level_rule_is_equal(a
->log_level_rule
, b
->log_level_rule
)) {
232 for (i
= 0; i
< count_a
; i
++) {
233 const char *exclusion_a
, *exclusion_b
;
235 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
236 _a
, i
, &exclusion_a
);
237 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
238 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
239 _b
, i
, &exclusion_b
);
240 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
241 if (strcmp(exclusion_a
, exclusion_b
) != 0) {
251 static enum lttng_error_code
252 lttng_event_rule_user_tracepoint_generate_filter_bytecode(struct lttng_event_rule
*rule
,
253 const struct lttng_credentials
*creds
)
256 enum lttng_error_code ret_code
;
257 struct lttng_event_rule_user_tracepoint
*tracepoint
;
258 enum lttng_event_rule_status status
;
260 struct lttng_bytecode
*bytecode
= nullptr;
264 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
266 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
267 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
269 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
270 ret_code
= LTTNG_ERR_FILTER_INVAL
;
274 if (filter
&& filter
[0] == '\0') {
275 ret_code
= LTTNG_ERR_FILTER_INVAL
;
280 tracepoint
->internal_filter
.filter
= strdup(filter
);
281 if (tracepoint
->internal_filter
.filter
== nullptr) {
282 ret_code
= LTTNG_ERR_NOMEM
;
286 tracepoint
->internal_filter
.filter
= nullptr;
289 if (tracepoint
->internal_filter
.filter
== nullptr) {
294 ret
= run_as_generate_filter_bytecode(tracepoint
->internal_filter
.filter
, creds
, &bytecode
);
296 ret_code
= LTTNG_ERR_FILTER_INVAL
;
300 tracepoint
->internal_filter
.bytecode
= bytecode
;
311 lttng_event_rule_user_tracepoint_get_internal_filter(const struct lttng_event_rule
*rule
)
313 struct lttng_event_rule_user_tracepoint
*tracepoint
;
316 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
317 return tracepoint
->internal_filter
.filter
;
320 static const struct lttng_bytecode
*
321 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(const struct lttng_event_rule
*rule
)
323 struct lttng_event_rule_user_tracepoint
*tracepoint
;
326 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
327 return tracepoint
->internal_filter
.bytecode
;
330 static enum lttng_event_rule_generate_exclusions_status
331 lttng_event_rule_user_tracepoint_generate_exclusions(const struct lttng_event_rule
*rule
,
332 struct lttng_event_exclusion
**_exclusions
)
334 unsigned int nb_exclusions
= 0, i
;
335 struct lttng_event_exclusion
*exclusions
;
336 enum lttng_event_rule_status event_rule_status
;
337 enum lttng_event_rule_generate_exclusions_status ret_status
;
339 LTTNG_ASSERT(_exclusions
);
341 event_rule_status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
342 rule
, &nb_exclusions
);
343 LTTNG_ASSERT(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
344 if (nb_exclusions
== 0) {
346 exclusions
= nullptr;
347 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
351 exclusions
= zmalloc
<lttng_event_exclusion
>(sizeof(struct lttng_event_exclusion
) +
352 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
354 PERROR("Failed to allocate exclusions buffer");
355 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
359 exclusions
->count
= nb_exclusions
;
360 for (i
= 0; i
< nb_exclusions
; i
++) {
362 const char *exclusion_str
;
365 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
366 rule
, i
, &exclusion_str
);
367 LTTNG_ASSERT(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
369 copy_ret
= lttng_strncpy(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions
, i
),
371 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions
, i
)));
374 exclusions
= nullptr;
375 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
380 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
383 *_exclusions
= exclusions
;
387 static void destroy_lttng_exclusions_element(void *ptr
)
392 static unsigned long lttng_event_rule_user_tracepoint_hash(const struct lttng_event_rule
*rule
)
395 unsigned int i
, exclusion_count
;
396 enum lttng_event_rule_status status
;
397 struct lttng_event_rule_user_tracepoint
*tp_rule
=
398 lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
400 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
, lttng_ht_seed
);
401 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
403 if (tp_rule
->filter_expression
) {
404 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
407 if (tp_rule
->log_level_rule
) {
408 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
411 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
412 rule
, &exclusion_count
);
413 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
415 for (i
= 0; i
< exclusion_count
; i
++) {
416 const char *exclusion
;
418 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
419 rule
, i
, &exclusion
);
420 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
421 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
427 static enum lttng_error_code
428 lttng_event_rule_user_tracepoint_mi_serialize(const struct lttng_event_rule
*rule
,
429 struct mi_writer
*writer
)
432 enum lttng_error_code ret_code
;
433 enum lttng_event_rule_status status
;
434 const char *filter
= nullptr;
435 const char *name_pattern
= nullptr;
436 const struct lttng_log_level_rule
*log_level_rule
= nullptr;
437 unsigned int exclusion_count
= 0;
440 LTTNG_ASSERT(writer
);
441 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule
));
443 status
= lttng_event_rule_user_tracepoint_get_name_pattern(rule
, &name_pattern
);
444 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
445 LTTNG_ASSERT(name_pattern
);
447 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
448 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
449 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
451 status
= lttng_event_rule_user_tracepoint_get_log_level_rule(rule
, &log_level_rule
);
452 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
453 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
455 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
456 rule
, &exclusion_count
);
457 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
459 /* Open event rule user tracepoint element. */
460 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_rule_user_tracepoint
);
466 ret
= mi_lttng_writer_write_element_string(
467 writer
, mi_lttng_element_event_rule_name_pattern
, name_pattern
);
472 /* Filter expression. */
473 if (filter
!= nullptr) {
474 ret
= mi_lttng_writer_write_element_string(
475 writer
, mi_lttng_element_event_rule_filter_expression
, filter
);
481 /* Log level rule. */
482 if (log_level_rule
) {
483 ret_code
= lttng_log_level_rule_mi_serialize(log_level_rule
, writer
);
484 if (ret_code
!= LTTNG_OK
) {
489 if (exclusion_count
!= 0) {
492 /* Open the exclusion list. */
493 ret
= mi_lttng_writer_open_element(
495 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions
);
500 for (i
= 0; i
< exclusion_count
; i
++) {
501 const char *exclusion
;
504 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
505 rule
, i
, &exclusion
);
506 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
508 ret
= mi_lttng_writer_write_element_string(
510 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion
,
517 /* Close the list. */
518 ret
= mi_lttng_writer_close_element(writer
);
524 /* Close event rule user tracepoint element. */
525 ret
= mi_lttng_writer_close_element(writer
);
534 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
539 struct lttng_event_rule
*lttng_event_rule_user_tracepoint_create(void)
541 struct lttng_event_rule
*rule
= nullptr;
542 struct lttng_event_rule_user_tracepoint
*tp_rule
;
543 enum lttng_event_rule_status status
;
545 tp_rule
= zmalloc
<lttng_event_rule_user_tracepoint
>();
550 rule
= &tp_rule
->parent
;
551 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
);
552 tp_rule
->parent
.validate
= lttng_event_rule_user_tracepoint_validate
;
553 tp_rule
->parent
.serialize
= lttng_event_rule_user_tracepoint_serialize
;
554 tp_rule
->parent
.equal
= lttng_event_rule_user_tracepoint_is_equal
;
555 tp_rule
->parent
.destroy
= lttng_event_rule_user_tracepoint_destroy
;
556 tp_rule
->parent
.generate_filter_bytecode
=
557 lttng_event_rule_user_tracepoint_generate_filter_bytecode
;
558 tp_rule
->parent
.get_filter
= lttng_event_rule_user_tracepoint_get_internal_filter
;
559 tp_rule
->parent
.get_filter_bytecode
=
560 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode
;
561 tp_rule
->parent
.generate_exclusions
= lttng_event_rule_user_tracepoint_generate_exclusions
;
562 tp_rule
->parent
.hash
= lttng_event_rule_user_tracepoint_hash
;
563 tp_rule
->parent
.mi_serialize
= lttng_event_rule_user_tracepoint_mi_serialize
;
565 /* Not necessary for now. */
566 tp_rule
->parent
.generate_lttng_event
= nullptr;
568 tp_rule
->log_level_rule
= nullptr;
570 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
, destroy_lttng_exclusions_element
);
572 /* Default pattern is '*'. */
573 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, "*");
574 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
575 lttng_event_rule_destroy(rule
);
583 ssize_t
lttng_event_rule_user_tracepoint_create_from_payload(struct lttng_payload_view
*view
,
584 struct lttng_event_rule
**_event_rule
)
586 ssize_t ret
, offset
= 0;
588 enum lttng_event_rule_status status
;
589 const struct lttng_event_rule_user_tracepoint_comm
*tracepoint_comm
;
591 const char *filter_expression
= nullptr;
592 const char **exclusions
= nullptr;
593 const uint32_t *exclusion_len
;
594 const char *exclusion
;
595 struct lttng_buffer_view current_buffer_view
;
596 struct lttng_event_rule
*rule
= nullptr;
597 struct lttng_log_level_rule
*log_level_rule
= nullptr;
604 current_buffer_view
=
605 lttng_buffer_view_from_view(&view
->buffer
, offset
, sizeof(*tracepoint_comm
));
606 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
607 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
612 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
614 rule
= lttng_event_rule_user_tracepoint_create();
616 ERR("Failed to create event rule user tracepoint.");
621 /* Skip to payload. */
622 offset
+= current_buffer_view
.size
;
624 /* Map the pattern. */
625 current_buffer_view
=
626 lttng_buffer_view_from_view(&view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
628 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
633 pattern
= current_buffer_view
.data
;
634 if (!lttng_buffer_view_contains_string(
635 ¤t_buffer_view
, pattern
, tracepoint_comm
->pattern_len
)) {
640 /* Skip after the pattern. */
641 offset
+= tracepoint_comm
->pattern_len
;
643 if (!tracepoint_comm
->filter_expression_len
) {
644 goto skip_filter_expression
;
647 /* Map the filter_expression. */
648 current_buffer_view
= lttng_buffer_view_from_view(
649 &view
->buffer
, offset
, tracepoint_comm
->filter_expression_len
);
650 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
655 filter_expression
= current_buffer_view
.data
;
656 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
658 tracepoint_comm
->filter_expression_len
)) {
663 /* Skip after the pattern. */
664 offset
+= tracepoint_comm
->filter_expression_len
;
666 skip_filter_expression
:
667 if (!tracepoint_comm
->log_level_rule_len
) {
668 goto skip_log_level_rule
;
672 /* Map the log level rule. */
673 struct lttng_payload_view current_payload_view
= lttng_payload_view_from_view(
674 view
, offset
, tracepoint_comm
->log_level_rule_len
);
676 ret
= lttng_log_level_rule_create_from_payload(¤t_payload_view
,
683 LTTNG_ASSERT(ret
== tracepoint_comm
->log_level_rule_len
);
686 /* Skip after the log level rule. */
687 offset
+= tracepoint_comm
->log_level_rule_len
;
690 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
691 current_buffer_view
=
692 lttng_buffer_view_from_view(&view
->buffer
, offset
, sizeof(*exclusion_len
));
693 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
698 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
699 offset
+= sizeof(*exclusion_len
);
701 current_buffer_view
=
702 lttng_buffer_view_from_view(&view
->buffer
, offset
, *exclusion_len
);
703 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
708 exclusion
= current_buffer_view
.data
;
709 if (!lttng_buffer_view_contains_string(
710 ¤t_buffer_view
, exclusion
, *exclusion_len
)) {
715 status
= lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule
,
717 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
718 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
724 /* Skip to next exclusion. */
725 offset
+= *exclusion_len
;
728 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, pattern
);
729 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
730 ERR("Failed to set event rule user tracepoint pattern.");
735 if (filter_expression
) {
736 status
= lttng_event_rule_user_tracepoint_set_filter(rule
, filter_expression
);
737 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
738 ERR("Failed to set event rule user tracepoint pattern.");
744 if (log_level_rule
) {
745 status
= lttng_event_rule_user_tracepoint_set_log_level_rule(rule
, log_level_rule
);
746 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
747 ERR("Failed to set event rule user tracepoint log level rule.");
758 lttng_log_level_rule_destroy(log_level_rule
);
759 lttng_event_rule_destroy(rule
);
763 enum lttng_event_rule_status
764 lttng_event_rule_user_tracepoint_set_name_pattern(struct lttng_event_rule
*rule
,
767 char *pattern_copy
= nullptr;
768 struct lttng_event_rule_user_tracepoint
*tracepoint
;
769 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
771 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
|| strlen(pattern
) == 0) {
772 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
776 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
777 pattern_copy
= strdup(pattern
);
779 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
783 /* Normalize the pattern. */
784 strutils_normalize_star_glob_pattern(pattern_copy
);
786 free(tracepoint
->pattern
);
788 tracepoint
->pattern
= pattern_copy
;
789 pattern_copy
= nullptr;
794 enum lttng_event_rule_status
795 lttng_event_rule_user_tracepoint_get_name_pattern(const struct lttng_event_rule
*rule
,
796 const char **pattern
)
798 struct lttng_event_rule_user_tracepoint
*tracepoint
;
799 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
801 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
802 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
806 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
807 if (!tracepoint
->pattern
) {
808 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
812 *pattern
= tracepoint
->pattern
;
817 enum lttng_event_rule_status
818 lttng_event_rule_user_tracepoint_set_filter(struct lttng_event_rule
*rule
, const char *expression
)
820 char *expression_copy
= nullptr;
821 struct lttng_event_rule_user_tracepoint
*tracepoint
;
822 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
824 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
825 strlen(expression
) == 0) {
826 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
830 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
831 expression_copy
= strdup(expression
);
832 if (!expression_copy
) {
833 PERROR("Failed to copy filter expression");
834 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
838 if (tracepoint
->filter_expression
) {
839 free(tracepoint
->filter_expression
);
842 tracepoint
->filter_expression
= expression_copy
;
843 expression_copy
= nullptr;
848 enum lttng_event_rule_status
849 lttng_event_rule_user_tracepoint_get_filter(const struct lttng_event_rule
*rule
,
850 const char **expression
)
852 struct lttng_event_rule_user_tracepoint
*tracepoint
;
853 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
855 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
856 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
860 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
861 if (!tracepoint
->filter_expression
) {
862 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
866 *expression
= tracepoint
->filter_expression
;
871 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
)
874 enum lttng_log_level_rule_status status
;
877 switch (lttng_log_level_rule_get_type(rule
)) {
878 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
879 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
881 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
882 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(rule
, &level
);
888 LTTNG_ASSERT(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
890 if (level
< LTTNG_LOGLEVEL_EMERG
) {
894 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
905 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_log_level_rule(
906 struct lttng_event_rule
*rule
, const struct lttng_log_level_rule
*log_level_rule
)
908 struct lttng_event_rule_user_tracepoint
*tracepoint
;
909 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
910 struct lttng_log_level_rule
*copy
= nullptr;
912 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
913 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
917 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
919 if (!log_level_rule_valid(log_level_rule
)) {
920 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
924 copy
= lttng_log_level_rule_copy(log_level_rule
);
925 if (copy
== nullptr) {
926 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
930 if (tracepoint
->log_level_rule
) {
931 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
934 tracepoint
->log_level_rule
= copy
;
940 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_log_level_rule(
941 const struct lttng_event_rule
*rule
, const struct lttng_log_level_rule
**log_level_rule
)
943 struct lttng_event_rule_user_tracepoint
*tracepoint
;
944 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
946 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
947 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
951 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
952 if (tracepoint
->log_level_rule
== nullptr) {
953 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
957 *log_level_rule
= tracepoint
->log_level_rule
;
962 enum lttng_event_rule_status
963 lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(struct lttng_event_rule
*rule
,
964 const char *exclusion
)
967 char *exclusion_copy
= nullptr;
968 struct lttng_event_rule_user_tracepoint
*tracepoint
;
969 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
971 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
972 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
976 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
978 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
979 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
983 exclusion_copy
= strdup(exclusion
);
984 if (!exclusion_copy
) {
985 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
989 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
, exclusion_copy
);
991 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
995 exclusion_copy
= nullptr;
997 free(exclusion_copy
);
1001 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1002 const struct lttng_event_rule
*rule
, unsigned int *count
)
1004 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1005 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1007 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1008 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1012 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
1013 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1018 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1019 const struct lttng_event_rule
*rule
, unsigned int index
, const char **exclusion
)
1022 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1023 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1025 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1026 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1030 tracepoint
= lttng::utils::container_of(rule
, <tng_event_rule_user_tracepoint::parent
);
1031 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
, &count
) !=
1032 LTTNG_EVENT_RULE_STATUS_OK
) {
1036 if (index
>= count
) {
1040 *exclusion
= (const char *) lttng_dynamic_pointer_array_get_pointer(&tracepoint
->exclusions
,