]> git.meshlink.io Git - meshlink/commitdiff
Lock meshlink.conf to ensure only one instance can run at a time.
authorGuus Sliepen <guus@meshlink.io>
Tue, 9 Oct 2018 12:06:04 +0000 (14:06 +0200)
committerGuus Sliepen <guus@meshlink.io>
Tue, 9 Oct 2018 21:33:18 +0000 (23:33 +0200)
src/conf.c
src/conf.h
src/meshlink.c
src/meshlink.h
src/meshlink_internal.h
src/net_socket.c

index 5d5c46c144dd14fcd8576f2393a07cdf770a5ed9..e3574ea5442888b3fa3edee6886040264f2378c5 100644 (file)
@@ -40,13 +40,7 @@ static int config_compare(const config_t *a, const config_t *b) {
                return result;
        }
 
-       result = a->line - b->line;
-
-       if(result) {
-               return result;
-       } else {
-               return a->file ? strcmp(a->file, b->file) : 0;
-       }
+       return result = a->line - b->line;
 }
 
 void init_configuration(splay_tree_t **config_tree) {
@@ -66,18 +60,8 @@ config_t *new_config(void) {
 }
 
 void free_config(config_t *cfg) {
-       if(cfg->variable) {
-               free(cfg->variable);
-       }
-
-       if(cfg->value) {
-               free(cfg->value);
-       }
-
-       if(cfg->file) {
-               free(cfg->file);
-       }
-
+       free(cfg->variable);
+       free(cfg->value);
        free(cfg);
 }
 
@@ -89,7 +73,6 @@ config_t *lookup_config(splay_tree_t *config_tree, char *variable) {
        config_t cfg, *found;
 
        cfg.variable = variable;
-       cfg.file = NULL;
        cfg.line = 0;
 
        found = splay_search_closest_greater(config_tree, &cfg);
@@ -137,8 +120,8 @@ bool get_config_bool(const config_t *cfg, bool *result) {
                return true;
        }
 
-       logger(NULL, MESHLINK_ERROR, "\"yes\" or \"no\" expected for configuration variable %s in %s line %d",
-              cfg->variable, cfg->file, cfg->line);
+       logger(NULL, MESHLINK_ERROR, "\"yes\" or \"no\" expected for configuration variable %s in line %d",
+              cfg->variable, cfg->line);
 
        return false;
 }
@@ -152,8 +135,8 @@ bool get_config_int(const config_t *cfg, int *result) {
                return true;
        }
 
-       logger(NULL, MESHLINK_ERROR, "Integer expected for configuration variable %s in %s line %d",
-              cfg->variable, cfg->file, cfg->line);
+       logger(NULL, MESHLINK_ERROR, "Integer expected for configuration variable %s in line %d",
+              cfg->variable, cfg->line);
 
        return false;
 }
@@ -213,8 +196,8 @@ bool get_config_address(const config_t *cfg, struct addrinfo **result) {
                return true;
        }
 
-       logger(NULL, MESHLINK_ERROR, "Hostname or IP address expected for configuration variable %s in %s line %d",
-              cfg->variable, cfg->file, cfg->line);
+       logger(NULL, MESHLINK_ERROR, "Hostname or IP address expected for configuration variable %s in line %d",
+              cfg->variable, cfg->line);
 
        return false;
 }
@@ -285,7 +268,6 @@ config_t *parse_config_line(char *line, const char *fname, int lineno) {
        cfg = new_config();
        cfg->variable = xstrdup(variable);
        cfg->value = xstrdup(value);
-       cfg->file = xstrdup(fname);
        cfg->line = lineno;
 
        return cfg;
index fd48ea64feb515b8cd94cf34a2cb70aed687b7db..fb29f02c829cdf27496dba533fc179ea4127d8d2 100644 (file)
@@ -27,7 +27,6 @@
 typedef struct config_t {
        char *variable;
        char *value;
-       char *file;
        int line;
 } config_t;
 
@@ -45,10 +44,6 @@ extern bool get_config_string(const config_t *, char **);
 extern bool set_config_string(config_t *, const char *);
 extern bool get_config_address(const config_t *, struct addrinfo **);
 
-extern config_t *parse_config_line(char *, const char *, int);
-extern bool read_config_file(struct splay_tree_t *, const char *);
-extern bool write_config_file(const struct splay_tree_t *, const char *);
-
 extern bool read_server_config(struct meshlink_handle *mesh);
 extern bool read_host_config(struct meshlink_handle *mesh, struct splay_tree_t *, const char *);
 extern bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *, const char *);
