0001
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
0073
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");