]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Add plugin types in jcr.h to reduce need to cast.
authorKern Sibbald <kern@sibbald.com>
Sat, 11 Oct 2008 15:39:23 +0000 (15:39 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 11 Oct 2008 15:39:23 +0000 (15:39 +0000)
kes  Do better checking of plugin return values.
kes  Free plugin context after calling pluginFree() as
     requested by James.
kes  Allow plugin to call JobMessage with NULL context.
kes  Do not add plugin to global list if loadPlugin returns error.
kes  Rework plugin.h a bit to reduce dependence on Bacula.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@7758 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/dird/dir_plugins.c
bacula/src/filed/fd_plugins.c
bacula/src/jcr.h
bacula/src/lib/plugins.c
bacula/src/lib/plugins.h
bacula/src/plugins/fd/bpipe-fd.c
bacula/src/stored/sd_plugins.c
bacula/src/version.h
bacula/technotes-2.5

index a8006074370928f311aed8148015c0daa0718b19..3c5243656fc338c495499de7f05193cf45f30097 100644 (file)
@@ -122,9 +122,9 @@ void new_plugins(JCR *jcr)
       return;
    }
 
-   jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
+   jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num);
 
-   bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+   bpContext *plugin_ctx_list = jcr->plugin_ctx_list;
    Dmsg2(dbglvl, "Instantiate plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
    foreach_alist(plugin, plugin_list) {
       /* Start a new instance of each plugin */
index beae72f4748764c689672f6cd97eb3e910eb1c37..12679e806f7cb8cf7a7b0578fb9c15b50cd1bb01 100644 (file)
@@ -99,10 +99,20 @@ static bFuncs bfuncs = {
 struct bacula_ctx {
    JCR *jcr;                             /* jcr for plugin */
    bRC  rc;                              /* last return code */
-   bool in_plugin;                       /* in plugin code */
    bool disabled;                        /* set if plugin disabled */
 };
 
+static bool is_plugin_disabled(JCR *jcr)
+{
+   bacula_ctx *b_ctx;
+   if (!jcr->plugin_ctx) {
+      return true;
+   }
+   b_ctx = (bacula_ctx *)jcr->plugin_ctx->bContext;
+   return b_ctx->disabled;
+}
+
+
 /*
  * Create a plugin event 
  */
@@ -124,12 +134,19 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
    /* Pass event to every plugin */
    foreach_alist(plugin, plugin_list) {
       bRC rc;
-      rc = plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i++], &event, value);
+      jcr->plugin_ctx = &plugin_ctx_list[i++];
+      jcr->plugin = plugin;
+      if (is_plugin_disabled(jcr)) {
+         continue;
+      }
+      rc = plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, value);
       if (rc != bRC_OK) {
          break;
       }
    }
 
+   jcr->plugin = NULL;
+   jcr->plugin_ctx = NULL;
    return;
 }
 
@@ -177,15 +194,27 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
       goto bail_out;
    }
 
+   /* Note, we stop the loop on the first plugin that matches the name */
    foreach_alist(plugin, plugin_list) {
       Dmsg3(dbglvl, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
       if (strncmp(plugin->file, cmd, len) != 0) {
          i++;
          continue;
       }
+      /* 
+       * We put the current plugin pointer, and the plugin context
+       *  into the jcr, because during save_file(), the plugin
+       *  will be called many times and these values are needed.
+       */
+      jcr->plugin_ctx = &plugin_ctx_list[i];
+      jcr->plugin = plugin;
+      if (is_plugin_disabled(jcr)) {
+         goto bail_out;
+      }
+
       Dmsg1(dbglvl, "Command plugin = %s\n", cmd);
       /* Send the backup command to the right plugin*/
-      if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], &event, cmd) != bRC_OK) {
+      if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx, &event, cmd) != bRC_OK) {
          goto bail_out;
       }
       /* Loop getting filenames to backup then saving them */
@@ -198,7 +227,7 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          Dmsg3(dbglvl, "startBackup st_size=%p st_blocks=%p sp=%p\n", &sp.statp.st_size, &sp.statp.st_blocks,
                 &sp);
          /* Get the file save parameters */
