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 */
is_present(const char * path)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 */
is_dir(const char * path)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 */
is_same(const char * file1,const char * file2)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 */
make_parent_dir(const char * path)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' */
conf_touch_dep(const char * 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
conf_errors(void)162 bool conf_errors(void)
163 {
164 if (conf_warnings)
165 return getenv("KCONFIG_WERROR");
166 return false;
167 }
168
conf_warning(const char * fmt,...)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
conf_default_message_callback(const char * s)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;
conf_set_message_callback(void (* fn)(const char * s))189 void conf_set_message_callback(void (*fn)(const char *s))
190 {
191 conf_message_callback = fn;
192 }
193
conf_message(const char * fmt,...)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
conf_changed_input_warning(const char * s)209 static void conf_changed_input_warning(const char *s)
210 {
211 fputs(s, stderr);
212 }
213
conf_warn_changed_input_enabled(void)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
sym_get_user_value_string(struct symbol * sym)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
sym_user_value_changed(struct symbol * sym)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
conf_clear_written_flags(void)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
conf_append_changed_input_warning(struct gstr * gs,struct symbol * sym,bool * changed_input_found)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
conf_get_configname(void)281 const char *conf_get_configname(void)
282 {
283 char *name = getenv("KCONFIG_CONFIG");
284
285 return name ? name : ".config";
286 }
287
conf_get_autoconfig_name(void)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
conf_get_autoheader_name(void)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
conf_get_rustccfg_name(void)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
conf_set_sym_val(struct symbol * sym,int def,int def_flags,char * p)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 sym->def[def].val = xstrdup(p);
358 sym->flags |= def_flags;
359 } else {
360 if (def != S_DEF_AUTO)
361 conf_warning("symbol value '%s' invalid for %s",
362 p, sym->name);
363 return 1;
364 }
365 break;
366 default:
367 ;
368 }
369 return 0;
370 }
371
372 /* like getline(), but the newline character is stripped away */
getline_stripped(char ** lineptr,size_t * n,FILE * stream)373 static ssize_t getline_stripped(char **lineptr, size_t *n, FILE *stream)
374 {
375 ssize_t len;
376
377 len = getline(lineptr, n, stream);
378
379 if (len > 0 && (*lineptr)[len - 1] == '\n') {
380 len--;
381 (*lineptr)[len] = '\0';
382
383 if (len > 0 && (*lineptr)[len - 1] == '\r') {
384 len--;
385 (*lineptr)[len] = '\0';
386 }
387 }
388
389 return len;
390 }
391
conf_read_simple(const char * name,int def)392 int conf_read_simple(const char *name, int def)
393 {
394 FILE *in = NULL;
395 char *line = NULL;
396 size_t line_asize = 0;
397 char *p, *val;
398 struct symbol *sym;
399 int def_flags;
400 const char *warn_unknown, *sym_name;
401
402 warn_unknown = getenv("KCONFIG_WARN_UNKNOWN_SYMBOLS");
403 if (name) {
404 in = zconf_fopen(name);
405 } else {
406 char *env;
407
408 name = conf_get_configname();
409 in = zconf_fopen(name);
410 if (in)
411 goto load;
412 conf_set_changed(true);
413
414 env = getenv("KCONFIG_DEFCONFIG_LIST");
415 if (!env)
416 return 1;
417
418 while (1) {
419 bool is_last;
420
421 while (isspace(*env))
422 env++;
423
424 if (!*env)
425 break;
426
427 p = env;
428 while (*p && !isspace(*p))
429 p++;
430
431 is_last = (*p == '\0');
432
433 *p = '\0';
434
435 name = env;
436
437 in = zconf_fopen(name);
438 if (in) {
439 conf_message("using defaults found in %s",
440 name);
441 goto load;
442 }
443
444 if (is_last)
445 break;
446
447 env = p + 1;
448 }
449 }
450 if (!in)
451 return 1;
452
453 load:
454 conf_filename = name;
455 conf_lineno = 0;
456 conf_warnings = 0;
457
458 def_flags = SYMBOL_DEF << def;
459 for_all_symbols(sym) {
460 sym->flags &= ~def_flags;
461 switch (sym->type) {
462 case S_INT:
463 case S_HEX:
464 case S_STRING:
465 free(sym->def[def].val);
466 /* fall through */
467 default:
468 sym->def[def].val = NULL;
469 sym->def[def].tri = no;
470 }
471 }
472
473 if (def == S_DEF_USER) {
474 for_all_symbols(sym)
475 sym->flags &= ~SYMBOL_VALID;
476 expr_invalidate_all();
477 }
478
479 while (getline_stripped(&line, &line_asize, in) != -1) {
480 struct menu *choice;
481
482 conf_lineno++;
483
484 if (!line[0]) /* blank line */
485 continue;
486
487 if (line[0] == '#') {
488 if (line[1] != ' ')
489 continue;
490 p = line + 2;
491 if (memcmp(p, CONFIG_, strlen(CONFIG_)))
492 continue;
493 sym_name = p + strlen(CONFIG_);
494 p = strchr(sym_name, ' ');
495 if (!p)
496 continue;
497 *p++ = 0;
498 if (strcmp(p, "is not set"))
499 continue;
500
501 val = "n";
502 } else {
503 if (memcmp(line, CONFIG_, strlen(CONFIG_))) {
504 conf_warning("unexpected data: %s", line);
505 continue;
506 }
507
508 sym_name = line + strlen(CONFIG_);
509 p = strchr(sym_name, '=');
510 if (!p) {
511 conf_warning("unexpected data: %s", line);
512 continue;
513 }
514 *p = 0;
515 val = p + 1;
516 }
517
518 sym = sym_find(sym_name);
519 if (!sym) {
520 if (def == S_DEF_AUTO) {
521 /*
522 * Reading from include/config/auto.conf.
523 * If CONFIG_FOO previously existed in auto.conf
524 * but it is missing now, include/config/FOO
525 * must be touched.
526 */
527 conf_touch_dep(sym_name);
528 } else {
529 if (warn_unknown)
530 conf_warning("unknown symbol: %s", sym_name);
531
532 conf_set_changed(true);
533 }
534 continue;
535 }
536
537 if (sym->flags & def_flags)
538 conf_warning("override: reassigning to symbol %s", sym->name);
539
540 if (conf_set_sym_val(sym, def, def_flags, val))
541 continue;
542
543 if (def != S_DEF_USER)
544 continue;
545
546 /*
547 * If this is a choice member, give it the highest priority.
548 * If conflicting CONFIG options are given from an input file,
549 * the last one wins.
550 */
551 choice = sym_get_choice_menu(sym);
552 if (choice)
553 list_move(&sym->choice_link, &choice->choice_members);
554 }
555 free(line);
556 fclose(in);
557
558 return 0;
559 }
560
conf_read(const char * name)561 int conf_read(const char *name)
562 {
563 struct symbol *sym;
564
565 conf_set_changed(false);
566
567 if (conf_read_simple(name, S_DEF_USER)) {
568 sym_calc_value(modules_sym);
569 return 1;
570 }
571
572 sym_calc_value(modules_sym);
573
574 for_all_symbols(sym) {
575 sym_calc_value(sym);
576 if (sym_is_choice(sym))
577 continue;
578 if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
579 /* check that calculated value agrees with saved value */
580 switch (sym->type) {
581 case S_BOOLEAN:
582 case S_TRISTATE:
583 if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
584 continue;
585 break;
586 default:
587 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
588 continue;
589 break;
590 }
591 } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
592 /* no previous value and not saved */
593 continue;
594 conf_set_changed(true);
595 /* maybe print value in verbose mode... */
596 }
597
598 if (conf_warnings)
599 conf_set_changed(true);
600
601 return 0;
602 }
603
604 struct comment_style {
605 const char *decoration;
606 const char *prefix;
607 const char *postfix;
608 };
609
610 static const struct comment_style comment_style_pound = {
611 .decoration = "#",
612 .prefix = "#",
613 .postfix = "#",
614 };
615
616 static const struct comment_style comment_style_c = {
617 .decoration = " *",
618 .prefix = "/*",
619 .postfix = " */",
620 };
621
conf_write_heading(FILE * fp,const struct comment_style * cs)622 static void conf_write_heading(FILE *fp, const struct comment_style *cs)
623 {
624 if (!cs)
625 return;
626
627 fprintf(fp, "%s\n", cs->prefix);
628
629 fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
630 cs->decoration);
631
632 fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
633
634 fprintf(fp, "%s\n", cs->postfix);
635 }
636
637 /* The returned pointer must be freed on the caller side */
escape_string_value(const char * in)638 static char *escape_string_value(const char *in)
639 {
640 const char *p;
641 char *out;
642 size_t len;
643
644 len = strlen(in) + strlen("\"\"") + 1;
645
646 p = in;
647 while (1) {
648 p += strcspn(p, "\"\\");
649
650 if (p[0] == '\0')
651 break;
652
653 len++;
654 p++;
655 }
656
657 out = xmalloc(len);
658 out[0] = '\0';
659
660 strcat(out, "\"");
661
662 p = in;
663 while (1) {
664 len = strcspn(p, "\"\\");
665 strncat(out, p, len);
666 p += len;
667
668 if (p[0] == '\0')
669 break;
670
671 strcat(out, "\\");
672 strncat(out, p++, 1);
673 }
674
675 strcat(out, "\"");
676
677 return out;
678 }
679
680 enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
681
__print_symbol(FILE * fp,struct symbol * sym,enum output_n output_n,bool escape_string)682 static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
683 bool escape_string)
684 {
685 const char *val;
686 char *escaped = NULL;
687
688 if (sym->type == S_UNKNOWN)
689 return;
690
691 val = sym_get_string_value(sym);
692
693 if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
694 output_n != OUTPUT_N && *val == 'n') {
695 if (output_n == OUTPUT_N_AS_UNSET)
696 fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
697 return;
698 }
699
700 if (sym->type == S_STRING && escape_string) {
701 escaped = escape_string_value(val);
702 val = escaped;
703 }
704
705 fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
706
707 free(escaped);
708 }
709
print_symbol_for_dotconfig(FILE * fp,struct symbol * sym)710 static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
711 {
712 __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
713 }
714
print_symbol_for_autoconf(FILE * fp,struct symbol * sym)715 static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
716 {
717 __print_symbol(fp, sym, OUTPUT_N_NONE, false);
718 }
719
print_symbol_for_listconfig(struct symbol * sym)720 void print_symbol_for_listconfig(struct symbol *sym)
721 {
722 __print_symbol(stdout, sym, OUTPUT_N, true);
723 }
724
print_symbol_for_c(FILE * fp,struct symbol * sym)725 static void print_symbol_for_c(FILE *fp, struct symbol *sym)
726 {
727 const char *val;
728 const char *sym_suffix = "";
729 const char *val_prefix = "";
730 char *escaped = NULL;
731
732 if (sym->type == S_UNKNOWN)
733 return;
734
735 val = sym_get_string_value(sym);
736
737 switch (sym->type) {
738 case S_BOOLEAN:
739 case S_TRISTATE:
740 switch (*val) {
741 case 'n':
742 return;
743 case 'm':
744 sym_suffix = "_MODULE";
745 /* fall through */
746 default:
747 val = "1";
748 }
749 break;
750 case S_HEX:
751 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
752 val_prefix = "0x";
753 break;
754 case S_STRING:
755 escaped = escape_string_value(val);
756 val = escaped;
757 default:
758 break;
759 }
760
761 fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
762 val_prefix, val);
763
764 free(escaped);
765 }
766
print_symbol_for_rustccfg(FILE * fp,struct symbol * sym)767 static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym)
768 {
769 const char *val;
770 const char *val_prefix = "";
771 char *val_prefixed = NULL;
772 size_t val_prefixed_len;
773 char *escaped = NULL;
774
775 if (sym->type == S_UNKNOWN)
776 return;
777
778 val = sym_get_string_value(sym);
779
780 switch (sym->type) {
781 case S_BOOLEAN:
782 case S_TRISTATE:
783 /*
784 * We do not care about disabled ones, i.e. no need for
785 * what otherwise are "comments" in other printers.
786 */
787 if (*val == 'n')
788 return;
789
790 /*
791 * To have similar functionality to the C macro `IS_ENABLED()`
792 * we provide an empty `--cfg CONFIG_X` here in both `y`
793 * and `m` cases.
794 *
795 * Then, the common `fprintf()` below will also give us
796 * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can
797 * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
798 */
799 fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name);
800 break;
801 case S_HEX:
802 if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
803 val_prefix = "0x";
804 break;
805 default:
806 break;
807 }
808
809 if (strlen(val_prefix) > 0) {
810 val_prefixed_len = strlen(val) + strlen(val_prefix) + 1;
811 val_prefixed = xmalloc(val_prefixed_len);
812 snprintf(val_prefixed, val_prefixed_len, "%s%s", val_prefix, val);
813 val = val_prefixed;
814 }
815
816 /* All values get escaped: the `--cfg` option only takes strings */
817 escaped = escape_string_value(val);
818 val = escaped;
819
820 fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val);
821
822 free(escaped);
823 free(val_prefixed);
824 }
825
826 /*
827 * Write out a minimal config.
828 * All values that has default values are skipped as this is redundant.
829 */
conf_write_defconfig(const char * filename)830 int conf_write_defconfig(const char *filename)
831 {
832 struct symbol *sym;
833 struct menu *menu;
834 struct gstr gs;
835 FILE *out;
836 bool warn_changed_input = conf_warn_changed_input_enabled();
837 bool changed_input_found = false;
838
839 out = fopen(filename, "w");
840 if (!out)
841 return 1;
842 gs = str_new();
843
844 sym_clear_all_valid();
845
846 menu_for_each_entry(menu) {
847 struct menu *choice;
848
849 sym = menu->sym;
850
851 if (!sym || sym_is_choice(sym) || sym->flags & SYMBOL_WRITTEN)
852 continue;
853
854 sym_calc_value(sym);
855 if (warn_changed_input)
856 conf_append_changed_input_warning(&gs, sym,
857 &changed_input_found);
858 sym->flags |= SYMBOL_WRITTEN;
859 if (!(sym->flags & SYMBOL_WRITE))
860 continue;
861 sym->flags &= ~SYMBOL_WRITE;
862 /* Skip unchangeable symbols */
863 if (!sym_is_changeable(sym))
864 continue;
865 /* Skip symbols that are equal to the default */
866 if (!strcmp(sym_get_string_value(sym), sym_get_string_default(sym)))
867 continue;
868
869 /* Skip choice values that are equal to the default */
870 choice = sym_get_choice_menu(sym);
871 if (choice) {
872 struct symbol *ds;
873
874 ds = sym_choice_default(choice);
875 if (sym == ds && sym_get_tristate_value(sym) == yes)
876 continue;
877 }
878 print_symbol_for_dotconfig(out, sym);
879 }
880 fclose(out);
881
882 conf_clear_written_flags();
883
884 if (changed_input_found)
885 conf_changed_input_warning(str_get(&gs));
886
887 str_free(&gs);
888 return 0;
889 }
890
conf_write(const char * name)891 int conf_write(const char *name)
892 {
893 FILE *out;
894 struct symbol *sym;
895 struct menu *menu;
896 const char *str;
897 char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
898 char *env;
899 struct gstr gs;
900 bool need_newline = false;
901 bool warn_changed_input = conf_warn_changed_input_enabled();
902 bool changed_input_found = false;
903
904 if (!name)
905 name = conf_get_configname();
906
907 if (!*name) {
908 fprintf(stderr, "config name is empty\n");
909 return -1;
910 }
911
912 if (is_dir(name)) {
913 fprintf(stderr, "%s: Is a directory\n", name);
914 return -1;
915 }
916
917 if (make_parent_dir(name))
918 return -1;
919
920 env = getenv("KCONFIG_OVERWRITECONFIG");
921 if (env && *env) {
922 *tmpname = 0;
923 out = fopen(name, "w");
924 } else {
925 snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
926 name, (int)getpid());
927 out = fopen(tmpname, "w");
928 }
929 if (!out)
930 return 1;
931 gs = str_new();
932
933 conf_write_heading(out, &comment_style_pound);
934
935 if (!conf_get_changed())
936 sym_clear_all_valid();
937
938 menu = rootmenu.list;
939 while (menu) {
940 sym = menu->sym;
941 if (!sym) {
942 if (!menu_is_visible(menu))
943 goto next;
944 str = menu_get_prompt(menu);
945 fprintf(out, "\n"
946 "#\n"
947 "# %s\n"
948 "#\n", str);
949 need_newline = false;
950 } else if (!sym_is_choice(sym) &&
951 !(sym->flags & SYMBOL_WRITTEN)) {
952 sym_calc_value(sym);
953 if (warn_changed_input)
954 conf_append_changed_input_warning(&gs, sym,
955 &changed_input_found);
956 sym->flags |= SYMBOL_WRITTEN;
957 if (!(sym->flags & SYMBOL_WRITE))
958 goto next;
959 if (need_newline) {
960 fprintf(out, "\n");
961 need_newline = false;
962 }
963 print_symbol_for_dotconfig(out, sym);
964 }
965
966 next:
967 if (menu->list) {
968 menu = menu->list;
969 continue;
970 }
971
972 end_check:
973 if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
974 menu->prompt->type == P_MENU) {
975 fprintf(out, "# end of %s\n", menu_get_prompt(menu));
976 need_newline = true;
977 }
978
979 if (menu->next) {
980 menu = menu->next;
981 } else {
982 menu = menu->parent;
983 if (menu)
984 goto end_check;
985 }
986 }
987 fclose(out);
988
989 conf_clear_written_flags();
990
991 if (changed_input_found)
992 conf_changed_input_warning(str_get(&gs));
993
994 str_free(&gs);
995
996 if (*tmpname) {
997 if (is_same(name, tmpname)) {
998 conf_message("No change to %s", name);
999 unlink(tmpname);
1000 conf_set_changed(false);
1001 return 0;
1002 }
1003
1004 snprintf(oldname, sizeof(oldname), "%s.old", name);
1005 rename(name, oldname);
1006 if (rename(tmpname, name))
1007 return 1;
1008 }
1009
1010 conf_message("configuration written to %s", name);
1011
1012 conf_set_changed(false);
1013
1014 return 0;
1015 }
1016
1017 /* write a dependency file as used by kbuild to track dependencies */
conf_write_autoconf_cmd(const char * autoconf_name)1018 static int conf_write_autoconf_cmd(const char *autoconf_name)
1019 {
1020 char name[PATH_MAX], tmp[PATH_MAX];
1021 FILE *out;
1022 int ret;
1023
1024 ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
1025 if (ret >= sizeof(name)) /* check truncation */
1026 return -1;
1027
1028 if (make_parent_dir(name))
1029 return -1;
1030
1031 ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name);
1032 if (ret >= sizeof(tmp)) /* check truncation */
1033 return -1;
1034
1035 out = fopen(tmp, "w");
1036 if (!out) {
1037 perror("fopen");
1038 return -1;
1039 }
1040
1041 fprintf(out, "autoconfig := %s\n", autoconf_name);
1042
1043 fputs(str_get(&autoconf_cmd), out);
1044
1045 fflush(out);
1046 ret = ferror(out); /* error check for all fprintf() calls */
1047 fclose(out);
1048 if (ret)
1049 return -1;
1050
1051 if (rename(tmp, name)) {
1052 perror("rename");
1053 return -1;
1054 }
1055
1056 return 0;
1057 }
1058
conf_touch_deps(void)1059 static int conf_touch_deps(void)
1060 {
1061 const char *name, *tmp;
1062 struct symbol *sym;
1063 int res;
1064
1065 name = conf_get_autoconfig_name();
1066 tmp = strrchr(name, '/');
1067 depfile_prefix_len = tmp ? tmp - name + 1 : 0;
1068 if (depfile_prefix_len + 1 > sizeof(depfile_path))
1069 return -1;
1070
1071 strncpy(depfile_path, name, depfile_prefix_len);
1072 depfile_path[depfile_prefix_len] = 0;
1073
1074 conf_read_simple(name, S_DEF_AUTO);
1075
1076 for_all_symbols(sym) {
1077 if (sym_is_choice(sym))
1078 continue;
1079 if (sym->flags & SYMBOL_WRITE) {
1080 if (sym->flags & SYMBOL_DEF_AUTO) {
1081 /*
1082 * symbol has old and new value,
1083 * so compare them...
1084 */
1085 switch (sym->type) {
1086 case S_BOOLEAN:
1087 case S_TRISTATE:
1088 if (sym_get_tristate_value(sym) ==
1089 sym->def[S_DEF_AUTO].tri)
1090 continue;
1091 break;
1092 case S_STRING:
1093 case S_HEX:
1094 case S_INT:
1095 if (!strcmp(sym_get_string_value(sym),
1096 sym->def[S_DEF_AUTO].val))
1097 continue;
1098 break;
1099 default:
1100 break;
1101 }
1102 } else {
1103 /*
1104 * If there is no old value, only 'no' (unset)
1105 * is allowed as new value.
1106 */
1107 switch (sym->type) {
1108 case S_BOOLEAN:
1109 case S_TRISTATE:
1110 if (sym_get_tristate_value(sym) == no)
1111 continue;
1112 break;
1113 default:
1114 break;
1115 }
1116 }
1117 } else if (!(sym->flags & SYMBOL_DEF_AUTO))
1118 /* There is neither an old nor a new value. */
1119 continue;
1120 /* else
1121 * There is an old value, but no new value ('no' (unset)
1122 * isn't saved in auto.conf, so the old value is always
1123 * different from 'no').
1124 */
1125
1126 res = conf_touch_dep(sym->name);
1127 if (res)
1128 return res;
1129 }
1130
1131 return 0;
1132 }
1133
__conf_write_autoconf(const char * filename,void (* print_symbol)(FILE *,struct symbol *),const struct comment_style * comment_style)1134 static int __conf_write_autoconf(const char *filename,
1135 void (*print_symbol)(FILE *, struct symbol *),
1136 const struct comment_style *comment_style)
1137 {
1138 char tmp[PATH_MAX];
1139 FILE *file;
1140 struct symbol *sym;
1141 int ret;
1142
1143 if (make_parent_dir(filename))
1144 return -1;
1145
1146 ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
1147 if (ret >= sizeof(tmp)) /* check truncation */
1148 return -1;
1149
1150 file = fopen(tmp, "w");
1151 if (!file) {
1152 perror("fopen");
1153 return -1;
1154 }
1155
1156 conf_write_heading(file, comment_style);
1157
1158 for_all_symbols(sym)
1159 if ((sym->flags & SYMBOL_WRITE) && sym->name)
1160 print_symbol(file, sym);
1161
1162 fflush(file);
1163 /* check possible errors in conf_write_heading() and print_symbol() */
1164 ret = ferror(file);
1165 fclose(file);
1166 if (ret)
1167 return -1;
1168
1169 if (rename(tmp, filename)) {
1170 perror("rename");
1171 return -1;
1172 }
1173
1174 return 0;
1175 }
1176
conf_write_autoconf(int overwrite)1177 int conf_write_autoconf(int overwrite)
1178 {
1179 struct symbol *sym;
1180 const char *autoconf_name = conf_get_autoconfig_name();
1181 int ret;
1182
1183 if (!overwrite && is_present(autoconf_name))
1184 return 0;
1185
1186 ret = conf_write_autoconf_cmd(autoconf_name);
1187 if (ret)
1188 return -1;
1189
1190 for_all_symbols(sym)
1191 sym_calc_value(sym);
1192
1193 if (conf_touch_deps())
1194 return 1;
1195
1196 ret = __conf_write_autoconf(conf_get_autoheader_name(),
1197 print_symbol_for_c,
1198 &comment_style_c);
1199 if (ret)
1200 return ret;
1201
1202 ret = __conf_write_autoconf(conf_get_rustccfg_name(),
1203 print_symbol_for_rustccfg,
1204 NULL);
1205 if (ret)
1206 return ret;
1207
1208 /*
1209 * Create include/config/auto.conf. This must be the last step because
1210 * Kbuild has a dependency on auto.conf and this marks the successful
1211 * completion of the previous steps.
1212 */
1213 ret = __conf_write_autoconf(conf_get_autoconfig_name(),
1214 print_symbol_for_autoconf,
1215 &comment_style_pound);
1216 if (ret)
1217 return ret;
1218
1219 return 0;
1220 }
1221
1222 static bool conf_changed;
1223 static void (*conf_changed_callback)(bool);
1224
conf_set_changed(bool val)1225 void conf_set_changed(bool val)
1226 {
1227 if (conf_changed_callback && conf_changed != val)
1228 conf_changed_callback(val);
1229
1230 conf_changed = val;
1231 }
1232
conf_get_changed(void)1233 bool conf_get_changed(void)
1234 {
1235 return conf_changed;
1236 }
1237
conf_set_changed_callback(void (* fn)(bool))1238 void conf_set_changed_callback(void (*fn)(bool))
1239 {
1240 conf_changed_callback = fn;
1241 }
1242