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 v4.8 420 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_ASTERISK ((__u16) 0xF021) 61#define SFM_QUESTION ((__u16) 0xF025) 62#define SFM_COLON ((__u16) 0xF022) 63#define SFM_GRTRTHAN ((__u16) 0xF024) 64#define SFM_LESSTHAN ((__u16) 0xF023) 65#define SFM_PIPE ((__u16) 0xF027) 66#define SFM_SLASH ((__u16) 0xF026) 67#define SFM_PERIOD ((__u16) 0xF028) 68#define SFM_SPACE ((__u16) 0xF029) 69 70/* 71 * Mapping mechanism to use when one of the seven reserved characters is 72 * encountered. We can only map using one of the mechanisms at a time 73 * since otherwise readdir could return directory entries which we would 74 * not be able to open 75 * 76 * NO_MAP_UNI_RSVD = do not perform any remapping of the character 77 * SFM_MAP_UNI_RSVD = map reserved characters using SFM scheme (MAC compatible) 78 * SFU_MAP_UNI_RSVD = map reserved characters ala SFU ("mapchars" option) 79 * 80 */ 81#define NO_MAP_UNI_RSVD 0 82#define SFM_MAP_UNI_RSVD 1 83#define SFU_MAP_UNI_RSVD 2 84 85/* Just define what we want from uniupr.h. We don't want to define the tables 86 * in each source file. 87 */ 88#ifndef UNICASERANGE_DEFINED 89struct UniCaseRange { 90 wchar_t start; 91 wchar_t end; 92 signed char *table; 93}; 94#endif /* UNICASERANGE_DEFINED */ 95 96#ifndef UNIUPR_NOUPPER 97extern signed char CifsUniUpperTable[512]; 98extern const struct UniCaseRange CifsUniUpperRange[]; 99#endif /* UNIUPR_NOUPPER */ 100 101#ifndef UNIUPR_NOLOWER 102extern signed char CifsUniLowerTable[512]; 103extern const struct UniCaseRange CifsUniLowerRange[]; 104#endif /* UNIUPR_NOLOWER */ 105 106#ifdef __KERNEL__ 107int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, 108 const struct nls_table *cp, int map_type); 109int cifs_utf16_bytes(const __le16 *from, int maxbytes, 110 const struct nls_table *codepage); 111int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); 112char *cifs_strndup_from_utf16(const char *src, const int maxlen, 113 const bool is_unicode, 114 const struct nls_table *codepage); 115extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, 116 const struct nls_table *cp, int mapChars); 117extern int cifs_remap(struct cifs_sb_info *cifs_sb); 118#ifdef CONFIG_CIFS_SMB2 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 /* CONFIG_CIFS_SMB2 */ 123#endif 124 125wchar_t cifs_toupper(wchar_t in); 126 127/* 128 * UniStrcat: Concatenate the second string to the first 129 * 130 * Returns: 131 * Address of the first string 132 */ 133static inline wchar_t * 134UniStrcat(wchar_t *ucs1, const wchar_t *ucs2) 135{ 136 wchar_t *anchor = ucs1; /* save a pointer to start of ucs1 */ 137 138 while (*ucs1++) ; /* To end of first string */ 139 ucs1--; /* Return to the null */ 140 while ((*ucs1++ = *ucs2++)) ; /* copy string 2 over */ 141 return anchor; 142} 143 144/* 145 * UniStrchr: Find a character in a string 146 * 147 * Returns: 148 * Address of first occurrence of character in string 149 * or NULL if the character is not in the string 150 */ 151static inline wchar_t * 152UniStrchr(const wchar_t *ucs, wchar_t uc) 153{ 154 while ((*ucs != uc) && *ucs) 155 ucs++; 156 157 if (*ucs == uc) 158 return (wchar_t *) ucs; 159 return NULL; 160} 161 162/* 163 * UniStrcmp: Compare two strings 164 * 165 * Returns: 166 * < 0: First string is less than second 167 * = 0: Strings are equal 168 * > 0: First string is greater than second 169 */ 170static inline int 171UniStrcmp(const wchar_t *ucs1, const wchar_t *ucs2) 172{ 173 while ((*ucs1 == *ucs2) && *ucs1) { 174 ucs1++; 175 ucs2++; 176 } 177 return (int) *ucs1 - (int) *ucs2; 178} 179 180/* 181 * UniStrcpy: Copy a string 182 */ 183static inline wchar_t * 184UniStrcpy(wchar_t *ucs1, const wchar_t *ucs2) 185{ 186 wchar_t *anchor = ucs1; /* save the start of result string */ 187 188 while ((*ucs1++ = *ucs2++)) ; 189 return anchor; 190} 191 192/* 193 * UniStrlen: Return the length of a string (in 16 bit Unicode chars not bytes) 194 */ 195static inline size_t 196UniStrlen(const wchar_t *ucs1) 197{ 198 int i = 0; 199 200 while (*ucs1++) 201 i++; 202 return i; 203} 204 205/* 206 * UniStrnlen: Return the length (in 16 bit Unicode chars not bytes) of a 207 * string (length limited) 208 */ 209static inline size_t 210UniStrnlen(const wchar_t *ucs1, int maxlen) 211{ 212 int i = 0; 213 214 while (*ucs1++) { 215 i++; 216 if (i >= maxlen) 217 break; 218 } 219 return i; 220} 221 222/* 223 * UniStrncat: Concatenate length limited string 224 */ 225static inline wchar_t * 226UniStrncat(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 227{ 228 wchar_t *anchor = ucs1; /* save pointer to string 1 */ 229 230 while (*ucs1++) ; 231 ucs1--; /* point to null terminator of s1 */ 232 while (n-- && (*ucs1 = *ucs2)) { /* copy s2 after s1 */ 233 ucs1++; 234 ucs2++; 235 } 236 *ucs1 = 0; /* Null terminate the result */ 237 return (anchor); 238} 239 240/* 241 * UniStrncmp: Compare length limited string 242 */ 243static inline int 244UniStrncmp(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 245{ 246 if (!n) 247 return 0; /* Null strings are equal */ 248 while ((*ucs1 == *ucs2) && *ucs1 && --n) { 249 ucs1++; 250 ucs2++; 251 } 252 return (int) *ucs1 - (int) *ucs2; 253} 254 255/* 256 * UniStrncmp_le: Compare length limited string - native to little-endian 257 */ 258static inline int 259UniStrncmp_le(const wchar_t *ucs1, const wchar_t *ucs2, size_t n) 260{ 261 if (!n) 262 return 0; /* Null strings are equal */ 263 while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) { 264 ucs1++; 265 ucs2++; 266 } 267 return (int) *ucs1 - (int) __le16_to_cpu(*ucs2); 268} 269 270/* 271 * UniStrncpy: Copy length limited string with pad 272 */ 273static inline wchar_t * 274UniStrncpy(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 275{ 276 wchar_t *anchor = ucs1; 277 278 while (n-- && *ucs2) /* Copy the strings */ 279 *ucs1++ = *ucs2++; 280 281 n++; 282 while (n--) /* Pad with nulls */ 283 *ucs1++ = 0; 284 return anchor; 285} 286 287/* 288 * UniStrncpy_le: Copy length limited string with pad to little-endian 289 */ 290static inline wchar_t * 291UniStrncpy_le(wchar_t *ucs1, const wchar_t *ucs2, size_t n) 292{ 293 wchar_t *anchor = ucs1; 294 295 while (n-- && *ucs2) /* Copy the strings */ 296 *ucs1++ = __le16_to_cpu(*ucs2++); 297 298 n++; 299 while (n--) /* Pad with nulls */ 300 *ucs1++ = 0; 301 return anchor; 302} 303 304/* 305 * UniStrstr: Find a string in a string 306 * 307 * Returns: 308 * Address of first match found 309 * NULL if no matching string is found 310 */ 311static inline wchar_t * 312UniStrstr(const wchar_t *ucs1, const wchar_t *ucs2) 313{ 314 const wchar_t *anchor1 = ucs1; 315 const wchar_t *anchor2 = ucs2; 316 317 while (*ucs1) { 318 if (*ucs1 == *ucs2) { 319 /* Partial match found */ 320 ucs1++; 321 ucs2++; 322 } else { 323 if (!*ucs2) /* Match found */ 324 return (wchar_t *) anchor1; 325 ucs1 = ++anchor1; /* No match */ 326 ucs2 = anchor2; 327 } 328 } 329 330 if (!*ucs2) /* Both end together */ 331 return (wchar_t *) anchor1; /* Match found */ 332 return NULL; /* No match */ 333} 334 335#ifndef UNIUPR_NOUPPER 336/* 337 * UniToupper: Convert a unicode character to upper case 338 */ 339static inline wchar_t 340UniToupper(register wchar_t uc) 341{ 342 register const struct UniCaseRange *rp; 343 344 if (uc < sizeof(CifsUniUpperTable)) { 345 /* Latin characters */ 346 return uc + CifsUniUpperTable[uc]; /* Use base tables */ 347 } else { 348 rp = CifsUniUpperRange; /* Use range tables */ 349 while (rp->start) { 350 if (uc < rp->start) /* Before start of range */ 351 return uc; /* Uppercase = input */ 352 if (uc <= rp->end) /* In range */ 353 return uc + rp->table[uc - rp->start]; 354 rp++; /* Try next range */ 355 } 356 } 357 return uc; /* Past last range */ 358} 359 360/* 361 * UniStrupr: Upper case a unicode string 362 */ 363static inline __le16 * 364UniStrupr(register __le16 *upin) 365{ 366 register __le16 *up; 367 368 up = upin; 369 while (*up) { /* For all characters */ 370 *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); 371 up++; 372 } 373 return upin; /* Return input pointer */ 374} 375#endif /* UNIUPR_NOUPPER */ 376 377#ifndef UNIUPR_NOLOWER 378/* 379 * UniTolower: Convert a unicode character to lower case 380 */ 381static inline wchar_t 382UniTolower(register wchar_t uc) 383{ 384 register const struct UniCaseRange *rp; 385 386 if (uc < sizeof(CifsUniLowerTable)) { 387 /* Latin characters */ 388 return uc + CifsUniLowerTable[uc]; /* Use base tables */ 389 } else { 390 rp = CifsUniLowerRange; /* Use range tables */ 391 while (rp->start) { 392 if (uc < rp->start) /* Before start of range */ 393 return uc; /* Uppercase = input */ 394 if (uc <= rp->end) /* In range */ 395 return uc + rp->table[uc - rp->start]; 396 rp++; /* Try next range */ 397 } 398 } 399 return uc; /* Past last range */ 400} 401 402/* 403 * UniStrlwr: Lower case a unicode string 404 */ 405static inline wchar_t * 406UniStrlwr(register wchar_t *upin) 407{ 408 register wchar_t *up; 409 410 up = upin; 411 while (*up) { /* For all characters */ 412 *up = UniTolower(*up); 413 up++; 414 } 415 return upin; /* Return input pointer */ 416} 417 418#endif 419 420#endif /* _CIFS_UNICODE_H */