1 /* 2 * GIT - The information manager from hell 3 * 4 * Copyright (C) Linus Torvalds, 2005 5 * Copyright (C) Johannes Schindelin, 2005 6 * 7 */ 8 #include "util.h" 9 #include "cache.h" 10 #include "exec_cmd.h" 11 12 #define MAXNAME (256) 13 14 static FILE *config_file; 15 static const char *config_file_name; 16 static int config_linenr; 17 static int config_file_eof; 18 19 const char *config_exclusive_filename = NULL; 20 21 static int get_next_char(void) 22 { 23 int c; 24 FILE *f; 25 26 c = '\n'; 27 if ((f = config_file) != NULL) { 28 c = fgetc(f); 29 if (c == '\r') { 30 /* DOS like systems */ 31 c = fgetc(f); 32 if (c != '\n') { 33 ungetc(c, f); 34 c = '\r'; 35 } 36 } 37 if (c == '\n') 38 config_linenr++; 39 if (c == EOF) { 40 config_file_eof = 1; 41 c = '\n'; 42 } 43 } 44 return c; 45 } 46 47 static char *parse_value(void) 48 { 49 static char value[1024]; 50 int quote = 0, comment = 0, space = 0; 51 size_t len = 0; 52 53 for (;;) { 54 int c = get_next_char(); 55 56 if (len >= sizeof(value) - 1) 57 return NULL; 58 if (c == '\n') { 59 if (quote) 60 return NULL; 61 value[len] = 0; 62 return value; 63 } 64 if (comment) 65 continue; 66 if (isspace(c) && !quote) { 67 space = 1; 68 continue; 69 } 70 if (!quote) { 71 if (c == ';' || c == '#') { 72 comment = 1; 73 continue; 74 } 75 } 76 if (space) { 77 if (len) 78 value[len++] = ' '; 79 space = 0; 80 } 81 if (c == '\\') { 82 c = get_next_char(); 83 switch (c) { 84 case '\n': 85 continue; 86 case 't': 87 c = '\t'; 88 break; 89 case 'b': 90 c = '\b'; 91 break; 92 case 'n': 93 c = '\n'; 94 break; 95 /* Some characters escape as themselves */ 96 case '\\': case '"': 97 break; 98 /* Reject unknown escape sequences */ 99 default: 100 return NULL; 101 } 102 value[len++] = c; 103 continue; 104 } 105 if (c == '"') { 106 quote = 1-quote; 107 continue; 108 } 109 value[len++] = c; 110 } 111 } 112 113 static inline int iskeychar(int c) 114 { 115 return isalnum(c) || c == '-'; 116 } 117 118 static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) 119 { 120 int c; 121 char *value; 122 123 /* Get the full name */ 124 for (;;) { 125 c = get_next_char(); 126 if (config_file_eof) 127 break; 128 if (!iskeychar(c)) 129 break; 130 name[len++] = tolower(c); 131 if (len >= MAXNAME) 132 return -1; 133 } 134 name[len] = 0; 135 while (c == ' ' || c == '\t') 136 c = get_next_char(); 137 138 value = NULL; 139 if (c != '\n') { 140 if (c != '=') 141 return -1; 142 value = parse_value(); 143 if (!value) 144 return -1; 145 } 146 return fn(name, value, data); 147 } 148 149 static int get_extended_base_var(char *name, int baselen, int c) 150 { 151 do { 152 if (c == '\n') 153 return -1; 154 c = get_next_char(); 155 } while (isspace(c)); 156 157 /* We require the format to be '[base "extension"]' */ 158 if (c != '"') 159 return -1; 160 name[baselen++] = '.'; 161 162 for (;;) { 163 int ch = get_next_char(); 164 165 if (ch == '\n') 166 return -1; 167 if (ch == '"') 168 break; 169 if (ch == '\\') { 170 ch = get_next_char(); 171 if (ch == '\n') 172 return -1; 173 } 174 name[baselen++] = ch; 175 if (baselen > MAXNAME / 2) 176 return -1; 177 } 178 179 /* Final ']' */ 180 if (get_next_char() != ']') 181 return -1; 182 return baselen; 183 } 184 185 static int get_base_var(char *name) 186 { 187 int baselen = 0; 188 189 for (;;) { 190 int c = get_next_char(); 191 if (config_file_eof) 192 return -1; 193 if (c == ']') 194 return baselen; 195 if (isspace(c)) 196 return get_extended_base_var(name, baselen, c); 197 if (!iskeychar(c) && c != '.') 198 return -1; 199 if (baselen > MAXNAME / 2) 200 return -1; 201 name[baselen++] = tolower(c); 202 } 203 } 204 205 static int perf_parse_file(config_fn_t fn, void *data) 206 { 207 int comment = 0; 208 int baselen = 0; 209 static char var[MAXNAME]; 210 211 /* U+FEFF Byte Order Mark in UTF8 */ 212 static const unsigned char *utf8_bom = (unsigned char *) "\xef\xbb\xbf"; 213 const unsigned char *bomptr = utf8_bom; 214 215 for (;;) { 216 int c = get_next_char(); 217 if (bomptr && *bomptr) { 218 /* We are at the file beginning; skip UTF8-encoded BOM 219 * if present. Sane editors won't put this in on their 220 * own, but e.g. Windows Notepad will do it happily. */ 221 if ((unsigned char) c == *bomptr) { 222 bomptr++; 223 continue; 224 } else { 225 /* Do not tolerate partial BOM. */ 226 if (bomptr != utf8_bom) 227 break; 228 /* No BOM at file beginning. Cool. */ 229 bomptr = NULL; 230 } 231 } 232 if (c == '\n') { 233 if (config_file_eof) 234 return 0; 235 comment = 0; 236 continue; 237 } 238 if (comment || isspace(c)) 239 continue; 240 if (c == '#' || c == ';') { 241 comment = 1; 242 continue; 243 } 244 if (c == '[') { 245 baselen = get_base_var(var); 246 if (baselen <= 0) 247 break; 248 var[baselen++] = '.'; 249 var[baselen] = 0; 250 continue; 251 } 252 if (!isalpha(c)) 253 break; 254 var[baselen] = tolower(c); 255 if (get_value(fn, data, var, baselen+1) < 0) 256 break; 257 } 258 die("bad config file line %d in %s", config_linenr, config_file_name); 259 } 260 261 static int parse_unit_factor(const char *end, unsigned long *val) 262 { 263 if (!*end) 264 return 1; 265 else if (!strcasecmp(end, "k")) { 266 *val *= 1024; 267 return 1; 268 } 269 else if (!strcasecmp(end, "m")) { 270 *val *= 1024 * 1024; 271 return 1; 272 } 273 else if (!strcasecmp(end, "g")) { 274 *val *= 1024 * 1024 * 1024; 275 return 1; 276 } 277 return 0; 278 } 279 280 static int perf_parse_long(const char *value, long *ret) 281 { 282 if (value && *value) { 283 char *end; 284 long val = strtol(value, &end, 0); 285 unsigned long factor = 1; 286 if (!parse_unit_factor(end, &factor)) 287 return 0; 288 *ret = val * factor; 289 return 1; 290 } 291 return 0; 292 } 293 294 int perf_parse_ulong(const char *value, unsigned long *ret) 295 { 296 if (value && *value) { 297 char *end; 298 unsigned long val = strtoul(value, &end, 0); 299 if (!parse_unit_factor(end, &val)) 300 return 0; 301 *ret = val; 302 return 1; 303 } 304 return 0; 305 } 306 307 static void die_bad_config(const char *name) 308 { 309 if (config_file_name) 310 die("bad config value for '%s' in %s", name, config_file_name); 311 die("bad config value for '%s'", name); 312 } 313 314 int perf_config_int(const char *name, const char *value) 315 { 316 long ret = 0; 317 if (!perf_parse_long(value, &ret)) 318 die_bad_config(name); 319 return ret; 320 } 321 322 unsigned long perf_config_ulong(const char *name, const char *value) 323 { 324 unsigned long ret; 325 if (!perf_parse_ulong(value, &ret)) 326 die_bad_config(name); 327 return ret; 328 } 329 330 int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) 331 { 332 *is_bool = 1; 333 if (!value) 334 return 1; 335 if (!*value) 336 return 0; 337 if (!strcasecmp(value, "true") || !strcasecmp(value, "yes") || !strcasecmp(value, "on")) 338 return 1; 339 if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) 340 return 0; 341 *is_bool = 0; 342 return perf_config_int(name, value); 343 } 344 345 int perf_config_bool(const char *name, const char *value) 346 { 347 int discard; 348 return !!perf_config_bool_or_int(name, value, &discard); 349 } 350 351 int perf_config_string(const char **dest, const char *var, const char *value) 352 { 353 if (!value) 354 return config_error_nonbool(var); 355 *dest = strdup(value); 356 return 0; 357 } 358 359 static int perf_default_core_config(const char *var __used, const char *value __used) 360 { 361 /* Add other config variables here and to Documentation/config.txt. */ 362 return 0; 363 } 364 365 int perf_default_config(const char *var, const char *value, void *dummy __used) 366 { 367 if (!prefixcmp(var, "core.")) 368 return perf_default_core_config(var, value); 369 370 /* Add other config variables here and to Documentation/config.txt. */ 371 return 0; 372 } 373 374 int perf_config_from_file(config_fn_t fn, const char *filename, void *data) 375 { 376 int ret; 377 FILE *f = fopen(filename, "r"); 378 379 ret = -1; 380 if (f) { 381 config_file = f; 382 config_file_name = filename; 383 config_linenr = 1; 384 config_file_eof = 0; 385 ret = perf_parse_file(fn, data); 386 fclose(f); 387 config_file_name = NULL; 388 } 389 return ret; 390 } 391 392 const char *perf_etc_perfconfig(void) 393 { 394 static const char *system_wide; 395 if (!system_wide) 396 system_wide = system_path(ETC_PERFCONFIG); 397 return system_wide; 398 } 399 400 static int perf_env_bool(const char *k, int def) 401 { 402 const char *v = getenv(k); 403 return v ? perf_config_bool(k, v) : def; 404 } 405 406 int perf_config_system(void) 407 { 408 return !perf_env_bool("PERF_CONFIG_NOSYSTEM", 0); 409 } 410 411 int perf_config_global(void) 412 { 413 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 414 } 415 416 int perf_config(config_fn_t fn, void *data) 417 { 418 int ret = 0, found = 0; 419 char *repo_config = NULL; 420 const char *home = NULL; 421 422 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 423 if (config_exclusive_filename) 424 return perf_config_from_file(fn, config_exclusive_filename, data); 425 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 426 ret += perf_config_from_file(fn, perf_etc_perfconfig(), 427 data); 428 found += 1; 429 } 430 431 home = getenv("HOME"); 432 if (perf_config_global() && home) { 433 char *user_config = strdup(mkpath("%s/.perfconfig", home)); 434 if (!access(user_config, R_OK)) { 435 ret += perf_config_from_file(fn, user_config, data); 436 found += 1; 437 } 438 free(user_config); 439 } 440 441 repo_config = perf_pathdup("config"); 442 if (!access(repo_config, R_OK)) { 443 ret += perf_config_from_file(fn, repo_config, data); 444 found += 1; 445 } 446 free(repo_config); 447 if (found == 0) 448 return -1; 449 return ret; 450 } 451 452 /* 453 * Find all the stuff for perf_config_set() below. 454 */ 455 456 #define MAX_MATCHES 512 457 458 static struct { 459 int baselen; 460 char* key; 461 int do_not_match; 462 regex_t* value_regex; 463 int multi_replace; 464 size_t offset[MAX_MATCHES]; 465 enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state; 466 int seen; 467 } store; 468 469 static int matches(const char* key, const char* value) 470 { 471 return !strcmp(key, store.key) && 472 (store.value_regex == NULL || 473 (store.do_not_match ^ 474 !regexec(store.value_regex, value, 0, NULL, 0))); 475 } 476 477 static int store_aux(const char* key, const char* value, void *cb __used) 478 { 479 int section_len; 480 const char *ep; 481 482 switch (store.state) { 483 case KEY_SEEN: 484 if (matches(key, value)) { 485 if (store.seen == 1 && store.multi_replace == 0) { 486 warning("%s has multiple values", key); 487 } else if (store.seen >= MAX_MATCHES) { 488 error("too many matches for %s", key); 489 return 1; 490 } 491 492 store.offset[store.seen] = ftell(config_file); 493 store.seen++; 494 } 495 break; 496 case SECTION_SEEN: 497 /* 498 * What we are looking for is in store.key (both 499 * section and var), and its section part is baselen 500 * long. We found key (again, both section and var). 501 * We would want to know if this key is in the same 502 * section as what we are looking for. We already 503 * know we are in the same section as what should 504 * hold store.key. 505 */ 506 ep = strrchr(key, '.'); 507 section_len = ep - key; 508 509 if ((section_len != store.baselen) || 510 memcmp(key, store.key, section_len+1)) { 511 store.state = SECTION_END_SEEN; 512 break; 513 } 514 515 /* 516 * Do not increment matches: this is no match, but we 517 * just made sure we are in the desired section. 518 */ 519 store.offset[store.seen] = ftell(config_file); 520 /* fallthru */ 521 case SECTION_END_SEEN: 522 case START: 523 if (matches(key, value)) { 524 store.offset[store.seen] = ftell(config_file); 525 store.state = KEY_SEEN; 526 store.seen++; 527 } else { 528 if (strrchr(key, '.') - key == store.baselen && 529 !strncmp(key, store.key, store.baselen)) { 530 store.state = SECTION_SEEN; 531 store.offset[store.seen] = ftell(config_file); 532 } 533 } 534 default: 535 break; 536 } 537 return 0; 538 } 539 540 static int store_write_section(int fd, const char* key) 541 { 542 const char *dot; 543 int i, success; 544 struct strbuf sb = STRBUF_INIT; 545 546 dot = memchr(key, '.', store.baselen); 547 if (dot) { 548 strbuf_addf(&sb, "[%.*s \"", (int)(dot - key), key); 549 for (i = dot - key + 1; i < store.baselen; i++) { 550 if (key[i] == '"' || key[i] == '\\') 551 strbuf_addch(&sb, '\\'); 552 strbuf_addch(&sb, key[i]); 553 } 554 strbuf_addstr(&sb, "\"]\n"); 555 } else { 556 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); 557 } 558 559 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); 560 strbuf_release(&sb); 561 562 return success; 563 } 564 565 static int store_write_pair(int fd, const char* key, const char* value) 566 { 567 int i, success; 568 int length = strlen(key + store.baselen + 1); 569 const char *quote = ""; 570 struct strbuf sb = STRBUF_INIT; 571 572 /* 573 * Check to see if the value needs to be surrounded with a dq pair. 574 * Note that problematic characters are always backslash-quoted; this 575 * check is about not losing leading or trailing SP and strings that 576 * follow beginning-of-comment characters (i.e. ';' and '#') by the 577 * configuration parser. 578 */ 579 if (value[0] == ' ') 580 quote = "\""; 581 for (i = 0; value[i]; i++) 582 if (value[i] == ';' || value[i] == '#') 583 quote = "\""; 584 if (i && value[i - 1] == ' ') 585 quote = "\""; 586 587 strbuf_addf(&sb, "\t%.*s = %s", 588 length, key + store.baselen + 1, quote); 589 590 for (i = 0; value[i]; i++) 591 switch (value[i]) { 592 case '\n': 593 strbuf_addstr(&sb, "\\n"); 594 break; 595 case '\t': 596 strbuf_addstr(&sb, "\\t"); 597 break; 598 case '"': 599 case '\\': 600 strbuf_addch(&sb, '\\'); 601 default: 602 strbuf_addch(&sb, value[i]); 603 break; 604 } 605 strbuf_addf(&sb, "%s\n", quote); 606 607 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len); 608 strbuf_release(&sb); 609 610 return success; 611 } 612 613 static ssize_t find_beginning_of_line(const char* contents, size_t size, 614 size_t offset_, int* found_bracket) 615 { 616 size_t equal_offset = size, bracket_offset = size; 617 ssize_t offset; 618 619 contline: 620 for (offset = offset_-2; offset > 0 621 && contents[offset] != '\n'; offset--) 622 switch (contents[offset]) { 623 case '=': equal_offset = offset; break; 624 case ']': bracket_offset = offset; break; 625 default: break; 626 } 627 if (offset > 0 && contents[offset-1] == '\\') { 628 offset_ = offset; 629 goto contline; 630 } 631 if (bracket_offset < equal_offset) { 632 *found_bracket = 1; 633 offset = bracket_offset+1; 634 } else 635 offset++; 636 637 return offset; 638 } 639 640 int perf_config_set(const char* key, const char* value) 641 { 642 return perf_config_set_multivar(key, value, NULL, 0); 643 } 644 645 /* 646 * If value==NULL, unset in (remove from) config, 647 * if value_regex!=NULL, disregard key/value pairs where value does not match. 648 * if multi_replace==0, nothing, or only one matching key/value is replaced, 649 * else all matching key/values (regardless how many) are removed, 650 * before the new pair is written. 651 * 652 * Returns 0 on success. 653 * 654 * This function does this: 655 * 656 * - it locks the config file by creating ".perf/config.lock" 657 * 658 * - it then parses the config using store_aux() as validator to find 659 * the position on the key/value pair to replace. If it is to be unset, 660 * it must be found exactly once. 661 * 662 * - the config file is mmap()ed and the part before the match (if any) is 663 * written to the lock file, then the changed part and the rest. 664 * 665 * - the config file is removed and the lock file rename()d to it. 666 * 667 */ 668 int perf_config_set_multivar(const char* key, const char* value, 669 const char* value_regex, int multi_replace) 670 { 671 int i, dot; 672 int fd = -1, in_fd; 673 int ret = 0; 674 char* config_filename; 675 const char* last_dot = strrchr(key, '.'); 676 677 if (config_exclusive_filename) 678 config_filename = strdup(config_exclusive_filename); 679 else 680 config_filename = perf_pathdup("config"); 681 682 /* 683 * Since "key" actually contains the section name and the real 684 * key name separated by a dot, we have to know where the dot is. 685 */ 686 687 if (last_dot == NULL) { 688 error("key does not contain a section: %s", key); 689 ret = 2; 690 goto out_free; 691 } 692 store.baselen = last_dot - key; 693 694 store.multi_replace = multi_replace; 695 696 /* 697 * Validate the key and while at it, lower case it for matching. 698 */ 699 store.key = malloc(strlen(key) + 1); 700 dot = 0; 701 for (i = 0; key[i]; i++) { 702 unsigned char c = key[i]; 703 if (c == '.') 704 dot = 1; 705 /* Leave the extended basename untouched.. */ 706 if (!dot || i > store.baselen) { 707 if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) { 708 error("invalid key: %s", key); 709 free(store.key); 710 ret = 1; 711 goto out_free; 712 } 713 c = tolower(c); 714 } else if (c == '\n') { 715 error("invalid key (newline): %s", key); 716 free(store.key); 717 ret = 1; 718 goto out_free; 719 } 720 store.key[i] = c; 721 } 722 store.key[i] = 0; 723 724 /* 725 * If .perf/config does not exist yet, write a minimal version. 726 */ 727 in_fd = open(config_filename, O_RDONLY); 728 if ( in_fd < 0 ) { 729 free(store.key); 730 731 if ( ENOENT != errno ) { 732 error("opening %s: %s", config_filename, 733 strerror(errno)); 734 ret = 3; /* same as "invalid config file" */ 735 goto out_free; 736 } 737 /* if nothing to unset, error out */ 738 if (value == NULL) { 739 ret = 5; 740 goto out_free; 741 } 742 743 store.key = (char*)key; 744 if (!store_write_section(fd, key) || 745 !store_write_pair(fd, key, value)) 746 goto write_err_out; 747 } else { 748 struct stat st; 749 char *contents; 750 ssize_t contents_sz, copy_begin, copy_end; 751 int new_line = 0; 752 753 if (value_regex == NULL) 754 store.value_regex = NULL; 755 else { 756 if (value_regex[0] == '!') { 757 store.do_not_match = 1; 758 value_regex++; 759 } else 760 store.do_not_match = 0; 761 762 store.value_regex = (regex_t*)malloc(sizeof(regex_t)); 763 if (regcomp(store.value_regex, value_regex, 764 REG_EXTENDED)) { 765 error("invalid pattern: %s", value_regex); 766 free(store.value_regex); 767 ret = 6; 768 goto out_free; 769 } 770 } 771 772 store.offset[0] = 0; 773 store.state = START; 774 store.seen = 0; 775 776 /* 777 * After this, store.offset will contain the *end* offset 778 * of the last match, or remain at 0 if no match was found. 779 * As a side effect, we make sure to transform only a valid 780 * existing config file. 781 */ 782 if (perf_config_from_file(store_aux, config_filename, NULL)) { 783 error("invalid config file %s", config_filename); 784 free(store.key); 785 if (store.value_regex != NULL) { 786 regfree(store.value_regex); 787 free(store.value_regex); 788 } 789 ret = 3; 790 goto out_free; 791 } 792 793 free(store.key); 794 if (store.value_regex != NULL) { 795 regfree(store.value_regex); 796 free(store.value_regex); 797 } 798 799 /* if nothing to unset, or too many matches, error out */ 800 if ((store.seen == 0 && value == NULL) || 801 (store.seen > 1 && multi_replace == 0)) { 802 ret = 5; 803 goto out_free; 804 } 805 806 fstat(in_fd, &st); 807 contents_sz = xsize_t(st.st_size); 808 contents = mmap(NULL, contents_sz, PROT_READ, 809 MAP_PRIVATE, in_fd, 0); 810 close(in_fd); 811 812 if (store.seen == 0) 813 store.seen = 1; 814 815 for (i = 0, copy_begin = 0; i < store.seen; i++) { 816 if (store.offset[i] == 0) { 817 store.offset[i] = copy_end = contents_sz; 818 } else if (store.state != KEY_SEEN) { 819 copy_end = store.offset[i]; 820 } else 821 copy_end = find_beginning_of_line( 822 contents, contents_sz, 823 store.offset[i]-2, &new_line); 824 825 if (copy_end > 0 && contents[copy_end-1] != '\n') 826 new_line = 1; 827 828 /* write the first part of the config */ 829 if (copy_end > copy_begin) { 830 if (write_in_full(fd, contents + copy_begin, 831 copy_end - copy_begin) < 832 copy_end - copy_begin) 833 goto write_err_out; 834 if (new_line && 835 write_in_full(fd, "\n", 1) != 1) 836 goto write_err_out; 837 } 838 copy_begin = store.offset[i]; 839 } 840 841 /* write the pair (value == NULL means unset) */ 842 if (value != NULL) { 843 if (store.state == START) { 844 if (!store_write_section(fd, key)) 845 goto write_err_out; 846 } 847 if (!store_write_pair(fd, key, value)) 848 goto write_err_out; 849 } 850 851 /* write the rest of the config */ 852 if (copy_begin < contents_sz) 853 if (write_in_full(fd, contents + copy_begin, 854 contents_sz - copy_begin) < 855 contents_sz - copy_begin) 856 goto write_err_out; 857 858 munmap(contents, contents_sz); 859 } 860 861 ret = 0; 862 863 out_free: 864 free(config_filename); 865 return ret; 866 867 write_err_out: 868 goto out_free; 869 870 } 871 872 /* 873 * Call this to report error for your variable that should not 874 * get a boolean value (i.e. "[my] var" means "true"). 875 */ 876 int config_error_nonbool(const char *var) 877 { 878 return error("Missing value for '%s'", var); 879 } 880