![]() |
|
|||
0001 #include <linux/module.h> 0002 #include <linux/glob.h> 0003 0004 /* 0005 * The only reason this code can be compiled as a module is because the 0006 * ATA code that depends on it can be as well. In practice, they're 0007 * both usually compiled in and the module overhead goes away. 0008 */ 0009 MODULE_DESCRIPTION("glob(7) matching"); 0010 MODULE_LICENSE("Dual MIT/GPL"); 0011 0012 /** 0013 * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0) 0014 * @pat: Shell-style pattern to match, e.g. "*.[ch]". 0015 * @str: String to match. The pattern must match the entire string. 0016 * 0017 * Perform shell-style glob matching, returning true (1) if the match 0018 * succeeds, or false (0) if it fails. Equivalent to !fnmatch(@pat, @str, 0). 0019 * 0020 * Pattern metacharacters are ?, *, [ and \. 0021 * (And, inside character classes, !, - and ].) 0022 * 0023 * This is small and simple implementation intended for device blacklists 0024 * where a string is matched against a number of patterns. Thus, it 0025 * does not preprocess the patterns. It is non-recursive, and run-time 0026 * is at most quadratic: strlen(@str)*strlen(@pat). 0027 * 0028 * An example of the worst case is glob_match("*aaaaa", "aaaaaaaaaa"); 0029 * it takes 6 passes over the pattern before matching the string. 0030 * 0031 * Like !fnmatch(@pat, @str, 0) and unlike the shell, this does NOT 0032 * treat / or leading . specially; it isn't actually used for pathnames. 0033 * 0034 * Note that according to glob(7) (and unlike bash), character classes 0035 * are complemented by a leading !; this does not support the regex-style 0036 * [^a-z] syntax. 0037 * 0038 * An opening bracket without a matching close is matched literally. 0039 */ 0040 bool __pure glob_match(char const *pat, char const *str) 0041 { 0042 /* 0043 * Backtrack to previous * on mismatch and retry starting one 0044 * character later in the string. Because * matches all characters 0045 * (no exception for /), it can be easily proved that there's 0046 * never a need to backtrack multiple levels. 0047 */ 0048 char const *back_pat = NULL, *back_str; 0049 0050 /* 0051 * Loop over each token (character or class) in pat, matching 0052 * it against the remaining unmatched tail of str. Return false 0053 * on mismatch, or true after matching the trailing nul bytes. 0054 */ 0055 for (;;) { 0056 unsigned char c = *str++; 0057 unsigned char d = *pat++; 0058 0059 switch (d) { 0060 case '?': /* Wildcard: anything but nul */ 0061 if (c == '\0') 0062 return false; 0063 break; 0064 case '*': /* Any-length wildcard */ 0065 if (*pat == '\0') /* Optimize trailing * case */ 0066 return true; 0067 back_pat = pat; 0068 back_str = --str; /* Allow zero-length match */ 0069 break; 0070 case '[': { /* Character class */ 0071 bool match = false, inverted = (*pat == '!'); 0072 char const *class = pat + inverted; 0073 unsigned char a = *class++; 0074 0075 /* 0076 * Iterate over each span in the character class. 0077 * A span is either a single character a, or a 0078 * range a-b. The first span may begin with ']'. 0079 */ 0080 do { 0081 unsigned char b = a; 0082 0083 if (a == '\0') /* Malformed */ 0084 goto literal; 0085 0086 if (class[0] == '-' && class[1] != ']') { 0087 b = class[1]; 0088 0089 if (b == '\0') 0090 goto literal; 0091 0092 class += 2; 0093 /* Any special action if a > b? */ 0094 } 0095 match |= (a <= c && c <= b); 0096 } while ((a = *class++) != ']'); 0097 0098 if (match == inverted) 0099 goto backtrack; 0100 pat = class; 0101 } 0102 break; 0103 case '\\': 0104 d = *pat++; 0105 fallthrough; 0106 default: /* Literal character */ 0107 literal: 0108 if (c == d) { 0109 if (d == '\0') 0110 return true; 0111 break; 0112 } 0113 backtrack: 0114 if (c == '\0' || !back_pat) 0115 return false; /* No point continuing */ 0116 /* Try again from last *, one character later in str. */ 0117 pat = back_pat; 0118 str = ++back_str; 0119 break; 0120 } 0121 } 0122 } 0123 EXPORT_SYMBOL(glob_match);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |