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