]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/patches/testing/file_relocation.patch
ebl fix compilation
[bacula/bacula] / bacula / patches / testing / file_relocation.patch
index f54b5cfabc315945484d9a00a115fc23c66e4ba7..1f9742033189eed73c2e0a50f1b2b573f0583aa5 100644 (file)
+Index: patches/testing/breg.c
+===================================================================
+--- patches/testing/breg.c     (révision 4529)
++++ patches/testing/breg.c     (copie de travail)
+@@ -7,7 +7,7 @@
+  *
+  */
+ /*
+-   Bacula® - The Network Backup Solution
++   Bacula\81Â\81® - The Network Backup Solution
+    Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
+@@ -28,9 +28,9 @@
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+-   Bacula® is a registered trademark of John Walker.
++   Bacula\81Â\81® is a registered trademark of John Walker.
+    The licensor of Bacula is the Free Software Foundation Europe
+-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
++   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Z\81Ã\81¼rich,
+    Switzerland, email:ftf@fsfeurope.org.
+ */
+@@ -383,10 +383,11 @@
+     * add_prefix   = !^!add_prefix!          5 bytes
+     * add_suffix   = !([^/])$!$1add_suffix! 13 bytes
+     */
+-   int str_size = (strip_prefix?strlen(strip_prefix)+4:0 +
+-                 add_prefix?strlen(add_prefix)+5:0     + /* escape + 3*, + \0 */ 
+-                 add_suffix?strlen(add_suffix)+14:0     )     * 2  + 3   + 1;
++   int str_size = ((strip_prefix?strlen(strip_prefix)+4:0) +
++                 (add_prefix?strlen(add_prefix)+5    :0) + /* escape + 3*, + \0 */ 
++                 (add_suffix?strlen(add_suffix)+14   :0) )   * 2     + 3   + 1;
++   Dmsg1(1, "bregexp_get_build_where_size = %i\n", str_size);
+    return str_size;
+ }
+@@ -432,7 +433,7 @@
+    free_pool_memory(str_tmp);
+-   return ret;
++   return dest;
+ }
+Index: patches/testing/bregtest.c
+===================================================================
+--- patches/testing/bregtest.c (révision 4529)
++++ patches/testing/bregtest.c (copie de travail)
+@@ -5,7 +5,7 @@
+  *
+  */
+ /*
+-   Bacula® - The Network Backup Solution
++   Bacula\81Â\81® - The Network Backup Solution
+    Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
+@@ -26,9 +26,9 @@
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+-   Bacula® is a registered trademark of John Walker.
++   Bacula\81Â\81® is a registered trademark of John Walker.
+    The licensor of Bacula is the Free Software Foundation Europe
+-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
++   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Z\81Ã\81¼rich,
+    Switzerland, email:ftf@fsfeurope.org.
+ */
+@@ -62,8 +62,11 @@
+ int main(int argc, char *const *argv)
+ {
+-      printf("%s\n", bregexp_build_where("/tmp", NULL, ".old"));
+-      exit(0);
++   char tab[500];
++   int len = bregexp_get_build_where_size("/tmp", "/tmp/toto", ".old");
++   
++   printf("%s\n", bregexp_build_where(tab, len, "/tmp", "/tmp/toto!", ".old"));
++   exit(0);
+    regex_t preg;
+Index: patches/testing/breg.h
+===================================================================
+--- patches/testing/breg.h     (révision 4529)
++++ patches/testing/breg.h     (copie de travail)
+@@ -4,7 +4,7 @@
+  * Version $Id$
+  */
+ /*
+-   Bacula® - The Network Backup Solution
++   Bacula\81Â\81® - The Network Backup Solution
+    Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
+@@ -25,9 +25,9 @@
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+-   Bacula® is a registered trademark of John Walker.
++   Bacula\81Â\81® is a registered trademark of John Walker.
+    The licensor of Bacula is the Free Software Foundation Europe
+-   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
++   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Z\81Ã\81¼rich,
+    Switzerland, email:ftf@fsfeurope.org.
+ */
+@@ -98,8 +98,16 @@
+ /* foreach_alist free RUNSCRIPT */
+ void free_bregexps(alist *bregexps); /* you have to free alist */
+-/* get a bregexp string from user arguments */
+-char *bregexp_build_where(char *strip_prefix, 
++/* get regexp size */
++int bregexp_get_build_where_size(char *strip_prefix, 
++                               char *add_prefix, 
++                               char *add_suffix);
++
++/* get a bregexp string from user arguments 
++ * you must allocate it with bregexp_get_build_where_size();
++ */
++char *bregexp_build_where(char *dest, int str_size,
++                        char *strip_prefix, 
+                           char *add_prefix, 
+                           char *add_suffix);
+Index: src/dird/ua_restore.c
+===================================================================
+--- src/dird/ua_restore.c      (révision 4529)
++++ src/dird/ua_restore.c      (copie de travail)
+@@ -43,8 +43,8 @@
+ #include "bacula.h"
+ #include "dird.h"
++#include "lib/breg.h"
+-
+ /* Imported functions */
+ extern void print_bsr(UAContext *ua, RBSR *bsr);
+@@ -83,6 +83,9 @@
+    JCR *jcr = ua->jcr;
+    char *escaped_bsr_name = NULL;
+    char *escaped_where_name = NULL;
++   bool where_use_regexp = false;
++   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 +97,45 @@
+    i = find_arg_with_value(ua, "where");
+    if (i >= 0) {
+       rx.where = ua->argv[i];
++   }
++
++   i = find_arg_with_value(ua, "strip_prefix");
++   if (i >= 0) {
++      strip_prefix = ua->argv[i];
++   }
++
++   i = find_arg_with_value(ua, "add_prefix");
++   if (i >= 0) {
++      add_prefix = ua->argv[i];
++   }
++
++   i = find_arg_with_value(ua, "add_suffix");
++   if (i >= 0) {
++      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) {
++      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;
++      
++      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 +237,10 @@
+       Mmsg(ua->cmd,
+           "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
+-          " where=\"%s\" files=%d catalog=\"%s\"",
++          " %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" : "",
+           escaped_where_name ? escaped_where_name : rx.where,
+           rx.selected_files, ua->catalog->name());
+    } else {
+@@ -216,6 +259,10 @@
+    if (escaped_where_name != NULL) {
+       bfree(escaped_where_name);
+    }
++   
++   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 +282,10 @@
+       bfree(escaped_where_name);
+    }
++   if (regexp) {
++      bfree(regexp);
++   }
++
+    free_rx(&rx);
+    return 0;
+@@ -333,23 +384,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 4529)
++++ src/dird/restore.c (copie de travail)
+@@ -50,8 +50,9 @@
+ #include "dird.h"
+ /* Commands sent to File daemon */
+-static char restorecmd[]   = "restore replace=%c prelinks=%d where=%s\n";
+-static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
++static char restorecmd[]        = "restore replace=%c prelinks=%d where=%s\n";
++static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
++static char storaddr[]   = "storage address=%s port=%d ssl=0\n";
+ /* Responses received from File daemon */
+ static char OKrestore[]   = "2000 OK restore\n";
+@@ -172,7 +173,7 @@
+    }
+    /* Send restore command */
+-   char replace, *where;
++   char replace, *where, *cmd;
+    char empty = '\0';
+    if (jcr->replace != 0) {
+@@ -189,9 +190,17 @@
+    } else {
+       where = ∅                 /* None */
+    }
++   
+    jcr->prefix_links = jcr->job->PrefixLinks;
++
++   if (jcr->where_use_regexp) {
++      cmd = restorecmdR;
++   } else {
++      cmd = restorecmd;
++   }
++
+    bash_spaces(where);
+-   bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
++   bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
+    unbash_spaces(where);
+    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
+Index: src/dird/dird_conf.c
+===================================================================
+--- src/dird/dird_conf.c       (révision 4529)
++++ src/dird/dird_conf.c       (copie de travail)
+@@ -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 +616,9 @@
+       if (res->res_job.RestoreWhere) {
+          sendit(sock, _("  --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
+       }
++      if (res->res_job.where_use_regexp) {
++         sendit(sock, _("  --> RWhere=%u\n"), res->res_job.where_use_regexp);
++      }
+       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,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;
++       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);
++          }
++          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;
++
++          /* 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 4529)
++++ src/dird/ua_run.c  (copie de travail)
+@@ -36,11 +36,13 @@
+ #include "bacula.h"
+ #include "dird.h"
++#include "lib/breg.h"
+ /* Forward referenced subroutines */
+ 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 +73,7 @@
+    int Priority = 0;
+    int i, j, opt, files = 0;
+    bool kw_ok;
++   bool where_use_regexp = false;
+    JOB *job = NULL;
+    JOB *verify_job = NULL;
+    JOB *previous_job = NULL;
+@@ -87,7 +90,7 @@
+       "level",                        /* 5 */
+       "storage",                      /* 6 */
+       "sd",                           /* 7 */
+-      "pool",                         /* 8 */
++      "rwhere",                       /* 8 where string as a bregexp */
+       "where",                        /* 9 */
+       "bootstrap",                    /* 10 */
+       "replace",                      /* 11 */
+@@ -101,6 +104,7 @@
+       "cloned",                       /* 19 cloned */
+       "verifylist",                   /* 20 verify output list */
+       "migrationjob",                 /* 21 migration job name */
++      "pool",                         /* 22 */
+       NULL};
+ #define YES_POS 14
+@@ -188,15 +192,10 @@
+                store_name = ua->argv[i];
+                kw_ok = true;
+                break;
+-            case 8: /* pool */
+-               if (pool_name) {
+-                  ua->send_msg(_("Pool specified twice.\n"));
+-                  return 0;
+-               }
+-               pool_name = ua->argv[i];
+-               kw_ok = true;
+-               break;
++            case 8: /* rwhere */
+             case 9: /* where */
++             where_use_regexp = (j == 9)?false:true; /* rwhere or where ? */
++
+                if (where) {
+                   ua->send_msg(_("Where specified twice.\n"));
+                   return 0;
+@@ -287,8 +286,15 @@
+                previous_job_name = ua->argv[i];
+                kw_ok = true;
+                break;
++            case 22: /* pool */
++               if (pool_name) {
++                  ua->send_msg(_("Pool specified twice.\n"));
++                  return 0;
++               }
++               pool_name = ua->argv[i];
++               kw_ok = true;
++               break;
+-
+             default:
+                break;
+             }
+@@ -478,6 +484,7 @@
+          free(jcr->where);
+       }
+       jcr->where = bstrdup(where);
++      jcr->where_use_regexp = where_use_regexp;
+    }
+    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,131 @@
+    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:
++   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) {
+Index: src/dird/dird_conf.h
+===================================================================
+--- src/dird/dird_conf.h       (révision 4529)
++++ src/dird/dird_conf.h       (copie de travail)
+@@ -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 */
+    union {
 Index: src/filed/job.c
 ===================================================================
---- src/filed/job.c    (révision 4467)
+--- src/filed/job.c    (révision 4529)
 +++ src/filed/job.c    (copie de travail)
-@@ -37,6 +37,8 @@
+@@ -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 @@
+ 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";
++static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
+ static char verifycmd[]   = "verify level=%30s";
+ static char estimatecmd[] = "estimate listing=%d";
+ static char runbefore[]   = "RunBeforeJob %s";
+@@ -1586,12 +1588,15 @@
+    *where = 0;
  
-@@ -1601,6 +1603,7 @@
+    if (sscanf(dir->msg, restorecmd, &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;
++      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;
+       }
+-      *where = 0;
++      jcr->where_use_regexp = true;
+    }
+    /* Turn / into nothing */
+    if (IsPathSeparator(where[0]) && where[1] == '\0') {
+@@ -1601,6 +1606,15 @@
     Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
     unbash_spaces(where);
     jcr->where = bstrdup(where);
-+   jcr->where_bregexp = get_bregexps(where);
++
++   if (jcr->where_use_regexp) {
++      jcr->where_bregexp = get_bregexps(jcr->where);
++      if (!jcr->where_bregexp) {
++       Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), jcr->where);
++       free_pool_memory(where);
++       return 0;
++      }
++   }
     free_pool_memory(where);
     jcr->replace = replace;
     jcr->prefix_links = prefix_links;
 Index: src/jcr.h
 ===================================================================
---- src/jcr.h  (révision 4466)
+--- src/jcr.h  (révision 4529)
 +++ src/jcr.h  (copie de travail)
-@@ -173,6 +173,7 @@
+@@ -173,6 +173,8 @@
     MSGS *jcr_msgs;                    /* Copy of message resource -- actually used */
     uint32_t ClientId;                 /* Client associated with Job */
     char *where;                       /* prefix to restore files to */
++   bool where_use_regexp;             /* True if where is a bregexp */
 +   alist *where_bregexp;              /* BREGEXP alist for path manipulation */
     int cached_pnl;                    /* cached path length */
     POOLMEM *cached_path;              /* cached path */
     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 4529)
 +++ src/lib/Makefile.in        (copie de travail)
 @@ -32,7 +32,7 @@
          res.c rwlock.c scan.c serial.c sha1.c \
