vfs_lookup.c revision 54655
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)vfs_lookup.c	8.4 (Berkeley) 2/16/94
39 * $FreeBSD: head/sys/kern/vfs_lookup.c 54655 1999-12-15 23:02:35Z eivind $
40 */
41
42#include "opt_ktrace.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/namei.h>
47#include <sys/vnode.h>
48#include <sys/mount.h>
49#include <sys/filedesc.h>
50#include <sys/proc.h>
51
52#ifdef KTRACE
53#include <sys/ktrace.h>
54#endif
55
56#include <vm/vm_zone.h>
57
58/*
59 * Convert a pathname into a pointer to a locked inode.
60 *
61 * The FOLLOW flag is set when symbolic links are to be followed
62 * when they occur at the end of the name translation process.
63 * Symbolic links are always followed for all other pathname
64 * components other than the last.
65 *
66 * The segflg defines whether the name is to be copied from user
67 * space or kernel space.
68 *
69 * Overall outline of namei:
70 *
71 *	copy in name
72 *	get starting directory
73 *	while (!done && !error) {
74 *		call lookup to search path.
75 *		if symbolic link, massage name in buffer and continue
76 *	}
77 */
78int
79namei(ndp)
80	register struct nameidata *ndp;
81{
82	register struct filedesc *fdp;	/* pointer to file descriptor state */
83	register char *cp;		/* pointer into pathname argument */
84	register struct vnode *dp;	/* the directory we are searching */
85	struct iovec aiov;		/* uio for reading symbolic links */
86	struct uio auio;
87	int error, linklen;
88	struct componentname *cnp = &ndp->ni_cnd;
89	struct proc *p = cnp->cn_proc;
90
91	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
92	KASSERT(cnp->cn_cred && cnp->cn_proc, ("namei: bad cred/proc"));
93	KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0,
94	    ("namei: nameiop contaminated with flags"));
95	KASSERT((cnp->cn_flags & OPMASK) == 0,
96	    ("namei: flags contaminated with nameiops"));
97	fdp = cnp->cn_proc->p_fd;
98
99	/*
100	 * Get a buffer for the name to be translated, and copy the
101	 * name into the buffer.
102	 */
103	if ((cnp->cn_flags & HASBUF) == 0)
104		cnp->cn_pnbuf = zalloc(namei_zone);
105	if (ndp->ni_segflg == UIO_SYSSPACE)
106		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
107			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
108	else
109		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
110			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
111
112	/*
113	 * Don't allow empty pathnames.
114	 */
115	if (!error && *cnp->cn_pnbuf == '\0')
116		error = ENOENT;
117
118	if (error) {
119		zfree(namei_zone, cnp->cn_pnbuf);
120		ndp->ni_vp = NULL;
121		return (error);
122	}
123	ndp->ni_loopcnt = 0;
124#ifdef KTRACE
125	if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
126		ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf);
127#endif
128
129	/*
130	 * Get starting point for the translation.
131	 */
132	ndp->ni_rootdir = fdp->fd_rdir;
133	ndp->ni_topdir = fdp->fd_jdir;
134
135	dp = fdp->fd_cdir;
136	VREF(dp);
137	for (;;) {
138		/*
139		 * Check if root directory should replace current directory.
140		 * Done at start of translation and after symbolic link.
141		 */
142		cnp->cn_nameptr = cnp->cn_pnbuf;
143		if (*(cnp->cn_nameptr) == '/') {
144			vrele(dp);
145			while (*(cnp->cn_nameptr) == '/') {
146				cnp->cn_nameptr++;
147				ndp->ni_pathlen--;
148			}
149			dp = ndp->ni_rootdir;
150			VREF(dp);
151		}
152		ndp->ni_startdir = dp;
153		error = lookup(ndp);
154		if (error) {
155			zfree(namei_zone, cnp->cn_pnbuf);
156			return (error);
157		}
158		/*
159		 * Check for symbolic link
160		 */
161		if ((cnp->cn_flags & ISSYMLINK) == 0) {
162			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
163				zfree(namei_zone, cnp->cn_pnbuf);
164			else
165				cnp->cn_flags |= HASBUF;
166
167			if (vn_canvmio(ndp->ni_vp) == TRUE &&
168				(cnp->cn_nameiop != DELETE) &&
169				((cnp->cn_flags & (NOOBJ|LOCKLEAF)) ==
170				 LOCKLEAF))
171				vfs_object_create(ndp->ni_vp,
172					ndp->ni_cnd.cn_proc,
173					ndp->ni_cnd.cn_cred);
174
175			return (0);
176		}
177		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
178			VOP_UNLOCK(ndp->ni_dvp, 0, p);
179		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
180			error = ELOOP;
181			break;
182		}
183		if (ndp->ni_pathlen > 1)
184			cp = zalloc(namei_zone);
185		else
186			cp = cnp->cn_pnbuf;
187		aiov.iov_base = cp;
188		aiov.iov_len = MAXPATHLEN;
189		auio.uio_iov = &aiov;
190		auio.uio_iovcnt = 1;
191		auio.uio_offset = 0;
192		auio.uio_rw = UIO_READ;
193		auio.uio_segflg = UIO_SYSSPACE;
194		auio.uio_procp = (struct proc *)0;
195		auio.uio_resid = MAXPATHLEN;
196		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
197		if (error) {
198			if (ndp->ni_pathlen > 1)
199				zfree(namei_zone, cp);
200			break;
201		}
202		linklen = MAXPATHLEN - auio.uio_resid;
203		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
204			if (ndp->ni_pathlen > 1)
205				zfree(namei_zone, cp);
206			error = ENAMETOOLONG;
207			break;
208		}
209		if (ndp->ni_pathlen > 1) {
210			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
211			zfree(namei_zone, cnp->cn_pnbuf);
212			cnp->cn_pnbuf = cp;
213		} else
214			cnp->cn_pnbuf[linklen] = '\0';
215		ndp->ni_pathlen += linklen;
216		vput(ndp->ni_vp);
217		dp = ndp->ni_dvp;
218	}
219	zfree(namei_zone, cnp->cn_pnbuf);
220	vrele(ndp->ni_dvp);
221	vput(ndp->ni_vp);
222	ndp->ni_vp = NULL;
223	return (error);
224}
225
226/*
227 * Search a pathname.
228 * This is a very central and rather complicated routine.
229 *
230 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
231 * The starting directory is taken from ni_startdir. The pathname is
232 * descended until done, or a symbolic link is encountered. The variable
233 * ni_more is clear if the path is completed; it is set to one if a
234 * symbolic link needing interpretation is encountered.
235 *
236 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
237 * whether the name is to be looked up, created, renamed, or deleted.
238 * When CREATE, RENAME, or DELETE is specified, information usable in
239 * creating, renaming, or deleting a directory entry may be calculated.
240 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
241 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
242 * returned unlocked. Otherwise the parent directory is not returned. If
243 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
244 * the target is returned locked, otherwise it is returned unlocked.
245 * When creating or renaming and LOCKPARENT is specified, the target may not
246 * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
247 *
248 * Overall outline of lookup:
249 *
250 * dirloop:
251 *	identify next component of name at ndp->ni_ptr
252 *	handle degenerate case where name is null string
253 *	if .. and crossing mount points and on mounted filesys, find parent
254 *	call VOP_LOOKUP routine for next component name
255 *	    directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
256 *	    component vnode returned in ni_vp (if it exists), locked.
257 *	if result vnode is mounted on and crossing mount points,
258 *	    find mounted on vnode
259 *	if more components of name, do next level at dirloop
260 *	return the answer in ni_vp, locked if LOCKLEAF set
261 *	    if LOCKPARENT set, return locked parent in ni_dvp
262 *	    if WANTPARENT set, return unlocked parent in ni_dvp
263 */
264int
265lookup(ndp)
266	register struct nameidata *ndp;
267{
268	register char *cp;		/* pointer into pathname argument */
269	register struct vnode *dp = 0;	/* the directory we are searching */
270	struct vnode *tdp;		/* saved dp */
271	struct mount *mp;		/* mount table entry */
272	int docache;			/* == 0 do not cache last component */
273	int wantparent;			/* 1 => wantparent or lockparent flag */
274	int rdonly;			/* lookup read-only flag bit */
275	int trailing_slash;
276	int error = 0;
277	struct componentname *cnp = &ndp->ni_cnd;
278	struct proc *p = cnp->cn_proc;
279
280	/*
281	 * Setup: break out flag bits into variables.
282	 */
283	wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
284	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
285	if (cnp->cn_nameiop == DELETE ||
286	    (wantparent && cnp->cn_nameiop != CREATE &&
287	     cnp->cn_nameiop != LOOKUP))
288		docache = 0;
289	rdonly = cnp->cn_flags & RDONLY;
290	ndp->ni_dvp = NULL;
291	cnp->cn_flags &= ~ISSYMLINK;
292	dp = ndp->ni_startdir;
293	ndp->ni_startdir = NULLVP;
294	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
295
296dirloop:
297	/*
298	 * Search a new directory.
299	 *
300	 * The last component of the filename is left accessible via
301	 * cnp->cn_nameptr for callers that need the name. Callers needing
302	 * the name set the SAVENAME flag. When done, they assume
303	 * responsibility for freeing the pathname buffer.
304	 */
305	cnp->cn_consume = 0;
306	for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
307		continue;
308	cnp->cn_namelen = cp - cnp->cn_nameptr;
309	if (cnp->cn_namelen > NAME_MAX) {
310		error = ENAMETOOLONG;
311		goto bad;
312	}
313#ifdef NAMEI_DIAGNOSTIC
314	{ char c = *cp;
315	*cp = '\0';
316	printf("{%s}: ", cnp->cn_nameptr);
317	*cp = c; }
318#endif
319	ndp->ni_pathlen -= cnp->cn_namelen;
320	ndp->ni_next = cp;
321
322	/*
323	 * Replace multiple slashes by a single slash and trailing slashes
324	 * by a null.  This must be done before VOP_LOOKUP() because some
325	 * fs's don't know about trailing slashes.  Remember if there were
326	 * trailing slashes to handle symlinks, existing non-directories
327	 * and non-existing files that won't be directories specially later.
328	 */
329	trailing_slash = 0;
330	while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
331		cp++;
332		ndp->ni_pathlen--;
333		if (*cp == '\0') {
334			trailing_slash = 1;
335			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
336		}
337	}
338	ndp->ni_next = cp;
339
340	cnp->cn_flags |= MAKEENTRY;
341	if (*cp == '\0' && docache == 0)
342		cnp->cn_flags &= ~MAKEENTRY;
343	if (cnp->cn_namelen == 2 &&
344	    cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
345		cnp->cn_flags |= ISDOTDOT;
346	else
347		cnp->cn_flags &= ~ISDOTDOT;
348	if (*ndp->ni_next == 0)
349		cnp->cn_flags |= ISLASTCN;
350	else
351		cnp->cn_flags &= ~ISLASTCN;
352
353
354	/*
355	 * Check for degenerate name (e.g. / or "")
356	 * which is a way of talking about a directory,
357	 * e.g. like "/." or ".".
358	 */
359	if (cnp->cn_nameptr[0] == '\0') {
360		if (dp->v_type != VDIR) {
361			error = ENOTDIR;
362			goto bad;
363		}
364		if (cnp->cn_nameiop != LOOKUP) {
365			error = EISDIR;
366			goto bad;
367		}
368		if (wantparent) {
369			ndp->ni_dvp = dp;
370			VREF(dp);
371		}
372		ndp->ni_vp = dp;
373		if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
374			VOP_UNLOCK(dp, 0, p);
375		/* XXX This should probably move to the top of function. */
376		if (cnp->cn_flags & SAVESTART)
377			panic("lookup: SAVESTART");
378		return (0);
379	}
380
381	/*
382	 * Handle "..": two special cases.
383	 * 1. If at root directory (e.g. after chroot)
384	 *    or at absolute root directory
385	 *    then ignore it so can't get out.
386	 * 2. If this vnode is the root of a mounted
387	 *    filesystem, then replace it with the
388	 *    vnode which was mounted on so we take the
389	 *    .. in the other file system.
390	 * 3. If the vnode is the top directory of
391	 *    the jail or chroot, don't let them out.
392	 */
393	if (cnp->cn_flags & ISDOTDOT) {
394		for (;;) {
395			if (dp == ndp->ni_rootdir ||
396			    dp == ndp->ni_topdir ||
397			    dp == rootvnode) {
398				ndp->ni_dvp = dp;
399				ndp->ni_vp = dp;
400				VREF(dp);
401				goto nextname;
402			}
403			if ((dp->v_flag & VROOT) == 0 ||
404			    (cnp->cn_flags & NOCROSSMOUNT))
405				break;
406			tdp = dp;
407			dp = dp->v_mount->mnt_vnodecovered;
408			vput(tdp);
409			VREF(dp);
410			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
411		}
412	}
413
414	/*
415	 * We now have a segment name to search for, and a directory to search.
416	 */
417unionlookup:
418	ndp->ni_dvp = dp;
419	ndp->ni_vp = NULL;
420	ASSERT_VOP_LOCKED(dp, "lookup");
421	if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
422		KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
423#ifdef NAMEI_DIAGNOSTIC
424		printf("not found\n");
425#endif
426		if ((error == ENOENT) &&
427		    (dp->v_flag & VROOT) &&
428		    (dp->v_mount->mnt_flag & MNT_UNION)) {
429			tdp = dp;
430			dp = dp->v_mount->mnt_vnodecovered;
431			vput(tdp);
432			VREF(dp);
433			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
434			goto unionlookup;
435		}
436
437		if (error != EJUSTRETURN)
438			goto bad;
439		/*
440		 * If creating and at end of pathname, then can consider
441		 * allowing file to be created.
442		 */
443		if (rdonly) {
444			error = EROFS;
445			goto bad;
446		}
447		if (*cp == '\0' && trailing_slash &&
448		     !(cnp->cn_flags & WILLBEDIR)) {
449			error = ENOENT;
450			goto bad;
451		}
452		/*
453		 * We return with ni_vp NULL to indicate that the entry
454		 * doesn't currently exist, leaving a pointer to the
455		 * (possibly locked) directory inode in ndp->ni_dvp.
456		 */
457		if (cnp->cn_flags & SAVESTART) {
458			ndp->ni_startdir = ndp->ni_dvp;
459			VREF(ndp->ni_startdir);
460		}
461		return (0);
462	}
463#ifdef NAMEI_DIAGNOSTIC
464	printf("found\n");
465#endif
466
467	ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup");
468
469	/*
470	 * Take into account any additional components consumed by
471	 * the underlying filesystem.
472	 */
473	if (cnp->cn_consume > 0) {
474		cnp->cn_nameptr += cnp->cn_consume;
475		ndp->ni_next += cnp->cn_consume;
476		ndp->ni_pathlen -= cnp->cn_consume;
477		cnp->cn_consume = 0;
478	}
479
480	dp = ndp->ni_vp;
481
482	/*
483	 * Check to see if the vnode has been mounted on;
484	 * if so find the root of the mounted file system.
485	 */
486	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
487	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
488		if (vfs_busy(mp, 0, 0, p))
489			continue;
490		error = VFS_ROOT(mp, &tdp);
491		vfs_unbusy(mp, p);
492		if (error)
493			goto bad2;
494		vput(dp);
495		ndp->ni_vp = dp = tdp;
496	}
497
498	/*
499	 * Check for symbolic link
500	 */
501	if ((dp->v_type == VLNK) &&
502	    ((cnp->cn_flags & FOLLOW) || trailing_slash ||
503	     *ndp->ni_next == '/')) {
504		cnp->cn_flags |= ISSYMLINK;
505		if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) {
506			error = EACCES;
507			goto bad2;
508		}
509		return (0);
510	}
511
512	/*
513	 * Check for bogus trailing slashes.
514	 */
515	if (trailing_slash && dp->v_type != VDIR) {
516		error = ENOTDIR;
517		goto bad2;
518	}
519
520nextname:
521	/*
522	 * Not a symbolic link.  If more pathname,
523	 * continue at next component, else return.
524	 */
525	if (*ndp->ni_next == '/') {
526		cnp->cn_nameptr = ndp->ni_next;
527		while (*cnp->cn_nameptr == '/') {
528			cnp->cn_nameptr++;
529			ndp->ni_pathlen--;
530		}
531		if (ndp->ni_dvp != ndp->ni_vp)
532			ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup");
533		vrele(ndp->ni_dvp);
534		goto dirloop;
535	}
536	/*
537	 * Disallow directory write attempts on read-only file systems.
538	 */
539	if (rdonly &&
540	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
541		error = EROFS;
542		goto bad2;
543	}
544	if (cnp->cn_flags & SAVESTART) {
545		ndp->ni_startdir = ndp->ni_dvp;
546		VREF(ndp->ni_startdir);
547	}
548	if (!wantparent)
549		vrele(ndp->ni_dvp);
550
551	if ((cnp->cn_flags & LOCKLEAF) == 0)
552		VOP_UNLOCK(dp, 0, p);
553	return (0);
554
555bad2:
556	if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
557		VOP_UNLOCK(ndp->ni_dvp, 0, p);
558	vrele(ndp->ni_dvp);
559bad:
560	vput(dp);
561	ndp->ni_vp = NULL;
562	return (error);
563}
564
565/*
566 * relookup - lookup a path name component
567 *    Used by lookup to re-aquire things.
568 */
569int
570relookup(dvp, vpp, cnp)
571	struct vnode *dvp, **vpp;
572	struct componentname *cnp;
573{
574	struct proc *p = cnp->cn_proc;
575	struct vnode *dp = 0;		/* the directory we are searching */
576	int docache;			/* == 0 do not cache last component */
577	int wantparent;			/* 1 => wantparent or lockparent flag */
578	int rdonly;			/* lookup read-only flag bit */
579	int error = 0;
580#ifdef NAMEI_DIAGNOSTIC
581	int newhash;			/* DEBUG: check name hash */
582	char *cp;			/* DEBUG: check name ptr/len */
583#endif
584
585	/*
586	 * Setup: break out flag bits into variables.
587	 */
588	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
589	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
590	if (cnp->cn_nameiop == DELETE ||
591	    (wantparent && cnp->cn_nameiop != CREATE))
592		docache = 0;
593	rdonly = cnp->cn_flags & RDONLY;
594	cnp->cn_flags &= ~ISSYMLINK;
595	dp = dvp;
596	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
597
598/* dirloop: */
599	/*
600	 * Search a new directory.
601	 *
602	 * The last component of the filename is left accessible via
603	 * cnp->cn_nameptr for callers that need the name. Callers needing
604	 * the name set the SAVENAME flag. When done, they assume
605	 * responsibility for freeing the pathname buffer.
606	 */
607#ifdef NAMEI_DIAGNOSTIC
608	if (cnp->cn_namelen != cp - cnp->cn_nameptr)
609		panic ("relookup: bad len");
610	if (*cp != 0)
611		panic("relookup: not last component");
612	printf("{%s}: ", cnp->cn_nameptr);
613#endif
614
615	/*
616	 * Check for degenerate name (e.g. / or "")
617	 * which is a way of talking about a directory,
618	 * e.g. like "/." or ".".
619	 */
620	if (cnp->cn_nameptr[0] == '\0') {
621		if (cnp->cn_nameiop != LOOKUP || wantparent) {
622			error = EISDIR;
623			goto bad;
624		}
625		if (dp->v_type != VDIR) {
626			error = ENOTDIR;
627			goto bad;
628		}
629		if (!(cnp->cn_flags & LOCKLEAF))
630			VOP_UNLOCK(dp, 0, p);
631		*vpp = dp;
632		/* XXX This should probably move to the top of function. */
633		if (cnp->cn_flags & SAVESTART)
634			panic("lookup: SAVESTART");
635		return (0);
636	}
637
638	if (cnp->cn_flags & ISDOTDOT)
639		panic ("relookup: lookup on dot-dot");
640
641	/*
642	 * We now have a segment name to search for, and a directory to search.
643	 */
644	if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {
645		KASSERT(*vpp == NULL, ("leaf should be empty"));
646		if (error != EJUSTRETURN)
647			goto bad;
648		/*
649		 * If creating and at end of pathname, then can consider
650		 * allowing file to be created.
651		 */
652		if (rdonly) {
653			error = EROFS;
654			goto bad;
655		}
656		/* ASSERT(dvp == ndp->ni_startdir) */
657		if (cnp->cn_flags & SAVESTART)
658			VREF(dvp);
659		/*
660		 * We return with ni_vp NULL to indicate that the entry
661		 * doesn't currently exist, leaving a pointer to the
662		 * (possibly locked) directory inode in ndp->ni_dvp.
663		 */
664		return (0);
665	}
666	dp = *vpp;
667
668	/*
669	 * Check for symbolic link
670	 */
671	KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW),
672	    ("relookup: symlink found.\n"));
673
674	/*
675	 * Disallow directory write attempts on read-only file systems.
676	 */
677	if (rdonly &&
678	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
679		error = EROFS;
680		goto bad2;
681	}
682	/* ASSERT(dvp == ndp->ni_startdir) */
683	if (cnp->cn_flags & SAVESTART)
684		VREF(dvp);
685
686	if (!wantparent)
687		vrele(dvp);
688
689	if (vn_canvmio(dp) == TRUE &&
690		((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
691		vfs_object_create(dp, cnp->cn_proc, cnp->cn_cred);
692
693	if ((cnp->cn_flags & LOCKLEAF) == 0)
694		VOP_UNLOCK(dp, 0, p);
695	return (0);
696
697bad2:
698	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
699		VOP_UNLOCK(dvp, 0, p);
700	vrele(dvp);
701bad:
702	vput(dp);
703	*vpp = NULL;
704	return (error);
705}
706