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