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

Configure Feed

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

at v5.1 419 lines 10 kB view raw
1/* 2 * cifs_unicode: Unicode kernel case support 3 * 4 * Function: 5 * Convert a unicode character to upper or lower case using 6 * compressed tables. 7 * 8 * Copyright (c) International Business Machines Corp., 2000,2009 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 18 * the GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 * 25 * Notes: 26 * These APIs are based on the C library functions. The semantics 27 * should match the C functions but with expanded size operands. 28 * 29 * The upper/lower functions are based on a table created by mkupr. 30 * This is a compressed table of upper and lower case conversion. 31 * 32 */ 33#ifndef _CIFS_UNICODE_H 34#define _CIFS_UNICODE_H 35 36#include <asm/byteorder.h> 37#include <linux/types.h> 38#include <linux/nls.h> 39 40#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ 41 42/* 43 * Windows maps these to the user defined 16 bit Unicode range since they are 44 * reserved symbols (along with \ and /), otherwise illegal to store 45 * in filenames in NTFS 46 */ 47#define UNI_ASTERISK (__u16) ('*' + 0xF000) 48#define UNI_QUESTION (__u16) ('?' + 0xF000) 49#define UNI_COLON (__u16) (':' + 0xF000) 50#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) 51#define UNI_LESSTHAN (__u16) ('<' + 0xF000) 52#define UNI_PIPE (__u16) ('|' + 0xF000) 53#define UNI_SLASH (__u16) ('\\' + 0xF000) 54 55/* 56 * Macs use an older "SFM" mapping of the symbols above. Fortunately it does 57 * not conflict (although almost does) with the mapping above. 58 */ 59 60#define SFM_DOUBLEQUOTE ((__u16) 0xF020) 61#define SFM_ASTERISK ((__u16) 0xF021) 62#define SFM_QUESTION ((__u16) 0xF025) 63#define SFM_COLON ((__u16) 0xF022) 64#define SFM_GRTRTHAN ((__u16) 0xF024) 65#define SFM_LESSTHAN ((__u16) 0xF023) 66#define SFM_PIPE ((__u16) 0xF027) 67#define SFM_SLASH ((__u16) 0xF026) 68#define SFM_SPACE ((__u16) 0xF028) 69#define SFM_PERIOD ((__u16) 0xF029) 70 71/* 72 * Mapping mechanism to use when one of the seven reserved characters is 73 * encountered. We can only map using one of the mechanisms at a time 74 * since otherwise readdir could return directory entries which we would 75 * not be able to open 76 * 77 * NO_MAP_UNI_RSVD = do not perform any remapping of the character 78 * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible) 79 * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option) 80 * 81 */ 82#define NO_MAP_UNI_RSVD 0 83#define SFM_MAP_UNI_RSVD 1 84#define SFU_MAP_UNI_RSVD 2 85 86/* Just define what we want from uniupr.h. We don't want to define the tables 87 * in each source file. 88 */ 89#ifndef UNICASERANGE_DEFINED 90struct UniCaseRange { 91 wchar_t start; 92 wchar_t end; 93 signed char *table; 94}; 95#endif /* UNICASERANGE_DEFINED */ 96 97#ifndef UNIUPR_NOUPPER 98extern signed char CifsUniUpperTable[512]; 99extern const struct UniCaseRange CifsUniUpperRange[]; 100#endif /* UNIUPR_NOUPPER */ 101 102#ifndef UNIUPR_NOLOWER 103extern signed char CifsUniLowerTable[512]; 104extern const struct UniCaseRange CifsUniLowerRange[]; 105#endif /* UNIUPR_NOLOWER */ 106 107#ifdef __KERNEL__ 108int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, 109 const struct nls_table *cp, int map_type); 110int cifs_utf16_bytes(const __le16 *from, int maxbytes, 111 const struct nls_table *codepage); 112int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); 113char *cifs_strndup_from_utf16(const char *src, const int maxlen, 114 const bool is_unicode, 115 const struct nls_table *codepage); 116extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, 117 const struct nls_table *cp, int mapChars); 118extern int cifs_remap(struct cifs_sb_info *cifs_sb); 119extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, 120 int *utf16_len, const struct nls_table *cp, 121 int remap); 122#endif 123 124wchar_t cifs_toupper(wchar_t in); 125 126/* 127 * UniStrcat: Concatenate the second string to the first 128 * 129 * Returns: 130 * Address of the first string 131 */ 132static inline __le16 * 133UniStrcat(__le16 *ucs1, const __le16 *ucs2) 134{ 135 __le16 *anchor = ucs1; /* save a pointer to start of ucs1 */ 136 137 while (*ucs1++) ; /* To end of first string */ 138 ucs1--; /* Return to the null */ 139 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ 140 return anchor; 141} 142 143/* 144 * UniStrchr: Find a character in a string 145 * 146 * Returns: 147 * Address of first occurrence of character in string 148 * or NULL if the character is not in the string 149 */ 150static inline wchar_t * 151UniStrchr(const wchar_t *ucs, wchar_t uc) 152{ 153 while ((*ucs != uc) && *ucs) 154 ucs++; 155 156 if (*ucs == uc) 157 return (wchar_t *) ucs; 158 return NULL; 159} 160 161/* 162 * UniStrcmp: Compare two strings 163 * 164 * Returns: 165 * < 0: First string is less than second 166 * = 0: Strings are equal 167 * > 0: First string is greater than second 168 */ 169static inline int 170UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 171{ 172 while ((*ucs1 == *ucs2) && *ucs1) { 173 ucs1++; 174 ucs2++; 175 } 176 return (int) *ucs1 - (int) *ucs2; 177} 178 179/* 180 * UniStrcpy: Copy a string 181 */ 182static inline wchar_t * 183UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 184{ 185 wchar_t *anchor = ucs1; /* save the start of result string */ 186 187 while ((*ucs1++ = *ucs2++)) ; 188 return anchor; 189} 190 191/* 192 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 193 */ 194static inline size_t 195UniStrlen(const wchar_t *ucs1) 196{ 197 int i = 0; 198 199 while (*ucs1++) 200 i++; 201 return i; 202} 203 204/* 205 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 206 * string (length limited) 207 */ 208static inline size_t 209UniStrnlen(const wchar_t *ucs1, int maxlen) 210{ 211 int i = 0; 212 213 while (*ucs1++) { 214 i++; 215 if (i >= maxlen) 216 break; 217 } 218 return i; 219} 220 221/* 222 * UniStrncat: Concatenate length limited string 223 */ 224static inline wchar_t * 225UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 226{ 227 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 228 229 while (*ucs1++) ; 230 ucs1--; /* point to null terminator of s1 */ 231 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 232 ucs1++; 233 ucs2++; 234 } 235 *ucs1 = 0; /* Null terminate the result */ 236 return (anchor); 237} 238 239/* 240 * UniStrncmp: Compare length limited string 241 */ 242static inline int 243UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 244{ 245 if (!n) 246 return 0; /* Null strings are equal */ 247 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 248 ucs1++; 249 ucs2++; 250 } 251 return (int) *ucs1 - (int) *ucs2; 252} 253 254/* 255 * UniStrncmp_le: Compare length limited string - native to little-endian 256 */ 257static inline int 258UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 259{ 260 if (!n) 261 return 0; /* Null strings are equal */ 262 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 263 ucs1++; 264 ucs2++; 265 } 266 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); 267} 268 269/* 270 * UniStrncpy: Copy length limited string with pad 271 */ 272static inline wchar_t * 273UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 274{ 275 wchar_t *anchor = ucs1; 276 277 while (n-- && *ucs2) /* Copy the strings */ 278 *ucs1++ = *ucs2++; 279 280 n++; 281 while (n--) /* Pad with nulls */ 282 *ucs1++ = 0; 283 return anchor; 284} 285 286/* 287 * UniStrncpy_le: Copy length limited string with pad to little-endian 288 */ 289static inline wchar_t * 290UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 291{ 292 wchar_t *anchor = ucs1; 293 294 while (n-- && *ucs2) /* Copy the strings */ 295 *ucs1++ = __le16_to_cpu(*ucs2++); 296 297 n++; 298 while (n--) /* Pad with nulls */ 299 *ucs1++ = 0; 300 return anchor; 301} 302 303/* 304 * UniStrstr: Find a string in a string 305 * 306 * Returns: 307 * Address of first match found 308 * NULL if no matching string is found 309 */ 310static inline wchar_t * 311UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 312{ 313 const wchar_t *anchor1 = ucs1; 314 const wchar_t *anchor2 = ucs2; 315 316 while (*ucs1) { 317 if (*ucs1 == *ucs2) { 318 /* Partial match found */ 319 ucs1++; 320 ucs2++; 321 } else { 322 if (!*ucs2) /* Match found */ 323 return (wchar_t *) anchor1; 324 ucs1 = ++anchor1; /* No match */ 325 ucs2 = anchor2; 326 } 327 } 328 329 if (!*ucs2) /* Both end together */ 330 return (wchar_t *) anchor1; /* Match found */ 331 return NULL; /* No match */ 332} 333 334#ifndef UNIUPR_NOUPPER 335/* 336 * UniToupper: Convert a unicode character to upper case 337 */ 338static inline wchar_t 339UniToupper(register wchar_t uc) 340{ 341 register const struct UniCaseRange *rp; 342 343 if (uc < sizeof(CifsUniUpperTable)) { 344 /* Latin characters */ 345 return uc + CifsUniUpperTable[uc]; /* Use base tables */ 346 } else { 347 rp = CifsUniUpperRange; /* Use range tables */ 348 while (rp->start) { 349 if (uc < rp->start) /* Before start of range */ 350 return uc; /* Uppercase = input */ 351 if (uc <= rp->end) /* In range */ 352 return uc + rp->table[uc - rp->start]; 353 rp++; /* Try next range */ 354 } 355 } 356 return uc; /* Past last range */ 357} 358 359/* 360 * UniStrupr: Upper case a unicode string 361 */ 362static inline __le16 * 363UniStrupr(register __le16 *upin) 364{ 365 register __le16 *up; 366 367 up = upin; 368 while (*up) { /* For all characters */ 369 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); 370 up++; 371 } 372 return upin; /* Return input pointer */ 373} 374#endif /* UNIUPR_NOUPPER */ 375 376#ifndef UNIUPR_NOLOWER 377/* 378 * UniTolower: Convert a unicode character to lower case 379 */ 380static inline wchar_t 381UniTolower(register wchar_t uc) 382{ 383 register const struct UniCaseRange *rp; 384 385 if (uc < sizeof(CifsUniLowerTable)) { 386 /* Latin characters */ 387 return uc + CifsUniLowerTable[uc]; /* Use base tables */ 388 } else { 389 rp = CifsUniLowerRange; /* Use range tables */ 390 while (rp->start) { 391 if (uc < rp->start) /* Before start of range */ 392 return uc; /* Uppercase = input */ 393 if (uc <= rp->end) /* In range */ 394 return uc + rp->table[uc - rp->start]; 395 rp++; /* Try next range */ 396 } 397 } 398 return uc; /* Past last range */ 399} 400 401/* 402 * UniStrlwr: Lower case a unicode string 403 */ 404static inline wchar_t * 405UniStrlwr(register wchar_t *upin) 406{ 407 register wchar_t *up; 408 409 up = upin; 410 while (*up) { /* For all characters */ 411 *up = UniTolower(*up); 412 up++; 413 } 414 return upin; /* Return input pointer */ 415} 416 417#endif 418 419#endif /* _CIFS_UNICODE_H */