]> git.meshlink.io Git - meshlink/commitdiff
Add modify_config_file() to allow overwriting existing configuration values.
authorGuus Sliepen <guus@meshlink.io>
Fri, 11 Mar 2016 15:01:24 +0000 (16:01 +0100)
committerGuus Sliepen <guus@meshlink.io>
Sun, 25 Jun 2017 14:41:55 +0000 (16:41 +0200)
src/conf.c
src/conf.h

index ef595efca958f8cdb22ad240f41fb4f09864f0d1..af8b0b0e20ba5e44a3c9953e5562577ef17eafd8 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "system.h"
+#include <assert.h>
 
 #include "splay_tree.h"
 #include "connection.h"
@@ -387,115 +388,110 @@ bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *
        return write_config_file(config_tree, filename);
 }
 
-bool change_config_file(meshlink_handle_t *mesh, const char *name, const char *key, const char *value) {
+bool modify_config_file(struct meshlink_handle *mesh, const char *name, const char *key, const char *value, bool replace) {
+       assert(mesh && name && key && (replace || value));
+
        char filename[PATH_MAX];
        char tmpname[PATH_MAX];
-       char buf[MAX_STRING_SIZE];
-       const int keylen = strlen(key);
+       bool error = false;
+
+       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(tmpname, sizeof tmpname, "%s.tmp", filename);
 
-       snprintf(filename, PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
-       snprintf(tmpname, PATH_MAX, "%s.tmp", filename);
+       FILE *fr = fopen(filename, "r");
 
-       FILE *in = fopen(filename, "r");
-       if(!in) {
-               // Hm, maybe the file does not exist? Try appending.
-               return append_config_file(mesh, name, key, value);
+       if(!fr) {
+               logger(mesh, MESHLINK_ERROR, "Cannot open config file %s: %s", filename, strerror(errno));
+               return false;
        }
 
-       FILE *out = fopen(tmpname, "w");
-       if(!out) {
-               logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
-               fclose(in);
+       FILE *fw = fopen(tmpname, "w");
+
+       if(!fw) {
+               logger(mesh, MESHLINK_ERROR, "Cannot open temporary file %s: %s", tmpname, strerror(errno));
+               fclose(fr);
                return false;
        }
 
-       bool ignore = false;
+       char buf[4096];
+       char *sep;
+       bool found = false;
 
-       while(readline(in, buf, sizeof buf)) {
-               if(ignore) {
-                       if(!strncmp(buf, "-----END", 8))
-                               ignore = false;
-               } else {
-                       if(!strncmp(buf, "-----BEGIN", 10))
-                               ignore = true;
+       while(readline(fr, buf, sizeof buf)) {
+               if(!*buf || *buf == '#')
+                       goto copy;
+
+               sep = strchr(buf, ' ');
+               if(!sep)
+                       goto copy;
+
+               *sep = 0;
+               if(strcmp(buf, key)) {
+                       *sep = ' ';
+                       goto copy;
                }
 
-               if(!ignore && !strncmp(buf, key, keylen)) {
-                       if(strchr("\t =", buf[keylen])) {
+               if(!value) {
+                       found = true;
+                       continue;
+               }
+
+               // We found the key and the value. Keep one copy around.
+               if(sep[1] == '=' && sep[2] == ' ' && !strcmp(sep + 3, value)) {
+                       if(found)
                                continue;
-                       }
+                       found = true;
                }
 
-               fputs(buf, out);
-               fputc('\n', out);
-       }       
+               // We found the key but with a different value, delete it if wanted.
+               if(!found && replace)
+                       continue;
 
-       if(ferror(in)) {
-               logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", filename, strerror(errno));
-               fclose(in);
-               fclose(out);
-               return false;
+               *sep = ' ';
+
+copy:
+               fprintf(fw, "%s\n", buf);
        }
 
-       fclose(in);
+       if(ferror(fr))
+               error = true;
+
+       fclose(fr);
 
-       fprintf(out, "%s = %s\n", key, value);
+       // Add new key/value pair if necessary
+       if(!found && value)
+               fprintf(fw, "%s = %s\n", key, value);
 
-       if(ferror(out)) {
-               logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
-               fclose(out);
+       if(ferror(fw))
+               error = true;
+
+       if(fclose(fw))
+               error = true;
+
+       // If any error occured during reading or writing, exit.
+       if(error) {
+               unlink(tmpname);
                return false;
        }
 
-       fclose(out);
-
+       // Try to atomically replace the old config file with the new one.
 #ifdef HAVE_MINGW
-       // We cannot atomically replace files on Windows.
        char bakname[PATH_MAX];
-       snprintf(bakname, PATH_MAX, "%s.bak", filename);
-       if(rename(tmpname, bakfile) || rename(bakfile, filename)) {
-               rename(bakfile, filename);
+       snprintf(bakname, sizeof bakname, "%s.bak", filename);
+       if(rename(filename, bakname) || rename(tmpname, filename)) {
+               rename(bakname, filename);
 #else
        if(rename(tmpname, filename)) {
 #endif
-               logger(mesh, MESHLINK_ERROR, "Failed to update `%s': %s", filename, strerror(errno));
                return false;
+       } else {
+#ifdef HAVE_MINGW
+               unlink(bakname);
+#endif
+               return true;
        }
-
-       return true;
 }
 
 bool append_config_file(meshlink_handle_t *mesh, const char *name, const char *key, const char *value) {
-       char filename[PATH_MAX];
-       snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
-
-       FILE *fp = fopen(filename, "a");
-
-       if(!fp) {
-               logger(mesh, MESHLINK_ERROR, "Cannot open config file %s: %s", filename, strerror(errno));
-               return false;
-       }
-
-       // Check if we don't add a duplicate entry
-
-       char entry[MAX_STRING_SIZE];
-       snprintf(entry, sizeof entry, "%s = %s", key, value);
-
-       char buffer[MAX_STRING_SIZE];
-       bool found = false;
-
-       while(readline(fp, buffer, sizeof buffer)) {
-               if(!strcmp(buffer, entry)) {
-                       found = true;
-                       break;
-               }
-       }
-
-       // If not, append the new entry
-
-       if(!found)
-               fprintf(fp, "%s\n", entry);
-
-       fclose(fp);
-       return true;
+       return modify_config_file(mesh, name, key, value, false);
 }
index b1e50c7744b95fe462761b8ec8d0b2bcbb369daf..46f1c89e68f2e0365f4b610270e02ca853fd9f0e 100644 (file)
@@ -52,7 +52,7 @@ extern bool write_config_file(const struct splay_tree_t *, const char *);
 extern bool read_server_config(struct meshlink_handle *mesh);
 extern bool read_host_config(struct meshlink_handle *mesh, struct splay_tree_t *, const char *);
 extern bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *, const char *);
-extern bool change_config_file(struct meshlink_handle *mesh, const char *, const char *, const char *);
+extern bool modify_config_file(struct meshlink_handle *mesh, const char *, const char *, const char *, bool);
 extern bool append_config_file(struct meshlink_handle *mesh, const char *, const char *, const char *);
 
 #endif /* __MESHLINK_CONF_H__ */