[linux-cifs-client,1/5] cifs: Introduce helpers for unicode buffer handing
diff mbox

Message ID 49E89BA8.4020107@suse.de
State New, archived
Headers show

Commit Message

Suresh Jayaraman April 17, 2009, 3:09 p.m. UTC
Introduce helpers to compute length of NLS string in bytes and to
convert ucs string to nls format.

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

Comments

Jeff Layton April 17, 2009, 7:16 p.m. UTC | #1
On Fri, 17 Apr 2009 20:39:28 +0530
Suresh Jayaraman <sjayaraman@suse.de> wrote:

> Introduce helpers to compute length of NLS string in bytes and to
> convert ucs string to nls format.
> 
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
> ---
>  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)
> +{

^^^^
I don't think we really need a new function for this. Why not just fix
cifs_strncpy_to_host do the right thing?

> +	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:
> _______________________________________________
> linux-cifs-client mailing list
> linux-cifs-client@lists.samba.org
> https://lists.samba.org/mailman/listinfo/linux-cifs-client
>

Patch
diff mbox

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: