^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * config.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Helper functions for parsing config items.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Originally copied from GIT source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) Linus Torvalds, 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) Johannes Schindelin, 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sys/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "cache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "callchain.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <subcmd/exec-cmd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "util/event.h" /* proc_map_timeout */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "util/hist.h" /* perf_hist_config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "util/llvm-utils.h" /* perf_llvm_config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "util/stat.h" /* perf_stat__set_big_num */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "build-id.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "config.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MAXNAME (256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DEBUG_CACHE_DIR ".debug"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static FILE *config_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const char *config_file_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int config_linenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int config_file_eof;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static struct perf_config_set *config_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const char *config_exclusive_filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static int get_next_char(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) FILE *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) c = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if ((f = config_file) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) c = fgetc(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (c == '\r') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* DOS like systems */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) c = fgetc(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (c != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ungetc(c, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) c = '\r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (c == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) config_linenr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (c == EOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) config_file_eof = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) c = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static char *parse_value(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static char value[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int quote = 0, comment = 0, space = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (len >= sizeof(value) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (c == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (quote)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) value[len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (comment)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (isspace(c) && !quote) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) space = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!quote) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (c == ';' || c == '#') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) comment = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (space) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) value[len++] = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) space = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (c == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case '\n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) c = '\t';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) case 'b':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) c = '\b';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case 'n':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) c = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Some characters escape as themselves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case '\\': case '"':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Reject unknown escape sequences */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) value[len++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (c == '"') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) quote = 1-quote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) value[len++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static inline int iskeychar(int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return isalnum(c) || c == '-' || c == '_';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int get_value(config_fn_t fn, void *data, char *name, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) char *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Get the full name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (config_file_eof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!iskeychar(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) name[len++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (len >= MAXNAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) name[len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) while (c == ' ' || c == '\t')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) value = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (c != '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (c != '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) value = parse_value();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return fn(name, value, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int get_extended_base_var(char *name, int baselen, int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (c == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) } while (isspace(c));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* We require the format to be '[base "extension"]' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (c != '"')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) name[baselen++] = '.';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int ch = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ch == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (ch == '"')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (ch == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ch = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ch == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) name[baselen++] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (baselen > MAXNAME / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* Final ']' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (get_next_char() != ']')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return baselen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int get_base_var(char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int baselen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (config_file_eof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (c == ']')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return baselen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (isspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return get_extended_base_var(name, baselen, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!iskeychar(c) && c != '.')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (baselen > MAXNAME / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) name[baselen++] = tolower(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static int perf_parse_file(config_fn_t fn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int comment = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) int baselen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static char var[MAXNAME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* U+FEFF Byte Order Mark in UTF8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) const unsigned char *bomptr = utf8_bom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int line, c = get_next_char();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (bomptr && *bomptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* We are at the file beginning; skip UTF8-encoded BOM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * if present. Sane editors won't put this in on their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * own, but e.g. Windows Notepad will do it happily. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if ((unsigned char) c == *bomptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) bomptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Do not tolerate partial BOM. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (bomptr != utf8_bom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* No BOM at file beginning. Cool. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) bomptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (c == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (config_file_eof)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) comment = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (comment || isspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (c == '#' || c == ';') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) comment = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (c == '[') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) baselen = get_base_var(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (baselen <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) var[baselen++] = '.';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) var[baselen] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!isalpha(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) var[baselen] = tolower(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * The get_value function might or might not reach the '\n',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * so saving the current line number for error reporting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) line = config_linenr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (get_value(fn, data, var, baselen+1) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) config_linenr = line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) pr_err("bad config file line %d in %s\n", config_linenr, config_file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static int parse_unit_factor(const char *end, unsigned long *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (!*end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) else if (!strcasecmp(end, "k")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *val *= 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) else if (!strcasecmp(end, "m")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *val *= 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) else if (!strcasecmp(end, "g")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *val *= 1024 * 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int perf_parse_llong(const char *value, long long *ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (value && *value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) long long val = strtoll(value, &end, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) unsigned long factor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (!parse_unit_factor(end, &factor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *ret = val * factor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static int perf_parse_long(const char *value, long *ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (value && *value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) long val = strtol(value, &end, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) unsigned long factor = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!parse_unit_factor(end, &factor))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) *ret = val * factor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void bad_config(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (config_file_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) pr_warning("bad config value for '%s' in %s, ignoring...\n", name, config_file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) pr_warning("bad config value for '%s', ignoring...\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int perf_config_u64(u64 *dest, const char *name, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) long long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (!perf_parse_llong(value, &ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) bad_config(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *dest = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int perf_config_int(int *dest, const char *name, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!perf_parse_long(value, &ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) bad_config(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) *dest = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int perf_config_u8(u8 *dest, const char *name, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (!perf_parse_long(value, &ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) bad_config(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *dest = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *is_bool = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (!value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (!*value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) *is_bool = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return perf_config_int(&ret, name, value) < 0 ? -1 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int perf_config_bool(const char *name, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return !!perf_config_bool_or_int(name, value, &discard);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static const char *perf_config_dirname(const char *name, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static int perf_buildid_config(const char *var, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* same dir for all commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!strcmp(var, "buildid.dir")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) const char *dir = perf_config_dirname(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (!dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) pr_err("Invalid buildid directory!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) strncpy(buildid_dir, dir, MAXPATHLEN-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) buildid_dir[MAXPATHLEN-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static int perf_default_core_config(const char *var __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) const char *value __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (!strcmp(var, "core.proc-map-timeout"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) proc_map_timeout = strtoul(value, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) /* Add other config variables here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static int perf_ui_config(const char *var, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* Add other config variables here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!strcmp(var, "ui.show-headers"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) symbol_conf.show_hist_headers = perf_config_bool(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static int perf_stat_config(const char *var, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!strcmp(var, "stat.big-num"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) perf_stat__set_big_num(perf_config_bool(var, value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Add other config variables here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int perf_default_config(const char *var, const char *value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) void *dummy __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (strstarts(var, "core."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return perf_default_core_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (strstarts(var, "hist."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return perf_hist_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (strstarts(var, "ui."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) return perf_ui_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (strstarts(var, "call-graph."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return perf_callchain_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (strstarts(var, "llvm."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return perf_llvm_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (strstarts(var, "buildid."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return perf_buildid_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (strstarts(var, "stat."))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return perf_stat_config(var, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /* Add other config variables here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int perf_config_from_file(config_fn_t fn, const char *filename, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) FILE *f = fopen(filename, "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) config_file = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) config_file_name = filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) config_linenr = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) config_file_eof = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ret = perf_parse_file(fn, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) fclose(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) config_file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) const char *perf_etc_perfconfig(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static const char *system_wide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (!system_wide)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) system_wide = system_path(ETC_PERFCONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return system_wide;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) static int perf_env_bool(const char *k, int def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) const char *v = getenv(k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return v ? perf_config_bool(k, v) : def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static int perf_config_system(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int perf_config_global(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static struct perf_config_section *find_section(struct list_head *sections,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) const char *section_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct perf_config_section *section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) list_for_each_entry(section, sections, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!strcmp(section->name, section_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static struct perf_config_item *find_config_item(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct perf_config_section *section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct perf_config_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) list_for_each_entry(item, §ion->items, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (!strcmp(item->name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static struct perf_config_section *add_section(struct list_head *sections,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) const char *section_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) struct perf_config_section *section = zalloc(sizeof(*section));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) INIT_LIST_HEAD(§ion->items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) section->name = strdup(section_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!section->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pr_debug("%s: strdup failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) free(section);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) list_add_tail(§ion->node, sections);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static struct perf_config_item *add_config_item(struct perf_config_section *section,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) struct perf_config_item *item = zalloc(sizeof(*item));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (!item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) item->name = strdup(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (!item->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) pr_debug("%s: strdup failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) free(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) list_add_tail(&item->node, §ion->items);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static int set_value(struct perf_config_item *item, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) char *val = strdup(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) zfree(&item->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) item->value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int collect_config(const char *var, const char *value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) void *perf_config_set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) char *ptr, *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) char *section_name, *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct perf_config_section *section = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct perf_config_item *item = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct perf_config_set *set = perf_config_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct list_head *sections;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (set == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) sections = &set->sections;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) key = ptr = strdup(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pr_debug("%s: strdup failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) section_name = strsep(&ptr, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) name = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (name == NULL || value == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) section = find_section(sections, section_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!section) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) section = add_section(sections, section_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (!section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) item = find_config_item(name, section);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (!item) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) item = add_config_item(section, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* perf_config_set can contain both user and system config items.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * So we should know where each value is from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * The classification would be needed when a particular config file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * is overwrited by setting feature i.e. set_config().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) section->from_system_config = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) item->from_system_config = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) section->from_system_config = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) item->from_system_config = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ret = set_value(item, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) free(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) const char *var, const char *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) config_file_name = file_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return collect_config(var, value, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static int perf_config_set__init(struct perf_config_set *set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) const char *home = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) char *user_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct stat st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) if (config_exclusive_filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return perf_config_from_file(collect_config, config_exclusive_filename, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) home = getenv("HOME");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * Skip reading user config if:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * - there is no place to read it from (HOME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * - we are asked not to (PERF_CONFIG_NOGLOBAL=1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if (!home || !*home || !perf_config_global())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) user_config = strdup(mkpath("%s/.perfconfig", home));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (user_config == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) pr_warning("Not enough memory to process %s/.perfconfig, ignoring it.", home);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (stat(user_config, &st) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (errno == ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (st.st_uid && (st.st_uid != geteuid())) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) pr_warning("File %s not owned by current user or root, ignoring it.", user_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (st.st_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ret = perf_config_from_file(collect_config, user_config, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) free(user_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct perf_config_set *perf_config_set__new(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) struct perf_config_set *set = zalloc(sizeof(*set));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (set) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) INIT_LIST_HEAD(&set->sections);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) perf_config_set__init(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static int perf_config__init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (config_set == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) config_set = perf_config_set__new();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return config_set == NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int perf_config(config_fn_t fn, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) char key[BUFSIZ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct perf_config_section *section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) struct perf_config_item *item;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (config_set == NULL && perf_config__init())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) perf_config_set__for_each_entry(config_set, section, item) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) char *value = item->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) scnprintf(key, sizeof(key), "%s.%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) section->name, item->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) ret = fn(key, value, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) pr_err("Error: wrong config key-value pair %s=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) key, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * Can't be just a 'break', as perf_config_set__for_each_entry()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) * expands to two nested for() loops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) void perf_config__exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) perf_config_set__delete(config_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) config_set = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) void perf_config__refresh(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) perf_config__exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) perf_config__init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static void perf_config_item__delete(struct perf_config_item *item)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) zfree(&item->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) zfree(&item->value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) free(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static void perf_config_section__purge(struct perf_config_section *section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct perf_config_item *item, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) list_for_each_entry_safe(item, tmp, §ion->items, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) list_del_init(&item->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) perf_config_item__delete(item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) static void perf_config_section__delete(struct perf_config_section *section)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) perf_config_section__purge(section);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) zfree(§ion->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) free(section);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) static void perf_config_set__purge(struct perf_config_set *set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) struct perf_config_section *section, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) list_for_each_entry_safe(section, tmp, &set->sections, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) list_del_init(§ion->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) perf_config_section__delete(section);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) void perf_config_set__delete(struct perf_config_set *set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (set == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) perf_config_set__purge(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) free(set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * Call this to report error for your variable that should not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * get a boolean value (i.e. "[my] var" means "true").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) int config_error_nonbool(const char *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) pr_err("Missing value for '%s'", var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) void set_buildid_dir(const char *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) scnprintf(buildid_dir, MAXPATHLEN, "%s", dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* default to $HOME/.debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (buildid_dir[0] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) char *home = getenv("HOME");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (home) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) snprintf(buildid_dir, MAXPATHLEN, "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) home, DEBUG_CACHE_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) buildid_dir[MAXPATHLEN-1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) /* for communicating with external commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) setenv("PERF_BUILDID_DIR", buildid_dir, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }