1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/fs.h>
25#include <linux/pagemap.h>
26#include <linux/slab.h>
27#include <linux/stat.h>
28#include "cifspdu.h"
29#include "cifsglob.h"
30#include "cifsproto.h"
31#include "cifs_unicode.h"
32#include "cifs_debug.h"
33#include "cifs_fs_sb.h"
34#include "cifsfs.h"
35
36
37
38
39
40
41#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
42
43#ifdef CONFIG_CIFS_DEBUG2
44static void dump_cifs_file_struct(struct file *file, char *label)
45{
46 struct cifsFileInfo *cf;
47
48 if (file) {
49 cf = file->private_data;
50 if (cf == NULL) {
51 cifs_dbg(FYI, "empty cifs private file data\n");
52 return;
53 }
54 if (cf->invalidHandle)
55 cifs_dbg(FYI, "invalid handle\n");
56 if (cf->srch_inf.endOfSearch)
57 cifs_dbg(FYI, "end of search\n");
58 if (cf->srch_inf.emptyDir)
59 cifs_dbg(FYI, "empty dir\n");
60 }
61}
62#else
63static inline void dump_cifs_file_struct(struct file *file, char *label)
64{
65}
66#endif
67
68
69
70
71
72
73
74
75static void
76cifs_prime_dcache(struct dentry *parent, struct qstr *name,
77 struct cifs_fattr *fattr)
78{
79 struct dentry *dentry, *alias;
80 struct inode *inode;
81 struct super_block *sb = d_inode(parent)->i_sb;
82 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
83
84 cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
85
86 dentry = d_hash_and_lookup(parent, name);
87 if (IS_ERR(dentry))
88 return;
89
90 if (dentry) {
91 inode = d_inode(dentry);
92 if (inode) {
93 if (d_mountpoint(dentry))
94 goto out;
95
96
97
98
99
100 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
101 fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
102
103
104
105 if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid &&
106 (inode->i_mode & S_IFMT) ==
107 (fattr->cf_mode & S_IFMT)) {
108 cifs_fattr_to_inode(inode, fattr);
109 goto out;
110 }
111 }
112 d_invalidate(dentry);
113 dput(dentry);
114 }
115
116
117
118
119
120
121 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
122 return;
123
124 dentry = d_alloc(parent, name);
125 if (!dentry)
126 return;
127
128 inode = cifs_iget(sb, fattr);
129 if (!inode)
130 goto out;
131
132 alias = d_splice_alias(inode, dentry);
133 if (alias && !IS_ERR(alias))
134 dput(alias);
135out:
136 dput(dentry);
137}
138
139static void
140cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
141{
142 fattr->cf_uid = cifs_sb->mnt_uid;
143 fattr->cf_gid = cifs_sb->mnt_gid;
144
145 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
146 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
147 fattr->cf_dtype = DT_DIR;
148 } else {
149 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
150 fattr->cf_dtype = DT_REG;
151 }
152
153
154
155
156
157
158 if (fattr->cf_cifsattrs & ATTR_REPARSE)
159 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
160
161
162 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
163
164 if (fattr->cf_cifsattrs & ATTR_READONLY)
165 fattr->cf_mode &= ~S_IWUGO;
166
167
168
169
170
171
172
173
174 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
175 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
176
177 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
178 fattr->cf_cifsattrs & ATTR_SYSTEM) {
179 if (fattr->cf_eof == 0) {
180 fattr->cf_mode &= ~S_IFMT;
181 fattr->cf_mode |= S_IFIFO;
182 fattr->cf_dtype = DT_FIFO;
183 } else {
184
185
186
187
188
189 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
190 }
191 }
192}
193
194void
195cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
196 struct cifs_sb_info *cifs_sb)
197{
198 memset(fattr, 0, sizeof(*fattr));
199 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
200 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
201 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
202 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
203 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
204 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
205 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
206
207 cifs_fill_common_info(fattr, cifs_sb);
208}
209
210static void
211cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
212 struct cifs_sb_info *cifs_sb)
213{
214 int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
215
216 memset(fattr, 0, sizeof(*fattr));
217 fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
218 info->LastAccessTime, offset);
219 fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
220 info->LastWriteTime, offset);
221 fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
222 info->LastWriteTime, offset);
223
224 fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
225 fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
226 fattr->cf_eof = le32_to_cpu(info->DataSize);
227
228 cifs_fill_common_info(fattr, cifs_sb);
229}
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263static int
264initiate_cifs_search(const unsigned int xid, struct file *file)
265{
266 __u16 search_flags;
267 int rc = 0;
268 char *full_path = NULL;
269 struct cifsFileInfo *cifsFile;
270 struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
271 struct tcon_link *tlink = NULL;
272 struct cifs_tcon *tcon;
273 struct TCP_Server_Info *server;
274
275 if (file->private_data == NULL) {
276 tlink = cifs_sb_tlink(cifs_sb);
277 if (IS_ERR(tlink))
278 return PTR_ERR(tlink);
279
280 cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
281 if (cifsFile == NULL) {
282 rc = -ENOMEM;
283 goto error_exit;
284 }
285 file->private_data = cifsFile;
286 cifsFile->tlink = cifs_get_tlink(tlink);
287 tcon = tlink_tcon(tlink);
288 } else {
289 cifsFile = file->private_data;
290 tcon = tlink_tcon(cifsFile->tlink);
291 }
292
293 server = tcon->ses->server;
294
295 if (!server->ops->query_dir_first) {
296 rc = -ENOSYS;
297 goto error_exit;
298 }
299
300 cifsFile->invalidHandle = true;
301 cifsFile->srch_inf.endOfSearch = false;
302
303 full_path = build_path_from_dentry(file->f_path.dentry);
304 if (full_path == NULL) {
305 rc = -ENOMEM;
306 goto error_exit;
307 }
308
309 cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
310
311ffirst_retry:
312
313
314
315 if (tcon->unix_ext)
316 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
317 else if ((tcon->ses->capabilities &
318 tcon->ses->server->vals->cap_nt_find) == 0) {
319 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
320 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
321 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
322 } else {
323 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
324 }
325
326 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
327 if (backup_cred(cifs_sb))
328 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
329
330 rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
331 &cifsFile->fid, search_flags,
332 &cifsFile->srch_inf);
333
334 if (rc == 0)
335 cifsFile->invalidHandle = false;
336
337
338
339 else if ((rc == -EOPNOTSUPP) &&
340 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
341 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
342 goto ffirst_retry;
343 }
344error_exit:
345 kfree(full_path);
346 cifs_put_tlink(tlink);
347 return rc;
348}
349
350
351static int cifs_unicode_bytelen(const char *str)
352{
353 int len;
354 const __le16 *ustr = (const __le16 *)str;
355
356 for (len = 0; len <= PATH_MAX; len++) {
357 if (ustr[len] == 0)
358 return len << 1;
359 }
360 cifs_dbg(FYI, "Unicode string longer than PATH_MAX found\n");
361 return len << 1;
362}
363
364static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
365{
366 char *new_entry;
367 FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
368
369 if (level == SMB_FIND_FILE_INFO_STANDARD) {
370 FIND_FILE_STANDARD_INFO *pfData;
371 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
372
373 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
374 pfData->FileNameLength;
375 } else
376 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
377 cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
378
379 if (new_entry >= end_of_smb) {
380 cifs_dbg(VFS, "search entry %p began after end of SMB %p old entry %p\n",
381 new_entry, end_of_smb, old_entry);
382 return NULL;
383 } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
384 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
385 || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
386 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
387 cifs_dbg(VFS, "search entry %p extends after end of SMB %p\n",
388 new_entry, end_of_smb);
389 return NULL;
390 } else
391 return new_entry;
392
393}
394
395struct cifs_dirent {
396 const char *name;
397 size_t namelen;
398 u32 resume_key;
399 u64 ino;
400};
401
402static void cifs_fill_dirent_unix(struct cifs_dirent *de,
403 const FILE_UNIX_INFO *info, bool is_unicode)
404{
405 de->name = &info->FileName[0];
406 if (is_unicode)
407 de->namelen = cifs_unicode_bytelen(de->name);
408 else
409 de->namelen = strnlen(de->name, PATH_MAX);
410 de->resume_key = info->ResumeKey;
411 de->ino = le64_to_cpu(info->basic.UniqueId);
412}
413
414static void cifs_fill_dirent_dir(struct cifs_dirent *de,
415 const FILE_DIRECTORY_INFO *info)
416{
417 de->name = &info->FileName[0];
418 de->namelen = le32_to_cpu(info->FileNameLength);
419 de->resume_key = info->FileIndex;
420}
421
422static void cifs_fill_dirent_full(struct cifs_dirent *de,
423 const FILE_FULL_DIRECTORY_INFO *info)
424{
425 de->name = &info->FileName[0];
426 de->namelen = le32_to_cpu(info->FileNameLength);
427 de->resume_key = info->FileIndex;
428}
429
430static void cifs_fill_dirent_search(struct cifs_dirent *de,
431 const SEARCH_ID_FULL_DIR_INFO *info)
432{
433 de->name = &info->FileName[0];
434 de->namelen = le32_to_cpu(info->FileNameLength);
435 de->resume_key = info->FileIndex;
436 de->ino = le64_to_cpu(info->UniqueId);
437}
438
439static void cifs_fill_dirent_both(struct cifs_dirent *de,
440 const FILE_BOTH_DIRECTORY_INFO *info)
441{
442 de->name = &info->FileName[0];
443 de->namelen = le32_to_cpu(info->FileNameLength);
444 de->resume_key = info->FileIndex;
445}
446
447static void cifs_fill_dirent_std(struct cifs_dirent *de,
448 const FIND_FILE_STANDARD_INFO *info)
449{
450 de->name = &info->FileName[0];
451
452 de->namelen = info->FileNameLength;
453 de->resume_key = info->ResumeKey;
454}
455
456static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
457 u16 level, bool is_unicode)
458{
459 memset(de, 0, sizeof(*de));
460
461 switch (level) {
462 case SMB_FIND_FILE_UNIX:
463 cifs_fill_dirent_unix(de, info, is_unicode);
464 break;
465 case SMB_FIND_FILE_DIRECTORY_INFO:
466 cifs_fill_dirent_dir(de, info);
467 break;
468 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
469 cifs_fill_dirent_full(de, info);
470 break;
471 case SMB_FIND_FILE_ID_FULL_DIR_INFO:
472 cifs_fill_dirent_search(de, info);
473 break;
474 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
475 cifs_fill_dirent_both(de, info);
476 break;
477 case SMB_FIND_FILE_INFO_STANDARD:
478 cifs_fill_dirent_std(de, info);
479 break;
480 default:
481 cifs_dbg(FYI, "Unknown findfirst level %d\n", level);
482 return -EINVAL;
483 }
484
485 return 0;
486}
487
488#define UNICODE_DOT cpu_to_le16(0x2e)
489
490
491static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
492{
493 int rc = 0;
494
495 if (!de->name)
496 return 0;
497
498 if (is_unicode) {
499 __le16 *ufilename = (__le16 *)de->name;
500 if (de->namelen == 2) {
501
502 if (ufilename[0] == UNICODE_DOT)
503 rc = 1;
504 } else if (de->namelen == 4) {
505
506 if (ufilename[0] == UNICODE_DOT &&
507 ufilename[1] == UNICODE_DOT)
508 rc = 2;
509 }
510 } else {
511 if (de->namelen == 1) {
512 if (de->name[0] == '.')
513 rc = 1;
514 } else if (de->namelen == 2) {
515 if (de->name[0] == '.' && de->name[1] == '.')
516 rc = 2;
517 }
518 }
519
520 return rc;
521}
522
523
524
525static int is_dir_changed(struct file *file)
526{
527 struct inode *inode = file_inode(file);
528 struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
529
530 if (cifsInfo->time == 0)
531 return 1;
532 else
533 return 0;
534
535}
536
537static int cifs_save_resume_key(const char *current_entry,
538 struct cifsFileInfo *file_info)
539{
540 struct cifs_dirent de;
541 int rc;
542
543 rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
544 file_info->srch_inf.unicode);
545 if (!rc) {
546 file_info->srch_inf.presume_name = de.name;
547 file_info->srch_inf.resume_name_len = de.namelen;
548 file_info->srch_inf.resume_key = de.resume_key;
549 }
550 return rc;
551}
552
553
554
555
556
557
558
559
560static int
561find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
562 struct file *file, char **current_entry, int *num_to_ret)
563{
564 __u16 search_flags;
565 int rc = 0;
566 int pos_in_buf = 0;
567 loff_t first_entry_in_buffer;
568 loff_t index_to_find = pos;
569 struct cifsFileInfo *cfile = file->private_data;
570 struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
571 struct TCP_Server_Info *server = tcon->ses->server;
572
573
574 if (!server->ops->query_dir_first || !server->ops->query_dir_next)
575 return -ENOSYS;
576
577 if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
578 return -ENOENT;
579
580 *current_entry = NULL;
581 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
582 cfile->srch_inf.entries_in_buffer;
583
584
585
586
587
588
589
590
591
592 dump_cifs_file_struct(file, "In fce ");
593 if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
594 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
595
596 cifs_dbg(FYI, "search backing up - close and restart search\n");
597 spin_lock(&cifs_file_list_lock);
598 if (server->ops->dir_needs_close(cfile)) {
599 cfile->invalidHandle = true;
600 spin_unlock(&cifs_file_list_lock);
601 if (server->ops->close_dir)
602 server->ops->close_dir(xid, tcon, &cfile->fid);
603 } else
604 spin_unlock(&cifs_file_list_lock);
605 if (cfile->srch_inf.ntwrk_buf_start) {
606 cifs_dbg(FYI, "freeing SMB ff cache buf on search rewind\n");
607 if (cfile->srch_inf.smallBuf)
608 cifs_small_buf_release(cfile->srch_inf.
609 ntwrk_buf_start);
610 else
611 cifs_buf_release(cfile->srch_inf.
612 ntwrk_buf_start);
613 cfile->srch_inf.ntwrk_buf_start = NULL;
614 }
615 rc = initiate_cifs_search(xid, file);
616 if (rc) {
617 cifs_dbg(FYI, "error %d reinitiating a search on rewind\n",
618 rc);
619 return rc;
620 }
621
622 if (cfile->srch_inf.last_entry)
623 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
624 }
625
626 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
627 if (backup_cred(cifs_sb))
628 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
629
630 while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
631 (rc == 0) && !cfile->srch_inf.endOfSearch) {
632 cifs_dbg(FYI, "calling findnext2\n");
633 rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
634 search_flags,
635 &cfile->srch_inf);
636
637 if (cfile->srch_inf.last_entry)
638 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
639 if (rc)
640 return -ENOENT;
641 }
642 if (index_to_find < cfile->srch_inf.index_of_last_entry) {
643
644
645 int i;
646 char *cur_ent;
647 char *end_of_smb = cfile->srch_inf.ntwrk_buf_start +
648 server->ops->calc_smb_size(
649 cfile->srch_inf.ntwrk_buf_start);
650
651 cur_ent = cfile->srch_inf.srch_entries_start;
652 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
653 - cfile->srch_inf.entries_in_buffer;
654 pos_in_buf = index_to_find - first_entry_in_buffer;
655 cifs_dbg(FYI, "found entry - pos_in_buf %d\n", pos_in_buf);
656
657 for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
658
659 cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
660 cfile->srch_inf.info_level);
661 }
662 if ((cur_ent == NULL) && (i < pos_in_buf)) {
663
664 cifs_dbg(VFS, "reached end of buf searching for pos in buf %d index to find %lld rc %d\n",
665 pos_in_buf, index_to_find, rc);
666 }
667 rc = 0;
668 *current_entry = cur_ent;
669 } else {
670 cifs_dbg(FYI, "index not in buffer - could not findnext into it\n");
671 return 0;
672 }
673
674 if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
675 cifs_dbg(FYI, "can not return entries pos_in_buf beyond last\n");
676 *num_to_ret = 0;
677 } else
678 *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
679
680 return rc;
681}
682
683static int cifs_filldir(char *find_entry, struct file *file,
684 struct dir_context *ctx,
685 char *scratch_buf, unsigned int max_len)
686{
687 struct cifsFileInfo *file_info = file->private_data;
688 struct super_block *sb = file_inode(file)->i_sb;
689 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
690 struct cifs_dirent de = { NULL, };
691 struct cifs_fattr fattr;
692 struct qstr name;
693 int rc = 0;
694 ino_t ino;
695
696 rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
697 file_info->srch_inf.unicode);
698 if (rc)
699 return rc;
700
701 if (de.namelen > max_len) {
702 cifs_dbg(VFS, "bad search response length %zd past smb end\n",
703 de.namelen);
704 return -EINVAL;
705 }
706
707
708 if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
709 return 0;
710
711 if (file_info->srch_inf.unicode) {
712 struct nls_table *nlt = cifs_sb->local_nls;
713 int map_type;
714
715 map_type = cifs_remap(cifs_sb);
716 name.name = scratch_buf;
717 name.len =
718 cifs_from_utf16((char *)name.name, (__le16 *)de.name,
719 UNICODE_NAME_MAX,
720 min_t(size_t, de.namelen,
721 (size_t)max_len), nlt, map_type);
722 name.len -= nls_nullsize(nlt);
723 } else {
724 name.name = de.name;
725 name.len = de.namelen;
726 }
727
728 switch (file_info->srch_inf.info_level) {
729 case SMB_FIND_FILE_UNIX:
730 cifs_unix_basic_to_fattr(&fattr,
731 &((FILE_UNIX_INFO *)find_entry)->basic,
732 cifs_sb);
733 break;
734 case SMB_FIND_FILE_INFO_STANDARD:
735 cifs_std_info_to_fattr(&fattr,
736 (FIND_FILE_STANDARD_INFO *)find_entry,
737 cifs_sb);
738 break;
739 default:
740 cifs_dir_info_to_fattr(&fattr,
741 (FILE_DIRECTORY_INFO *)find_entry,
742 cifs_sb);
743 break;
744 }
745
746 if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
747 fattr.cf_uniqueid = de.ino;
748 } else {
749 fattr.cf_uniqueid = iunique(sb, ROOT_I);
750 cifs_autodisable_serverino(cifs_sb);
751 }
752
753 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
754 couldbe_mf_symlink(&fattr))
755
756
757
758
759
760 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
761
762 cifs_prime_dcache(file->f_path.dentry, &name, &fattr);
763
764 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
765 return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);
766}
767
768
769int cifs_readdir(struct file *file, struct dir_context *ctx)
770{
771 int rc = 0;
772 unsigned int xid;
773 int i;
774 struct cifs_tcon *tcon;
775 struct cifsFileInfo *cifsFile = NULL;
776 char *current_entry;
777 int num_to_fill = 0;
778 char *tmp_buf = NULL;
779 char *end_of_smb;
780 unsigned int max_len;
781
782 xid = get_xid();
783
784
785
786
787
788 if (file->private_data == NULL) {
789 rc = initiate_cifs_search(xid, file);
790 cifs_dbg(FYI, "initiate cifs search rc %d\n", rc);
791 if (rc)
792 goto rddir2_exit;
793 }
794
795 if (!dir_emit_dots(file, ctx))
796 goto rddir2_exit;
797
798
799
800
801
802
803 cifsFile = file->private_data;
804 if (cifsFile->srch_inf.endOfSearch) {
805 if (cifsFile->srch_inf.emptyDir) {
806 cifs_dbg(FYI, "End of search, empty dir\n");
807 rc = 0;
808 goto rddir2_exit;
809 }
810 }
811
812
813
814
815 tcon = tlink_tcon(cifsFile->tlink);
816 rc = find_cifs_entry(xid, tcon, ctx->pos, file, ¤t_entry,
817 &num_to_fill);
818 if (rc) {
819 cifs_dbg(FYI, "fce error %d\n", rc);
820 goto rddir2_exit;
821 } else if (current_entry != NULL) {
822 cifs_dbg(FYI, "entry %lld found\n", ctx->pos);
823 } else {
824 cifs_dbg(FYI, "could not find entry\n");
825 goto rddir2_exit;
826 }
827 cifs_dbg(FYI, "loop through %d times filling dir for net buf %p\n",
828 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
829 max_len = tcon->ses->server->ops->calc_smb_size(
830 cifsFile->srch_inf.ntwrk_buf_start);
831 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
832
833 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
834 if (tmp_buf == NULL) {
835 rc = -ENOMEM;
836 goto rddir2_exit;
837 }
838
839 for (i = 0; i < num_to_fill; i++) {
840 if (current_entry == NULL) {
841
842 cifs_dbg(VFS, "past SMB end, num to fill %d i %d\n",
843 num_to_fill, i);
844 break;
845 }
846
847
848
849
850 *tmp_buf = 0;
851 rc = cifs_filldir(current_entry, file, ctx,
852 tmp_buf, max_len);
853 if (rc) {
854 if (rc > 0)
855 rc = 0;
856 break;
857 }
858
859 ctx->pos++;
860 if (ctx->pos ==
861 cifsFile->srch_inf.index_of_last_entry) {
862 cifs_dbg(FYI, "last entry in buf at pos %lld %s\n",
863 ctx->pos, tmp_buf);
864 cifs_save_resume_key(current_entry, cifsFile);
865 break;
866 } else
867 current_entry =
868 nxt_dir_entry(current_entry, end_of_smb,
869 cifsFile->srch_inf.info_level);
870 }
871 kfree(tmp_buf);
872
873rddir2_exit:
874 free_xid(xid);
875 return rc;
876}
877