2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/hashtable/hashtable.h>
12 #include <common/hashtable/utils.h>
13 #include <common/macros.h>
14 #include <common/mi-lttng.h>
15 #include <common/optional.h>
16 #include <common/payload-view.h>
17 #include <common/payload.h>
18 #include <common/runas.h>
19 #include <common/string-utils/string-utils.h>
20 #include <lttng/event-rule/event-rule-internal.h>
21 #include <lttng/event-rule/user-tracepoint-internal.h>
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
;
36 tracepoint
= container_of(
37 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
39 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
40 lttng_dynamic_pointer_array_reset(&tracepoint
->exclusions
);
41 free(tracepoint
->pattern
);
42 free(tracepoint
->filter_expression
);
43 free(tracepoint
->internal_filter
.filter
);
44 free(tracepoint
->internal_filter
.bytecode
);
48 static bool lttng_event_rule_user_tracepoint_validate(
49 const struct lttng_event_rule
*rule
)
52 struct lttng_event_rule_user_tracepoint
*tracepoint
;
58 tracepoint
= container_of(
59 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
62 if (!tracepoint
->pattern
) {
63 ERR("Invalid user tracepoint event rule: a pattern must be set.");
72 static int lttng_event_rule_user_tracepoint_serialize(
73 const struct lttng_event_rule
*rule
,
74 struct lttng_payload
*payload
)
77 size_t pattern_len
, filter_expression_len
, exclusions_len
, header_offset
;
78 size_t size_before_log_level_rule
;
79 struct lttng_event_rule_user_tracepoint
*tracepoint
;
80 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm
;
81 enum lttng_event_rule_status status
;
82 unsigned int exclusion_count
;
83 size_t exclusions_appended_len
= 0;
84 struct lttng_event_rule_user_tracepoint_comm
*header
;
86 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
91 header_offset
= payload
->buffer
.size
;
93 DBG("Serializing user tracepoint event rule.");
94 tracepoint
= container_of(
95 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
97 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
, &exclusion_count
);
98 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
100 pattern_len
= strlen(tracepoint
->pattern
) + 1;
102 if (tracepoint
->filter_expression
!= NULL
) {
103 filter_expression_len
=
104 strlen(tracepoint
->filter_expression
) + 1;
106 filter_expression_len
= 0;
110 for (i
= 0; i
< exclusion_count
; i
++) {
111 const char *exclusion
;
113 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
114 rule
, i
, &exclusion
);
115 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
118 exclusions_len
+= sizeof(uint32_t);
119 /* Payload (null terminated). */
120 exclusions_len
+= strlen(exclusion
) + 1;
123 tracepoint_comm
.pattern_len
= pattern_len
;
124 tracepoint_comm
.filter_expression_len
= filter_expression_len
;
125 tracepoint_comm
.exclusions_count
= exclusion_count
;
126 tracepoint_comm
.exclusions_len
= exclusions_len
;
128 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &tracepoint_comm
,
129 sizeof(tracepoint_comm
));
134 ret
= lttng_dynamic_buffer_append(
135 &payload
->buffer
, tracepoint
->pattern
, pattern_len
);
140 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, tracepoint
->filter_expression
,
141 filter_expression_len
);
146 size_before_log_level_rule
= payload
->buffer
.size
;
148 ret
= lttng_log_level_rule_serialize(tracepoint
->log_level_rule
, payload
);
153 header
= (typeof(header
)) ((char *) payload
->buffer
.data
+ header_offset
);
154 header
->log_level_rule_len
=
155 payload
->buffer
.size
- size_before_log_level_rule
;
157 for (i
= 0; i
< exclusion_count
; i
++) {
159 uint32_t serialized_len
;
160 const char *exclusion
;
162 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
163 rule
, i
, &exclusion
);
164 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
166 len
= strlen(exclusion
) + 1;
168 serialized_len
= len
;
169 /* Append exclusion length, includes the null terminator. */
170 ret
= lttng_dynamic_buffer_append(
171 &payload
->buffer
, &serialized_len
, sizeof(serialized_len
));
176 exclusions_appended_len
+= sizeof(uint32_t);
178 /* Include the '\0' in the payload. */
179 ret
= lttng_dynamic_buffer_append(
180 &payload
->buffer
, exclusion
, len
);
185 exclusions_appended_len
+= len
;
188 assert(exclusions_len
== exclusions_appended_len
);
194 static bool lttng_event_rule_user_tracepoint_is_equal(
195 const struct lttng_event_rule
*_a
,
196 const struct lttng_event_rule
*_b
)
199 bool is_equal
= false;
200 struct lttng_event_rule_user_tracepoint
*a
, *b
;
201 unsigned int count_a
, count_b
;
202 enum lttng_event_rule_status status
;
204 a
= container_of(_a
, struct lttng_event_rule_user_tracepoint
, parent
);
205 b
= container_of(_b
, struct lttng_event_rule_user_tracepoint
, parent
);
207 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a
, &count_a
);
208 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
209 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b
, &count_b
);
210 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
213 if (count_a
!= count_b
) {
217 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
224 if (strcmp(a
->pattern
, b
->pattern
)) {
228 if (a
->filter_expression
&& b
->filter_expression
) {
229 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
232 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
233 /* One is set; not the other. */
237 if (!lttng_log_level_rule_is_equal(
238 a
->log_level_rule
, b
->log_level_rule
)) {
242 for (i
= 0; i
< count_a
; i
++) {
243 const char *exclusion_a
, *exclusion_b
;
245 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
246 _a
, i
, &exclusion_a
);
247 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
248 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
249 _b
, i
, &exclusion_b
);
250 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
251 if (strcmp(exclusion_a
, exclusion_b
)) {
261 static enum lttng_error_code
262 lttng_event_rule_user_tracepoint_generate_filter_bytecode(
263 struct lttng_event_rule
*rule
,
264 const struct lttng_credentials
*creds
)
267 enum lttng_error_code ret_code
;
268 struct lttng_event_rule_user_tracepoint
*tracepoint
;
269 enum lttng_event_rule_status status
;
271 struct lttng_bytecode
*bytecode
= NULL
;
275 tracepoint
= container_of(
276 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
278 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
279 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
281 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
282 ret_code
= LTTNG_ERR_FILTER_INVAL
;
286 if (filter
&& filter
[0] == '\0') {
287 ret_code
= LTTNG_ERR_FILTER_INVAL
;
292 tracepoint
->internal_filter
.filter
= strdup(filter
);
293 if (tracepoint
->internal_filter
.filter
== NULL
) {
294 ret_code
= LTTNG_ERR_NOMEM
;
298 tracepoint
->internal_filter
.filter
= NULL
;
301 if (tracepoint
->internal_filter
.filter
== NULL
) {
306 ret
= run_as_generate_filter_bytecode(
307 tracepoint
->internal_filter
.filter
, creds
,
310 ret_code
= LTTNG_ERR_FILTER_INVAL
;
314 tracepoint
->internal_filter
.bytecode
= bytecode
;
324 static const char *lttng_event_rule_user_tracepoint_get_internal_filter(
325 const struct lttng_event_rule
*rule
)
327 struct lttng_event_rule_user_tracepoint
*tracepoint
;
330 tracepoint
= container_of(
331 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
332 return tracepoint
->internal_filter
.filter
;
335 static const struct lttng_bytecode
*
336 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(
337 const struct lttng_event_rule
*rule
)
339 struct lttng_event_rule_user_tracepoint
*tracepoint
;
342 tracepoint
= container_of(
343 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
344 return tracepoint
->internal_filter
.bytecode
;
347 static enum lttng_event_rule_generate_exclusions_status
348 lttng_event_rule_user_tracepoint_generate_exclusions(
349 const struct lttng_event_rule
*rule
,
350 struct lttng_event_exclusion
**_exclusions
)
352 unsigned int nb_exclusions
= 0, i
;
353 struct lttng_event_exclusion
*exclusions
;
354 enum lttng_event_rule_status event_rule_status
;
355 enum lttng_event_rule_generate_exclusions_status ret_status
;
359 event_rule_status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
360 rule
, &nb_exclusions
);
361 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
362 if (nb_exclusions
== 0) {
365 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
369 exclusions
= zmalloc(sizeof(struct lttng_event_exclusion
) +
370 (LTTNG_SYMBOL_NAME_LEN
* nb_exclusions
));
372 PERROR("Failed to allocate exclusions buffer");
373 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY
;
377 exclusions
->count
= nb_exclusions
;
378 for (i
= 0; i
< nb_exclusions
; i
++) {
380 const char *exclusion_str
;
383 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
384 rule
, i
, &exclusion_str
);
385 assert(event_rule_status
== LTTNG_EVENT_RULE_STATUS_OK
);
387 copy_ret
= lttng_strncpy(exclusions
->names
[i
], exclusion_str
,
388 LTTNG_SYMBOL_NAME_LEN
);
392 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR
;
397 ret_status
= LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK
;
400 *_exclusions
= exclusions
;
404 static void destroy_lttng_exclusions_element(void *ptr
)
409 static unsigned long lttng_event_rule_user_tracepoint_hash(
410 const struct lttng_event_rule
*rule
)
413 unsigned int i
, exclusion_count
;
414 enum lttng_event_rule_status status
;
415 struct lttng_event_rule_user_tracepoint
*tp_rule
=
416 container_of(rule
, typeof(*tp_rule
), parent
);
418 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
,
420 hash
^= hash_key_str(tp_rule
->pattern
, lttng_ht_seed
);
422 if (tp_rule
->filter_expression
) {
423 hash
^= hash_key_str(tp_rule
->filter_expression
, lttng_ht_seed
);
426 if (tp_rule
->log_level_rule
) {
427 hash
^= lttng_log_level_rule_hash(tp_rule
->log_level_rule
);
430 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
,
432 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
434 for (i
= 0; i
< exclusion_count
; i
++) {
435 const char *exclusion
;
437 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
438 rule
, i
, &exclusion
);
439 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
440 hash
^= hash_key_str(exclusion
, lttng_ht_seed
);
446 static enum lttng_error_code
lttng_event_rule_user_tracepoint_mi_serialize(
447 const struct lttng_event_rule
*rule
, struct mi_writer
*writer
)
450 enum lttng_error_code ret_code
;
451 enum lttng_event_rule_status status
;
452 const char *filter
= NULL
;
453 const char *name_pattern
= NULL
;
454 const struct lttng_log_level_rule
*log_level_rule
= NULL
;
455 unsigned int exclusion_count
= 0;
459 assert(IS_USER_TRACEPOINT_EVENT_RULE(rule
));
461 status
= lttng_event_rule_user_tracepoint_get_name_pattern(
462 rule
, &name_pattern
);
463 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
464 assert(name_pattern
);
466 status
= lttng_event_rule_user_tracepoint_get_filter(rule
, &filter
);
467 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
||
468 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
470 status
= lttng_event_rule_user_tracepoint_get_log_level_rule(
471 rule
, &log_level_rule
);
472 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
||
473 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
475 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
476 rule
, &exclusion_count
);
477 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
479 /* Open event rule user tracepoint element. */
480 ret
= mi_lttng_writer_open_element(
481 writer
, mi_lttng_element_event_rule_user_tracepoint
);
487 ret
= mi_lttng_writer_write_element_string(writer
,
488 mi_lttng_element_event_rule_name_pattern
, name_pattern
);
493 /* Filter expression. */
494 if (filter
!= NULL
) {
495 ret
= mi_lttng_writer_write_element_string(writer
,
496 mi_lttng_element_event_rule_filter_expression
,
503 /* Log level rule. */
504 if (log_level_rule
) {
505 ret_code
= lttng_log_level_rule_mi_serialize(
506 log_level_rule
, writer
);
507 if (ret_code
!= LTTNG_OK
) {
512 if (exclusion_count
!= 0) {
515 /* Open the exclusion list. */
516 ret
= mi_lttng_writer_open_element(writer
,
517 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions
);
522 for (i
= 0; i
< exclusion_count
; i
++) {
523 const char *exclusion
;
525 status
= lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
526 rule
, i
, &exclusion
);
527 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
529 ret
= mi_lttng_writer_write_element_string(writer
,
530 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion
,
537 /* Close the list. */
538 ret
= mi_lttng_writer_close_element(writer
);
544 /* Close event rule user tracepoint element. */
545 ret
= mi_lttng_writer_close_element(writer
);
554 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
559 struct lttng_event_rule
*lttng_event_rule_user_tracepoint_create(void)
561 struct lttng_event_rule
*rule
= NULL
;
562 struct lttng_event_rule_user_tracepoint
*tp_rule
;
563 enum lttng_event_rule_status status
;
565 tp_rule
= zmalloc(sizeof(struct lttng_event_rule_user_tracepoint
));
570 rule
= &tp_rule
->parent
;
571 lttng_event_rule_init(&tp_rule
->parent
, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT
);
572 tp_rule
->parent
.validate
= lttng_event_rule_user_tracepoint_validate
;
573 tp_rule
->parent
.serialize
= lttng_event_rule_user_tracepoint_serialize
;
574 tp_rule
->parent
.equal
= lttng_event_rule_user_tracepoint_is_equal
;
575 tp_rule
->parent
.destroy
= lttng_event_rule_user_tracepoint_destroy
;
576 tp_rule
->parent
.generate_filter_bytecode
=
577 lttng_event_rule_user_tracepoint_generate_filter_bytecode
;
578 tp_rule
->parent
.get_filter
=
579 lttng_event_rule_user_tracepoint_get_internal_filter
;
580 tp_rule
->parent
.get_filter_bytecode
=
581 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode
;
582 tp_rule
->parent
.generate_exclusions
=
583 lttng_event_rule_user_tracepoint_generate_exclusions
;
584 tp_rule
->parent
.hash
= lttng_event_rule_user_tracepoint_hash
;
585 tp_rule
->parent
.mi_serialize
= lttng_event_rule_user_tracepoint_mi_serialize
;
587 /* Not necessary for now. */
588 tp_rule
->parent
.generate_lttng_event
= NULL
;
590 tp_rule
->log_level_rule
= NULL
;
592 lttng_dynamic_pointer_array_init(&tp_rule
->exclusions
,
593 destroy_lttng_exclusions_element
);
595 /* Default pattern is '*'. */
596 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, "*");
597 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
598 lttng_event_rule_destroy(rule
);
607 ssize_t
lttng_event_rule_user_tracepoint_create_from_payload(
608 struct lttng_payload_view
*view
,
609 struct lttng_event_rule
**_event_rule
)
611 ssize_t ret
, offset
= 0;
613 enum lttng_event_rule_status status
;
614 const struct lttng_event_rule_user_tracepoint_comm
*tracepoint_comm
;
616 const char *filter_expression
= NULL
;
617 const char **exclusions
= NULL
;
618 const uint32_t *exclusion_len
;
619 const char *exclusion
;
620 struct lttng_buffer_view current_buffer_view
;
621 struct lttng_event_rule
*rule
= NULL
;
622 struct lttng_log_level_rule
*log_level_rule
= NULL
;
629 current_buffer_view
= lttng_buffer_view_from_view(
630 &view
->buffer
, offset
, sizeof(*tracepoint_comm
));
631 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
632 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
637 tracepoint_comm
= (typeof(tracepoint_comm
)) current_buffer_view
.data
;
639 rule
= lttng_event_rule_user_tracepoint_create();
641 ERR("Failed to create event rule user tracepoint.");
646 /* Skip to payload. */
647 offset
+= current_buffer_view
.size
;
649 /* Map the pattern. */
650 current_buffer_view
= lttng_buffer_view_from_view(
651 &view
->buffer
, offset
, tracepoint_comm
->pattern_len
);
653 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
658 pattern
= current_buffer_view
.data
;
659 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
660 tracepoint_comm
->pattern_len
)) {
665 /* Skip after the pattern. */
666 offset
+= tracepoint_comm
->pattern_len
;
668 if (!tracepoint_comm
->filter_expression_len
) {
669 goto skip_filter_expression
;
672 /* Map the filter_expression. */
673 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
674 tracepoint_comm
->filter_expression_len
);
675 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
680 filter_expression
= current_buffer_view
.data
;
681 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
683 tracepoint_comm
->filter_expression_len
)) {
688 /* Skip after the pattern. */
689 offset
+= tracepoint_comm
->filter_expression_len
;
691 skip_filter_expression
:
692 if (!tracepoint_comm
->log_level_rule_len
) {
693 goto skip_log_level_rule
;
697 /* Map the log level rule. */
698 struct lttng_payload_view current_payload_view
=
699 lttng_payload_view_from_view(view
, offset
,
700 tracepoint_comm
->log_level_rule_len
);
702 ret
= lttng_log_level_rule_create_from_payload(
703 ¤t_payload_view
, &log_level_rule
);
709 assert(ret
== tracepoint_comm
->log_level_rule_len
);
712 /* Skip after the log level rule. */
713 offset
+= tracepoint_comm
->log_level_rule_len
;
716 for (i
= 0; i
< tracepoint_comm
->exclusions_count
; i
++) {
717 current_buffer_view
= lttng_buffer_view_from_view(
718 &view
->buffer
, offset
, sizeof(*exclusion_len
));
719 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
724 exclusion_len
= (typeof(exclusion_len
)) current_buffer_view
.data
;
725 offset
+= sizeof(*exclusion_len
);
727 current_buffer_view
= lttng_buffer_view_from_view(
728 &view
->buffer
, offset
, *exclusion_len
);
729 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
734 exclusion
= current_buffer_view
.data
;
735 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
736 exclusion
, *exclusion_len
)) {
741 status
= lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule
, exclusion
);
742 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
743 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
749 /* Skip to next exclusion. */
750 offset
+= *exclusion_len
;
753 status
= lttng_event_rule_user_tracepoint_set_name_pattern(rule
, pattern
);
754 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
755 ERR("Failed to set event rule user tracepoint pattern.");
760 if (filter_expression
) {
761 status
= lttng_event_rule_user_tracepoint_set_filter(
762 rule
, filter_expression
);
763 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
764 ERR("Failed to set event rule user tracepoint pattern.");
770 if (log_level_rule
) {
771 status
= lttng_event_rule_user_tracepoint_set_log_level_rule(
772 rule
, log_level_rule
);
773 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
774 ERR("Failed to set event rule user tracepoint log level rule.");
785 lttng_log_level_rule_destroy(log_level_rule
);
786 lttng_event_rule_destroy(rule
);
790 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_name_pattern(
791 struct lttng_event_rule
*rule
, const char *pattern
)
793 char *pattern_copy
= NULL
;
794 struct lttng_event_rule_user_tracepoint
*tracepoint
;
795 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
797 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
||
798 strlen(pattern
) == 0) {
799 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
803 tracepoint
= container_of(
804 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
805 pattern_copy
= strdup(pattern
);
807 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
811 /* Normalize the pattern. */
812 strutils_normalize_star_glob_pattern(pattern_copy
);
814 free(tracepoint
->pattern
);
816 tracepoint
->pattern
= pattern_copy
;
822 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern(
823 const struct lttng_event_rule
*rule
, const char **pattern
)
825 struct lttng_event_rule_user_tracepoint
*tracepoint
;
826 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
828 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !pattern
) {
829 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
833 tracepoint
= container_of(
834 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
835 if (!tracepoint
->pattern
) {
836 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
840 *pattern
= tracepoint
->pattern
;
845 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_filter(
846 struct lttng_event_rule
*rule
, const char *expression
)
848 char *expression_copy
= NULL
;
849 struct lttng_event_rule_user_tracepoint
*tracepoint
;
850 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
852 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
||
853 strlen(expression
) == 0) {
854 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
858 tracepoint
= container_of(
859 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
860 expression_copy
= strdup(expression
);
861 if (!expression_copy
) {
862 PERROR("Failed to copy filter expression");
863 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
867 if (tracepoint
->filter_expression
) {
868 free(tracepoint
->filter_expression
);
871 tracepoint
->filter_expression
= expression_copy
;
872 expression_copy
= NULL
;
877 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_filter(
878 const struct lttng_event_rule
*rule
, const char **expression
)
880 struct lttng_event_rule_user_tracepoint
*tracepoint
;
881 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
883 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !expression
) {
884 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
888 tracepoint
= container_of(
889 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
890 if (!tracepoint
->filter_expression
) {
891 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
895 *expression
= tracepoint
->filter_expression
;
900 static bool log_level_rule_valid(const struct lttng_log_level_rule
*rule
)
903 enum lttng_log_level_rule_status status
;
906 switch (lttng_log_level_rule_get_type(rule
)) {
907 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY
:
908 status
= lttng_log_level_rule_exactly_get_level(rule
, &level
);
910 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS
:
911 status
= lttng_log_level_rule_at_least_as_severe_as_get_level(
918 assert(status
== LTTNG_LOG_LEVEL_RULE_STATUS_OK
);
920 if (level
< LTTNG_LOGLEVEL_EMERG
) {
924 if (level
> LTTNG_LOGLEVEL_DEBUG
) {
935 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_set_log_level_rule(
936 struct lttng_event_rule
*rule
,
937 const struct lttng_log_level_rule
*log_level_rule
)
939 struct lttng_event_rule_user_tracepoint
*tracepoint
;
940 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
941 struct lttng_log_level_rule
*copy
= NULL
;
943 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
)) {
944 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
948 tracepoint
= container_of(
949 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
951 if (!log_level_rule_valid(log_level_rule
)) {
952 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
956 copy
= lttng_log_level_rule_copy(log_level_rule
);
958 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
962 if (tracepoint
->log_level_rule
) {
963 lttng_log_level_rule_destroy(tracepoint
->log_level_rule
);
966 tracepoint
->log_level_rule
= copy
;
972 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_log_level_rule(
973 const struct lttng_event_rule
*rule
,
974 const struct lttng_log_level_rule
**log_level_rule
977 struct lttng_event_rule_user_tracepoint
*tracepoint
;
978 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
980 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !log_level_rule
) {
981 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
985 tracepoint
= container_of(
986 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
987 if (tracepoint
->log_level_rule
== NULL
) {
988 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
992 *log_level_rule
= tracepoint
->log_level_rule
;
997 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(
998 struct lttng_event_rule
*rule
,
999 const char *exclusion
)
1002 char *exclusion_copy
= NULL
;
1003 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1004 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1006 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) ||
1008 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1012 tracepoint
= container_of(
1013 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1015 if (strlen(exclusion
) >= LTTNG_SYMBOL_NAME_LEN
) {
1016 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1020 exclusion_copy
= strdup(exclusion
);
1021 if (!exclusion_copy
) {
1022 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1026 ret
= lttng_dynamic_pointer_array_add_pointer(&tracepoint
->exclusions
,
1029 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
1033 exclusion_copy
= NULL
;
1035 free(exclusion_copy
);
1039 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1040 const struct lttng_event_rule
*rule
, unsigned int *count
)
1042 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1043 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1045 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !count
) {
1046 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1050 tracepoint
= container_of(
1051 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1052 *count
= lttng_dynamic_pointer_array_get_count(&tracepoint
->exclusions
);
1057 enum lttng_event_rule_status
lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1058 const struct lttng_event_rule
*rule
,
1060 const char **exclusion
)
1063 struct lttng_event_rule_user_tracepoint
*tracepoint
;
1064 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
1066 if (!rule
|| !IS_USER_TRACEPOINT_EVENT_RULE(rule
) || !exclusion
) {
1067 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
1071 tracepoint
= container_of(
1072 rule
, struct lttng_event_rule_user_tracepoint
, parent
);
1073 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule
, &count
) !=
1074 LTTNG_EVENT_RULE_STATUS_OK
) {
1078 if (index
>= count
) {
1082 *exclusion
= lttng_dynamic_pointer_array_get_pointer(
1083 &tracepoint
->exclusions
, index
);