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