9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 1) /* SPDX-License-Identifier: GPL-2.0 */
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 2) #include <linux/module.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 3) #include <linux/kernel.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 4) #include <linux/string.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 5) #include <linux/slab.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 6) #include <linux/parser.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 7) #include <linux/errno.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 8) #include <linux/unicode.h>
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 9) #include <linux/stringhash.h>
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 10)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 11) #include "utf8n.h"
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 12)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 13) int utf8_validate(const struct unicode_map *um, const struct qstr *str)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 14) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 15) const struct utf8data *data = utf8nfdi(um->version);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 16)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 17) if (utf8nlen(data, str->name, str->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 18) return -1;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 19) return 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 20) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 21) EXPORT_SYMBOL(utf8_validate);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 22)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 23) int utf8_strncmp(const struct unicode_map *um,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 24) const struct qstr *s1, const struct qstr *s2)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 25) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 26) const struct utf8data *data = utf8nfdi(um->version);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 27) struct utf8cursor cur1, cur2;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 28) int c1, c2;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 29)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 30) if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 31) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 32)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 33) if (utf8ncursor(&cur2, data, s2->name, s2->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 34) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 35)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 36) do {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 37) c1 = utf8byte(&cur1);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 38) c2 = utf8byte(&cur2);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 39)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 40) if (c1 < 0 || c2 < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 41) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 42) if (c1 != c2)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 43) return 1;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 44) } while (c1);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 45)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 46) return 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 47) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 48) EXPORT_SYMBOL(utf8_strncmp);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 49)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 50) int utf8_strncasecmp(const struct unicode_map *um,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 51) const struct qstr *s1, const struct qstr *s2)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 52) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 53) const struct utf8data *data = utf8nfdicf(um->version);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 54) struct utf8cursor cur1, cur2;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 55) int c1, c2;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 56)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 57) if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 58) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 59)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 60) if (utf8ncursor(&cur2, data, s2->name, s2->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 61) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 62)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 63) do {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 64) c1 = utf8byte(&cur1);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 65) c2 = utf8byte(&cur2);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 66)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 67) if (c1 < 0 || c2 < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 68) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 69) if (c1 != c2)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 70) return 1;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 71) } while (c1);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 72)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 73) return 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 74) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 75) EXPORT_SYMBOL(utf8_strncasecmp);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 76)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 77) /* String cf is expected to be a valid UTF-8 casefolded
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 78) * string.
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 79) */
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 80) int utf8_strncasecmp_folded(const struct unicode_map *um,
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 81) const struct qstr *cf,
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 82) const struct qstr *s1)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 83) {
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 84) const struct utf8data *data = utf8nfdicf(um->version);
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 85) struct utf8cursor cur1;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 86) int c1, c2;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 87) int i = 0;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 88)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 89) if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 90) return -EINVAL;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 91)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 92) do {
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 93) c1 = utf8byte(&cur1);
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 94) c2 = cf->name[i++];
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 95) if (c1 < 0)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 96) return -EINVAL;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 97) if (c1 != c2)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 98) return 1;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 99) } while (c1);
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 100)
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 101) return 0;
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 102) }
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 103) EXPORT_SYMBOL(utf8_strncasecmp_folded);
3ae72562ad917 (Gabriel Krisman Bertazi 2019-06-19 23:45:09 -0400 104)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 105) int utf8_casefold(const struct unicode_map *um, const struct qstr *str,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 106) unsigned char *dest, size_t dlen)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 107) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 108) const struct utf8data *data = utf8nfdicf(um->version);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 109) struct utf8cursor cur;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 110) size_t nlen = 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 111)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 112) if (utf8ncursor(&cur, data, str->name, str->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 113) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 114)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 115) for (nlen = 0; nlen < dlen; nlen++) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 116) int c = utf8byte(&cur);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 117)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 118) dest[nlen] = c;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 119) if (!c)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 120) return nlen;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 121) if (c == -1)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 122) break;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 123) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 124) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 125) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 126) EXPORT_SYMBOL(utf8_casefold);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 127)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 128) int utf8_casefold_hash(const struct unicode_map *um, const void *salt,
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 129) struct qstr *str)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 130) {
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 131) const struct utf8data *data = utf8nfdicf(um->version);
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 132) struct utf8cursor cur;
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 133) int c;
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 134) unsigned long hash = init_name_hash(salt);
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 135)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 136) if (utf8ncursor(&cur, data, str->name, str->len) < 0)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 137) return -EINVAL;
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 138)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 139) while ((c = utf8byte(&cur))) {
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 140) if (c < 0)
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 141) return -EINVAL;
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 142) hash = partial_name_hash((unsigned char)c, hash);
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 143) }
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 144) str->hash = end_name_hash(hash);
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 145) return 0;
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 146) }
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 147) EXPORT_SYMBOL(utf8_casefold_hash);
3d7bfea8b8378 (Daniel Rosenberg 2020-07-08 02:12:34 -0700 148)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 149) int utf8_normalize(const struct unicode_map *um, const struct qstr *str,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 150) unsigned char *dest, size_t dlen)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 151) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 152) const struct utf8data *data = utf8nfdi(um->version);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 153) struct utf8cursor cur;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 154) ssize_t nlen = 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 155)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 156) if (utf8ncursor(&cur, data, str->name, str->len) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 157) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 158)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 159) for (nlen = 0; nlen < dlen; nlen++) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 160) int c = utf8byte(&cur);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 161)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 162) dest[nlen] = c;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 163) if (!c)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 164) return nlen;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 165) if (c == -1)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 166) break;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 167) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 168) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 169) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 170)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 171) EXPORT_SYMBOL(utf8_normalize);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 172)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 173) static int utf8_parse_version(const char *version, unsigned int *maj,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 174) unsigned int *min, unsigned int *rev)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 175) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 176) substring_t args[3];
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 177) char version_string[12];
aa28b98d6dbcd (Colin Ian King 2019-09-06 14:58:07 +0100 178) static const struct match_token token[] = {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 179) {1, "%d.%d.%d"},
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 180) {0, NULL}
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 181) };
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 182)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 183) strncpy(version_string, version, sizeof(version_string));
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 184)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 185) if (match_token(version_string, token, args) != 1)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 186) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 187)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 188) if (match_int(&args[0], maj) || match_int(&args[1], min) ||
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 189) match_int(&args[2], rev))
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 190) return -EINVAL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 191)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 192) return 0;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 193) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 194)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 195) struct unicode_map *utf8_load(const char *version)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 196) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 197) struct unicode_map *um = NULL;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 198) int unicode_version;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 199)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 200) if (version) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 201) unsigned int maj, min, rev;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 202)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 203) if (utf8_parse_version(version, &maj, &min, &rev) < 0)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 204) return ERR_PTR(-EINVAL);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 205)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 206) if (!utf8version_is_supported(maj, min, rev))
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 207) return ERR_PTR(-EINVAL);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 208)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 209) unicode_version = UNICODE_AGE(maj, min, rev);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 210) } else {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 211) unicode_version = utf8version_latest();
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 212) printk(KERN_WARNING"UTF-8 version not specified. "
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 213) "Assuming latest supported version (%d.%d.%d).",
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 214) (unicode_version >> 16) & 0xff,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 215) (unicode_version >> 8) & 0xff,
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 216) (unicode_version & 0xff));
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 217) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 218)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 219) um = kzalloc(sizeof(struct unicode_map), GFP_KERNEL);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 220) if (!um)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 221) return ERR_PTR(-ENOMEM);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 222)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 223) um->charset = "UTF-8";
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 224) um->version = unicode_version;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 225)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 226) return um;
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 227) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 228) EXPORT_SYMBOL(utf8_load);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 229)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 230) void utf8_unload(struct unicode_map *um)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 231) {
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 232) kfree(um);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 233) }
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 234) EXPORT_SYMBOL(utf8_unload);
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 235)
9d53690f0d4e5 (Gabriel Krisman Bertazi 2019-04-25 13:51:22 -0400 236) MODULE_LICENSE("GPL v2");