X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fconf.c;h=dd0761705ee0b3ff356d195500a4269b56299309;hb=HEAD;hp=212b7c4ac7ae53d832bfe9e54e89344fa36b982e;hpb=6bb60661aa20e6aa4a6a6c2244a3fb7df6cf2c4d;p=meshlink diff --git a/src/conf.c b/src/conf.c index 212b7c4a..db91d5fb 100644 --- a/src/conf.c +++ b/src/conf.c @@ -69,7 +69,7 @@ static void make_used_invitation_path(meshlink_handle_t *mesh, const char *conf_ } /// Remove a directory recursively -static void deltree(const char *dirname) { +static bool deltree(const char *dirname) { assert(dirname); DIR *d = opendir(dirname); @@ -79,21 +79,27 @@ static void deltree(const char *dirname) { while((ent = readdir(d))) { if(ent->d_name[0] == '.') { - continue; + if(!ent->d_name[1] || (ent->d_name[1] == '.' && !ent->d_name[2])) { + continue; + } } char filename[PATH_MAX]; snprintf(filename, sizeof(filename), "%s" SLASH "%s", dirname, ent->d_name); if(unlink(filename)) { - deltree(filename); + if(!deltree(filename)) { + return false; + } } } closedir(d); + } else { + return errno == ENOENT; } - rmdir(dirname); + return rmdir(dirname) == 0; } bool sync_path(const char *pathname) { @@ -157,7 +163,11 @@ bool config_init(meshlink_handle_t *mesh, const char *conf_subdir) { // Create "current" sub-directory in the confbase snprintf(path, sizeof(path), "%s" SLASH "%s", mesh->confbase, conf_subdir); - deltree(path); + + if(!deltree(path)) { + logger(mesh, MESHLINK_DEBUG, "Could not delete directory %s: %s\n", path, strerror(errno)); + return false; + } if(mkdir(path, 0700)) { logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", path, strerror(errno)); @@ -218,8 +228,14 @@ bool config_destroy(const char *confbase, const char *conf_subdir) { } snprintf(path, sizeof(path), "%s" SLASH "%s", confbase, conf_subdir); - deltree(path); - return true; + + if(!deltree(path)) { + logger(NULL, MESHLINK_ERROR, "Cannot delete %s: %s\n", path, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; + return false; + } + + return sync_path(confbase); } static bool copytree(const char *src_dir_name, const void *src_key, const char *dst_dir_name, const void *dst_key) { @@ -234,14 +250,20 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(!src_dir) { logger(NULL, MESHLINK_ERROR, "Could not open directory file %s\n", src_dir_name); + meshlink_errno = MESHLINK_ESTORAGE; return false; } // Delete if already exists and create a new destination directory - deltree(dst_dir_name); + if(!deltree(dst_dir_name)) { + logger(NULL, MESHLINK_ERROR, "Cannot delete %s: %s\n", dst_dir_name, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; + return false; + } if(mkdir(dst_dir_name, 0700)) { logger(NULL, MESHLINK_ERROR, "Could not create directory %s\n", dst_filename); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -256,6 +278,7 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(ent->d_type == DT_DIR) { if(!copytree(src_filename, src_key, dst_filename, dst_key)) { logger(NULL, MESHLINK_ERROR, "Copying %s to %s failed\n", src_filename, dst_filename); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -268,6 +291,7 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(stat(src_filename, &st)) { logger(NULL, MESHLINK_ERROR, "Could not stat file `%s': %s\n", src_filename, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -275,18 +299,21 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(!f) { logger(NULL, MESHLINK_ERROR, "Failed to open `%s': %s\n", src_filename, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; return false; } if(!config_read_file(NULL, f, &config, src_key)) { logger(NULL, MESHLINK_ERROR, "Failed to read `%s': %s\n", src_filename, strerror(errno)); fclose(f); + meshlink_errno = MESHLINK_ESTORAGE; return false; } if(fclose(f)) { logger(NULL, MESHLINK_ERROR, "Failed to close `%s': %s\n", src_filename, strerror(errno)); config_free(&config); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -295,6 +322,7 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(!f) { logger(NULL, MESHLINK_ERROR, "Failed to open `%s': %s", dst_filename, strerror(errno)); config_free(&config); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -302,12 +330,14 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * logger(NULL, MESHLINK_ERROR, "Failed to write `%s': %s", dst_filename, strerror(errno)); config_free(&config); fclose(f); + meshlink_errno = MESHLINK_ESTORAGE; return false; } if(fclose(f)) { logger(NULL, MESHLINK_ERROR, "Failed to close `%s': %s", dst_filename, strerror(errno)); config_free(&config); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -319,6 +349,7 @@ static bool copytree(const char *src_dir_name, const void *src_key, const char * if(utime(dst_filename, ×)) { logger(NULL, MESHLINK_ERROR, "Failed to utime `%s': %s", dst_filename, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; return false; } } @@ -368,13 +399,13 @@ bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const c snprintf(old_path, sizeof(old_path), "%s" SLASH "%s", mesh->confbase, old_conf_subdir); snprintf(new_path, sizeof(new_path), "%s" SLASH "%s", mesh->confbase, new_conf_subdir); - return rename(old_path, new_path) == 0; + return rename(old_path, new_path) == 0 && sync_path(mesh->confbase); } bool config_sync(meshlink_handle_t *mesh, const char *conf_subdir) { assert(conf_subdir); - if(!mesh->confbase) { + if(!mesh->confbase || mesh->storage_policy == MESHLINK_STORAGE_DISABLED) { return true; } @@ -453,11 +484,13 @@ bool meshlink_confbase_exists(meshlink_handle_t *mesh) { } /// Lock the main configuration file. Creates confbase if necessary. -bool main_config_lock(meshlink_handle_t *mesh) { +bool main_config_lock(meshlink_handle_t *mesh, const char *lock_filename) { if(!mesh->confbase) { return true; } + assert(lock_filename); + if(mkdir(mesh->confbase, 0700) && errno != EEXIST) { logger(NULL, MESHLINK_ERROR, "Cannot create configuration directory %s: %s", mesh->confbase, strerror(errno)); meshlink_close(mesh); @@ -465,13 +498,10 @@ bool main_config_lock(meshlink_handle_t *mesh) { return NULL; } - char path[PATH_MAX]; - snprintf(path, sizeof(path), "%s" SLASH "meshlink.lock", mesh->confbase); - - mesh->lockfile = fopen(path, "w+"); + mesh->lockfile = fopen(lock_filename, "w+"); if(!mesh->lockfile) { - logger(NULL, MESHLINK_ERROR, "Cannot not open %s: %s\n", path, strerror(errno)); + logger(NULL, MESHLINK_ERROR, "Cannot not open %s: %s\n", lock_filename, strerror(errno)); meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -485,7 +515,7 @@ bool main_config_lock(meshlink_handle_t *mesh) { #else if(flock(fileno(mesh->lockfile), LOCK_EX | LOCK_NB) != 0) { - logger(NULL, MESHLINK_ERROR, "Cannot lock %s: %s\n", path, strerror(errno)); + logger(NULL, MESHLINK_ERROR, "Cannot lock %s: %s\n", lock_filename, strerror(errno)); fclose(mesh->lockfile); mesh->lockfile = NULL; meshlink_errno = MESHLINK_EBUSY; @@ -874,7 +904,7 @@ bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const cha return false; } - if(mesh->loop.now.tv_sec >= st.st_mtime + mesh->invitation_timeout) { + if(time(NULL) >= st.st_mtime + mesh->invitation_timeout) { logger(mesh, MESHLINK_ERROR, "Peer tried to use an outdated invitation file %s\n", name); fclose(f); unlink(used_path); @@ -1007,3 +1037,79 @@ size_t invitation_purge_old(meshlink_handle_t *mesh, time_t deadline) { return count; } + +/// Purge invitations for the given node +size_t invitation_purge_node(meshlink_handle_t *mesh, const char *node_name) { + if(!mesh->confbase) { + return true; + } + + char path[PATH_MAX]; + make_invitation_path(mesh, "current", "", path, sizeof(path)); + + DIR *dir = opendir(path); + + if(!dir) { + logger(mesh, MESHLINK_DEBUG, "Could not read directory %s: %s\n", path, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; + return 0; + } + + errno = 0; + size_t count = 0; + struct dirent *ent; + + while((ent = readdir(dir))) { + if(strlen(ent->d_name) != 24) { + continue; + } + + char invname[PATH_MAX]; + + if(snprintf(invname, sizeof(invname), "%s" SLASH "%s", path, ent->d_name) >= PATH_MAX) { + logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", path, ent->d_name); + continue; + } + + FILE *f = fopen(invname, "r"); + + if(!f) { + errno = 0; + continue; + } + + config_t config; + + if(!config_read_file(mesh, f, &config, mesh->config_key)) { + logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", invname, strerror(errno)); + config_free(&config); + fclose(f); + errno = 0; + continue; + } + + packmsg_input_t in = {config.buf, config.len}; + packmsg_get_uint32(&in); // skip version + char *name = packmsg_get_str_dup(&in); + + if(name && !strcmp(name, node_name)) { + logger(mesh, MESHLINK_DEBUG, "Removing invitation for %s", node_name); + unlink(invname); + } + + free(name); + config_free(&config); + fclose(f); + } + + if(errno) { + logger(mesh, MESHLINK_DEBUG, "Error while reading directory %s: %s\n", path, strerror(errno)); + closedir(dir); + meshlink_errno = MESHLINK_ESTORAGE; + return 0; + } + + closedir(dir); + + return count; +}