- xasprintf(&fname, "%s" SLASH "tinc.conf", confbase);
- errno = 0;
- x = read_config_file(config_tree, fname);
-
- // We will try to read the conf files in the "conf.d" dir
- if (x) {
- char * dname;
- xasprintf(&dname, "%s" SLASH "conf.d", confbase);
- DIR *dir = opendir (dname);
- // If we can find this dir
- if (dir) {
- struct dirent *ep;
- // We list all the files in it
- while (x && (ep = readdir (dir))) {
- size_t l = strlen(ep->d_name);
- // And we try to read the ones that end with ".conf"
- if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
- free(fname);
- xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
- x = read_config_file(config_tree, fname);
- }
- }
- closedir (dir);
+ 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(tmp_path, "w");
+
+ if(!f) {
+ logger(mesh, MESHLINK_ERROR, "Failed to open `%s': %s", tmp_path, strerror(errno));
+ meshlink_errno = MESHLINK_ESTORAGE;
+ return false;
+ }
+
+ if(!config_write_file(mesh, f, config, key)) {
+ logger(mesh, MESHLINK_ERROR, "Failed to write `%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));
+ meshlink_errno = MESHLINK_ESTORAGE;
+ fclose(f);
+ return false;
+ }
+
+ if(fclose(f)) {
+ logger(mesh, MESHLINK_ERROR, "Failed to close `%s': %s", tmp_path, strerror(errno));
+ meshlink_errno = MESHLINK_ESTORAGE;
+ return false;
+ }
+
+ return true;
+}
+
+/// Read an invitation file from the confbase sub-directory, and immediately delete it.
+bool invitation_read(meshlink_handle_t *mesh, const char *conf_subdir, const char *name, config_t *config, void *key) {
+ assert(conf_subdir);
+ assert(name);
+ assert(config);
+
+ if(!mesh->confbase) {
+ return false;
+ }
+
+ char path[PATH_MAX];
+ char used_path[PATH_MAX];
+ make_invitation_path(mesh, conf_subdir, name, path, sizeof(path));
+ make_used_invitation_path(mesh, conf_subdir, name, used_path, sizeof(used_path));
+
+ // Atomically rename the invitation file
+ if(rename(path, used_path)) {
+ if(errno == ENOENT) {
+ logger(mesh, MESHLINK_ERROR, "Peer tried to use non-existing invitation %s\n", name);
+ } else {
+ logger(mesh, MESHLINK_ERROR, "Error trying to rename invitation %s\n", name);