*/
#include "amanda.h"
+#include "match.h"
#include <regex.h>
static int match_word(const char *glob, const char *word, const char separator);
+static char *tar_to_regex(const char *glob);
char *
validate_regexp(
char *
clean_regex(
- const char * regex)
+ const char * str,
+ gboolean anchor)
{
char *result;
int j;
size_t i;
- result = alloc(2*strlen(regex)+1);
+ result = alloc(2*strlen(str)+3);
- for(i=0,j=0;i<strlen(regex);i++) {
- if(!isalnum((int)regex[i]))
+ j = 0;
+ if (anchor)
+ result[j++] = '^';
+ for(i=0;i<strlen(str);i++) {
+ if(!isalnum((int)str[i]))
result[j++]='\\';
- result[j++]=regex[i];
+ result[j++]=str[i];
}
+ if (anchor)
+ result[j++] = '$';
+ result[j] = '\0';
+ return result;
+}
+
+char *
+make_exact_host_expression(
+ const char * host)
+{
+ char *result;
+ int j;
+ size_t i;
+ result = alloc(2*strlen(host)+3);
+
+ j = 0;
+ result[j++] = '^';
+ for(i=0;i<strlen(host);i++) {
+ /* quote host expression metcharacters *except* '.'. Note that
+ * most of these are invalid in a DNS hostname anyway. */
+ switch (host[i]) {
+ case '\\':
+ case '/':
+ case '^':
+ case '$':
+ case '?':
+ case '*':
+ case '[':
+ case ']':
+ result[j++]='\\';
+ /* fall through */
+
+ default:
+ result[j++]=host[i];
+ }
+ }
+ result[j++] = '$';
+ result[j] = '\0';
+ return result;
+}
+
+char *
+make_exact_disk_expression(
+ const char * disk)
+{
+ char *result;
+ int j;
+ size_t i;
+ result = alloc(2*strlen(disk)+3);
+
+ j = 0;
+ result[j++] = '^';
+ for(i=0;i<strlen(disk);i++) {
+ /* quote disk expression metcharacters *except* '/' */
+ switch (disk[i]) {
+ case '\\':
+ case '.':
+ case '^':
+ case '$':
+ case '?':
+ case '*':
+ case '[':
+ case ']':
+ result[j++]='\\';
+ /* fall through */
+
+ default:
+ result[j++]=disk[i];
+ }
+ }
+ result[j++] = '$';
result[j] = '\0';
return result;
}
*
* ? -> [^/]
* * -> [^/]*
+ * [...] -> [...]
* [!...] -> [^...]
*
* The following are given a leading backslash to protect them
return result == 0;
}
-char *
+static char *
tar_to_regex(
const char * glob)
{
* 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
*
* ( ) { } + . ^ $ |
*
- * 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 == '\\') {
}
}
if (last_ch != '\\') {
+ *r++ = '(';
*r++ = '$';
+ *r++ = '|';
+ *r++ = '/';
+ *r++ = ')';
}
*r = '\0';
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;
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;
* 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) ||
i = match(regex,nword);
+ amfree(mword);
+ amfree(mglob);
amfree(nword);
amfree(nglob);
amfree(regex);
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;
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);
}
return (strncmp(level, mylevelexp, strlen(mylevelexp)) == 0);
}
}
+illegal:
+ error(_("Illegal level expression %s"),levelexp);
+ /*NOTREACHED*/
}