summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifs_unicode.c38
-rw-r--r--fs/cifs/cifs_unicode.h2
-rw-r--r--fs/cifs/cifssmb.c55
3 files changed, 52 insertions, 43 deletions
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 614512573c67..2a879cff3a40 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -243,3 +243,41 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
return i;
}
+/*
+ * cifs_strndup - copy a string from wire format to the local codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @is_unicode - is this a unicode string?
+ * @codepage - destination codepage
+ *
+ * Take a string given by the server, convert it to the local codepage and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+char *
+cifs_strndup(const char *src, const int maxlen, const bool is_unicode,
+ const struct nls_table *codepage)
+{
+ int len;
+ char *dst;
+
+ if (is_unicode) {
+ len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+ len += nls_nullsize(codepage);
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+ false);
+ } else {
+ len = strnlen(src, maxlen);
+ len++;
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ strlcpy(dst, src, len);
+ }
+
+ return dst;
+}
+
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 1857f5ff9337..e620f0b42201 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -78,6 +78,8 @@ int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
const struct nls_table *codepage);
int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup(const char *src, const int maxlen, const bool is_unicode,
+ const struct nls_table *codepage);
#endif
/*
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index cadacae46b82..f15848374cfa 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -81,41 +81,6 @@ static struct {
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
#endif /* CIFS_POSIX */
-/* Allocates buffer into dst and copies smb string from src to it.
- * caller is responsible for freeing dst if function returned 0.
- * returns:
- * on success - 0
- * on failure - errno
- */
-static int
-cifs_strlcpy_to_host(char **dst, const char *src, const int maxlen,
- const bool is_unicode, const struct nls_table *nls_codepage)
-{
- int plen;
-
- if (is_unicode) {
- plen = UniStrnlen((wchar_t *)src, maxlen);
- *dst = kmalloc((4 * plen) + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strlcpy_to_host_ErrExit;
- cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
- (*dst)[plen] = 0;
- (*dst)[plen+1] = 0; /* needed for Unicode */
- } else {
- plen = strnlen(src, maxlen);
- *dst = kmalloc(plen + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strlcpy_to_host_ErrExit;
- strlcpy(*dst, src, plen);
- }
- return 0;
-
-cifs_strlcpy_to_host_ErrExit:
- cERROR(1, ("Failed to allocate buffer for string\n"));
- return -ENOMEM;
-}
-
-
/* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */
static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
@@ -4008,20 +3973,24 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
/* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp;
- rc = cifs_strlcpy_to_host(&(node->path_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->path_name = cifs_strndup(temp, max_len, is_unicode,
+ nls_codepage);
+ if (IS_ERR(node->path_name)) {
+ rc = PTR_ERR(node->path_name);
+ node->path_name = NULL;
goto parse_DFS_referrals_exit;
+ }
/* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp;
- rc = cifs_strlcpy_to_host(&(node->node_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->node_name = cifs_strndup(temp, max_len, is_unicode,
+ nls_codepage);
+ if (IS_ERR(node->node_name)) {
+ rc = PTR_ERR(node->node_name);
+ node->node_name = NULL;
goto parse_DFS_referrals_exit;
-
- ref += le16_to_cpu(ref->Size);
+ }
}
parse_DFS_referrals_exit: