diff options
author | Steve French <sfrench@us.ibm.com> | 2008-05-14 21:50:56 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-05-14 21:50:56 -0400 |
commit | 646dd539878a194bc14b104621c0b2b33587e40f (patch) | |
tree | ba3e9a8a9565e66ea53905b209438fae6d413853 /fs/cifs/inode.c | |
parent | 35fc37d5175091c36d034a28c057da0f9594ee7e (diff) |
[CIFS] Fix paths when share is in DFS to include proper prefix
Some versions of Samba (3.2-pre e.g.) are stricter about checking to make sure that
paths in DFS name spaces are sent in the form \\server\share\dir\subdir ...
instead of \dir\subdir
Acked-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 65 |
1 files changed, 8 insertions, 57 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2d53b436d511..9d9b56a9c08e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -161,52 +161,18 @@ static void cifs_unix_info_to_inode(struct inode *inode, | |||
161 | spin_unlock(&inode->i_lock); | 161 | spin_unlock(&inode->i_lock); |
162 | } | 162 | } |
163 | 163 | ||
164 | static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb, | ||
165 | const char *search_path) | ||
166 | { | ||
167 | int tree_len; | ||
168 | int path_len; | ||
169 | int i; | ||
170 | char *tmp_path; | ||
171 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | ||
172 | |||
173 | if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) | ||
174 | return search_path; | ||
175 | |||
176 | /* use full path name for working with DFS */ | ||
177 | tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); | ||
178 | path_len = strnlen(search_path, MAX_PATHCONF); | ||
179 | |||
180 | tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); | ||
181 | if (tmp_path == NULL) | ||
182 | return search_path; | ||
183 | |||
184 | strncpy(tmp_path, pTcon->treeName, tree_len); | ||
185 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | ||
186 | for (i = 0; i < tree_len; i++) { | ||
187 | if (tmp_path[i] == '\\') | ||
188 | tmp_path[i] = '/'; | ||
189 | } | ||
190 | strncpy(tmp_path+tree_len, search_path, path_len); | ||
191 | tmp_path[tree_len+path_len] = 0; | ||
192 | return tmp_path; | ||
193 | } | ||
194 | |||
195 | int cifs_get_inode_info_unix(struct inode **pinode, | 164 | int cifs_get_inode_info_unix(struct inode **pinode, |
196 | const unsigned char *search_path, struct super_block *sb, int xid) | 165 | const unsigned char *full_path, struct super_block *sb, int xid) |
197 | { | 166 | { |
198 | int rc = 0; | 167 | int rc = 0; |
199 | FILE_UNIX_BASIC_INFO findData; | 168 | FILE_UNIX_BASIC_INFO findData; |
200 | struct cifsTconInfo *pTcon; | 169 | struct cifsTconInfo *pTcon; |
201 | struct inode *inode; | 170 | struct inode *inode; |
202 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 171 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
203 | const unsigned char *full_path; | ||
204 | bool is_dfs_referral = false; | 172 | bool is_dfs_referral = false; |
205 | 173 | ||
206 | pTcon = cifs_sb->tcon; | 174 | pTcon = cifs_sb->tcon; |
207 | cFYI(1, ("Getting info on %s", search_path)); | 175 | cFYI(1, ("Getting info on %s", full_path)); |
208 | |||
209 | full_path = cifs_get_search_path(cifs_sb, search_path); | ||
210 | 176 | ||
211 | try_again_CIFSSMBUnixQPathInfo: | 177 | try_again_CIFSSMBUnixQPathInfo: |
212 | /* could have done a find first instead but this returns more info */ | 178 | /* could have done a find first instead but this returns more info */ |
@@ -218,10 +184,6 @@ try_again_CIFSSMBUnixQPathInfo: | |||
218 | if (rc) { | 184 | if (rc) { |
219 | if (rc == -EREMOTE && !is_dfs_referral) { | 185 | if (rc == -EREMOTE && !is_dfs_referral) { |
220 | is_dfs_referral = true; | 186 | is_dfs_referral = true; |
221 | if (full_path != search_path) { | ||
222 | kfree(full_path); | ||
223 | full_path = search_path; | ||
224 | } | ||
225 | goto try_again_CIFSSMBUnixQPathInfo; | 187 | goto try_again_CIFSSMBUnixQPathInfo; |
226 | } | 188 | } |
227 | goto cgiiu_exit; | 189 | goto cgiiu_exit; |
@@ -271,8 +233,6 @@ try_again_CIFSSMBUnixQPathInfo: | |||
271 | cifs_set_ops(inode, is_dfs_referral); | 233 | cifs_set_ops(inode, is_dfs_referral); |
272 | } | 234 | } |
273 | cgiiu_exit: | 235 | cgiiu_exit: |
274 | if (full_path != search_path) | ||
275 | kfree(full_path); | ||
276 | return rc; | 236 | return rc; |
277 | } | 237 | } |
278 | 238 | ||
@@ -380,20 +340,19 @@ static int get_sfu_mode(struct inode *inode, | |||
380 | } | 340 | } |
381 | 341 | ||
382 | int cifs_get_inode_info(struct inode **pinode, | 342 | int cifs_get_inode_info(struct inode **pinode, |
383 | const unsigned char *search_path, FILE_ALL_INFO *pfindData, | 343 | const unsigned char *full_path, FILE_ALL_INFO *pfindData, |
384 | struct super_block *sb, int xid, const __u16 *pfid) | 344 | struct super_block *sb, int xid, const __u16 *pfid) |
385 | { | 345 | { |
386 | int rc = 0; | 346 | int rc = 0; |
387 | struct cifsTconInfo *pTcon; | 347 | struct cifsTconInfo *pTcon; |
388 | struct inode *inode; | 348 | struct inode *inode; |
389 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 349 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
390 | const unsigned char *full_path = NULL; | ||
391 | char *buf = NULL; | 350 | char *buf = NULL; |
392 | bool adjustTZ = false; | 351 | bool adjustTZ = false; |
393 | bool is_dfs_referral = false; | 352 | bool is_dfs_referral = false; |
394 | 353 | ||
395 | pTcon = cifs_sb->tcon; | 354 | pTcon = cifs_sb->tcon; |
396 | cFYI(1, ("Getting info on %s", search_path)); | 355 | cFYI(1, ("Getting info on %s", full_path)); |
397 | 356 | ||
398 | if ((pfindData == NULL) && (*pinode != NULL)) { | 357 | if ((pfindData == NULL) && (*pinode != NULL)) { |
399 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 358 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
@@ -409,8 +368,6 @@ int cifs_get_inode_info(struct inode **pinode, | |||
409 | return -ENOMEM; | 368 | return -ENOMEM; |
410 | pfindData = (FILE_ALL_INFO *)buf; | 369 | pfindData = (FILE_ALL_INFO *)buf; |
411 | 370 | ||
412 | full_path = cifs_get_search_path(cifs_sb, search_path); | ||
413 | |||
414 | try_again_CIFSSMBQPathInfo: | 371 | try_again_CIFSSMBQPathInfo: |
415 | /* could do find first instead but this returns more info */ | 372 | /* could do find first instead but this returns more info */ |
416 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, | 373 | rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, |
@@ -432,10 +389,6 @@ try_again_CIFSSMBQPathInfo: | |||
432 | if (rc) { | 389 | if (rc) { |
433 | if (rc == -EREMOTE && !is_dfs_referral) { | 390 | if (rc == -EREMOTE && !is_dfs_referral) { |
434 | is_dfs_referral = true; | 391 | is_dfs_referral = true; |
435 | if (full_path != search_path) { | ||
436 | kfree(full_path); | ||
437 | full_path = search_path; | ||
438 | } | ||
439 | goto try_again_CIFSSMBQPathInfo; | 392 | goto try_again_CIFSSMBQPathInfo; |
440 | } | 393 | } |
441 | goto cgii_exit; | 394 | goto cgii_exit; |
@@ -470,7 +423,7 @@ try_again_CIFSSMBQPathInfo: | |||
470 | __u64 inode_num; | 423 | __u64 inode_num; |
471 | 424 | ||
472 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, | 425 | rc1 = CIFSGetSrvInodeNumber(xid, pTcon, |
473 | search_path, &inode_num, | 426 | full_path, &inode_num, |
474 | cifs_sb->local_nls, | 427 | cifs_sb->local_nls, |
475 | cifs_sb->mnt_cifs_flags & | 428 | cifs_sb->mnt_cifs_flags & |
476 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 429 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -539,7 +492,7 @@ try_again_CIFSSMBQPathInfo: | |||
539 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { | 492 | (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { |
540 | if (decode_sfu_inode(inode, | 493 | if (decode_sfu_inode(inode, |
541 | le64_to_cpu(pfindData->EndOfFile), | 494 | le64_to_cpu(pfindData->EndOfFile), |
542 | search_path, | 495 | full_path, |
543 | cifs_sb, xid)) | 496 | cifs_sb, xid)) |
544 | cFYI(1, ("Unrecognized sfu inode type")); | 497 | cFYI(1, ("Unrecognized sfu inode type")); |
545 | 498 | ||
@@ -582,12 +535,12 @@ try_again_CIFSSMBQPathInfo: | |||
582 | /* fill in 0777 bits from ACL */ | 535 | /* fill in 0777 bits from ACL */ |
583 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 536 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
584 | cFYI(1, ("Getting mode bits from ACL")); | 537 | cFYI(1, ("Getting mode bits from ACL")); |
585 | acl_to_uid_mode(inode, search_path, pfid); | 538 | acl_to_uid_mode(inode, full_path, pfid); |
586 | } | 539 | } |
587 | #endif | 540 | #endif |
588 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 541 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
589 | /* fill in remaining high mode bits e.g. SUID, VTX */ | 542 | /* fill in remaining high mode bits e.g. SUID, VTX */ |
590 | get_sfu_mode(inode, search_path, cifs_sb, xid); | 543 | get_sfu_mode(inode, full_path, cifs_sb, xid); |
591 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | 544 | } else if (atomic_read(&cifsInfo->inUse) == 0) { |
592 | inode->i_uid = cifs_sb->mnt_uid; | 545 | inode->i_uid = cifs_sb->mnt_uid; |
593 | inode->i_gid = cifs_sb->mnt_gid; | 546 | inode->i_gid = cifs_sb->mnt_gid; |
@@ -599,8 +552,6 @@ try_again_CIFSSMBQPathInfo: | |||
599 | cifs_set_ops(inode, is_dfs_referral); | 552 | cifs_set_ops(inode, is_dfs_referral); |
600 | } | 553 | } |
601 | cgii_exit: | 554 | cgii_exit: |
602 | if (full_path != search_path) | ||
603 | kfree(full_path); | ||
604 | kfree(buf); | 555 | kfree(buf); |
605 | return rc; | 556 | return rc; |
606 | } | 557 | } |