at v4.8 53 kB view raw
1/* 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 16 * License along with this program; if not, see <http://www.gnu.org/licenses> 17 * 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#define CPU "CPU" 32 33static struct format_field comm = { 34 .name = "COMM", 35}; 36 37static struct format_field cpu = { 38 .name = "CPU", 39}; 40 41struct event_list { 42 struct event_list *next; 43 struct event_format *event; 44}; 45 46static void show_error(char *error_buf, const char *fmt, ...) 47{ 48 unsigned long long index; 49 const char *input; 50 va_list ap; 51 int len; 52 int i; 53 54 input = pevent_get_input_buf(); 55 index = pevent_get_input_buf_ptr(); 56 len = input ? strlen(input) : 0; 57 58 if (len) { 59 strcpy(error_buf, input); 60 error_buf[len] = '\n'; 61 for (i = 1; i < len && i < index; i++) 62 error_buf[len+i] = ' '; 63 error_buf[len + i] = '^'; 64 error_buf[len + i + 1] = '\n'; 65 len += i+2; 66 } 67 68 va_start(ap, fmt); 69 vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap); 70 va_end(ap); 71} 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 */ 93 *tok = malloc(3); 94 if (*tok == NULL) { 95 free_token(token); 96 return EVENT_ERROR; 97 } 98 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 149 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; 156 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 186 filter = malloc(sizeof(*filter)); 187 if (filter == NULL) 188 return NULL; 189 190 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{ 199 return calloc(1, sizeof(struct filter_arg)); 200} 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: 210 break; 211 212 case FILTER_ARG_NUM: 213 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); 220 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 228 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 234 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 244static int add_event(struct event_list **events, 245 struct event_format *event) 246{ 247 struct event_list *list; 248 249 list = malloc(sizeof(*list)); 250 if (list == NULL) 251 return -1; 252 253 list->next = *events; 254 *events = list; 255 list->event = event; 256 return 0; 257} 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 271static enum pevent_errno 272find_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; 279 int fail = 0; 280 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 290 reg = malloc(strlen(event_name) + 3); 291 if (reg == NULL) 292 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 293 294 sprintf(reg, "^%s$", event_name); 295 296 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); 297 free(reg); 298 299 if (ret) 300 return PEVENT_ERRNO__INVALID_EVENT_NAME; 301 302 if (sys_name) { 303 reg = malloc(strlen(sys_name) + 3); 304 if (reg == NULL) { 305 regfree(&ereg); 306 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 307 } 308 309 sprintf(reg, "^%s$", sys_name); 310 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); 311 free(reg); 312 if (ret) { 313 regfree(&ereg); 314 return PEVENT_ERRNO__INVALID_EVENT_NAME; 315 } 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; 322 if (add_event(events, event) < 0) { 323 fail = 1; 324 break; 325 } 326 } 327 } 328 329 regfree(&ereg); 330 if (sys_name) 331 regfree(&sreg); 332 333 if (!match) 334 return PEVENT_ERRNO__EVENT_NOT_FOUND; 335 if (fail) 336 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 337 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 352static enum pevent_errno 353create_arg_item(struct event_format *event, const char *token, 354 enum event_type type, struct filter_arg **parg, char *error_str) 355{ 356 struct format_field *field; 357 struct filter_arg *arg; 358 359 arg = allocate_arg(); 360 if (arg == NULL) { 361 show_error(error_str, "failed to allocate filter arg"); 362 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 363 } 364 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); 373 if (!arg->value.str) { 374 free_arg(arg); 375 show_error(error_str, "failed to allocate string filter arg"); 376 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 377 } 378 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) { 390 /* 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 { 396 /* not a field, Make it false */ 397 arg->type = FILTER_ARG_BOOLEAN; 398 arg->boolean.value = FILTER_FALSE; 399 break; 400 } 401 } 402 arg->type = FILTER_ARG_FIELD; 403 arg->field.field = field; 404 break; 405 default: 406 free_arg(arg); 407 show_error(error_str, "expected a value but found %s", token); 408 return PEVENT_ERRNO__UNEXPECTED_TYPE; 409 } 410 *parg = arg; 411 return 0; 412} 413 414static struct filter_arg * 415create_arg_op(enum filter_op_type btype) 416{ 417 struct filter_arg *arg; 418 419 arg = allocate_arg(); 420 if (!arg) 421 return NULL; 422 423 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(); 435 if (!arg) 436 return NULL; 437 438 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(); 450 if (!arg) 451 return NULL; 452 453 /* Use NUM and change if necessary */ 454 arg->type = FILTER_ARG_NUM; 455 arg->op.type = etype; 456 457 return arg; 458} 459 460static enum pevent_errno 461add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) 462{ 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: 492 show_error(error_str, "Illegal rvalue"); 493 return PEVENT_ERRNO__ILLEGAL_RVALUE; 494 } 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; 532 op->boolean.value = FILTER_FALSE; 533 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"); 540 return PEVENT_ERRNO__ILLEGAL_LVALUE; 541 } 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); 559 return PEVENT_ERRNO__INVALID_REGEX; 560 } 561 break; 562 default: 563 show_error(error_str, 564 "Illegal comparison for string"); 565 return PEVENT_ERRNO__ILLEGAL_STRING_CMP; 566 } 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); 572 if (!op->str.val) { 573 show_error(error_str, "Failed to allocate string filter"); 574 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 575 } 576 /* 577 * Need a buffer to copy data for tests 578 */ 579 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 } 584 /* 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"); 601 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; 602 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: 621 show_error(error_str, "Syntax error"); 622 return PEVENT_ERRNO__SYNTAX_ERROR; 623} 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 635static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg) 636{ 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) 654 return PEVENT_ERRNO__INVALID_ARG_TYPE; 655 op->num.left = arg; 656 break; 657 default: 658 return PEVENT_ERRNO__INVALID_ARG_TYPE; 659 } 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 771static enum pevent_errno 772reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, 773 struct filter_arg *arg, char *error_str) 774{ 775 struct filter_arg *other_child; 776 struct filter_arg **ptr; 777 778 if (parent->type != FILTER_ARG_OP && 779 arg->type != FILTER_ARG_OP) { 780 show_error(error_str, "can not reparent other than OP"); 781 return PEVENT_ERRNO__REPARENT_NOT_OP; 782 } 783 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; 791 } else { 792 show_error(error_str, "Error in reparent op, find other child"); 793 return PEVENT_ERRNO__REPARENT_FAILED; 794 } 795 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); 805 return 0; 806 } 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; 812 else { 813 show_error(error_str, "Error in reparent op"); 814 return PEVENT_ERRNO__REPARENT_FAILED; 815 } 816 817 *ptr = arg; 818 819 free_arg(old_child); 820 return 0; 821} 822 823/* Returns either filter_vals (success) or pevent_errno (failfure) */ 824static int test_arg(struct filter_arg *parent, struct filter_arg *arg, 825 char *error_str) 826{ 827 int lval, rval; 828 829 switch (arg->type) { 830 831 /* bad case */ 832 case FILTER_ARG_BOOLEAN: 833 return FILTER_VAL_FALSE + arg->boolean.value; 834 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: 842 lval = test_arg(arg, arg->exp.left, error_str); 843 if (lval != FILTER_VAL_NORM) 844 return lval; 845 rval = test_arg(arg, arg->exp.right, error_str); 846 if (rval != FILTER_VAL_NORM) 847 return rval; 848 return FILTER_VAL_NORM; 849 850 case FILTER_ARG_NUM: 851 lval = test_arg(arg, arg->num.left, error_str); 852 if (lval != FILTER_VAL_NORM) 853 return lval; 854 rval = test_arg(arg, arg->num.right, error_str); 855 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) { 861 lval = test_arg(arg, arg->op.left, error_str); 862 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; 868 rval = test_arg(arg, arg->op.right, error_str); 869 if (rval != FILTER_VAL_NORM) 870 return rval; 871 872 return reparent_op_arg(parent, arg, arg->op.right, 873 error_str); 874 875 case FILTER_VAL_FALSE: 876 if (arg->op.type == FILTER_OP_AND) 877 return FILTER_VAL_FALSE; 878 rval = test_arg(arg, arg->op.right, error_str); 879 if (rval != FILTER_VAL_NORM) 880 return rval; 881 882 return reparent_op_arg(parent, arg, arg->op.right, 883 error_str); 884 885 default: 886 return lval; 887 } 888 } 889 890 rval = test_arg(arg, arg->op.right, error_str); 891 switch (rval) { 892 case FILTER_VAL_NORM: 893 default: 894 break; 895 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 return reparent_op_arg(parent, arg, arg->op.left, 903 error_str); 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 return reparent_op_arg(parent, arg, arg->op.left, 912 error_str); 913 } 914 915 return rval; 916 default: 917 show_error(error_str, "bad arg in filter tree"); 918 return PEVENT_ERRNO__BAD_FILTER_ARG; 919 } 920 return FILTER_VAL_NORM; 921} 922 923/* Remove any unknown event fields */ 924static int collapse_tree(struct filter_arg *arg, 925 struct filter_arg **arg_collapsed, char *error_str) 926{ 927 int ret; 928 929 ret = test_arg(arg, arg, error_str); 930 switch (ret) { 931 case FILTER_VAL_NORM: 932 break; 933 934 case FILTER_VAL_TRUE: 935 case FILTER_VAL_FALSE: 936 free_arg(arg); 937 arg = allocate_arg(); 938 if (arg) { 939 arg->type = FILTER_ARG_BOOLEAN; 940 arg->boolean.value = ret == FILTER_VAL_TRUE; 941 } else { 942 show_error(error_str, "Failed to allocate filter arg"); 943 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 944 } 945 break; 946 947 default: 948 /* test_arg() already set the error_str */ 949 free_arg(arg); 950 arg = NULL; 951 break; 952 } 953 954 *arg_collapsed = arg; 955 return ret; 956} 957 958static enum pevent_errno 959process_filter(struct event_format *event, struct filter_arg **parg, 960 char *error_str, int not) 961{ 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; 972 enum pevent_errno ret; 973 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: 983 ret = create_arg_item(event, token, type, &arg, error_str); 984 if (ret < 0) 985 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) 997 goto fail_syntax; 998 free(token); 999 *parg = current_exp; 1000 return 0; 1001 } 1002 } else 1003 goto fail_syntax; 1004 arg = NULL; 1005 break; 1006 1007 case EVENT_DELIM: 1008 if (*token == ',') { 1009 show_error(error_str, "Illegal token ','"); 1010 ret = PEVENT_ERRNO__ILLEGAL_TOKEN; 1011 goto fail; 1012 } 1013 1014 if (*token == '(') { 1015 if (left_item) { 1016 show_error(error_str, 1017 "Open paren can not come after item"); 1018 ret = PEVENT_ERRNO__INVALID_PAREN; 1019 goto fail; 1020 } 1021 if (current_exp) { 1022 show_error(error_str, 1023 "Open paren can not come after expression"); 1024 ret = PEVENT_ERRNO__INVALID_PAREN; 1025 goto fail; 1026 } 1027 1028 ret = process_filter(event, &arg, error_str, 0); 1029 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) { 1030 if (ret == 0) { 1031 show_error(error_str, 1032 "Unbalanced number of '('"); 1033 ret = PEVENT_ERRNO__UNBALANCED_PAREN; 1034 } 1035 goto fail; 1036 } 1037 ret = 0; 1038 1039 /* A not wants just one expression */ 1040 if (not) { 1041 if (current_op) 1042 goto fail_syntax; 1043 *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) 1057 goto fail_syntax; 1058 1059 /* Make sure everything is finished at this level */ 1060 if (current_exp && !check_op_done(current_exp)) 1061 goto fail_syntax; 1062 if (current_op && !check_op_done(current_op)) 1063 goto fail_syntax; 1064 1065 if (current_op) 1066 *parg = current_op; 1067 else 1068 *parg = current_exp; 1069 free(token); 1070 return PEVENT_ERRNO__UNBALANCED_PAREN; 1071 } 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) 1082 goto fail_syntax; 1083 /* fall through */ 1084 case OP_NOT: 1085 /* logic only processes ops and exp */ 1086 if (left_item) 1087 goto fail_syntax; 1088 break; 1089 case OP_EXP: 1090 case OP_CMP: 1091 if (!left_item) 1092 goto fail_syntax; 1093 break; 1094 case OP_NONE: 1095 show_error(error_str, 1096 "Unknown op token %s", token); 1097 ret = PEVENT_ERRNO__UNKNOWN_TOKEN; 1098 goto fail; 1099 } 1100 1101 ret = 0; 1102 switch (op_type) { 1103 case OP_BOOL: 1104 arg = create_arg_op(btype); 1105 if (arg == NULL) 1106 goto fail_alloc; 1107 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); 1117 if (arg == NULL) 1118 goto fail_alloc; 1119 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); 1138 if (arg == NULL) 1139 goto fail_alloc; 1140 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; 1148 goto fail_syntax; 1149 } 1150 current_exp = arg; 1151 break; 1152 default: 1153 break; 1154 } 1155 arg = NULL; 1156 if (ret < 0) 1157 goto fail_syntax; 1158 break; 1159 case EVENT_NONE: 1160 break; 1161 case EVENT_ERROR: 1162 goto fail_alloc; 1163 default: 1164 goto fail_syntax; 1165 } 1166 } while (type != EVENT_NONE); 1167 1168 if (!current_op && !current_exp) 1169 goto fail_syntax; 1170 1171 if (!current_op) 1172 current_op = current_exp; 1173 1174 ret = collapse_tree(current_op, parg, error_str); 1175 /* collapse_tree() may free current_op, and updates parg accordingly */ 1176 current_op = NULL; 1177 if (ret < 0) 1178 goto fail; 1179 1180 free(token); 1181 return 0; 1182 1183 fail_alloc: 1184 show_error(error_str, "failed to allocate filter arg"); 1185 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 1186 goto fail; 1187 fail_syntax: 1188 show_error(error_str, "Syntax error"); 1189 ret = PEVENT_ERRNO__SYNTAX_ERROR; 1190 fail: 1191 free_arg(current_op); 1192 free_arg(current_exp); 1193 free_arg(arg); 1194 free(token); 1195 return ret; 1196} 1197 1198static enum pevent_errno 1199process_event(struct event_format *event, const char *filter_str, 1200 struct filter_arg **parg, char *error_str) 1201{ 1202 int ret; 1203 1204 pevent_buffer_init(filter_str, strlen(filter_str)); 1205 1206 ret = process_filter(event, parg, error_str, 0); 1207 if (ret < 0) 1208 return ret; 1209 1210 /* If parg is NULL, then make it into FALSE */ 1211 if (!*parg) { 1212 *parg = allocate_arg(); 1213 if (*parg == NULL) 1214 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1215 1216 (*parg)->type = FILTER_ARG_BOOLEAN; 1217 (*parg)->boolean.value = FILTER_FALSE; 1218 } 1219 1220 return 0; 1221} 1222 1223static enum pevent_errno 1224filter_event(struct event_filter *filter, struct event_format *event, 1225 const char *filter_str, char *error_str) 1226{ 1227 struct filter_type *filter_type; 1228 struct filter_arg *arg; 1229 enum pevent_errno ret; 1230 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(); 1239 if (arg == NULL) 1240 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1241 1242 arg->type = FILTER_ARG_BOOLEAN; 1243 arg->boolean.value = FILTER_TRUE; 1244 } 1245 1246 filter_type = add_filter_type(filter, event->id); 1247 if (filter_type == NULL) 1248 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1249 1250 if (filter_type->filter) 1251 free_arg(filter_type->filter); 1252 filter_type->filter = arg; 1253 1254 return 0; 1255} 1256 1257static 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 1264/** 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 1268 * 1269 * Returns 0 if the filter was successfully added or a 1270 * negative error code. Use pevent_filter_strerror() to see 1271 * actual error message in case of error. 1272 */ 1273enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, 1274 const char *filter_str) 1275{ 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; 1285 enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ 1286 int len; 1287 int ret; 1288 1289 filter_init_error_buf(filter); 1290 1291 filter_start = strchr(filter_str, ':'); 1292 if (filter_start) 1293 len = filter_start - filter_str; 1294 else 1295 len = strlen(filter_str); 1296 1297 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 1307 this_event = malloc(len + 1); 1308 if (this_event == NULL) { 1309 /* This can only happen when events is NULL, but still */ 1310 free_events(events); 1311 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1312 } 1313 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) { 1325 /* This can only happen when events is NULL, but still */ 1326 free_events(events); 1327 free(this_event); 1328 return PEVENT_ERRNO__FILTER_NOT_FOUND; 1329 } 1330 1331 /* Find this event */ 1332 ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); 1333 if (ret < 0) { 1334 free_events(events); 1335 free(this_event); 1336 return ret; 1337 } 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, 1348 filter->error_buffer); 1349 /* 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); 1356 if (test) { 1357 printf(" '%s: %s'\n", event->event->name, test); 1358 free(test); 1359 } 1360 } 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/** 1377 * 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/** 1403 * 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(); 1495 if (arg == NULL) 1496 return -1; 1497 1498 arg->type = FILTER_ARG_BOOLEAN; 1499 if (strcmp(str, "TRUE") == 0) 1500 arg->boolean.value = 1; 1501 else 1502 arg->boolean.value = 0; 1503 1504 filter_type = add_filter_type(filter, event->id); 1505 if (filter_type == NULL) 1506 return -1; 1507 1508 filter_type->filter = arg; 1509 1510 free(str); 1511 return 0; 1512 } 1513 1514 filter_event(filter, event, str, NULL); 1515 free(str); 1516 1517 return 0; 1518} 1519 1520/** 1521 * pevent_filter_copy - copy a filter using another filter 1522 * @dest - the filter to copy to 1523 * @source - the filter to copy from 1524 * 1525 * Returns 0 on success and -1 if not all filters were copied 1526 */ 1527int pevent_filter_copy(struct event_filter *dest, struct event_filter *source) 1528{ 1529 int ret = 0; 1530 int i; 1531 1532 pevent_filter_reset(dest); 1533 1534 for (i = 0; i < source->filters; i++) { 1535 if (copy_filter_type(dest, source, &source->event_filters[i])) 1536 ret = -1; 1537 } 1538 return ret; 1539} 1540 1541 1542/** 1543 * pevent_update_trivial - update the trivial filters with the given filter 1544 * @dest - the filter to update 1545 * @source - the filter as the source of the update 1546 * @type - the type of trivial filter to update. 1547 * 1548 * Scan dest for trivial events matching @type to replace with the source. 1549 * 1550 * Returns 0 on success and -1 if there was a problem updating, but 1551 * events may have still been updated on error. 1552 */ 1553int pevent_update_trivial(struct event_filter *dest, struct event_filter *source, 1554 enum filter_trivial_type type) 1555{ 1556 struct pevent *src_pevent; 1557 struct pevent *dest_pevent; 1558 struct event_format *event; 1559 struct filter_type *filter_type; 1560 struct filter_arg *arg; 1561 char *str; 1562 int i; 1563 1564 src_pevent = source->pevent; 1565 dest_pevent = dest->pevent; 1566 1567 /* Do nothing if either of the filters has nothing to filter */ 1568 if (!dest->filters || !source->filters) 1569 return 0; 1570 1571 for (i = 0; i < dest->filters; i++) { 1572 filter_type = &dest->event_filters[i]; 1573 arg = filter_type->filter; 1574 if (arg->type != FILTER_ARG_BOOLEAN) 1575 continue; 1576 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) || 1577 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE)) 1578 continue; 1579 1580 event = filter_type->event; 1581 1582 if (src_pevent != dest_pevent) { 1583 /* do a look up */ 1584 event = pevent_find_event_by_name(src_pevent, 1585 event->system, 1586 event->name); 1587 if (!event) 1588 return -1; 1589 } 1590 1591 str = pevent_filter_make_string(source, event->id); 1592 if (!str) 1593 continue; 1594 1595 /* Don't bother if the filter is trivial too */ 1596 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0) 1597 filter_event(dest, event, str, NULL); 1598 free(str); 1599 } 1600 return 0; 1601} 1602 1603/** 1604 * pevent_filter_clear_trivial - clear TRUE and FALSE filters 1605 * @filter: the filter to remove trivial filters from 1606 * @type: remove only true, false, or both 1607 * 1608 * Removes filters that only contain a TRUE or FALES boolean arg. 1609 * 1610 * Returns 0 on success and -1 if there was a problem. 1611 */ 1612int pevent_filter_clear_trivial(struct event_filter *filter, 1613 enum filter_trivial_type type) 1614{ 1615 struct filter_type *filter_type; 1616 int count = 0; 1617 int *ids = NULL; 1618 int i; 1619 1620 if (!filter->filters) 1621 return 0; 1622 1623 /* 1624 * Two steps, first get all ids with trivial filters. 1625 * then remove those ids. 1626 */ 1627 for (i = 0; i < filter->filters; i++) { 1628 int *new_ids; 1629 1630 filter_type = &filter->event_filters[i]; 1631 if (filter_type->filter->type != FILTER_ARG_BOOLEAN) 1632 continue; 1633 switch (type) { 1634 case FILTER_TRIVIAL_FALSE: 1635 if (filter_type->filter->boolean.value) 1636 continue; 1637 case FILTER_TRIVIAL_TRUE: 1638 if (!filter_type->filter->boolean.value) 1639 continue; 1640 default: 1641 break; 1642 } 1643 1644 new_ids = realloc(ids, sizeof(*ids) * (count + 1)); 1645 if (!new_ids) { 1646 free(ids); 1647 return -1; 1648 } 1649 1650 ids = new_ids; 1651 ids[count++] = filter_type->event_id; 1652 } 1653 1654 if (!count) 1655 return 0; 1656 1657 for (i = 0; i < count; i++) 1658 pevent_filter_remove_event(filter, ids[i]); 1659 1660 free(ids); 1661 return 0; 1662} 1663 1664/** 1665 * pevent_filter_event_has_trivial - return true event contains trivial filter 1666 * @filter: the filter with the information 1667 * @event_id: the id of the event to test 1668 * @type: trivial type to test for (TRUE, FALSE, EITHER) 1669 * 1670 * Returns 1 if the event contains a matching trivial type 1671 * otherwise 0. 1672 */ 1673int pevent_filter_event_has_trivial(struct event_filter *filter, 1674 int event_id, 1675 enum filter_trivial_type type) 1676{ 1677 struct filter_type *filter_type; 1678 1679 if (!filter->filters) 1680 return 0; 1681 1682 filter_type = find_filter_type(filter, event_id); 1683 1684 if (!filter_type) 1685 return 0; 1686 1687 if (filter_type->filter->type != FILTER_ARG_BOOLEAN) 1688 return 0; 1689 1690 switch (type) { 1691 case FILTER_TRIVIAL_FALSE: 1692 return !filter_type->filter->boolean.value; 1693 1694 case FILTER_TRIVIAL_TRUE: 1695 return filter_type->filter->boolean.value; 1696 default: 1697 return 1; 1698 } 1699} 1700 1701static int test_filter(struct event_format *event, struct filter_arg *arg, 1702 struct pevent_record *record, enum pevent_errno *err); 1703 1704static const char * 1705get_comm(struct event_format *event, struct pevent_record *record) 1706{ 1707 const char *comm; 1708 int pid; 1709 1710 pid = pevent_data_pid(event->pevent, record); 1711 comm = pevent_data_comm_from_pid(event->pevent, pid); 1712 return comm; 1713} 1714 1715static unsigned long long 1716get_value(struct event_format *event, 1717 struct format_field *field, struct pevent_record *record) 1718{ 1719 unsigned long long val; 1720 1721 /* Handle our dummy "comm" field */ 1722 if (field == &comm) { 1723 const char *name; 1724 1725 name = get_comm(event, record); 1726 return (unsigned long)name; 1727 } 1728 1729 /* Handle our dummy "cpu" field */ 1730 if (field == &cpu) 1731 return record->cpu; 1732 1733 pevent_read_number_field(field, record->data, &val); 1734 1735 if (!(field->flags & FIELD_IS_SIGNED)) 1736 return val; 1737 1738 switch (field->size) { 1739 case 1: 1740 return (char)val; 1741 case 2: 1742 return (short)val; 1743 case 4: 1744 return (int)val; 1745 case 8: 1746 return (long long)val; 1747 } 1748 return val; 1749} 1750 1751static unsigned long long 1752get_arg_value(struct event_format *event, struct filter_arg *arg, 1753 struct pevent_record *record, enum pevent_errno *err); 1754 1755static unsigned long long 1756get_exp_value(struct event_format *event, struct filter_arg *arg, 1757 struct pevent_record *record, enum pevent_errno *err) 1758{ 1759 unsigned long long lval, rval; 1760 1761 lval = get_arg_value(event, arg->exp.left, record, err); 1762 rval = get_arg_value(event, arg->exp.right, record, err); 1763 1764 if (*err) { 1765 /* 1766 * There was an error, no need to process anymore. 1767 */ 1768 return 0; 1769 } 1770 1771 switch (arg->exp.type) { 1772 case FILTER_EXP_ADD: 1773 return lval + rval; 1774 1775 case FILTER_EXP_SUB: 1776 return lval - rval; 1777 1778 case FILTER_EXP_MUL: 1779 return lval * rval; 1780 1781 case FILTER_EXP_DIV: 1782 return lval / rval; 1783 1784 case FILTER_EXP_MOD: 1785 return lval % rval; 1786 1787 case FILTER_EXP_RSHIFT: 1788 return lval >> rval; 1789 1790 case FILTER_EXP_LSHIFT: 1791 return lval << rval; 1792 1793 case FILTER_EXP_AND: 1794 return lval & rval; 1795 1796 case FILTER_EXP_OR: 1797 return lval | rval; 1798 1799 case FILTER_EXP_XOR: 1800 return lval ^ rval; 1801 1802 case FILTER_EXP_NOT: 1803 default: 1804 if (!*err) 1805 *err = PEVENT_ERRNO__INVALID_EXP_TYPE; 1806 } 1807 return 0; 1808} 1809 1810static unsigned long long 1811get_arg_value(struct event_format *event, struct filter_arg *arg, 1812 struct pevent_record *record, enum pevent_errno *err) 1813{ 1814 switch (arg->type) { 1815 case FILTER_ARG_FIELD: 1816 return get_value(event, arg->field.field, record); 1817 1818 case FILTER_ARG_VALUE: 1819 if (arg->value.type != FILTER_NUMBER) { 1820 if (!*err) 1821 *err = PEVENT_ERRNO__NOT_A_NUMBER; 1822 } 1823 return arg->value.val; 1824 1825 case FILTER_ARG_EXP: 1826 return get_exp_value(event, arg, record, err); 1827 1828 default: 1829 if (!*err) 1830 *err = PEVENT_ERRNO__INVALID_ARG_TYPE; 1831 } 1832 return 0; 1833} 1834 1835static int test_num(struct event_format *event, struct filter_arg *arg, 1836 struct pevent_record *record, enum pevent_errno *err) 1837{ 1838 unsigned long long lval, rval; 1839 1840 lval = get_arg_value(event, arg->num.left, record, err); 1841 rval = get_arg_value(event, arg->num.right, record, err); 1842 1843 if (*err) { 1844 /* 1845 * There was an error, no need to process anymore. 1846 */ 1847 return 0; 1848 } 1849 1850 switch (arg->num.type) { 1851 case FILTER_CMP_EQ: 1852 return lval == rval; 1853 1854 case FILTER_CMP_NE: 1855 return lval != rval; 1856 1857 case FILTER_CMP_GT: 1858 return lval > rval; 1859 1860 case FILTER_CMP_LT: 1861 return lval < rval; 1862 1863 case FILTER_CMP_GE: 1864 return lval >= rval; 1865 1866 case FILTER_CMP_LE: 1867 return lval <= rval; 1868 1869 default: 1870 if (!*err) 1871 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; 1872 return 0; 1873 } 1874} 1875 1876static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) 1877{ 1878 struct event_format *event; 1879 struct pevent *pevent; 1880 unsigned long long addr; 1881 const char *val = NULL; 1882 char hex[64]; 1883 1884 /* If the field is not a string convert it */ 1885 if (arg->str.field->flags & FIELD_IS_STRING) { 1886 val = record->data + arg->str.field->offset; 1887 1888 /* 1889 * We need to copy the data since we can't be sure the field 1890 * is null terminated. 1891 */ 1892 if (*(val + arg->str.field->size - 1)) { 1893 /* copy it */ 1894 memcpy(arg->str.buffer, val, arg->str.field->size); 1895 /* the buffer is already NULL terminated */ 1896 val = arg->str.buffer; 1897 } 1898 1899 } else { 1900 event = arg->str.field->event; 1901 pevent = event->pevent; 1902 addr = get_value(event, arg->str.field, record); 1903 1904 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG)) 1905 /* convert to a kernel symbol */ 1906 val = pevent_find_function(pevent, addr); 1907 1908 if (val == NULL) { 1909 /* just use the hex of the string name */ 1910 snprintf(hex, 64, "0x%llx", addr); 1911 val = hex; 1912 } 1913 } 1914 1915 return val; 1916} 1917 1918static int test_str(struct event_format *event, struct filter_arg *arg, 1919 struct pevent_record *record, enum pevent_errno *err) 1920{ 1921 const char *val; 1922 1923 if (arg->str.field == &comm) 1924 val = get_comm(event, record); 1925 else 1926 val = get_field_str(arg, record); 1927 1928 switch (arg->str.type) { 1929 case FILTER_CMP_MATCH: 1930 return strcmp(val, arg->str.val) == 0; 1931 1932 case FILTER_CMP_NOT_MATCH: 1933 return strcmp(val, arg->str.val) != 0; 1934 1935 case FILTER_CMP_REGEX: 1936 /* Returns zero on match */ 1937 return !regexec(&arg->str.reg, val, 0, NULL, 0); 1938 1939 case FILTER_CMP_NOT_REGEX: 1940 return regexec(&arg->str.reg, val, 0, NULL, 0); 1941 1942 default: 1943 if (!*err) 1944 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP; 1945 return 0; 1946 } 1947} 1948 1949static int test_op(struct event_format *event, struct filter_arg *arg, 1950 struct pevent_record *record, enum pevent_errno *err) 1951{ 1952 switch (arg->op.type) { 1953 case FILTER_OP_AND: 1954 return test_filter(event, arg->op.left, record, err) && 1955 test_filter(event, arg->op.right, record, err); 1956 1957 case FILTER_OP_OR: 1958 return test_filter(event, arg->op.left, record, err) || 1959 test_filter(event, arg->op.right, record, err); 1960 1961 case FILTER_OP_NOT: 1962 return !test_filter(event, arg->op.right, record, err); 1963 1964 default: 1965 if (!*err) 1966 *err = PEVENT_ERRNO__INVALID_OP_TYPE; 1967 return 0; 1968 } 1969} 1970 1971static int test_filter(struct event_format *event, struct filter_arg *arg, 1972 struct pevent_record *record, enum pevent_errno *err) 1973{ 1974 if (*err) { 1975 /* 1976 * There was an error, no need to process anymore. 1977 */ 1978 return 0; 1979 } 1980 1981 switch (arg->type) { 1982 case FILTER_ARG_BOOLEAN: 1983 /* easy case */ 1984 return arg->boolean.value; 1985 1986 case FILTER_ARG_OP: 1987 return test_op(event, arg, record, err); 1988 1989 case FILTER_ARG_NUM: 1990 return test_num(event, arg, record, err); 1991 1992 case FILTER_ARG_STR: 1993 return test_str(event, arg, record, err); 1994 1995 case FILTER_ARG_EXP: 1996 case FILTER_ARG_VALUE: 1997 case FILTER_ARG_FIELD: 1998 /* 1999 * Expressions, fields and values evaluate 2000 * to true if they return non zero 2001 */ 2002 return !!get_arg_value(event, arg, record, err); 2003 2004 default: 2005 if (!*err) 2006 *err = PEVENT_ERRNO__INVALID_ARG_TYPE; 2007 return 0; 2008 } 2009} 2010 2011/** 2012 * pevent_event_filtered - return true if event has filter 2013 * @filter: filter struct with filter information 2014 * @event_id: event id to test if filter exists 2015 * 2016 * Returns 1 if filter found for @event_id 2017 * otherwise 0; 2018 */ 2019int pevent_event_filtered(struct event_filter *filter, int event_id) 2020{ 2021 struct filter_type *filter_type; 2022 2023 if (!filter->filters) 2024 return 0; 2025 2026 filter_type = find_filter_type(filter, event_id); 2027 2028 return filter_type ? 1 : 0; 2029} 2030 2031/** 2032 * pevent_filter_match - test if a record matches a filter 2033 * @filter: filter struct with filter information 2034 * @record: the record to test against the filter 2035 * 2036 * Returns: match result or error code (prefixed with PEVENT_ERRNO__) 2037 * FILTER_MATCH - filter found for event and @record matches 2038 * FILTER_MISS - filter found for event and @record does not match 2039 * FILTER_NOT_FOUND - no filter found for @record's event 2040 * NO_FILTER - if no filters exist 2041 * otherwise - error occurred during test 2042 */ 2043enum pevent_errno pevent_filter_match(struct event_filter *filter, 2044 struct pevent_record *record) 2045{ 2046 struct pevent *pevent = filter->pevent; 2047 struct filter_type *filter_type; 2048 int event_id; 2049 int ret; 2050 enum pevent_errno err = 0; 2051 2052 filter_init_error_buf(filter); 2053 2054 if (!filter->filters) 2055 return PEVENT_ERRNO__NO_FILTER; 2056 2057 event_id = pevent_data_type(pevent, record); 2058 2059 filter_type = find_filter_type(filter, event_id); 2060 if (!filter_type) 2061 return PEVENT_ERRNO__FILTER_NOT_FOUND; 2062 2063 ret = test_filter(filter_type->event, filter_type->filter, record, &err); 2064 if (err) 2065 return err; 2066 2067 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS; 2068} 2069 2070static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) 2071{ 2072 char *str = NULL; 2073 char *left = NULL; 2074 char *right = NULL; 2075 char *op = NULL; 2076 int left_val = -1; 2077 int right_val = -1; 2078 int val; 2079 2080 switch (arg->op.type) { 2081 case FILTER_OP_AND: 2082 op = "&&"; 2083 /* fall through */ 2084 case FILTER_OP_OR: 2085 if (!op) 2086 op = "||"; 2087 2088 left = arg_to_str(filter, arg->op.left); 2089 right = arg_to_str(filter, arg->op.right); 2090 if (!left || !right) 2091 break; 2092 2093 /* Try to consolidate boolean values */ 2094 if (strcmp(left, "TRUE") == 0) 2095 left_val = 1; 2096 else if (strcmp(left, "FALSE") == 0) 2097 left_val = 0; 2098 2099 if (strcmp(right, "TRUE") == 0) 2100 right_val = 1; 2101 else if (strcmp(right, "FALSE") == 0) 2102 right_val = 0; 2103 2104 if (left_val >= 0) { 2105 if ((arg->op.type == FILTER_OP_AND && !left_val) || 2106 (arg->op.type == FILTER_OP_OR && left_val)) { 2107 /* Just return left value */ 2108 str = left; 2109 left = NULL; 2110 break; 2111 } 2112 if (right_val >= 0) { 2113 /* just evaluate this. */ 2114 val = 0; 2115 switch (arg->op.type) { 2116 case FILTER_OP_AND: 2117 val = left_val && right_val; 2118 break; 2119 case FILTER_OP_OR: 2120 val = left_val || right_val; 2121 break; 2122 default: 2123 break; 2124 } 2125 asprintf(&str, val ? "TRUE" : "FALSE"); 2126 break; 2127 } 2128 } 2129 if (right_val >= 0) { 2130 if ((arg->op.type == FILTER_OP_AND && !right_val) || 2131 (arg->op.type == FILTER_OP_OR && right_val)) { 2132 /* Just return right value */ 2133 str = right; 2134 right = NULL; 2135 break; 2136 } 2137 /* The right value is meaningless */ 2138 str = left; 2139 left = NULL; 2140 break; 2141 } 2142 2143 asprintf(&str, "(%s) %s (%s)", left, op, right); 2144 break; 2145 2146 case FILTER_OP_NOT: 2147 op = "!"; 2148 right = arg_to_str(filter, arg->op.right); 2149 if (!right) 2150 break; 2151 2152 /* See if we can consolidate */ 2153 if (strcmp(right, "TRUE") == 0) 2154 right_val = 1; 2155 else if (strcmp(right, "FALSE") == 0) 2156 right_val = 0; 2157 if (right_val >= 0) { 2158 /* just return the opposite */ 2159 asprintf(&str, right_val ? "FALSE" : "TRUE"); 2160 break; 2161 } 2162 asprintf(&str, "%s(%s)", op, right); 2163 break; 2164 2165 default: 2166 /* ?? */ 2167 break; 2168 } 2169 free(left); 2170 free(right); 2171 return str; 2172} 2173 2174static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) 2175{ 2176 char *str = NULL; 2177 2178 asprintf(&str, "%lld", arg->value.val); 2179 2180 return str; 2181} 2182 2183static char *field_to_str(struct event_filter *filter, struct filter_arg *arg) 2184{ 2185 return strdup(arg->field.field->name); 2186} 2187 2188static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) 2189{ 2190 char *lstr; 2191 char *rstr; 2192 char *op; 2193 char *str = NULL; 2194 2195 lstr = arg_to_str(filter, arg->exp.left); 2196 rstr = arg_to_str(filter, arg->exp.right); 2197 if (!lstr || !rstr) 2198 goto out; 2199 2200 switch (arg->exp.type) { 2201 case FILTER_EXP_ADD: 2202 op = "+"; 2203 break; 2204 case FILTER_EXP_SUB: 2205 op = "-"; 2206 break; 2207 case FILTER_EXP_MUL: 2208 op = "*"; 2209 break; 2210 case FILTER_EXP_DIV: 2211 op = "/"; 2212 break; 2213 case FILTER_EXP_MOD: 2214 op = "%"; 2215 break; 2216 case FILTER_EXP_RSHIFT: 2217 op = ">>"; 2218 break; 2219 case FILTER_EXP_LSHIFT: 2220 op = "<<"; 2221 break; 2222 case FILTER_EXP_AND: 2223 op = "&"; 2224 break; 2225 case FILTER_EXP_OR: 2226 op = "|"; 2227 break; 2228 case FILTER_EXP_XOR: 2229 op = "^"; 2230 break; 2231 default: 2232 op = "[ERROR IN EXPRESSION TYPE]"; 2233 break; 2234 } 2235 2236 asprintf(&str, "%s %s %s", lstr, op, rstr); 2237out: 2238 free(lstr); 2239 free(rstr); 2240 2241 return str; 2242} 2243 2244static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) 2245{ 2246 char *lstr; 2247 char *rstr; 2248 char *str = NULL; 2249 char *op = NULL; 2250 2251 lstr = arg_to_str(filter, arg->num.left); 2252 rstr = arg_to_str(filter, arg->num.right); 2253 if (!lstr || !rstr) 2254 goto out; 2255 2256 switch (arg->num.type) { 2257 case FILTER_CMP_EQ: 2258 op = "=="; 2259 /* fall through */ 2260 case FILTER_CMP_NE: 2261 if (!op) 2262 op = "!="; 2263 /* fall through */ 2264 case FILTER_CMP_GT: 2265 if (!op) 2266 op = ">"; 2267 /* fall through */ 2268 case FILTER_CMP_LT: 2269 if (!op) 2270 op = "<"; 2271 /* fall through */ 2272 case FILTER_CMP_GE: 2273 if (!op) 2274 op = ">="; 2275 /* fall through */ 2276 case FILTER_CMP_LE: 2277 if (!op) 2278 op = "<="; 2279 2280 asprintf(&str, "%s %s %s", lstr, op, rstr); 2281 break; 2282 2283 default: 2284 /* ?? */ 2285 break; 2286 } 2287 2288out: 2289 free(lstr); 2290 free(rstr); 2291 return str; 2292} 2293 2294static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) 2295{ 2296 char *str = NULL; 2297 char *op = NULL; 2298 2299 switch (arg->str.type) { 2300 case FILTER_CMP_MATCH: 2301 op = "=="; 2302 /* fall through */ 2303 case FILTER_CMP_NOT_MATCH: 2304 if (!op) 2305 op = "!="; 2306 /* fall through */ 2307 case FILTER_CMP_REGEX: 2308 if (!op) 2309 op = "=~"; 2310 /* fall through */ 2311 case FILTER_CMP_NOT_REGEX: 2312 if (!op) 2313 op = "!~"; 2314 2315 asprintf(&str, "%s %s \"%s\"", 2316 arg->str.field->name, op, arg->str.val); 2317 break; 2318 2319 default: 2320 /* ?? */ 2321 break; 2322 } 2323 return str; 2324} 2325 2326static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) 2327{ 2328 char *str = NULL; 2329 2330 switch (arg->type) { 2331 case FILTER_ARG_BOOLEAN: 2332 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE"); 2333 return str; 2334 2335 case FILTER_ARG_OP: 2336 return op_to_str(filter, arg); 2337 2338 case FILTER_ARG_NUM: 2339 return num_to_str(filter, arg); 2340 2341 case FILTER_ARG_STR: 2342 return str_to_str(filter, arg); 2343 2344 case FILTER_ARG_VALUE: 2345 return val_to_str(filter, arg); 2346 2347 case FILTER_ARG_FIELD: 2348 return field_to_str(filter, arg); 2349 2350 case FILTER_ARG_EXP: 2351 return exp_to_str(filter, arg); 2352 2353 default: 2354 /* ?? */ 2355 return NULL; 2356 } 2357 2358} 2359 2360/** 2361 * pevent_filter_make_string - return a string showing the filter 2362 * @filter: filter struct with filter information 2363 * @event_id: the event id to return the filter string with 2364 * 2365 * Returns a string that displays the filter contents. 2366 * This string must be freed with free(str). 2367 * NULL is returned if no filter is found or allocation failed. 2368 */ 2369char * 2370pevent_filter_make_string(struct event_filter *filter, int event_id) 2371{ 2372 struct filter_type *filter_type; 2373 2374 if (!filter->filters) 2375 return NULL; 2376 2377 filter_type = find_filter_type(filter, event_id); 2378 2379 if (!filter_type) 2380 return NULL; 2381 2382 return arg_to_str(filter, filter_type->filter); 2383} 2384 2385/** 2386 * pevent_filter_compare - compare two filters and return if they are the same 2387 * @filter1: Filter to compare with @filter2 2388 * @filter2: Filter to compare with @filter1 2389 * 2390 * Returns: 2391 * 1 if the two filters hold the same content. 2392 * 0 if they do not. 2393 */ 2394int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2) 2395{ 2396 struct filter_type *filter_type1; 2397 struct filter_type *filter_type2; 2398 char *str1, *str2; 2399 int result; 2400 int i; 2401 2402 /* Do the easy checks first */ 2403 if (filter1->filters != filter2->filters) 2404 return 0; 2405 if (!filter1->filters && !filter2->filters) 2406 return 1; 2407 2408 /* 2409 * Now take a look at each of the events to see if they have the same 2410 * filters to them. 2411 */ 2412 for (i = 0; i < filter1->filters; i++) { 2413 filter_type1 = &filter1->event_filters[i]; 2414 filter_type2 = find_filter_type(filter2, filter_type1->event_id); 2415 if (!filter_type2) 2416 break; 2417 if (filter_type1->filter->type != filter_type2->filter->type) 2418 break; 2419 switch (filter_type1->filter->type) { 2420 case FILTER_TRIVIAL_FALSE: 2421 case FILTER_TRIVIAL_TRUE: 2422 /* trivial types just need the type compared */ 2423 continue; 2424 default: 2425 break; 2426 } 2427 /* The best way to compare complex filters is with strings */ 2428 str1 = arg_to_str(filter1, filter_type1->filter); 2429 str2 = arg_to_str(filter2, filter_type2->filter); 2430 if (str1 && str2) 2431 result = strcmp(str1, str2) != 0; 2432 else 2433 /* bail out if allocation fails */ 2434 result = 1; 2435 2436 free(str1); 2437 free(str2); 2438 if (result) 2439 break; 2440 } 2441 2442 if (i < filter1->filters) 2443 return 0; 2444 return 1; 2445} 2446