blob: 569bceff5f51ba00dc1e8b2825cb5c86a125be8f [file] [log] [blame]
Steven Rostedtf7d82352012-04-06 00:47:53 +02001/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
Jon Stanley7b9f6b42012-09-07 16:32:46 -040016 * License along with this program; if not, see <http://www.gnu.org/licenses>
Steven Rostedtf7d82352012-04-06 00:47:53 +020017 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <stdarg.h>
24#include <errno.h>
25#include <sys/types.h>
26
27#include "event-parse.h"
28#include "event-utils.h"
29
30#define COMM "COMM"
Steven Rostedt6d248fb2016-07-12 09:33:06 -040031#define CPU "CPU"
Steven Rostedtf7d82352012-04-06 00:47:53 +020032
33static struct format_field comm = {
34 .name = "COMM",
35};
36
Steven Rostedt6d248fb2016-07-12 09:33:06 -040037static struct format_field cpu = {
38 .name = "CPU",
39};
40
Steven Rostedtf7d82352012-04-06 00:47:53 +020041struct event_list {
42 struct event_list *next;
43 struct event_format *event;
44};
45
Namhyung Kimbf19b822013-12-12 16:36:17 +090046static void show_error(char *error_buf, const char *fmt, ...)
Steven Rostedtf7d82352012-04-06 00:47:53 +020047{
48 unsigned long long index;
49 const char *input;
Steven Rostedtf7d82352012-04-06 00:47:53 +020050 va_list ap;
51 int len;
52 int i;
53
Steven Rostedtf7d82352012-04-06 00:47:53 +020054 input = pevent_get_input_buf();
55 index = pevent_get_input_buf_ptr();
56 len = input ? strlen(input) : 0;
57
Steven Rostedtf7d82352012-04-06 00:47:53 +020058 if (len) {
Namhyung Kimbf19b822013-12-12 16:36:17 +090059 strcpy(error_buf, input);
60 error_buf[len] = '\n';
Steven Rostedtf7d82352012-04-06 00:47:53 +020061 for (i = 1; i < len && i < index; i++)
Namhyung Kimbf19b822013-12-12 16:36:17 +090062 error_buf[len+i] = ' ';
63 error_buf[len + i] = '^';
64 error_buf[len + i + 1] = '\n';
Steven Rostedtf7d82352012-04-06 00:47:53 +020065 len += i+2;
66 }
67
68 va_start(ap, fmt);
Namhyung Kimbf19b822013-12-12 16:36:17 +090069 vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
Steven Rostedtf7d82352012-04-06 00:47:53 +020070 va_end(ap);
Steven Rostedtf7d82352012-04-06 00:47:53 +020071}
72
73static void free_token(char *token)
74{
75 pevent_free_token(token);
76}
77
78static enum event_type read_token(char **tok)
79{
80 enum event_type type;
81 char *token = NULL;
82
83 do {
84 free_token(token);
85 type = pevent_read_token(&token);
86 } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
87
88 /* If token is = or ! check to see if the next char is ~ */
89 if (token &&
90 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
91 pevent_peek_char() == '~') {
92 /* append it */
Namhyung Kim91dfa492013-12-12 16:36:07 +090093 *tok = malloc(3);
94 if (*tok == NULL) {
95 free_token(token);
96 return EVENT_ERROR;
97 }
Steven Rostedtf7d82352012-04-06 00:47:53 +020098 sprintf(*tok, "%c%c", *token, '~');
99 free_token(token);
100 /* Now remove the '~' from the buffer */
101 pevent_read_token(&token);
102 free_token(token);
103 } else
104 *tok = token;
105
106 return type;
107}
108
109static int filter_cmp(const void *a, const void *b)
110{
111 const struct filter_type *ea = a;
112 const struct filter_type *eb = b;
113
114 if (ea->event_id < eb->event_id)
115 return -1;
116
117 if (ea->event_id > eb->event_id)
118 return 1;
119
120 return 0;
121}
122
123static struct filter_type *
124find_filter_type(struct event_filter *filter, int id)
125{
126 struct filter_type *filter_type;
127 struct filter_type key;
128
129 key.event_id = id;
130
131 filter_type = bsearch(&key, filter->event_filters,
132 filter->filters,
133 sizeof(*filter->event_filters),
134 filter_cmp);
135
136 return filter_type;
137}
138
139static struct filter_type *
140add_filter_type(struct event_filter *filter, int id)
141{
142 struct filter_type *filter_type;
143 int i;
144
145 filter_type = find_filter_type(filter, id);
146 if (filter_type)
147 return filter_type;
148
Namhyung Kimef3072c2013-12-12 16:36:05 +0900149 filter_type = realloc(filter->event_filters,
150 sizeof(*filter->event_filters) *
151 (filter->filters + 1));
152 if (!filter_type)
153 return NULL;
154
155 filter->event_filters = filter_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200156
157 for (i = 0; i < filter->filters; i++) {
158 if (filter->event_filters[i].event_id > id)
159 break;
160 }
161
162 if (i < filter->filters)
163 memmove(&filter->event_filters[i+1],
164 &filter->event_filters[i],
165 sizeof(*filter->event_filters) *
166 (filter->filters - i));
167
168 filter_type = &filter->event_filters[i];
169 filter_type->event_id = id;
170 filter_type->event = pevent_find_event(filter->pevent, id);
171 filter_type->filter = NULL;
172
173 filter->filters++;
174
175 return filter_type;
176}
177
178/**
179 * pevent_filter_alloc - create a new event filter
180 * @pevent: The pevent that this filter is associated with
181 */
182struct event_filter *pevent_filter_alloc(struct pevent *pevent)
183{
184 struct event_filter *filter;
185
Namhyung Kim4f244162013-12-09 14:34:00 +0900186 filter = malloc(sizeof(*filter));
187 if (filter == NULL)
188 return NULL;
189
Steven Rostedtf7d82352012-04-06 00:47:53 +0200190 memset(filter, 0, sizeof(*filter));
191 filter->pevent = pevent;
192 pevent_ref(pevent);
193
194 return filter;
195}
196
197static struct filter_arg *allocate_arg(void)
198{
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900199 return calloc(1, sizeof(struct filter_arg));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200200}
201
202static void free_arg(struct filter_arg *arg)
203{
204 if (!arg)
205 return;
206
207 switch (arg->type) {
208 case FILTER_ARG_NONE:
209 case FILTER_ARG_BOOLEAN:
Steven Rostedt743df752012-10-01 20:23:28 -0400210 break;
211
Steven Rostedtf7d82352012-04-06 00:47:53 +0200212 case FILTER_ARG_NUM:
Steven Rostedt743df752012-10-01 20:23:28 -0400213 free_arg(arg->num.left);
214 free_arg(arg->num.right);
215 break;
216
217 case FILTER_ARG_EXP:
218 free_arg(arg->exp.left);
219 free_arg(arg->exp.right);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200220 break;
221
222 case FILTER_ARG_STR:
223 free(arg->str.val);
224 regfree(&arg->str.reg);
225 free(arg->str.buffer);
226 break;
227
Steven Rostedt743df752012-10-01 20:23:28 -0400228 case FILTER_ARG_VALUE:
229 if (arg->value.type == FILTER_STRING ||
230 arg->value.type == FILTER_CHAR)
231 free(arg->value.str);
232 break;
233
Steven Rostedtf7d82352012-04-06 00:47:53 +0200234 case FILTER_ARG_OP:
235 free_arg(arg->op.left);
236 free_arg(arg->op.right);
237 default:
238 break;
239 }
240
241 free(arg);
242}
243
Namhyung Kim234520d2013-12-09 14:34:04 +0900244static int add_event(struct event_list **events,
Steven Rostedtf7d82352012-04-06 00:47:53 +0200245 struct event_format *event)
246{
247 struct event_list *list;
248
Namhyung Kim234520d2013-12-09 14:34:04 +0900249 list = malloc(sizeof(*list));
250 if (list == NULL)
251 return -1;
252
Steven Rostedtf7d82352012-04-06 00:47:53 +0200253 list->next = *events;
254 *events = list;
255 list->event = event;
Namhyung Kim234520d2013-12-09 14:34:04 +0900256 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200257}
258
259static int event_match(struct event_format *event,
260 regex_t *sreg, regex_t *ereg)
261{
262 if (sreg) {
263 return !regexec(sreg, event->system, 0, NULL, 0) &&
264 !regexec(ereg, event->name, 0, NULL, 0);
265 }
266
267 return !regexec(ereg, event->system, 0, NULL, 0) ||
268 !regexec(ereg, event->name, 0, NULL, 0);
269}
270
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900271static enum pevent_errno
Steven Rostedtf7d82352012-04-06 00:47:53 +0200272find_event(struct pevent *pevent, struct event_list **events,
273 char *sys_name, char *event_name)
274{
275 struct event_format *event;
276 regex_t ereg;
277 regex_t sreg;
278 int match = 0;
Namhyung Kim234520d2013-12-09 14:34:04 +0900279 int fail = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200280 char *reg;
281 int ret;
282 int i;
283
284 if (!event_name) {
285 /* if no name is given, then swap sys and name */
286 event_name = sys_name;
287 sys_name = NULL;
288 }
289
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900290 reg = malloc(strlen(event_name) + 3);
291 if (reg == NULL)
292 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
293
Steven Rostedtf7d82352012-04-06 00:47:53 +0200294 sprintf(reg, "^%s$", event_name);
295
296 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
297 free(reg);
298
299 if (ret)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900300 return PEVENT_ERRNO__INVALID_EVENT_NAME;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200301
302 if (sys_name) {
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900303 reg = malloc(strlen(sys_name) + 3);
304 if (reg == NULL) {
305 regfree(&ereg);
306 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
307 }
308
Steven Rostedtf7d82352012-04-06 00:47:53 +0200309 sprintf(reg, "^%s$", sys_name);
310 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
311 free(reg);
312 if (ret) {
313 regfree(&ereg);
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900314 return PEVENT_ERRNO__INVALID_EVENT_NAME;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200315 }
316 }
317
318 for (i = 0; i < pevent->nr_events; i++) {
319 event = pevent->events[i];
320 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
321 match = 1;
Namhyung Kim234520d2013-12-09 14:34:04 +0900322 if (add_event(events, event) < 0) {
323 fail = 1;
324 break;
325 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200326 }
327 }
328
329 regfree(&ereg);
330 if (sys_name)
331 regfree(&sreg);
332
333 if (!match)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900334 return PEVENT_ERRNO__EVENT_NOT_FOUND;
Namhyung Kim234520d2013-12-09 14:34:04 +0900335 if (fail)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900336 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200337
338 return 0;
339}
340
341static void free_events(struct event_list *events)
342{
343 struct event_list *event;
344
345 while (events) {
346 event = events;
347 events = events->next;
348 free(event);
349 }
350}
351
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900352static enum pevent_errno
Namhyung Kimeaec12d2012-05-23 11:36:56 +0900353create_arg_item(struct event_format *event, const char *token,
Namhyung Kimbf19b822013-12-12 16:36:17 +0900354 enum event_type type, struct filter_arg **parg, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200355{
356 struct format_field *field;
357 struct filter_arg *arg;
358
359 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900360 if (arg == NULL) {
361 show_error(error_str, "failed to allocate filter arg");
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900362 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900363 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200364
365 switch (type) {
366
367 case EVENT_SQUOTE:
368 case EVENT_DQUOTE:
369 arg->type = FILTER_ARG_VALUE;
370 arg->value.type =
371 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
372 arg->value.str = strdup(token);
Namhyung Kim2036fcd2013-12-09 14:34:05 +0900373 if (!arg->value.str) {
374 free_arg(arg);
375 show_error(error_str, "failed to allocate string filter arg");
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900376 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kim2036fcd2013-12-09 14:34:05 +0900377 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200378 break;
379 case EVENT_ITEM:
380 /* if it is a number, then convert it */
381 if (isdigit(token[0])) {
382 arg->type = FILTER_ARG_VALUE;
383 arg->value.type = FILTER_NUMBER;
384 arg->value.val = strtoull(token, NULL, 0);
385 break;
386 }
387 /* Consider this a field */
388 field = pevent_find_any_field(event, token);
389 if (!field) {
Steven Rostedt6d248fb2016-07-12 09:33:06 -0400390 /* If token is 'COMM' or 'CPU' then it is special */
391 if (strcmp(token, COMM) == 0) {
392 field = &comm;
393 } else if (strcmp(token, CPU) == 0) {
394 field = &cpu;
395 } else {
Steven Rostedtf7d82352012-04-06 00:47:53 +0200396 /* not a field, Make it false */
397 arg->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +0200398 arg->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200399 break;
400 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200401 }
402 arg->type = FILTER_ARG_FIELD;
403 arg->field.field = field;
404 break;
405 default:
406 free_arg(arg);
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900407 show_error(error_str, "expected a value but found %s", token);
408 return PEVENT_ERRNO__UNEXPECTED_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200409 }
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900410 *parg = arg;
411 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200412}
413
414static struct filter_arg *
415create_arg_op(enum filter_op_type btype)
416{
417 struct filter_arg *arg;
418
419 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900420 if (!arg)
421 return NULL;
422
Steven Rostedtf7d82352012-04-06 00:47:53 +0200423 arg->type = FILTER_ARG_OP;
424 arg->op.type = btype;
425
426 return arg;
427}
428
429static struct filter_arg *
430create_arg_exp(enum filter_exp_type etype)
431{
432 struct filter_arg *arg;
433
434 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900435 if (!arg)
436 return NULL;
437
Steven Rostedtf7d82352012-04-06 00:47:53 +0200438 arg->type = FILTER_ARG_EXP;
439 arg->op.type = etype;
440
441 return arg;
442}
443
444static struct filter_arg *
445create_arg_cmp(enum filter_exp_type etype)
446{
447 struct filter_arg *arg;
448
449 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900450 if (!arg)
451 return NULL;
452
Steven Rostedtf7d82352012-04-06 00:47:53 +0200453 /* Use NUM and change if necessary */
454 arg->type = FILTER_ARG_NUM;
455 arg->op.type = etype;
456
457 return arg;
458}
459
Namhyung Kim02d62d62013-12-12 16:36:09 +0900460static enum pevent_errno
Namhyung Kimbf19b822013-12-12 16:36:17 +0900461add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200462{
463 struct filter_arg *left;
464 char *str;
465 int op_type;
466 int ret;
467
468 switch (op->type) {
469 case FILTER_ARG_EXP:
470 if (op->exp.right)
471 goto out_fail;
472 op->exp.right = arg;
473 break;
474
475 case FILTER_ARG_OP:
476 if (op->op.right)
477 goto out_fail;
478 op->op.right = arg;
479 break;
480
481 case FILTER_ARG_NUM:
482 if (op->op.right)
483 goto out_fail;
484 /*
485 * The arg must be num, str, or field
486 */
487 switch (arg->type) {
488 case FILTER_ARG_VALUE:
489 case FILTER_ARG_FIELD:
490 break;
491 default:
Namhyung Kim02d62d62013-12-12 16:36:09 +0900492 show_error(error_str, "Illegal rvalue");
493 return PEVENT_ERRNO__ILLEGAL_RVALUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200494 }
495
496 /*
497 * Depending on the type, we may need to
498 * convert this to a string or regex.
499 */
500 switch (arg->value.type) {
501 case FILTER_CHAR:
502 /*
503 * A char should be converted to number if
504 * the string is 1 byte, and the compare
505 * is not a REGEX.
506 */
507 if (strlen(arg->value.str) == 1 &&
508 op->num.type != FILTER_CMP_REGEX &&
509 op->num.type != FILTER_CMP_NOT_REGEX) {
510 arg->value.type = FILTER_NUMBER;
511 goto do_int;
512 }
513 /* fall through */
514 case FILTER_STRING:
515
516 /* convert op to a string arg */
517 op_type = op->num.type;
518 left = op->num.left;
519 str = arg->value.str;
520
521 /* reset the op for the new field */
522 memset(op, 0, sizeof(*op));
523
524 /*
525 * If left arg was a field not found then
526 * NULL the entire op.
527 */
528 if (left->type == FILTER_ARG_BOOLEAN) {
529 free_arg(left);
530 free_arg(arg);
531 op->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +0200532 op->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200533 break;
534 }
535
536 /* Left arg must be a field */
537 if (left->type != FILTER_ARG_FIELD) {
538 show_error(error_str,
539 "Illegal lvalue for string comparison");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900540 return PEVENT_ERRNO__ILLEGAL_LVALUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200541 }
542
543 /* Make sure this is a valid string compare */
544 switch (op_type) {
545 case FILTER_CMP_EQ:
546 op_type = FILTER_CMP_MATCH;
547 break;
548 case FILTER_CMP_NE:
549 op_type = FILTER_CMP_NOT_MATCH;
550 break;
551
552 case FILTER_CMP_REGEX:
553 case FILTER_CMP_NOT_REGEX:
554 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
555 if (ret) {
556 show_error(error_str,
557 "RegEx '%s' did not compute",
558 str);
Namhyung Kim02d62d62013-12-12 16:36:09 +0900559 return PEVENT_ERRNO__INVALID_REGEX;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200560 }
561 break;
562 default:
563 show_error(error_str,
564 "Illegal comparison for string");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900565 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200566 }
567
568 op->type = FILTER_ARG_STR;
569 op->str.type = op_type;
570 op->str.field = left->field.field;
571 op->str.val = strdup(str);
Namhyung Kim02d62d62013-12-12 16:36:09 +0900572 if (!op->str.val) {
573 show_error(error_str, "Failed to allocate string filter");
574 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
575 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200576 /*
577 * Need a buffer to copy data for tests
578 */
Namhyung Kim02d62d62013-12-12 16:36:09 +0900579 op->str.buffer = malloc(op->str.field->size + 1);
580 if (!op->str.buffer) {
581 show_error(error_str, "Failed to allocate string filter");
582 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
583 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200584 /* Null terminate this buffer */
585 op->str.buffer[op->str.field->size] = 0;
586
587 /* We no longer have left or right args */
588 free_arg(arg);
589 free_arg(left);
590
591 break;
592
593 case FILTER_NUMBER:
594
595 do_int:
596 switch (op->num.type) {
597 case FILTER_CMP_REGEX:
598 case FILTER_CMP_NOT_REGEX:
599 show_error(error_str,
600 "Op not allowed with integers");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900601 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200602
603 default:
604 break;
605 }
606
607 /* numeric compare */
608 op->num.right = arg;
609 break;
610 default:
611 goto out_fail;
612 }
613 break;
614 default:
615 goto out_fail;
616 }
617
618 return 0;
619
620 out_fail:
Namhyung Kim02d62d62013-12-12 16:36:09 +0900621 show_error(error_str, "Syntax error");
622 return PEVENT_ERRNO__SYNTAX_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200623}
624
625static struct filter_arg *
626rotate_op_right(struct filter_arg *a, struct filter_arg *b)
627{
628 struct filter_arg *arg;
629
630 arg = a->op.right;
631 a->op.right = b;
632 return arg;
633}
634
Namhyung Kimff533fc2013-12-12 16:36:10 +0900635static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200636{
637 switch (op->type) {
638 case FILTER_ARG_EXP:
639 if (arg->type == FILTER_ARG_OP)
640 arg = rotate_op_right(arg, op);
641 op->exp.left = arg;
642 break;
643
644 case FILTER_ARG_OP:
645 op->op.left = arg;
646 break;
647 case FILTER_ARG_NUM:
648 if (arg->type == FILTER_ARG_OP)
649 arg = rotate_op_right(arg, op);
650
651 /* left arg of compares must be a field */
652 if (arg->type != FILTER_ARG_FIELD &&
653 arg->type != FILTER_ARG_BOOLEAN)
Namhyung Kimff533fc2013-12-12 16:36:10 +0900654 return PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200655 op->num.left = arg;
656 break;
657 default:
Namhyung Kimff533fc2013-12-12 16:36:10 +0900658 return PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200659 }
660 return 0;
661}
662
663enum op_type {
664 OP_NONE,
665 OP_BOOL,
666 OP_NOT,
667 OP_EXP,
668 OP_CMP,
669};
670
671static enum op_type process_op(const char *token,
672 enum filter_op_type *btype,
673 enum filter_cmp_type *ctype,
674 enum filter_exp_type *etype)
675{
676 *btype = FILTER_OP_NOT;
677 *etype = FILTER_EXP_NONE;
678 *ctype = FILTER_CMP_NONE;
679
680 if (strcmp(token, "&&") == 0)
681 *btype = FILTER_OP_AND;
682 else if (strcmp(token, "||") == 0)
683 *btype = FILTER_OP_OR;
684 else if (strcmp(token, "!") == 0)
685 return OP_NOT;
686
687 if (*btype != FILTER_OP_NOT)
688 return OP_BOOL;
689
690 /* Check for value expressions */
691 if (strcmp(token, "+") == 0) {
692 *etype = FILTER_EXP_ADD;
693 } else if (strcmp(token, "-") == 0) {
694 *etype = FILTER_EXP_SUB;
695 } else if (strcmp(token, "*") == 0) {
696 *etype = FILTER_EXP_MUL;
697 } else if (strcmp(token, "/") == 0) {
698 *etype = FILTER_EXP_DIV;
699 } else if (strcmp(token, "%") == 0) {
700 *etype = FILTER_EXP_MOD;
701 } else if (strcmp(token, ">>") == 0) {
702 *etype = FILTER_EXP_RSHIFT;
703 } else if (strcmp(token, "<<") == 0) {
704 *etype = FILTER_EXP_LSHIFT;
705 } else if (strcmp(token, "&") == 0) {
706 *etype = FILTER_EXP_AND;
707 } else if (strcmp(token, "|") == 0) {
708 *etype = FILTER_EXP_OR;
709 } else if (strcmp(token, "^") == 0) {
710 *etype = FILTER_EXP_XOR;
711 } else if (strcmp(token, "~") == 0)
712 *etype = FILTER_EXP_NOT;
713
714 if (*etype != FILTER_EXP_NONE)
715 return OP_EXP;
716
717 /* Check for compares */
718 if (strcmp(token, "==") == 0)
719 *ctype = FILTER_CMP_EQ;
720 else if (strcmp(token, "!=") == 0)
721 *ctype = FILTER_CMP_NE;
722 else if (strcmp(token, "<") == 0)
723 *ctype = FILTER_CMP_LT;
724 else if (strcmp(token, ">") == 0)
725 *ctype = FILTER_CMP_GT;
726 else if (strcmp(token, "<=") == 0)
727 *ctype = FILTER_CMP_LE;
728 else if (strcmp(token, ">=") == 0)
729 *ctype = FILTER_CMP_GE;
730 else if (strcmp(token, "=~") == 0)
731 *ctype = FILTER_CMP_REGEX;
732 else if (strcmp(token, "!~") == 0)
733 *ctype = FILTER_CMP_NOT_REGEX;
734 else
735 return OP_NONE;
736
737 return OP_CMP;
738}
739
740static int check_op_done(struct filter_arg *arg)
741{
742 switch (arg->type) {
743 case FILTER_ARG_EXP:
744 return arg->exp.right != NULL;
745
746 case FILTER_ARG_OP:
747 return arg->op.right != NULL;
748
749 case FILTER_ARG_NUM:
750 return arg->num.right != NULL;
751
752 case FILTER_ARG_STR:
753 /* A string conversion is always done */
754 return 1;
755
756 case FILTER_ARG_BOOLEAN:
757 /* field not found, is ok */
758 return 1;
759
760 default:
761 return 0;
762 }
763}
764
765enum filter_vals {
766 FILTER_VAL_NORM,
767 FILTER_VAL_FALSE,
768 FILTER_VAL_TRUE,
769};
770
Namhyung Kim7bb73552013-12-12 16:36:11 +0900771static enum pevent_errno
772reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
Namhyung Kimbf19b822013-12-12 16:36:17 +0900773 struct filter_arg *arg, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200774{
775 struct filter_arg *other_child;
776 struct filter_arg **ptr;
777
778 if (parent->type != FILTER_ARG_OP &&
Namhyung Kim7bb73552013-12-12 16:36:11 +0900779 arg->type != FILTER_ARG_OP) {
780 show_error(error_str, "can not reparent other than OP");
781 return PEVENT_ERRNO__REPARENT_NOT_OP;
782 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200783
784 /* Get the sibling */
785 if (old_child->op.right == arg) {
786 ptr = &old_child->op.right;
787 other_child = old_child->op.left;
788 } else if (old_child->op.left == arg) {
789 ptr = &old_child->op.left;
790 other_child = old_child->op.right;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900791 } else {
792 show_error(error_str, "Error in reparent op, find other child");
793 return PEVENT_ERRNO__REPARENT_FAILED;
794 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200795
796 /* Detach arg from old_child */
797 *ptr = NULL;
798
799 /* Check for root */
800 if (parent == old_child) {
801 free_arg(other_child);
802 *parent = *arg;
803 /* Free arg without recussion */
804 free(arg);
Namhyung Kim7bb73552013-12-12 16:36:11 +0900805 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200806 }
807
808 if (parent->op.right == old_child)
809 ptr = &parent->op.right;
810 else if (parent->op.left == old_child)
811 ptr = &parent->op.left;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900812 else {
813 show_error(error_str, "Error in reparent op");
814 return PEVENT_ERRNO__REPARENT_FAILED;
815 }
816
Steven Rostedtf7d82352012-04-06 00:47:53 +0200817 *ptr = arg;
818
819 free_arg(old_child);
Namhyung Kim7bb73552013-12-12 16:36:11 +0900820 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200821}
822
Namhyung Kim7bb73552013-12-12 16:36:11 +0900823/* Returns either filter_vals (success) or pevent_errno (failfure) */
824static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
Namhyung Kimbf19b822013-12-12 16:36:17 +0900825 char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200826{
Namhyung Kim7bb73552013-12-12 16:36:11 +0900827 int lval, rval;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200828
829 switch (arg->type) {
830
831 /* bad case */
832 case FILTER_ARG_BOOLEAN:
Steven Rostedt668fe012012-04-06 00:47:55 +0200833 return FILTER_VAL_FALSE + arg->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200834
835 /* good cases: */
836 case FILTER_ARG_STR:
837 case FILTER_ARG_VALUE:
838 case FILTER_ARG_FIELD:
839 return FILTER_VAL_NORM;
840
841 case FILTER_ARG_EXP:
Namhyung Kim7bb73552013-12-12 16:36:11 +0900842 lval = test_arg(arg, arg->exp.left, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200843 if (lval != FILTER_VAL_NORM)
844 return lval;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900845 rval = test_arg(arg, arg->exp.right, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200846 if (rval != FILTER_VAL_NORM)
847 return rval;
848 return FILTER_VAL_NORM;
849
850 case FILTER_ARG_NUM:
Namhyung Kim7bb73552013-12-12 16:36:11 +0900851 lval = test_arg(arg, arg->num.left, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200852 if (lval != FILTER_VAL_NORM)
853 return lval;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900854 rval = test_arg(arg, arg->num.right, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200855 if (rval != FILTER_VAL_NORM)
856 return rval;
857 return FILTER_VAL_NORM;
858
859 case FILTER_ARG_OP:
860 if (arg->op.type != FILTER_OP_NOT) {
Namhyung Kim7bb73552013-12-12 16:36:11 +0900861 lval = test_arg(arg, arg->op.left, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200862 switch (lval) {
863 case FILTER_VAL_NORM:
864 break;
865 case FILTER_VAL_TRUE:
866 if (arg->op.type == FILTER_OP_OR)
867 return FILTER_VAL_TRUE;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900868 rval = test_arg(arg, arg->op.right, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200869 if (rval != FILTER_VAL_NORM)
870 return rval;
871
Namhyung Kim7bb73552013-12-12 16:36:11 +0900872 return reparent_op_arg(parent, arg, arg->op.right,
873 error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200874
875 case FILTER_VAL_FALSE:
876 if (arg->op.type == FILTER_OP_AND)
877 return FILTER_VAL_FALSE;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900878 rval = test_arg(arg, arg->op.right, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200879 if (rval != FILTER_VAL_NORM)
880 return rval;
881
Namhyung Kim7bb73552013-12-12 16:36:11 +0900882 return reparent_op_arg(parent, arg, arg->op.right,
883 error_str);
884
885 default:
886 return lval;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200887 }
888 }
889
Namhyung Kim7bb73552013-12-12 16:36:11 +0900890 rval = test_arg(arg, arg->op.right, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200891 switch (rval) {
892 case FILTER_VAL_NORM:
Namhyung Kim7bb73552013-12-12 16:36:11 +0900893 default:
Steven Rostedtf7d82352012-04-06 00:47:53 +0200894 break;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900895
Steven Rostedtf7d82352012-04-06 00:47:53 +0200896 case FILTER_VAL_TRUE:
897 if (arg->op.type == FILTER_OP_OR)
898 return FILTER_VAL_TRUE;
899 if (arg->op.type == FILTER_OP_NOT)
900 return FILTER_VAL_FALSE;
901
Namhyung Kim7bb73552013-12-12 16:36:11 +0900902 return reparent_op_arg(parent, arg, arg->op.left,
903 error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200904
905 case FILTER_VAL_FALSE:
906 if (arg->op.type == FILTER_OP_AND)
907 return FILTER_VAL_FALSE;
908 if (arg->op.type == FILTER_OP_NOT)
909 return FILTER_VAL_TRUE;
910
Namhyung Kim7bb73552013-12-12 16:36:11 +0900911 return reparent_op_arg(parent, arg, arg->op.left,
912 error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200913 }
914
Namhyung Kim7bb73552013-12-12 16:36:11 +0900915 return rval;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200916 default:
Namhyung Kim7bb73552013-12-12 16:36:11 +0900917 show_error(error_str, "bad arg in filter tree");
918 return PEVENT_ERRNO__BAD_FILTER_ARG;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200919 }
920 return FILTER_VAL_NORM;
921}
922
923/* Remove any unknown event fields */
Namhyung Kim42d61942013-12-12 16:36:13 +0900924static int collapse_tree(struct filter_arg *arg,
Namhyung Kimbf19b822013-12-12 16:36:17 +0900925 struct filter_arg **arg_collapsed, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200926{
Namhyung Kim42d61942013-12-12 16:36:13 +0900927 int ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200928
Namhyung Kim7bb73552013-12-12 16:36:11 +0900929 ret = test_arg(arg, arg, error_str);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200930 switch (ret) {
931 case FILTER_VAL_NORM:
Namhyung Kim7bb73552013-12-12 16:36:11 +0900932 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200933
934 case FILTER_VAL_TRUE:
935 case FILTER_VAL_FALSE:
936 free_arg(arg);
937 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900938 if (arg) {
939 arg->type = FILTER_ARG_BOOLEAN;
940 arg->boolean.value = ret == FILTER_VAL_TRUE;
Namhyung Kim7bb73552013-12-12 16:36:11 +0900941 } else {
942 show_error(error_str, "Failed to allocate filter arg");
Namhyung Kim42d61942013-12-12 16:36:13 +0900943 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900944 }
Namhyung Kim7bb73552013-12-12 16:36:11 +0900945 break;
946
947 default:
948 /* test_arg() already set the error_str */
949 free_arg(arg);
950 arg = NULL;
951 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200952 }
953
Namhyung Kim42d61942013-12-12 16:36:13 +0900954 *arg_collapsed = arg;
955 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200956}
957
Namhyung Kim42d61942013-12-12 16:36:13 +0900958static enum pevent_errno
Steven Rostedtf7d82352012-04-06 00:47:53 +0200959process_filter(struct event_format *event, struct filter_arg **parg,
Namhyung Kimbf19b822013-12-12 16:36:17 +0900960 char *error_str, int not)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200961{
962 enum event_type type;
963 char *token = NULL;
964 struct filter_arg *current_op = NULL;
965 struct filter_arg *current_exp = NULL;
966 struct filter_arg *left_item = NULL;
967 struct filter_arg *arg = NULL;
968 enum op_type op_type;
969 enum filter_op_type btype;
970 enum filter_exp_type etype;
971 enum filter_cmp_type ctype;
Namhyung Kim42d61942013-12-12 16:36:13 +0900972 enum pevent_errno ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200973
974 *parg = NULL;
975
976 do {
977 free(token);
978 type = read_token(&token);
979 switch (type) {
980 case EVENT_SQUOTE:
981 case EVENT_DQUOTE:
982 case EVENT_ITEM:
Namhyung Kimc8ea6902013-12-12 16:36:12 +0900983 ret = create_arg_item(event, token, type, &arg, error_str);
984 if (ret < 0)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200985 goto fail;
986 if (!left_item)
987 left_item = arg;
988 else if (current_exp) {
989 ret = add_right(current_exp, arg, error_str);
990 if (ret < 0)
991 goto fail;
992 left_item = NULL;
993 /* Not's only one one expression */
994 if (not) {
995 arg = NULL;
996 if (current_op)
Namhyung Kim42d61942013-12-12 16:36:13 +0900997 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200998 free(token);
999 *parg = current_exp;
1000 return 0;
1001 }
1002 } else
Namhyung Kim42d61942013-12-12 16:36:13 +09001003 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001004 arg = NULL;
1005 break;
1006
1007 case EVENT_DELIM:
1008 if (*token == ',') {
Namhyung Kim42d61942013-12-12 16:36:13 +09001009 show_error(error_str, "Illegal token ','");
1010 ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001011 goto fail;
1012 }
1013
1014 if (*token == '(') {
1015 if (left_item) {
1016 show_error(error_str,
1017 "Open paren can not come after item");
Namhyung Kim42d61942013-12-12 16:36:13 +09001018 ret = PEVENT_ERRNO__INVALID_PAREN;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001019 goto fail;
1020 }
1021 if (current_exp) {
1022 show_error(error_str,
1023 "Open paren can not come after expression");
Namhyung Kim42d61942013-12-12 16:36:13 +09001024 ret = PEVENT_ERRNO__INVALID_PAREN;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001025 goto fail;
1026 }
1027
1028 ret = process_filter(event, &arg, error_str, 0);
Namhyung Kim42d61942013-12-12 16:36:13 +09001029 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
1030 if (ret == 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02001031 show_error(error_str,
1032 "Unbalanced number of '('");
Namhyung Kim42d61942013-12-12 16:36:13 +09001033 ret = PEVENT_ERRNO__UNBALANCED_PAREN;
1034 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001035 goto fail;
1036 }
1037 ret = 0;
1038
1039 /* A not wants just one expression */
1040 if (not) {
1041 if (current_op)
Namhyung Kim42d61942013-12-12 16:36:13 +09001042 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001043 *parg = arg;
1044 return 0;
1045 }
1046
1047 if (current_op)
1048 ret = add_right(current_op, arg, error_str);
1049 else
1050 current_exp = arg;
1051
1052 if (ret < 0)
1053 goto fail;
1054
1055 } else { /* ')' */
1056 if (!current_op && !current_exp)
Namhyung Kim42d61942013-12-12 16:36:13 +09001057 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001058
1059 /* Make sure everything is finished at this level */
1060 if (current_exp && !check_op_done(current_exp))
Namhyung Kim42d61942013-12-12 16:36:13 +09001061 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001062 if (current_op && !check_op_done(current_op))
Namhyung Kim42d61942013-12-12 16:36:13 +09001063 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001064
1065 if (current_op)
1066 *parg = current_op;
1067 else
1068 *parg = current_exp;
Steven Rostedt (Red Hat)e1644aa2015-03-24 09:57:57 -04001069 free(token);
Namhyung Kim42d61942013-12-12 16:36:13 +09001070 return PEVENT_ERRNO__UNBALANCED_PAREN;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001071 }
1072 break;
1073
1074 case EVENT_OP:
1075 op_type = process_op(token, &btype, &ctype, &etype);
1076
1077 /* All expect a left arg except for NOT */
1078 switch (op_type) {
1079 case OP_BOOL:
1080 /* Logic ops need a left expression */
1081 if (!current_exp && !current_op)
Namhyung Kim42d61942013-12-12 16:36:13 +09001082 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001083 /* fall through */
1084 case OP_NOT:
1085 /* logic only processes ops and exp */
1086 if (left_item)
Namhyung Kim42d61942013-12-12 16:36:13 +09001087 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001088 break;
1089 case OP_EXP:
1090 case OP_CMP:
1091 if (!left_item)
Namhyung Kim42d61942013-12-12 16:36:13 +09001092 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001093 break;
1094 case OP_NONE:
1095 show_error(error_str,
1096 "Unknown op token %s", token);
Namhyung Kim42d61942013-12-12 16:36:13 +09001097 ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001098 goto fail;
1099 }
1100
1101 ret = 0;
1102 switch (op_type) {
1103 case OP_BOOL:
1104 arg = create_arg_op(btype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001105 if (arg == NULL)
1106 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001107 if (current_op)
1108 ret = add_left(arg, current_op);
1109 else
1110 ret = add_left(arg, current_exp);
1111 current_op = arg;
1112 current_exp = NULL;
1113 break;
1114
1115 case OP_NOT:
1116 arg = create_arg_op(btype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001117 if (arg == NULL)
1118 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001119 if (current_op)
1120 ret = add_right(current_op, arg, error_str);
1121 if (ret < 0)
1122 goto fail;
1123 current_exp = arg;
1124 ret = process_filter(event, &arg, error_str, 1);
1125 if (ret < 0)
1126 goto fail;
1127 ret = add_right(current_exp, arg, error_str);
1128 if (ret < 0)
1129 goto fail;
1130 break;
1131
1132 case OP_EXP:
1133 case OP_CMP:
1134 if (op_type == OP_EXP)
1135 arg = create_arg_exp(etype);
1136 else
1137 arg = create_arg_cmp(ctype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001138 if (arg == NULL)
1139 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001140
1141 if (current_op)
1142 ret = add_right(current_op, arg, error_str);
1143 if (ret < 0)
1144 goto fail;
1145 ret = add_left(arg, left_item);
1146 if (ret < 0) {
1147 arg = NULL;
Namhyung Kim42d61942013-12-12 16:36:13 +09001148 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001149 }
1150 current_exp = arg;
1151 break;
1152 default:
1153 break;
1154 }
1155 arg = NULL;
1156 if (ret < 0)
Namhyung Kim42d61942013-12-12 16:36:13 +09001157 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001158 break;
1159 case EVENT_NONE:
1160 break;
Namhyung Kim91dfa492013-12-12 16:36:07 +09001161 case EVENT_ERROR:
1162 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001163 default:
Namhyung Kim42d61942013-12-12 16:36:13 +09001164 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001165 }
1166 } while (type != EVENT_NONE);
1167
1168 if (!current_op && !current_exp)
Namhyung Kim42d61942013-12-12 16:36:13 +09001169 goto fail_syntax;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001170
1171 if (!current_op)
1172 current_op = current_exp;
1173
Namhyung Kim42d61942013-12-12 16:36:13 +09001174 ret = collapse_tree(current_op, parg, error_str);
Steven Rostedt106b8162016-05-11 15:09:36 -04001175 /* collapse_tree() may free current_op, and updates parg accordingly */
1176 current_op = NULL;
Namhyung Kim42d61942013-12-12 16:36:13 +09001177 if (ret < 0)
Namhyung Kim7bb73552013-12-12 16:36:11 +09001178 goto fail;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001179
Steven Rostedt (Red Hat)e1644aa2015-03-24 09:57:57 -04001180 free(token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001181 return 0;
1182
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001183 fail_alloc:
1184 show_error(error_str, "failed to allocate filter arg");
Namhyung Kim42d61942013-12-12 16:36:13 +09001185 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001186 goto fail;
Namhyung Kim42d61942013-12-12 16:36:13 +09001187 fail_syntax:
Steven Rostedtf7d82352012-04-06 00:47:53 +02001188 show_error(error_str, "Syntax error");
Namhyung Kim42d61942013-12-12 16:36:13 +09001189 ret = PEVENT_ERRNO__SYNTAX_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001190 fail:
1191 free_arg(current_op);
1192 free_arg(current_exp);
1193 free_arg(arg);
1194 free(token);
Namhyung Kim42d61942013-12-12 16:36:13 +09001195 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001196}
1197
Namhyung Kim69c770a2013-12-12 16:36:14 +09001198static enum pevent_errno
Steven Rostedtf7d82352012-04-06 00:47:53 +02001199process_event(struct event_format *event, const char *filter_str,
Namhyung Kimbf19b822013-12-12 16:36:17 +09001200 struct filter_arg **parg, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001201{
1202 int ret;
1203
1204 pevent_buffer_init(filter_str, strlen(filter_str));
1205
1206 ret = process_filter(event, parg, error_str, 0);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001207 if (ret < 0)
1208 return ret;
1209
1210 /* If parg is NULL, then make it into FALSE */
1211 if (!*parg) {
1212 *parg = allocate_arg();
Namhyung Kim69c770a2013-12-12 16:36:14 +09001213 if (*parg == NULL)
1214 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1215
Steven Rostedtf7d82352012-04-06 00:47:53 +02001216 (*parg)->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +02001217 (*parg)->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001218 }
1219
1220 return 0;
1221}
1222
Namhyung Kim69c770a2013-12-12 16:36:14 +09001223static enum pevent_errno
1224filter_event(struct event_filter *filter, struct event_format *event,
Namhyung Kimbf19b822013-12-12 16:36:17 +09001225 const char *filter_str, char *error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001226{
1227 struct filter_type *filter_type;
1228 struct filter_arg *arg;
Namhyung Kim69c770a2013-12-12 16:36:14 +09001229 enum pevent_errno ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001230
1231 if (filter_str) {
1232 ret = process_event(event, filter_str, &arg, error_str);
1233 if (ret < 0)
1234 return ret;
1235
1236 } else {
1237 /* just add a TRUE arg */
1238 arg = allocate_arg();
Namhyung Kim69c770a2013-12-12 16:36:14 +09001239 if (arg == NULL)
1240 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
1241
Steven Rostedtf7d82352012-04-06 00:47:53 +02001242 arg->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +02001243 arg->boolean.value = FILTER_TRUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001244 }
1245
1246 filter_type = add_filter_type(filter, event->id);
Namhyung Kim69c770a2013-12-12 16:36:14 +09001247 if (filter_type == NULL)
1248 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kimef3072c2013-12-12 16:36:05 +09001249
Steven Rostedtf7d82352012-04-06 00:47:53 +02001250 if (filter_type->filter)
1251 free_arg(filter_type->filter);
1252 filter_type->filter = arg;
1253
1254 return 0;
1255}
1256
Namhyung Kimbf19b822013-12-12 16:36:17 +09001257static void filter_init_error_buf(struct event_filter *filter)
1258{
1259 /* clear buffer to reset show error */
1260 pevent_buffer_init("", 0);
1261 filter->error_buffer[0] = '\0';
1262}
1263
Steven Rostedtf7d82352012-04-06 00:47:53 +02001264/**
1265 * pevent_filter_add_filter_str - add a new filter
1266 * @filter: the event filter to add to
1267 * @filter_str: the filter string that contains the filter
Steven Rostedtf7d82352012-04-06 00:47:53 +02001268 *
Namhyung Kim69c770a2013-12-12 16:36:14 +09001269 * Returns 0 if the filter was successfully added or a
Namhyung Kimbf19b822013-12-12 16:36:17 +09001270 * negative error code. Use pevent_filter_strerror() to see
1271 * actual error message in case of error.
Steven Rostedtf7d82352012-04-06 00:47:53 +02001272 */
Namhyung Kim69c770a2013-12-12 16:36:14 +09001273enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
1274 const char *filter_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001275{
1276 struct pevent *pevent = filter->pevent;
1277 struct event_list *event;
1278 struct event_list *events = NULL;
1279 const char *filter_start;
1280 const char *next_event;
1281 char *this_event;
1282 char *event_name = NULL;
1283 char *sys_name = NULL;
1284 char *sp;
Namhyung Kim69c770a2013-12-12 16:36:14 +09001285 enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
Steven Rostedtf7d82352012-04-06 00:47:53 +02001286 int len;
1287 int ret;
1288
Namhyung Kimbf19b822013-12-12 16:36:17 +09001289 filter_init_error_buf(filter);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001290
Steven Rostedtf7d82352012-04-06 00:47:53 +02001291 filter_start = strchr(filter_str, ':');
1292 if (filter_start)
1293 len = filter_start - filter_str;
1294 else
1295 len = strlen(filter_str);
1296
Steven Rostedtf7d82352012-04-06 00:47:53 +02001297 do {
1298 next_event = strchr(filter_str, ',');
1299 if (next_event &&
1300 (!filter_start || next_event < filter_start))
1301 len = next_event - filter_str;
1302 else if (filter_start)
1303 len = filter_start - filter_str;
1304 else
1305 len = strlen(filter_str);
1306
Namhyung Kim28942c82013-12-09 14:34:08 +09001307 this_event = malloc(len + 1);
1308 if (this_event == NULL) {
Namhyung Kim28942c82013-12-09 14:34:08 +09001309 /* This can only happen when events is NULL, but still */
1310 free_events(events);
Namhyung Kim69c770a2013-12-12 16:36:14 +09001311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kim28942c82013-12-09 14:34:08 +09001312 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001313 memcpy(this_event, filter_str, len);
1314 this_event[len] = 0;
1315
1316 if (next_event)
1317 next_event++;
1318
1319 filter_str = next_event;
1320
1321 sys_name = strtok_r(this_event, "/", &sp);
1322 event_name = strtok_r(NULL, "/", &sp);
1323
1324 if (!sys_name) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02001325 /* This can only happen when events is NULL, but still */
1326 free_events(events);
1327 free(this_event);
Namhyung Kim69c770a2013-12-12 16:36:14 +09001328 return PEVENT_ERRNO__FILTER_NOT_FOUND;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001329 }
1330
1331 /* Find this event */
1332 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1333 if (ret < 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02001334 free_events(events);
1335 free(this_event);
Namhyung Kim69c770a2013-12-12 16:36:14 +09001336 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001337 }
1338 free(this_event);
1339 } while (filter_str);
1340
1341 /* Skip the ':' */
1342 if (filter_start)
1343 filter_start++;
1344
1345 /* filter starts here */
1346 for (event = events; event; event = event->next) {
1347 ret = filter_event(filter, event->event, filter_start,
Namhyung Kimbf19b822013-12-12 16:36:17 +09001348 filter->error_buffer);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001349 /* Failures are returned if a parse error happened */
1350 if (ret < 0)
1351 rtn = ret;
1352
1353 if (ret >= 0 && pevent->test_filters) {
1354 char *test;
1355 test = pevent_filter_make_string(filter, event->event->id);
Namhyung Kimf23b24f2013-12-17 09:02:36 +09001356 if (test) {
1357 printf(" '%s: %s'\n", event->event->name, test);
1358 free(test);
1359 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001360 }
1361 }
1362
1363 free_events(events);
1364
1365 if (rtn >= 0 && pevent->test_filters)
1366 exit(0);
1367
1368 return rtn;
1369}
1370
1371static void free_filter_type(struct filter_type *filter_type)
1372{
1373 free_arg(filter_type->filter);
1374}
1375
1376/**
Namhyung Kimbf19b822013-12-12 16:36:17 +09001377 * pevent_filter_strerror - fill error message in a buffer
1378 * @filter: the event filter contains error
1379 * @err: the error code
1380 * @buf: the buffer to be filled in
1381 * @buflen: the size of the buffer
1382 *
1383 * Returns 0 if message was filled successfully, -1 if error
1384 */
1385int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
1386 char *buf, size_t buflen)
1387{
1388 if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
1389 return -1;
1390
1391 if (strlen(filter->error_buffer) > 0) {
1392 size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
1393
1394 if (len > buflen)
1395 return -1;
1396 return 0;
1397 }
1398
1399 return pevent_strerror(filter->pevent, err, buf, buflen);
1400}
1401
1402/**
Steven Rostedtf7d82352012-04-06 00:47:53 +02001403 * pevent_filter_remove_event - remove a filter for an event
1404 * @filter: the event filter to remove from
1405 * @event_id: the event to remove a filter for
1406 *
1407 * Removes the filter saved for an event defined by @event_id
1408 * from the @filter.
1409 *
1410 * Returns 1: if an event was removed
1411 * 0: if the event was not found
1412 */
1413int pevent_filter_remove_event(struct event_filter *filter,
1414 int event_id)
1415{
1416 struct filter_type *filter_type;
1417 unsigned long len;
1418
1419 if (!filter->filters)
1420 return 0;
1421
1422 filter_type = find_filter_type(filter, event_id);
1423
1424 if (!filter_type)
1425 return 0;
1426
1427 free_filter_type(filter_type);
1428
1429 /* The filter_type points into the event_filters array */
1430 len = (unsigned long)(filter->event_filters + filter->filters) -
1431 (unsigned long)(filter_type + 1);
1432
1433 memmove(filter_type, filter_type + 1, len);
1434 filter->filters--;
1435
1436 memset(&filter->event_filters[filter->filters], 0,
1437 sizeof(*filter_type));
1438
1439 return 1;
1440}
1441
1442/**
1443 * pevent_filter_reset - clear all filters in a filter
1444 * @filter: the event filter to reset
1445 *
1446 * Removes all filters from a filter and resets it.
1447 */
1448void pevent_filter_reset(struct event_filter *filter)
1449{
1450 int i;
1451
1452 for (i = 0; i < filter->filters; i++)
1453 free_filter_type(&filter->event_filters[i]);
1454
1455 free(filter->event_filters);
1456 filter->filters = 0;
1457 filter->event_filters = NULL;
1458}
1459
1460void pevent_filter_free(struct event_filter *filter)
1461{
1462 pevent_unref(filter->pevent);
1463
1464 pevent_filter_reset(filter);
1465
1466 free(filter);
1467}
1468
1469static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1470
1471static int copy_filter_type(struct event_filter *filter,
1472 struct event_filter *source,
1473 struct filter_type *filter_type)
1474{
1475 struct filter_arg *arg;
1476 struct event_format *event;
1477 const char *sys;
1478 const char *name;
1479 char *str;
1480
1481 /* Can't assume that the pevent's are the same */
1482 sys = filter_type->event->system;
1483 name = filter_type->event->name;
1484 event = pevent_find_event_by_name(filter->pevent, sys, name);
1485 if (!event)
1486 return -1;
1487
1488 str = arg_to_str(source, filter_type->filter);
1489 if (!str)
1490 return -1;
1491
1492 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1493 /* Add trivial event */
1494 arg = allocate_arg();
Hewenliang9d47b112019-11-18 20:44:15 -05001495 if (arg == NULL) {
1496 free(str);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001497 return -1;
Hewenliang9d47b112019-11-18 20:44:15 -05001498 }
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001499
Steven Rostedtf7d82352012-04-06 00:47:53 +02001500 arg->type = FILTER_ARG_BOOLEAN;
1501 if (strcmp(str, "TRUE") == 0)
Steven Rostedt668fe012012-04-06 00:47:55 +02001502 arg->boolean.value = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001503 else
Steven Rostedt668fe012012-04-06 00:47:55 +02001504 arg->boolean.value = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001505
1506 filter_type = add_filter_type(filter, event->id);
Hewenliang9d47b112019-11-18 20:44:15 -05001507 if (filter_type == NULL) {
1508 free(str);
1509 free_arg(arg);
Namhyung Kimef3072c2013-12-12 16:36:05 +09001510 return -1;
Hewenliang9d47b112019-11-18 20:44:15 -05001511 }
Namhyung Kimef3072c2013-12-12 16:36:05 +09001512
Steven Rostedtf7d82352012-04-06 00:47:53 +02001513 filter_type->filter = arg;
1514
1515 free(str);
1516 return 0;
1517 }
1518
1519 filter_event(filter, event, str, NULL);
1520 free(str);
1521
1522 return 0;
1523}
1524
1525/**
1526 * pevent_filter_copy - copy a filter using another filter
1527 * @dest - the filter to copy to
1528 * @source - the filter to copy from
1529 *
1530 * Returns 0 on success and -1 if not all filters were copied
1531 */
1532int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1533{
1534 int ret = 0;
1535 int i;
1536
1537 pevent_filter_reset(dest);
1538
1539 for (i = 0; i < source->filters; i++) {
1540 if (copy_filter_type(dest, source, &source->event_filters[i]))
1541 ret = -1;
1542 }
1543 return ret;
1544}
1545
1546
1547/**
1548 * pevent_update_trivial - update the trivial filters with the given filter
1549 * @dest - the filter to update
1550 * @source - the filter as the source of the update
1551 * @type - the type of trivial filter to update.
1552 *
1553 * Scan dest for trivial events matching @type to replace with the source.
1554 *
1555 * Returns 0 on success and -1 if there was a problem updating, but
1556 * events may have still been updated on error.
1557 */
1558int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1559 enum filter_trivial_type type)
1560{
1561 struct pevent *src_pevent;
1562 struct pevent *dest_pevent;
1563 struct event_format *event;
1564 struct filter_type *filter_type;
1565 struct filter_arg *arg;
1566 char *str;
1567 int i;
1568
1569 src_pevent = source->pevent;
1570 dest_pevent = dest->pevent;
1571
1572 /* Do nothing if either of the filters has nothing to filter */
1573 if (!dest->filters || !source->filters)
1574 return 0;
1575
1576 for (i = 0; i < dest->filters; i++) {
1577 filter_type = &dest->event_filters[i];
1578 arg = filter_type->filter;
1579 if (arg->type != FILTER_ARG_BOOLEAN)
1580 continue;
Steven Rostedt668fe012012-04-06 00:47:55 +02001581 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1582 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
Steven Rostedtf7d82352012-04-06 00:47:53 +02001583 continue;
1584
1585 event = filter_type->event;
1586
1587 if (src_pevent != dest_pevent) {
1588 /* do a look up */
1589 event = pevent_find_event_by_name(src_pevent,
1590 event->system,
1591 event->name);
1592 if (!event)
1593 return -1;
1594 }
1595
1596 str = pevent_filter_make_string(source, event->id);
1597 if (!str)
1598 continue;
1599
1600 /* Don't bother if the filter is trivial too */
1601 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1602 filter_event(dest, event, str, NULL);
1603 free(str);
1604 }
1605 return 0;
1606}
1607
1608/**
1609 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1610 * @filter: the filter to remove trivial filters from
1611 * @type: remove only true, false, or both
1612 *
1613 * Removes filters that only contain a TRUE or FALES boolean arg.
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001614 *
1615 * Returns 0 on success and -1 if there was a problem.
Steven Rostedtf7d82352012-04-06 00:47:53 +02001616 */
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001617int pevent_filter_clear_trivial(struct event_filter *filter,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001618 enum filter_trivial_type type)
1619{
1620 struct filter_type *filter_type;
1621 int count = 0;
Namhyung Kimf6ced602012-04-24 10:29:44 +09001622 int *ids = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001623 int i;
1624
1625 if (!filter->filters)
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001626 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001627
1628 /*
1629 * Two steps, first get all ids with trivial filters.
1630 * then remove those ids.
1631 */
1632 for (i = 0; i < filter->filters; i++) {
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001633 int *new_ids;
1634
Steven Rostedtf7d82352012-04-06 00:47:53 +02001635 filter_type = &filter->event_filters[i];
1636 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1637 continue;
1638 switch (type) {
1639 case FILTER_TRIVIAL_FALSE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001640 if (filter_type->filter->boolean.value)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001641 continue;
1642 case FILTER_TRIVIAL_TRUE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001643 if (!filter_type->filter->boolean.value)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001644 continue;
1645 default:
1646 break;
1647 }
Namhyung Kimf6ced602012-04-24 10:29:44 +09001648
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001649 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1650 if (!new_ids) {
1651 free(ids);
1652 return -1;
1653 }
1654
1655 ids = new_ids;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001656 ids[count++] = filter_type->event_id;
1657 }
1658
1659 if (!count)
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001660 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001661
1662 for (i = 0; i < count; i++)
1663 pevent_filter_remove_event(filter, ids[i]);
1664
1665 free(ids);
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001666 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001667}
1668
1669/**
1670 * pevent_filter_event_has_trivial - return true event contains trivial filter
1671 * @filter: the filter with the information
1672 * @event_id: the id of the event to test
1673 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1674 *
1675 * Returns 1 if the event contains a matching trivial type
1676 * otherwise 0.
1677 */
1678int pevent_filter_event_has_trivial(struct event_filter *filter,
1679 int event_id,
1680 enum filter_trivial_type type)
1681{
1682 struct filter_type *filter_type;
1683
1684 if (!filter->filters)
1685 return 0;
1686
1687 filter_type = find_filter_type(filter, event_id);
1688
1689 if (!filter_type)
1690 return 0;
1691
1692 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1693 return 0;
1694
1695 switch (type) {
1696 case FILTER_TRIVIAL_FALSE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001697 return !filter_type->filter->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001698
1699 case FILTER_TRIVIAL_TRUE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001700 return filter_type->filter->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001701 default:
1702 return 1;
1703 }
1704}
1705
Namhyung Kim41e12e52013-12-12 16:36:15 +09001706static int test_filter(struct event_format *event, struct filter_arg *arg,
1707 struct pevent_record *record, enum pevent_errno *err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001708
1709static const char *
Steven Rostedt1c698182012-04-06 00:48:06 +02001710get_comm(struct event_format *event, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001711{
1712 const char *comm;
1713 int pid;
1714
1715 pid = pevent_data_pid(event->pevent, record);
1716 comm = pevent_data_comm_from_pid(event->pevent, pid);
1717 return comm;
1718}
1719
1720static unsigned long long
1721get_value(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001722 struct format_field *field, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001723{
1724 unsigned long long val;
1725
1726 /* Handle our dummy "comm" field */
1727 if (field == &comm) {
1728 const char *name;
1729
1730 name = get_comm(event, record);
Namhyung Kim42c59cd2012-05-26 12:41:31 +09001731 return (unsigned long)name;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001732 }
1733
Steven Rostedt6d248fb2016-07-12 09:33:06 -04001734 /* Handle our dummy "cpu" field */
1735 if (field == &cpu)
1736 return record->cpu;
1737
Steven Rostedtf7d82352012-04-06 00:47:53 +02001738 pevent_read_number_field(field, record->data, &val);
1739
1740 if (!(field->flags & FIELD_IS_SIGNED))
1741 return val;
1742
1743 switch (field->size) {
1744 case 1:
1745 return (char)val;
1746 case 2:
1747 return (short)val;
1748 case 4:
1749 return (int)val;
1750 case 8:
1751 return (long long)val;
1752 }
1753 return val;
1754}
1755
1756static unsigned long long
Namhyung Kim41e12e52013-12-12 16:36:15 +09001757get_arg_value(struct event_format *event, struct filter_arg *arg,
1758 struct pevent_record *record, enum pevent_errno *err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001759
1760static unsigned long long
Namhyung Kim41e12e52013-12-12 16:36:15 +09001761get_exp_value(struct event_format *event, struct filter_arg *arg,
1762 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001763{
1764 unsigned long long lval, rval;
1765
Namhyung Kim41e12e52013-12-12 16:36:15 +09001766 lval = get_arg_value(event, arg->exp.left, record, err);
1767 rval = get_arg_value(event, arg->exp.right, record, err);
1768
1769 if (*err) {
1770 /*
1771 * There was an error, no need to process anymore.
1772 */
1773 return 0;
1774 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001775
1776 switch (arg->exp.type) {
1777 case FILTER_EXP_ADD:
1778 return lval + rval;
1779
1780 case FILTER_EXP_SUB:
1781 return lval - rval;
1782
1783 case FILTER_EXP_MUL:
1784 return lval * rval;
1785
1786 case FILTER_EXP_DIV:
1787 return lval / rval;
1788
1789 case FILTER_EXP_MOD:
1790 return lval % rval;
1791
1792 case FILTER_EXP_RSHIFT:
1793 return lval >> rval;
1794
1795 case FILTER_EXP_LSHIFT:
1796 return lval << rval;
1797
1798 case FILTER_EXP_AND:
1799 return lval & rval;
1800
1801 case FILTER_EXP_OR:
1802 return lval | rval;
1803
1804 case FILTER_EXP_XOR:
1805 return lval ^ rval;
1806
1807 case FILTER_EXP_NOT:
1808 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001809 if (!*err)
1810 *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001811 }
1812 return 0;
1813}
1814
1815static unsigned long long
Namhyung Kim41e12e52013-12-12 16:36:15 +09001816get_arg_value(struct event_format *event, struct filter_arg *arg,
1817 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001818{
1819 switch (arg->type) {
1820 case FILTER_ARG_FIELD:
1821 return get_value(event, arg->field.field, record);
1822
1823 case FILTER_ARG_VALUE:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001824 if (arg->value.type != FILTER_NUMBER) {
1825 if (!*err)
1826 *err = PEVENT_ERRNO__NOT_A_NUMBER;
1827 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001828 return arg->value.val;
1829
1830 case FILTER_ARG_EXP:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001831 return get_exp_value(event, arg, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001832
1833 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001834 if (!*err)
1835 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001836 }
1837 return 0;
1838}
1839
Namhyung Kim41e12e52013-12-12 16:36:15 +09001840static int test_num(struct event_format *event, struct filter_arg *arg,
1841 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001842{
1843 unsigned long long lval, rval;
1844
Namhyung Kim41e12e52013-12-12 16:36:15 +09001845 lval = get_arg_value(event, arg->num.left, record, err);
1846 rval = get_arg_value(event, arg->num.right, record, err);
1847
1848 if (*err) {
1849 /*
1850 * There was an error, no need to process anymore.
1851 */
1852 return 0;
1853 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001854
1855 switch (arg->num.type) {
1856 case FILTER_CMP_EQ:
1857 return lval == rval;
1858
1859 case FILTER_CMP_NE:
1860 return lval != rval;
1861
1862 case FILTER_CMP_GT:
1863 return lval > rval;
1864
1865 case FILTER_CMP_LT:
1866 return lval < rval;
1867
1868 case FILTER_CMP_GE:
1869 return lval >= rval;
1870
1871 case FILTER_CMP_LE:
1872 return lval <= rval;
1873
1874 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001875 if (!*err)
1876 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001877 return 0;
1878 }
1879}
1880
Steven Rostedt1c698182012-04-06 00:48:06 +02001881static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001882{
Steven Rostedte84c2822012-05-22 14:45:21 +09001883 struct event_format *event;
1884 struct pevent *pevent;
1885 unsigned long long addr;
1886 const char *val = NULL;
Steven Rostedt (VMware)d23d7b02018-01-11 19:47:51 -05001887 unsigned int size;
Steven Rostedte84c2822012-05-22 14:45:21 +09001888 char hex[64];
Steven Rostedtf7d82352012-04-06 00:47:53 +02001889
Steven Rostedte84c2822012-05-22 14:45:21 +09001890 /* If the field is not a string convert it */
1891 if (arg->str.field->flags & FIELD_IS_STRING) {
1892 val = record->data + arg->str.field->offset;
Steven Rostedt (VMware)d23d7b02018-01-11 19:47:51 -05001893 size = arg->str.field->size;
1894
1895 if (arg->str.field->flags & FIELD_IS_DYNAMIC) {
1896 addr = *(unsigned int *)val;
1897 val = record->data + (addr & 0xffff);
1898 size = addr >> 16;
1899 }
Steven Rostedte84c2822012-05-22 14:45:21 +09001900
1901 /*
1902 * We need to copy the data since we can't be sure the field
1903 * is null terminated.
1904 */
Steven Rostedt (VMware)d23d7b02018-01-11 19:47:51 -05001905 if (*(val + size - 1)) {
Steven Rostedte84c2822012-05-22 14:45:21 +09001906 /* copy it */
1907 memcpy(arg->str.buffer, val, arg->str.field->size);
1908 /* the buffer is already NULL terminated */
1909 val = arg->str.buffer;
1910 }
1911
1912 } else {
1913 event = arg->str.field->event;
1914 pevent = event->pevent;
1915 addr = get_value(event, arg->str.field, record);
1916
1917 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1918 /* convert to a kernel symbol */
1919 val = pevent_find_function(pevent, addr);
1920
1921 if (val == NULL) {
1922 /* just use the hex of the string name */
1923 snprintf(hex, 64, "0x%llx", addr);
1924 val = hex;
1925 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001926 }
Steven Rostedte84c2822012-05-22 14:45:21 +09001927
Steven Rostedtf7d82352012-04-06 00:47:53 +02001928 return val;
1929}
1930
Namhyung Kim41e12e52013-12-12 16:36:15 +09001931static int test_str(struct event_format *event, struct filter_arg *arg,
1932 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001933{
1934 const char *val;
1935
1936 if (arg->str.field == &comm)
1937 val = get_comm(event, record);
1938 else
1939 val = get_field_str(arg, record);
1940
1941 switch (arg->str.type) {
1942 case FILTER_CMP_MATCH:
1943 return strcmp(val, arg->str.val) == 0;
1944
1945 case FILTER_CMP_NOT_MATCH:
1946 return strcmp(val, arg->str.val) != 0;
1947
1948 case FILTER_CMP_REGEX:
1949 /* Returns zero on match */
1950 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1951
1952 case FILTER_CMP_NOT_REGEX:
1953 return regexec(&arg->str.reg, val, 0, NULL, 0);
1954
1955 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001956 if (!*err)
1957 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001958 return 0;
1959 }
1960}
1961
Namhyung Kim41e12e52013-12-12 16:36:15 +09001962static int test_op(struct event_format *event, struct filter_arg *arg,
1963 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001964{
1965 switch (arg->op.type) {
1966 case FILTER_OP_AND:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001967 return test_filter(event, arg->op.left, record, err) &&
1968 test_filter(event, arg->op.right, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001969
1970 case FILTER_OP_OR:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001971 return test_filter(event, arg->op.left, record, err) ||
1972 test_filter(event, arg->op.right, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001973
1974 case FILTER_OP_NOT:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001975 return !test_filter(event, arg->op.right, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001976
1977 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09001978 if (!*err)
1979 *err = PEVENT_ERRNO__INVALID_OP_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001980 return 0;
1981 }
1982}
1983
Namhyung Kim41e12e52013-12-12 16:36:15 +09001984static int test_filter(struct event_format *event, struct filter_arg *arg,
1985 struct pevent_record *record, enum pevent_errno *err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001986{
Namhyung Kim41e12e52013-12-12 16:36:15 +09001987 if (*err) {
1988 /*
1989 * There was an error, no need to process anymore.
1990 */
1991 return 0;
1992 }
1993
Steven Rostedtf7d82352012-04-06 00:47:53 +02001994 switch (arg->type) {
1995 case FILTER_ARG_BOOLEAN:
1996 /* easy case */
Steven Rostedt668fe012012-04-06 00:47:55 +02001997 return arg->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001998
1999 case FILTER_ARG_OP:
Namhyung Kim41e12e52013-12-12 16:36:15 +09002000 return test_op(event, arg, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002001
2002 case FILTER_ARG_NUM:
Namhyung Kim41e12e52013-12-12 16:36:15 +09002003 return test_num(event, arg, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002004
2005 case FILTER_ARG_STR:
Namhyung Kim41e12e52013-12-12 16:36:15 +09002006 return test_str(event, arg, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002007
2008 case FILTER_ARG_EXP:
2009 case FILTER_ARG_VALUE:
2010 case FILTER_ARG_FIELD:
2011 /*
2012 * Expressions, fields and values evaluate
2013 * to true if they return non zero
2014 */
Namhyung Kim41e12e52013-12-12 16:36:15 +09002015 return !!get_arg_value(event, arg, record, err);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002016
2017 default:
Namhyung Kim41e12e52013-12-12 16:36:15 +09002018 if (!*err)
2019 *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002020 return 0;
2021 }
2022}
2023
2024/**
2025 * pevent_event_filtered - return true if event has filter
2026 * @filter: filter struct with filter information
2027 * @event_id: event id to test if filter exists
2028 *
2029 * Returns 1 if filter found for @event_id
2030 * otherwise 0;
2031 */
Namhyung Kim41e12e52013-12-12 16:36:15 +09002032int pevent_event_filtered(struct event_filter *filter, int event_id)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002033{
2034 struct filter_type *filter_type;
2035
2036 if (!filter->filters)
2037 return 0;
2038
2039 filter_type = find_filter_type(filter, event_id);
2040
2041 return filter_type ? 1 : 0;
2042}
2043
2044/**
2045 * pevent_filter_match - test if a record matches a filter
2046 * @filter: filter struct with filter information
2047 * @record: the record to test against the filter
2048 *
Namhyung Kim41e12e52013-12-12 16:36:15 +09002049 * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
2050 * FILTER_MATCH - filter found for event and @record matches
2051 * FILTER_MISS - filter found for event and @record does not match
2052 * FILTER_NOT_FOUND - no filter found for @record's event
2053 * NO_FILTER - if no filters exist
2054 * otherwise - error occurred during test
Steven Rostedtf7d82352012-04-06 00:47:53 +02002055 */
Namhyung Kim41e12e52013-12-12 16:36:15 +09002056enum pevent_errno pevent_filter_match(struct event_filter *filter,
2057 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002058{
2059 struct pevent *pevent = filter->pevent;
2060 struct filter_type *filter_type;
2061 int event_id;
Namhyung Kim41e12e52013-12-12 16:36:15 +09002062 int ret;
2063 enum pevent_errno err = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002064
Namhyung Kimbf19b822013-12-12 16:36:17 +09002065 filter_init_error_buf(filter);
2066
Steven Rostedtf7d82352012-04-06 00:47:53 +02002067 if (!filter->filters)
Namhyung Kim41e12e52013-12-12 16:36:15 +09002068 return PEVENT_ERRNO__NO_FILTER;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002069
2070 event_id = pevent_data_type(pevent, record);
2071
2072 filter_type = find_filter_type(filter, event_id);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002073 if (!filter_type)
Namhyung Kim41e12e52013-12-12 16:36:15 +09002074 return PEVENT_ERRNO__FILTER_NOT_FOUND;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002075
Namhyung Kim41e12e52013-12-12 16:36:15 +09002076 ret = test_filter(filter_type->event, filter_type->filter, record, &err);
2077 if (err)
2078 return err;
2079
2080 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002081}
2082
2083static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2084{
2085 char *str = NULL;
2086 char *left = NULL;
2087 char *right = NULL;
2088 char *op = NULL;
2089 int left_val = -1;
2090 int right_val = -1;
2091 int val;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002092
2093 switch (arg->op.type) {
2094 case FILTER_OP_AND:
2095 op = "&&";
2096 /* fall through */
2097 case FILTER_OP_OR:
2098 if (!op)
2099 op = "||";
2100
2101 left = arg_to_str(filter, arg->op.left);
2102 right = arg_to_str(filter, arg->op.right);
2103 if (!left || !right)
2104 break;
2105
2106 /* Try to consolidate boolean values */
2107 if (strcmp(left, "TRUE") == 0)
2108 left_val = 1;
2109 else if (strcmp(left, "FALSE") == 0)
2110 left_val = 0;
2111
2112 if (strcmp(right, "TRUE") == 0)
2113 right_val = 1;
2114 else if (strcmp(right, "FALSE") == 0)
2115 right_val = 0;
2116
2117 if (left_val >= 0) {
2118 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2119 (arg->op.type == FILTER_OP_OR && left_val)) {
2120 /* Just return left value */
2121 str = left;
2122 left = NULL;
2123 break;
2124 }
2125 if (right_val >= 0) {
2126 /* just evaluate this. */
2127 val = 0;
2128 switch (arg->op.type) {
2129 case FILTER_OP_AND:
2130 val = left_val && right_val;
2131 break;
2132 case FILTER_OP_OR:
2133 val = left_val || right_val;
2134 break;
2135 default:
2136 break;
2137 }
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002138 asprintf(&str, val ? "TRUE" : "FALSE");
Steven Rostedtf7d82352012-04-06 00:47:53 +02002139 break;
2140 }
2141 }
2142 if (right_val >= 0) {
2143 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2144 (arg->op.type == FILTER_OP_OR && right_val)) {
2145 /* Just return right value */
2146 str = right;
2147 right = NULL;
2148 break;
2149 }
2150 /* The right value is meaningless */
2151 str = left;
2152 left = NULL;
2153 break;
2154 }
2155
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002156 asprintf(&str, "(%s) %s (%s)", left, op, right);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002157 break;
2158
2159 case FILTER_OP_NOT:
2160 op = "!";
2161 right = arg_to_str(filter, arg->op.right);
2162 if (!right)
2163 break;
2164
2165 /* See if we can consolidate */
2166 if (strcmp(right, "TRUE") == 0)
2167 right_val = 1;
2168 else if (strcmp(right, "FALSE") == 0)
2169 right_val = 0;
2170 if (right_val >= 0) {
2171 /* just return the opposite */
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002172 asprintf(&str, right_val ? "FALSE" : "TRUE");
Steven Rostedtf7d82352012-04-06 00:47:53 +02002173 break;
2174 }
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002175 asprintf(&str, "%s(%s)", op, right);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002176 break;
2177
2178 default:
2179 /* ?? */
2180 break;
2181 }
2182 free(left);
2183 free(right);
2184 return str;
2185}
2186
2187static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2188{
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002189 char *str = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002190
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002191 asprintf(&str, "%lld", arg->value.val);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002192
2193 return str;
2194}
2195
2196static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2197{
2198 return strdup(arg->field.field->name);
2199}
2200
2201static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2202{
2203 char *lstr;
2204 char *rstr;
2205 char *op;
Namhyung Kim0fed4832012-04-23 13:58:38 +09002206 char *str = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002207
2208 lstr = arg_to_str(filter, arg->exp.left);
2209 rstr = arg_to_str(filter, arg->exp.right);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002210 if (!lstr || !rstr)
2211 goto out;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002212
2213 switch (arg->exp.type) {
2214 case FILTER_EXP_ADD:
2215 op = "+";
2216 break;
2217 case FILTER_EXP_SUB:
2218 op = "-";
2219 break;
2220 case FILTER_EXP_MUL:
2221 op = "*";
2222 break;
2223 case FILTER_EXP_DIV:
2224 op = "/";
2225 break;
2226 case FILTER_EXP_MOD:
2227 op = "%";
2228 break;
2229 case FILTER_EXP_RSHIFT:
2230 op = ">>";
2231 break;
2232 case FILTER_EXP_LSHIFT:
2233 op = "<<";
2234 break;
2235 case FILTER_EXP_AND:
2236 op = "&";
2237 break;
2238 case FILTER_EXP_OR:
2239 op = "|";
2240 break;
2241 case FILTER_EXP_XOR:
2242 op = "^";
2243 break;
2244 default:
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002245 op = "[ERROR IN EXPRESSION TYPE]";
2246 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002247 }
2248
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002249 asprintf(&str, "%s %s %s", lstr, op, rstr);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002250out:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002251 free(lstr);
2252 free(rstr);
2253
2254 return str;
2255}
2256
2257static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2258{
2259 char *lstr;
2260 char *rstr;
2261 char *str = NULL;
2262 char *op = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002263
2264 lstr = arg_to_str(filter, arg->num.left);
2265 rstr = arg_to_str(filter, arg->num.right);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002266 if (!lstr || !rstr)
2267 goto out;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002268
2269 switch (arg->num.type) {
2270 case FILTER_CMP_EQ:
2271 op = "==";
2272 /* fall through */
2273 case FILTER_CMP_NE:
2274 if (!op)
2275 op = "!=";
2276 /* fall through */
2277 case FILTER_CMP_GT:
2278 if (!op)
2279 op = ">";
2280 /* fall through */
2281 case FILTER_CMP_LT:
2282 if (!op)
2283 op = "<";
2284 /* fall through */
2285 case FILTER_CMP_GE:
2286 if (!op)
2287 op = ">=";
2288 /* fall through */
2289 case FILTER_CMP_LE:
2290 if (!op)
2291 op = "<=";
2292
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002293 asprintf(&str, "%s %s %s", lstr, op, rstr);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002294 break;
2295
2296 default:
2297 /* ?? */
2298 break;
2299 }
2300
Namhyung Kim0fed4832012-04-23 13:58:38 +09002301out:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002302 free(lstr);
2303 free(rstr);
2304 return str;
2305}
2306
2307static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2308{
2309 char *str = NULL;
2310 char *op = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002311
2312 switch (arg->str.type) {
2313 case FILTER_CMP_MATCH:
2314 op = "==";
2315 /* fall through */
2316 case FILTER_CMP_NOT_MATCH:
2317 if (!op)
2318 op = "!=";
2319 /* fall through */
2320 case FILTER_CMP_REGEX:
2321 if (!op)
2322 op = "=~";
2323 /* fall through */
2324 case FILTER_CMP_NOT_REGEX:
2325 if (!op)
2326 op = "!~";
2327
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002328 asprintf(&str, "%s %s \"%s\"",
2329 arg->str.field->name, op, arg->str.val);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002330 break;
2331
2332 default:
2333 /* ?? */
2334 break;
2335 }
2336 return str;
2337}
2338
2339static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2340{
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002341 char *str = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002342
2343 switch (arg->type) {
2344 case FILTER_ARG_BOOLEAN:
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002345 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE");
Steven Rostedtf7d82352012-04-06 00:47:53 +02002346 return str;
2347
2348 case FILTER_ARG_OP:
2349 return op_to_str(filter, arg);
2350
2351 case FILTER_ARG_NUM:
2352 return num_to_str(filter, arg);
2353
2354 case FILTER_ARG_STR:
2355 return str_to_str(filter, arg);
2356
2357 case FILTER_ARG_VALUE:
2358 return val_to_str(filter, arg);
2359
2360 case FILTER_ARG_FIELD:
2361 return field_to_str(filter, arg);
2362
2363 case FILTER_ARG_EXP:
2364 return exp_to_str(filter, arg);
2365
2366 default:
2367 /* ?? */
2368 return NULL;
2369 }
2370
2371}
2372
2373/**
2374 * pevent_filter_make_string - return a string showing the filter
2375 * @filter: filter struct with filter information
2376 * @event_id: the event id to return the filter string with
2377 *
2378 * Returns a string that displays the filter contents.
2379 * This string must be freed with free(str).
Namhyung Kimf23b24f2013-12-17 09:02:36 +09002380 * NULL is returned if no filter is found or allocation failed.
Steven Rostedtf7d82352012-04-06 00:47:53 +02002381 */
2382char *
2383pevent_filter_make_string(struct event_filter *filter, int event_id)
2384{
2385 struct filter_type *filter_type;
2386
2387 if (!filter->filters)
2388 return NULL;
2389
2390 filter_type = find_filter_type(filter, event_id);
2391
2392 if (!filter_type)
2393 return NULL;
2394
2395 return arg_to_str(filter, filter_type->filter);
2396}
2397
2398/**
2399 * pevent_filter_compare - compare two filters and return if they are the same
2400 * @filter1: Filter to compare with @filter2
2401 * @filter2: Filter to compare with @filter1
2402 *
2403 * Returns:
2404 * 1 if the two filters hold the same content.
2405 * 0 if they do not.
2406 */
2407int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2408{
2409 struct filter_type *filter_type1;
2410 struct filter_type *filter_type2;
2411 char *str1, *str2;
2412 int result;
2413 int i;
2414
2415 /* Do the easy checks first */
2416 if (filter1->filters != filter2->filters)
2417 return 0;
2418 if (!filter1->filters && !filter2->filters)
2419 return 1;
2420
2421 /*
2422 * Now take a look at each of the events to see if they have the same
2423 * filters to them.
2424 */
2425 for (i = 0; i < filter1->filters; i++) {
2426 filter_type1 = &filter1->event_filters[i];
2427 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2428 if (!filter_type2)
2429 break;
2430 if (filter_type1->filter->type != filter_type2->filter->type)
2431 break;
2432 switch (filter_type1->filter->type) {
2433 case FILTER_TRIVIAL_FALSE:
2434 case FILTER_TRIVIAL_TRUE:
2435 /* trivial types just need the type compared */
2436 continue;
2437 default:
2438 break;
2439 }
2440 /* The best way to compare complex filters is with strings */
2441 str1 = arg_to_str(filter1, filter_type1->filter);
2442 str2 = arg_to_str(filter2, filter_type2->filter);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002443 if (str1 && str2)
2444 result = strcmp(str1, str2) != 0;
2445 else
2446 /* bail out if allocation fails */
2447 result = 1;
2448
Steven Rostedtf7d82352012-04-06 00:47:53 +02002449 free(str1);
2450 free(str2);
2451 if (result)
2452 break;
2453 }
2454
2455 if (i < filter1->filters)
2456 return 0;
2457 return 1;
2458}
2459