at v4.18-rc2 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 ret = asprintf(&reg, "^%s$", event_name); 291 if (ret < 0) 292 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 293 294 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); 295 free(reg); 296 297 if (ret) 298 return PEVENT_ERRNO__INVALID_EVENT_NAME; 299 300 if (sys_name) { 301 ret = asprintf(&reg, "^%s$", sys_name); 302 if (ret < 0) { 303 regfree(&ereg); 304 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 305 } 306 307 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); 308 free(reg); 309 if (ret) { 310 regfree(&ereg); 311 return PEVENT_ERRNO__INVALID_EVENT_NAME; 312 } 313 } 314 315 for (i = 0; i < pevent->nr_events; i++) { 316 event = pevent->events[i]; 317 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) { 318 match = 1; 319 if (add_event(events, event) < 0) { 320 fail = 1; 321 break; 322 } 323 } 324 } 325 326 regfree(&ereg); 327 if (sys_name) 328 regfree(&sreg); 329 330 if (!match) 331 return PEVENT_ERRNO__EVENT_NOT_FOUND; 332 if (fail) 333 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 334 335 return 0; 336} 337 338static void free_events(struct event_list *events) 339{ 340 struct event_list *event; 341 342 while (events) { 343 event = events; 344 events = events->next; 345 free(event); 346 } 347} 348 349static enum pevent_errno 350create_arg_item(struct event_format *event, const char *token, 351 enum event_type type, struct filter_arg **parg, char *error_str) 352{ 353 struct format_field *field; 354 struct filter_arg *arg; 355 356 arg = allocate_arg(); 357 if (arg == NULL) { 358 show_error(error_str, "failed to allocate filter arg"); 359 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 360 } 361 362 switch (type) { 363 364 case EVENT_SQUOTE: 365 case EVENT_DQUOTE: 366 arg->type = FILTER_ARG_VALUE; 367 arg->value.type = 368 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; 369 arg->value.str = strdup(token); 370 if (!arg->value.str) { 371 free_arg(arg); 372 show_error(error_str, "failed to allocate string filter arg"); 373 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 374 } 375 break; 376 case EVENT_ITEM: 377 /* if it is a number, then convert it */ 378 if (isdigit(token[0])) { 379 arg->type = FILTER_ARG_VALUE; 380 arg->value.type = FILTER_NUMBER; 381 arg->value.val = strtoull(token, NULL, 0); 382 break; 383 } 384 /* Consider this a field */ 385 field = pevent_find_any_field(event, token); 386 if (!field) { 387 /* If token is 'COMM' or 'CPU' then it is special */ 388 if (strcmp(token, COMM) == 0) { 389 field = &comm; 390 } else if (strcmp(token, CPU) == 0) { 391 field = &cpu; 392 } else { 393 /* not a field, Make it false */ 394 arg->type = FILTER_ARG_BOOLEAN; 395 arg->boolean.value = FILTER_FALSE; 396 break; 397 } 398 } 399 arg->type = FILTER_ARG_FIELD; 400 arg->field.field = field; 401 break; 402 default: 403 free_arg(arg); 404 show_error(error_str, "expected a value but found %s", token); 405 return PEVENT_ERRNO__UNEXPECTED_TYPE; 406 } 407 *parg = arg; 408 return 0; 409} 410 411static struct filter_arg * 412create_arg_op(enum filter_op_type btype) 413{ 414 struct filter_arg *arg; 415 416 arg = allocate_arg(); 417 if (!arg) 418 return NULL; 419 420 arg->type = FILTER_ARG_OP; 421 arg->op.type = btype; 422 423 return arg; 424} 425 426static struct filter_arg * 427create_arg_exp(enum filter_exp_type etype) 428{ 429 struct filter_arg *arg; 430 431 arg = allocate_arg(); 432 if (!arg) 433 return NULL; 434 435 arg->type = FILTER_ARG_EXP; 436 arg->exp.type = etype; 437 438 return arg; 439} 440 441static struct filter_arg * 442create_arg_cmp(enum filter_cmp_type ctype) 443{ 444 struct filter_arg *arg; 445 446 arg = allocate_arg(); 447 if (!arg) 448 return NULL; 449 450 /* Use NUM and change if necessary */ 451 arg->type = FILTER_ARG_NUM; 452 arg->num.type = ctype; 453 454 return arg; 455} 456 457static enum pevent_errno 458add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) 459{ 460 struct filter_arg *left; 461 char *str; 462 int op_type; 463 int ret; 464 465 switch (op->type) { 466 case FILTER_ARG_EXP: 467 if (op->exp.right) 468 goto out_fail; 469 op->exp.right = arg; 470 break; 471 472 case FILTER_ARG_OP: 473 if (op->op.right) 474 goto out_fail; 475 op->op.right = arg; 476 break; 477 478 case FILTER_ARG_NUM: 479 if (op->op.right) 480 goto out_fail; 481 /* 482 * The arg must be num, str, or field 483 */ 484 switch (arg->type) { 485 case FILTER_ARG_VALUE: 486 case FILTER_ARG_FIELD: 487 break; 488 default: 489 show_error(error_str, "Illegal rvalue"); 490 return PEVENT_ERRNO__ILLEGAL_RVALUE; 491 } 492 493 /* 494 * Depending on the type, we may need to 495 * convert this to a string or regex. 496 */ 497 switch (arg->value.type) { 498 case FILTER_CHAR: 499 /* 500 * A char should be converted to number if 501 * the string is 1 byte, and the compare 502 * is not a REGEX. 503 */ 504 if (strlen(arg->value.str) == 1 && 505 op->num.type != FILTER_CMP_REGEX && 506 op->num.type != FILTER_CMP_NOT_REGEX) { 507 arg->value.type = FILTER_NUMBER; 508 goto do_int; 509 } 510 /* fall through */ 511 case FILTER_STRING: 512 513 /* convert op to a string arg */ 514 op_type = op->num.type; 515 left = op->num.left; 516 str = arg->value.str; 517 518 /* reset the op for the new field */ 519 memset(op, 0, sizeof(*op)); 520 521 /* 522 * If left arg was a field not found then 523 * NULL the entire op. 524 */ 525 if (left->type == FILTER_ARG_BOOLEAN) { 526 free_arg(left); 527 free_arg(arg); 528 op->type = FILTER_ARG_BOOLEAN; 529 op->boolean.value = FILTER_FALSE; 530 break; 531 } 532 533 /* Left arg must be a field */ 534 if (left->type != FILTER_ARG_FIELD) { 535 show_error(error_str, 536 "Illegal lvalue for string comparison"); 537 return PEVENT_ERRNO__ILLEGAL_LVALUE; 538 } 539 540 /* Make sure this is a valid string compare */ 541 switch (op_type) { 542 case FILTER_CMP_EQ: 543 op_type = FILTER_CMP_MATCH; 544 break; 545 case FILTER_CMP_NE: 546 op_type = FILTER_CMP_NOT_MATCH; 547 break; 548 549 case FILTER_CMP_REGEX: 550 case FILTER_CMP_NOT_REGEX: 551 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB); 552 if (ret) { 553 show_error(error_str, 554 "RegEx '%s' did not compute", 555 str); 556 return PEVENT_ERRNO__INVALID_REGEX; 557 } 558 break; 559 default: 560 show_error(error_str, 561 "Illegal comparison for string"); 562 return PEVENT_ERRNO__ILLEGAL_STRING_CMP; 563 } 564 565 op->type = FILTER_ARG_STR; 566 op->str.type = op_type; 567 op->str.field = left->field.field; 568 op->str.val = strdup(str); 569 if (!op->str.val) { 570 show_error(error_str, "Failed to allocate string filter"); 571 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 572 } 573 /* 574 * Need a buffer to copy data for tests 575 */ 576 op->str.buffer = malloc(op->str.field->size + 1); 577 if (!op->str.buffer) { 578 show_error(error_str, "Failed to allocate string filter"); 579 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 580 } 581 /* Null terminate this buffer */ 582 op->str.buffer[op->str.field->size] = 0; 583 584 /* We no longer have left or right args */ 585 free_arg(arg); 586 free_arg(left); 587 588 break; 589 590 case FILTER_NUMBER: 591 592 do_int: 593 switch (op->num.type) { 594 case FILTER_CMP_REGEX: 595 case FILTER_CMP_NOT_REGEX: 596 show_error(error_str, 597 "Op not allowed with integers"); 598 return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; 599 600 default: 601 break; 602 } 603 604 /* numeric compare */ 605 op->num.right = arg; 606 break; 607 default: 608 goto out_fail; 609 } 610 break; 611 default: 612 goto out_fail; 613 } 614 615 return 0; 616 617 out_fail: 618 show_error(error_str, "Syntax error"); 619 return PEVENT_ERRNO__SYNTAX_ERROR; 620} 621 622static struct filter_arg * 623rotate_op_right(struct filter_arg *a, struct filter_arg *b) 624{ 625 struct filter_arg *arg; 626 627 arg = a->op.right; 628 a->op.right = b; 629 return arg; 630} 631 632static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg) 633{ 634 switch (op->type) { 635 case FILTER_ARG_EXP: 636 if (arg->type == FILTER_ARG_OP) 637 arg = rotate_op_right(arg, op); 638 op->exp.left = arg; 639 break; 640 641 case FILTER_ARG_OP: 642 op->op.left = arg; 643 break; 644 case FILTER_ARG_NUM: 645 if (arg->type == FILTER_ARG_OP) 646 arg = rotate_op_right(arg, op); 647 648 /* left arg of compares must be a field */ 649 if (arg->type != FILTER_ARG_FIELD && 650 arg->type != FILTER_ARG_BOOLEAN) 651 return PEVENT_ERRNO__INVALID_ARG_TYPE; 652 op->num.left = arg; 653 break; 654 default: 655 return PEVENT_ERRNO__INVALID_ARG_TYPE; 656 } 657 return 0; 658} 659 660enum op_type { 661 OP_NONE, 662 OP_BOOL, 663 OP_NOT, 664 OP_EXP, 665 OP_CMP, 666}; 667 668static enum op_type process_op(const char *token, 669 enum filter_op_type *btype, 670 enum filter_cmp_type *ctype, 671 enum filter_exp_type *etype) 672{ 673 *btype = FILTER_OP_NOT; 674 *etype = FILTER_EXP_NONE; 675 *ctype = FILTER_CMP_NONE; 676 677 if (strcmp(token, "&&") == 0) 678 *btype = FILTER_OP_AND; 679 else if (strcmp(token, "||") == 0) 680 *btype = FILTER_OP_OR; 681 else if (strcmp(token, "!") == 0) 682 return OP_NOT; 683 684 if (*btype != FILTER_OP_NOT) 685 return OP_BOOL; 686 687 /* Check for value expressions */ 688 if (strcmp(token, "+") == 0) { 689 *etype = FILTER_EXP_ADD; 690 } else if (strcmp(token, "-") == 0) { 691 *etype = FILTER_EXP_SUB; 692 } else if (strcmp(token, "*") == 0) { 693 *etype = FILTER_EXP_MUL; 694 } else if (strcmp(token, "/") == 0) { 695 *etype = FILTER_EXP_DIV; 696 } else if (strcmp(token, "%") == 0) { 697 *etype = FILTER_EXP_MOD; 698 } else if (strcmp(token, ">>") == 0) { 699 *etype = FILTER_EXP_RSHIFT; 700 } else if (strcmp(token, "<<") == 0) { 701 *etype = FILTER_EXP_LSHIFT; 702 } else if (strcmp(token, "&") == 0) { 703 *etype = FILTER_EXP_AND; 704 } else if (strcmp(token, "|") == 0) { 705 *etype = FILTER_EXP_OR; 706 } else if (strcmp(token, "^") == 0) { 707 *etype = FILTER_EXP_XOR; 708 } else if (strcmp(token, "~") == 0) 709 *etype = FILTER_EXP_NOT; 710 711 if (*etype != FILTER_EXP_NONE) 712 return OP_EXP; 713 714 /* Check for compares */ 715 if (strcmp(token, "==") == 0) 716 *ctype = FILTER_CMP_EQ; 717 else if (strcmp(token, "!=") == 0) 718 *ctype = FILTER_CMP_NE; 719 else if (strcmp(token, "<") == 0) 720 *ctype = FILTER_CMP_LT; 721 else if (strcmp(token, ">") == 0) 722 *ctype = FILTER_CMP_GT; 723 else if (strcmp(token, "<=") == 0) 724 *ctype = FILTER_CMP_LE; 725 else if (strcmp(token, ">=") == 0) 726 *ctype = FILTER_CMP_GE; 727 else if (strcmp(token, "=~") == 0) 728 *ctype = FILTER_CMP_REGEX; 729 else if (strcmp(token, "!~") == 0) 730 *ctype = FILTER_CMP_NOT_REGEX; 731 else 732 return OP_NONE; 733 734 return OP_CMP; 735} 736 737static int check_op_done(struct filter_arg *arg) 738{ 739 switch (arg->type) { 740 case FILTER_ARG_EXP: 741 return arg->exp.right != NULL; 742 743 case FILTER_ARG_OP: 744 return arg->op.right != NULL; 745 746 case FILTER_ARG_NUM: 747 return arg->num.right != NULL; 748 749 case FILTER_ARG_STR: 750 /* A string conversion is always done */ 751 return 1; 752 753 case FILTER_ARG_BOOLEAN: 754 /* field not found, is ok */ 755 return 1; 756 757 default: 758 return 0; 759 } 760} 761 762enum filter_vals { 763 FILTER_VAL_NORM, 764 FILTER_VAL_FALSE, 765 FILTER_VAL_TRUE, 766}; 767 768static enum pevent_errno 769reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, 770 struct filter_arg *arg, char *error_str) 771{ 772 struct filter_arg *other_child; 773 struct filter_arg **ptr; 774 775 if (parent->type != FILTER_ARG_OP && 776 arg->type != FILTER_ARG_OP) { 777 show_error(error_str, "can not reparent other than OP"); 778 return PEVENT_ERRNO__REPARENT_NOT_OP; 779 } 780 781 /* Get the sibling */ 782 if (old_child->op.right == arg) { 783 ptr = &old_child->op.right; 784 other_child = old_child->op.left; 785 } else if (old_child->op.left == arg) { 786 ptr = &old_child->op.left; 787 other_child = old_child->op.right; 788 } else { 789 show_error(error_str, "Error in reparent op, find other child"); 790 return PEVENT_ERRNO__REPARENT_FAILED; 791 } 792 793 /* Detach arg from old_child */ 794 *ptr = NULL; 795 796 /* Check for root */ 797 if (parent == old_child) { 798 free_arg(other_child); 799 *parent = *arg; 800 /* Free arg without recussion */ 801 free(arg); 802 return 0; 803 } 804 805 if (parent->op.right == old_child) 806 ptr = &parent->op.right; 807 else if (parent->op.left == old_child) 808 ptr = &parent->op.left; 809 else { 810 show_error(error_str, "Error in reparent op"); 811 return PEVENT_ERRNO__REPARENT_FAILED; 812 } 813 814 *ptr = arg; 815 816 free_arg(old_child); 817 return 0; 818} 819 820/* Returns either filter_vals (success) or pevent_errno (failfure) */ 821static int test_arg(struct filter_arg *parent, struct filter_arg *arg, 822 char *error_str) 823{ 824 int lval, rval; 825 826 switch (arg->type) { 827 828 /* bad case */ 829 case FILTER_ARG_BOOLEAN: 830 return FILTER_VAL_FALSE + arg->boolean.value; 831 832 /* good cases: */ 833 case FILTER_ARG_STR: 834 case FILTER_ARG_VALUE: 835 case FILTER_ARG_FIELD: 836 return FILTER_VAL_NORM; 837 838 case FILTER_ARG_EXP: 839 lval = test_arg(arg, arg->exp.left, error_str); 840 if (lval != FILTER_VAL_NORM) 841 return lval; 842 rval = test_arg(arg, arg->exp.right, error_str); 843 if (rval != FILTER_VAL_NORM) 844 return rval; 845 return FILTER_VAL_NORM; 846 847 case FILTER_ARG_NUM: 848 lval = test_arg(arg, arg->num.left, error_str); 849 if (lval != FILTER_VAL_NORM) 850 return lval; 851 rval = test_arg(arg, arg->num.right, error_str); 852 if (rval != FILTER_VAL_NORM) 853 return rval; 854 return FILTER_VAL_NORM; 855 856 case FILTER_ARG_OP: 857 if (arg->op.type != FILTER_OP_NOT) { 858 lval = test_arg(arg, arg->op.left, error_str); 859 switch (lval) { 860 case FILTER_VAL_NORM: 861 break; 862 case FILTER_VAL_TRUE: 863 if (arg->op.type == FILTER_OP_OR) 864 return FILTER_VAL_TRUE; 865 rval = test_arg(arg, arg->op.right, error_str); 866 if (rval != FILTER_VAL_NORM) 867 return rval; 868 869 return reparent_op_arg(parent, arg, arg->op.right, 870 error_str); 871 872 case FILTER_VAL_FALSE: 873 if (arg->op.type == FILTER_OP_AND) 874 return FILTER_VAL_FALSE; 875 rval = test_arg(arg, arg->op.right, error_str); 876 if (rval != FILTER_VAL_NORM) 877 return rval; 878 879 return reparent_op_arg(parent, arg, arg->op.right, 880 error_str); 881 882 default: 883 return lval; 884 } 885 } 886 887 rval = test_arg(arg, arg->op.right, error_str); 888 switch (rval) { 889 case FILTER_VAL_NORM: 890 default: 891 break; 892 893 case FILTER_VAL_TRUE: 894 if (arg->op.type == FILTER_OP_OR) 895 return FILTER_VAL_TRUE; 896 if (arg->op.type == FILTER_OP_NOT) 897 return FILTER_VAL_FALSE; 898 899 return reparent_op_arg(parent, arg, arg->op.left, 900 error_str); 901 902 case FILTER_VAL_FALSE: 903 if (arg->op.type == FILTER_OP_AND) 904 return FILTER_VAL_FALSE; 905 if (arg->op.type == FILTER_OP_NOT) 906 return FILTER_VAL_TRUE; 907 908 return reparent_op_arg(parent, arg, arg->op.left, 909 error_str); 910 } 911 912 return rval; 913 default: 914 show_error(error_str, "bad arg in filter tree"); 915 return PEVENT_ERRNO__BAD_FILTER_ARG; 916 } 917 return FILTER_VAL_NORM; 918} 919 920/* Remove any unknown event fields */ 921static int collapse_tree(struct filter_arg *arg, 922 struct filter_arg **arg_collapsed, char *error_str) 923{ 924 int ret; 925 926 ret = test_arg(arg, arg, error_str); 927 switch (ret) { 928 case FILTER_VAL_NORM: 929 break; 930 931 case FILTER_VAL_TRUE: 932 case FILTER_VAL_FALSE: 933 free_arg(arg); 934 arg = allocate_arg(); 935 if (arg) { 936 arg->type = FILTER_ARG_BOOLEAN; 937 arg->boolean.value = ret == FILTER_VAL_TRUE; 938 } else { 939 show_error(error_str, "Failed to allocate filter arg"); 940 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 941 } 942 break; 943 944 default: 945 /* test_arg() already set the error_str */ 946 free_arg(arg); 947 arg = NULL; 948 break; 949 } 950 951 *arg_collapsed = arg; 952 return ret; 953} 954 955static enum pevent_errno 956process_filter(struct event_format *event, struct filter_arg **parg, 957 char *error_str, int not) 958{ 959 enum event_type type; 960 char *token = NULL; 961 struct filter_arg *current_op = NULL; 962 struct filter_arg *current_exp = NULL; 963 struct filter_arg *left_item = NULL; 964 struct filter_arg *arg = NULL; 965 enum op_type op_type; 966 enum filter_op_type btype; 967 enum filter_exp_type etype; 968 enum filter_cmp_type ctype; 969 enum pevent_errno ret; 970 971 *parg = NULL; 972 973 do { 974 free(token); 975 type = read_token(&token); 976 switch (type) { 977 case EVENT_SQUOTE: 978 case EVENT_DQUOTE: 979 case EVENT_ITEM: 980 ret = create_arg_item(event, token, type, &arg, error_str); 981 if (ret < 0) 982 goto fail; 983 if (!left_item) 984 left_item = arg; 985 else if (current_exp) { 986 ret = add_right(current_exp, arg, error_str); 987 if (ret < 0) 988 goto fail; 989 left_item = NULL; 990 /* Not's only one one expression */ 991 if (not) { 992 arg = NULL; 993 if (current_op) 994 goto fail_syntax; 995 free(token); 996 *parg = current_exp; 997 return 0; 998 } 999 } else 1000 goto fail_syntax; 1001 arg = NULL; 1002 break; 1003 1004 case EVENT_DELIM: 1005 if (*token == ',') { 1006 show_error(error_str, "Illegal token ','"); 1007 ret = PEVENT_ERRNO__ILLEGAL_TOKEN; 1008 goto fail; 1009 } 1010 1011 if (*token == '(') { 1012 if (left_item) { 1013 show_error(error_str, 1014 "Open paren can not come after item"); 1015 ret = PEVENT_ERRNO__INVALID_PAREN; 1016 goto fail; 1017 } 1018 if (current_exp) { 1019 show_error(error_str, 1020 "Open paren can not come after expression"); 1021 ret = PEVENT_ERRNO__INVALID_PAREN; 1022 goto fail; 1023 } 1024 1025 ret = process_filter(event, &arg, error_str, 0); 1026 if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) { 1027 if (ret == 0) { 1028 show_error(error_str, 1029 "Unbalanced number of '('"); 1030 ret = PEVENT_ERRNO__UNBALANCED_PAREN; 1031 } 1032 goto fail; 1033 } 1034 ret = 0; 1035 1036 /* A not wants just one expression */ 1037 if (not) { 1038 if (current_op) 1039 goto fail_syntax; 1040 *parg = arg; 1041 return 0; 1042 } 1043 1044 if (current_op) 1045 ret = add_right(current_op, arg, error_str); 1046 else 1047 current_exp = arg; 1048 1049 if (ret < 0) 1050 goto fail; 1051 1052 } else { /* ')' */ 1053 if (!current_op && !current_exp) 1054 goto fail_syntax; 1055 1056 /* Make sure everything is finished at this level */ 1057 if (current_exp && !check_op_done(current_exp)) 1058 goto fail_syntax; 1059 if (current_op && !check_op_done(current_op)) 1060 goto fail_syntax; 1061 1062 if (current_op) 1063 *parg = current_op; 1064 else 1065 *parg = current_exp; 1066 free(token); 1067 return PEVENT_ERRNO__UNBALANCED_PAREN; 1068 } 1069 break; 1070 1071 case EVENT_OP: 1072 op_type = process_op(token, &btype, &ctype, &etype); 1073 1074 /* All expect a left arg except for NOT */ 1075 switch (op_type) { 1076 case OP_BOOL: 1077 /* Logic ops need a left expression */ 1078 if (!current_exp && !current_op) 1079 goto fail_syntax; 1080 /* fall through */ 1081 case OP_NOT: 1082 /* logic only processes ops and exp */ 1083 if (left_item) 1084 goto fail_syntax; 1085 break; 1086 case OP_EXP: 1087 case OP_CMP: 1088 if (!left_item) 1089 goto fail_syntax; 1090 break; 1091 case OP_NONE: 1092 show_error(error_str, 1093 "Unknown op token %s", token); 1094 ret = PEVENT_ERRNO__UNKNOWN_TOKEN; 1095 goto fail; 1096 } 1097 1098 ret = 0; 1099 switch (op_type) { 1100 case OP_BOOL: 1101 arg = create_arg_op(btype); 1102 if (arg == NULL) 1103 goto fail_alloc; 1104 if (current_op) 1105 ret = add_left(arg, current_op); 1106 else 1107 ret = add_left(arg, current_exp); 1108 current_op = arg; 1109 current_exp = NULL; 1110 break; 1111 1112 case OP_NOT: 1113 arg = create_arg_op(btype); 1114 if (arg == NULL) 1115 goto fail_alloc; 1116 if (current_op) 1117 ret = add_right(current_op, arg, error_str); 1118 if (ret < 0) 1119 goto fail; 1120 current_exp = arg; 1121 ret = process_filter(event, &arg, error_str, 1); 1122 if (ret < 0) 1123 goto fail; 1124 ret = add_right(current_exp, arg, error_str); 1125 if (ret < 0) 1126 goto fail; 1127 break; 1128 1129 case OP_EXP: 1130 case OP_CMP: 1131 if (op_type == OP_EXP) 1132 arg = create_arg_exp(etype); 1133 else 1134 arg = create_arg_cmp(ctype); 1135 if (arg == NULL) 1136 goto fail_alloc; 1137 1138 if (current_op) 1139 ret = add_right(current_op, arg, error_str); 1140 if (ret < 0) 1141 goto fail; 1142 ret = add_left(arg, left_item); 1143 if (ret < 0) { 1144 arg = NULL; 1145 goto fail_syntax; 1146 } 1147 current_exp = arg; 1148 break; 1149 default: 1150 break; 1151 } 1152 arg = NULL; 1153 if (ret < 0) 1154 goto fail_syntax; 1155 break; 1156 case EVENT_NONE: 1157 break; 1158 case EVENT_ERROR: 1159 goto fail_alloc; 1160 default: 1161 goto fail_syntax; 1162 } 1163 } while (type != EVENT_NONE); 1164 1165 if (!current_op && !current_exp) 1166 goto fail_syntax; 1167 1168 if (!current_op) 1169 current_op = current_exp; 1170 1171 ret = collapse_tree(current_op, parg, error_str); 1172 /* collapse_tree() may free current_op, and updates parg accordingly */ 1173 current_op = NULL; 1174 if (ret < 0) 1175 goto fail; 1176 1177 free(token); 1178 return 0; 1179 1180 fail_alloc: 1181 show_error(error_str, "failed to allocate filter arg"); 1182 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 1183 goto fail; 1184 fail_syntax: 1185 show_error(error_str, "Syntax error"); 1186 ret = PEVENT_ERRNO__SYNTAX_ERROR; 1187 fail: 1188 free_arg(current_op); 1189 free_arg(current_exp); 1190 free_arg(arg); 1191 free(token); 1192 return ret; 1193} 1194 1195static enum pevent_errno 1196process_event(struct event_format *event, const char *filter_str, 1197 struct filter_arg **parg, char *error_str) 1198{ 1199 int ret; 1200 1201 pevent_buffer_init(filter_str, strlen(filter_str)); 1202 1203 ret = process_filter(event, parg, error_str, 0); 1204 if (ret < 0) 1205 return ret; 1206 1207 /* If parg is NULL, then make it into FALSE */ 1208 if (!*parg) { 1209 *parg = allocate_arg(); 1210 if (*parg == NULL) 1211 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1212 1213 (*parg)->type = FILTER_ARG_BOOLEAN; 1214 (*parg)->boolean.value = FILTER_FALSE; 1215 } 1216 1217 return 0; 1218} 1219 1220static enum pevent_errno 1221filter_event(struct event_filter *filter, struct event_format *event, 1222 const char *filter_str, char *error_str) 1223{ 1224 struct filter_type *filter_type; 1225 struct filter_arg *arg; 1226 enum pevent_errno ret; 1227 1228 if (filter_str) { 1229 ret = process_event(event, filter_str, &arg, error_str); 1230 if (ret < 0) 1231 return ret; 1232 1233 } else { 1234 /* just add a TRUE arg */ 1235 arg = allocate_arg(); 1236 if (arg == NULL) 1237 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1238 1239 arg->type = FILTER_ARG_BOOLEAN; 1240 arg->boolean.value = FILTER_TRUE; 1241 } 1242 1243 filter_type = add_filter_type(filter, event->id); 1244 if (filter_type == NULL) 1245 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1246 1247 if (filter_type->filter) 1248 free_arg(filter_type->filter); 1249 filter_type->filter = arg; 1250 1251 return 0; 1252} 1253 1254static void filter_init_error_buf(struct event_filter *filter) 1255{ 1256 /* clear buffer to reset show error */ 1257 pevent_buffer_init("", 0); 1258 filter->error_buffer[0] = '\0'; 1259} 1260 1261/** 1262 * pevent_filter_add_filter_str - add a new filter 1263 * @filter: the event filter to add to 1264 * @filter_str: the filter string that contains the filter 1265 * 1266 * Returns 0 if the filter was successfully added or a 1267 * negative error code. Use pevent_filter_strerror() to see 1268 * actual error message in case of error. 1269 */ 1270enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, 1271 const char *filter_str) 1272{ 1273 struct pevent *pevent = filter->pevent; 1274 struct event_list *event; 1275 struct event_list *events = NULL; 1276 const char *filter_start; 1277 const char *next_event; 1278 char *this_event; 1279 char *event_name = NULL; 1280 char *sys_name = NULL; 1281 char *sp; 1282 enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ 1283 int len; 1284 int ret; 1285 1286 filter_init_error_buf(filter); 1287 1288 filter_start = strchr(filter_str, ':'); 1289 if (filter_start) 1290 len = filter_start - filter_str; 1291 else 1292 len = strlen(filter_str); 1293 1294 do { 1295 next_event = strchr(filter_str, ','); 1296 if (next_event && 1297 (!filter_start || next_event < filter_start)) 1298 len = next_event - filter_str; 1299 else if (filter_start) 1300 len = filter_start - filter_str; 1301 else 1302 len = strlen(filter_str); 1303 1304 this_event = malloc(len + 1); 1305 if (this_event == NULL) { 1306 /* This can only happen when events is NULL, but still */ 1307 free_events(events); 1308 return PEVENT_ERRNO__MEM_ALLOC_FAILED; 1309 } 1310 memcpy(this_event, filter_str, len); 1311 this_event[len] = 0; 1312 1313 if (next_event) 1314 next_event++; 1315 1316 filter_str = next_event; 1317 1318 sys_name = strtok_r(this_event, "/", &sp); 1319 event_name = strtok_r(NULL, "/", &sp); 1320 1321 if (!sys_name) { 1322 /* This can only happen when events is NULL, but still */ 1323 free_events(events); 1324 free(this_event); 1325 return PEVENT_ERRNO__FILTER_NOT_FOUND; 1326 } 1327 1328 /* Find this event */ 1329 ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); 1330 if (ret < 0) { 1331 free_events(events); 1332 free(this_event); 1333 return ret; 1334 } 1335 free(this_event); 1336 } while (filter_str); 1337 1338 /* Skip the ':' */ 1339 if (filter_start) 1340 filter_start++; 1341 1342 /* filter starts here */ 1343 for (event = events; event; event = event->next) { 1344 ret = filter_event(filter, event->event, filter_start, 1345 filter->error_buffer); 1346 /* Failures are returned if a parse error happened */ 1347 if (ret < 0) 1348 rtn = ret; 1349 1350 if (ret >= 0 && pevent->test_filters) { 1351 char *test; 1352 test = pevent_filter_make_string(filter, event->event->id); 1353 if (test) { 1354 printf(" '%s: %s'\n", event->event->name, test); 1355 free(test); 1356 } 1357 } 1358 } 1359 1360 free_events(events); 1361 1362 if (rtn >= 0 && pevent->test_filters) 1363 exit(0); 1364 1365 return rtn; 1366} 1367 1368static void free_filter_type(struct filter_type *filter_type) 1369{ 1370 free_arg(filter_type->filter); 1371} 1372 1373/** 1374 * pevent_filter_strerror - fill error message in a buffer 1375 * @filter: the event filter contains error 1376 * @err: the error code 1377 * @buf: the buffer to be filled in 1378 * @buflen: the size of the buffer 1379 * 1380 * Returns 0 if message was filled successfully, -1 if error 1381 */ 1382int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, 1383 char *buf, size_t buflen) 1384{ 1385 if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END) 1386 return -1; 1387 1388 if (strlen(filter->error_buffer) > 0) { 1389 size_t len = snprintf(buf, buflen, "%s", filter->error_buffer); 1390 1391 if (len > buflen) 1392 return -1; 1393 return 0; 1394 } 1395 1396 return pevent_strerror(filter->pevent, err, buf, buflen); 1397} 1398 1399/** 1400 * pevent_filter_remove_event - remove a filter for an event 1401 * @filter: the event filter to remove from 1402 * @event_id: the event to remove a filter for 1403 * 1404 * Removes the filter saved for an event defined by @event_id 1405 * from the @filter. 1406 * 1407 * Returns 1: if an event was removed 1408 * 0: if the event was not found 1409 */ 1410int pevent_filter_remove_event(struct event_filter *filter, 1411 int event_id) 1412{ 1413 struct filter_type *filter_type; 1414 unsigned long len; 1415 1416 if (!filter->filters) 1417 return 0; 1418 1419 filter_type = find_filter_type(filter, event_id); 1420 1421 if (!filter_type) 1422 return 0; 1423 1424 free_filter_type(filter_type); 1425 1426 /* The filter_type points into the event_filters array */ 1427 len = (unsigned long)(filter->event_filters + filter->filters) - 1428 (unsigned long)(filter_type + 1); 1429 1430 memmove(filter_type, filter_type + 1, len); 1431 filter->filters--; 1432 1433 memset(&filter->event_filters[filter->filters], 0, 1434 sizeof(*filter_type)); 1435 1436 return 1; 1437} 1438 1439/** 1440 * pevent_filter_reset - clear all filters in a filter 1441 * @filter: the event filter to reset 1442 * 1443 * Removes all filters from a filter and resets it. 1444 */ 1445void pevent_filter_reset(struct event_filter *filter) 1446{ 1447 int i; 1448 1449 for (i = 0; i < filter->filters; i++) 1450 free_filter_type(&filter->event_filters[i]); 1451 1452 free(filter->event_filters); 1453 filter->filters = 0; 1454 filter->event_filters = NULL; 1455} 1456 1457void pevent_filter_free(struct event_filter *filter) 1458{ 1459 pevent_unref(filter->pevent); 1460 1461 pevent_filter_reset(filter); 1462 1463 free(filter); 1464} 1465 1466static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg); 1467 1468static int copy_filter_type(struct event_filter *filter, 1469 struct event_filter *source, 1470 struct filter_type *filter_type) 1471{ 1472 struct filter_arg *arg; 1473 struct event_format *event; 1474 const char *sys; 1475 const char *name; 1476 char *str; 1477 1478 /* Can't assume that the pevent's are the same */ 1479 sys = filter_type->event->system; 1480 name = filter_type->event->name; 1481 event = pevent_find_event_by_name(filter->pevent, sys, name); 1482 if (!event) 1483 return -1; 1484 1485 str = arg_to_str(source, filter_type->filter); 1486 if (!str) 1487 return -1; 1488 1489 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { 1490 /* Add trivial event */ 1491 arg = allocate_arg(); 1492 if (arg == NULL) 1493 return -1; 1494 1495 arg->type = FILTER_ARG_BOOLEAN; 1496 if (strcmp(str, "TRUE") == 0) 1497 arg->boolean.value = 1; 1498 else 1499 arg->boolean.value = 0; 1500 1501 filter_type = add_filter_type(filter, event->id); 1502 if (filter_type == NULL) 1503 return -1; 1504 1505 filter_type->filter = arg; 1506 1507 free(str); 1508 return 0; 1509 } 1510 1511 filter_event(filter, event, str, NULL); 1512 free(str); 1513 1514 return 0; 1515} 1516 1517/** 1518 * pevent_filter_copy - copy a filter using another filter 1519 * @dest - the filter to copy to 1520 * @source - the filter to copy from 1521 * 1522 * Returns 0 on success and -1 if not all filters were copied 1523 */ 1524int pevent_filter_copy(struct event_filter *dest, struct event_filter *source) 1525{ 1526 int ret = 0; 1527 int i; 1528 1529 pevent_filter_reset(dest); 1530 1531 for (i = 0; i < source->filters; i++) { 1532 if (copy_filter_type(dest, source, &source->event_filters[i])) 1533 ret = -1; 1534 } 1535 return ret; 1536} 1537 1538 1539/** 1540 * pevent_update_trivial - update the trivial filters with the given filter 1541 * @dest - the filter to update 1542 * @source - the filter as the source of the update 1543 * @type - the type of trivial filter to update. 1544 * 1545 * Scan dest for trivial events matching @type to replace with the source. 1546 * 1547 * Returns 0 on success and -1 if there was a problem updating, but 1548 * events may have still been updated on error. 1549 */ 1550int pevent_update_trivial(struct event_filter *dest, struct event_filter *source, 1551 enum filter_trivial_type type) 1552{ 1553 struct pevent *src_pevent; 1554 struct pevent *dest_pevent; 1555 struct event_format *event; 1556 struct filter_type *filter_type; 1557 struct filter_arg *arg; 1558 char *str; 1559 int i; 1560 1561 src_pevent = source->pevent; 1562 dest_pevent = dest->pevent; 1563 1564 /* Do nothing if either of the filters has nothing to filter */ 1565 if (!dest->filters || !source->filters) 1566 return 0; 1567 1568 for (i = 0; i < dest->filters; i++) { 1569 filter_type = &dest->event_filters[i]; 1570 arg = filter_type->filter; 1571 if (arg->type != FILTER_ARG_BOOLEAN) 1572 continue; 1573 if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) || 1574 (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE)) 1575 continue; 1576 1577 event = filter_type->event; 1578 1579 if (src_pevent != dest_pevent) { 1580 /* do a look up */ 1581 event = pevent_find_event_by_name(src_pevent, 1582 event->system, 1583 event->name); 1584 if (!event) 1585 return -1; 1586 } 1587 1588 str = pevent_filter_make_string(source, event->id); 1589 if (!str) 1590 continue; 1591 1592 /* Don't bother if the filter is trivial too */ 1593 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0) 1594 filter_event(dest, event, str, NULL); 1595 free(str); 1596 } 1597 return 0; 1598} 1599 1600/** 1601 * pevent_filter_clear_trivial - clear TRUE and FALSE filters 1602 * @filter: the filter to remove trivial filters from 1603 * @type: remove only true, false, or both 1604 * 1605 * Removes filters that only contain a TRUE or FALES boolean arg. 1606 * 1607 * Returns 0 on success and -1 if there was a problem. 1608 */ 1609int pevent_filter_clear_trivial(struct event_filter *filter, 1610 enum filter_trivial_type type) 1611{ 1612 struct filter_type *filter_type; 1613 int count = 0; 1614 int *ids = NULL; 1615 int i; 1616 1617 if (!filter->filters) 1618 return 0; 1619 1620 /* 1621 * Two steps, first get all ids with trivial filters. 1622 * then remove those ids. 1623 */ 1624 for (i = 0; i < filter->filters; i++) { 1625 int *new_ids; 1626 1627 filter_type = &filter->event_filters[i]; 1628 if (filter_type->filter->type != FILTER_ARG_BOOLEAN) 1629 continue; 1630 switch (type) { 1631 case FILTER_TRIVIAL_FALSE: 1632 if (filter_type->filter->boolean.value) 1633 continue; 1634 break; 1635 case FILTER_TRIVIAL_TRUE: 1636 if (!filter_type->filter->boolean.value) 1637 continue; 1638 default: 1639 break; 1640 } 1641 1642 new_ids = realloc(ids, sizeof(*ids) * (count + 1)); 1643 if (!new_ids) { 1644 free(ids); 1645 return -1; 1646 } 1647 1648 ids = new_ids; 1649 ids[count++] = filter_type->event_id; 1650 } 1651 1652 if (!count) 1653 return 0; 1654 1655 for (i = 0; i < count; i++) 1656 pevent_filter_remove_event(filter, ids[i]); 1657 1658 free(ids); 1659 return 0; 1660} 1661 1662/** 1663 * pevent_filter_event_has_trivial - return true event contains trivial filter 1664 * @filter: the filter with the information 1665 * @event_id: the id of the event to test 1666 * @type: trivial type to test for (TRUE, FALSE, EITHER) 1667 * 1668 * Returns 1 if the event contains a matching trivial type 1669 * otherwise 0. 1670 */ 1671int pevent_filter_event_has_trivial(struct event_filter *filter, 1672 int event_id, 1673 enum filter_trivial_type type) 1674{ 1675 struct filter_type *filter_type; 1676 1677 if (!filter->filters) 1678 return 0; 1679 1680 filter_type = find_filter_type(filter, event_id); 1681 1682 if (!filter_type) 1683 return 0; 1684 1685 if (filter_type->filter->type != FILTER_ARG_BOOLEAN) 1686 return 0; 1687 1688 switch (type) { 1689 case FILTER_TRIVIAL_FALSE: 1690 return !filter_type->filter->boolean.value; 1691 1692 case FILTER_TRIVIAL_TRUE: 1693 return filter_type->filter->boolean.value; 1694 default: 1695 return 1; 1696 } 1697} 1698 1699static int test_filter(struct event_format *event, struct filter_arg *arg, 1700 struct pevent_record *record, enum pevent_errno *err); 1701 1702static const char * 1703get_comm(struct event_format *event, struct pevent_record *record) 1704{ 1705 const char *comm; 1706 int pid; 1707 1708 pid = pevent_data_pid(event->pevent, record); 1709 comm = pevent_data_comm_from_pid(event->pevent, pid); 1710 return comm; 1711} 1712 1713static unsigned long long 1714get_value(struct event_format *event, 1715 struct format_field *field, struct pevent_record *record) 1716{ 1717 unsigned long long val; 1718 1719 /* Handle our dummy "comm" field */ 1720 if (field == &comm) { 1721 const char *name; 1722 1723 name = get_comm(event, record); 1724 return (unsigned long)name; 1725 } 1726 1727 /* Handle our dummy "cpu" field */ 1728 if (field == &cpu) 1729 return record->cpu; 1730 1731 pevent_read_number_field(field, record->data, &val); 1732 1733 if (!(field->flags & FIELD_IS_SIGNED)) 1734 return val; 1735 1736 switch (field->size) { 1737 case 1: 1738 return (char)val; 1739 case 2: 1740 return (short)val; 1741 case 4: 1742 return (int)val; 1743 case 8: 1744 return (long long)val; 1745 } 1746 return val; 1747} 1748 1749static unsigned long long 1750get_arg_value(struct event_format *event, struct filter_arg *arg, 1751 struct pevent_record *record, enum pevent_errno *err); 1752 1753static unsigned long long 1754get_exp_value(struct event_format *event, struct filter_arg *arg, 1755 struct pevent_record *record, enum pevent_errno *err) 1756{ 1757 unsigned long long lval, rval; 1758 1759 lval = get_arg_value(event, arg->exp.left, record, err); 1760 rval = get_arg_value(event, arg->exp.right, record, err); 1761 1762 if (*err) { 1763 /* 1764 * There was an error, no need to process anymore. 1765 */ 1766 return 0; 1767 } 1768 1769 switch (arg->exp.type) { 1770 case FILTER_EXP_ADD: 1771 return lval + rval; 1772 1773 case FILTER_EXP_SUB: 1774 return lval - rval; 1775 1776 case FILTER_EXP_MUL: 1777 return lval * rval; 1778 1779 case FILTER_EXP_DIV: 1780 return lval / rval; 1781 1782 case FILTER_EXP_MOD: 1783 return lval % rval; 1784 1785 case FILTER_EXP_RSHIFT: 1786 return lval >> rval; 1787 1788 case FILTER_EXP_LSHIFT: 1789 return lval << rval; 1790 1791 case FILTER_EXP_AND: 1792 return lval & rval; 1793 1794 case FILTER_EXP_OR: 1795 return lval | rval; 1796 1797 case FILTER_EXP_XOR: 1798 return lval ^ rval; 1799 1800 case FILTER_EXP_NOT: 1801 default: 1802 if (!*err) 1803 *err = PEVENT_ERRNO__INVALID_EXP_TYPE; 1804 } 1805 return 0; 1806} 1807 1808static unsigned long long 1809get_arg_value(struct event_format *event, struct filter_arg *arg, 1810 struct pevent_record *record, enum pevent_errno *err) 1811{ 1812 switch (arg->type) { 1813 case FILTER_ARG_FIELD: 1814 return get_value(event, arg->field.field, record); 1815 1816 case FILTER_ARG_VALUE: 1817 if (arg->value.type != FILTER_NUMBER) { 1818 if (!*err) 1819 *err = PEVENT_ERRNO__NOT_A_NUMBER; 1820 } 1821 return arg->value.val; 1822 1823 case FILTER_ARG_EXP: 1824 return get_exp_value(event, arg, record, err); 1825 1826 default: 1827 if (!*err) 1828 *err = PEVENT_ERRNO__INVALID_ARG_TYPE; 1829 } 1830 return 0; 1831} 1832 1833static int test_num(struct event_format *event, struct filter_arg *arg, 1834 struct pevent_record *record, enum pevent_errno *err) 1835{ 1836 unsigned long long lval, rval; 1837 1838 lval = get_arg_value(event, arg->num.left, record, err); 1839 rval = get_arg_value(event, arg->num.right, record, err); 1840 1841 if (*err) { 1842 /* 1843 * There was an error, no need to process anymore. 1844 */ 1845 return 0; 1846 } 1847 1848 switch (arg->num.type) { 1849 case FILTER_CMP_EQ: 1850 return lval == rval; 1851 1852 case FILTER_CMP_NE: 1853 return lval != rval; 1854 1855 case FILTER_CMP_GT: 1856 return lval > rval; 1857 1858 case FILTER_CMP_LT: 1859 return lval < rval; 1860 1861 case FILTER_CMP_GE: 1862 return lval >= rval; 1863 1864 case FILTER_CMP_LE: 1865 return lval <= rval; 1866 1867 default: 1868 if (!*err) 1869 *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; 1870 return 0; 1871 } 1872} 1873 1874static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) 1875{ 1876 struct event_format *event; 1877 struct pevent *pevent; 1878 unsigned long long addr; 1879 const char *val = NULL; 1880 unsigned int size; 1881 char hex[64]; 1882 1883 /* If the field is not a string convert it */ 1884 if (arg->str.field->flags & FIELD_IS_STRING) { 1885 val = record->data + arg->str.field->offset; 1886 size = arg->str.field->size; 1887 1888 if (arg->str.field->flags & FIELD_IS_DYNAMIC) { 1889 addr = *(unsigned int *)val; 1890 val = record->data + (addr & 0xffff); 1891 size = addr >> 16; 1892 } 1893 1894 /* 1895 * We need to copy the data since we can't be sure the field 1896 * is null terminated. 1897 */ 1898 if (*(val + size - 1)) { 1899 /* copy it */ 1900 memcpy(arg->str.buffer, val, arg->str.field->size); 1901 /* the buffer is already NULL terminated */ 1902 val = arg->str.buffer; 1903 } 1904 1905 } else { 1906 event = arg->str.field->event; 1907 pevent = event->pevent; 1908 addr = get_value(event, arg->str.field, record); 1909 1910 if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG)) 1911 /* convert to a kernel symbol */ 1912 val = pevent_find_function(pevent, addr); 1913 1914 if (val == NULL) { 1915 /* just use the hex of the string name */ 1916 snprintf(hex, 64, "0x%llx", addr); 1917 val = hex; 1918 } 1919 } 1920 1921 return val; 1922} 1923 1924static int test_str(struct event_format *event, struct filter_arg *arg, 1925 struct pevent_record *record, enum pevent_errno *err) 1926{ 1927 const char *val; 1928 1929 if (arg->str.field == &comm) 1930 val = get_comm(event, record); 1931 else 1932 val = get_field_str(arg, record); 1933 1934 switch (arg->str.type) { 1935 case FILTER_CMP_MATCH: 1936 return strcmp(val, arg->str.val) == 0; 1937 1938 case FILTER_CMP_NOT_MATCH: 1939 return strcmp(val, arg->str.val) != 0; 1940 1941 case FILTER_CMP_REGEX: 1942 /* Returns zero on match */ 1943 return !regexec(&arg->str.reg, val, 0, NULL, 0); 1944 1945 case FILTER_CMP_NOT_REGEX: 1946 return regexec(&arg->str.reg, val, 0, NULL, 0); 1947 1948 default: 1949 if (!*err) 1950 *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP; 1951 return 0; 1952 } 1953} 1954 1955static int test_op(struct event_format *event, struct filter_arg *arg, 1956 struct pevent_record *record, enum pevent_errno *err) 1957{ 1958 switch (arg->op.type) { 1959 case FILTER_OP_AND: 1960 return test_filter(event, arg->op.left, record, err) && 1961 test_filter(event, arg->op.right, record, err); 1962 1963 case FILTER_OP_OR: 1964 return test_filter(event, arg->op.left, record, err) || 1965 test_filter(event, arg->op.right, record, err); 1966 1967 case FILTER_OP_NOT: 1968 return !test_filter(event, arg->op.right, record, err); 1969 1970 default: 1971 if (!*err) 1972 *err = PEVENT_ERRNO__INVALID_OP_TYPE; 1973 return 0; 1974 } 1975} 1976 1977static int test_filter(struct event_format *event, struct filter_arg *arg, 1978 struct pevent_record *record, enum pevent_errno *err) 1979{ 1980 if (*err) { 1981 /* 1982 * There was an error, no need to process anymore. 1983 */ 1984 return 0; 1985 } 1986 1987 switch (arg->type) { 1988 case FILTER_ARG_BOOLEAN: 1989 /* easy case */ 1990 return arg->boolean.value; 1991 1992 case FILTER_ARG_OP: 1993 return test_op(event, arg, record, err); 1994 1995 case FILTER_ARG_NUM: 1996 return test_num(event, arg, record, err); 1997 1998 case FILTER_ARG_STR: 1999 return test_str(event, arg, record, err); 2000 2001 case FILTER_ARG_EXP: 2002 case FILTER_ARG_VALUE: 2003 case FILTER_ARG_FIELD: 2004 /* 2005 * Expressions, fields and values evaluate 2006 * to true if they return non zero 2007 */ 2008 return !!get_arg_value(event, arg, record, err); 2009 2010 default: 2011 if (!*err) 2012 *err = PEVENT_ERRNO__INVALID_ARG_TYPE; 2013 return 0; 2014 } 2015} 2016 2017/** 2018 * pevent_event_filtered - return true if event has filter 2019 * @filter: filter struct with filter information 2020 * @event_id: event id to test if filter exists 2021 * 2022 * Returns 1 if filter found for @event_id 2023 * otherwise 0; 2024 */ 2025int pevent_event_filtered(struct event_filter *filter, int event_id) 2026{ 2027 struct filter_type *filter_type; 2028 2029 if (!filter->filters) 2030 return 0; 2031 2032 filter_type = find_filter_type(filter, event_id); 2033 2034 return filter_type ? 1 : 0; 2035} 2036 2037/** 2038 * pevent_filter_match - test if a record matches a filter 2039 * @filter: filter struct with filter information 2040 * @record: the record to test against the filter 2041 * 2042 * Returns: match result or error code (prefixed with PEVENT_ERRNO__) 2043 * FILTER_MATCH - filter found for event and @record matches 2044 * FILTER_MISS - filter found for event and @record does not match 2045 * FILTER_NOT_FOUND - no filter found for @record's event 2046 * NO_FILTER - if no filters exist 2047 * otherwise - error occurred during test 2048 */ 2049enum pevent_errno pevent_filter_match(struct event_filter *filter, 2050 struct pevent_record *record) 2051{ 2052 struct pevent *pevent = filter->pevent; 2053 struct filter_type *filter_type; 2054 int event_id; 2055 int ret; 2056 enum pevent_errno err = 0; 2057 2058 filter_init_error_buf(filter); 2059 2060 if (!filter->filters) 2061 return PEVENT_ERRNO__NO_FILTER; 2062 2063 event_id = pevent_data_type(pevent, record); 2064 2065 filter_type = find_filter_type(filter, event_id); 2066 if (!filter_type) 2067 return PEVENT_ERRNO__FILTER_NOT_FOUND; 2068 2069 ret = test_filter(filter_type->event, filter_type->filter, record, &err); 2070 if (err) 2071 return err; 2072 2073 return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS; 2074} 2075 2076static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) 2077{ 2078 char *str = NULL; 2079 char *left = NULL; 2080 char *right = NULL; 2081 char *op = NULL; 2082 int left_val = -1; 2083 int right_val = -1; 2084 int val; 2085 2086 switch (arg->op.type) { 2087 case FILTER_OP_AND: 2088 op = "&&"; 2089 /* fall through */ 2090 case FILTER_OP_OR: 2091 if (!op) 2092 op = "||"; 2093 2094 left = arg_to_str(filter, arg->op.left); 2095 right = arg_to_str(filter, arg->op.right); 2096 if (!left || !right) 2097 break; 2098 2099 /* Try to consolidate boolean values */ 2100 if (strcmp(left, "TRUE") == 0) 2101 left_val = 1; 2102 else if (strcmp(left, "FALSE") == 0) 2103 left_val = 0; 2104 2105 if (strcmp(right, "TRUE") == 0) 2106 right_val = 1; 2107 else if (strcmp(right, "FALSE") == 0) 2108 right_val = 0; 2109 2110 if (left_val >= 0) { 2111 if ((arg->op.type == FILTER_OP_AND && !left_val) || 2112 (arg->op.type == FILTER_OP_OR && left_val)) { 2113 /* Just return left value */ 2114 str = left; 2115 left = NULL; 2116 break; 2117 } 2118 if (right_val >= 0) { 2119 /* just evaluate this. */ 2120 val = 0; 2121 switch (arg->op.type) { 2122 case FILTER_OP_AND: 2123 val = left_val && right_val; 2124 break; 2125 case FILTER_OP_OR: 2126 val = left_val || right_val; 2127 break; 2128 default: 2129 break; 2130 } 2131 asprintf(&str, val ? "TRUE" : "FALSE"); 2132 break; 2133 } 2134 } 2135 if (right_val >= 0) { 2136 if ((arg->op.type == FILTER_OP_AND && !right_val) || 2137 (arg->op.type == FILTER_OP_OR && right_val)) { 2138 /* Just return right value */ 2139 str = right; 2140 right = NULL; 2141 break; 2142 } 2143 /* The right value is meaningless */ 2144 str = left; 2145 left = NULL; 2146 break; 2147 } 2148 2149 asprintf(&str, "(%s) %s (%s)", left, op, right); 2150 break; 2151 2152 case FILTER_OP_NOT: 2153 op = "!"; 2154 right = arg_to_str(filter, arg->op.right); 2155 if (!right) 2156 break; 2157 2158 /* See if we can consolidate */ 2159 if (strcmp(right, "TRUE") == 0) 2160 right_val = 1; 2161 else if (strcmp(right, "FALSE") == 0) 2162 right_val = 0; 2163 if (right_val >= 0) { 2164 /* just return the opposite */ 2165 asprintf(&str, right_val ? "FALSE" : "TRUE"); 2166 break; 2167 } 2168 asprintf(&str, "%s(%s)", op, right); 2169 break; 2170 2171 default: 2172 /* ?? */ 2173 break; 2174 } 2175 free(left); 2176 free(right); 2177 return str; 2178} 2179 2180static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) 2181{ 2182 char *str = NULL; 2183 2184 asprintf(&str, "%lld", arg->value.val); 2185 2186 return str; 2187} 2188 2189static char *field_to_str(struct event_filter *filter, struct filter_arg *arg) 2190{ 2191 return strdup(arg->field.field->name); 2192} 2193 2194static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) 2195{ 2196 char *lstr; 2197 char *rstr; 2198 char *op; 2199 char *str = NULL; 2200 2201 lstr = arg_to_str(filter, arg->exp.left); 2202 rstr = arg_to_str(filter, arg->exp.right); 2203 if (!lstr || !rstr) 2204 goto out; 2205 2206 switch (arg->exp.type) { 2207 case FILTER_EXP_ADD: 2208 op = "+"; 2209 break; 2210 case FILTER_EXP_SUB: 2211 op = "-"; 2212 break; 2213 case FILTER_EXP_MUL: 2214 op = "*"; 2215 break; 2216 case FILTER_EXP_DIV: 2217 op = "/"; 2218 break; 2219 case FILTER_EXP_MOD: 2220 op = "%"; 2221 break; 2222 case FILTER_EXP_RSHIFT: 2223 op = ">>"; 2224 break; 2225 case FILTER_EXP_LSHIFT: 2226 op = "<<"; 2227 break; 2228 case FILTER_EXP_AND: 2229 op = "&"; 2230 break; 2231 case FILTER_EXP_OR: 2232 op = "|"; 2233 break; 2234 case FILTER_EXP_XOR: 2235 op = "^"; 2236 break; 2237 default: 2238 op = "[ERROR IN EXPRESSION TYPE]"; 2239 break; 2240 } 2241 2242 asprintf(&str, "%s %s %s", lstr, op, rstr); 2243out: 2244 free(lstr); 2245 free(rstr); 2246 2247 return str; 2248} 2249 2250static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) 2251{ 2252 char *lstr; 2253 char *rstr; 2254 char *str = NULL; 2255 char *op = NULL; 2256 2257 lstr = arg_to_str(filter, arg->num.left); 2258 rstr = arg_to_str(filter, arg->num.right); 2259 if (!lstr || !rstr) 2260 goto out; 2261 2262 switch (arg->num.type) { 2263 case FILTER_CMP_EQ: 2264 op = "=="; 2265 /* fall through */ 2266 case FILTER_CMP_NE: 2267 if (!op) 2268 op = "!="; 2269 /* fall through */ 2270 case FILTER_CMP_GT: 2271 if (!op) 2272 op = ">"; 2273 /* fall through */ 2274 case FILTER_CMP_LT: 2275 if (!op) 2276 op = "<"; 2277 /* fall through */ 2278 case FILTER_CMP_GE: 2279 if (!op) 2280 op = ">="; 2281 /* fall through */ 2282 case FILTER_CMP_LE: 2283 if (!op) 2284 op = "<="; 2285 2286 asprintf(&str, "%s %s %s", lstr, op, rstr); 2287 break; 2288 2289 default: 2290 /* ?? */ 2291 break; 2292 } 2293 2294out: 2295 free(lstr); 2296 free(rstr); 2297 return str; 2298} 2299 2300static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) 2301{ 2302 char *str = NULL; 2303 char *op = NULL; 2304 2305 switch (arg->str.type) { 2306 case FILTER_CMP_MATCH: 2307 op = "=="; 2308 /* fall through */ 2309 case FILTER_CMP_NOT_MATCH: 2310 if (!op) 2311 op = "!="; 2312 /* fall through */ 2313 case FILTER_CMP_REGEX: 2314 if (!op) 2315 op = "=~"; 2316 /* fall through */ 2317 case FILTER_CMP_NOT_REGEX: 2318 if (!op) 2319 op = "!~"; 2320 2321 asprintf(&str, "%s %s \"%s\"", 2322 arg->str.field->name, op, arg->str.val); 2323 break; 2324 2325 default: 2326 /* ?? */ 2327 break; 2328 } 2329 return str; 2330} 2331 2332static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) 2333{ 2334 char *str = NULL; 2335 2336 switch (arg->type) { 2337 case FILTER_ARG_BOOLEAN: 2338 asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE"); 2339 return str; 2340 2341 case FILTER_ARG_OP: 2342 return op_to_str(filter, arg); 2343 2344 case FILTER_ARG_NUM: 2345 return num_to_str(filter, arg); 2346 2347 case FILTER_ARG_STR: 2348 return str_to_str(filter, arg); 2349 2350 case FILTER_ARG_VALUE: 2351 return val_to_str(filter, arg); 2352 2353 case FILTER_ARG_FIELD: 2354 return field_to_str(filter, arg); 2355 2356 case FILTER_ARG_EXP: 2357 return exp_to_str(filter, arg); 2358 2359 default: 2360 /* ?? */ 2361 return NULL; 2362 } 2363 2364} 2365 2366/** 2367 * pevent_filter_make_string - return a string showing the filter 2368 * @filter: filter struct with filter information 2369 * @event_id: the event id to return the filter string with 2370 * 2371 * Returns a string that displays the filter contents. 2372 * This string must be freed with free(str). 2373 * NULL is returned if no filter is found or allocation failed. 2374 */ 2375char * 2376pevent_filter_make_string(struct event_filter *filter, int event_id) 2377{ 2378 struct filter_type *filter_type; 2379 2380 if (!filter->filters) 2381 return NULL; 2382 2383 filter_type = find_filter_type(filter, event_id); 2384 2385 if (!filter_type) 2386 return NULL; 2387 2388 return arg_to_str(filter, filter_type->filter); 2389} 2390 2391/** 2392 * pevent_filter_compare - compare two filters and return if they are the same 2393 * @filter1: Filter to compare with @filter2 2394 * @filter2: Filter to compare with @filter1 2395 * 2396 * Returns: 2397 * 1 if the two filters hold the same content. 2398 * 0 if they do not. 2399 */ 2400int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2) 2401{ 2402 struct filter_type *filter_type1; 2403 struct filter_type *filter_type2; 2404 char *str1, *str2; 2405 int result; 2406 int i; 2407 2408 /* Do the easy checks first */ 2409 if (filter1->filters != filter2->filters) 2410 return 0; 2411 if (!filter1->filters && !filter2->filters) 2412 return 1; 2413 2414 /* 2415 * Now take a look at each of the events to see if they have the same 2416 * filters to them. 2417 */ 2418 for (i = 0; i < filter1->filters; i++) { 2419 filter_type1 = &filter1->event_filters[i]; 2420 filter_type2 = find_filter_type(filter2, filter_type1->event_id); 2421 if (!filter_type2) 2422 break; 2423 if (filter_type1->filter->type != filter_type2->filter->type) 2424 break; 2425 switch (filter_type1->filter->type) { 2426 case FILTER_TRIVIAL_FALSE: 2427 case FILTER_TRIVIAL_TRUE: 2428 /* trivial types just need the type compared */ 2429 continue; 2430 default: 2431 break; 2432 } 2433 /* The best way to compare complex filters is with strings */ 2434 str1 = arg_to_str(filter1, filter_type1->filter); 2435 str2 = arg_to_str(filter2, filter_type2->filter); 2436 if (str1 && str2) 2437 result = strcmp(str1, str2) != 0; 2438 else 2439 /* bail out if allocation fails */ 2440 result = 1; 2441 2442 free(str1); 2443 free(str2); 2444 if (result) 2445 break; 2446 } 2447 2448 if (i < filter1->filters) 2449 return 0; 2450 return 1; 2451} 2452