diff options
Diffstat (limited to 'fs/cifs/readdir.c')
-rw-r--r-- | fs/cifs/readdir.c | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 1a8be6228333..964e097c8203 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -31,6 +31,13 @@ | |||
31 | #include "cifs_fs_sb.h" | 31 | #include "cifs_fs_sb.h" |
32 | #include "cifsfs.h" | 32 | #include "cifsfs.h" |
33 | 33 | ||
34 | /* | ||
35 | * To be safe - for UCS to UTF-8 with strings loaded with the rare long | ||
36 | * characters alloc more to account for such multibyte target UTF-8 | ||
37 | * characters. | ||
38 | */ | ||
39 | #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) | ||
40 | |||
34 | #ifdef CONFIG_CIFS_DEBUG2 | 41 | #ifdef CONFIG_CIFS_DEBUG2 |
35 | static void dump_cifs_file_struct(struct file *file, char *label) | 42 | static void dump_cifs_file_struct(struct file *file, char *label) |
36 | { | 43 | { |
@@ -438,6 +445,38 @@ static void unix_fill_in_inode(struct inode *tmp_inode, | |||
438 | } | 445 | } |
439 | } | 446 | } |
440 | 447 | ||
448 | /* BB eventually need to add the following helper function to | ||
449 | resolve NT_STATUS_STOPPED_ON_SYMLINK return code when | ||
450 | we try to do FindFirst on (NTFS) directory symlinks */ | ||
451 | /* | ||
452 | int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, | ||
453 | int xid) | ||
454 | { | ||
455 | __u16 fid; | ||
456 | int len; | ||
457 | int oplock = 0; | ||
458 | int rc; | ||
459 | struct cifsTconInfo *ptcon = cifs_sb->tcon; | ||
460 | char *tmpbuffer; | ||
461 | |||
462 | rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, | ||
463 | OPEN_REPARSE_POINT, &fid, &oplock, NULL, | ||
464 | cifs_sb->local_nls, | ||
465 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
466 | if (!rc) { | ||
467 | tmpbuffer = kmalloc(maxpath); | ||
468 | rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, | ||
469 | tmpbuffer, | ||
470 | maxpath -1, | ||
471 | fid, | ||
472 | cifs_sb->local_nls); | ||
473 | if (CIFSSMBClose(xid, ptcon, fid)) { | ||
474 | cFYI(1, ("Error closing temporary reparsepoint open)")); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | */ | ||
479 | |||
441 | static int initiate_cifs_search(const int xid, struct file *file) | 480 | static int initiate_cifs_search(const int xid, struct file *file) |
442 | { | 481 | { |
443 | int rc = 0; | 482 | int rc = 0; |
@@ -493,7 +532,10 @@ ffirst_retry: | |||
493 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); | 532 | CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); |
494 | if (rc == 0) | 533 | if (rc == 0) |
495 | cifsFile->invalidHandle = false; | 534 | cifsFile->invalidHandle = false; |
496 | if ((rc == -EOPNOTSUPP) && | 535 | /* BB add following call to handle readdir on new NTFS symlink errors |
536 | else if STATUS_STOPPED_ON_SYMLINK | ||
537 | call get_symlink_reparse_path and retry with new path */ | ||
538 | else if ((rc == -EOPNOTSUPP) && | ||
497 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { | 539 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { |
498 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; | 540 | cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
499 | goto ffirst_retry; | 541 | goto ffirst_retry; |
@@ -822,7 +864,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, | |||
822 | /* inode num, inode type and filename returned */ | 864 | /* inode num, inode type and filename returned */ |
823 | static int cifs_get_name_from_search_buf(struct qstr *pqst, | 865 | static int cifs_get_name_from_search_buf(struct qstr *pqst, |
824 | char *current_entry, __u16 level, unsigned int unicode, | 866 | char *current_entry, __u16 level, unsigned int unicode, |
825 | struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum) | 867 | struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum) |
826 | { | 868 | { |
827 | int rc = 0; | 869 | int rc = 0; |
828 | unsigned int len = 0; | 870 | unsigned int len = 0; |
@@ -881,14 +923,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
881 | } | 923 | } |
882 | 924 | ||
883 | if (unicode) { | 925 | if (unicode) { |
884 | /* BB fixme - test with long names */ | 926 | pqst->len = cifs_from_ucs2((char *) pqst->name, |
885 | /* Note converted filename can be longer than in unicode */ | 927 | (__le16 *) filename, |
886 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | 928 | UNICODE_NAME_MAX, |
887 | pqst->len = cifs_convertUCSpath((char *)pqst->name, | 929 | min(len, max_len), nlt, |
888 | (__le16 *)filename, len/2, nlt); | 930 | cifs_sb->mnt_cifs_flags & |
889 | else | 931 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
890 | pqst->len = cifs_strfromUCS_le((char *)pqst->name, | ||
891 | (__le16 *)filename, len/2, nlt); | ||
892 | } else { | 932 | } else { |
893 | pqst->name = filename; | 933 | pqst->name = filename; |
894 | pqst->len = len; | 934 | pqst->len = len; |
@@ -898,8 +938,8 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
898 | return rc; | 938 | return rc; |
899 | } | 939 | } |
900 | 940 | ||
901 | static int cifs_filldir(char *pfindEntry, struct file *file, | 941 | static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, |
902 | filldir_t filldir, void *direntry, char *scratch_buf, int max_len) | 942 | void *direntry, char *scratch_buf, unsigned int max_len) |
903 | { | 943 | { |
904 | int rc = 0; | 944 | int rc = 0; |
905 | struct qstr qstring; | 945 | struct qstr qstring; |
@@ -996,7 +1036,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
996 | int num_to_fill = 0; | 1036 | int num_to_fill = 0; |
997 | char *tmp_buf = NULL; | 1037 | char *tmp_buf = NULL; |
998 | char *end_of_smb; | 1038 | char *end_of_smb; |
999 | int max_len; | 1039 | unsigned int max_len; |
1000 | 1040 | ||
1001 | xid = GetXid(); | 1041 | xid = GetXid(); |
1002 | 1042 | ||
@@ -1070,11 +1110,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
1070 | cifsFile->srch_inf.ntwrk_buf_start); | 1110 | cifsFile->srch_inf.ntwrk_buf_start); |
1071 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | 1111 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; |
1072 | 1112 | ||
1073 | /* To be safe - for UCS to UTF-8 with strings loaded | 1113 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); |
1074 | with the rare long characters alloc more to account for | ||
1075 | such multibyte target UTF-8 characters. cifs_unicode.c, | ||
1076 | which actually does the conversion, has the same limit */ | ||
1077 | tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); | ||
1078 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | 1114 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { |
1079 | if (current_entry == NULL) { | 1115 | if (current_entry == NULL) { |
1080 | /* evaluate whether this case is an error */ | 1116 | /* evaluate whether this case is an error */ |