--- /dev/null
+#
+# Simple Makefile for building test plugins for Bacula
+#
+
+first_rule: all
+dummy:
+
+all: dir fd sd
+
+dir: dummy
+ (cd dir && make DESTDIR=$(DESTDIR) || exit 1)
+ @echo
+
+fd: dummy
+ (cd fd && make DESTDIR=$(DESTDIR) || exit 1)
+ @echo
+
+sd: dummy
+ (cd sd && make DESTDIR=$(DESTDIR) || exit 1)
+ @echo
+
+
+clean:
+ (cd dir && make DESTDIR=$(DESTDIR) clean || exit 1)
+ (cd fd && make DESTDIR=$(DESTDIR) clean || exit 1)
+ (cd sd && make DESTDIR=$(DESTDIR) clean || exit 1)
+
--- /dev/null
+
+This is a first cut of a plugins implementation for Bacula.
+The current code is simply a test program named main, which
+when executed will load the plugin named plugin.so and then
+call it with a few calls, then exit.
+
+What is implemented:
+- load a plugin
+- get main entry points in plugin (two)
+- pass plugin Bacula entry points
+- get plugin's entry points
+- keep list of plugins that are loaded
+- The plugin currently only needs config.h and bc_types.h
+ in the Bacula src directory to be build. Otherwise, it is
+ totally independent of Bacula.
+- The main test program is intended to be integrated into
+ Bacula (at least a number of the functions therein).
+
+What is not yet implemented:
+- Search for all plugins in the plugin directory
+- Implement Bacula context for plugin instances
+- Implement plugin context for plugin instances
+- Some better method to pass variables
+- Pass Version information in plugin Initialize
+- Define more functionality (Bacula entry points, ...)
+- Integrate the code into Bacula
+- Make libbac.a into a shared object and allow plugin
+ to call functions in directly so that plugins can use
+ the same "safe" system utilities that Bacula uses.
+- Document the interface
+- Document libbac.so (when implemented)
+- Write a couple of plugins that really do something.
+- Figure out a way to deal with 3 types of plugins (Director,
+ File daemon, Storage daemon).
+- Error handling must be much improved and brought into Bacula
+ programming style. It currently just printf()s a message then
+ exits.
--- /dev/null
+#
+# Simple Makefile for building test plugins for Bacula
+#
+
+# No optimization for now for easy debugging
+CC = g++ -g -O0 -Wall
+
+.SUFFIXES: .c .o
+.c.o:
+ $(CC) -I../.. -DTEST_PROGRAM -c $<
+
+all: main plugin-dir.so
+
+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
+ $(CC) -shared plugin-dir.o -o plugin-dir.so
+
+clean:
+ rm -f main *.so *.o
--- /dev/null
+/*
+ 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 <dlfcn.h>
+#include "plugin-dir.h"
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 2
+#endif
+
+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);
+
+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(plugin_dir);
+
+ foreach_alist(plugin, plugin_list) {
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+ }
+
+ unload_plugins();
+
+ printf("bacula: OK ...\n");
+ 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);
+ if (value) {
+ *((int *)value) = 100;
+ }
+ return 0;
+}
+
+static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value)
+{
+ printf("baculaSetValue var=%d\n", var);
+ return 0;
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include "plugin-dir.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+
+/* Pointers to Bacula functions */
+bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value);
+bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value);
+
+pFuncs pluginFuncs = {
+ sizeof(pluginFuncs),
+ 1,
+ pNew,
+ pDestroy,
+ pGetValue,
+ pSetValue,
+ pHandleEvent
+};
+
+bpError bpInitialize(bFuncs *bfuncs, 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;
+
+ return 0;
+}
+
+bpError bpShutdown()
+{
+ printf("plugin: Shutting down\n");
+ return 0;
+}
+
+bpError pNew(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: New JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pDestroy(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: Destroy JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pGetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: GetValue var=%d\n", var);
+ return 0;
+}
+
+bpError pSetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: PutValue var=%d\n", var);
+ return 0;
+}
+
+bpError pHandleEvent(bpContext *ctx, bEvent *event)
+{
+ printf("plugin: HandleEvent Event=%d\n", event->eventType);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*
+ 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_H
+#define __PLUGIN_H
+
+#include <sys/types.h>
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include "config.h"
+#endif
+#include "bc_types.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 *
+ * *
+ ****************************************************************************/
+
+/* 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 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);
+} bFuncs;
+
+
+/****************************************************************************
+ * *
+ * Plugin definitions *
+ * *
+ ****************************************************************************/
+
+typedef enum {
+ pVarName = 1,
+ pVarDescription = 2
+} pVariable;
+
+
+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);
+} pFuncs;
+
+typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs);
+typedef bpError (*t_bpShutdown)(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PLUGIN_H */
--- /dev/null
+#
+# Simple Makefile for building test plugin-fds for Bacula
+#
+
+# No optimization for now for easy debugging
+CC = g++ -g -O0 -Wall
+
+.SUFFIXES: .c .o
+.c.o:
+ $(CC) -I../.. -DTEST_PROGRAM -c $<
+
+all: main plugin-fd.so
+
+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
+ $(CC) -shared plugin-fd.o -o plugin-fd.so
+
+clean:
+ rm -f main *.so *.o
--- /dev/null
+/*
+ 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 <dlfcn.h>
+#include "plugin-fd.h"
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 2
+#endif
+
+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);
+
+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(plugin_dir);
+
+ foreach_alist(plugin, plugin_list) {
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+ }
+
+ unload_plugins();
+
+ printf("bacula: OK ...\n");
+ 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);
+ if (value) {
+ *((int *)value) = 100;
+ }
+ return 0;
+}
+
+static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value)
+{
+ printf("baculaSetValue var=%d\n", var);
+ return 0;
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include "plugin-fd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+
+/* Pointers to Bacula functions */
+bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value);
+bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value);
+
+pFuncs pluginFuncs = {
+ sizeof(pluginFuncs),
+ 1,
+ pNew,
+ pDestroy,
+ pGetValue,
+ pSetValue,
+ pHandleEvent
+};
+
+bpError bpInitialize(bFuncs *bfuncs, 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;
+
+ return 0;
+}
+
+bpError bpShutdown()
+{
+ printf("plugin: Shutting down\n");
+ return 0;
+}
+
+bpError pNew(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: New JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pDestroy(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: Destroy JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pGetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: GetValue var=%d\n", var);
+ return 0;
+}
+
+bpError pSetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: PutValue var=%d\n", var);
+ return 0;
+}
+
+bpError pHandleEvent(bpContext *ctx, bEvent *event)
+{
+ printf("plugin: HandleEvent Event=%d\n", event->eventType);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*
+ 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_H
+#define __PLUGIN_H
+
+#include <sys/types.h>
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include "config.h"
+#endif
+#include "bc_types.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 *
+ * *
+ ****************************************************************************/
+
+/* 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 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);
+} bFuncs;
+
+
+/****************************************************************************
+ * *
+ * Plugin definitions *
+ * *
+ ****************************************************************************/
+
+typedef enum {
+ pVarName = 1,
+ pVarDescription = 2
+} pVariable;
+
+
+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);
+} pFuncs;
+
+typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs);
+typedef bpError (*t_bpShutdown)(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PLUGIN_H */
--- /dev/null
+#
+# Simple Makefile for building test plugin-sds for Bacula
+#
+
+# No optimization for now for easy debugging
+CC = g++ -g -O0 -Wall
+
+.SUFFIXES: .c .o
+.c.o:
+ $(CC) -I../.. -DTEST_PROGRAM -c $<
+
+all: main plugin-sd.so
+
+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
+ $(CC) -shared plugin-sd.o -o plugin-sd.so
+
+clean:
+ rm -f main *.so *.o
--- /dev/null
+/*
+ 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 <dlfcn.h>
+#include "plugin-sd.h"
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 2
+#endif
+
+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);
+
+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(plugin_dir);
+
+ foreach_alist(plugin, plugin_list) {
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+
+ /* Start a new instance of the plugin */
+ plugin->pfuncs.pNew(&ctx);
+ event.eventType = bEventNewVolume;
+ plugin->pfuncs.pHandleEvent(&ctx, &event);
+ /* Destroy the instance */
+ plugin->pfuncs.pDestroy(&ctx);
+ }
+
+ unload_plugins();
+
+ printf("bacula: OK ...\n");
+ 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);
+ if (value) {
+ *((int *)value) = 100;
+ }
+ return 0;
+}
+
+static bpError baculaSetValue(bpContext *ctx, bVariable var, void *value)
+{
+ printf("baculaSetValue var=%d\n", var);
+ return 0;
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include "plugin-sd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+
+/* Pointers to Bacula functions */
+bpError (*p_bGetValue)(bpContext *ctx, bVariable var, void *value);
+bpError (*p_bSetValue)(bpContext *ctx, bVariable var, void *value);
+
+pFuncs pluginFuncs = {
+ sizeof(pluginFuncs),
+ 1,
+ pNew,
+ pDestroy,
+ pGetValue,
+ pSetValue,
+ pHandleEvent
+};
+
+bpError bpInitialize(bFuncs *bfuncs, 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;
+
+ return 0;
+}
+
+bpError bpShutdown()
+{
+ printf("plugin: Shutting down\n");
+ return 0;
+}
+
+bpError pNew(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: New JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pDestroy(bpContext *ctx)
+{
+ int JobId = 0;
+ p_bGetValue(ctx, bVarJobId, (void *)&JobId);
+ printf("plugin: Destroy JobId=%d\n", JobId);
+ return 0;
+}
+
+bpError pGetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: GetValue var=%d\n", var);
+ return 0;
+}
+
+bpError pSetValue(bpContext *ctx, pVariable var, void *value)
+{
+ printf("plugin: PutValue var=%d\n", var);
+ return 0;
+}
+
+bpError pHandleEvent(bpContext *ctx, bEvent *event)
+{
+ printf("plugin: HandleEvent Event=%d\n", event->eventType);
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/*
+ 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_H
+#define __PLUGIN_H
+
+#include <sys/types.h>
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include "config.h"
+#endif
+#include "bc_types.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 *
+ * *
+ ****************************************************************************/
+
+/* 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 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);
+} bFuncs;
+
+
+/****************************************************************************
+ * *
+ * Plugin definitions *
+ * *
+ ****************************************************************************/
+
+typedef enum {
+ pVarName = 1,
+ pVarDescription = 2
+} pVariable;
+
+
+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);
+} pFuncs;
+
+typedef bpError (*t_bpInitialize)(bFuncs *bfuncs, pFuncs *pfuncs);
+typedef bpError (*t_bpShutdown)(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PLUGIN_H */