1
2
3
4
5
6
7
8#include <linux/ctype.h>
9#include <linux/types.h>
10#include <linux/export.h>
11#include <linux/parser.h>
12#include <linux/slab.h>
13#include <linux/string.h>
14
15
16
17
18
19
20
21
22
23
24
25
26static int match_one(char *s, const char *p, substring_t args[])
27{
28 char *meta;
29 int argc = 0;
30
31 if (!p)
32 return 1;
33
34 while(1) {
35 int len = -1;
36 meta = strchr(p, '%');
37 if (!meta)
38 return strcmp(p, s) == 0;
39
40 if (strncmp(p, s, meta-p))
41 return 0;
42
43 s += meta - p;
44 p = meta + 1;
45
46 if (isdigit(*p))
47 len = simple_strtoul(p, (char **) &p, 10);
48 else if (*p == '%') {
49 if (*s++ != '%')
50 return 0;
51 p++;
52 continue;
53 }
54
55 if (argc >= MAX_OPT_ARGS)
56 return 0;
57
58 args[argc].from = s;
59 switch (*p++) {
60 case 's': {
61 size_t str_len = strlen(s);
62
63 if (str_len == 0)
64 return 0;
65 if (len == -1 || len > str_len)
66 len = str_len;
67 args[argc].to = s + len;
68 break;
69 }
70 case 'd':
71 simple_strtol(s, &args[argc].to, 0);
72 goto num;
73 case 'u':
74 simple_strtoul(s, &args[argc].to, 0);
75 goto num;
76 case 'o':
77 simple_strtoul(s, &args[argc].to, 8);
78 goto num;
79 case 'x':
80 simple_strtoul(s, &args[argc].to, 16);
81 num:
82 if (args[argc].to == args[argc].from)
83 return 0;
84 break;
85 default:
86 return 0;
87 }
88 s = args[argc].to;
89 argc++;
90 }
91}
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107int match_token(char *s, const match_table_t table, substring_t args[])
108{
109 const struct match_token *p;
110
111 for (p = table; !match_one(s, p->pattern, args) ; p++)
112 ;
113
114 return p->token;
115}
116EXPORT_SYMBOL(match_token);
117
118
119
120
121
122
123
124
125
126
127
128static int match_number(substring_t *s, int *result, int base)
129{
130 char *endp;
131 char *buf;
132 int ret;
133 long val;
134 size_t len = s->to - s->from;
135
136 buf = kmalloc(len + 1, GFP_KERNEL);
137 if (!buf)
138 return -ENOMEM;
139 memcpy(buf, s->from, len);
140 buf[len] = '\0';
141
142 ret = 0;
143 val = simple_strtol(buf, &endp, base);
144 if (endp == buf)
145 ret = -EINVAL;
146 else if (val < (long)INT_MIN || val > (long)INT_MAX)
147 ret = -ERANGE;
148 else
149 *result = (int) val;
150 kfree(buf);
151 return ret;
152}
153
154
155
156
157
158
159
160
161
162
163int match_int(substring_t *s, int *result)
164{
165 return match_number(s, result, 0);
166}
167EXPORT_SYMBOL(match_int);
168
169
170
171
172
173
174
175
176
177
178int match_octal(substring_t *s, int *result)
179{
180 return match_number(s, result, 8);
181}
182EXPORT_SYMBOL(match_octal);
183
184
185
186
187
188
189
190
191
192
193int match_hex(substring_t *s, int *result)
194{
195 return match_number(s, result, 16);
196}
197EXPORT_SYMBOL(match_hex);
198
199
200
201
202
203
204
205
206
207
208
209
210bool match_wildcard(const char *pattern, const char *str)
211{
212 const char *s = str;
213 const char *p = pattern;
214 bool star = false;
215
216 while (*s) {
217 switch (*p) {
218 case '?':
219 s++;
220 p++;
221 break;
222 case '*':
223 star = true;
224 str = s;
225 if (!*++p)
226 return true;
227 pattern = p;
228 break;
229 default:
230 if (*s == *p) {
231 s++;
232 p++;
233 } else {
234 if (!star)
235 return false;
236 str++;
237 s = str;
238 p = pattern;
239 }
240 break;
241 }
242 }
243
244 if (*p == '*')
245 ++p;
246 return !*p;
247}
248EXPORT_SYMBOL(match_wildcard);
249
250
251
252
253
254
255
256
257
258
259
260size_t match_strlcpy(char *dest, const substring_t *src, size_t size)
261{
262 size_t ret = src->to - src->from;
263
264 if (size) {
265 size_t len = ret >= size ? size - 1 : ret;
266 memcpy(dest, src->from, len);
267 dest[len] = '\0';
268 }
269 return ret;
270}
271EXPORT_SYMBOL(match_strlcpy);
272
273
274
275
276
277
278
279
280
281char *match_strdup(const substring_t *s)
282{
283 size_t sz = s->to - s->from + 1;
284 char *p = kmalloc(sz, GFP_KERNEL);
285 if (p)
286 match_strlcpy(p, s, sz);
287 return p;
288}
289EXPORT_SYMBOL(match_strdup);
290