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.10.4.1.4.1.2.4.2.2 2004/12/21 14:20:20 martinea Exp $
29 * functions for checking and matching regular expressions
35 char *validate_regexp(regex)
40 static char errmsg[STR_SIZE];
42 if ((result = regcomp(®c, regex,
43 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
44 regerror(result, ®c, errmsg, sizeof(errmsg));
53 char *clean_regex(regex)
59 result = alloc(2*strlen(regex)+1);
61 for(i=0,j=0;i<strlen(regex);i++) {
62 if(!isalnum((int)regex[i]))
75 char errmsg[STR_SIZE];
77 if((result = regcomp(®c, regex,
78 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
79 regerror(result, ®c, errmsg, sizeof(errmsg));
80 error("regex \"%s\": %s", regex, errmsg);
83 if((result = regexec(®c, str, 0, 0, 0)) != 0
84 && result != REG_NOMATCH) {
85 regerror(result, ®c, errmsg, sizeof(errmsg));
86 error("regex \"%s\": %s", regex, errmsg);
94 char *validate_glob(glob)
100 static char errmsg[STR_SIZE];
102 regex = glob_to_regex(glob);
103 if ((result = regcomp(®c, regex,
104 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
105 regerror(result, ®c, errmsg, sizeof(errmsg));
116 int match_glob(glob, str)
122 char errmsg[STR_SIZE];
124 regex = glob_to_regex(glob);
125 if((result = regcomp(®c, regex,
126 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
127 regerror(result, ®c, errmsg, sizeof(errmsg));
128 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
131 if((result = regexec(®c, str, 0, 0, 0)) != 0
132 && result != REG_NOMATCH) {
133 regerror(result, ®c, errmsg, sizeof(errmsg));
134 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
143 char *glob_to_regex(glob)
153 * Allocate an area to convert into. The worst case is a five to
157 regex = alloc(1 + len * 5 + 1 + 1);
166 * The following are given a leading backslash to protect them
167 * unless they already have a backslash:
171 * Put a leading ^ and trailing $ around the result. If the last
172 * non-escaped character is \ leave the $ off to cause a syntax
173 * error when the regex is compiled.
179 for (ch = *glob++; ch != '\0'; last_ch = ch, ch = *glob++) {
180 if (last_ch == '\\') {
182 ch = '\0'; /* so last_ch != '\\' next time */
183 } else if (last_ch == '[' && ch == '!') {
185 } else if (ch == '\\') {
187 } else if (ch == '*' || ch == '?') {
210 if (last_ch != '\\') {
219 int match_tar(glob, str)
225 char errmsg[STR_SIZE];
227 regex = tar_to_regex(glob);
228 if((result = regcomp(®c, regex,
229 REG_EXTENDED|REG_NOSUB|REG_NEWLINE)) != 0) {
230 regerror(result, ®c, errmsg, sizeof(errmsg));
231 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
234 if((result = regexec(®c, str, 0, 0, 0)) != 0
235 && result != REG_NOMATCH) {
236 regerror(result, ®c, errmsg, sizeof(errmsg));
237 error("glob \"%s\" -> regex \"%s\": %s", glob, regex, errmsg);
246 char *tar_to_regex(glob)
256 * Allocate an area to convert into. The worst case is a five to
260 regex = alloc(1 + len * 5 + 1 + 1);
269 * The following are given a leading backslash to protect them
270 * unless they already have a backslash:
274 * Put a leading ^ and trailing $ around the result. If the last
275 * non-escaped character is \ leave the $ off to cause a syntax
276 * error when the regex is compiled.
282 for (ch = *glob++; ch != '\0'; last_ch = ch, ch = *glob++) {
283 if (last_ch == '\\') {
285 ch = '\0'; /* so last_ch != '\\' next time */
286 } else if (last_ch == '[' && ch == '!') {
288 } else if (ch == '\\') {
290 } else if (ch == '*') {
293 } else if (ch == '?') {
313 if (last_ch != '\\') {
322 int match_word(glob, word, separator)
338 lenword = strlen(word);
339 nword = (char *)alloc(lenword + 3);
343 if(lenword == 1 && *w == separator) {
352 if(*(r-1) != separator)
358 * Allocate an area to convert into. The worst case is a six to
362 regex = (char *)alloc(1 + len * 6 + 1 + 1 + 2 + 2);
364 nglob = stralloc(glob);
367 if((len == 1 && nglob[0] == separator) ||
368 (len == 2 && nglob[0] == '^' && nglob[1] == separator) ||
369 (len == 2 && nglob[0] == separator && nglob[1] == '$') ||
370 (len == 3 && nglob[0] == '^' && nglob[1] == separator &&
384 * * -> [^\separator]*
388 * The following are given a leading backslash to protect them
389 * unless they already have a backslash:
394 * non-escaped character is \ leave it to cause a syntax
395 * error when the regex is compiled.
400 *r++ = '\\'; /* escape the separator */
403 if(*g == separator) g++;
405 else if(*g != separator) {
406 *r++ = '\\'; /* add a leading \separator */
410 for (ch = *g++; ch != '\0'; last_ch = ch, ch = *g++) {
412 if (last_ch == '\\') {
414 ch = '\0'; /* so last_ch != '\\' next time */
415 } else if (last_ch == '[' && ch == '!') {
417 } else if (ch == '\\') {
419 } else if (ch == '*' || ch == '?') {
420 if(ch == '*' && next_ch == '*') {
434 } else if (ch == '$' && next_ch == '\0') {
435 if(last_ch != separator) {
440 } else if ( ch == '('
455 if(last_ch != '\\') {
456 if(last_ch != separator && last_ch != '$') {
458 *r++ = separator; /* add a trailing \separator */
464 i = match(regex,nword);
473 int match_host(glob, host)
481 lglob = (char *)alloc(strlen(glob)+1);
484 *c++ = tolower(*d++);
487 lhost = (char *)alloc(strlen(host)+1);
490 *c++ = tolower(*d++);
493 i = match_word(lglob, lhost, '.');
500 int match_disk(glob, disk)
504 i = match_word(glob, disk, '/');
508 int match_datestamp(dateexp, datestamp)
509 char *dateexp, *datestamp;
512 size_t len, len_suffix;
514 char firstdate[100], lastdate[100];
518 if(strlen(dateexp) >= 100 || strlen(dateexp) < 1) {
519 error("Illegal datestamp expression %s",dateexp);
522 if(dateexp[0] == '^') {
523 strncpy(mydateexp, dateexp+1, strlen(dateexp)-1);
524 mydateexp[strlen(dateexp)-1] = '\0';
527 strncpy(mydateexp, dateexp, strlen(dateexp));
528 mydateexp[strlen(dateexp)] = '\0';
531 if(mydateexp[strlen(mydateexp)] == '$') {
533 mydateexp[strlen(mydateexp)] = '\0';
538 if((dash = strchr(mydateexp,'-'))) {
539 if(match_exact == 1) {
540 error("Illegal datestamp expression %s",dateexp);
542 len = dash - mydateexp;
543 len_suffix = strlen(dash) - 1;
544 len_prefix = len - len_suffix;
547 error("Illegal datestamp expression %s",dateexp);
551 strncpy(firstdate, mydateexp, len);
552 firstdate[len] = '\0';
553 strncpy(lastdate, mydateexp, len_prefix);
554 strncpy(&(lastdate[len_prefix]), dash, len_suffix);
555 lastdate[len] = '\0';
556 return ((strncmp(datestamp, firstdate, strlen(firstdate)) >= 0) &&
557 (strncmp(datestamp, lastdate , strlen(lastdate)) <= 0));
560 if(match_exact == 1) {
561 return (strcmp(datestamp, mydateexp) == 0);
564 return (strncmp(datestamp, mydateexp, strlen(mydateexp)) == 0);