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) {
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);
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;
}