]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/fd_plugins.c
Add more plugin restore debug code.
[bacula/bacula] / bacula / src / filed / fd_plugins.c
index d72f7700f1144993298c260c59aa98a6dacad4cf..0d52728dddbe69af32ea83dd16db5fe3fed0640a 100644 (file)
 #include "filed.h"
 
 const int dbglvl = 50;
+#ifdef HAVE_WIN32
+const char *plugin_type = "-fd.dll";
+#else
 const char *plugin_type = "-fd.so";
+#endif
 
 extern int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
 
 /* Function pointers to be set here */
-extern DLL_IMP_EXP int     (*plugin_bopen)(JCR *jcr, const char *fname, int flags, mode_t mode);
-extern DLL_IMP_EXP int     (*plugin_bclose)(JCR *jcr);
-extern DLL_IMP_EXP ssize_t (*plugin_bread)(JCR *jcr, void *buf, size_t count);
-extern DLL_IMP_EXP ssize_t (*plugin_bwrite)(JCR *jcr, void *buf, size_t count);
-extern DLL_IMP_EXP boffset_t (*plugin_blseek)(JCR *jcr, boffset_t offset, int whence);
+extern DLL_IMP_EXP int     (*plugin_bopen)(BFILE *bfd, const char *fname, int flags, mode_t mode);
+extern DLL_IMP_EXP int     (*plugin_bclose)(BFILE *bfd);
+extern DLL_IMP_EXP ssize_t (*plugin_bread)(BFILE *bfd, void *buf, size_t count);
+extern DLL_IMP_EXP ssize_t (*plugin_bwrite)(BFILE *bfd, void *buf, size_t count);
+extern DLL_IMP_EXP boffset_t (*plugin_blseek)(BFILE *bfd, boffset_t offset, int whence);
 
 
 /* Forward referenced functions */
@@ -56,11 +60,11 @@ static bRC baculaJobMsg(bpContext *ctx, const char *file, int line,
 static bRC baculaDebugMsg(bpContext *ctx, const char *file, int line,
   int level, const char *fmt, ...);
 
-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);
-static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence);
+static int     my_plugin_bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
+static int     my_plugin_bclose(BFILE *bfd);
+static ssize_t my_plugin_bread(BFILE *bfd, void *buf, size_t count);
+static ssize_t my_plugin_bwrite(BFILE *bfd, void *buf, size_t count);
+static boffset_t my_plugin_blseek(BFILE *bfd, boffset_t offset, int whence);
 
 
 /* Bacula info */
@@ -90,7 +94,7 @@ void generate_plugin_event(JCR *jcr, bEventType eventType, void *value)
    Plugin *plugin;
    int i = 0;
 
