X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fmatch.c;h=826a2867fafceb46bd2e9dbc2b65184e2350b21e;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=f9ce31ded98bf71d8e8f78bc72b60636fe62957c;hpb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;p=debian%2Famanda diff --git a/common-src/match.c b/common-src/match.c index f9ce31d..826a286 100644 --- a/common-src/match.c +++ b/common-src/match.c @@ -30,9 +30,11 @@ */ #include "amanda.h" +#include "match.h" #include static int match_word(const char *glob, const char *word, const char separator); +static char *tar_to_regex(const char *glob); char * validate_regexp( @@ -55,18 +57,93 @@ validate_regexp( char * clean_regex( - const char * regex) + const char * str, + gboolean anchor) +{ + char *result; + int j; + size_t i; + result = alloc(2*strlen(str)+3); + + j = 0; + if (anchor) + result[j++] = '^'; + for(i=0;i [^/] * * -> [^/]* + * [...] -> [...] * [!...] -> [^...] * * The following are given a leading backslash to protect them @@ -261,7 +367,7 @@ match_tar( return result == 0; } -char * +static char * tar_to_regex( const char * glob) { @@ -276,13 +382,14 @@ tar_to_regex( * one expansion. */ len = strlen(glob); - regex = alloc(1 + len * 5 + 1 + 1); + regex = alloc(1 + len * 5 + 5 + 5); /* * Do the conversion: * * ? -> [^/] * * -> .* + * [...] -> [...] * [!...] -> [^...] * * The following are given a leading backslash to protect them @@ -290,13 +397,19 @@ tar_to_regex( * * ( ) { } + . ^ $ | * - * Put a leading ^ and trailing $ around the result. If the last - * non-escaped character is \ leave the $ off to cause a syntax + * The expression must begin and end either at the beginning/end of the string or + * at at a pathname separator. + * + * If the last non-escaped character is \ leave the $ off to cause a syntax * error when the regex is compiled. */ r = regex; + *r++ = '('; *r++ = '^'; + *r++ = '|'; + *r++ = '/'; + *r++ = ')'; last_ch = '\0'; for (ch = *glob++; ch != '\0'; last_ch = ch, ch = *glob++) { if (last_ch == '\\') { @@ -330,7 +443,11 @@ tar_to_regex( } } if (last_ch != '\\') { + *r++ = '('; *r++ = '$'; + *r++ = '|'; + *r++ = '/'; + *r++ = ')'; } *r = '\0'; @@ -351,8 +468,8 @@ match_word( int last_ch; int next_ch; size_t lenword; - char *nword; - char *nglob; + char *mword, *nword; + char *mglob, *nglob; char *g; const char *w; int i; @@ -360,8 +477,42 @@ match_word( lenword = strlen(word); nword = (char *)alloc(lenword + 3); + if (separator == '/' && lenword > 2 && word[0] == '\\' && word[1] == '\\' && !strchr(word, '/')) { + /* Convert all "\" to '/' */ + mword = (char *)alloc(lenword + 1); + r = mword; + w = word; + while (*w != '\0') { + if (*w == '\\') { + *r++ = '/'; + w += 1; + } else { + *r++ = *w++; + } + } + *r++ = '\0'; + lenword = strlen(word); + + /* Convert all "\\" to '/' */ + mglob = (char *)alloc(strlen(glob) + 1); + r = mglob; + w = glob; + while (*w != '\0') { + if (*w == '\\' && *(w+1) == '\\') { + *r++ = '/'; + w += 2; + } else { + *r++ = *w++; + } + } + *r++ = '\0'; + } else { + mword = stralloc(word); + mglob = stralloc(glob); + } + r = nword; - w = word; + w = mword; if(lenword == 1 && *w == separator) { *r++ = separator; *r++ = separator; @@ -380,10 +531,10 @@ match_word( * Allocate an area to convert into. The worst case is a six to * one expansion. */ - len = strlen(glob); + len = strlen(mglob); regex = (char *)alloc(1 + len * 6 + 1 + 1 + 2 + 2); r = regex; - nglob = stralloc(glob); + nglob = stralloc(mglob); g = nglob; if((len == 1 && nglob[0] == separator) || @@ -485,6 +636,8 @@ match_word( i = match(regex,nword); + amfree(mword); + amfree(mglob); amfree(nword); amfree(nglob); amfree(regex); @@ -530,6 +683,17 @@ match_disk( return match_word(glob, disk, '/'); } +static int +alldigits( + const char *str) +{ + while (*str) { + if (!isdigit((int)*(str++))) + return 0; + } + return 1; +} + int match_datestamp( const char * dateexp, @@ -543,45 +707,56 @@ match_datestamp( int match_exact; if(strlen(dateexp) >= 100 || strlen(dateexp) < 1) { - error(_("Illegal datestamp expression %s"),dateexp); - /*NOTREACHED*/ + goto illegal; } + /* strip and ignore an initial "^" */ if(dateexp[0] == '^') { - strncpy(mydateexp, dateexp+1, strlen(dateexp)-1); - mydateexp[strlen(dateexp)-1] = '\0'; + strncpy(mydateexp, dateexp+1, sizeof(mydateexp)-1); + mydateexp[sizeof(mydateexp)-1] = '\0'; } else { - strncpy(mydateexp, dateexp, strlen(dateexp)); - mydateexp[strlen(dateexp)] = '\0'; + strncpy(mydateexp, dateexp, sizeof(mydateexp)-1); + mydateexp[sizeof(mydateexp)-1] = '\0'; } - if(mydateexp[strlen(mydateexp)] == '$') { + if(mydateexp[strlen(mydateexp)-1] == '$') { match_exact = 1; - mydateexp[strlen(mydateexp)] = '\0'; + mydateexp[strlen(mydateexp)-1] = '\0'; /* strip the trailing $ */ } else match_exact = 0; + /* a single dash represents a date range */ if((dash = strchr(mydateexp,'-'))) { - if(match_exact == 1) { - error(_("Illegal datestamp expression %s"),dateexp); - /*NOTREACHED*/ + if(match_exact == 1 || strchr(dash+1, '-')) { + goto illegal; } - len = (size_t)(dash - mydateexp); - len_suffix = strlen(dash) - 1; - len_prefix = len - len_suffix; + + /* format: XXXYYYY-ZZZZ, indicating dates XXXYYYY to XXXZZZZ */ + + len = (size_t)(dash - mydateexp); /* length of XXXYYYY */ + len_suffix = strlen(dash) - 1; /* length of ZZZZ */ + if (len_suffix > len) goto illegal; + len_prefix = len - len_suffix; /* length of XXX */ dash++; + strncpy(firstdate, mydateexp, len); firstdate[len] = '\0'; strncpy(lastdate, mydateexp, len_prefix); strncpy(&(lastdate[len_prefix]), dash, len_suffix); lastdate[len] = '\0'; + if (!alldigits(firstdate) || !alldigits(lastdate)) + goto illegal; + if (strncmp(firstdate, lastdate, strlen(firstdate)) > 0) + goto illegal; return ((strncmp(datestamp, firstdate, strlen(firstdate)) >= 0) && (strncmp(datestamp, lastdate , strlen(lastdate)) <= 0)); } else { + if (!alldigits(mydateexp)) + goto illegal; if(match_exact == 1) { return (strcmp(datestamp, mydateexp) == 0); } @@ -589,6 +764,9 @@ match_datestamp( return (strncmp(datestamp, mydateexp, strlen(mydateexp)) == 0); } } +illegal: + error(_("Illegal datestamp expression %s"),dateexp); + /*NOTREACHED*/ } @@ -598,9 +776,7 @@ match_level( const char * level) { char *dash; - size_t len, len_suffix; - size_t len_prefix; - char lowend[100], highend[100]; + long int low, hi, level_i; char mylevelexp[100]; int match_exact; @@ -618,32 +794,33 @@ match_level( mylevelexp[strlen(levelexp)] = '\0'; } - if(mylevelexp[strlen(mylevelexp)] == '$') { + if(mylevelexp[strlen(mylevelexp)-1] == '$') { match_exact = 1; - mylevelexp[strlen(mylevelexp)] = '\0'; + mylevelexp[strlen(mylevelexp)-1] = '\0'; } else match_exact = 0; if((dash = strchr(mylevelexp,'-'))) { if(match_exact == 1) { - error(_("Illegal level expression %s"),levelexp); - /*NOTREACHED*/ + goto illegal; } - len = (size_t)(dash - mylevelexp); - len_suffix = strlen(dash) - 1; - len_prefix = len - len_suffix; - dash++; - strncpy(lowend, mylevelexp, len); - lowend[len] = '\0'; - strncpy(highend, mylevelexp, len_prefix); - strncpy(&(highend[len_prefix]), dash, len_suffix); - highend[len] = '\0'; - return ((strncmp(level, lowend, strlen(lowend)) >= 0) && - (strncmp(level, highend , strlen(highend)) <= 0)); + *dash = '\0'; + if (!alldigits(mylevelexp) || !alldigits(dash+1)) goto illegal; + + errno = 0; + low = strtol(mylevelexp, (char **) NULL, 10); + if (errno) goto illegal; + hi = strtol(dash+1, (char **) NULL, 10); + if (errno) goto illegal; + level_i = strtol(level, (char **) NULL, 10); + if (errno) goto illegal; + + return ((level_i >= low) && (level_i <= hi)); } else { + if (!alldigits(mylevelexp)) goto illegal; if(match_exact == 1) { return (strcmp(level, mylevelexp) == 0); } @@ -651,4 +828,7 @@ match_level( return (strncmp(level, mylevelexp, strlen(mylevelexp)) == 0); } } +illegal: + error(_("Illegal level expression %s"),levelexp); + /*NOTREACHED*/ }