diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r-- | fs/cifs/cifssmb.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index e6bb2d9d5b09..bdda46dd435a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -3899,6 +3899,27 @@ GetInodeNumOut: | |||
3899 | return rc; | 3899 | return rc; |
3900 | } | 3900 | } |
3901 | 3901 | ||
3902 | /* computes length of UCS string converted to host codepage | ||
3903 | * @src: UCS string | ||
3904 | * @maxlen: length of the input string in UCS characters | ||
3905 | * (not in bytes) | ||
3906 | * | ||
3907 | * return: size of input string in host codepage | ||
3908 | */ | ||
3909 | static int hostlen_fromUCS(const __le16 *src, const int maxlen, | ||
3910 | const struct nls_table *nls_codepage) { | ||
3911 | int i; | ||
3912 | int hostlen = 0; | ||
3913 | char to[4]; | ||
3914 | int charlen; | ||
3915 | for (i = 0; (i < maxlen) && src[i]; ++i) { | ||
3916 | charlen = nls_codepage->uni2char(le16_to_cpu(src[i]), | ||
3917 | to, NLS_MAX_CHARSET_SIZE); | ||
3918 | hostlen += charlen > 0 ? charlen : 1; | ||
3919 | } | ||
3920 | return hostlen; | ||
3921 | } | ||
3922 | |||
3902 | /* parses DFS refferal V3 structure | 3923 | /* parses DFS refferal V3 structure |
3903 | * caller is responsible for freeing target_nodes | 3924 | * caller is responsible for freeing target_nodes |
3904 | * returns: | 3925 | * returns: |
@@ -3909,7 +3930,8 @@ static int | |||
3909 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | 3930 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, |
3910 | unsigned int *num_of_nodes, | 3931 | unsigned int *num_of_nodes, |
3911 | struct dfs_info3_param **target_nodes, | 3932 | struct dfs_info3_param **target_nodes, |
3912 | const struct nls_table *nls_codepage) | 3933 | const struct nls_table *nls_codepage, int remap, |
3934 | const char *searchName) | ||
3913 | { | 3935 | { |
3914 | int i, rc = 0; | 3936 | int i, rc = 0; |
3915 | char *data_end; | 3937 | char *data_end; |
@@ -3960,7 +3982,17 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3960 | struct dfs_info3_param *node = (*target_nodes)+i; | 3982 | struct dfs_info3_param *node = (*target_nodes)+i; |
3961 | 3983 | ||
3962 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | 3984 | node->flags = le16_to_cpu(pSMBr->DFSFlags); |
3963 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | 3985 | if (is_unicode) { |
3986 | __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL); | ||
3987 | cifsConvertToUCS((__le16 *) tmp, searchName, | ||
3988 | PATH_MAX, nls_codepage, remap); | ||
3989 | node->path_consumed = hostlen_fromUCS(tmp, | ||
3990 | le16_to_cpu(pSMBr->PathConsumed)/2, | ||
3991 | nls_codepage); | ||
3992 | kfree(tmp); | ||
3993 | } else | ||
3994 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | ||
3995 | |||
3964 | node->server_type = le16_to_cpu(ref->ServerType); | 3996 | node->server_type = le16_to_cpu(ref->ServerType); |
3965 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); | 3997 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); |
3966 | 3998 | ||
@@ -4093,7 +4125,8 @@ getDFSRetry: | |||
4093 | 4125 | ||
4094 | /* parse returned result into more usable form */ | 4126 | /* parse returned result into more usable form */ |
4095 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, | 4127 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, |
4096 | target_nodes, nls_codepage); | 4128 | target_nodes, nls_codepage, remap, |
4129 | searchName); | ||
4097 | 4130 | ||
4098 | GetDFSRefExit: | 4131 | GetDFSRefExit: |
4099 | cifs_buf_release(pSMB); | 4132 | cifs_buf_release(pSMB); |