]> git.meshlink.io Git - meshlink/commitdiff
Add a function to change a configuration file on disk.
authorGuus Sliepen <guus@meshlink.io>
Tue, 16 Dec 2014 13:50:42 +0000 (14:50 +0100)
committerGuus Sliepen <guus@meshlink.io>
Sat, 27 Dec 2014 16:25:37 +0000 (17:25 +0100)
src/conf.c
src/conf.h

index ad4b28b89708e0db5378ac5ec8ef460295c04dce..2195d69c42ff32230e85f54c67bae00aeac9a674 100644 (file)
@@ -391,6 +391,84 @@ 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) {
+       char filename[PATH_MAX];
+       char tmpname[PATH_MAX];
+       char buf[MAX_STRING_SIZE];
+       const int keylen = strlen(key);
+
+       snprintf(filename, PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(tmpname, PATH_MAX, "%s.tmp", filename);
+
+       FILE *in = fopen(filename, "r");
+       if(!in) {
+               // Hm, maybe the file does not exist? Try appending.
+               return append_config_file(mesh, name, key, value);
+       }
+
+       FILE *out = fopen(tmpname, "w");
+       if(!out) {
+               logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
+               fclose(in);
+               return false;
+       }
+
+       bool ignore = false;
+
+       while(readline(in, buf, sizeof buf)) {
+               if(ignore) {
+                       if(!strncmp(buf, "-----END", 8))
+                               ignore = false;
+               } else {
+                       if(!strncmp(buf, "-----BEGIN", 10))
+                               ignore = true;
+               }
+
+               if(!ignore && !strncmp(buf, key, keylen)) {
+                       if(strchr("\t =", buf[keylen])) {
+                               continue;
+                       }
+               }
+
+               fputs(buf, out);
+               fputc('\n', out);
+       }       
+
+       if(ferror(in)) {
+               logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", filename, strerror(errno));
+               fclose(in);
+               fclose(out);
+               return false;
+       }
+
+       fclose(in);
+
+       fprintf(out, "%s = %s\n", key, value);
+
+       if(ferror(out)) {
+               logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
+               fclose(out);
+               return false;
+       }
+
+       fclose(out);
+
+#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);
+#else
+       if(rename(tmpname, filename)) {
+#endif
+               logger(mesh, MESHLINK_ERROR, "Failed to update `%s': %s", filename, strerror(errno));
+               return false;
+       }
+
+       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);
index c3cf6f7d642fee59748e4acf92518e95067d32f4..b1e50c7744b95fe462761b8ec8d0b2bcbb369daf 100644 (file)
@@ -52,6 +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 append_config_file(struct meshlink_handle *mesh, const char *, const char *, const char *);
 
 #endif /* __MESHLINK_CONF_H__ */