|
@@ -3,6 +3,7 @@
|
|
|
* Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
|
|
|
*/
|
|
|
|
|
|
+#include <sys/mman.h>
|
|
|
#include <sys/stat.h>
|
|
|
#include <ctype.h>
|
|
|
#include <errno.h>
|
|
@@ -36,6 +37,52 @@ static bool is_dir(const char *path)
|
|
|
return S_ISDIR(st.st_mode);
|
|
|
}
|
|
|
|
|
|
+/* return true if the given two files are the same, false otherwise */
|
|
|
+static bool is_same(const char *file1, const char *file2)
|
|
|
+{
|
|
|
+ int fd1, fd2;
|
|
|
+ struct stat st1, st2;
|
|
|
+ void *map1, *map2;
|
|
|
+ bool ret = false;
|
|
|
+
|
|
|
+ fd1 = open(file1, O_RDONLY);
|
|
|
+ if (fd1 < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ fd2 = open(file2, O_RDONLY);
|
|
|
+ if (fd2 < 0)
|
|
|
+ goto close1;
|
|
|
+
|
|
|
+ ret = fstat(fd1, &st1);
|
|
|
+ if (ret)
|
|
|
+ goto close2;
|
|
|
+ ret = fstat(fd2, &st2);
|
|
|
+ if (ret)
|
|
|
+ goto close2;
|
|
|
+
|
|
|
+ if (st1.st_size != st2.st_size)
|
|
|
+ goto close2;
|
|
|
+
|
|
|
+ map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
|
|
|
+ if (map1 == MAP_FAILED)
|
|
|
+ goto close2;
|
|
|
+
|
|
|
+ map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
|
|
|
+ if (map2 == MAP_FAILED)
|
|
|
+ goto close2;
|
|
|
+
|
|
|
+ if (bcmp(map1, map2, st1.st_size))
|
|
|
+ goto close2;
|
|
|
+
|
|
|
+ ret = true;
|
|
|
+close2:
|
|
|
+ close(fd2);
|
|
|
+close1:
|
|
|
+ close(fd1);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Create the parent directory of the given path.
|
|
|
*
|
|
@@ -130,8 +177,6 @@ static void conf_message(const char *fmt, ...)
|
|
|
static const char *conf_filename;
|
|
|
static int conf_lineno, conf_warnings;
|
|
|
|
|
|
-const char conf_defname[] = "include/generated/defconfig";
|
|
|
-
|
|
|
static void conf_warning(const char *fmt, ...)
|
|
|
{
|
|
|
va_list ap;
|
|
@@ -179,28 +224,13 @@ const char *conf_get_configname(void)
|
|
|
return name ? name : ".config";
|
|
|
}
|
|
|
|
|
|
-const char *conf_get_autoconfig_name(void)
|
|
|
+static const char *conf_get_autoconfig_name(void)
|
|
|
{
|
|
|
char *name = getenv("KCONFIG_AUTOCONFIG");
|
|
|
|
|
|
return name ? name : "include/generated/auto.conf";
|
|
|
}
|
|
|
|
|
|
-char *conf_get_default_confname(void)
|
|
|
-{
|
|
|
- static char fullname[PATH_MAX+1];
|
|
|
- char *env, *name;
|
|
|
-
|
|
|
- name = expand_string(conf_defname);
|
|
|
- env = getenv(SRCTREE);
|
|
|
- if (env) {
|
|
|
- sprintf(fullname, "%s/%s", env, name);
|
|
|
- if (is_present(fullname))
|
|
|
- return fullname;
|
|
|
- }
|
|
|
- return name;
|
|
|
-}
|
|
|
-
|
|
|
static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
|
|
|
{
|
|
|
char *p2;
|
|
@@ -504,11 +534,9 @@ int conf_read(const char *name)
|
|
|
switch (sym->type) {
|
|
|
case S_BOOLEAN:
|
|
|
case S_TRISTATE:
|
|
|
- if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
|
|
|
- break;
|
|
|
- if (!sym_is_choice(sym))
|
|
|
+ if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
|
|
|
continue;
|
|
|
- /* fall through */
|
|
|
+ break;
|
|
|
default:
|
|
|
if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
|
|
|
continue;
|
|
@@ -812,7 +840,7 @@ int conf_write_defconfig(const char *filename)
|
|
|
goto next_menu;
|
|
|
sym->flags &= ~SYMBOL_WRITE;
|
|
|
/* If we cannot change the symbol - skip */
|
|
|
- if (!sym_is_changable(sym))
|
|
|
+ if (!sym_is_changeable(sym))
|
|
|
goto next_menu;
|
|
|
/* If symbol equals to default value - skip */
|
|
|
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
|
|
@@ -863,40 +891,36 @@ int conf_write(const char *name)
|
|
|
FILE *out;
|
|
|
struct symbol *sym;
|
|
|
struct menu *menu;
|
|
|
- const char *basename;
|
|
|
const char *str;
|
|
|
- char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
|
|
|
+ char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
|
|
|
char *env;
|
|
|
+ int i;
|
|
|
+ bool need_newline = false;
|
|
|
+
|
|
|
+ if (!name)
|
|
|
+ name = conf_get_configname();
|
|
|
+
|
|
|
+ if (!*name) {
|
|
|
+ fprintf(stderr, "config name is empty\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_dir(name)) {
|
|
|
+ fprintf(stderr, "%s: Is a directory\n", name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (make_parent_dir(name))
|
|
|
+ return -1;
|
|
|
|
|
|
- dirname[0] = 0;
|
|
|
- if (name && name[0]) {
|
|
|
- char *slash;
|
|
|
-
|
|
|
- if (is_dir(name)) {
|
|
|
- strcpy(dirname, name);
|
|
|
- strcat(dirname, "/");
|
|
|
- basename = conf_get_configname();
|
|
|
- } else if ((slash = strrchr(name, '/'))) {
|
|
|
- int size = slash - name + 1;
|
|
|
- memcpy(dirname, name, size);
|
|
|
- dirname[size] = 0;
|
|
|
- if (slash[1])
|
|
|
- basename = slash + 1;
|
|
|
- else
|
|
|
- basename = conf_get_configname();
|
|
|
- } else
|
|
|
- basename = name;
|
|
|
- } else
|
|
|
- basename = conf_get_configname();
|
|
|
-
|
|
|
- sprintf(newname, "%s%s", dirname, basename);
|
|
|
env = getenv("KCONFIG_OVERWRITECONFIG");
|
|
|
- if (!env || !*env) {
|
|
|
- sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
|
|
|
- out = fopen(tmpname, "w");
|
|
|
- } else {
|
|
|
+ if (env && *env) {
|
|
|
*tmpname = 0;
|
|
|
- out = fopen(newname, "w");
|
|
|
+ out = fopen(name, "w");
|
|
|
+ } else {
|
|
|
+ snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
|
|
|
+ name, (int)getpid());
|
|
|
+ out = fopen(tmpname, "w");
|
|
|
}
|
|
|
if (!out)
|
|
|
return 1;
|
|
@@ -917,12 +941,17 @@ int conf_write(const char *name)
|
|
|
"#\n"
|
|
|
"# %s\n"
|
|
|
"#\n", str);
|
|
|
- } else if (!(sym->flags & SYMBOL_CHOICE)) {
|
|
|
+ need_newline = false;
|
|
|
+ } else if (!(sym->flags & SYMBOL_CHOICE) &&
|
|
|
+ !(sym->flags & SYMBOL_WRITTEN)) {
|
|
|
sym_calc_value(sym);
|
|
|
if (!(sym->flags & SYMBOL_WRITE))
|
|
|
goto next;
|
|
|
- sym->flags &= ~SYMBOL_WRITE;
|
|
|
-
|
|
|
+ if (need_newline) {
|
|
|
+ fprintf(out, "\n");
|
|
|
+ need_newline = false;
|
|
|
+ }
|
|
|
+ sym->flags |= SYMBOL_WRITTEN;
|
|
|
conf_write_symbol(out, sym, &kconfig_printer_cb, NULL);
|
|
|
}
|
|
|
|
|
@@ -934,6 +963,12 @@ next:
|
|
|
if (menu->next)
|
|
|
menu = menu->next;
|
|
|
else while ((menu = menu->parent)) {
|
|
|
+ if (!menu->sym && menu_is_visible(menu) &&
|
|
|
+ menu != &rootmenu) {
|
|
|
+ str = menu_get_prompt(menu);
|
|
|
+ fprintf(out, "# end of %s\n", str);
|
|
|
+ need_newline = true;
|
|
|
+ }
|
|
|
if (menu->next) {
|
|
|
menu = menu->next;
|
|
|
break;
|
|
@@ -942,15 +977,24 @@ next:
|
|
|
}
|
|
|
fclose(out);
|
|
|
|
|
|
+ for_all_symbols(i, sym)
|
|
|
+ sym->flags &= ~SYMBOL_WRITTEN;
|
|
|
+
|
|
|
if (*tmpname) {
|
|
|
- strcat(dirname, basename);
|
|
|
- strcat(dirname, ".old");
|
|
|
- rename(newname, dirname);
|
|
|
- if (rename(tmpname, newname))
|
|
|
+ if (is_same(name, tmpname)) {
|
|
|
+ conf_message("No change to %s", name);
|
|
|
+ unlink(tmpname);
|
|
|
+ sym_set_change_count(0);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ snprintf(oldname, sizeof(oldname), "%s.old", name);
|
|
|
+ rename(name, oldname);
|
|
|
+ if (rename(tmpname, name))
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
- conf_message("configuration written to %s", newname);
|
|
|
+ conf_message("configuration written to %s", name);
|
|
|
|
|
|
sym_set_change_count(0);
|
|
|
|
|
@@ -963,8 +1007,6 @@ static int conf_write_dep(const char *name)
|
|
|
struct file *file;
|
|
|
FILE *out;
|
|
|
|
|
|
- if (!name)
|
|
|
- name = ".kconfig.d";
|
|
|
out = fopen("..config.tmp", "w");
|
|
|
if (!out)
|
|
|
return 1;
|
|
@@ -1072,8 +1114,6 @@ int conf_write_autoconf(int overwrite)
|
|
|
if (!overwrite && is_present(autoconf_name))
|
|
|
return 0;
|
|
|
|
|
|
- sym_clear_all_valid();
|
|
|
-
|
|
|
conf_write_dep("include/generated/auto.conf.cmd");
|
|
|
|
|
|
if (conf_touch_deps())
|