-   if (!plugin_list) {
+   if (!plugin_list || !jcr->plugin_ctx_list) {
       return;                         /* Return if no plugins loaded */
    }
 
@@ -136,15 +140,16 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
    struct save_pkt sp;
    bEvent event;
 
-   if (!plugin_list) {
+   if (!plugin_list || !jcr->plugin_ctx_list) {
       return 1;                            /* Return if no plugins loaded */
    }
 
+   jcr->cmd_plugin = true;
    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
    event.eventType = bEventBackupCommand;
 
    /* Handle plugin command here backup */
-   Dmsg1(100, "plugin cmd=%s\n", cmd);
+   Dmsg1(dbglvl, "plugin cmd=%s\n", cmd);
    if (!(p = strchr(cmd, ':'))) {
       Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
       goto bail_out;
@@ -155,28 +160,34 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
    }
 
    foreach_alist(plugin, plugin_list) {
-      Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+      Dmsg3(dbglvl, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
       if (strncmp(plugin->file, cmd, len) != 0) {
          i++;
          continue;
       }
-      Dmsg1(100, "Command plugin = %s\n", cmd);
-      /* Send the backup command */
+      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) {
          goto bail_out;
       }
       /* Loop getting filenames to backup then saving them */
       while (!job_canceled(jcr)) { 
          memset(&sp, 0, sizeof(sp));
-         sp.type = FT_REG;
+         sp.pkt_size = sizeof(sp);
+         sp.pkt_end = sizeof(sp);
          sp.portable = true;
          sp.cmd = cmd;
-         Dmsg3(000, "startBackup st_size=%p st_blocks=%p sp=%p\n", &sp.statp.st_size, &sp.statp.st_blocks,
+         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) {
             goto bail_out;
          }
+         if (sp.type == 0 || sp.fname == NULL) {
+            Jmsg1(jcr, M_FATAL, 0, _("Command plugin \"%s\" returned bad startBackupFile packet.\n"),
+               cmd);
+            goto bail_out;
+         }
          jcr->plugin_ctx = &plugin_ctx_list[i];
          jcr->plugin = plugin;
          jcr->plugin_sp = &sp;
@@ -184,16 +195,19 @@ int plugin_save(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          ff_pkt->fname = sp.fname;
          ff_pkt->type = sp.type;
          memcpy(&ff_pkt->statp, &sp.statp, sizeof(ff_pkt->statp));
-         Dmsg1(000, "Save_file: file=%s\n", ff_pkt->fname);
+         Dmsg1(dbglvl, "Save_file: file=%s\n", ff_pkt->fname);
          save_file(jcr, ff_pkt, true);
-         if (plug_func(plugin)->endBackupFile(&plugin_ctx_list[i]) != bRC_More) {
-            goto bail_out;
+         bRC rc = plug_func(plugin)->endBackupFile(&plugin_ctx_list[i]);
+         if (rc == bRC_More) {
+            continue;
          }
+         goto bail_out;
       }
    }
    Jmsg1(jcr, M_ERROR, 0, "Command plugin \"%s\" not found.\n", cmd);
 
 bail_out:
+   jcr->cmd_plugin = false;
    return 1;
 }
 
@@ -205,7 +219,7 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start)
    int stat;
    struct save_pkt *sp = (struct save_pkt *)jcr->plugin_sp;
   
-   Dmsg1(000, "send_plugin_name=%s\n", sp->cmd);
+   Dmsg1(dbglvl, "send_plugin_name=%s\n", sp->cmd);
    /* Send stream header */
    if (!sd->fsend("%ld %d 0", jcr->JobFiles+1, STREAM_PLUGIN_NAME)) {
      Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
@@ -226,7 +240,7 @@ bool send_plugin_name(JCR *jcr, BSOCK *sd, bool start)
             sd->bstrerror());
          return false;
    }
-   Dmsg1(000, "send: %s\n", sd->msg);
+   Dmsg1(dbglvl, "send: %s\n", sd->msg);
    sd->signal(BNET_EOD);            /* indicate end of plugin name data */
    return true;
 }
@@ -244,8 +258,11 @@ void plugin_name_stream(JCR *jcr, char *name)
    int len;
    int i = 0;
    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
+   if (!plugin_ctx_list) {
+      goto bail_out;
+   }
 
-   Dmsg1(100, "Read plugin stream string=%s\n", name);
+   Dmsg1(dbglvl, "Read plugin stream string=%s\n", name);
    skip_nonspaces(&p);             /* skip over jcr->JobFiles */
    skip_spaces(&p);
    start = *p == '1';
@@ -261,8 +278,11 @@ void plugin_name_stream(JCR *jcr, char *name)
       /*
        * End of plugin data, notify plugin, then clear flags   
        */
-      plugin = (Plugin *)jcr->plugin;
-      plug_func(plugin)->endRestoreFile(&plugin_ctx_list[i]);
+      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);
+      }
       jcr->plugin_ctx = NULL;
       jcr->plugin = NULL;
       goto bail_out;
@@ -272,9 +292,10 @@ void plugin_name_stream(JCR *jcr, char *name)
     * After this point, we are dealing with a restore start
     */
 
-   Dmsg1(100, "plugin restore cmd=%s\n", cmd);
+// Dmsg1(dbglvl, "plugin restore cmd=%s\n", cmd);
    if (!(p = strchr(cmd, ':'))) {
-      Jmsg1(jcr, M_ERROR, 0, "Malformed plugin command: %s\n", cmd);
+      Jmsg1(jcr, M_ERROR, 0,
+           _("Malformed plugin command. Name not terminated by colon: %s\n"), cmd);
       goto bail_out;
    }
    len = p - cmd;
