From: Kern Sibbald Date: Mon, 26 Nov 2007 17:01:24 +0000 (+0000) Subject: Zeroth integration of plugins X-Git-Tag: Release-3.0.0~2199 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=c9a58a80f821adb2b347deec126d0d4f0e3180a4;p=bacula%2Fbacula Zeroth integration of plugins git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5990 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index c32085f460..6da35951cf 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -25,7 +25,7 @@ LIBSRCS = attr.c base64.c berrno.c bsys.c bget_msg.c \ cram-md5.c crc32.c crypto.c daemon.c edit.c fnmatch.c \ guid_to_name.c hmac.c jcr.c lex.c alist.c dlist.c \ md5.c message.c mem_pool.c openssl.c parse_conf.c \ - queue.c bregex.c \ + plugin.c queue.c bregex.c \ res.c rwlock.c scan.c serial.c sha1.c \ signal.c smartall.c rblist.c tls.c tree.c \ util.c var.c watchdog.c workq.c btimers.c \ @@ -38,7 +38,7 @@ LIBOBJS = attr.o base64.o berrno.o bsys.o bget_msg.o \ cram-md5.o crc32.o crypto.o daemon.o edit.o fnmatch.o \ guid_to_name.o hmac.o jcr.o lex.o alist.o dlist.o \ md5.o message.o mem_pool.o openssl.o parse_conf.o \ - queue.o bregex.o \ + plugin.o queue.o bregex.o \ res.o rwlock.o scan.o serial.o sha1.o \ signal.o smartall.o rblist.o tls.o tree.o \ util.o var.o watchdog.o workq.o btimers.o \ @@ -108,7 +108,10 @@ bsnprintf: bsnprintf.o $(CXX) $(LDFLAGS) -L. -o $@ bsnprintf.o $(LIBS) $(DLIB) -lbac $(OPENSSL_LIBS) -lm rm -f bsnprintf.o $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) bsnprintf.c - + +plugin.o: plugin.c + $(NO_ECHO)$(CXX) -fPIC $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< + install: diff --git a/bacula/src/lib/plugin.c b/bacula/src/lib/plugin.c new file mode 100644 index 0000000000..18704a6678 --- /dev/null +++ b/bacula/src/lib/plugin.c @@ -0,0 +1,170 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2007 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 John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Plugin load/unloader for all Bacula daemons + * + * Kern Sibbald, October 2007 + */ +#include "bacula.h" +#include +#include "plugin.h" + +/* All loaded plugins */ +alist *plugin_list; + +/* + * 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. + */ +Plugin *new_plugin() +{ + Plugin *plugin; + + plugin = (Plugin *)malloc(sizeof(Plugin)); + memset(plugin, 0, sizeof(Plugin)); + plugin_list->append(plugin); + return plugin; +} + + +/* + * Load all the plugins in the specified directory. + */ +bool load_plugins(void *bfuncs, const char *plugin_dir, const char *type) +{ + t_loadPlugin loadPlugin; + Plugin *plugin; + char *error; + DIR* dp = NULL; + struct dirent *entry, *result; + int name_max; + struct stat statp; + bool found = false; + POOL_MEM fname(PM_FNAME); + bool need_slash = false; + int len, type_len; + + plugin = new_plugin(); + + name_max = pathconf(".", _PC_NAME_MAX); + if (name_max < 1024) { + name_max = 1024; + } + + if (!(dp = opendir(plugin_dir))) { + berrno be; + Dmsg2(29, "load_plugins: failed to open dir %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]); + } + entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); + for ( ;; ) { + if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { + Dmsg1(129, "load_plugins: failed to find suitable file in dir %s\n", + plugin_dir); + break; + } + if (strcmp(result->d_name, ".") == 0 || + strcmp(result->d_name, "..") == 0) { + continue; + } + + len = strlen(result->d_name); + type_len = strlen(type); + if (len < type_len+1 || strcmp(&result->d_name[len-type_len], type) != 0) { + continue; + } + printf("Got: name=%s len=%d\n", result->d_name, len); + + pm_strcpy(fname, plugin_dir); + if (need_slash) { + pm_strcat(fname, "/"); + } + pm_strcat(fname, result->d_name); + if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) { + continue; /* ignore directories & special files */ + } + + plugin->file = bstrdup(result->d_name); + plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW); + if (!plugin->pHandle) { + printf("dlopen of %s failed: ERR=%s\n", fname.c_str(), dlerror()); + goto get_out; + } + + /* Get two global entry points */ + loadPlugin = (t_loadPlugin)dlsym(plugin->pHandle, "loadPlugin"); + if ((error=dlerror()) != NULL) { + printf("dlsym failed: ERR=%s\n", error); + goto get_out; + } + plugin->unloadPlugin = (t_unloadPlugin)dlsym(plugin->pHandle, "unloadPlugin"); + if ((error=dlerror()) != NULL) { + printf("dlsym failed: ERR=%s\n", error); + goto get_out; + } + + /* Initialize the plugin */ + loadPlugin(bfuncs, &plugin->pfuncs); + + found = true; /* found a plugin */ + } + +get_out: + free(entry); + if (dp) { + closedir(dp); + } + return found; +} + +/* + * Unload all the loaded plugins + */ +void unload_plugins() +{ + Plugin *plugin; + + foreach_alist(plugin, plugin_list) { + /* Shut it down and unload it */ + plugin->unloadPlugin(); + dlclose(plugin->pHandle); + if (plugin->file) { + free(plugin->file); + } + free(plugin); + } + delete plugin_list; + plugin_list = NULL; +} diff --git a/bacula/src/lib/plugin.h b/bacula/src/lib/plugin.h new file mode 100644 index 0000000000..0ff939955a --- /dev/null +++ b/bacula/src/lib/plugin.h @@ -0,0 +1,87 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2007 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 John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Bacula plugin loader/unloader + * + * Kern Sibbald, October 2007 + */ +#ifndef __PLUGIN_H +#define __PLUGIN_H + +#include "bacula.h" +#include +#ifdef HAVE_DIRENT_H +#include +#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 + +/**************************************************************************** + * * + * Common definitions for all plugins * + * * + ****************************************************************************/ + +extern alist *plugin_list; + + +/* Universal return code from all functions */ +typedef int32_t bpError; + +/* Context packet as first argument of all functions */ +typedef struct s_bpContext { + void *bContext; /* Bacula private context */ + void *pContext; /* Plugin private context */ +} bpContext; + +extern "C" { +typedef bpError (*t_loadPlugin)(void *bfuncs, void **pfuncs); +typedef bpError (*t_unloadPlugin)(void); +} + +class Plugin { +public: + char *file; + t_unloadPlugin unloadPlugin; + void *pfuncs; + void *pHandle; +}; + +/* Functions */ +extern Plugin *new_plugin(); +extern bool load_plugins(void *bfuncs, const char *plugin_dir, const char *type); +extern void unload_plugins(); + + +#endif /* __PLUGIN_H */ diff --git a/bacula/src/plugins/dir/Makefile b/bacula/src/plugins/dir/Makefile index 4988aede02..f5c430e655 100644 --- a/bacula/src/plugins/dir/Makefile +++ b/bacula/src/plugins/dir/Makefile @@ -11,14 +11,15 @@ CC = g++ -g -O0 -Wall all: main plugin-dir.so -main: main.o plugin-dir.h +main: main.o plugin-dir.h $(CC) -L../../lib main.o -o main -lbac -lpthread -lssl -l crypto -ldl plugin-dir.o: plugin-dir.c plugin-dir.h $(CC) -fPIC -I../.. -c plugin-dir.c -plugin-dir.so: plugin-dir.o +plugin-dir.so: plugin-dir.o $(CC) -shared plugin-dir.o -o plugin-dir.so + clean: - rm -f main *.so *.o + rm -f main *.so *.o 1 2 3 diff --git a/bacula/src/plugins/dir/main.c b/bacula/src/plugins/dir/main.c index a9b3ec3cd7..387df26128 100644 --- a/bacula/src/plugins/dir/main.c +++ b/bacula/src/plugins/dir/main.c @@ -33,37 +33,30 @@ */ #include "bacula.h" #include +#include "lib/plugin.h" #include "plugin-dir.h" -#ifdef HAVE_DIRENT_H -#include -#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 +const char *plugin_type = "-dir.so"; -class Plugin { -public: - char *file; - t_bpShutdown p_bpShutdown; - pFuncs pfuncs; - void *pHandle; -}; - -/* All loaded plugins */ -alist *plugin_list; /* Forward referenced functions */ -static Plugin *new_plugin(); -bool load_plugins(const char *plugin_dir); -void unload_plugins(); static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value); static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value); + +/* Bacula entry points */ +static bFuncs bfuncs = { + sizeof(bFuncs), + PLUGIN_INTERFACE, + baculaGetValue, + baculaSetValue, + NULL, + NULL +}; + + + + int main(int argc, char *argv[]) { char plugin_dir[1000]; @@ -76,174 +69,43 @@ int main(int argc, char *argv[]) ctx.bContext = NULL; ctx.pContext = NULL; getcwd(plugin_dir, sizeof(plugin_dir)-1); - load_plugins(plugin_dir); + + load_plugins((void *)&bfuncs, plugin_dir, plugin_type); foreach_alist(plugin, plugin_list) { + printf("bacula: plugin_size=%d plugin_version=%d\n", + pref(plugin)->size, pref(plugin)->interface); + printf("License: %s\nAuthor: %s\nDate: %s\nVersion: %s\nDescription: %s\n", + pref(plugin)->plugin_license, pref(plugin)->plugin_author, + pref(plugin)->plugin_date, pref(plugin)->plugin_version, + pref(plugin)->plugin_description); + /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); } unload_plugins(); printf("bacula: OK ...\n"); + close_memory_pool(); sm_dump(false); return 0; } -/* - * 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. - */ -static Plugin *new_plugin() -{ - Plugin *plugin; - - plugin = (Plugin *)malloc(sizeof(Plugin)); - memset(plugin, 0, sizeof(Plugin)); - plugin_list->append(plugin); - return plugin; -} - - -/* - * Load all the plugins in the specified directory. - */ -bool load_plugins(const char *plugin_dir) -{ - t_bpInitialize p_bpInitialize; - bFuncs bfuncs; - Plugin *plugin; - char *error; - DIR* dp = NULL; - struct dirent *entry, *result; - int name_max; - struct stat statp; - bool found = false; - POOL_MEM fname(PM_FNAME); - bool need_slash = false; - int len; - - /* Setup pointers to Bacula functions */ - bfuncs.size = sizeof(bFuncs); - bfuncs.version = 1; - bfuncs.bGetValue = baculaGetValue; - bfuncs.bSetValue = baculaSetValue; - - plugin = new_plugin(); - - name_max = pathconf(".", _PC_NAME_MAX); - if (name_max < 1024) { - name_max = 1024; - } - - if (!(dp = opendir(plugin_dir))) { - berrno be; - Dmsg2(29, "load_plugins: failed to open dir %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]); - } - entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); - for ( ;; ) { - if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { - Dmsg1(129, "load_plugins: failed to find suitable file in dir %s\n", - plugin_dir); - break; - } - if (strcmp(result->d_name, ".") == 0 || - strcmp(result->d_name, "..") == 0) { - continue; - } - - len = strlen(result->d_name); - if (len < 8 || strcmp(&result->d_name[len-7], "-dir.so") != 0) { - continue; - } - printf("Got: name=%s len=%d\n", result->d_name, len); - - pm_strcpy(fname, plugin_dir); - if (need_slash) { - pm_strcat(fname, "/"); - } - pm_strcat(fname, result->d_name); - if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) { - continue; /* ignore directories & special files */ - } - - plugin->file = bstrdup(result->d_name); - plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW); - if (!plugin->pHandle) { - printf("dlopen of %s failed: ERR=%s\n", fname.c_str(), dlerror()); - goto get_out; - } - - /* Get two global entry points */ - p_bpInitialize = (t_bpInitialize)dlsym(plugin->pHandle, "bpInitialize"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - plugin->p_bpShutdown = (t_bpShutdown)dlsym(plugin->pHandle, "bpShutdown"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - - /* Initialize the plugin */ - p_bpInitialize(&bfuncs, &plugin->pfuncs); - printf("bacula: plugin_size=%d plugin_version=%d\n", - plugin->pfuncs.size, plugin->pfuncs.version); - - found = true; /* found a plugin */ - } - -get_out: - free(entry); - if (dp) { - closedir(dp); - } - return found; -} - -/* - * Unload all the loaded plugins - */ -void unload_plugins() -{ - Plugin *plugin; - - foreach_alist(plugin, plugin_list) { - /* Shut it down and unload it */ - plugin->p_bpShutdown(); - dlclose(plugin->pHandle); - if (plugin->file) { - free(plugin->file); - } - free(plugin); - } - delete plugin_list; - plugin_list = NULL; -} - static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) { - printf("bacula: GetValue var=%d\n", var); + printf("bacula: baculaGetValue var=%d\n", var); if (value) { *((int *)value) = 100; } @@ -252,6 +114,6 @@ static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) { - printf("baculaSetValue var=%d\n", var); + printf("bacula: baculaSetValue var=%d\n", var); return 0; } diff --git a/bacula/src/plugins/dir/plugin-dir.c b/bacula/src/plugins/dir/plugin-dir.c index 4e032d7e14..8d5e8e93b0 100644 --- a/bacula/src/plugins/dir/plugin-dir.c +++ b/bacula/src/plugins/dir/plugin-dir.c @@ -38,80 +38,86 @@ extern "C" { #endif +#define PLUGIN_LICENSE "GPL" +#define PLUGIN_AUTHOR "Kern Sibbald" +#define PLUGIN_DATE "November 2007" +#define PLUGIN_VERSION "1" +#define PLUGIN_DESCRIPTION "Test Director Plugin" + /* Forward referenced functions */ -bpError pNew(bpContext *ctx); -bpError pDestroy(bpContext *ctx); -bpError pGetValue(bpContext *ctx, pVariable var, void *value); -bpError pSetValue(bpContext *ctx, pVariable var, void *value); -bpError pHandleEvent(bpContext *ctx, bEvent *event); +static bpError newPlugin(bpContext *ctx); +static bpError freePlugin(bpContext *ctx); +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError handlePluginEvent(bpContext *ctx, bEvent *event); /* Pointers to Bacula functions */ -bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value); -bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value); +static bFuncs *bfuncs = NULL; -pFuncs pluginFuncs = { +static pFuncs pluginFuncs = { sizeof(pluginFuncs), - 1, - pNew, - pDestroy, - pGetValue, - pSetValue, - pHandleEvent + PLUGIN_INTERFACE, + PLUGIN_MAGIC, + PLUGIN_LICENSE, + PLUGIN_AUTHOR, + PLUGIN_DATE, + PLUGIN_VERSION, + PLUGIN_DESCRIPTION, + + /* Entry points into plugin */ + newPlugin, /* new plugin instance */ + freePlugin, /* free plugin instance */ + getPluginValue, + setPluginValue, + handlePluginEvent }; -bpError bpInitialize(bFuncs *bfuncs, pFuncs *pfuncs) +bpError loadPlugin(bFuncs *lbfuncs, pFuncs **pfuncs) { - printf("plugin: Initializing. size=%d version=%d\n", bfuncs->size, bfuncs->version); - p_bGetValue = bfuncs->bGetValue; - p_bSetValue = bfuncs->bSetValue; - - pfuncs->pNew = pNew; - pfuncs->pDestroy = pDestroy; - pfuncs->pGetValue = pGetValue; - pfuncs->pSetValue = pSetValue; - pfuncs->pHandleEvent = pHandleEvent; - pfuncs->size = sizeof(pFuncs); - pfuncs->version = 1; + bfuncs = lbfuncs; /* set Bacula funct pointers */ + printf("plugin: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->interface); + + *pfuncs = &pluginFuncs; /* return pointer to our functions */ return 0; } -bpError bpShutdown() +bpError unloadPlugin() { - printf("plugin: Shutting down\n"); + printf("plugin: Unloaded\n"); return 0; } -bpError pNew(bpContext *ctx) +static bpError newPlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: New JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: newPlugin JobId=%d\n", JobId); return 0; } -bpError pDestroy(bpContext *ctx) +static bpError freePlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: Destroy JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: freePlugin JobId=%d\n", JobId); return 0; } -bpError pGetValue(bpContext *ctx, pVariable var, void *value) +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: GetValue var=%d\n", var); + printf("plugin: getPluginValue var=%d\n", var); return 0; } -bpError pSetValue(bpContext *ctx, pVariable var, void *value) +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: PutValue var=%d\n", var); + printf("plugin: setPluginValue var=%d\n", var); return 0; } -bpError pHandleEvent(bpContext *ctx, bEvent *event) +static bpError handlePluginEvent(bpContext *ctx, bEvent *event) { printf("plugin: HandleEvent Event=%d\n", event->eventType); return 0; diff --git a/bacula/src/plugins/dir/plugin-dir.h b/bacula/src/plugins/dir/plugin-dir.h index 9fd2d530cc..cc78a42cb6 100644 --- a/bacula/src/plugins/dir/plugin-dir.h +++ b/bacula/src/plugins/dir/plugin-dir.h @@ -32,8 +32,8 @@ * */ -#ifndef __PLUGIN_H -#define __PLUGIN_H +#ifndef __PLUGIN_FD_H +#define __PLUGIN_FD_H #include #ifndef __CONFIG_H @@ -41,28 +41,13 @@ #include "config.h" #endif #include "bc_types.h" +#include "lib/plugin.h" #ifdef __cplusplus extern "C" { #endif -/**************************************************************************** - * * - * Common definitions * - * * - ****************************************************************************/ - -/* Universal return code from all functions */ -typedef int32_t bpError; - -/* Context packet as first argument of all functions */ -typedef struct s_bpContext { - void *bContext; /* Bacula private context */ - void *pContext; /* Plugin private context */ -} bpContext; - - /**************************************************************************** * * * Bacula definitions * @@ -92,13 +77,11 @@ typedef struct s_bEvent { /* Bacula interface version and function pointers */ typedef struct s_baculaFuncs { uint32_t size; - uint32_t version; - bpError (*bGetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bSetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bMemAlloc)(bpContext *ctx, uint32_t size, char *addr); - bpError (*bMemFree)(bpContext *ctx, char *addr); - bpError (*bMemFlush)(bpContext *ctx); - bpError (*bVersion)(bVariable var, void *value); + uint32_t interface; + bpError (*getBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*setBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*allocBaculaMem)(bpContext *ctx, uint32_t size, char *addr); + bpError (*freeBaculaMem)(bpContext *ctx, char *addr); } bFuncs; @@ -114,22 +97,29 @@ typedef enum { } pVariable; +#define PLUGIN_MAGIC "*PluginData*" +#define PLUGIN_INTERFACE 1 + typedef struct s_pluginFuncs { uint32_t size; - uint32_t version; - bpError (*pNew)(bpContext *ctx); - bpError (*pDestroy)(bpContext *ctx); - bpError (*pGetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pSetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pHandleEvent)(bpContext *ctx, bEvent *event); + uint32_t interface; + char *plugin_magic; + char *plugin_license; + char *plugin_author; + char *plugin_date; + char *plugin_version; + char *plugin_description; + bpError (*newPlugin)(bpContext *ctx); + bpError (*freePlugin)(bpContext *ctx); + bpError (*getPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*setPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*handlePluginEvent)(bpContext *ctx, bEvent *event); } pFuncs; -typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs); -typedef bpError (*t_bpShutdown)(void); - +#define pref(plugin) ((pFuncs *)(plugin->pfuncs)) #ifdef __cplusplus } #endif -#endif /* __PLUGIN_H */ +#endif /* __PLUGIN_FD_H */ diff --git a/bacula/src/plugins/fd/Makefile b/bacula/src/plugins/fd/Makefile index fee6491cf1..96776447bf 100644 --- a/bacula/src/plugins/fd/Makefile +++ b/bacula/src/plugins/fd/Makefile @@ -11,14 +11,19 @@ CC = g++ -g -O0 -Wall all: main plugin-fd.so -main: main.o plugin-fd.h +main: main.o plugin-fd.h $(CC) -L../../lib main.o -o main -lbac -lpthread -lssl -l crypto -ldl plugin-fd.o: plugin-fd.c plugin-fd.h $(CC) -fPIC -I../.. -c plugin-fd.c -plugin-fd.so: plugin-fd.o +plugin.o: plugin.c plugin.h + $(CC) -fPIC -I../.. -c plugin.c + + +plugin-fd.so: plugin-fd.o $(CC) -shared plugin-fd.o -o plugin-fd.so + clean: - rm -f main *.so *.o + rm -f main *.so *.o 1 2 3 diff --git a/bacula/src/plugins/fd/main.c b/bacula/src/plugins/fd/main.c index e15f8de2fd..eae0a818df 100644 --- a/bacula/src/plugins/fd/main.c +++ b/bacula/src/plugins/fd/main.c @@ -33,37 +33,30 @@ */ #include "bacula.h" #include +#include "lib/plugin.h" #include "plugin-fd.h" -#ifdef HAVE_DIRENT_H -#include -#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 +const char *plugin_type = "-fd.so"; -class Plugin { -public: - char *file; - t_bpShutdown p_bpShutdown; - pFuncs pfuncs; - void *pHandle; -}; - -/* All loaded plugins */ -alist *plugin_list; /* Forward referenced functions */ -static Plugin *new_plugin(); -bool load_plugins(const char *plugin_dir); -void unload_plugins(); static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value); static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value); + +/* Bacula entry points */ +static bFuncs bfuncs = { + sizeof(bFuncs), + PLUGIN_INTERFACE, + baculaGetValue, + baculaSetValue, + NULL, + NULL +}; + + + + int main(int argc, char *argv[]) { char plugin_dir[1000]; @@ -76,174 +69,43 @@ int main(int argc, char *argv[]) ctx.bContext = NULL; ctx.pContext = NULL; getcwd(plugin_dir, sizeof(plugin_dir)-1); - load_plugins(plugin_dir); + + load_plugins((void *)&bfuncs, plugin_dir, plugin_type); foreach_alist(plugin, plugin_list) { + printf("bacula: plugin_size=%d plugin_version=%d\n", + pref(plugin)->size, pref(plugin)->interface); + printf("License: %s\nAuthor: %s\nDate: %s\nVersion: %s\nDescription: %s\n", + pref(plugin)->plugin_license, pref(plugin)->plugin_author, + pref(plugin)->plugin_date, pref(plugin)->plugin_version, + pref(plugin)->plugin_description); + /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); } unload_plugins(); printf("bacula: OK ...\n"); + close_memory_pool(); sm_dump(false); return 0; } -/* - * 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. - */ -static Plugin *new_plugin() -{ - Plugin *plugin; - - plugin = (Plugin *)malloc(sizeof(Plugin)); - memset(plugin, 0, sizeof(Plugin)); - plugin_list->append(plugin); - return plugin; -} - - -/* - * Load all the plugins in the specified directory. - */ -bool load_plugins(const char *plugin_dir) -{ - t_bpInitialize p_bpInitialize; - bFuncs bfuncs; - Plugin *plugin; - char *error; - DIR* dp = NULL; - struct dirent *entry, *result; - int name_max; - struct stat statp; - bool found = false; - POOL_MEM fname(PM_FNAME); - bool need_slash = false; - int len; - - /* Setup pointers to Bacula functions */ - bfuncs.size = sizeof(bFuncs); - bfuncs.version = 1; - bfuncs.bGetValue = baculaGetValue; - bfuncs.bSetValue = baculaSetValue; - - plugin = new_plugin(); - - name_max = pathconf(".", _PC_NAME_MAX); - if (name_max < 1024) { - name_max = 1024; - } - - if (!(dp = opendir(plugin_dir))) { - berrno be; - Dmsg2(29, "load_plugins: failed to open dir %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]); - } - entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); - for ( ;; ) { - if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { - Dmsg1(129, "load_plugins: failed to find suitable file in dir %s\n", - plugin_dir); - break; - } - if (strcmp(result->d_name, ".") == 0 || - strcmp(result->d_name, "..") == 0) { - continue; - } - - len = strlen(result->d_name); - if (len < 7 || strcmp(&result->d_name[len-6], "-fd.so") != 0) { - continue; - } - printf("Got: name=%s len=%d\n", result->d_name, len); - - pm_strcpy(fname, plugin_dir); - if (need_slash) { - pm_strcat(fname, "/"); - } - pm_strcat(fname, result->d_name); - if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) { - continue; /* ignore directories & special files */ - } - - plugin->file = bstrdup(result->d_name); - plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW); - if (!plugin->pHandle) { - printf("dlopen of %s failed: ERR=%s\n", fname.c_str(), dlerror()); - goto get_out; - } - - /* Get two global entry points */ - p_bpInitialize = (t_bpInitialize)dlsym(plugin->pHandle, "bpInitialize"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - plugin->p_bpShutdown = (t_bpShutdown)dlsym(plugin->pHandle, "bpShutdown"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - - /* Initialize the plugin */ - p_bpInitialize(&bfuncs, &plugin->pfuncs); - printf("bacula: plugin_size=%d plugin_version=%d\n", - plugin->pfuncs.size, plugin->pfuncs.version); - - found = true; /* found a plugin */ - } - -get_out: - free(entry); - if (dp) { - closedir(dp); - } - return found; -} - -/* - * Unload all the loaded plugins - */ -void unload_plugins() -{ - Plugin *plugin; - - foreach_alist(plugin, plugin_list) { - /* Shut it down and unload it */ - plugin->p_bpShutdown(); - dlclose(plugin->pHandle); - if (plugin->file) { - free(plugin->file); - } - free(plugin); - } - delete plugin_list; - plugin_list = NULL; -} - static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) { - printf("bacula: GetValue var=%d\n", var); + printf("bacula: baculaGetValue var=%d\n", var); if (value) { *((int *)value) = 100; } @@ -252,6 +114,6 @@ static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) { - printf("baculaSetValue var=%d\n", var); + printf("bacula: baculaSetValue var=%d\n", var); return 0; } diff --git a/bacula/src/plugins/fd/plugin-fd.c b/bacula/src/plugins/fd/plugin-fd.c index fb66ec921b..3181d94a8d 100644 --- a/bacula/src/plugins/fd/plugin-fd.c +++ b/bacula/src/plugins/fd/plugin-fd.c @@ -38,80 +38,86 @@ extern "C" { #endif +#define PLUGIN_LICENSE "GPL" +#define PLUGIN_AUTHOR "Kern Sibbald" +#define PLUGIN_DATE "November 2007" +#define PLUGIN_VERSION "1" +#define PLUGIN_DESCRIPTION "Test File Daemon Plugin" + /* Forward referenced functions */ -bpError pNew(bpContext *ctx); -bpError pDestroy(bpContext *ctx); -bpError pGetValue(bpContext *ctx, pVariable var, void *value); -bpError pSetValue(bpContext *ctx, pVariable var, void *value); -bpError pHandleEvent(bpContext *ctx, bEvent *event); +static bpError newPlugin(bpContext *ctx); +static bpError freePlugin(bpContext *ctx); +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError handlePluginEvent(bpContext *ctx, bEvent *event); /* Pointers to Bacula functions */ -bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value); -bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value); +static bFuncs *bfuncs = NULL; -pFuncs pluginFuncs = { +static pFuncs pluginFuncs = { sizeof(pluginFuncs), - 1, - pNew, - pDestroy, - pGetValue, - pSetValue, - pHandleEvent + PLUGIN_INTERFACE, + PLUGIN_MAGIC, + PLUGIN_LICENSE, + PLUGIN_AUTHOR, + PLUGIN_DATE, + PLUGIN_VERSION, + PLUGIN_DESCRIPTION, + + /* Entry points into plugin */ + newPlugin, /* new plugin instance */ + freePlugin, /* free plugin instance */ + getPluginValue, + setPluginValue, + handlePluginEvent }; -bpError bpInitialize(bFuncs *bfuncs, pFuncs *pfuncs) +bpError loadPlugin(bFuncs *lbfuncs, pFuncs **pfuncs) { - printf("plugin: Initializing. size=%d version=%d\n", bfuncs->size, bfuncs->version); - p_bGetValue = bfuncs->bGetValue; - p_bSetValue = bfuncs->bSetValue; - - pfuncs->pNew = pNew; - pfuncs->pDestroy = pDestroy; - pfuncs->pGetValue = pGetValue; - pfuncs->pSetValue = pSetValue; - pfuncs->pHandleEvent = pHandleEvent; - pfuncs->size = sizeof(pFuncs); - pfuncs->version = 1; + bfuncs = lbfuncs; /* set Bacula funct pointers */ + printf("plugin: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->interface); + + *pfuncs = &pluginFuncs; /* return pointer to our functions */ return 0; } -bpError bpShutdown() +bpError unloadPlugin() { - printf("plugin: Shutting down\n"); + printf("plugin: Unloaded\n"); return 0; } -bpError pNew(bpContext *ctx) +static bpError newPlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: New JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: newPlugin JobId=%d\n", JobId); return 0; } -bpError pDestroy(bpContext *ctx) +static bpError freePlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: Destroy JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: freePlugin JobId=%d\n", JobId); return 0; } -bpError pGetValue(bpContext *ctx, pVariable var, void *value) +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: GetValue var=%d\n", var); + printf("plugin: getPluginValue var=%d\n", var); return 0; } -bpError pSetValue(bpContext *ctx, pVariable var, void *value) +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: PutValue var=%d\n", var); + printf("plugin: setPluginValue var=%d\n", var); return 0; } -bpError pHandleEvent(bpContext *ctx, bEvent *event) +static bpError handlePluginEvent(bpContext *ctx, bEvent *event) { printf("plugin: HandleEvent Event=%d\n", event->eventType); return 0; diff --git a/bacula/src/plugins/fd/plugin-fd.h b/bacula/src/plugins/fd/plugin-fd.h index 9fd2d530cc..cc78a42cb6 100644 --- a/bacula/src/plugins/fd/plugin-fd.h +++ b/bacula/src/plugins/fd/plugin-fd.h @@ -32,8 +32,8 @@ * */ -#ifndef __PLUGIN_H -#define __PLUGIN_H +#ifndef __PLUGIN_FD_H +#define __PLUGIN_FD_H #include #ifndef __CONFIG_H @@ -41,28 +41,13 @@ #include "config.h" #endif #include "bc_types.h" +#include "lib/plugin.h" #ifdef __cplusplus extern "C" { #endif -/**************************************************************************** - * * - * Common definitions * - * * - ****************************************************************************/ - -/* Universal return code from all functions */ -typedef int32_t bpError; - -/* Context packet as first argument of all functions */ -typedef struct s_bpContext { - void *bContext; /* Bacula private context */ - void *pContext; /* Plugin private context */ -} bpContext; - - /**************************************************************************** * * * Bacula definitions * @@ -92,13 +77,11 @@ typedef struct s_bEvent { /* Bacula interface version and function pointers */ typedef struct s_baculaFuncs { uint32_t size; - uint32_t version; - bpError (*bGetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bSetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bMemAlloc)(bpContext *ctx, uint32_t size, char *addr); - bpError (*bMemFree)(bpContext *ctx, char *addr); - bpError (*bMemFlush)(bpContext *ctx); - bpError (*bVersion)(bVariable var, void *value); + uint32_t interface; + bpError (*getBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*setBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*allocBaculaMem)(bpContext *ctx, uint32_t size, char *addr); + bpError (*freeBaculaMem)(bpContext *ctx, char *addr); } bFuncs; @@ -114,22 +97,29 @@ typedef enum { } pVariable; +#define PLUGIN_MAGIC "*PluginData*" +#define PLUGIN_INTERFACE 1 + typedef struct s_pluginFuncs { uint32_t size; - uint32_t version; - bpError (*pNew)(bpContext *ctx); - bpError (*pDestroy)(bpContext *ctx); - bpError (*pGetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pSetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pHandleEvent)(bpContext *ctx, bEvent *event); + uint32_t interface; + char *plugin_magic; + char *plugin_license; + char *plugin_author; + char *plugin_date; + char *plugin_version; + char *plugin_description; + bpError (*newPlugin)(bpContext *ctx); + bpError (*freePlugin)(bpContext *ctx); + bpError (*getPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*setPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*handlePluginEvent)(bpContext *ctx, bEvent *event); } pFuncs; -typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs); -typedef bpError (*t_bpShutdown)(void); - +#define pref(plugin) ((pFuncs *)(plugin->pfuncs)) #ifdef __cplusplus } #endif -#endif /* __PLUGIN_H */ +#endif /* __PLUGIN_FD_H */ diff --git a/bacula/src/plugins/sd/Makefile b/bacula/src/plugins/sd/Makefile index dfb9346a8f..fc79538f3a 100644 --- a/bacula/src/plugins/sd/Makefile +++ b/bacula/src/plugins/sd/Makefile @@ -11,14 +11,15 @@ CC = g++ -g -O0 -Wall all: main plugin-sd.so -main: main.o plugin-sd.h +main: main.o plugin-sd.h $(CC) -L../../lib main.o -o main -lbac -lpthread -lssl -l crypto -ldl plugin-sd.o: plugin-sd.c plugin-sd.h $(CC) -fPIC -I../.. -c plugin-sd.c -plugin-sd.so: plugin-sd.o +plugin-sd.so: plugin-sd.o $(CC) -shared plugin-sd.o -o plugin-sd.so + clean: - rm -f main *.so *.o + rm -f main *.so *.o 1 2 3 diff --git a/bacula/src/plugins/sd/main.c b/bacula/src/plugins/sd/main.c index 7c66137134..a381c7ae24 100644 --- a/bacula/src/plugins/sd/main.c +++ b/bacula/src/plugins/sd/main.c @@ -33,37 +33,30 @@ */ #include "bacula.h" #include +#include "lib/plugin.h" #include "plugin-sd.h" -#ifdef HAVE_DIRENT_H -#include -#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 +const char *plugin_type = "-sd.so"; -class Plugin { -public: - char *file; - t_bpShutdown p_bpShutdown; - pFuncs pfuncs; - void *pHandle; -}; - -/* All loaded plugins */ -alist *plugin_list; /* Forward referenced functions */ -static Plugin *new_plugin(); -bool load_plugins(const char *plugin_dir); -void unload_plugins(); static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value); static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value); + +/* Bacula entry points */ +static bFuncs bfuncs = { + sizeof(bFuncs), + PLUGIN_INTERFACE, + baculaGetValue, + baculaSetValue, + NULL, + NULL +}; + + + + int main(int argc, char *argv[]) { char plugin_dir[1000]; @@ -76,174 +69,43 @@ int main(int argc, char *argv[]) ctx.bContext = NULL; ctx.pContext = NULL; getcwd(plugin_dir, sizeof(plugin_dir)-1); - load_plugins(plugin_dir); + + load_plugins((void *)&bfuncs, plugin_dir, plugin_type); foreach_alist(plugin, plugin_list) { + printf("bacula: plugin_size=%d plugin_version=%d\n", + pref(plugin)->size, pref(plugin)->interface); + printf("License: %s\nAuthor: %s\nDate: %s\nVersion: %s\nDescription: %s\n", + pref(plugin)->plugin_license, pref(plugin)->plugin_author, + pref(plugin)->plugin_date, pref(plugin)->plugin_version, + pref(plugin)->plugin_description); + /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); /* Start a new instance of the plugin */ - plugin->pfuncs.pNew(&ctx); + pref(plugin)->newPlugin(&ctx); event.eventType = bEventNewVolume; - plugin->pfuncs.pHandleEvent(&ctx, &event); - /* Destroy the instance */ - plugin->pfuncs.pDestroy(&ctx); + pref(plugin)->handlePluginEvent(&ctx, &event); + /* Free the plugin instance */ + pref(plugin)->freePlugin(&ctx); } unload_plugins(); printf("bacula: OK ...\n"); + close_memory_pool(); sm_dump(false); return 0; } -/* - * 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. - */ -static Plugin *new_plugin() -{ - Plugin *plugin; - - plugin = (Plugin *)malloc(sizeof(Plugin)); - memset(plugin, 0, sizeof(Plugin)); - plugin_list->append(plugin); - return plugin; -} - - -/* - * Load all the plugins in the specified directory. - */ -bool load_plugins(const char *plugin_dir) -{ - t_bpInitialize p_bpInitialize; - bFuncs bfuncs; - Plugin *plugin; - char *error; - DIR* dp = NULL; - struct dirent *entry, *result; - int name_max; - struct stat statp; - bool found = false; - POOL_MEM fname(PM_FNAME); - bool need_slash = false; - int len; - - /* Setup pointers to Bacula functions */ - bfuncs.size = sizeof(bFuncs); - bfuncs.version = 1; - bfuncs.bGetValue = baculaGetValue; - bfuncs.bSetValue = baculaSetValue; - - plugin = new_plugin(); - - name_max = pathconf(".", _PC_NAME_MAX); - if (name_max < 1024) { - name_max = 1024; - } - - if (!(dp = opendir(plugin_dir))) { - berrno be; - Dmsg2(29, "load_plugins: failed to open dir %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]); - } - entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); - for ( ;; ) { - if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) { - Dmsg1(129, "load_plugins: failed to find suitable file in dir %s\n", - plugin_dir); - break; - } - if (strcmp(result->d_name, ".") == 0 || - strcmp(result->d_name, "..") == 0) { - continue; - } - - len = strlen(result->d_name); - if (len < 7 || strcmp(&result->d_name[len-6], "-sd.so") != 0) { - continue; - } - printf("Got: name=%s len=%d\n", result->d_name, len); - - pm_strcpy(fname, plugin_dir); - if (need_slash) { - pm_strcat(fname, "/"); - } - pm_strcat(fname, result->d_name); - if (lstat(fname.c_str(), &statp) != 0 || !S_ISREG(statp.st_mode)) { - continue; /* ignore directories & special files */ - } - - plugin->file = bstrdup(result->d_name); - plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW); - if (!plugin->pHandle) { - printf("dlopen of %s failed: ERR=%s\n", fname.c_str(), dlerror()); - goto get_out; - } - - /* Get two global entry points */ - p_bpInitialize = (t_bpInitialize)dlsym(plugin->pHandle, "bpInitialize"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - plugin->p_bpShutdown = (t_bpShutdown)dlsym(plugin->pHandle, "bpShutdown"); - if ((error=dlerror()) != NULL) { - printf("dlsym failed: ERR=%s\n", error); - goto get_out; - } - - /* Initialize the plugin */ - p_bpInitialize(&bfuncs, &plugin->pfuncs); - printf("bacula: plugin_size=%d plugin_version=%d\n", - plugin->pfuncs.size, plugin->pfuncs.version); - - found = true; /* found a plugin */ - } - -get_out: - free(entry); - if (dp) { - closedir(dp); - } - return found; -} - -/* - * Unload all the loaded plugins - */ -void unload_plugins() -{ - Plugin *plugin; - - foreach_alist(plugin, plugin_list) { - /* Shut it down and unload it */ - plugin->p_bpShutdown(); - dlclose(plugin->pHandle); - if (plugin->file) { - free(plugin->file); - } - free(plugin); - } - delete plugin_list; - plugin_list = NULL; -} - static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) { - printf("bacula: GetValue var=%d\n", var); + printf("bacula: baculaGetValue var=%d\n", var); if (value) { *((int *)value) = 100; } @@ -252,6 +114,6 @@ static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) { - printf("baculaSetValue var=%d\n", var); + printf("bacula: baculaSetValue var=%d\n", var); return 0; } diff --git a/bacula/src/plugins/sd/plugin-sd.c b/bacula/src/plugins/sd/plugin-sd.c index bce4eda281..17f74b06ee 100644 --- a/bacula/src/plugins/sd/plugin-sd.c +++ b/bacula/src/plugins/sd/plugin-sd.c @@ -38,80 +38,86 @@ extern "C" { #endif +#define PLUGIN_LICENSE "GPL" +#define PLUGIN_AUTHOR "Kern Sibbald" +#define PLUGIN_DATE "November 2007" +#define PLUGIN_VERSION "1" +#define PLUGIN_DESCRIPTION "Test Storage Daemon Plugin" + /* Forward referenced functions */ -bpError pNew(bpContext *ctx); -bpError pDestroy(bpContext *ctx); -bpError pGetValue(bpContext *ctx, pVariable var, void *value); -bpError pSetValue(bpContext *ctx, pVariable var, void *value); -bpError pHandleEvent(bpContext *ctx, bEvent *event); +static bpError newPlugin(bpContext *ctx); +static bpError freePlugin(bpContext *ctx); +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value); +static bpError handlePluginEvent(bpContext *ctx, bEvent *event); /* Pointers to Bacula functions */ -bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value); -bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value); +static bFuncs *bfuncs = NULL; -pFuncs pluginFuncs = { +static pFuncs pluginFuncs = { sizeof(pluginFuncs), - 1, - pNew, - pDestroy, - pGetValue, - pSetValue, - pHandleEvent + PLUGIN_INTERFACE, + PLUGIN_MAGIC, + PLUGIN_LICENSE, + PLUGIN_AUTHOR, + PLUGIN_DATE, + PLUGIN_VERSION, + PLUGIN_DESCRIPTION, + + /* Entry points into plugin */ + newPlugin, /* new plugin instance */ + freePlugin, /* free plugin instance */ + getPluginValue, + setPluginValue, + handlePluginEvent }; -bpError bpInitialize(bFuncs *bfuncs, pFuncs *pfuncs) +bpError loadPlugin(bFuncs *lbfuncs, pFuncs **pfuncs) { - printf("plugin: Initializing. size=%d version=%d\n", bfuncs->size, bfuncs->version); - p_bGetValue = bfuncs->bGetValue; - p_bSetValue = bfuncs->bSetValue; - - pfuncs->pNew = pNew; - pfuncs->pDestroy = pDestroy; - pfuncs->pGetValue = pGetValue; - pfuncs->pSetValue = pSetValue; - pfuncs->pHandleEvent = pHandleEvent; - pfuncs->size = sizeof(pFuncs); - pfuncs->version = 1; + bfuncs = lbfuncs; /* set Bacula funct pointers */ + printf("plugin: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->interface); + + *pfuncs = &pluginFuncs; /* return pointer to our functions */ return 0; } -bpError bpShutdown() +bpError unloadPlugin() { - printf("plugin: Shutting down\n"); + printf("plugin: Unloaded\n"); return 0; } -bpError pNew(bpContext *ctx) +static bpError newPlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: New JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: newPlugin JobId=%d\n", JobId); return 0; } -bpError pDestroy(bpContext *ctx) +static bpError freePlugin(bpContext *ctx) { int JobId = 0; - p_bGetValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: Destroy JobId=%d\n", JobId); + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: freePlugin JobId=%d\n", JobId); return 0; } -bpError pGetValue(bpContext *ctx, pVariable var, void *value) +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: GetValue var=%d\n", var); + printf("plugin: getPluginValue var=%d\n", var); return 0; } -bpError pSetValue(bpContext *ctx, pVariable var, void *value) +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value) { - printf("plugin: PutValue var=%d\n", var); + printf("plugin: setPluginValue var=%d\n", var); return 0; } -bpError pHandleEvent(bpContext *ctx, bEvent *event) +static bpError handlePluginEvent(bpContext *ctx, bEvent *event) { printf("plugin: HandleEvent Event=%d\n", event->eventType); return 0; diff --git a/bacula/src/plugins/sd/plugin-sd.h b/bacula/src/plugins/sd/plugin-sd.h index 9fd2d530cc..cc78a42cb6 100644 --- a/bacula/src/plugins/sd/plugin-sd.h +++ b/bacula/src/plugins/sd/plugin-sd.h @@ -32,8 +32,8 @@ * */ -#ifndef __PLUGIN_H -#define __PLUGIN_H +#ifndef __PLUGIN_FD_H +#define __PLUGIN_FD_H #include #ifndef __CONFIG_H @@ -41,28 +41,13 @@ #include "config.h" #endif #include "bc_types.h" +#include "lib/plugin.h" #ifdef __cplusplus extern "C" { #endif -/**************************************************************************** - * * - * Common definitions * - * * - ****************************************************************************/ - -/* Universal return code from all functions */ -typedef int32_t bpError; - -/* Context packet as first argument of all functions */ -typedef struct s_bpContext { - void *bContext; /* Bacula private context */ - void *pContext; /* Plugin private context */ -} bpContext; - - /**************************************************************************** * * * Bacula definitions * @@ -92,13 +77,11 @@ typedef struct s_bEvent { /* Bacula interface version and function pointers */ typedef struct s_baculaFuncs { uint32_t size; - uint32_t version; - bpError (*bGetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bSetValue)(bpContext *ctx, bVariable var, void *value); - bpError (*bMemAlloc)(bpContext *ctx, uint32_t size, char *addr); - bpError (*bMemFree)(bpContext *ctx, char *addr); - bpError (*bMemFlush)(bpContext *ctx); - bpError (*bVersion)(bVariable var, void *value); + uint32_t interface; + bpError (*getBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*setBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*allocBaculaMem)(bpContext *ctx, uint32_t size, char *addr); + bpError (*freeBaculaMem)(bpContext *ctx, char *addr); } bFuncs; @@ -114,22 +97,29 @@ typedef enum { } pVariable; +#define PLUGIN_MAGIC "*PluginData*" +#define PLUGIN_INTERFACE 1 + typedef struct s_pluginFuncs { uint32_t size; - uint32_t version; - bpError (*pNew)(bpContext *ctx); - bpError (*pDestroy)(bpContext *ctx); - bpError (*pGetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pSetValue)(bpContext *ctx, pVariable var, void *value); - bpError (*pHandleEvent)(bpContext *ctx, bEvent *event); + uint32_t interface; + char *plugin_magic; + char *plugin_license; + char *plugin_author; + char *plugin_date; + char *plugin_version; + char *plugin_description; + bpError (*newPlugin)(bpContext *ctx); + bpError (*freePlugin)(bpContext *ctx); + bpError (*getPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*setPluginValue)(bpContext *ctx, pVariable var, void *value); + bpError (*handlePluginEvent)(bpContext *ctx, bEvent *event); } pFuncs; -typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs); -typedef bpError (*t_bpShutdown)(void); - +#define pref(plugin) ((pFuncs *)(plugin->pfuncs)) #ifdef __cplusplus } #endif -#endif /* __PLUGIN_H */ +#endif /* __PLUGIN_FD_H */