2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2007-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Manipulation routines for BREGEXP list
23 * Eric Bollengier, March 2007
33 BREGEXP *new_bregexp(const char *motif)
35 Dmsg0(500, "bregexp: creating new bregexp object\n");
36 BREGEXP *self = (BREGEXP *)bmalloc(sizeof(BREGEXP));
37 memset(self, 0, sizeof(BREGEXP));
39 if (!self->extract_regexp(motif)) {
40 Dmsg0(100, "bregexp: extract_regexp error\n");
45 self->result = get_pool_memory(PM_FNAME);
46 self->result[0] = '\0';
51 void free_bregexp(BREGEXP *self)
53 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
63 free_pool_memory(self->result);
69 /* Free a bregexps alist
71 void free_bregexps(alist *bregexps)
73 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
76 foreach_alist(elt, bregexps) {
81 /* Apply all regexps to fname
83 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
88 char *ret = (char *) fname;
89 foreach_alist(elt, bregexps) {
90 ret = elt->replace(ret);
91 ok = ok || elt->success;
93 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
99 /* return an alist of BREGEXP or return NULL if it's not a
100 * where=!tmp!opt!ig,!temp!opt!i
102 alist *get_bregexps(const char *where)
104 char *p = (char *)where;
105 alist *list = New(alist(10, not_owned_by_alist));
108 reg = new_bregexp(p);
113 reg = new_bregexp(p);
124 bool BREGEXP::extract_regexp(const char *motif)
148 char *search = (char *) motif + 1;
149 int options = REG_EXTENDED | REG_NEWLINE;
152 /* extract 1st part */
153 char *dest = expr = bstrdup(motif);
155 while (*search && !ok) {
156 if (search[0] == '\\' && search[1] == sep) {
157 *dest++ = *++search; /* we skip separator */
159 } else if (search[0] == '\\' && search[1] == '\\') {
160 *dest++ = *++search; /* we skip the second \ */
162 } else if (*search == sep) { /* we found end of expression */
165 if (subst) { /* already have found motif */
169 *dest++ = *++search; /* we skip separator */
170 subst = dest; /* get replaced string */
177 *dest = '\0'; /* in case of */
186 while (*search && !ok) {
187 if (*search == 'i') {
188 options |= REG_ICASE;
190 } else if (*search == 'g') {
191 /* recherche multiple*/
193 } else if (*search == sep) {
196 } else { /* end of options */
202 int rc = regcomp(&preg, expr, options);
205 regerror(rc, &preg, prbuf, sizeof(prbuf));
206 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
210 eor = search; /* useful to find the next regexp in where */
215 /* return regexp->result */
216 char *BREGEXP::replace(const char *fname)
218 success = false; /* use this.success to known if it's ok */
219 int flen = strlen(fname);
220 int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
222 if (rc == REG_NOMATCH) {
223 Dmsg0(500, "bregexp: regex mismatch\n");
224 return return_fname(fname, flen);
227 int len = compute_dest_len(fname, regs);
230 result = check_pool_memory_size(result, len);
231 edit_subst(fname, regs);
233 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
235 } else { /* error in substitution */
236 Dmsg0(100, "bregexp: error in substitution\n");
237 return return_fname(fname, flen);
243 char *BREGEXP::return_fname(const char *fname, int len)
245 result = check_pool_memory_size(result, len+1);
246 strcpy(result,fname);
250 int BREGEXP::compute_dest_len(const char *fname, regmatch_t breg[])
254 char *psubst = subst;
257 if (!fname || !breg) {
262 if (breg[0].rm_so < 0) {
266 for (p = psubst++; *p ; p = psubst++) {
267 /* match $1 \1 back references */
268 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
269 no = *psubst++ - '0';
271 /* we check if the back reference exists */
272 /* references can not match if we are using (..)? */
274 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
275 len += breg[no].rm_eo - breg[no].rm_so;
283 /* $0 is replaced by subst */
284 len -= breg[0].rm_eo - breg[0].rm_so;
285 len += strlen(fname) + 1;
290 char *BREGEXP::edit_subst(const char *fname, regmatch_t breg[])
294 char *psubst = subst;
298 /* il faut recopier fname dans dest
299 * on recopie le debut fname -> breg->start[0]
302 for (i = 0; i < breg[0].rm_so ; i++) {
303 result[i] = fname[i];
306 /* on recopie le motif de remplacement (avec tous les $x) */
308 for (p = psubst++; *p ; p = psubst++) {
309 /* match $1 \1 back references */
310 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
311 no = *psubst++ - '0';
313 /* have a back reference ? */
314 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
315 len = breg[no].rm_eo - breg[no].rm_so;
316 bstrncpy(result + i, fname + breg[no].rm_so, len + 1);
325 /* we copy what is out of the match */
326 strcpy(result + i, fname + breg[0].rm_eo);
331 /* escape sep char and \
332 * dest must be long enough (src*2+1)
333 * return end of the string */
334 char *bregexp_escape_string(char *dest, const char *src, const char sep)
341 } else if (*src == '\\') {
351 static const char regexp_sep = '!';
352 static const char *str_strip_prefix = "!%s!!i";
353 static const char *str_add_prefix = "!^!%s!";
354 static const char *str_add_suffix = "!([^/])$!$1%s!";
356 int bregexp_get_build_where_size(char *strip_prefix,
360 int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
361 (add_prefix?strlen(add_prefix)+strlen(str_add_prefix) :0) +
362 (add_suffix?strlen(add_suffix)+strlen(str_add_suffix) :0) )
363 /* escape + 3*, + \0 */
366 Dmsg1(200, "bregexp_get_build_where_size = %i\n", str_size);
370 /* build a regexp string with user arguments
373 * int len = bregexp_get_build_where_size(a,b,c) ;
374 * char *dest = (char *) bmalloc (len * sizeof(char));
375 * bregexp_build_where(dest, len, a, b, c);
379 char *bregexp_build_where(char *dest, int str_size,
386 POOLMEM *str_tmp = get_memory(str_size);
388 *str_tmp = *dest = '\0';
391 len += bsnprintf(dest, str_size - len, str_strip_prefix,
392 bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
396 if (len) dest[len++] = ',';
398 len += bsnprintf(dest + len, str_size - len, str_add_suffix,
399 bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
403 if (len) dest[len++] = ',';
405 len += bsnprintf(dest + len, str_size - len, str_add_prefix,
406 bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
409 free_pool_memory(str_tmp);
415 void BREGEXP::debug()
417 printf("expr=[%s]\n", expr);
418 printf("subst=[%s]\n", subst);
419 printf("result=%s\n", NPRT(result));