From c4068f51d40df151a661a384ab1309b11d7f012e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 19 Nov 2015 15:04:53 +0900 Subject: perf tools: Make perf_exec_path() always return malloc'd string Since system_path() returns malloc'd string if given path is not an absolute path, perf_exec_path() sometimes returns a static string and sometimes returns a malloc'd string depending on the environment variables or command options. This may cause a memory leak because the caller can not unconditionally free the returned string. This fixes perf_exec_path() and system_path() to always return a malloc'd string, so the caller can always free it. Signed-off-by: Masami Hiramatsu Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20151119060453.14210.65666.stgit@localhost.localdomain Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 86c37c472263..fa1fc4acb8a4 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -159,7 +159,7 @@ void load_command_list(const char *prefix, struct cmdnames *other_cmds) { const char *env_path = getenv("PATH"); - const char *exec_path = perf_exec_path(); + char *exec_path = perf_exec_path(); if (exec_path) { list_commands_in_dir(main_cmds, exec_path, prefix); @@ -187,6 +187,7 @@ void load_command_list(const char *prefix, sizeof(*other_cmds->names), cmdname_compare); uniq(other_cmds); } + free(exec_path); exclude_cmds(other_cmds, main_cmds); } @@ -203,13 +204,14 @@ void list_commands(const char *title, struct cmdnames *main_cmds, longest = other_cmds->names[i]->len; if (main_cmds->cnt) { - const char *exec_path = perf_exec_path(); + char *exec_path = perf_exec_path(); printf("available %s in '%s'\n", title, exec_path); printf("----------------"); mput_char('-', strlen(title) + strlen(exec_path)); putchar('\n'); pretty_print_string_list(main_cmds, longest); putchar('\n'); + free(exec_path); } if (other_cmds->cnt) { -- cgit From 0a4bb5da957b83ece8b4723c5bac7a5d29fbfb33 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Mon, 7 Dec 2015 22:21:48 -0600 Subject: perf tools: Move cmd_version() to builtin-version.c Move cmd_version() to its own file so that help.c can be moved to a library. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/e908b1b68f20ab6d8d33941d5571c23110622e60.1449548395.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index fa1fc4acb8a4..929c93f2c333 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -332,10 +332,3 @@ const char *help_unknown_cmd(const char *cmd) exit(1); } - -int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused, - const char *prefix __maybe_unused) -{ - printf("perf version %s\n", perf_version_string); - return 0; -} -- cgit From 5feaac248a46dd5f9876c4ae45c4bbbde5472e90 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Sun, 13 Dec 2015 22:18:09 -0600 Subject: perf tools: Move help_unknown_cmd() to its own file help_unknown_cmd() is quite perf-specific because it relies on some perf_config*() functions. Move it and its supporting functions out into a separate file so that help.c can be moved to a library. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/562d918bcaaf340c1ae3e47586b3f0ae33b9918b.1449965119.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 107 ++----------------------------------------------- 1 file changed, 3 insertions(+), 104 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 929c93f2c333..8d74f7d05674 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -1,9 +1,7 @@ #include "cache.h" #include "../builtin.h" #include "exec_cmd.h" -#include "levenshtein.h" #include "help.h" -#include void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { @@ -17,7 +15,7 @@ void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) cmds->names[cmds->cnt++] = ent; } -static void clean_cmdnames(struct cmdnames *cmds) +void clean_cmdnames(struct cmdnames *cmds) { unsigned int i; @@ -28,14 +26,14 @@ static void clean_cmdnames(struct cmdnames *cmds) cmds->alloc = 0; } -static int cmdname_compare(const void *a_, const void *b_) +int cmdname_compare(const void *a_, const void *b_) { struct cmdname *a = *(struct cmdname **)a_; struct cmdname *b = *(struct cmdname **)b_; return strcmp(a->name, b->name); } -static void uniq(struct cmdnames *cmds) +void uniq(struct cmdnames *cmds) { unsigned int i, j; @@ -233,102 +231,3 @@ int is_in_cmdlist(struct cmdnames *c, const char *s) return 1; return 0; } - -static int autocorrect; -static struct cmdnames aliases; - -static int perf_unknown_cmd_config(const char *var, const char *value, void *cb) -{ - if (!strcmp(var, "help.autocorrect")) - autocorrect = perf_config_int(var,value); - /* Also use aliases for command lookup */ - if (!prefixcmp(var, "alias.")) - add_cmdname(&aliases, var + 6, strlen(var + 6)); - - return perf_default_config(var, value, cb); -} - -static int levenshtein_compare(const void *p1, const void *p2) -{ - const struct cmdname *const *c1 = p1, *const *c2 = p2; - const char *s1 = (*c1)->name, *s2 = (*c2)->name; - int l1 = (*c1)->len; - int l2 = (*c2)->len; - return l1 != l2 ? l1 - l2 : strcmp(s1, s2); -} - -static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) -{ - unsigned int i; - - ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); - - for (i = 0; i < old->cnt; i++) - cmds->names[cmds->cnt++] = old->names[i]; - zfree(&old->names); - old->cnt = 0; -} - -const char *help_unknown_cmd(const char *cmd) -{ - unsigned int i, n = 0, best_similarity = 0; - struct cmdnames main_cmds, other_cmds; - - memset(&main_cmds, 0, sizeof(main_cmds)); - memset(&other_cmds, 0, sizeof(main_cmds)); - memset(&aliases, 0, sizeof(aliases)); - - perf_config(perf_unknown_cmd_config, NULL); - - load_command_list("perf-", &main_cmds, &other_cmds); - - add_cmd_list(&main_cmds, &aliases); - add_cmd_list(&main_cmds, &other_cmds); - qsort(main_cmds.names, main_cmds.cnt, - sizeof(main_cmds.names), cmdname_compare); - uniq(&main_cmds); - - if (main_cmds.cnt) { - /* This reuses cmdname->len for similarity index */ - for (i = 0; i < main_cmds.cnt; ++i) - main_cmds.names[i]->len = - levenshtein(cmd, main_cmds.names[i]->name, 0, 2, 1, 4); - - qsort(main_cmds.names, main_cmds.cnt, - sizeof(*main_cmds.names), levenshtein_compare); - - best_similarity = main_cmds.names[0]->len; - n = 1; - while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len) - ++n; - } - - if (autocorrect && n == 1) { - const char *assumed = main_cmds.names[0]->name; - - main_cmds.names[0] = NULL; - clean_cmdnames(&main_cmds); - fprintf(stderr, "WARNING: You called a perf program named '%s', " - "which does not exist.\n" - "Continuing under the assumption that you meant '%s'\n", - cmd, assumed); - if (autocorrect > 0) { - fprintf(stderr, "in %0.1f seconds automatically...\n", - (float)autocorrect/10.0); - poll(NULL, 0, autocorrect * 100); - } - return assumed; - } - - fprintf(stderr, "perf: '%s' is not a perf-command. See 'perf --help'.\n", cmd); - - if (main_cmds.cnt && best_similarity < 6) { - fprintf(stderr, "\nDid you mean %s?\n", - n < 2 ? "this": "one of these"); - - for (i = 0; i < n; i++) - fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); - } - - exit(1); -} -- cgit From 901421a5bdf605d24c278825cdd032cd6038bcb8 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 15 Dec 2015 09:39:36 -0600 Subject: perf tools: Remove subcmd dependencies on strbuf Introduce and use new astrcat() and astrcatf() functions which replace the strbuf functionality for subcmd. For now they duplicate strbuf's die-on-allocation-error policy. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/957d207e1254406fa11fc2e405e75a7e405aad8f.1450193761.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8d74f7d05674..8e5e0ce3870e 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -2,6 +2,7 @@ #include "../builtin.h" #include "exec_cmd.h" #include "help.h" +#include "subcmd-util.h" void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { @@ -119,8 +120,7 @@ static void list_commands_in_dir(struct cmdnames *cmds, int prefix_len; DIR *dir = opendir(path); struct dirent *de; - struct strbuf buf = STRBUF_INIT; - int len; + char *buf = NULL; if (!dir) return; @@ -128,8 +128,7 @@ static void list_commands_in_dir(struct cmdnames *cmds, prefix = "perf-"; prefix_len = strlen(prefix); - strbuf_addf(&buf, "%s/", path); - len = buf.len; + astrcatf(&buf, "%s/", path); while ((de = readdir(dir)) != NULL) { int entlen; @@ -137,9 +136,8 @@ static void list_commands_in_dir(struct cmdnames *cmds, if (prefixcmp(de->d_name, prefix)) continue; - strbuf_setlen(&buf, len); - strbuf_addstr(&buf, de->d_name); - if (!is_executable(buf.buf)) + astrcat(&buf, de->d_name); + if (!is_executable(buf)) continue; entlen = strlen(de->d_name) - prefix_len; @@ -149,7 +147,7 @@ static void list_commands_in_dir(struct cmdnames *cmds, add_cmdname(cmds, de->d_name + prefix_len, entlen); } closedir(dir); - strbuf_release(&buf); + free(buf); } void load_command_list(const char *prefix, -- cgit From 46113a54be53aea50a4f5926b87e86e2e66c4266 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 15 Dec 2015 09:39:37 -0600 Subject: perf tools: Remove 'perf' from subcmd function and variable names In preparation for moving exec_cmd.c and run-command.c out of perf and into a library, remove 'perf' from all the symbol names. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/bc3ee82b40b8f396b644fa49e0f7260ce442635b.1450193761.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 8e5e0ce3870e..303a347ee234 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -155,7 +155,7 @@ void load_command_list(const char *prefix, struct cmdnames *other_cmds) { const char *env_path = getenv("PATH"); - char *exec_path = perf_exec_path(); + char *exec_path = get_argv_exec_path(); if (exec_path) { list_commands_in_dir(main_cmds, exec_path, prefix); @@ -200,7 +200,7 @@ void list_commands(const char *title, struct cmdnames *main_cmds, longest = other_cmds->names[i]->len; if (main_cmds->cnt) { - char *exec_path = perf_exec_path(); + char *exec_path = get_argv_exec_path(); printf("available %s in '%s'\n", title, exec_path); printf("----------------"); mput_char('-', strlen(title) + strlen(exec_path)); -- cgit From 2f4ce5ec1d447beb42143a9653716a2ab025161e Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 15 Dec 2015 09:39:38 -0600 Subject: perf tools: Finalize subcmd independence For the files that will be moved to the subcmd library, remove all their perf-specific includes and duplicate any needed functionality. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/6e12946f0f26ce4d543d34db68d9dae3c8551cb9.1450193761.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 47 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 5 deletions(-) (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c index 303a347ee234..8169480066c6 100644 --- a/tools/perf/util/help.c +++ b/tools/perf/util/help.c @@ -1,8 +1,15 @@ -#include "cache.h" -#include "../builtin.h" -#include "exec_cmd.h" -#include "help.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "subcmd-util.h" +#include "help.h" +#include "exec_cmd.h" void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) { @@ -70,6 +77,28 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) cmds->cnt = cj; } +static void get_term_dimensions(struct winsize *ws) +{ + char *s = getenv("LINES"); + + if (s != NULL) { + ws->ws_row = atoi(s); + s = getenv("COLUMNS"); + if (s != NULL) { + ws->ws_col = atoi(s); + if (ws->ws_row && ws->ws_col) + return; + } + } +#ifdef TIOCGWINSZ + if (ioctl(1, TIOCGWINSZ, ws) == 0 && + ws->ws_row && ws->ws_col) + return; +#endif + ws->ws_row = 25; + ws->ws_col = 80; +} + static void pretty_print_string_list(struct cmdnames *cmds, int longest) { int cols = 1, rows; @@ -113,6 +142,14 @@ static int is_executable(const char *name) return st.st_mode & S_IXUSR; } +static int has_extension(const char *filename, const char *ext) +{ + size_t len = strlen(filename); + size_t extlen = strlen(ext); + + return len > extlen && !memcmp(filename + len - extlen, ext, extlen); +} + static void list_commands_in_dir(struct cmdnames *cmds, const char *path, const char *prefix) @@ -168,7 +205,7 @@ void load_command_list(const char *prefix, char *paths, *path, *colon; path = paths = strdup(env_path); while (1) { - if ((colon = strchr(path, PATH_SEP))) + if ((colon = strchr(path, ':'))) *colon = 0; if (!exec_path || strcmp(path, exec_path)) list_commands_in_dir(other_cmds, path, prefix); -- cgit From 4b6ab94eabe4f55371cff4569750bb3996c55db6 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 15 Dec 2015 09:39:39 -0600 Subject: perf subcmd: Create subcmd library Move the subcommand-related files from perf to a new library named libsubcmd.a. Since we're moving files anyway, go ahead and rename 'exec_cmd.*' to 'exec-cmd.*' to be consistent with the naming of all the other files. Signed-off-by: Josh Poimboeuf Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/c0a838d4c878ab17fee50998811612b2281355c1.1450193761.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/help.c | 268 ------------------------------------------------- 1 file changed, 268 deletions(-) delete mode 100644 tools/perf/util/help.c (limited to 'tools/perf/util/help.c') diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c deleted file mode 100644 index 8169480066c6..000000000000 --- a/tools/perf/util/help.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "subcmd-util.h" -#include "help.h" -#include "exec_cmd.h" - -void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) -{ - struct cmdname *ent = malloc(sizeof(*ent) + len + 1); - - ent->len = len; - memcpy(ent->name, name, len); - ent->name[len] = 0; - - ALLOC_GROW(cmds->names, cmds->cnt + 1, cmds->alloc); - cmds->names[cmds->cnt++] = ent; -} - -void clean_cmdnames(struct cmdnames *cmds) -{ - unsigned int i; - - for (i = 0; i < cmds->cnt; ++i) - zfree(&cmds->names[i]); - zfree(&cmds->names); - cmds->cnt = 0; - cmds->alloc = 0; -} - -int cmdname_compare(const void *a_, const void *b_) -{ - struct cmdname *a = *(struct cmdname **)a_; - struct cmdname *b = *(struct cmdname **)b_; - return strcmp(a->name, b->name); -} - -void uniq(struct cmdnames *cmds) -{ - unsigned int i, j; - - if (!cmds->cnt) - return; - - for (i = j = 1; i < cmds->cnt; i++) - if (strcmp(cmds->names[i]->name, cmds->names[i-1]->name)) - cmds->names[j++] = cmds->names[i]; - - cmds->cnt = j; -} - -void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) -{ - size_t ci, cj, ei; - int cmp; - - ci = cj = ei = 0; - while (ci < cmds->cnt && ei < excludes->cnt) { - cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); - if (cmp < 0) - cmds->names[cj++] = cmds->names[ci++]; - else if (cmp == 0) - ci++, ei++; - else if (cmp > 0) - ei++; - } - - while (ci < cmds->cnt) - cmds->names[cj++] = cmds->names[ci++]; - - cmds->cnt = cj; -} - -static void get_term_dimensions(struct winsize *ws) -{ - char *s = getenv("LINES"); - - if (s != NULL) { - ws->ws_row = atoi(s); - s = getenv("COLUMNS"); - if (s != NULL) { - ws->ws_col = atoi(s); - if (ws->ws_row && ws->ws_col) - return; - } - } -#ifdef TIOCGWINSZ - if (ioctl(1, TIOCGWINSZ, ws) == 0 && - ws->ws_row && ws->ws_col) - return; -#endif - ws->ws_row = 25; - ws->ws_col = 80; -} - -static void pretty_print_string_list(struct cmdnames *cmds, int longest) -{ - int cols = 1, rows; - int space = longest + 1; /* min 1 SP between words */ - struct winsize win; - int max_cols; - int i, j; - - get_term_dimensions(&win); - max_cols = win.ws_col - 1; /* don't print *on* the edge */ - - if (space < max_cols) - cols = max_cols / space; - rows = (cmds->cnt + cols - 1) / cols; - - for (i = 0; i < rows; i++) { - printf(" "); - - for (j = 0; j < cols; j++) { - unsigned int n = j * rows + i; - unsigned int size = space; - - if (n >= cmds->cnt) - break; - if (j == cols-1 || n + rows >= cmds->cnt) - size = 1; - printf("%-*s", size, cmds->names[n]->name); - } - putchar('\n'); - } -} - -static int is_executable(const char *name) -{ - struct stat st; - - if (stat(name, &st) || /* stat, not lstat */ - !S_ISREG(st.st_mode)) - return 0; - - return st.st_mode & S_IXUSR; -} - -static int has_extension(const char *filename, const char *ext) -{ - size_t len = strlen(filename); - size_t extlen = strlen(ext); - - return len > extlen && !memcmp(filename + len - extlen, ext, extlen); -} - -static void list_commands_in_dir(struct cmdnames *cmds, - const char *path, - const char *prefix) -{ - int prefix_len; - DIR *dir = opendir(path); - struct dirent *de; - char *buf = NULL; - - if (!dir) - return; - if (!prefix) - prefix = "perf-"; - prefix_len = strlen(prefix); - - astrcatf(&buf, "%s/", path); - - while ((de = readdir(dir)) != NULL) { - int entlen; - - if (prefixcmp(de->d_name, prefix)) - continue; - - astrcat(&buf, de->d_name); - if (!is_executable(buf)) - continue; - - entlen = strlen(de->d_name) - prefix_len; - if (has_extension(de->d_name, ".exe")) - entlen -= 4; - - add_cmdname(cmds, de->d_name + prefix_len, entlen); - } - closedir(dir); - free(buf); -} - -void load_command_list(const char *prefix, - struct cmdnames *main_cmds, - struct cmdnames *other_cmds) -{ - const char *env_path = getenv("PATH"); - char *exec_path = get_argv_exec_path(); - - if (exec_path) { - list_commands_in_dir(main_cmds, exec_path, prefix); - qsort(main_cmds->names, main_cmds->cnt, - sizeof(*main_cmds->names), cmdname_compare); - uniq(main_cmds); - } - - if (env_path) { - char *paths, *path, *colon; - path = paths = strdup(env_path); - while (1) { - if ((colon = strchr(path, ':'))) - *colon = 0; - if (!exec_path || strcmp(path, exec_path)) - list_commands_in_dir(other_cmds, path, prefix); - - if (!colon) - break; - path = colon + 1; - } - free(paths); - - qsort(other_cmds->names, other_cmds->cnt, - sizeof(*other_cmds->names), cmdname_compare); - uniq(other_cmds); - } - free(exec_path); - exclude_cmds(other_cmds, main_cmds); -} - -void list_commands(const char *title, struct cmdnames *main_cmds, - struct cmdnames *other_cmds) -{ - unsigned int i, longest = 0; - - for (i = 0; i < main_cmds->cnt; i++) - if (longest < main_cmds->names[i]->len) - longest = main_cmds->names[i]->len; - for (i = 0; i < other_cmds->cnt; i++) - if (longest < other_cmds->names[i]->len) - longest = other_cmds->names[i]->len; - - if (main_cmds->cnt) { - char *exec_path = get_argv_exec_path(); - printf("available %s in '%s'\n", title, exec_path); - printf("----------------"); - mput_char('-', strlen(title) + strlen(exec_path)); - putchar('\n'); - pretty_print_string_list(main_cmds, longest); - putchar('\n'); - free(exec_path); - } - - if (other_cmds->cnt) { - printf("%s available from elsewhere on your $PATH\n", title); - printf("---------------------------------------"); - mput_char('-', strlen(title)); - putchar('\n'); - pretty_print_string_list(other_cmds, longest); - putchar('\n'); - } -} - -int is_in_cmdlist(struct cmdnames *c, const char *s) -{ - unsigned int i; - - for (i = 0; i < c->cnt; i++) - if (!strcmp(s, c->names[i]->name)) - return 1; - return 0; -} -- cgit