@@ -55,7 +761,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 4529)
 +++ src/lib/attr.c     (copie de travail)
 @@ -35,8 +35,8 @@
  
@@ -86,13 +792,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 {
@@ -100,7 +806,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 4529)
 +++ src/lib/jcr.c      (copie de travail)
 @@ -56,6 +56,9 @@
  /* External variables we reference */
@@ -124,112 +830,3 @@ Index: src/lib/jcr.c
     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 4483)
-+++ patches/testing/breg.c     (copie de travail)
-@@ -52,9 +52,6 @@
-       return NULL;
-    }
--   static int _start[RE_NREGS];
--   static int _end[RE_NREGS];
--
-    self->result = get_pool_memory(PM_FNAME);
-    self->result[0] = '\0';
-@@ -102,15 +99,20 @@
- /* Apply all regexps to fname
-  */
--char *apply_bregexps(const char *fname, alist *bregexps)
-+bool apply_bregexps(const char *fname, alist *bregexps, char **result)
- {
-    BREGEXP *elt;
-+   bool ok=false;
-+
-    char *ret = (char *) fname;
-    foreach_alist(elt, bregexps) {
-       ret = elt->replace(ret);
-+      ok = ok || elt->success;
-    }
-    Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
--   return ret;
-+
-+   *result = ret;
-+   return ok;
- }
- /* return an alist of BREGEXP or return NULL if it's not a 
-@@ -149,7 +151,7 @@
-    if (!(sep == '!' || 
-        sep == ':' || 
-        sep == ';' || 
--       sep == '§' || 
-+       sep == '|' || 
-        sep == ',' || 
-        sep == '&' || 
-        sep == '%' || 
-@@ -163,7 +165,6 @@
-    char *search = (char *) motif + 1;
-    int options = REG_EXTENDED | REG_NEWLINE;
-    bool ok = false;
--   bool found_motif = false;
-    /* extract 1st part */
-    char *dest = expr = bstrdup(motif);
-@@ -234,6 +235,7 @@
- /* return regexp->result */
- char *BREGEXP::replace(const char *fname)
- {
-+   success = false;           /* use this.success to known if it's ok */
-    int flen = strlen(fname);
-    int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, &regs);
-@@ -247,7 +249,7 @@
-    if (len) {
-       result = check_pool_memory_size(result, len);
-       edit_subst(fname, &regs);
--
-+      success = true;
-       Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
-    } else {                   /* error in substitution */
-Index: patches/testing/bregtest.c
-===================================================================
---- patches/testing/bregtest.c (révision 4472)
-+++ patches/testing/bregtest.c (copie de travail)
-@@ -135,7 +135,7 @@
-    while (fgets(data, sizeof(data)-1, fd)) {
-       strip_trailing_newline(data);
--      p = apply_bregexps(data, list);
-+      apply_bregexps(data, list, &p);
-       printf("%s => %s\n", data, p);
-    }
-    fclose(fd);
-Index: patches/testing/breg.h
-===================================================================
---- patches/testing/breg.h     (révision 4472)
-+++ patches/testing/breg.h     (copie de travail)
-@@ -60,7 +60,9 @@
- class BREGEXP {
- public:
-    POOLMEM *result;           /* match result */
--   char *replace(const char *fname);
-+   bool success;              /* match is ok */
-+
-+   char *replace(const char *fname); /* return this.result */
-    void debug();
-    /* private */
-@@ -90,7 +92,8 @@
- /* fill an alist with BREGEXP from where */
- alist *get_bregexps(const char *where);
--char *apply_bregexps(const char *fname, alist *bregexps);
-+/* apply every regexps from the alist */
-+bool apply_bregexps(const char *fname, alist *bregexps, char **result);
- /* foreach_alist free RUNSCRIPT */
- void free_bregexps(alist *bregexps); /* you have to free alist */