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