libtracefs(3)
=============

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

SYNOPSIS
--------
[verse]
--
*#include <tracefs.h>*

int *tracefs_filter_string_append*(struct tep_event pass:[*]_event_, char pass:[**]_filter_,
				 struct tracefs_filter _type_, const char pass:[*]_field_,
				 enum tracefs_synth_compare _compare_, const char pass:[*]_val_);
int *tracefs_filter_string_verify*(struct tep_event pass:[*]_event_, const char pass:[*]_filter_, char pass:[**]_err_);
int *tracefs_event_filter_apply*(struct tracefs_instance pass:[*]_instance_, struct tep_event pass:[*]_event_, const char pass:[*]_filter_);
int *tracefs_event_filter_clear*(struct tracefs_instance pass:[*]_instance_, struct tep_event pass:[*]_event_);

--

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_ == _val_

*TRACEFS_COMPARE_NE* - _field_ != _val_

*TRACEFS_COMPARE_GT* - _field_ > _val_

*TRACEFS_COMPARE_GE* - _field_ >= _val_

*TRACEFS_COMPARE_LT* - _field_ < _val_

*TRACEFS_COMPARE_LE* - _field_ <pass:[=] _val_

*TRACEFS_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_.

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.

EXAMPLE
-------
[source,c]
--
#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
-----
[verse]
--
*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.
--

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)

AUTHOR
------
[verse]
--
*Steven Rostedt* <rostedt@goodmis.org>
*Tzvetomir Stoyanov* <tz.stoyanov@gmail.com>
*sameeruddin shaik* <sameeruddin.shaik8@gmail.com>
--
REPORTING BUGS
--------------
Report bugs to  <linux-trace-devel@vger.kernel.org>

LICENSE
-------
libtracefs is Free Software licensed under the GNU LGPL 2.1

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

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