]> git.meshlink.io Git - meshlink/blobdiff - src/conf.c
Add a function to change a configuration file on disk.
[meshlink] / src / conf.c
index e76262271703bf6d477b225934f3361c4a7468c7..2195d69c42ff32230e85f54c67bae00aeac9a674 100644 (file)
@@ -144,6 +144,22 @@ bool get_config_int(const config_t *cfg, int *result) {
        return false;
 }
 
+bool set_config_int(config_t *cfg, int val)
+{
+       if(!cfg)
+               return false;
+
+       char val_str[1024];
+       snprintf(val_str, sizeof(val_str), "%d", val);
+
+       if(cfg->value)
+               free(cfg->value);
+
+       cfg->value = xstrdup(val_str);
+
+       return true;
+}
+
 bool get_config_string(const config_t *cfg, char **result) {
        if(!cfg)
                return false;
@@ -153,6 +169,19 @@ bool get_config_string(const config_t *cfg, char **result) {
        return true;
 }
 
+bool set_config_string(config_t *cfg, const char* val)
+{
+       if(!cfg)
+               return false;
+
+       if(cfg->value)
+               free(cfg->value);
+
+       cfg->value = xstrdup(val);
+
+       return true;
+}
+
 bool get_config_address(const config_t *cfg, struct addrinfo **result) {
        struct addrinfo *ai;
 
@@ -291,6 +320,45 @@ bool read_config_file(splay_tree_t *config_tree, const char *fname) {
        return result;
 }
 
+bool write_config_file(const struct splay_tree_t *config_tree, const char *fname)
+{
+       FILE *fp;
+
+       fp = fopen(fname, "w+");
+
+       if(!fp) {
+               logger(NULL, MESHLINK_ERROR, "Cannot open config file %s: %s", fname, strerror(errno));
+               return false;
+       }
+
+       for splay_each(config_t, cnf, config_tree)
+       {
+               if(fwrite(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable)) {
+                       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+                       return false;
+               }
+
+               if(fwrite(" = ", sizeof(char), 3, fp) < 3) {
+                       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+                       return false;
+               }
+
+               if(fwrite(cnf->value, sizeof(char), strlen(cnf->value), fp) < strlen(cnf->value)) {
+                       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+                       return false;
+               }
+
+               if(fwrite("\n", sizeof(char), 1, fp) < 1) {
+                       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+                       return false;
+               }
+       }
+
+       fclose(fp);
+
+       return true;
+}
+
 bool read_server_config(meshlink_handle_t *mesh) {
        char filename[PATH_MAX];
        bool x;
@@ -315,6 +383,92 @@ bool read_host_config(meshlink_handle_t *mesh, splay_tree_t *config_tree, const
        return x;
 }
 
+bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *config_tree, const char *name)
+{
+       char filename[PATH_MAX];
+
+       snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       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);