]> git.meshlink.io Git - meshlink/commitdiff
Call fsync() on the configuration directories where appropriate.
authorGuus Sliepen <guus@meshlink.io>
Thu, 5 Sep 2019 17:56:29 +0000 (19:56 +0200)
committerGuus Sliepen <guus@meshlink.io>
Thu, 5 Sep 2019 18:00:11 +0000 (20:00 +0200)
Just ensuring individual config files are written atomically is good enough
to keep internal consistency, but we want to make sure directory metadata
is also synced to disk when returning from functions that expect the changes
to have been made permanent, such as meshlink_import() and
meshlink_blacklist(). Also do this when we create the initial directory
structure.

We already took care of syncing directory metadata when rotating keys for
encrypted storage.

src/conf.c
src/conf.h
src/meshlink.c

index bafa87d49c5bd5a563e9d82d5969ca4a51f7ec72..8244ba7c918c0fde52fdc361c73c11ec66c93ad3 100644 (file)
@@ -80,18 +80,21 @@ static bool sync_path(const char *pathname) {
 
        if(fd < 0) {
                logger(NULL, MESHLINK_ERROR, "Failed to open %s: %s\n", pathname, strerror(errno));
+               meshlink_errno = MESHLINK_ESTORAGE;
                return false;
        }
 
        if(fsync(fd)) {
                logger(NULL, MESHLINK_ERROR, "Failed to sync %s: %s\n", pathname, strerror(errno));
                close(fd);
+               meshlink_errno = MESHLINK_ESTORAGE;
                return false;
        }
 
        if(close(fd)) {
                logger(NULL, MESHLINK_ERROR, "Failed to close %s: %s\n", pathname, strerror(errno));
                close(fd);
+               meshlink_errno = MESHLINK_ESTORAGE;
                return false;
        }
 
@@ -343,6 +346,31 @@ bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const c
        return rename(old_path, new_path) == 0;
 }
 
+bool config_sync(meshlink_handle_t *mesh, const char *conf_subdir) {
+       if(!mesh->confbase) {
+               return true;
+       }
+
+       if(!conf_subdir) {
+               return false;
+       }
+
+       char path[PATH_MAX];
+       snprintf(path, sizeof(path), "%s" SLASH "%s" SLASH "hosts", mesh->confbase, conf_subdir);
+
+       if(!sync_path(path)) {
+               return false;
+       }
+
+       snprintf(path, sizeof(path), "%s" SLASH "%s", mesh->confbase, conf_subdir);
+
+       if(!sync_path(path)) {
+               return false;
+       }
+
+       return true;
+}
+
 bool meshlink_confbase_exists(meshlink_handle_t *mesh) {
        if(!mesh->confbase) {
                return false;
index 93ee5bb9bebb3f0b5f32ea8a9febf82c90f55b8b..b3763ea7b0970c00c2a8382af65d097959fb44e5 100644 (file)
@@ -39,6 +39,7 @@ extern bool config_init(struct meshlink_handle *mesh, const char *conf_subdir);
 extern bool config_destroy(const char *confbase, const char *conf_subdir);
 extern bool config_copy(struct meshlink_handle *mesh, const char *src_dir_name, const void *src_key, const char *dst_dir_name, const void *dst_key);
 extern bool config_rename(struct meshlink_handle *mesh, const char *old_conf_subdir, const char *new_conf_subdir);
+extern bool config_sync(struct meshlink_handle *mesh, const char *conf_subdir);
 
 extern bool main_config_exists(struct meshlink_handle *mesh, const char *conf_subdir);
 extern bool main_config_lock(struct meshlink_handle *mesh);
index ebe585d2960eed6c0271e03716507a85972c7c7b..164c993784b54e5401f19ba364732d304297c002 100644 (file)
@@ -661,6 +661,11 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len
                }
        }
 
+       /* Ensure the configuration directory metadata is on disk */
+       if(!config_sync(mesh, "current")) {
+               return false;
+       }
+
        sptps_send_record(&(mesh->sptps), 1, ecdsa_get_public_key(mesh->private_key), 32);
 
        logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
@@ -890,6 +895,11 @@ static bool meshlink_setup(meshlink_handle_t *mesh) {
                return false;
        }
 
+       /* Ensure the configuration directory metadata is on disk */
+       if(!config_sync(mesh, "current")) {
+               return false;
+       }
+
        if(!main_config_lock(mesh)) {
                logger(NULL, MESHLINK_ERROR, "Cannot lock main config file\n");
                meshlink_errno = MESHLINK_ESTORAGE;
@@ -2711,6 +2721,10 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
                return false;
        }
 
+       if(!config_sync(mesh, "current")) {
+               return false;
+       }
+
        return true;
 }
 
@@ -2740,6 +2754,8 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
 
        n->status.blacklisted = true;
        node_write_config(mesh, n);
+       config_sync(mesh, "current");
+
        logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
 
        //Immediately terminate any connections we have with the blacklisted node
@@ -2783,6 +2799,7 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) {
 
        n->status.blacklisted = false;
        node_write_config(mesh, n);
+       config_sync(mesh, "current");
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
        return;