[linux-cifs-client] [PATCH 2/7] [CIFS] add cifs_nls_convert function to convert from one nls to another

Jeff Layton jlayton at redhat.com
Fri Jul 25 15:23:15 GMT 2008


Add a cifs_nls_convert function, that does a conversion from one codepage
to another. When one or both codepages is NULL, it just does a memcpy
from one to the other.

Signed-off-by: Jeff Layton <jlayton at redhat.com>
---

 fs/cifs/cifs_unicode.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/cifs/cifs_unicode.h |    3 +++
 2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 7d75272..f827422 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -88,3 +88,60 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
 	return i;
 }
 
+/*
+ * cifs_nls_convert - convert string from one character set to another
+ * @from: original string
+ * @to: destination for converted string
+ * @from_nls: nls that the "from" string is in
+ * @to_nls: nls to which we need to convert the "to" string
+ * @len: from string length
+ * @from_le: is the original string in little endian format?
+ * 
+ * convert a string from one nls_codepage to another. If either codepage is
+ * NULL, then we assume that both ends are using the same codepage and just
+ * do a memcpy.
+ */
+int
+cifs_nls_convert(const unsigned char *from, unsigned char *to,
+		 const struct nls_table *from_nls,
+		 const struct nls_table *to_nls, unsigned int inlen)
+{
+	int charlen, outlen = 0;
+	wchar_t temp;
+
+	/* if either codepage is NULL, then just memcpy */
+	if (!from_nls || !to_nls) {
+		memcpy(to, from, inlen);
+		/* NULL terminate */
+		to[inlen] = 0;
+		return inlen;
+	}
+
+	while (inlen && *from) {
+		/* convert character to unicode */
+		charlen = from_nls->char2uni(from, inlen, &temp);
+		if (charlen < 1) {
+			cFYI(1, ("strtoUCS: char2uni of %x returned %d",
+				*from, charlen));
+			/* A question mark */
+			temp = 0x003f;
+			charlen = 1;
+		}
+
+		/* adjust input lengths */
+		from += charlen;
+		inlen -= charlen;
+
+		/* convert temp char from unicode to to_nls */
+		charlen = to_nls->uni2char(temp, &to[outlen],
+					   NLS_MAX_CHARSET_SIZE);
+		if (charlen > 0)
+			outlen += charlen;
+		else
+			to[outlen++] = '?';
+	}
+
+	/* NULL terminate */
+	to[outlen] = 0;
+	return outlen;
+}
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 14eb9a2..9577972 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -61,6 +61,9 @@ extern struct UniCaseRange UniLowerRange[];
 #ifdef __KERNEL__
 int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
 int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
+int cifs_nls_convert(const unsigned char *from, unsigned char *to,
+			const struct nls_table *from_nls,
+			const struct nls_table *to_nls, unsigned int inlen);
 #endif
 
 /*



More information about the linux-cifs-client mailing list