]> git.meshlink.io Git - meshlink/blobdiff - src/conf.c
Fix resource leaks found by cppcheck.
[meshlink] / src / conf.c
index ad4b28b89708e0db5378ac5ec8ef460295c04dce..ef595efca958f8cdb22ad240f41fb4f09864f0d1 100644 (file)
@@ -333,30 +333,26 @@ bool write_config_file(const struct splay_tree_t *config_tree, const char *fname
 
        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(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable))
+                       goto error;
 
-               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(" = ", sizeof(char), 3, fp) < 3)
+                       goto error;
 
-               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(cnf->value, sizeof(char), strlen(cnf->value), fp) < strlen(cnf->value))
+                       goto error;
 
-               if(fwrite("\n", sizeof(char), 1, fp) < 1) {
-                       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
-                       return false;
-               }
+               if(fwrite("\n", sizeof(char), 1, fp) < 1)
+                       goto error;
        }
 
        fclose(fp);
-
        return true;
+
+error:
+       logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+       fclose(fp);
+       return false;
 }
 
 bool read_server_config(meshlink_handle_t *mesh) {
@@ -391,6 +387,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);
@@ -399,10 +473,29 @@ bool append_config_file(meshlink_handle_t *mesh, const char *name, const char *k
 
        if(!fp) {
                logger(mesh, MESHLINK_ERROR, "Cannot open config file %s: %s", filename, strerror(errno));
-       } else {
-               fprintf(fp, "%s = %s\n", key, value);
-               fclose(fp);
+               return false;
        }
 
-       return fp != NULL;
+       // 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;
 }