-         if (plug_func(plugin)->startBackupFile(&plugin_ctx_list[i], &sp) != bRC_OK) {
+         if (plug_func(plugin)->startBackupFile(jcr->plugin_ctx, &sp) != bRC_OK) {
             goto bail_out;
          }
          if (sp.type == 0 || sp.fname == NULL) {
@@ -206,8 +235,6 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
                cmd);
             goto bail_out;
          }
-         jcr->plugin_ctx = &plugin_ctx_list[i];
-         jcr->plugin = plugin;
          jcr->plugin_sp = &sp;
          ff_pkt = jcr->ff;
          ff_pkt->fname = sp.fname;
@@ -216,17 +243,20 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp));
          Dmsg1(dbglvl, "Save_file: file=%s\n", ff_pkt->fname);
          save_file(jcr, ff_pkt, true);
-         bRC rc = plug_func(plugin)->endBackupFile(&plugin_ctx_list[i]);
+         bRC rc = plug_func(plugin)->endBackupFile(jcr->plugin_ctx);
          if (rc == bRC_More) {
             continue;
          }
          goto bail_out;
       }
+      goto bail_out;
    }
    Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
 
 bail_out:
    jcr->cmd_plugin = false;
+   jcr->plugin = NULL;
+   jcr->plugin_ctx = NULL;
    return 1;
 }
 
@@ -238,6 +268,11 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start)
    int stat;
    int index = jcr->JobFiles;
    struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp;
+
+   if (!sp) {
+      Jmsg0(jcr, M_FATAL, 0, _("Plugin save packet not found.\n"));
+      return false;
+   }
   
    if (start) {
       index++;                  /* JobFiles not incremented yet */
@@ -283,7 +318,7 @@ bool plugin_name_stream(JCR *jcr, char *name)
    Plugin *plugin;
    int len;
    int i = 0;
-   bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+   bpContext *plugin_ctx_list = jcr->plugin_ctx_list;
 
    Dmsg1(dbglvl, "Read plugin stream string=%s\n", name);
    skip_nonspaces(&p);             /* skip over jcr->JobFiles */
@@ -303,8 +338,7 @@ bool plugin_name_stream(JCR *jcr, char *name)
        */
       Dmsg2(dbglvl, "End plugin data plugin=%p ctx=%p\n", jcr->plugin, jcr->plugin_ctx);
       if (jcr->plugin) {
-         plugin = (Plugin *)jcr->plugin;
-         plug_func(plugin)->endRestoreFile((bpContext *)jcr->plugin_ctx);
+         plug_func(jcr->plugin)->endRestoreFile(jcr->plugin_ctx);
       }
       jcr->plugin_ctx = NULL;
       jcr->plugin = NULL;
@@ -339,17 +373,23 @@ bool plugin_name_stream(JCR *jcr, char *name)
          i++;
          continue;
       }
+      jcr->plugin_ctx = &plugin_ctx_list[i];
+      jcr->plugin = plugin;
+      if (is_plugin_disabled(jcr)) {
+         goto bail_out;
+      }
       Dmsg1(dbglvl, "Restore Command plugin = %s\n", cmd);
       event.eventType = bEventRestoreCommand;     
-      if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i]
+      if (plug_func(plugin)->handlePluginEvent(jcr->plugin_ctx
             &event, cmd) != bRC_OK) {
          goto bail_out;
       }
-      jcr->plugin_ctx = &plugin_ctx_list[i];
-      jcr->plugin = plugin;
+      /* ***FIXME**** check error code */
       plug_func(plugin)->startRestoreFile((bpContext *)jcr->plugin_ctx, cmd);
       goto bail_out;
    }
+   Jmsg1(jcr, M_WARNING, 0, _("Plugin=%s not found.\n"), cmd);
+
 bail_out:
    return start;
 }
