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