cifs: fix unaligned accesses in cifsConvertToUCS

Move cifsConvertToUCS to cifs_unicode.c where all of the other unicode
related functions live. Have it store mapped characters in 'temp' and
then use put_unaligned_le16 to copy it to the target buffer. Also fix
the comments to match kernel coding style.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Acked-by: Pavel Shilovsky <piastryyy@gmail.com>
Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

authored by Jeff Layton and committed by Steve French 84cdf74e ba2dbf30

+76 -71
+76
fs/cifs/cifs_unicode.c
··· 257 257 return dst; 258 258 } 259 259 260 + /* 261 + * Convert 16 bit Unicode pathname to wire format from string in current code 262 + * page. Conversion may involve remapping up the six characters that are 263 + * only legal in POSIX-like OS (if they are present in the string). Path 264 + * names are little endian 16 bit Unicode on the wire 265 + */ 266 + int 267 + cifsConvertToUCS(__le16 *target, const char *source, int maxlen, 268 + const struct nls_table *cp, int mapChars) 269 + { 270 + int i, j, charlen; 271 + int len_remaining = maxlen; 272 + char src_char; 273 + __u16 temp; 274 + 275 + if (!mapChars) 276 + return cifs_strtoUCS(target, source, PATH_MAX, cp); 277 + 278 + for (i = 0, j = 0; i < maxlen; j++) { 279 + src_char = source[i]; 280 + switch (src_char) { 281 + case 0: 282 + put_unaligned_le16(0, &target[j]); 283 + goto ctoUCS_out; 284 + case ':': 285 + temp = UNI_COLON; 286 + break; 287 + case '*': 288 + temp = UNI_ASTERIK; 289 + break; 290 + case '?': 291 + temp = UNI_QUESTION; 292 + break; 293 + case '<': 294 + temp = UNI_LESSTHAN; 295 + break; 296 + case '>': 297 + temp = UNI_GRTRTHAN; 298 + break; 299 + case '|': 300 + temp = UNI_PIPE; 301 + break; 302 + /* 303 + * FIXME: We can not handle remapping backslash (UNI_SLASH) 304 + * until all the calls to build_path_from_dentry are modified, 305 + * as they use backslash as separator. 306 + */ 307 + default: 308 + charlen = cp->char2uni(source+i, len_remaining, 309 + &temp); 310 + /* 311 + * if no match, use question mark, which at least in 312 + * some cases serves as wild card 313 + */ 314 + if (charlen < 1) { 315 + temp = 0x003f; 316 + charlen = 1; 317 + } 318 + len_remaining -= charlen; 319 + /* 320 + * character may take more than one byte in the source 321 + * string, but will take exactly two bytes in the 322 + * target string 323 + */ 324 + i += charlen; 325 + continue; 326 + } 327 + put_unaligned_le16(temp, &target[j]); 328 + i++; /* move to next char in source string */ 329 + len_remaining--; 330 + } 331 + 332 + ctoUCS_out: 333 + return i; 334 + } 335 +
-71
fs/cifs/misc.c
··· 637 637 return; 638 638 } 639 639 640 - /* Convert 16 bit Unicode pathname to wire format from string in current code 641 - page. Conversion may involve remapping up the seven characters that are 642 - only legal in POSIX-like OS (if they are present in the string). Path 643 - names are little endian 16 bit Unicode on the wire */ 644 - int 645 - cifsConvertToUCS(__le16 *target, const char *source, int maxlen, 646 - const struct nls_table *cp, int mapChars) 647 - { 648 - int i, j, charlen; 649 - int len_remaining = maxlen; 650 - char src_char; 651 - __u16 temp; 652 - 653 - if (!mapChars) 654 - return cifs_strtoUCS(target, source, PATH_MAX, cp); 655 - 656 - for (i = 0, j = 0; i < maxlen; j++) { 657 - src_char = source[i]; 658 - switch (src_char) { 659 - case 0: 660 - target[j] = 0; 661 - goto ctoUCS_out; 662 - case ':': 663 - target[j] = cpu_to_le16(UNI_COLON); 664 - break; 665 - case '*': 666 - target[j] = cpu_to_le16(UNI_ASTERIK); 667 - break; 668 - case '?': 669 - target[j] = cpu_to_le16(UNI_QUESTION); 670 - break; 671 - case '<': 672 - target[j] = cpu_to_le16(UNI_LESSTHAN); 673 - break; 674 - case '>': 675 - target[j] = cpu_to_le16(UNI_GRTRTHAN); 676 - break; 677 - case '|': 678 - target[j] = cpu_to_le16(UNI_PIPE); 679 - break; 680 - /* BB We can not handle remapping slash until 681 - all the calls to build_path_from_dentry 682 - are modified, as they use slash as separator BB */ 683 - /* case '\\': 684 - target[j] = cpu_to_le16(UNI_SLASH); 685 - break;*/ 686 - default: 687 - charlen = cp->char2uni(source+i, 688 - len_remaining, &temp); 689 - /* if no match, use question mark, which 690 - at least in some cases servers as wild card */ 691 - if (charlen < 1) { 692 - target[j] = cpu_to_le16(0x003f); 693 - charlen = 1; 694 - } else 695 - target[j] = cpu_to_le16(temp); 696 - len_remaining -= charlen; 697 - /* character may take more than one byte in the 698 - the source string, but will take exactly two 699 - bytes in the target string */ 700 - i += charlen; 701 - continue; 702 - } 703 - i++; /* move to next char in source string */ 704 - len_remaining--; 705 - } 706 - 707 - ctoUCS_out: 708 - return i; 709 - } 710 - 711 640 void 712 641 cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) 713 642 {