1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 4 */ 5 6 #include <sys/mman.h> 7 #include <sys/stat.h> 8 #include <sys/types.h> 9 #include <ctype.h> 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <limits.h> 13 #include <stdarg.h> 14 #include <stdbool.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <time.h> 19 #include <unistd.h> 20 21 #include <xalloc.h> 22 #include "internal.h" 23 #include "lkc.h" 24 25 struct gstr autoconf_cmd; 26 27 /* return true if 'path' exists, false otherwise */ 28 static bool is_present(const char *path) 29 { 30 struct stat st; 31 32 return !stat(path, &st); 33 } 34 35 /* return true if 'path' exists and it is a directory, false otherwise */ 36 static bool is_dir(const char *path) 37 { 38 struct stat st; 39 40 if (stat(path, &st)) 41 return false; 42 43 return S_ISDIR(st.st_mode); 44 } 45 46 /* return true if the given two files are the same, false otherwise */ 47 static bool is_same(const char *file1, const char *file2) 48 { 49 int fd1, fd2; 50 struct stat st1, st2; 51 void *map1, *map2; 52 bool ret = false; 53 54 fd1 = open(file1, O_RDONLY); 55 if (fd1 < 0) 56 return ret; 57 58 fd2 = open(file2, O_RDONLY); 59 if (fd2 < 0) 60 goto close1; 61 62 ret = fstat(fd1, &st1); 63 if (ret) 64 goto close2; 65 ret = fstat(fd2, &st2); 66 if (ret) 67 goto close2; 68 69 if (st1.st_size != st2.st_size) 70 goto close2; 71 72 map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); 73 if (map1 == MAP_FAILED) 74 goto close2; 75 76 map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0); 77 if (map2 == MAP_FAILED) 78 goto close2; 79 80 if (memcmp(map1, map2, st1.st_size)) 81 goto close2; 82 83 ret = true; 84 close2: 85 close(fd2); 86 close1: 87 close(fd1); 88 89 return ret; 90 } 91 92 /* 93 * Create the parent directory of the given path. 94 * 95 * For example, if 'include/config/auto.conf' is given, create 'include/config'. 96 */ 97 static int make_parent_dir(const char *path) 98 { 99 char tmp[PATH_MAX + 1]; 100 char *p; 101 102 strncpy(tmp, path, sizeof(tmp)); 103 tmp[sizeof(tmp) - 1] = 0; 104 105 /* Remove the base name. Just return if nothing is left */ 106 p = strrchr(tmp, '/'); 107 if (!p) 108 return 0; 109 *(p + 1) = 0; 110 111 /* Just in case it is an absolute path */ 112 p = tmp; 113 while (*p == '/') 114 p++; 115 116 while ((p = strchr(p, '/'))) { 117 *p = 0; 118 119 /* skip if the directory exists */ 120 if (!is_dir(tmp) && mkdir(tmp, 0755)) 121 return -1; 122 123 *p = '/'; 124 while (*p == '/') 125 p++; 126 } 127 128 return 0; 129 } 130 131 static char depfile_path[PATH_MAX]; 132 static size_t depfile_prefix_len; 133 134 /* touch depfile for symbol 'name' */ 135 static int conf_touch_dep(const char *name) 136 { 137 int fd; 138 139 /* check overflow: prefix + name + '\0' must fit in buffer. */ 140 if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path)) 141 return -1; 142 143 strcpy(depfile_path + depfile_prefix_len, name); 144 145 fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); 146 if (fd == -1) 147 return -1; 148 close(fd); 149 150 return 0; 151 } 152 153 static void conf_warning(const char *fmt, ...) 154 __attribute__ ((format (printf, 1, 2))); 155 156 static void conf_message(const char *fmt, ...) 157 __attribute__ ((format (printf, 1, 2))); 158 159 static const char *conf_filename; 160 static int conf_lineno, conf_warnings; 161 162 bool conf_errors(void) 163 { 164 if (conf_warnings) 165 return getenv("KCONFIG_WERROR"); 166 return false; 167 } 168 169 static void conf_warning(const char *fmt, ...) 170 { 171 va_list ap; 172 va_start(ap, fmt); 173 fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); 174 vfprintf(stderr, fmt, ap); 175 fprintf(stderr, "\n"); 176 va_end(ap); 177 conf_warnings++; 178 } 179 180 static void conf_default_message_callback(const char *s) 181 { 182 printf("#\n# "); 183 printf("%s", s); 184 printf("\n#\n"); 185 } 186 187 static void (*conf_message_callback)(const char *s) = 188 conf_default_message_callback; 189 void conf_set_message_callback(void (*fn)(const char *s)) 190 { 191 conf_message_callback = fn; 192 } 193 194 static void conf_message(const char *fmt, ...) 195 { 196 va_list ap; 197 char buf[4096]; 198 199 if (!conf_message_callback) 200 return; 201 202 va_start(ap, fmt); 203 204 vsnprintf(buf, sizeof(buf), fmt, ap); 205 conf_message_callback(buf); 206 va_end(ap); 207 } 208 209 static void conf_changed_input_warning(const char *s) 210 { 211 fputs(s, stderr); 212 } 213 214 static bool conf_warn_changed_input_enabled(void) 215 { 216 const char *env = getenv("KCONFIG_WARN_CHANGED_INPUT"); 217 218 return env && *env; 219 } 220 221 static const char *sym_get_user_value_string(struct symbol *sym) 222 { 223 switch (sym->type) { 224 case S_BOOLEAN: 225 case S_TRISTATE: 226 switch (sym->def[S_DEF_USER].tri) { 227 case yes: 228 return "y"; 229 case mod: 230 return "m"; 231 default: 232 return "n"; 233 } 234 default: 235 return sym->def[S_DEF_USER].val ?: ""; 236 } 237 } 238 239 static bool sym_user_value_changed(struct symbol *sym) 240 { 241 if (!sym_has_value(sym) || sym->type == S_UNKNOWN) 242 return false; 243 244 switch (sym->type) { 245 case S_BOOLEAN: 246 case S_TRISTATE: 247 return sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym); 248 default: 249 return strcmp(sym_get_user_value_string(sym), 250 sym_get_string_value(sym)); 251 } 252 } 253 254 static void conf_clear_written_flags(void) 255 { 256 struct symbol *sym; 257 258 for_all_symbols(sym) 259 sym->flags &= ~SYMBOL_WRITTEN; 260 } 261 262 static void conf_append_changed_input_warning(struct gstr *gs, 263 struct symbol *sym, 264 bool *changed_input_found) 265 { 266 if (!sym_user_value_changed(sym)) 267 return; 268 269 if (!*changed_input_found) { 270 str_printf(gs, 271 "warning: user-provided values changed by Kconfig:\n"); 272 *changed_input_found = true; 273 } 274 275 str_printf(gs, " %s%s: %s -> %s\n", 276 CONFIG_, sym->name, 277 sym_get_user_value_string(sym), 278 sym_get_string_value(sym)); 279 } 280 281 const char *conf_get_configname(void) 282 { 283 char *name = getenv("KCONFIG_CONFIG"); 284 285 return name ? name : ".config"; 286 } 287 288 static const char *conf_get_autoconfig_name(void) 289 { 290 char *name = getenv("KCONFIG_AUTOCONFIG"); 291 292 return name ? name : "include/config/auto.conf"; 293 } 294 295 static const char *conf_get_autoheader_name(void) 296 { 297 char *name = getenv("KCONFIG_AUTOHEADER"); 298 299 return name ? name : "include/generated/autoconf.h"; 300 } 301 302 static const char *conf_get_rustccfg_name(void) 303 { 304 char *name = getenv("KCONFIG_RUSTCCFG"); 305 306 return name ? name : "include/generated/rustc_cfg"; 307 } 308 309 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) 310 { 311 char *p2; 312 313 switch (sym->type) { 314 case S_TRISTATE: 315 if (p[0] == 'm') { 316 sym->def[def].tri = mod; 317 sym->flags |= def_flags; 318 break; 319 } 320 /* fall through */ 321 case S_BOOLEAN: 322 if (p[0] == 'y') { 323 sym->def[def].tri = yes; 324 sym->flags |= def_flags; 325 break; 326 } 327 if (p[0] == 'n') { 328 sym->def[def].tri = no; 329 sym->flags |= def_flags; 330 break; 331 } 332 if (def != S_DEF_AUTO) 333 conf_warning("symbol value '%s' invalid for %s", 334 p, sym->name); 335 return 1; 336 case S_STRING: 337 /* No escaping for S_DEF_AUTO (include/config/auto.conf) */ 338 if (def != S_DEF_AUTO) { 339 if (*p++ != '"') 340 break; 341 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { 342 if (*p2 == '"') { 343 *p2 = 0; 344 break; 345 } 346 memmove(p2, p2 + 1, strlen(p2)); 347 } 348 if (!p2) { 349 conf_warning("invalid string found"); 350 return 1; 351 } 352 } 353 /* fall through */ 354 case S_INT: 355 case S_HEX: 356 if (sym_string_valid(sym, p)) { 357 if (def != S_DEF_AUTO && 358 !sym_string_check_bounds(sym, p)) 359 /* hex uses 64-bit unsigned integer */ 360 conf_warning("value '%s' for %s is outside the 64-bit %s integer bounds", 361 p, sym->name, 362 sym->type == S_INT ? "signed" : "unsigned"); 363 sym->def[def].val = xstrdup(p); 364 sym->flags |= def_flags; 365 } else { 366 if (def != S_DEF_AUTO) 367 conf_warning("symbol value '%s' invalid for %s", 368 p, sym->name); 369 return 1; 370 } 371 break; 372 default: 373 ; 374 } 375 return 0; 376 } 377 378 /* like getline(), but the newline character is stripped away */ 379 static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream) 380 { 381 ssize_t len; 382 383 len = getline(lineptr, n, stream); 384 385 if (len > 0 && (*lineptr)[len - 1] == '\n') { 386 len--; 387 (*lineptr)[len] = '\0'; 388 389 if (len > 0 && (*lineptr)[len - 1] == '\r') { 390 len--; 391 (*lineptr)[len] = '\0'; 392 } 393 } 394 395 return len; 396 } 397 398 int conf_read_simple(const char *name, int def) 399 { 400 FILE *in = NULL; 401 char *line = NULL; 402 size_t line_asize = 0; 403 char *p, *val; 404 struct symbol *sym; 405 int def_flags; 406 const char *warn_unknown, *sym_name; 407 408 warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS"); 409 if (name) { 410 in = zconf_fopen(name); 411 } else { 412 char *env; 413 414 name = conf_get_configname(); 415 in = zconf_fopen(name); 416 if (in) 417 goto load; 418 conf_set_changed(true); 419 420 env = getenv("KCONFIG_DEFCONFIG_LIST"); 421 if (!env) 422 return 1; 423 424 while (1) { 425 bool is_last; 426 427 while (isspace(*env)) 428 env++; 429 430 if (!*env) 431 break; 432 433 p = env; 434 while (*p && !isspace(*p)) 435 p++; 436 437 is_last = (*p == '\0'); 438 439 *p = '\0'; 440 441 name = env; 442 443 in = zconf_fopen(name); 444 if (in) { 445 conf_message("using defaults found in %s", 446 name); 447 goto load; 448 } 449 450 if (is_last) 451 break; 452 453 env = p + 1; 454 } 455 } 456 if (!in) 457 return 1; 458 459 load: 460 conf_filename = name; 461 conf_lineno = 0; 462 conf_warnings = 0; 463 464 def_flags = SYMBOL_DEF << def; 465 for_all_symbols(sym) { 466 sym->flags &= ~def_flags; 467 switch (sym->type) { 468 case S_INT: 469 case S_HEX: 470 case S_STRING: 471 free(sym->def[def].val); 472 /* fall through */ 473 default: 474 sym->def[def].val = NULL; 475 sym->def[def].tri = no; 476 } 477 } 478 479 if (def == S_DEF_USER) { 480 for_all_symbols(sym) 481 sym->flags &= ~SYMBOL_VALID; 482 expr_invalidate_all(); 483 } 484 485 while (getline_stripped(&line, &line_asize, in) != -1) { 486 struct menu *choice; 487 488 conf_lineno++; 489 490 if (!line[0]) /* blank line */ 491 continue; 492 493 if (line[0] == '#') { 494 if (line[1] != ' ') 495 continue; 496 p = line + 2; 497 if (memcmp(p, CONFIG_, strlen(CONFIG_))) 498 continue; 499 sym_name = p + strlen(CONFIG_); 500 p = strchr(sym_name, ' '); 501 if (!p) 502 continue; 503 *p++ = 0; 504 if (strcmp(p, "is not set")) 505 continue; 506 507 val = "n"; 508 } else { 509 if (memcmp(line, CONFIG_, strlen(CONFIG_))) { 510 conf_warning("unexpected data: %s", line); 511 continue; 512 } 513 514 sym_name = line + strlen(CONFIG_); 515 p = strchr(sym_name, '='); 516 if (!p) { 517 conf_warning("unexpected data: %s", line); 518 continue; 519 } 520 *p = 0; 521 val = p + 1; 522 } 523 524 sym = sym_find(sym_name); 525 if (!sym) { 526 if (def == S_DEF_AUTO) { 527 /* 528 * Reading from include/config/auto.conf. 529 * If CONFIG_FOO previously existed in auto.conf 530 * but it is missing now, include/config/FOO 531 * must be touched. 532 */ 533 conf_touch_dep(sym_name); 534 } else { 535 if (warn_unknown) 536 conf_warning("unknown symbol: %s", sym_name); 537 538 conf_set_changed(true); 539 } 540 continue; 541 } 542 543 if (sym->flags & def_flags) 544 conf_warning("override: reassigning to symbol %s", sym->name); 545 546 if (conf_set_sym_val(sym, def, def_flags, val)) 547 continue; 548 549 if (def != S_DEF_USER) 550 continue; 551 552 /* 553 * If this is a choice member, give it the highest priority. 554 * If conflicting CONFIG options are given from an input file, 555 * the last one wins. 556 */ 557 choice = sym_get_choice_menu(sym); 558 if (choice) 559 list_move(&sym->choice_link, &choice->choice_members); 560 } 561 free(line); 562 fclose(in); 563 564 return 0; 565 } 566 567 int conf_read(const char *name) 568 { 569 struct symbol *sym; 570 571 conf_set_changed(false); 572 573 if (conf_read_simple(name, S_DEF_USER)) { 574 sym_calc_value(modules_sym); 575 return 1; 576 } 577 578 sym_calc_value(modules_sym); 579 580 for_all_symbols(sym) { 581 sym_calc_value(sym); 582 if (sym_is_choice(sym)) 583 continue; 584 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { 585 /* check that calculated value agrees with saved value */ 586 switch (sym->type) { 587 case S_BOOLEAN: 588 case S_TRISTATE: 589 if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym)) 590 continue; 591 break; 592 default: 593 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) 594 continue; 595 break; 596 } 597 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) 598 /* no previous value and not saved */ 599 continue; 600 conf_set_changed(true); 601 /* maybe print value in verbose mode... */ 602 } 603 604 if (conf_warnings) 605 conf_set_changed(true); 606 607 return 0; 608 } 609 610 struct comment_style { 611 const char *decoration; 612 const char *prefix; 613 const char *postfix; 614 }; 615 616 static const struct comment_style comment_style_pound = { 617 .decoration = "#", 618 .prefix = "#", 619 .postfix = "#", 620 }; 621 622 static const struct comment_style comment_style_c = { 623 .decoration = " *", 624 .prefix = "/*", 625 .postfix = " */", 626 }; 627 628 static void conf_write_heading(FILE *fp, const struct comment_style *cs) 629 { 630 if (!cs) 631 return; 632 633 fprintf(fp, "%s\n", cs->prefix); 634 635 fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n", 636 cs->decoration); 637 638 fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text); 639 640 fprintf(fp, "%s\n", cs->postfix); 641 } 642 643 /* The returned pointer must be freed on the caller side */ 644 static char *escape_string_value(const char *in) 645 { 646 const char *p; 647 char *out; 648 size_t len; 649 650 len = strlen(in) + strlen("\"\"") + 1; 651 652 p = in; 653 while (1) { 654 p += strcspn(p, "\"\\"); 655 656 if (p[0] == '\0') 657 break; 658 659 len++; 660 p++; 661 } 662 663 out = xmalloc(len); 664 out[0] = '\0'; 665 666 strcat(out, "\""); 667 668 p = in; 669 while (1) { 670 len = strcspn(p, "\"\\"); 671 strncat(out, p, len); 672 p += len; 673 674 if (p[0] == '\0') 675 break; 676 677 strcat(out, "\\"); 678 strncat(out, p++, 1); 679 } 680 681 strcat(out, "\""); 682 683 return out; 684 } 685 686 enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE }; 687 688 static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n, 689 bool escape_string) 690 { 691 const char *val; 692 char *escaped = NULL; 693 694 if (sym->type == S_UNKNOWN) 695 return; 696 697 val = sym_get_string_value(sym); 698 699 if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) && 700 output_n != OUTPUT_N && *val == 'n') { 701 if (output_n == OUTPUT_N_AS_UNSET) 702 fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name); 703 return; 704 } 705 706 if (sym->type == S_STRING && escape_string) { 707 escaped = escape_string_value(val); 708 val = escaped; 709 } 710 711 fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val); 712 713 free(escaped); 714 } 715 716 static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym) 717 { 718 __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true); 719 } 720 721 static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym) 722 { 723 __print_symbol(fp, sym, OUTPUT_N_NONE, false); 724 } 725 726 void print_symbol_for_listconfig(struct symbol *sym) 727 { 728 __print_symbol(stdout, sym, OUTPUT_N, true); 729 } 730 731 static void print_symbol_for_c(FILE *fp, struct symbol *sym) 732 { 733 const char *val; 734 const char *sym_suffix = ""; 735 const char *val_prefix = ""; 736 char *escaped = NULL; 737 738 if (sym->type == S_UNKNOWN) 739 return; 740 741 val = sym_get_string_value(sym); 742 743 switch (sym->type) { 744 case S_BOOLEAN: 745 case S_TRISTATE: 746 switch (*val) { 747 case 'n': 748 return; 749 case 'm': 750 sym_suffix = "_MODULE"; 751 /* fall through */ 752 default: 753 val = "1"; 754 } 755 break; 756 case S_HEX: 757 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X')) 758 val_prefix = "0x"; 759 break; 760 case S_STRING: 761 escaped = escape_string_value(val); 762 val = escaped; 763 default: 764 break; 765 } 766 767 fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix, 768 val_prefix, val); 769 770 free(escaped); 771 } 772 773 static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym) 774 { 775 const char *val; 776 const char *val_prefix = ""; 777 char *val_prefixed = NULL; 778 size_t val_prefixed_len; 779 char *escaped = NULL; 780 781 if (sym->type == S_UNKNOWN) 782 return; 783 784 val = sym_get_string_value(sym); 785 786 switch (sym->type) { 787 case S_BOOLEAN: 788 case S_TRISTATE: 789 /* 790 * We do not care about disabled ones, i.e. no need for 791 * what otherwise are "comments" in other printers. 792 */ 793 if (*val == 'n') 794 return; 795 796 /* 797 * To have similar functionality to the C macro `IS_ENABLED()` 798 * we provide an empty `--cfg CONFIG_X` here in both `y` 799 * and `m` cases. 800 * 801 * Then, the common `fprintf()` below will also give us 802 * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can 803 * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`. 804 */ 805 fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name); 806 break; 807 case S_HEX: 808 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X')) 809 val_prefix = "0x"; 810 break; 811 default: 812 break; 813 } 814 815 if (strlen(val_prefix) > 0) { 816 val_prefixed_len = strlen(val) + strlen(val_prefix) + 1; 817 val_prefixed = xmalloc(val_prefixed_len); 818 snprintf(val_prefixed, val_prefixed_len, "%s%s", val_prefix, val); 819 val = val_prefixed; 820 } 821 822 /* All values get escaped: the `--cfg` option only takes strings */ 823 escaped = escape_string_value(val); 824 val = escaped; 825 826 fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val); 827 828 free(escaped); 829 free(val_prefixed); 830 } 831 832 /* 833 * Write out a minimal config. 834 * All values that has default values are skipped as this is redundant. 835 */ 836 int conf_write_defconfig(const char *filename) 837 { 838 struct symbol *sym; 839 struct menu *menu; 840 struct gstr gs; 841 FILE *out; 842 bool warn_changed_input = conf_warn_changed_input_enabled(); 843 bool changed_input_found = false; 844 845 out = fopen(filename, "w"); 846 if (!out) 847 return 1; 848 gs = str_new(); 849 850 sym_clear_all_valid(); 851 852 menu_for_each_entry(menu) { 853 struct menu *choice; 854 855 sym = menu->sym; 856 857 if (!sym || sym_is_choice(sym) || sym->flags & SYMBOL_WRITTEN) 858 continue; 859 860 sym_calc_value(sym); 861 if (warn_changed_input) 862 conf_append_changed_input_warning(&gs, sym, 863 &changed_input_found); 864 sym->flags |= SYMBOL_WRITTEN; 865 if (!(sym->flags & SYMBOL_WRITE)) 866 continue; 867 sym->flags &= ~SYMBOL_WRITE; 868 /* Skip unchangeable symbols */ 869 if (!sym_is_changeable(sym)) 870 continue; 871 /* Skip symbols that are equal to the default */ 872 if (!strcmp(sym_get_string_value(sym), sym_get_string_default(sym))) 873 continue; 874 875 /* Skip choice values that are equal to the default */ 876 choice = sym_get_choice_menu(sym); 877 if (choice) { 878 struct symbol *ds; 879 880 ds = sym_choice_default(choice); 881 if (sym == ds && sym_get_tristate_value(sym) == yes) 882 continue; 883 } 884 print_symbol_for_dotconfig(out, sym); 885 } 886 fclose(out); 887 888 conf_clear_written_flags(); 889 890 if (changed_input_found) 891 conf_changed_input_warning(str_get(&gs)); 892 893 str_free(&gs); 894 return 0; 895 } 896 897 int conf_write(const char *name) 898 { 899 FILE *out; 900 struct symbol *sym; 901 struct menu *menu; 902 const char *str; 903 char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; 904 char *env; 905 struct gstr gs; 906 bool need_newline = false; 907 bool warn_changed_input = conf_warn_changed_input_enabled(); 908 bool changed_input_found = false; 909 910 if (!name) 911 name = conf_get_configname(); 912 913 if (!*name) { 914 fprintf(stderr, "config name is empty\n"); 915 return -1; 916 } 917 918 if (is_dir(name)) { 919 fprintf(stderr, "%s: Is a directory\n", name); 920 return -1; 921 } 922 923 if (make_parent_dir(name)) 924 return -1; 925 926 env = getenv("KCONFIG_OVERWRITECONFIG"); 927 if (env && *env) { 928 *tmpname = 0; 929 out = fopen(name, "w"); 930 } else { 931 snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp", 932 name, (int)getpid()); 933 out = fopen(tmpname, "w"); 934 } 935 if (!out) 936 return 1; 937 gs = str_new(); 938 939 conf_write_heading(out, &comment_style_pound); 940 941 if (!conf_get_changed()) 942 sym_clear_all_valid(); 943 944 menu = rootmenu.list; 945 while (menu) { 946 sym = menu->sym; 947 if (!sym) { 948 if (!menu_is_visible(menu)) 949 goto next; 950 str = menu_get_prompt(menu); 951 fprintf(out, "\n" 952 "#\n" 953 "# %s\n" 954 "#\n", str); 955 need_newline = false; 956 } else if (!sym_is_choice(sym) && 957 !(sym->flags & SYMBOL_WRITTEN)) { 958 sym_calc_value(sym); 959 if (warn_changed_input) 960 conf_append_changed_input_warning(&gs, sym, 961 &changed_input_found); 962 sym->flags |= SYMBOL_WRITTEN; 963 if (!(sym->flags & SYMBOL_WRITE)) 964 goto next; 965 if (need_newline) { 966 fprintf(out, "\n"); 967 need_newline = false; 968 } 969 print_symbol_for_dotconfig(out, sym); 970 } 971 972 next: 973 if (menu->list) { 974 menu = menu->list; 975 continue; 976 } 977 978 end_check: 979 if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu && 980 menu->prompt->type == P_MENU) { 981 fprintf(out, "# end of %s\n", menu_get_prompt(menu)); 982 need_newline = true; 983 } 984 985 if (menu->next) { 986 menu = menu->next; 987 } else { 988 menu = menu->parent; 989 if (menu) 990 goto end_check; 991 } 992 } 993 fclose(out); 994 995 conf_clear_written_flags(); 996 997 if (changed_input_found) 998 conf_changed_input_warning(str_get(&gs)); 999 1000 str_free(&gs); 1001 1002 if (*tmpname) { 1003 if (is_same(name, tmpname)) { 1004 conf_message("No change to %s", name); 1005 unlink(tmpname); 1006 conf_set_changed(false); 1007 return 0; 1008 } 1009 1010 snprintf(oldname, sizeof(oldname), "%s.old", name); 1011 rename(name, oldname); 1012 if (rename(tmpname, name)) 1013 return 1; 1014 } 1015 1016 conf_message("configuration written to %s", name); 1017 1018 conf_set_changed(false); 1019 1020 return 0; 1021 } 1022 1023 /* write a dependency file as used by kbuild to track dependencies */ 1024 static int conf_write_autoconf_cmd(const char *autoconf_name) 1025 { 1026 char name[PATH_MAX], tmp[PATH_MAX]; 1027 FILE *out; 1028 int ret; 1029 1030 ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name); 1031 if (ret >= sizeof(name)) /* check truncation */ 1032 return -1; 1033 1034 if (make_parent_dir(name)) 1035 return -1; 1036 1037 ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name); 1038 if (ret >= sizeof(tmp)) /* check truncation */ 1039 return -1; 1040 1041 out = fopen(tmp, "w"); 1042 if (!out) { 1043 perror("fopen"); 1044 return -1; 1045 } 1046 1047 fprintf(out, "autoconfig := %s\n", autoconf_name); 1048 1049 fputs(str_get(&autoconf_cmd), out); 1050 1051 fflush(out); 1052 ret = ferror(out); /* error check for all fprintf() calls */ 1053 fclose(out); 1054 if (ret) 1055 return -1; 1056 1057 if (rename(tmp, name)) { 1058 perror("rename"); 1059 return -1; 1060 } 1061 1062 return 0; 1063 } 1064 1065 static int conf_touch_deps(void) 1066 { 1067 const char *name, *tmp; 1068 struct symbol *sym; 1069 int res; 1070 1071 name = conf_get_autoconfig_name(); 1072 tmp = strrchr(name, '/'); 1073 depfile_prefix_len = tmp ? tmp - name + 1 : 0; 1074 if (depfile_prefix_len + 1 > sizeof(depfile_path)) 1075 return -1; 1076 1077 strncpy(depfile_path, name, depfile_prefix_len); 1078 depfile_path[depfile_prefix_len] = 0; 1079 1080 conf_read_simple(name, S_DEF_AUTO); 1081 1082 for_all_symbols(sym) { 1083 if (sym_is_choice(sym)) 1084 continue; 1085 if (sym->flags & SYMBOL_WRITE) { 1086 if (sym->flags & SYMBOL_DEF_AUTO) { 1087 /* 1088 * symbol has old and new value, 1089 * so compare them... 1090 */ 1091 switch (sym->type) { 1092 case S_BOOLEAN: 1093 case S_TRISTATE: 1094 if (sym_get_tristate_value(sym) == 1095 sym->def[S_DEF_AUTO].tri) 1096 continue; 1097 break; 1098 case S_STRING: 1099 case S_HEX: 1100 case S_INT: 1101 if (!strcmp(sym_get_string_value(sym), 1102 sym->def[S_DEF_AUTO].val)) 1103 continue; 1104 break; 1105 default: 1106 break; 1107 } 1108 } else { 1109 /* 1110 * If there is no old value, only 'no' (unset) 1111 * is allowed as new value. 1112 */ 1113 switch (sym->type) { 1114 case S_BOOLEAN: 1115 case S_TRISTATE: 1116 if (sym_get_tristate_value(sym) == no) 1117 continue; 1118 break; 1119 default: 1120 break; 1121 } 1122 } 1123 } else if (!(sym->flags & SYMBOL_DEF_AUTO)) 1124 /* There is neither an old nor a new value. */ 1125 continue; 1126 /* else 1127 * There is an old value, but no new value ('no' (unset) 1128 * isn't saved in auto.conf, so the old value is always 1129 * different from 'no'). 1130 */ 1131 1132 res = conf_touch_dep(sym->name); 1133 if (res) 1134 return res; 1135 } 1136 1137 return 0; 1138 } 1139 1140 static int __conf_write_autoconf(const char *filename, 1141 void (*print_symbol)(FILE *, struct symbol *), 1142 const struct comment_style *comment_style) 1143 { 1144 char tmp[PATH_MAX]; 1145 FILE *file; 1146 struct symbol *sym; 1147 int ret; 1148 1149 if (make_parent_dir(filename)) 1150 return -1; 1151 1152 ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename); 1153 if (ret >= sizeof(tmp)) /* check truncation */ 1154 return -1; 1155 1156 file = fopen(tmp, "w"); 1157 if (!file) { 1158 perror("fopen"); 1159 return -1; 1160 } 1161 1162 conf_write_heading(file, comment_style); 1163 1164 for_all_symbols(sym) 1165 if ((sym->flags & SYMBOL_WRITE) && sym->name) 1166 print_symbol(file, sym); 1167 1168 fflush(file); 1169 /* check possible errors in conf_write_heading() and print_symbol() */ 1170 ret = ferror(file); 1171 fclose(file); 1172 if (ret) 1173 return -1; 1174 1175 if (rename(tmp, filename)) { 1176 perror("rename"); 1177 return -1; 1178 } 1179 1180 return 0; 1181 } 1182 1183 int conf_write_autoconf(int overwrite) 1184 { 1185 struct symbol *sym; 1186 const char *autoconf_name = conf_get_autoconfig_name(); 1187 int ret; 1188 1189 if (!overwrite && is_present(autoconf_name)) 1190 return 0; 1191 1192 ret = conf_write_autoconf_cmd(autoconf_name); 1193 if (ret) 1194 return -1; 1195 1196 for_all_symbols(sym) 1197 sym_calc_value(sym); 1198 1199 if (conf_touch_deps()) 1200 return 1; 1201 1202 ret = __conf_write_autoconf(conf_get_autoheader_name(), 1203 print_symbol_for_c, 1204 &comment_style_c); 1205 if (ret) 1206 return ret; 1207 1208 ret = __conf_write_autoconf(conf_get_rustccfg_name(), 1209 print_symbol_for_rustccfg, 1210 NULL); 1211 if (ret) 1212 return ret; 1213 1214 /* 1215 * Create include/config/auto.conf. This must be the last step because 1216 * Kbuild has a dependency on auto.conf and this marks the successful 1217 * completion of the previous steps. 1218 */ 1219 ret = __conf_write_autoconf(conf_get_autoconfig_name(), 1220 print_symbol_for_autoconf, 1221 &comment_style_pound); 1222 if (ret) 1223 return ret; 1224 1225 return 0; 1226 } 1227 1228 static bool conf_changed; 1229 static void (*conf_changed_callback)(bool); 1230 1231 void conf_set_changed(bool val) 1232 { 1233 if (conf_changed_callback && conf_changed != val) 1234 conf_changed_callback(val); 1235 1236 conf_changed = val; 1237 } 1238 1239 bool conf_get_changed(void) 1240 { 1241 return conf_changed; 1242 } 1243 1244 void conf_set_changed_callback(void (*fn)(bool)) 1245 { 1246 conf_changed_callback = fn; 1247 } 1248