186470930SIngo Molnar /* 25f9273d6SNamhyung Kim * config.c 35f9273d6SNamhyung Kim * 45f9273d6SNamhyung Kim * Helper functions for parsing config items. 55f9273d6SNamhyung Kim * Originally copied from GIT source. 686470930SIngo Molnar * 786470930SIngo Molnar * Copyright (C) Linus Torvalds, 2005 886470930SIngo Molnar * Copyright (C) Johannes Schindelin, 2005 986470930SIngo Molnar * 1086470930SIngo Molnar */ 1186470930SIngo Molnar #include "util.h" 1286470930SIngo Molnar #include "cache.h" 134b6ab94eSJosh Poimboeuf #include <subcmd/exec-cmd.h> 140b93da17SNamhyung Kim #include "util/hist.h" /* perf_hist_config */ 15aa61fd05SWang Nan #include "util/llvm-utils.h" /* perf_llvm_config */ 1620105ca1STaeung Song #include "config.h" 1786470930SIngo Molnar 1886470930SIngo Molnar #define MAXNAME (256) 1986470930SIngo Molnar 2045de34bbSStephane Eranian #define DEBUG_CACHE_DIR ".debug" 2145de34bbSStephane Eranian 2245de34bbSStephane Eranian 2345de34bbSStephane Eranian char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */ 2445de34bbSStephane Eranian 2586470930SIngo Molnar static FILE *config_file; 2686470930SIngo Molnar static const char *config_file_name; 2786470930SIngo Molnar static int config_linenr; 2886470930SIngo Molnar static int config_file_eof; 2986470930SIngo Molnar 30c7ac2417STaeung Song const char *config_exclusive_filename; 3186470930SIngo Molnar 3286470930SIngo Molnar static int get_next_char(void) 3386470930SIngo Molnar { 3486470930SIngo Molnar int c; 3586470930SIngo Molnar FILE *f; 3686470930SIngo Molnar 3786470930SIngo Molnar c = '\n'; 3886470930SIngo Molnar if ((f = config_file) != NULL) { 3986470930SIngo Molnar c = fgetc(f); 4086470930SIngo Molnar if (c == '\r') { 4186470930SIngo Molnar /* DOS like systems */ 4286470930SIngo Molnar c = fgetc(f); 4386470930SIngo Molnar if (c != '\n') { 4486470930SIngo Molnar ungetc(c, f); 4586470930SIngo Molnar c = '\r'; 4686470930SIngo Molnar } 4786470930SIngo Molnar } 4886470930SIngo Molnar if (c == '\n') 4986470930SIngo Molnar config_linenr++; 5086470930SIngo Molnar if (c == EOF) { 5186470930SIngo Molnar config_file_eof = 1; 5286470930SIngo Molnar c = '\n'; 5386470930SIngo Molnar } 5486470930SIngo Molnar } 5586470930SIngo Molnar return c; 5686470930SIngo Molnar } 5786470930SIngo Molnar 5886470930SIngo Molnar static char *parse_value(void) 5986470930SIngo Molnar { 6086470930SIngo Molnar static char value[1024]; 61f37a291cSIngo Molnar int quote = 0, comment = 0, space = 0; 62f37a291cSIngo Molnar size_t len = 0; 6386470930SIngo Molnar 6486470930SIngo Molnar for (;;) { 6586470930SIngo Molnar int c = get_next_char(); 66f37a291cSIngo Molnar 6786470930SIngo Molnar if (len >= sizeof(value) - 1) 6886470930SIngo Molnar return NULL; 6986470930SIngo Molnar if (c == '\n') { 7086470930SIngo Molnar if (quote) 7186470930SIngo Molnar return NULL; 7286470930SIngo Molnar value[len] = 0; 7386470930SIngo Molnar return value; 7486470930SIngo Molnar } 7586470930SIngo Molnar if (comment) 7686470930SIngo Molnar continue; 7786470930SIngo Molnar if (isspace(c) && !quote) { 7886470930SIngo Molnar space = 1; 7986470930SIngo Molnar continue; 8086470930SIngo Molnar } 8186470930SIngo Molnar if (!quote) { 8286470930SIngo Molnar if (c == ';' || c == '#') { 8386470930SIngo Molnar comment = 1; 8486470930SIngo Molnar continue; 8586470930SIngo Molnar } 8686470930SIngo Molnar } 8786470930SIngo Molnar if (space) { 8886470930SIngo Molnar if (len) 8986470930SIngo Molnar value[len++] = ' '; 9086470930SIngo Molnar space = 0; 9186470930SIngo Molnar } 9286470930SIngo Molnar if (c == '\\') { 9386470930SIngo Molnar c = get_next_char(); 9486470930SIngo Molnar switch (c) { 9586470930SIngo Molnar case '\n': 9686470930SIngo Molnar continue; 9786470930SIngo Molnar case 't': 9886470930SIngo Molnar c = '\t'; 9986470930SIngo Molnar break; 10086470930SIngo Molnar case 'b': 10186470930SIngo Molnar c = '\b'; 10286470930SIngo Molnar break; 10386470930SIngo Molnar case 'n': 10486470930SIngo Molnar c = '\n'; 10586470930SIngo Molnar break; 10686470930SIngo Molnar /* Some characters escape as themselves */ 10786470930SIngo Molnar case '\\': case '"': 10886470930SIngo Molnar break; 10986470930SIngo Molnar /* Reject unknown escape sequences */ 11086470930SIngo Molnar default: 11186470930SIngo Molnar return NULL; 11286470930SIngo Molnar } 11386470930SIngo Molnar value[len++] = c; 11486470930SIngo Molnar continue; 11586470930SIngo Molnar } 11686470930SIngo Molnar if (c == '"') { 11786470930SIngo Molnar quote = 1-quote; 11886470930SIngo Molnar continue; 11986470930SIngo Molnar } 12086470930SIngo Molnar value[len++] = c; 12186470930SIngo Molnar } 12286470930SIngo Molnar } 12386470930SIngo Molnar 12486470930SIngo Molnar static inline int iskeychar(int c) 12586470930SIngo Molnar { 1268dc7c651SArnaldo Carvalho de Melo return isalnum(c) || c == '-' || c == '_'; 12786470930SIngo Molnar } 12886470930SIngo Molnar 12986470930SIngo Molnar static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) 13086470930SIngo Molnar { 13186470930SIngo Molnar int c; 13286470930SIngo Molnar char *value; 13386470930SIngo Molnar 13486470930SIngo Molnar /* Get the full name */ 13586470930SIngo Molnar for (;;) { 13686470930SIngo Molnar c = get_next_char(); 13786470930SIngo Molnar if (config_file_eof) 13886470930SIngo Molnar break; 13986470930SIngo Molnar if (!iskeychar(c)) 14086470930SIngo Molnar break; 14145de34bbSStephane Eranian name[len++] = c; 14286470930SIngo Molnar if (len >= MAXNAME) 14386470930SIngo Molnar return -1; 14486470930SIngo Molnar } 14586470930SIngo Molnar name[len] = 0; 14686470930SIngo Molnar while (c == ' ' || c == '\t') 14786470930SIngo Molnar c = get_next_char(); 14886470930SIngo Molnar 14986470930SIngo Molnar value = NULL; 15086470930SIngo Molnar if (c != '\n') { 15186470930SIngo Molnar if (c != '=') 15286470930SIngo Molnar return -1; 15386470930SIngo Molnar value = parse_value(); 15486470930SIngo Molnar if (!value) 15586470930SIngo Molnar return -1; 15686470930SIngo Molnar } 15786470930SIngo Molnar return fn(name, value, data); 15886470930SIngo Molnar } 15986470930SIngo Molnar 16086470930SIngo Molnar static int get_extended_base_var(char *name, int baselen, int c) 16186470930SIngo Molnar { 16286470930SIngo Molnar do { 16386470930SIngo Molnar if (c == '\n') 16486470930SIngo Molnar return -1; 16586470930SIngo Molnar c = get_next_char(); 16686470930SIngo Molnar } while (isspace(c)); 16786470930SIngo Molnar 16886470930SIngo Molnar /* We require the format to be '[base "extension"]' */ 16986470930SIngo Molnar if (c != '"') 17086470930SIngo Molnar return -1; 17186470930SIngo Molnar name[baselen++] = '.'; 17286470930SIngo Molnar 17386470930SIngo Molnar for (;;) { 17483a0944fSIngo Molnar int ch = get_next_char(); 17583a0944fSIngo Molnar 17683a0944fSIngo Molnar if (ch == '\n') 17786470930SIngo Molnar return -1; 17883a0944fSIngo Molnar if (ch == '"') 17986470930SIngo Molnar break; 18083a0944fSIngo Molnar if (ch == '\\') { 18183a0944fSIngo Molnar ch = get_next_char(); 18283a0944fSIngo Molnar if (ch == '\n') 18386470930SIngo Molnar return -1; 18486470930SIngo Molnar } 18583a0944fSIngo Molnar name[baselen++] = ch; 18686470930SIngo Molnar if (baselen > MAXNAME / 2) 18786470930SIngo Molnar return -1; 18886470930SIngo Molnar } 18986470930SIngo Molnar 19086470930SIngo Molnar /* Final ']' */ 19186470930SIngo Molnar if (get_next_char() != ']') 19286470930SIngo Molnar return -1; 19386470930SIngo Molnar return baselen; 19486470930SIngo Molnar } 19586470930SIngo Molnar 19686470930SIngo Molnar static int get_base_var(char *name) 19786470930SIngo Molnar { 19886470930SIngo Molnar int baselen = 0; 19986470930SIngo Molnar 20086470930SIngo Molnar for (;;) { 20186470930SIngo Molnar int c = get_next_char(); 20286470930SIngo Molnar if (config_file_eof) 20386470930SIngo Molnar return -1; 20486470930SIngo Molnar if (c == ']') 20586470930SIngo Molnar return baselen; 20686470930SIngo Molnar if (isspace(c)) 20786470930SIngo Molnar return get_extended_base_var(name, baselen, c); 20886470930SIngo Molnar if (!iskeychar(c) && c != '.') 20986470930SIngo Molnar return -1; 21086470930SIngo Molnar if (baselen > MAXNAME / 2) 21186470930SIngo Molnar return -1; 21286470930SIngo Molnar name[baselen++] = tolower(c); 21386470930SIngo Molnar } 21486470930SIngo Molnar } 21586470930SIngo Molnar 21686470930SIngo Molnar static int perf_parse_file(config_fn_t fn, void *data) 21786470930SIngo Molnar { 21886470930SIngo Molnar int comment = 0; 21986470930SIngo Molnar int baselen = 0; 22086470930SIngo Molnar static char var[MAXNAME]; 22186470930SIngo Molnar 22286470930SIngo Molnar /* U+FEFF Byte Order Mark in UTF8 */ 22386470930SIngo Molnar static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; 22486470930SIngo Molnar const unsigned char *bomptr = utf8_bom; 22586470930SIngo Molnar 22686470930SIngo Molnar for (;;) { 22749757c9cSJiri Olsa int line, c = get_next_char(); 22849757c9cSJiri Olsa 22986470930SIngo Molnar if (bomptr && *bomptr) { 23086470930SIngo Molnar /* We are at the file beginning; skip UTF8-encoded BOM 23186470930SIngo Molnar * if present. Sane editors won't put this in on their 23286470930SIngo Molnar * own, but e.g. Windows Notepad will do it happily. */ 23386470930SIngo Molnar if ((unsigned char) c == *bomptr) { 23486470930SIngo Molnar bomptr++; 23586470930SIngo Molnar continue; 23686470930SIngo Molnar } else { 23786470930SIngo Molnar /* Do not tolerate partial BOM. */ 23886470930SIngo Molnar if (bomptr != utf8_bom) 23986470930SIngo Molnar break; 24086470930SIngo Molnar /* No BOM at file beginning. Cool. */ 24186470930SIngo Molnar bomptr = NULL; 24286470930SIngo Molnar } 24386470930SIngo Molnar } 24486470930SIngo Molnar if (c == '\n') { 24586470930SIngo Molnar if (config_file_eof) 24686470930SIngo Molnar return 0; 24786470930SIngo Molnar comment = 0; 24886470930SIngo Molnar continue; 24986470930SIngo Molnar } 25086470930SIngo Molnar if (comment || isspace(c)) 25186470930SIngo Molnar continue; 25286470930SIngo Molnar if (c == '#' || c == ';') { 25386470930SIngo Molnar comment = 1; 25486470930SIngo Molnar continue; 25586470930SIngo Molnar } 25686470930SIngo Molnar if (c == '[') { 25786470930SIngo Molnar baselen = get_base_var(var); 25886470930SIngo Molnar if (baselen <= 0) 25986470930SIngo Molnar break; 26086470930SIngo Molnar var[baselen++] = '.'; 26186470930SIngo Molnar var[baselen] = 0; 26286470930SIngo Molnar continue; 26386470930SIngo Molnar } 26486470930SIngo Molnar if (!isalpha(c)) 26586470930SIngo Molnar break; 26686470930SIngo Molnar var[baselen] = tolower(c); 26749757c9cSJiri Olsa 26849757c9cSJiri Olsa /* 26949757c9cSJiri Olsa * The get_value function might or might not reach the '\n', 27049757c9cSJiri Olsa * so saving the current line number for error reporting. 27149757c9cSJiri Olsa */ 27249757c9cSJiri Olsa line = config_linenr; 27349757c9cSJiri Olsa if (get_value(fn, data, var, baselen+1) < 0) { 27449757c9cSJiri Olsa config_linenr = line; 27586470930SIngo Molnar break; 27686470930SIngo Molnar } 27749757c9cSJiri Olsa } 278*78f71c99STaeung Song pr_err("bad config file line %d in %s\n", config_linenr, config_file_name); 279*78f71c99STaeung Song return -1; 28086470930SIngo Molnar } 28186470930SIngo Molnar 28286470930SIngo Molnar static int parse_unit_factor(const char *end, unsigned long *val) 28386470930SIngo Molnar { 28486470930SIngo Molnar if (!*end) 28586470930SIngo Molnar return 1; 28686470930SIngo Molnar else if (!strcasecmp(end, "k")) { 28786470930SIngo Molnar *val *= 1024; 28886470930SIngo Molnar return 1; 28986470930SIngo Molnar } 29086470930SIngo Molnar else if (!strcasecmp(end, "m")) { 29186470930SIngo Molnar *val *= 1024 * 1024; 29286470930SIngo Molnar return 1; 29386470930SIngo Molnar } 29486470930SIngo Molnar else if (!strcasecmp(end, "g")) { 29586470930SIngo Molnar *val *= 1024 * 1024 * 1024; 29686470930SIngo Molnar return 1; 29786470930SIngo Molnar } 29886470930SIngo Molnar return 0; 29986470930SIngo Molnar } 30086470930SIngo Molnar 30194c0655fSJiri Olsa static int perf_parse_llong(const char *value, long long *ret) 30294c0655fSJiri Olsa { 30394c0655fSJiri Olsa if (value && *value) { 30494c0655fSJiri Olsa char *end; 30594c0655fSJiri Olsa long long val = strtoll(value, &end, 0); 30694c0655fSJiri Olsa unsigned long factor = 1; 30794c0655fSJiri Olsa 30894c0655fSJiri Olsa if (!parse_unit_factor(end, &factor)) 30994c0655fSJiri Olsa return 0; 31094c0655fSJiri Olsa *ret = val * factor; 31194c0655fSJiri Olsa return 1; 31294c0655fSJiri Olsa } 31394c0655fSJiri Olsa return 0; 31494c0655fSJiri Olsa } 31594c0655fSJiri Olsa 31686470930SIngo Molnar static int perf_parse_long(const char *value, long *ret) 31786470930SIngo Molnar { 31886470930SIngo Molnar if (value && *value) { 31986470930SIngo Molnar char *end; 32086470930SIngo Molnar long val = strtol(value, &end, 0); 32186470930SIngo Molnar unsigned long factor = 1; 32286470930SIngo Molnar if (!parse_unit_factor(end, &factor)) 32386470930SIngo Molnar return 0; 32486470930SIngo Molnar *ret = val * factor; 32586470930SIngo Molnar return 1; 32686470930SIngo Molnar } 32786470930SIngo Molnar return 0; 32886470930SIngo Molnar } 32986470930SIngo Molnar 33086470930SIngo Molnar static void die_bad_config(const char *name) 33186470930SIngo Molnar { 33286470930SIngo Molnar if (config_file_name) 33386470930SIngo Molnar die("bad config value for '%s' in %s", name, config_file_name); 33486470930SIngo Molnar die("bad config value for '%s'", name); 33586470930SIngo Molnar } 33686470930SIngo Molnar 33794c0655fSJiri Olsa u64 perf_config_u64(const char *name, const char *value) 33894c0655fSJiri Olsa { 33994c0655fSJiri Olsa long long ret = 0; 34094c0655fSJiri Olsa 34194c0655fSJiri Olsa if (!perf_parse_llong(value, &ret)) 34294c0655fSJiri Olsa die_bad_config(name); 34394c0655fSJiri Olsa return (u64) ret; 34494c0655fSJiri Olsa } 34594c0655fSJiri Olsa 34686470930SIngo Molnar int perf_config_int(const char *name, const char *value) 34786470930SIngo Molnar { 34886470930SIngo Molnar long ret = 0; 34986470930SIngo Molnar if (!perf_parse_long(value, &ret)) 35086470930SIngo Molnar die_bad_config(name); 35186470930SIngo Molnar return ret; 35286470930SIngo Molnar } 35386470930SIngo Molnar 354a41794cdSArnaldo Carvalho de Melo static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 35586470930SIngo Molnar { 35686470930SIngo Molnar *is_bool = 1; 35786470930SIngo Molnar if (!value) 35886470930SIngo Molnar return 1; 35986470930SIngo Molnar if (!*value) 36086470930SIngo Molnar return 0; 36186470930SIngo Molnar if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) 36286470930SIngo Molnar return 1; 36386470930SIngo Molnar if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 36486470930SIngo Molnar return 0; 36586470930SIngo Molnar *is_bool = 0; 36686470930SIngo Molnar return perf_config_int(name, value); 36786470930SIngo Molnar } 36886470930SIngo Molnar 36986470930SIngo Molnar int perf_config_bool(const char *name, const char *value) 37086470930SIngo Molnar { 37186470930SIngo Molnar int discard; 37286470930SIngo Molnar return !!perf_config_bool_or_int(name, value, &discard); 37386470930SIngo Molnar } 37486470930SIngo Molnar 37545de34bbSStephane Eranian const char *perf_config_dirname(const char *name, const char *value) 37645de34bbSStephane Eranian { 37745de34bbSStephane Eranian if (!name) 37845de34bbSStephane Eranian return NULL; 37945de34bbSStephane Eranian return value; 38045de34bbSStephane Eranian } 38145de34bbSStephane Eranian 3829cb5987cSTaeung Song static int perf_buildid_config(const char *var, const char *value) 3839cb5987cSTaeung Song { 3849cb5987cSTaeung Song /* same dir for all commands */ 3859cb5987cSTaeung Song if (!strcmp(var, "buildid.dir")) { 386d8e28654SVinson Lee const char *dir = perf_config_dirname(var, value); 3879cb5987cSTaeung Song 388d8e28654SVinson Lee if (!dir) 3899cb5987cSTaeung Song return -1; 390d8e28654SVinson Lee strncpy(buildid_dir, dir, MAXPATHLEN-1); 3919cb5987cSTaeung Song buildid_dir[MAXPATHLEN-1] = '\0'; 3929cb5987cSTaeung Song } 3939cb5987cSTaeung Song 3949cb5987cSTaeung Song return 0; 3959cb5987cSTaeung Song } 3969cb5987cSTaeung Song 3971d037ca1SIrina Tirdea static int perf_default_core_config(const char *var __maybe_unused, 3981d037ca1SIrina Tirdea const char *value __maybe_unused) 39986470930SIngo Molnar { 400395cf969SPaul Bolle /* Add other config variables here. */ 40186470930SIngo Molnar return 0; 40286470930SIngo Molnar } 40386470930SIngo Molnar 404c8302367SJiri Olsa static int perf_ui_config(const char *var, const char *value) 405c8302367SJiri Olsa { 406c8302367SJiri Olsa /* Add other config variables here. */ 407c8302367SJiri Olsa if (!strcmp(var, "ui.show-headers")) { 408c8302367SJiri Olsa symbol_conf.show_hist_headers = perf_config_bool(var, value); 409c8302367SJiri Olsa return 0; 410c8302367SJiri Olsa } 411c8302367SJiri Olsa return 0; 412c8302367SJiri Olsa } 413c8302367SJiri Olsa 4141d037ca1SIrina Tirdea int perf_default_config(const char *var, const char *value, 4151d037ca1SIrina Tirdea void *dummy __maybe_unused) 41686470930SIngo Molnar { 41786470930SIngo Molnar if (!prefixcmp(var, "core.")) 41886470930SIngo Molnar return perf_default_core_config(var, value); 41986470930SIngo Molnar 4200b93da17SNamhyung Kim if (!prefixcmp(var, "hist.")) 4210b93da17SNamhyung Kim return perf_hist_config(var, value); 4220b93da17SNamhyung Kim 423c8302367SJiri Olsa if (!prefixcmp(var, "ui.")) 424c8302367SJiri Olsa return perf_ui_config(var, value); 425c8302367SJiri Olsa 4262b9240caSNamhyung Kim if (!prefixcmp(var, "call-graph.")) 4272b9240caSNamhyung Kim return perf_callchain_config(var, value); 4282b9240caSNamhyung Kim 429aa61fd05SWang Nan if (!prefixcmp(var, "llvm.")) 430aa61fd05SWang Nan return perf_llvm_config(var, value); 431aa61fd05SWang Nan 4329cb5987cSTaeung Song if (!prefixcmp(var, "buildid.")) 4339cb5987cSTaeung Song return perf_buildid_config(var, value); 4349cb5987cSTaeung Song 435395cf969SPaul Bolle /* Add other config variables here. */ 43686470930SIngo Molnar return 0; 43786470930SIngo Molnar } 43886470930SIngo Molnar 439a41794cdSArnaldo Carvalho de Melo static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 44086470930SIngo Molnar { 44186470930SIngo Molnar int ret; 44286470930SIngo Molnar FILE *f = fopen(filename, "r"); 44386470930SIngo Molnar 44486470930SIngo Molnar ret = -1; 44586470930SIngo Molnar if (f) { 44686470930SIngo Molnar config_file = f; 44786470930SIngo Molnar config_file_name = filename; 44886470930SIngo Molnar config_linenr = 1; 44986470930SIngo Molnar config_file_eof = 0; 45086470930SIngo Molnar ret = perf_parse_file(fn, data); 45186470930SIngo Molnar fclose(f); 45286470930SIngo Molnar config_file_name = NULL; 45386470930SIngo Molnar } 45486470930SIngo Molnar return ret; 45586470930SIngo Molnar } 45686470930SIngo Molnar 457c7ac2417STaeung Song const char *perf_etc_perfconfig(void) 45886470930SIngo Molnar { 45986470930SIngo Molnar static const char *system_wide; 46086470930SIngo Molnar if (!system_wide) 46186470930SIngo Molnar system_wide = system_path(ETC_PERFCONFIG); 46286470930SIngo Molnar return system_wide; 46386470930SIngo Molnar } 46486470930SIngo Molnar 46586470930SIngo Molnar static int perf_env_bool(const char *k, int def) 46686470930SIngo Molnar { 46786470930SIngo Molnar const char *v = getenv(k); 46886470930SIngo Molnar return v ? perf_config_bool(k, v) : def; 46986470930SIngo Molnar } 47086470930SIngo Molnar 471a41794cdSArnaldo Carvalho de Melo static int perf_config_system(void) 47286470930SIngo Molnar { 47386470930SIngo Molnar return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 47486470930SIngo Molnar } 47586470930SIngo Molnar 476a41794cdSArnaldo Carvalho de Melo static int perf_config_global(void) 47786470930SIngo Molnar { 47886470930SIngo Molnar return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 47986470930SIngo Molnar } 48086470930SIngo Molnar 48186470930SIngo Molnar int perf_config(config_fn_t fn, void *data) 48286470930SIngo Molnar { 483*78f71c99STaeung Song int ret = -1; 48486470930SIngo Molnar const char *home = NULL; 48586470930SIngo Molnar 48686470930SIngo Molnar /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 48786470930SIngo Molnar if (config_exclusive_filename) 48886470930SIngo Molnar return perf_config_from_file(fn, config_exclusive_filename, data); 48986470930SIngo Molnar if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 490*78f71c99STaeung Song if (perf_config_from_file(fn, perf_etc_perfconfig(), data) < 0) 491*78f71c99STaeung Song goto out; 49286470930SIngo Molnar } 49386470930SIngo Molnar 49486470930SIngo Molnar home = getenv("HOME"); 49586470930SIngo Molnar if (perf_config_global() && home) { 49686470930SIngo Molnar char *user_config = strdup(mkpath("%s/.perfconfig", home)); 497069e3725SArnaldo Carvalho de Melo struct stat st; 498069e3725SArnaldo Carvalho de Melo 499069e3725SArnaldo Carvalho de Melo if (user_config == NULL) { 500069e3725SArnaldo Carvalho de Melo warning("Not enough memory to process %s/.perfconfig, " 501069e3725SArnaldo Carvalho de Melo "ignoring it.", home); 502069e3725SArnaldo Carvalho de Melo goto out; 50386470930SIngo Molnar } 50486470930SIngo Molnar 505069e3725SArnaldo Carvalho de Melo if (stat(user_config, &st) < 0) 506069e3725SArnaldo Carvalho de Melo goto out_free; 507069e3725SArnaldo Carvalho de Melo 508069e3725SArnaldo Carvalho de Melo if (st.st_uid && (st.st_uid != geteuid())) { 509069e3725SArnaldo Carvalho de Melo warning("File %s not owned by current user or root, " 510069e3725SArnaldo Carvalho de Melo "ignoring it.", user_config); 511069e3725SArnaldo Carvalho de Melo goto out_free; 512069e3725SArnaldo Carvalho de Melo } 513069e3725SArnaldo Carvalho de Melo 514069e3725SArnaldo Carvalho de Melo if (!st.st_size) 515069e3725SArnaldo Carvalho de Melo goto out_free; 516069e3725SArnaldo Carvalho de Melo 517*78f71c99STaeung Song ret = perf_config_from_file(fn, user_config, data); 518*78f71c99STaeung Song 519069e3725SArnaldo Carvalho de Melo out_free: 520069e3725SArnaldo Carvalho de Melo free(user_config); 521069e3725SArnaldo Carvalho de Melo } 522069e3725SArnaldo Carvalho de Melo out: 52386470930SIngo Molnar return ret; 52486470930SIngo Molnar } 52586470930SIngo Molnar 52620105ca1STaeung Song static struct perf_config_section *find_section(struct list_head *sections, 52720105ca1STaeung Song const char *section_name) 52820105ca1STaeung Song { 52920105ca1STaeung Song struct perf_config_section *section; 53020105ca1STaeung Song 53120105ca1STaeung Song list_for_each_entry(section, sections, node) 53220105ca1STaeung Song if (!strcmp(section->name, section_name)) 53320105ca1STaeung Song return section; 53420105ca1STaeung Song 53520105ca1STaeung Song return NULL; 53620105ca1STaeung Song } 53720105ca1STaeung Song 53820105ca1STaeung Song static struct perf_config_item *find_config_item(const char *name, 53920105ca1STaeung Song struct perf_config_section *section) 54020105ca1STaeung Song { 54120105ca1STaeung Song struct perf_config_item *item; 54220105ca1STaeung Song 54320105ca1STaeung Song list_for_each_entry(item, §ion->items, node) 54420105ca1STaeung Song if (!strcmp(item->name, name)) 54520105ca1STaeung Song return item; 54620105ca1STaeung Song 54720105ca1STaeung Song return NULL; 54820105ca1STaeung Song } 54920105ca1STaeung Song 55020105ca1STaeung Song static struct perf_config_section *add_section(struct list_head *sections, 55120105ca1STaeung Song const char *section_name) 55220105ca1STaeung Song { 55320105ca1STaeung Song struct perf_config_section *section = zalloc(sizeof(*section)); 55420105ca1STaeung Song 55520105ca1STaeung Song if (!section) 55620105ca1STaeung Song return NULL; 55720105ca1STaeung Song 55820105ca1STaeung Song INIT_LIST_HEAD(§ion->items); 55920105ca1STaeung Song section->name = strdup(section_name); 56020105ca1STaeung Song if (!section->name) { 56120105ca1STaeung Song pr_debug("%s: strdup failed\n", __func__); 56220105ca1STaeung Song free(section); 56320105ca1STaeung Song return NULL; 56420105ca1STaeung Song } 56520105ca1STaeung Song 56620105ca1STaeung Song list_add_tail(§ion->node, sections); 56720105ca1STaeung Song return section; 56820105ca1STaeung Song } 56920105ca1STaeung Song 57020105ca1STaeung Song static struct perf_config_item *add_config_item(struct perf_config_section *section, 57120105ca1STaeung Song const char *name) 57220105ca1STaeung Song { 57320105ca1STaeung Song struct perf_config_item *item = zalloc(sizeof(*item)); 57420105ca1STaeung Song 57520105ca1STaeung Song if (!item) 57620105ca1STaeung Song return NULL; 57720105ca1STaeung Song 57820105ca1STaeung Song item->name = strdup(name); 57920105ca1STaeung Song if (!item->name) { 58020105ca1STaeung Song pr_debug("%s: strdup failed\n", __func__); 58120105ca1STaeung Song free(item); 58220105ca1STaeung Song return NULL; 58320105ca1STaeung Song } 58420105ca1STaeung Song 58520105ca1STaeung Song list_add_tail(&item->node, §ion->items); 58620105ca1STaeung Song return item; 58720105ca1STaeung Song } 58820105ca1STaeung Song 58920105ca1STaeung Song static int set_value(struct perf_config_item *item, const char *value) 59020105ca1STaeung Song { 59120105ca1STaeung Song char *val = strdup(value); 59220105ca1STaeung Song 59320105ca1STaeung Song if (!val) 59420105ca1STaeung Song return -1; 59520105ca1STaeung Song 59620105ca1STaeung Song zfree(&item->value); 59720105ca1STaeung Song item->value = val; 59820105ca1STaeung Song return 0; 59920105ca1STaeung Song } 60020105ca1STaeung Song 60120105ca1STaeung Song static int collect_config(const char *var, const char *value, 60220105ca1STaeung Song void *perf_config_set) 60320105ca1STaeung Song { 60420105ca1STaeung Song int ret = -1; 60520105ca1STaeung Song char *ptr, *key; 60620105ca1STaeung Song char *section_name, *name; 60720105ca1STaeung Song struct perf_config_section *section = NULL; 60820105ca1STaeung Song struct perf_config_item *item = NULL; 60920105ca1STaeung Song struct perf_config_set *set = perf_config_set; 61020105ca1STaeung Song struct list_head *sections = &set->sections; 61120105ca1STaeung Song 61220105ca1STaeung Song key = ptr = strdup(var); 61320105ca1STaeung Song if (!key) { 61420105ca1STaeung Song pr_debug("%s: strdup failed\n", __func__); 61520105ca1STaeung Song return -1; 61620105ca1STaeung Song } 61720105ca1STaeung Song 61820105ca1STaeung Song section_name = strsep(&ptr, "."); 61920105ca1STaeung Song name = ptr; 62020105ca1STaeung Song if (name == NULL || value == NULL) 62120105ca1STaeung Song goto out_free; 62220105ca1STaeung Song 62320105ca1STaeung Song section = find_section(sections, section_name); 62420105ca1STaeung Song if (!section) { 62520105ca1STaeung Song section = add_section(sections, section_name); 62620105ca1STaeung Song if (!section) 62720105ca1STaeung Song goto out_free; 62820105ca1STaeung Song } 62920105ca1STaeung Song 63020105ca1STaeung Song item = find_config_item(name, section); 63120105ca1STaeung Song if (!item) { 63220105ca1STaeung Song item = add_config_item(section, name); 63320105ca1STaeung Song if (!item) 63420105ca1STaeung Song goto out_free; 63520105ca1STaeung Song } 63620105ca1STaeung Song 63720105ca1STaeung Song ret = set_value(item, value); 63820105ca1STaeung Song return ret; 63920105ca1STaeung Song 64020105ca1STaeung Song out_free: 64120105ca1STaeung Song free(key); 64220105ca1STaeung Song perf_config_set__delete(set); 64320105ca1STaeung Song return -1; 64420105ca1STaeung Song } 64520105ca1STaeung Song 64620105ca1STaeung Song struct perf_config_set *perf_config_set__new(void) 64720105ca1STaeung Song { 64820105ca1STaeung Song struct perf_config_set *set = zalloc(sizeof(*set)); 64920105ca1STaeung Song 65020105ca1STaeung Song if (set) { 65120105ca1STaeung Song INIT_LIST_HEAD(&set->sections); 65220105ca1STaeung Song perf_config(collect_config, set); 65320105ca1STaeung Song } 65420105ca1STaeung Song 65520105ca1STaeung Song return set; 65620105ca1STaeung Song } 65720105ca1STaeung Song 65820105ca1STaeung Song static void perf_config_item__delete(struct perf_config_item *item) 65920105ca1STaeung Song { 66020105ca1STaeung Song zfree(&item->name); 66120105ca1STaeung Song zfree(&item->value); 66220105ca1STaeung Song free(item); 66320105ca1STaeung Song } 66420105ca1STaeung Song 66520105ca1STaeung Song static void perf_config_section__purge(struct perf_config_section *section) 66620105ca1STaeung Song { 66720105ca1STaeung Song struct perf_config_item *item, *tmp; 66820105ca1STaeung Song 66920105ca1STaeung Song list_for_each_entry_safe(item, tmp, §ion->items, node) { 67020105ca1STaeung Song list_del_init(&item->node); 67120105ca1STaeung Song perf_config_item__delete(item); 67220105ca1STaeung Song } 67320105ca1STaeung Song } 67420105ca1STaeung Song 67520105ca1STaeung Song static void perf_config_section__delete(struct perf_config_section *section) 67620105ca1STaeung Song { 67720105ca1STaeung Song perf_config_section__purge(section); 67820105ca1STaeung Song zfree(§ion->name); 67920105ca1STaeung Song free(section); 68020105ca1STaeung Song } 68120105ca1STaeung Song 68220105ca1STaeung Song static void perf_config_set__purge(struct perf_config_set *set) 68320105ca1STaeung Song { 68420105ca1STaeung Song struct perf_config_section *section, *tmp; 68520105ca1STaeung Song 68620105ca1STaeung Song list_for_each_entry_safe(section, tmp, &set->sections, node) { 68720105ca1STaeung Song list_del_init(§ion->node); 68820105ca1STaeung Song perf_config_section__delete(section); 68920105ca1STaeung Song } 69020105ca1STaeung Song } 69120105ca1STaeung Song 69220105ca1STaeung Song void perf_config_set__delete(struct perf_config_set *set) 69320105ca1STaeung Song { 69420105ca1STaeung Song perf_config_set__purge(set); 69520105ca1STaeung Song free(set); 69620105ca1STaeung Song } 69720105ca1STaeung Song 69886470930SIngo Molnar /* 69986470930SIngo Molnar * Call this to report error for your variable that should not 70086470930SIngo Molnar * get a boolean value (i.e. "[my] var" means "true"). 70186470930SIngo Molnar */ 70286470930SIngo Molnar int config_error_nonbool(const char *var) 70386470930SIngo Molnar { 70486470930SIngo Molnar return error("Missing value for '%s'", var); 70586470930SIngo Molnar } 70645de34bbSStephane Eranian 70799ce8e9fSJiri Olsa void set_buildid_dir(const char *dir) 70845de34bbSStephane Eranian { 70999ce8e9fSJiri Olsa if (dir) 71099ce8e9fSJiri Olsa scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 71145de34bbSStephane Eranian 71245de34bbSStephane Eranian /* default to $HOME/.debug */ 71345de34bbSStephane Eranian if (buildid_dir[0] == '\0') { 71437194f44STaeung Song char *home = getenv("HOME"); 71537194f44STaeung Song 71637194f44STaeung Song if (home) { 71745de34bbSStephane Eranian snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 71837194f44STaeung Song home, DEBUG_CACHE_DIR); 71945de34bbSStephane Eranian } else { 72045de34bbSStephane Eranian strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 72145de34bbSStephane Eranian } 72245de34bbSStephane Eranian buildid_dir[MAXPATHLEN-1] = '\0'; 72345de34bbSStephane Eranian } 72445de34bbSStephane Eranian /* for communicating with external commands */ 72545de34bbSStephane Eranian setenv("PERF_BUILDID_DIR", buildid_dir, 1); 72645de34bbSStephane Eranian } 727