2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many 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 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Manipulation routines for BREGEXP list
22 * Eric Bollengier, March 2007
32 BREGEXP *new_bregexp(const char *motif)
34 Dmsg0(500, "bregexp: creating new bregexp object\n");
35 BREGEXP *self = (BREGEXP *)bmalloc(sizeof(BREGEXP));
36 memset(self, 0, sizeof(BREGEXP));
38 if (!self->extract_regexp(motif)) {
39 Dmsg0(100, "bregexp: extract_regexp error\n");
44 self->result = get_pool_memory(PM_FNAME);
45 self->result[0] = '\0';
50 void free_bregexp(BREGEXP *self)
52 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
62 free_pool_memory(self->result);
68 /* Free a bregexps alist
70 void free_bregexps(alist *bregexps)
73 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
77 foreach_alist(elt, bregexps) {
82 /* Apply all regexps to fname
84 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
89 char *ret = (char *) fname;
90 foreach_alist(elt, bregexps) {
91 ret = elt->replace(ret);
92 ok = ok || elt->success;
94 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
100 /* return an alist of BREGEXP or return NULL if it's not a
101 * where=!tmp!opt!ig,!temp!opt!i
103 alist *get_bregexps(const char *where)
105 char *p = (char *)where;
106 alist *list = New(alist(10, not_owned_by_alist));
109 reg = new_bregexp(p);
114 reg = new_bregexp(p);
125 bool BREGEXP::extract_regexp(const char *motif)
149 char *search = (char *) motif + 1;
150 int options = REG_EXTENDED | REG_NEWLINE;
153 /* extract 1st part */
154 char *dest = expr = bstrdup(motif);
156 while (*search && !ok) {
157 if (search[0] == '\\' && search[1] == sep) {
158 *dest++ = *++search; /* we skip separator */
160 } else if (search[0] == '\\' && search[1] == '\\') {
161 *dest++ = *++search; /* we skip the second \ */
163 } else if (*search == sep) { /* we found end of expression */
166 if (subst) { /* already have found motif */
170 *dest++ = *++search; /* we skip separator */
171 subst = dest; /* get replaced string */
178 *dest = '\0'; /* in case of */
187 while (*search && !ok) {
188 if (*search == 'i') {
189 options |= REG_ICASE;
191 } else if (*search == 'g') {
192 /* recherche multiple*/
194 } else if (*search == sep) {
197 } else { /* end of options */
203 int rc = regcomp(&preg, expr, options);
206 regerror(rc, &preg, prbuf, sizeof(prbuf));
207 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
211 eor = search; /* useful to find the next regexp in where */
216 /* return regexp->result */
217 char *BREGEXP::replace(const char *fname)
219 success = false; /* use this.success to known if it's ok */
220 int flen = strlen(fname);
221 int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
223 if (rc == REG_NOMATCH) {
224 Dmsg0(500, "bregexp: regex mismatch\n");
225 return return_fname(fname, flen);
228 int len = compute_dest_len(fname, regs);
231 result = check_pool_memory_size(result, len);
232 edit_subst(fname, regs);
234 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
236 } else { /* error in substitution */
237 Dmsg0(100, "bregexp: error in substitution\n");
238 return return_fname(fname, flen);
244 char *BREGEXP::return_fname(const char *fname, int len)
246 result = check_pool_memory_size(result, len+1);
247 strcpy(result,fname);
251 int BREGEXP::compute_dest_len(const char *fname, regmatch_t breg[])
255 char *psubst = subst;
258 if (!fname || !breg) {
263 if (breg[0].rm_so < 0) {
267 for (p = psubst++; *p ; p = psubst++) {
268 /* match $1 \1 back references */
269 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
270 no = *psubst++ - '0';
272 /* we check if the back reference exists */
273 /* references can not match if we are using (..)? */
275 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
276 len += breg[no].rm_eo - breg[no].rm_so;
284 /* $0 is replaced by subst */
285 len -= breg[0].rm_eo - breg[0].rm_so;
286 len += strlen(fname) + 1;
291 char *BREGEXP::edit_subst(const char *fname, regmatch_t breg[])
295 char *psubst = subst;
299 /* il faut recopier fname dans dest
300 * on recopie le debut fname -> breg->start[0]
303 for (i = 0; i < breg[0].rm_so ; i++) {
304 result[i] = fname[i];
307 /* on recopie le motif de remplacement (avec tous les $x) */
309 for (p = psubst++; *p ; p = psubst++) {
310 /* match $1 \1 back references */
311 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
312 no = *psubst++ - '0';
314 /* have a back reference ? */
315 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
316 len = breg[no].rm_eo - breg[no].rm_so;
317 bstrncpy(result + i, fname + breg[no].rm_so, len + 1);
326 /* we copy what is out of the match */
327 strcpy(result + i, fname + breg[0].rm_eo);
332 /* escape sep char and \
333 * dest must be long enough (src*2+1)
334 * return end of the string */
335 char *bregexp_escape_string(char *dest, const char *src, const char sep)
342 } else if (*src == '\\') {
352 static const char regexp_sep = '!';
353 static const char *str_strip_prefix = "!%s!!i";
354 static const char *str_add_prefix = "!^!%s!";
355 static const char *str_add_suffix = "!([^/])$!$1%s!";
357 int bregexp_get_build_where_size(char *strip_prefix,
361 int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
362 (add_prefix?strlen(add_prefix)+strlen(str_add_prefix) :0) +
363 (add_suffix?strlen(add_suffix)+strlen(str_add_suffix) :0) )
364 /* escape + 3*, + \0 */
367 Dmsg1(200, "bregexp_get_build_where_size = %i\n", str_size);
371 /* build a regexp string with user arguments
374 * int len = bregexp_get_build_where_size(a,b,c) ;
375 * char *dest = (char *) bmalloc (len * sizeof(char));
376 * bregexp_build_where(dest, len, a, b, c);
380 char *bregexp_build_where(char *dest, int str_size,
387 POOLMEM *str_tmp = get_memory(str_size);
389 *str_tmp = *dest = '\0';
392 len += bsnprintf(dest, str_size - len, str_strip_prefix,
393 bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
397 if (len) dest[len++] = ',';
399 len += bsnprintf(dest + len, str_size - len, str_add_suffix,
400 bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
404 if (len) dest[len++] = ',';
406 len += bsnprintf(dest + len, str_size - len, str_add_prefix,
407 bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
410 free_pool_memory(str_tmp);
416 void BREGEXP::debug()
418 printf("expr=[%s]\n", expr);
419 printf("subst=[%s]\n", subst);
420 printf("result=%s\n", NPRT(result));