]> bbs.cooldavid.org Git - net-next-2.6.git/blame - fs/cifs/readdir.c
[CIFS] update cifs version number
[net-next-2.6.git] / fs / cifs / readdir.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/readdir.c
3 *
4 * Directory search handling
6dc0f87e 5 *
ad7a2926 6 * Copyright (C) International Business Machines Corp., 2004, 2008
1da177e4
LT
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>
273d81d6 24#include <linux/pagemap.h>
1da177e4 25#include <linux/stat.h>
1da177e4
LT
26#include "cifspdu.h"
27#include "cifsglob.h"
28#include "cifsproto.h"
29#include "cifs_unicode.h"
30#include "cifs_debug.h"
31#include "cifs_fs_sb.h"
32#include "cifsfs.h"
33
f5884166
JL
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
3979877e
SF
41#ifdef CONFIG_CIFS_DEBUG2
42static void dump_cifs_file_struct(struct file *file, char *label)
1da177e4 43{
6dc0f87e 44 struct cifsFileInfo *cf;
1da177e4 45
4523cc30 46 if (file) {
1da177e4 47 cf = file->private_data;
4523cc30 48 if (cf == NULL) {
6dc0f87e 49 cFYI(1, ("empty cifs private file data"));
1da177e4
LT
50 return;
51 }
ad7a2926 52 if (cf->invalidHandle)
6dc0f87e 53 cFYI(1, ("invalid handle"));
ad7a2926 54 if (cf->srch_inf.endOfSearch)
6dc0f87e 55 cFYI(1, ("end of search"));
ad7a2926 56 if (cf->srch_inf.emptyDir)
6dc0f87e 57 cFYI(1, ("empty dir"));
1da177e4 58 }
3979877e 59}
90c81e0b
SF
60#else
61static inline void dump_cifs_file_struct(struct file *file, char *label)
62{
63}
3979877e 64#endif /* DEBUG2 */
1da177e4 65
cc0bad75
JL
66/*
67 * Find the dentry that matches "name". If there isn't one, create one. If it's
68 * a negative dentry or the uniqueid changed, then drop it and recreate it.
69 */
70static struct dentry *
71cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
72 struct cifs_fattr *fattr)
73{
74 struct dentry *dentry, *alias;
75 struct inode *inode;
76 struct super_block *sb = parent->d_inode->i_sb;
77
78 cFYI(1, ("For %s", name->name));
79
80 dentry = d_lookup(parent, name);
81 if (dentry) {
82 /* FIXME: check for inode number changes? */
83 if (dentry->d_inode != NULL)
84 return dentry;
85 d_drop(dentry);
86 dput(dentry);
87 }
88
89 dentry = d_alloc(parent, name);
90 if (dentry == NULL)
91 return NULL;
92
93 inode = cifs_iget(sb, fattr);
94 if (!inode) {
95 dput(dentry);
96 return NULL;
97 }
98
99 if (CIFS_SB(sb)->tcon->nocase)
100 dentry->d_op = &cifs_ci_dentry_ops;
101 else
102 dentry->d_op = &cifs_dentry_ops;
103
104 alias = d_materialise_unique(dentry, inode);
105 if (alias != NULL) {
106 dput(dentry);
107 if (IS_ERR(alias))
108 return NULL;
109 dentry = alias;
110 }
111
112 return dentry;
113}
114
132ac7b7 115/* Returns 1 if new inode created, 2 if both dentry and inode were */
1da177e4 116/* Might check in the future if inode number changed so we can rehash inode */
132ac7b7
JL
117static int
118construct_dentry(struct qstr *qstring, struct file *file,
119 struct inode **ptmp_inode, struct dentry **pnew_dentry,
950ec528 120 __u64 *inum)
1da177e4 121{
132ac7b7
JL
122 struct dentry *tmp_dentry = NULL;
123 struct super_block *sb = file->f_path.dentry->d_sb;
1da177e4
LT
124 int rc = 0;
125
966ca923 126 cFYI(1, ("For %s", qstring->name));
1da177e4 127
e6a00296 128 tmp_dentry = d_lookup(file->f_path.dentry, qstring);
1da177e4 129 if (tmp_dentry) {
132ac7b7
JL
130 /* BB: overwrite old name? i.e. tmp_dentry->d_name and
131 * tmp_dentry->d_name.len??
132 */
6dc0f87e
SF
133 cFYI(0, ("existing dentry with inode 0x%p",
134 tmp_dentry->d_inode));
1da177e4 135 *ptmp_inode = tmp_dentry->d_inode;
4523cc30 136 if (*ptmp_inode == NULL) {
132ac7b7 137 *ptmp_inode = cifs_new_inode(sb, inum);
4523cc30 138 if (*ptmp_inode == NULL)
1da177e4
LT
139 return rc;
140 rc = 1;
1da177e4
LT
141 }
142 } else {
e6a00296 143 tmp_dentry = d_alloc(file->f_path.dentry, qstring);
4523cc30 144 if (tmp_dentry == NULL) {
6dc0f87e 145 cERROR(1, ("Failed allocating dentry"));
1da177e4
LT
146 *ptmp_inode = NULL;
147 return rc;
148 }
149
132ac7b7 150 if (CIFS_SB(sb)->tcon->nocase)
b92327fe
SF
151 tmp_dentry->d_op = &cifs_ci_dentry_ops;
152 else
153 tmp_dentry->d_op = &cifs_dentry_ops;
132ac7b7
JL
154
155 *ptmp_inode = cifs_new_inode(sb, inum);
4523cc30 156 if (*ptmp_inode == NULL)
1da177e4 157 return rc;
b835bebe 158 rc = 2;
1da177e4
LT
159 }
160
161 tmp_dentry->d_time = jiffies;
162 *pnew_dentry = tmp_dentry;
163 return rc;
164}
165
5bafd765 166static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
2c2130e1 167 char *buf, unsigned int *pobject_type, int isNewInode)
1da177e4 168{
966ca923
SF
169 loff_t local_size;
170 struct timespec local_mtime;
171
1da177e4
LT
172 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
173 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
5bafd765
SF
174 __u32 attr;
175 __u64 allocation_size;
176 __u64 end_of_file;
4468eb3f 177 umode_t default_mode;
1da177e4 178
966ca923
SF
179 /* save mtime and size */
180 local_mtime = tmp_inode->i_mtime;
181 local_size = tmp_inode->i_size;
182
4523cc30 183 if (new_buf_type) {
5bafd765
SF
184 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
185
186 attr = le32_to_cpu(pfindData->ExtFileAttributes);
187 allocation_size = le64_to_cpu(pfindData->AllocationSize);
188 end_of_file = le64_to_cpu(pfindData->EndOfFile);
189 tmp_inode->i_atime =
07119a4d 190 cifs_NTtimeToUnix(pfindData->LastAccessTime);
5bafd765 191 tmp_inode->i_mtime =
07119a4d 192 cifs_NTtimeToUnix(pfindData->LastWriteTime);
5bafd765 193 tmp_inode->i_ctime =
07119a4d 194 cifs_NTtimeToUnix(pfindData->ChangeTime);
5bafd765 195 } else { /* legacy, OS2 and DOS style */
c4a2c08d 196 int offset = cifs_sb->tcon->ses->server->timeAdj;
ad7a2926 197 FIND_FILE_STANDARD_INFO *pfindData =
5bafd765
SF
198 (FIND_FILE_STANDARD_INFO *)buf;
199
c4a2c08d
JL
200 tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
201 pfindData->LastWriteTime,
202 offset);
203 tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
204 pfindData->LastAccessTime,
205 offset);
206 tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
207 pfindData->LastWriteTime,
208 offset);
5bafd765
SF
209 attr = le16_to_cpu(pfindData->Attributes);
210 allocation_size = le32_to_cpu(pfindData->AllocationSize);
211 end_of_file = le32_to_cpu(pfindData->DataSize);
5bafd765
SF
212 }
213
1da177e4 214 /* Linux can not store file creation time unfortunately so ignore it */
5bafd765
SF
215
216 cifsInfo->cifsAttrs = attr;
a6f8de3d
SF
217#ifdef CONFIG_CIFS_EXPERIMENTAL
218 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
219 /* get more accurate mode via ACL - so force inode refresh */
220 cifsInfo->time = 0;
221 } else
222#endif /* CONFIG_CIFS_EXPERIMENTAL */
223 cifsInfo->time = jiffies;
5bafd765 224
1da177e4
LT
225 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
226 /* 2767 perms - indicate mandatory locking */
790fe579 227 /* BB fill in uid and gid here? with help from winbind?
1da177e4
LT
228 or retrieve from NTFS stream extended attribute */
229 if (atomic_read(&cifsInfo->inUse) == 0) {
230 tmp_inode->i_uid = cifs_sb->mnt_uid;
231 tmp_inode->i_gid = cifs_sb->mnt_gid;
4468eb3f
JL
232 }
233
234 if (attr & ATTR_DIRECTORY)
235 default_mode = cifs_sb->mnt_dir_mode;
236 else
237 default_mode = cifs_sb->mnt_file_mode;
238
239 /* set initial permissions */
240 if ((atomic_read(&cifsInfo->inUse) == 0) ||
241 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
242 tmp_inode->i_mode = default_mode;
243 else {
244 /* just reenable write bits if !ATTR_READONLY */
245 if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
246 (attr & ATTR_READONLY) == 0)
247 tmp_inode->i_mode |= (S_IWUGO & default_mode);
248
3020a1f5 249 tmp_inode->i_mode &= ~S_IFMT;
1da177e4
LT
250 }
251
4468eb3f
JL
252 /* clear write bits if ATTR_READONLY is set */
253 if (attr & ATTR_READONLY)
254 tmp_inode->i_mode &= ~S_IWUGO;
255
256 /* set inode type */
257 if ((attr & ATTR_SYSTEM) &&
258 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
3020a1f5 259 if (end_of_file == 0) {
3020a1f5 260 tmp_inode->i_mode |= S_IFIFO;
4468eb3f 261 *pobject_type = DT_FIFO;
3020a1f5 262 } else {
4468eb3f
JL
263 /*
264 * trying to get the type can be slow, so just call
265 * this a regular file for now, and mark for reval
266 */
790fe579 267 tmp_inode->i_mode |= S_IFREG;
4468eb3f 268 *pobject_type = DT_REG;
790fe579 269 cifsInfo->time = 0;
3020a1f5 270 }
1da177e4 271 } else {
4468eb3f
JL
272 if (attr & ATTR_DIRECTORY) {
273 tmp_inode->i_mode |= S_IFDIR;
274 *pobject_type = DT_DIR;
275 } else {
276 tmp_inode->i_mode |= S_IFREG;
277 *pobject_type = DT_REG;
278 }
279 }
1da177e4
LT
280
281 /* can not fill in nlink here as in qpathinfo version and Unx search */
ad7a2926 282 if (atomic_read(&cifsInfo->inUse) == 0)
1da177e4 283 atomic_set(&cifsInfo->inUse, 1);
1da177e4 284
fbec9ab9 285 cifsInfo->server_eof = end_of_file;
3677db10 286 spin_lock(&tmp_inode->i_lock);
7ba52631 287 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
790fe579 288 /* can not safely change the file size here if the
1da177e4
LT
289 client is writing to it due to potential races */
290 i_size_write(tmp_inode, end_of_file);
291
292 /* 512 bytes (2**9) is the fake blocksize that must be used */
293 /* for this calculation, even though the reported blocksize is larger */
294 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
295 }
3677db10 296 spin_unlock(&tmp_inode->i_lock);
1da177e4
LT
297
298 if (allocation_size < end_of_file)
299 cFYI(1, ("May be sparse file, allocation less than file size"));
ba52de12 300 cFYI(1, ("File Size %ld and blocks %llu",
5515eff8 301 (unsigned long)tmp_inode->i_size,
ba52de12 302 (unsigned long long)tmp_inode->i_blocks));
1da177e4 303 if (S_ISREG(tmp_inode->i_mode)) {
966ca923 304 cFYI(1, ("File inode"));
1da177e4 305 tmp_inode->i_op = &cifs_file_inode_ops;
4523cc30
SF
306 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
307 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
8b94bcb9
SF
308 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
309 else
310 tmp_inode->i_fop = &cifs_file_direct_ops;
4523cc30 311 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
8b94bcb9 312 tmp_inode->i_fop = &cifs_file_nobrl_ops;
1da177e4
LT
313 else
314 tmp_inode->i_fop = &cifs_file_ops;
f3f6ec4b 315
4523cc30 316 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
bfa0d75a 317 (cifs_sb->tcon->ses->server->maxBuf <
273d81d6
DK
318 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
319 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
320 else
321 tmp_inode->i_data.a_ops = &cifs_addr_ops;
322
4523cc30 323 if (isNewInode)
dfb7533b
SF
324 return; /* No sense invalidating pages for new inode
325 since have not started caching readahead file
326 data yet */
966ca923
SF
327
328 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
329 (local_size == tmp_inode->i_size)) {
330 cFYI(1, ("inode exists but unchanged"));
331 } else {
332 /* file may have changed on server */
333 cFYI(1, ("invalidate inode, readdir detected change"));
334 invalidate_remote_inode(tmp_inode);
335 }
1da177e4 336 } else if (S_ISDIR(tmp_inode->i_mode)) {
966ca923 337 cFYI(1, ("Directory inode"));
1da177e4
LT
338 tmp_inode->i_op = &cifs_dir_inode_ops;
339 tmp_inode->i_fop = &cifs_dir_ops;
340 } else if (S_ISLNK(tmp_inode->i_mode)) {
966ca923 341 cFYI(1, ("Symbolic Link inode"));
1da177e4
LT
342 tmp_inode->i_op = &cifs_symlink_inode_ops;
343 } else {
966ca923 344 cFYI(1, ("Init special inode"));
1da177e4
LT
345 init_special_inode(tmp_inode, tmp_inode->i_mode,
346 tmp_inode->i_rdev);
347 }
348}
349
0e0d2cf3
SF
350/* BB eventually need to add the following helper function to
351 resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
352 we try to do FindFirst on (NTFS) directory symlinks */
353/*
354int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
355 int xid)
356{
357 __u16 fid;
358 int len;
359 int oplock = 0;
360 int rc;
361 struct cifsTconInfo *ptcon = cifs_sb->tcon;
362 char *tmpbuffer;
363
364 rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
365 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
366 cifs_sb->local_nls,
367 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
368 if (!rc) {
369 tmpbuffer = kmalloc(maxpath);
370 rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
371 tmpbuffer,
372 maxpath -1,
373 fid,
374 cifs_sb->local_nls);
375 if (CIFSSMBClose(xid, ptcon, fid)) {
376 cFYI(1, ("Error closing temporary reparsepoint open)"));
377 }
378 }
379}
380 */
381
1da177e4
LT
382static int initiate_cifs_search(const int xid, struct file *file)
383{
384 int rc = 0;
3870253e
SF
385 char *full_path;
386 struct cifsFileInfo *cifsFile;
1da177e4
LT
387 struct cifs_sb_info *cifs_sb;
388 struct cifsTconInfo *pTcon;
389
4523cc30 390 if (file->private_data == NULL) {
3870253e
SF
391 file->private_data =
392 kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
1da177e4
LT
393 }
394
4523cc30 395 if (file->private_data == NULL)
1da177e4 396 return -ENOMEM;
1da177e4 397 cifsFile = file->private_data;
4b18f2a9
SF
398 cifsFile->invalidHandle = true;
399 cifsFile->srch_inf.endOfSearch = false;
1da177e4 400
e6a00296 401 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
4523cc30 402 if (cifs_sb == NULL)
1da177e4
LT
403 return -EINVAL;
404
405 pTcon = cifs_sb->tcon;
4523cc30 406 if (pTcon == NULL)
1da177e4
LT
407 return -EINVAL;
408
e6a00296 409 full_path = build_path_from_dentry(file->f_path.dentry);
1da177e4 410
ad7a2926 411 if (full_path == NULL)
1da177e4 412 return -ENOMEM;
1da177e4 413
966ca923 414 cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos));
1da177e4 415
75cf6bdc 416ffirst_retry:
1da177e4 417 /* test for Unix extensions */
c18c842b
SF
418 /* but now check for them on the share/mount not on the SMB session */
419/* if (pTcon->ses->capabilities & CAP_UNIX) { */
ad7a2926 420 if (pTcon->unix_ext)
5bafd765 421 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
ad7a2926 422 else if ((pTcon->ses->capabilities &
5bafd765
SF
423 (CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
424 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
1da177e4
LT
425 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
426 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
427 } else /* not srvinos - BB fixme add check for backlevel? */ {
428 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
429 }
430
3870253e 431 rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls,
737b758c 432 &cifsFile->netfid, &cifsFile->srch_inf,
3870253e 433 cifs_sb->mnt_cifs_flags &
eafe8701 434 CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
4523cc30 435 if (rc == 0)
4b18f2a9 436 cifsFile->invalidHandle = false;
e836f015 437 /* BB add following call to handle readdir on new NTFS symlink errors
0e0d2cf3
SF
438 else if STATUS_STOPPED_ON_SYMLINK
439 call get_symlink_reparse_path and retry with new path */
440 else if ((rc == -EOPNOTSUPP) &&
75cf6bdc
SF
441 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
442 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
443 goto ffirst_retry;
444 }
1da177e4
LT
445 kfree(full_path);
446 return rc;
447}
448
449/* return length of unicode string in bytes */
450static int cifs_unicode_bytelen(char *str)
451{
452 int len;
63d2583f 453 __le16 *ustr = (__le16 *)str;
1da177e4 454
3870253e 455 for (len = 0; len <= PATH_MAX; len++) {
4523cc30 456 if (ustr[len] == 0)
1da177e4
LT
457 return len << 1;
458 }
790fe579 459 cFYI(1, ("Unicode string longer than PATH_MAX found"));
1da177e4
LT
460 return len << 1;
461}
462
5bafd765 463static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
1da177e4 464{
3870253e 465 char *new_entry;
ad7a2926 466 FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
1da177e4 467
4523cc30 468 if (level == SMB_FIND_FILE_INFO_STANDARD) {
ad7a2926 469 FIND_FILE_STANDARD_INFO *pfData;
5bafd765
SF
470 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
471
472 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
473 pfData->FileNameLength;
474 } else
475 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
790fe579 476 cFYI(1, ("new entry %p old entry %p", new_entry, old_entry));
1da177e4 477 /* validate that new_entry is not past end of SMB */
4523cc30 478 if (new_entry >= end_of_smb) {
09d1db5c
SF
479 cERROR(1,
480 ("search entry %p began after end of SMB %p old entry %p",
3870253e 481 new_entry, end_of_smb, old_entry));
1da177e4 482 return NULL;
4523cc30 483 } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
3870253e
SF
484 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
485 || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
5bafd765 486 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
3870253e 487 cERROR(1, ("search entry %p extends after end of SMB %p",
09d1db5c
SF
488 new_entry, end_of_smb));
489 return NULL;
3870253e 490 } else
1da177e4
LT
491 return new_entry;
492
493}
494
495#define UNICODE_DOT cpu_to_le16(0x2e)
496
497/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
498static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
499{
500 int rc = 0;
3870253e
SF
501 char *filename = NULL;
502 int len = 0;
1da177e4 503
4523cc30 504 if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
ad7a2926 505 FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
1da177e4 506 filename = &pFindData->FileName[0];
4523cc30 507 if (cfile->srch_inf.unicode) {
1da177e4
LT
508 len = cifs_unicode_bytelen(filename);
509 } else {
510 /* BB should we make this strnlen of PATH_MAX? */
511 len = strnlen(filename, 5);
512 }
4523cc30 513 } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
ad7a2926 514 FILE_DIRECTORY_INFO *pFindData =
1da177e4
LT
515 (FILE_DIRECTORY_INFO *)current_entry;
516 filename = &pFindData->FileName[0];
517 len = le32_to_cpu(pFindData->FileNameLength);
3870253e 518 } else if (cfile->srch_inf.info_level ==
5bafd765 519 SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
ad7a2926 520 FILE_FULL_DIRECTORY_INFO *pFindData =
1da177e4
LT
521 (FILE_FULL_DIRECTORY_INFO *)current_entry;
522 filename = &pFindData->FileName[0];
523 len = le32_to_cpu(pFindData->FileNameLength);
4523cc30 524 } else if (cfile->srch_inf.info_level ==
5bafd765 525 SMB_FIND_FILE_ID_FULL_DIR_INFO) {
ad7a2926 526 SEARCH_ID_FULL_DIR_INFO *pFindData =
1da177e4
LT
527 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
528 filename = &pFindData->FileName[0];
529 len = le32_to_cpu(pFindData->FileNameLength);
3870253e 530 } else if (cfile->srch_inf.info_level ==
5bafd765 531 SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
ad7a2926 532 FILE_BOTH_DIRECTORY_INFO *pFindData =
1da177e4
LT
533 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
534 filename = &pFindData->FileName[0];
535 len = le32_to_cpu(pFindData->FileNameLength);
4523cc30 536 } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
ad7a2926 537 FIND_FILE_STANDARD_INFO *pFindData =
5bafd765
SF
538 (FIND_FILE_STANDARD_INFO *)current_entry;
539 filename = &pFindData->FileName[0];
5ddaa683 540 len = pFindData->FileNameLength;
1da177e4 541 } else {
790fe579
SF
542 cFYI(1, ("Unknown findfirst level %d",
543 cfile->srch_inf.info_level));
1da177e4
LT
544 }
545
4523cc30
SF
546 if (filename) {
547 if (cfile->srch_inf.unicode) {
1da177e4 548 __le16 *ufilename = (__le16 *)filename;
4523cc30 549 if (len == 2) {
1da177e4 550 /* check for . */
4523cc30 551 if (ufilename[0] == UNICODE_DOT)
1da177e4 552 rc = 1;
4523cc30 553 } else if (len == 4) {
1da177e4 554 /* check for .. */
4523cc30 555 if ((ufilename[0] == UNICODE_DOT)
3870253e 556 && (ufilename[1] == UNICODE_DOT))
1da177e4
LT
557 rc = 2;
558 }
559 } else /* ASCII */ {
4523cc30 560 if (len == 1) {
3870253e 561 if (filename[0] == '.')
1da177e4 562 rc = 1;
4523cc30 563 } else if (len == 2) {
790fe579 564 if ((filename[0] == '.') && (filename[1] == '.'))
1da177e4
LT
565 rc = 2;
566 }
567 }
568 }
569
570 return rc;
571}
572
eafe8701
SF
573/* Check if directory that we are searching has changed so we can decide
574 whether we can use the cached search results from the previous search */
3870253e 575static int is_dir_changed(struct file *file)
eafe8701 576{
c33f8d32
CH
577 struct inode *inode = file->f_path.dentry->d_inode;
578 struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
eafe8701 579
c33f8d32 580 if (cifsInfo->time == 0)
eafe8701
SF
581 return 1; /* directory was changed, perhaps due to unlink */
582 else
583 return 0;
584
585}
586
0752f152
SF
587static int cifs_save_resume_key(const char *current_entry,
588 struct cifsFileInfo *cifsFile)
589{
590 int rc = 0;
591 unsigned int len = 0;
592 __u16 level;
593 char *filename;
594
595 if ((cifsFile == NULL) || (current_entry == NULL))
596 return -EINVAL;
597
598 level = cifsFile->srch_inf.info_level;
599
600 if (level == SMB_FIND_FILE_UNIX) {
601 FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
602
603 filename = &pFindData->FileName[0];
604 if (cifsFile->srch_inf.unicode) {
605 len = cifs_unicode_bytelen(filename);
606 } else {
607 /* BB should we make this strnlen of PATH_MAX? */
608 len = strnlen(filename, PATH_MAX);
609 }
610 cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
611 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
612 FILE_DIRECTORY_INFO *pFindData =
613 (FILE_DIRECTORY_INFO *)current_entry;
614 filename = &pFindData->FileName[0];
615 len = le32_to_cpu(pFindData->FileNameLength);
616 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
617 } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
618 FILE_FULL_DIRECTORY_INFO *pFindData =
619 (FILE_FULL_DIRECTORY_INFO *)current_entry;
620 filename = &pFindData->FileName[0];
621 len = le32_to_cpu(pFindData->FileNameLength);
622 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
623 } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
624 SEARCH_ID_FULL_DIR_INFO *pFindData =
625 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
626 filename = &pFindData->FileName[0];
627 len = le32_to_cpu(pFindData->FileNameLength);
628 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
629 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
630 FILE_BOTH_DIRECTORY_INFO *pFindData =
631 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
632 filename = &pFindData->FileName[0];
633 len = le32_to_cpu(pFindData->FileNameLength);
634 cifsFile->srch_inf.resume_key = pFindData->FileIndex;
635 } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
636 FIND_FILE_STANDARD_INFO *pFindData =
637 (FIND_FILE_STANDARD_INFO *)current_entry;
638 filename = &pFindData->FileName[0];
639 /* one byte length, no name conversion */
640 len = (unsigned int)pFindData->FileNameLength;
641 cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
642 } else {
643 cFYI(1, ("Unknown findfirst level %d", level));
644 return -EINVAL;
645 }
646 cifsFile->srch_inf.resume_name_len = len;
647 cifsFile->srch_inf.presume_name = filename;
648 return rc;
649}
650
1da177e4
LT
651/* find the corresponding entry in the search */
652/* Note that the SMB server returns search entries for . and .. which
653 complicates logic here if we choose to parse for them and we do not
654 assume that they are located in the findfirst return buffer.*/
655/* We start counting in the buffer with entry 2 and increment for every
656 entry (do not increment for . or .. entry) */
657static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
3870253e 658 struct file *file, char **ppCurrentEntry, int *num_to_ret)
1da177e4
LT
659{
660 int rc = 0;
661 int pos_in_buf = 0;
662 loff_t first_entry_in_buffer;
663 loff_t index_to_find = file->f_pos;
3870253e 664 struct cifsFileInfo *cifsFile = file->private_data;
1da177e4 665 /* check if index in the buffer */
50c2f753 666
3870253e 667 if ((cifsFile == NULL) || (ppCurrentEntry == NULL) ||
eafe8701 668 (num_to_ret == NULL))
1da177e4 669 return -ENOENT;
50c2f753 670
1da177e4 671 *ppCurrentEntry = NULL;
3870253e
SF
672 first_entry_in_buffer =
673 cifsFile->srch_inf.index_of_last_entry -
1da177e4 674 cifsFile->srch_inf.entries_in_buffer;
60808233
SF
675
676 /* if first entry in buf is zero then is first buffer
677 in search response data which means it is likely . and ..
678 will be in this buffer, although some servers do not return
679 . and .. for the root of a drive and for those we need
680 to start two entries earlier */
681
3979877e 682 dump_cifs_file_struct(file, "In fce ");
3870253e
SF
683 if (((index_to_find < cifsFile->srch_inf.index_of_last_entry) &&
684 is_dir_changed(file)) ||
eafe8701 685 (index_to_find < first_entry_in_buffer)) {
1da177e4 686 /* close and restart search */
790fe579 687 cFYI(1, ("search backing up - close and restart search"));
ddb4cbfc 688 write_lock(&GlobalSMBSeslock);
77c57ec8
SF
689 if (!cifsFile->srch_inf.endOfSearch &&
690 !cifsFile->invalidHandle) {
691 cifsFile->invalidHandle = true;
ddb4cbfc 692 write_unlock(&GlobalSMBSeslock);
77c57ec8 693 CIFSFindClose(xid, pTcon, cifsFile->netfid);
ddb4cbfc
SF
694 } else
695 write_unlock(&GlobalSMBSeslock);
4523cc30 696 if (cifsFile->srch_inf.ntwrk_buf_start) {
790fe579 697 cFYI(1, ("freeing SMB ff cache buf on search rewind"));
4523cc30 698 if (cifsFile->srch_inf.smallBuf)
d47d7c1a
SF
699 cifs_small_buf_release(cifsFile->srch_inf.
700 ntwrk_buf_start);
701 else
702 cifs_buf_release(cifsFile->srch_inf.
703 ntwrk_buf_start);
76c510ad 704 cifsFile->srch_inf.ntwrk_buf_start = NULL;
1da177e4 705 }
3870253e 706 rc = initiate_cifs_search(xid, file);
4523cc30 707 if (rc) {
790fe579
SF
708 cFYI(1, ("error %d reinitiating a search on rewind",
709 rc));
1da177e4
LT
710 return rc;
711 }
a364bc0b 712 cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
1da177e4
LT
713 }
714
3870253e 715 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
4b18f2a9 716 (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
790fe579 717 cFYI(1, ("calling findnext2"));
3870253e 718 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
dfb7533b 719 &cifsFile->srch_inf);
a364bc0b 720 cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
4523cc30 721 if (rc)
1da177e4
LT
722 return -ENOENT;
723 }
4523cc30 724 if (index_to_find < cifsFile->srch_inf.index_of_last_entry) {
1da177e4
LT
725 /* we found the buffer that contains the entry */
726 /* scan and find it */
727 int i;
3870253e
SF
728 char *current_entry;
729 char *end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
1da177e4
LT
730 smbCalcSize((struct smb_hdr *)
731 cifsFile->srch_inf.ntwrk_buf_start);
60808233
SF
732
733 current_entry = cifsFile->srch_inf.srch_entries_start;
1da177e4
LT
734 first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
735 - cifsFile->srch_inf.entries_in_buffer;
736 pos_in_buf = index_to_find - first_entry_in_buffer;
790fe579 737 cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf));
5bafd765 738
ad7a2926 739 for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) {
dfb7533b 740 /* go entry by entry figuring out which is first */
3870253e 741 current_entry = nxt_dir_entry(current_entry, end_of_smb,
5bafd765 742 cifsFile->srch_inf.info_level);
1da177e4 743 }
790fe579 744 if ((current_entry == NULL) && (i < pos_in_buf)) {
1da177e4 745 /* BB fixme - check if we should flag this error */
3870253e 746 cERROR(1, ("reached end of buf searching for pos in buf"
1da177e4 747 " %d index to find %lld rc %d",
3870253e 748 pos_in_buf, index_to_find, rc));
1da177e4
LT
749 }
750 rc = 0;
751 *ppCurrentEntry = current_entry;
752 } else {
790fe579 753 cFYI(1, ("index not in buffer - could not findnext into it"));
1da177e4
LT
754 return 0;
755 }
756
790fe579
SF
757 if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
758 cFYI(1, ("can not return entries pos_in_buf beyond last"));
1da177e4
LT
759 *num_to_ret = 0;
760 } else
761 *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
1da177e4
LT
762
763 return rc;
764}
765
766/* inode num, inode type and filename returned */
767static int cifs_get_name_from_search_buf(struct qstr *pqst,
768 char *current_entry, __u16 level, unsigned int unicode,
18295796 769 struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
1da177e4
LT
770{
771 int rc = 0;
772 unsigned int len = 0;
3870253e
SF
773 char *filename;
774 struct nls_table *nlt = cifs_sb->local_nls;
1da177e4
LT
775
776 *pinum = 0;
777
790fe579 778 if (level == SMB_FIND_FILE_UNIX) {
3870253e 779 FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry;
1da177e4
LT
780
781 filename = &pFindData->FileName[0];
790fe579 782 if (unicode) {
1da177e4
LT
783 len = cifs_unicode_bytelen(filename);
784 } else {
785 /* BB should we make this strnlen of PATH_MAX? */
786 len = strnlen(filename, PATH_MAX);
787 }
788
cc0bad75 789 *pinum = le64_to_cpu(pFindData->basic.UniqueId);
790fe579 790 } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
3870253e 791 FILE_DIRECTORY_INFO *pFindData =
1da177e4
LT
792 (FILE_DIRECTORY_INFO *)current_entry;
793 filename = &pFindData->FileName[0];
794 len = le32_to_cpu(pFindData->FileNameLength);
790fe579 795 } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
3870253e 796 FILE_FULL_DIRECTORY_INFO *pFindData =
1da177e4
LT
797 (FILE_FULL_DIRECTORY_INFO *)current_entry;
798 filename = &pFindData->FileName[0];
799 len = le32_to_cpu(pFindData->FileNameLength);
790fe579 800 } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
3870253e 801 SEARCH_ID_FULL_DIR_INFO *pFindData =
1da177e4
LT
802 (SEARCH_ID_FULL_DIR_INFO *)current_entry;
803 filename = &pFindData->FileName[0];
804 len = le32_to_cpu(pFindData->FileNameLength);
85a6dac5 805 *pinum = le64_to_cpu(pFindData->UniqueId);
790fe579 806 } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
3870253e 807 FILE_BOTH_DIRECTORY_INFO *pFindData =
1da177e4
LT
808 (FILE_BOTH_DIRECTORY_INFO *)current_entry;
809 filename = &pFindData->FileName[0];
810 len = le32_to_cpu(pFindData->FileNameLength);
790fe579 811 } else if (level == SMB_FIND_FILE_INFO_STANDARD) {
ad7a2926 812 FIND_FILE_STANDARD_INFO *pFindData =
5bafd765
SF
813 (FIND_FILE_STANDARD_INFO *)current_entry;
814 filename = &pFindData->FileName[0];
815 /* one byte length, no name conversion */
816 len = (unsigned int)pFindData->FileNameLength;
1da177e4 817 } else {
790fe579 818 cFYI(1, ("Unknown findfirst level %d", level));
1da177e4
LT
819 return -EINVAL;
820 }
5bafd765 821
790fe579 822 if (len > max_len) {
3870253e 823 cERROR(1, ("bad search response length %d past smb end", len));
5bafd765
SF
824 return -EINVAL;
825 }
826
790fe579 827 if (unicode) {
f5884166
JL
828 pqst->len = cifs_from_ucs2((char *) pqst->name,
829 (__le16 *) filename,
18295796
JL
830 UNICODE_NAME_MAX,
831 min(len, max_len), nlt,
f5884166
JL
832 cifs_sb->mnt_cifs_flags &
833 CIFS_MOUNT_MAP_SPECIAL_CHR);
1da177e4
LT
834 } else {
835 pqst->name = filename;
836 pqst->len = len;
837 }
3870253e 838 pqst->hash = full_name_hash(pqst->name, pqst->len);
790fe579 839/* cFYI(1, ("filldir on %s",pqst->name)); */
1da177e4
LT
840 return rc;
841}
842
18295796
JL
843static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
844 void *direntry, char *scratch_buf, unsigned int max_len)
1da177e4
LT
845{
846 int rc = 0;
847 struct qstr qstring;
3870253e 848 struct cifsFileInfo *pCifsF;
2c2130e1 849 unsigned int obj_type;
950ec528 850 __u64 inum;
cc0bad75 851 ino_t ino;
3870253e 852 struct cifs_sb_info *cifs_sb;
1da177e4
LT
853 struct inode *tmp_inode;
854 struct dentry *tmp_dentry;
cc0bad75 855 struct cifs_fattr fattr;
1da177e4
LT
856
857 /* get filename and len into qstring */
858 /* get dentry */
859 /* decide whether to create and populate ionde */
790fe579 860 if ((direntry == NULL) || (file == NULL))
1da177e4
LT
861 return -EINVAL;
862
863 pCifsF = file->private_data;
50c2f753 864
790fe579 865 if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
1da177e4
LT
866 return -ENOENT;
867
3870253e 868 rc = cifs_entry_is_dot(pfindEntry, pCifsF);
60808233 869 /* skip . and .. since we added them first */
790fe579 870 if (rc != 0)
60808233
SF
871 return 0;
872
e6a00296 873 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1da177e4
LT
874
875 qstring.name = scratch_buf;
3870253e 876 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
1da177e4 877 pCifsF->srch_inf.info_level,
3870253e 878 pCifsF->srch_inf.unicode, cifs_sb,
5bafd765 879 max_len,
1da177e4
LT
880 &inum /* returned */);
881
790fe579 882 if (rc)
1da177e4
LT
883 return rc;
884
132ac7b7 885 /* only these two infolevels return valid inode numbers */
cc0bad75
JL
886 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
887 cifs_unix_basic_to_fattr(&fattr,
888 &((FILE_UNIX_INFO *) pfindEntry)->basic,
889 cifs_sb);
890 tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring,
891 &fattr);
892 obj_type = fattr.cf_dtype;
893 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
894 } else {
895 if (pCifsF->srch_inf.info_level ==
896 SMB_FIND_FILE_ID_FULL_DIR_INFO)
897 rc = construct_dentry(&qstring, file, &tmp_inode,
898 &tmp_dentry, &inum);
899 else
900 rc = construct_dentry(&qstring, file, &tmp_inode,
901 &tmp_dentry, NULL);
132ac7b7 902
cc0bad75
JL
903 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) {
904 rc = -ENOMEM;
905 goto out;
906 }
1da177e4 907
cc0bad75
JL
908 /* we pass in rc below, indicating whether it is a new inode,
909 * so we can figure out whether to invalidate the inode cached
910 * data if the file has changed
911 */
912 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
913 fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc);
914 else
915 fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc);
b835bebe 916
cc0bad75
JL
917 /* new inode - needs to be tied to dentry */
918 if (rc) {
919 d_instantiate(tmp_dentry, tmp_inode);
920 if (rc == 2)
921 d_rehash(tmp_dentry);
922 }
50c2f753 923
cc0bad75
JL
924 ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino);
925 }
3870253e
SF
926
927 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
cc0bad75 928 ino, obj_type);
790fe579
SF
929 if (rc) {
930 cFYI(1, ("filldir rc = %d", rc));
7ca85ba7
SF
931 /* we can not return filldir errors to the caller
932 since they are "normal" when the stat blocksize
933 is too small - we return remapped error instead */
934 rc = -EOVERFLOW;
1da177e4
LT
935 }
936
cc0bad75 937out:
1da177e4
LT
938 dput(tmp_dentry);
939 return rc;
940}
941
1da177e4
LT
942
943int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
944{
945 int rc = 0;
3870253e 946 int xid, i;
1da177e4
LT
947 struct cifs_sb_info *cifs_sb;
948 struct cifsTconInfo *pTcon;
949 struct cifsFileInfo *cifsFile = NULL;
3870253e 950 char *current_entry;
1da177e4 951 int num_to_fill = 0;
3870253e 952 char *tmp_buf = NULL;
50c2f753 953 char *end_of_smb;
18295796 954 unsigned int max_len;
1da177e4
LT
955
956 xid = GetXid();
957
e6a00296 958 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
1da177e4 959 pTcon = cifs_sb->tcon;
790fe579 960 if (pTcon == NULL)
1da177e4
LT
961 return -EINVAL;
962
1da177e4
LT
963 switch ((int) file->f_pos) {
964 case 0:
60808233 965 if (filldir(direntry, ".", 1, file->f_pos,
e6a00296 966 file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
60808233 967 cERROR(1, ("Filldir for current dir failed"));
1da177e4
LT
968 rc = -ENOMEM;
969 break;
970 }
60808233 971 file->f_pos++;
1da177e4 972 case 1:
60808233 973 if (filldir(direntry, "..", 2, file->f_pos,
e6a00296 974 file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
26a21b98 975 cERROR(1, ("Filldir for parent dir failed"));
1da177e4
LT
976 rc = -ENOMEM;
977 break;
978 }
60808233
SF
979 file->f_pos++;
980 default:
3870253e
SF
981 /* 1) If search is active,
982 is in current search buffer?
1da177e4
LT
983 if it before then restart search
984 if after then keep searching till find it */
985
790fe579 986 if (file->private_data == NULL) {
3870253e 987 rc = initiate_cifs_search(xid, file);
790fe579
SF
988 cFYI(1, ("initiate cifs search rc %d", rc));
989 if (rc) {
1da177e4
LT
990 FreeXid(xid);
991 return rc;
992 }
993 }
790fe579 994 if (file->private_data == NULL) {
1da177e4
LT
995 rc = -EINVAL;
996 FreeXid(xid);
997 return rc;
998 }
999 cifsFile = file->private_data;
1000 if (cifsFile->srch_inf.endOfSearch) {
790fe579 1001 if (cifsFile->srch_inf.emptyDir) {
1da177e4
LT
1002 cFYI(1, ("End of search, empty dir"));
1003 rc = 0;
1004 break;
1005 }
1006 } /* else {
4b18f2a9 1007 cifsFile->invalidHandle = true;
1da177e4 1008 CIFSFindClose(xid, pTcon, cifsFile->netfid);
aaa9bbe0 1009 } */
1da177e4 1010
3870253e
SF
1011 rc = find_cifs_entry(xid, pTcon, file,
1012 &current_entry, &num_to_fill);
790fe579
SF
1013 if (rc) {
1014 cFYI(1, ("fce error %d", rc));
1da177e4
LT
1015 goto rddir2_exit;
1016 } else if (current_entry != NULL) {
790fe579 1017 cFYI(1, ("entry %lld found", file->f_pos));
1da177e4 1018 } else {
790fe579 1019 cFYI(1, ("could not find entry"));
1da177e4
LT
1020 goto rddir2_exit;
1021 }
790fe579
SF
1022 cFYI(1, ("loop through %d times filling dir for net buf %p",
1023 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start));
5bafd765
SF
1024 max_len = smbCalcSize((struct smb_hdr *)
1025 cifsFile->srch_inf.ntwrk_buf_start);
1026 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
1027
f5884166 1028 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
790fe579
SF
1029 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
1030 if (current_entry == NULL) {
1da177e4 1031 /* evaluate whether this case is an error */
26f57364 1032 cERROR(1, ("past SMB end, num to fill %d i %d",
1da177e4
LT
1033 num_to_fill, i));
1034 break;
1035 }
60808233
SF
1036 /* if buggy server returns . and .. late do
1037 we want to check for that here? */
5bafd765
SF
1038 rc = cifs_filldir(current_entry, file,
1039 filldir, direntry, tmp_buf, max_len);
790fe579 1040 if (rc == -EOVERFLOW) {
7ca85ba7
SF
1041 rc = 0;
1042 break;
1043 }
1044
1da177e4 1045 file->f_pos++;
790fe579 1046 if (file->f_pos ==
3979877e 1047 cifsFile->srch_inf.index_of_last_entry) {
790fe579
SF
1048 cFYI(1, ("last entry in buf at pos %lld %s",
1049 file->f_pos, tmp_buf));
1050 cifs_save_resume_key(current_entry, cifsFile);
1da177e4 1051 break;
790fe579
SF
1052 } else
1053 current_entry =
5bafd765
SF
1054 nxt_dir_entry(current_entry, end_of_smb,
1055 cifsFile->srch_inf.info_level);
1da177e4
LT
1056 }
1057 kfree(tmp_buf);
1058 break;
1059 } /* end switch */
1060
1061rddir2_exit:
1da177e4
LT
1062 FreeXid(xid);
1063 return rc;
1064}