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)
72 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
75 foreach_alist(elt, bregexps) {
80 /* Apply all regexps to fname
82 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
87 char *ret = (char *) fname;
88 foreach_alist(elt, bregexps) {
89 ret = elt->replace(ret);
90 ok = ok || elt->success;
92 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
98 /* return an alist of BREGEXP or return NULL if it's not a
99 * where=!tmp!opt!ig,!temp!opt!i
101 alist *get_bregexps(const char *where)
103 char *p = (char *)where;
104 alist *list = New(alist(10, not_owned_by_alist));
107 reg = new_bregexp(p);
112 reg = new_bregexp(p);
123 bool BREGEXP::extract_regexp(const char *motif)
147 char *search = (char *) motif + 1;
148 int options = REG_EXTENDED | REG_NEWLINE;
151 /* extract 1st part */
152 char *dest = expr = bstrdup(motif);
154 while (*search && !ok) {
155 if (search[0] == '\\' && search[1] == sep) {
156 *dest++ = *++search; /* we skip separator */
158 } else if (search[0] == '\\' && search[1] == '\\') {
159 *dest++ = *++search; /* we skip the second \ */
161 } else if (*search == sep) { /* we found end of expression */
164 if (subst) { /* already have found motif */
168 *dest++ = *++search; /* we skip separator */
169 subst = dest; /* get replaced string */
176 *dest = '\0'; /* in case of */
185 while (*search && !ok) {
186 if (*search == 'i') {
187 options |= REG_ICASE;
189 } else if (*search == 'g') {
190 /* recherche multiple*/
192 } else if (*search == sep) {
195 } else { /* end of options */
201 int rc = regcomp(&preg, expr, options);
204 regerror(rc, &preg, prbuf, sizeof(prbuf));
205 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
209 eor = search; /* useful to find the next regexp in where */
214 /* return regexp->result */
215 char *BREGEXP::replace(const char *fname)
217 success = false; /* use this.success to known if it's ok */
218 int flen = strlen(fname);
219 int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
221 if (rc == REG_NOMATCH) {
222 Dmsg0(500, "bregexp: regex mismatch\n");
223 return return_fname(fname, flen);
226 int len = compute_dest_len(fname, regs);
229 result = check_pool_memory_size(result, len);
230 edit_subst(fname, regs);
232 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
234 } else { /* error in substitution */
235 Dmsg0(100, "bregexp: error in substitution\n");
236 return return_fname(fname, flen);
242 char *BREGEXP::return_fname(const char *fname, int len)
244 result = check_pool_memory_size(result, len+1);
245 strcpy(result,fname);
249 int BREGEXP::compute_dest_len(const char *fname, regmatch_t breg[])
253 char *psubst = subst;
256 if (!fname || !breg) {
261 if (breg[0].rm_so < 0) {
265 for (p = psubst++; *p ; p = psubst++) {
266 /* match $1 \1 back references */
267 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
268 no = *psubst++ - '0';
270 /* we check if the back reference exists */
271 /* references can not match if we are using (..)? */
273 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
274 len += breg[no].rm_eo - breg[no].rm_so;
282 /* $0 is replaced by subst */
283 len -= breg[0].rm_eo - breg[0].rm_so;
284 len += strlen(fname) + 1;
289 char *BREGEXP::edit_subst(const char *fname, regmatch_t breg[])
293 char *psubst = subst;
297 /* il faut recopier fname dans dest
298 * on recopie le debut fname -> breg->start[0]
301 for (i = 0; i < breg[0].rm_so ; i++) {
302 result[i] = fname[i];
305 /* on recopie le motif de remplacement (avec tous les $x) */
307 for (p = psubst++; *p ; p = psubst++) {
308 /* match $1 \1 back references */
309 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
310 no = *psubst++ - '0';
312 /* have a back reference ? */
313 if (breg[no].rm_so >= 0 && breg[no].rm_eo >= 0) {
314 len = breg[no].rm_eo - breg[no].rm_so;
315 bstrncpy(result + i, fname + breg[no].rm_so, len + 1);
324 /* we copy what is out of the match */
325 strcpy(result + i, fname + breg[0].rm_eo);
330 /* escape sep char and \
331 * dest must be long enough (src*2+1)
332 * return end of the string */
333 char *bregexp_escape_string(char *dest, const char *src, const char sep)
340 } else if (*src == '\\') {
350 static const char regexp_sep = '!';
351 static const char *str_strip_prefix = "!%s!!i";
352 static const char *str_add_prefix = "!^!%s!";
353 static const char *str_add_suffix = "!([^/])$!$1%s!";
355 int bregexp_get_build_where_size(char *strip_prefix,
359 int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
360 (add_prefix?strlen(add_prefix)+strlen(str_add_prefix) :0) +
361 (add_suffix?strlen(add_suffix)+strlen(str_add_suffix) :0) )
362 /* escape + 3*, + \0 */
365 Dmsg1(200, "bregexp_get_build_where_size = %i\n", str_size);
369 /* build a regexp string with user arguments
372 * int len = bregexp_get_build_where_size(a,b,c) ;
373 * char *dest = (char *) bmalloc (len * sizeof(char));
374 * bregexp_build_where(dest, len, a, b, c);
378 char *bregexp_build_where(char *dest, int str_size,
385 POOLMEM *str_tmp = get_memory(str_size);
387 *str_tmp = *dest = '\0';
390 len += bsnprintf(dest, str_size - len, str_strip_prefix,
391 bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
395 if (len) dest[len++] = ',';
397 len += bsnprintf(dest + len, str_size - len, str_add_suffix,
398 bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
402 if (len) dest[len++] = ',';
404 len += bsnprintf(dest + len, str_size - len, str_add_prefix,
405 bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
408 free_pool_memory(str_tmp);
414 void BREGEXP::debug()
416 printf("expr=[%s]\n", expr);
417 printf("subst=[%s]\n", subst);
418 printf("result=%s\n", NPRT(result));