00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "rsync.h"
00013
00014
00015 #define NEGATE_CLASS '!'
00016 #define NEGATE_CLASS2 '^'
00017
00018 #define FALSE 0
00019 #define TRUE 1
00020 #define ABORT_ALL -1
00021 #define ABORT_TO_STARSTAR -2
00022
00023 #define CC_EQ(class, len, litmatch) ((len) == sizeof (litmatch)-1 \
00024 && *(class) == *(litmatch) \
00025 && strncmp((char*)class, litmatch, len) == 0)
00026
00027 #if defined STDC_HEADERS || !defined isascii
00028 # define ISASCII(c) 1
00029 #else
00030 # define ISASCII(c) isascii(c)
00031 #endif
00032
00033 #ifdef isblank
00034 # define ISBLANK(c) (ISASCII(c) && isblank(c))
00035 #else
00036 # define ISBLANK(c) ((c) == ' ' || (c) == '\t')
00037 #endif
00038
00039 #ifdef isgraph
00040 # define ISGRAPH(c) (ISASCII(c) && isgraph(c))
00041 #else
00042 # define ISGRAPH(c) (ISASCII(c) && isprint(c) && !isspace(c))
00043 #endif
00044
00045 #define ISPRINT(c) (ISASCII(c) && isprint(c))
00046 #define ISDIGIT(c) (ISASCII(c) && isdigit(c))
00047 #define ISALNUM(c) (ISASCII(c) && isalnum(c))
00048 #define ISALPHA(c) (ISASCII(c) && isalpha(c))
00049 #define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
00050 #define ISLOWER(c) (ISASCII(c) && islower(c))
00051 #define ISPUNCT(c) (ISASCII(c) && ispunct(c))
00052 #define ISSPACE(c) (ISASCII(c) && isspace(c))
00053 #define ISUPPER(c) (ISASCII(c) && isupper(c))
00054 #define ISXDIGIT(c) (ISASCII(c) && isxdigit(c))
00055
00056 #ifdef WILD_TEST_ITERATIONS
00057 int wildmatch_iteration_count;
00058 #endif
00059
00060 static int force_lower_case = 0;
00061
00062
00063
00064 static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
00065 {
00066 uchar p_ch;
00067
00068 #ifdef WILD_TEST_ITERATIONS
00069 wildmatch_iteration_count++;
00070 #endif
00071
00072 for ( ; (p_ch = *p) != '\0'; text++, p++) {
00073 int matched, special;
00074 uchar t_ch, prev_ch;
00075 while ((t_ch = *text) == '\0') {
00076 if (*a == NULL) {
00077 if (p_ch != '*')
00078 return ABORT_ALL;
00079 break;
00080 }
00081 text = *a++;
00082 }
00083 if (force_lower_case && ISUPPER(t_ch))
00084 t_ch = tolower(t_ch);
00085 switch (p_ch) {
00086 case '\\':
00087
00088
00089 p_ch = *++p;
00090
00091 default:
00092 if (t_ch != p_ch)
00093 return FALSE;
00094 continue;
00095 case '?':
00096
00097 if (t_ch == '/')
00098 return FALSE;
00099 continue;
00100 case '*':
00101 if (*++p == '*') {
00102 while (*++p == '*') {}
00103 special = TRUE;
00104 } else
00105 special = FALSE;
00106 if (*p == '\0') {
00107
00108
00109 if (!special) {
00110 do {
00111 if (strchr((char*)text, '/') != NULL)
00112 return FALSE;
00113 } while ((text = *a++) != NULL);
00114 }
00115 return TRUE;
00116 }
00117 while (1) {
00118 if (t_ch == '\0') {
00119 if ((text = *a++) == NULL)
00120 break;
00121 t_ch = *text;
00122 continue;
00123 }
00124 if ((matched = dowild(p, text, a)) != FALSE) {
00125 if (!special || matched != ABORT_TO_STARSTAR)
00126 return matched;
00127 } else if (!special && t_ch == '/')
00128 return ABORT_TO_STARSTAR;
00129 t_ch = *++text;
00130 }
00131 return ABORT_ALL;
00132 case '[':
00133 p_ch = *++p;
00134 #ifdef NEGATE_CLASS2
00135 if (p_ch == NEGATE_CLASS2)
00136 p_ch = NEGATE_CLASS;
00137 #endif
00138
00139 special = p_ch == NEGATE_CLASS? TRUE : FALSE;
00140 if (special) {
00141
00142 p_ch = *++p;
00143 }
00144 prev_ch = 0;
00145 matched = FALSE;
00146 do {
00147 if (!p_ch)
00148 return ABORT_ALL;
00149 if (p_ch == '\\') {
00150 p_ch = *++p;
00151 if (!p_ch)
00152 return ABORT_ALL;
00153 if (t_ch == p_ch)
00154 matched = TRUE;
00155 } else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
00156 p_ch = *++p;
00157 if (p_ch == '\\') {
00158 p_ch = *++p;
00159 if (!p_ch)
00160 return ABORT_ALL;
00161 }
00162 if (t_ch <= p_ch && t_ch >= prev_ch)
00163 matched = TRUE;
00164 p_ch = 0;
00165 } else if (p_ch == '[' && p[1] == ':') {
00166 const uchar *s;
00167 int i;
00168 for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {}
00169 if (!p_ch)
00170 return ABORT_ALL;
00171 i = p - s - 1;
00172 if (i < 0 || p[-1] != ':') {
00173
00174 p = s - 2;
00175 p_ch = '[';
00176 if (t_ch == p_ch)
00177 matched = TRUE;
00178 continue;
00179 }
00180 if (CC_EQ(s,i, "alnum")) {
00181 if (ISALNUM(t_ch))
00182 matched = TRUE;
00183 } else if (CC_EQ(s,i, "alpha")) {
00184 if (ISALPHA(t_ch))
00185 matched = TRUE;
00186 } else if (CC_EQ(s,i, "blank")) {
00187 if (ISBLANK(t_ch))
00188 matched = TRUE;
00189 } else if (CC_EQ(s,i, "cntrl")) {
00190 if (ISCNTRL(t_ch))
00191 matched = TRUE;
00192 } else if (CC_EQ(s,i, "digit")) {
00193 if (ISDIGIT(t_ch))
00194 matched = TRUE;
00195 } else if (CC_EQ(s,i, "graph")) {
00196 if (ISGRAPH(t_ch))
00197 matched = TRUE;
00198 } else if (CC_EQ(s,i, "lower")) {
00199 if (ISLOWER(t_ch))
00200 matched = TRUE;
00201 } else if (CC_EQ(s,i, "print")) {
00202 if (ISPRINT(t_ch))
00203 matched = TRUE;
00204 } else if (CC_EQ(s,i, "punct")) {
00205 if (ISPUNCT(t_ch))
00206 matched = TRUE;
00207 } else if (CC_EQ(s,i, "space")) {
00208 if (ISSPACE(t_ch))
00209 matched = TRUE;
00210 } else if (CC_EQ(s,i, "upper")) {
00211 if (ISUPPER(t_ch))
00212 matched = TRUE;
00213 } else if (CC_EQ(s,i, "xdigit")) {
00214 if (ISXDIGIT(t_ch))
00215 matched = TRUE;
00216 } else
00217 return ABORT_ALL;
00218 p_ch = 0;
00219 } else if (t_ch == p_ch)
00220 matched = TRUE;
00221 } while (prev_ch = p_ch, (p_ch = *++p) != ']');
00222 if (matched == special || t_ch == '/')
00223 return FALSE;
00224 continue;
00225 }
00226 }
00227
00228 do {
00229 if (*text)
00230 return FALSE;
00231 } while ((text = *a++) != NULL);
00232
00233 return TRUE;
00234 }
00235
00236
00237
00238 static int doliteral(const uchar *s, const uchar *text, const uchar*const *a)
00239 {
00240 for ( ; *s != '\0'; text++, s++) {
00241 while (*text == '\0') {
00242 if ((text = *a++) == NULL)
00243 return FALSE;
00244 }
00245 if (*text != *s)
00246 return FALSE;
00247 }
00248
00249 do {
00250 if (*text)
00251 return FALSE;
00252 } while ((text = *a++) != NULL);
00253
00254 return TRUE;
00255 }
00256
00257
00258
00259
00260 static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
00261 {
00262 const uchar*const *a = *a_ptr;
00263 const uchar*const *first_a = a;
00264
00265 while (*a)
00266 a++;
00267
00268 while (a != first_a) {
00269 const uchar *s = *--a;
00270 s += strlen((char*)s);
00271 while (--s >= *a) {
00272 if (*s == '/' && !--count) {
00273 *a_ptr = a+1;
00274 return s+1;
00275 }
00276 }
00277 }
00278
00279 if (count == 1) {
00280 *a_ptr = a+1;
00281 return *a;
00282 }
00283
00284 return NULL;
00285 }
00286
00287
00288 int wildmatch(const char *pattern, const char *text)
00289 {
00290 static const uchar *nomore[1];
00291 #ifdef WILD_TEST_ITERATIONS
00292 wildmatch_iteration_count = 0;
00293 #endif
00294 return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
00295 }
00296
00297
00298 int iwildmatch(const char *pattern, const char *text)
00299 {
00300 static const uchar *nomore[1];
00301 int ret;
00302 #ifdef WILD_TEST_ITERATIONS
00303 wildmatch_iteration_count = 0;
00304 #endif
00305 force_lower_case = 1;
00306 ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
00307 force_lower_case = 0;
00308 return ret;
00309 }
00310
00311
00312
00313
00314
00315
00316 int wildmatch_array(const char *pattern, const char*const *texts, int where)
00317 {
00318 const uchar *p = (const uchar*)pattern;
00319 const uchar*const *a = (const uchar*const*)texts;
00320 const uchar *text;
00321 int matched;
00322
00323 #ifdef WILD_TEST_ITERATIONS
00324 wildmatch_iteration_count = 0;
00325 #endif
00326
00327 if (where > 0)
00328 text = trailing_N_elements(&a, where);
00329 else
00330 text = *a++;
00331 if (!text)
00332 return FALSE;
00333
00334 if ((matched = dowild(p, text, a)) != TRUE && where < 0
00335 && matched != ABORT_ALL) {
00336 while (1) {
00337 if (*text == '\0') {
00338 if ((text = (uchar*)*a++) == NULL)
00339 return FALSE;
00340 continue;
00341 }
00342 if (*text++ == '/' && (matched = dowild(p, text, a)) != FALSE
00343 && matched != ABORT_TO_STARSTAR)
00344 break;
00345 }
00346 }
00347 return matched == TRUE;
00348 }
00349
00350
00351
00352
00353
00354 int litmatch_array(const char *string, const char*const *texts, int where)
00355 {
00356 const uchar *s = (const uchar*)string;
00357 const uchar*const *a = (const uchar* const*)texts;
00358 const uchar *text;
00359
00360 if (where > 0)
00361 text = trailing_N_elements(&a, where);
00362 else
00363 text = *a++;
00364 if (!text)
00365 return FALSE;
00366
00367 return doliteral(s, text, a) == TRUE;
00368 }