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