[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bacula-devel] Pre-alpha version of Bacula plugins working


Kern,

On Tuesday 11 March 2008, you wrote:
> On Tuesday 11 March 2008 10.39:52 Bastian Friedrich wrote:
> > Hi,
> >
> > On Friday 22 February 2008, Bastian Friedrich wrote:
> > > I'm sure you already have that on your radar; nonetheless, I'd like to
> > > mention that (if I understood things right...) currently plugins -- and
> > > the reader/writer executables in the bpipe plugin -- do not have access
> > > to the target directory specification during restore ("where"; the same
> > > holds true for the "replace" setting).
> >
> > thanks for your additional work on the plugin interface on that topic.
> >
> > I have supplemented your basic work in the bpipe plugin to allow two
> > codes, %w and %r, to reference the "where" and "replace" flags. See
> > attached patch.
>
> Your patch looks interesting and worth applying.  However, unless I
> misunderstood it, you have created a global pointer CreateRP that points to
> a packet, so the code is going to run into problems for the following
> reasons:
>
> 1. the restore packet that is passed should be considered volitale (if I am
> not mistaken it is a stack variable, so it gets clobbered on return to the
> function), so if you want information in it, you must copy it and not
> retain a pointer to it.
>
> 2. CreateRP is a global within bpipe-fd, and that will just not work
> because there can be multiple threads running through it at the same time. 
> To make it work correctly, you must move the CreateRP into the bpipe
> context packet, which is "local" to any particular instance of bpipe, and
> thus will be used only by one thread.  At the same time, you need to copy
> the data you want as mentioned above rather than keeping a pointer to it.

thx a lot for your comments. You are of course right with both of your points. 
I'm attaching an improved version that should fix both problems by creating 
two variables in the plugin context and storing the "where" and "replace" 
attributes there.

However, I was having a little difficulty understanding how/where to 
allocate/deallocate the proper buffer for the "where" string; due to this, 
I'm using a statically sized buffer inside the context. Hope this is OK?

Best regards,
   Bastian

-- 
Collax GmbH . Burkheimer Straße 3 . 79111 Freiburg . Germany
p: +49 (0) 761-45684-24
f: +49 (0) 761-45684-10        www.collax.com

Geschäftsführer: William K. Hite / Boris Nalbach
AG München HRB 158898 . Ust.-IdNr: DE 814464942
\ Smash forehead on keyboard to continue.
Index: src/plugins/fd/bpipe-fd.c
===================================================================
--- src/plugins/fd/bpipe-fd.c	(revision 6592)
+++ src/plugins/fd/bpipe-fd.c	(working copy)
@@ -109,6 +109,9 @@
    char *fname;                       /* filename to "backup/restore" */
    char *reader;                      /* reader program for backup */
    char *writer;                      /* writer program for backup */
+
+   char where[512];
+   int replace;
 };
 
 /*
@@ -288,6 +291,98 @@
 }
 
 /*
+ * Apply codes in writer command:
+ * %w -> "where"
+ * %r -> "replace"
+ *
+ * Replace:
+ * 'always' => 'a', chr(97)
+ * 'ifnewer' => 'w', chr(119)
+ * 'ifolder' => 'o', chr(111)
+ * 'never' => 'n', chr(110)
+ *
+ * This function will allocate the required amount of memory with malloc.
+ * Need to be free()d manually.
+ * Inspired by edit_job_codes in lib/util.c
+ */
+
+char *apply_rp_codes(struct plugin_ctx * p_ctx)
+{
+   char *p, *q;
+   const char *str;
+   char add[10];
+   int w_count = 0, r_count = 0;
+   char *omsg;
+
+   char *imsg = p_ctx->writer;
+
+   if (!strcmp(p_ctx->where, "")) {
+      if (imsg) {
+         return strdup(imsg);
+      } else {
+         return NULL;
+      }
+   }
+
+   if ((p = imsg)) {
+      while ((q = strstr(p, "%w"))) {
+         w_count++;
+         p=q+1;
+      }
+
+      p = imsg;
+      while ((q = strstr(p, "%r"))) {
+         r_count++;
+         p=q+1;
+      }
+   }
+
+   /* Required mem: 
+    * len(imsg) 
+    * + number of "where" codes * (len(where)-2) 
+    * - number of "replace" codes
+    */
+   omsg = (char*)malloc(strlen(imsg) + (w_count * (strlen(p_ctx->where)-2)) - r_count + 1);
+   if (!omsg) {
+      fprintf(stderr, "Out of memory.");
+      exit(1);
+   }
+
+   *omsg = 0;
+   //printf("apply_rp_codes: %s\n", imsg);
+   for (p=imsg; *p; p++) {
+      if (*p == '%') {
+         switch (*++p) {
+         case '%':
+            str = "%";
+            break;
+         case 'w':
+	     str = p_ctx->where;
+             break;
+         case 'r':
+	    snprintf(add, 2, "%c", p_ctx->replace);
+	    str = add;
+            break;
+         default:
+            add[0] = '%';
+            add[1] = *p;
+            add[2] = 0;
+            str = add;
+            break;
+         }
+      } else {
+         add[0] = *p;
+         add[1] = 0;
+         str = add;
+      }
+      //printf("add_str %s\n", str);
+      strcat(omsg, str);
+      //printf("omsg=%s\n", omsg);
+   }
+   return omsg;
+}
+
+/*
  * Bacula is calling us to do the actual I/O
  */
 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
@@ -300,14 +395,22 @@
    case IO_OPEN:
 //    printf("bpipe-fd: IO_OPEN\n");
       if (io->flags & (O_CREAT | O_WRONLY)) {
-         p_ctx->fd = popen(p_ctx->writer, "w");
-         printf("bpipe-fd: IO_OPEN writer=%s\n", p_ctx->writer);
+	 char *writer_codes = apply_rp_codes(p_ctx);
+
+         p_ctx->fd = popen(writer_codes, "w");
+         printf("bpipe-fd: IO_OPEN writer=%s\n", writer_codes);
          if (!p_ctx->fd) {
             io->io_errno = errno;
             bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, 
-               "Open pipe writer=%s failed: ERR=%s\n", p_ctx->writer, strerror(errno));
+               "Open pipe writer=%s failed: ERR=%s\n", writer_codes, strerror(errno));
+            if (writer_codes) {
+               free(writer_codes);
+            }
             return bRC_Error;
          }
+         if (writer_codes) {
+            free(writer_codes);
+         }
       } else {
          p_ctx->fd = popen(p_ctx->reader, "r");
 //       printf("bpipe-fd: IO_OPEN reader=%s\n", p_ctx->reader);
@@ -382,6 +485,11 @@
 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
 {
 // printf("bpipe-fd: createFile\n");
+   if (strlen(rp->where) > 512) {
+      printf("Restore target dir too long. Restricting to first 512 bytes.\n");
+   }
+   strncpy(((struct plugin_ctx *)ctx->pContext)->where, rp->where, 513);
+   ((struct plugin_ctx *)ctx->pContext)->replace = rp->replace;
    return bRC_OK;
 }
 
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Bacula-devel mailing list
Bacula-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/bacula-devel


This mailing list archive is a service of Copilotco.