1 /*
2  *   fs/cifs/dir.c
3  *
4  *   vfs operations that deal with dentries
5  *
6  *   Copyright (C) International Business Machines  Corp., 2002,2009
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/stat.h>
25 #include <linux/slab.h>
26 #include <linux/namei.h>
27 #include <linux/mount.h>
28 #include <linux/file.h>
29 #include "cifsfs.h"
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsproto.h"
33 #include "cifs_debug.h"
34 #include "cifs_fs_sb.h"
35 
36 static void
renew_parental_timestamps(struct dentry * direntry)37 renew_parental_timestamps(struct dentry *direntry)
38 {
39 	/* BB check if there is a way to get the kernel to do this or if we
40 	   really need this */
41 	do {
42 		direntry->d_time = jiffies;
43 		direntry = direntry->d_parent;
44 	} while (!IS_ROOT(direntry));
45 }
46 
47 /* Note: caller must free return buffer */
48 char *
build_path_from_dentry(struct dentry * direntry)49 build_path_from_dentry(struct dentry *direntry)
50 {
51 	struct dentry *temp;
52 	int namelen;
53 	int pplen;
54 	int dfsplen;
55 	char *full_path;
56 	char dirsep;
57 	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
58 	struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
59 
60 	if (direntry == NULL)
61 		return NULL;  /* not much we can do if dentry is freed and
62 		we need to reopen the file after it was closed implicitly
63 		when the server crashed */
64 
65 	dirsep = CIFS_DIR_SEP(cifs_sb);
66 	pplen = cifs_sb->prepathlen;
67 	if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
68 		dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
69 	else
70 		dfsplen = 0;
71 cifs_bp_rename_retry:
72 	namelen = pplen + dfsplen;
73 	for (temp = direntry; !IS_ROOT(temp);) {
74 		namelen += (1 + temp->d_name.len);
75 		temp = temp->d_parent;
76 		if (temp == NULL) {
77 			cERROR(1, "corrupt dentry");
78 			return NULL;
79 		}
80 	}
81 
82 	full_path = kmalloc(namelen+1, GFP_KERNEL);
83 	if (full_path == NULL)
84 		return full_path;
85 	full_path[namelen] = 0;	/* trailing null */
86 	for (temp = direntry; !IS_ROOT(temp);) {
87 		namelen -= 1 + temp->d_name.len;
88 		if (namelen < 0) {
89 			break;
90 		} else {
91 			full_path[namelen] = dirsep;
92 			strncpy(full_path + namelen + 1, temp->d_name.name,
93 				temp->d_name.len);
94 			cFYI(0, "name: %s", full_path + namelen);
95 		}
96 		temp = temp->d_parent;
97 		if (temp == NULL) {
98 			cERROR(1, "corrupt dentry");
99 			kfree(full_path);
100 			return NULL;
101 		}
102 	}
103 	if (namelen != pplen + dfsplen) {
104 		cERROR(1, "did not end path lookup where expected namelen is %d",
105 			namelen);
106 		/* presumably this is only possible if racing with a rename
107 		of one of the parent directories  (we can not lock the dentries
108 		above us to prevent this, but retrying should be harmless) */
109 		kfree(full_path);
110 		goto cifs_bp_rename_retry;
111 	}
112 	/* DIR_SEP already set for byte  0 / vs \ but not for
113 	   subsequent slashes in prepath which currently must
114 	   be entered the right way - not sure if there is an alternative
115 	   since the '\' is a valid posix character so we can not switch
116 	   those safely to '/' if any are found in the middle of the prepath */
117 	/* BB test paths to Windows with '/' in the midst of prepath */
118 
119 	if (dfsplen) {
120 		strncpy(full_path, tcon->treeName, dfsplen);
121 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
122 			int i;
123 			for (i = 0; i < dfsplen; i++) {
124 				if (full_path[i] == '\\')
125 					full_path[i] = '/';
126 			}
127 		}
128 	}
129 	strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
130 	return full_path;
131 }
132 
133 /* Inode operations in similar order to how they appear in Linux file fs.h */
134 
135 int
cifs_create(struct inode * inode,struct dentry * direntry,int mode,struct nameidata * nd)136 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
137 		struct nameidata *nd)
138 {
139 	int rc = -ENOENT;
140 	int xid;
141 	int create_options = CREATE_NOT_DIR;
142 	__u32 oplock = 0;
143 	int oflags;
144 	/*
145 	 * BB below access is probably too much for mknod to request
146 	 *    but we have to do query and setpathinfo so requesting
147 	 *    less could fail (unless we want to request getatr and setatr
148 	 *    permissions (only).  At least for POSIX we do not have to
149 	 *    request so much.
150 	 */
151 	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
152 	__u16 fileHandle;
153 	struct cifs_sb_info *cifs_sb;
154 	struct tcon_link *tlink;
155 	struct cifsTconInfo *tcon;
156 	char *full_path = NULL;
157 	FILE_ALL_INFO *buf = NULL;
158 	struct inode *newinode = NULL;
159 	int disposition = FILE_OVERWRITE_IF;
160 
161 	xid = GetXid();
162 
163 	cifs_sb = CIFS_SB(inode->i_sb);
164 	tlink = cifs_sb_tlink(cifs_sb);
165 	if (IS_ERR(tlink)) {
166 		FreeXid(xid);
167 		return PTR_ERR(tlink);
168 	}
169 	tcon = tlink_tcon(tlink);
170 
171 	if (oplockEnabled)
172 		oplock = REQ_OPLOCK;
173 
174 	if (nd && (nd->flags & LOOKUP_OPEN))
175 		oflags = nd->intent.open.file->f_flags;
176 	else
177 		oflags = O_RDONLY | O_CREAT;
178 
179 	full_path = build_path_from_dentry(direntry);
180 	if (full_path == NULL) {
181 		rc = -ENOMEM;
182 		goto cifs_create_out;
183 	}
184 
185 	if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
186 	    (CIFS_UNIX_POSIX_PATH_OPS_CAP &
187 			le64_to_cpu(tcon->fsUnixInfo.Capability))) {
188 		rc = cifs_posix_open(full_path, &newinode,
189 			inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
190 		/* EIO could indicate that (posix open) operation is not
191 		   supported, despite what server claimed in capability
192 		   negotiation.  EREMOTE indicates DFS junction, which is not
193 		   handled in posix open */
194 
195 		if (rc == 0) {
196 			if (newinode == NULL) /* query inode info */
197 				goto cifs_create_get_file_info;
198 			else /* success, no need to query */
199 				goto cifs_create_set_dentry;
200 		} else if ((rc != -EIO) && (rc != -EREMOTE) &&
201 			 (rc != -EOPNOTSUPP) && (rc != -EINVAL))
202 			goto cifs_create_out;
203 		/* else fallthrough to retry, using older open call, this is
204 		   case where server does not support this SMB level, and
205 		   falsely claims capability (also get here for DFS case
206 		   which should be rare for path not covered on files) */
207 	}
208 
209 	if (nd && (nd->flags & LOOKUP_OPEN)) {
210 		/* if the file is going to stay open, then we
211 		   need to set the desired access properly */
212 		desiredAccess = 0;
213 		if (OPEN_FMODE(oflags) & FMODE_READ)
214 			desiredAccess |= GENERIC_READ; /* is this too little? */
215 		if (OPEN_FMODE(oflags) & FMODE_WRITE)
216 			desiredAccess |= GENERIC_WRITE;
217 
218 		if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
219 			disposition = FILE_CREATE;
220 		else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
221 			disposition = FILE_OVERWRITE_IF;
222 		else if ((oflags & O_CREAT) == O_CREAT)
223 			disposition = FILE_OPEN_IF;
224 		else
225 			cFYI(1, "Create flag not set in create function");
226 	}
227 
228 	/* BB add processing to set equivalent of mode - e.g. via CreateX with
229 	   ACLs */
230 
231 	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
232 	if (buf == NULL) {
233 		rc = -ENOMEM;
234 		goto cifs_create_out;
235 	}
236 
237 	/*
238 	 * if we're not using unix extensions, see if we need to set
239 	 * ATTR_READONLY on the create call
240 	 */
241 	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
242 		create_options |= CREATE_OPTION_READONLY;
243 
244 	if (tcon->ses->capabilities & CAP_NT_SMBS)
245 		rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
246 			 desiredAccess, create_options,
247 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
248 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
249 	else
250 		rc = -EIO; /* no NT SMB support fall into legacy open below */
251 
252 	if (rc == -EIO) {
253 		/* old server, retry the open legacy style */
254 		rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
255 			desiredAccess, create_options,
256 			&fileHandle, &oplock, buf, cifs_sb->local_nls,
257 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
258 	}
259 	if (rc) {
260 		cFYI(1, "cifs_create returned 0x%x", rc);
261 		goto cifs_create_out;
262 	}
263 
264 	/* If Open reported that we actually created a file
265 	   then we now have to set the mode if possible */
266 	if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
267 		struct cifs_unix_set_info_args args = {
268 				.mode	= mode,
269 				.ctime	= NO_CHANGE_64,
270 				.atime	= NO_CHANGE_64,
271 				.mtime	= NO_CHANGE_64,
272 				.device	= 0,
273 		};
274 
275 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
276 			args.uid = (__u64) current_fsuid();
277 			if (inode->i_mode & S_ISGID)
278 				args.gid = (__u64) inode->i_gid;
279 			else
280 				args.gid = (__u64) current_fsgid();
281 		} else {
282 			args.uid = NO_CHANGE_64;
283 			args.gid = NO_CHANGE_64;
284 		}
285 		CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
286 					current->tgid);
287 	} else {
288 		/* BB implement mode setting via Windows security
289 		   descriptors e.g. */
290 		/* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
291 
292 		/* Could set r/o dos attribute if mode & 0222 == 0 */
293 	}
294 
295 cifs_create_get_file_info:
296 	/* server might mask mode so we have to query for it */
297 	if (tcon->unix_ext)
298 		rc = cifs_get_inode_info_unix(&newinode, full_path,
299 					      inode->i_sb, xid);
300 	else {
301 		rc = cifs_get_inode_info(&newinode, full_path, buf,
302 					 inode->i_sb, xid, &fileHandle);
303 		if (newinode) {
304 			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
305 				newinode->i_mode = mode;
306 			if ((oplock & CIFS_CREATE_ACTION) &&
307 			    (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
308 				newinode->i_uid = current_fsuid();
309 				if (inode->i_mode & S_ISGID)
310 					newinode->i_gid = inode->i_gid;
311 				else
312 					newinode->i_gid = current_fsgid();
313 			}
314 		}
315 	}
316 
317 cifs_create_set_dentry:
318 	if (rc == 0)
319 		d_instantiate(direntry, newinode);
320 	else
321 		cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
322 
323 	if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
324 		struct cifsFileInfo *pfile_info;
325 		struct file *filp;
326 
327 		filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
328 		if (IS_ERR(filp)) {
329 			rc = PTR_ERR(filp);
330 			CIFSSMBClose(xid, tcon, fileHandle);
331 			goto cifs_create_out;
332 		}
333 
334 		pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
335 		if (pfile_info == NULL) {
336 			fput(filp);
337 			CIFSSMBClose(xid, tcon, fileHandle);
338 			rc = -ENOMEM;
339 		}
340 	} else {
341 		CIFSSMBClose(xid, tcon, fileHandle);
342 	}
343 
344 cifs_create_out:
345 	kfree(buf);
346 	kfree(full_path);
347 	cifs_put_tlink(tlink);
348 	FreeXid(xid);
349 	return rc;
350 }
351 
cifs_mknod(struct inode * inode,struct dentry * direntry,int mode,dev_t device_number)352 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
353 		dev_t device_number)
354 {
355 	int rc = -EPERM;
356 	int xid;
357 	struct cifs_sb_info *cifs_sb;
358 	struct tcon_link *tlink;
359 	struct cifsTconInfo *pTcon;
360 	char *full_path = NULL;
361 	struct inode *newinode = NULL;
362 	int oplock = 0;
363 	u16 fileHandle;
364 	FILE_ALL_INFO *buf = NULL;
365 	unsigned int bytes_written;
366 	struct win_dev *pdev;
367 
368 	if (!old_valid_dev(device_number))
369 		return -EINVAL;
370 
371 	cifs_sb = CIFS_SB(inode->i_sb);
372 	tlink = cifs_sb_tlink(cifs_sb);
373 	if (IS_ERR(tlink))
374 		return PTR_ERR(tlink);
375 
376 	pTcon = tlink_tcon(tlink);
377 
378 	xid = GetXid();
379 
380 	full_path = build_path_from_dentry(direntry);
381 	if (full_path == NULL) {
382 		rc = -ENOMEM;
383 		goto mknod_out;
384 	}
385 
386 	if (pTcon->unix_ext) {
387 		struct cifs_unix_set_info_args args = {
388 			.mode	= mode & ~current_umask(),
389 			.ctime	= NO_CHANGE_64,
390 			.atime	= NO_CHANGE_64,
391 			.mtime	= NO_CHANGE_64,
392 			.device	= device_number,
393 		};
394 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
395 			args.uid = (__u64) current_fsuid();
396 			args.gid = (__u64) current_fsgid();
397 		} else {
398 			args.uid = NO_CHANGE_64;
399 			args.gid = NO_CHANGE_64;
400 		}
401 		rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
402 					    cifs_sb->local_nls,
403 					    cifs_sb->mnt_cifs_flags &
404 						CIFS_MOUNT_MAP_SPECIAL_CHR);
405 		if (rc)
406 			goto mknod_out;
407 
408 		rc = cifs_get_inode_info_unix(&newinode, full_path,
409 						inode->i_sb, xid);
410 
411 		if (rc == 0)
412 			d_instantiate(direntry, newinode);
413 		goto mknod_out;
414 	}
415 
416 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
417 		goto mknod_out;
418 
419 
420 	cFYI(1, "sfu compat create special file");
421 
422 	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
423 	if (buf == NULL) {
424 		kfree(full_path);
425 		rc = -ENOMEM;
426 		FreeXid(xid);
427 		return rc;
428 	}
429 
430 	/* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
431 	rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
432 			 GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
433 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
434 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
435 	if (rc)
436 		goto mknod_out;
437 
438 	/* BB Do not bother to decode buf since no local inode yet to put
439 	 * timestamps in, but we can reuse it safely */
440 
441 	pdev = (struct win_dev *)buf;
442 	if (S_ISCHR(mode)) {
443 		memcpy(pdev->type, "IntxCHR", 8);
444 		pdev->major =
445 		      cpu_to_le64(MAJOR(device_number));
446 		pdev->minor =
447 		      cpu_to_le64(MINOR(device_number));
448 		rc = CIFSSMBWrite(xid, pTcon,
449 			fileHandle,
450 			sizeof(struct win_dev),
451 			0, &bytes_written, (char *)pdev,
452 			NULL, 0);
453 	} else if (S_ISBLK(mode)) {
454 		memcpy(pdev->type, "IntxBLK", 8);
455 		pdev->major =
456 		      cpu_to_le64(MAJOR(device_number));
457 		pdev->minor =
458 		      cpu_to_le64(MINOR(device_number));
459 		rc = CIFSSMBWrite(xid, pTcon,
460 			fileHandle,
461 			sizeof(struct win_dev),
462 			0, &bytes_written, (char *)pdev,
463 			NULL, 0);
464 	} /* else if (S_ISFIFO) */
465 	CIFSSMBClose(xid, pTcon, fileHandle);
466 	d_drop(direntry);
467 
468 	/* FIXME: add code here to set EAs */
469 
470 mknod_out:
471 	kfree(full_path);
472 	kfree(buf);
473 	FreeXid(xid);
474 	cifs_put_tlink(tlink);
475 	return rc;
476 }
477 
478 struct dentry *
cifs_lookup(struct inode * parent_dir_inode,struct dentry * direntry,struct nameidata * nd)479 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
480 	    struct nameidata *nd)
481 {
482 	int xid;
483 	int rc = 0; /* to get around spurious gcc warning, set to zero here */
484 	__u32 oplock = 0;
485 	__u16 fileHandle = 0;
486 	bool posix_open = false;
487 	struct cifs_sb_info *cifs_sb;
488 	struct tcon_link *tlink;
489 	struct cifsTconInfo *pTcon;
490 	struct cifsFileInfo *cfile;
491 	struct inode *newInode = NULL;
492 	char *full_path = NULL;
493 	struct file *filp;
494 
495 	xid = GetXid();
496 
497 	cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
498 	      parent_dir_inode, direntry->d_name.name, direntry);
499 
500 	/* check whether path exists */
501 
502 	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
503 	tlink = cifs_sb_tlink(cifs_sb);
504 	if (IS_ERR(tlink)) {
505 		FreeXid(xid);
506 		return (struct dentry *)tlink;
507 	}
508 	pTcon = tlink_tcon(tlink);
509 
510 	/*
511 	 * Don't allow the separator character in a path component.
512 	 * The VFS will not allow "/", but "\" is allowed by posix.
513 	 */
514 	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
515 		int i;
516 		for (i = 0; i < direntry->d_name.len; i++)
517 			if (direntry->d_name.name[i] == '\\') {
518 				cFYI(1, "Invalid file name");
519 				rc = -EINVAL;
520 				goto lookup_out;
521 			}
522 	}
523 
524 	/*
525 	 * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
526 	 * the VFS handle the create.
527 	 */
528 	if (nd && (nd->flags & LOOKUP_EXCL)) {
529 		d_instantiate(direntry, NULL);
530 		rc = 0;
531 		goto lookup_out;
532 	}
533 
534 	/* can not grab the rename sem here since it would
535 	deadlock in the cases (beginning of sys_rename itself)
536 	in which we already have the sb rename sem */
537 	full_path = build_path_from_dentry(direntry);
538 	if (full_path == NULL) {
539 		rc = -ENOMEM;
540 		goto lookup_out;
541 	}
542 
543 	if (direntry->d_inode != NULL) {
544 		cFYI(1, "non-NULL inode in lookup");
545 	} else {
546 		cFYI(1, "NULL inode in lookup");
547 	}
548 	cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
549 
550 	/* Posix open is only called (at lookup time) for file create now.
551 	 * For opens (rather than creates), because we do not know if it
552 	 * is a file or directory yet, and current Samba no longer allows
553 	 * us to do posix open on dirs, we could end up wasting an open call
554 	 * on what turns out to be a dir. For file opens, we wait to call posix
555 	 * open till cifs_open.  It could be added here (lookup) in the future
556 	 * but the performance tradeoff of the extra network request when EISDIR
557 	 * or EACCES is returned would have to be weighed against the 50%
558 	 * reduction in network traffic in the other paths.
559 	 */
560 	if (pTcon->unix_ext) {
561 		if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
562 		     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
563 		     (nd->intent.open.file->f_flags & O_CREAT)) {
564 			rc = cifs_posix_open(full_path, &newInode,
565 					parent_dir_inode->i_sb,
566 					nd->intent.open.create_mode,
567 					nd->intent.open.file->f_flags, &oplock,
568 					&fileHandle, xid);
569 			/*
570 			 * The check below works around a bug in POSIX
571 			 * open in samba versions 3.3.1 and earlier where
572 			 * open could incorrectly fail with invalid parameter.
573 			 * If either that or op not supported returned, follow
574 			 * the normal lookup.
575 			 */
576 			if ((rc == 0) || (rc == -ENOENT))
577 				posix_open = true;
578 			else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
579 				pTcon->broken_posix_open = true;
580 		}
581 		if (!posix_open)
582 			rc = cifs_get_inode_info_unix(&newInode, full_path,
583 						parent_dir_inode->i_sb, xid);
584 	} else
585 		rc = cifs_get_inode_info(&newInode, full_path, NULL,
586 				parent_dir_inode->i_sb, xid, NULL);
587 
588 	if ((rc == 0) && (newInode != NULL)) {
589 		d_add(direntry, newInode);
590 		if (posix_open) {
591 			filp = lookup_instantiate_filp(nd, direntry,
592 						       generic_file_open);
593 			if (IS_ERR(filp)) {
594 				rc = PTR_ERR(filp);
595 				CIFSSMBClose(xid, pTcon, fileHandle);
596 				goto lookup_out;
597 			}
598 
599 			cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
600 						  oplock);
601 			if (cfile == NULL) {
602 				fput(filp);
603 				CIFSSMBClose(xid, pTcon, fileHandle);
604 				rc = -ENOMEM;
605 				goto lookup_out;
606 			}
607 		}
608 		/* since paths are not looked up by component - the parent
609 		   directories are presumed to be good here */
610 		renew_parental_timestamps(direntry);
611 
612 	} else if (rc == -ENOENT) {
613 		rc = 0;
614 		direntry->d_time = jiffies;
615 		d_add(direntry, NULL);
616 	/*	if it was once a directory (but how can we tell?) we could do
617 		shrink_dcache_parent(direntry); */
618 	} else if (rc != -EACCES) {
619 		cERROR(1, "Unexpected lookup error %d", rc);
620 		/* We special case check for Access Denied - since that
621 		is a common return code */
622 	}
623 
624 lookup_out:
625 	kfree(full_path);
626 	cifs_put_tlink(tlink);
627 	FreeXid(xid);
628 	return ERR_PTR(rc);
629 }
630 
631 static int
cifs_d_revalidate(struct dentry * direntry,struct nameidata * nd)632 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
633 {
634 	if (nd->flags & LOOKUP_RCU)
635 		return -ECHILD;
636 
637 	if (direntry->d_inode) {
638 		if (cifs_revalidate_dentry(direntry))
639 			return 0;
640 		else
641 			return 1;
642 	}
643 
644 	/*
645 	 * This may be nfsd (or something), anyway, we can't see the
646 	 * intent of this. So, since this can be for creation, drop it.
647 	 */
648 	if (!nd)
649 		return 0;
650 
651 	/*
652 	 * Drop the negative dentry, in order to make sure to use the
653 	 * case sensitive name which is specified by user if this is
654 	 * for creation.
655 	 */
656 	if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
657 		if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
658 			return 0;
659 	}
660 
661 	if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
662 		return 0;
663 
664 	return 1;
665 }
666 
667 /* static int cifs_d_delete(struct dentry *direntry)
668 {
669 	int rc = 0;
670 
671 	cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
672 
673 	return rc;
674 }     */
675 
676 const struct dentry_operations cifs_dentry_ops = {
677 	.d_revalidate = cifs_d_revalidate,
678 	.d_automount = cifs_dfs_d_automount,
679 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
680 };
681 
cifs_ci_hash(const struct dentry * dentry,const struct inode * inode,struct qstr * q)682 static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
683 		struct qstr *q)
684 {
685 	struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
686 	unsigned long hash;
687 	int i;
688 
689 	hash = init_name_hash();
690 	for (i = 0; i < q->len; i++)
691 		hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
692 					 hash);
693 	q->hash = end_name_hash(hash);
694 
695 	return 0;
696 }
697 
cifs_ci_compare(const struct dentry * parent,const struct inode * pinode,const struct dentry * dentry,const struct inode * inode,unsigned int len,const char * str,const struct qstr * name)698 static int cifs_ci_compare(const struct dentry *parent,
699 		const struct inode *pinode,
700 		const struct dentry *dentry, const struct inode *inode,
701 		unsigned int len, const char *str, const struct qstr *name)
702 {
703 	struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
704 
705 	if ((name->len == len) &&
706 	    (nls_strnicmp(codepage, name->name, str, len) == 0))
707 		return 0;
708 	return 1;
709 }
710 
711 const struct dentry_operations cifs_ci_dentry_ops = {
712 	.d_revalidate = cifs_d_revalidate,
713 	.d_hash = cifs_ci_hash,
714 	.d_compare = cifs_ci_compare,
715 	.d_automount = cifs_dfs_d_automount,
716 };
717