]>
Commit | Line | Data |
---|---|---|
ba95b045 GU |
1 | /* |
2 | * Extracted fronm glob.c | |
3 | */ | |
4 | ||
5 | #include <linux/module.h> | |
6 | #include <linux/moduleparam.h> | |
7 | #include <linux/glob.h> | |
8 | #include <linux/printk.h> | |
9 | ||
10 | /* Boot with "glob.verbose=1" to show successful tests, too */ | |
11 | static bool verbose = false; | |
12 | module_param(verbose, bool, 0); | |
13 | ||
14 | struct glob_test { | |
15 | char const *pat, *str; | |
16 | bool expected; | |
17 | }; | |
18 | ||
19 | static bool __pure __init test(char const *pat, char const *str, bool expected) | |
20 | { | |
21 | bool match = glob_match(pat, str); | |
22 | bool success = match == expected; | |
23 | ||
24 | /* Can't get string literals into a particular section, so... */ | |
25 | static char const msg_error[] __initconst = | |
26 | KERN_ERR "glob: \"%s\" vs. \"%s\": %s *** ERROR ***\n"; | |
27 | static char const msg_ok[] __initconst = | |
28 | KERN_DEBUG "glob: \"%s\" vs. \"%s\": %s OK\n"; | |
29 | static char const mismatch[] __initconst = "mismatch"; | |
30 | char const *message; | |
31 | ||
32 | if (!success) | |
33 | message = msg_error; | |
34 | else if (verbose) | |
35 | message = msg_ok; | |
36 | else | |
37 | return success; | |
38 | ||
39 | printk(message, pat, str, mismatch + 3*match); | |
40 | return success; | |
41 | } | |
42 | ||
43 | /* | |
44 | * The tests are all jammed together in one array to make it simpler | |
45 | * to place that array in the .init.rodata section. The obvious | |
46 | * "array of structures containing char *" has no way to force the | |
47 | * pointed-to strings to be in a particular section. | |
48 | * | |
49 | * Anyway, a test consists of: | |
50 | * 1. Expected glob_match result: '1' or '0'. | |
51 | * 2. Pattern to match: null-terminated string | |
52 | * 3. String to match against: null-terminated string | |
53 | * | |
54 | * The list of tests is terminated with a final '\0' instead of | |
55 | * a glob_match result character. | |
56 | */ | |
57 | static char const glob_tests[] __initconst = | |
58 | /* Some basic tests */ | |
59 | "1" "a\0" "a\0" | |
60 | "0" "a\0" "b\0" | |
61 | "0" "a\0" "aa\0" | |
62 | "0" "a\0" "\0" | |
63 | "1" "\0" "\0" | |
64 | "0" "\0" "a\0" | |
65 | /* Simple character class tests */ | |
66 | "1" "[a]\0" "a\0" | |
67 | "0" "[a]\0" "b\0" | |
68 | "0" "[!a]\0" "a\0" | |
69 | "1" "[!a]\0" "b\0" | |
70 | "1" "[ab]\0" "a\0" | |
71 | "1" "[ab]\0" "b\0" | |
72 | "0" "[ab]\0" "c\0" | |
73 | "1" "[!ab]\0" "c\0" | |
74 | "1" "[a-c]\0" "b\0" | |
75 | "0" "[a-c]\0" "d\0" | |
76 | /* Corner cases in character class parsing */ | |
77 | "1" "[a-c-e-g]\0" "-\0" | |
78 | "0" "[a-c-e-g]\0" "d\0" | |
79 | "1" "[a-c-e-g]\0" "f\0" | |
80 | "1" "[]a-ceg-ik[]\0" "a\0" | |
81 | "1" "[]a-ceg-ik[]\0" "]\0" | |
82 | "1" "[]a-ceg-ik[]\0" "[\0" | |
83 | "1" "[]a-ceg-ik[]\0" "h\0" | |
84 | "0" "[]a-ceg-ik[]\0" "f\0" | |
85 | "0" "[!]a-ceg-ik[]\0" "h\0" | |
86 | "0" "[!]a-ceg-ik[]\0" "]\0" | |
87 | "1" "[!]a-ceg-ik[]\0" "f\0" | |
88 | /* Simple wild cards */ | |
89 | "1" "?\0" "a\0" | |
90 | "0" "?\0" "aa\0" | |
91 | "0" "??\0" "a\0" | |
92 | "1" "?x?\0" "axb\0" | |
93 | "0" "?x?\0" "abx\0" | |
94 | "0" "?x?\0" "xab\0" | |
95 | /* Asterisk wild cards (backtracking) */ | |
96 | "0" "*??\0" "a\0" | |
97 | "1" "*??\0" "ab\0" | |
98 | "1" "*??\0" "abc\0" | |
99 | "1" "*??\0" "abcd\0" | |
100 | "0" "??*\0" "a\0" | |
101 | "1" "??*\0" "ab\0" | |
102 | "1" "??*\0" "abc\0" | |
103 | "1" "??*\0" "abcd\0" | |
104 | "0" "?*?\0" "a\0" | |
105 | "1" "?*?\0" "ab\0" | |
106 | "1" "?*?\0" "abc\0" | |
107 | "1" "?*?\0" "abcd\0" | |
108 | "1" "*b\0" "b\0" | |
109 | "1" "*b\0" "ab\0" | |
110 | "0" "*b\0" "ba\0" | |
111 | "1" "*b\0" "bb\0" | |
112 | "1" "*b\0" "abb\0" | |
113 | "1" "*b\0" "bab\0" | |
114 | "1" "*bc\0" "abbc\0" | |
115 | "1" "*bc\0" "bc\0" | |
116 | "1" "*bc\0" "bbc\0" | |
117 | "1" "*bc\0" "bcbc\0" | |
118 | /* Multiple asterisks (complex backtracking) */ | |
119 | "1" "*ac*\0" "abacadaeafag\0" | |
120 | "1" "*ac*ae*ag*\0" "abacadaeafag\0" | |
121 | "1" "*a*b*[bc]*[ef]*g*\0" "abacadaeafag\0" | |
122 | "0" "*a*b*[ef]*[cd]*g*\0" "abacadaeafag\0" | |
123 | "1" "*abcd*\0" "abcabcabcabcdefg\0" | |
124 | "1" "*ab*cd*\0" "abcabcabcabcdefg\0" | |
125 | "1" "*abcd*abcdef*\0" "abcabcdabcdeabcdefg\0" | |
126 | "0" "*abcd*\0" "abcabcabcabcefg\0" | |
127 | "0" "*ab*cd*\0" "abcabcabcabcefg\0"; | |
128 | ||
129 | static int __init glob_init(void) | |
130 | { | |
131 | unsigned successes = 0; | |
132 | unsigned n = 0; | |
133 | char const *p = glob_tests; | |
134 | static char const message[] __initconst = | |
135 | KERN_INFO "glob: %u self-tests passed, %u failed\n"; | |
136 | ||
137 | /* | |
138 | * Tests are jammed together in a string. The first byte is '1' | |
139 | * or '0' to indicate the expected outcome, or '\0' to indicate the | |
140 | * end of the tests. Then come two null-terminated strings: the | |
141 | * pattern and the string to match it against. | |
142 | */ | |
143 | while (*p) { | |
144 | bool expected = *p++ & 1; | |
145 | char const *pat = p; | |
146 | ||
147 | p += strlen(p) + 1; | |
148 | successes += test(pat, p, expected); | |
149 | p += strlen(p) + 1; | |
150 | n++; | |
151 | } | |
152 | ||
153 | n -= successes; | |
154 | printk(message, successes, n); | |
155 | ||
156 | /* What's the errno for "kernel bug detected"? Guess... */ | |
157 | return n ? -ECANCELED : 0; | |
158 | } | |
159 | ||
160 | /* We need a dummy exit function to allow unload */ | |
161 | static void __exit glob_fini(void) { } | |
162 | ||
163 | module_init(glob_init); | |
164 | module_exit(glob_fini); | |
165 | ||
166 | MODULE_DESCRIPTION("glob(7) matching tests"); | |
167 | MODULE_LICENSE("Dual MIT/GPL"); |