2 * Manipulation routines for BREGEXP list
4 * Eric Bollengier, March 2007
10 Bacula
\81Â
\81® - The Network Backup Solution
12 Copyright (C) 2006-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula
\81Â
\81® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Z
\81Ã
\81¼rich,
34 Switzerland, email:ftf@fsfeurope.org.
43 BREGEXP *new_bregexp(const char *motif)
45 Dmsg0(500, "bregexp: creating new bregexp object\n");
46 BREGEXP *self = (BREGEXP *)bmalloc(sizeof(BREGEXP));
47 memset(self, 0, sizeof(BREGEXP));
49 if (!self->extract_regexp(motif)) {
50 Dmsg0(100, "bregexp: extract_regexp error\n");
55 self->result = get_pool_memory(PM_FNAME);
56 self->result[0] = '\0';
61 void free_bregexp(BREGEXP *self)
63 Dmsg0(500, "bregexp: freeing BREGEXP object\n");
73 free_pool_memory(self->result);
79 /* Free a bregexps alist
81 void free_bregexps(alist *bregexps)
83 Dmsg0(500, "bregexp: freeing all BREGEXP object\n");
86 foreach_alist(elt, bregexps) {
91 /* Apply all regexps to fname
93 bool apply_bregexps(const char *fname, alist *bregexps, char **result)
98 char *ret = (char *) fname;
99 foreach_alist(elt, bregexps) {
100 ret = elt->replace(ret);
101 ok = ok || elt->success;
103 Dmsg2(500, "bregexp: fname=%s ret=%s\n", fname, ret);
109 /* return an alist of BREGEXP or return NULL if it's not a
110 * where=!tmp!opt!ig,!temp!opt!i
112 alist *get_bregexps(const char *where)
114 char *p = (char *)where;
115 alist *list = New(alist(10, not_owned_by_alist));
118 reg = new_bregexp(p);
123 reg = new_bregexp(p);
134 bool BREGEXP::extract_regexp(const char *motif)
157 char *search = (char *) motif + 1;
158 int options = REG_EXTENDED | REG_NEWLINE;
161 /* extract 1st part */
162 char *dest = expr = bstrdup(motif);
164 while (*search && !ok) {
165 if (search[0] == '\\' && search[1] == sep) {
166 *dest++ = *++search; /* we skip separator */
168 } else if (search[0] == '\\' && search[1] == '\\') {
169 *dest++ = *++search; /* we skip the second \ */
171 } else if (*search == sep) { /* we found end of expression */
174 if (subst) { /* already have found motif */
178 *dest++ = *++search; /* we skip separator */
179 subst = dest; /* get replaced string */
186 *dest = '\0'; /* in case of */
195 while (*search && !ok) {
196 if (*search == 'i') {
197 options |= REG_ICASE;
199 } else if (*search == 'g') {
200 /* recherche multiple*/
202 } else if (*search == sep) {
205 } else { /* end of options */
211 int rc = regcomp(&preg, expr, options);
214 regerror(rc, &preg, prbuf, sizeof(prbuf));
215 Dmsg1(100, "bregexp: compile error: %s\n", prbuf);
219 eor = search; /* useful to find the next regexp in where */
224 /* return regexp->result */
225 char *BREGEXP::replace(const char *fname)
227 success = false; /* use this.success to known if it's ok */
228 int flen = strlen(fname);
229 int rc = regexec(&preg, fname, BREG_NREGS, regs, 0);
231 if (rc == REG_NOMATCH) {
232 Dmsg0(500, "bregexp: regex mismatch\n");
233 return return_fname(fname, flen);
236 int len = compute_dest_len(fname, regs);
239 result = check_pool_memory_size(result, len);
240 edit_subst(fname, regs);
242 Dmsg2(500, "bregexp: len = %i, result_len = %i\n", len, strlen(result));
244 } else { /* error in substitution */
245 Dmsg0(100, "bregexp: error in substitution\n");
246 return return_fname(fname, flen);
252 char *BREGEXP::return_fname(const char *fname, int len)
254 result = check_pool_memory_size(result, len+1);
255 strcpy(result,fname);
259 int BREGEXP::compute_dest_len(const char *fname, regmatch_t regs[])
263 char *psubst = subst;
266 if (!fname || !regs) {
271 if (regs[0].rm_so < 0) {
275 for (p = psubst++; *p ; p = psubst++) {
276 /* match $1 \1 back references */
277 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
278 no = *psubst++ - '0';
280 /* we check if the back reference exists */
281 /* references can not match if we are using (..)? */
283 if (regs[no].rm_so >= 0 && regs[no].rm_eo >= 0) {
284 len += regs[no].rm_eo - regs[no].rm_so;
292 /* $0 is replaced by subst */
293 len -= regs[0].rm_eo - regs[0].rm_so;
294 len += strlen(fname) + 1;
299 char *BREGEXP::edit_subst(const char *fname, regmatch_t regs[])
303 char *psubst = subst;
307 /* il faut recopier fname dans dest
308 * on recopie le debut fname -> regs->start[0]
311 for (i = 0; i < regs[0].rm_so ; i++) {
312 result[i] = fname[i];
315 /* on recopie le motif de remplacement (avec tous les $x) */
317 for (p = psubst++; *p ; p = psubst++) {
318 /* match $1 \1 back references */
319 if ((*p == '$' || *p == '\\') && ('0' <= *psubst && *psubst <= '9')) {
320 no = *psubst++ - '0';
322 /* have a back reference ? */
323 if (regs[no].rm_so >= 0 && regs[no].rm_eo >= 0) {
324 len = regs[no].rm_eo - regs[no].rm_so;
325 bstrncpy(result + i, fname + regs[no].rm_so, len + 1);
334 /* we copy what is out of the match */
335 strcpy(result + i, fname + regs[0].rm_eo);
340 /* escape sep char and \
341 * dest must be long enough (src*2+1)
342 * return end of the string */
343 char *bregexp_escape_string(char *dest, char *src, char sep)
350 } else if (*src == '\\') {
360 static char regexp_sep = '!';
361 static char *str_strip_prefix = "!%s!!i";
362 static char *str_add_prefix = "!^!%s!";
363 static char *str_add_suffix = "!([^/])$!$1%s!";
365 int bregexp_get_build_where_size(char *strip_prefix,
369 int str_size = ((strip_prefix?strlen(strip_prefix)+strlen(str_strip_prefix):0) +
370 (add_prefix?strlen(add_prefix)+strlen(str_add_prefix) :0) +
371 (add_suffix?strlen(add_suffix)+strlen(str_add_suffix) :0) )
372 /* escape + 3*, + \0 */
375 Dmsg1(1, "bregexp_get_build_where_size = %i\n", str_size);
379 /* build a regexp string with user arguments
382 * int len = bregexp_get_build_where_size(a,b,c) ;
383 * char *dest = (char *) bmalloc (len * sizeof(char));
384 * bregexp_build_where(dest, len, a, b, c);
388 char *bregexp_build_where(char *dest, int str_size,
395 POOLMEM *str_tmp = get_memory(str_size);
397 *str_tmp = *dest = '\0';
400 len += bsnprintf(dest, str_size - len, str_strip_prefix,
401 bregexp_escape_string(str_tmp, strip_prefix, regexp_sep));
405 if (len) dest[len++] = ',';
407 len += bsnprintf(dest + len, str_size - len, str_add_suffix,
408 bregexp_escape_string(str_tmp, add_suffix, regexp_sep));
412 if (len) dest[len++] = ',';
414 len += bsnprintf(dest + len, str_size - len, str_add_prefix,
415 bregexp_escape_string(str_tmp, add_prefix, regexp_sep));
418 free_pool_memory(str_tmp);
424 void BREGEXP::debug()
426 printf("expr=[%s]\n", expr);
427 printf("subst=[%s]\n", subst);
428 printf("result=%s\n", NPRT(result));