1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Some of the source code in this file came from fs/cifs/cifs_unicode.c 4 * cifs_unicode: Unicode kernel case support 5 * 6 * Function: 7 * Convert a unicode character to upper or lower case using 8 * compressed tables. 9 * 10 * Copyright (c) International Business Machines Corp., 2000,2009 11 * 12 * 13 * Notes: 14 * These APIs are based on the C library functions. The semantics 15 * should match the C functions but with expanded size operands. 16 * 17 * The upper/lower functions are based on a table created by mkupr. 18 * This is a compressed table of upper and lower case conversion. 19 * 20 */ 21 #ifndef _CIFS_UNICODE_H 22 #define _CIFS_UNICODE_H 23 24 #include <asm/byteorder.h> 25 #include <linux/types.h> 26 #include <linux/nls.h> 27 #include <linux/unicode.h> 28 29 #define UNIUPR_NOLOWER /* Example to not expand lower case tables */ 30 31 /* 32 * Windows maps these to the user defined 16 bit Unicode range since they are 33 * reserved symbols (along with \ and /), otherwise illegal to store 34 * in filenames in NTFS 35 */ 36 #define UNI_ASTERISK ((__u16)('*' + 0xF000)) 37 #define UNI_QUESTION ((__u16)('?' + 0xF000)) 38 #define UNI_COLON ((__u16)(':' + 0xF000)) 39 #define UNI_GRTRTHAN ((__u16)('>' + 0xF000)) 40 #define UNI_LESSTHAN ((__u16)('<' + 0xF000)) 41 #define UNI_PIPE ((__u16)('|' + 0xF000)) 42 #define UNI_SLASH ((__u16)('\\' + 0xF000)) 43 44 /* Just define what we want from uniupr.h. We don't want to define the tables 45 * in each source file. 46 */ 47 #ifndef UNICASERANGE_DEFINED 48 struct UniCaseRange { 49 wchar_t start; 50 wchar_t end; 51 signed char *table; 52 }; 53 #endif /* UNICASERANGE_DEFINED */ 54 55 #ifndef UNIUPR_NOUPPER 56 extern signed char SmbUniUpperTable[512]; 57 extern const struct UniCaseRange SmbUniUpperRange[]; 58 #endif /* UNIUPR_NOUPPER */ 59 60 #ifndef UNIUPR_NOLOWER 61 extern signed char CifsUniLowerTable[512]; 62 extern const struct UniCaseRange CifsUniLowerRange[]; 63 #endif /* UNIUPR_NOLOWER */ 64 65 #ifdef __KERNEL__ 66 int smb_strtoUTF16(__le16 *to, const char *from, int len, 67 const struct nls_table *codepage); 68 char *smb_strndup_from_utf16(const char *src, const int maxlen, 69 const bool is_unicode, 70 const struct nls_table *codepage); 71 int smbConvertToUTF16(__le16 *target, const char *source, int srclen, 72 const struct nls_table *cp, int mapchars); 73 char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename); 74 #endif 75 76 /* 77 * UniStrcat: Concatenate the second string to the first 78 * 79 * Returns: 80 * Address of the first string 81 */ 82 static inline wchar_t *UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 83 { 84 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 85 86 while (*ucs1++) 87 /*NULL*/; /* To end of first string */ 88 ucs1--; /* Return to the null */ 89 while ((*ucs1++ = *ucs2++)) 90 /*NULL*/; /* copy string 2 over */ 91 return anchor; 92 } 93 94 /* 95 * UniStrchr: Find a character in a string 96 * 97 * Returns: 98 * Address of first occurrence of character in string 99 * or NULL if the character is not in the string 100 */ 101 static inline wchar_t *UniStrchr(const wchar_t *ucs, wchar_t uc) 102 { 103 while ((*ucs != uc) && *ucs) 104 ucs++; 105 106 if (*ucs == uc) 107 return (wchar_t *)ucs; 108 return NULL; 109 } 110 111 /* 112 * UniStrcmp: Compare two strings 113 * 114 * Returns: 115 * < 0: First string is less than second 116 * = 0: Strings are equal 117 * > 0: First string is greater than second 118 */ 119 static inline int UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 120 { 121 while ((*ucs1 == *ucs2) && *ucs1) { 122 ucs1++; 123 ucs2++; 124 } 125 return (int)*ucs1 - (int)*ucs2; 126 } 127 128 /* 129 * UniStrcpy: Copy a string 130 */ 131 static inline wchar_t *UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 132 { 133 wchar_t *anchor = ucs1; /* save the start of result string */ 134 135 while ((*ucs1++ = *ucs2++)) 136 /*NULL*/; 137 return anchor; 138 } 139 140 /* 141 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 142 */ 143 static inline size_t UniStrlen(const wchar_t *ucs1) 144 { 145 int i = 0; 146 147 while (*ucs1++) 148 i++; 149 return i; 150 } 151 152 /* 153 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 154 * string (length limited) 155 */ 156 static inline size_t UniStrnlen(const wchar_t *ucs1, int maxlen) 157 { 158 int i = 0; 159 160 while (*ucs1++) { 161 i++; 162 if (i >= maxlen) 163 break; 164 } 165 return i; 166 } 167 168 /* 169 * UniStrncat: Concatenate length limited string 170 */ 171 static inline wchar_t *UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 172 { 173 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 174 175 while (*ucs1++) 176 /*NULL*/; 177 ucs1--; /* point to null terminator of s1 */ 178 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 179 ucs1++; 180 ucs2++; 181 } 182 *ucs1 = 0; /* Null terminate the result */ 183 return anchor; 184 } 185 186 /* 187 * UniStrncmp: Compare length limited string 188 */ 189 static inline int UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 190 { 191 if (!n) 192 return 0; /* Null strings are equal */ 193 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 194 ucs1++; 195 ucs2++; 196 } 197 return (int)*ucs1 - (int)*ucs2; 198 } 199 200 /* 201 * UniStrncmp_le: Compare length limited string - native to little-endian 202 */ 203 static inline int 204 UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 205 { 206 if (!n) 207 return 0; /* Null strings are equal */ 208 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 209 ucs1++; 210 ucs2++; 211 } 212 return (int)*ucs1 - (int)__le16_to_cpu(*ucs2); 213 } 214 215 /* 216 * UniStrncpy: Copy length limited string with pad 217 */ 218 static inline wchar_t *UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 219 { 220 wchar_t *anchor = ucs1; 221 222 while (n-- && *ucs2) /* Copy the strings */ 223 *ucs1++ = *ucs2++; 224 225 n++; 226 while (n--) /* Pad with nulls */ 227 *ucs1++ = 0; 228 return anchor; 229 } 230 231 /* 232 * UniStrncpy_le: Copy length limited string with pad to little-endian 233 */ 234 static inline wchar_t *UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 235 { 236 wchar_t *anchor = ucs1; 237 238 while (n-- && *ucs2) /* Copy the strings */ 239 *ucs1++ = __le16_to_cpu(*ucs2++); 240 241 n++; 242 while (n--) /* Pad with nulls */ 243 *ucs1++ = 0; 244 return anchor; 245 } 246 247 /* 248 * UniStrstr: Find a string in a string 249 * 250 * Returns: 251 * Address of first match found 252 * NULL if no matching string is found 253 */ 254 static inline wchar_t *UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 255 { 256 const wchar_t *anchor1 = ucs1; 257 const wchar_t *anchor2 = ucs2; 258 259 while (*ucs1) { 260 if (*ucs1 == *ucs2) { 261 /* Partial match found */ 262 ucs1++; 263 ucs2++; 264 } else { 265 if (!*ucs2) /* Match found */ 266 return (wchar_t *)anchor1; 267 ucs1 = ++anchor1; /* No match */ 268 ucs2 = anchor2; 269 } 270 } 271 272 if (!*ucs2) /* Both end together */ 273 return (wchar_t *)anchor1; /* Match found */ 274 return NULL; /* No match */ 275 } 276 277 #ifndef UNIUPR_NOUPPER 278 /* 279 * UniToupper: Convert a unicode character to upper case 280 */ 281 static inline wchar_t UniToupper(register wchar_t uc) 282 { 283 register const struct UniCaseRange *rp; 284 285 if (uc < sizeof(SmbUniUpperTable)) { 286 /* Latin characters */ 287 return uc + SmbUniUpperTable[uc]; /* Use base tables */ 288 } 289 290 rp = SmbUniUpperRange; /* Use range tables */ 291 while (rp->start) { 292 if (uc < rp->start) /* Before start of range */ 293 return uc; /* Uppercase = input */ 294 if (uc <= rp->end) /* In range */ 295 return uc + rp->table[uc - rp->start]; 296 rp++; /* Try next range */ 297 } 298 return uc; /* Past last range */ 299 } 300 301 /* 302 * UniStrupr: Upper case a unicode string 303 */ 304 static inline __le16 *UniStrupr(register __le16 *upin) 305 { 306 register __le16 *up; 307 308 up = upin; 309 while (*up) { /* For all characters */ 310 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); 311 up++; 312 } 313 return upin; /* Return input pointer */ 314 } 315 #endif /* UNIUPR_NOUPPER */ 316 317 #ifndef UNIUPR_NOLOWER 318 /* 319 * UniTolower: Convert a unicode character to lower case 320 */ 321 static inline wchar_t UniTolower(register wchar_t uc) 322 { 323 register const struct UniCaseRange *rp; 324 325 if (uc < sizeof(CifsUniLowerTable)) { 326 /* Latin characters */ 327 return uc + CifsUniLowerTable[uc]; /* Use base tables */ 328 } 329 330 rp = CifsUniLowerRange; /* Use range tables */ 331 while (rp->start) { 332 if (uc < rp->start) /* Before start of range */ 333 return uc; /* Uppercase = input */ 334 if (uc <= rp->end) /* In range */ 335 return uc + rp->table[uc - rp->start]; 336 rp++; /* Try next range */ 337 } 338 return uc; /* Past last range */ 339 } 340 341 /* 342 * UniStrlwr: Lower case a unicode string 343 */ 344 static inline wchar_t *UniStrlwr(register wchar_t *upin) 345 { 346 register wchar_t *up; 347 348 up = upin; 349 while (*up) { /* For all characters */ 350 *up = UniTolower(*up); 351 up++; 352 } 353 return upin; /* Return input pointer */ 354 } 355 356 #endif 357 358 #endif /* _CIFS_UNICODE_H */ 359