@@ -365,13 +405,13 @@ bail_out:
  */
 int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
 {
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
-   Plugin *plugin = (Plugin *)jcr->plugin;
+   bpContext *plugin_ctx = jcr->plugin_ctx;
+   Plugin *plugin = jcr->plugin;
    struct restore_pkt rp;
    int flags;
    int rc;
 
-   if (!set_cmd_plugin(bfd, jcr)) {
+   if (!plugin || !plugin_ctx || !set_cmd_plugin(bfd, jcr)) {
       return CF_ERROR;
    }
    rp.pkt_size = sizeof(rp);
@@ -500,7 +540,7 @@ void new_plugins(JCR *jcr)
       return;
    }
 
-   jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
+   jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num);
 
    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
    Dmsg2(dbglvl, "Instantiate plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
@@ -511,7 +551,9 @@ void new_plugins(JCR *jcr)
       b_ctx->jcr = jcr;
       plugin_ctx_list[i].bContext = (void *)b_ctx;   /* Bacula private context */
       plugin_ctx_list[i].pContext = NULL;
-      plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]);
+      if (plug_func(plugin)->newPlugin(&plugin_ctx_list[i++]) != bRC_OK) {
+         b_ctx->disabled = true;
+      }
    }
 }
 
@@ -530,9 +572,9 @@ void free_plugins(JCR *jcr)
    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
    Dmsg2(dbglvl, "Free instance plugin_ctx=%p JobId=%d\n", plugin_ctx_list, jcr->JobId);
    foreach_alist(plugin, plugin_list) {   
-      free(plugin_ctx_list[i].bContext);     /* free Bacula private context */
       /* Free the plugin instance */
-      plug_func(plugin)->freePlugin(&plugin_ctx_list[i++]);
+      plug_func(plugin)->freePlugin(&plugin_ctx_list[i]);
+      free(plugin_ctx_list[i++].bContext);     /* free Bacula private context */
    }
    free(plugin_ctx_list);
    jcr->plugin_ctx_list = NULL;
@@ -542,8 +584,8 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode
 {
    JCR *jcr = bfd->jcr;
    Plugin *plugin = (Plugin *)jcr->plugin;
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    struct io_pkt io;
+
    Dmsg1(dbglvl, "plugin_bopen flags=%x\n", flags);
    io.pkt_size = sizeof(io);
    io.pkt_end = sizeof(io);
@@ -555,7 +597,7 @@ static int my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode
    io.mode = mode;
    io.win32 = false;
    io.lerror = 0;
-   plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io);
    bfd->berrno = io.io_errno;
    if (io.win32) {
       errno = b_errno_win32;
@@ -571,7 +613,6 @@ static int my_plugin_bclose(BFILE *bfd)
 {
    JCR *jcr = bfd->jcr;
    Plugin *plugin = (Plugin *)jcr->plugin;
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    struct io_pkt io;
    Dmsg0(dbglvl, "===== plugin_bclose\n");
    io.pkt_size = sizeof(io);
@@ -581,7 +622,7 @@ static int my_plugin_bclose(BFILE *bfd)
    io.buf = NULL;
    io.win32 = false;
    io.lerror = 0;
-   plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io);
    bfd->berrno = io.io_errno;
    if (io.win32) {
       errno = b_errno_win32;
@@ -597,7 +638,6 @@ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count)
 {
    JCR *jcr = bfd->jcr;
    Plugin *plugin = (Plugin *)jcr->plugin;
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    struct io_pkt io;
    Dmsg0(dbglvl, "plugin_bread\n");
    io.pkt_size = sizeof(io);
@@ -607,7 +647,7 @@ static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count)
    io.buf = (char *)buf;
    io.win32 = false;
    io.lerror = 0;
-   plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io);
    bfd->berrno = io.io_errno;
    if (io.win32) {
       errno = b_errno_win32;
@@ -622,7 +662,6 @@ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count)
 {
    JCR *jcr = bfd->jcr;
    Plugin *plugin = (Plugin *)jcr->plugin;
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    struct io_pkt io;
    Dmsg0(dbglvl, "plugin_bwrite\n");
    io.pkt_size = sizeof(io);
@@ -632,7 +671,7 @@ static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count)
    io.buf = (char *)buf;
    io.win32 = false;
    io.lerror = 0;
-   plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io);
    bfd->berrno = io.io_errno;
    if (io.win32) {
       errno = b_errno_win32;
@@ -647,7 +686,6 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence)
 {
    JCR *jcr = bfd->jcr;
    Plugin *plugin = (Plugin *)jcr->plugin;
-   bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    struct io_pkt io;
    Dmsg0(dbglvl, "plugin_bseek\n");
    io.pkt_size = sizeof(io);
@@ -657,7 +695,7 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence)
    io.whence = whence;
    io.win32 = false;
    io.lerror = 0;
