cifs: fix unaligned accesses in cifsConvertToUCS
authorJeff Layton <jlayton@redhat.com>
Thu, 20 Jan 2011 18:36:51 +0000 (13:36 -0500)
committerSteve French <sfrench@us.ibm.com>
Thu, 20 Jan 2011 21:48:00 +0000 (21:48 +0000)
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>
fs/cifs/cifs_unicode.c
fs/cifs/misc.c

index 5f6e71857be6598b204892265e789fd06c61ff55..fc0fd4fde306b989c1593ef11ce2611fd49dca54 100644 (file)
@@ -257,3 +257,79 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
        return dst;
 }
 
+/*
+ * Convert 16 bit Unicode pathname to wire format from string in current code
+ * page. Conversion may involve remapping up the six characters that are
+ * only legal in POSIX-like OS (if they are present in the string). Path
+ * names are little endian 16 bit Unicode on the wire
+ */
+int
+cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
+                const struct nls_table *cp, int mapChars)
+{
+       int i, j, charlen;
+       int len_remaining = maxlen;
+       char src_char;
+       __u16 temp;
+
+       if (!mapChars)
+               return cifs_strtoUCS(target, source, PATH_MAX, cp);
+
+       for (i = 0, j = 0; i < maxlen; j++) {
+               src_char = source[i];
+               switch (src_char) {
+               case 0:
+                       put_unaligned_le16(0, &target[j]);
+                       goto ctoUCS_out;
+               case ':':
+                       temp = UNI_COLON;
+                       break;
+               case '*':
+                       temp = UNI_ASTERIK;
+                       break;
+               case '?':
+                       temp = UNI_QUESTION;
+                       break;
+               case '<':
+                       temp = UNI_LESSTHAN;
+                       break;
+               case '>':
+                       temp = UNI_GRTRTHAN;
+                       break;
+               case '|':
+                       temp = UNI_PIPE;
+                       break;
+               /*
+                * FIXME: We can not handle remapping backslash (UNI_SLASH)
+                * until all the calls to build_path_from_dentry are modified,
+                * as they use backslash as separator.
+                */
+               default:
+                       charlen = cp->char2uni(source+i, len_remaining,
+                                               &temp);
+                       /*
+                        * if no match, use question mark, which at least in
+                        * some cases serves as wild card
+                        */
+                       if (charlen < 1) {
+                               temp = 0x003f;
+                               charlen = 1;
+                       }
+                       len_remaining -= charlen;
+                       /*
+                        * character may take more than one byte in the source
+                        * string, but will take exactly two bytes in the
+                        * target string
+                        */
+                       i += charlen;
+                       continue;
+               }
+               put_unaligned_le16(temp, &target[j]);
+               i++; /* move to next char in source string */
+               len_remaining--;
+       }
+
+ctoUCS_out:
+       return i;
+}
+
index 09bfcf08a90ff7a9b05bec53abc34196f052106b..a09e077ba92531e7d8614fc2ce0f8878613c36fb 100644 (file)
@@ -637,77 +637,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
        return;
 }
 
-/* Convert 16 bit Unicode pathname to wire format from string in current code
-   page.  Conversion may involve remapping up the seven characters that are
-   only legal in POSIX-like OS (if they are present in the string). Path
-   names are little endian 16 bit Unicode on the wire */
-int
-cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
-                const struct nls_table *cp, int mapChars)
-{
-       int i, j, charlen;
-       int len_remaining = maxlen;
-       char src_char;
-       __u16 temp;
-
-       if (!mapChars)
-               return cifs_strtoUCS(target, source, PATH_MAX, cp);
-
-       for (i = 0, j = 0; i < maxlen; j++) {
-               src_char = source[i];
-               switch (src_char) {
-                       case 0:
-                               target[j] = 0;
-                               goto ctoUCS_out;
-                       case ':':
-                               target[j] = cpu_to_le16(UNI_COLON);
-                               break;
-                       case '*':
-                               target[j] = cpu_to_le16(UNI_ASTERIK);
-                               break;
-                       case '?':
-                               target[j] = cpu_to_le16(UNI_QUESTION);
-                               break;
-                       case '<':
-                               target[j] = cpu_to_le16(UNI_LESSTHAN);
-                               break;
-                       case '>':
-                               target[j] = cpu_to_le16(UNI_GRTRTHAN);
-                               break;
-                       case '|':
-                               target[j] = cpu_to_le16(UNI_PIPE);
-                               break;
-                       /* BB We can not handle remapping slash until
-                          all the calls to build_path_from_dentry
-                          are modified, as they use slash as separator BB */
-                       /* case '\\':
-                               target[j] = cpu_to_le16(UNI_SLASH);
-                               break;*/
-                       default:
-                               charlen = cp->char2uni(source+i,
-                                       len_remaining, &temp);
-                               /* if no match, use question mark, which
-                               at least in some cases servers as wild card */
-                               if (charlen < 1) {
-                                       target[j] = cpu_to_le16(0x003f);
-                                       charlen = 1;
-                               } else
-                                       target[j] = cpu_to_le16(temp);
-                               len_remaining -= charlen;
-                               /* character may take more than one byte in the
-                                  the source string, but will take exactly two
-                                  bytes in the target string */
-                               i += charlen;
-                               continue;
-               }
-               i++; /* move to next char in source string */
-               len_remaining--;
-       }
-
-ctoUCS_out:
-       return i;
-}
-
 void
 cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
 {