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