Item: 18 Quick release of FD-SD connection after backup.
Item: 40 Include JobID in spool file name
Item: 25 Implement huge exclude list support using dlist
+Item: 41 Enable to relocate files and directories when restoring
Summary:
Item: 1 Accurate restoration of renamed/deleted files
Item: 38 Include timestamp of job launch in "stat clients" output
Item: 39 Message mailing based on backup types
Item: 40* Include JobID in spool file name
-
+Item: 41* Enable to relocate files and directories when restoring
Item 1: Accurate restoration of renamed/deleted files
Date: 28 November 2005
stamp is useful (and should be retained).
============= New Freature Requests after vote of 26 Jan 2007 ========
-Item n: Enable to relocate files and directories when restoring
+Item 41: Enable to relocate files and directories when restoring
Date: 2007-03-01
Origin: Eric Bollengier <eric@eb.homelinux.org>
- Status:
+ Status: Done.
What: The where= option is not powerful enough. It will be
a great feature if bacula can restore a file in the
Notes: I think we can enhance the where= option very easily by
- allowing regexp expression. (by replacing bregex by libpcre
- see http://en.wikipedia.org/wiki/PCRE and http://www.pcre.org/)
+ allowing regexp expression.
Since, many users think that regexp are not user friendly, i think
that bat, bconsole or brestore must provide a simple way to
self->result = get_pool_memory(PM_FNAME);
self->result[0] = '\0';
-#ifdef HAVE_REGEX_H
- /* TODO: que devient cette memoire... */
- self->_regs_match = (int *) bmalloc (2*RE_NREGS * sizeof(int));
-
- self->regs.num_regs = RE_NREGS;
- self->regs.start = self->_regs_match;
- self->regs.end = self->_regs_match+(RE_NREGS * sizeof(int));
-#endif
-
return self;
}
if (self->result) {
free_pool_memory(self->result);
}
- if (self->_regs_match) {
- bfree(self->_regs_match);
- }
-
regfree(&self->preg);
bfree(self);
}
return true;
}
-#ifndef HAVE_REGEX_H
- #define BREGEX_CAST unsigned
-#else
- #define BREGEX_CAST const
-#endif
-
/* return regexp->result */
char *BREGEXP::replace(const char *fname)
{
success = false; /* use this.success to known if it's ok */
int flen = strlen(fname);
- int rc = re_search(&preg, (BREGEX_CAST char*) fname, flen, 0, flen, ®s);
+ int rc = regexec(&preg, fname, RE_NREGS, regs, 0);
- if (rc < 0) {
+ if (rc == REG_NOMATCH) {
Dmsg0(500, "bregexp: regex mismatch\n");
return return_fname(fname, flen);
}
- int len = compute_dest_len(fname, ®s);
+ int len = compute_dest_len(fname, regs);
if (len) {
result = check_pool_memory_size(result, len);
- edit_subst(fname, ®s);
+ edit_subst(fname, regs);
success = true;
Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
return result;
}
-int BREGEXP::compute_dest_len(const char *fname, struct re_registers *regs)
+int BREGEXP::compute_dest_len(const char *fname, regmatch_t regs[])
{
int len=0;
char *p;
}
/* match failed ? */
- if (regs->start[0] < 0) {
+ if (regs[0].rm_so < 0) {
return 0;
}
/* we check if the back reference exists */
/* references can not match if we are using (..)? */
- if (regs->start[no] >= 0 && regs->end[no] >= 0) {
- len += regs->end[no] - regs->start[no];
+ if (regs[no].rm_so >= 0 && regs[no].rm_eo >= 0) {
+ len += regs[no].rm_eo - regs[no].rm_so;
}
} else {
}
/* $0 is replaced by subst */
- len -= regs->end[0] - regs->start[0];
+ len -= regs[0].rm_eo - regs[0].rm_so;
len += strlen(fname) + 1;
return len;
}
-char *BREGEXP::edit_subst(const char *fname, struct re_registers *regs)
+char *BREGEXP::edit_subst(const char *fname, regmatch_t regs[])
{
int i;
char *p;
* on recopie le debut fname -> regs->start[0]
*/
- for (i = 0; i < regs->start[0] ; i++) {
+ for (i = 0; i < regs[0].rm_so ; i++) {
result[i] = fname[i];
}
no = *psubst++ - '0';
/* have a back reference ? */
- if (regs->start[no] >= 0 && regs->end[no] >= 0) {
- len = regs->end[no] - regs->start[no];
- bstrncpy(result + i, fname + regs->start[no], len + 1);
+ if (regs[no].rm_so >= 0 && regs[no].rm_eo >= 0) {
+ len = regs[no].rm_eo - regs[no].rm_so;
+ bstrncpy(result + i, fname + regs[no].rm_so, len + 1);
i += len ;
}
}
/* we copy what is out of the match */
- strcpy(result + i, fname + regs->end[0]);
+ strcpy(result + i, fname + regs[0].rm_eo);
return result;
}
POOLMEM *expr; /* search epression */
POOLMEM *subst; /* substitution */
regex_t preg; /* regex_t result of regcomp() */
- struct re_registers regs; /* contains match */
+ regmatch_t regs[RE_NREGS]; /* contains match */
char *eor; /* end of regexp in expr */
- int *_regs_match;
-
char *return_fname(const char *fname, int len); /* return fname as result */
- char *edit_subst(const char *fname, struct re_registers *regs);
- int compute_dest_len(const char *fname, struct re_registers *regs);
+ char *edit_subst(const char *fname, regmatch_t regs[]);
+ int compute_dest_len(const char *fname, regmatch_t regs[]);
bool extract_regexp(const char *motif);
};
return 0;
}
+void re_registers_to_regmatch(regexp_registers_t old_regs,
+ regmatch_t pmatch[],
+ size_t nmatch)
+{
+ size_t i=0;
+
+ /* We have to set the last entry to -1 */
+ nmatch = nmatch - 1;
+ for (i=0; (i < nmatch) && (old_regs->start[i] > -1) ; i++) {
+ pmatch[i].rm_so = old_regs->start[i];
+ pmatch[i].rm_eo = old_regs->end[i];
+ }
+
+ pmatch[i].rm_eo = pmatch[i].rm_so = -1;
+}
+
int regexec(regex_t * preg, const char *string, size_t nmatch,
regmatch_t pmatch[], int eflags)
{
int len = strlen(string);
struct re_registers regs;
stat = re_search(preg, (unsigned char *)string, len, 0, len, ®s);
+ re_registers_to_regmatch(®s, pmatch, nmatch);
/* stat is the start position in the string base 0 where
* the pattern was found or negative if not found.
*/