| @@ -3,6 +3,7 @@ · 2 unmodified lines |
| 3 | 3 | * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | +#include <sys/mman.h> |
| 6 | 7 | #include <sys/stat.h> |
| 7 | 8 | #include <ctype.h> |
| 8 | 9 | #include <errno.h> |
| @@ -36,6 +37,52 @@ static bool is_dir(const char *path) · 27 unmodified lines |
| 36 | 37 | return S_ISDIR(st.st_mode); |
| 37 | 38 | } |
| 38 | 39 | |
| 40 | +/* return true if the given two files are the same, false otherwise */ |
| 41 | +static bool is_same(const char *file1, const char *file2) |
| 42 | +{ |
| 43 | + int fd1, fd2; |
| 44 | + struct stat st1, st2; |
| 45 | + void *map1, *map2; |
| 46 | + bool ret = false; |
| 47 | + |
| 48 | + fd1 = open(file1, O_RDONLY); |
| 49 | + if (fd1 < 0) |
| 50 | + return ret; |
| 51 | + |
| 52 | + fd2 = open(file2, O_RDONLY); |
| 53 | + if (fd2 < 0) |
| 54 | + goto close1; |
| 55 | + |
| 56 | + ret = fstat(fd1, &st1); |
| 57 | + if (ret) |
| 58 | + goto close2; |
| 59 | + ret = fstat(fd2, &st2); |
| 60 | + if (ret) |
| 61 | + goto close2; |
| 62 | + |
| 63 | + if (st1.st_size != st2.st_size) |
| 64 | + goto close2; |
| 65 | + |
| 66 | + map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); |
| 67 | + if (map1 == MAP_FAILED) |
| 68 | + goto close2; |
| 69 | + |
| 70 | + map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0); |
| 71 | + if (map2 == MAP_FAILED) |
| 72 | + goto close2; |
| 73 | + |
| 74 | + if (bcmp(map1, map2, st1.st_size)) |
| 75 | + goto close2; |
| 76 | + |
| 77 | + ret = true; |
| 78 | +close2: |
| 79 | + close(fd2); |
| 80 | +close1: |
| 81 | + close(fd1); |
| 82 | + |
| 83 | + return ret; |
| 84 | +} |
| 85 | + |
| 39 | 86 | /* |
| 40 | 87 | * Create the parent directory of the given path. |
| 41 | 88 | * |
| @@ -179,7 +226,7 @@ const char *conf_get_configname(void) · 137 unmodified lines |
| 179 | 226 | return name ? name : ".config"; |
| 180 | 227 | } |
| 181 | 228 | |
| 182 | | −const char *conf_get_autoconfig_name(void) |
| 229 | +static const char *conf_get_autoconfig_name(void) |
| 183 | 230 | { |
| 184 | 231 | char *name = getenv("KCONFIG_AUTOCONFIG"); |
| 185 | 232 | |
| @@ -194,7 +241,7 @@ char *conf_get_default_confname(void) · 8 unmodified lines |
| 194 | 241 | name = expand_string(conf_defname); |
| 195 | 242 | env = getenv(SRCTREE); |
| 196 | 243 | if (env) { |
| 197 | | − sprintf(fullname, "%s/%s", env, name); |
| 244 | + snprintf(fullname, sizeof(fullname), "%s/%s", env, name); |
| 198 | 245 | if (is_present(fullname)) |
| 199 | 246 | return fullname; |
| 200 | 247 | } |
| @@ -817,40 +864,34 @@ int conf_write(const char *name) · 616 unmodified lines |
| 817 | 864 | FILE *out; |
| 818 | 865 | struct symbol *sym; |
| 819 | 866 | struct menu *menu; |
| 820 | | − const char *basename; |
| 821 | 867 | const char *str; |
| 822 | | − char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8]; |
| 868 | + char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1]; |
| 823 | 869 | char *env; |
| 824 | 870 | |
| 825 | | − dirname[0] = 0; |
| 826 | | − if (name && name[0]) { |
| 827 | | − char *slash; |
| 828 | | − |
| 829 | | − if (is_dir(name)) { |
| 830 | | − strcpy(dirname, name); |
| 831 | | − strcat(dirname, "/"); |
| 832 | | − basename = conf_get_configname(); |
| 833 | | − } else if ((slash = strrchr(name, '/'))) { |
| 834 | | − int size = slash - name + 1; |
| 835 | | − memcpy(dirname, name, size); |
| 836 | | − dirname[size] = 0; |
| 837 | | − if (slash[1]) |
| 838 | | − basename = slash + 1; |
| 839 | | − else |
| 840 | | − basename = conf_get_configname(); |
| 841 | | − } else |
| 842 | | − basename = name; |
| 843 | | − } else |
| 844 | | − basename = conf_get_configname(); |
| 845 | | − |
| 846 | | − sprintf(newname, "%s%s", dirname, basename); |
| 871 | + if (!name) |
| 872 | + name = conf_get_configname(); |
| 873 | + |
| 874 | + if (!*name) { |
| 875 | + fprintf(stderr, "config name is empty\n"); |
| 876 | + return -1; |
| 877 | + } |
| 878 | + |
| 879 | + if (is_dir(name)) { |
| 880 | + fprintf(stderr, "%s: Is a directory\n", name); |
| 881 | + return -1; |
| 882 | + } |
| 883 | + |
| 884 | + if (make_parent_dir(name)) |
| 885 | + return -1; |
| 886 | + |
| 847 | 887 | env = getenv("KCONFIG_OVERWRITECONFIG"); |
| 848 | | − if (!env || !*env) { |
| 849 | | − sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); |
| 850 | | − out = fopen(tmpname, "w"); |
| 851 | | − } else { |
| 888 | + if (env && *env) { |
| 852 | 889 | *tmpname = 0; |
| 853 | | − out = fopen(newname, "w"); |
| 890 | + out = fopen(name, "w"); |
| 891 | + } else { |
| 892 | + snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp", |
| 893 | + name, (int)getpid()); |
| 894 | + out = fopen(tmpname, "w"); |
| 854 | 895 | } |
| 855 | 896 | if (!out) |
| 856 | 897 | return 1; |
| @@ -897,14 +938,20 @@ next: · 40 unmodified lines |
| 897 | 938 | fclose(out); |
| 898 | 939 | |
| 899 | 940 | if (*tmpname) { |
| 900 | | − strcat(dirname, basename); |
| 901 | | − strcat(dirname, ".old"); |
| 902 | | − rename(newname, dirname); |
| 903 | | − if (rename(tmpname, newname)) |
| 941 | + if (is_same(name, tmpname)) { |
| 942 | + conf_message("No change to %s", name); |
| 943 | + unlink(tmpname); |
| 944 | + sym_set_change_count(0); |
| 945 | + return 0; |
| 946 | + } |
| 947 | + |
| 948 | + snprintf(oldname, sizeof(oldname), "%s.old", name); |
| 949 | + rename(name, oldname); |
| 950 | + if (rename(tmpname, name)) |
| 904 | 951 | return 1; |
| 905 | 952 | } |
| 906 | 953 | |
| 907 | | − conf_message("configuration written to %s", newname); |
| 954 | + conf_message("configuration written to %s", name); |
| 908 | 955 | |
| 909 | 956 | sym_set_change_count(0); |
| 910 | 957 | |
| @@ -917,8 +964,6 @@ static int conf_write_dep(const char *name) · 6 unmodified lines |
| 917 | 964 | struct file *file; |
| 918 | 965 | FILE *out; |
| 919 | 966 | |
| 920 | | − if (!name) |
| 921 | | − name = ".kconfig.d"; |
| 922 | 967 | out = fopen("..config.tmp", "w"); |
| 923 | 968 | if (!out) |
| 924 | 969 | return 1; |