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