Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ 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.
*
* Kern Sibbald, October 2007
*/
+
#include "bacula.h"
+#include <dlfcn.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 2
+#endif
+
#include "plugins.h"
+static const int dbglvl = 50;
+
/* All loaded plugins */
-alist *plugin_list;
+alist *plugin_list = NULL;
/*
* Create a new plugin "class" entry and enter it in the
plugin = (Plugin *)malloc(sizeof(Plugin));
memset(plugin, 0, sizeof(Plugin));
- plugin_list->append(plugin);
return plugin;
}
bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, const char *type)
{
bool found = false;
-#ifndef HAVE_WIN32
t_loadPlugin loadPlugin;
- Plugin *plugin;
+ Plugin *plugin = NULL;
DIR* dp = NULL;
struct dirent *entry = NULL, *result;
int name_max;
if (!(dp = opendir(plugin_dir))) {
berrno be;
- Jmsg(NULL, M_ERROR, 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",
plugin_dir, be.bstrerror());
goto get_out;
}
for ( ;; ) {
if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
if (!found) {
- Jmsg(NULL, M_INFO, 0, _("Failed to find suitable plugin 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;
}
len = strlen(result->d_name);
type_len = strlen(type);
if (len < type_len+1 || strcmp(&result->d_name[len-type_len], type) != 0) {
+ Dmsg3(dbglvl, "Rejected plugin: want=%s name=%s len=%d\n", type, result->d_name, len);
continue;
}
- Dmsg2(000, "Loaded plugin: name=%s len=%d\n", result->d_name, len);
+ Dmsg2(dbglvl, "Loaded plugin: name=%s len=%d\n", result->d_name, len);
pm_strcpy(fname, plugin_dir);
if (need_slash) {
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(), dlerror());
+ fname.c_str(), NPRT(dlerror()));
+ Dmsg2(dbglvl, "Plugin load %s failed: ERR=%s\n", fname.c_str(),
+ NPRT(dlerror()));
goto get_out;
}
loadPlugin = (t_loadPlugin)dlsym(plugin->pHandle, "loadPlugin");
if (!loadPlugin) {
Jmsg(NULL, M_ERROR, 0, _("Lookup of loadPlugin in plugin %s failed: ERR=%s\n"),
- fname.c_str(), dlerror());
+ fname.c_str(), NPRT(dlerror()));
+ Dmsg2(dbglvl, "Lookup of loadPlugin in plugin %s failed: ERR=%s\n",
+ fname.c_str(), NPRT(dlerror()));
goto get_out;
}
plugin->unloadPlugin = (t_unloadPlugin)dlsym(plugin->pHandle, "unloadPlugin");
if (!plugin->unloadPlugin) {
Jmsg(NULL, M_ERROR, 0, _("Lookup of unloadPlugin in plugin %s failed: ERR=%s\n"),
- fname.c_str(), dlerror());
+ fname.c_str(), NPRT(dlerror()));
+ Dmsg2(dbglvl, "Lookup of unloadPlugin in plugin %s failed: ERR=%s\n",
+ fname.c_str(), NPRT(dlerror()));
goto get_out;
}
/* Initialize the plugin */
- loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs);
+ if (loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs) != bRC_OK) {
+ goto get_out;
+ }
found = true; /* found a plugin */
+ plugin_list->append(plugin);
}
get_out:
+ if (!found && plugin) {
+ free(plugin);
+ }
if (entry) {
free(entry);
}
if (dp) {
closedir(dp);
}
-#endif
return found;
}
*/
void unload_plugins()
{
-#ifndef HAVE_WIN32
Plugin *plugin;
+ if (!plugin_list) {
+ return;
+ }
foreach_alist(plugin, plugin_list) {
/* Shut it down and unload it */
plugin->unloadPlugin();
}
delete plugin_list;
plugin_list = NULL;
-#endif
+}
+
+/*
+ * Dump plugin information
+ * Each daemon can register a hook that will be called
+ * after a fatal signal.
+ */
+#define DBG_MAX_HOOK 10
+static dbg_plugin_hook_t *dbg_plugin_hooks[DBG_MAX_HOOK];
+static int dbg_plugin_hook_count=0;
+
+void dbg_plugin_add_hook(dbg_plugin_hook_t *fct)
+{
+ ASSERT(dbg_plugin_hook_count < DBG_MAX_HOOK);
+ dbg_plugin_hooks[dbg_plugin_hook_count++] = fct;
+}
+
+void _dbg_print_plugin(FILE *fp)
+{
+ Plugin *plugin;
+ fprintf(fp, "Attempt to dump plugins\n");
+
+ if (!plugin_list) {
+ return;
+ }
+
+ foreach_alist(plugin, 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",
+ plugin, plugin->file, plugin->disabled);
+ fct(plugin, fp);
+ }
+ }
}