Commit | Line | Data |
---|---|---|
af0818ef JR |
1 | /* |
2 | * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
c9e313bc SM |
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> | |
28ab034a | 19 | |
c9e313bc SM |
20 | #include <lttng/event-rule/event-rule-internal.hpp> |
21 | #include <lttng/event-rule/kernel-tracepoint-internal.hpp> | |
af0818ef JR |
22 | #include <lttng/event.h> |
23 | ||
24 | #define IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) \ | |
25 | (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT) | |
26 | ||
27 | static void lttng_event_rule_kernel_tracepoint_destroy(struct lttng_event_rule *rule) | |
28 | { | |
29 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
30 | ||
cd9adb8b | 31 | if (rule == nullptr) { |
af0818ef JR |
32 | return; |
33 | } | |
34 | ||
28ab034a | 35 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
36 | |
37 | free(tracepoint->pattern); | |
38 | free(tracepoint->filter_expression); | |
39 | free(tracepoint->internal_filter.filter); | |
40 | free(tracepoint->internal_filter.bytecode); | |
41 | free(tracepoint); | |
42 | } | |
43 | ||
28ab034a | 44 | static bool lttng_event_rule_kernel_tracepoint_validate(const struct lttng_event_rule *rule) |
af0818ef JR |
45 | { |
46 | bool valid = false; | |
47 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
48 | ||
49 | if (!rule) { | |
50 | goto end; | |
51 | } | |
52 | ||
28ab034a | 53 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
54 | |
55 | /* Required field. */ | |
56 | if (!tracepoint->pattern) { | |
57 | ERR("Invalid kernel tracepoint event rule: a pattern must be set."); | |
58 | goto end; | |
59 | } | |
60 | ||
61 | valid = true; | |
62 | end: | |
63 | return valid; | |
64 | } | |
65 | ||
28ab034a JG |
66 | static int lttng_event_rule_kernel_tracepoint_serialize(const struct lttng_event_rule *rule, |
67 | struct lttng_payload *payload) | |
af0818ef JR |
68 | { |
69 | int ret; | |
70 | size_t pattern_len, filter_expression_len; | |
71 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
72 | struct lttng_event_rule_kernel_tracepoint_comm tracepoint_comm; | |
73 | ||
74 | if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule)) { | |
75 | ret = -1; | |
76 | goto end; | |
77 | } | |
78 | ||
79 | DBG("Serializing kernel tracepoint event rule."); | |
28ab034a | 80 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
81 | |
82 | pattern_len = strlen(tracepoint->pattern) + 1; | |
83 | ||
cd9adb8b | 84 | if (tracepoint->filter_expression != nullptr) { |
28ab034a | 85 | filter_expression_len = strlen(tracepoint->filter_expression) + 1; |
af0818ef JR |
86 | } else { |
87 | filter_expression_len = 0; | |
88 | } | |
89 | ||
90 | tracepoint_comm.pattern_len = pattern_len; | |
91 | tracepoint_comm.filter_expression_len = filter_expression_len; | |
92 | ||
28ab034a JG |
93 | ret = lttng_dynamic_buffer_append( |
94 | &payload->buffer, &tracepoint_comm, sizeof(tracepoint_comm)); | |
af0818ef JR |
95 | if (ret) { |
96 | goto end; | |
97 | } | |
98 | ||
28ab034a | 99 | ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->pattern, pattern_len); |
af0818ef JR |
100 | if (ret) { |
101 | goto end; | |
102 | } | |
103 | ||
28ab034a JG |
104 | ret = lttng_dynamic_buffer_append( |
105 | &payload->buffer, tracepoint->filter_expression, filter_expression_len); | |
af0818ef JR |
106 | if (ret) { |
107 | goto end; | |
108 | } | |
109 | ||
110 | end: | |
111 | return ret; | |
112 | } | |
113 | ||
28ab034a JG |
114 | static bool lttng_event_rule_kernel_tracepoint_is_equal(const struct lttng_event_rule *_a, |
115 | const struct lttng_event_rule *_b) | |
af0818ef JR |
116 | { |
117 | bool is_equal = false; | |
118 | struct lttng_event_rule_kernel_tracepoint *a, *b; | |
119 | ||
0114db0e JG |
120 | a = lttng::utils::container_of(_a, <tng_event_rule_kernel_tracepoint::parent); |
121 | b = lttng::utils::container_of(_b, <tng_event_rule_kernel_tracepoint::parent); | |
af0818ef JR |
122 | |
123 | if (!!a->filter_expression != !!b->filter_expression) { | |
124 | goto end; | |
125 | } | |
126 | ||
127 | /* Long check. */ | |
a0377dfe FD |
128 | LTTNG_ASSERT(a->pattern); |
129 | LTTNG_ASSERT(b->pattern); | |
5c7248cd | 130 | if (strcmp(a->pattern, b->pattern) != 0) { |
af0818ef JR |
131 | goto end; |
132 | } | |
133 | ||
134 | if (a->filter_expression && b->filter_expression) { | |
5c7248cd | 135 | if (strcmp(a->filter_expression, b->filter_expression) != 0) { |
af0818ef JR |
136 | goto end; |
137 | } | |
138 | } else if (!!a->filter_expression != !!b->filter_expression) { | |
139 | /* One is set; not the other. */ | |
140 | goto end; | |
141 | } | |
142 | ||
143 | is_equal = true; | |
144 | end: | |
145 | return is_equal; | |
146 | } | |
147 | ||
148 | static enum lttng_error_code | |
28ab034a JG |
149 | lttng_event_rule_kernel_tracepoint_generate_filter_bytecode(struct lttng_event_rule *rule, |
150 | const struct lttng_credentials *creds) | |
af0818ef JR |
151 | { |
152 | int ret; | |
153 | enum lttng_error_code ret_code; | |
154 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
155 | enum lttng_event_rule_status status; | |
156 | const char *filter; | |
cd9adb8b | 157 | struct lttng_bytecode *bytecode = nullptr; |
af0818ef | 158 | |
a0377dfe | 159 | LTTNG_ASSERT(rule); |
af0818ef | 160 | |
28ab034a | 161 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
162 | |
163 | status = lttng_event_rule_kernel_tracepoint_get_filter(rule, &filter); | |
164 | if (status == LTTNG_EVENT_RULE_STATUS_UNSET) { | |
cd9adb8b | 165 | filter = nullptr; |
af0818ef JR |
166 | } else if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
167 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
168 | goto end; | |
169 | } | |
170 | ||
171 | if (filter && filter[0] == '\0') { | |
172 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
173 | goto error; | |
174 | } | |
175 | ||
176 | if (filter) { | |
177 | tracepoint->internal_filter.filter = strdup(filter); | |
cd9adb8b | 178 | if (tracepoint->internal_filter.filter == nullptr) { |
af0818ef JR |
179 | ret_code = LTTNG_ERR_NOMEM; |
180 | goto error; | |
181 | } | |
182 | } else { | |
cd9adb8b | 183 | tracepoint->internal_filter.filter = nullptr; |
af0818ef JR |
184 | } |
185 | ||
cd9adb8b | 186 | if (tracepoint->internal_filter.filter == nullptr) { |
af0818ef JR |
187 | ret_code = LTTNG_OK; |
188 | goto end; | |
189 | } | |
190 | ||
28ab034a | 191 | ret = run_as_generate_filter_bytecode(tracepoint->internal_filter.filter, creds, &bytecode); |
af0818ef JR |
192 | if (ret) { |
193 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
194 | goto end; | |
195 | } | |
196 | ||
197 | tracepoint->internal_filter.bytecode = bytecode; | |
cd9adb8b | 198 | bytecode = nullptr; |
af0818ef JR |
199 | ret_code = LTTNG_OK; |
200 | ||
201 | error: | |
202 | end: | |
203 | free(bytecode); | |
204 | return ret_code; | |
205 | } | |
206 | ||
28ab034a JG |
207 | static const char * |
208 | lttng_event_rule_kernel_tracepoint_get_internal_filter(const struct lttng_event_rule *rule) | |
af0818ef JR |
209 | { |
210 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
211 | ||
a0377dfe | 212 | LTTNG_ASSERT(rule); |
28ab034a | 213 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
214 | return tracepoint->internal_filter.filter; |
215 | } | |
216 | ||
217 | static const struct lttng_bytecode * | |
28ab034a | 218 | lttng_event_rule_kernel_tracepoint_get_internal_filter_bytecode(const struct lttng_event_rule *rule) |
af0818ef JR |
219 | { |
220 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
221 | ||
a0377dfe | 222 | LTTNG_ASSERT(rule); |
28ab034a | 223 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
224 | return tracepoint->internal_filter.bytecode; |
225 | } | |
226 | ||
227 | static enum lttng_event_rule_generate_exclusions_status | |
28ab034a JG |
228 | lttng_event_rule_kernel_tracepoint_generate_exclusions(const struct lttng_event_rule *rule |
229 | __attribute__((unused)), | |
230 | struct lttng_event_exclusion **_exclusions) | |
af0818ef JR |
231 | { |
232 | /* Unsupported. */ | |
cd9adb8b | 233 | *_exclusions = nullptr; |
af0818ef JR |
234 | return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE; |
235 | } | |
236 | ||
28ab034a | 237 | static unsigned long lttng_event_rule_kernel_tracepoint_hash(const struct lttng_event_rule *rule) |
af0818ef JR |
238 | { |
239 | unsigned long hash; | |
28ab034a JG |
240 | struct lttng_event_rule_kernel_tracepoint *tp_rule = |
241 | lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); | |
af0818ef | 242 | |
28ab034a | 243 | hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT, lttng_ht_seed); |
af0818ef JR |
244 | hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed); |
245 | ||
246 | if (tp_rule->filter_expression) { | |
247 | hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed); | |
248 | } | |
249 | ||
250 | return hash; | |
251 | } | |
252 | ||
28ab034a JG |
253 | static enum lttng_error_code |
254 | lttng_event_rule_kernel_tracepoint_mi_serialize(const struct lttng_event_rule *rule, | |
255 | struct mi_writer *writer) | |
6a751b95 JR |
256 | { |
257 | int ret; | |
258 | enum lttng_error_code ret_code; | |
259 | enum lttng_event_rule_status status; | |
cd9adb8b JG |
260 | const char *filter = nullptr; |
261 | const char *name_pattern = nullptr; | |
6a751b95 | 262 | |
a0377dfe FD |
263 | LTTNG_ASSERT(rule); |
264 | LTTNG_ASSERT(writer); | |
265 | LTTNG_ASSERT(IS_KERNEL_TRACEPOINT_EVENT_RULE(rule)); | |
6a751b95 | 266 | |
28ab034a | 267 | status = lttng_event_rule_kernel_tracepoint_get_name_pattern(rule, &name_pattern); |
a0377dfe FD |
268 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
269 | LTTNG_ASSERT(name_pattern); | |
6a751b95 JR |
270 | |
271 | status = lttng_event_rule_kernel_tracepoint_get_filter(rule, &filter); | |
a0377dfe | 272 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK || |
28ab034a | 273 | status == LTTNG_EVENT_RULE_STATUS_UNSET); |
6a751b95 JR |
274 | |
275 | /* Open event rule kernel tracepoint element. */ | |
28ab034a | 276 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_kernel_tracepoint); |
6a751b95 JR |
277 | if (ret) { |
278 | goto mi_error; | |
279 | } | |
280 | ||
281 | /* Name pattern. */ | |
28ab034a JG |
282 | ret = mi_lttng_writer_write_element_string( |
283 | writer, mi_lttng_element_event_rule_name_pattern, name_pattern); | |
6a751b95 JR |
284 | if (ret) { |
285 | goto mi_error; | |
286 | } | |
287 | ||
288 | /* Filter. */ | |
cd9adb8b | 289 | if (filter != nullptr) { |
28ab034a JG |
290 | ret = mi_lttng_writer_write_element_string( |
291 | writer, mi_lttng_element_event_rule_filter_expression, filter); | |
6a751b95 JR |
292 | if (ret) { |
293 | goto mi_error; | |
294 | } | |
295 | } | |
296 | ||
297 | /* Close event rule kernel tracepoint element. */ | |
298 | ret = mi_lttng_writer_close_element(writer); | |
299 | if (ret) { | |
300 | goto mi_error; | |
301 | } | |
302 | ||
303 | ret_code = LTTNG_OK; | |
304 | goto end; | |
305 | ||
306 | mi_error: | |
307 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
308 | end: | |
309 | return ret_code; | |
310 | } | |
311 | ||
af0818ef JR |
312 | struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void) |
313 | { | |
cd9adb8b | 314 | struct lttng_event_rule *rule = nullptr; |
af0818ef JR |
315 | struct lttng_event_rule_kernel_tracepoint *tp_rule; |
316 | enum lttng_event_rule_status status; | |
317 | ||
64803277 | 318 | tp_rule = zmalloc<lttng_event_rule_kernel_tracepoint>(); |
af0818ef JR |
319 | if (!tp_rule) { |
320 | goto end; | |
321 | } | |
322 | ||
323 | rule = &tp_rule->parent; | |
324 | lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT); | |
325 | tp_rule->parent.validate = lttng_event_rule_kernel_tracepoint_validate; | |
326 | tp_rule->parent.serialize = lttng_event_rule_kernel_tracepoint_serialize; | |
327 | tp_rule->parent.equal = lttng_event_rule_kernel_tracepoint_is_equal; | |
328 | tp_rule->parent.destroy = lttng_event_rule_kernel_tracepoint_destroy; | |
329 | tp_rule->parent.generate_filter_bytecode = | |
28ab034a JG |
330 | lttng_event_rule_kernel_tracepoint_generate_filter_bytecode; |
331 | tp_rule->parent.get_filter = lttng_event_rule_kernel_tracepoint_get_internal_filter; | |
af0818ef | 332 | tp_rule->parent.get_filter_bytecode = |
28ab034a | 333 | lttng_event_rule_kernel_tracepoint_get_internal_filter_bytecode; |
af0818ef | 334 | tp_rule->parent.generate_exclusions = |
28ab034a | 335 | lttng_event_rule_kernel_tracepoint_generate_exclusions; |
af0818ef | 336 | tp_rule->parent.hash = lttng_event_rule_kernel_tracepoint_hash; |
6a751b95 | 337 | tp_rule->parent.mi_serialize = lttng_event_rule_kernel_tracepoint_mi_serialize; |
af0818ef JR |
338 | |
339 | /* Not necessary for now. */ | |
cd9adb8b | 340 | tp_rule->parent.generate_lttng_event = nullptr; |
af0818ef JR |
341 | |
342 | /* Default pattern is '*'. */ | |
343 | status = lttng_event_rule_kernel_tracepoint_set_name_pattern(rule, "*"); | |
344 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { | |
345 | lttng_event_rule_destroy(rule); | |
cd9adb8b | 346 | rule = nullptr; |
af0818ef JR |
347 | } |
348 | ||
349 | end: | |
350 | return rule; | |
351 | } | |
352 | ||
28ab034a JG |
353 | ssize_t |
354 | lttng_event_rule_kernel_tracepoint_create_from_payload(struct lttng_payload_view *view, | |
355 | struct lttng_event_rule **_event_rule) | |
af0818ef JR |
356 | { |
357 | ssize_t ret, offset = 0; | |
358 | enum lttng_event_rule_status status; | |
359 | const struct lttng_event_rule_kernel_tracepoint_comm *tracepoint_comm; | |
360 | const char *pattern; | |
cd9adb8b | 361 | const char *filter_expression = nullptr; |
af0818ef | 362 | struct lttng_buffer_view current_buffer_view; |
cd9adb8b | 363 | struct lttng_event_rule *rule = nullptr; |
af0818ef JR |
364 | |
365 | if (!_event_rule) { | |
366 | ret = -1; | |
367 | goto end; | |
368 | } | |
369 | ||
28ab034a JG |
370 | current_buffer_view = |
371 | lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*tracepoint_comm)); | |
af0818ef JR |
372 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { |
373 | ERR("Failed to initialize from malformed event rule kernel tracepoint: buffer too short to contain header."); | |
374 | ret = -1; | |
375 | goto end; | |
376 | } | |
377 | ||
378 | tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data; | |
379 | ||
380 | /* Skip to payload. */ | |
381 | offset += current_buffer_view.size; | |
382 | ||
383 | /* Map the pattern. */ | |
28ab034a JG |
384 | current_buffer_view = |
385 | lttng_buffer_view_from_view(&view->buffer, offset, tracepoint_comm->pattern_len); | |
af0818ef JR |
386 | |
387 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { | |
388 | ret = -1; | |
389 | goto end; | |
390 | } | |
391 | ||
392 | pattern = current_buffer_view.data; | |
28ab034a JG |
393 | if (!lttng_buffer_view_contains_string( |
394 | ¤t_buffer_view, pattern, tracepoint_comm->pattern_len)) { | |
af0818ef JR |
395 | ret = -1; |
396 | goto end; | |
397 | } | |
398 | ||
399 | /* Skip after the pattern. */ | |
400 | offset += tracepoint_comm->pattern_len; | |
401 | ||
402 | if (!tracepoint_comm->filter_expression_len) { | |
403 | goto skip_filter_expression; | |
404 | } | |
405 | ||
406 | /* Map the filter_expression. */ | |
28ab034a JG |
407 | current_buffer_view = lttng_buffer_view_from_view( |
408 | &view->buffer, offset, tracepoint_comm->filter_expression_len); | |
af0818ef JR |
409 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { |
410 | ret = -1; | |
411 | goto end; | |
412 | } | |
413 | ||
414 | filter_expression = current_buffer_view.data; | |
415 | if (!lttng_buffer_view_contains_string(¤t_buffer_view, | |
28ab034a JG |
416 | filter_expression, |
417 | tracepoint_comm->filter_expression_len)) { | |
af0818ef JR |
418 | ret = -1; |
419 | goto end; | |
420 | } | |
421 | ||
422 | /* Skip after the pattern. */ | |
423 | offset += tracepoint_comm->filter_expression_len; | |
424 | ||
425 | skip_filter_expression: | |
426 | ||
427 | rule = lttng_event_rule_kernel_tracepoint_create(); | |
428 | if (!rule) { | |
429 | ERR("Failed to create event rule kernel tracepoint."); | |
430 | ret = -1; | |
431 | goto end; | |
432 | } | |
433 | ||
434 | status = lttng_event_rule_kernel_tracepoint_set_name_pattern(rule, pattern); | |
435 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { | |
436 | ERR("Failed to set event rule kernel tracepoint pattern."); | |
437 | ret = -1; | |
438 | goto end; | |
439 | } | |
440 | ||
441 | if (filter_expression) { | |
28ab034a | 442 | status = lttng_event_rule_kernel_tracepoint_set_filter(rule, filter_expression); |
af0818ef JR |
443 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
444 | ERR("Failed to set event rule kernel tracepoint pattern."); | |
445 | ret = -1; | |
446 | goto end; | |
447 | } | |
448 | } | |
449 | ||
450 | *_event_rule = rule; | |
cd9adb8b | 451 | rule = nullptr; |
af0818ef JR |
452 | ret = offset; |
453 | end: | |
454 | lttng_event_rule_destroy(rule); | |
455 | return ret; | |
456 | } | |
457 | ||
28ab034a JG |
458 | enum lttng_event_rule_status |
459 | lttng_event_rule_kernel_tracepoint_set_name_pattern(struct lttng_event_rule *rule, | |
460 | const char *pattern) | |
af0818ef | 461 | { |
cd9adb8b | 462 | char *pattern_copy = nullptr; |
af0818ef JR |
463 | struct lttng_event_rule_kernel_tracepoint *tracepoint; |
464 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; | |
465 | ||
28ab034a | 466 | if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) { |
af0818ef JR |
467 | status = LTTNG_EVENT_RULE_STATUS_INVALID; |
468 | goto end; | |
469 | } | |
470 | ||
28ab034a | 471 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
472 | pattern_copy = strdup(pattern); |
473 | if (!pattern_copy) { | |
474 | status = LTTNG_EVENT_RULE_STATUS_ERROR; | |
475 | goto end; | |
476 | } | |
477 | ||
478 | /* Normalize the pattern. */ | |
479 | strutils_normalize_star_glob_pattern(pattern_copy); | |
480 | ||
481 | free(tracepoint->pattern); | |
482 | ||
483 | tracepoint->pattern = pattern_copy; | |
cd9adb8b | 484 | pattern_copy = nullptr; |
af0818ef JR |
485 | end: |
486 | return status; | |
487 | } | |
488 | ||
28ab034a JG |
489 | enum lttng_event_rule_status |
490 | lttng_event_rule_kernel_tracepoint_get_name_pattern(const struct lttng_event_rule *rule, | |
491 | const char **pattern) | |
af0818ef JR |
492 | { |
493 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
494 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; | |
495 | ||
496 | if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !pattern) { | |
497 | status = LTTNG_EVENT_RULE_STATUS_INVALID; | |
498 | goto end; | |
499 | } | |
500 | ||
28ab034a | 501 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
502 | if (!tracepoint->pattern) { |
503 | status = LTTNG_EVENT_RULE_STATUS_UNSET; | |
504 | goto end; | |
505 | } | |
506 | ||
507 | *pattern = tracepoint->pattern; | |
508 | end: | |
509 | return status; | |
510 | } | |
511 | ||
28ab034a JG |
512 | enum lttng_event_rule_status |
513 | lttng_event_rule_kernel_tracepoint_set_filter(struct lttng_event_rule *rule, const char *expression) | |
af0818ef | 514 | { |
cd9adb8b | 515 | char *expression_copy = nullptr; |
af0818ef JR |
516 | struct lttng_event_rule_kernel_tracepoint *tracepoint; |
517 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; | |
518 | ||
519 | if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !expression || | |
28ab034a | 520 | strlen(expression) == 0) { |
af0818ef JR |
521 | status = LTTNG_EVENT_RULE_STATUS_INVALID; |
522 | goto end; | |
523 | } | |
524 | ||
28ab034a | 525 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
526 | expression_copy = strdup(expression); |
527 | if (!expression_copy) { | |
528 | PERROR("Failed to copy filter expression"); | |
529 | status = LTTNG_EVENT_RULE_STATUS_ERROR; | |
530 | goto end; | |
531 | } | |
532 | ||
533 | if (tracepoint->filter_expression) { | |
534 | free(tracepoint->filter_expression); | |
535 | } | |
536 | ||
537 | tracepoint->filter_expression = expression_copy; | |
cd9adb8b | 538 | expression_copy = nullptr; |
af0818ef JR |
539 | end: |
540 | return status; | |
541 | } | |
542 | ||
28ab034a JG |
543 | enum lttng_event_rule_status |
544 | lttng_event_rule_kernel_tracepoint_get_filter(const struct lttng_event_rule *rule, | |
545 | const char **expression) | |
af0818ef JR |
546 | { |
547 | struct lttng_event_rule_kernel_tracepoint *tracepoint; | |
548 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; | |
549 | ||
550 | if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !expression) { | |
551 | status = LTTNG_EVENT_RULE_STATUS_INVALID; | |
552 | goto end; | |
553 | } | |
554 | ||
28ab034a | 555 | tracepoint = lttng::utils::container_of(rule, <tng_event_rule_kernel_tracepoint::parent); |
af0818ef JR |
556 | if (!tracepoint->filter_expression) { |
557 | status = LTTNG_EVENT_RULE_STATUS_UNSET; | |
558 | goto end; | |
559 | } | |
560 | ||
561 | *expression = tracepoint->filter_expression; | |
562 | end: | |
563 | return status; | |
564 | } |