ALPHA: advice for a patch to CIFS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,
  I'm currently trying to support utf-16 with characters not in plane 0.

I'm currently end up with this patch. Currently is not against latest
kernel but the problem still reside in last git kernel.

wchar_t is currently 16bit so converting a utf8 encoded characters not
in plane 0 (>= 0x10000) to wchar_t (that is calling char2uni) lead to a
-EINVAL return. This patch detect utf8 in cifs_strtoUCS and add special
code calling directly utf8_to_utf32.

Does it sound a good patch or just a bad hack. Perhaps would be better
to change char2uni converting to unicode_t (32bit) instead of wchar_t
but probably many code have to be checked in order to make sure it does
not lead to wrong conversions, overflows or other bad stuff.

Is it worth working in this hacking way? I'd like to upstream this
patch.


diff -r c2325d754e8d fs/cifs/cifs_unicode.c
--- a/fs/cifs/cifs_unicode.c	Fri Jul 27 15:12:23 2012 +0100
+++ b/fs/cifs/cifs_unicode.c	Fri Jul 27 19:09:04 2012 +0100
@@ -192,22 +192,40 @@ cifs_strtoUCS(__le16 *to, const char *fr
 {
 	int charlen;
 	int i;
-	wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */
+	int is_utf8 = !strcmp(codepage->charset, "utf8");
+	wchar_t wchar_to; /* needed to quiet sparse */
+	unicode_t uni;
 
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 
 		/* works for 2.4.0 kernel or later */
-		charlen = codepage->char2uni(from, len, &wchar_to[i]);
+		if (is_utf8) {
+			charlen = utf8_to_utf32(from, len, &uni);
+		} else {
+			charlen = codepage->char2uni(from, len, &wchar_to);
+			uni = wchar_to;
+		}
+
 		if (charlen < 1) {
 			cERROR(1,
 			       ("strtoUCS: char2uni of %d returned %d",
 				(int)*from, charlen));
 			/* A question mark */
-			to[i] = cpu_to_le16(0x003f);
+			wchar_to = 0x003f;
 			charlen = 1;
-		} else
-			to[i] = cpu_to_le16(wchar_to[i]);
-
+		} else if (uni < 0x10000) {
+			wchar_to = uni;
+		} else if (uni < 0x110000) {
+			uni -= 0x10000;
+			to[i++] = cpu_to_le16(0xD800 | (uni >> 10));
+			wchar_to = 0xDC00 | (uni & 0x3FF);
+		} else {
+			cERROR(1,
+			       ("strtoUCS: char2uni of %d returned %d",
+				(int)*from, charlen));
+			wchar_to = 0x003f;
+		}
+		to[i] = cpu_to_le16(wchar_to);
 	}
 
 	to[i] = 0;

Signed-off-by: "Frediano Ziglio" <frediano.ziglio@xxxxxxxxxx>

Regards,
  Frediano

��.n��������+%������w��{.n�����{�����ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux