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