readdir.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  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,
  282. ("search entry %p began after end of SMB %p old entry %p",
  283. new_entry, end_of_smb, old_entry));
  284. return NULL;
  285. } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
  286. (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
  287. || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
  288. (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
  289. cERROR(1, ("search entry %p extends after end of SMB %p",
  290. new_entry, end_of_smb));
  291. return NULL;
  292. } else
  293. return new_entry;
  294. }
  295. #define UNICODE_DOT cpu_to_le16(0x2e)
  296. /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
  297. static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
  298. {
  299. int rc = 0;
  300. char *filename = NULL;
  301. int len = 0;
  302. if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
  303. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  304. filename = &pFindData->FileName[0];
  305. if (cfile->srch_inf.unicode) {
  306. len = cifs_unicode_bytelen(filename);
  307. } else {
  308. /* BB should we make this strnlen of PATH_MAX? */
  309. len = strnlen(filename, 5);
  310. }
  311. } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
  312. FILE_DIRECTORY_INFO *pFindData =
  313. (FILE_DIRECTORY_INFO *)current_entry;
  314. filename = &pFindData->FileName[0];
  315. len = le32_to_cpu(pFindData->FileNameLength);
  316. } else if (cfile->srch_inf.info_level ==
  317. SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  318. FILE_FULL_DIRECTORY_INFO *pFindData =
  319. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  320. filename = &pFindData->FileName[0];
  321. len = le32_to_cpu(pFindData->FileNameLength);
  322. } else if (cfile->srch_inf.info_level ==
  323. SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  324. SEARCH_ID_FULL_DIR_INFO *pFindData =
  325. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  326. filename = &pFindData->FileName[0];
  327. len = le32_to_cpu(pFindData->FileNameLength);
  328. } else if (cfile->srch_inf.info_level ==
  329. SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  330. FILE_BOTH_DIRECTORY_INFO *pFindData =
  331. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  332. filename = &pFindData->FileName[0];
  333. len = le32_to_cpu(pFindData->FileNameLength);
  334. } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
  335. FIND_FILE_STANDARD_INFO *pFindData =
  336. (FIND_FILE_STANDARD_INFO *)current_entry;
  337. filename = &pFindData->FileName[0];
  338. len = pFindData->FileNameLength;
  339. } else {
  340. cFYI(1, ("Unknown findfirst level %d",
  341. cfile->srch_inf.info_level));
  342. }
  343. if (filename) {
  344. if (cfile->srch_inf.unicode) {
  345. __le16 *ufilename = (__le16 *)filename;
  346. if (len == 2) {
  347. /* check for . */
  348. if (ufilename[0] == UNICODE_DOT)
  349. rc = 1;
  350. } else if (len == 4) {
  351. /* check for .. */
  352. if ((ufilename[0] == UNICODE_DOT)
  353. && (ufilename[1] == UNICODE_DOT))
  354. rc = 2;
  355. }
  356. } else /* ASCII */ {
  357. if (len == 1) {
  358. if (filename[0] == '.')
  359. rc = 1;
  360. } else if (len == 2) {
  361. if ((filename[0] == '.') && (filename[1] == '.'))
  362. rc = 2;
  363. }
  364. }
  365. }
  366. return rc;
  367. }
  368. /* Check if directory that we are searching has changed so we can decide
  369. whether we can use the cached search results from the previous search */
  370. static int is_dir_changed(struct file *file)
  371. {
  372. struct inode *inode = file->f_path.dentry->d_inode;
  373. struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
  374. if (cifsInfo->time == 0)
  375. return 1; /* directory was changed, perhaps due to unlink */
  376. else
  377. return 0;
  378. }
  379. static int cifs_save_resume_key(const char *current_entry,
  380. struct cifsFileInfo *cifsFile)
  381. {
  382. int rc = 0;
  383. unsigned int len = 0;
  384. __u16 level;
  385. char *filename;
  386. if ((cifsFile == NULL) || (current_entry == NULL))
  387. return -EINVAL;
  388. level = cifsFile->srch_inf.info_level;
  389. if (level == SMB_FIND_FILE_UNIX) {
  390. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  391. filename = &pFindData->FileName[0];
  392. if (cifsFile->srch_inf.unicode) {
  393. len = cifs_unicode_bytelen(filename);
  394. } else {
  395. /* BB should we make this strnlen of PATH_MAX? */
  396. len = strnlen(filename, PATH_MAX);
  397. }
  398. cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
  399. } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
  400. FILE_DIRECTORY_INFO *pFindData =
  401. (FILE_DIRECTORY_INFO *)current_entry;
  402. filename = &pFindData->FileName[0];
  403. len = le32_to_cpu(pFindData->FileNameLength);
  404. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  405. } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  406. FILE_FULL_DIRECTORY_INFO *pFindData =
  407. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  408. filename = &pFindData->FileName[0];
  409. len = le32_to_cpu(pFindData->FileNameLength);
  410. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  411. } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  412. SEARCH_ID_FULL_DIR_INFO *pFindData =
  413. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  414. filename = &pFindData->FileName[0];
  415. len = le32_to_cpu(pFindData->FileNameLength);
  416. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  417. } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  418. FILE_BOTH_DIRECTORY_INFO *pFindData =
  419. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  420. filename = &pFindData->FileName[0];
  421. len = le32_to_cpu(pFindData->FileNameLength);
  422. cifsFile->srch_inf.resume_key = pFindData->FileIndex;
  423. } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
  424. FIND_FILE_STANDARD_INFO *pFindData =
  425. (FIND_FILE_STANDARD_INFO *)current_entry;
  426. filename = &pFindData->FileName[0];
  427. /* one byte length, no name conversion */
  428. len = (unsigned int)pFindData->FileNameLength;
  429. cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
  430. } else {
  431. cFYI(1, ("Unknown findfirst level %d", level));
  432. return -EINVAL;
  433. }
  434. cifsFile->srch_inf.resume_name_len = len;
  435. cifsFile->srch_inf.presume_name = filename;
  436. return rc;
  437. }
  438. /* find the corresponding entry in the search */
  439. /* Note that the SMB server returns search entries for . and .. which
  440. complicates logic here if we choose to parse for them and we do not
  441. assume that they are located in the findfirst return buffer.*/
  442. /* We start counting in the buffer with entry 2 and increment for every
  443. entry (do not increment for . or .. entry) */
  444. static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
  445. struct file *file, char **ppCurrentEntry, int *num_to_ret)
  446. {
  447. int rc = 0;
  448. int pos_in_buf = 0;
  449. loff_t first_entry_in_buffer;
  450. loff_t index_to_find = file->f_pos;
  451. struct cifsFileInfo *cifsFile = file->private_data;
  452. /* check if index in the buffer */
  453. if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
  454. (num_to_ret == NULL))
  455. return -ENOENT;
  456. *ppCurrentEntry = NULL;
  457. first_entry_in_buffer =
  458. cifsFile->srch_inf.index_of_last_entry -
  459. cifsFile->srch_inf.entries_in_buffer;
  460. /* if first entry in buf is zero then is first buffer
  461. in search response data which means it is likely . and ..
  462. will be in this buffer, although some servers do not return
  463. . and .. for the root of a drive and for those we need
  464. to start two entries earlier */
  465. dump_cifs_file_struct(file, "In fce ");
  466. if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
  467. is_dir_changed(file)) ||
  468. (index_to_find < first_entry_in_buffer)) {
  469. /* close and restart search */
  470. cFYI(1, ("search backing up - close and restart search"));
  471. write_lock(&GlobalSMBSeslock);
  472. if (!cifsFile->srch_inf.endOfSearch &&
  473. !cifsFile->invalidHandle) {
  474. cifsFile->invalidHandle = true;
  475. write_unlock(&GlobalSMBSeslock);
  476. CIFSFindClose(xid, pTcon, cifsFile->netfid);
  477. } else
  478. write_unlock(&GlobalSMBSeslock);
  479. if (cifsFile->srch_inf.ntwrk_buf_start) {
  480. cFYI(1, ("freeing SMB ff cache buf on search rewind"));
  481. if (cifsFile->srch_inf.smallBuf)
  482. cifs_small_buf_release(cifsFile->srch_inf.
  483. ntwrk_buf_start);
  484. else
  485. cifs_buf_release(cifsFile->srch_inf.
  486. ntwrk_buf_start);
  487. cifsFile->srch_inf.ntwrk_buf_start = NULL;
  488. }
  489. rc = initiate_cifs_search(xid, file);
  490. if (rc) {
  491. cFYI(1, ("error %d reinitiating a search on rewind",
  492. rc));
  493. return rc;
  494. }
  495. cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
  496. }
  497. while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
  498. (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
  499. cFYI(1, ("calling findnext2"));
  500. rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
  501. &cifsFile->srch_inf);
  502. cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
  503. if (rc)
  504. return -ENOENT;
  505. }
  506. if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
  507. /* we found the buffer that contains the entry */
  508. /* scan and find it */
  509. int i;
  510. char *current_entry;
  511. char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
  512. smbCalcSize((struct smb_hdr *)
  513. cifsFile->srch_inf.ntwrk_buf_start);
  514. current_entry = cifsFile->srch_inf.srch_entries_start;
  515. first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
  516. - cifsFile->srch_inf.entries_in_buffer;
  517. pos_in_buf = index_to_find - first_entry_in_buffer;
  518. cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf));
  519. for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
  520. /* go entry by entry figuring out which is first */
  521. current_entry = nxt_dir_entry(current_entry, end_of_smb,
  522. cifsFile->srch_inf.info_level);
  523. }
  524. if ((current_entry == NULL) && (i < pos_in_buf)) {
  525. /* BB fixme - check if we should flag this error */
  526. cERROR(1, ("reached end of buf searching for pos in buf"
  527. " %d index to find %lld rc %d",
  528. pos_in_buf, index_to_find, rc));
  529. }
  530. rc = 0;
  531. *ppCurrentEntry = current_entry;
  532. } else {
  533. cFYI(1, ("index not in buffer - could not findnext into it"));
  534. return 0;
  535. }
  536. if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
  537. cFYI(1, ("can not return entries pos_in_buf beyond last"));
  538. *num_to_ret = 0;
  539. } else
  540. *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
  541. return rc;
  542. }
  543. /* inode num, inode type and filename returned */
  544. static int cifs_get_name_from_search_buf(struct qstr *pqst,
  545. char *current_entry, __u16 level, unsigned int unicode,
  546. struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
  547. {
  548. int rc = 0;
  549. unsigned int len = 0;
  550. char *filename;
  551. struct nls_table *nlt = cifs_sb->local_nls;
  552. *pinum = 0;
  553. if (level == SMB_FIND_FILE_UNIX) {
  554. FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
  555. filename = &pFindData->FileName[0];
  556. if (unicode) {
  557. len = cifs_unicode_bytelen(filename);
  558. } else {
  559. /* BB should we make this strnlen of PATH_MAX? */
  560. len = strnlen(filename, PATH_MAX);
  561. }
  562. *pinum = le64_to_cpu(pFindData->basic.UniqueId);
  563. } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
  564. FILE_DIRECTORY_INFO *pFindData =
  565. (FILE_DIRECTORY_INFO *)current_entry;
  566. filename = &pFindData->FileName[0];
  567. len = le32_to_cpu(pFindData->FileNameLength);
  568. } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
  569. FILE_FULL_DIRECTORY_INFO *pFindData =
  570. (FILE_FULL_DIRECTORY_INFO *)current_entry;
  571. filename = &pFindData->FileName[0];
  572. len = le32_to_cpu(pFindData->FileNameLength);
  573. } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
  574. SEARCH_ID_FULL_DIR_INFO *pFindData =
  575. (SEARCH_ID_FULL_DIR_INFO *)current_entry;
  576. filename = &pFindData->FileName[0];
  577. len = le32_to_cpu(pFindData->FileNameLength);
  578. *pinum = le64_to_cpu(pFindData->UniqueId);
  579. } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
  580. FILE_BOTH_DIRECTORY_INFO *pFindData =
  581. (FILE_BOTH_DIRECTORY_INFO *)current_entry;
  582. filename = &pFindData->FileName[0];
  583. len = le32_to_cpu(pFindData->FileNameLength);
  584. } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
  585. FIND_FILE_STANDARD_INFO *pFindData =
  586. (FIND_FILE_STANDARD_INFO *)current_entry;
  587. filename = &pFindData->FileName[0];
  588. /* one byte length, no name conversion */
  589. len = (unsigned int)pFindData->FileNameLength;
  590. } else {
  591. cFYI(1, ("Unknown findfirst level %d", level));
  592. return -EINVAL;
  593. }
  594. if (len > max_len) {
  595. cERROR(1, ("bad search response length %d past smb end", len));
  596. return -EINVAL;
  597. }
  598. if (unicode) {
  599. pqst->len = cifs_from_ucs2((char *) pqst->name,
  600. (__le16 *) filename,
  601. UNICODE_NAME_MAX,
  602. min(len, max_len), nlt,
  603. cifs_sb->mnt_cifs_flags &
  604. CIFS_MOUNT_MAP_SPECIAL_CHR);
  605. pqst->len -= nls_nullsize(nlt);
  606. } else {
  607. pqst->name = filename;
  608. pqst->len = len;
  609. }
  610. return rc;
  611. }
  612. static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
  613. void *direntry, char *scratch_buf, unsigned int max_len)
  614. {
  615. int rc = 0;
  616. struct qstr qstring;
  617. struct cifsFileInfo *pCifsF;
  618. u64 inum;
  619. ino_t ino;
  620. struct super_block *sb;
  621. struct cifs_sb_info *cifs_sb;
  622. struct dentry *tmp_dentry;
  623. struct cifs_fattr fattr;
  624. /* get filename and len into qstring */
  625. /* get dentry */
  626. /* decide whether to create and populate ionde */
  627. if ((direntry == NULL) || (file == NULL))
  628. return -EINVAL;
  629. pCifsF = file->private_data;
  630. if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
  631. return -ENOENT;
  632. rc = cifs_entry_is_dot(pfindEntry, pCifsF);
  633. /* skip . and .. since we added them first */
  634. if (rc != 0)
  635. return 0;
  636. sb = file->f_path.dentry->d_sb;
  637. cifs_sb = CIFS_SB(sb);
  638. qstring.name = scratch_buf;
  639. rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
  640. pCifsF->srch_inf.info_level,
  641. pCifsF->srch_inf.unicode, cifs_sb,
  642. max_len, &inum /* returned */);
  643. if (rc)
  644. return rc;
  645. if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
  646. cifs_unix_basic_to_fattr(&fattr,
  647. &((FILE_UNIX_INFO *) pfindEntry)->basic,
  648. cifs_sb);
  649. else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
  650. cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
  651. pfindEntry, cifs_sb);
  652. else
  653. cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
  654. pfindEntry, cifs_sb);
  655. if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
  656. fattr.cf_uniqueid = inum;
  657. } else {
  658. fattr.cf_uniqueid = iunique(sb, ROOT_I);
  659. cifs_autodisable_serverino(cifs_sb);
  660. }
  661. ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
  662. tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
  663. rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
  664. ino, fattr.cf_dtype);
  665. /*
  666. * we can not return filldir errors to the caller since they are
  667. * "normal" when the stat blocksize is too small - we return remapped
  668. * error instead
  669. *
  670. * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
  671. * case already. Why should we be clobbering other errors from it?
  672. */
  673. if (rc) {
  674. cFYI(1, ("filldir rc = %d", rc));
  675. rc = -EOVERFLOW;
  676. }
  677. dput(tmp_dentry);
  678. return rc;
  679. }
  680. int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
  681. {
  682. int rc = 0;
  683. int xid, i;
  684. struct cifs_sb_info *cifs_sb;
  685. struct cifsTconInfo *pTcon;
  686. struct cifsFileInfo *cifsFile = NULL;
  687. char *current_entry;
  688. int num_to_fill = 0;
  689. char *tmp_buf = NULL;
  690. char *end_of_smb;
  691. unsigned int max_len;
  692. xid = GetXid();
  693. cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
  694. pTcon = cifs_sb->tcon;
  695. if (pTcon == NULL)
  696. return -EINVAL;
  697. switch ((int) file->f_pos) {
  698. case 0:
  699. if (filldir(direntry, ".", 1, file->f_pos,
  700. file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
  701. cERROR(1, ("Filldir for current dir failed"));
  702. rc = -ENOMEM;
  703. break;
  704. }
  705. file->f_pos++;
  706. case 1:
  707. if (filldir(direntry, "..", 2, file->f_pos,
  708. file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
  709. cERROR(1, ("Filldir for parent dir failed"));
  710. rc = -ENOMEM;
  711. break;
  712. }
  713. file->f_pos++;
  714. default:
  715. /* 1) If search is active,
  716. is in current search buffer?
  717. if it before then restart search
  718. if after then keep searching till find it */
  719. if (file->private_data == NULL) {
  720. rc = initiate_cifs_search(xid, file);
  721. cFYI(1, ("initiate cifs search rc %d", rc));
  722. if (rc) {
  723. FreeXid(xid);
  724. return rc;
  725. }
  726. }
  727. if (file->private_data == NULL) {
  728. rc = -EINVAL;
  729. FreeXid(xid);
  730. return rc;
  731. }
  732. cifsFile = file->private_data;
  733. if (cifsFile->srch_inf.endOfSearch) {
  734. if (cifsFile->srch_inf.emptyDir) {
  735. cFYI(1, ("End of search, empty dir"));
  736. rc = 0;
  737. break;
  738. }
  739. } /* else {
  740. cifsFile->invalidHandle = true;
  741. CIFSFindClose(xid, pTcon, cifsFile->netfid);
  742. } */
  743. rc = find_cifs_entry(xid, pTcon, file,
  744. &current_entry, &num_to_fill);
  745. if (rc) {
  746. cFYI(1, ("fce error %d", rc));
  747. goto rddir2_exit;
  748. } else if (current_entry != NULL) {
  749. cFYI(1, ("entry %lld found", file->f_pos));
  750. } else {
  751. cFYI(1, ("could not find entry"));
  752. goto rddir2_exit;
  753. }
  754. cFYI(1, ("loop through %d times filling dir for net buf %p",
  755. num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
  756. max_len = smbCalcSize((struct smb_hdr *)
  757. cifsFile->srch_inf.ntwrk_buf_start);
  758. end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
  759. tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
  760. for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
  761. if (current_entry == NULL) {
  762. /* evaluate whether this case is an error */
  763. cERROR(1, ("past SMB end, num to fill %d i %d",
  764. num_to_fill, i));
  765. break;
  766. }
  767. /* if buggy server returns . and .. late do
  768. we want to check for that here? */
  769. rc = cifs_filldir(current_entry, file,
  770. filldir, direntry, tmp_buf, max_len);
  771. if (rc == -EOVERFLOW) {
  772. rc = 0;
  773. break;
  774. }
  775. file->f_pos++;
  776. if (file->f_pos ==
  777. cifsFile->srch_inf.index_of_last_entry) {
  778. cFYI(1, ("last entry in buf at pos %lld %s",
  779. file->f_pos, tmp_buf));
  780. cifs_save_resume_key(current_entry, cifsFile);
  781. break;
  782. } else
  783. current_entry =
  784. nxt_dir_entry(current_entry, end_of_smb,
  785. cifsFile->srch_inf.info_level);
  786. }
  787. kfree(tmp_buf);
  788. break;
  789. } /* end switch */
  790. rddir2_exit:
  791. FreeXid(xid);
  792. return rc;
  793. }