[PATCH 1/5] cifs: Introduce helpers for unicode buffer handing

Suresh Jayaraman <[email protected]>
Newsgroups gmane.linux.file-systems.cifs
Message-ID <[email protected]>
Introduce helpers to compute length of NLS string in bytes and to
convert ucs string to nls format.

Signed-off-by: Suresh Jayaraman <[email protected]>
---
 fs/cifs/cifs_unicode.h |   27 +++++++++++++++++++++++++++
 fs/cifs/cifsproto.h    |    2 ++
 fs/cifs/cifssmb.c      |   31 +++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 0 deletions(-)

Index: cifs-2.6.git/fs/cifs/cifs_unicode.h
===================================================================
--- cifs-2.6.git.orig/fs/cifs/cifs_unicode.h
+++ cifs-2.6.git/fs/cifs/cifs_unicode.h
@@ -159,6 +159,33 @@ UniStrnlen(const wchar_t *ucs1, int maxl
 }
 
 /*
+ * UniStrnlenBytes: Return the length of a NLS string in bytes. Also, populates
+ * 'nchars' with the length of string in 16 bit Unicode chars.
+ */
+static inline size_t
+UniStrnlenBytes(const wchar_t *str, int maxlen, int *nchars,
+		const struct nls_table *codepage)
+{
+	int nc;
+	size_t nbytes = 0;
+	char buf[NLS_MAX_CHARSET_SIZE]; /* enough for one char at a time */
+
+	*nchars = 0;
+	while (*str++ && maxlen) {
+		nc = codepage->uni2char(*str, buf, NLS_MAX_CHARSET_SIZE);
+		if (nc > 0)
+			nbytes += nc;
+		else
+			nbytes += 1; /* for '?' */
+		(*nchars)++;
+		if (*nchars >= maxlen)
+			break;
+	}
+
+	return nbytes;
+}
+
+/*
  * UniStrncat:  Concatenate length limited string
  */
 static inline wchar_t *
Index: cifs-2.6.git/fs/cifs/cifsproto.h
===================================================================
--- cifs-2.6.git.orig/fs/cifs/cifsproto.h
+++ cifs-2.6.git/fs/cifs/cifsproto.h
@@ -383,4 +383,6 @@ extern int CIFSSMBSetPosixACL(const int
 		const struct nls_table *nls_codepage, int remap_special_chars);
 extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
 			const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
+extern int cifs_ucs_to_nls(char **dst, const char *src, const int maxlen,
+			   int *plen, const struct nls_table *nls_codepage);
 #endif			/* _CIFSPROTO_H */
Index: cifs-2.6.git/fs/cifs/cifssmb.c
===================================================================
--- cifs-2.6.git.orig/fs/cifs/cifssmb.c
+++ cifs-2.6.git/fs/cifs/cifssmb.c
@@ -81,6 +81,37 @@ static struct {
 #endif /* CONFIG_CIFS_WEAK_PW_HASH */
 #endif /* CIFS_POSIX */
 
+
+/*
+ * Calculates, allocates memory and converts to a NLS string.
+ * Note: caller is responsible for freeing dst if function returned 0.
+ * returns:
+ * 	on success - 0
+ * 	on failure - errno
+ */
+int
+cifs_ucs_to_nls(char **dst, const char *src, const int maxlen, int *plen,
+		       const struct nls_table *nls_codepage)
+{
+	size_t nbytes;
+
+	nbytes = UniStrnlenBytes((wchar_t *)src, maxlen, plen, nls_codepage);
+	cFYI(1, ("UniStrnlenBytes returned %ld bytes", nbytes));
+	*dst = kzalloc(nbytes + 2, GFP_KERNEL);
+	if (!*dst)
+		goto err_exit;
+
+	cifs_strfromUCS_le(*dst, (__le16 *)src, *plen, nls_codepage);
+
+	/* kzalloc() ensures NULL termination */
+
+	return 0;
+
+err_exit:
+	cERROR(1, ("Failed to allocate buffer for string\n"));
+	return -ENOMEM;
+}
+
 /* Allocates buffer into dst and copies smb string from src to it.
  * caller is responsible for freeing dst if function returned 0.
  * returns:
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.