Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #include <linux/module.h>
0003 #include <linux/kernel.h>
0004 #include <linux/string.h>
0005 #include <linux/slab.h>
0006 #include <linux/parser.h>
0007 #include <linux/errno.h>
0008 #include <linux/stringhash.h>
0009 
0010 #include "utf8n.h"
0011 
0012 int utf8_validate(const struct unicode_map *um, const struct qstr *str)
0013 {
0014     if (utf8nlen(um, UTF8_NFDI, str->name, str->len) < 0)
0015         return -1;
0016     return 0;
0017 }
0018 EXPORT_SYMBOL(utf8_validate);
0019 
0020 int utf8_strncmp(const struct unicode_map *um,
0021          const struct qstr *s1, const struct qstr *s2)
0022 {
0023     struct utf8cursor cur1, cur2;
0024     int c1, c2;
0025 
0026     if (utf8ncursor(&cur1, um, UTF8_NFDI, s1->name, s1->len) < 0)
0027         return -EINVAL;
0028 
0029     if (utf8ncursor(&cur2, um, UTF8_NFDI, s2->name, s2->len) < 0)
0030         return -EINVAL;
0031 
0032     do {
0033         c1 = utf8byte(&cur1);
0034         c2 = utf8byte(&cur2);
0035 
0036         if (c1 < 0 || c2 < 0)
0037             return -EINVAL;
0038         if (c1 != c2)
0039             return 1;
0040     } while (c1);
0041 
0042     return 0;
0043 }
0044 EXPORT_SYMBOL(utf8_strncmp);
0045 
0046 int utf8_strncasecmp(const struct unicode_map *um,
0047              const struct qstr *s1, const struct qstr *s2)
0048 {
0049     struct utf8cursor cur1, cur2;
0050     int c1, c2;
0051 
0052     if (utf8ncursor(&cur1, um, UTF8_NFDICF, s1->name, s1->len) < 0)
0053         return -EINVAL;
0054 
0055     if (utf8ncursor(&cur2, um, UTF8_NFDICF, s2->name, s2->len) < 0)
0056         return -EINVAL;
0057 
0058     do {
0059         c1 = utf8byte(&cur1);
0060         c2 = utf8byte(&cur2);
0061 
0062         if (c1 < 0 || c2 < 0)
0063             return -EINVAL;
0064         if (c1 != c2)
0065             return 1;
0066     } while (c1);
0067 
0068     return 0;
0069 }
0070 EXPORT_SYMBOL(utf8_strncasecmp);
0071 
0072 /* String cf is expected to be a valid UTF-8 casefolded
0073  * string.
0074  */
0075 int utf8_strncasecmp_folded(const struct unicode_map *um,
0076                 const struct qstr *cf,
0077                 const struct qstr *s1)
0078 {
0079     struct utf8cursor cur1;
0080     int c1, c2;
0081     int i = 0;
0082 
0083     if (utf8ncursor(&cur1, um, UTF8_NFDICF, s1->name, s1->len) < 0)
0084         return -EINVAL;
0085 
0086     do {
0087         c1 = utf8byte(&cur1);
0088         c2 = cf->name[i++];
0089         if (c1 < 0)
0090             return -EINVAL;
0091         if (c1 != c2)
0092             return 1;
0093     } while (c1);
0094 
0095     return 0;
0096 }
0097 EXPORT_SYMBOL(utf8_strncasecmp_folded);
0098 
0099 int utf8_casefold(const struct unicode_map *um, const struct qstr *str,
0100           unsigned char *dest, size_t dlen)
0101 {
0102     struct utf8cursor cur;
0103     size_t nlen = 0;
0104 
0105     if (utf8ncursor(&cur, um, UTF8_NFDICF, str->name, str->len) < 0)
0106         return -EINVAL;
0107 
0108     for (nlen = 0; nlen < dlen; nlen++) {
0109         int c = utf8byte(&cur);
0110 
0111         dest[nlen] = c;
0112         if (!c)
0113             return nlen;
0114         if (c == -1)
0115             break;
0116     }
0117     return -EINVAL;
0118 }
0119 EXPORT_SYMBOL(utf8_casefold);
0120 
0121 int utf8_casefold_hash(const struct unicode_map *um, const void *salt,
0122                struct qstr *str)
0123 {
0124     struct utf8cursor cur;
0125     int c;
0126     unsigned long hash = init_name_hash(salt);
0127 
0128     if (utf8ncursor(&cur, um, UTF8_NFDICF, str->name, str->len) < 0)
0129         return -EINVAL;
0130 
0131     while ((c = utf8byte(&cur))) {
0132         if (c < 0)
0133             return -EINVAL;
0134         hash = partial_name_hash((unsigned char)c, hash);
0135     }
0136     str->hash = end_name_hash(hash);
0137     return 0;
0138 }
0139 EXPORT_SYMBOL(utf8_casefold_hash);
0140 
0141 int utf8_normalize(const struct unicode_map *um, const struct qstr *str,
0142            unsigned char *dest, size_t dlen)
0143 {
0144     struct utf8cursor cur;
0145     ssize_t nlen = 0;
0146 
0147     if (utf8ncursor(&cur, um, UTF8_NFDI, str->name, str->len) < 0)
0148         return -EINVAL;
0149 
0150     for (nlen = 0; nlen < dlen; nlen++) {
0151         int c = utf8byte(&cur);
0152 
0153         dest[nlen] = c;
0154         if (!c)
0155             return nlen;
0156         if (c == -1)
0157             break;
0158     }
0159     return -EINVAL;
0160 }
0161 EXPORT_SYMBOL(utf8_normalize);
0162 
0163 static const struct utf8data *find_table_version(const struct utf8data *table,
0164         size_t nr_entries, unsigned int version)
0165 {
0166     size_t i = nr_entries - 1;
0167 
0168     while (version < table[i].maxage)
0169         i--;
0170     if (version > table[i].maxage)
0171         return NULL;
0172     return &table[i];
0173 }
0174 
0175 struct unicode_map *utf8_load(unsigned int version)
0176 {
0177     struct unicode_map *um;
0178 
0179     um = kzalloc(sizeof(struct unicode_map), GFP_KERNEL);
0180     if (!um)
0181         return ERR_PTR(-ENOMEM);
0182     um->version = version;
0183 
0184     um->tables = symbol_request(utf8_data_table);
0185     if (!um->tables)
0186         goto out_free_um;
0187 
0188     if (!utf8version_is_supported(um, version))
0189         goto out_symbol_put;
0190     um->ntab[UTF8_NFDI] = find_table_version(um->tables->utf8nfdidata,
0191             um->tables->utf8nfdidata_size, um->version);
0192     if (!um->ntab[UTF8_NFDI])
0193         goto out_symbol_put;
0194     um->ntab[UTF8_NFDICF] = find_table_version(um->tables->utf8nfdicfdata,
0195             um->tables->utf8nfdicfdata_size, um->version);
0196     if (!um->ntab[UTF8_NFDICF])
0197         goto out_symbol_put;
0198     return um;
0199 
0200 out_symbol_put:
0201     symbol_put(um->tables);
0202 out_free_um:
0203     kfree(um);
0204     return ERR_PTR(-EINVAL);
0205 }
0206 EXPORT_SYMBOL(utf8_load);
0207 
0208 void utf8_unload(struct unicode_map *um)
0209 {
0210     if (um) {
0211         symbol_put(utf8_data_table);
0212         kfree(um);
0213     }
0214 }
0215 EXPORT_SYMBOL(utf8_unload);
0216 
0217 MODULE_LICENSE("GPL v2");