@@ -287,12 +308,12 @@ void plugin_name_stream(JCR *jcr, char *name)
     */
    foreach_alist(plugin, plugin_list) {
       bEvent event;
-      Dmsg3(100, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
+      Dmsg3(dbglvl, "plugin=%s cmd=%s len=%d\n", plugin->file, cmd, len);
       if (strncmp(plugin->file, cmd, len) != 0) {
          i++;
          continue;
       }
-      Dmsg1(100, "Restore Command plugin = %s\n", cmd);
+      Dmsg1(dbglvl, "Restore Command plugin = %s\n", cmd);
       event.eventType = bEventRestoreCommand;     
       if (plug_func(plugin)->handlePluginEvent(&plugin_ctx_list[i], 
             &event, cmd) != bRC_OK) {
@@ -320,11 +341,14 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
    bpContext *plugin_ctx = (bpContext *)jcr->plugin_ctx;
    Plugin *plugin = (Plugin *)jcr->plugin;
    struct restore_pkt rp;
-   struct io_pkt io;
+   int flags;
+   int rc;
 
    if (!set_cmd_plugin(bfd, jcr)) {
       return CF_ERROR;
    }
+   rp.pkt_size = sizeof(rp);
+   rp.pkt_end = sizeof(rp);
    rp.stream = attr->stream;
    rp.data_stream = attr->data_stream;
    rp.type = attr->type;
@@ -338,15 +362,31 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
    rp.where = jcr->where;
    rp.RegexWhere = jcr->RegexWhere;
    rp.replace = jcr->replace;
-   if (plug_func(plugin)->createFile(plugin_ctx, &rp) != bRC_OK) {
+   rp.create_status = CF_ERROR;
+   Dmsg1(dbglvl, "call plugin createFile=%s\n", rp.ofname);
+   rc = plug_func(plugin)->createFile(plugin_ctx, &rp);
+   if (rc != bRC_OK) {
+      Qmsg2(jcr, M_ERROR, 0, _("Plugin createFile call failed. Stat=%d file=%s\n"),
+            rc, attr->ofname);
       return CF_ERROR;
    }
-   io.func = IO_OPEN;
-   io.count = 0;
-   io.buf = NULL;
-   io.mode = 0777 & attr->statp.st_mode;
-   io.flags = O_WRONLY;
-   if (plug_func(plugin)->pluginIO(plugin_ctx, &io) != bRC_OK) {
+   if (rp.create_status == CF_ERROR) {
+      Qmsg1(jcr, M_ERROR, 0, _("Plugin createFile call failed. Returned CF_ERROR file=%s\n"),
+            attr->ofname);
+      return CF_ERROR;
+   }
+   /* Created link or directory? */
+   if (rp.create_status == CF_CREATED) {
+      return rp.create_status;        /* yes, no need to bopen */
+   }
+   flags =  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
+   Dmsg0(dbglvl, "call bopen\n");
+   if ((bopen(bfd, attr->ofname, flags, S_IRUSR | S_IWUSR)) < 0) {
+      berrno be;
+      be.set_errno(bfd->berrno);
+      Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
+            attr->ofname, be.bstrerror());
+      Dmsg2(dbglvl,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror());
       return CF_ERROR;
    }
    return CF_EXTRACT;
@@ -359,6 +399,7 @@ int plugin_create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
  */
 bool plugin_set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
 {
+   Dmsg0(dbglvl, "plugin_set_attributes\n");
    return true;
 }
 
@@ -371,11 +412,20 @@ void load_fd_plugins(const char *plugin_dir)
    Plugin *plugin;
 
    if (!plugin_dir) {
+      Dmsg0(dbglvl, "plugin dir is NULL\n");
       return;
    }
 
    plugin_list = New(alist(10, not_owned_by_alist));
-   load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type);
+   if (!load_plugins((void *)&binfo, (void *)&bfuncs, plugin_dir, plugin_type)) {
+      /* Either none found, or some error */
+      if (plugin_list->size() == 0) {
+         delete plugin_list;
+         plugin_list = NULL;
+         Dmsg0(dbglvl, "No plugins loaded\n");
+         return;
+      }
+   }
 
    /* Plug entry points called from findlib */
    plugin_bopen  = my_plugin_bopen;
@@ -385,12 +435,15 @@ void load_fd_plugins(const char *plugin_dir)
    plugin_blseek = my_plugin_blseek;
    foreach_alist(plugin, plugin_list) {
       Jmsg(NULL, M_INFO, 0, _("Loaded plugin: %s\n"), plugin->file);
-   }
+      Dmsg1(dbglvl, "Loaded plugin: %s\n", plugin->file);
 
+   }
 }
 
 /*
  * Create a new instance of each plugin for this Job
+ *   Note, plugin_list can exist but jcr->plugin_ctx_list can
+ *   be NULL if no plugins were loaded.
  */
 void new_plugins(JCR *jcr)
 {
@@ -398,12 +451,14 @@ void new_plugins(JCR *jcr)
    int i = 0;
 
    if (!plugin_list) {
+      Dmsg0(dbglvl, "plugin list is NULL\n");
       return;
    }
 
    int num = plugin_list->size();
 
    if (num == 0) {
+      Dmsg0(dbglvl, "No plugins loaded\n");
       return;
    }
 
@@ -427,8 +482,8 @@ void free_plugins(JCR *jcr)
    Plugin *plugin;
    int i = 0;
 
-   if (!plugin_list) {
-      return;
+   if (!plugin_list || !jcr->plugin_ctx_list) {
+      return;                         /* no plugins, nothing to do */
    }
 
    bpContext *plugin_ctx_list = (bpContext *)jcr->plugin_ctx_list;
@@ -441,70 +496,132 @@ void free_plugins(JCR *jcr)
    jcr->plugin_ctx_list = NULL;
 }
 
-static int my_plugin_bopen(JCR *jcr, const char *fname, int flags, mode_t mode)
+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;
-   Dmsg0(000, "plugin_bopen\n");
+   Dmsg0(dbglvl, "plugin_bopen\n");
+   io.pkt_size = sizeof(io);
+   io.pkt_end = sizeof(io);
    io.func = IO_OPEN;
    io.count = 0;
    io.buf = NULL;
-   io.mode = mode;
+   io.fname = fname;
    io.flags = flags;
+   io.mode = mode;
+   io.win32 = false;
+   io.lerror = 0;
    plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   bfd->berrno = io.io_errno;
+   if (io.win32) {
+      errno = b_errno_win32;
+   } else {
+      errno = io.io_errno;
+      bfd->lerror = io.lerror;
+   }
    return io.status;
 }
 
-static int my_plugin_bclose(JCR *jcr)
+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(000, "plugin_bclose\n");
+   Dmsg0(dbglvl, "plugin_bclose\n");
+   io.pkt_size = sizeof(io);
+   io.pkt_end = sizeof(io);
    io.func = IO_CLOSE;
    io.count = 0;
    io.buf = NULL;
+   io.win32 = false;
+   io.lerror = 0;
    plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   bfd->berrno = io.io_errno;
+   if (io.win32) {
+      errno = b_errno_win32;
+   } else {
+      errno = io.io_errno;
+      bfd->lerror = io.lerror;
+   }
+   Dmsg1(dbglvl, "plugin_bclose stat=%d\n", io.status);
    return io.status;
 }
 
