~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kconfig/confdata.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  4  */
  5 
  6 #include <sys/mman.h>
  7 #include <sys/stat.h>
  8 #include <sys/types.h>
  9 #include <ctype.h>
 10 #include <errno.h>
 11 #include <fcntl.h>
 12 #include <limits.h>
 13 #include <stdarg.h>
 14 #include <stdbool.h>
 15 #include <stdio.h>
 16 #include <stdlib.h>
 17 #include <string.h>
 18 #include <time.h>
 19 #include <unistd.h>
 20 
 21 #include "internal.h"
 22 #include "lkc.h"
 23 
 24 struct gstr autoconf_cmd;
 25 
 26 /* return true if 'path' exists, false otherwise */
 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 
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 
520 struct comment_style {
521         const char *decoration;
522         const char *prefix;
523         const char *postfix;
524 };
525 
526 static const struct comment_style comment_style_pound = {
527         .decoration = "#",
528         .prefix = "#",
529         .postfix = "#",
530 };
531 
532 static const struct comment_style comment_style_c = {
533         .decoration = " *",
534         .prefix = "/*",
535         .postfix = " */",
536 };
537 
538 static 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 */
554 static 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 
596 enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
597 
598 static 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 
626 static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
627 {
628         __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
629 }
630 
631 static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
632 {
633         __print_symbol(fp, sym, OUTPUT_N_NONE, false);
634 }
635 
636 void print_symbol_for_listconfig(struct symbol *sym)
637 {
638         __print_symbol(stdout, sym, OUTPUT_N, true);
639 }
640 
641 static 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] != '' || (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 
683 static 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] != '' || (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  */
746 int 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 
792 int 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 
860 next:
861                 if (menu->list) {
862                         menu = menu->list;
863                         continue;
864                 }
865 
866 end_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 */
908 static 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 
949 static 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 
1026 static 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 
1069 int 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 
1114 static bool conf_changed;
1115 static void (*conf_changed_callback)(bool);
1116 
1117 void 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 
1125 bool conf_get_changed(void)
1126 {
1127         return conf_changed;
1128 }
1129 
1130 void conf_set_changed_callback(void (*fn)(bool))
1131 {
1132         conf_changed_callback = fn;
1133 }
1134 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php