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