]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/patches/testing/file_relocation.patch
ebl fix compilation bug
[bacula/bacula] / bacula / patches / testing / file_relocation.patch
index d48061339273281058581c6919cf4ee928f0db49..8570dcf1d1d63f850d288580f777b7b26cd2eb66 100644 (file)
@@ -1,29 +1,26 @@
 Index: src/dird/ua_restore.c
 ===================================================================
---- src/dird/ua_restore.c      (révision 4466)
+--- src/dird/ua_restore.c      (révision 4588)
 +++ src/dird/ua_restore.c      (copie de travail)
-@@ -43,8 +43,8 @@
+@@ -44,7 +44,6 @@
  #include "bacula.h"
  #include "dird.h"
-+#include "lib/breg.h"
  
 -
  /* Imported functions */
  extern void print_bsr(UAContext *ua, RBSR *bsr);
  
-@@ -83,6 +83,10 @@
+@@ -83,6 +82,9 @@
     JCR *jcr = ua->jcr;
     char *escaped_bsr_name = NULL;
     char *escaped_where_name = NULL;
 +   bool where_use_regexp = false;
-+   bool have_to_free_where = false;
-+   char *strip_prefix, *add_prefix, *add_suffix;
-+   strip_prefix = add_prefix = add_suffix = NULL;
++   char *strip_prefix, *add_prefix, *add_suffix, *regexp;
++   strip_prefix = add_prefix = add_suffix = regexp = NULL;
  
     memset(&rx, 0, sizeof(rx));
     rx.path = get_pool_memory(PM_FNAME);
