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