2009-07-01 02:01:20 +04:00
/*
* ( c ) 2009 Arnaldo Carvalho de Melo < acme @ redhat . com >
*
* Licensed under the GPLv2 .
*/
# include "strlist.h"
2013-12-27 23:55:14 +04:00
# include "util.h"
2009-07-01 02:01:20 +04:00
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2012-07-31 08:31:33 +04:00
static
struct rb_node * strlist__node_new ( struct rblist * rblist , const void * entry )
2009-07-01 02:01:20 +04:00
{
2012-07-31 08:31:33 +04:00
const char * s = entry ;
struct rb_node * rc = NULL ;
struct strlist * strlist = container_of ( rblist , struct strlist , rblist ) ;
struct str_node * snode = malloc ( sizeof ( * snode ) ) ;
2009-07-01 02:01:20 +04:00
2012-07-31 08:31:33 +04:00
if ( snode ! = NULL ) {
if ( strlist - > dupstr ) {
2009-07-01 02:01:20 +04:00
s = strdup ( s ) ;
if ( s = = NULL )
goto out_delete ;
}
2012-07-31 08:31:33 +04:00
snode - > s = s ;
rc = & snode - > rb_node ;
2009-07-01 02:01:20 +04:00
}
2012-07-31 08:31:33 +04:00
return rc ;
2009-07-01 02:01:20 +04:00
out_delete :
2012-07-31 08:31:33 +04:00
free ( snode ) ;
2009-07-01 02:01:20 +04:00
return NULL ;
}
2013-01-25 04:59:59 +04:00
static void str_node__delete ( struct str_node * snode , bool dupstr )
2009-07-01 02:01:20 +04:00
{
if ( dupstr )
2014-01-09 18:07:59 +04:00
zfree ( ( char * * ) & snode - > s ) ;
2013-01-25 04:59:59 +04:00
free ( snode ) ;
2009-07-01 02:01:20 +04:00
}
2012-07-31 08:31:33 +04:00
static
void strlist__node_delete ( struct rblist * rblist , struct rb_node * rb_node )
2009-07-01 02:01:20 +04:00
{
2012-07-31 08:31:33 +04:00
struct strlist * slist = container_of ( rblist , struct strlist , rblist ) ;
struct str_node * snode = container_of ( rb_node , struct str_node , rb_node ) ;
2009-07-01 02:01:20 +04:00
2012-07-31 08:31:33 +04:00
str_node__delete ( snode , slist - > dupstr ) ;
}
2009-07-01 02:01:20 +04:00
2012-07-31 08:31:33 +04:00
static int strlist__node_cmp ( struct rb_node * rb_node , const void * entry )
{
const char * str = entry ;
struct str_node * snode = container_of ( rb_node , struct str_node , rb_node ) ;
return strcmp ( snode - > s , str ) ;
}
2009-07-01 02:01:20 +04:00
2013-01-25 04:59:59 +04:00
int strlist__add ( struct strlist * slist , const char * new_entry )
2012-07-31 08:31:33 +04:00
{
2013-01-25 04:59:59 +04:00
return rblist__add_node ( & slist - > rblist , new_entry ) ;
2009-07-01 02:01:20 +04:00
}
2013-01-25 04:59:59 +04:00
int strlist__load ( struct strlist * slist , const char * filename )
2009-07-01 02:01:20 +04:00
{
char entry [ 1024 ] ;
int err ;
FILE * fp = fopen ( filename , " r " ) ;
if ( fp = = NULL )
2015-07-16 17:08:34 +03:00
return - errno ;
2009-07-01 02:01:20 +04:00
while ( fgets ( entry , sizeof ( entry ) , fp ) ! = NULL ) {
const size_t len = strlen ( entry ) ;
if ( len = = 0 )
continue ;
entry [ len - 1 ] = ' \0 ' ;
2013-01-25 04:59:59 +04:00
err = strlist__add ( slist , entry ) ;
2009-07-01 02:01:20 +04:00
if ( err ! = 0 )
goto out ;
}
err = 0 ;
out :
fclose ( fp ) ;
return err ;
}
2012-07-31 08:31:33 +04:00
void strlist__remove ( struct strlist * slist , struct str_node * snode )
2009-07-01 02:01:20 +04:00
{
2012-08-29 10:00:07 +04:00
rblist__remove_node ( & slist - > rblist , & snode - > rb_node ) ;
2009-07-01 02:01:20 +04:00
}
2012-07-31 08:31:33 +04:00
struct str_node * strlist__find ( struct strlist * slist , const char * entry )
2009-07-01 02:01:20 +04:00
{
2012-07-31 08:31:33 +04:00
struct str_node * snode = NULL ;
struct rb_node * rb_node = rblist__find ( & slist - > rblist , entry ) ;
2009-07-01 02:01:20 +04:00
2012-07-31 08:31:33 +04:00
if ( rb_node )
snode = container_of ( rb_node , struct str_node , rb_node ) ;
return snode ;
2009-07-01 02:01:20 +04:00
}
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
static int strlist__parse_list_entry ( struct strlist * slist , const char * s ,
const char * subst_dir )
2009-07-01 02:01:20 +04:00
{
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
int err ;
char * subst = NULL ;
2009-07-01 02:01:20 +04:00
if ( strncmp ( s , " file:// " , 7 ) = = 0 )
2013-01-25 04:59:59 +04:00
return strlist__load ( slist , s + 7 ) ;
2009-07-01 02:01:20 +04:00
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
if ( subst_dir ) {
err = - ENOMEM ;
if ( asprintf ( & subst , " %s/%s " , subst_dir , s ) < 0 )
goto out ;
if ( access ( subst , F_OK ) = = 0 ) {
err = strlist__load ( slist , subst ) ;
goto out ;
}
2016-01-09 13:16:27 +03:00
if ( slist - > file_only ) {
err = - ENOENT ;
goto out ;
}
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
}
err = strlist__add ( slist , s ) ;
out :
free ( subst ) ;
return err ;
2009-07-01 02:01:20 +04:00
}
2015-07-17 21:10:33 +03:00
static int strlist__parse_list ( struct strlist * slist , const char * s , const char * subst_dir )
2009-07-01 02:01:20 +04:00
{
char * sep ;
int err ;
while ( ( sep = strchr ( s , ' , ' ) ) ! = NULL ) {
* sep = ' \0 ' ;
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
err = strlist__parse_list_entry ( slist , s , subst_dir ) ;
2009-07-01 02:01:20 +04:00
* sep = ' , ' ;
if ( err ! = 0 )
return err ;
s = sep + 1 ;
}
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
return * s ? strlist__parse_list_entry ( slist , s , subst_dir ) : 0 ;
2009-07-01 02:01:20 +04:00
}
2015-07-20 18:13:34 +03:00
struct strlist * strlist__new ( const char * list , const struct strlist_config * config )
2009-07-01 02:01:20 +04:00
{
2013-01-25 04:59:59 +04:00
struct strlist * slist = malloc ( sizeof ( * slist ) ) ;
2009-07-01 02:01:20 +04:00
2013-01-25 04:59:59 +04:00
if ( slist ! = NULL ) {
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
bool dupstr = true ;
2016-01-09 13:16:27 +03:00
bool file_only = false ;
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
const char * dirname = NULL ;
if ( config ) {
dupstr = ! config - > dont_dupstr ;
dirname = config - > dirname ;
2016-01-09 13:16:27 +03:00
file_only = config - > file_only ;
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
}
2013-01-25 04:59:59 +04:00
rblist__init ( & slist - > rblist ) ;
slist - > rblist . node_cmp = strlist__node_cmp ;
slist - > rblist . node_new = strlist__node_new ;
slist - > rblist . node_delete = strlist__node_delete ;
2012-07-31 08:31:33 +04:00
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
slist - > dupstr = dupstr ;
2016-01-09 13:16:27 +03:00
slist - > file_only = file_only ;
perf strlist: Allow substitutions from file contents in a given directory
So, if we have an strlist equal to:
"file,close"
And we call it as:
struct strlist_config *config = { .dirname = "~/strace/groups", };
struct strlist *slist = strlist__new("file, close", &config);
And we have:
$ cat ~/strace/groups/file
access
open
openat
statfs
Then the resulting strlist will have these contents:
[ "access", "open", "openat", "statfs", "close" ]
This will be used to implement strace syscall groups in 'perf trace',
but can be used in some other tool, thus being implemented in 'strlist'.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-wi6l6qtomqlywwr6005jvs05@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2015-07-17 18:07:25 +03:00
if ( list & & strlist__parse_list ( slist , list , dirname ) ! = 0 )
2009-07-01 02:01:20 +04:00
goto out_error ;
}
2013-01-25 04:59:59 +04:00
return slist ;
2009-07-01 02:01:20 +04:00
out_error :
2013-01-25 04:59:59 +04:00
free ( slist ) ;
2009-07-01 02:01:20 +04:00
return NULL ;
}
2013-01-25 04:59:59 +04:00
void strlist__delete ( struct strlist * slist )
2009-07-01 02:01:20 +04:00
{
2013-01-25 04:59:59 +04:00
if ( slist ! = NULL )
rblist__delete ( & slist - > rblist ) ;
2009-07-01 02:01:20 +04:00
}
2009-07-11 19:18:34 +04:00
2012-07-31 08:31:33 +04:00
struct str_node * strlist__entry ( const struct strlist * slist , unsigned int idx )
2009-07-11 19:18:34 +04:00
{
2012-07-31 08:31:33 +04:00
struct str_node * snode = NULL ;
struct rb_node * rb_node ;
2009-07-11 19:18:34 +04:00
2012-07-31 08:31:33 +04:00
rb_node = rblist__entry ( & slist - > rblist , idx ) ;
if ( rb_node )
snode = container_of ( rb_node , struct str_node , rb_node ) ;
2009-07-11 19:18:34 +04:00
2012-07-31 08:31:33 +04:00
return snode ;
2009-07-11 19:18:34 +04:00
}