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>
12 int utf8_validate(const struct unicode_map
*um
, const struct qstr
*str
)
14 const struct utf8data
*data
= utf8nfdi(um
->version
);
16 if (utf8nlen(data
, str
->name
, str
->len
) < 0)
20 EXPORT_SYMBOL(utf8_validate
);
22 int utf8_strncmp(const struct unicode_map
*um
,
23 const struct qstr
*s1
, const struct qstr
*s2
)
25 const struct utf8data
*data
= utf8nfdi(um
->version
);
26 struct utf8cursor cur1
, cur2
;
29 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
32 if (utf8ncursor(&cur2
, data
, s2
->name
, s2
->len
) < 0)
47 EXPORT_SYMBOL(utf8_strncmp
);
49 int utf8_strncasecmp(const struct unicode_map
*um
,
50 const struct qstr
*s1
, const struct qstr
*s2
)
52 const struct utf8data
*data
= utf8nfdicf(um
->version
);
53 struct utf8cursor cur1
, cur2
;
56 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
59 if (utf8ncursor(&cur2
, data
, s2
->name
, s2
->len
) < 0)
74 EXPORT_SYMBOL(utf8_strncasecmp
);
76 /* String cf is expected to be a valid UTF-8 casefolded
79 int utf8_strncasecmp_folded(const struct unicode_map
*um
,
80 const struct qstr
*cf
,
81 const struct qstr
*s1
)
83 const struct utf8data
*data
= utf8nfdicf(um
->version
);
84 struct utf8cursor cur1
;
88 if (utf8ncursor(&cur1
, data
, s1
->name
, s1
->len
) < 0)
102 EXPORT_SYMBOL(utf8_strncasecmp_folded
);
104 int utf8_casefold(const struct unicode_map
*um
, const struct qstr
*str
,
105 unsigned char *dest
, size_t dlen
)
107 const struct utf8data
*data
= utf8nfdicf(um
->version
);
108 struct utf8cursor cur
;
111 if (utf8ncursor(&cur
, data
, str
->name
, str
->len
) < 0)
114 for (nlen
= 0; nlen
< dlen
; nlen
++) {
115 int c
= utf8byte(&cur
);
126 EXPORT_SYMBOL(utf8_casefold
);
128 int utf8_normalize(const struct unicode_map
*um
, const struct qstr
*str
,
129 unsigned char *dest
, size_t dlen
)
131 const struct utf8data
*data
= utf8nfdi(um
->version
);
132 struct utf8cursor cur
;
135 if (utf8ncursor(&cur
, data
, str
->name
, str
->len
) < 0)
138 for (nlen
= 0; nlen
< dlen
; nlen
++) {
139 int c
= utf8byte(&cur
);
150 EXPORT_SYMBOL(utf8_normalize
);
152 static int utf8_parse_version(const char *version
, unsigned int *maj
,
153 unsigned int *min
, unsigned int *rev
)
156 char version_string
[12];
157 static const struct match_token token
[] = {
162 strncpy(version_string
, version
, sizeof(version_string
));
164 if (match_token(version_string
, token
, args
) != 1)
167 if (match_int(&args
[0], maj
) || match_int(&args
[1], min
) ||
168 match_int(&args
[2], rev
))
174 struct unicode_map
*utf8_load(const char *version
)
176 struct unicode_map
*um
= NULL
;
180 unsigned int maj
, min
, rev
;
182 if (utf8_parse_version(version
, &maj
, &min
, &rev
) < 0)
183 return ERR_PTR(-EINVAL
);
185 if (!utf8version_is_supported(maj
, min
, rev
))
186 return ERR_PTR(-EINVAL
);
188 unicode_version
= UNICODE_AGE(maj
, min
, rev
);
190 unicode_version
= utf8version_latest();
191 printk(KERN_WARNING
"UTF-8 version not specified. "
192 "Assuming latest supported version (%d.%d.%d).",
193 (unicode_version
>> 16) & 0xff,
194 (unicode_version
>> 8) & 0xff,
195 (unicode_version
& 0xff));
198 um
= kzalloc(sizeof(struct unicode_map
), GFP_KERNEL
);
200 return ERR_PTR(-ENOMEM
);
202 um
->charset
= "UTF-8";
203 um
->version
= unicode_version
;
207 EXPORT_SYMBOL(utf8_load
);
209 void utf8_unload(struct unicode_map
*um
)
213 EXPORT_SYMBOL(utf8_unload
);
215 MODULE_LICENSE("GPL v2");