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, str: 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" ); |
168 | |