]> git.sur5r.net Git - bacula/bacula/commitdiff
More plugin implementation
authorKern Sibbald <kern@sibbald.com>
Mon, 4 Feb 2008 22:12:14 +0000 (22:12 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 4 Feb 2008 22:12:14 +0000 (22:12 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6368 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/filed/backup.c
bacula/src/filed/fd-plugins.c
bacula/src/filed/fd-plugins.h
bacula/src/filed/job.c
bacula/src/findlib/bfile.c
bacula/src/findlib/bfile.h
bacula/src/findlib/find.c
bacula/src/findlib/find.h
bacula/src/plugins/fd/example-plugin-fd.c
bacula/src/tools/testfind.c
bacula/technotes-2.3

index 3620355675898ba686529e076fafc74cd7d8c818..5660fb824458c8a6fc69f8aeef9958834fd6e85f 100644 (file)
@@ -439,10 +439,8 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
    if (ff_pkt->flags & FO_PORTABLE) {
       set_portable_backup(&ff_pkt->bfd); /* disable Win32 BackupRead() */
    }
-   if (ff_pkt->reader) {
-      if (!set_prog(&ff_pkt->bfd, ff_pkt->reader, jcr)) {
-         Jmsg(jcr, M_FATAL, 0, _("Python reader program \"%s\" not found.\n"), 
-            ff_pkt->reader);
+   if (ff_pkt->cmd_plugin) {
+      if (!set_cmd_plugin(&ff_pkt->bfd, jcr)) {
          goto bail_out;
       }
    }
index c503da898d5435d2234c3e084b5735dedd23ee10..72b4151573c3794d4e49d30bc521faab390ae911 100644 (file)
 const int dbglvl = 50;
 const char *plugin_type = "-fd.so";
 
+/* External functions */
+extern int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
+extern int     (*plugin_bclose)(JCR *jcr);
+extern ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
+extern ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
+
 
 /* Forward referenced functions */
 static bpError baculaGetValue(bpContext *ctx, bVariable var, void *value);
@@ -48,6 +54,11 @@ static bpError baculaJobMsg(bpContext *ctx, const char *file, int line,
 static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line,
   int level, const char *msg);
 
+static int     my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode);
+static int     my_plugin_bclose(JCR *jcr);
+static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count);
+static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count);
+
 
 /* Bacula info */
 static bInfo binfo = {
@@ -66,6 +77,7 @@ static bFuncs bfuncs = {
    baculaDebugMsg
 };
 
+
 /*
  * Create a plugin event 
  */
@@ -74,17 +86,44 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
    bEvent event;
    Plugin *plugin;
    int i = 0;
+   int len;
+   char *p;
+   char *cmd = (char *)value;
 
    if (!plugin_list) {
       return;
    }
 
    bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
-   Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
    event.eventType = eventType;
-   foreach_alist(plugin, plugin_list) {
-      plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event, value);
+
+   Dmsg2(dbglvl, "plugin_ctx=%p JobId=%d\n", jcr->plugin_ctx, jcr->JobId);
+   if (eventType != bEventPluginCommand) {
+      /* Pass event to every plugin */
+      foreach_alist(plugin, plugin_list) {
+         plug_func(plugin)->handlePluginEvent(&plugin_ctx[i++], &event, value);
+      }
+      return;
    }
+
+   /* Handle plugin command here (backup/restore of file) */
+   if (!(p = strchr(cmd, ':'))) {
+      Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
+      return;
+   }
+   len = p - cmd;
+   if (len > 0) {
+      foreach_alist(plugin, plugin_list) {
+         Dmsg3(000, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+         if (strncmp(plugin->file, cmd, len) == 0) {
+            Dmsg1(000, "Command plugin = %s\n", cmd);
+            plug_func(plugin)->handlePluginEvent(&plugin_ctx[i], &event, value);
+            return;
+         }
+         i++;
+      }
+   }
+      
 }
 
 void load_fd_plugins(const char *plugin_dir)
@@ -95,6 +134,11 @@ void load_fd_plugins(const char *plugin_dir)
 
    plugin_list = New(alist(10, not_owned_by_alist));
    load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
+   plugin_bopen     = my_plugin_bopen;
+   plugin_bclose    = my_plugin_bclose;
+   plugin_bread     = my_plugin_bread;
+   plugin_bwrite    = my_plugin_bwrite;
+
 }
 
 /*
@@ -149,6 +193,46 @@ void free_plugins(JCR *jcr)
    jcr->plugin_ctx = NULL;
 }
 
+static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
+{
+   struct io_pkt io;
+   Dmsg0(000, "plugin_bopen\n");
+   io.func = IO_OPEN;
+   io.count = 0;
+   io.buf = NULL;
+
+   return 0;
+}
+
+static int my_plugin_bclose(JCR *jcr)
+{
+   struct io_pkt io;
+   Dmsg0(000, "plugin_bclose\n");
+   io.func = IO_CLOSE;
+   io.count = 0;
+   io.buf = NULL;
+   return 0;
+}
+
+static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
+{
+   struct io_pkt io;
+   Dmsg0(000, "plugin_bread\n");
+   io.func = IO_READ;
+   io.count = count;
+   io.buf = (char *)buf;
+   return 0;
+}
+
+static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
+{
+   struct io_pkt io;
+   Dmsg0(000, "plugin_bwrite\n");
+   io.func = IO_WRITE;
+   io.count = count;
+   io.buf = (char *)buf;
+   return 0;
+}
 
 /* ==============================================================
  *
@@ -221,6 +305,12 @@ static bpError baculaDebugMsg(bpContext *ctx, const char *file, int line,
 
 #ifdef TEST_PROGRAM
 
+int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
+int     (*plugin_bclose)(JCR *jcr) = NULL;
+ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
+ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
+
+
 int main(int argc, char *argv[])
 {
    char plugin_dir[1000];
index dc608f557c4218ab0a7d5aad9f7fdff4f1137d52..513739603d699471023836c7672c5b7cd93ea31a 100644 (file)
 #endif
 #include "bc_types.h"
 #include "lib/plugins.h"
+#include <sys/stat.h>
 
+/*
+ * This packet is used for file save/restore info transfer */
+struct save_pkt {
+  char *fname;                        /* Full path and filename */
+  char *link;                         /* Link name if any */
+  struct stat statp;                  /* System stat() packet for file */
+  int type;                           /* FT_xx for this file */             
+  uint32_t flags;                     /* Bacula internal flags */
+  bool portable;                      /* set if data format is portable */
+};
+
+#define IO_OPEN  1
+#define IO_READ  2
+#define IO_WRITE 3
+#define IO_CLOSE 4
+
+struct io_pkt {
+   int func;                          /* Function code */
+   int count;                         /* read/write count */
+   char *buf;                         /* read/write buffer */
+};
 
 /****************************************************************************
  *                                                                          *
@@ -146,6 +168,8 @@ typedef struct s_pluginFuncs {
    bpError (*getPluginValue)(bpContext *ctx, pVariable var, void *value);
    bpError (*setPluginValue)(bpContext *ctx, pVariable var, void *value);
    bpError (*handlePluginEvent)(bpContext *ctx, bEvent *event, void *value);
+   bpError (*startPluginBackup)(bpContext *ctx, struct save_pkt *sp);
+   bpError (*pluginIO)(bpContext *ctx, struct io_pkt *io);
 } pFuncs;
 
 #define plug_func(plugin) ((pFuncs *)(plugin->pfuncs))
index 6965a863a7edbcef93aa8b2e7e31110e5f9ebb30..5673a633cc1f2b3b8983b4b9c4a7cbb0a32d18b6 100644 (file)
@@ -313,12 +313,6 @@ void *handle_client_request(void *dirp)
             fo->base.destroy();
             fo->fstype.destroy();
             fo->drivetype.destroy();
-            if (fo->reader) {
-               free(fo->reader);
-            }
-            if (fo->writer) {
-               free(fo->writer);
-            }
          }
          incexe->opts_list.destroy();
          incexe->name_list.destroy();
@@ -846,12 +840,12 @@ static void add_fileset(JCR *jcr, const char *item)
       break;
    case 'D':
       current_opts = start_options(ff);
-      current_opts->reader = bstrdup(item);
+//    current_opts->reader = bstrdup(item);
       state = state_options;
       break;
    case 'T':
       current_opts = start_options(ff);
-      current_opts->writer = bstrdup(item);
+//    current_opts->writer = bstrdup(item);
       state = state_options;
       break;
    default:
@@ -905,12 +899,6 @@ static bool term_fileset(JCR *jcr)
          for (k=0; k<fo->drivetype.size(); k++) {
             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
          }
-         if (fo->reader) {
-            Dmsg1(400, "D %s\n", fo->reader);
-         }
-         if (fo->writer) {
-            Dmsg1(400, "T %s\n", fo->writer);
-         }
       }
       dlistString *node;
       foreach_dlist(node, &incexe->name_list) {
index 4597d42c940ebfd3f442b170b21993d05c1ec7ca..8ee2ff7cd5f105197d9076762690969db39045c2 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2003-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -45,6 +45,12 @@ int     (*python_close)(BFILE *bfd) = NULL;
 ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL;
 ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL;
 
+int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode) = NULL;
+int     (*plugin_bclose)(JCR *jcr) = NULL;
+ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count) = NULL;
+ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count) = NULL;
+
+
 #ifdef HAVE_DARWIN_OS
 #include <sys/paths.h>
 #endif
@@ -287,6 +293,7 @@ void binit(BFILE *bfd)
    bfd->fid = -1;
    bfd->mode = BF_CLOSED;
    bfd->use_backup_api = have_win32_api();
+   bfd->cmd_plugin = false;
 }
 
 /*
@@ -310,11 +317,16 @@ bool set_portable_backup(BFILE *bfd)
 
 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
 {
-   bfd->prog = prog;
-   bfd->jcr = jcr;
    return false;
 }
 
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
+{
+   bfd->cmd_plugin = true;
+   bfd->jcr = jcr;
+   return true;
+}
+
 /*
  * Return 1 if we are NOT using Win32 BackupWrite()
  * return 0 if are
@@ -567,6 +579,7 @@ int bclose(BFILE *bfd)
    }
    bfd->mode = BF_CLOSED;
    bfd->lpContext = NULL;
+   bfd->cmd_plugin = false;
    return stat;
 }
 
@@ -705,22 +718,14 @@ bool is_portable_backup(BFILE *bfd)
 
 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
 {
-#ifdef HAVE_PYTHON
-   if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
-      return true;                    /* already setup */
-   }
-
-   if (python_set_prog(jcr, prog)) {
-      Dmsg1(000, "Set prog=%s\n", prog);
-      bfd->prog = prog;
-      bfd->jcr = jcr;
-      return true;
-   }
-#endif
-   Dmsg0(000, "No prog set\n");
-   bfd->prog = NULL;
    return false;