-   plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   plug_func(plugin)->pluginIO(jcr->plugin_ctx, &io);
    bfd->berrno = io.io_errno;
    if (io.win32) {
       errno = b_errno_win32;
@@ -676,9 +714,14 @@ static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence)
  */
 static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
 {
-   JCR *jcr = ((bacula_ctx *)ctx->bContext)->jcr;
+   JCR *jcr;
+   jcr = ((bacula_ctx *)ctx->bContext)->jcr;
 // Dmsg1(dbglvl, "bacula: baculaGetValue var=%d\n", var);
-   if (!value) {
+   if (!value || !ctx) {
+      return bRC_Error;
+   }
+   jcr = ((bacula_ctx *)ctx->bContext)->jcr;
+   if (!jcr) {
       return bRC_Error;
    }
 // Dmsg1(dbglvl, "Bacula: jcr=%p\n", jcr); 
@@ -704,6 +747,9 @@ static bRC baculaGetValue(bpContext *ctx, bVariable var, void *value)
 
 static bRC baculaSetValue(bpContext *ctx, bVariable var, void *value)
 {
+   if (!value || !ctx) {
+      return bRC_Error;
+   }
    Dmsg1(dbglvl, "bacula: baculaSetValue var=%d\n", var);
    return bRC_OK;
 }
@@ -713,6 +759,10 @@ static bRC baculaRegisterEvents(bpContext *ctx, ...)
    va_list args;
    uint32_t event;
 
+   if (!ctx) {
+      return bRC_Error;
+   }
+
    va_start(args, ctx);
    while ((event = va_arg(args, uint32_t))) {
       Dmsg1(dbglvl, "Plugin wants event=%u\n", event);
@@ -726,7 +776,13 @@ static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
 {
    va_list arg_ptr;
    char buf[2000];
-   JCR *jcr = ((bacula_ctx *)ctx->bContext)->jcr;
+   JCR *jcr;
+
+   if (ctx) {
+      jcr = ((bacula_ctx *)ctx->bContext)->jcr;
+   } else {
+      jcr = NULL;
+   }
 
    va_start(arg_ptr, fmt);
    bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
index 9e04c570a379894602e6977cf15fa4e3ff127bb3..e100a26a6ad89f88ebd0627ab92aaa2f92050ce4 100644 (file)
@@ -142,6 +142,7 @@ struct B_DB;
 struct ATTR_DBR;
 struct Plugin;
 struct save_pkt;
+struct bpContext;
 
 #ifdef FILE_DAEMON
 class htable;
@@ -242,8 +243,8 @@ public:
    guid_list *id_list;                /* User/group id to name list */
    bool accurate;                     /* true if job is accurate */
 
-   void *plugin_ctx_list;             /* list of contexts for plugins */
-   void *plugin_ctx;                  /* current plugin context */
+   bpContext *plugin_ctx_list;        /* list of contexts for plugins */
+   bpContext *plugin_ctx;             /* current plugin context */
    Plugin *plugin;                    /* plugin instance */
    save_pkt *plugin_sp;               /* plugin save packet */
    char *plugin_options;              /* user set options for plugin */
index 2a135dd470b289d50f3669315ddb7e2894743122..6cc5e43286b855fcba3468485f7c891efce698d1 100644 (file)
  *
  * Kern Sibbald, October 2007
  */
+
 #include "bacula.h"
+#include <dlfcn.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMELEN(dirent) (strlen((dirent)->d_name))
+#endif
+#ifndef HAVE_READDIR_R
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+#endif
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 2
+#endif
+
 #include "plugins.h"
 
 static const int dbglvl = 50;
@@ -49,7 +63,6 @@ Plugin *new_plugin()
 
    plugin = (Plugin *)malloc(sizeof(Plugin));
    memset(plugin, 0, sizeof(Plugin));
-   plugin_list->append(plugin);
    return plugin;
 }
 
@@ -61,7 +74,7 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, const char
 {
    bool found = false;
    t_loadPlugin loadPlugin;
-   Plugin *plugin;
+   Plugin *plugin = NULL;
    DIR* dp = NULL;
    struct dirent *entry = NULL, *result;
    int name_max;
@@ -151,12 +164,18 @@ bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir, const char
       }
 
       /* Initialize the plugin */
-      loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs);
+      if (loadPlugin(binfo, bfuncs, &plugin->pinfo, &plugin->pfuncs) != bRC_OK) {
+         goto get_out;
+      }
 
       found = true;                /* found a plugin */
+      plugin_list->append(plugin);
    }
 
 get_out:
+   if (!found && plugin) {
+      free(plugin);
+   }
    if (entry) {
       free(entry);
    }
index 787b2ca226833d84414e49e367ac5beab85d5d58..456b5fc6994cf92f0e13fe9c70493ac49a2620ff 100644 (file)
    Switzerland, email:ftf@fsfeurope.org.
 */
 /*
- * Bacula plugin loader/unloader
+ * Common plugin definitions
  *
  * Kern Sibbald, October 2007
  */
 #ifndef __PLUGINS_H
 #define __PLUGINS_H
 
-#include "bacula.h"
-#include <dlfcn.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#define NAMELEN(dirent) (strlen((dirent)->d_name))
-#endif
-#ifndef HAVE_READDIR_R
-int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
-#endif
-
-#ifndef RTLD_NOW
-#define RTLD_NOW 2
-#endif
-
 /****************************************************************************
  *                                                                          *
  *                Common definitions for all plugins                        *
@@ -64,11 +50,12 @@ typedef enum {
   bRC_Term   = 4                         /* Unload me */
 } bRC;
 
