diff options
Diffstat (limited to 'scripts/kconfig/confdata.c')
-rw-r--r-- | scripts/kconfig/confdata.c | 121 |
1 files changed, 83 insertions, 38 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 08ba146a83c5..492ac3410147 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -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. * @@ -179,7 +226,7 @@ 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"); @@ -194,7 +241,7 @@ char *conf_get_default_confname(void) name = expand_string(conf_defname); env = getenv(SRCTREE); if (env) { - sprintf(fullname, "%s/%s", env, name); + snprintf(fullname, sizeof(fullname), "%s/%s", env, name); if (is_present(fullname)) return fullname; } @@ -817,40 +864,34 @@ 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; - 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); + 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; + 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; @@ -897,14 +938,20 @@ next: fclose(out); 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); @@ -917,8 +964,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; |