index a26c4181af4325193d2d59ba0268c52335f29c64..6df7c419261fc30f175ef016d00538c295d77f29 100644 (file)
@@ -869,6 +869,8 @@ static const char *errstr[] = {
        [MESHLINK_ESTORAGE] = "Storage error",
        [MESHLINK_ENETWORK] = "Network error",
        [MESHLINK_EPEER] = "Error communicating with peer",
+       [MESHLINK_ENOTSUP] = "Operation not supported",
+       [MESHLINK_EBUSY] = "MeshLink instance already in use",
 };
 
 const char *meshlink_strerror(meshlink_errno_t err) {
@@ -1116,6 +1118,32 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c
                }
        }
 
+       // Open the configuration file and lock it
+
+       mesh->conffile = fopen(filename, "r");
+
+       if(!mesh->conffile) {
+               logger(NULL, MESHLINK_ERROR, "Cannot not open %s: %s\n", filename, strerror(errno));
+               meshlink_close(mesh);
+               meshlink_errno = MESHLINK_ESTORAGE;
+               return NULL;
+       }
+
+#ifdef FD_CLOEXEC
+       fcntl(fileno(mesh->conffile), F_SETFD, FD_CLOEXEC);
+#endif
+
+#ifdef HAVE_MINGW
+       // TODO: use _locking()?
+#else
+       if(flock(fileno(mesh->conffile), LOCK_EX | LOCK_NB) != 0) {
+               logger(NULL, MESHLINK_ERROR, "Cannot lock %s: %s\n", filename, strerror(errno));
+               meshlink_close(mesh);
+               meshlink_errno = MESHLINK_EBUSY;
+               return NULL;
+       }
+#endif
+
        // Read the configuration
 
        init_configuration(&mesh->config);
@@ -1325,6 +1353,10 @@ void meshlink_close(meshlink_handle_t *mesh) {
        free(mesh->confbase);
        pthread_mutex_destroy(&(mesh->mesh_mutex));
 
+       if(mesh->conffile) {
+               fclose(mesh->conffile);
+        }
+
        memset(mesh, 0, sizeof(*mesh));
 
        free(mesh);
index 15fb6e6965cedd6569f6de89c30afc00d85eaef3..2f2e7f841054e2ea3d21622c09906bb881d95970 100644 (file)
@@ -53,17 +53,18 @@ typedef struct meshlink_channel meshlink_channel_t;
 
 /// Code of most recent error encountered.
 typedef enum {
-       MESHLINK_OK,     ///< Everything is fine
-       MESHLINK_EINVAL, ///< Invalid parameter(s) to function call
-       MESHLINK_ENOMEM, ///< Out of memory
-       MESHLINK_ENOENT, ///< Node is not known
-       MESHLINK_EEXIST, ///< Node already exists
+       MESHLINK_OK,        ///< Everything is fine
+       MESHLINK_EINVAL,    ///< Invalid parameter(s) to function call
+       MESHLINK_ENOMEM,    ///< Out of memory
+       MESHLINK_ENOENT,    ///< Node is not known
+       MESHLINK_EEXIST,    ///< Node already exists
        MESHLINK_EINTERNAL, ///< MeshLink internal error
-       MESHLINK_ERESOLV, ///< MeshLink could not resolve a hostname
-       MESHLINK_ESTORAGE, ///< MeshLink coud not load or write data from/to disk
-       MESHLINK_ENETWORK, ///< MeshLink encountered a network error
-       MESHLINK_EPEER, ///< A peer caused an error
-       MESHLINK_ENOTSUP, ///< The operation is not supported in the current configuration of MeshLink
+       MESHLINK_ERESOLV,   ///< MeshLink could not resolve a hostname
+       MESHLINK_ESTORAGE,  ///< MeshLink coud not load or write data from/to disk
+       MESHLINK_ENETWORK,  ///< MeshLink encountered a network error
+       MESHLINK_EPEER,     ///< A peer caused an error
+       MESHLINK_ENOTSUP,   ///< The operation is not supported in the current configuration of MeshLink
+       MESHLINK_EBUSY,     ///< The MeshLink instance is already in use by another process
 } meshlink_errno_t;
 
 /// Device class
index 545bd52615c87edb6b5b0b23dc9bf253de6fbbf8..92774c49baf3c9481d4aac62273256156c77d629 100644 (file)
@@ -66,6 +66,7 @@ struct meshlink_handle {
        dev_class_t devclass;
 
        char *confbase;
+       FILE *conffile;
 
        meshlink_receive_cb_t receive_cb;
        meshlink_node_status_cb_t node_status_cb;
index 1e981af6b2a61e48357e32b23a83dbbfa613cacf..ea5fdaa03853131d9b19c7b9b17b8fb06525873a 100644 (file)
@@ -782,8 +782,8 @@ void try_outgoing_connections(meshlink_handle_t *mesh) {
 
                if(!check_id(name)) {
                        logger(mesh, MESHLINK_ERROR,
-                              "Invalid name for outgoing connection in %s line %d",
-                              cfg->file, cfg->line);
+                              "Invalid name for outgoing connection in line %d",
+                              cfg->line);
                        free(name);
                        continue;
                }