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