~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/glob.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <linux/module.h>
  2 #include <linux/glob.h>
  3 
  4 /*
  5  * The only reason this code can be compiled as a module is because the
  6  * ATA code that depends on it can be as well.  In practice, they're
  7  * both usually compiled in and the module overhead goes away.
  8  */
  9 MODULE_DESCRIPTION("glob(7) matching");
 10 MODULE_LICENSE("Dual MIT/GPL");
 11 
 12 /**
 13  * glob_match - Shell-style pattern matching, like !fnmatch(pat, str, 0)
 14  * @pat: Shell-style pattern to match, e.g. "*.[ch]".
 15  * @str: String to match.  The pattern must match the entire string.
 16  *
 17  * Perform shell-style glob matching, returning true (1) if the match
 18  * succeeds, or false (0) if it fails.  Equivalent to !fnmatch(@pat, @str, 0).
 19  *
 20  * Pattern metacharacters are ?, *, [ and \.
 21  * (And, inside character classes, !, - and ].)
 22  *
 23  * This is small and simple implementation intended for device blacklists
 24  * where a string is matched against a number of patterns.  Thus, it
 25  * does not preprocess the patterns.  It is non-recursive, and run-time
 26  * is at most quadratic: strlen(@str)*strlen(@pat).
 27  *
 28  * An example of the worst case is glob_match("*aaaaa", "aaaaaaaaaa");
 29  * it takes 6 passes over the pattern before matching the string.
 30  *
 31  * Like !fnmatch(@pat, @str, 0) and unlike the shell, this does NOT
 32  * treat / or leading . specially; it isn't actually used for pathnames.
 33  *
 34  * Note that according to glob(7) (and unlike bash), character classes
 35  * are complemented by a leading !; this does not support the regex-style
 36  * [^a-z] syntax.
 37  *
 38  * An opening bracket without a matching close is matched literally.
 39  */
 40 bool __pure glob_match(char const *pat, char const *str)
 41 {
 42         /*
 43          * Backtrack to previous * on mismatch and retry starting one
 44          * character later in the string.  Because * matches all characters
 45          * (no exception for /), it can be easily proved that there's
 46          * never a need to backtrack multiple levels.
 47          */
 48         char const *back_pat = NULL, *back_str;
 49 
 50         /*
 51          * Loop over each token (character or class) in pat, matching
 52          * it against the remaining unmatched tail of str.  Return false
 53          * on mismatch, or true after matching the trailing nul bytes.
 54          */
 55         for (;;) {
 56                 unsigned char c = *str++;
 57                 unsigned char d = *pat++;
 58 
 59                 switch (d) {
 60                 case '?':       /* Wildcard: anything but nul */
 61                         if (c == '\0')
 62                                 return false;
 63                         break;
 64                 case '*':       /* Any-length wildcard */
 65                         if (*pat == '\0')       /* Optimize trailing * case */
 66                                 return true;
 67                         back_pat = pat;
 68                         back_str = --str;       /* Allow zero-length match */
 69                         break;
 70                 case '[': {     /* Character class */
 71                         bool match = false, inverted = (*pat == '!');
 72                         char const *class = pat + inverted;
 73                         unsigned char a = *class++;
 74 
 75                         /*
 76                          * Iterate over each span in the character class.
 77                          * A span is either a single character a, or a
 78                          * range a-b.  The first span may begin with ']'.
 79                          */
 80                         do {
 81                                 unsigned char b = a;
 82 
 83                                 if (a == '\0')  /* Malformed */
 84                                         goto literal;
 85 
 86                                 if (class[0] == '-' && class[1] != ']') {
 87                                         b = class[1];
 88 
 89                                         if (b == '\0')
 90                                                 goto literal;
 91 
 92                                         class += 2;
 93                                         /* Any special action if a > b? */
 94                                 }
 95                                 match |= (a <= c && c <= b);
 96                         } while ((a = *class++) != ']');
 97 
 98                         if (match == inverted)
 99                                 goto backtrack;
100                         pat = class;
101                         }
102                         break;
103                 case '\\':
104                         d = *pat++;
105                         fallthrough;
106                 default:        /* Literal character */
107 literal:
108                         if (c == d) {
109                                 if (d == '\0')
110                                         return true;
111                                 break;
112                         }
113 backtrack:
114                         if (c == '\0' || !back_pat)
115                                 return false;   /* No point continuing */
116                         /* Try again from last *, one character later in str. */
117                         pat = back_pat;
118                         str = ++back_str;
119                         break;
120                 }
121         }
122 }
123 EXPORT_SYMBOL(glob_match);
124 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php