-@@ -94,6 +98,41 @@
+@@ -94,6 +96,45 @@
     i = find_arg_with_value(ua, "where");
     if (i >= 0) {
        rx.where = ua->argv[i];
@@ -56,16 +53,20 @@ Index: src/dird/ua_restore.c
 +   }
 +
 +   if (strip_prefix || add_suffix || add_prefix) {
++      int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
++      regexp = (char *) bmalloc (len * sizeof(char));
++
++      bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
 +      where_use_regexp = true;
-+      have_to_free_where = true;
-+      rx.where = bregexp_build_where(strip_prefix, add_prefix, add_suffix);
++      
++      rx.where = regexp;
 +   }
 +
 +   if (rx.where) {
        if (!acl_access_ok(ua, Where_ACL, rx.where)) {
           ua->error_msg(_("\"where\" specification not authorized.\n"));
           goto bail_out;
-@@ -195,9 +234,10 @@
+@@ -195,9 +236,10 @@
  
        Mmsg(ua->cmd,
            "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
@@ -73,33 +74,33 @@ Index: src/dird/ua_restore.c
 +          " %swhere=\"%s\" files=%d catalog=\"%s\"",
            job->name(), rx.ClientName, rx.store?rx.store->name():"",
            escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
-+        where_use_regexp ? "r" : "",
++          where_use_regexp ? "r" : "",
            escaped_where_name ? escaped_where_name : rx.where,
            rx.selected_files, ua->catalog->name());
     } else {
-@@ -216,6 +256,10 @@
+@@ -216,6 +258,10 @@
     if (escaped_where_name != NULL) {
        bfree(escaped_where_name);
     }
 +   
-+   if (have_to_free_where) {
-+      free_pool_memory(rx.where);
++   if (regexp) {
++      bfree(regexp);
 +   }
  
     if (find_arg(ua, NT_("yes")) > 0) {
        pm_strcat(ua->cmd, " yes");    /* pass it on to the run command */
-@@ -235,6 +279,10 @@
+@@ -235,6 +281,10 @@
        bfree(escaped_where_name);
     }
  
-+   if (have_to_free_where) {
-+      free_pool_memory(rx.where);
++   if (regexp) {
++      bfree(regexp);
 +   }
 +
     free_rx(&rx);
     return 0;
  
-@@ -331,23 +379,28 @@
+@@ -333,23 +383,28 @@
  
     const char *kw[] = {
         /* These keywords are handled in a for loop */
@@ -145,7 +146,7 @@ Index: src/dird/ua_restore.c
  
 Index: src/dird/restore.c
 ===================================================================
---- src/dird/restore.c (révision 4466)
+--- src/dird/restore.c (révision 4588)
 +++ src/dird/restore.c (copie de travail)
 @@ -50,8 +50,9 @@
  #include "dird.h"
@@ -187,19 +188,23 @@ Index: src/dird/restore.c
     unbash_spaces(where);
  
     if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
-Index: src/dird/dird_conf.c
+Index: src/dird/dird.h
 ===================================================================
---- src/dird/dird_conf.c       (révision 4466)
-+++ src/dird/dird_conf.c       (copie de travail)
-@@ -52,6 +52,7 @@
+--- src/dird/dird.h    (révision 4588)
++++ src/dird/dird.h    (copie de travail)
+@@ -34,6 +34,7 @@
+  */
  
- #include "bacula.h"
- #include "dird.h"
+ #include "lib/runscript.h"
 +#include "lib/breg.h"
+ #include "dird_conf.h"
  
- /* Define the first and last resource ID record
-  * types. Note, these should be unique for each
-@@ -268,6 +269,10 @@
+ #define DIRECTOR_DAEMON 1
+Index: src/dird/dird_conf.c
+===================================================================
+--- src/dird/dird_conf.c       (révision 4588)
++++ src/dird/dird_conf.c       (copie de travail)
+@@ -268,6 +268,10 @@
     {"run",       store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
     /* Root of where to restore files */
     {"where",    store_dir,      ITEM(res_job.RestoreWhere), 0, 0, 0},
@@ -210,7 +215,7 @@ Index: src/dird/dird_conf.c
     /* Where to find bootstrap during restore */
     {"bootstrap",store_dir,      ITEM(res_job.RestoreBootstrap), 0, 0, 0},
     /* Where to write bootstrap file during backup */
-@@ -611,6 +616,9 @@
+@@ -611,6 +615,9 @@
        if (res->res_job.RestoreWhere) {
           sendit(sock, _("  --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
        }
@@ -220,7 +225,7 @@ Index: src/dird/dird_conf.c
        if (res->res_job.RestoreBootstrap) {
           sendit(sock, _("  --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap));
        }
-@@ -1143,6 +1151,15 @@
+@@ -1143,6 +1150,15 @@
        if (res->res_job.RestoreWhere) {
           free(res->res_job.RestoreWhere);
        }
@@ -236,7 +241,7 @@ Index: src/dird/dird_conf.c
        if (res->res_job.RestoreBootstrap) {
           free(res->res_job.RestoreBootstrap);
        }
-@@ -1299,6 +1316,19 @@
+@@ -1299,6 +1315,25 @@
           res->res_job.jobdefs    = res_all.res_job.jobdefs;
           res->res_job.run_cmds   = res_all.res_job.run_cmds;
           res->res_job.RunScripts = res_all.res_job.RunScripts;
@@ -247,10 +252,16 @@ Index: src/dird/dird_conf.c
 +          if (res->res_job.RestoreWhere) {
 +             free(res->res_job.RestoreWhere);
 +          }
++          int len = bregexp_get_build_where_size(res->res_job.strip_prefix,
++                                                 res->res_job.add_prefix,
++                                                 res->res_job.add_suffix);
++          res->res_job.RestoreWhere = (char *) bmalloc (len * sizeof(char));
++          bregexp_build_where(res->res_job.RestoreWhere, len,
++                              res->res_job.strip_prefix,
++                              res->res_job.add_prefix,
++                              res->res_job.add_suffix);
 +          res->res_job.where_use_regexp = true;
-+          res->res_job.RestoreWhere=bregexp_build_where(res->res_job.strip_prefix,
-+                                                        res->res_job.add_prefix,
-+                                                        res->res_job.add_suffix);
++
 +          /* TODO: test bregexp */
 +       }
           break;
@@ -258,9 +269,17 @@ Index: src/dird/dird_conf.c
           if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
 Index: src/dird/ua_run.c
 ===================================================================
---- src/dird/ua_run.c  (révision 4466)
+--- src/dird/ua_run.c  (révision 4588)
 +++ src/dird/ua_run.c  (copie de travail)
-@@ -71,6 +71,7 @@
+@@ -41,6 +41,7 @@
+ static void select_job_level(UAContext *ua, JCR *jcr);
+ static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, char *verify_list, 
+    char *jid, const char *replace);
++static void select_where_regexp(UAContext *ua, JCR *jcr);
+ /* Imported variables */
+@@ -71,6 +72,7 @@
     int Priority = 0;
     int i, j, opt, files = 0;
     bool kw_ok;
@@ -268,7 +287,7 @@ Index: src/dird/ua_run.c
     JOB *job = NULL;
     JOB *verify_job = NULL;
     JOB *previous_job = NULL;
-@@ -87,7 +88,7 @@
+@@ -87,7 +89,7 @@
        "level",                        /* 5 */
        "storage",                      /* 6 */
        "sd",                           /* 7 */
@@ -277,7 +296,7 @@ Index: src/dird/ua_run.c
        "where",                        /* 9 */
        "bootstrap",                    /* 10 */
        "replace",                      /* 11 */
-@@ -101,6 +102,7 @@
+@@ -101,6 +103,7 @@
        "cloned",                       /* 19 cloned */
        "verifylist",                   /* 20 verify output list */
        "migrationjob",                 /* 21 migration job name */
@@ -285,7 +304,7 @@ Index: src/dird/ua_run.c
        NULL};
  
  #define YES_POS 14
-@@ -188,14 +190,8 @@
+@@ -188,15 +191,11 @@
                 store_name = ua->argv[i];
                 kw_ok = true;
                 break;
@@ -297,12 +316,15 @@ Index: src/dird/ua_run.c
 -               pool_name = ua->argv[i];
 -               kw_ok = true;
 -               break;
-+          case 8:
-+             where_use_regexp = true;
++            case 8: /* rwhere */
              case 9: /* where */
++               /* TODO: this is ugly ... */
++               where_use_regexp = (j == 9)?false:true; /* rwhere or where ? */
++
                 if (where) {
                    ua->send_msg(_("Where specified twice.\n"));
-@@ -287,8 +283,15 @@
+                   return 0;
+@@ -287,8 +286,15 @@
                 previous_job_name = ua->argv[i];
                 kw_ok = true;
                 break;
@@ -319,7 +341,7 @@ Index: src/dird/ua_run.c
              default:
                 break;
              }
-@@ -478,6 +481,7 @@
+@@ -478,6 +484,7 @@
           free(jcr->where);
        }
        jcr->where = bstrdup(where);
@@ -327,9 +349,214 @@ Index: src/dird/ua_run.c
     }
  
     if (when) {
+@@ -595,8 +602,9 @@
+       } else if (jcr->JobType == JT_RESTORE) {
+          add_prompt(ua, _("Bootstrap"));     /* 7 */
+          add_prompt(ua, _("Where"));         /* 8 */
+-         add_prompt(ua, _("Replace"));       /* 9 */
+-         add_prompt(ua, _("JobId"));         /* 10 */
++         add_prompt(ua, _("File Relocation"));/* 9 */  
++         add_prompt(ua, _("Replace"));       /* 10 */
++         add_prompt(ua, _("JobId"));         /* 11 */
+       }
+       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
+       case 0:
+@@ -719,8 +727,13 @@
+             ua->cmd[0] = 0;
+          }
+          jcr->where = bstrdup(ua->cmd);
++       jcr->where_use_regexp = false;
+          goto try_again;
+-      case 9:
++      case 9: 
++       /* File relocation */
++       select_where_regexp(ua, jcr);
++       goto try_again;
++      case 10:
+          /* Replace */
+          start_prompt(ua, _("Replace:\n"));
+          for (i=0; ReplaceOptions[i].name; i++) {
+@@ -731,7 +744,7 @@
+             jcr->replace = ReplaceOptions[opt].token;
+          }
+          goto try_again;
+-      case 10:
++      case 11:
+          /* JobId */
+          jid = NULL;                  /* force reprompt */
+          jcr->RestoreJobId = 0;
+@@ -775,6 +788,134 @@
+    return 0;                       /* do not run */
+ }
++static void select_where_regexp(UAContext *ua, JCR *jcr)
++{
++   alist *regs;
++   char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
++   strip_prefix = add_suffix = rwhere = add_prefix = NULL;
++
++try_again_reg:
++   ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
++              NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
++
++   start_prompt(ua, _("This will replace your current Where value\n"));
++   add_prompt(ua, _("Strip prefix"));                /* 0 */
++   add_prompt(ua, _("Add prefix"));                  /* 1 */
++   add_prompt(ua, _("Add file suffix"));             /* 2 */
++   add_prompt(ua, _("Enter a regexp"));              /* 3 */
++   add_prompt(ua, _("Test filename manipulation"));  /* 4 */
++   add_prompt(ua, _("Use this ?"));                  /* 5 */
++   
++   switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
++   case 0:
++      /* Strip prefix */
++      if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
++       if (strip_prefix) bfree(strip_prefix);
++       strip_prefix = bstrdup(ua->cmd);
++      }
++      
++      goto try_again_reg;
++   case 1:
++      /* Add prefix */
++      if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
++       if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
++          ua->cmd[0] = 0;
++       }
++
++       if (add_prefix) bfree(add_prefix);
++       add_prefix = bstrdup(ua->cmd);
++      }
++      goto try_again_reg;
++   case 2:
++      /* Add suffix */
++      if (get_cmd(ua, _("Please enter file suffix to add: "))) {
++       if (add_suffix) bfree(add_suffix);
++       add_suffix = bstrdup(ua->cmd);
++      }      
++      goto try_again_reg;
++   case 3:
++      /* Add rwhere */
++      if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
++       if (rwhere) bfree(rwhere);
++       rwhere = bstrdup(ua->cmd);
++      }
++      
++      goto try_again_reg;      
++   case 4:
++      /* Test regexp */ 
++      char *result;
++      char *regexp;
++      
++      if (rwhere && rwhere[0] != '\0') {
++       regs = get_bregexps(rwhere);
++       ua->send_msg(_("rwhere=%s\n"), NPRT(rwhere));
++      } else {
++       int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
++       regexp = (char *) bmalloc (len * sizeof(char));
++       bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
++       regs = get_bregexps(regexp);
++       ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
++                    NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
++       
++       bfree(regexp);
++      }
++
++      if (!regs) {
++       ua->send_msg(_("Cannot use your regexp\n"));
++       goto try_again_reg;
++      }
++
++      while (get_cmd(ua, _("Please enter filename to test: "))) {
++       apply_bregexps(ua->cmd, regs, &result);
++       ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
++      }
++      free_bregexps(regs);
++      delete regs;
++      goto try_again_reg;
++
++   case 5:
++      /* OK */
++      break;
++   case -1:                        /* error or cancel */
++      goto bail_out_reg;
++   default:
++      goto try_again_reg;
++   }
++
++   /* replace the existing where */
++   if (jcr->where) {
++      bfree(jcr->where);
++      jcr->where = NULL;
++   }
++
++   if (rwhere) {
++      jcr->where = bstrdup(rwhere);
++   } else if (strip_prefix || add_prefix || add_suffix) {
++      int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
++      jcr->where = (char *) bmalloc(len*sizeof(char));
++      bregexp_build_where(jcr->where, len, strip_prefix, add_prefix, add_suffix);
++   }
++
++   regs = get_bregexps(jcr->where);
++   if (regs) {
++      free_bregexps(regs);
++      delete regs;
++      jcr->where_use_regexp = true;
++   } else {
++      if (jcr->where) {
++       bfree(jcr->where);
++       jcr->where = NULL;
++      }
++      ua->send_msg(_("Cannot use your regexp.\n"));
++   }
++
++bail_out_reg:
++   if (strip_prefix) bfree(strip_prefix);
++   if (add_prefix)   bfree(add_prefix);
++   if (add_suffix)   bfree(add_suffix);
++   if (rwhere)       bfree(rwhere);
++}
++
+ static void select_job_level(UAContext *ua, JCR *jcr)
+ {
+    if (jcr->JobType == JT_BACKUP) {
+@@ -938,7 +1079,7 @@
+          ua->send_msg(_("Run Restore job\n"
+                         "JobName:    %s\n"
+                         "Bootstrap:  %s\n"
+-                        "Where:      %s\n"
++                        "%s     %s\n"             /* Where or RWhere */
+                         "Replace:    %s\n"
+                         "FileSet:    %s\n"
+                         "Client:     %s\n"
+@@ -948,6 +1089,7 @@
+                         "Priority:   %d\n"),
+               job->name(),
+               NPRT(jcr->RestoreBootstrap),
++              jcr->where_use_regexp?"RWhere:":"Where: ",
+               jcr->where?jcr->where:NPRT(job->RestoreWhere),
+               replace,
+               jcr->fileset->name(),
+@@ -961,7 +1103,7 @@
+          ua->send_msg(_("Run Restore job\n"
+                        "JobName:    %s\n"
+                        "Bootstrap:  %s\n"
+-                       "Where:      %s\n"
++                       "%s     %s\n"              /* Where or RWhere */
+                        "Replace:    %s\n"
+                        "Client:     %s\n"
+                        "Storage:    %s\n"
+@@ -971,6 +1113,7 @@
+                        "Priority:   %d\n"),
+               job->name(),
+               NPRT(jcr->RestoreBootstrap),
++              jcr->where_use_regexp?"RWhere:":"Where: ",
+               jcr->where?jcr->where:NPRT(job->RestoreWhere),
+               replace,
+               jcr->client->name(),
 Index: src/dird/dird_conf.h
 ===================================================================
---- src/dird/dird_conf.h       (révision 4466)
+--- src/dird/dird_conf.h       (révision 4588)
 +++ src/dird/dird_conf.h       (copie de travail)
 @@ -356,6 +356,10 @@
     int   Priority;                    /* Job priority */
@@ -344,17 +571,9 @@ Index: src/dird/dird_conf.h
     union {
 Index: src/filed/job.c
 ===================================================================
---- src/filed/job.c    (révision 4467)
+--- src/filed/job.c    (révision 4588)
 +++ src/filed/job.c    (copie de travail)
-@@ -36,6 +36,7 @@
- #include "bacula.h"
- #include "filed.h"
-+#include "lib/breg.h"
- #if defined(WIN32_VSS)
- #include "vss.h"
-@@ -115,6 +116,7 @@
+@@ -115,6 +115,7 @@
  static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
  static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
  static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
@@ -362,7 +581,7 @@ Index: src/filed/job.c
  static char verifycmd[]   = "verify level=%30s";
  static char estimatecmd[] = "estimate listing=%d";
  static char runbefore[]   = "RunBeforeJob %s";
-@@ -1586,12 +1588,15 @@
+@@ -1586,12 +1587,15 @@
     *where = 0;
  
     if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
@@ -371,19 +590,19 @@ Index: src/filed/job.c
 -         Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
 -         return 0;
 +      if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, where) != 3){
-+       if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
-+          pm_strcpy(jcr->errmsg, dir->msg);
-+          Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
-+          return 0;
-+       }
-+       *where = 0;
++         if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
++            pm_strcpy(jcr->errmsg, dir->msg);
++            Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
++            return 0;
++         }
++         *where = 0;
        }
 -      *where = 0;
 +      jcr->where_use_regexp = true;
     }
     /* Turn / into nothing */
     if (IsPathSeparator(where[0]) && where[1] == '\0') {
-@@ -1601,6 +1606,15 @@
+@@ -1601,6 +1605,15 @@
     Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
     unbash_spaces(where);
     jcr->where = bstrdup(where);
@@ -399,9 +618,21 @@ Index: src/filed/job.c
     free_pool_memory(where);
     jcr->replace = replace;
     jcr->prefix_links = prefix_links;
+Index: src/filed/filed.h
+===================================================================
+--- src/filed/filed.h  (révision 4588)
++++ src/filed/filed.h  (copie de travail)
+@@ -40,6 +40,7 @@
+ #include "acl.h"
+ #include "protos.h"                   /* file daemon prototypes */
+ #include "lib/runscript.h"
++#include "lib/breg.h"
+ #ifdef HAVE_LIBZ
+ #include <zlib.h>                     /* compression headers */
+ #else
 Index: src/jcr.h
 ===================================================================
---- src/jcr.h  (révision 4466)
+--- src/jcr.h  (révision 4588)
 +++ src/jcr.h  (copie de travail)
 @@ -173,6 +173,8 @@
     MSGS *jcr_msgs;                    /* Copy of message resource -- actually used */
@@ -414,7 +645,7 @@ Index: src/jcr.h
     bool prefix_links;                 /* Prefix links with Where path */
 Index: src/lib/Makefile.in
 ===================================================================
---- src/lib/Makefile.in        (révision 4466)
+--- src/lib/Makefile.in        (révision 4588)
 +++ src/lib/Makefile.in        (copie de travail)
 @@ -32,7 +32,7 @@
          res.c rwlock.c scan.c serial.c sha1.c \
@@ -436,7 +667,7 @@ Index: src/lib/Makefile.in
  EXTRAOBJS = @OBJLIST@
 Index: src/lib/attr.c
 ===================================================================
---- src/lib/attr.c     (révision 4466)
+--- src/lib/attr.c     (révision 4588)
 +++ src/lib/attr.c     (copie de travail)
 @@ -35,8 +35,8 @@
  
@@ -467,13 +698,13 @@ Index: src/lib/attr.c
 +          *  on user request to soft links
 +          */
 +
-+       if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
-+          apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
-+          pm_strcpy(attr->olname, ret);
++         if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
++            apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
++            pm_strcpy(attr->olname, ret);
 +
-+       } else {
-+          pm_strcpy(attr->olname, attr->lname);
-+       }
++         } else {
++            pm_strcpy(attr->olname, attr->lname);
++         }
 +      }
 +      
     } else {
@@ -481,7 +712,7 @@ Index: src/lib/attr.c
        int wherelen = strlen(jcr->where);
 Index: src/lib/jcr.c
 ===================================================================
---- src/lib/jcr.c      (révision 4466)
+--- src/lib/jcr.c      (révision 4588)
 +++ src/lib/jcr.c      (copie de travail)
 @@ -56,6 +56,9 @@
  /* External variables we reference */
@@ -505,253 +736,3 @@ Index: src/lib/jcr.c
     if (jcr->cached_path) {
        free_pool_memory(jcr->cached_path);
        jcr->cached_path = NULL;
-Index: patches/testing/file_relocation.patch
-===================================================================
---- patches/testing/file_relocation.patch      (révision 4514)
-+++ patches/testing/file_relocation.patch      (copie de travail)
-@@ -12,17 +12,18 @@
-  /* Imported functions */
-  extern void print_bsr(UAContext *ua, RBSR *bsr);
-  
--@@ -83,6 +83,9 @@
-+@@ -83,6 +83,10 @@
-     JCR *jcr = ua->jcr;
-     char *escaped_bsr_name = NULL;
-     char *escaped_where_name = NULL;
- +   bool where_use_regexp = false;
-++   bool have_to_free_where = false;
- +   char *strip_prefix, *add_prefix, *add_suffix;
- +   strip_prefix = add_prefix = add_suffix = NULL;
-  
-     memset(&rx, 0, sizeof(rx));
-     rx.path = get_pool_memory(PM_FNAME);
--@@ -94,6 +97,29 @@
-+@@ -94,6 +98,41 @@
-     i = find_arg_with_value(ua, "where");
-     if (i >= 0) {
-        rx.where = ua->argv[i];
-@@ -43,8 +44,20 @@
- +      add_suffix = ua->argv[i];
- +   }
- +
-++   i = find_arg(ua, "where_use_regexp");
-++   if (i >= 0) {
-++      where_use_regexp = true;
-++   }
-++
-++   i = find_arg_with_value(ua, "rwhere");
-++   if (i >= 0) {
-++      where_use_regexp = true;
-++      rx.where = ua->argv[i];
-++   }
-++
- +   if (strip_prefix || add_suffix || add_prefix) {
- +      where_use_regexp = true;
-++      have_to_free_where = true;
- +      rx.where = bregexp_build_where(strip_prefix, add_prefix, add_suffix);
- +   }
- +
-@@ -52,7 +65,7 @@
-        if (!acl_access_ok(ua, Where_ACL, rx.where)) {
-           ua->error_msg(_("\"where\" specification not authorized.\n"));
-           goto bail_out;
--@@ -195,9 +221,10 @@
-+@@ -195,9 +234,10 @@
-  
-        Mmsg(ua->cmd,
-            "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
-@@ -64,28 +77,72 @@
-            escaped_where_name ? escaped_where_name : rx.where,
-            rx.selected_files, ua->catalog->name());
-     } else {
--@@ -216,6 +243,10 @@
-+@@ -216,6 +256,10 @@
-     if (escaped_where_name != NULL) {
-        bfree(escaped_where_name);
-     }
- +   
--+   if (where_use_regexp) {
-++   if (have_to_free_where) {
- +      free_pool_memory(rx.where);
- +   }
-  
-     if (find_arg(ua, NT_("yes")) > 0) {
-        pm_strcat(ua->cmd, " yes");    /* pass it on to the run command */
--@@ -235,6 +266,10 @@
-+@@ -235,6 +279,10 @@
-        bfree(escaped_where_name);
-     }
-  
--+   if (where_use_regexp) {
-++   if (have_to_free_where) {
- +      free_pool_memory(rx.where);
- +   }
- +
-     free_rx(&rx);
-     return 0;
-  
-+@@ -331,23 +379,28 @@
-+ 
-+    const char *kw[] = {
-+        /* These keywords are handled in a for loop */
-+-      "jobid",     /* 0 */
-+-      "current",   /* 1 */
-+-      "before",    /* 2 */
-+-      "file",      /* 3 */
-+-      "directory", /* 4 */
-+-      "select",    /* 5 */
-+-      "pool",      /* 6 */
-+-      "all",       /* 7 */
-++      "jobid",       /* 0 */
-++      "current",     /* 1 */
-++      "before",      /* 2 */
-++      "file",        /* 3 */
-++      "directory",   /* 4 */
-++      "select",      /* 5 */
-++      "pool",        /* 6 */
-++      "all",         /* 7 */
-+ 
-+       /* The keyword below are handled by individual arg lookups */
-+-      "client",    /* 8 */
-+-      "storage",   /* 9 */
-+-      "fileset",   /* 10 */
-+-      "where",     /* 11 */
-+-      "yes",       /* 12 */
-+-      "bootstrap", /* 13 */
-+-      "done",      /* 14 */
-++      "client",       /* 8 */
-++      "storage",      /* 9 */
-++      "fileset",      /* 10 */
-++      "where",        /* 11 */
-++      "yes",          /* 12 */
-++      "bootstrap",    /* 13 */
-++      "done",         /* 14 */
-++      "strip_prefix", /* 15 */
-++      "add_prefix",   /* 16 */
-++      "add_suffix",   /* 17 */
-++      "where_use_regexp",/* 18 */
-++      "rwhere",       /* 19 like where + where_use_regexp */
-+       NULL
-+    };
-+ 
- Index: src/dird/restore.c
- ===================================================================
- --- src/dird/restore.c        (révision 4466)
-@@ -134,15 +191,26 @@
- ===================================================================
- --- src/dird/dird_conf.c      (révision 4466)
- +++ src/dird/dird_conf.c      (copie de travail)
--@@ -268,6 +268,7 @@
-+@@ -52,6 +52,7 @@
-+ 
-+ #include "bacula.h"
-+ #include "dird.h"
-++#include "lib/breg.h"
-+ 
-+ /* Define the first and last resource ID record
-+  * types. Note, these should be unique for each
-+@@ -268,6 +269,10 @@
-     {"run",       store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
-     /* Root of where to restore files */
-     {"where",    store_dir,      ITEM(res_job.RestoreWhere), 0, 0, 0},
- +   {"whereuseregexp", store_bool, ITEM(res_job.where_use_regexp), 0, 0, 0},
-++   {"stripprefix",    store_str,  ITEM(res_job.strip_prefix), 0, 0, 0},
-++   {"addprefix",    store_str,  ITEM(res_job.add_prefix), 0, 0, 0},
-++   {"addsuffix",    store_str,  ITEM(res_job.add_suffix), 0, 0, 0},
-     /* Where to find bootstrap during restore */
-     {"bootstrap",store_dir,      ITEM(res_job.RestoreBootstrap), 0, 0, 0},
-     /* Where to write bootstrap file during backup */
--@@ -611,6 +612,9 @@
-+@@ -611,6 +616,9 @@
-        if (res->res_job.RestoreWhere) {
-           sendit(sock, _("  --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
-        }
-@@ -152,6 +220,42 @@
-        if (res->res_job.RestoreBootstrap) {
-           sendit(sock, _("  --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap));
-        }
-+@@ -1143,6 +1151,15 @@
-+       if (res->res_job.RestoreWhere) {
-+          free(res->res_job.RestoreWhere);
-+       }
-++      if (res->res_job.strip_prefix) {
-++         free(res->res_job.strip_prefix);
-++      }
-++      if (res->res_job.add_prefix) {
-++         free(res->res_job.add_prefix);
-++      }
-++      if (res->res_job.add_suffix) {
-++         free(res->res_job.add_suffix);
-++      }
-+       if (res->res_job.RestoreBootstrap) {
-+          free(res->res_job.RestoreBootstrap);
-+       }
-+@@ -1299,6 +1316,19 @@
-+          res->res_job.jobdefs    = res_all.res_job.jobdefs;
-+          res->res_job.run_cmds   = res_all.res_job.run_cmds;
-+          res->res_job.RunScripts = res_all.res_job.RunScripts;
-++      if (res->res_job.strip_prefix ||
-++          res->res_job.add_suffix   ||
-++          res->res_job.add_prefix)
-++      {
-++         if (res->res_job.RestoreWhere) {
-++            free(res->res_job.RestoreWhere);
-++         }
-++         res->res_job.where_use_regexp = true;
-++         res->res_job.RestoreWhere=bregexp_build_where(res->res_job.strip_prefix,
-++                                                       res->res_job.add_prefix,
-++                                                       res->res_job.add_suffix);
-++         /* TODO: test bregexp */
-++      }
-+          break;
-+       case R_COUNTER:
-+          if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
- Index: src/dird/ua_run.c
- ===================================================================
- --- src/dird/ua_run.c (révision 4466)
-@@ -227,10 +331,13 @@
- ===================================================================
- --- src/dird/dird_conf.h      (révision 4466)
- +++ src/dird/dird_conf.h      (copie de travail)
--@@ -356,6 +356,7 @@
-+@@ -356,6 +356,10 @@
-     int   Priority;                    /* Job priority */
-     int   RestoreJobId;                /* What -- JobId to restore */
-     char *RestoreWhere;                /* Where on disk to restore -- directory */
-++   char *strip_prefix;                /* remove prefix from filename  */
-++   char *add_prefix;                  /* add prefix to filename  */
-++   char *add_suffix;                  /* add suffix to filename -- .old */
- +   bool  where_use_regexp;            /* true if RestoreWhere is a BREGEXP */
-     char *RestoreBootstrap;            /* Bootstrap file */
-     alist *RunScripts;                 /* Run {client} program {after|before} Job */
-@@ -398,30 +505,3 @@
-     if (jcr->cached_path) {
-        free_pool_memory(jcr->cached_path);
-        jcr->cached_path = NULL;
--Index: patches/testing/breg.c
--===================================================================
----- patches/testing/breg.c    (révision 4510)
--+++ patches/testing/breg.c    (copie de travail)
--@@ -393,19 +393,19 @@
-- 
--    *str_tmp = *ret = '\0';
--    
---   if (*strip_prefix) {
--+   if (strip_prefix) {
--       len += bsnprintf(ret, str_size - len, "!%s!!",
--                     bregexp_escape_string(str_tmp, strip_prefix, sep));
--    }
-- 
---   if (*add_suffix) {
--+   if (add_suffix) {
--       if (len) ret[len++] = ',';
-- 
--       len += bsnprintf(ret + len,  str_size - len, "!([^/])$!$1%s!",
--                     bregexp_escape_string(str_tmp, add_suffix, sep));
--    }
-- 
---   if (*add_prefix) {
--+   if (add_prefix) {
--       if (len) ret[len++] = ',';
-- 
--       len += bsnprintf(ret + len, str_size - len, "!^!%s!",