-static ssize_t my_plugin_bread(JCR *jcr, void *buf, size_t count)
+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(000, "plugin_bread\n");
+   Dmsg0(dbglvl, "plugin_bread\n");
+   io.pkt_size = sizeof(io);
+   io.pkt_end = sizeof(io);
    io.func = IO_READ;
    io.count = count;
    io.buf = (char *)buf;
+   io.win32 = false;
+   io.lerror = 0;
    plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   bfd->berrno = io.io_errno;
+   if (io.win32) {
+      errno = b_errno_win32;
+   } else {
+      errno = io.io_errno;
+      bfd->lerror = io.lerror;
+   }
    return (ssize_t)io.status;
 }
 
-static ssize_t my_plugin_bwrite(JCR *jcr, void *buf, size_t count)
+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(000, "plugin_bwrite\n");
+   Dmsg0(dbglvl, "plugin_bwrite\n");
+   io.pkt_size = sizeof(io);
+   io.pkt_end = sizeof(io);
    io.func = IO_WRITE;
    io.count = count;
    io.buf = (char *)buf;
+   io.win32 = false;
+   io.lerror = 0;
    plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   bfd->berrno = io.io_errno;
+   if (io.win32) {
+      errno = b_errno_win32;
+   } else {
+      errno = io.io_errno;
+      bfd->lerror = io.lerror;
+   }
    return (ssize_t)io.status;
 }
 
-static boffset_t my_plugin_blseek(JCR *jcr, boffset_t offset, int whence)
+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(000, "plugin_bseek\n");
+   Dmsg0(dbglvl, "plugin_bseek\n");
+   io.pkt_size = sizeof(io);
+   io.pkt_end = sizeof(io);
    io.func = IO_SEEK;
    io.offset = offset;
    io.whence = whence;
+   io.win32 = false;
+   io.lerror = 0;
    plug_func(plugin)->pluginIO(plugin_ctx, &io);
+   bfd->berrno = io.io_errno;
+   if (io.win32) {
+      errno = b_errno_win32;
+   } else {
+      errno = io.io_errno;
+      bfd->lerror = io.lerror;
+   }
    return (boffset_t)io.offset;
 }