plugin-loader: Method added to provide additional search paths for plugins
authorTobias Brunner <tobias@strongswan.org>
Tue, 25 Jun 2013 17:40:52 +0000 (19:40 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 27 Jun 2013 08:27:24 +0000 (10:27 +0200)
src/libstrongswan/plugins/plugin_loader.c
src/libstrongswan/plugins/plugin_loader.h

index e08b123..025e97a 100644 (file)
@@ -17,6 +17,9 @@
 #define _GNU_SOURCE
 #include "plugin_loader.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include <string.h>
 #include <dlfcn.h>
 #include <limits.h>
@@ -60,6 +63,11 @@ struct private_plugin_loader_t {
        linked_list_t *loaded;
 
        /**
+        * List of paths to search for plugins
+        */
+       linked_list_t *paths;
+
+       /**
         * List of names of loaded plugins
         */
        char *loaded_plugins;
@@ -909,17 +917,36 @@ METHOD(plugin_loader_t, add_static_features, void,
        register_features(this, entry);
 }
 
+/**
+ * Tries to find the plugin with the given name in the given path.
+ */
+static bool find_plugin(char *path, char *name, char *buf, char **file)
+{
+       struct stat stb;
+
+       if (path && snprintf(buf, PATH_MAX, "%s/libstrongswan-%s.so",
+                                                path, name) < PATH_MAX)
+       {
+               if (stat(buf, &stb) == 0)
+               {
+                       *file = buf;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
 METHOD(plugin_loader_t, load_plugins, bool,
-       private_plugin_loader_t *this, char *path, char *list)
+       private_plugin_loader_t *this, char *default_path, char *list)
 {
        enumerator_t *enumerator;
        char *token;
        bool critical_failed = FALSE;
 
 #ifdef PLUGINDIR
-       if (path == NULL)
+       if (default_path == NULL)
        {
-               path = PLUGINDIR;
+               default_path = PLUGINDIR;
        }
 #endif /* PLUGINDIR */
 
@@ -943,14 +970,14 @@ METHOD(plugin_loader_t, load_plugins, bool,
                        free(token);
                        continue;
                }
-               if (path)
+               if (this->paths)
                {
-                       if (snprintf(buf, sizeof(buf), "%s/libstrongswan-%s.so",
-                                                path, token) >= sizeof(buf))
-                       {
-                               return FALSE;
-                       }
-                       file = buf;
+                       this->paths->find_first(this->paths, (void*)find_plugin, NULL,
+                                                                       token, buf, &file);
+               }
+               if (!file)
+               {
+                       find_plugin(default_path, token, buf, &file);
                }
                entry = load_plugin(this, token, file, critical);
                if (entry)
@@ -1027,6 +1054,16 @@ METHOD(plugin_loader_t, unload, void,
        memset(&this->stats, 0, sizeof(this->stats));
 }
 
+METHOD(plugin_loader_t, add_path, void,
+       private_plugin_loader_t *this, char *path)
+{
+       if (!this->paths)
+       {
+               this->paths = linked_list_create();
+       }
+       this->paths->insert_last(this->paths, strdupnull(path));
+}
+
 /**
  * Reload a plugin by name, NULL for all
  */
@@ -1102,6 +1139,7 @@ METHOD(plugin_loader_t, destroy, void,
        this->features->destroy(this->features);
        this->loaded->destroy(this->loaded);
        this->plugins->destroy(this->plugins);
+       DESTROY_FUNCTION_IF(this->paths, free);
        free(this->loaded_plugins);
        free(this);
 }
@@ -1117,6 +1155,7 @@ plugin_loader_t *plugin_loader_create()
                .public = {
                        .add_static_features = _add_static_features,
                        .load = _load_plugins,
+                       .add_path = _add_path,
                        .reload = _reload,
                        .unload = _unload,
                        .create_plugin_enumerator = _create_plugin_enumerator,
index d4f74b9..15496f4 100644 (file)
@@ -63,6 +63,14 @@ struct plugin_loader_t {
         * as a critical plugin. If loading a critical plugin fails, plugin loading
         * is aborted and FALSE is returned.
         *
+        * Additional paths can be added with add_path(), these will be searched
+        * for the plugins first, in the order they were added, then the given path
+        * or the default follow.
+        *
+        * @note Even though this method could be called multiple times this is
+        * currently not really supported in regards to plugin features and their
+        * dependencies (in particular soft dependencies).
+        *
         * @param path                  path containing loadable plugins, NULL for default
         * @param list                  space separated list of plugins to load
         * @return                              TRUE if all critical plugins loaded successfully
@@ -70,6 +78,15 @@ struct plugin_loader_t {
        bool (*load)(plugin_loader_t *this, char *path, char *list);
 
        /**
+        * Add an additional search path for plugins.
+        *
+        * These will be searched in the order they were added.
+        *
+        * @param path                  path containing loadable plugins
+        */
+       void (*add_path)(plugin_loader_t *this, char *path);
+
+       /**
         * Reload the configuration of one or multiple plugins.
         *
         * @param                               space separated plugin names to reload, NULL for all