~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/config.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 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 
 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 
140 static inline int iskeychar(int c)
141 {
142         return isalnum(c) || c == '-' || c == '_';
143 }
144 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
530 int perf_config_system(void)
531 {
532         return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0);
533 }
534 
535 int perf_config_global(void)
536 {
537         return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
538 }
539 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
826 void perf_config__exit(void)
827 {
828         perf_config_set__delete(config_set);
829         config_set = NULL;
830 }
831 
832 void perf_config__refresh(void)
833 {
834         perf_config__exit();
835         perf_config__init();
836 }
837 
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 
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 
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 
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 
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  */
885 int config_error_nonbool(const char *var)
886 {
887         pr_err("Missing value for '%s'", var);
888         return -1;
889 }
890 
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 
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 
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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php