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/stringhash.h>
12 int utf8_validate(const struct unicode_map
*um
, const struct qstr
*str
)
14 if (utf8nlen(um
, UTF8_NFDI
, str
->name
, str
->len
) < 0)
18 EXPORT_SYMBOL(utf8_validate
);
20 int utf8_strncmp(const struct unicode_map
*um
,
21 const struct qstr
*s1
, const struct qstr
*s2
)
23 struct utf8cursor cur1
, cur2
;
26 if (utf8ncursor(&cur1
, um
, UTF8_NFDI
, s1
->name
, s1
->len
) < 0)
29 if (utf8ncursor(&cur2
, um
, UTF8_NFDI
, s2
->name
, s2
->len
) < 0)
44 EXPORT_SYMBOL(utf8_strncmp
);
46 int utf8_strncasecmp(const struct unicode_map
*um
,
47 const struct qstr
*s1
, const struct qstr
*s2
)
49 struct utf8cursor cur1
, cur2
;
52 if (utf8ncursor(&cur1
, um
, UTF8_NFDICF
, s1
->name
, s1
->len
) < 0)
55 if (utf8ncursor(&cur2
, um
, UTF8_NFDICF
, s2
->name
, s2
->len
) < 0)
70 EXPORT_SYMBOL(utf8_strncasecmp
);
72 /* String cf is expected to be a valid UTF-8 casefolded
75 int utf8_strncasecmp_folded(const struct unicode_map
*um
,
76 const struct qstr
*cf
,
77 const struct qstr
*s1
)
79 struct utf8cursor cur1
;
83 if (utf8ncursor(&cur1
, um
, UTF8_NFDICF
, s1
->name
, s1
->len
) < 0)
97 EXPORT_SYMBOL(utf8_strncasecmp_folded
);
99 int utf8_casefold(const struct unicode_map
*um
, const struct qstr
*str
,
100 unsigned char *dest
, size_t dlen
)
102 struct utf8cursor cur
;
105 if (utf8ncursor(&cur
, um
, UTF8_NFDICF
, str
->name
, str
->len
) < 0)
108 for (nlen
= 0; nlen
< dlen
; nlen
++) {
109 int c
= utf8byte(&cur
);
119 EXPORT_SYMBOL(utf8_casefold
);
121 int utf8_casefold_hash(const struct unicode_map
*um
, const void *salt
,
124 struct utf8cursor cur
;
126 unsigned long hash
= init_name_hash(salt
);
128 if (utf8ncursor(&cur
, um
, UTF8_NFDICF
, str
->name
, str
->len
) < 0)
131 while ((c
= utf8byte(&cur
))) {
134 hash
= partial_name_hash((unsigned char)c
, hash
);
136 str
->hash
= end_name_hash(hash
);
139 EXPORT_SYMBOL(utf8_casefold_hash
);
141 int utf8_normalize(const struct unicode_map
*um
, const struct qstr
*str
,
142 unsigned char *dest
, size_t dlen
)
144 struct utf8cursor cur
;
147 if (utf8ncursor(&cur
, um
, UTF8_NFDI
, str
->name
, str
->len
) < 0)
150 for (nlen
= 0; nlen
< dlen
; nlen
++) {
151 int c
= utf8byte(&cur
);
161 EXPORT_SYMBOL(utf8_normalize
);
163 static const struct utf8data
*find_table_version(const struct utf8data
*table
,
164 size_t nr_entries
, unsigned int version
)
166 size_t i
= nr_entries
- 1;
168 while (version
< table
[i
].maxage
)
170 if (version
> table
[i
].maxage
)
175 struct unicode_map
*utf8_load(unsigned int version
)
177 struct unicode_map
*um
;
179 um
= kzalloc(sizeof(struct unicode_map
), GFP_KERNEL
);
181 return ERR_PTR(-ENOMEM
);
182 um
->version
= version
;
184 um
->tables
= symbol_request(utf8_data_table
);
188 if (!utf8version_is_supported(um
, version
))
190 um
->ntab
[UTF8_NFDI
] = find_table_version(um
->tables
->utf8nfdidata
,
191 um
->tables
->utf8nfdidata_size
, um
->version
);
192 if (!um
->ntab
[UTF8_NFDI
])
194 um
->ntab
[UTF8_NFDICF
] = find_table_version(um
->tables
->utf8nfdicfdata
,
195 um
->tables
->utf8nfdicfdata_size
, um
->version
);
196 if (!um
->ntab
[UTF8_NFDICF
])
201 symbol_put(utf8_data_table
);
204 return ERR_PTR(-EINVAL
);
206 EXPORT_SYMBOL(utf8_load
);
208 void utf8_unload(struct unicode_map
*um
)
211 symbol_put(utf8_data_table
);
215 EXPORT_SYMBOL(utf8_unload
);
218 * utf8_parse_version - Parse a UTF-8 version number from a string
220 * @version: input string
222 * Returns the parsed version on success, negative code on error
224 int utf8_parse_version(char *version
)
227 unsigned int maj
, min
, rev
;
228 static const struct match_token token
[] = {
233 if (match_token(version
, token
, args
) != 1)
236 if (match_int(&args
[0], &maj
) || match_int(&args
[1], &min
) ||
237 match_int(&args
[2], &rev
))
240 return UNICODE_AGE(maj
, min
, rev
);
242 EXPORT_SYMBOL(utf8_parse_version
);