readdir.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /*
  2. * fs/cifs/readdir.c
  3. *
  4. * Directory search handling
  5. *
  6. * Copyright (C) International Business Machines Corp., 2004, 2008
  7. * Author(s): Steve French (sfrench@us.ibm.com)
  8. *
  9. * This library is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published
  11. * by the Free Software Foundation; either version 2.1 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  17. * the GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. */
  23. #include <linux/fs.h>
  24. #include <linux/pagemap.h>
  25. #include <linux/slab.h>
  26. #include <linux/stat.h>
  27. #include "cifspdu.h"
  28. #include "cifsglob.h"
  29. #include "cifsproto.h"
  30. #include "cifs_unicode.h"
  31. #include "cifs_debug.h"
  32. #include "cifs_fs_sb.h"
  33. #include "cifsfs.h"
  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. #ifdef CONFIG_CIFS_DEBUG2
  41. static void dump_cifs_file_struct(struct file *file, char *label)
  42. {
  43. struct cifsFileInfo *cf;
  44. if (file) {
  45. cf = file->private_data;
  46. if (cf == NULL) {
  47. cFYI(1, "empty cifs private file data");
  48. return;
  49. }
  50. if (cf->invalidHandle)
  51. cFYI(1, "invalid handle");
  52. if (cf->srch_inf.endOfSearch)
  53. cFYI(1, "end of search");
  54. if (cf->srch_inf.emptyDir)
  55. cFYI(1, "empty dir");
  56. }
  57. }
  58. #else
  59. static inline void dump_cifs_file_struct(struct file *file, char *label)
  60. {
  61. }
  62. #endif /* DEBUG2 */
  63. /*
  64. * Find the dentry that matches "name". If there isn't one, create one. If it's
  65. * a negative dentry or the uniqueid changed, then drop it and recreate it.
  66. */
  67. static struct dentry *
  68. cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
  69. struct cifs_fattr *fattr)
  70. {
  71. struct dentry *dentry, *alias;
  72. struct inode *inode;
  73. struct super_block *sb = parent->d_inode->i_sb;
  74. cFYI(1, "For %s", name->name);
  75. if (parent->d_op && parent->d_op->d_hash)
  76. parent->d_op->d_hash(parent, name);
  77. else
  78. name->hash = full_name_hash(name->name, name->len);
  79. dentry = d_lookup(parent, name);
  80. if (dentry) {
  81. /* FIXME: check for inode number changes? */
  82. if (dentry->d_inode != NULL)
  83. return dentry;
  84. d_drop(dentry);
  85. dput(dentry);
  86. }
  87. dentry = d_alloc(parent, name);
  88. if (dentry == NULL)
  89. return NULL;
  90. inode = cifs_iget(sb, fattr);
  91. if (!inode) {
  92. dput(dentry);
  93. return NULL;
  94. }
  95. if (CIFS_SB(sb)->tcon->nocase)
  96. dentry->d_op = &cifs_ci_dentry_ops;
  97. else
  98. dentry->d_op = &cifs_dentry_ops;
  99. alias = d_materialise_unique(dentry, inode);
  100. if (alias != NULL) {
  101. dput(dentry);
  102. if (IS_ERR(alias))
  103. return NULL;
  104. dentry = alias;
  105. }
  106. return dentry;
  107. }
  108. static void
  109. cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
  110. {
  111. fattr->cf_uid = cifs_sb->mnt_uid;
  112. fattr->cf_gid = cifs_sb->mnt_gid;
  113. if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
  114. fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
  115. fattr->cf_dtype = DT_DIR;
  116. } else {
  117. fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
  118. fattr->cf_dtype = DT_REG;
  119. }
  120. if (fattr->cf_cifsattrs & ATTR_READONLY)
  121. fattr->cf_mode &= ~S_IWUGO;
  122. if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
  123. fattr->cf_cifsattrs & ATTR_SYSTEM) {
  124. if (fattr->cf_eof == 0) {
  125. fattr->cf_mode &= ~S_IFMT;
  126. fattr->cf_mode |= S_IFIFO;
  127. fattr->cf_dtype = DT_FIFO;
  128. } else {
  129. /*
  130. * trying to get the type and mode via SFU can be slow,
  131. * so just call those regular files for now, and mark
  132. * for reval
  133. */
  134. fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
  135. }
  136. }
  137. }
  138. static void
  139. cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
  140. struct cifs_sb_info *cifs_sb)
  141. {
  142. memset(fattr, 0, sizeof(*fattr));
  143. fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
  144. fattr->cf_eof = le64_to_cpu(info->EndOfFile);
  145. fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
  146. fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
  147. fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
  148. fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
  149. cifs_fill_common_info(fattr, cifs_sb);
  150. }
  151. static void
  152. cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
  153. struct cifs_sb_info *cifs_sb)
  154. {
  155. int offset = cifs_sb->tcon->ses->server->timeAdj;
  156. memset(fattr, 0, sizeof(*fattr));
  157. fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
  158. info->LastAccessTime, offset);
  159. fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
  160. info->LastWriteTime, offset);
  161. fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
  162. info->LastWriteTime, offset);
  163. fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
  164. fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
  165. fattr->cf_eof = le32_to_cpu(info->DataSize);
  166. cifs_fill_common_info(fattr, cifs_sb);
  167. }
  168. /* BB eventually need to add the following helper function to
  169. resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
  170. we try to do FindFirst on (NTFS) directory symlinks */
  171. /*
  172. int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
  173. int xid)
  174. {
  175. __u16 fid;
  176. int len;
  177. int oplock = 0;
  178. int rc;
  179. struct cifsTconInfo *ptcon = cifs_sb->tcon;
  180. char *tmpbuffer;
  181. rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
  182. OPEN_REPARSE_POINT, &fid, &oplock, NULL,
  183. cifs_sb->local_nls,
  184. cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
  185. if (!rc) {
  186. tmpbuffer = kmalloc(maxpath);
  187. rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
  188. tmpbuffer,
  189. maxpath -1,
  190. fid,
  191. cifs_sb->local_nls);
  192. if (CIFSSMBClose(xid, ptcon, fid)) {
  193. cFYI(1, "Error closing temporary reparsepoint open");
  194. }
  195. }
  196. }
  197. */
  198. static int initiate_cifs_search(const int xid, struct file *file)
  199. {
  200. int rc = 0;
  201. char *full_path;
  202. struct cifsFileInfo *cifsFile;
  203. struct cifs_sb_info *cifs_sb;
  204. struct cifsTconInfo *pTcon;
  205. if (file->private_data == NULL) {
  206. file->private_data =
  207. kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
  208. }
  209. if (file->private_data == NULL)
  210. return -ENOMEM;
  211. cifsFile = file->private_data;
  212. cifsFile->invalidHandle = true;
  213. cifsFile->srch_inf.endOfSearch = false;
  214. cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
  215. if (cifs_sb == NULL)
  216. return -EINVAL;
  217. pTcon = cifs_sb->tcon;
  218. if (pTcon == NULL)
  219. return -EINVAL;
  220. full_path = build_path_from_dentry(file->f_path.dentry);
  221. if (full_path == NULL)
  222. return -ENOMEM;
  223. cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
  224. ffirst_retry:
  225. /* test for Unix extensions */
  226. /* but now check for them on the share/mount not on the SMB session */
  227. /* if (pTcon->ses->capabilities & CAP_UNIX) { */
  228. if (pTcon->unix_ext)
  229. cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
  230. else if ((pTcon->ses->capabilities &
  231. (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
  232. cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
  233. } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
  234. cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
  235. } else /* not srvinos - BB fixme add check for backlevel? */ {
  236. cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
  237. }
  238. rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
  239. &cifsFile->netfid, &cifsFile->srch_inf,
  240. cifs_sb->mnt_cifs_flags &
  241. CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
  242. if (rc == 0)
  243. cifsFile->invalidHandle = false;
  244. /* BB add following call to handle readdir on new NTFS symlink errors
  245. else if STATUS_STOPPED_ON_SYMLINK
  246. call get_symlink_reparse_path and retry with new path */
  247. else if ((rc == -EOPNOTSUPP) &&
  248. (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
  249. cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
  250. goto ffirst_retry;
  251. }
  252. kfree(full_path);
  253. return rc;
  254. }
  255. /* return length of unicode string in bytes */
  256. static int cifs_unicode_bytelen(char *str)
  257. {
  258. int len;
  259. __le16 *ustr = (__le16 *)str;
  260. for (len = 0; len <= PATH_MAX; len++) {
  261. if (ustr[len] == 0)
  262. return len << 1;
  263. }
  264. cFYI(1, "Unicode string longer than PATH_MAX found");
  265. return len << 1;
  266. }
  267. static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
  268. {
  269. char *new_entry;
  270. FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
  271. if (level == SMB_FIND_FILE_INFO_STANDARD) {
  272. FIND_FILE_STANDARD_INFO *pfData;
  273. pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
  274. new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
  275. pfData->FileNameLength;
  276. } else
  277. new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
  278. cFYI(1, "new entry %p old entry %p", new_entry, old_entry);
  279. /* validate that new_entry is not past end of SMB */
  280. if (new_entry >= end_of_smb) {
  281. cERROR(1, "search entry %p began after end of SMB %p old entry %p",
  282. new_entry, end_of_smb, old_entry);
  283. return NULL;
  284. } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
  285. (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
  286. || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
  287. (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
  288. cERROR(1, "search entry %p extends after end of SMB %p",
  289. new_entry, end_of_smb);
  290. return NULL;
  291. } else
  292. return new_entry;
  293. }
  294. #define UNICODE_DOT cpu_to_le16(0x2e)
  295. /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
  296. static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
  297. {
  298. int rc = 0;
  299. char *filename = NULL;
  300. int len = 0;
  301. if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
  302. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  303. filename = &pFindData->FileName[0];
  304. if (cfile->srch_inf.unicode) {
  305. len = cifs_unicode_bytelen(filename);
  306. } else {
  307. /* BB should we make this strnlen of PATH_MAX? */
  308. len = strnlen(filename, 5);
  309. }
  310. } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
  311. FILE_DIRECTORY_INFO *pFindData =
  312. (FILE_DIRECTORY_INFO *)current_entry;
  313. filename = &pFindData->FileName[0];
  314. len = le32_to_cpu(pFindData->FileNameLength);
  315. } else if (cfile->srch_inf.info_level ==
  316. SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  317. FILE_FULL_DIRECTORY_INFO *pFindData =
  318. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  319. filename = &pFindData->FileName[0];
  320. len = le32_to_cpu(pFindData->FileNameLength);
  321. } else if (cfile->srch_inf.info_level ==
  322. SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  323. SEARCH_ID_FULL_DIR_INFO *pFindData =
  324. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  325. filename = &pFindData->FileName[0];
  326. len = le32_to_cpu(pFindData->FileNameLength);
  327. } else if (cfile->srch_inf.info_level ==
  328. SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  329. FILE_BOTH_DIRECTORY_INFO *pFindData =
  330. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  331. filename = &pFindData->FileName[0];
  332. len = le32_to_cpu(pFindData->FileNameLength);
  333. } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
  334. FIND_FILE_STANDARD_INFO *pFindData =
  335. (FIND_FILE_STANDARD_INFO *)current_entry;
  336. filename = &pFindData->FileName[0];
  337. len = pFindData->FileNameLength;
  338. } else {
  339. cFYI(1, "Unknown findfirst level %d",
  340. cfile->srch_inf.info_level);
  341. }
  342. if (filename) {
  343. if (cfile->srch_inf.unicode) {
  344. __le16 *ufilename = (__le16 *)filename;
  345. if (len == 2) {
  346. /* check for . */
  347. if (ufilename[0] == UNICODE_DOT)
  348. rc = 1;
  349. } else if (len == 4) {
  350. /* check for .. */
  351. if ((ufilename[0] == UNICODE_DOT)
  352. && (ufilename[1] == UNICODE_DOT))
  353. rc = 2;
  354. }
  355. } else /* ASCII */ {
  356. if (len == 1) {
  357. if (filename[0] == '.')
  358. rc = 1;
  359. } else if (len == 2) {
  360. if ((filename[0] == '.') && (filename[1] == '.'))
  361. rc = 2;
  362. }
  363. }
  364. }
  365. return rc;
  366. }
  367. /* Check if directory that we are searching has changed so we can decide
  368. whether we can use the cached search results from the previous search */
  369. static int is_dir_changed(struct file *file)
  370. {
  371. struct inode *inode = file->f_path.dentry->d_inode;
  372. struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
  373. if (cifsInfo->time == 0)
  374. return 1; /* directory was changed, perhaps due to unlink */
  375. else
  376. return 0;
  377. }
  378. static int cifs_save_resume_key(const char *current_entry,
  379. struct cifsFileInfo *cifsFile)
  380. {
  381. int rc = 0;
  382. unsigned int len = 0;
  383. __u16 level;
  384. char *filename;
  385. if ((cifsFile == NULL) || (current_entry == NULL))
  386. return -EINVAL;
  387. level = cifsFile->srch_inf.info_level;
  388. if (level == SMB_FIND_FILE_UNIX) {
  389. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  390. filename = &pFindData->FileName[0];
  391. if (cifsFile->srch_inf.unicode) {
  392. len = cifs_unicode_bytelen(filename);
  393. } else {
  394. /* BB should we make this strnlen of PATH_MAX? */
  395. len = strnlen(filename, PATH_MAX);
  396. }
  397. cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
  398. } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
  399. FILE_DIRECTORY_INFO *pFindData =
  400. (FILE_DIRECTORY_INFO *)current_entry;
  401. filename = &pFindData->FileName[0];
  402. len = le32_to_cpu(pFindData->FileNameLength);
  403. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  404. } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  405. FILE_FULL_DIRECTORY_INFO *pFindData =
  406. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  407. filename = &pFindData->FileName[0];
  408. len = le32_to_cpu(pFindData->FileNameLength);
  409. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  410. } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  411. SEARCH_ID_FULL_DIR_INFO *pFindData =
  412. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  413. filename = &pFindData->FileName[0];
  414. len = le32_to_cpu(pFindData->FileNameLength);
  415. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  416. } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  417. FILE_BOTH_DIRECTORY_INFO *pFindData =
  418. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  419. filename = &pFindData->FileName[0];
  420. len = le32_to_cpu(pFindData->FileNameLength);
  421. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  422. } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
  423. FIND_FILE_STANDARD_INFO *pFindData =
  424. (FIND_FILE_STANDARD_INFO *)current_entry;
  425. filename = &pFindData->FileName[0];
  426. /* one byte length, no name conversion */
  427. len = (unsigned int)pFindData->FileNameLength;
  428. cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
  429. } else {
  430. cFYI(1, "Unknown findfirst level %d", level);
  431. return -EINVAL;
  432. }
  433. cifsFile->srch_inf.resume_name_len = len;
  434. cifsFile->srch_inf.presume_name = filename;
  435. return rc;
  436. }
  437. /* find the corresponding entry in the search */
  438. /* Note that the SMB server returns search entries for . and .. which
  439. complicates logic here if we choose to parse for them and we do not
  440. assume that they are located in the findfirst return buffer.*/
  441. /* We start counting in the buffer with entry 2 and increment for every
  442. entry (do not increment for . or .. entry) */
  443. static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
  444. struct file *file, char **ppCurrentEntry, int *num_to_ret)
  445. {
  446. int rc = 0;
  447. int pos_in_buf = 0;
  448. loff_t first_entry_in_buffer;
  449. loff_t index_to_find = file->f_pos;
  450. struct cifsFileInfo *cifsFile = file->private_data;
  451. /* check if index in the buffer */
  452. if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
  453. (num_to_ret == NULL))
  454. return -ENOENT;
  455. *ppCurrentEntry = NULL;
  456. first_entry_in_buffer =
  457. cifsFile->srch_inf.index_of_last_entry -
  458. cifsFile->srch_inf.entries_in_buffer;
  459. /* if first entry in buf is zero then is first buffer
  460. in search response data which means it is likely . and ..
  461. will be in this buffer, although some servers do not return
  462. . and .. for the root of a drive and for those we need
  463. to start two entries earlier */
  464. dump_cifs_file_struct(file, "In fce ");
  465. if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
  466. is_dir_changed(file)) ||
  467. (index_to_find < first_entry_in_buffer)) {
  468. /* close and restart search */
  469. cFYI(1, "search backing up - close and restart search");
  470. write_lock(&GlobalSMBSeslock);
  471. if (!cifsFile->srch_inf.endOfSearch &&
  472. !cifsFile->invalidHandle) {
  473. cifsFile->invalidHandle = true;
  474. write_unlock(&GlobalSMBSeslock);
  475. CIFSFindClose(xid, pTcon, cifsFile->netfid);
  476. } else
  477. write_unlock(&GlobalSMBSeslock);
  478. if (cifsFile->srch_inf.ntwrk_buf_start) {
  479. cFYI(1, "freeing SMB ff cache buf on search rewind");
  480. if (cifsFile->srch_inf.smallBuf)
  481. cifs_small_buf_release(cifsFile->srch_inf.
  482. ntwrk_buf_start);
  483. else
  484. cifs_buf_release(cifsFile->srch_inf.
  485. ntwrk_buf_start);
  486. cifsFile->srch_inf.ntwrk_buf_start = NULL;
  487. }
  488. rc = initiate_cifs_search(xid, file);
  489. if (rc) {
  490. cFYI(1, "error %d reinitiating a search on rewind",
  491. rc);
  492. return rc;
  493. }
  494. cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
  495. }
  496. while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
  497. (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
  498. cFYI(1, "calling findnext2");
  499. rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
  500. &cifsFile->srch_inf);
  501. cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
  502. if (rc)
  503. return -ENOENT;
  504. }
  505. if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
  506. /* we found the buffer that contains the entry */
  507. /* scan and find it */
  508. int i;
  509. char *current_entry;
  510. char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
  511. smbCalcSize((struct smb_hdr *)
  512. cifsFile->srch_inf.ntwrk_buf_start);
  513. current_entry = cifsFile->srch_inf.srch_entries_start;
  514. first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
  515. - cifsFile->srch_inf.entries_in_buffer;
  516. pos_in_buf = index_to_find - first_entry_in_buffer;
  517. cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
  518. for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
  519. /* go entry by entry figuring out which is first */
  520. current_entry = nxt_dir_entry(current_entry, end_of_smb,
  521. cifsFile->srch_inf.info_level);
  522. }
  523. if ((current_entry == NULL) && (i < pos_in_buf)) {
  524. /* BB fixme - check if we should flag this error */
  525. cERROR(1, "reached end of buf searching for pos in buf"
  526. " %d index to find %lld rc %d",
  527. pos_in_buf, index_to_find, rc);
  528. }
  529. rc = 0;
  530. *ppCurrentEntry = current_entry;
  531. } else {
  532. cFYI(1, "index not in buffer - could not findnext into it");
  533. return 0;
  534. }
  535. if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
  536. cFYI(1, "can not return entries pos_in_buf beyond last");
  537. *num_to_ret = 0;
  538. } else
  539. *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
  540. return rc;
  541. }
  542. /* inode num, inode type and filename returned */
  543. static int cifs_get_name_from_search_buf(struct qstr *pqst,
  544. char *current_entry, __u16 level, unsigned int unicode,
  545. struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
  546. {
  547. int rc = 0;
  548. unsigned int len = 0;
  549. char *filename;
  550. struct nls_table *nlt = cifs_sb->local_nls;
  551. *pinum = 0;
  552. if (level == SMB_FIND_FILE_UNIX) {
  553. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  554. filename = &pFindData->FileName[0];
  555. if (unicode) {
  556. len = cifs_unicode_bytelen(filename);
  557. } else {
  558. /* BB should we make this strnlen of PATH_MAX? */
  559. len = strnlen(filename, PATH_MAX);
  560. }
  561. *pinum = le64_to_cpu(pFindData->basic.UniqueId);
  562. } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
  563. FILE_DIRECTORY_INFO *pFindData =
  564. (FILE_DIRECTORY_INFO *)current_entry;
  565. filename = &pFindData->FileName[0];
  566. len = le32_to_cpu(pFindData->FileNameLength);
  567. } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  568. FILE_FULL_DIRECTORY_INFO *pFindData =
  569. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  570. filename = &pFindData->FileName[0];
  571. len = le32_to_cpu(pFindData->FileNameLength);
  572. } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  573. SEARCH_ID_FULL_DIR_INFO *pFindData =
  574. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  575. filename = &pFindData->FileName[0];
  576. len = le32_to_cpu(pFindData->FileNameLength);
  577. *pinum = le64_to_cpu(pFindData->UniqueId);
  578. } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  579. FILE_BOTH_DIRECTORY_INFO *pFindData =
  580. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  581. filename = &pFindData->FileName[0];
  582. len = le32_to_cpu(pFindData->FileNameLength);
  583. } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
  584. FIND_FILE_STANDARD_INFO *pFindData =
  585. (FIND_FILE_STANDARD_INFO *)current_entry;
  586. filename = &pFindData->FileName[0];
  587. /* one byte length, no name conversion */
  588. len = (unsigned int)pFindData->FileNameLength;
  589. } else {
  590. cFYI(1, "Unknown findfirst level %d", level);
  591. return -EINVAL;
  592. }
  593. if (len > max_len) {
  594. cERROR(1, "bad search response length %d past smb end", len);
  595. return -EINVAL;
  596. }
  597. if (unicode) {
  598. pqst->len = cifs_from_ucs2((char *) pqst->name,
  599. (__le16 *) filename,
  600. UNICODE_NAME_MAX,
  601. min(len, max_len), nlt,
  602. cifs_sb->mnt_cifs_flags &
  603. CIFS_MOUNT_MAP_SPECIAL_CHR);
  604. pqst->len -= nls_nullsize(nlt);
  605. } else {
  606. pqst->name = filename;
  607. pqst->len = len;
  608. }
  609. return rc;
  610. }
  611. static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
  612. void *direntry, char *scratch_buf, unsigned int max_len)
  613. {
  614. int rc = 0;
  615. struct qstr qstring;
  616. struct cifsFileInfo *pCifsF;
  617. u64 inum;
  618. ino_t ino;
  619. struct super_block *sb;
  620. struct cifs_sb_info *cifs_sb;
  621. struct dentry *tmp_dentry;
  622. struct cifs_fattr fattr;
  623. /* get filename and len into qstring */
  624. /* get dentry */
  625. /* decide whether to create and populate ionde */
  626. if ((direntry == NULL) || (file == NULL))
  627. return -EINVAL;
  628. pCifsF = file->private_data;
  629. if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
  630. return -ENOENT;
  631. rc = cifs_entry_is_dot(pfindEntry, pCifsF);
  632. /* skip . and .. since we added them first */
  633. if (rc != 0)
  634. return 0;
  635. sb = file->f_path.dentry->d_sb;
  636. cifs_sb = CIFS_SB(sb);
  637. qstring.name = scratch_buf;
  638. rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
  639. pCifsF->srch_inf.info_level,
  640. pCifsF->srch_inf.unicode, cifs_sb,
  641. max_len, &inum /* returned */);
  642. if (rc)
  643. return rc;
  644. if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
  645. cifs_unix_basic_to_fattr(&fattr,
  646. &((FILE_UNIX_INFO *) pfindEntry)->basic,
  647. cifs_sb);
  648. else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
  649. cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
  650. pfindEntry, cifs_sb);
  651. else
  652. cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
  653. pfindEntry, cifs_sb);
  654. if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
  655. fattr.cf_uniqueid = inum;
  656. } else {
  657. fattr.cf_uniqueid = iunique(sb, ROOT_I);
  658. cifs_autodisable_serverino(cifs_sb);
  659. }
  660. ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
  661. tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
  662. rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
  663. ino, fattr.cf_dtype);
  664. /*
  665. * we can not return filldir errors to the caller since they are
  666. * "normal" when the stat blocksize is too small - we return remapped
  667. * error instead
  668. *
  669. * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
  670. * case already. Why should we be clobbering other errors from it?
  671. */
  672. if (rc) {
  673. cFYI(1, "filldir rc = %d", rc);
  674. rc = -EOVERFLOW;
  675. }
  676. dput(tmp_dentry);
  677. return rc;
  678. }
  679. int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
  680. {
  681. int rc = 0;
  682. int xid, i;
  683. struct cifs_sb_info *cifs_sb;
  684. struct cifsTconInfo *pTcon;
  685. struct cifsFileInfo *cifsFile = NULL;
  686. char *current_entry;
  687. int num_to_fill = 0;
  688. char *tmp_buf = NULL;
  689. char *end_of_smb;
  690. unsigned int max_len;
  691. xid = GetXid();
  692. cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
  693. pTcon = cifs_sb->tcon;
  694. if (pTcon == NULL)
  695. return -EINVAL;
  696. switch ((int) file->f_pos) {
  697. case 0:
  698. if (filldir(direntry, ".", 1, file->f_pos,
  699. file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
  700. cERROR(1, "Filldir for current dir failed");
  701. rc = -ENOMEM;
  702. break;
  703. }
  704. file->f_pos++;
  705. case 1:
  706. if (filldir(direntry, "..", 2, file->f_pos,
  707. file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
  708. cERROR(1, "Filldir for parent dir failed");
  709. rc = -ENOMEM;
  710. break;
  711. }
  712. file->f_pos++;
  713. default:
  714. /* 1) If search is active,
  715. is in current search buffer?
  716. if it before then restart search
  717. if after then keep searching till find it */
  718. if (file->private_data == NULL) {
  719. rc = initiate_cifs_search(xid, file);
  720. cFYI(1, "initiate cifs search rc %d", rc);
  721. if (rc) {
  722. FreeXid(xid);
  723. return rc;
  724. }
  725. }
  726. if (file->private_data == NULL) {
  727. rc = -EINVAL;
  728. FreeXid(xid);
  729. return rc;
  730. }
  731. cifsFile = file->private_data;
  732. if (cifsFile->srch_inf.endOfSearch) {
  733. if (cifsFile->srch_inf.emptyDir) {
  734. cFYI(1, "End of search, empty dir");
  735. rc = 0;
  736. break;
  737. }
  738. } /* else {
  739. cifsFile->invalidHandle = true;
  740. CIFSFindClose(xid, pTcon, cifsFile->netfid);
  741. } */
  742. rc = find_cifs_entry(xid, pTcon, file,
  743. &current_entry, &num_to_fill);
  744. if (rc) {
  745. cFYI(1, "fce error %d", rc);
  746. goto rddir2_exit;
  747. } else if (current_entry != NULL) {
  748. cFYI(1, "entry %lld found", file->f_pos);
  749. } else {
  750. cFYI(1, "could not find entry");
  751. goto rddir2_exit;
  752. }
  753. cFYI(1, "loop through %d times filling dir for net buf %p",
  754. num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
  755. max_len = smbCalcSize((struct smb_hdr *)
  756. cifsFile->srch_inf.ntwrk_buf_start);
  757. end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
  758. tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
  759. if (tmp_buf == NULL) {
  760. rc = -ENOMEM;
  761. break;
  762. }
  763. for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
  764. if (current_entry == NULL) {
  765. /* evaluate whether this case is an error */
  766. cERROR(1, "past SMB end, num to fill %d i %d",
  767. num_to_fill, i);
  768. break;
  769. }
  770. /* if buggy server returns . and .. late do
  771. we want to check for that here? */
  772. rc = cifs_filldir(current_entry, file,
  773. filldir, direntry, tmp_buf, max_len);
  774. if (rc == -EOVERFLOW) {
  775. rc = 0;
  776. break;
  777. }
  778. file->f_pos++;
  779. if (file->f_pos ==
  780. cifsFile->srch_inf.index_of_last_entry) {
  781. cFYI(1, "last entry in buf at pos %lld %s",
  782. file->f_pos, tmp_buf);
  783. cifs_save_resume_key(current_entry, cifsFile);
  784. break;
  785. } else
  786. current_entry =
  787. nxt_dir_entry(current_entry, end_of_smb,
  788. cifsFile->srch_inf.info_level);
  789. }
  790. kfree(tmp_buf);
  791. break;
  792. } /* end switch */
  793. rddir2_exit:
  794. FreeXid(xid);
  795. return rc;
  796. }