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