+
 /* Context packet as first argument of all functions */
-typedef struct s_bpContext {
+struct bpContext {
   void *bContext;                        /* Bacula private context */
   void *pContext;                        /* Plugin private context */
-} bpContext;
+};
 
 extern "C" {
 typedef bRC (*t_loadPlugin)(void *binfo, void *bfuncs, void **pinfo, void **pfuncs);
@@ -82,6 +69,7 @@ public:
    void *pinfo;
    void *pfuncs;
    void *pHandle;
+   bool disabled;
 };
 
 /* Functions */
index 6058655c675904e301d7f51d77cf34bd3c0a457f..a22811186b25563488c312ffd229a640248581cf 100644 (file)
@@ -31,6 +31,7 @@
  *  Kern Sibbald, October 2007
  *
  */
+#include "bacula.h"
 #include "fd_plugins.h"
 
 #undef malloc
index d289c986d894a4db003facff97bb67dff6f1584f..6c0d6dc571935ff2df04418b5f7c087259112923 100644 (file)
@@ -123,9 +123,9 @@ void new_plugins(JCR *jcr)
       return;
    }
 
-   jcr->plugin_ctx_list = (void *)malloc(sizeof(bpContext) * num);
+   jcr->plugin_ctx_list = (bpContext *)malloc(sizeof(bpContext) * num);
 
-   bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+   bpContext *plugin_ctx_list = jcr->plugin_ctx_list;
    Dmsg2(dbglvl, "Instantiate plugin_ctx_list=%p JobId=%d\n", jcr->plugin_ctx_list, jcr->JobId);
    foreach_alist(plugin, plugin_list) {
       /* Start a new instance of each plugin */
index f1bad0be54811f22c4fa37837fc719917e38fa70..4b5c919a98a4683935bfef76e81dd4abc4da0054 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "2.5.13"
-#define BDATE   "10 October 2008"
-#define LSMDATE "10Oct08"
+#define VERSION "2.5.14"
+#define BDATE   "11 October 2008"
+#define LSMDATE "11Oct08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index 8bd5a9e4d8cbafd0eb6eb9ed3ae3fe34e8f189e2..0b20c4c53887be36a2e5ab5d91424802643c779c 100644 (file)
@@ -17,6 +17,14 @@ dbdriver
 remove reader/writer in FOPTS????
 
 General:
+11Oct08
+kes  Add plugin types in jcr.h to reduce need to cast.
+kes  Do better checking of plugin return values.
+kes  Free plugin context after calling pluginFree() as
+     requested by James.
+kes  Allow plugin to call JobMessage with NULL context.
+kes  Do not add plugin to global list if loadPlugin returns error.
+kes  Rework plugin.h a bit to reduce dependence on Bacula.
 10Oct08
 kes  Move generation of bsr file for Virtual Backup to run section
      so that it is generated just before actually running.