]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/plugins.c
Update ACL/XATTR code and define new ACL/XATTR API for Plugins.
[bacula/bacula] / bacula / src / lib / plugins.c
index 7b7d324fe056324878f1428afcef9bc8c3693c1e..00559e86e9fd19b187a23a2a6835a3d375db75cf 100644 (file)
@@ -1,29 +1,20 @@
 /*
-   Bacula® - The Network Backup Solution
-
-   Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
-
-   The main author of Bacula is Kern Sibbald, with contributions from
-   many others, a complete list can be found in the file AUTHORS.
-   This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
-   License as published by the Free Software Foundation, which is 
-   listed in the file LICENSE.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-   Bacula® is a registered trademark of Kern Sibbald.
-   The licensor of Bacula is the Free Software Foundation Europe
-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
-   Switzerland, email:ftf@fsfeurope.org.
+   Bacula(R) - The Network Backup Solution
+
+   Copyright (C) 2000-2016 Kern Sibbald
+
+   The original author of Bacula is Kern Sibbald, with contributions
+   from many others, a complete list can be found in the file AUTHORS.
+
+   You may use this file and others of this release according to the
+   license defined in the LICENSE file, which includes the Affero General
+   Public License, v3.0 ("AGPLv3") and some additional permissions and
+   terms pursuant to its AGPLv3 Section 7.
+
+   This notice must be preserved when any source code is 
+   conveyed and/or propagated.
+
+   Bacula(R) is a registered trademark of Kern Sibbald.
 */
 /*
  *    Plugin load/unloader for all Bacula daemons
@@ -49,13 +40,18 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
 
 static const int dbglvl = 50;
 
-/* All loaded plugins */
-alist *plugin_list = NULL;
+/*
+ * List of all loaded plugins.
+ *
+ * NOTE!!! This is a global do not try walking it with
+ *   foreach_alist, you must use foreach_alist_index !!!!!!
+ */
+alist *b_plugin_list = NULL;
 
 /*
  * Create a new plugin "class" entry and enter it in the
  *  list of plugins.  Note, this is not the same as
- *  an instance of the plugin. 
+ *  an instance of the plugin.
  */
 Plugin *new_plugin()
 {
@@ -86,7 +82,7 @@ static void close_plugin(Plugin *plugin)
 /*
  * Load all the plugins in the specified directory.
  */
-bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, 
+bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
         const char *type, bool is_plugin_compatible(Plugin *plugin))
 {
    bool found = false;
@@ -101,6 +97,7 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
    int len, type_len;
 
 
+   Dmsg0(dbglvl, "load_plugins\n");
    name_max = pathconf(".", _PC_NAME_MAX);
    if (name_max < 1024) {
       name_max = 1024;
@@ -108,13 +105,13 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
 
    if (!(dp = opendir(plugin_dir))) {
       berrno be;
-      Jmsg(NULL, M_ERROR_TERM, 0, _("Failed to open Plugin directory %s: ERR=%s\n"), 
+      Jmsg(NULL, M_ERROR_TERM, 0, _("Failed to open Plugin directory %s: ERR=%s\n"),
             plugin_dir, be.bstrerror());
-      Dmsg2(dbglvl, "Failed to open Plugin directory %s: ERR=%s\n", 
+      Dmsg2(dbglvl, "Failed to open Plugin directory %s: ERR=%s\n",
             plugin_dir, be.bstrerror());
       goto get_out;
    }
-   
+
    len = strlen(plugin_dir);
    if (len > 0) {
       need_slash = !IsPathSeparator(plugin_dir[len - 1]);
@@ -125,13 +122,13 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
 
       if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
          if (!found) {
-            Jmsg(NULL, M_WARNING, 0, _("Failed to find any plugins in %s\n"), 
+            Jmsg(NULL, M_WARNING, 0, _("Failed to find any plugins in %s\n"),
                   plugin_dir);
             Dmsg1(dbglvl, "Failed to find any plugins in %s\n", plugin_dir);
          }
          break;
       }
-      if (strcmp(result->d_name, ".") == 0 || 
+      if (strcmp(result->d_name, ".") == 0 ||
           strcmp(result->d_name, "..") == 0) {
          continue;
       }
@@ -142,8 +139,8 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
          Dmsg3(dbglvl, "Rejected plugin: want=%s name=%s len=%d\n", type, result->d_name, len);
          continue;
       }
-      Dmsg2(dbglvl, "Loaded plugin: name=%s len=%d\n", result->d_name, len);
-       
+      Dmsg2(dbglvl, "Found plugin: name=%s len=%d\n", result->d_name, len);
+
       pm_strcpy(fname, plugin_dir);
       if (need_slash) {
          pm_strcat(fname, "/");
@@ -155,12 +152,14 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
 
       plugin = new_plugin();
       plugin->file = bstrdup(result->d_name);
+      plugin->file_len = strstr(plugin->file, type) - plugin->file;
       plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW);
       if (!plugin->pHandle) {
-         Jmsg(NULL, M_ERROR, 0, _("Plugin load %s failed: ERR=%s\n"), 
-              fname.c_str(), NPRT(dlerror()));
-         Dmsg2(dbglvl, "Plugin load %s failed: ERR=%s\n", fname.c_str(), 
-               NPRT(dlerror()));
+         const char *error = dlerror();
+         Jmsg(NULL, M_ERROR, 0, _("dlopen plugin %s failed: ERR=%s\n"),
+              fname.c_str(), NPRT(error));
+         Dmsg2(dbglvl, "dlopen plugin %s failed: ERR=%s\n", fname.c_str(),
+               NPRT(error));
          close_plugin(plugin);
          continue;
       }
@@ -170,7 +169,7 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
       if (!loadPlugin) {
          Jmsg(NULL, M_ERROR, 0, _("Lookup of loadPlugin in plugin %s failed: ERR=%s\n"),
             fname.c_str(), NPRT(dlerror()));
-         Dmsg2(dbglvl, "Lookup of loadPlugin in plugin %s failed: ERR=%s\n", 
+         Dmsg2(dbglvl, "Lookup of loadPlugin in plugin %s failed: ERR=%s\n",
             fname.c_str(), NPRT(dlerror()));
          close_plugin(plugin);
          continue;
@@ -191,14 +190,14 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
          continue;
       }
       if (!is_plugin_compatible) {
-         Dmsg0(50, "Plugin compatibility pointer not set.\n");   
+         Dmsg0(50, "Plugin compatibility pointer not set.\n");
       } else if (!is_plugin_compatible(plugin)) {
          close_plugin(plugin);
          continue;
       }
 
       found = true;                /* found a plugin */
-      plugin_list->append(plugin);
+      b_plugin_list->append(plugin);
    }
 
 get_out:
@@ -215,26 +214,33 @@ get_out:
 }
 
 /*
- * Unload all the loaded plugins 
+ * Unload all the loaded plugins
  */
 void unload_plugins()
 {
    Plugin *plugin;
 
-   if (!plugin_list) {
+   if (!b_plugin_list) {
       return;
    }
-   foreach_alist(plugin, plugin_list) {
+   foreach_alist(plugin, b_plugin_list) {
       /* Shut it down and unload it */
       plugin->unloadPlugin();
+      /* TODO:
+       * If you get a SIGSEGV when using plugins then it is very plausible that
+       * one of the plugins has a memory leakage which cannot be tracked by
+       * SMARTALLOC mechanism when you need to disable dlclose() below for
+       * further investigation.
+       * The problem was registered as #0002330 (http://bugs.bacula.org/view.php?id=2330)
+       */
       dlclose(plugin->pHandle);
       if (plugin->file) {
          free(plugin->file);
       }
       free(plugin);
    }
-   delete plugin_list;
-   plugin_list = NULL;
+   delete b_plugin_list;
+   b_plugin_list = NULL;
 }
 
 /*
@@ -255,12 +261,12 @@ void dbg_plugin_add_hook(dbg_plugin_hook_t *fct)
 void dbg_print_plugin(FILE *fp)
 {
    Plugin *plugin;
-   fprintf(fp, "Attempt to dump plugins. Hook count=%d\n", dbg_plugin_hook_count);
+   fprintf(fp, "List plugins. Hook count=%d\n", dbg_plugin_hook_count);
 
-   if (!plugin_list) {
+   if (!b_plugin_list) {
       return;
    }
-   foreach_alist(plugin, plugin_list) {
+   foreach_alist(plugin, b_plugin_list) {
       for(int i=0; i < dbg_plugin_hook_count; i++) {
 //       dbg_plugin_hook_t *fct = dbg_plugin_hooks[i];
          fprintf(fp, "Plugin %p name=\"%s\" disabled=%d\n",