Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
0004  */
0005 
0006 #include <sys/mman.h>
0007 #include <sys/stat.h>
0008 #include <sys/types.h>
0009 #include <ctype.h>
0010 #include <errno.h>
0011 #include <fcntl.h>
0012 #include <limits.h>
0013 #include <stdarg.h>
0014 #include <stdbool.h>
0015 #include <stdio.h>
0016 #include <stdlib.h>
0017 #include <string.h>
0018 #include <time.h>
0019 #include <unistd.h>
0020 
0021 #include "lkc.h"
0022 
0023 /* return true if 'path' exists, false otherwise */
0024 static bool is_present(const char *path)
0025 {
0026     struct stat st;
0027 
0028     return !stat(path, &st);
0029 }
0030 
0031 /* return true if 'path' exists and it is a directory, false otherwise */
0032 static bool is_dir(const char *path)
0033 {
0034     struct stat st;
0035 
0036     if (stat(path, &st))
0037         return false;
0038 
0039     return S_ISDIR(st.st_mode);
0040 }
0041 
0042 /* return true if the given two files are the same, false otherwise */
0043 static bool is_same(const char *file1, const char *file2)
0044 {
0045     int fd1, fd2;
0046     struct stat st1, st2;
0047     void *map1, *map2;
0048     bool ret = false;
0049 
0050     fd1 = open(file1, O_RDONLY);
0051     if (fd1 < 0)
0052         return ret;
0053 
0054     fd2 = open(file2, O_RDONLY);
0055     if (fd2 < 0)
0056         goto close1;
0057 
0058     ret = fstat(fd1, &st1);
0059     if (ret)
0060         goto close2;
0061     ret = fstat(fd2, &st2);
0062     if (ret)
0063         goto close2;
0064 
0065     if (st1.st_size != st2.st_size)
0066         goto close2;
0067 
0068     map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
0069     if (map1 == MAP_FAILED)
0070         goto close2;
0071 
0072     map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
0073     if (map2 == MAP_FAILED)
0074         goto close2;
0075 
0076     if (bcmp(map1, map2, st1.st_size))
0077         goto close2;
0078 
0079     ret = true;
0080 close2:
0081     close(fd2);
0082 close1:
0083     close(fd1);
0084 
0085     return ret;
0086 }
0087 
0088 /*
0089  * Create the parent directory of the given path.
0090  *
0091  * For example, if 'include/config/auto.conf' is given, create 'include/config'.
0092  */
0093 static int make_parent_dir(const char *path)
0094 {
0095     char tmp[PATH_MAX + 1];
0096     char *p;
0097 
0098     strncpy(tmp, path, sizeof(tmp));
0099     tmp[sizeof(tmp) - 1] = 0;
0100 
0101     /* Remove the base name. Just return if nothing is left */
0102     p = strrchr(tmp, '/');
0103     if (!p)
0104         return 0;
0105     *(p + 1) = 0;
0106 
0107     /* Just in case it is an absolute path */
0108     p = tmp;
0109     while (*p == '/')
0110         p++;
0111 
0112     while ((p = strchr(p, '/'))) {
0113         *p = 0;
0114 
0115         /* skip if the directory exists */
0116         if (!is_dir(tmp) && mkdir(tmp, 0755))
0117             return -1;
0118 
0119         *p = '/';
0120         while (*p == '/')
0121             p++;
0122     }
0123 
0124     return 0;
0125 }
0126 
0127 static char depfile_path[PATH_MAX];
0128 static size_t depfile_prefix_len;
0129 
0130 /* touch depfile for symbol 'name' */
0131 static int conf_touch_dep(const char *name)
0132 {
0133     int fd;
0134 
0135     /* check overflow: prefix + name + '\0' must fit in buffer. */
0136     if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
0137         return -1;
0138 
0139     strcpy(depfile_path + depfile_prefix_len, name);
0140 
0141     fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
0142     if (fd == -1)
0143         return -1;
0144     close(fd);
0145 
0146     return 0;
0147 }
0148 
0149 static void conf_warning(const char *fmt, ...)
0150     __attribute__ ((format (printf, 1, 2)));
0151 
0152 static void conf_message(const char *fmt, ...)
0153     __attribute__ ((format (printf, 1, 2)));
0154 
0155 static const char *conf_filename;
0156 static int conf_lineno, conf_warnings;
0157 
0158 static void conf_warning(const char *fmt, ...)
0159 {
0160     va_list ap;
0161     va_start(ap, fmt);
0162     fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
0163     vfprintf(stderr, fmt, ap);
0164     fprintf(stderr, "\n");
0165     va_end(ap);
0166     conf_warnings++;
0167 }
0168 
0169 static void conf_default_message_callback(const char *s)
0170 {
0171     printf("#\n# ");
0172     printf("%s", s);
0173     printf("\n#\n");
0174 }
0175 
0176 static void (*conf_message_callback)(const char *s) =
0177     conf_default_message_callback;
0178 void conf_set_message_callback(void (*fn)(const char *s))
0179 {
0180     conf_message_callback = fn;
0181 }
0182 
0183 static void conf_message(const char *fmt, ...)
0184 {
0185     va_list ap;
0186     char buf[4096];
0187 
0188     if (!conf_message_callback)
0189         return;
0190 
0191     va_start(ap, fmt);
0192 
0193     vsnprintf(buf, sizeof(buf), fmt, ap);
0194     conf_message_callback(buf);
0195     va_end(ap);
0196 }
0197 
0198 const char *conf_get_configname(void)
0199 {
0200     char *name = getenv("KCONFIG_CONFIG");
0201 
0202     return name ? name : ".config";
0203 }
0204 
0205 static const char *conf_get_autoconfig_name(void)
0206 {
0207     char *name = getenv("KCONFIG_AUTOCONFIG");
0208 
0209     return name ? name : "include/config/auto.conf";
0210 }
0211 
0212 static const char *conf_get_autoheader_name(void)
0213 {
0214     char *name = getenv("KCONFIG_AUTOHEADER");
0215 
0216     return name ? name : "include/generated/autoconf.h";
0217 }
0218 
0219 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
0220 {
0221     char *p2;
0222 
0223     switch (sym->type) {
0224     case S_TRISTATE:
0225         if (p[0] == 'm') {
0226             sym->def[def].tri = mod;
0227             sym->flags |= def_flags;
0228             break;
0229         }
0230         /* fall through */
0231     case S_BOOLEAN:
0232         if (p[0] == 'y') {
0233             sym->def[def].tri = yes;
0234             sym->flags |= def_flags;
0235             break;
0236         }
0237         if (p[0] == 'n') {
0238             sym->def[def].tri = no;
0239             sym->flags |= def_flags;
0240             break;
0241         }
0242         if (def != S_DEF_AUTO)
0243             conf_warning("symbol value '%s' invalid for %s",
0244                      p, sym->name);
0245         return 1;
0246     case S_STRING:
0247         /* No escaping for S_DEF_AUTO (include/config/auto.conf) */
0248         if (def != S_DEF_AUTO) {
0249             if (*p++ != '"')
0250                 break;
0251             for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
0252                 if (*p2 == '"') {
0253                     *p2 = 0;
0254                     break;
0255                 }
0256                 memmove(p2, p2 + 1, strlen(p2));
0257             }
0258             if (!p2) {
0259                 conf_warning("invalid string found");
0260                 return 1;
0261             }
0262         }
0263         /* fall through */
0264     case S_INT:
0265     case S_HEX:
0266         if (sym_string_valid(sym, p)) {
0267             sym->def[def].val = xstrdup(p);
0268             sym->flags |= def_flags;
0269         } else {
0270             if (def != S_DEF_AUTO)
0271                 conf_warning("symbol value '%s' invalid for %s",
0272                          p, sym->name);
0273             return 1;
0274         }
0275         break;
0276     default:
0277         ;
0278     }
0279     return 0;
0280 }
0281 
0282 #define LINE_GROWTH 16
0283 static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
0284 {
0285     char *nline;
0286     size_t new_size = slen + 1;
0287     if (new_size > *n) {
0288         new_size += LINE_GROWTH - 1;
0289         new_size *= 2;
0290         nline = xrealloc(*lineptr, new_size);
0291         if (!nline)
0292             return -1;
0293 
0294         *lineptr = nline;
0295         *n = new_size;
0296     }
0297 
0298     (*lineptr)[slen] = c;
0299 
0300     return 0;
0301 }
0302 
0303 static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
0304 {
0305     char *line = *lineptr;
0306     size_t slen = 0;
0307 
0308     for (;;) {
0309         int c = getc(stream);
0310 
0311         switch (c) {
0312         case '\n':
0313             if (add_byte(c, &line, slen, n) < 0)
0314                 goto e_out;
0315             slen++;
0316             /* fall through */
0317         case EOF:
0318             if (add_byte('\0', &line, slen, n) < 0)
0319                 goto e_out;
0320             *lineptr = line;
0321             if (slen == 0)
0322                 return -1;
0323             return slen;
0324         default:
0325             if (add_byte(c, &line, slen, n) < 0)
0326                 goto e_out;
0327             slen++;
0328         }
0329     }
0330 
0331 e_out:
0332     line[slen-1] = '\0';
0333     *lineptr = line;
0334     return -1;
0335 }
0336 
0337 int conf_read_simple(const char *name, int def)
0338 {
0339     FILE *in = NULL;
0340     char   *line = NULL;
0341     size_t  line_asize = 0;
0342     char *p, *p2;
0343     struct symbol *sym;
0344     int i, def_flags;
0345 
0346     if (name) {
0347         in = zconf_fopen(name);
0348     } else {
0349         char *env;
0350 
0351         name = conf_get_configname();
0352         in = zconf_fopen(name);
0353         if (in)
0354             goto load;
0355         conf_set_changed(true);
0356 
0357         env = getenv("KCONFIG_DEFCONFIG_LIST");
0358         if (!env)
0359             return 1;
0360 
0361         while (1) {
0362             bool is_last;
0363 
0364             while (isspace(*env))
0365                 env++;
0366 
0367             if (!*env)
0368                 break;
0369 
0370             p = env;
0371             while (*p && !isspace(*p))
0372                 p++;
0373 
0374             is_last = (*p == '\0');
0375 
0376             *p = '\0';
0377 
0378             in = zconf_fopen(env);
0379             if (in) {
0380                 conf_message("using defaults found in %s",
0381                          env);
0382                 goto load;
0383             }
0384 
0385             if (is_last)
0386                 break;
0387 
0388             env = p + 1;
0389         }
0390     }
0391     if (!in)
0392         return 1;
0393 
0394 load:
0395     conf_filename = name;
0396     conf_lineno = 0;
0397     conf_warnings = 0;
0398 
0399     def_flags = SYMBOL_DEF << def;
0400     for_all_symbols(i, sym) {
0401         sym->flags |= SYMBOL_CHANGED;
0402         sym->flags &= ~(def_flags|SYMBOL_VALID);
0403         if (sym_is_choice(sym))
0404             sym->flags |= def_flags;
0405         switch (sym->type) {
0406         case S_INT:
0407         case S_HEX:
0408         case S_STRING:
0409             if (sym->def[def].val)
0410                 free(sym->def[def].val);
0411             /* fall through */
0412         default:
0413             sym->def[def].val = NULL;
0414             sym->def[def].tri = no;
0415         }
0416     }
0417 
0418     while (compat_getline(&line, &line_asize, in) != -1) {
0419         conf_lineno++;
0420         sym = NULL;
0421         if (line[0] == '#') {
0422             if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
0423                 continue;
0424             p = strchr(line + 2 + strlen(CONFIG_), ' ');
0425             if (!p)
0426                 continue;
0427             *p++ = 0;
0428             if (strncmp(p, "is not set", 10))
0429                 continue;
0430             if (def == S_DEF_USER) {
0431                 sym = sym_find(line + 2 + strlen(CONFIG_));
0432                 if (!sym) {
0433                     conf_set_changed(true);
0434                     continue;
0435                 }
0436             } else {
0437                 sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
0438                 if (sym->type == S_UNKNOWN)
0439                     sym->type = S_BOOLEAN;
0440             }
0441             if (sym->flags & def_flags) {
0442                 conf_warning("override: reassigning to symbol %s", sym->name);
0443             }
0444             switch (sym->type) {
0445             case S_BOOLEAN:
0446             case S_TRISTATE:
0447                 sym->def[def].tri = no;
0448                 sym->flags |= def_flags;
0449                 break;
0450             default:
0451                 ;
0452             }
0453         } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
0454             p = strchr(line + strlen(CONFIG_), '=');
0455             if (!p)
0456                 continue;
0457             *p++ = 0;
0458             p2 = strchr(p, '\n');
0459             if (p2) {
0460                 *p2-- = 0;
0461                 if (*p2 == '\r')
0462                     *p2 = 0;
0463             }
0464 
0465             sym = sym_find(line + strlen(CONFIG_));
0466             if (!sym) {
0467                 if (def == S_DEF_AUTO)
0468                     /*
0469                      * Reading from include/config/auto.conf
0470                      * If CONFIG_FOO previously existed in
0471                      * auto.conf but it is missing now,
0472                      * include/config/FOO must be touched.
0473                      */
0474                     conf_touch_dep(line + strlen(CONFIG_));
0475                 else
0476                     conf_set_changed(true);
0477                 continue;
0478             }
0479 
0480             if (sym->flags & def_flags) {
0481                 conf_warning("override: reassigning to symbol %s", sym->name);
0482             }
0483             if (conf_set_sym_val(sym, def, def_flags, p))
0484                 continue;
0485         } else {
0486             if (line[0] != '\r' && line[0] != '\n')
0487                 conf_warning("unexpected data: %.*s",
0488                          (int)strcspn(line, "\r\n"), line);
0489 
0490             continue;
0491         }
0492 
0493         if (sym && sym_is_choice_value(sym)) {
0494             struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
0495             switch (sym->def[def].tri) {
0496             case no:
0497                 break;
0498             case mod:
0499                 if (cs->def[def].tri == yes) {
0500                     conf_warning("%s creates inconsistent choice state", sym->name);
0501                     cs->flags &= ~def_flags;
0502                 }
0503                 break;
0504             case yes:
0505                 if (cs->def[def].tri != no)
0506                     conf_warning("override: %s changes choice state", sym->name);
0507                 cs->def[def].val = sym;
0508                 break;
0509             }
0510             cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
0511         }
0512     }
0513     free(line);
0514     fclose(in);
0515     return 0;
0516 }
0517 
0518 int conf_read(const char *name)
0519 {
0520     struct symbol *sym;
0521     int conf_unsaved = 0;
0522     int i;
0523 
0524     conf_set_changed(false);
0525 
0526     if (conf_read_simple(name, S_DEF_USER)) {
0527         sym_calc_value(modules_sym);
0528         return 1;
0529     }
0530 
0531     sym_calc_value(modules_sym);
0532 
0533     for_all_symbols(i, sym) {
0534         sym_calc_value(sym);
0535         if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
0536             continue;
0537         if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
0538             /* check that calculated value agrees with saved value */
0539             switch (sym->type) {
0540             case S_BOOLEAN:
0541             case S_TRISTATE:
0542                 if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
0543                     continue;
0544                 break;
0545             default:
0546                 if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
0547                     continue;
0548                 break;
0549             }
0550         } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
0551             /* no previous value and not saved */
0552             continue;
0553         conf_unsaved++;
0554         /* maybe print value in verbose mode... */
0555     }
0556 
0557     for_all_symbols(i, sym) {
0558         if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
0559             /* Reset values of generates values, so they'll appear
0560              * as new, if they should become visible, but that
0561              * doesn't quite work if the Kconfig and the saved
0562              * configuration disagree.
0563              */
0564             if (sym->visible == no && !conf_unsaved)
0565                 sym->flags &= ~SYMBOL_DEF_USER;
0566             switch (sym->type) {
0567             case S_STRING:
0568             case S_INT:
0569             case S_HEX:
0570                 /* Reset a string value if it's out of range */
0571                 if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
0572                     break;
0573                 sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
0574                 conf_unsaved++;
0575                 break;
0576             default:
0577                 break;
0578             }
0579         }
0580     }
0581 
0582     if (conf_warnings || conf_unsaved)
0583         conf_set_changed(true);
0584 
0585     return 0;
0586 }
0587 
0588 struct comment_style {
0589     const char *decoration;
0590     const char *prefix;
0591     const char *postfix;
0592 };
0593 
0594 static const struct comment_style comment_style_pound = {
0595     .decoration = "#",
0596     .prefix = "#",
0597     .postfix = "#",
0598 };
0599 
0600 static const struct comment_style comment_style_c = {
0601     .decoration = " *",
0602     .prefix = "/*",
0603     .postfix = " */",
0604 };
0605 
0606 static void conf_write_heading(FILE *fp, const struct comment_style *cs)
0607 {
0608     fprintf(fp, "%s\n", cs->prefix);
0609 
0610     fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
0611         cs->decoration);
0612 
0613     fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
0614 
0615     fprintf(fp, "%s\n", cs->postfix);
0616 }
0617 
0618 /* The returned pointer must be freed on the caller side */
0619 static char *escape_string_value(const char *in)
0620 {
0621     const char *p;
0622     char *out;
0623     size_t len;
0624 
0625     len = strlen(in) + strlen("\"\"") + 1;
0626 
0627     p = in;
0628     while (1) {
0629         p += strcspn(p, "\"\\");
0630 
0631         if (p[0] == '\0')
0632             break;
0633 
0634         len++;
0635         p++;
0636     }
0637 
0638     out = xmalloc(len);
0639     out[0] = '\0';
0640 
0641     strcat(out, "\"");
0642 
0643     p = in;
0644     while (1) {
0645         len = strcspn(p, "\"\\");
0646         strncat(out, p, len);
0647         p += len;
0648 
0649         if (p[0] == '\0')
0650             break;
0651 
0652         strcat(out, "\\");
0653         strncat(out, p++, 1);
0654     }
0655 
0656     strcat(out, "\"");
0657 
0658     return out;
0659 }
0660 
0661 enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
0662 
0663 static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
0664                bool escape_string)
0665 {
0666     const char *val;
0667     char *escaped = NULL;
0668 
0669     if (sym->type == S_UNKNOWN)
0670         return;
0671 
0672     val = sym_get_string_value(sym);
0673 
0674     if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
0675         output_n != OUTPUT_N && *val == 'n') {
0676         if (output_n == OUTPUT_N_AS_UNSET)
0677             fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
0678         return;
0679     }
0680 
0681     if (sym->type == S_STRING && escape_string) {
0682         escaped = escape_string_value(val);
0683         val = escaped;
0684     }
0685 
0686     fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
0687 
0688     free(escaped);
0689 }
0690 
0691 static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
0692 {
0693     __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
0694 }
0695 
0696 static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
0697 {
0698     __print_symbol(fp, sym, OUTPUT_N_NONE, false);
0699 }
0700 
0701 void print_symbol_for_listconfig(struct symbol *sym)
0702 {
0703     __print_symbol(stdout, sym, OUTPUT_N, true);
0704 }
0705 
0706 static void print_symbol_for_c(FILE *fp, struct symbol *sym)
0707 {
0708     const char *val;
0709     const char *sym_suffix = "";
0710     const char *val_prefix = "";
0711     char *escaped = NULL;
0712 
0713     if (sym->type == S_UNKNOWN)
0714         return;
0715 
0716     val = sym_get_string_value(sym);
0717 
0718     switch (sym->type) {
0719     case S_BOOLEAN:
0720     case S_TRISTATE:
0721         switch (*val) {
0722         case 'n':
0723             return;
0724         case 'm':
0725             sym_suffix = "_MODULE";
0726             /* fall through */
0727         default:
0728             val = "1";
0729         }
0730         break;
0731     case S_HEX:
0732         if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
0733             val_prefix = "0x";
0734         break;
0735     case S_STRING:
0736         escaped = escape_string_value(val);
0737         val = escaped;
0738     default:
0739         break;
0740     }
0741 
0742     fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
0743         val_prefix, val);
0744 
0745     free(escaped);
0746 }
0747 
0748 /*
0749  * Write out a minimal config.
0750  * All values that has default values are skipped as this is redundant.
0751  */
0752 int conf_write_defconfig(const char *filename)
0753 {
0754     struct symbol *sym;
0755     struct menu *menu;
0756     FILE *out;
0757 
0758     out = fopen(filename, "w");
0759     if (!out)
0760         return 1;
0761 
0762     sym_clear_all_valid();
0763 
0764     /* Traverse all menus to find all relevant symbols */
0765     menu = rootmenu.list;
0766 
0767     while (menu != NULL)
0768     {
0769         sym = menu->sym;
0770         if (sym == NULL) {
0771             if (!menu_is_visible(menu))
0772                 goto next_menu;
0773         } else if (!sym_is_choice(sym)) {
0774             sym_calc_value(sym);
0775             if (!(sym->flags & SYMBOL_WRITE))
0776                 goto next_menu;
0777             sym->flags &= ~SYMBOL_WRITE;
0778             /* If we cannot change the symbol - skip */
0779             if (!sym_is_changeable(sym))
0780                 goto next_menu;
0781             /* If symbol equals to default value - skip */
0782             if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
0783                 goto next_menu;
0784 
0785             /*
0786              * If symbol is a choice value and equals to the
0787              * default for a choice - skip.
0788              * But only if value is bool and equal to "y" and
0789              * choice is not "optional".
0790              * (If choice is "optional" then all values can be "n")
0791              */
0792             if (sym_is_choice_value(sym)) {
0793                 struct symbol *cs;
0794                 struct symbol *ds;
0795 
0796                 cs = prop_get_symbol(sym_get_choice_prop(sym));
0797                 ds = sym_choice_default(cs);
0798                 if (!sym_is_optional(cs) && sym == ds) {
0799                     if ((sym->type == S_BOOLEAN) &&
0800                         sym_get_tristate_value(sym) == yes)
0801                         goto next_menu;
0802                 }
0803             }
0804             print_symbol_for_dotconfig(out, sym);
0805         }
0806 next_menu:
0807         if (menu->list != NULL) {
0808             menu = menu->list;
0809         }
0810         else if (menu->next != NULL) {
0811             menu = menu->next;
0812         } else {
0813             while ((menu = menu->parent)) {
0814                 if (menu->next != NULL) {
0815                     menu = menu->next;
0816                     break;
0817                 }
0818             }
0819         }
0820     }
0821     fclose(out);
0822     return 0;
0823 }
0824 
0825 int conf_write(const char *name)
0826 {
0827     FILE *out;
0828     struct symbol *sym;
0829     struct menu *menu;
0830     const char *str;
0831     char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
0832     char *env;
0833     int i;
0834     bool need_newline = false;
0835 
0836     if (!name)
0837         name = conf_get_configname();
0838 
0839     if (!*name) {
0840         fprintf(stderr, "config name is empty\n");
0841         return -1;
0842     }
0843 
0844     if (is_dir(name)) {
0845         fprintf(stderr, "%s: Is a directory\n", name);
0846         return -1;
0847     }
0848 
0849     if (make_parent_dir(name))
0850         return -1;
0851 
0852     env = getenv("KCONFIG_OVERWRITECONFIG");
0853     if (env && *env) {
0854         *tmpname = 0;
0855         out = fopen(name, "w");
0856     } else {
0857         snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
0858              name, (int)getpid());
0859         out = fopen(tmpname, "w");
0860     }
0861     if (!out)
0862         return 1;
0863 
0864     conf_write_heading(out, &comment_style_pound);
0865 
0866     if (!conf_get_changed())
0867         sym_clear_all_valid();
0868 
0869     menu = rootmenu.list;
0870     while (menu) {
0871         sym = menu->sym;
0872         if (!sym) {
0873             if (!menu_is_visible(menu))
0874                 goto next;
0875             str = menu_get_prompt(menu);
0876             fprintf(out, "\n"
0877                      "#\n"
0878                      "# %s\n"
0879                      "#\n", str);
0880             need_newline = false;
0881         } else if (!(sym->flags & SYMBOL_CHOICE) &&
0882                !(sym->flags & SYMBOL_WRITTEN)) {
0883             sym_calc_value(sym);
0884             if (!(sym->flags & SYMBOL_WRITE))
0885                 goto next;
0886             if (need_newline) {
0887                 fprintf(out, "\n");
0888                 need_newline = false;
0889             }
0890             sym->flags |= SYMBOL_WRITTEN;
0891             print_symbol_for_dotconfig(out, sym);
0892         }
0893 
0894 next:
0895         if (menu->list) {
0896             menu = menu->list;
0897             continue;
0898         }
0899 
0900 end_check:
0901         if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
0902             menu->prompt->type == P_MENU) {
0903             fprintf(out, "# end of %s\n", menu_get_prompt(menu));
0904             need_newline = true;
0905         }
0906 
0907         if (menu->next) {
0908             menu = menu->next;
0909         } else {
0910             menu = menu->parent;
0911             if (menu)
0912                 goto end_check;
0913         }
0914     }
0915     fclose(out);
0916 
0917     for_all_symbols(i, sym)
0918         sym->flags &= ~SYMBOL_WRITTEN;
0919 
0920     if (*tmpname) {
0921         if (is_same(name, tmpname)) {
0922             conf_message("No change to %s", name);
0923             unlink(tmpname);
0924             conf_set_changed(false);
0925             return 0;
0926         }
0927 
0928         snprintf(oldname, sizeof(oldname), "%s.old", name);
0929         rename(name, oldname);
0930         if (rename(tmpname, name))
0931             return 1;
0932     }
0933 
0934     conf_message("configuration written to %s", name);
0935 
0936     conf_set_changed(false);
0937 
0938     return 0;
0939 }
0940 
0941 /* write a dependency file as used by kbuild to track dependencies */
0942 static int conf_write_autoconf_cmd(const char *autoconf_name)
0943 {
0944     char name[PATH_MAX], tmp[PATH_MAX];
0945     struct file *file;
0946     FILE *out;
0947     int ret;
0948 
0949     ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
0950     if (ret >= sizeof(name)) /* check truncation */
0951         return -1;
0952 
0953     if (make_parent_dir(name))
0954         return -1;
0955 
0956     ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name);
0957     if (ret >= sizeof(tmp)) /* check truncation */
0958         return -1;
0959 
0960     out = fopen(tmp, "w");
0961     if (!out) {
0962         perror("fopen");
0963         return -1;
0964     }
0965 
0966     fprintf(out, "deps_config := \\\n");
0967     for (file = file_list; file; file = file->next)
0968         fprintf(out, "\t%s \\\n", file->name);
0969 
0970     fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
0971 
0972     env_write_dep(out, autoconf_name);
0973 
0974     fprintf(out, "\n$(deps_config): ;\n");
0975 
0976     fflush(out);
0977     ret = ferror(out); /* error check for all fprintf() calls */
0978     fclose(out);
0979     if (ret)
0980         return -1;
0981 
0982     if (rename(tmp, name)) {
0983         perror("rename");
0984         return -1;
0985     }
0986 
0987     return 0;
0988 }
0989 
0990 static int conf_touch_deps(void)
0991 {
0992     const char *name, *tmp;
0993     struct symbol *sym;
0994     int res, i;
0995 
0996     name = conf_get_autoconfig_name();
0997     tmp = strrchr(name, '/');
0998     depfile_prefix_len = tmp ? tmp - name + 1 : 0;
0999     if (depfile_prefix_len + 1 > sizeof(depfile_path))
1000         return -1;
1001 
1002     strncpy(depfile_path, name, depfile_prefix_len);
1003     depfile_path[depfile_prefix_len] = 0;
1004 
1005     conf_read_simple(name, S_DEF_AUTO);
1006     sym_calc_value(modules_sym);
1007 
1008     for_all_symbols(i, sym) {
1009         sym_calc_value(sym);
1010         if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
1011             continue;
1012         if (sym->flags & SYMBOL_WRITE) {
1013             if (sym->flags & SYMBOL_DEF_AUTO) {
1014                 /*
1015                  * symbol has old and new value,
1016                  * so compare them...
1017                  */
1018                 switch (sym->type) {
1019                 case S_BOOLEAN:
1020                 case S_TRISTATE:
1021                     if (sym_get_tristate_value(sym) ==
1022                         sym->def[S_DEF_AUTO].tri)
1023                         continue;
1024                     break;
1025                 case S_STRING:
1026                 case S_HEX:
1027                 case S_INT:
1028                     if (!strcmp(sym_get_string_value(sym),
1029                             sym->def[S_DEF_AUTO].val))
1030                         continue;
1031                     break;
1032                 default:
1033                     break;
1034                 }
1035             } else {
1036                 /*
1037                  * If there is no old value, only 'no' (unset)
1038                  * is allowed as new value.
1039                  */
1040                 switch (sym->type) {
1041                 case S_BOOLEAN:
1042                 case S_TRISTATE:
1043                     if (sym_get_tristate_value(sym) == no)
1044                         continue;
1045                     break;
1046                 default:
1047                     break;
1048                 }
1049             }
1050         } else if (!(sym->flags & SYMBOL_DEF_AUTO))
1051             /* There is neither an old nor a new value. */
1052             continue;
1053         /* else
1054          *  There is an old value, but no new value ('no' (unset)
1055          *  isn't saved in auto.conf, so the old value is always
1056          *  different from 'no').
1057          */
1058 
1059         res = conf_touch_dep(sym->name);
1060         if (res)
1061             return res;
1062     }
1063 
1064     return 0;
1065 }
1066 
1067 static int __conf_write_autoconf(const char *filename,
1068                  void (*print_symbol)(FILE *, struct symbol *),
1069                  const struct comment_style *comment_style)
1070 {
1071     char tmp[PATH_MAX];
1072     FILE *file;
1073     struct symbol *sym;
1074     int ret, i;
1075 
1076     if (make_parent_dir(filename))
1077         return -1;
1078 
1079     ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
1080     if (ret >= sizeof(tmp)) /* check truncation */
1081         return -1;
1082 
1083     file = fopen(tmp, "w");
1084     if (!file) {
1085         perror("fopen");
1086         return -1;
1087     }
1088 
1089     conf_write_heading(file, comment_style);
1090 
1091     for_all_symbols(i, sym)
1092         if ((sym->flags & SYMBOL_WRITE) && sym->name)
1093             print_symbol(file, sym);
1094 
1095     fflush(file);
1096     /* check possible errors in conf_write_heading() and print_symbol() */
1097     ret = ferror(file);
1098     fclose(file);
1099     if (ret)
1100         return -1;
1101 
1102     if (rename(tmp, filename)) {
1103         perror("rename");
1104         return -1;
1105     }
1106 
1107     return 0;
1108 }
1109 
1110 int conf_write_autoconf(int overwrite)
1111 {
1112     struct symbol *sym;
1113     const char *autoconf_name = conf_get_autoconfig_name();
1114     int ret, i;
1115 
1116     if (!overwrite && is_present(autoconf_name))
1117         return 0;
1118 
1119     ret = conf_write_autoconf_cmd(autoconf_name);
1120     if (ret)
1121         return -1;
1122 
1123     if (conf_touch_deps())
1124         return 1;
1125 
1126     for_all_symbols(i, sym)
1127         sym_calc_value(sym);
1128 
1129     ret = __conf_write_autoconf(conf_get_autoheader_name(),
1130                     print_symbol_for_c,
1131                     &comment_style_c);
1132     if (ret)
1133         return ret;
1134 
1135     /*
1136      * Create include/config/auto.conf. This must be the last step because
1137      * Kbuild has a dependency on auto.conf and this marks the successful
1138      * completion of the previous steps.
1139      */
1140     ret = __conf_write_autoconf(conf_get_autoconfig_name(),
1141                     print_symbol_for_autoconf,
1142                     &comment_style_pound);
1143     if (ret)
1144         return ret;
1145 
1146     return 0;
1147 }
1148 
1149 static bool conf_changed;
1150 static void (*conf_changed_callback)(void);
1151 
1152 void conf_set_changed(bool val)
1153 {
1154     if (conf_changed_callback && conf_changed != val)
1155         conf_changed_callback();
1156 
1157     conf_changed = val;
1158 }
1159 
1160 bool conf_get_changed(void)
1161 {
1162     return conf_changed;
1163 }
1164 
1165 void conf_set_changed_callback(void (*fn)(void))
1166 {
1167     conf_changed_callback = fn;
1168 }
1169 
1170 void set_all_choice_values(struct symbol *csym)
1171 {
1172     struct property *prop;
1173     struct symbol *sym;
1174     struct expr *e;
1175 
1176     prop = sym_get_choice_prop(csym);
1177 
1178     /*
1179      * Set all non-assinged choice values to no
1180      */
1181     expr_list_for_each_sym(prop->expr, e, sym) {
1182         if (!sym_has_value(sym))
1183             sym->def[S_DEF_USER].tri = no;
1184     }
1185     csym->flags |= SYMBOL_DEF_USER;
1186     /* clear VALID to get value calculated */
1187     csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
1188 }