From 349d48bd8c9659017ebd2ebf105a14776ceb9c85 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 5 Sep 2019 19:33:53 +0200 Subject: [PATCH] Write config files atomically. --- src/conf.c | 47 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) 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; -- 2.39.2