aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/readdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r--fs/cifs/readdir.c109
1 files changed, 23 insertions, 86 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 67fc1199699f..47bb1b8cd305 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -656,82 +656,6 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon,
656 return rc; 656 return rc;
657} 657}
658 658
659/* inode num, inode type and filename returned */
660static int cifs_get_name_from_search_buf(struct qstr *pqst,
661 char *current_entry, __u16 level, unsigned int unicode,
662 struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
663{
664 int rc = 0;
665 unsigned int len = 0;
666 char *filename;
667 struct nls_table *nlt = cifs_sb->local_nls;
668
669 *pinum = 0;
670
671 if (level == SMB_FIND_FILE_UNIX) {
672 FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
673
674 filename = &pFindData->FileName[0];
675 if (unicode) {
676 len = cifs_unicode_bytelen(filename);
677 } else {
678 /* BB should we make this strnlen of PATH_MAX? */
679 len = strnlen(filename, PATH_MAX);
680 }
681
682 *pinum = le64_to_cpu(pFindData->basic.UniqueId);
683 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
684 FILE_DIRECTORY_INFO *pFindData =
685 (FILE_DIRECTORY_INFO *)current_entry;
686 filename = &pFindData->FileName[0];
687 len = le32_to_cpu(pFindData->FileNameLength);
688 } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
689 FILE_FULL_DIRECTORY_INFO *pFindData =
690 (FILE_FULL_DIRECTORY_INFO *)current_entry;
691 filename = &pFindData->FileName[0];
692 len = le32_to_cpu(pFindData->FileNameLength);
693 } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
694 SEARCH_ID_FULL_DIR_INFO *pFindData =
695 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
696 filename = &pFindData->FileName[0];
697 len = le32_to_cpu(pFindData->FileNameLength);
698 *pinum = le64_to_cpu(pFindData->UniqueId);
699 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
700 FILE_BOTH_DIRECTORY_INFO *pFindData =
701 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
702 filename = &pFindData->FileName[0];
703 len = le32_to_cpu(pFindData->FileNameLength);
704 } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
705 FIND_FILE_STANDARD_INFO *pFindData =
706 (FIND_FILE_STANDARD_INFO *)current_entry;
707 filename = &pFindData->FileName[0];
708 /* one byte length, no name conversion */
709 len = (unsigned int)pFindData->FileNameLength;
710 } else {
711 cFYI(1, "Unknown findfirst level %d", level);
712 return -EINVAL;
713 }
714
715 if (len > max_len) {
716 cERROR(1, "bad search response length %d past smb end", len);
717 return -EINVAL;
718 }
719
720 if (unicode) {
721 pqst->len = cifs_from_ucs2((char *) pqst->name,
722 (__le16 *) filename,
723 UNICODE_NAME_MAX,
724 min(len, max_len), nlt,
725 cifs_sb->mnt_cifs_flags &
726 CIFS_MOUNT_MAP_SPECIAL_CHR);
727 pqst->len -= nls_nullsize(nlt);
728 } else {
729 pqst->name = filename;
730 pqst->len = len;
731 }
732 return rc;
733}
734
735static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, 659static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
736 void *dirent, char *scratch_buf, unsigned int max_len) 660 void *dirent, char *scratch_buf, unsigned int max_len)
737{ 661{
@@ -743,7 +667,6 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
743 struct dentry *dentry; 667 struct dentry *dentry;
744 struct qstr name; 668 struct qstr name;
745 int rc = 0; 669 int rc = 0;
746 u64 inum;
747 ino_t ino; 670 ino_t ino;
748 671
749 rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, 672 rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
@@ -751,17 +674,31 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
751 if (rc) 674 if (rc)
752 return rc; 675 return rc;
753 676
677 if (de.namelen > max_len) {
678 cERROR(1, "bad search response length %zd past smb end",
679 de.namelen);
680 return -EINVAL;
681 }
682
754 /* skip . and .. since we added them first */ 683 /* skip . and .. since we added them first */
755 if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) 684 if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
756 return 0; 685 return 0;
757 686
758 name.name = scratch_buf; 687 if (file_info->srch_inf.unicode) {
759 rc = cifs_get_name_from_search_buf(&name, find_entry, 688 struct nls_table *nlt = cifs_sb->local_nls;
760 file_info->srch_inf.info_level, 689
761 file_info->srch_inf.unicode, 690 name.name = scratch_buf;
762 cifs_sb, max_len, &inum); 691 name.len =
763 if (rc) 692 cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
764 return rc; 693 UNICODE_NAME_MAX,
694 min(de.namelen, (size_t)max_len), nlt,
695 cifs_sb->mnt_cifs_flags &
696 CIFS_MOUNT_MAP_SPECIAL_CHR);
697 name.len -= nls_nullsize(nlt);
698 } else {
699 name.name = de.name;
700 name.len = de.namelen;
701 }
765 702
766 switch (file_info->srch_inf.info_level) { 703 switch (file_info->srch_inf.info_level) {
767 case SMB_FIND_FILE_UNIX: 704 case SMB_FIND_FILE_UNIX:
@@ -781,8 +718,8 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
781 break; 718 break;
782 } 719 }
783 720
784 if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 721 if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
785 fattr.cf_uniqueid = inum; 722 fattr.cf_uniqueid = de.ino;
786 } else { 723 } else {
787 fattr.cf_uniqueid = iunique(sb, ROOT_I); 724 fattr.cf_uniqueid = iunique(sb, ROOT_I);
788 cifs_autodisable_serverino(cifs_sb); 725 cifs_autodisable_serverino(cifs_sb);