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