]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/file_relocation.patch
ebl fix spaces
[bacula/bacula] / bacula / patches / testing / file_relocation.patch
1 Index: src/dird/ua_restore.c
2 ===================================================================
3 --- src/dird/ua_restore.c       (révision 4466)
4 +++ src/dird/ua_restore.c       (copie de travail)
5 @@ -43,8 +43,8 @@
6  
7  #include "bacula.h"
8  #include "dird.h"
9 +#include "lib/breg.h"
10  
11 -
12  /* Imported functions */
13  extern void print_bsr(UAContext *ua, RBSR *bsr);
14  
15 @@ -83,6 +83,10 @@
16     JCR *jcr = ua->jcr;
17     char *escaped_bsr_name = NULL;
18     char *escaped_where_name = NULL;
19 +   bool where_use_regexp = false;
20 +   bool have_to_free_where = false;
21 +   char *strip_prefix, *add_prefix, *add_suffix;
22 +   strip_prefix = add_prefix = add_suffix = NULL;
23  
24     memset(&rx, 0, sizeof(rx));
25     rx.path = get_pool_memory(PM_FNAME);
26 @@ -94,6 +98,41 @@
27     i = find_arg_with_value(ua, "where");
28     if (i >= 0) {
29        rx.where = ua->argv[i];
30 +   }
31 +
32 +   i = find_arg_with_value(ua, "strip_prefix");
33 +   if (i >= 0) {
34 +      strip_prefix = ua->argv[i];
35 +   }
36 +
37 +   i = find_arg_with_value(ua, "add_prefix");
38 +   if (i >= 0) {
39 +      add_prefix = ua->argv[i];
40 +   }
41 +
42 +   i = find_arg_with_value(ua, "add_suffix");
43 +   if (i >= 0) {
44 +      add_suffix = ua->argv[i];
45 +   }
46 +
47 +   i = find_arg(ua, "where_use_regexp");
48 +   if (i >= 0) {
49 +      where_use_regexp = true;
50 +   }
51 +
52 +   i = find_arg_with_value(ua, "rwhere");
53 +   if (i >= 0) {
54 +      where_use_regexp = true;
55 +      rx.where = ua->argv[i];
56 +   }
57 +
58 +   if (strip_prefix || add_suffix || add_prefix) {
59 +      where_use_regexp = true;
60 +      have_to_free_where = true;
61 +      rx.where = bregexp_build_where(strip_prefix, add_prefix, add_suffix);
62 +   }
63 +
64 +   if (rx.where) {
65        if (!acl_access_ok(ua, Where_ACL, rx.where)) {
66           ua->error_msg(_("\"where\" specification not authorized.\n"));
67           goto bail_out;
68 @@ -195,9 +234,10 @@
69  
70        Mmsg(ua->cmd,
71            "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
72 -          " where=\"%s\" files=%d catalog=\"%s\"",
73 +          " %swhere=\"%s\" files=%d catalog=\"%s\"",
74            job->name(), rx.ClientName, rx.store?rx.store->name():"",
75            escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
76 +          where_use_regexp ? "r" : "",
77            escaped_where_name ? escaped_where_name : rx.where,
78            rx.selected_files, ua->catalog->name());
79     } else {
80 @@ -216,6 +256,10 @@
81     if (escaped_where_name != NULL) {
82        bfree(escaped_where_name);
83     }
84 +   
85 +   if (have_to_free_where) {
86 +      free_pool_memory(rx.where);
87 +   }
88  
89     if (find_arg(ua, NT_("yes")) > 0) {
90        pm_strcat(ua->cmd, " yes");    /* pass it on to the run command */
91 @@ -235,6 +279,10 @@
92        bfree(escaped_where_name);
93     }
94  
95 +   if (have_to_free_where) {
96 +      free_pool_memory(rx.where);
97 +   }
98 +
99     free_rx(&rx);
100     return 0;
101  
102 @@ -331,23 +379,28 @@
103  
104     const char *kw[] = {
105         /* These keywords are handled in a for loop */
106 -      "jobid",     /* 0 */
107 -      "current",   /* 1 */
108 -      "before",    /* 2 */
109 -      "file",      /* 3 */
110 -      "directory", /* 4 */
111 -      "select",    /* 5 */
112 -      "pool",      /* 6 */
113 -      "all",       /* 7 */
114 +      "jobid",       /* 0 */
115 +      "current",     /* 1 */
116 +      "before",      /* 2 */
117 +      "file",        /* 3 */
118 +      "directory",   /* 4 */
119 +      "select",      /* 5 */
120 +      "pool",        /* 6 */
121 +      "all",         /* 7 */
122  
123        /* The keyword below are handled by individual arg lookups */
124 -      "client",    /* 8 */
125 -      "storage",   /* 9 */
126 -      "fileset",   /* 10 */
127 -      "where",     /* 11 */
128 -      "yes",       /* 12 */
129 -      "bootstrap", /* 13 */
130 -      "done",      /* 14 */
131 +      "client",       /* 8 */
132 +      "storage",      /* 9 */
133 +      "fileset",      /* 10 */
134 +      "where",        /* 11 */
135 +      "yes",          /* 12 */
136 +      "bootstrap",    /* 13 */
137 +      "done",         /* 14 */
138 +      "strip_prefix", /* 15 */
139 +      "add_prefix",   /* 16 */
140 +      "add_suffix",   /* 17 */
141 +      "where_use_regexp",/* 18 */
142 +      "rwhere",       /* 19 like where + where_use_regexp */
143        NULL
144     };
145  
146 Index: src/dird/restore.c
147 ===================================================================
148 --- src/dird/restore.c  (révision 4466)
149 +++ src/dird/restore.c  (copie de travail)
150 @@ -50,8 +50,9 @@
151  #include "dird.h"
152  
153  /* Commands sent to File daemon */
154 -static char restorecmd[]   = "restore replace=%c prelinks=%d where=%s\n";
155 -static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
156 +static char restorecmd[]        = "restore replace=%c prelinks=%d where=%s\n";
157 +static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
158 +static char storaddr[]   = "storage address=%s port=%d ssl=0\n";
159  
160  /* Responses received from File daemon */
161  static char OKrestore[]   = "2000 OK restore\n";
162 @@ -172,7 +173,7 @@
163     }
164  
165     /* Send restore command */
166 -   char replace, *where;
167 +   char replace, *where, *cmd;
168     char empty = '\0';
169  
170     if (jcr->replace != 0) {
171 @@ -189,9 +190,17 @@
172     } else {
173        where = ∅                 /* None */
174     }
175 +   
176     jcr->prefix_links = jcr->job->PrefixLinks;
177 +
178 +   if (jcr->where_use_regexp) {
179 +      cmd = restorecmdR;
180 +   } else {
181 +      cmd = restorecmd;
182 +   }
183 +
184     bash_spaces(where);
185 -   bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
186 +   bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
187     unbash_spaces(where);
188  
189     if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
190 Index: src/dird/dird_conf.c
191 ===================================================================
192 --- src/dird/dird_conf.c        (révision 4466)
193 +++ src/dird/dird_conf.c        (copie de travail)
194 @@ -52,6 +52,7 @@
195  
196  #include "bacula.h"
197  #include "dird.h"
198 +#include "lib/breg.h"
199  
200  /* Define the first and last resource ID record
201   * types. Note, these should be unique for each
202 @@ -268,6 +269,10 @@
203     {"run",       store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
204     /* Root of where to restore files */
205     {"where",    store_dir,      ITEM(res_job.RestoreWhere), 0, 0, 0},
206 +   {"whereuseregexp", store_bool, ITEM(res_job.where_use_regexp), 0, 0, 0},
207 +   {"stripprefix",    store_str,  ITEM(res_job.strip_prefix), 0, 0, 0},
208 +   {"addprefix",    store_str,  ITEM(res_job.add_prefix), 0, 0, 0},
209 +   {"addsuffix",    store_str,  ITEM(res_job.add_suffix), 0, 0, 0},
210     /* Where to find bootstrap during restore */
211     {"bootstrap",store_dir,      ITEM(res_job.RestoreBootstrap), 0, 0, 0},
212     /* Where to write bootstrap file during backup */
213 @@ -611,6 +616,9 @@
214        if (res->res_job.RestoreWhere) {
215           sendit(sock, _("  --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
216        }
217 +      if (res->res_job.where_use_regexp) {
218 +         sendit(sock, _("  --> RWhere=%u\n"), res->res_job.where_use_regexp);
219 +      }
220        if (res->res_job.RestoreBootstrap) {
221           sendit(sock, _("  --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap));
222        }
223 @@ -1143,6 +1151,15 @@
224        if (res->res_job.RestoreWhere) {
225           free(res->res_job.RestoreWhere);
226        }
227 +      if (res->res_job.strip_prefix) {
228 +         free(res->res_job.strip_prefix);
229 +      }
230 +      if (res->res_job.add_prefix) {
231 +         free(res->res_job.add_prefix);
232 +      }
233 +      if (res->res_job.add_suffix) {
234 +         free(res->res_job.add_suffix);
235 +      }
236        if (res->res_job.RestoreBootstrap) {
237           free(res->res_job.RestoreBootstrap);
238        }
239 @@ -1299,6 +1316,19 @@
240           res->res_job.jobdefs    = res_all.res_job.jobdefs;
241           res->res_job.run_cmds   = res_all.res_job.run_cmds;
242           res->res_job.RunScripts = res_all.res_job.RunScripts;
243 +        if (res->res_job.strip_prefix ||
244 +            res->res_job.add_suffix   ||
245 +            res->res_job.add_prefix)
246 +        {
247 +           if (res->res_job.RestoreWhere) {
248 +              free(res->res_job.RestoreWhere);
249 +           }
250 +           res->res_job.where_use_regexp = true;
251 +           res->res_job.RestoreWhere=bregexp_build_where(res->res_job.strip_prefix,
252 +                                                         res->res_job.add_prefix,
253 +                                                         res->res_job.add_suffix);
254 +           /* TODO: test bregexp */
255 +        }
256           break;
257        case R_COUNTER:
258           if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
259 Index: src/dird/ua_run.c
260 ===================================================================
261 --- src/dird/ua_run.c   (révision 4466)
262 +++ src/dird/ua_run.c   (copie de travail)
263 @@ -71,6 +71,7 @@
264     int Priority = 0;
265     int i, j, opt, files = 0;
266     bool kw_ok;
267 +   bool where_use_regexp = false;
268     JOB *job = NULL;
269     JOB *verify_job = NULL;
270     JOB *previous_job = NULL;
271 @@ -87,7 +88,7 @@
272        "level",                        /* 5 */
273        "storage",                      /* 6 */
274        "sd",                           /* 7 */
275 -      "pool",                         /* 8 */
276 +      "rwhere",                       /* 8 where string as a bregexp */
277        "where",                        /* 9 */
278        "bootstrap",                    /* 10 */
279        "replace",                      /* 11 */
280 @@ -101,6 +102,7 @@
281        "cloned",                       /* 19 cloned */
282        "verifylist",                   /* 20 verify output list */
283        "migrationjob",                 /* 21 migration job name */
284 +      "pool",                         /* 22 */
285        NULL};
286  
287  #define YES_POS 14
288 @@ -188,14 +190,8 @@
289                 store_name = ua->argv[i];
290                 kw_ok = true;
291                 break;
292 -            case 8: /* pool */
293 -               if (pool_name) {
294 -                  ua->send_msg(_("Pool specified twice.\n"));
295 -                  return 0;
296 -               }
297 -               pool_name = ua->argv[i];
298 -               kw_ok = true;
299 -               break;
300 +            case 8: /* rwhere */
301 +               where_use_regexp = true;
302              case 9: /* where */
303                 if (where) {
304                    ua->send_msg(_("Where specified twice.\n"));
305 @@ -287,8 +283,15 @@
306                 previous_job_name = ua->argv[i];
307                 kw_ok = true;
308                 break;
309 +            case 22: /* pool */
310 +               if (pool_name) {
311 +                  ua->send_msg(_("Pool specified twice.\n"));
312 +                  return 0;
313 +               }
314 +               pool_name = ua->argv[i];
315 +               kw_ok = true;
316 +               break;
317  
318 -
319              default:
320                 break;
321              }
322 @@ -478,6 +481,7 @@
323           free(jcr->where);
324        }
325        jcr->where = bstrdup(where);
326 +      jcr->where_use_regexp = where_use_regexp;
327     }
328  
329     if (when) {
330 Index: src/dird/dird_conf.h
331 ===================================================================
332 --- src/dird/dird_conf.h        (révision 4466)
333 +++ src/dird/dird_conf.h        (copie de travail)
334 @@ -356,6 +356,10 @@
335     int   Priority;                    /* Job priority */
336     int   RestoreJobId;                /* What -- JobId to restore */
337     char *RestoreWhere;                /* Where on disk to restore -- directory */
338 +   char *strip_prefix;                /* remove prefix from filename  */
339 +   char *add_prefix;                  /* add prefix to filename  */
340 +   char *add_suffix;                  /* add suffix to filename -- .old */
341 +   bool  where_use_regexp;            /* true if RestoreWhere is a BREGEXP */
342     char *RestoreBootstrap;            /* Bootstrap file */
343     alist *RunScripts;                 /* Run {client} program {after|before} Job */
344     union {
345 Index: src/filed/job.c
346 ===================================================================
347 --- src/filed/job.c     (révision 4467)
348 +++ src/filed/job.c     (copie de travail)
349 @@ -36,6 +36,7 @@
350  
351  #include "bacula.h"
352  #include "filed.h"
353 +#include "lib/breg.h"
354  
355  #if defined(WIN32_VSS)
356  #include "vss.h"
357 @@ -115,6 +116,7 @@
358  static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
359  static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
360  static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
361 +static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
362  static char verifycmd[]   = "verify level=%30s";
363  static char estimatecmd[] = "estimate listing=%d";
364  static char runbefore[]   = "RunBeforeJob %s";
365 @@ -1586,12 +1588,15 @@
366     *where = 0;
367  
368     if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
369 -      if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
370 -         pm_strcpy(jcr->errmsg, dir->msg);
371 -         Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
372 -         return 0;
373 +      if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, where) != 3){
374 +         if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
375 +            pm_strcpy(jcr->errmsg, dir->msg);
376 +            Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
377 +            return 0;
378 +         }
379 +         *where = 0;
380        }
381 -      *where = 0;
382 +      jcr->where_use_regexp = true;
383     }
384     /* Turn / into nothing */
385     if (IsPathSeparator(where[0]) && where[1] == '\0') {
386 @@ -1601,6 +1606,15 @@
387     Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
388     unbash_spaces(where);
389     jcr->where = bstrdup(where);
390 +
391 +   if (jcr->where_use_regexp) {
392 +      jcr->where_bregexp = get_bregexps(jcr->where);
393 +      if (!jcr->where_bregexp) {
394 +        Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), jcr->where);
395 +        free_pool_memory(where);
396 +        return 0;
397 +      }
398 +   }
399     free_pool_memory(where);
400     jcr->replace = replace;
401     jcr->prefix_links = prefix_links;
402 Index: src/jcr.h
403 ===================================================================
404 --- src/jcr.h   (révision 4466)
405 +++ src/jcr.h   (copie de travail)
406 @@ -173,6 +173,8 @@
407     MSGS *jcr_msgs;                    /* Copy of message resource -- actually used */
408     uint32_t ClientId;                 /* Client associated with Job */
409     char *where;                       /* prefix to restore files to */
410 +   bool where_use_regexp;             /* True if where is a bregexp */
411 +   alist *where_bregexp;              /* BREGEXP alist for path manipulation */
412     int cached_pnl;                    /* cached path length */
413     POOLMEM *cached_path;              /* cached path */
414     bool prefix_links;                 /* Prefix links with Where path */
415 Index: src/lib/Makefile.in
416 ===================================================================
417 --- src/lib/Makefile.in (révision 4466)
418 +++ src/lib/Makefile.in (copie de travail)
419 @@ -32,7 +32,7 @@
420           res.c rwlock.c scan.c serial.c sha1.c \
421           signal.c smartall.c rblist.c tls.c tree.c \
422           util.c var.c watchdog.c workq.c btimers.c \
423 -         address_conf.c pythonlib.c
424 +         address_conf.c pythonlib.c breg.c
425  
426  
427  LIBOBJS = attr.o base64.o berrno.o bsys.o bget_msg.o \
428 @@ -45,7 +45,7 @@
429           res.o rwlock.o scan.o serial.o sha1.o \
430           signal.o smartall.o rblist.o tls.o tree.o \
431           util.o var.o watchdog.o workq.o btimers.o \
432 -         address_conf.o pythonlib.o
433 +         address_conf.o pythonlib.o breg.o
434  
435  
436  EXTRAOBJS = @OBJLIST@
437 Index: src/lib/attr.c
438 ===================================================================
439 --- src/lib/attr.c      (révision 4466)
440 +++ src/lib/attr.c      (copie de travail)
441 @@ -35,8 +35,8 @@
442  
443  #include "bacula.h"
444  #include "jcr.h"
445 +#include "lib/breg.h"
446  
447 -
448  ATTR *new_attr()
449  {
450     ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
451 @@ -148,9 +148,30 @@
452      *   every filename if a prefix is supplied.
453      *
454      */
455 +
456     if (jcr->where[0] == 0) {
457        pm_strcpy(attr->ofname, attr->fname);
458        pm_strcpy(attr->olname, attr->lname);
459 +
460 +   } else if (jcr->where_bregexp) { 
461 +      char *ret;
462 +      apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
463 +      pm_strcpy(attr->ofname, ret);
464 +
465 +      if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
466 +         /* Always add prefix to hard links (FT_LNKSAVED) and
467 +          *  on user request to soft links
468 +          */
469 +
470 +         if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
471 +            apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
472 +            pm_strcpy(attr->olname, ret);
473 +
474 +         } else {
475 +            pm_strcpy(attr->olname, attr->lname);
476 +         }
477 +      }
478 +      
479     } else {
480        const char *fn;
481        int wherelen = strlen(jcr->where);
482 Index: src/lib/jcr.c
483 ===================================================================
484 --- src/lib/jcr.c       (révision 4466)
485 +++ src/lib/jcr.c       (copie de travail)
486 @@ -56,6 +56,9 @@
487  /* External variables we reference */
488  extern time_t watchdog_time;
489  
490 +/* External referenced functions */
491 +void free_bregexps(alist *bregexps);
492 +
493  /* Forward referenced functions */
494  extern "C" void timeout_handler(int sig);
495  static void jcr_timeout_check(watchdog_t *self);
496 @@ -381,6 +384,11 @@
497        free(jcr->where);
498        jcr->where = NULL;
499     }
500 +   if (jcr->where_bregexp) {
501 +      free_bregexps(jcr->where_bregexp);
502 +      delete jcr->where_bregexp;
503 +      jcr->where_bregexp = NULL;
504 +   }
505     if (jcr->cached_path) {
506        free_pool_memory(jcr->cached_path);
507        jcr->cached_path = NULL;
508 Index: patches/testing/file_relocation.patch
509 ===================================================================
510 --- patches/testing/file_relocation.patch       (révision 4515)
511 +++ patches/testing/file_relocation.patch       (copie de travail)
512 @@ -73,7 +73,7 @@
513  +          " %swhere=\"%s\" files=%d catalog=\"%s\"",
514             job->name(), rx.ClientName, rx.store?rx.store->name():"",
515             escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
516 -+        where_use_regexp ? "r" : "",
517 ++          where_use_regexp ? "r" : "",
518             escaped_where_name ? escaped_where_name : rx.where,
519             rx.selected_files, ua->catalog->name());
520      } else {
521 @@ -297,8 +297,8 @@
522  -               pool_name = ua->argv[i];
523  -               kw_ok = true;
524  -               break;
525 -+          case 8:
526 -+             where_use_regexp = true;
527 ++            case 8: /* rwhere */
528 ++               where_use_regexp = true;
529               case 9: /* where */
530                  if (where) {
531                     ua->send_msg(_("Where specified twice.\n"));
532 @@ -371,12 +371,12 @@
533  -         Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
534  -         return 0;
535  +      if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, where) != 3){
536 -+       if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
537 -+          pm_strcpy(jcr->errmsg, dir->msg);
538 -+          Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
539 -+          return 0;
540 -+       }
541 -+       *where = 0;
542 ++         if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
543 ++            pm_strcpy(jcr->errmsg, dir->msg);
544 ++            Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
545 ++            return 0;
546 ++         }
547 ++         *where = 0;
548         }
549  -      *where = 0;
550  +      jcr->where_use_regexp = true;
551 @@ -467,13 +467,13 @@
552  +          *  on user request to soft links
553  +          */
554  +
555 -+       if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
556 -+          apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
557 -+          pm_strcpy(attr->olname, ret);
558 ++         if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
559 ++            apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
560 ++            pm_strcpy(attr->olname, ret);
561  +
562 -+       } else {
563 -+          pm_strcpy(attr->olname, attr->lname);
564 -+       }
565 ++         } else {
566 ++            pm_strcpy(attr->olname, attr->lname);
567 ++         }
568  +      }
569  +      
570      } else {
571 @@ -505,253 +505,3 @@
572      if (jcr->cached_path) {
573         free_pool_memory(jcr->cached_path);
574         jcr->cached_path = NULL;
575 -Index: patches/testing/file_relocation.patch
576 -===================================================================
577 ---- patches/testing/file_relocation.patch      (révision 4514)
578 -+++ patches/testing/file_relocation.patch      (copie de travail)
579 -@@ -12,17 +12,18 @@
580 -  /* Imported functions */
581 -  extern void print_bsr(UAContext *ua, RBSR *bsr);
582 -  
583 --@@ -83,6 +83,9 @@
584 -+@@ -83,6 +83,10 @@
585 -     JCR *jcr = ua->jcr;
586 -     char *escaped_bsr_name = NULL;
587 -     char *escaped_where_name = NULL;
588 - +   bool where_use_regexp = false;
589 -++   bool have_to_free_where = false;
590 - +   char *strip_prefix, *add_prefix, *add_suffix;
591 - +   strip_prefix = add_prefix = add_suffix = NULL;
592 -  
593 -     memset(&rx, 0, sizeof(rx));
594 -     rx.path = get_pool_memory(PM_FNAME);
595 --@@ -94,6 +97,29 @@
596 -+@@ -94,6 +98,41 @@
597 -     i = find_arg_with_value(ua, "where");
598 -     if (i >= 0) {
599 -        rx.where = ua->argv[i];
600 -@@ -43,8 +44,20 @@
601 - +      add_suffix = ua->argv[i];
602 - +   }
603 - +
604 -++   i = find_arg(ua, "where_use_regexp");
605 -++   if (i >= 0) {
606 -++      where_use_regexp = true;
607 -++   }
608 -++
609 -++   i = find_arg_with_value(ua, "rwhere");
610 -++   if (i >= 0) {
611 -++      where_use_regexp = true;
612 -++      rx.where = ua->argv[i];
613 -++   }
614 -++
615 - +   if (strip_prefix || add_suffix || add_prefix) {
616 - +      where_use_regexp = true;
617 -++      have_to_free_where = true;
618 - +      rx.where = bregexp_build_where(strip_prefix, add_prefix, add_suffix);
619 - +   }
620 - +
621 -@@ -52,7 +65,7 @@
622 -        if (!acl_access_ok(ua, Where_ACL, rx.where)) {
623 -           ua->error_msg(_("\"where\" specification not authorized.\n"));
624 -           goto bail_out;
625 --@@ -195,9 +221,10 @@
626 -+@@ -195,9 +234,10 @@
627 -  
628 -        Mmsg(ua->cmd,
629 -            "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
630 -@@ -64,28 +77,72 @@
631 -            escaped_where_name ? escaped_where_name : rx.where,
632 -            rx.selected_files, ua->catalog->name());
633 -     } else {
634 --@@ -216,6 +243,10 @@
635 -+@@ -216,6 +256,10 @@
636 -     if (escaped_where_name != NULL) {
637 -        bfree(escaped_where_name);
638 -     }
639 - +   
640 --+   if (where_use_regexp) {
641 -++   if (have_to_free_where) {
642 - +      free_pool_memory(rx.where);
643 - +   }
644 -  
645 -     if (find_arg(ua, NT_("yes")) > 0) {
646 -        pm_strcat(ua->cmd, " yes");    /* pass it on to the run command */
647 --@@ -235,6 +266,10 @@
648 -+@@ -235,6 +279,10 @@
649 -        bfree(escaped_where_name);
650 -     }
651 -  
652 --+   if (where_use_regexp) {
653 -++   if (have_to_free_where) {
654 - +      free_pool_memory(rx.where);
655 - +   }
656 - +
657 -     free_rx(&rx);
658 -     return 0;
659 -  
660 -+@@ -331,23 +379,28 @@
661 -+ 
662 -+    const char *kw[] = {
663 -+        /* These keywords are handled in a for loop */
664 -+-      "jobid",     /* 0 */
665 -+-      "current",   /* 1 */
666 -+-      "before",    /* 2 */
667 -+-      "file",      /* 3 */
668 -+-      "directory", /* 4 */
669 -+-      "select",    /* 5 */
670 -+-      "pool",      /* 6 */
671 -+-      "all",       /* 7 */
672 -++      "jobid",       /* 0 */
673 -++      "current",     /* 1 */
674 -++      "before",      /* 2 */
675 -++      "file",        /* 3 */
676 -++      "directory",   /* 4 */
677 -++      "select",      /* 5 */
678 -++      "pool",        /* 6 */
679 -++      "all",         /* 7 */
680 -+ 
681 -+       /* The keyword below are handled by individual arg lookups */
682 -+-      "client",    /* 8 */
683 -+-      "storage",   /* 9 */
684 -+-      "fileset",   /* 10 */
685 -+-      "where",     /* 11 */
686 -+-      "yes",       /* 12 */
687 -+-      "bootstrap", /* 13 */
688 -+-      "done",      /* 14 */
689 -++      "client",       /* 8 */
690 -++      "storage",      /* 9 */
691 -++      "fileset",      /* 10 */
692 -++      "where",        /* 11 */
693 -++      "yes",          /* 12 */
694 -++      "bootstrap",    /* 13 */
695 -++      "done",         /* 14 */
696 -++      "strip_prefix", /* 15 */
697 -++      "add_prefix",   /* 16 */
698 -++      "add_suffix",   /* 17 */
699 -++      "where_use_regexp",/* 18 */
700 -++      "rwhere",       /* 19 like where + where_use_regexp */
701 -+       NULL
702 -+    };
703 -+ 
704 - Index: src/dird/restore.c
705 - ===================================================================
706 - --- src/dird/restore.c        (révision 4466)
707 -@@ -134,15 +191,26 @@
708 - ===================================================================
709 - --- src/dird/dird_conf.c      (révision 4466)
710 - +++ src/dird/dird_conf.c      (copie de travail)
711 --@@ -268,6 +268,7 @@
712 -+@@ -52,6 +52,7 @@
713 -+ 
714 -+ #include "bacula.h"
715 -+ #include "dird.h"
716 -++#include "lib/breg.h"
717 -+ 
718 -+ /* Define the first and last resource ID record
719 -+  * types. Note, these should be unique for each
720 -+@@ -268,6 +269,10 @@
721 -     {"run",       store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
722 -     /* Root of where to restore files */
723 -     {"where",    store_dir,      ITEM(res_job.RestoreWhere), 0, 0, 0},
724 - +   {"whereuseregexp", store_bool, ITEM(res_job.where_use_regexp), 0, 0, 0},
725 -++   {"stripprefix",    store_str,  ITEM(res_job.strip_prefix), 0, 0, 0},
726 -++   {"addprefix",    store_str,  ITEM(res_job.add_prefix), 0, 0, 0},
727 -++   {"addsuffix",    store_str,  ITEM(res_job.add_suffix), 0, 0, 0},
728 -     /* Where to find bootstrap during restore */
729 -     {"bootstrap",store_dir,      ITEM(res_job.RestoreBootstrap), 0, 0, 0},
730 -     /* Where to write bootstrap file during backup */
731 --@@ -611,6 +612,9 @@
732 -+@@ -611,6 +616,9 @@
733 -        if (res->res_job.RestoreWhere) {
734 -           sendit(sock, _("  --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
735 -        }
736 -@@ -152,6 +220,42 @@
737 -        if (res->res_job.RestoreBootstrap) {
738 -           sendit(sock, _("  --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap));
739 -        }
740 -+@@ -1143,6 +1151,15 @@
741 -+       if (res->res_job.RestoreWhere) {
742 -+          free(res->res_job.RestoreWhere);
743 -+       }
744 -++      if (res->res_job.strip_prefix) {
745 -++         free(res->res_job.strip_prefix);
746 -++      }
747 -++      if (res->res_job.add_prefix) {
748 -++         free(res->res_job.add_prefix);
749 -++      }
750 -++      if (res->res_job.add_suffix) {
751 -++         free(res->res_job.add_suffix);
752 -++      }
753 -+       if (res->res_job.RestoreBootstrap) {
754 -+          free(res->res_job.RestoreBootstrap);
755 -+       }
756 -+@@ -1299,6 +1316,19 @@
757 -+          res->res_job.jobdefs    = res_all.res_job.jobdefs;
758 -+          res->res_job.run_cmds   = res_all.res_job.run_cmds;
759 -+          res->res_job.RunScripts = res_all.res_job.RunScripts;
760 -++      if (res->res_job.strip_prefix ||
761 -++          res->res_job.add_suffix   ||
762 -++          res->res_job.add_prefix)
763 -++      {
764 -++         if (res->res_job.RestoreWhere) {
765 -++            free(res->res_job.RestoreWhere);
766 -++         }
767 -++         res->res_job.where_use_regexp = true;
768 -++         res->res_job.RestoreWhere=bregexp_build_where(res->res_job.strip_prefix,
769 -++                                                       res->res_job.add_prefix,
770 -++                                                       res->res_job.add_suffix);
771 -++         /* TODO: test bregexp */
772 -++      }
773 -+          break;
774 -+       case R_COUNTER:
775 -+          if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
776 - Index: src/dird/ua_run.c
777 - ===================================================================
778 - --- src/dird/ua_run.c (révision 4466)
779 -@@ -227,10 +331,13 @@
780 - ===================================================================
781 - --- src/dird/dird_conf.h      (révision 4466)
782 - +++ src/dird/dird_conf.h      (copie de travail)
783 --@@ -356,6 +356,7 @@
784 -+@@ -356,6 +356,10 @@
785 -     int   Priority;                    /* Job priority */
786 -     int   RestoreJobId;                /* What -- JobId to restore */
787 -     char *RestoreWhere;                /* Where on disk to restore -- directory */
788 -++   char *strip_prefix;                /* remove prefix from filename  */
789 -++   char *add_prefix;                  /* add prefix to filename  */
790 -++   char *add_suffix;                  /* add suffix to filename -- .old */
791 - +   bool  where_use_regexp;            /* true if RestoreWhere is a BREGEXP */
792 -     char *RestoreBootstrap;            /* Bootstrap file */
793 -     alist *RunScripts;                 /* Run {client} program {after|before} Job */
794 -@@ -398,30 +505,3 @@
795 -     if (jcr->cached_path) {
796 -        free_pool_memory(jcr->cached_path);
797 -        jcr->cached_path = NULL;
798 --Index: patches/testing/breg.c
799 --===================================================================
800 ----- patches/testing/breg.c    (révision 4510)
801 --+++ patches/testing/breg.c    (copie de travail)
802 --@@ -393,19 +393,19 @@
803 -- 
804 --    *str_tmp = *ret = '\0';
805 --    
806 ---   if (*strip_prefix) {
807 --+   if (strip_prefix) {
808 --       len += bsnprintf(ret, str_size - len, "!%s!!",
809 --                     bregexp_escape_string(str_tmp, strip_prefix, sep));
810 --    }
811 -- 
812 ---   if (*add_suffix) {
813 --+   if (add_suffix) {
814 --       if (len) ret[len++] = ',';
815 -- 
816 --       len += bsnprintf(ret + len,  str_size - len, "!([^/])$!$1%s!",
817 --                     bregexp_escape_string(str_tmp, add_suffix, sep));
818 --    }
819 -- 
820 ---   if (*add_prefix) {
821 --+   if (add_prefix) {
822 --       if (len) ret[len++] = ',';
823 -- 
824 --       len += bsnprintf(ret + len, str_size - len, "!^!%s!",