2 Bacula® - The Network Backup Solution
4 Copyright (C) 2006-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Manipulation routines for BREGEXP list
19 * Eric Bollengier, March 2007
29 BREGEXP *new_bregexp(const char *motif)
31 Dmsg0(500, "bregexp: creating new bregexp object\n");
32 BREGEXP *self = (BREGEXP *)bmalloc(sizeof(BREGEXP));
33 memset(self, 0, sizeof(BREGEXP));
35 if (!self->extract_regexp(motif)) {
36 Dmsg0(100, "bregexp: extract_regexp error\n");
41 self->result = get_pool_memory(PM_FNAME);
42 self->result[0] = '\0';
47 void free_bregexp(BREGEXP *self)
49 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
59 free_pool_memory(self->result);
65 /* Free a bregexps alist
67 void free_bregexps(alist *bregexps)
69 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
72 foreach_alist(elt, bregexps) {
77 /* Apply all regexps to fname
79 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
84 char *ret = (char *) fname;
85 foreach_alist(elt, bregexps) {
86 ret = elt->replace(ret);
87 ok = ok || elt->success;
89 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
95 /* return an alist of BREGEXP or return NULL if it's not a
96 * where=!tmp!opt!ig,!temp!opt!i
98 alist *get_bregexps(const char *where)
100 char *p = (char *)where;
101 alist *list = New(alist(10, not_owned_by_alist));
104 reg = new_bregexp(p);
109 reg = new_bregexp(p);
120 bool BREGEXP::extract_regexp(const char *motif)
144 char *search = (char *) motif + 1;
145 int options = REG_EXTENDED | REG_NEWLINE;
148 /* extract 1st part */
149 char *dest = expr = bstrdup(motif);
151 while (*search && !ok) {
152 if (search[0] == '\\' && search[1] == sep) {
153 *dest++ = *++search; /* we skip separator */
155 } else if (search[0] == '\\' && search[1] == '\\') {
156 *dest++ = *++search; /* we skip the second \ */
158 } else if (*search == sep) { /* we found end of expression */
161 if (subst) { /* already have found motif */
165 *dest++ = *++search; /* we skip separator */
166 subst = dest; /* get replaced string */
173 *dest = '\0'; /* in case of */
182 while (*search && !ok) {
183 if (*search == 'i') {
184 options |= REG_ICASE;
186 } else if (*search == 'g') {
187 /* recherche multiple*/
189 } else if (*search == sep) {
192 } else { /* end of options */
198 int rc = regcomp(&preg, expr, options);
201 regerror(rc, &preg, prbuf, sizeof(prbuf));
202 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
206 eor = search; /* useful to find the next regexp in where */
211 /* return regexp->result */
212 char *BREGEXP::replace(const char *fname)
214 success = false; /* use this.success to known if it's ok */
215 int flen = strlen(fname);
216 int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
218 if (rc == REG_NOMATCH) {
219 Dmsg0(500, "bregexp: regex mismatch\n");
220 return return_fname(fname, flen);
223 int len = compute_dest_len(fname, regs);
226 result = check_pool_memory_size(result, len);
227 edit_subst(fname, regs);
229 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
231 } else { /* error in substitution */
232 Dmsg0(100, "bregexp: error in substitution\n");
233 return return_fname(fname, flen);
239 char *BREGEXP::return_fname(const char *fname, int len)
241 result = check_pool_memory_size(result, len+1);
242 strcpy(result,fname);
246 int BREGEXP::compute_dest_len(const char *fname, regmatch_t pmatch[])
250 char *psubst = subst;
253 if (!fname || !pmatch) {
258 if (pmatch[0].rm_so < 0) {
262 for (p = psubst++; *p ; p = psubst++) {
263 /* match $1 \1 back references */
264 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
265 no = *psubst++ - '0';
267 /* we check if the back reference exists */
268 /* references can not match if we are using (..)? */
270 if (pmatch[no].rm_so >= 0 && pmatch[no].rm_eo >= 0) {
271 len += pmatch[no].rm_eo - pmatch[no].rm_so;
279 /* $0 is replaced by subst */
280 len -= pmatch[0].rm_eo - pmatch[0].rm_so;
281 len += strlen(fname) + 1;
286 char *BREGEXP::edit_subst(const char *fname, regmatch_t pmatch[])
290 char *psubst = subst;
294 /* il faut recopier fname dans dest
295 * on recopie le debut fname -> pmatch->start[0]
298 for (i = 0; i < pmatch[0].rm_so ; i++) {
299 result[i] = fname[i];
302 /* on recopie le motif de remplacement (avec tous les $x) */
304 for (p = psubst++; *p ; p = psubst++) {
305 /* match $1 \1 back references */
306 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
307 no = *psubst++ - '0';
309 /* have a back reference ? */
310 if (pmatch[no].rm_so >= 0 && pmatch[no].rm_eo >= 0) {
311 len = pmatch[no].rm_eo - pmatch[no].rm_so;
312 bstrncpy(result + i, fname + pmatch[no].rm_so, len + 1);
321 /* we copy what is out of the match */
322 strcpy(result + i, fname + pmatch[0].rm_eo);
327 /* escape sep char and \
328 * dest must be long enough (src*2+1)
329 * return end of the string */
330 char *bregexp_escape_string(char *dest, const char *src, const char sep)
337 } else if (*src == '\\') {
347 static const char regexp_sep = '!';
348 static const char *str_strip_prefix = "!%s!!i";
349 static const char *str_add_prefix = "!^!%s!";
350 static const char *str_add_suffix = "!([^/])$!$1%s!";
352 int bregexp_get_build_where_size(char *strip_prefix,
356 int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
357 (add_prefix?strlen(add_prefix)+strlen(str_add_prefix) :0) +
358 (add_suffix?strlen(add_suffix)+strlen(str_add_suffix) :0) )
359 /* escape + 3*, + \0 */
362 Dmsg1(200, "bregexp_get_build_where_size = %i\n", str_size);
366 /* build a regexp string with user arguments
369 * int len = bregexp_get_build_where_size(a,b,c) ;
370 * char *dest = (char *) bmalloc (len * sizeof(char));
371 * bregexp_build_where(dest, len, a, b, c);
375 char *bregexp_build_where(char *dest, int str_size,
382 POOLMEM *str_tmp = get_memory(str_size);
384 *str_tmp = *dest = '\0';
387 len += bsnprintf(dest, str_size - len, str_strip_prefix,
388 bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
392 if (len) dest[len++] = ',';
394 len += bsnprintf(dest + len, str_size - len, str_add_suffix,
395 bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
399 if (len) dest[len++] = ',';
401 len += bsnprintf(dest + len, str_size - len, str_add_prefix,
402 bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
405 free_pool_memory(str_tmp);
411 void BREGEXP::debug()
413 printf("expr=[%s]\n", expr);
414 printf("subst=[%s]\n", subst);
415 printf("result=%s\n", NPRT(result));