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