at v6.4 358 lines 8.4 kB view raw
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 48struct UniCaseRange { 49 wchar_t start; 50 wchar_t end; 51 signed char *table; 52}; 53#endif /* UNICASERANGE_DEFINED */ 54 55#ifndef UNIUPR_NOUPPER 56extern signed char SmbUniUpperTable[512]; 57extern const struct UniCaseRange SmbUniUpperRange[]; 58#endif /* UNIUPR_NOUPPER */ 59 60#ifndef UNIUPR_NOLOWER 61extern signed char CifsUniLowerTable[512]; 62extern const struct UniCaseRange CifsUniLowerRange[]; 63#endif /* UNIUPR_NOLOWER */ 64 65#ifdef __KERNEL__ 66int smb_strtoUTF16(__le16 *to, const char *from, int len, 67 const struct nls_table *codepage); 68char *smb_strndup_from_utf16(const char *src, const int maxlen, 69 const bool is_unicode, 70 const struct nls_table *codepage); 71int smbConvertToUTF16(__le16 *target, const char *source, int srclen, 72 const struct nls_table *cp, int mapchars); 73char *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 */ 82static 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 */ 101static 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 */ 119static 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 */ 131static 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 */ 143static 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 */ 156static 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 */ 171static 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 */ 189static 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 */ 203static inline int 204UniStrncmp_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 */ 218static 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 */ 234static 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 */ 254static 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 */ 281static 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 */ 304static 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 */ 321static 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 */ 344static 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 */