+}
 
+bool set_cmd_plugin(BFILE *bfd, JCR *jcr)
+{
+   bfd->cmd_plugin = true;
+   bfd->jcr = jcr;
+   return true;
 }
 
 /* 
@@ -783,10 +788,8 @@ bool is_restore_stream_supported(int stream)
 
 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
 {
-   /* Open reader/writer program */
-   if (bfd->prog) {
-      Dmsg1(000, "Open file %d\n", bfd->fid);
-      return python_open(bfd, fname, flags, mode);
+   if (bfd->cmd_plugin && plugin_bopen) {
+      return plugin_bopen(bfd->jcr, fname, flags, mode);
    }
 
    /* Normal file open */
@@ -850,9 +853,8 @@ int bclose(BFILE *bfd)
 
    Dmsg1(400, "Close file %d\n", bfd->fid);
 
-   /* Close reader/writer program */
-   if (bfd->prog) {
-      return python_close(bfd);
+   if (bfd->cmd_plugin && plugin_bclose) {
+      return plugin_bclose(bfd->jcr);
    }
 
    if (bfd->fid == -1) {
@@ -870,6 +872,7 @@ int bclose(BFILE *bfd)
    stat = close(bfd->fid);
    bfd->berrno = errno;
    bfd->fid = -1;
+   bfd->cmd_plugin = false;
    return stat;
 }
 
@@ -877,9 +880,10 @@ ssize_t bread(BFILE *bfd, void *buf, size_t count)
 {
    ssize_t stat;
 
-   if (bfd->prog) {
-      return python_read(bfd, buf, count);
+   if (bfd->cmd_plugin && plugin_bread) {
+      return plugin_bread(bfd->jcr, buf, count);
    }
+
    stat = read(bfd->fid, buf, count);
    bfd->berrno = errno;
    return stat;
@@ -889,8 +893,8 @@ ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
 {
    ssize_t stat;
 
-   if (bfd->prog) {
-      return python_write(bfd, buf, count);
+   if (bfd->cmd_plugin && plugin_bwrite) {
+      return plugin_bwrite(bfd->jcr, buf, count);
    }
    stat = write(bfd->fid, buf, count);
    bfd->berrno = errno;
index ed3f6c6d2866a3d0b764df8508f08fbc452c8aef..7d267753900f006a6196c34cfddcfbb55d398f51 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2003-2008 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -98,12 +98,12 @@ struct BFILE {
    DWORD rw_bytes;                    /* Bytes read or written */
    DWORD lerror;                      /* Last error code */
    int berrno;                        /* errno */
-   char *prog;                        /* reader/writer program if any */
    JCR *jcr;                          /* jcr for editing job codes */
    Python_IO pio;                     /* Python I/O routines */
    PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
    int use_backup_decomp;             /* set if using BackupRead Stream Decomposition */
    bool reparse_point;                /* set if reparse point */ 
+   bool cmd_plugin;                   /* set if we have a command plugin */
 };
 
 HANDLE bget_handle(BFILE *bfd);
@@ -122,12 +122,12 @@ struct BFILE {
    int fid;                           /* file id on Unix */
    int m_flags;                       /* open flags */
    int berrno;
-   char *prog;                        /* reader/writer program if any */
    JCR *jcr;                          /* jcr for editing job codes */
    Python_IO pio;                     /* Python I/O routines */
    PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */
    int use_backup_decomp;             /* set if using BackupRead Stream Decomposition */
    bool reparse_point;                /* not used in Unix */
+   bool cmd_plugin;                   /* set if we have a command plugin */
 };
 
 #endif
@@ -136,7 +136,7 @@ void    binit(BFILE *bfd);
 bool    is_bopen(BFILE *bfd);
 bool    set_win32_backup(BFILE *bfd);
 bool    set_portable_backup(BFILE *bfd);
-bool    set_prog(BFILE *bfd, char *prog, JCR *jcr);
+bool    set_cmd_plugin(BFILE *bfd, JCR *jcr);
 bool    have_win32_api();
 bool    is_portable_backup(BFILE *bfd);
 bool    is_restore_stream_supported(int stream);
index e9e1d94f25ba0bca0e8e048b4b248cd99b7ece15..e2f1c0cd75f2a0b40d669a974e79b51e41a7e388 100644 (file)
@@ -148,11 +148,6 @@ get_win32_driveletters(FF_PKT *ff, char* szDrives)
 }
 
 /*
- * Find all specified files (determined by calls to name_add()
- * This routine calls the (handle_file) subroutine with all
- * sorts of good information for the final disposition of
- * the file.
- *
  * Call this subroutine with a callback subroutine as the first
  * argument and a packet as the second argument, this packet
  * will be passed back to the callback subroutine as the last
@@ -205,7 +200,9 @@ find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool t
             char *fname = node->c_str();
             Dmsg1(100, "P %s\n", fname);
             ff->top_fname = fname;
+            ff->cmd_plugin = true;
             generate_plugin_event(jcr, bEventPluginCommand, (void *)fname);
+            ff->cmd_plugin = false;
          }
       }
    }
@@ -237,8 +234,6 @@ static bool accept_file(FF_PKT *ff)
       findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
       ff->flags = fo->flags;
       ff->GZIP_level = fo->GZIP_level;
-      ff->reader = fo->reader;
-      ff->writer = fo->writer;
       ff->fstypes = fo->fstype;
       ff->drivetypes = fo->drivetype;
 
@@ -398,7 +393,6 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level)
    case FT_SPEC:
    case FT_DIRNOCHG:
       if (accept_file(ff)) {
-//       Dmsg2(000, "Accept file %s; reader=%s\n", ff->fname, NPRT(ff->reader));
          return ff->callback(ff, hpkt, top_level);
       } else {
          Dmsg1(100, "Skip file %s\n", ff->fname);
index 9860ff5369c01d10fec2e47ee6c5c8ddb7bf11d9..8bedc7a687699c21cb64a12179fff7cb36fd886a 100644 (file)
@@ -68,7 +68,6 @@ struct utimbuf {
 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
 #endif
 
-
 /*
  * Status codes returned by create_file()
  */
@@ -80,7 +79,8 @@ enum {
 };
 
 
-/* Options saved int "options" of the include/exclude lists.
+/*  
+ * Options saved int "options" of the include/exclude lists.
  * They are directly jammed ito  "flag" of ff packet
  */
 #define FO_MD5          (1<<1)        /* Do MD5 checksum */
@@ -156,8 +156,6 @@ struct findFOPTS {
    alist base;                        /* list of base names */
    alist fstype;                      /* file system type limitation */
    alist drivetype;                   /* drive type limitation */
-   char *reader;                      /* reader program */
-   char *writer;                      /* writer program */
 };
 
 
@@ -221,8 +219,7 @@ struct FF_PKT {
    uint32_t flags;                    /* backup options */
    int GZIP_level;                    /* compression level */
    int strip_path;                    /* strip path count */
-   char *reader;                      /* reader program */
-   char *writer;                      /* writer program */
+   bool cmd_plugin;                   /* set if we have a command plugin */
    alist fstypes;                     /* allowed file system types */
    alist drivetypes;                  /* allowed drive types */
 
index 7599c4d9c75e514827681c368db624383708b15e..b87a448264ed26d9509d9c99b764603a67209ebf 100644 (file)
@@ -151,6 +151,8 @@ static bpError handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
    case bEventSince:
       printf("plugin: since=%d\n", (int)value);
       break;
+   default:
+      printf("plugin: unknown event=%d\n", event->eventType);
    }
    bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
 // printf("FD Name=%s\n", name);
index c42a9043a36365ccd40361cf63a84cb423e18a99..57528e309dd6db2fd802be11375c19a0f00f3a72 100644 (file)
@@ -191,12 +191,6 @@ main (int argc, char *const *argv)
             fo->wildbase.destroy();
             fo->fstype.destroy();
             fo->drivetype.destroy();
-            if (fo->reader) {
-               free(fo->reader);
-            }
-            if (fo->writer) {
-               free(fo->writer);
-            }
          }
          incexe->opts_list.destroy();
          incexe->name_list.destroy();
@@ -513,12 +507,6 @@ static bool copy_fileset(FF_PKT *ff, JCR *jcr)
             for (k=0; k<fo->drivetype.size(); k++) {
                current_opts->drivetype.append(bstrdup((const char *)fo->drivetype.get(k)));
             }
-            if (fo->reader) {
-               current_opts->reader = bstrdup(fo->reader);
-            }
-            if (fo->writer) {
-               current_opts->writer = bstrdup(fo->writer);
-            }
          }
 
          for (j=0; j<ie->name_list.size(); j++) {
index d7009b849d5510b0ac168af671c35b958dfbe47f..f160f189529867bfa9602c331845b87002e83e84 100644 (file)
@@ -21,6 +21,8 @@ kes  Attempt to work around gcc FORTIFY_SOURCE bug that crashes the
      FD by using casting. Reported in bug #1042.
 28Jan08
 kes  A bit of crypto cleanup.  More later.
+
+Release Version 2.2.8
 25Jan08
 kes  Apply patch from Martin to correct bug #1040, bscan sets existing
      ClientId to zero.