1 Index: src/dird/ua_restore.c
2 ===================================================================
3 --- src/dird/ua_restore.c (révision 4588)
4 +++ src/dird/ua_restore.c (copie de travail)
10 /* Imported functions */
11 extern void print_bsr(UAContext *ua, RBSR *bsr);
15 char *escaped_bsr_name = NULL;
16 char *escaped_where_name = NULL;
17 + bool where_use_regexp = false;
18 + char *strip_prefix, *add_prefix, *add_suffix, *regexp;
19 + strip_prefix = add_prefix = add_suffix = regexp = NULL;
21 memset(&rx, 0, sizeof(rx));
22 rx.path = get_pool_memory(PM_FNAME);
24 i = find_arg_with_value(ua, "where");
26 rx.where = ua->argv[i];
29 + i = find_arg_with_value(ua, "strip_prefix");
31 + strip_prefix = ua->argv[i];
34 + i = find_arg_with_value(ua, "add_prefix");
36 + add_prefix = ua->argv[i];
39 + i = find_arg_with_value(ua, "add_suffix");
41 + add_suffix = ua->argv[i];
44 + i = find_arg(ua, "where_use_regexp");
46 + where_use_regexp = true;
49 + i = find_arg_with_value(ua, "rwhere");
51 + where_use_regexp = true;
52 + rx.where = ua->argv[i];
55 + if (strip_prefix || add_suffix || add_prefix) {
56 + int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
57 + regexp = (char *) bmalloc (len * sizeof(char));
59 + bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
60 + where_use_regexp = true;
66 if (!acl_access_ok(ua, Where_ACL, rx.where)) {
67 ua->error_msg(_("\"where\" specification not authorized.\n"));
72 "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s\""
73 - " where=\"%s\" files=%d catalog=\"%s\"",
74 + " %swhere=\"%s\" files=%d catalog=\"%s\"",
75 job->name(), rx.ClientName, rx.store?rx.store->name():"",
76 escaped_bsr_name ? escaped_bsr_name : jcr->RestoreBootstrap,
77 + where_use_regexp ? "r" : "",
78 escaped_where_name ? escaped_where_name : rx.where,
79 rx.selected_files, ua->catalog->name());
82 if (escaped_where_name != NULL) {
83 bfree(escaped_where_name);
90 if (find_arg(ua, NT_("yes")) > 0) {
91 pm_strcat(ua->cmd, " yes"); /* pass it on to the run command */
93 bfree(escaped_where_name);
103 @@ -333,23 +383,28 @@
106 /* These keywords are handled in a for loop */
111 - "directory", /* 4 */
119 + "directory", /* 4 */
124 /* The keyword below are handled by individual arg lookups */
127 - "fileset", /* 10 */
130 - "bootstrap", /* 13 */
134 + "fileset", /* 10 */
137 + "bootstrap", /* 13 */
139 + "strip_prefix", /* 15 */
140 + "add_prefix", /* 16 */
141 + "add_suffix", /* 17 */
142 + "where_use_regexp",/* 18 */
143 + "rwhere", /* 19 like where + where_use_regexp */
147 Index: src/dird/restore.c
148 ===================================================================
149 --- src/dird/restore.c (révision 4588)
150 +++ src/dird/restore.c (copie de travail)
154 /* Commands sent to File daemon */
155 -static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
156 -static char storaddr[] = "storage address=%s port=%d ssl=0\n";
157 +static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
158 +static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
159 +static char storaddr[] = "storage address=%s port=%d ssl=0\n";
161 /* Responses received from File daemon */
162 static char OKrestore[] = "2000 OK restore\n";
166 /* Send restore command */
167 - char replace, *where;
168 + char replace, *where, *cmd;
171 if (jcr->replace != 0) {
174 where = ∅ /* None */
177 jcr->prefix_links = jcr->job->PrefixLinks;
179 + if (jcr->where_use_regexp) {
186 - bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
187 + bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
188 unbash_spaces(where);
190 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
191 Index: src/dird/dird.h
192 ===================================================================
193 --- src/dird/dird.h (révision 4588)
194 +++ src/dird/dird.h (copie de travail)
198 #include "lib/runscript.h"
199 +#include "lib/breg.h"
200 #include "dird_conf.h"
202 #define DIRECTOR_DAEMON 1
203 Index: src/dird/dird_conf.c
204 ===================================================================
205 --- src/dird/dird_conf.c (révision 4588)
206 +++ src/dird/dird_conf.c (copie de travail)
208 {"run", store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
209 /* Root of where to restore files */
210 {"where", store_dir, ITEM(res_job.RestoreWhere), 0, 0, 0},
211 + {"whereuseregexp", store_bool, ITEM(res_job.where_use_regexp), 0, 0, 0},
212 + {"stripprefix", store_str, ITEM(res_job.strip_prefix), 0, 0, 0},
213 + {"addprefix", store_str, ITEM(res_job.add_prefix), 0, 0, 0},
214 + {"addsuffix", store_str, ITEM(res_job.add_suffix), 0, 0, 0},
215 /* Where to find bootstrap during restore */
216 {"bootstrap",store_dir, ITEM(res_job.RestoreBootstrap), 0, 0, 0},
217 /* Where to write bootstrap file during backup */
219 if (res->res_job.RestoreWhere) {
220 sendit(sock, _(" --> Where=%s\n"), NPRT(res->res_job.RestoreWhere));
222 + if (res->res_job.where_use_regexp) {
223 + sendit(sock, _(" --> RWhere=%u\n"), res->res_job.where_use_regexp);
225 if (res->res_job.RestoreBootstrap) {
226 sendit(sock, _(" --> Bootstrap=%s\n"), NPRT(res->res_job.RestoreBootstrap));
228 @@ -1143,6 +1150,15 @@
229 if (res->res_job.RestoreWhere) {
230 free(res->res_job.RestoreWhere);
232 + if (res->res_job.strip_prefix) {
233 + free(res->res_job.strip_prefix);
235 + if (res->res_job.add_prefix) {
236 + free(res->res_job.add_prefix);
238 + if (res->res_job.add_suffix) {
239 + free(res->res_job.add_suffix);
241 if (res->res_job.RestoreBootstrap) {
242 free(res->res_job.RestoreBootstrap);
244 @@ -1299,6 +1315,25 @@
245 res->res_job.jobdefs = res_all.res_job.jobdefs;
246 res->res_job.run_cmds = res_all.res_job.run_cmds;
247 res->res_job.RunScripts = res_all.res_job.RunScripts;
248 + if (res->res_job.strip_prefix ||
249 + res->res_job.add_suffix ||
250 + res->res_job.add_prefix)
252 + if (res->res_job.RestoreWhere) {
253 + free(res->res_job.RestoreWhere);
255 + int len = bregexp_get_build_where_size(res->res_job.strip_prefix,
256 + res->res_job.add_prefix,
257 + res->res_job.add_suffix);
258 + res->res_job.RestoreWhere = (char *) bmalloc (len * sizeof(char));
259 + bregexp_build_where(res->res_job.RestoreWhere, len,
260 + res->res_job.strip_prefix,
261 + res->res_job.add_prefix,
262 + res->res_job.add_suffix);
263 + res->res_job.where_use_regexp = true;
265 + /* TODO: test bregexp */
269 if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
270 Index: src/dird/ua_run.c
271 ===================================================================
272 --- src/dird/ua_run.c (révision 4588)
273 +++ src/dird/ua_run.c (copie de travail)
275 static void select_job_level(UAContext *ua, JCR *jcr);
276 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, char *verify_list,
277 char *jid, const char *replace);
278 +static void select_where_regexp(UAContext *ua, JCR *jcr);
281 /* Imported variables */
284 int i, j, opt, files = 0;
286 + bool where_use_regexp = false;
288 JOB *verify_job = NULL;
289 JOB *previous_job = NULL;
295 + "rwhere", /* 8 where string as a bregexp */
297 "bootstrap", /* 10 */
300 "cloned", /* 19 cloned */
301 "verifylist", /* 20 verify output list */
302 "migrationjob", /* 21 migration job name */
307 @@ -188,15 +191,11 @@
308 store_name = ua->argv[i];
313 - ua->send_msg(_("Pool specified twice.\n"));
316 - pool_name = ua->argv[i];
319 + case 8: /* rwhere */
321 + /* TODO: this is ugly ... */
322 + where_use_regexp = (j == 9)?false:true; /* rwhere or where ? */
325 ua->send_msg(_("Where specified twice.\n"));
328 previous_job_name = ua->argv[i];
331 + case 22: /* pool */
333 + ua->send_msg(_("Pool specified twice.\n"));
336 + pool_name = ua->argv[i];
347 jcr->where = bstrdup(where);
348 + jcr->where_use_regexp = where_use_regexp;
353 } else if (jcr->JobType == JT_RESTORE) {
354 add_prompt(ua, _("Bootstrap")); /* 7 */
355 add_prompt(ua, _("Where")); /* 8 */
356 - add_prompt(ua, _("Replace")); /* 9 */
357 - add_prompt(ua, _("JobId")); /* 10 */
358 + add_prompt(ua, _("File Relocation"));/* 9 */
359 + add_prompt(ua, _("Replace")); /* 10 */
360 + add_prompt(ua, _("JobId")); /* 11 */
362 switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
367 jcr->where = bstrdup(ua->cmd);
368 + jcr->where_use_regexp = false;
372 + /* File relocation */
373 + select_where_regexp(ua, jcr);
377 start_prompt(ua, _("Replace:\n"));
378 for (i=0; ReplaceOptions[i].name; i++) {
380 jcr->replace = ReplaceOptions[opt].token;
386 jid = NULL; /* force reprompt */
387 jcr->RestoreJobId = 0;
388 @@ -775,6 +788,134 @@
389 return 0; /* do not run */
392 +static void select_where_regexp(UAContext *ua, JCR *jcr)
395 + char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
396 + strip_prefix = add_suffix = rwhere = add_prefix = NULL;
399 + ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
400 + NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
402 + start_prompt(ua, _("This will replace your current Where value\n"));
403 + add_prompt(ua, _("Strip prefix")); /* 0 */
404 + add_prompt(ua, _("Add prefix")); /* 1 */
405 + add_prompt(ua, _("Add file suffix")); /* 2 */
406 + add_prompt(ua, _("Enter a regexp")); /* 3 */
407 + add_prompt(ua, _("Test filename manipulation")); /* 4 */
408 + add_prompt(ua, _("Use this ?")); /* 5 */
410 + switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
413 + if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
414 + if (strip_prefix) bfree(strip_prefix);
415 + strip_prefix = bstrdup(ua->cmd);
418 + goto try_again_reg;
421 + if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
422 + if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
426 + if (add_prefix) bfree(add_prefix);
427 + add_prefix = bstrdup(ua->cmd);
429 + goto try_again_reg;
432 + if (get_cmd(ua, _("Please enter file suffix to add: "))) {
433 + if (add_suffix) bfree(add_suffix);
434 + add_suffix = bstrdup(ua->cmd);
436 + goto try_again_reg;
439 + if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
440 + if (rwhere) bfree(rwhere);
441 + rwhere = bstrdup(ua->cmd);
444 + goto try_again_reg;
450 + if (rwhere && rwhere[0] != '\0') {
451 + regs = get_bregexps(rwhere);
452 + ua->send_msg(_("rwhere=%s\n"), NPRT(rwhere));
454 + int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
455 + regexp = (char *) bmalloc (len * sizeof(char));
456 + bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
457 + regs = get_bregexps(regexp);
458 + ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
459 + NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
465 + ua->send_msg(_("Cannot use your regexp\n"));
466 + goto try_again_reg;
469 + while (get_cmd(ua, _("Please enter filename to test: "))) {
470 + apply_bregexps(ua->cmd, regs, &result);
471 + ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
473 + free_bregexps(regs);
475 + goto try_again_reg;
480 + case -1: /* error or cancel */
483 + goto try_again_reg;
486 + /* replace the existing where */
493 + jcr->where = bstrdup(rwhere);
494 + } else if (strip_prefix || add_prefix || add_suffix) {
495 + int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
496 + jcr->where = (char *) bmalloc(len*sizeof(char));
497 + bregexp_build_where(jcr->where, len, strip_prefix, add_prefix, add_suffix);
500 + regs = get_bregexps(jcr->where);
502 + free_bregexps(regs);
504 + jcr->where_use_regexp = true;
510 + ua->send_msg(_("Cannot use your regexp.\n"));
514 + if (strip_prefix) bfree(strip_prefix);
515 + if (add_prefix) bfree(add_prefix);
516 + if (add_suffix) bfree(add_suffix);
517 + if (rwhere) bfree(rwhere);
520 static void select_job_level(UAContext *ua, JCR *jcr)
522 if (jcr->JobType == JT_BACKUP) {
524 ua->send_msg(_("Run Restore job\n"
528 + "%s %s\n" /* Where or RWhere */
535 NPRT(jcr->RestoreBootstrap),
536 + jcr->where_use_regexp?"RWhere:":"Where: ",
537 jcr->where?jcr->where:NPRT(job->RestoreWhere),
539 jcr->fileset->name(),
541 ua->send_msg(_("Run Restore job\n"
545 + "%s %s\n" /* Where or RWhere */
552 NPRT(jcr->RestoreBootstrap),
553 + jcr->where_use_regexp?"RWhere:":"Where: ",
554 jcr->where?jcr->where:NPRT(job->RestoreWhere),
557 Index: src/dird/dird_conf.h
558 ===================================================================
559 --- src/dird/dird_conf.h (révision 4588)
560 +++ src/dird/dird_conf.h (copie de travail)
562 int Priority; /* Job priority */
563 int RestoreJobId; /* What -- JobId to restore */
564 char *RestoreWhere; /* Where on disk to restore -- directory */
565 + char *strip_prefix; /* remove prefix from filename */
566 + char *add_prefix; /* add prefix to filename */
567 + char *add_suffix; /* add suffix to filename -- .old */
568 + bool where_use_regexp; /* true if RestoreWhere is a BREGEXP */
569 char *RestoreBootstrap; /* Bootstrap file */
570 alist *RunScripts; /* Run {client} program {after|before} Job */
572 Index: src/filed/job.c
573 ===================================================================
574 --- src/filed/job.c (révision 4588)
575 +++ src/filed/job.c (copie de travail)
577 static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n";
578 static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
579 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
580 +static char restorecmdR[] = "restore replace=%c prelinks=%d rwhere=%s\n";
581 static char verifycmd[] = "verify level=%30s";
582 static char estimatecmd[] = "estimate listing=%d";
583 static char runbefore[] = "RunBeforeJob %s";
584 @@ -1586,12 +1587,15 @@
587 if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
588 - if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
589 - pm_strcpy(jcr->errmsg, dir->msg);
590 - Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
592 + if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, where) != 3){
593 + if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
594 + pm_strcpy(jcr->errmsg, dir->msg);
595 + Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
601 + jcr->where_use_regexp = true;
603 /* Turn / into nothing */
604 if (IsPathSeparator(where[0]) && where[1] == '\0') {
605 @@ -1601,6 +1605,15 @@
606 Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
607 unbash_spaces(where);
608 jcr->where = bstrdup(where);
610 + if (jcr->where_use_regexp) {
611 + jcr->where_bregexp = get_bregexps(jcr->where);
612 + if (!jcr->where_bregexp) {
613 + Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), jcr->where);
614 + free_pool_memory(where);
618 free_pool_memory(where);
619 jcr->replace = replace;
620 jcr->prefix_links = prefix_links;
621 Index: src/filed/filed.h
622 ===================================================================
623 --- src/filed/filed.h (révision 4588)
624 +++ src/filed/filed.h (copie de travail)
627 #include "protos.h" /* file daemon prototypes */
628 #include "lib/runscript.h"
629 +#include "lib/breg.h"
631 #include <zlib.h> /* compression headers */
634 ===================================================================
635 --- src/jcr.h (révision 4588)
636 +++ src/jcr.h (copie de travail)
638 MSGS *jcr_msgs; /* Copy of message resource -- actually used */
639 uint32_t ClientId; /* Client associated with Job */
640 char *where; /* prefix to restore files to */
641 + bool where_use_regexp; /* True if where is a bregexp */
642 + alist *where_bregexp; /* BREGEXP alist for path manipulation */
643 int cached_pnl; /* cached path length */
644 POOLMEM *cached_path; /* cached path */
645 bool prefix_links; /* Prefix links with Where path */
646 Index: src/lib/Makefile.in
647 ===================================================================
648 --- src/lib/Makefile.in (révision 4588)
649 +++ src/lib/Makefile.in (copie de travail)
651 res.c rwlock.c scan.c serial.c sha1.c \
652 signal.c smartall.c rblist.c tls.c tree.c \
653 util.c var.c watchdog.c workq.c btimers.c \
654 - address_conf.c pythonlib.c
655 + address_conf.c pythonlib.c breg.c
658 LIBOBJS = attr.o base64.o berrno.o bsys.o bget_msg.o \
660 res.o rwlock.o scan.o serial.o sha1.o \
661 signal.o smartall.o rblist.o tls.o tree.o \
662 util.o var.o watchdog.o workq.o btimers.o \
663 - address_conf.o pythonlib.o
664 + address_conf.o pythonlib.o breg.o
667 EXTRAOBJS = @OBJLIST@
668 Index: src/lib/attr.c
669 ===================================================================
670 --- src/lib/attr.c (révision 4588)
671 +++ src/lib/attr.c (copie de travail)
676 +#include "lib/breg.h"
681 ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
683 * every filename if a prefix is supplied.
687 if (jcr->where[0] == 0) {
688 pm_strcpy(attr->ofname, attr->fname);
689 pm_strcpy(attr->olname, attr->lname);
691 + } else if (jcr->where_bregexp) {
693 + apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
694 + pm_strcpy(attr->ofname, ret);
696 + if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
697 + /* Always add prefix to hard links (FT_LNKSAVED) and
698 + * on user request to soft links
701 + if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
702 + apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
703 + pm_strcpy(attr->olname, ret);
706 + pm_strcpy(attr->olname, attr->lname);
712 int wherelen = strlen(jcr->where);
714 ===================================================================
715 --- src/lib/jcr.c (révision 4588)
716 +++ src/lib/jcr.c (copie de travail)
718 /* External variables we reference */
719 extern time_t watchdog_time;
721 +/* External referenced functions */
722 +void free_bregexps(alist *bregexps);
724 /* Forward referenced functions */
725 extern "C" void timeout_handler(int sig);
726 static void jcr_timeout_check(watchdog_t *self);
731 + if (jcr->where_bregexp) {
732 + free_bregexps(jcr->where_bregexp);
733 + delete jcr->where_bregexp;
734 + jcr->where_bregexp = NULL;
736 if (jcr->cached_path) {
737 free_pool_memory(jcr->cached_path);
738 jcr->cached_path = NULL;