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>
This commit is contained in:
Arnaldo Carvalho de Melo 2015-07-17 12:07:25 -03:00
parent 4a77e2183f
commit 8ff9daf3c1
2 changed files with 36 additions and 8 deletions

View file

@ -108,29 +108,47 @@ struct str_node *strlist__find(struct strlist *slist, const char *entry)
return snode;
}
static int strlist__parse_list_entry(struct strlist *slist, const char *s)
static int strlist__parse_list_entry(struct strlist *slist, const char *s,
const char *subst_dir)
{
int err;
char *subst = NULL;
if (strncmp(s, "file://", 7) == 0)
return strlist__load(slist, s + 7);
return strlist__add(slist, s);
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;
}
}
err = strlist__add(slist, s);
out:
free(subst);
return err;
}
int strlist__parse_list(struct strlist *slist, const char *s)
int strlist__parse_list(struct strlist *slist, const char *s, const char *subst_dir)
{
char *sep;
int err;
while ((sep = strchr(s, ',')) != NULL) {
*sep = '\0';
err = strlist__parse_list_entry(slist, s);
err = strlist__parse_list_entry(slist, s, subst_dir);
*sep = ',';
if (err != 0)
return err;
s = sep + 1;
}
return *s ? strlist__parse_list_entry(slist, s) : 0;
return *s ? strlist__parse_list_entry(slist, s, subst_dir) : 0;
}
struct strlist *strlist__new(const char *list, const struct strlist_config *config)
@ -138,13 +156,22 @@ struct strlist *strlist__new(const char *list, const struct strlist_config *conf
struct strlist *slist = malloc(sizeof(*slist));
if (slist != NULL) {
bool dupstr = true;
const char *dirname = NULL;
if (config) {
dupstr = !config->dont_dupstr;
dirname = config->dirname;
}
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;
slist->dupstr = config ? !config->dont_dupstr : true;
if (list && strlist__parse_list(slist, list) != 0)
slist->dupstr = dupstr;
if (list && strlist__parse_list(slist, list, dirname) != 0)
goto out_error;
}

View file

@ -18,6 +18,7 @@ struct strlist {
struct strlist_config {
bool dont_dupstr;
const char *dirname;
};
struct strlist *strlist__new(const char *slist, const struct strlist_config *config);
@ -79,5 +80,5 @@ static inline struct str_node *strlist__next(struct str_node *sn)
for (pos = strlist__first(slist), n = strlist__next(pos); pos;\
pos = n, n = strlist__next(n))
int strlist__parse_list(struct strlist *slist, const char *s);
int strlist__parse_list(struct strlist *slist, const char *s, const char *subst_dir);
#endif /* __PERF_STRLIST_H */