logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

tracefs_filter_string_append, tracefs_filter_string_verify, tracefs_event_filter_apply,

Author

StevenRostedt <rostedt@goodmis.org[1]>
           TzvetomirStoyanov <tz.stoyanov@gmail.com[2]>
           sameeruddinshaik <sameeruddin.shaik8@gmail.com[3]>

Copying

       Copyright (C) 2020 VMware, Inc. Free use of this software is granted under the terms of the GNU Public
       License (GPL).

Description

tracefs_filter_string_append() is a way to create and verify event filters for a given event. It will
       verify that the field belongs to the event and that the compare option that is used is valid for the type
       of the field, as well as val. For the type that is not of TRACEFS_FILTER_COMPARE, it will build the
       logical string and also make sure that the syntax is correct. For example, there are no more close
       parenthesis than open parenthesis. An AND (&&) or OR (||) is not misplaced, etc.

       tracefs_synth_append_start_filter() creates a filter or appends to it for the starting event. Depending
       on type, it will build a string of tokens for parenthesis or logic statemens, or it may add a comparison
       of field to val based on compare.

       If type is: TRACEFS_FILTER_COMPARE - See below TRACEFS_FILTER_AND - Append "&&" to the filter
       TRACEFS_FILTER_OR - Append "||" to the filter TRACEFS_FILTER_NOT - Append "!" to the filter
       TRACEFS_FILTER_OPEN_PAREN - Append "(" to the filter TRACEFS_FILTER_CLOSE_PAREN - Append ")" to the
       filter

       field, compare, and val are ignored unless type is equal to TRACEFS_FILTER_COMPARE, then _compare will be
       used for the following:

       TRACEFS_COMPARE_EQ - field == valTRACEFS_COMPARE_NE - field != valTRACEFS_COMPARE_GT - field > valTRACEFS_COMPARE_GE - field >= valTRACEFS_COMPARE_LT - field < valTRACEFS_COMPARE_LE - field <= valTRACEFS_COMPARE_RE - field ~ "val" : where field is a string.

       TRACEFS_COMPARE_AND - field & val : where field is a flags field.

       tracefs_filter_string_verify() will parse filter to make sure that the fields are for the event, and that
       the syntax is correct. If there’s an error in the syntax, and err is not NULL, then it will be allocated
       with an error message stating what was found wrong with the filter. err must be freed with free().

       tracefs_event_filter_apply() applies given filter string on event in given instance.

       tracefs_event_filter_clear() clear all filters on event in given instance.

