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 bad_config(const char *name) 339 { 340 if (config_file_name) 341 pr_warning("bad config value for '%s' in %s, ignoring...\n", name, config_file_name); 342 else 343 pr_warning("bad config value for '%s', ignoring...\n", name); 344 } 345 346 int perf_config_u64(u64 *dest, const char *name, const char *value) 347 { 348 long long ret = 0; 349 350 if (!perf_parse_llong(value, &ret)) { 351 bad_config(name); 352 return -1; 353 } 354 355 *dest = ret; 356 return 0; 357 } 358 359 int perf_config_int(int *dest, const char *name, const char *value) 360 { 361 long ret = 0; 362 if (!perf_parse_long(value, &ret)) { 363 bad_config(name); 364 return -1; 365 } 366 *dest = ret; 367 return 0; 368 } 369 370 static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 371 { 372 int ret; 373 374 *is_bool = 1; 375 if (!value) 376 return 1; 377 if (!*value) 378 return 0; 379 if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) 380 return 1; 381 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 382 return 0; 383 *is_bool = 0; 384 return perf_config_int(&ret, name, value) < 0 ? -1 : ret; 385 } 386 387 int perf_config_bool(const char *name, const char *value) 388 { 389 int discard; 390 return !!perf_config_bool_or_int(name, value, &discard); 391 } 392 393 static const char *perf_config_dirname(const char *name, const char *value) 394 { 395 if (!name) 396 return NULL; 397 return value; 398 } 399 400 static int perf_buildid_config(const char *var, const char *value) 401 { 402 /* same dir for all commands */ 403 if (!strcmp(var, "buildid.dir")) { 404 const char *dir = perf_config_dirname(var, value); 405 406 if (!dir) { 407 pr_err("Invalid buildid directory!\n"); 408 return -1; 409 } 410 strncpy(buildid_dir, dir, MAXPATHLEN-1); 411 buildid_dir[MAXPATHLEN-1] = '\0'; 412 } 413 414 return 0; 415 } 416 417 static int perf_default_core_config(const char *var __maybe_unused, 418 const char *value __maybe_unused) 419 { 420 /* Add other config variables here. */ 421 return 0; 422 } 423 424 static int perf_ui_config(const char *var, const char *value) 425 { 426 /* Add other config variables here. */ 427 if (!strcmp(var, "ui.show-headers")) 428 symbol_conf.show_hist_headers = perf_config_bool(var, value); 429 430 return 0; 431 } 432 433 int perf_default_config(const char *var, const char *value, 434 void *dummy __maybe_unused) 435 { 436 if (!prefixcmp(var, "core.")) 437 return perf_default_core_config(var, value); 438 439 if (!prefixcmp(var, "hist.")) 440 return perf_hist_config(var, value); 441 442 if (!prefixcmp(var, "ui.")) 443 return perf_ui_config(var, value); 444 445 if (!prefixcmp(var, "call-graph.")) 446 return perf_callchain_config(var, value); 447 448 if (!prefixcmp(var, "llvm.")) 449 return perf_llvm_config(var, value); 450 451 if (!prefixcmp(var, "buildid.")) 452 return perf_buildid_config(var, value); 453 454 /* Add other config variables here. */ 455 return 0; 456 } 457 458 static int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 459 { 460 int ret; 461 FILE *f = fopen(filename, "r"); 462 463 ret = -1; 464 if (f) { 465 config_file = f; 466 config_file_name = filename; 467 config_linenr = 1; 468 config_file_eof = 0; 469 ret = perf_parse_file(fn, data); 470 fclose(f); 471 config_file_name = NULL; 472 } 473 return ret; 474 } 475 476 const char *perf_etc_perfconfig(void) 477 { 478 static const char *system_wide; 479 if (!system_wide) 480 system_wide = system_path(ETC_PERFCONFIG); 481 return system_wide; 482 } 483 484 static int perf_env_bool(const char *k, int def) 485 { 486 const char *v = getenv(k); 487 return v ? perf_config_bool(k, v) : def; 488 } 489 490 static int perf_config_system(void) 491 { 492 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 493 } 494 495 static int perf_config_global(void) 496 { 497 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 498 } 499 500 static struct perf_config_section *find_section(struct list_head *sections, 501 const char *section_name) 502 { 503 struct perf_config_section *section; 504 505 list_for_each_entry(section, sections, node) 506 if (!strcmp(section->name, section_name)) 507 return section; 508 509 return NULL; 510 } 511 512 static struct perf_config_item *find_config_item(const char *name, 513 struct perf_config_section *section) 514 { 515 struct perf_config_item *item; 516 517 list_for_each_entry(item, §ion->items, node) 518 if (!strcmp(item->name, name)) 519 return item; 520 521 return NULL; 522 } 523 524 static struct perf_config_section *add_section(struct list_head *sections, 525 const char *section_name) 526 { 527 struct perf_config_section *section = zalloc(sizeof(*section)); 528 529 if (!section) 530 return NULL; 531 532 INIT_LIST_HEAD(§ion->items); 533 section->name = strdup(section_name); 534 if (!section->name) { 535 pr_debug("%s: strdup failed\n", __func__); 536 free(section); 537 return NULL; 538 } 539 540 list_add_tail(§ion->node, sections); 541 return section; 542 } 543 544 static struct perf_config_item *add_config_item(struct perf_config_section *section, 545 const char *name) 546 { 547 struct perf_config_item *item = zalloc(sizeof(*item)); 548 549 if (!item) 550 return NULL; 551 552 item->name = strdup(name); 553 if (!item->name) { 554 pr_debug("%s: strdup failed\n", __func__); 555 free(item); 556 return NULL; 557 } 558 559 list_add_tail(&item->node, §ion->items); 560 return item; 561 } 562 563 static int set_value(struct perf_config_item *item, const char *value) 564 { 565 char *val = strdup(value); 566 567 if (!val) 568 return -1; 569 570 zfree(&item->value); 571 item->value = val; 572 return 0; 573 } 574 575 static int collect_config(const char *var, const char *value, 576 void *perf_config_set) 577 { 578 int ret = -1; 579 char *ptr, *key; 580 char *section_name, *name; 581 struct perf_config_section *section = NULL; 582 struct perf_config_item *item = NULL; 583 struct perf_config_set *set = perf_config_set; 584 struct list_head *sections; 585 586 if (set == NULL) 587 return -1; 588 589 sections = &set->sections; 590 key = ptr = strdup(var); 591 if (!key) { 592 pr_debug("%s: strdup failed\n", __func__); 593 return -1; 594 } 595 596 section_name = strsep(&ptr, "."); 597 name = ptr; 598 if (name == NULL || value == NULL) 599 goto out_free; 600 601 section = find_section(sections, section_name); 602 if (!section) { 603 section = add_section(sections, section_name); 604 if (!section) 605 goto out_free; 606 } 607 608 item = find_config_item(name, section); 609 if (!item) { 610 item = add_config_item(section, name); 611 if (!item) 612 goto out_free; 613 } 614 615 /* perf_config_set can contain both user and system config items. 616 * So we should know where each value is from. 617 * The classification would be needed when a particular config file 618 * is overwrited by setting feature i.e. set_config(). 619 */ 620 if (strcmp(config_file_name, perf_etc_perfconfig()) == 0) { 621 section->from_system_config = true; 622 item->from_system_config = true; 623 } else { 624 section->from_system_config = false; 625 item->from_system_config = false; 626 } 627 628 ret = set_value(item, value); 629 return ret; 630 631 out_free: 632 free(key); 633 return -1; 634 } 635 636 int perf_config_set__collect(struct perf_config_set *set, const char *file_name, 637 const char *var, const char *value) 638 { 639 config_file_name = file_name; 640 return collect_config(var, value, set); 641 } 642 643 static int perf_config_set__init(struct perf_config_set *set) 644 { 645 int ret = -1; 646 const char *home = NULL; 647 char *user_config; 648 struct stat st; 649 650 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 651 if (config_exclusive_filename) 652 return perf_config_from_file(collect_config, config_exclusive_filename, set); 653 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 654 if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0) 655 goto out; 656 } 657 658 home = getenv("HOME"); 659 660 /* 661 * Skip reading user config if: 662 * - there is no place to read it from (HOME) 663 * - we are asked not to (PERF_CONFIG_NOGLOBAL=1) 664 */ 665 if (!home || !*home || !perf_config_global()) 666 return 0; 667 668 user_config = strdup(mkpath("%s/.perfconfig", home)); 669 if (user_config == NULL) { 670 pr_warning("Not enough memory to process %s/.perfconfig, ignoring it.", home); 671 goto out; 672 } 673 674 if (stat(user_config, &st) < 0) { 675 if (errno == ENOENT) 676 ret = 0; 677 goto out_free; 678 } 679 680 ret = 0; 681 682 if (st.st_uid && (st.st_uid != geteuid())) { 683 pr_warning("File %s not owned by current user or root, ignoring it.", user_config); 684 goto out_free; 685 } 686 687 if (st.st_size) 688 ret = perf_config_from_file(collect_config, user_config, set); 689 690 out_free: 691 free(user_config); 692 out: 693 return ret; 694 } 695 696 struct perf_config_set *perf_config_set__new(void) 697 { 698 struct perf_config_set *set = zalloc(sizeof(*set)); 699 700 if (set) { 701 INIT_LIST_HEAD(&set->sections); 702 if (perf_config_set__init(set) < 0) { 703 perf_config_set__delete(set); 704 set = NULL; 705 } 706 } 707 708 return set; 709 } 710 711 int perf_config(config_fn_t fn, void *data) 712 { 713 int ret = 0; 714 char key[BUFSIZ]; 715 struct perf_config_section *section; 716 struct perf_config_item *item; 717 718 if (config_set == NULL) 719 return -1; 720 721 perf_config_set__for_each_entry(config_set, section, item) { 722 char *value = item->value; 723 724 if (value) { 725 scnprintf(key, sizeof(key), "%s.%s", 726 section->name, item->name); 727 ret = fn(key, value, data); 728 if (ret < 0) { 729 pr_err("Error: wrong config key-value pair %s=%s\n", 730 key, value); 731 break; 732 } 733 } 734 } 735 736 return ret; 737 } 738 739 void perf_config__init(void) 740 { 741 if (config_set == NULL) 742 config_set = perf_config_set__new(); 743 } 744 745 void perf_config__exit(void) 746 { 747 perf_config_set__delete(config_set); 748 config_set = NULL; 749 } 750 751 void perf_config__refresh(void) 752 { 753 perf_config__exit(); 754 perf_config__init(); 755 } 756 757 static void perf_config_item__delete(struct perf_config_item *item) 758 { 759 zfree(&item->name); 760 zfree(&item->value); 761 free(item); 762 } 763 764 static void perf_config_section__purge(struct perf_config_section *section) 765 { 766 struct perf_config_item *item, *tmp; 767 768 list_for_each_entry_safe(item, tmp, §ion->items, node) { 769 list_del_init(&item->node); 770 perf_config_item__delete(item); 771 } 772 } 773 774 static void perf_config_section__delete(struct perf_config_section *section) 775 { 776 perf_config_section__purge(section); 777 zfree(§ion->name); 778 free(section); 779 } 780 781 static void perf_config_set__purge(struct perf_config_set *set) 782 { 783 struct perf_config_section *section, *tmp; 784 785 list_for_each_entry_safe(section, tmp, &set->sections, node) { 786 list_del_init(§ion->node); 787 perf_config_section__delete(section); 788 } 789 } 790 791 void perf_config_set__delete(struct perf_config_set *set) 792 { 793 if (set == NULL) 794 return; 795 796 perf_config_set__purge(set); 797 free(set); 798 } 799 800 /* 801 * Call this to report error for your variable that should not 802 * get a boolean value (i.e. "[my] var" means "true"). 803 */ 804 int config_error_nonbool(const char *var) 805 { 806 pr_err("Missing value for '%s'", var); 807 return -1; 808 } 809 810 void set_buildid_dir(const char *dir) 811 { 812 if (dir) 813 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 814 815 /* default to $HOME/.debug */ 816 if (buildid_dir[0] == '\0') { 817 char *home = getenv("HOME"); 818 819 if (home) { 820 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 821 home, DEBUG_CACHE_DIR); 822 } else { 823 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 824 } 825 buildid_dir[MAXPATHLEN-1] = '\0'; 826 } 827 /* for communicating with external commands */ 828 setenv("PERF_BUILDID_DIR", buildid_dir, 1); 829 } 830