blob: 774c3e4c1d9fe53bcd6405d039b4365644a40f1c [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"
31
32static struct format_field comm = {
33 .name = "COMM",
34};
35
36struct event_list {
37 struct event_list *next;
38 struct event_format *event;
39};
40
41#define MAX_ERR_STR_SIZE 256
42
43static void show_error(char **error_str, const char *fmt, ...)
44{
45 unsigned long long index;
46 const char *input;
47 char *error;
48 va_list ap;
49 int len;
50 int i;
51
52 if (!error_str)
53 return;
54
55 input = pevent_get_input_buf();
56 index = pevent_get_input_buf_ptr();
57 len = input ? strlen(input) : 0;
58
Namhyung Kim9451a2f2013-12-12 16:36:04 +090059 error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
60 if (error == NULL) {
61 /*
62 * Maybe it's due to len is too long.
63 * Retry without the input buffer part.
64 */
65 len = 0;
66
67 error = malloc(MAX_ERR_STR_SIZE);
68 if (error == NULL) {
69 /* no memory */
70 *error_str = NULL;
71 return;
72 }
73 }
Steven Rostedtf7d82352012-04-06 00:47:53 +020074
75 if (len) {
76 strcpy(error, input);
77 error[len] = '\n';
78 for (i = 1; i < len && i < index; i++)
79 error[len+i] = ' ';
80 error[len + i] = '^';
81 error[len + i + 1] = '\n';
82 len += i+2;
83 }
84
85 va_start(ap, fmt);
86 vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
87 va_end(ap);
88
89 *error_str = error;
90}
91
92static void free_token(char *token)
93{
94 pevent_free_token(token);
95}
96
97static enum event_type read_token(char **tok)
98{
99 enum event_type type;
100 char *token = NULL;
101
102 do {
103 free_token(token);
104 type = pevent_read_token(&token);
105 } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
106
107 /* If token is = or ! check to see if the next char is ~ */
108 if (token &&
109 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
110 pevent_peek_char() == '~') {
111 /* append it */
Namhyung Kim91dfa492013-12-12 16:36:07 +0900112 *tok = malloc(3);
113 if (*tok == NULL) {
114 free_token(token);
115 return EVENT_ERROR;
116 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200117 sprintf(*tok, "%c%c", *token, '~');
118 free_token(token);
119 /* Now remove the '~' from the buffer */
120 pevent_read_token(&token);
121 free_token(token);
122 } else
123 *tok = token;
124
125 return type;
126}
127
128static int filter_cmp(const void *a, const void *b)
129{
130 const struct filter_type *ea = a;
131 const struct filter_type *eb = b;
132
133 if (ea->event_id < eb->event_id)
134 return -1;
135
136 if (ea->event_id > eb->event_id)
137 return 1;
138
139 return 0;
140}
141
142static struct filter_type *
143find_filter_type(struct event_filter *filter, int id)
144{
145 struct filter_type *filter_type;
146 struct filter_type key;
147
148 key.event_id = id;
149
150 filter_type = bsearch(&key, filter->event_filters,
151 filter->filters,
152 sizeof(*filter->event_filters),
153 filter_cmp);
154
155 return filter_type;
156}
157
158static struct filter_type *
159add_filter_type(struct event_filter *filter, int id)
160{
161 struct filter_type *filter_type;
162 int i;
163
164 filter_type = find_filter_type(filter, id);
165 if (filter_type)
166 return filter_type;
167
Namhyung Kimef3072c2013-12-12 16:36:05 +0900168 filter_type = realloc(filter->event_filters,
169 sizeof(*filter->event_filters) *
170 (filter->filters + 1));
171 if (!filter_type)
172 return NULL;
173
174 filter->event_filters = filter_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200175
176 for (i = 0; i < filter->filters; i++) {
177 if (filter->event_filters[i].event_id > id)
178 break;
179 }
180
181 if (i < filter->filters)
182 memmove(&filter->event_filters[i+1],
183 &filter->event_filters[i],
184 sizeof(*filter->event_filters) *
185 (filter->filters - i));
186
187 filter_type = &filter->event_filters[i];
188 filter_type->event_id = id;
189 filter_type->event = pevent_find_event(filter->pevent, id);
190 filter_type->filter = NULL;
191
192 filter->filters++;
193
194 return filter_type;
195}
196
197/**
198 * pevent_filter_alloc - create a new event filter
199 * @pevent: The pevent that this filter is associated with
200 */
201struct event_filter *pevent_filter_alloc(struct pevent *pevent)
202{
203 struct event_filter *filter;
204
Namhyung Kim4f244162013-12-09 14:34:00 +0900205 filter = malloc(sizeof(*filter));
206 if (filter == NULL)
207 return NULL;
208
Steven Rostedtf7d82352012-04-06 00:47:53 +0200209 memset(filter, 0, sizeof(*filter));
210 filter->pevent = pevent;
211 pevent_ref(pevent);
212
213 return filter;
214}
215
216static struct filter_arg *allocate_arg(void)
217{
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900218 return calloc(1, sizeof(struct filter_arg));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200219}
220
221static void free_arg(struct filter_arg *arg)
222{
223 if (!arg)
224 return;
225
226 switch (arg->type) {
227 case FILTER_ARG_NONE:
228 case FILTER_ARG_BOOLEAN:
Steven Rostedt743df752012-10-01 20:23:28 -0400229 break;
230
Steven Rostedtf7d82352012-04-06 00:47:53 +0200231 case FILTER_ARG_NUM:
Steven Rostedt743df752012-10-01 20:23:28 -0400232 free_arg(arg->num.left);
233 free_arg(arg->num.right);
234 break;
235
236 case FILTER_ARG_EXP:
237 free_arg(arg->exp.left);
238 free_arg(arg->exp.right);
Steven Rostedtf7d82352012-04-06 00:47:53 +0200239 break;
240
241 case FILTER_ARG_STR:
242 free(arg->str.val);
243 regfree(&arg->str.reg);
244 free(arg->str.buffer);
245 break;
246
Steven Rostedt743df752012-10-01 20:23:28 -0400247 case FILTER_ARG_VALUE:
248 if (arg->value.type == FILTER_STRING ||
249 arg->value.type == FILTER_CHAR)
250 free(arg->value.str);
251 break;
252
Steven Rostedtf7d82352012-04-06 00:47:53 +0200253 case FILTER_ARG_OP:
254 free_arg(arg->op.left);
255 free_arg(arg->op.right);
256 default:
257 break;
258 }
259
260 free(arg);
261}
262
Namhyung Kim234520d2013-12-09 14:34:04 +0900263static int add_event(struct event_list **events,
Steven Rostedtf7d82352012-04-06 00:47:53 +0200264 struct event_format *event)
265{
266 struct event_list *list;
267
Namhyung Kim234520d2013-12-09 14:34:04 +0900268 list = malloc(sizeof(*list));
269 if (list == NULL)
270 return -1;
271
Steven Rostedtf7d82352012-04-06 00:47:53 +0200272 list->next = *events;
273 *events = list;
274 list->event = event;
Namhyung Kim234520d2013-12-09 14:34:04 +0900275 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200276}
277
278static int event_match(struct event_format *event,
279 regex_t *sreg, regex_t *ereg)
280{
281 if (sreg) {
282 return !regexec(sreg, event->system, 0, NULL, 0) &&
283 !regexec(ereg, event->name, 0, NULL, 0);
284 }
285
286 return !regexec(ereg, event->system, 0, NULL, 0) ||
287 !regexec(ereg, event->name, 0, NULL, 0);
288}
289
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900290static enum pevent_errno
Steven Rostedtf7d82352012-04-06 00:47:53 +0200291find_event(struct pevent *pevent, struct event_list **events,
292 char *sys_name, char *event_name)
293{
294 struct event_format *event;
295 regex_t ereg;
296 regex_t sreg;
297 int match = 0;
Namhyung Kim234520d2013-12-09 14:34:04 +0900298 int fail = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200299 char *reg;
300 int ret;
301 int i;
302
303 if (!event_name) {
304 /* if no name is given, then swap sys and name */
305 event_name = sys_name;
306 sys_name = NULL;
307 }
308
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900309 reg = malloc(strlen(event_name) + 3);
310 if (reg == NULL)
311 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
312
Steven Rostedtf7d82352012-04-06 00:47:53 +0200313 sprintf(reg, "^%s$", event_name);
314
315 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
316 free(reg);
317
318 if (ret)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900319 return PEVENT_ERRNO__INVALID_EVENT_NAME;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200320
321 if (sys_name) {
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900322 reg = malloc(strlen(sys_name) + 3);
323 if (reg == NULL) {
324 regfree(&ereg);
325 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
326 }
327
Steven Rostedtf7d82352012-04-06 00:47:53 +0200328 sprintf(reg, "^%s$", sys_name);
329 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
330 free(reg);
331 if (ret) {
332 regfree(&ereg);
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900333 return PEVENT_ERRNO__INVALID_EVENT_NAME;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200334 }
335 }
336
337 for (i = 0; i < pevent->nr_events; i++) {
338 event = pevent->events[i];
339 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
340 match = 1;
Namhyung Kim234520d2013-12-09 14:34:04 +0900341 if (add_event(events, event) < 0) {
342 fail = 1;
343 break;
344 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200345 }
346 }
347
348 regfree(&ereg);
349 if (sys_name)
350 regfree(&sreg);
351
352 if (!match)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900353 return PEVENT_ERRNO__EVENT_NOT_FOUND;
Namhyung Kim234520d2013-12-09 14:34:04 +0900354 if (fail)
Namhyung Kim605b8fd2013-12-12 16:36:08 +0900355 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200356
357 return 0;
358}
359
360static void free_events(struct event_list *events)
361{
362 struct event_list *event;
363
364 while (events) {
365 event = events;
366 events = events->next;
367 free(event);
368 }
369}
370
371static struct filter_arg *
Namhyung Kimeaec12d2012-05-23 11:36:56 +0900372create_arg_item(struct event_format *event, const char *token,
373 enum event_type type, char **error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200374{
375 struct format_field *field;
376 struct filter_arg *arg;
377
378 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900379 if (arg == NULL) {
380 show_error(error_str, "failed to allocate filter arg");
381 return NULL;
382 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200383
384 switch (type) {
385
386 case EVENT_SQUOTE:
387 case EVENT_DQUOTE:
388 arg->type = FILTER_ARG_VALUE;
389 arg->value.type =
390 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
391 arg->value.str = strdup(token);
Namhyung Kim2036fcd2013-12-09 14:34:05 +0900392 if (!arg->value.str) {
393 free_arg(arg);
394 show_error(error_str, "failed to allocate string filter arg");
395 return NULL;
396 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200397 break;
398 case EVENT_ITEM:
399 /* if it is a number, then convert it */
400 if (isdigit(token[0])) {
401 arg->type = FILTER_ARG_VALUE;
402 arg->value.type = FILTER_NUMBER;
403 arg->value.val = strtoull(token, NULL, 0);
404 break;
405 }
406 /* Consider this a field */
407 field = pevent_find_any_field(event, token);
408 if (!field) {
409 if (strcmp(token, COMM) != 0) {
410 /* not a field, Make it false */
411 arg->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +0200412 arg->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200413 break;
414 }
415 /* If token is 'COMM' then it is special */
416 field = &comm;
417 }
418 arg->type = FILTER_ARG_FIELD;
419 arg->field.field = field;
420 break;
421 default:
422 free_arg(arg);
423 show_error(error_str, "expected a value but found %s",
424 token);
425 return NULL;
426 }
427 return arg;
428}
429
430static struct filter_arg *
431create_arg_op(enum filter_op_type btype)
432{
433 struct filter_arg *arg;
434
435 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900436 if (!arg)
437 return NULL;
438
Steven Rostedtf7d82352012-04-06 00:47:53 +0200439 arg->type = FILTER_ARG_OP;
440 arg->op.type = btype;
441
442 return arg;
443}
444
445static struct filter_arg *
446create_arg_exp(enum filter_exp_type etype)
447{
448 struct filter_arg *arg;
449
450 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900451 if (!arg)
452 return NULL;
453
Steven Rostedtf7d82352012-04-06 00:47:53 +0200454 arg->type = FILTER_ARG_EXP;
455 arg->op.type = etype;
456
457 return arg;
458}
459
460static struct filter_arg *
461create_arg_cmp(enum filter_exp_type etype)
462{
463 struct filter_arg *arg;
464
465 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900466 if (!arg)
467 return NULL;
468
Steven Rostedtf7d82352012-04-06 00:47:53 +0200469 /* Use NUM and change if necessary */
470 arg->type = FILTER_ARG_NUM;
471 arg->op.type = etype;
472
473 return arg;
474}
475
Namhyung Kim02d62d62013-12-12 16:36:09 +0900476static enum pevent_errno
477add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200478{
479 struct filter_arg *left;
480 char *str;
481 int op_type;
482 int ret;
483
484 switch (op->type) {
485 case FILTER_ARG_EXP:
486 if (op->exp.right)
487 goto out_fail;
488 op->exp.right = arg;
489 break;
490
491 case FILTER_ARG_OP:
492 if (op->op.right)
493 goto out_fail;
494 op->op.right = arg;
495 break;
496
497 case FILTER_ARG_NUM:
498 if (op->op.right)
499 goto out_fail;
500 /*
501 * The arg must be num, str, or field
502 */
503 switch (arg->type) {
504 case FILTER_ARG_VALUE:
505 case FILTER_ARG_FIELD:
506 break;
507 default:
Namhyung Kim02d62d62013-12-12 16:36:09 +0900508 show_error(error_str, "Illegal rvalue");
509 return PEVENT_ERRNO__ILLEGAL_RVALUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200510 }
511
512 /*
513 * Depending on the type, we may need to
514 * convert this to a string or regex.
515 */
516 switch (arg->value.type) {
517 case FILTER_CHAR:
518 /*
519 * A char should be converted to number if
520 * the string is 1 byte, and the compare
521 * is not a REGEX.
522 */
523 if (strlen(arg->value.str) == 1 &&
524 op->num.type != FILTER_CMP_REGEX &&
525 op->num.type != FILTER_CMP_NOT_REGEX) {
526 arg->value.type = FILTER_NUMBER;
527 goto do_int;
528 }
529 /* fall through */
530 case FILTER_STRING:
531
532 /* convert op to a string arg */
533 op_type = op->num.type;
534 left = op->num.left;
535 str = arg->value.str;
536
537 /* reset the op for the new field */
538 memset(op, 0, sizeof(*op));
539
540 /*
541 * If left arg was a field not found then
542 * NULL the entire op.
543 */
544 if (left->type == FILTER_ARG_BOOLEAN) {
545 free_arg(left);
546 free_arg(arg);
547 op->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +0200548 op->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200549 break;
550 }
551
552 /* Left arg must be a field */
553 if (left->type != FILTER_ARG_FIELD) {
554 show_error(error_str,
555 "Illegal lvalue for string comparison");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900556 return PEVENT_ERRNO__ILLEGAL_LVALUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200557 }
558
559 /* Make sure this is a valid string compare */
560 switch (op_type) {
561 case FILTER_CMP_EQ:
562 op_type = FILTER_CMP_MATCH;
563 break;
564 case FILTER_CMP_NE:
565 op_type = FILTER_CMP_NOT_MATCH;
566 break;
567
568 case FILTER_CMP_REGEX:
569 case FILTER_CMP_NOT_REGEX:
570 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
571 if (ret) {
572 show_error(error_str,
573 "RegEx '%s' did not compute",
574 str);
Namhyung Kim02d62d62013-12-12 16:36:09 +0900575 return PEVENT_ERRNO__INVALID_REGEX;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200576 }
577 break;
578 default:
579 show_error(error_str,
580 "Illegal comparison for string");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900581 return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200582 }
583
584 op->type = FILTER_ARG_STR;
585 op->str.type = op_type;
586 op->str.field = left->field.field;
587 op->str.val = strdup(str);
Namhyung Kim02d62d62013-12-12 16:36:09 +0900588 if (!op->str.val) {
589 show_error(error_str, "Failed to allocate string filter");
590 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
591 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200592 /*
593 * Need a buffer to copy data for tests
594 */
Namhyung Kim02d62d62013-12-12 16:36:09 +0900595 op->str.buffer = malloc(op->str.field->size + 1);
596 if (!op->str.buffer) {
597 show_error(error_str, "Failed to allocate string filter");
598 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
599 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200600 /* Null terminate this buffer */
601 op->str.buffer[op->str.field->size] = 0;
602
603 /* We no longer have left or right args */
604 free_arg(arg);
605 free_arg(left);
606
607 break;
608
609 case FILTER_NUMBER:
610
611 do_int:
612 switch (op->num.type) {
613 case FILTER_CMP_REGEX:
614 case FILTER_CMP_NOT_REGEX:
615 show_error(error_str,
616 "Op not allowed with integers");
Namhyung Kim02d62d62013-12-12 16:36:09 +0900617 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200618
619 default:
620 break;
621 }
622
623 /* numeric compare */
624 op->num.right = arg;
625 break;
626 default:
627 goto out_fail;
628 }
629 break;
630 default:
631 goto out_fail;
632 }
633
634 return 0;
635
636 out_fail:
Namhyung Kim02d62d62013-12-12 16:36:09 +0900637 show_error(error_str, "Syntax error");
638 return PEVENT_ERRNO__SYNTAX_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200639}
640
641static struct filter_arg *
642rotate_op_right(struct filter_arg *a, struct filter_arg *b)
643{
644 struct filter_arg *arg;
645
646 arg = a->op.right;
647 a->op.right = b;
648 return arg;
649}
650
Namhyung Kimff533fc2013-12-12 16:36:10 +0900651static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200652{
653 switch (op->type) {
654 case FILTER_ARG_EXP:
655 if (arg->type == FILTER_ARG_OP)
656 arg = rotate_op_right(arg, op);
657 op->exp.left = arg;
658 break;
659
660 case FILTER_ARG_OP:
661 op->op.left = arg;
662 break;
663 case FILTER_ARG_NUM:
664 if (arg->type == FILTER_ARG_OP)
665 arg = rotate_op_right(arg, op);
666
667 /* left arg of compares must be a field */
668 if (arg->type != FILTER_ARG_FIELD &&
669 arg->type != FILTER_ARG_BOOLEAN)
Namhyung Kimff533fc2013-12-12 16:36:10 +0900670 return PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200671 op->num.left = arg;
672 break;
673 default:
Namhyung Kimff533fc2013-12-12 16:36:10 +0900674 return PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200675 }
676 return 0;
677}
678
679enum op_type {
680 OP_NONE,
681 OP_BOOL,
682 OP_NOT,
683 OP_EXP,
684 OP_CMP,
685};
686
687static enum op_type process_op(const char *token,
688 enum filter_op_type *btype,
689 enum filter_cmp_type *ctype,
690 enum filter_exp_type *etype)
691{
692 *btype = FILTER_OP_NOT;
693 *etype = FILTER_EXP_NONE;
694 *ctype = FILTER_CMP_NONE;
695
696 if (strcmp(token, "&&") == 0)
697 *btype = FILTER_OP_AND;
698 else if (strcmp(token, "||") == 0)
699 *btype = FILTER_OP_OR;
700 else if (strcmp(token, "!") == 0)
701 return OP_NOT;
702
703 if (*btype != FILTER_OP_NOT)
704 return OP_BOOL;
705
706 /* Check for value expressions */
707 if (strcmp(token, "+") == 0) {
708 *etype = FILTER_EXP_ADD;
709 } else if (strcmp(token, "-") == 0) {
710 *etype = FILTER_EXP_SUB;
711 } else if (strcmp(token, "*") == 0) {
712 *etype = FILTER_EXP_MUL;
713 } else if (strcmp(token, "/") == 0) {
714 *etype = FILTER_EXP_DIV;
715 } else if (strcmp(token, "%") == 0) {
716 *etype = FILTER_EXP_MOD;
717 } else if (strcmp(token, ">>") == 0) {
718 *etype = FILTER_EXP_RSHIFT;
719 } else if (strcmp(token, "<<") == 0) {
720 *etype = FILTER_EXP_LSHIFT;
721 } else if (strcmp(token, "&") == 0) {
722 *etype = FILTER_EXP_AND;
723 } else if (strcmp(token, "|") == 0) {
724 *etype = FILTER_EXP_OR;
725 } else if (strcmp(token, "^") == 0) {
726 *etype = FILTER_EXP_XOR;
727 } else if (strcmp(token, "~") == 0)
728 *etype = FILTER_EXP_NOT;
729
730 if (*etype != FILTER_EXP_NONE)
731 return OP_EXP;
732
733 /* Check for compares */
734 if (strcmp(token, "==") == 0)
735 *ctype = FILTER_CMP_EQ;
736 else if (strcmp(token, "!=") == 0)
737 *ctype = FILTER_CMP_NE;
738 else if (strcmp(token, "<") == 0)
739 *ctype = FILTER_CMP_LT;
740 else if (strcmp(token, ">") == 0)
741 *ctype = FILTER_CMP_GT;
742 else if (strcmp(token, "<=") == 0)
743 *ctype = FILTER_CMP_LE;
744 else if (strcmp(token, ">=") == 0)
745 *ctype = FILTER_CMP_GE;
746 else if (strcmp(token, "=~") == 0)
747 *ctype = FILTER_CMP_REGEX;
748 else if (strcmp(token, "!~") == 0)
749 *ctype = FILTER_CMP_NOT_REGEX;
750 else
751 return OP_NONE;
752
753 return OP_CMP;
754}
755
756static int check_op_done(struct filter_arg *arg)
757{
758 switch (arg->type) {
759 case FILTER_ARG_EXP:
760 return arg->exp.right != NULL;
761
762 case FILTER_ARG_OP:
763 return arg->op.right != NULL;
764
765 case FILTER_ARG_NUM:
766 return arg->num.right != NULL;
767
768 case FILTER_ARG_STR:
769 /* A string conversion is always done */
770 return 1;
771
772 case FILTER_ARG_BOOLEAN:
773 /* field not found, is ok */
774 return 1;
775
776 default:
777 return 0;
778 }
779}
780
781enum filter_vals {
782 FILTER_VAL_NORM,
783 FILTER_VAL_FALSE,
784 FILTER_VAL_TRUE,
785};
786
787void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
788 struct filter_arg *arg)
789{
790 struct filter_arg *other_child;
791 struct filter_arg **ptr;
792
793 if (parent->type != FILTER_ARG_OP &&
794 arg->type != FILTER_ARG_OP)
795 die("can not reparent other than OP");
796
797 /* Get the sibling */
798 if (old_child->op.right == arg) {
799 ptr = &old_child->op.right;
800 other_child = old_child->op.left;
801 } else if (old_child->op.left == arg) {
802 ptr = &old_child->op.left;
803 other_child = old_child->op.right;
804 } else
805 die("Error in reparent op, find other child");
806
807 /* Detach arg from old_child */
808 *ptr = NULL;
809
810 /* Check for root */
811 if (parent == old_child) {
812 free_arg(other_child);
813 *parent = *arg;
814 /* Free arg without recussion */
815 free(arg);
816 return;
817 }
818
819 if (parent->op.right == old_child)
820 ptr = &parent->op.right;
821 else if (parent->op.left == old_child)
822 ptr = &parent->op.left;
823 else
824 die("Error in reparent op");
825 *ptr = arg;
826
827 free_arg(old_child);
828}
829
830enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
831{
832 enum filter_vals lval, rval;
833
834 switch (arg->type) {
835
836 /* bad case */
837 case FILTER_ARG_BOOLEAN:
Steven Rostedt668fe012012-04-06 00:47:55 +0200838 return FILTER_VAL_FALSE + arg->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200839
840 /* good cases: */
841 case FILTER_ARG_STR:
842 case FILTER_ARG_VALUE:
843 case FILTER_ARG_FIELD:
844 return FILTER_VAL_NORM;
845
846 case FILTER_ARG_EXP:
847 lval = test_arg(arg, arg->exp.left);
848 if (lval != FILTER_VAL_NORM)
849 return lval;
850 rval = test_arg(arg, arg->exp.right);
851 if (rval != FILTER_VAL_NORM)
852 return rval;
853 return FILTER_VAL_NORM;
854
855 case FILTER_ARG_NUM:
856 lval = test_arg(arg, arg->num.left);
857 if (lval != FILTER_VAL_NORM)
858 return lval;
859 rval = test_arg(arg, arg->num.right);
860 if (rval != FILTER_VAL_NORM)
861 return rval;
862 return FILTER_VAL_NORM;
863
864 case FILTER_ARG_OP:
865 if (arg->op.type != FILTER_OP_NOT) {
866 lval = test_arg(arg, arg->op.left);
867 switch (lval) {
868 case FILTER_VAL_NORM:
869 break;
870 case FILTER_VAL_TRUE:
871 if (arg->op.type == FILTER_OP_OR)
872 return FILTER_VAL_TRUE;
873 rval = test_arg(arg, arg->op.right);
874 if (rval != FILTER_VAL_NORM)
875 return rval;
876
877 reparent_op_arg(parent, arg, arg->op.right);
878 return FILTER_VAL_NORM;
879
880 case FILTER_VAL_FALSE:
881 if (arg->op.type == FILTER_OP_AND)
882 return FILTER_VAL_FALSE;
883 rval = test_arg(arg, arg->op.right);
884 if (rval != FILTER_VAL_NORM)
885 return rval;
886
887 reparent_op_arg(parent, arg, arg->op.right);
888 return FILTER_VAL_NORM;
889 }
890 }
891
892 rval = test_arg(arg, arg->op.right);
893 switch (rval) {
894 case FILTER_VAL_NORM:
895 break;
896 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
902 reparent_op_arg(parent, arg, arg->op.left);
903 return FILTER_VAL_NORM;
904
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
911 reparent_op_arg(parent, arg, arg->op.left);
912 return FILTER_VAL_NORM;
913 }
914
915 return FILTER_VAL_NORM;
916 default:
917 die("bad arg in filter tree");
918 }
919 return FILTER_VAL_NORM;
920}
921
922/* Remove any unknown event fields */
923static struct filter_arg *collapse_tree(struct filter_arg *arg)
924{
925 enum filter_vals ret;
926
927 ret = test_arg(arg, arg);
928 switch (ret) {
929 case FILTER_VAL_NORM:
930 return arg;
931
932 case FILTER_VAL_TRUE:
933 case FILTER_VAL_FALSE:
934 free_arg(arg);
935 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +0900936 if (arg) {
937 arg->type = FILTER_ARG_BOOLEAN;
938 arg->boolean.value = ret == FILTER_VAL_TRUE;
939 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200940 }
941
942 return arg;
943}
944
945static int
946process_filter(struct event_format *event, struct filter_arg **parg,
947 char **error_str, int not)
948{
949 enum event_type type;
950 char *token = NULL;
951 struct filter_arg *current_op = NULL;
952 struct filter_arg *current_exp = NULL;
953 struct filter_arg *left_item = NULL;
954 struct filter_arg *arg = NULL;
955 enum op_type op_type;
956 enum filter_op_type btype;
957 enum filter_exp_type etype;
958 enum filter_cmp_type ctype;
959 int ret;
960
961 *parg = NULL;
962
963 do {
964 free(token);
965 type = read_token(&token);
966 switch (type) {
967 case EVENT_SQUOTE:
968 case EVENT_DQUOTE:
969 case EVENT_ITEM:
970 arg = create_arg_item(event, token, type, error_str);
971 if (!arg)
972 goto fail;
973 if (!left_item)
974 left_item = arg;
975 else if (current_exp) {
976 ret = add_right(current_exp, arg, error_str);
977 if (ret < 0)
978 goto fail;
979 left_item = NULL;
980 /* Not's only one one expression */
981 if (not) {
982 arg = NULL;
983 if (current_op)
984 goto fail_print;
985 free(token);
986 *parg = current_exp;
987 return 0;
988 }
989 } else
990 goto fail_print;
991 arg = NULL;
992 break;
993
994 case EVENT_DELIM:
995 if (*token == ',') {
996 show_error(error_str,
997 "Illegal token ','");
998 goto fail;
999 }
1000
1001 if (*token == '(') {
1002 if (left_item) {
1003 show_error(error_str,
1004 "Open paren can not come after item");
1005 goto fail;
1006 }
1007 if (current_exp) {
1008 show_error(error_str,
1009 "Open paren can not come after expression");
1010 goto fail;
1011 }
1012
1013 ret = process_filter(event, &arg, error_str, 0);
1014 if (ret != 1) {
1015 if (ret == 0)
1016 show_error(error_str,
1017 "Unbalanced number of '('");
1018 goto fail;
1019 }
1020 ret = 0;
1021
1022 /* A not wants just one expression */
1023 if (not) {
1024 if (current_op)
1025 goto fail_print;
1026 *parg = arg;
1027 return 0;
1028 }
1029
1030 if (current_op)
1031 ret = add_right(current_op, arg, error_str);
1032 else
1033 current_exp = arg;
1034
1035 if (ret < 0)
1036 goto fail;
1037
1038 } else { /* ')' */
1039 if (!current_op && !current_exp)
1040 goto fail_print;
1041
1042 /* Make sure everything is finished at this level */
1043 if (current_exp && !check_op_done(current_exp))
1044 goto fail_print;
1045 if (current_op && !check_op_done(current_op))
1046 goto fail_print;
1047
1048 if (current_op)
1049 *parg = current_op;
1050 else
1051 *parg = current_exp;
1052 return 1;
1053 }
1054 break;
1055
1056 case EVENT_OP:
1057 op_type = process_op(token, &btype, &ctype, &etype);
1058
1059 /* All expect a left arg except for NOT */
1060 switch (op_type) {
1061 case OP_BOOL:
1062 /* Logic ops need a left expression */
1063 if (!current_exp && !current_op)
1064 goto fail_print;
1065 /* fall through */
1066 case OP_NOT:
1067 /* logic only processes ops and exp */
1068 if (left_item)
1069 goto fail_print;
1070 break;
1071 case OP_EXP:
1072 case OP_CMP:
1073 if (!left_item)
1074 goto fail_print;
1075 break;
1076 case OP_NONE:
1077 show_error(error_str,
1078 "Unknown op token %s", token);
1079 goto fail;
1080 }
1081
1082 ret = 0;
1083 switch (op_type) {
1084 case OP_BOOL:
1085 arg = create_arg_op(btype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001086 if (arg == NULL)
1087 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001088 if (current_op)
1089 ret = add_left(arg, current_op);
1090 else
1091 ret = add_left(arg, current_exp);
1092 current_op = arg;
1093 current_exp = NULL;
1094 break;
1095
1096 case OP_NOT:
1097 arg = create_arg_op(btype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001098 if (arg == NULL)
1099 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001100 if (current_op)
1101 ret = add_right(current_op, arg, error_str);
1102 if (ret < 0)
1103 goto fail;
1104 current_exp = arg;
1105 ret = process_filter(event, &arg, error_str, 1);
1106 if (ret < 0)
1107 goto fail;
1108 ret = add_right(current_exp, arg, error_str);
1109 if (ret < 0)
1110 goto fail;
1111 break;
1112
1113 case OP_EXP:
1114 case OP_CMP:
1115 if (op_type == OP_EXP)
1116 arg = create_arg_exp(etype);
1117 else
1118 arg = create_arg_cmp(ctype);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001119 if (arg == NULL)
1120 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001121
1122 if (current_op)
1123 ret = add_right(current_op, arg, error_str);
1124 if (ret < 0)
1125 goto fail;
1126 ret = add_left(arg, left_item);
1127 if (ret < 0) {
1128 arg = NULL;
1129 goto fail_print;
1130 }
1131 current_exp = arg;
1132 break;
1133 default:
1134 break;
1135 }
1136 arg = NULL;
1137 if (ret < 0)
1138 goto fail_print;
1139 break;
1140 case EVENT_NONE:
1141 break;
Namhyung Kim91dfa492013-12-12 16:36:07 +09001142 case EVENT_ERROR:
1143 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001144 default:
1145 goto fail_print;
1146 }
1147 } while (type != EVENT_NONE);
1148
1149 if (!current_op && !current_exp)
1150 goto fail_print;
1151
1152 if (!current_op)
1153 current_op = current_exp;
1154
1155 current_op = collapse_tree(current_op);
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001156 if (current_op == NULL)
1157 goto fail_alloc;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001158
1159 *parg = current_op;
1160
1161 return 0;
1162
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001163 fail_alloc:
1164 show_error(error_str, "failed to allocate filter arg");
1165 goto fail;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001166 fail_print:
1167 show_error(error_str, "Syntax error");
1168 fail:
1169 free_arg(current_op);
1170 free_arg(current_exp);
1171 free_arg(arg);
1172 free(token);
1173 return -1;
1174}
1175
1176static int
1177process_event(struct event_format *event, const char *filter_str,
1178 struct filter_arg **parg, char **error_str)
1179{
1180 int ret;
1181
1182 pevent_buffer_init(filter_str, strlen(filter_str));
1183
1184 ret = process_filter(event, parg, error_str, 0);
1185 if (ret == 1) {
1186 show_error(error_str,
1187 "Unbalanced number of ')'");
1188 return -1;
1189 }
1190 if (ret < 0)
1191 return ret;
1192
1193 /* If parg is NULL, then make it into FALSE */
1194 if (!*parg) {
1195 *parg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001196 if (*parg == NULL) {
1197 show_error(error_str, "failed to allocate filter arg");
1198 return -1;
1199 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001200 (*parg)->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +02001201 (*parg)->boolean.value = FILTER_FALSE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001202 }
1203
1204 return 0;
1205}
1206
1207static int filter_event(struct event_filter *filter,
1208 struct event_format *event,
1209 const char *filter_str, char **error_str)
1210{
1211 struct filter_type *filter_type;
1212 struct filter_arg *arg;
1213 int ret;
1214
1215 if (filter_str) {
1216 ret = process_event(event, filter_str, &arg, error_str);
1217 if (ret < 0)
1218 return ret;
1219
1220 } else {
1221 /* just add a TRUE arg */
1222 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001223 if (arg == NULL) {
1224 show_error(error_str, "failed to allocate filter arg");
1225 return -1;
1226 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001227 arg->type = FILTER_ARG_BOOLEAN;
Steven Rostedt668fe012012-04-06 00:47:55 +02001228 arg->boolean.value = FILTER_TRUE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001229 }
1230
1231 filter_type = add_filter_type(filter, event->id);
Namhyung Kimef3072c2013-12-12 16:36:05 +09001232 if (filter_type == NULL) {
1233 show_error(error_str, "failed to add a new filter: %s",
1234 filter_str ? filter_str : "true");
1235 return -1;
1236 }
1237
Steven Rostedtf7d82352012-04-06 00:47:53 +02001238 if (filter_type->filter)
1239 free_arg(filter_type->filter);
1240 filter_type->filter = arg;
1241
1242 return 0;
1243}
1244
1245/**
1246 * pevent_filter_add_filter_str - add a new filter
1247 * @filter: the event filter to add to
1248 * @filter_str: the filter string that contains the filter
1249 * @error_str: string containing reason for failed filter
1250 *
1251 * Returns 0 if the filter was successfully added
1252 * -1 if there was an error.
1253 *
1254 * On error, if @error_str points to a string pointer,
1255 * it is set to the reason that the filter failed.
1256 * This string must be freed with "free".
1257 */
1258int pevent_filter_add_filter_str(struct event_filter *filter,
1259 const char *filter_str,
1260 char **error_str)
1261{
1262 struct pevent *pevent = filter->pevent;
1263 struct event_list *event;
1264 struct event_list *events = NULL;
1265 const char *filter_start;
1266 const char *next_event;
1267 char *this_event;
1268 char *event_name = NULL;
1269 char *sys_name = NULL;
1270 char *sp;
1271 int rtn = 0;
1272 int len;
1273 int ret;
1274
1275 /* clear buffer to reset show error */
1276 pevent_buffer_init("", 0);
1277
1278 if (error_str)
1279 *error_str = NULL;
1280
1281 filter_start = strchr(filter_str, ':');
1282 if (filter_start)
1283 len = filter_start - filter_str;
1284 else
1285 len = strlen(filter_str);
1286
1287
1288 do {
1289 next_event = strchr(filter_str, ',');
1290 if (next_event &&
1291 (!filter_start || next_event < filter_start))
1292 len = next_event - filter_str;
1293 else if (filter_start)
1294 len = filter_start - filter_str;
1295 else
1296 len = strlen(filter_str);
1297
Namhyung Kim28942c82013-12-09 14:34:08 +09001298 this_event = malloc(len + 1);
1299 if (this_event == NULL) {
1300 show_error(error_str, "Memory allocation failure");
1301 /* This can only happen when events is NULL, but still */
1302 free_events(events);
1303 return -1;
1304 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001305 memcpy(this_event, filter_str, len);
1306 this_event[len] = 0;
1307
1308 if (next_event)
1309 next_event++;
1310
1311 filter_str = next_event;
1312
1313 sys_name = strtok_r(this_event, "/", &sp);
1314 event_name = strtok_r(NULL, "/", &sp);
1315
1316 if (!sys_name) {
1317 show_error(error_str, "No filter found");
1318 /* This can only happen when events is NULL, but still */
1319 free_events(events);
1320 free(this_event);
1321 return -1;
1322 }
1323
1324 /* Find this event */
1325 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1326 if (ret < 0) {
Namhyung Kim605b8fd2013-12-12 16:36:08 +09001327 if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED)
1328 show_error(error_str,
1329 "Memory allocation failure");
1330 else if (event_name)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001331 show_error(error_str,
1332 "No event found under '%s.%s'",
1333 sys_name, event_name);
1334 else
1335 show_error(error_str,
1336 "No event found under '%s'",
1337 sys_name);
1338 free_events(events);
1339 free(this_event);
1340 return -1;
1341 }
1342 free(this_event);
1343 } while (filter_str);
1344
1345 /* Skip the ':' */
1346 if (filter_start)
1347 filter_start++;
1348
1349 /* filter starts here */
1350 for (event = events; event; event = event->next) {
1351 ret = filter_event(filter, event->event, filter_start,
1352 error_str);
1353 /* Failures are returned if a parse error happened */
1354 if (ret < 0)
1355 rtn = ret;
1356
1357 if (ret >= 0 && pevent->test_filters) {
1358 char *test;
1359 test = pevent_filter_make_string(filter, event->event->id);
1360 printf(" '%s: %s'\n", event->event->name, test);
1361 free(test);
1362 }
1363 }
1364
1365 free_events(events);
1366
1367 if (rtn >= 0 && pevent->test_filters)
1368 exit(0);
1369
1370 return rtn;
1371}
1372
1373static void free_filter_type(struct filter_type *filter_type)
1374{
1375 free_arg(filter_type->filter);
1376}
1377
1378/**
1379 * pevent_filter_remove_event - remove a filter for an event
1380 * @filter: the event filter to remove from
1381 * @event_id: the event to remove a filter for
1382 *
1383 * Removes the filter saved for an event defined by @event_id
1384 * from the @filter.
1385 *
1386 * Returns 1: if an event was removed
1387 * 0: if the event was not found
1388 */
1389int pevent_filter_remove_event(struct event_filter *filter,
1390 int event_id)
1391{
1392 struct filter_type *filter_type;
1393 unsigned long len;
1394
1395 if (!filter->filters)
1396 return 0;
1397
1398 filter_type = find_filter_type(filter, event_id);
1399
1400 if (!filter_type)
1401 return 0;
1402
1403 free_filter_type(filter_type);
1404
1405 /* The filter_type points into the event_filters array */
1406 len = (unsigned long)(filter->event_filters + filter->filters) -
1407 (unsigned long)(filter_type + 1);
1408
1409 memmove(filter_type, filter_type + 1, len);
1410 filter->filters--;
1411
1412 memset(&filter->event_filters[filter->filters], 0,
1413 sizeof(*filter_type));
1414
1415 return 1;
1416}
1417
1418/**
1419 * pevent_filter_reset - clear all filters in a filter
1420 * @filter: the event filter to reset
1421 *
1422 * Removes all filters from a filter and resets it.
1423 */
1424void pevent_filter_reset(struct event_filter *filter)
1425{
1426 int i;
1427
1428 for (i = 0; i < filter->filters; i++)
1429 free_filter_type(&filter->event_filters[i]);
1430
1431 free(filter->event_filters);
1432 filter->filters = 0;
1433 filter->event_filters = NULL;
1434}
1435
1436void pevent_filter_free(struct event_filter *filter)
1437{
1438 pevent_unref(filter->pevent);
1439
1440 pevent_filter_reset(filter);
1441
1442 free(filter);
1443}
1444
1445static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1446
1447static int copy_filter_type(struct event_filter *filter,
1448 struct event_filter *source,
1449 struct filter_type *filter_type)
1450{
1451 struct filter_arg *arg;
1452 struct event_format *event;
1453 const char *sys;
1454 const char *name;
1455 char *str;
1456
1457 /* Can't assume that the pevent's are the same */
1458 sys = filter_type->event->system;
1459 name = filter_type->event->name;
1460 event = pevent_find_event_by_name(filter->pevent, sys, name);
1461 if (!event)
1462 return -1;
1463
1464 str = arg_to_str(source, filter_type->filter);
1465 if (!str)
1466 return -1;
1467
1468 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1469 /* Add trivial event */
1470 arg = allocate_arg();
Namhyung Kim2e4eb102013-12-12 16:36:06 +09001471 if (arg == NULL)
1472 return -1;
1473
Steven Rostedtf7d82352012-04-06 00:47:53 +02001474 arg->type = FILTER_ARG_BOOLEAN;
1475 if (strcmp(str, "TRUE") == 0)
Steven Rostedt668fe012012-04-06 00:47:55 +02001476 arg->boolean.value = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001477 else
Steven Rostedt668fe012012-04-06 00:47:55 +02001478 arg->boolean.value = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001479
1480 filter_type = add_filter_type(filter, event->id);
Namhyung Kimef3072c2013-12-12 16:36:05 +09001481 if (filter_type == NULL)
1482 return -1;
1483
Steven Rostedtf7d82352012-04-06 00:47:53 +02001484 filter_type->filter = arg;
1485
1486 free(str);
1487 return 0;
1488 }
1489
1490 filter_event(filter, event, str, NULL);
1491 free(str);
1492
1493 return 0;
1494}
1495
1496/**
1497 * pevent_filter_copy - copy a filter using another filter
1498 * @dest - the filter to copy to
1499 * @source - the filter to copy from
1500 *
1501 * Returns 0 on success and -1 if not all filters were copied
1502 */
1503int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1504{
1505 int ret = 0;
1506 int i;
1507
1508 pevent_filter_reset(dest);
1509
1510 for (i = 0; i < source->filters; i++) {
1511 if (copy_filter_type(dest, source, &source->event_filters[i]))
1512 ret = -1;
1513 }
1514 return ret;
1515}
1516
1517
1518/**
1519 * pevent_update_trivial - update the trivial filters with the given filter
1520 * @dest - the filter to update
1521 * @source - the filter as the source of the update
1522 * @type - the type of trivial filter to update.
1523 *
1524 * Scan dest for trivial events matching @type to replace with the source.
1525 *
1526 * Returns 0 on success and -1 if there was a problem updating, but
1527 * events may have still been updated on error.
1528 */
1529int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1530 enum filter_trivial_type type)
1531{
1532 struct pevent *src_pevent;
1533 struct pevent *dest_pevent;
1534 struct event_format *event;
1535 struct filter_type *filter_type;
1536 struct filter_arg *arg;
1537 char *str;
1538 int i;
1539
1540 src_pevent = source->pevent;
1541 dest_pevent = dest->pevent;
1542
1543 /* Do nothing if either of the filters has nothing to filter */
1544 if (!dest->filters || !source->filters)
1545 return 0;
1546
1547 for (i = 0; i < dest->filters; i++) {
1548 filter_type = &dest->event_filters[i];
1549 arg = filter_type->filter;
1550 if (arg->type != FILTER_ARG_BOOLEAN)
1551 continue;
Steven Rostedt668fe012012-04-06 00:47:55 +02001552 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
1553 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
Steven Rostedtf7d82352012-04-06 00:47:53 +02001554 continue;
1555
1556 event = filter_type->event;
1557
1558 if (src_pevent != dest_pevent) {
1559 /* do a look up */
1560 event = pevent_find_event_by_name(src_pevent,
1561 event->system,
1562 event->name);
1563 if (!event)
1564 return -1;
1565 }
1566
1567 str = pevent_filter_make_string(source, event->id);
1568 if (!str)
1569 continue;
1570
1571 /* Don't bother if the filter is trivial too */
1572 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1573 filter_event(dest, event, str, NULL);
1574 free(str);
1575 }
1576 return 0;
1577}
1578
1579/**
1580 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1581 * @filter: the filter to remove trivial filters from
1582 * @type: remove only true, false, or both
1583 *
1584 * Removes filters that only contain a TRUE or FALES boolean arg.
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001585 *
1586 * Returns 0 on success and -1 if there was a problem.
Steven Rostedtf7d82352012-04-06 00:47:53 +02001587 */
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001588int pevent_filter_clear_trivial(struct event_filter *filter,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001589 enum filter_trivial_type type)
1590{
1591 struct filter_type *filter_type;
1592 int count = 0;
Namhyung Kimf6ced602012-04-24 10:29:44 +09001593 int *ids = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001594 int i;
1595
1596 if (!filter->filters)
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001597 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001598
1599 /*
1600 * Two steps, first get all ids with trivial filters.
1601 * then remove those ids.
1602 */
1603 for (i = 0; i < filter->filters; i++) {
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001604 int *new_ids;
1605
Steven Rostedtf7d82352012-04-06 00:47:53 +02001606 filter_type = &filter->event_filters[i];
1607 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1608 continue;
1609 switch (type) {
1610 case FILTER_TRIVIAL_FALSE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001611 if (filter_type->filter->boolean.value)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001612 continue;
1613 case FILTER_TRIVIAL_TRUE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001614 if (!filter_type->filter->boolean.value)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001615 continue;
1616 default:
1617 break;
1618 }
Namhyung Kimf6ced602012-04-24 10:29:44 +09001619
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001620 new_ids = realloc(ids, sizeof(*ids) * (count + 1));
1621 if (!new_ids) {
1622 free(ids);
1623 return -1;
1624 }
1625
1626 ids = new_ids;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001627 ids[count++] = filter_type->event_id;
1628 }
1629
1630 if (!count)
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001631 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001632
1633 for (i = 0; i < count; i++)
1634 pevent_filter_remove_event(filter, ids[i]);
1635
1636 free(ids);
Namhyung Kim7ef2e812013-12-09 14:34:09 +09001637 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001638}
1639
1640/**
1641 * pevent_filter_event_has_trivial - return true event contains trivial filter
1642 * @filter: the filter with the information
1643 * @event_id: the id of the event to test
1644 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1645 *
1646 * Returns 1 if the event contains a matching trivial type
1647 * otherwise 0.
1648 */
1649int pevent_filter_event_has_trivial(struct event_filter *filter,
1650 int event_id,
1651 enum filter_trivial_type type)
1652{
1653 struct filter_type *filter_type;
1654
1655 if (!filter->filters)
1656 return 0;
1657
1658 filter_type = find_filter_type(filter, event_id);
1659
1660 if (!filter_type)
1661 return 0;
1662
1663 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1664 return 0;
1665
1666 switch (type) {
1667 case FILTER_TRIVIAL_FALSE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001668 return !filter_type->filter->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001669
1670 case FILTER_TRIVIAL_TRUE:
Steven Rostedt668fe012012-04-06 00:47:55 +02001671 return filter_type->filter->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001672 default:
1673 return 1;
1674 }
1675}
1676
1677static int test_filter(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001678 struct filter_arg *arg, struct pevent_record *record);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001679
1680static const char *
Steven Rostedt1c698182012-04-06 00:48:06 +02001681get_comm(struct event_format *event, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001682{
1683 const char *comm;
1684 int pid;
1685
1686 pid = pevent_data_pid(event->pevent, record);
1687 comm = pevent_data_comm_from_pid(event->pevent, pid);
1688 return comm;
1689}
1690
1691static unsigned long long
1692get_value(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001693 struct format_field *field, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001694{
1695 unsigned long long val;
1696
1697 /* Handle our dummy "comm" field */
1698 if (field == &comm) {
1699 const char *name;
1700
1701 name = get_comm(event, record);
Namhyung Kim42c59cd2012-05-26 12:41:31 +09001702 return (unsigned long)name;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001703 }
1704
1705 pevent_read_number_field(field, record->data, &val);
1706
1707 if (!(field->flags & FIELD_IS_SIGNED))
1708 return val;
1709
1710 switch (field->size) {
1711 case 1:
1712 return (char)val;
1713 case 2:
1714 return (short)val;
1715 case 4:
1716 return (int)val;
1717 case 8:
1718 return (long long)val;
1719 }
1720 return val;
1721}
1722
1723static unsigned long long
Steven Rostedt1c698182012-04-06 00:48:06 +02001724get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001725
1726static unsigned long long
Steven Rostedt1c698182012-04-06 00:48:06 +02001727get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001728{
1729 unsigned long long lval, rval;
1730
1731 lval = get_arg_value(event, arg->exp.left, record);
1732 rval = get_arg_value(event, arg->exp.right, record);
1733
1734 switch (arg->exp.type) {
1735 case FILTER_EXP_ADD:
1736 return lval + rval;
1737
1738 case FILTER_EXP_SUB:
1739 return lval - rval;
1740
1741 case FILTER_EXP_MUL:
1742 return lval * rval;
1743
1744 case FILTER_EXP_DIV:
1745 return lval / rval;
1746
1747 case FILTER_EXP_MOD:
1748 return lval % rval;
1749
1750 case FILTER_EXP_RSHIFT:
1751 return lval >> rval;
1752
1753 case FILTER_EXP_LSHIFT:
1754 return lval << rval;
1755
1756 case FILTER_EXP_AND:
1757 return lval & rval;
1758
1759 case FILTER_EXP_OR:
1760 return lval | rval;
1761
1762 case FILTER_EXP_XOR:
1763 return lval ^ rval;
1764
1765 case FILTER_EXP_NOT:
1766 default:
1767 die("error in exp");
1768 }
1769 return 0;
1770}
1771
1772static unsigned long long
Steven Rostedt1c698182012-04-06 00:48:06 +02001773get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001774{
1775 switch (arg->type) {
1776 case FILTER_ARG_FIELD:
1777 return get_value(event, arg->field.field, record);
1778
1779 case FILTER_ARG_VALUE:
1780 if (arg->value.type != FILTER_NUMBER)
1781 die("must have number field!");
1782 return arg->value.val;
1783
1784 case FILTER_ARG_EXP:
1785 return get_exp_value(event, arg, record);
1786
1787 default:
1788 die("oops in filter");
1789 }
1790 return 0;
1791}
1792
1793static int test_num(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001794 struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001795{
1796 unsigned long long lval, rval;
1797
1798 lval = get_arg_value(event, arg->num.left, record);
1799 rval = get_arg_value(event, arg->num.right, record);
1800
1801 switch (arg->num.type) {
1802 case FILTER_CMP_EQ:
1803 return lval == rval;
1804
1805 case FILTER_CMP_NE:
1806 return lval != rval;
1807
1808 case FILTER_CMP_GT:
1809 return lval > rval;
1810
1811 case FILTER_CMP_LT:
1812 return lval < rval;
1813
1814 case FILTER_CMP_GE:
1815 return lval >= rval;
1816
1817 case FILTER_CMP_LE:
1818 return lval <= rval;
1819
1820 default:
1821 /* ?? */
1822 return 0;
1823 }
1824}
1825
Steven Rostedt1c698182012-04-06 00:48:06 +02001826static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001827{
Steven Rostedte84c2822012-05-22 14:45:21 +09001828 struct event_format *event;
1829 struct pevent *pevent;
1830 unsigned long long addr;
1831 const char *val = NULL;
1832 char hex[64];
Steven Rostedtf7d82352012-04-06 00:47:53 +02001833
Steven Rostedte84c2822012-05-22 14:45:21 +09001834 /* If the field is not a string convert it */
1835 if (arg->str.field->flags & FIELD_IS_STRING) {
1836 val = record->data + arg->str.field->offset;
1837
1838 /*
1839 * We need to copy the data since we can't be sure the field
1840 * is null terminated.
1841 */
1842 if (*(val + arg->str.field->size - 1)) {
1843 /* copy it */
1844 memcpy(arg->str.buffer, val, arg->str.field->size);
1845 /* the buffer is already NULL terminated */
1846 val = arg->str.buffer;
1847 }
1848
1849 } else {
1850 event = arg->str.field->event;
1851 pevent = event->pevent;
1852 addr = get_value(event, arg->str.field, record);
1853
1854 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
1855 /* convert to a kernel symbol */
1856 val = pevent_find_function(pevent, addr);
1857
1858 if (val == NULL) {
1859 /* just use the hex of the string name */
1860 snprintf(hex, 64, "0x%llx", addr);
1861 val = hex;
1862 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001863 }
Steven Rostedte84c2822012-05-22 14:45:21 +09001864
Steven Rostedtf7d82352012-04-06 00:47:53 +02001865 return val;
1866}
1867
1868static int test_str(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001869 struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001870{
1871 const char *val;
1872
1873 if (arg->str.field == &comm)
1874 val = get_comm(event, record);
1875 else
1876 val = get_field_str(arg, record);
1877
1878 switch (arg->str.type) {
1879 case FILTER_CMP_MATCH:
1880 return strcmp(val, arg->str.val) == 0;
1881
1882 case FILTER_CMP_NOT_MATCH:
1883 return strcmp(val, arg->str.val) != 0;
1884
1885 case FILTER_CMP_REGEX:
1886 /* Returns zero on match */
1887 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1888
1889 case FILTER_CMP_NOT_REGEX:
1890 return regexec(&arg->str.reg, val, 0, NULL, 0);
1891
1892 default:
1893 /* ?? */
1894 return 0;
1895 }
1896}
1897
1898static int test_op(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001899 struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001900{
1901 switch (arg->op.type) {
1902 case FILTER_OP_AND:
1903 return test_filter(event, arg->op.left, record) &&
1904 test_filter(event, arg->op.right, record);
1905
1906 case FILTER_OP_OR:
1907 return test_filter(event, arg->op.left, record) ||
1908 test_filter(event, arg->op.right, record);
1909
1910 case FILTER_OP_NOT:
1911 return !test_filter(event, arg->op.right, record);
1912
1913 default:
1914 /* ?? */
1915 return 0;
1916 }
1917}
1918
1919static int test_filter(struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02001920 struct filter_arg *arg, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001921{
1922 switch (arg->type) {
1923 case FILTER_ARG_BOOLEAN:
1924 /* easy case */
Steven Rostedt668fe012012-04-06 00:47:55 +02001925 return arg->boolean.value;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001926
1927 case FILTER_ARG_OP:
1928 return test_op(event, arg, record);
1929
1930 case FILTER_ARG_NUM:
1931 return test_num(event, arg, record);
1932
1933 case FILTER_ARG_STR:
1934 return test_str(event, arg, record);
1935
1936 case FILTER_ARG_EXP:
1937 case FILTER_ARG_VALUE:
1938 case FILTER_ARG_FIELD:
1939 /*
1940 * Expressions, fields and values evaluate
1941 * to true if they return non zero
1942 */
1943 return !!get_arg_value(event, arg, record);
1944
1945 default:
1946 die("oops!");
1947 /* ?? */
1948 return 0;
1949 }
1950}
1951
1952/**
1953 * pevent_event_filtered - return true if event has filter
1954 * @filter: filter struct with filter information
1955 * @event_id: event id to test if filter exists
1956 *
1957 * Returns 1 if filter found for @event_id
1958 * otherwise 0;
1959 */
1960int pevent_event_filtered(struct event_filter *filter,
1961 int event_id)
1962{
1963 struct filter_type *filter_type;
1964
1965 if (!filter->filters)
1966 return 0;
1967
1968 filter_type = find_filter_type(filter, event_id);
1969
1970 return filter_type ? 1 : 0;
1971}
1972
1973/**
1974 * pevent_filter_match - test if a record matches a filter
1975 * @filter: filter struct with filter information
1976 * @record: the record to test against the filter
1977 *
1978 * Returns:
1979 * 1 - filter found for event and @record matches
1980 * 0 - filter found for event and @record does not match
1981 * -1 - no filter found for @record's event
1982 * -2 - if no filters exist
1983 */
1984int pevent_filter_match(struct event_filter *filter,
Steven Rostedt1c698182012-04-06 00:48:06 +02001985 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001986{
1987 struct pevent *pevent = filter->pevent;
1988 struct filter_type *filter_type;
1989 int event_id;
1990
1991 if (!filter->filters)
1992 return FILTER_NONE;
1993
1994 event_id = pevent_data_type(pevent, record);
1995
1996 filter_type = find_filter_type(filter, event_id);
1997
1998 if (!filter_type)
1999 return FILTER_NOEXIST;
2000
2001 return test_filter(filter_type->event, filter_type->filter, record) ?
2002 FILTER_MATCH : FILTER_MISS;
2003}
2004
2005static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
2006{
2007 char *str = NULL;
2008 char *left = NULL;
2009 char *right = NULL;
2010 char *op = NULL;
2011 int left_val = -1;
2012 int right_val = -1;
2013 int val;
2014 int len;
2015
2016 switch (arg->op.type) {
2017 case FILTER_OP_AND:
2018 op = "&&";
2019 /* fall through */
2020 case FILTER_OP_OR:
2021 if (!op)
2022 op = "||";
2023
2024 left = arg_to_str(filter, arg->op.left);
2025 right = arg_to_str(filter, arg->op.right);
2026 if (!left || !right)
2027 break;
2028
2029 /* Try to consolidate boolean values */
2030 if (strcmp(left, "TRUE") == 0)
2031 left_val = 1;
2032 else if (strcmp(left, "FALSE") == 0)
2033 left_val = 0;
2034
2035 if (strcmp(right, "TRUE") == 0)
2036 right_val = 1;
2037 else if (strcmp(right, "FALSE") == 0)
2038 right_val = 0;
2039
2040 if (left_val >= 0) {
2041 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
2042 (arg->op.type == FILTER_OP_OR && left_val)) {
2043 /* Just return left value */
2044 str = left;
2045 left = NULL;
2046 break;
2047 }
2048 if (right_val >= 0) {
2049 /* just evaluate this. */
2050 val = 0;
2051 switch (arg->op.type) {
2052 case FILTER_OP_AND:
2053 val = left_val && right_val;
2054 break;
2055 case FILTER_OP_OR:
2056 val = left_val || right_val;
2057 break;
2058 default:
2059 break;
2060 }
2061 str = malloc_or_die(6);
2062 if (val)
2063 strcpy(str, "TRUE");
2064 else
2065 strcpy(str, "FALSE");
2066 break;
2067 }
2068 }
2069 if (right_val >= 0) {
2070 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
2071 (arg->op.type == FILTER_OP_OR && right_val)) {
2072 /* Just return right value */
2073 str = right;
2074 right = NULL;
2075 break;
2076 }
2077 /* The right value is meaningless */
2078 str = left;
2079 left = NULL;
2080 break;
2081 }
2082
2083 len = strlen(left) + strlen(right) + strlen(op) + 10;
2084 str = malloc_or_die(len);
2085 snprintf(str, len, "(%s) %s (%s)",
2086 left, op, right);
2087 break;
2088
2089 case FILTER_OP_NOT:
2090 op = "!";
2091 right = arg_to_str(filter, arg->op.right);
2092 if (!right)
2093 break;
2094
2095 /* See if we can consolidate */
2096 if (strcmp(right, "TRUE") == 0)
2097 right_val = 1;
2098 else if (strcmp(right, "FALSE") == 0)
2099 right_val = 0;
2100 if (right_val >= 0) {
2101 /* just return the opposite */
2102 str = malloc_or_die(6);
2103 if (right_val)
2104 strcpy(str, "FALSE");
2105 else
2106 strcpy(str, "TRUE");
2107 break;
2108 }
2109 len = strlen(right) + strlen(op) + 3;
2110 str = malloc_or_die(len);
2111 snprintf(str, len, "%s(%s)", op, right);
2112 break;
2113
2114 default:
2115 /* ?? */
2116 break;
2117 }
2118 free(left);
2119 free(right);
2120 return str;
2121}
2122
2123static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
2124{
2125 char *str;
2126
2127 str = malloc_or_die(30);
2128
2129 snprintf(str, 30, "%lld", arg->value.val);
2130
2131 return str;
2132}
2133
2134static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
2135{
2136 return strdup(arg->field.field->name);
2137}
2138
2139static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2140{
2141 char *lstr;
2142 char *rstr;
2143 char *op;
Namhyung Kim0fed4832012-04-23 13:58:38 +09002144 char *str = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002145 int len;
2146
2147 lstr = arg_to_str(filter, arg->exp.left);
2148 rstr = arg_to_str(filter, arg->exp.right);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002149 if (!lstr || !rstr)
2150 goto out;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002151
2152 switch (arg->exp.type) {
2153 case FILTER_EXP_ADD:
2154 op = "+";
2155 break;
2156 case FILTER_EXP_SUB:
2157 op = "-";
2158 break;
2159 case FILTER_EXP_MUL:
2160 op = "*";
2161 break;
2162 case FILTER_EXP_DIV:
2163 op = "/";
2164 break;
2165 case FILTER_EXP_MOD:
2166 op = "%";
2167 break;
2168 case FILTER_EXP_RSHIFT:
2169 op = ">>";
2170 break;
2171 case FILTER_EXP_LSHIFT:
2172 op = "<<";
2173 break;
2174 case FILTER_EXP_AND:
2175 op = "&";
2176 break;
2177 case FILTER_EXP_OR:
2178 op = "|";
2179 break;
2180 case FILTER_EXP_XOR:
2181 op = "^";
2182 break;
2183 default:
2184 die("oops in exp");
2185 }
2186
2187 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
2188 str = malloc_or_die(len);
2189 snprintf(str, len, "%s %s %s", lstr, op, rstr);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002190out:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002191 free(lstr);
2192 free(rstr);
2193
2194 return str;
2195}
2196
2197static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2198{
2199 char *lstr;
2200 char *rstr;
2201 char *str = NULL;
2202 char *op = NULL;
2203 int len;
2204
2205 lstr = arg_to_str(filter, arg->num.left);
2206 rstr = arg_to_str(filter, arg->num.right);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002207 if (!lstr || !rstr)
2208 goto out;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002209
2210 switch (arg->num.type) {
2211 case FILTER_CMP_EQ:
2212 op = "==";
2213 /* fall through */
2214 case FILTER_CMP_NE:
2215 if (!op)
2216 op = "!=";
2217 /* fall through */
2218 case FILTER_CMP_GT:
2219 if (!op)
2220 op = ">";
2221 /* fall through */
2222 case FILTER_CMP_LT:
2223 if (!op)
2224 op = "<";
2225 /* fall through */
2226 case FILTER_CMP_GE:
2227 if (!op)
2228 op = ">=";
2229 /* fall through */
2230 case FILTER_CMP_LE:
2231 if (!op)
2232 op = "<=";
2233
2234 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
2235 str = malloc_or_die(len);
2236 sprintf(str, "%s %s %s", lstr, op, rstr);
2237
2238 break;
2239
2240 default:
2241 /* ?? */
2242 break;
2243 }
2244
Namhyung Kim0fed4832012-04-23 13:58:38 +09002245out:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002246 free(lstr);
2247 free(rstr);
2248 return str;
2249}
2250
2251static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2252{
2253 char *str = NULL;
2254 char *op = NULL;
2255 int len;
2256
2257 switch (arg->str.type) {
2258 case FILTER_CMP_MATCH:
2259 op = "==";
2260 /* fall through */
2261 case FILTER_CMP_NOT_MATCH:
2262 if (!op)
2263 op = "!=";
2264 /* fall through */
2265 case FILTER_CMP_REGEX:
2266 if (!op)
2267 op = "=~";
2268 /* fall through */
2269 case FILTER_CMP_NOT_REGEX:
2270 if (!op)
2271 op = "!~";
2272
2273 len = strlen(arg->str.field->name) + strlen(op) +
2274 strlen(arg->str.val) + 6;
2275 str = malloc_or_die(len);
2276 snprintf(str, len, "%s %s \"%s\"",
2277 arg->str.field->name,
2278 op, arg->str.val);
2279 break;
2280
2281 default:
2282 /* ?? */
2283 break;
2284 }
2285 return str;
2286}
2287
2288static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2289{
2290 char *str;
2291
2292 switch (arg->type) {
2293 case FILTER_ARG_BOOLEAN:
2294 str = malloc_or_die(6);
Steven Rostedt668fe012012-04-06 00:47:55 +02002295 if (arg->boolean.value)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002296 strcpy(str, "TRUE");
2297 else
2298 strcpy(str, "FALSE");
2299 return str;
2300
2301 case FILTER_ARG_OP:
2302 return op_to_str(filter, arg);
2303
2304 case FILTER_ARG_NUM:
2305 return num_to_str(filter, arg);
2306
2307 case FILTER_ARG_STR:
2308 return str_to_str(filter, arg);
2309
2310 case FILTER_ARG_VALUE:
2311 return val_to_str(filter, arg);
2312
2313 case FILTER_ARG_FIELD:
2314 return field_to_str(filter, arg);
2315
2316 case FILTER_ARG_EXP:
2317 return exp_to_str(filter, arg);
2318
2319 default:
2320 /* ?? */
2321 return NULL;
2322 }
2323
2324}
2325
2326/**
2327 * pevent_filter_make_string - return a string showing the filter
2328 * @filter: filter struct with filter information
2329 * @event_id: the event id to return the filter string with
2330 *
2331 * Returns a string that displays the filter contents.
2332 * This string must be freed with free(str).
2333 * NULL is returned if no filter is found.
2334 */
2335char *
2336pevent_filter_make_string(struct event_filter *filter, int event_id)
2337{
2338 struct filter_type *filter_type;
2339
2340 if (!filter->filters)
2341 return NULL;
2342
2343 filter_type = find_filter_type(filter, event_id);
2344
2345 if (!filter_type)
2346 return NULL;
2347
2348 return arg_to_str(filter, filter_type->filter);
2349}
2350
2351/**
2352 * pevent_filter_compare - compare two filters and return if they are the same
2353 * @filter1: Filter to compare with @filter2
2354 * @filter2: Filter to compare with @filter1
2355 *
2356 * Returns:
2357 * 1 if the two filters hold the same content.
2358 * 0 if they do not.
2359 */
2360int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2361{
2362 struct filter_type *filter_type1;
2363 struct filter_type *filter_type2;
2364 char *str1, *str2;
2365 int result;
2366 int i;
2367
2368 /* Do the easy checks first */
2369 if (filter1->filters != filter2->filters)
2370 return 0;
2371 if (!filter1->filters && !filter2->filters)
2372 return 1;
2373
2374 /*
2375 * Now take a look at each of the events to see if they have the same
2376 * filters to them.
2377 */
2378 for (i = 0; i < filter1->filters; i++) {
2379 filter_type1 = &filter1->event_filters[i];
2380 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2381 if (!filter_type2)
2382 break;
2383 if (filter_type1->filter->type != filter_type2->filter->type)
2384 break;
2385 switch (filter_type1->filter->type) {
2386 case FILTER_TRIVIAL_FALSE:
2387 case FILTER_TRIVIAL_TRUE:
2388 /* trivial types just need the type compared */
2389 continue;
2390 default:
2391 break;
2392 }
2393 /* The best way to compare complex filters is with strings */
2394 str1 = arg_to_str(filter1, filter_type1->filter);
2395 str2 = arg_to_str(filter2, filter_type2->filter);
Namhyung Kim0fed4832012-04-23 13:58:38 +09002396 if (str1 && str2)
2397 result = strcmp(str1, str2) != 0;
2398 else
2399 /* bail out if allocation fails */
2400 result = 1;
2401
Steven Rostedtf7d82352012-04-06 00:47:53 +02002402 free(str1);
2403 free(str2);
2404 if (result)
2405 break;
2406 }
2407
2408 if (i < filter1->filters)
2409 return 0;
2410 return 1;
2411}
2412