2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: match.c,v 1.23 2006/05/25 01:47:12 johnfranks Exp $
29 * functions for checking and matching regular expressions
35 static int match_word(const char *glob, const char *word, const char separator);
43 static char errmsg[STR_SIZE];
45 if ((result = regcomp(®c, regex,
46 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
47 regerror(result, ®c, errmsg, SIZEOF(errmsg));
63 result = alloc(2*strlen(regex)+1);
65 for(i=0,j=0;i<strlen(regex);i++) {
66 if(!isalnum((int)regex[i]))
81 char errmsg[STR_SIZE];
83 if((result = regcomp(®c, regex,
84 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
85 regerror(result, ®c, errmsg, SIZEOF(errmsg));
86 error("regex \"%s\": %s", regex, errmsg);
90 if((result = regexec(®c, str, 0, 0, 0)) != 0
91 && result != REG_NOMATCH) {
92 regerror(result, ®c, errmsg, SIZEOF(errmsg));
93 error("regex \"%s\": %s", regex, errmsg);
109 static char errmsg[STR_SIZE];
111 regex = glob_to_regex(glob);
112 if ((result = regcomp(®c, regex,
113 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
114 regerror(result, ®c, errmsg, SIZEOF(errmsg));
133 char errmsg[STR_SIZE];
135 regex = glob_to_regex(glob);
136 if((result = regcomp(®c, regex,
137 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
138 regerror(result, ®c, errmsg, SIZEOF(errmsg));
139 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
143 if((result = regexec(®c, str, 0, 0, 0)) != 0
144 && result != REG_NOMATCH) {
145 regerror(result, ®c, errmsg, SIZEOF(errmsg));
146 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
167 * Allocate an area to convert into. The worst case is a five to
171 regex = alloc(1 + len * 5 + 1 + 1);
180 * The following are given a leading backslash to protect them
181 * unless they already have a backslash:
185 * Put a leading ^ and trailing $ around the result. If the last
186 * non-escaped character is \ leave the $ off to cause a syntax
187 * error when the regex is compiled.
193 for (ch = *glob++; ch != '\0'; last_ch = ch, ch = *glob++) {
194 if (last_ch == '\\') {
196 ch = '\0'; /* so last_ch != '\\' next time */
197 } else if (last_ch == '[' && ch == '!') {
199 } else if (ch == '\\') {
201 } else if (ch == '*' || ch == '?') {
224 if (last_ch != '\\') {
241 char errmsg[STR_SIZE];
243 regex = tar_to_regex(glob);
244 if((result = regcomp(®c, regex,
245 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
246 regerror(result, ®c, errmsg, SIZEOF(errmsg));
247 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
251 if((result = regexec(®c, str, 0, 0, 0)) != 0
252 && result != REG_NOMATCH) {
253 regerror(result, ®c, errmsg, SIZEOF(errmsg));
254 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
275 * Allocate an area to convert into. The worst case is a five to
279 regex = alloc(1 + len * 5 + 1 + 1);
288 * The following are given a leading backslash to protect them
289 * unless they already have a backslash:
293 * Put a leading ^ and trailing $ around the result. If the last
294 * non-escaped character is \ leave the $ off to cause a syntax
295 * error when the regex is compiled.
301 for (ch = *glob++; ch != '\0'; last_ch = ch, ch = *glob++) {
302 if (last_ch == '\\') {
304 ch = '\0'; /* so last_ch != '\\' next time */
305 } else if (last_ch == '[' && ch == '!') {
307 } else if (ch == '\\') {
309 } else if (ch == '*') {
312 } else if (ch == '?') {
332 if (last_ch != '\\') {
345 const char separator)
360 lenword = strlen(word);
361 nword = (char *)alloc(lenword + 3);
365 if(lenword == 1 && *w == separator) {
374 if(*(r-1) != separator)
380 * Allocate an area to convert into. The worst case is a six to
384 regex = (char *)alloc(1 + len * 6 + 1 + 1 + 2 + 2);
386 nglob = stralloc(glob);
389 if((len == 1 && nglob[0] == separator) ||
390 (len == 2 && nglob[0] == '^' && nglob[1] == separator) ||
391 (len == 2 && nglob[0] == separator && nglob[1] == '$') ||
392 (len == 3 && nglob[0] == '^' && nglob[1] == separator &&
406 * * -> [^\separator]*
410 * The following are given a leading backslash to protect them
411 * unless they already have a backslash:
416 * non-escaped character is \ leave it to cause a syntax
417 * error when the regex is compiled.
422 *r++ = '\\'; /* escape the separator */
425 if(*g == separator) g++;
427 else if(*g != separator) {
428 *r++ = '\\'; /* add a leading \separator */
432 for (ch = *g++; ch != '\0'; last_ch = ch, ch = *g++) {
434 if (last_ch == '\\') {
436 ch = '\0'; /* so last_ch != '\\' next time */
437 } else if (last_ch == '[' && ch == '!') {
439 } else if (ch == '\\') {
441 } else if (ch == '*' || ch == '?') {
442 if(ch == '*' && next_ch == '*') {
456 } else if (ch == '$' && next_ch == '\0') {
457 if(last_ch != separator) {
462 } else if ( ch == '('
477 if(last_ch != '\\') {
478 if(last_ch != separator && last_ch != '$') {
480 *r++ = separator; /* add a trailing \separator */
486 i = match(regex,nword);
506 lglob = (char *)alloc(strlen(glob)+1);
509 *c++ = (char)tolower(*d++);
512 lhost = (char *)alloc(strlen(host)+1);
515 *c++ = (char)tolower(*d++);
518 i = match_word(lglob, lhost, (int)'.');
530 return match_word(glob, disk, '/');
535 const char * dateexp,
536 const char * datestamp)
539 size_t len, len_suffix;
541 char firstdate[100], lastdate[100];
545 if(strlen(dateexp) >= 100 || strlen(dateexp) < 1) {
546 error("Illegal datestamp expression %s",dateexp);
550 if(dateexp[0] == '^') {
551 strncpy(mydateexp, dateexp+1, strlen(dateexp)-1);
552 mydateexp[strlen(dateexp)-1] = '\0';
555 strncpy(mydateexp, dateexp, strlen(dateexp));
556 mydateexp[strlen(dateexp)] = '\0';
559 if(mydateexp[strlen(mydateexp)] == '$') {
561 mydateexp[strlen(mydateexp)] = '\0';
566 if((dash = strchr(mydateexp,'-'))) {
567 if(match_exact == 1) {
568 error("Illegal datestamp expression %s",dateexp);
571 len = (size_t)(dash - mydateexp);
572 len_suffix = strlen(dash) - 1;
573 len_prefix = len - len_suffix;
576 strncpy(firstdate, mydateexp, len);
577 firstdate[len] = '\0';
578 strncpy(lastdate, mydateexp, len_prefix);
579 strncpy(&(lastdate[len_prefix]), dash, len_suffix);
580 lastdate[len] = '\0';
581 return ((strncmp(datestamp, firstdate, strlen(firstdate)) >= 0) &&
582 (strncmp(datestamp, lastdate , strlen(lastdate)) <= 0));
585 if(match_exact == 1) {
586 return (strcmp(datestamp, mydateexp) == 0);
589 return (strncmp(datestamp, mydateexp, strlen(mydateexp)) == 0);
597 const char * levelexp,
601 size_t len, len_suffix;
603 char lowend[100], highend[100];
604 char mylevelexp[100];
607 if(strlen(levelexp) >= 100 || strlen(levelexp) < 1) {
608 error("Illegal level expression %s",levelexp);
612 if(levelexp[0] == '^') {
613 strncpy(mylevelexp, levelexp+1, strlen(levelexp)-1);
614 mylevelexp[strlen(levelexp)-1] = '\0';
617 strncpy(mylevelexp, levelexp, strlen(levelexp));
618 mylevelexp[strlen(levelexp)] = '\0';
621 if(mylevelexp[strlen(mylevelexp)] == '$') {
623 mylevelexp[strlen(mylevelexp)] = '\0';
628 if((dash = strchr(mylevelexp,'-'))) {
629 if(match_exact == 1) {
630 error("Illegal level expression %s",levelexp);
633 len = (size_t)(dash - mylevelexp);
634 len_suffix = strlen(dash) - 1;
635 len_prefix = len - len_suffix;
638 strncpy(lowend, mylevelexp, len);
640 strncpy(highend, mylevelexp, len_prefix);
641 strncpy(&(highend[len_prefix]), dash, len_suffix);
643 return ((strncmp(level, lowend, strlen(lowend)) >= 0) &&
644 (strncmp(level, highend , strlen(highend)) <= 0));
647 if(match_exact == 1) {
648 return (strcmp(level, mylevelexp) == 0);
651 return (strncmp(level, mylevelexp, strlen(mylevelexp)) == 0);