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