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