diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 43 | ||||
-rw-r--r-- | fs/cifs/inode.c | 64 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 2 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 6 |
5 files changed, 80 insertions, 41 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 09ea6321c55a..5144e9fbeb8c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -140,6 +140,8 @@ void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr); | |||
140 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, | 140 | extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, |
141 | FILE_UNIX_BASIC_INFO *info, | 141 | FILE_UNIX_BASIC_INFO *info, |
142 | struct cifs_sb_info *cifs_sb); | 142 | struct cifs_sb_info *cifs_sb); |
143 | extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *, | ||
144 | struct cifs_sb_info *); | ||
143 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); | 145 | extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); |
144 | extern struct inode *cifs_iget(struct super_block *sb, | 146 | extern struct inode *cifs_iget(struct super_block *sb, |
145 | struct cifs_fattr *fattr); | 147 | struct cifs_fattr *fattr); |
@@ -216,10 +218,10 @@ extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses, | |||
216 | const struct nls_table *); | 218 | const struct nls_table *); |
217 | 219 | ||
218 | extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, | 220 | extern int CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, |
219 | const char *searchName, const struct nls_table *nls_codepage, | 221 | const char *searchName, struct cifs_sb_info *cifs_sb, |
220 | __u16 *searchHandle, __u16 search_flags, | 222 | __u16 *searchHandle, __u16 search_flags, |
221 | struct cifs_search_info *psrch_inf, | 223 | struct cifs_search_info *psrch_inf, |
222 | int map, const char dirsep); | 224 | bool msearch); |
223 | 225 | ||
224 | extern int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon, | 226 | extern int CIFSFindNext(const unsigned int xid, struct cifs_tcon *tcon, |
225 | __u16 searchHandle, __u16 search_flags, | 227 | __u16 searchHandle, __u16 search_flags, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 88bbb3ef95b3..76d0d2998850 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -4214,10 +4214,9 @@ UnixQPathInfoRetry: | |||
4214 | /* xid, tcon, searchName and codepage are input parms, rest are returned */ | 4214 | /* xid, tcon, searchName and codepage are input parms, rest are returned */ |
4215 | int | 4215 | int |
4216 | CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, | 4216 | CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, |
4217 | const char *searchName, | 4217 | const char *searchName, struct cifs_sb_info *cifs_sb, |
4218 | const struct nls_table *nls_codepage, | ||
4219 | __u16 *pnetfid, __u16 search_flags, | 4218 | __u16 *pnetfid, __u16 search_flags, |
4220 | struct cifs_search_info *psrch_inf, int remap, const char dirsep) | 4219 | struct cifs_search_info *psrch_inf, bool msearch) |
4221 | { | 4220 | { |
4222 | /* level 257 SMB_ */ | 4221 | /* level 257 SMB_ */ |
4223 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; | 4222 | TRANSACTION2_FFIRST_REQ *pSMB = NULL; |
@@ -4225,8 +4224,9 @@ CIFSFindFirst(const unsigned int xid, struct cifs_tcon *tcon, | |||
4225 | T2_FFIRST_RSP_PARMS *parms; | 4224 | T2_FFIRST_RSP_PARMS *parms; |
4226 | int rc = 0; | 4225 | int rc = 0; |
4227 | int bytes_returned = 0; | 4226 | int bytes_returned = 0; |
4228 | int name_len; | 4227 | int name_len, remap; |
4229 | __u16 params, byte_count; | 4228 | __u16 params, byte_count; |
4229 | struct nls_table *nls_codepage; | ||
4230 | 4230 | ||
4231 | cFYI(1, "In FindFirst for %s", searchName); | 4231 | cFYI(1, "In FindFirst for %s", searchName); |
4232 | 4232 | ||
@@ -4236,6 +4236,9 @@ findFirstRetry: | |||
4236 | if (rc) | 4236 | if (rc) |
4237 | return rc; | 4237 | return rc; |
4238 | 4238 | ||
4239 | nls_codepage = cifs_sb->local_nls; | ||
4240 | remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
4241 | |||
4239 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 4242 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
4240 | name_len = | 4243 | name_len = |
4241 | cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, | 4244 | cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, |
@@ -4244,24 +4247,29 @@ findFirstRetry: | |||
4244 | it got remapped to 0xF03A as if it were part of the | 4247 | it got remapped to 0xF03A as if it were part of the |
4245 | directory name instead of a wildcard */ | 4248 | directory name instead of a wildcard */ |
4246 | name_len *= 2; | 4249 | name_len *= 2; |
4247 | pSMB->FileName[name_len] = dirsep; | 4250 | if (msearch) { |
4248 | pSMB->FileName[name_len+1] = 0; | 4251 | pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); |
4249 | pSMB->FileName[name_len+2] = '*'; | 4252 | pSMB->FileName[name_len+1] = 0; |
4250 | pSMB->FileName[name_len+3] = 0; | 4253 | pSMB->FileName[name_len+2] = '*'; |
4251 | name_len += 4; /* now the trailing null */ | 4254 | pSMB->FileName[name_len+3] = 0; |
4252 | pSMB->FileName[name_len] = 0; /* null terminate just in case */ | 4255 | name_len += 4; /* now the trailing null */ |
4253 | pSMB->FileName[name_len+1] = 0; | 4256 | /* null terminate just in case */ |
4254 | name_len += 2; | 4257 | pSMB->FileName[name_len] = 0; |
4258 | pSMB->FileName[name_len+1] = 0; | ||
4259 | name_len += 2; | ||
4260 | } | ||
4255 | } else { /* BB add check for overrun of SMB buf BB */ | 4261 | } else { /* BB add check for overrun of SMB buf BB */ |
4256 | name_len = strnlen(searchName, PATH_MAX); | 4262 | name_len = strnlen(searchName, PATH_MAX); |
4257 | /* BB fix here and in unicode clause above ie | 4263 | /* BB fix here and in unicode clause above ie |
4258 | if (name_len > buffersize-header) | 4264 | if (name_len > buffersize-header) |
4259 | free buffer exit; BB */ | 4265 | free buffer exit; BB */ |
4260 | strncpy(pSMB->FileName, searchName, name_len); | 4266 | strncpy(pSMB->FileName, searchName, name_len); |
4261 | pSMB->FileName[name_len] = dirsep; | 4267 | if (msearch) { |
4262 | pSMB->FileName[name_len+1] = '*'; | 4268 | pSMB->FileName[name_len] = CIFS_DIR_SEP(cifs_sb); |
4263 | pSMB->FileName[name_len+2] = 0; | 4269 | pSMB->FileName[name_len+1] = '*'; |
4264 | name_len += 3; | 4270 | pSMB->FileName[name_len+2] = 0; |
4271 | name_len += 3; | ||
4272 | } | ||
4265 | } | 4273 | } |
4266 | 4274 | ||
4267 | params = 12 + name_len /* includes null */ ; | 4275 | params = 12 + name_len /* includes null */ ; |
@@ -4349,7 +4357,8 @@ findFirstRetry: | |||
4349 | psrch_inf->last_entry = psrch_inf->srch_entries_start + | 4357 | psrch_inf->last_entry = psrch_inf->srch_entries_start + |
4350 | lnoff; | 4358 | lnoff; |
4351 | 4359 | ||
4352 | *pnetfid = parms->SearchHandle; | 4360 | if (pnetfid) |
4361 | *pnetfid = parms->SearchHandle; | ||
4353 | } else { | 4362 | } else { |
4354 | cifs_buf_release(pSMB); | 4363 | cifs_buf_release(pSMB); |
4355 | } | 4364 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3d155875f446..afdff79651f1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -607,7 +607,9 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
607 | FILE_ALL_INFO *data, struct super_block *sb, int xid, | 607 | FILE_ALL_INFO *data, struct super_block *sb, int xid, |
608 | const __u16 *fid) | 608 | const __u16 *fid) |
609 | { | 609 | { |
610 | int rc = 0, tmprc; | 610 | bool validinum = false; |
611 | __u16 srchflgs; | ||
612 | int rc = 0, tmprc = ENOSYS; | ||
611 | struct cifs_tcon *tcon; | 613 | struct cifs_tcon *tcon; |
612 | struct TCP_Server_Info *server; | 614 | struct TCP_Server_Info *server; |
613 | struct tcon_link *tlink; | 615 | struct tcon_link *tlink; |
@@ -615,6 +617,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
615 | char *buf = NULL; | 617 | char *buf = NULL; |
616 | bool adjust_tz = false; | 618 | bool adjust_tz = false; |
617 | struct cifs_fattr fattr; | 619 | struct cifs_fattr fattr; |
620 | struct cifs_search_info *srchinf = NULL; | ||
618 | 621 | ||
619 | tlink = cifs_sb_tlink(cifs_sb); | 622 | tlink = cifs_sb_tlink(cifs_sb); |
620 | if (IS_ERR(tlink)) | 623 | if (IS_ERR(tlink)) |
@@ -653,9 +656,38 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
653 | } else if (rc == -EREMOTE) { | 656 | } else if (rc == -EREMOTE) { |
654 | cifs_create_dfs_fattr(&fattr, sb); | 657 | cifs_create_dfs_fattr(&fattr, sb); |
655 | rc = 0; | 658 | rc = 0; |
656 | } else { | 659 | } else if (rc == -EACCES && backup_cred(cifs_sb)) { |
660 | srchinf = kzalloc(sizeof(struct cifs_search_info), | ||
661 | GFP_KERNEL); | ||
662 | if (srchinf == NULL) { | ||
663 | rc = -ENOMEM; | ||
664 | goto cgii_exit; | ||
665 | } | ||
666 | |||
667 | srchinf->endOfSearch = false; | ||
668 | srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; | ||
669 | |||
670 | srchflgs = CIFS_SEARCH_CLOSE_ALWAYS | | ||
671 | CIFS_SEARCH_CLOSE_AT_END | | ||
672 | CIFS_SEARCH_BACKUP_SEARCH; | ||
673 | |||
674 | rc = CIFSFindFirst(xid, tcon, full_path, | ||
675 | cifs_sb, NULL, srchflgs, srchinf, false); | ||
676 | if (!rc) { | ||
677 | data = | ||
678 | (FILE_ALL_INFO *)srchinf->srch_entries_start; | ||
679 | |||
680 | cifs_dir_info_to_fattr(&fattr, | ||
681 | (FILE_DIRECTORY_INFO *)data, cifs_sb); | ||
682 | fattr.cf_uniqueid = le64_to_cpu( | ||
683 | ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId); | ||
684 | validinum = true; | ||
685 | |||
686 | cifs_buf_release(srchinf->ntwrk_buf_start); | ||
687 | } | ||
688 | kfree(srchinf); | ||
689 | } else | ||
657 | goto cgii_exit; | 690 | goto cgii_exit; |
658 | } | ||
659 | 691 | ||
660 | /* | 692 | /* |
661 | * If an inode wasn't passed in, then get the inode number | 693 | * If an inode wasn't passed in, then get the inode number |
@@ -666,23 +698,21 @@ cifs_get_inode_info(struct inode **inode, const char *full_path, | |||
666 | */ | 698 | */ |
667 | if (*inode == NULL) { | 699 | if (*inode == NULL) { |
668 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 700 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
669 | if (server->ops->get_srv_inum) | 701 | if (validinum == false) { |
670 | tmprc = server->ops->get_srv_inum(xid, tcon, | 702 | if (server->ops->get_srv_inum) |
671 | cifs_sb, full_path, &fattr.cf_uniqueid, | 703 | tmprc = server->ops->get_srv_inum(xid, |
672 | data); | 704 | tcon, cifs_sb, full_path, |
673 | else | 705 | &fattr.cf_uniqueid, data); |
674 | tmprc = -ENOSYS; | 706 | if (tmprc) { |
675 | if (tmprc || !fattr.cf_uniqueid) { | 707 | cFYI(1, "GetSrvInodeNum rc %d", tmprc); |
676 | cFYI(1, "GetSrvInodeNum rc %d", tmprc); | 708 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
677 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 709 | cifs_autodisable_serverino(cifs_sb); |
678 | cifs_autodisable_serverino(cifs_sb); | 710 | } |
679 | } | 711 | } |
680 | } else { | 712 | } else |
681 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 713 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
682 | } | 714 | } else |
683 | } else { | ||
684 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; | 715 | fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid; |
685 | } | ||
686 | 716 | ||
687 | /* query for SFU type info if supported and needed */ | 717 | /* query for SFU type info if supported and needed */ |
688 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && | 718 | if (fattr.cf_cifsattrs & ATTR_SYSTEM && |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index b0f4a428398d..f9b5d3d6cf33 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -151,7 +151,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | |||
151 | } | 151 | } |
152 | } | 152 | } |
153 | 153 | ||
154 | static void | 154 | void |
155 | cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, | 155 | cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, |
156 | struct cifs_sb_info *cifs_sb) | 156 | struct cifs_sb_info *cifs_sb) |
157 | { | 157 | { |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 42dccbb57c40..56cc4be87807 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -837,10 +837,8 @@ cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, | |||
837 | struct cifs_fid *fid, __u16 search_flags, | 837 | struct cifs_fid *fid, __u16 search_flags, |
838 | struct cifs_search_info *srch_inf) | 838 | struct cifs_search_info *srch_inf) |
839 | { | 839 | { |
840 | return CIFSFindFirst(xid, tcon, path, cifs_sb->local_nls, | 840 | return CIFSFindFirst(xid, tcon, path, cifs_sb, |
841 | &fid->netfid, search_flags, srch_inf, | 841 | &fid->netfid, search_flags, srch_inf, true); |
842 | cifs_sb->mnt_cifs_flags & | ||
843 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | ||
844 | } | 842 | } |
845 | 843 | ||
846 | static int | 844 | static int |