From: Kern Sibbald Date: Mon, 28 Jan 2008 14:41:46 +0000 (+0000) Subject: Alpha integration of Dir plugin X-Git-Tag: Release-7.0.0~5098 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=85b9ac1d1f3494ba97b3a9257deb48ded0ab3284;p=bacula%2Fbacula Alpha integration of Dir plugin git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6333 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/dird/Makefile.in b/bacula/src/dird/Makefile.in index 3e44d46227..e3e68e76fc 100644 --- a/bacula/src/dird/Makefile.in +++ b/bacula/src/dird/Makefile.in @@ -29,7 +29,7 @@ dummy: # SVRSRCS = dird.c admin.c authenticate.c \ autoprune.c backup.c bsr.c \ - catreq.c dird_conf.c expand.c \ + catreq.c dir-plugins.c dird_conf.c expand.c \ fd_cmds.c getmsg.c inc_conf.c job.c \ jobq.c migrate.c \ mountreq.c msgchan.c next_vol.c newvol.c \ @@ -44,7 +44,7 @@ SVRSRCS = dird.c admin.c authenticate.c \ ua_status.c ua_tree.c ua_update.c verify.c SVROBJS = dird.o admin.o authenticate.o \ autoprune.o backup.o bsr.o \ - catreq.o dird_conf.o expand.o \ + catreq.o dir-plugins.o dird_conf.o expand.o \ fd_cmds.o getmsg.o inc_conf.o job.o \ jobq.o migrate.o \ mountreq.o msgchan.o next_vol.o newvol.o \ diff --git a/bacula/src/dird/dir-plugins.c b/bacula/src/dird/dir-plugins.c new file mode 100644 index 0000000000..69518b9f42 --- /dev/null +++ b/bacula/src/dird/dir-plugins.c @@ -0,0 +1,258 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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. +*/ +/* + * Main program to test loading and running Bacula plugins. + * Destined to become Bacula pluginloader, ... + * + * Kern Sibbald, October 2007 + */ +#include "bacula.h" +#include "jcr.h" +#include "dir-plugins.h" + +const int dbglvl = 0; +const char *plugin_type = "-dir.so"; + + +/* Forward referenced functions */ +static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value); +static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value); +static bpError baculaRegisterEvents(bpContext *ctx, ...); +static bpError baculaJobMsg(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg); +static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, + int level, const char *msg); + + +/* Bacula info */ +static bInfo binfo = { + sizeof(bFuncs), + PLUGIN_INTERFACE, +}; + +/* Bacula entry points */ +static bFuncs bfuncs = { + sizeof(bFuncs), + PLUGIN_INTERFACE, + baculaRegisterEvents, + baculaGetValue, + baculaSetValue, + baculaJobMsg, + baculaDebugMsg +}; + +/* + * Create a plugin event + */ +void generate_plugin_event(JCR *jcr, bEventType eventType) +{ + bEvent event; + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + event.eventType = eventType; + foreach_alist(plugin, plugin_list) { + plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event); + } +} + +void load_dir_plugins(const char *plugin_dir) +{ + if (!plugin_dir) { + return; + } + + plugin_list = New(alist(10, not_owned_by_alist)); + load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type); +} + +/* + * Create a new instance of each plugin for this Job + */ +void new_plugins(JCR *jcr) +{ + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + int num = plugin_list->size(); + + if (num == 0) { + return; + } + + jcr->plugin_ctx = (void *)malloc(sizeof(bpContext) * num); + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + foreach_alist(plugin, plugin_list) { + /* Start a new instance of each plugin */ + plugin_ctx[i].bContext = (void *)jcr; + plugin_ctx[i].pContext = NULL; + plug_func(plugin)->newPlugin(&plugin_ctx[i++]); + } +} + +/* + * Free the plugin instances for this Job + */ +void free_plugins(JCR *jcr) +{ + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + foreach_alist(plugin, plugin_list) { + /* Free the plugin instance */ + plug_func(plugin)->freePlugin(&plugin_ctx[i++]); + } + free(plugin_ctx); + jcr->plugin_ctx = NULL; +} + + +/* ============================================================== + * + * Callbacks from the plugin + * + * ============================================================== + */ +static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) +{ + JCR *jcr = (JCR *)(ctx->bContext); +// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); + if (!value) { + return 1; + } +// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); + switch (var) { + case bVarJobId: + *((int *)value) = jcr->JobId; + Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId); + break; + case bVarFDName: + *((char **)value) = my_name; + Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name); + break; + case bVarLevel: + case bVarType: + case bVarClient: + case bVarJobName: + case bVarJobStatus: + case bVarSinceTime: + break; + } + return 0; +} + +static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) +{ + Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var); + return 0; +} + +static bpError baculaRegisterEvents(bpContext *ctx, ...) +{ + va_list args; + uint32_t event; + + va_start(args, ctx); + while ((event = va_arg(args, uint32_t))) { + Dmsg1(dbglvl, "Plugin wants event=%u\n", event); + } + va_end(args); + return 0; +} + +static bpError baculaJobMsg(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg) +{ + Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n", + file, line, type, mtime, msg); + return 0; +} + +static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, + int level, const char *msg) +{ + Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n", + file, line, level, msg); + return 0; +} + +#ifdef TEST_PROGRAM + + +int main(int argc, char *argv[]) +{ + char plugin_dir[1000]; + JCR mjcr1, mjcr2; + JCR *jcr1 = &mjcr1; + JCR *jcr2 = &mjcr2; + + strcpy(my_name, "test-dir"); + + getcwd(plugin_dir, sizeof(plugin_dir)-1); + load_dir_plugins(plugin_dir); + + jcr1->JobId = 111; + new_plugins(jcr1); + + jcr2->JobId = 222; + new_plugins(jcr2); + + generate_plugin_event(jcr1, bEventJobStart); + generate_plugin_event(jcr1, bEventJobEnd); + generate_plugin_event(jcr2, bEventJobStart); + free_plugins(jcr1); + generate_plugin_event(jcr2, bEventJobEnd); + free_plugins(jcr2); + + unload_plugins(); + + Dmsg0(dbglvl, "bacula: OK ...\n"); + close_memory_pool(); + sm_dump(false); + return 0; +} + +#endif /* TEST_PROGRAM */ diff --git a/bacula/src/dird/dir-plugins.h b/bacula/src/dird/dir-plugins.h new file mode 100644 index 0000000000..e25b3265c4 --- /dev/null +++ b/bacula/src/dird/dir-plugins.h @@ -0,0 +1,149 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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. +*/ +/* + * Interface definition for Bacula Plugins + * + * Kern Sibbald, October 2007 + * + */ + +#ifndef __FD_PLUGINS_H +#define __FD_PLUGINS_H + +#include +#ifndef __CONFIG_H +#define __CONFIG_H +#include "config.h" +#endif +#include "bc_types.h" +#include "lib/plugins.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/**************************************************************************** + * * + * Bacula definitions * + * * + ****************************************************************************/ + +/* Bacula Variable Ids */ +typedef enum { + bVarJobId = 1, + bVarFDName = 2, + bVarLevel = 3, + bVarType = 4, + bVarClient = 5, + bVarJobName = 6, + bVarJobStatus = 7, + bVarSinceTime = 8 +} bVariable; + +typedef enum { + bEventJobStart = 1, + bEventJobEnd = 2, +} bEventType; + +typedef struct s_bEvent { + uint32_t eventType; +} bEvent; + +typedef struct s_baculaInfo { + uint32_t size; + uint32_t interface; +} bInfo; + +/* Bacula interface version and function pointers */ +typedef struct s_baculaFuncs { + uint32_t size; + uint32_t interface; + bpError (*registerBaculaEvents)(bpContext *ctx, ...); + bpError (*getBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*setBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*JobMessage)(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg); + bpError (*DebugMessage)(bpContext *ctx, const char *file, int line, + int level, const char *msg); +} bFuncs; + +/* Bacula Subroutines */ +void load_dir_plugins(const char *plugin_dir); +void new_plugins(JCR *jcr); +void free_plugins(JCR *jcr); +void generate_plugin_event(JCR *jcr, bEventType event); + + + +/**************************************************************************** + * * + * Plugin definitions * + * * + ****************************************************************************/ + +typedef enum { + pVarName = 1, + pVarDescription = 2 +} pVariable; + + +#define PLUGIN_MAGIC "*PluginData*" +#define PLUGIN_INTERFACE 1 + +typedef struct s_pluginInfo { + uint32_t size; + uint32_t interface; + char *plugin_magic; + char *plugin_license; + char *plugin_author; + char *plugin_date; + char *plugin_version; + char *plugin_description; +} pInfo; + +typedef struct s_pluginFuncs { + uint32_t size; + uint32_t interface; + 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; + +#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs)) +#define plug_info(plugin) ((pInfo *)(plugin->pinfo)) + +#ifdef __cplusplus +} +#endif + +#endif /* __FD_PLUGINS_H */ diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index 7a065582de..db0c015d7c 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2008 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. @@ -247,6 +247,8 @@ int main (int argc, char *argv[]) read_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); } + load_dir_plugins(director->plugin_directory); + drop(uid, gid); /* reduce privileges if requested */ if (!check_catalog()) { @@ -333,6 +335,7 @@ void terminate_dird(int sig) already_here = true; stop_watchdog(); generate_daemon_event(NULL, "Exit"); + unload_plugins(); write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); delete_pid_file(director->pid_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs)); term_scheduler(); diff --git a/bacula/src/dird/dird.h b/bacula/src/dird/dird.h index 8caea1ebb5..f4c603fb74 100644 --- a/bacula/src/dird/dird.h +++ b/bacula/src/dird/dird.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2008 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. @@ -36,6 +36,7 @@ #include "lib/runscript.h" #include "lib/breg.h" #include "dird_conf.h" +#include "dir-plugins.h" #define DIRECTOR_DAEMON 1 diff --git a/bacula/src/filed/fd-plugins.c b/bacula/src/filed/fd-plugins.c index ef6ecc3f4b..1547f14a52 100644 --- a/bacula/src/filed/fd-plugins.c +++ b/bacula/src/filed/fd-plugins.c @@ -221,7 +221,6 @@ static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, #ifdef TEST_PROGRAM -char my_name = "test-fd"; int main(int argc, char *argv[]) { @@ -229,6 +228,8 @@ int main(int argc, char *argv[]) JCR mjcr1, mjcr2; JCR *jcr1 = &mjcr1; JCR *jcr2 = &mjcr2; + + strcpy(my_name, "test-fd"); getcwd(plugin_dir, sizeof(plugin_dir)-1); load_fd_plugins(plugin_dir); diff --git a/bacula/src/filed/fd-plugins.h b/bacula/src/filed/fd-plugins.h index af575c9841..702abb4d61 100644 --- a/bacula/src/filed/fd-plugins.h +++ b/bacula/src/filed/fd-plugins.h @@ -32,8 +32,8 @@ * */ -#ifndef __PLUGIN_FD_H -#define __PLUGIN_FD_H +#ifndef __FD_PLUGINS_H +#define __FD_PLUGINS_H #include #ifndef __CONFIG_H @@ -41,7 +41,7 @@ #include "config.h" #endif #include "bc_types.h" -#include "lib/plugin.h" +#include "lib/plugins.h" #ifdef __cplusplus extern "C" { @@ -146,4 +146,4 @@ typedef struct s_pluginFuncs { } #endif -#endif /* __PLUGIN_FD_H */ +#endif /* __FD_PLUGINS_H */ diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index 5b7e5f08b1..dc819f8276 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 \ - plugin.c queue.c bregex.c \ + plugins.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 \ - plugin.o queue.o bregex.o \ + plugins.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 \ @@ -109,7 +109,7 @@ bsnprintf: bsnprintf.o rm -f bsnprintf.o $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) bsnprintf.c -plugin.o: plugin.c plugin.h +plugins.o: plugins.c plugins.h @echo "Compiling $<" $(NO_ECHO)$(CXX) -fPIC $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $< diff --git a/bacula/src/lib/plugin.c b/bacula/src/lib/plugin.c deleted file mode 100644 index 110e7fcf63..0000000000 --- a/bacula/src/lib/plugin.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2007-2008 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 "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 *binfo, void *bfuncs, const char *plugin_dir, const char *type) -{ - bool found = false; -#ifndef HAVE_WIN32 - t_loadPlugin loadPlugin; - Plugin *plugin; - DIR* dp = NULL; - struct dirent *entry = NULL, *result; - int name_max; - struct stat statp; - POOL_MEM fname(PM_FNAME); - bool need_slash = false; - int len, type_len; - - - name_max = pathconf(".", _PC_NAME_MAX); - if (name_max < 1024) { - name_max = 1024; - } - - if (!(dp = opendir(plugin_dir))) { - berrno be; - Jmsg(NULL, M_ERROR, 0, _("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]); - } - entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); - 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"), - 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 = new_plugin(); - plugin->file = bstrdup(result->d_name); - 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()); - goto get_out; - } - - /* Get two global entry points */ - 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()); - 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()); - goto get_out; - } - - /* Initialize the plugin */ - loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs); - - found = true; /* found a plugin */ - } - -get_out: - if (entry) { - free(entry); - } - if (dp) { - closedir(dp); - } -#endif - return found; -} - -/* - * Unload all the loaded plugins - */ -void unload_plugins() -{ -#ifndef HAVE_WIN32 - 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; -#endif -} diff --git a/bacula/src/lib/plugin.h b/bacula/src/lib/plugin.h deleted file mode 100644 index 07f0741fd7..0000000000 --- a/bacula/src/lib/plugin.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2007-2008 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" -#ifndef HAVE_WIN32 -#include -#endif -#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 *binfo, void *bfuncs, void **pinfo, void **pfuncs); -typedef bpError (*t_unloadPlugin)(void); -} - -class Plugin { -public: - char *file; - t_unloadPlugin unloadPlugin; - void *pinfo; - void *pfuncs; - void *pHandle; -}; - -/* Functions */ -extern Plugin *new_plugin(); -extern bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, const char *type); -extern void unload_plugins(); - - -#endif /* __PLUGIN_H */ diff --git a/bacula/src/lib/plugins.c b/bacula/src/lib/plugins.c new file mode 100644 index 0000000000..c67228e6fd --- /dev/null +++ b/bacula/src/lib/plugins.c @@ -0,0 +1,179 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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 "plugins.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 *binfo, void *bfuncs, const char *plugin_dir, const char *type) +{ + bool found = false; +#ifndef HAVE_WIN32 + t_loadPlugin loadPlugin; + Plugin *plugin; + DIR* dp = NULL; + struct dirent *entry = NULL, *result; + int name_max; + struct stat statp; + POOL_MEM fname(PM_FNAME); + bool need_slash = false; + int len, type_len; + + + name_max = pathconf(".", _PC_NAME_MAX); + if (name_max < 1024) { + name_max = 1024; + } + + if (!(dp = opendir(plugin_dir))) { + berrno be; + Jmsg(NULL, M_ERROR, 0, _("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]); + } + entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000); + 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"), + 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 = new_plugin(); + plugin->file = bstrdup(result->d_name); + 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()); + goto get_out; + } + + /* Get two global entry points */ + 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()); + 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()); + goto get_out; + } + + /* Initialize the plugin */ + loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs); + + found = true; /* found a plugin */ + } + +get_out: + if (entry) { + free(entry); + } + if (dp) { + closedir(dp); + } +#endif + return found; +} + +/* + * Unload all the loaded plugins + */ +void unload_plugins() +{ +#ifndef HAVE_WIN32 + 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; +#endif +} diff --git a/bacula/src/lib/plugins.h b/bacula/src/lib/plugins.h new file mode 100644 index 0000000000..5af9e05c4a --- /dev/null +++ b/bacula/src/lib/plugins.h @@ -0,0 +1,90 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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 __PLUGINS_H +#define __PLUGINS_H + +#include "bacula.h" +#ifndef HAVE_WIN32 +#include +#endif +#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 *binfo, void *bfuncs, void **pinfo, void **pfuncs); +typedef bpError (*t_unloadPlugin)(void); +} + +class Plugin { +public: + char *file; + t_unloadPlugin unloadPlugin; + void *pinfo; + void *pfuncs; + void *pHandle; +}; + +/* Functions */ +extern Plugin *new_plugin(); +extern bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, const char *type); +extern void unload_plugins(); + + +#endif /* __PLUGINS_H */ diff --git a/bacula/src/plugins/dir/Makefile b/bacula/src/plugins/dir/Makefile index f5c430e655..97e4dbb052 100644 --- a/bacula/src/plugins/dir/Makefile +++ b/bacula/src/plugins/dir/Makefile @@ -1,5 +1,5 @@ # -# Simple Makefile for building test plugins for Bacula +# Simple Makefile for building test Director plugins for Bacula # # No optimization for now for easy debugging @@ -9,16 +9,16 @@ CC = g++ -g -O0 -Wall .c.o: $(CC) -I../.. -DTEST_PROGRAM -c $< -all: main plugin-dir.so +all: dir-plugins example-plugin-dir.so -main: main.o plugin-dir.h - $(CC) -L../../lib main.o -o main -lbac -lpthread -lssl -l crypto -ldl +dir-plugins: dir-plugins.o dir-plugins.h + $(CC) -L../../lib dir-plugins.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 +example-plugin-dir.o: example-plugin-dir.c dir-plugins.h + $(CC) -fPIC -I../.. -c example-plugin-dir.c -plugin-dir.so: plugin-dir.o - $(CC) -shared plugin-dir.o -o plugin-dir.so +example-plugin-dir.so: example-plugin-dir.o + $(CC) -shared example-plugin-dir.o -o example-plugin-dir.so clean: diff --git a/bacula/src/plugins/dir/dir-plugins.c b/bacula/src/plugins/dir/dir-plugins.c new file mode 100644 index 0000000000..69518b9f42 --- /dev/null +++ b/bacula/src/plugins/dir/dir-plugins.c @@ -0,0 +1,258 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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. +*/ +/* + * Main program to test loading and running Bacula plugins. + * Destined to become Bacula pluginloader, ... + * + * Kern Sibbald, October 2007 + */ +#include "bacula.h" +#include "jcr.h" +#include "dir-plugins.h" + +const int dbglvl = 0; +const char *plugin_type = "-dir.so"; + + +/* Forward referenced functions */ +static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value); +static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value); +static bpError baculaRegisterEvents(bpContext *ctx, ...); +static bpError baculaJobMsg(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg); +static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, + int level, const char *msg); + + +/* Bacula info */ +static bInfo binfo = { + sizeof(bFuncs), + PLUGIN_INTERFACE, +}; + +/* Bacula entry points */ +static bFuncs bfuncs = { + sizeof(bFuncs), + PLUGIN_INTERFACE, + baculaRegisterEvents, + baculaGetValue, + baculaSetValue, + baculaJobMsg, + baculaDebugMsg +}; + +/* + * Create a plugin event + */ +void generate_plugin_event(JCR *jcr, bEventType eventType) +{ + bEvent event; + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + event.eventType = eventType; + foreach_alist(plugin, plugin_list) { + plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event); + } +} + +void load_dir_plugins(const char *plugin_dir) +{ + if (!plugin_dir) { + return; + } + + plugin_list = New(alist(10, not_owned_by_alist)); + load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type); +} + +/* + * Create a new instance of each plugin for this Job + */ +void new_plugins(JCR *jcr) +{ + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + int num = plugin_list->size(); + + if (num == 0) { + return; + } + + jcr->plugin_ctx = (void *)malloc(sizeof(bpContext) * num); + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + foreach_alist(plugin, plugin_list) { + /* Start a new instance of each plugin */ + plugin_ctx[i].bContext = (void *)jcr; + plugin_ctx[i].pContext = NULL; + plug_func(plugin)->newPlugin(&plugin_ctx[i++]); + } +} + +/* + * Free the plugin instances for this Job + */ +void free_plugins(JCR *jcr) +{ + Plugin *plugin; + int i = 0; + + if (!plugin_list) { + return; + } + + bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx; + Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId); + foreach_alist(plugin, plugin_list) { + /* Free the plugin instance */ + plug_func(plugin)->freePlugin(&plugin_ctx[i++]); + } + free(plugin_ctx); + jcr->plugin_ctx = NULL; +} + + +/* ============================================================== + * + * Callbacks from the plugin + * + * ============================================================== + */ +static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) +{ + JCR *jcr = (JCR *)(ctx->bContext); +// Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var); + if (!value) { + return 1; + } +// Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); + switch (var) { + case bVarJobId: + *((int *)value) = jcr->JobId; + Dmsg1(dbglvl, "Bacula: return bVarJobId=%d\n", jcr->JobId); + break; + case bVarFDName: + *((char **)value) = my_name; + Dmsg1(dbglvl, "Bacula: return my_name=%s\n", my_name); + break; + case bVarLevel: + case bVarType: + case bVarClient: + case bVarJobName: + case bVarJobStatus: + case bVarSinceTime: + break; + } + return 0; +} + +static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) +{ + Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var); + return 0; +} + +static bpError baculaRegisterEvents(bpContext *ctx, ...) +{ + va_list args; + uint32_t event; + + va_start(args, ctx); + while ((event = va_arg(args, uint32_t))) { + Dmsg1(dbglvl, "Plugin wants event=%u\n", event); + } + va_end(args); + return 0; +} + +static bpError baculaJobMsg(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg) +{ + Dmsg5(dbglvl, "Job message: %s:%d type=%d time=%ld msg=%s\n", + file, line, type, mtime, msg); + return 0; +} + +static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line, + int level, const char *msg) +{ + Dmsg4(dbglvl, "Debug message: %s:%d level=%d msg=%s\n", + file, line, level, msg); + return 0; +} + +#ifdef TEST_PROGRAM + + +int main(int argc, char *argv[]) +{ + char plugin_dir[1000]; + JCR mjcr1, mjcr2; + JCR *jcr1 = &mjcr1; + JCR *jcr2 = &mjcr2; + + strcpy(my_name, "test-dir"); + + getcwd(plugin_dir, sizeof(plugin_dir)-1); + load_dir_plugins(plugin_dir); + + jcr1->JobId = 111; + new_plugins(jcr1); + + jcr2->JobId = 222; + new_plugins(jcr2); + + generate_plugin_event(jcr1, bEventJobStart); + generate_plugin_event(jcr1, bEventJobEnd); + generate_plugin_event(jcr2, bEventJobStart); + free_plugins(jcr1); + generate_plugin_event(jcr2, bEventJobEnd); + free_plugins(jcr2); + + unload_plugins(); + + Dmsg0(dbglvl, "bacula: OK ...\n"); + close_memory_pool(); + sm_dump(false); + return 0; +} + +#endif /* TEST_PROGRAM */ diff --git a/bacula/src/plugins/dir/dir-plugins.h b/bacula/src/plugins/dir/dir-plugins.h new file mode 100644 index 0000000000..e25b3265c4 --- /dev/null +++ b/bacula/src/plugins/dir/dir-plugins.h @@ -0,0 +1,149 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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. +*/ +/* + * Interface definition for Bacula Plugins + * + * Kern Sibbald, October 2007 + * + */ + +#ifndef __FD_PLUGINS_H +#define __FD_PLUGINS_H + +#include +#ifndef __CONFIG_H +#define __CONFIG_H +#include "config.h" +#endif +#include "bc_types.h" +#include "lib/plugins.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + + +/**************************************************************************** + * * + * Bacula definitions * + * * + ****************************************************************************/ + +/* Bacula Variable Ids */ +typedef enum { + bVarJobId = 1, + bVarFDName = 2, + bVarLevel = 3, + bVarType = 4, + bVarClient = 5, + bVarJobName = 6, + bVarJobStatus = 7, + bVarSinceTime = 8 +} bVariable; + +typedef enum { + bEventJobStart = 1, + bEventJobEnd = 2, +} bEventType; + +typedef struct s_bEvent { + uint32_t eventType; +} bEvent; + +typedef struct s_baculaInfo { + uint32_t size; + uint32_t interface; +} bInfo; + +/* Bacula interface version and function pointers */ +typedef struct s_baculaFuncs { + uint32_t size; + uint32_t interface; + bpError (*registerBaculaEvents)(bpContext *ctx, ...); + bpError (*getBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*setBaculaValue)(bpContext *ctx, bVariable var, void *value); + bpError (*JobMessage)(bpContext *ctx, const char *file, int line, + int type, time_t mtime, const char *msg); + bpError (*DebugMessage)(bpContext *ctx, const char *file, int line, + int level, const char *msg); +} bFuncs; + +/* Bacula Subroutines */ +void load_dir_plugins(const char *plugin_dir); +void new_plugins(JCR *jcr); +void free_plugins(JCR *jcr); +void generate_plugin_event(JCR *jcr, bEventType event); + + + +/**************************************************************************** + * * + * Plugin definitions * + * * + ****************************************************************************/ + +typedef enum { + pVarName = 1, + pVarDescription = 2 +} pVariable; + + +#define PLUGIN_MAGIC "*PluginData*" +#define PLUGIN_INTERFACE 1 + +typedef struct s_pluginInfo { + uint32_t size; + uint32_t interface; + char *plugin_magic; + char *plugin_license; + char *plugin_author; + char *plugin_date; + char *plugin_version; + char *plugin_description; +} pInfo; + +typedef struct s_pluginFuncs { + uint32_t size; + uint32_t interface; + 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; + +#define plug_func(plugin) ((pFuncs *)(plugin->pfuncs)) +#define plug_info(plugin) ((pInfo *)(plugin->pinfo)) + +#ifdef __cplusplus +} +#endif + +#endif /* __FD_PLUGINS_H */ diff --git a/bacula/src/plugins/dir/example-plugin-dir.c b/bacula/src/plugins/dir/example-plugin-dir.c new file mode 100644 index 0000000000..f58679ff60 --- /dev/null +++ b/bacula/src/plugins/dir/example-plugin-dir.c @@ -0,0 +1,149 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2007-2008 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. +*/ +/* + * Sample Plugin program + * + * Kern Sibbald, October 2007 + * + */ +#include +#include "dir-plugins.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PLUGIN_LICENSE "GPL" +#define PLUGIN_AUTHOR "Kern Sibbald" +#define PLUGIN_DATE "January 2008" +#define PLUGIN_VERSION "1" +#define PLUGIN_DESCRIPTION "Test File Daemon Plugin" + +/* Forward referenced functions */ +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 */ +static bFuncs *bfuncs = NULL; +static bInfo *binfo = NULL; + +static pInfo pluginInfo = { + sizeof(pluginInfo), + PLUGIN_INTERFACE, + PLUGIN_MAGIC, + PLUGIN_LICENSE, + PLUGIN_AUTHOR, + PLUGIN_DATE, + PLUGIN_VERSION, + PLUGIN_DESCRIPTION, +}; + +static pFuncs pluginFuncs = { + sizeof(pluginFuncs), + PLUGIN_INTERFACE, + + /* Entry points into plugin */ + newPlugin, /* new plugin instance */ + freePlugin, /* free plugin instance */ + getPluginValue, + setPluginValue, + handlePluginEvent +}; + +bpError loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs) +{ + bfuncs = lbfuncs; /* set Bacula funct pointers */ + binfo = lbinfo; + printf("plugin: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->interface); + + *pinfo = &pluginInfo; /* return pointer to our info */ + *pfuncs = &pluginFuncs; /* return pointer to our functions */ + + return 0; +} + +bpError unloadPlugin() +{ + printf("plugin: Unloaded\n"); + return 0; +} + +static bpError newPlugin(bpContext *ctx) +{ + int JobId = 0; + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: newPlugin JobId=%d\n", JobId); + bfuncs->registerBaculaEvents(ctx, 1, 2, 0); + return 0; +} + +static bpError freePlugin(bpContext *ctx) +{ + int JobId = 0; + bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); + printf("plugin: freePlugin JobId=%d\n", JobId); + return 0; +} + +static bpError getPluginValue(bpContext *ctx, pVariable var, void *value) +{ + printf("plugin: getPluginValue var=%d\n", var); + return 0; +} + +static bpError setPluginValue(bpContext *ctx, pVariable var, void *value) +{ + printf("plugin: setPluginValue var=%d\n", var); + return 0; +} + +static bpError handlePluginEvent(bpContext *ctx, bEvent *event) +{ + char *name; + switch (event->eventType) { + case bEventJobStart: + printf("plugin: HandleEvent JobStart\n"); + break; + case bEventJobEnd: + printf("plugin: HandleEvent JobEnd\n"); + break; + } + bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name); + printf("FD Name=%s\n", name); + bfuncs->JobMessage(ctx, __FILE__, __LINE__, 1, 0, "JobMesssage message"); + bfuncs->DebugMessage(ctx, __FILE__, __LINE__, 1, "DebugMesssage message"); + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/bacula/src/plugins/dir/main.c b/bacula/src/plugins/dir/main.c deleted file mode 100644 index 387df26128..0000000000 --- a/bacula/src/plugins/dir/main.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - 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. -*/ -/* - * Main program to test loading and running Bacula plugins. - * Destined to become Bacula pluginloader, ... - * - * Kern Sibbald, October 2007 - */ -#include "bacula.h" -#include -#include "lib/plugin.h" -#include "plugin-dir.h" - -const char *plugin_type = "-dir.so"; - - -/* Forward referenced functions */ -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]; - bpContext ctx; - bEvent event; - Plugin *plugin; - - plugin_list = New(alist(10, not_owned_by_alist)); - - ctx.bContext = NULL; - ctx.pContext = NULL; - getcwd(plugin_dir, sizeof(plugin_dir)-1); - - 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 */ - pref(plugin)->newPlugin(&ctx); - event.eventType = bEventNewVolume; - pref(plugin)->handlePluginEvent(&ctx, &event); - /* Free the plugin instance */ - pref(plugin)->freePlugin(&ctx); - - /* Start a new instance of the plugin */ - pref(plugin)->newPlugin(&ctx); - event.eventType = bEventNewVolume; - 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; -} - -static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value) -{ - printf("bacula: baculaGetValue var=%d\n", var); - if (value) { - *((int *)value) = 100; - } - return 0; -} - -static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value) -{ - 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 deleted file mode 100644 index 8d5e8e93b0..0000000000 --- a/bacula/src/plugins/dir/plugin-dir.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - 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. -*/ -/* - * Sample Plugin program - * - * Kern Sibbald, October 2007 - * - */ -#include -#include "plugin-dir.h" - -#ifdef __cplusplus -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 */ -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 */ -static bFuncs *bfuncs = NULL; - -static pFuncs pluginFuncs = { - sizeof(pluginFuncs), - 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 loadPlugin(bFuncs *lbfuncs, pFuncs **pfuncs) -{ - 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 unloadPlugin() -{ - printf("plugin: Unloaded\n"); - return 0; -} - -static bpError newPlugin(bpContext *ctx) -{ - int JobId = 0; - bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: newPlugin JobId=%d\n", JobId); - return 0; -} - -static bpError freePlugin(bpContext *ctx) -{ - int JobId = 0; - bfuncs->getBaculaValue(ctx, bVarJobId, (void *)&JobId); - printf("plugin: freePlugin JobId=%d\n", JobId); - return 0; -} - -static bpError getPluginValue(bpContext *ctx, pVariable var, void *value) -{ - printf("plugin: getPluginValue var=%d\n", var); - return 0; -} - -static bpError setPluginValue(bpContext *ctx, pVariable var, void *value) -{ - printf("plugin: setPluginValue var=%d\n", var); - return 0; -} - -static bpError handlePluginEvent(bpContext *ctx, bEvent *event) -{ - printf("plugin: HandleEvent Event=%d\n", event->eventType); - return 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/bacula/src/plugins/dir/plugin-dir.h b/bacula/src/plugins/dir/plugin-dir.h deleted file mode 100644 index cc78a42cb6..0000000000 --- a/bacula/src/plugins/dir/plugin-dir.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - 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. -*/ -/* - * Interface definition for Bacula Plugins - * - * Kern Sibbald, October 2007 - * - */ - -#ifndef __PLUGIN_FD_H -#define __PLUGIN_FD_H - -#include -#ifndef __CONFIG_H -#define __CONFIG_H -#include "config.h" -#endif -#include "bc_types.h" -#include "lib/plugin.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**************************************************************************** - * * - * Bacula definitions * - * * - ****************************************************************************/ - -/* Bacula Variable Ids */ -typedef enum { - bVarJobId = 1 -} bVariable; - -typedef enum { - bEventJobStart = 1, - bEventJobInit = 2, - bEventJobRun = 3, - bEventJobEnd = 4, - bEventNewVolume = 5, - bEventVolumePurged = 6, - bEventReload = 7 -} bEventType; - -typedef struct s_bEvent { - uint32_t eventType; -} bEvent; - - -/* Bacula interface version and function pointers */ -typedef struct s_baculaFuncs { - uint32_t size; - 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; - - -/**************************************************************************** - * * - * Plugin definitions * - * * - ****************************************************************************/ - -typedef enum { - pVarName = 1, - pVarDescription = 2 -} pVariable; - - -#define PLUGIN_MAGIC "*PluginData*" -#define PLUGIN_INTERFACE 1 - -typedef struct s_pluginFuncs { - uint32_t size; - 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; - -#define pref(plugin) ((pFuncs *)(plugin->pfuncs)) - -#ifdef __cplusplus -} -#endif - -#endif /* __PLUGIN_FD_H */ diff --git a/bacula/src/plugins/fd/fd-plugins.h b/bacula/src/plugins/fd/fd-plugins.h index af575c9841..702abb4d61 100644 --- a/bacula/src/plugins/fd/fd-plugins.h +++ b/bacula/src/plugins/fd/fd-plugins.h @@ -32,8 +32,8 @@ * */ -#ifndef __PLUGIN_FD_H -#define __PLUGIN_FD_H +#ifndef __FD_PLUGINS_H +#define __FD_PLUGINS_H #include #ifndef __CONFIG_H @@ -41,7 +41,7 @@ #include "config.h" #endif #include "bc_types.h" -#include "lib/plugin.h" +#include "lib/plugins.h" #ifdef __cplusplus extern "C" { @@ -146,4 +146,4 @@ typedef struct s_pluginFuncs { } #endif -#endif /* __PLUGIN_FD_H */ +#endif /* __FD_PLUGINS_H */