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