From: Guus Sliepen Date: Thu, 5 Sep 2019 17:33:53 +0000 (+0200) Subject: Write config files atomically. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=349d48bd8c9659017ebd2ebf105a14776ceb9c85;p=meshlink Write config files atomically. --- diff --git a/src/conf.c b/src/conf.c index e0d35950..bafa87d4 100644 --- a/src/conf.c +++ b/src/conf.c @@ -616,23 +616,36 @@ bool config_write(meshlink_handle_t *mesh, const char *conf_subdir, const char * } char path[PATH_MAX]; + char tmp_path[PATH_MAX + 4]; make_host_path(mesh, conf_subdir, name, path, sizeof(path)); + snprintf(tmp_path, sizeof(tmp_path), "%s.tmp", path); - FILE *f = fopen(path, "w"); + FILE *f = fopen(tmp_path, "w"); if(!f) { - logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", tmp_path, strerror(errno)); return false; } if(!config_write_file(mesh, f, config, key)) { - logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmp_path, strerror(errno)); + fclose(f); + return false; + } + + if(fsync(fileno(f))) { + logger(mesh, MESHLINK_ERROR, "Failed to sync `%s': %s", tmp_path, strerror(errno)); fclose(f); return false; } if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", tmp_path, strerror(errno)); + return false; + } + + if(rename(tmp_path, path)) { + logger(mesh, MESHLINK_ERROR, "Failed to rename `%s' to `%s': %s", tmp_path, path, strerror(errno)); return false; } @@ -673,23 +686,36 @@ bool main_config_write(meshlink_handle_t *mesh, const char *conf_subdir, const c } char path[PATH_MAX]; + char tmp_path[PATH_MAX + 4]; make_main_path(mesh, conf_subdir, path, sizeof(path)); + snprintf(tmp_path, sizeof(tmp_path), "%s.tmp", path); - FILE *f = fopen(path, "w"); + FILE *f = fopen(tmp_path, "w"); if(!f) { - logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", tmp_path, strerror(errno)); return false; } if(!config_write_file(mesh, f, config, key)) { - logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmp_path, strerror(errno)); fclose(f); return false; } + if(fsync(fileno(f))) { + logger(mesh, MESHLINK_ERROR, "Failed to sync `%s': %s", tmp_path, strerror(errno)); + fclose(f); + return false; + } + + if(rename(tmp_path, path)) { + logger(mesh, MESHLINK_ERROR, "Failed to rename `%s' to `%s': %s", tmp_path, path, strerror(errno)); + return false; + } + if(fclose(f)) { - logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); + logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", tmp_path, strerror(errno)); return false; } @@ -777,6 +803,11 @@ bool invitation_write(meshlink_handle_t *mesh, const char *conf_subdir, const ch return false; } + if(fsync(fileno(f))) { + logger(mesh, MESHLINK_ERROR, "Failed to sync `%s': %s", path, strerror(errno)); + return false; + } + if(fclose(f)) { logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", path, strerror(errno)); return false;