]> git.sur5r.net Git - bacula/bacula/commitdiff
Commit 0th cut of plugins
authorKern Sibbald <kern@sibbald.com>
Wed, 14 Nov 2007 14:11:55 +0000 (14:11 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 14 Nov 2007 14:11:55 +0000 (14:11 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5929 91ce42f0-d328-0410-95d8-f526ca767f89

14 files changed:
bacula/src/plugins/Makefile [new file with mode: 0644]
bacula/src/plugins/README [new file with mode: 0644]
bacula/src/plugins/dir/Makefile [new file with mode: 0644]
bacula/src/plugins/dir/main.c [new file with mode: 0644]
bacula/src/plugins/dir/plugin-dir.c [new file with mode: 0644]
bacula/src/plugins/dir/plugin-dir.h [new file with mode: 0644]
bacula/src/plugins/fd/Makefile [new file with mode: 0644]
bacula/src/plugins/fd/main.c [new file with mode: 0644]
bacula/src/plugins/fd/plugin-fd.c [new file with mode: 0644]
bacula/src/plugins/fd/plugin-fd.h [new file with mode: 0644]
bacula/src/plugins/sd/Makefile [new file with mode: 0644]
bacula/src/plugins/sd/main.c [new file with mode: 0644]
bacula/src/plugins/sd/plugin-sd.c [new file with mode: 0644]
bacula/src/plugins/sd/plugin-sd.h [new file with mode: 0644]

diff --git a/bacula/src/plugins/Makefile b/bacula/src/plugins/Makefile
new file mode 100644 (file)
index 0000000..cd007a2
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# 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)
+       
diff --git a/bacula/src/plugins/README b/bacula/src/plugins/README
new file mode 100644 (file)
index 0000000..559a1f1
--- /dev/null
@@ -0,0 +1,37 @@
+
+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.
diff --git a/bacula/src/plugins/dir/Makefile b/bacula/src/plugins/dir/Makefile
new file mode 100644 (file)
index 0000000..4988aed
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# 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
diff --git a/bacula/src/plugins/dir/main.c b/bacula/src/plugins/dir/main.c
new file mode 100644 (file)
index 0000000..a9b3ec3
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+   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;
+}
diff --git a/bacula/src/plugins/dir/plugin-dir.c b/bacula/src/plugins/dir/plugin-dir.c
new file mode 100644 (file)
index 0000000..4e032d7
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   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
diff --git a/bacula/src/plugins/dir/plugin-dir.h b/bacula/src/plugins/dir/plugin-dir.h
new file mode 100644 (file)
index 0000000..9fd2d53
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+   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 */
diff --git a/bacula/src/plugins/fd/Makefile b/bacula/src/plugins/fd/Makefile
new file mode 100644 (file)
index 0000000..fee6491
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# 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
diff --git a/bacula/src/plugins/fd/main.c b/bacula/src/plugins/fd/main.c
new file mode 100644 (file)
index 0000000..e15f8de
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+   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;
+}
diff --git a/bacula/src/plugins/fd/plugin-fd.c b/bacula/src/plugins/fd/plugin-fd.c
new file mode 100644 (file)
index 0000000..fb66ec9
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   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
diff --git a/bacula/src/plugins/fd/plugin-fd.h b/bacula/src/plugins/fd/plugin-fd.h
new file mode 100644 (file)
index 0000000..9fd2d53
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+   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 */
diff --git a/bacula/src/plugins/sd/Makefile b/bacula/src/plugins/sd/Makefile
new file mode 100644 (file)
index 0000000..dfb9346
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# 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
diff --git a/bacula/src/plugins/sd/main.c b/bacula/src/plugins/sd/main.c
new file mode 100644 (file)
index 0000000..7c66137
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+   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;
+}
diff --git a/bacula/src/plugins/sd/plugin-sd.c b/bacula/src/plugins/sd/plugin-sd.c
new file mode 100644 (file)
index 0000000..bce4eda
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   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
diff --git a/bacula/src/plugins/sd/plugin-sd.h b/bacula/src/plugins/sd/plugin-sd.h
new file mode 100644 (file)
index 0000000..9fd2d53
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+   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 */