1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/string.h>
5 #include <linux/slab.h>
6 #include <linux/parser.h>
7 #include <linux/errno.h>
8 #include <linux/unicode.h>
9 #include <linux/stringhash.h>
13 int utf8_validate(const struct unicode_map
*um
, const struct qstr
*str
)
15 const struct utf8data
*data
= utf8nfdi(um
->version
);
17 if (utf8nlen(data
, str
->name
, str
->len
) < 0)
21 EXPORT_SYMBOL(utf8_validate
);
23 int utf8_strncmp(const struct unicode_map
*um
,
24 const struct qstr
*s1
, const struct qstr
*s2
)
26 const struct utf8data
*data
= utf8nfdi(um
->version
);
27 struct utf8cursor cur1
, cur2
;
30 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
33 if (utf8ncursor(&cur2
, data
, s2
->name
, s2
->len
) < 0)
48 EXPORT_SYMBOL(utf8_strncmp
);
50 int utf8_strncasecmp(const struct unicode_map
*um
,
51 const struct qstr
*s1
, const struct qstr
*s2
)
53 const struct utf8data
*data
= utf8nfdicf(um
->version
);
54 struct utf8cursor cur1
, cur2
;
57 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
60 if (utf8ncursor(&cur2
, data
, s2
->name
, s2
->len
) < 0)
75 EXPORT_SYMBOL(utf8_strncasecmp
);
77 /* String cf is expected to be a valid UTF-8 casefolded
80 int utf8_strncasecmp_folded(const struct unicode_map
*um
,
81 const struct qstr
*cf
,
82 const struct qstr
*s1
)
84 const struct utf8data
*data
= utf8nfdicf(um
->version
);
85 struct utf8cursor cur1
;
89 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
103 EXPORT_SYMBOL(utf8_strncasecmp_folded
);
105 int utf8_casefold(const struct unicode_map
*um
, const struct qstr
*str
,
106 unsigned char *dest
, size_t dlen
)
108 const struct utf8data
*data
= utf8nfdicf(um
->version
);
109 struct utf8cursor cur
;
112 if (utf8ncursor(&cur
, data
, str
->name
, str
->len
) < 0)
115 for (nlen
= 0; nlen
< dlen
; nlen
++) {
116 int c
= utf8byte(&cur
);
126 EXPORT_SYMBOL(utf8_casefold
);
128 int utf8_casefold_hash(const struct unicode_map
*um
, const void *salt
,
131 const struct utf8data
*data
= utf8nfdicf(um
->version
);
132 struct utf8cursor cur
;
134 unsigned long hash
= init_name_hash(salt
);
136 if (utf8ncursor(&cur
, data
, str
->name
, str
->len
) < 0)
139 while ((c
= utf8byte(&cur
))) {
142 hash
= partial_name_hash((unsigned char)c
, hash
);
144 str
->hash
= end_name_hash(hash
);
147 EXPORT_SYMBOL(utf8_casefold_hash
);
149 int utf8_normalize(const struct unicode_map
*um
, const struct qstr
*str
,
150 unsigned char *dest
, size_t dlen
)
152 const struct utf8data
*data
= utf8nfdi(um
->version
);
153 struct utf8cursor cur
;
156 if (utf8ncursor(&cur
, data
, str
->name
, str
->len
) < 0)
159 for (nlen
= 0; nlen
< dlen
; nlen
++) {
160 int c
= utf8byte(&cur
);
171 EXPORT_SYMBOL(utf8_normalize
);
173 static int utf8_parse_version(const char *version
, unsigned int *maj
,
174 unsigned int *min
, unsigned int *rev
)
177 char version_string
[12];
178 static const struct match_token token
[] = {
183 strncpy(version_string
, version
, sizeof(version_string
));
185 if (match_token(version_string
, token
, args
) != 1)
188 if (match_int(&args
[0], maj
) || match_int(&args
[1], min
) ||
189 match_int(&args
[2], rev
))
195 struct unicode_map
*utf8_load(const char *version
)
197 struct unicode_map
*um
= NULL
;
201 unsigned int maj
, min
, rev
;
203 if (utf8_parse_version(version
, &maj
, &min
, &rev
) < 0)
204 return ERR_PTR(-EINVAL
);
206 if (!utf8version_is_supported(maj
, min
, rev
))
207 return ERR_PTR(-EINVAL
);
209 unicode_version
= UNICODE_AGE(maj
, min
, rev
);
211 unicode_version
= utf8version_latest();
212 printk(KERN_WARNING
"UTF-8 version not specified. "
213 "Assuming latest supported version (%d.%d.%d).",
214 (unicode_version
>> 16) & 0xff,
215 (unicode_version
>> 8) & 0xff,
216 (unicode_version
& 0xff));
219 um
= kzalloc(sizeof(struct unicode_map
), GFP_KERNEL
);
221 return ERR_PTR(-ENOMEM
);
223 um
->charset
= "UTF-8";
224 um
->version
= unicode_version
;
228 EXPORT_SYMBOL(utf8_load
);
230 void utf8_unload(struct unicode_map
*um
)
234 EXPORT_SYMBOL(utf8_unload
);
236 MODULE_LICENSE("GPL v2");