26 #include <linux/slab.h>
27 #include <linux/stat.h>
41 #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
43 #ifdef CONFIG_CIFS_DEBUG2
44 static void dump_cifs_file_struct(
struct file *
file,
char *
label)
51 cFYI(1,
"empty cifs private file data");
55 cFYI(1,
"invalid handle");
57 cFYI(1,
"end of search");
63 static inline void dump_cifs_file_struct(
struct file *
file,
char *
label)
82 if (parent->
d_op && parent->
d_op->d_hash)
83 parent->
d_op->d_hash(parent, parent->
d_inode, name);
92 if (inode && CIFS_I(inode)->uniqueid == fattr->
cf_uniqueid) {
102 dentry =
d_alloc(parent, name);
161 memset(fattr, 0,
sizeof(*fattr));
170 cifs_fill_common_info(fattr, cifs_sb);
174 cifs_std_info_to_fattr(
struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *
info,
179 memset(fattr, 0,
sizeof(*fattr));
181 info->LastAccessTime, offset);
183 info->LastWriteTime, offset);
185 info->LastWriteTime, offset);
191 cifs_fill_common_info(fattr, cifs_sb);
227 initiate_cifs_search(
const unsigned int xid,
struct file *
file)
231 char *full_path =
NULL;
241 return PTR_ERR(tlink);
244 if (cifsFile ==
NULL) {
249 cifsFile->
tlink = cifs_get_tlink(tlink);
250 tcon = tlink_tcon(tlink);
253 tcon = tlink_tcon(cifsFile->
tlink);
256 server = tcon->
ses->server;
258 if (!server->
ops->query_dir_first) {
264 cifsFile->
srch_inf.endOfSearch =
false;
267 if (full_path ==
NULL) {
272 cFYI(1,
"Full path: %s start at: %lld", full_path, file->
f_pos);
280 else if ((tcon->
ses->capabilities &
281 tcon->
ses->server->vals->cap_nt_find) == 0) {
293 rc = server->
ops->query_dir_first(xid, tcon, full_path, cifs_sb,
294 &cifsFile->
fid, search_flags,
314 static int cifs_unicode_bytelen(
const char *
str)
319 for (len = 0; len <=
PATH_MAX; len++) {
323 cFYI(1,
"Unicode string longer than PATH_MAX found");
327 static char *nxt_dir_entry(
char *old_entry,
char *end_of_smb,
int level)
330 FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
333 FIND_FILE_STANDARD_INFO *pfData;
334 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
336 new_entry = old_entry +
sizeof(FIND_FILE_STANDARD_INFO) +
337 pfData->FileNameLength;
339 new_entry = old_entry +
le32_to_cpu(pDirInfo->NextEntryOffset);
340 cFYI(1,
"new entry %p old entry %p", new_entry, old_entry);
342 if (new_entry >= end_of_smb) {
343 cERROR(1,
"search entry %p began after end of SMB %p old entry %p",
344 new_entry, end_of_smb, old_entry);
347 (new_entry +
sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
349 (new_entry +
sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
350 cERROR(1,
"search entry %p extends after end of SMB %p",
351 new_entry, end_of_smb);
365 static void cifs_fill_dirent_unix(
struct cifs_dirent *de,
366 const FILE_UNIX_INFO *info,
bool is_unicode)
368 de->
name = &info->FileName[0];
377 static void cifs_fill_dirent_dir(
struct cifs_dirent *de,
378 const FILE_DIRECTORY_INFO *info)
380 de->
name = &info->FileName[0];
385 static void cifs_fill_dirent_full(
struct cifs_dirent *de,
386 const FILE_FULL_DIRECTORY_INFO *info)
388 de->
name = &info->FileName[0];
393 static void cifs_fill_dirent_search(
struct cifs_dirent *de,
394 const SEARCH_ID_FULL_DIR_INFO *info)
396 de->
name = &info->FileName[0];
402 static void cifs_fill_dirent_both(
struct cifs_dirent *de,
403 const FILE_BOTH_DIRECTORY_INFO *info)
405 de->
name = &info->FileName[0];
410 static void cifs_fill_dirent_std(
struct cifs_dirent *de,
411 const FIND_FILE_STANDARD_INFO *info)
413 de->
name = &info->FileName[0];
415 de->
namelen = info->FileNameLength;
419 static int cifs_fill_dirent(
struct cifs_dirent *de,
const void *info,
420 u16 level,
bool is_unicode)
422 memset(de, 0,
sizeof(*de));
426 cifs_fill_dirent_unix(de, info, is_unicode);
429 cifs_fill_dirent_dir(de, info);
432 cifs_fill_dirent_full(de, info);
435 cifs_fill_dirent_search(de, info);
438 cifs_fill_dirent_both(de, info);
441 cifs_fill_dirent_std(de, info);
444 cFYI(1,
"Unknown findfirst level %d", level);
451 #define UNICODE_DOT cpu_to_le16(0x2e)
454 static int cifs_entry_is_dot(
struct cifs_dirent *de,
bool is_unicode)
475 if (de->
name[0] ==
'.')
478 if (de->
name[0] ==
'.' && de->
name[1] ==
'.')
488 static int is_dir_changed(
struct file *file)
490 struct inode *inode = file->
f_path.dentry->d_inode;
493 if (cifsInfo->
time == 0)
500 static int cifs_save_resume_key(
const char *current_entry,
506 rc = cifs_fill_dirent(&de, current_entry, file_info->
srch_inf.info_level,
524 find_cifs_entry(
const unsigned int xid,
struct cifs_tcon *tcon,
525 struct file *file,
char **current_entry,
int *num_to_ret)
530 loff_t first_entry_in_buffer;
531 loff_t index_to_find = file->
f_pos;
537 if (!server->
ops->query_dir_first || !server->
ops->query_dir_next)
540 if ((cfile ==
NULL) || (current_entry ==
NULL) || (num_to_ret ==
NULL))
543 *current_entry =
NULL;
544 first_entry_in_buffer = cfile->
srch_inf.index_of_last_entry -
555 dump_cifs_file_struct(file,
"In fce ");
556 if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
557 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
559 cFYI(1,
"search backing up - close and restart search");
564 if (server->
ops->close)
565 server->
ops->close(xid, tcon, &cfile->
fid);
568 if (cfile->
srch_inf.ntwrk_buf_start) {
569 cFYI(1,
"freeing SMB ff cache buf on search rewind");
578 rc = initiate_cifs_search(xid, file);
580 cFYI(1,
"error %d reinitiating a search on rewind",
586 cifs_save_resume_key(cfile->
srch_inf.last_entry, cfile);
593 while ((index_to_find >= cfile->
srch_inf.index_of_last_entry) &&
594 (rc == 0) && !cfile->
srch_inf.endOfSearch) {
595 cFYI(1,
"calling findnext2");
596 rc = server->
ops->query_dir_next(xid, tcon, &cfile->
fid,
601 cifs_save_resume_key(cfile->
srch_inf.last_entry, cfile);
605 if (index_to_find < cfile->srch_inf.index_of_last_entry) {
610 char *end_of_smb = cfile->
srch_inf.ntwrk_buf_start +
611 server->
ops->calc_smb_size(
614 cur_ent = cfile->
srch_inf.srch_entries_start;
615 first_entry_in_buffer = cfile->
srch_inf.index_of_last_entry
616 - cfile->
srch_inf.entries_in_buffer;
617 pos_in_buf = index_to_find - first_entry_in_buffer;
618 cFYI(1,
"found entry - pos_in_buf %d", pos_in_buf);
620 for (i = 0; (i < (pos_in_buf)) && (cur_ent !=
NULL); i++) {
622 cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
625 if ((cur_ent ==
NULL) && (i < pos_in_buf)) {
627 cERROR(1,
"reached end of buf searching for pos in buf"
628 " %d index to find %lld rc %d", pos_in_buf,
632 *current_entry = cur_ent;
634 cFYI(1,
"index not in buffer - could not findnext into it");
638 if (pos_in_buf >= cfile->
srch_inf.entries_in_buffer) {
639 cFYI(1,
"can not return entries pos_in_buf beyond last");
642 *num_to_ret = cfile->
srch_inf.entries_in_buffer - pos_in_buf;
647 static int cifs_filldir(
char *find_entry,
struct file *file,
filldir_t filldir,
648 void *
dirent,
char *scratch_buf,
unsigned int max_len)
655 struct dentry *dentry;
660 rc = cifs_fill_dirent(&de, find_entry, file_info->
srch_inf.info_level,
666 cERROR(1,
"bad search response length %zd past smb end",
672 if (cifs_entry_is_dot(&de, file_info->
srch_inf.unicode))
678 name.
name = scratch_buf;
683 (
size_t)max_len), nlt,
686 name.len -= nls_nullsize(nlt);
692 switch (file_info->
srch_inf.info_level) {
695 &((FILE_UNIX_INFO *)find_entry)->basic,
699 cifs_std_info_to_fattr(&fattr,
700 (FIND_FILE_STANDARD_INFO *)find_entry,
705 (FILE_DIRECTORY_INFO *)find_entry,
727 dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr);
729 rc = filldir(dirent, name.
name, name.len, file->
f_pos, ino,
746 char *tmp_buf =
NULL;
748 unsigned int max_len;
757 rc = initiate_cifs_search(xid, file);
758 cFYI(1,
"initiate cifs search rc %d", rc);
763 switch ((
int) file->
f_pos) {
765 if (filldir(direntry,
".", 1, file->
f_pos,
767 cERROR(1,
"Filldir for current dir failed");
773 if (filldir(direntry,
"..", 2, file->
f_pos,
775 cERROR(1,
"Filldir for parent dir failed");
792 if (cifsFile->
srch_inf.endOfSearch) {
794 cFYI(1,
"End of search, empty dir");
803 tcon = tlink_tcon(cifsFile->
tlink);
804 rc = find_cifs_entry(xid, tcon, file, ¤t_entry,
807 cFYI(1,
"fce error %d", rc);
809 }
else if (current_entry !=
NULL) {
810 cFYI(1,
"entry %lld found", file->
f_pos);
812 cFYI(1,
"could not find entry");
815 cFYI(1,
"loop through %d times filling dir for net buf %p",
816 num_to_fill, cifsFile->
srch_inf.ntwrk_buf_start);
817 max_len = tcon->
ses->server->ops->calc_smb_size(
818 cifsFile->
srch_inf.ntwrk_buf_start);
819 end_of_smb = cifsFile->
srch_inf.ntwrk_buf_start + max_len;
822 if (tmp_buf ==
NULL) {
827 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
828 if (current_entry ==
NULL) {
830 cERROR(1,
"past SMB end, num to fill %d i %d",
838 rc = cifs_filldir(current_entry, file, filldir,
839 direntry, tmp_buf, max_len);
847 cifsFile->
srch_inf.index_of_last_entry) {
848 cFYI(1,
"last entry in buf at pos %lld %s",
849 file->
f_pos, tmp_buf);
850 cifs_save_resume_key(current_entry, cifsFile);
854 nxt_dir_entry(current_entry, end_of_smb,