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" 1386470930SIngo Molnar #include "exec_cmd.h" 140b93da17SNamhyung Kim #include "util/hist.h" /* perf_hist_config */ 1586470930SIngo Molnar 1686470930SIngo Molnar #define MAXNAME (256) 1786470930SIngo Molnar 1845de34bbSStephane Eranian #define DEBUG_CACHE_DIR ".debug" 1945de34bbSStephane Eranian 2045de34bbSStephane Eranian 2145de34bbSStephane Eranian char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */ 2245de34bbSStephane Eranian 2386470930SIngo Molnar static FILE *config_file; 2486470930SIngo Molnar static const char *config_file_name; 2586470930SIngo Molnar static int config_linenr; 2686470930SIngo Molnar static int config_file_eof; 2786470930SIngo Molnar 28a41794cdSArnaldo Carvalho de Melo static const char *config_exclusive_filename; 2986470930SIngo Molnar 3086470930SIngo Molnar static int get_next_char(void) 3186470930SIngo Molnar { 3286470930SIngo Molnar int c; 3386470930SIngo Molnar FILE *f; 3486470930SIngo Molnar 3586470930SIngo Molnar c = '\n'; 3686470930SIngo Molnar if ((f = config_file) != NULL) { 3786470930SIngo Molnar c = fgetc(f); 3886470930SIngo Molnar if (c == '\r') { 3986470930SIngo Molnar /* DOS like systems */ 4086470930SIngo Molnar c = fgetc(f); 4186470930SIngo Molnar if (c != '\n') { 4286470930SIngo Molnar ungetc(c, f); 4386470930SIngo Molnar c = '\r'; 4486470930SIngo Molnar } 4586470930SIngo Molnar } 4686470930SIngo Molnar if (c == '\n') 4786470930SIngo Molnar config_linenr++; 4886470930SIngo Molnar if (c == EOF) { 4986470930SIngo Molnar config_file_eof = 1; 5086470930SIngo Molnar c = '\n'; 5186470930SIngo Molnar } 5286470930SIngo Molnar } 5386470930SIngo Molnar return c; 5486470930SIngo Molnar } 5586470930SIngo Molnar 5686470930SIngo Molnar static char *parse_value(void) 5786470930SIngo Molnar { 5886470930SIngo Molnar static char value[1024]; 59f37a291cSIngo Molnar int quote = 0, comment = 0, space = 0; 60f37a291cSIngo Molnar size_t len = 0; 6186470930SIngo Molnar 6286470930SIngo Molnar for (;;) { 6386470930SIngo Molnar int c = get_next_char(); 64f37a291cSIngo Molnar 6586470930SIngo Molnar if (len >= sizeof(value) - 1) 6686470930SIngo Molnar return NULL; 6786470930SIngo Molnar if (c == '\n') { 6886470930SIngo Molnar if (quote) 6986470930SIngo Molnar return NULL; 7086470930SIngo Molnar value[len] = 0; 7186470930SIngo Molnar return value; 7286470930SIngo Molnar } 7386470930SIngo Molnar if (comment) 7486470930SIngo Molnar continue; 7586470930SIngo Molnar if (isspace(c) && !quote) { 7686470930SIngo Molnar space = 1; 7786470930SIngo Molnar continue; 7886470930SIngo Molnar } 7986470930SIngo Molnar if (!quote) { 8086470930SIngo Molnar if (c == ';' || c == '#') { 8186470930SIngo Molnar comment = 1; 8286470930SIngo Molnar continue; 8386470930SIngo Molnar } 8486470930SIngo Molnar } 8586470930SIngo Molnar if (space) { 8686470930SIngo Molnar if (len) 8786470930SIngo Molnar value[len++] = ' '; 8886470930SIngo Molnar space = 0; 8986470930SIngo Molnar } 9086470930SIngo Molnar if (c == '\\') { 9186470930SIngo Molnar c = get_next_char(); 9286470930SIngo Molnar switch (c) { 9386470930SIngo Molnar case '\n': 9486470930SIngo Molnar continue; 9586470930SIngo Molnar case 't': 9686470930SIngo Molnar c = '\t'; 9786470930SIngo Molnar break; 9886470930SIngo Molnar case 'b': 9986470930SIngo Molnar c = '\b'; 10086470930SIngo Molnar break; 10186470930SIngo Molnar case 'n': 10286470930SIngo Molnar c = '\n'; 10386470930SIngo Molnar break; 10486470930SIngo Molnar /* Some characters escape as themselves */ 10586470930SIngo Molnar case '\\': case '"': 10686470930SIngo Molnar break; 10786470930SIngo Molnar /* Reject unknown escape sequences */ 10886470930SIngo Molnar default: 10986470930SIngo Molnar return NULL; 11086470930SIngo Molnar } 11186470930SIngo Molnar value[len++] = c; 11286470930SIngo Molnar continue; 11386470930SIngo Molnar } 11486470930SIngo Molnar if (c == '"') { 11586470930SIngo Molnar quote = 1-quote; 11686470930SIngo Molnar continue; 11786470930SIngo Molnar } 11886470930SIngo Molnar value[len++] = c; 11986470930SIngo Molnar } 12086470930SIngo Molnar } 12186470930SIngo Molnar 12286470930SIngo Molnar static inline int iskeychar(int c) 12386470930SIngo Molnar { 1248dc7c651SArnaldo Carvalho de Melo return isalnum(c) || c == '-' || c == '_'; 12586470930SIngo Molnar } 12686470930SIngo Molnar 12786470930SIngo Molnar static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) 12886470930SIngo Molnar { 12986470930SIngo Molnar int c; 13086470930SIngo Molnar char *value; 13186470930SIngo Molnar 13286470930SIngo Molnar /* Get the full name */ 13386470930SIngo Molnar for (;;) { 13486470930SIngo Molnar c = get_next_char(); 13586470930SIngo Molnar if (config_file_eof) 13686470930SIngo Molnar break; 13786470930SIngo Molnar if (!iskeychar(c)) 13886470930SIngo Molnar break; 13945de34bbSStephane Eranian name[len++] = c; 14086470930SIngo Molnar if (len >= MAXNAME) 14186470930SIngo Molnar return -1; 14286470930SIngo Molnar } 14386470930SIngo Molnar name[len] = 0; 14486470930SIngo Molnar while (c == ' ' || c == '\t') 14586470930SIngo Molnar c = get_next_char(); 14686470930SIngo Molnar 14786470930SIngo Molnar value = NULL; 14886470930SIngo Molnar if (c != '\n') { 14986470930SIngo Molnar if (c != '=') 15086470930SIngo Molnar return -1; 15186470930SIngo Molnar value = parse_value(); 15286470930SIngo Molnar if (!value) 15386470930SIngo Molnar return -1; 15486470930SIngo Molnar } 15586470930SIngo Molnar return fn(name, value, data); 15686470930SIngo Molnar } 15786470930SIngo Molnar 15886470930SIngo Molnar static int get_extended_base_var(char *name, int baselen, int c) 15986470930SIngo Molnar { 16086470930SIngo Molnar do { 16186470930SIngo Molnar if (c == '\n') 16286470930SIngo Molnar return -1; 16386470930SIngo Molnar c = get_next_char(); 16486470930SIngo Molnar } while (isspace(c)); 16586470930SIngo Molnar 16686470930SIngo Molnar /* We require the format to be '[base "extension"]' */ 16786470930SIngo Molnar if (c != '"') 16886470930SIngo Molnar return -1; 16986470930SIngo Molnar name[baselen++] = '.'; 17086470930SIngo Molnar 17186470930SIngo Molnar for (;;) { 17283a0944fSIngo Molnar int ch = get_next_char(); 17383a0944fSIngo Molnar 17483a0944fSIngo Molnar if (ch == '\n') 17586470930SIngo Molnar return -1; 17683a0944fSIngo Molnar if (ch == '"') 17786470930SIngo Molnar break; 17883a0944fSIngo Molnar if (ch == '\\') { 17983a0944fSIngo Molnar ch = get_next_char(); 18083a0944fSIngo Molnar if (ch == '\n') 18186470930SIngo Molnar return -1; 18286470930SIngo Molnar } 18383a0944fSIngo Molnar name[baselen++] = ch; 18486470930SIngo Molnar if (baselen > MAXNAME / 2) 18586470930SIngo Molnar return -1; 18686470930SIngo Molnar } 18786470930SIngo Molnar 18886470930SIngo Molnar /* Final ']' */ 18986470930SIngo Molnar if (get_next_char() != ']') 19086470930SIngo Molnar return -1; 19186470930SIngo Molnar return baselen; 19286470930SIngo Molnar } 19386470930SIngo Molnar 19486470930SIngo Molnar static int get_base_var(char *name) 19586470930SIngo Molnar { 19686470930SIngo Molnar int baselen = 0; 19786470930SIngo Molnar 19886470930SIngo Molnar for (;;) { 19986470930SIngo Molnar int c = get_next_char(); 20086470930SIngo Molnar if (config_file_eof) 20186470930SIngo Molnar return -1; 20286470930SIngo Molnar if (c == ']') 20386470930SIngo Molnar return baselen; 20486470930SIngo Molnar if (isspace(c)) 20586470930SIngo Molnar return get_extended_base_var(name, baselen, c); 20686470930SIngo Molnar if (!iskeychar(c) && c != '.') 20786470930SIngo Molnar return -1; 20886470930SIngo Molnar if (baselen > MAXNAME / 2) 20986470930SIngo Molnar return -1; 21086470930SIngo Molnar name[baselen++] = tolower(c); 21186470930SIngo Molnar } 21286470930SIngo Molnar } 21386470930SIngo Molnar 21486470930SIngo Molnar static int perf_parse_file(config_fn_t fn, void *data) 21586470930SIngo Molnar { 21686470930SIngo Molnar int comment = 0; 21786470930SIngo Molnar int baselen = 0; 21886470930SIngo Molnar static char var[MAXNAME]; 21986470930SIngo Molnar 22086470930SIngo Molnar /* U+FEFF Byte Order Mark in UTF8 */ 22186470930SIngo Molnar static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; 22286470930SIngo Molnar const unsigned char *bomptr = utf8_bom; 22386470930SIngo Molnar 22486470930SIngo Molnar for (;;) { 22549757c9cSJiri Olsa int line, c = get_next_char(); 22649757c9cSJiri Olsa 22786470930SIngo Molnar if (bomptr && *bomptr) { 22886470930SIngo Molnar /* We are at the file beginning; skip UTF8-encoded BOM 22986470930SIngo Molnar * if present. Sane editors won't put this in on their 23086470930SIngo Molnar * own, but e.g. Windows Notepad will do it happily. */ 23186470930SIngo Molnar if ((unsigned char) c == *bomptr) { 23286470930SIngo Molnar bomptr++; 23386470930SIngo Molnar continue; 23486470930SIngo Molnar } else { 23586470930SIngo Molnar /* Do not tolerate partial BOM. */ 23686470930SIngo Molnar if (bomptr != utf8_bom) 23786470930SIngo Molnar break; 23886470930SIngo Molnar /* No BOM at file beginning. Cool. */ 23986470930SIngo Molnar bomptr = NULL; 24086470930SIngo Molnar } 24186470930SIngo Molnar } 24286470930SIngo Molnar if (c == '\n') { 24386470930SIngo Molnar if (config_file_eof) 24486470930SIngo Molnar return 0; 24586470930SIngo Molnar comment = 0; 24686470930SIngo Molnar continue; 24786470930SIngo Molnar } 24886470930SIngo Molnar if (comment || isspace(c)) 24986470930SIngo Molnar continue; 25086470930SIngo Molnar if (c == '#' || c == ';') { 25186470930SIngo Molnar comment = 1; 25286470930SIngo Molnar continue; 25386470930SIngo Molnar } 25486470930SIngo Molnar if (c == '[') { 25586470930SIngo Molnar baselen = get_base_var(var); 25686470930SIngo Molnar if (baselen <= 0) 25786470930SIngo Molnar break; 25886470930SIngo Molnar var[baselen++] = '.'; 25986470930SIngo Molnar var[baselen] = 0; 26086470930SIngo Molnar continue; 26186470930SIngo Molnar } 26286470930SIngo Molnar if (!isalpha(c)) 26386470930SIngo Molnar break; 26486470930SIngo Molnar var[baselen] = tolower(c); 26549757c9cSJiri Olsa 26649757c9cSJiri Olsa /* 26749757c9cSJiri Olsa * The get_value function might or might not reach the '\n', 26849757c9cSJiri Olsa * so saving the current line number for error reporting. 26949757c9cSJiri Olsa */ 27049757c9cSJiri Olsa line = config_linenr; 27149757c9cSJiri Olsa if (get_value(fn, data, var, baselen+1) < 0) { 27249757c9cSJiri Olsa config_linenr = line; 27386470930SIngo Molnar break; 27486470930SIngo Molnar } 27549757c9cSJiri Olsa } 27686470930SIngo Molnar die("bad config file line %d in %s", config_linenr, config_file_name); 27786470930SIngo Molnar } 27886470930SIngo Molnar 27986470930SIngo Molnar static int parse_unit_factor(const char *end, unsigned long *val) 28086470930SIngo Molnar { 28186470930SIngo Molnar if (!*end) 28286470930SIngo Molnar return 1; 28386470930SIngo Molnar else if (!strcasecmp(end, "k")) { 28486470930SIngo Molnar *val *= 1024; 28586470930SIngo Molnar return 1; 28686470930SIngo Molnar } 28786470930SIngo Molnar else if (!strcasecmp(end, "m")) { 28886470930SIngo Molnar *val *= 1024 * 1024; 28986470930SIngo Molnar return 1; 29086470930SIngo Molnar } 29186470930SIngo Molnar else if (!strcasecmp(end, "g")) { 29286470930SIngo Molnar *val *= 1024 * 1024 * 1024; 29386470930SIngo Molnar return 1; 29486470930SIngo Molnar } 29586470930SIngo Molnar return 0; 29686470930SIngo Molnar } 29786470930SIngo Molnar 29894c0655fSJiri Olsa static int perf_parse_llong(const char *value, long long *ret) 29994c0655fSJiri Olsa { 30094c0655fSJiri Olsa if (value && *value) { 30194c0655fSJiri Olsa char *end; 30294c0655fSJiri Olsa long long val = strtoll(value, &end, 0); 30394c0655fSJiri Olsa unsigned long factor = 1; 30494c0655fSJiri Olsa 30594c0655fSJiri Olsa if (!parse_unit_factor(end, &factor)) 30694c0655fSJiri Olsa return 0; 30794c0655fSJiri Olsa *ret = val * factor; 30894c0655fSJiri Olsa return 1; 30994c0655fSJiri Olsa } 31094c0655fSJiri Olsa return 0; 31194c0655fSJiri Olsa } 31294c0655fSJiri Olsa 31386470930SIngo Molnar static int perf_parse_long(const char *value, long *ret) 31486470930SIngo Molnar { 31586470930SIngo Molnar if (value && *value) { 31686470930SIngo Molnar char *end; 31786470930SIngo Molnar long val = strtol(value, &end, 0); 31886470930SIngo Molnar unsigned long factor = 1; 31986470930SIngo Molnar if (!parse_unit_factor(end, &factor)) 32086470930SIngo Molnar return 0; 32186470930SIngo Molnar *ret = val * factor; 32286470930SIngo Molnar return 1; 32386470930SIngo Molnar } 32486470930SIngo Molnar return 0; 32586470930SIngo Molnar } 32686470930SIngo Molnar 32786470930SIngo Molnar static void die_bad_config(const char *name) 32886470930SIngo Molnar { 32986470930SIngo Molnar if (config_file_name) 33086470930SIngo Molnar die("bad config value for '%s' in %s", name, config_file_name); 33186470930SIngo Molnar die("bad config value for '%s'", name); 33286470930SIngo Molnar } 33386470930SIngo Molnar 33494c0655fSJiri Olsa u64 perf_config_u64(const char *name, const char *value) 33594c0655fSJiri Olsa { 33694c0655fSJiri Olsa long long ret = 0; 33794c0655fSJiri Olsa 33894c0655fSJiri Olsa if (!perf_parse_llong(value, &ret)) 33994c0655fSJiri Olsa die_bad_config(name); 34094c0655fSJiri Olsa return (u64) ret; 34194c0655fSJiri Olsa } 34294c0655fSJiri Olsa 34386470930SIngo Molnar int perf_config_int(const char *name, const char *value) 34486470930SIngo Molnar { 34586470930SIngo Molnar long ret = 0; 34686470930SIngo Molnar if (!perf_parse_long(value, &ret)) 34786470930SIngo Molnar die_bad_config(name); 34886470930SIngo Molnar return ret; 34986470930SIngo Molnar } 35086470930SIngo Molnar 351a41794cdSArnaldo Carvalho de Melo static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 35286470930SIngo Molnar { 35386470930SIngo Molnar *is_bool = 1; 35486470930SIngo Molnar if (!value) 35586470930SIngo Molnar return 1; 35686470930SIngo Molnar if (!*value) 35786470930SIngo Molnar return 0; 35886470930SIngo Molnar if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) 35986470930SIngo Molnar return 1; 36086470930SIngo Molnar if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 36186470930SIngo Molnar return 0; 36286470930SIngo Molnar *is_bool = 0; 36386470930SIngo Molnar return perf_config_int(name, value); 36486470930SIngo Molnar } 36586470930SIngo Molnar 36686470930SIngo Molnar int perf_config_bool(const char *name, const char *value) 36786470930SIngo Molnar { 36886470930SIngo Molnar int discard; 36986470930SIngo Molnar return !!perf_config_bool_or_int(name, value, &discard); 37086470930SIngo Molnar } 37186470930SIngo Molnar 37245de34bbSStephane Eranian const char *perf_config_dirname(const char *name, const char *value) 37345de34bbSStephane Eranian { 37445de34bbSStephane Eranian if (!name) 37545de34bbSStephane Eranian return NULL; 37645de34bbSStephane Eranian return value; 37745de34bbSStephane Eranian } 37845de34bbSStephane Eranian 3791d037ca1SIrina Tirdea static int perf_default_core_config(const char *var __maybe_unused, 3801d037ca1SIrina Tirdea const char *value __maybe_unused) 38186470930SIngo Molnar { 382395cf969SPaul Bolle /* Add other config variables here. */ 38386470930SIngo Molnar return 0; 38486470930SIngo Molnar } 38586470930SIngo Molnar 386c8302367SJiri Olsa static int perf_ui_config(const char *var, const char *value) 387c8302367SJiri Olsa { 388c8302367SJiri Olsa /* Add other config variables here. */ 389c8302367SJiri Olsa if (!strcmp(var, "ui.show-headers")) { 390c8302367SJiri Olsa symbol_conf.show_hist_headers = perf_config_bool(var, value); 391c8302367SJiri Olsa return 0; 392c8302367SJiri Olsa } 393c8302367SJiri Olsa return 0; 394c8302367SJiri Olsa } 395c8302367SJiri Olsa 3961d037ca1SIrina Tirdea int perf_default_config(const char *var, const char *value, 3971d037ca1SIrina Tirdea void *dummy __maybe_unused) 39886470930SIngo Molnar { 39986470930SIngo Molnar if (!prefixcmp(var, "core.")) 40086470930SIngo Molnar return perf_default_core_config(var, value); 40186470930SIngo Molnar 4020b93da17SNamhyung Kim if (!prefixcmp(var, "hist.")) 4030b93da17SNamhyung Kim return perf_hist_config(var, value); 4040b93da17SNamhyung Kim 405c8302367SJiri Olsa if (!prefixcmp(var, "ui.")) 406c8302367SJiri Olsa return perf_ui_config(var, value); 407c8302367SJiri Olsa 4082b9240caSNamhyung Kim if (!prefixcmp(var, "call-graph.")) 4092b9240caSNamhyung Kim return perf_callchain_config(var, value); 4102b9240caSNamhyung Kim 411395cf969SPaul Bolle /* Add other config variables here. */ 41286470930SIngo Molnar return 0; 41386470930SIngo Molnar } 41486470930SIngo Molnar 415a41794cdSArnaldo Carvalho de Melo static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 41686470930SIngo Molnar { 41786470930SIngo Molnar int ret; 41886470930SIngo Molnar FILE *f = fopen(filename, "r"); 41986470930SIngo Molnar 42086470930SIngo Molnar ret = -1; 42186470930SIngo Molnar if (f) { 42286470930SIngo Molnar config_file = f; 42386470930SIngo Molnar config_file_name = filename; 42486470930SIngo Molnar config_linenr = 1; 42586470930SIngo Molnar config_file_eof = 0; 42686470930SIngo Molnar ret = perf_parse_file(fn, data); 42786470930SIngo Molnar fclose(f); 42886470930SIngo Molnar config_file_name = NULL; 42986470930SIngo Molnar } 43086470930SIngo Molnar return ret; 43186470930SIngo Molnar } 43286470930SIngo Molnar 433a41794cdSArnaldo Carvalho de Melo static const char *perf_etc_perfconfig(void) 43486470930SIngo Molnar { 43586470930SIngo Molnar static const char *system_wide; 43686470930SIngo Molnar if (!system_wide) 43786470930SIngo Molnar system_wide = system_path(ETC_PERFCONFIG); 43886470930SIngo Molnar return system_wide; 43986470930SIngo Molnar } 44086470930SIngo Molnar 44186470930SIngo Molnar static int perf_env_bool(const char *k, int def) 44286470930SIngo Molnar { 44386470930SIngo Molnar const char *v = getenv(k); 44486470930SIngo Molnar return v ? perf_config_bool(k, v) : def; 44586470930SIngo Molnar } 44686470930SIngo Molnar 447a41794cdSArnaldo Carvalho de Melo static int perf_config_system(void) 44886470930SIngo Molnar { 44986470930SIngo Molnar return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 45086470930SIngo Molnar } 45186470930SIngo Molnar 452a41794cdSArnaldo Carvalho de Melo static int perf_config_global(void) 45386470930SIngo Molnar { 45486470930SIngo Molnar return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 45586470930SIngo Molnar } 45686470930SIngo Molnar 45786470930SIngo Molnar int perf_config(config_fn_t fn, void *data) 45886470930SIngo Molnar { 45986470930SIngo Molnar int ret = 0, found = 0; 46086470930SIngo Molnar const char *home = NULL; 46186470930SIngo Molnar 46286470930SIngo Molnar /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 46386470930SIngo Molnar if (config_exclusive_filename) 46486470930SIngo Molnar return perf_config_from_file(fn, config_exclusive_filename, data); 46586470930SIngo Molnar if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 46686470930SIngo Molnar ret += perf_config_from_file(fn, perf_etc_perfconfig(), 46786470930SIngo Molnar data); 46886470930SIngo Molnar found += 1; 46986470930SIngo Molnar } 47086470930SIngo Molnar 47186470930SIngo Molnar home = getenv("HOME"); 47286470930SIngo Molnar if (perf_config_global() && home) { 47386470930SIngo Molnar char *user_config = strdup(mkpath("%s/.perfconfig", home)); 474069e3725SArnaldo Carvalho de Melo struct stat st; 475069e3725SArnaldo Carvalho de Melo 476069e3725SArnaldo Carvalho de Melo if (user_config == NULL) { 477069e3725SArnaldo Carvalho de Melo warning("Not enough memory to process %s/.perfconfig, " 478069e3725SArnaldo Carvalho de Melo "ignoring it.", home); 479069e3725SArnaldo Carvalho de Melo goto out; 48086470930SIngo Molnar } 48186470930SIngo Molnar 482069e3725SArnaldo Carvalho de Melo if (stat(user_config, &st) < 0) 483069e3725SArnaldo Carvalho de Melo goto out_free; 484069e3725SArnaldo Carvalho de Melo 485069e3725SArnaldo Carvalho de Melo if (st.st_uid && (st.st_uid != geteuid())) { 486069e3725SArnaldo Carvalho de Melo warning("File %s not owned by current user or root, " 487069e3725SArnaldo Carvalho de Melo "ignoring it.", user_config); 488069e3725SArnaldo Carvalho de Melo goto out_free; 489069e3725SArnaldo Carvalho de Melo } 490069e3725SArnaldo Carvalho de Melo 491069e3725SArnaldo Carvalho de Melo if (!st.st_size) 492069e3725SArnaldo Carvalho de Melo goto out_free; 493069e3725SArnaldo Carvalho de Melo 494069e3725SArnaldo Carvalho de Melo ret += perf_config_from_file(fn, user_config, data); 495069e3725SArnaldo Carvalho de Melo found += 1; 496069e3725SArnaldo Carvalho de Melo out_free: 497069e3725SArnaldo Carvalho de Melo free(user_config); 498069e3725SArnaldo Carvalho de Melo } 499069e3725SArnaldo Carvalho de Melo out: 50086470930SIngo Molnar if (found == 0) 50186470930SIngo Molnar return -1; 50286470930SIngo Molnar return ret; 50386470930SIngo Molnar } 50486470930SIngo Molnar 50586470930SIngo Molnar /* 50686470930SIngo Molnar * Call this to report error for your variable that should not 50786470930SIngo Molnar * get a boolean value (i.e. "[my] var" means "true"). 50886470930SIngo Molnar */ 50986470930SIngo Molnar int config_error_nonbool(const char *var) 51086470930SIngo Molnar { 51186470930SIngo Molnar return error("Missing value for '%s'", var); 51286470930SIngo Molnar } 51345de34bbSStephane Eranian 51445de34bbSStephane Eranian struct buildid_dir_config { 51545de34bbSStephane Eranian char *dir; 51645de34bbSStephane Eranian }; 51745de34bbSStephane Eranian 51845de34bbSStephane Eranian static int buildid_dir_command_config(const char *var, const char *value, 51945de34bbSStephane Eranian void *data) 52045de34bbSStephane Eranian { 52145de34bbSStephane Eranian struct buildid_dir_config *c = data; 52245de34bbSStephane Eranian const char *v; 52345de34bbSStephane Eranian 52445de34bbSStephane Eranian /* same dir for all commands */ 525cfd31d85SJiri Olsa if (!strcmp(var, "buildid.dir")) { 52645de34bbSStephane Eranian v = perf_config_dirname(var, value); 52745de34bbSStephane Eranian if (!v) 52845de34bbSStephane Eranian return -1; 52945de34bbSStephane Eranian strncpy(c->dir, v, MAXPATHLEN-1); 53045de34bbSStephane Eranian c->dir[MAXPATHLEN-1] = '\0'; 53145de34bbSStephane Eranian } 53245de34bbSStephane Eranian return 0; 53345de34bbSStephane Eranian } 53445de34bbSStephane Eranian 53545de34bbSStephane Eranian static void check_buildid_dir_config(void) 53645de34bbSStephane Eranian { 53745de34bbSStephane Eranian struct buildid_dir_config c; 53845de34bbSStephane Eranian c.dir = buildid_dir; 53945de34bbSStephane Eranian perf_config(buildid_dir_command_config, &c); 54045de34bbSStephane Eranian } 54145de34bbSStephane Eranian 542*99ce8e9fSJiri Olsa void set_buildid_dir(const char *dir) 54345de34bbSStephane Eranian { 544*99ce8e9fSJiri Olsa if (dir) 545*99ce8e9fSJiri Olsa scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 54645de34bbSStephane Eranian 54745de34bbSStephane Eranian /* try config file */ 548*99ce8e9fSJiri Olsa if (buildid_dir[0] == '\0') 54945de34bbSStephane Eranian check_buildid_dir_config(); 55045de34bbSStephane Eranian 55145de34bbSStephane Eranian /* default to $HOME/.debug */ 55245de34bbSStephane Eranian if (buildid_dir[0] == '\0') { 55345de34bbSStephane Eranian char *v = getenv("HOME"); 55445de34bbSStephane Eranian if (v) { 55545de34bbSStephane Eranian snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 55645de34bbSStephane Eranian v, DEBUG_CACHE_DIR); 55745de34bbSStephane Eranian } else { 55845de34bbSStephane Eranian strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 55945de34bbSStephane Eranian } 56045de34bbSStephane Eranian buildid_dir[MAXPATHLEN-1] = '\0'; 56145de34bbSStephane Eranian } 56245de34bbSStephane Eranian /* for communicating with external commands */ 56345de34bbSStephane Eranian setenv("PERF_BUILDID_DIR", buildid_dir, 1); 56445de34bbSStephane Eranian } 565