Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.4 215 lines 4.5 kB view raw
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> 9 10#include "utf8n.h" 11 12int utf8_validate(const struct unicode_map *um, const struct qstr *str) 13{ 14 const struct utf8data *data = utf8nfdi(um->version); 15 16 if (utf8nlen(data, str->name, str->len) < 0) 17 return -1; 18 return 0; 19} 20EXPORT_SYMBOL(utf8_validate); 21 22int utf8_strncmp(const struct unicode_map *um, 23 const struct qstr *s1, const struct qstr *s2) 24{ 25 const struct utf8data *data = utf8nfdi(um->version); 26 struct utf8cursor cur1, cur2; 27 int c1, c2; 28 29 if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0) 30 return -EINVAL; 31 32 if (utf8ncursor(&cur2, data, s2->name, s2->len) < 0) 33 return -EINVAL; 34 35 do { 36 c1 = utf8byte(&cur1); 37 c2 = utf8byte(&cur2); 38 39 if (c1 < 0 || c2 < 0) 40 return -EINVAL; 41 if (c1 != c2) 42 return 1; 43 } while (c1); 44 45 return 0; 46} 47EXPORT_SYMBOL(utf8_strncmp); 48 49int utf8_strncasecmp(const struct unicode_map *um, 50 const struct qstr *s1, const struct qstr *s2) 51{ 52 const struct utf8data *data = utf8nfdicf(um->version); 53 struct utf8cursor cur1, cur2; 54 int c1, c2; 55 56 if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0) 57 return -EINVAL; 58 59 if (utf8ncursor(&cur2, data, s2->name, s2->len) < 0) 60 return -EINVAL; 61 62 do { 63 c1 = utf8byte(&cur1); 64 c2 = utf8byte(&cur2); 65 66 if (c1 < 0 || c2 < 0) 67 return -EINVAL; 68 if (c1 != c2) 69 return 1; 70 } while (c1); 71 72 return 0; 73} 74EXPORT_SYMBOL(utf8_strncasecmp); 75 76/* String cf is expected to be a valid UTF-8 casefolded 77 * string. 78 */ 79int utf8_strncasecmp_folded(const struct unicode_map *um, 80 const struct qstr *cf, 81 const struct qstr *s1) 82{ 83 const struct utf8data *data = utf8nfdicf(um->version); 84 struct utf8cursor cur1; 85 int c1, c2; 86 int i = 0; 87 88 if (utf8ncursor(&cur1, data, s1->name, s1->len) < 0) 89 return -EINVAL; 90 91 do { 92 c1 = utf8byte(&cur1); 93 c2 = cf->name[i++]; 94 if (c1 < 0) 95 return -EINVAL; 96 if (c1 != c2) 97 return 1; 98 } while (c1); 99 100 return 0; 101} 102EXPORT_SYMBOL(utf8_strncasecmp_folded); 103 104int utf8_casefold(const struct unicode_map *um, const struct qstr *str, 105 unsigned char *dest, size_t dlen) 106{ 107 const struct utf8data *data = utf8nfdicf(um->version); 108 struct utf8cursor cur; 109 size_t nlen = 0; 110 111 if (utf8ncursor(&cur, data, str->name, str->len) < 0) 112 return -EINVAL; 113 114 for (nlen = 0; nlen < dlen; nlen++) { 115 int c = utf8byte(&cur); 116 117 dest[nlen] = c; 118 if (!c) 119 return nlen; 120 if (c == -1) 121 break; 122 } 123 return -EINVAL; 124} 125 126EXPORT_SYMBOL(utf8_casefold); 127 128int utf8_normalize(const struct unicode_map *um, const struct qstr *str, 129 unsigned char *dest, size_t dlen) 130{ 131 const struct utf8data *data = utf8nfdi(um->version); 132 struct utf8cursor cur; 133 ssize_t nlen = 0; 134 135 if (utf8ncursor(&cur, data, str->name, str->len) < 0) 136 return -EINVAL; 137 138 for (nlen = 0; nlen < dlen; nlen++) { 139 int c = utf8byte(&cur); 140 141 dest[nlen] = c; 142 if (!c) 143 return nlen; 144 if (c == -1) 145 break; 146 } 147 return -EINVAL; 148} 149 150EXPORT_SYMBOL(utf8_normalize); 151 152static int utf8_parse_version(const char *version, unsigned int *maj, 153 unsigned int *min, unsigned int *rev) 154{ 155 substring_t args[3]; 156 char version_string[12]; 157 static const struct match_token token[] = { 158 {1, "%d.%d.%d"}, 159 {0, NULL} 160 }; 161 162 strncpy(version_string, version, sizeof(version_string)); 163 164 if (match_token(version_string, token, args) != 1) 165 return -EINVAL; 166 167 if (match_int(&args[0], maj) || match_int(&args[1], min) || 168 match_int(&args[2], rev)) 169 return -EINVAL; 170 171 return 0; 172} 173 174struct unicode_map *utf8_load(const char *version) 175{ 176 struct unicode_map *um = NULL; 177 int unicode_version; 178 179 if (version) { 180 unsigned int maj, min, rev; 181 182 if (utf8_parse_version(version, &maj, &min, &rev) < 0) 183 return ERR_PTR(-EINVAL); 184 185 if (!utf8version_is_supported(maj, min, rev)) 186 return ERR_PTR(-EINVAL); 187 188 unicode_version = UNICODE_AGE(maj, min, rev); 189 } else { 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)); 196 } 197 198 um = kzalloc(sizeof(struct unicode_map), GFP_KERNEL); 199 if (!um) 200 return ERR_PTR(-ENOMEM); 201 202 um->charset = "UTF-8"; 203 um->version = unicode_version; 204 205 return um; 206} 207EXPORT_SYMBOL(utf8_load); 208 209void utf8_unload(struct unicode_map *um) 210{ 211 kfree(um); 212} 213EXPORT_SYMBOL(utf8_unload); 214 215MODULE_LICENSE("GPL v2");