Example

           #include <stdlib.h>
           #include <stdio.h>
           #include <ctype.h>
           #include <tracefs.h>

           static void usage(char **argv)
           {
                   fprintf(stderr, "usage: %s [system] event filter\n", argv[0]);
                   exit(-1);
           }

           int main (int argc, char **argv)
           {
                   struct tep_handle *tep;
                   struct tep_event *event;
                   const char *system = NULL;
                   const char *event_name;
                   const char *filter;
                   char *new_filter = NULL;
                   char *err = NULL;
                   int i;

                   if (argc < 3)
                           usage(argv);

                   if (argc < 4) {
                           event_name = argv[1];
                           filter = argv[2];
                   } else {
                           system = argv[1];
                           event_name = argv[2];
                           filter = argv[3];
                   }

                   /* Load all events from the system */
                   tep = tracefs_local_events(NULL);
                   if (!tep) {
                           perror("tep");
                           exit(-1);
                   }

                   event = tep_find_event_by_name(tep, system, event_name);
                   if (!event) {
                           fprintf(stderr, "Event %s%s%s not found\n",
                                   system ? system : "" , system ? " " : "",
                                   event_name);
                           exit(-1);
                   }

                   if (tracefs_filter_string_verify(event, filter, &err) < 0) {
                           perror("tracecfs_event_verify_filter");
                           if (err)
                                   fprintf(stderr, "%s", err);
                           free(err);
                           exit(-1);
                   }

                   for (i = 0; filter[i]; i++) {
                           char buf[strlen(filter)];
                           char *field = NULL;
                           char *val = NULL;
                           enum tracefs_filter type;
                           enum tracefs_compare compare = 0;
                           int start_i, n;
                           int quote;
                           bool backslash;

                           while (isspace(filter[i]))
                                   i++;

                           switch(filter[i]) {
                           case '(':
                                   type = TRACEFS_FILTER_OPEN_PAREN;
                                   break;
                           case ')':
                                   type = TRACEFS_FILTER_CLOSE_PAREN;
                                   break;
                           case '!':
                                   type = TRACEFS_FILTER_NOT;
                                   break;
                           case '&':
                                   type = TRACEFS_FILTER_AND;
                                   i++;
                                   break;
                           case '|':
                                   type = TRACEFS_FILTER_OR;
                                   i++;
                                   break;
                           default:
                                   type = TRACEFS_FILTER_COMPARE;

                                   while (isspace(filter[i]))
                                           i++;

                                   start_i = i;
                                   for (; filter[i]; i++) {
                                           switch(filter[i]) {
                                           case 'a' ... 'z':
                                           case 'A' ... 'Z':
                                           case '0' ... '9':
                                           case '_':
                                                   continue;
                                           }
                                           break;
                                   }

                                   n = i - start_i;
                                   field = buf;
                                   strncpy(field, filter + start_i, n);
                                   field[n++] = '\0';

                                   val = buf + n;

                                   while (isspace(filter[i]))
                                           i++;

                                   start_i = i;
                                   switch(filter[i++]) {
                                   case '>':
                                           compare = TRACEFS_COMPARE_GT;
                                           if (filter[i] == '=') {
                                                   i++;
                                                   compare = TRACEFS_COMPARE_GE;
                                           }
                                           break;
                                   case '<':
                                           compare = TRACEFS_COMPARE_LT;
                                           if (filter[i] == '=') {
                                                   i++;
                                                   compare = TRACEFS_COMPARE_LE;
                                           }
                                           break;
                                   case '=':
                                           compare = TRACEFS_COMPARE_EQ;
                                           i++;
                                           break;
                                   case '!':
                                           compare = TRACEFS_COMPARE_NE;
                                           i++;
                                           break;
                                   case '~':
                                           compare = TRACEFS_COMPARE_RE;
                                           break;
                                   case '&':
                                           compare = TRACEFS_COMPARE_AND;
                                           break;
                                   }

                                   while (isspace(filter[i]))
                                           i++;

                                   quote = 0;
                                   backslash = false;
                                   start_i = i;
                                   for (; filter[i]; i++) {
                                           if (quote) {
                                                   if (backslash)
                                                           backslash = false;
                                                   else if (filter[i] == '\\')
                                                           backslash = true;
                                                   else if (filter[i] == quote)
                                                           quote = 0;
                                                   continue;
                                           }
                                           switch(filter[i]) {
                                           case '"': case '\'':
                                                   quote = filter[i];
                                                   continue;
                                           case 'a' ... 'z':
                                           case 'A' ... 'Z':
                                           case '0' ... '9':
                                           case '_':
                                                   continue;
                                           }
                                           break;
                                   }
                                   n = i - start_i;
                                   strncpy(val, filter + start_i, n);
                                   val[n] = '\0';
                                   break;
                           }
                           n = tracefs_filter_string_append(event, &new_filter, type,
                                                           field, compare, val);
                           if (n < 0) {
                                   fprintf(stderr, "Failed making new filter:\n'%s'\n",
                                           new_filter ? new_filter : "(null)");
                                   exit(-1);
                           }
                   }

                   if (tracefs_event_filter_apply(NULL, event, new_filter))
                           fprintf(stderr, "Failed to apply filter on event");

                   tep_free(tep);

                   printf("Created new filter: '%s'\n", new_filter);
                   free(new_filter);

                   exit(0);
           }

Files

tracefs.h
                   Header file to include in order to have access to the library APIs.
           -ltracefs
                   Linker switch to add when building a program that uses the library.

License

       libtracefs is Free Software licensed under the GNU LGPL 2.1

Name

       tracefs_filter_string_append, tracefs_filter_string_verify, tracefs_event_filter_apply,
       tracefs_event_filter_clear - Add, verify and apply event filters

Notes

Reporting Bugs

       Report bugs to <linux-trace-devel@vger.kernel.org[4]>

Resources

https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/

Return Value

tracefs_filter_string_append() returns 0 on success and -1 on error.

       tracefs_filter_string_verify() returns 0 on success and -1 on error. if there is an error, and errno is
       not ENOMEM, then err is allocated and will contain a string describing what was found wrong with filter.
       err must be freed with free().

       tracefs_event_filter_apply() returns 0 on success and -1 on error.

       tracefs_event_filter_clear() returns 0 on success and -1 on error.

See Also

libtracefs(3), libtraceevent(3), trace-cmd(1), tracefs_hist_alloc(3), tracefs_hist_alloc_2d(3),
       tracefs_hist_alloc_nd(3), tracefs_hist_free(3), tracefs_hist_add_key(3), tracefs_hist_add_value(3),
       tracefs_hist_add_name(3), tracefs_hist_start(3), tracefs_hist_destory(3), tracefs_hist_add_sort_key(3),
       tracefs_hist_sort_key_direction(3)

Synopsis

#include<tracefs.h>

       int tracefs_filter_string_append(struct tep_event *event, char **filter,
                                        struct tracefs_filter type, const char *field,
                                        enum tracefs_synth_compare compare, const char *val);
       int tracefs_filter_string_verify(struct tep_event *event, const char *filter, char **err);
       int tracefs_event_filter_apply(struct tracefs_instance *instance, struct tep_event *event, const char *filter);
       int tracefs_event_filter_clear(struct tracefs_instance *instance, struct tep_event *event);

See Also