14Srgrimes// SPDX-License-Identifier: GPL-2.0-or-later 24Srgrimes/* 34Srgrimes * 44Srgrimes * Copyright (c) International Business Machines Corp., 2000,2009 54Srgrimes * Modified by Steve French (sfrench@us.ibm.com) 64Srgrimes */ 74Srgrimes#include <linux/fs.h> 84Srgrimes#include <linux/slab.h> 94Srgrimes#include "cifs_fs_sb.h" 104Srgrimes#include "cifs_unicode.h" 114Srgrimes#include "cifspdu.h" 124Srgrimes#include "cifsglob.h" 134Srgrimes#include "cifs_debug.h" 144Srgrimes 154Srgrimesint cifs_remap(struct cifs_sb_info *cifs_sb) 164Srgrimes{ 174Srgrimes int map_type; 184Srgrimes 194Srgrimes if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) 204Srgrimes map_type = SFM_MAP_UNI_RSVD; 214Srgrimes else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 224Srgrimes map_type = SFU_MAP_UNI_RSVD; 234Srgrimes else 244Srgrimes map_type = NO_MAP_UNI_RSVD; 254Srgrimes 264Srgrimes return map_type; 274Srgrimes} 284Srgrimes 294Srgrimes/* Convert character using the SFU - "Services for Unix" remapping range */ 304Srgrimesstatic bool 314Srgrimesconvert_sfu_char(const __u16 src_char, char *target) 324Srgrimes{ 334Srgrimes /* 344Srgrimes * BB: Cannot handle remapping UNI_SLASH until all the calls to 354Srgrimes * build_path_from_dentry are modified, as they use slash as 364Srgrimes * separator. 374Srgrimes */ 38620Srgrimes switch (src_char) { 3938485Sbde case UNI_COLON: 404Srgrimes *target = ':'; 414Srgrimes break; 4232726Seivind case UNI_ASTERISK: 4332726Seivind *target = '*'; 442056Swollman break; 4512675Sjulian case UNI_QUESTION: 4612675Sjulian *target = '?'; 4712675Sjulian break; 481549Srgrimes case UNI_PIPE: 495764Sbde *target = '|'; 5012675Sjulian break; 5118951Sjulian case UNI_GRTRTHAN: 5212701Sphk *target = '>'; 532056Swollman break; 542056Swollman case UNI_LESSTHAN: 5534924Sbde *target = '<'; 564Srgrimes break; 5712701Sphk default: 582056Swollman return false; 594Srgrimes } 608023Sbde return true; 618047Sbde} 628047Sbde 638047Sbde/* Convert character using the SFM - "Services for Mac" remapping range */ 645764Sbdestatic bool 6510666Sbdeconvert_sfm_char(const __u16 src_char, char *target) 6610666Sbde{ 6710666Sbde if (src_char >= 0xF001 && src_char <= 0xF01F) { 6810666Sbde *target = src_char - 0xF000; 693728Sphk return true; 702423Sdg } 71849Sdg switch (src_char) { 723728Sphk case SFM_COLON: 73849Sdg *target = ':'; 744Srgrimes break; 754Srgrimes case SFM_DOUBLEQUOTE: 764Srgrimes *target = '"'; 7712675Sjulian break; 7812675Sjulian case SFM_ASTERISK: 7912675Sjulian *target = '*'; 8012675Sjulian break; 8112675Sjulian case SFM_QUESTION: 8229368Speter *target = '?'; 8312675Sjulian break; 8438485Sbde case SFM_PIPE: 8538485Sbde *target = '|'; 8638485Sbde break; 8738485Sbde case SFM_GRTRTHAN: 8838485Sbde *target = '>'; 8938485Sbde break; 9038485Sbde case SFM_LESSTHAN: 9138485Sbde *target = '<'; 9212675Sjulian break; 9327982Sjulian case SFM_SPACE: 9412701Sphk *target = ' '; 9512701Sphk break; 9627982Sjulian case SFM_PERIOD: 9718951Sjulian *target = '.'; 9812701Sphk break; 997680Sjoerg default: 1007680Sjoerg return false; 1017680Sjoerg } 1027680Sjoerg return true; 1034Srgrimes} 10427982Sjulian 10527982Sjulian 10627982Sjulian/* 1075764Sbde * cifs_mapchar - convert a host-endian char to proper char in codepage 10827982Sjulian * @target - where converted character should be copied 10927982Sjulian * @src_char - 2 byte host-endian source character 11027982Sjulian * @cp - codepage to which character should be converted 11112675Sjulian * @map_type - How should the 7 NTFS/SMB reserved characters be mapped to UCS2? 11227982Sjulian * 11312675Sjulian * This function handles the conversion of a single character. It is the 1145764Sbde * responsibility of the caller to ensure that the target buffer is large 115798Swollman * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). 1164Srgrimes */ 1174Srgrimesstatic int 11810665Sbdecifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp, 1194Srgrimes int maptype) 1204Srgrimes{ 12110665Sbde int len = 1; 1224Srgrimes __u16 src_char; 12310665Sbde 1244Srgrimes src_char = *from; 1254Srgrimes 1264Srgrimes if ((maptype == SFM_MAP_UNI_RSVD) && convert_sfm_char(src_char, target)) 12710665Sbde return len; 12810665Sbde else if ((maptype == SFU_MAP_UNI_RSVD) && 1294Srgrimes convert_sfu_char(src_char, target)) 13010665Sbde return len; 1314Srgrimes 13218951Sjulian /* if character not one of seven in special remap set */ 13318951Sjulian len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); 13418951Sjulian if (len <= 0) 13518951Sjulian goto surrogate_pair; 13618951Sjulian 13718951Sjulian return len; 13818951Sjulian 13918951Sjuliansurrogate_pair: 14018951Sjulian /* convert SURROGATE_PAIR and IVS */ 14118951Sjulian if (strcmp(cp->charset, "utf8")) 14218951Sjulian goto unknown; 14318951Sjulian len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6); 14410665Sbde if (len <= 0) 1454Srgrimes goto unknown; 14610665Sbde return len; 14710665Sbde 1484Srgrimesunknown: 14910665Sbde *target = '?'; 15010665Sbde len = 1; 1514Srgrimes return len; 15210665Sbde} 15310665Sbde 15410665Sbde/* 15510665Sbde * cifs_from_utf16 - convert utf16le string to local charset 15610665Sbde * @to - destination buffer 15710665Sbde * @from - source buffer 15810665Sbde * @tolen - destination buffer size (in bytes) 15910665Sbde * @fromlen - source buffer size (in bytes) 16010665Sbde * @codepage - codepage to which characters should be converted 16110665Sbde * @mapchar - should characters be remapped according to the mapchars option? 16210665Sbde * 16310665Sbde * Convert a little-endian utf16le string (as sent by the server) to a string 16410665Sbde * in the provided codepage. The tolen and fromlen parameters are to ensure 16510665Sbde * that the code doesn't walk off of the end of the buffer (which is always 16627982Sjulian * a danger if the alignment of the source buffer is off). The destination 16710665Sbde * string is always properly null terminated and fits in the destination 16810665Sbde * buffer. Returns the length of the destination string in bytes (including 16910665Sbde * null terminator). 1705764Sbde * 1715764Sbde * Note that some windows versions actually send multiword UTF-16 characters 17212813Sjulian * instead of straight UTF16-2. The linux nls routines however aren't able to 1735764Sbde * deal with those characters properly. In the event that we get some of 1745764Sbde * those characters, they won't be translated properly. 1755764Sbde */ 1765764Sbdeint 1777588Sjoergcifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, 17812701Sphk const struct nls_table *codepage, int map_type) 1794Srgrimes{ 1804Srgrimes int i, charlen, safelen; 18127983Sjulian int outlen = 0; 18227983Sjulian int nullsize = nls_nullsize(codepage); 18327982Sjulian int fromwords = fromlen / 2; 18427982Sjulian char tmp[NLS_MAX_CHARSET_SIZE]; 18527982Sjulian __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */ 18627982Sjulian 18727982Sjulian /* 18827982Sjulian * because the chars can be of varying widths, we need to take care 18927982Sjulian * not to overflow the destination buffer when we get close to the 19027982Sjulian * end of it. Until we get to this offset, we don't need to check 19127982Sjulian * for overflow however. 19227982Sjulian */ 19327982Sjulian safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); 19427982Sjulian 19527982Sjulian for (i = 0; i < fromwords; i++) { 19627982Sjulian ftmp[0] = get_unaligned_le16(&from[i]); 19727982Sjulian if (ftmp[0] == 0) 19827982Sjulian break; 19927982Sjulian if (i + 1 < fromwords) 20027982Sjulian ftmp[1] = get_unaligned_le16(&from[i + 1]); 20127982Sjulian else 20227982Sjulian ftmp[1] = 0; 20327982Sjulian if (i + 2 < fromwords) 20427982Sjulian ftmp[2] = get_unaligned_le16(&from[i + 2]); 20512675Sjulian else 20627982Sjulian ftmp[2] = 0; 20727982Sjulian 20827982Sjulian /* 20927982Sjulian * check to see if converting this character might make the 21027982Sjulian * conversion bleed into the null terminator 21127982Sjulian */ 21227982Sjulian if (outlen >= safelen) { 21327982Sjulian charlen = cifs_mapchar(tmp, ftmp, codepage, map_type); 21427982Sjulian if ((outlen + charlen) > (tolen - nullsize)) 21527982Sjulian break; 21627982Sjulian } 21727982Sjulian 21827982Sjulian /* put converted char into 'to' buffer */ 21927982Sjulian charlen = cifs_mapchar(&to[outlen], ftmp, codepage, map_type); 22027982Sjulian outlen += charlen; 22127982Sjulian 22227982Sjulian /* charlen (=bytes of UTF-8 for 1 character) 22327982Sjulian * 4bytes UTF-8(surrogate pair) is charlen=4 22427982Sjulian * (4bytes UTF-16 code) 22527982Sjulian * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4 22627982Sjulian * (2 UTF-8 pairs divided to 2 UTF-16 pairs) */ 22727982Sjulian if (charlen == 4) 22827982Sjulian i++; 22927982Sjulian else if (charlen >= 5) 23027982Sjulian /* 5-6bytes UTF-8 */ 23127982Sjulian i += 2; 23227982Sjulian } 23327982Sjulian 23427982Sjulian /* properly null-terminate string */ 23527982Sjulian for (i = 0; i < nullsize; i++) 23627982Sjulian to[outlen++] = 0; 23727982Sjulian 23827982Sjulian return outlen; 23927982Sjulian} 24027982Sjulian 24127982Sjulian/* 24227982Sjulian * NAME: cifs_strtoUTF16() 24327982Sjulian * 24427982Sjulian * FUNCTION: Convert character string to unicode string 24527982Sjulian * 24627982Sjulian */ 24727982Sjulianint 24827982Sjuliancifs_strtoUTF16(__le16 *to, const char *from, int len, 24927982Sjulian const struct nls_table *codepage) 2504Srgrimes{ 2514Srgrimes int charlen; 2524Srgrimes int i; 2534Srgrimes wchar_t wchar_to; /* needed to quiet sparse */ 2544Srgrimes 2555764Sbde /* special case for utf8 to handle no plane0 chars */ 25627982Sjulian if (!strcmp(codepage->charset, "utf8")) { 2571007Sdg /* 2584Srgrimes * convert utf8 -> utf16, we assume we have enough space 2594Srgrimes * as caller should have assumed conversion does not overflow 2605764Sbde * in destination len is length in wchar_t units (16bits) 2615764Sbde */ 26227982Sjulian i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN, 26327982Sjulian (wchar_t *) to, len); 26427982Sjulian 26527982Sjulian /* if success terminate and exit */ 26627982Sjulian if (i >= 0) 26727982Sjulian goto success; 26827982Sjulian /* 2695764Sbde * if fails fall back to UCS encoding as this 27027982Sjulian * function should not return negative values 27127982Sjulian * currently can fail only if source contains 27227982Sjulian * invalid encoded characters 27327982Sjulian */ 2745764Sbde } 2755764Sbde 27627982Sjulian for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 27727982Sjulian charlen = codepage->char2uni(from, len, &wchar_to); 27827982Sjulian if (charlen < 1) { 2795764Sbde cifs_dbg(VFS, "strtoUTF16: char2uni of 0x%x returned %d\n", 28027982Sjulian *from, charlen); 2815764Sbde /* A question mark */ 2825764Sbde wchar_to = 0x003f; 2834Srgrimes charlen = 1; 2848876Srgrimes } 28512675Sjulian put_unaligned_le16(wchar_to, &to[i]); 2864Srgrimes } 2874Srgrimes 2884Srgrimessuccess: 2894Srgrimes put_unaligned_le16(0, &to[i]); 2904Srgrimes return i; 2915764Sbde} 2921007Sdg 2934Srgrimes/* 2944Srgrimes * cifs_utf16_bytes - how long will a string be after conversion? 2955764Sbde * @utf16 - pointer to input string 29627982Sjulian * @maxbytes - don't go past this many bytes of input string 29727982Sjulian * @codepage - destination codepage 29827982Sjulian * 29927982Sjulian * Walk a utf16le string and return the number of bytes that the string will 30027982Sjulian * be after being converted to the given charset, not including any null 30127982Sjulian * termination required. Don't walk past maxbytes in the source buffer. 3025764Sbde */ 3037588Sjoergint 3045764Sbdecifs_utf16_bytes(const __le16 *from, int maxbytes, 3057588Sjoerg const struct nls_table *codepage) 3067588Sjoerg{ 3077588Sjoerg int i; 3087588Sjoerg int charlen, outlen = 0; 3097588Sjoerg int maxwords = maxbytes / 2; 3107588Sjoerg char tmp[NLS_MAX_CHARSET_SIZE]; 3117588Sjoerg __u16 ftmp[3]; 3125764Sbde 3137588Sjoerg for (i = 0; i < maxwords; i++) { 3145764Sbde ftmp[0] = get_unaligned_le16(&from[i]); 3157588Sjoerg if (ftmp[0] == 0) 3165764Sbde break; 3175764Sbde if (i + 1 < maxwords) 3185764Sbde ftmp[1] = get_unaligned_le16(&from[i + 1]); 3195764Sbde else 3205764Sbde ftmp[1] = 0; 32127982Sjulian if (i + 2 < maxwords) 32227982Sjulian ftmp[2] = get_unaligned_le16(&from[i + 2]); 32327982Sjulian else 3244Srgrimes ftmp[2] = 0; 3258876Srgrimes 32612675Sjulian charlen = cifs_mapchar(tmp, ftmp, codepage, NO_MAP_UNI_RSVD); 3274Srgrimes outlen += charlen; 3284Srgrimes } 3294Srgrimes 330798Swollman return outlen; 3314Srgrimes} 33218951Sjulian 3334Srgrimes/* 3344Srgrimes * cifs_strndup_from_utf16 - copy a string from wire format to the local 33512813Sjulian * codepage 3364Srgrimes * @src - source string 3378876Srgrimes * @maxlen - don't walk past this many bytes in the source string 33812675Sjulian * @is_unicode - is this a unicode string? 3394Srgrimes * @codepage - destination codepage 3404Srgrimes * 3414Srgrimes * Take a string given by the server, convert it to the local codepage and 342798Swollman * put it in a new buffer. Returns a pointer to the new string or NULL on 3434Srgrimes * error. 34427982Sjulian */ 34527982Sjulianchar * 3464Srgrimescifs_strndup_from_utf16(const char *src, const int maxlen, 34727982Sjulian const bool is_unicode, const struct nls_table *codepage) 3481021Sdg{ 3494Srgrimes int len; 3504Srgrimes char *dst; 3514Srgrimes 35212813Sjulian if (is_unicode) { 3534Srgrimes len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage); 3548876Srgrimes len += nls_nullsize(codepage); 35512675Sjulian dst = kmalloc(len, GFP_KERNEL); 3564Srgrimes if (!dst) 3574Srgrimes return NULL; 35836735Sdfr cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage, 3594Srgrimes NO_MAP_UNI_RSVD); 360798Swollman } else { 3614Srgrimes dst = kstrndup(src, maxlen, GFP_KERNEL); 3624Srgrimes } 3634Srgrimes 3644Srgrimes return dst; 36518951Sjulian} 3664Srgrimes 3674Srgrimesstatic __le16 convert_to_sfu_char(char src_char) 3684Srgrimes{ 3694Srgrimes __le16 dest_char; 3704Srgrimes 3714Srgrimes switch (src_char) { 3724Srgrimes case ':': 3734Srgrimes dest_char = cpu_to_le16(UNI_COLON); 3744Srgrimes break; 3754Srgrimes case '*': 3764Srgrimes dest_char = cpu_to_le16(UNI_ASTERISK); 3774Srgrimes break; 3784Srgrimes case '?': 37912813Sjulian dest_char = cpu_to_le16(UNI_QUESTION); 3804Srgrimes break; 3814Srgrimes case '<': 38212675Sjulian dest_char = cpu_to_le16(UNI_LESSTHAN); 38329368Speter break; 3844Srgrimes case '>': 38529368Speter dest_char = cpu_to_le16(UNI_GRTRTHAN); 3864Srgrimes break; 3874Srgrimes case '|': 38818951Sjulian dest_char = cpu_to_le16(UNI_PIPE); 3894Srgrimes break; 3906712Spst default: 3916712Spst dest_char = 0; 3926712Spst } 39329368Speter 3944Srgrimes return dest_char; 3954Srgrimes} 396798Swollman 3974Srgrimesstatic __le16 convert_to_sfm_char(char src_char, bool end_of_string) 3984Srgrimes{ 3995160Sjoerg __le16 dest_char; 40018951Sjulian 40119268Sjulian if (src_char >= 0x01 && src_char <= 0x1F) { 4025160Sjoerg dest_char = cpu_to_le16(src_char + 0xF000); 4035160Sjoerg return dest_char; 4045160Sjoerg } 4054Srgrimes switch (src_char) { 4064Srgrimes case ':': 4073728Sphk dest_char = cpu_to_le16(SFM_COLON); 4083728Sphk break; 4093728Sphk case '"': 41018951Sjulian dest_char = cpu_to_le16(SFM_DOUBLEQUOTE); 41118287Sbde break; 4123728Sphk case '*': 4133728Sphk dest_char = cpu_to_le16(SFM_ASTERISK); 4143728Sphk break; 415798Swollman case '?': 4164Srgrimes dest_char = cpu_to_le16(SFM_QUESTION); 4174Srgrimes break; 4184Srgrimes case '<': 41918951Sjulian dest_char = cpu_to_le16(SFM_LESSTHAN); 4204Srgrimes break; 4214Srgrimes case '>': 4224Srgrimes dest_char = cpu_to_le16(SFM_GRTRTHAN); 4234Srgrimes break; 4249217Sbde case '|': 4254Srgrimes dest_char = cpu_to_le16(SFM_PIPE); 4264Srgrimes break; 4274Srgrimes case '.': 42812517Sjulian if (end_of_string) 42912517Sjulian dest_char = cpu_to_le16(SFM_PERIOD); 43012675Sjulian else 43112675Sjulian dest_char = 0; 43212517Sjulian break; 43312517Sjulian case ' ': 43412517Sjulian if (end_of_string) 43512517Sjulian dest_char = cpu_to_le16(SFM_SPACE); 43612517Sjulian else 43712517Sjulian dest_char = 0; 43812517Sjulian break; 43912517Sjulian default: 44014880Sbde dest_char = 0; 44114880Sbde } 44214880Sbde 44312517Sjulian return dest_char; 44412521Sjulian} 44512517Sjulian 44612517Sjulian/* 44712517Sjulian * Convert 16 bit Unicode pathname to wire format from string in current code 44812517Sjulian * page. Conversion may involve remapping up the six characters that are 44912517Sjulian * only legal in POSIX-like OS (if they are present in the string). Path 450 * names are little endian 16 bit Unicode on the wire 451 */ 452int 453cifsConvertToUTF16(__le16 *target, const char *source, int srclen, 454 const struct nls_table *cp, int map_chars) 455{ 456 int i, charlen; 457 int j = 0; 458 char src_char; 459 __le16 dst_char; 460 wchar_t tmp; 461 wchar_t *wchar_to; /* UTF-16 */ 462 int ret; 463 unicode_t u; 464 465 if (map_chars == NO_MAP_UNI_RSVD) 466 return cifs_strtoUTF16(target, source, PATH_MAX, cp); 467 468 wchar_to = kzalloc(6, GFP_KERNEL); 469 470 for (i = 0; i < srclen; j++) { 471 src_char = source[i]; 472 charlen = 1; 473 474 /* check if end of string */ 475 if (src_char == 0) 476 goto ctoUTF16_out; 477 478 /* see if we must remap this char */ 479 if (map_chars == SFU_MAP_UNI_RSVD) 480 dst_char = convert_to_sfu_char(src_char); 481 else if (map_chars == SFM_MAP_UNI_RSVD) { 482 bool end_of_string; 483 484 /** 485 * Remap spaces and periods found at the end of every 486 * component of the path. The special cases of '.' and 487 * '..' do not need to be dealt with explicitly because 488 * they are addressed in namei.c:link_path_walk(). 489 **/ 490 if ((i == srclen - 1) || (source[i+1] == '\\')) 491 end_of_string = true; 492 else 493 end_of_string = false; 494 495 dst_char = convert_to_sfm_char(src_char, end_of_string); 496 } else 497 dst_char = 0; 498 /* 499 * FIXME: We can not handle remapping backslash (UNI_SLASH) 500 * until all the calls to build_path_from_dentry are modified, 501 * as they use backslash as separator. 502 */ 503 if (dst_char == 0) { 504 charlen = cp->char2uni(source + i, srclen - i, &tmp); 505 dst_char = cpu_to_le16(tmp); 506 507 /* 508 * if no match, use question mark, which at least in 509 * some cases serves as wild card 510 */ 511 if (charlen > 0) 512 goto ctoUTF16; 513 514 /* convert SURROGATE_PAIR */ 515 if (strcmp(cp->charset, "utf8") || !wchar_to) 516 goto unknown; 517 if (*(source + i) & 0x80) { 518 charlen = utf8_to_utf32(source + i, 6, &u); 519 if (charlen < 0) 520 goto unknown; 521 } else 522 goto unknown; 523 ret = utf8s_to_utf16s(source + i, charlen, 524 UTF16_LITTLE_ENDIAN, 525 wchar_to, 6); 526 if (ret < 0) 527 goto unknown; 528 529 i += charlen; 530 dst_char = cpu_to_le16(*wchar_to); 531 if (charlen <= 3) 532 /* 1-3bytes UTF-8 to 2bytes UTF-16 */ 533 put_unaligned(dst_char, &target[j]); 534 else if (charlen == 4) { 535 /* 4bytes UTF-8(surrogate pair) to 4bytes UTF-16 536 * 7-8bytes UTF-8(IVS) divided to 2 UTF-16 537 * (charlen=3+4 or 4+4) */ 538 put_unaligned(dst_char, &target[j]); 539 dst_char = cpu_to_le16(*(wchar_to + 1)); 540 j++; 541 put_unaligned(dst_char, &target[j]); 542 } else if (charlen >= 5) { 543 /* 5-6bytes UTF-8 to 6bytes UTF-16 */ 544 put_unaligned(dst_char, &target[j]); 545 dst_char = cpu_to_le16(*(wchar_to + 1)); 546 j++; 547 put_unaligned(dst_char, &target[j]); 548 dst_char = cpu_to_le16(*(wchar_to + 2)); 549 j++; 550 put_unaligned(dst_char, &target[j]); 551 } 552 continue; 553 554unknown: 555 dst_char = cpu_to_le16(0x003f); 556 charlen = 1; 557 } 558 559ctoUTF16: 560 /* 561 * character may take more than one byte in the source string, 562 * but will take exactly two bytes in the target string 563 */ 564 i += charlen; 565 put_unaligned(dst_char, &target[j]); 566 } 567 568ctoUTF16_out: 569 put_unaligned(0, &target[j]); /* Null terminate target unicode string */ 570 kfree(wchar_to); 571 return j; 572} 573 574/* 575 * cifs_local_to_utf16_bytes - how long will a string be after conversion? 576 * @from - pointer to input string 577 * @maxbytes - don't go past this many bytes of input string 578 * @codepage - source codepage 579 * 580 * Walk a string and return the number of bytes that the string will 581 * be after being converted to the given charset, not including any null 582 * termination required. Don't walk past maxbytes in the source buffer. 583 */ 584 585static int 586cifs_local_to_utf16_bytes(const char *from, int len, 587 const struct nls_table *codepage) 588{ 589 int charlen; 590 int i; 591 wchar_t wchar_to; 592 593 for (i = 0; len && *from; i++, from += charlen, len -= charlen) { 594 charlen = codepage->char2uni(from, len, &wchar_to); 595 /* Failed conversion defaults to a question mark */ 596 if (charlen < 1) 597 charlen = 1; 598 } 599 return 2 * i; /* UTF16 characters are two bytes */ 600} 601 602/* 603 * cifs_strndup_to_utf16 - copy a string to wire format from the local codepage 604 * @src - source string 605 * @maxlen - don't walk past this many bytes in the source string 606 * @utf16_len - the length of the allocated string in bytes (including null) 607 * @cp - source codepage 608 * @remap - map special chars 609 * 610 * Take a string convert it from the local codepage to UTF16 and 611 * put it in a new buffer. Returns a pointer to the new string or NULL on 612 * error. 613 */ 614__le16 * 615cifs_strndup_to_utf16(const char *src, const int maxlen, int *utf16_len, 616 const struct nls_table *cp, int remap) 617{ 618 int len; 619 __le16 *dst; 620 621 len = cifs_local_to_utf16_bytes(src, maxlen, cp); 622 len += 2; /* NULL */ 623 dst = kmalloc(len, GFP_KERNEL); 624 if (!dst) { 625 *utf16_len = 0; 626 return NULL; 627 } 628 cifsConvertToUTF16(dst, src, strlen(src), cp, remap); 629 *utf16_len = len; 630 return dst; 631} 632