vfs_lookup.c revision 101127
194663Sscottl/*
294663Sscottl * Copyright (c) 1982, 1986, 1989, 1993
394663Sscottl *	The Regents of the University of California.  All rights reserved.
494663Sscottl * (c) UNIX System Laboratories, Inc.
594663Sscottl * All or some portions of this file are derived from material licensed
6122097Sscottl * to the University of California by American Telephone and Telegraph
7122097Sscottl * Co. or Unix System Laboratories, Inc. and are reproduced herein with
894663Sscottl * the permission of UNIX System Laboratories, Inc.
994663Sscottl *
10160447Sstefanf * Redistribution and use in source and binary forms, with or without
1194663Sscottl * modification, are permitted provided that the following conditions
1294663Sscottl * are met:
13122097Sscottl * 1. Redistributions of source code must retain the above copyright
14122097Sscottl *    notice, this list of conditions and the following disclaimer.
15139112Sru * 2. Redistributions in binary form must reproduce the above copyright
16122097Sscottl *    notice, this list of conditions and the following disclaimer in the
1794663Sscottl *    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 101127 2002-08-01 01:21:40Z rwatson $
40 */
41
42#include "opt_ktrace.h"
43#include "opt_mac.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/mac.h>
50#include <sys/mutex.h>
51#include <sys/namei.h>
52#include <sys/vnode.h>
53#include <sys/mount.h>
54#include <sys/filedesc.h>
55#include <sys/proc.h>
56#ifdef KTRACE
57#include <sys/ktrace.h>
58#endif
59
60#include <vm/uma.h>
61
62/*
63 * Allocation zone for namei
64 */
65uma_zone_t namei_zone;
66
67static void
68nameiinit(void *dummy __unused)
69{
70	namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL,
71	    UMA_ALIGN_PTR, 0);
72
73}
74SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL)
75
76/*
77 * Convert a pathname into a pointer to a locked inode.
78 *
79 * The FOLLOW flag is set when symbolic links are to be followed
80 * when they occur at the end of the name translation process.
81 * Symbolic links are always followed for all other pathname
82 * components other than the last.
83 *
84 * The segflg defines whether the name is to be copied from user
85 * space or kernel space.
86 *
87 * Overall outline of namei:
88 *
89 *	copy in name
90 *	get starting directory
91 *	while (!done && !error) {
92 *		call lookup to search path.
93 *		if symbolic link, massage name in buffer and continue
94 *	}
95 */
96int
97namei(ndp)
98	register struct nameidata *ndp;
99{
100	register struct filedesc *fdp;	/* pointer to file descriptor state */
101	register char *cp;		/* pointer into pathname argument */
102	register struct vnode *dp;	/* the directory we are searching */
103	struct iovec aiov;		/* uio for reading symbolic links */
104	struct uio auio;
105	int error, linklen;
106	struct componentname *cnp = &ndp->ni_cnd;
107	struct thread *td = cnp->cn_thread;
108	struct proc *p = td->td_proc;
109
110	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred;
111	KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc"));
112	KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0,
113	    ("namei: nameiop contaminated with flags"));
114	KASSERT((cnp->cn_flags & OPMASK) == 0,
115	    ("namei: flags contaminated with nameiops"));
116	fdp = p->p_fd;
117
118	/*
119	 * Get a buffer for the name to be translated, and copy the
120	 * name into the buffer.
121	 */
122	if ((cnp->cn_flags & HASBUF) == 0)
123		cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
124	if (ndp->ni_segflg == UIO_SYSSPACE)
125		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
126			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
127	else
128		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
129			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
130
131	/*
132	 * Don't allow empty pathnames.
133	 */
134	if (!error && *cnp->cn_pnbuf == '\0')
135		error = ENOENT;
136
137	if (error) {
138		uma_zfree(namei_zone, cnp->cn_pnbuf);
139#ifdef DIAGNOSTIC
140		cnp->cn_pnbuf = NULL;
141		cnp->cn_nameptr = NULL;
142#endif
143		ndp->ni_vp = NULL;
144		return (error);
145	}
146	ndp->ni_loopcnt = 0;
147#ifdef KTRACE
148	if (KTRPOINT(td, KTR_NAMEI)) {
149		KASSERT(cnp->cn_thread == curthread,
150		    ("namei not using curthread"));
151		ktrnamei(cnp->cn_pnbuf);
152	}
153#endif
154
155	/*
156	 * Get starting point for the translation.
157	 */
158	FILEDESC_LOCK(fdp);
159	ndp->ni_rootdir = fdp->fd_rdir;
160	ndp->ni_topdir = fdp->fd_jdir;
161
162	dp = fdp->fd_cdir;
163	VREF(dp);
164	FILEDESC_UNLOCK(fdp);
165	for (;;) {
166		/*
167		 * Check if root directory should replace current directory.
168		 * Done at start of translation and after symbolic link.
169		 */
170		cnp->cn_nameptr = cnp->cn_pnbuf;
171		if (*(cnp->cn_nameptr) == '/') {
172			vrele(dp);
173			while (*(cnp->cn_nameptr) == '/') {
174				cnp->cn_nameptr++;
175				ndp->ni_pathlen--;
176			}
177			dp = ndp->ni_rootdir;
178			VREF(dp);
179		}
180		ndp->ni_startdir = dp;
181		error = lookup(ndp);
182		if (error) {
183			uma_zfree(namei_zone, cnp->cn_pnbuf);
184#ifdef DIAGNOSTIC
185			cnp->cn_pnbuf = NULL;
186			cnp->cn_nameptr = NULL;
187#endif
188			return (error);
189		}
190		/*
191		 * Check for symbolic link
192		 */
193		if ((cnp->cn_flags & ISSYMLINK) == 0) {
194			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) {
195				uma_zfree(namei_zone, cnp->cn_pnbuf);
196#ifdef DIAGNOSTIC
197				cnp->cn_pnbuf = NULL;
198				cnp->cn_nameptr = NULL;
199#endif
200			} else
201				cnp->cn_flags |= HASBUF;
202
203			if (vn_canvmio(ndp->ni_vp) == TRUE &&
204				(cnp->cn_nameiop != DELETE) &&
205				((cnp->cn_flags & (NOOBJ|LOCKLEAF)) ==
206				 LOCKLEAF))
207				vfs_object_create(ndp->ni_vp, td,
208					ndp->ni_cnd.cn_cred);
209
210			return (0);
211		}
212		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
213			VOP_UNLOCK(ndp->ni_dvp, 0, td);
214		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
215			error = ELOOP;
216			break;
217		}
218#ifdef MAC
219		error = mac_check_vnode_readlink(td->td_ucred, ndp->ni_vp);
220		if (error)
221			break;
222#endif
223		if (ndp->ni_pathlen > 1)
224			cp = uma_zalloc(namei_zone, M_WAITOK);
225		else
226			cp = cnp->cn_pnbuf;
227		aiov.iov_base = cp;
228		aiov.iov_len = MAXPATHLEN;
229		auio.uio_iov = &aiov;
230		auio.uio_iovcnt = 1;
231		auio.uio_offset = 0;
232		auio.uio_rw = UIO_READ;
233		auio.uio_segflg = UIO_SYSSPACE;
234		auio.uio_td = (struct thread *)0;
235		auio.uio_resid = MAXPATHLEN;
236		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
237		if (error) {
238			if (ndp->ni_pathlen > 1)
239				uma_zfree(namei_zone, cp);
240			break;
241		}
242		linklen = MAXPATHLEN - auio.uio_resid;
243		if (linklen == 0) {
244			if (ndp->ni_pathlen > 1)
245				uma_zfree(namei_zone, cp);
246			error = ENOENT;
247			break;
248		}
249		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
250			if (ndp->ni_pathlen > 1)
251				uma_zfree(namei_zone, cp);
252			error = ENAMETOOLONG;
253			break;
254		}
255		if (ndp->ni_pathlen > 1) {
256			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
257			uma_zfree(namei_zone, cnp->cn_pnbuf);
258			cnp->cn_pnbuf = cp;
259		} else
260			cnp->cn_pnbuf[linklen] = '\0';
261		ndp->ni_pathlen += linklen;
262		vput(ndp->ni_vp);
263		dp = ndp->ni_dvp;
264	}
265	uma_zfree(namei_zone, cnp->cn_pnbuf);
266#ifdef DIAGNOSTIC
267	cnp->cn_pnbuf = NULL;
268	cnp->cn_nameptr = NULL;
269#endif
270	vrele(ndp->ni_dvp);
271	vput(ndp->ni_vp);
272	ndp->ni_vp = NULL;
273	return (error);
274}
275
276/*
277 * Search a pathname.
278 * This is a very central and rather complicated routine.
279 *
280 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
281 * The starting directory is taken from ni_startdir. The pathname is
282 * descended until done, or a symbolic link is encountered. The variable
283 * ni_more is clear if the path is completed; it is set to one if a
284 * symbolic link needing interpretation is encountered.
285 *
286 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
287 * whether the name is to be looked up, created, renamed, or deleted.
288 * When CREATE, RENAME, or DELETE is specified, information usable in
289 * creating, renaming, or deleting a directory entry may be calculated.
290 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
291 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
292 * returned unlocked. Otherwise the parent directory is not returned. If
293 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
294 * the target is returned locked, otherwise it is returned unlocked.
295 * When creating or renaming and LOCKPARENT is specified, the target may not
296 * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
297 *
298 * Overall outline of lookup:
299 *
300 * dirloop:
301 *	identify next component of name at ndp->ni_ptr
302 *	handle degenerate case where name is null string
303 *	if .. and crossing mount points and on mounted filesys, find parent
304 *	call VOP_LOOKUP routine for next component name
305 *	    directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
306 *	    component vnode returned in ni_vp (if it exists), locked.
307 *	if result vnode is mounted on and crossing mount points,
308 *	    find mounted on vnode
309 *	if more components of name, do next level at dirloop
310 *	return the answer in ni_vp, locked if LOCKLEAF set
311 *	    if LOCKPARENT set, return locked parent in ni_dvp
312 *	    if WANTPARENT set, return unlocked parent in ni_dvp
313 */
314int
315lookup(ndp)
316	register struct nameidata *ndp;
317{
318	register char *cp;		/* pointer into pathname argument */
319	register struct vnode *dp = 0;	/* the directory we are searching */
320	struct vnode *tdp;		/* saved dp */
321	struct mount *mp;		/* mount table entry */
322	int docache;			/* == 0 do not cache last component */
323	int wantparent;			/* 1 => wantparent or lockparent flag */
324	int rdonly;			/* lookup read-only flag bit */
325	int trailing_slash;
326	int error = 0;
327	int dpunlocked = 0;		/* dp has already been unlocked */
328	struct componentname *cnp = &ndp->ni_cnd;
329	struct thread *td = cnp->cn_thread;
330
331	/*
332	 * Setup: break out flag bits into variables.
333	 */
334	wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
335	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
336	if (cnp->cn_nameiop == DELETE ||
337	    (wantparent && cnp->cn_nameiop != CREATE &&
338	     cnp->cn_nameiop != LOOKUP))
339		docache = 0;
340	rdonly = cnp->cn_flags & RDONLY;
341	ndp->ni_dvp = NULL;
342	cnp->cn_flags &= ~ISSYMLINK;
343	dp = ndp->ni_startdir;
344	ndp->ni_startdir = NULLVP;
345	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
346
347dirloop:
348	/*
349	 * Search a new directory.
350	 *
351	 * The last component of the filename is left accessible via
352	 * cnp->cn_nameptr for callers that need the name. Callers needing
353	 * the name set the SAVENAME flag. When done, they assume
354	 * responsibility for freeing the pathname buffer.
355	 */
356	cnp->cn_consume = 0;
357	for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
358		continue;
359	cnp->cn_namelen = cp - cnp->cn_nameptr;
360	if (cnp->cn_namelen > NAME_MAX) {
361		error = ENAMETOOLONG;
362		goto bad;
363	}
364#ifdef NAMEI_DIAGNOSTIC
365	{ char c = *cp;
366	*cp = '\0';
367	printf("{%s}: ", cnp->cn_nameptr);
368	*cp = c; }
369#endif
370	ndp->ni_pathlen -= cnp->cn_namelen;
371	ndp->ni_next = cp;
372
373	/*
374	 * Replace multiple slashes by a single slash and trailing slashes
375	 * by a null.  This must be done before VOP_LOOKUP() because some
376	 * fs's don't know about trailing slashes.  Remember if there were
377	 * trailing slashes to handle symlinks, existing non-directories
378	 * and non-existing files that won't be directories specially later.
379	 */
380	trailing_slash = 0;
381	while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
382		cp++;
383		ndp->ni_pathlen--;
384		if (*cp == '\0') {
385			trailing_slash = 1;
386			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
387		}
388	}
389	ndp->ni_next = cp;
390
391	cnp->cn_flags |= MAKEENTRY;
392	if (*cp == '\0' && docache == 0)
393		cnp->cn_flags &= ~MAKEENTRY;
394	if (cnp->cn_namelen == 2 &&
395	    cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
396		cnp->cn_flags |= ISDOTDOT;
397	else
398		cnp->cn_flags &= ~ISDOTDOT;
399	if (*ndp->ni_next == 0)
400		cnp->cn_flags |= ISLASTCN;
401	else
402		cnp->cn_flags &= ~ISLASTCN;
403
404
405	/*
406	 * Check for degenerate name (e.g. / or "")
407	 * which is a way of talking about a directory,
408	 * e.g. like "/." or ".".
409	 */
410	if (cnp->cn_nameptr[0] == '\0') {
411		if (dp->v_type != VDIR) {
412			error = ENOTDIR;
413			goto bad;
414		}
415		if (cnp->cn_nameiop != LOOKUP) {
416			error = EISDIR;
417			goto bad;
418		}
419		if (wantparent) {
420			ndp->ni_dvp = dp;
421			VREF(dp);
422		}
423		ndp->ni_vp = dp;
424		if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
425			VOP_UNLOCK(dp, 0, td);
426		/* XXX This should probably move to the top of function. */
427		if (cnp->cn_flags & SAVESTART)
428			panic("lookup: SAVESTART");
429		return (0);
430	}
431
432	/*
433	 * Handle "..": two special cases.
434	 * 1. If at root directory (e.g. after chroot)
435	 *    or at absolute root directory
436	 *    then ignore it so can't get out.
437	 * 2. If this vnode is the root of a mounted
438	 *    filesystem, then replace it with the
439	 *    vnode which was mounted on so we take the
440	 *    .. in the other filesystem.
441	 * 3. If the vnode is the top directory of
442	 *    the jail or chroot, don't let them out.
443	 */
444	if (cnp->cn_flags & ISDOTDOT) {
445		for (;;) {
446			if (dp == ndp->ni_rootdir ||
447			    dp == ndp->ni_topdir ||
448			    dp == rootvnode) {
449				ndp->ni_dvp = dp;
450				ndp->ni_vp = dp;
451				VREF(dp);
452				goto nextname;
453			}
454			if ((dp->v_flag & VROOT) == 0 ||
455			    (cnp->cn_flags & NOCROSSMOUNT))
456				break;
457			if (dp->v_mount == NULL) {	/* forced unmount */
458				error = EBADF;
459				goto bad;
460			}
461			tdp = dp;
462			dp = dp->v_mount->mnt_vnodecovered;
463			vput(tdp);
464			VREF(dp);
465			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
466		}
467	}
468
469	/*
470	 * We now have a segment name to search for, and a directory to search.
471	 */
472unionlookup:
473#ifdef MAC
474	error = mac_check_vnode_lookup(td->td_ucred, dp, cnp);
475	if (error)
476		goto bad;
477#endif
478	ndp->ni_dvp = dp;
479	ndp->ni_vp = NULL;
480	cnp->cn_flags &= ~PDIRUNLOCK;
481	ASSERT_VOP_LOCKED(dp, "lookup");
482	if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
483		KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
484#ifdef NAMEI_DIAGNOSTIC
485		printf("not found\n");
486#endif
487		if ((error == ENOENT) &&
488		    (dp->v_flag & VROOT) && (dp->v_mount != NULL) &&
489		    (dp->v_mount->mnt_flag & MNT_UNION)) {
490			tdp = dp;
491			dp = dp->v_mount->mnt_vnodecovered;
492			if (cnp->cn_flags & PDIRUNLOCK)
493				vrele(tdp);
494			else
495				vput(tdp);
496			VREF(dp);
497			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
498			goto unionlookup;
499		}
500
501		if (error != EJUSTRETURN)
502			goto bad;
503		/*
504		 * If creating and at end of pathname, then can consider
505		 * allowing file to be created.
506		 */
507		if (rdonly) {
508			error = EROFS;
509			goto bad;
510		}
511		if (*cp == '\0' && trailing_slash &&
512		     !(cnp->cn_flags & WILLBEDIR)) {
513			error = ENOENT;
514			goto bad;
515		}
516		/*
517		 * We return with ni_vp NULL to indicate that the entry
518		 * doesn't currently exist, leaving a pointer to the
519		 * (possibly locked) directory inode in ndp->ni_dvp.
520		 */
521		if (cnp->cn_flags & SAVESTART) {
522			ndp->ni_startdir = ndp->ni_dvp;
523			VREF(ndp->ni_startdir);
524		}
525		return (0);
526	}
527#ifdef NAMEI_DIAGNOSTIC
528	printf("found\n");
529#endif
530
531	ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup");
532
533	/*
534	 * Take into account any additional components consumed by
535	 * the underlying filesystem.
536	 */
537	if (cnp->cn_consume > 0) {
538		cnp->cn_nameptr += cnp->cn_consume;
539		ndp->ni_next += cnp->cn_consume;
540		ndp->ni_pathlen -= cnp->cn_consume;
541		cnp->cn_consume = 0;
542	}
543
544	dp = ndp->ni_vp;
545
546	/*
547	 * Check to see if the vnode has been mounted on;
548	 * if so find the root of the mounted filesystem.
549	 */
550	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
551	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
552		if (vfs_busy(mp, 0, 0, td))
553			continue;
554		VOP_UNLOCK(dp, 0, td);
555		error = VFS_ROOT(mp, &tdp);
556		vfs_unbusy(mp, td);
557		if (error) {
558			dpunlocked = 1;
559			goto bad2;
560		}
561		vrele(dp);
562		ndp->ni_vp = dp = tdp;
563	}
564
565	/*
566	 * Check for symbolic link
567	 */
568	if ((dp->v_type == VLNK) &&
569	    ((cnp->cn_flags & FOLLOW) || trailing_slash ||
570	     *ndp->ni_next == '/')) {
571		cnp->cn_flags |= ISSYMLINK;
572		if (dp->v_mount == NULL) {
573			/* We can't know whether the directory was mounted with
574			 * NOSYMFOLLOW, so we can't follow safely. */
575			error = EBADF;
576			goto bad2;
577		}
578		if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) {
579			error = EACCES;
580			goto bad2;
581		}
582		return (0);
583	}
584
585	/*
586	 * Check for bogus trailing slashes.
587	 */
588	if (trailing_slash && dp->v_type != VDIR) {
589		error = ENOTDIR;
590		goto bad2;
591	}
592
593nextname:
594	/*
595	 * Not a symbolic link.  If more pathname,
596	 * continue at next component, else return.
597	 */
598	if (*ndp->ni_next == '/') {
599		cnp->cn_nameptr = ndp->ni_next;
600		while (*cnp->cn_nameptr == '/') {
601			cnp->cn_nameptr++;
602			ndp->ni_pathlen--;
603		}
604		if (ndp->ni_dvp != ndp->ni_vp)
605			ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup");
606		vrele(ndp->ni_dvp);
607		goto dirloop;
608	}
609	/*
610	 * Disallow directory write attempts on read-only filesystems.
611	 */
612	if (rdonly &&
613	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
614		error = EROFS;
615		goto bad2;
616	}
617	if (cnp->cn_flags & SAVESTART) {
618		ndp->ni_startdir = ndp->ni_dvp;
619		VREF(ndp->ni_startdir);
620	}
621	if (!wantparent)
622		vrele(ndp->ni_dvp);
623
624	if ((cnp->cn_flags & LOCKLEAF) == 0)
625		VOP_UNLOCK(dp, 0, td);
626	return (0);
627
628bad2:
629	if ((cnp->cn_flags & (LOCKPARENT | PDIRUNLOCK)) == LOCKPARENT &&
630	    *ndp->ni_next == '\0')
631		VOP_UNLOCK(ndp->ni_dvp, 0, td);
632	vrele(ndp->ni_dvp);
633bad:
634	if (dpunlocked)
635		vrele(dp);
636	else
637		vput(dp);
638	ndp->ni_vp = NULL;
639	return (error);
640}
641
642/*
643 * relookup - lookup a path name component
644 *    Used by lookup to re-aquire things.
645 */
646int
647relookup(dvp, vpp, cnp)
648	struct vnode *dvp, **vpp;
649	struct componentname *cnp;
650{
651	struct thread *td = cnp->cn_thread;
652	struct vnode *dp = 0;		/* the directory we are searching */
653	int docache;			/* == 0 do not cache last component */
654	int wantparent;			/* 1 => wantparent or lockparent flag */
655	int rdonly;			/* lookup read-only flag bit */
656	int error = 0;
657#ifdef NAMEI_DIAGNOSTIC
658	int newhash;			/* DEBUG: check name hash */
659	char *cp;			/* DEBUG: check name ptr/len */
660#endif
661
662	/*
663	 * Setup: break out flag bits into variables.
664	 */
665	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
666	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
667	if (cnp->cn_nameiop == DELETE ||
668	    (wantparent && cnp->cn_nameiop != CREATE))
669		docache = 0;
670	rdonly = cnp->cn_flags & RDONLY;
671	cnp->cn_flags &= ~ISSYMLINK;
672	dp = dvp;
673	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
674
675/* dirloop: */
676	/*
677	 * Search a new directory.
678	 *
679	 * The last component of the filename is left accessible via
680	 * cnp->cn_nameptr for callers that need the name. Callers needing
681	 * the name set the SAVENAME flag. When done, they assume
682	 * responsibility for freeing the pathname buffer.
683	 */
684#ifdef NAMEI_DIAGNOSTIC
685	if (cnp->cn_namelen != cp - cnp->cn_nameptr)
686		panic ("relookup: bad len");
687	if (*cp != 0)
688		panic("relookup: not last component");
689	printf("{%s}: ", cnp->cn_nameptr);
690#endif
691
692	/*
693	 * Check for degenerate name (e.g. / or "")
694	 * which is a way of talking about a directory,
695	 * e.g. like "/." or ".".
696	 */
697	if (cnp->cn_nameptr[0] == '\0') {
698		if (cnp->cn_nameiop != LOOKUP || wantparent) {
699			error = EISDIR;
700			goto bad;
701		}
702		if (dp->v_type != VDIR) {
703			error = ENOTDIR;
704			goto bad;
705		}
706		if (!(cnp->cn_flags & LOCKLEAF))
707			VOP_UNLOCK(dp, 0, td);
708		*vpp = dp;
709		/* XXX This should probably move to the top of function. */
710		if (cnp->cn_flags & SAVESTART)
711			panic("lookup: SAVESTART");
712		return (0);
713	}
714
715	if (cnp->cn_flags & ISDOTDOT)
716		panic ("relookup: lookup on dot-dot");
717
718	/*
719	 * We now have a segment name to search for, and a directory to search.
720	 */
721	if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {
722		KASSERT(*vpp == NULL, ("leaf should be empty"));
723		if (error != EJUSTRETURN)
724			goto bad;
725		/*
726		 * If creating and at end of pathname, then can consider
727		 * allowing file to be created.
728		 */
729		if (rdonly) {
730			error = EROFS;
731			goto bad;
732		}
733		/* ASSERT(dvp == ndp->ni_startdir) */
734		if (cnp->cn_flags & SAVESTART)
735			VREF(dvp);
736		/*
737		 * We return with ni_vp NULL to indicate that the entry
738		 * doesn't currently exist, leaving a pointer to the
739		 * (possibly locked) directory inode in ndp->ni_dvp.
740		 */
741		return (0);
742	}
743	dp = *vpp;
744
745	/*
746	 * Check for symbolic link
747	 */
748	KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW),
749	    ("relookup: symlink found.\n"));
750
751	/*
752	 * Disallow directory write attempts on read-only filesystems.
753	 */
754	if (rdonly &&
755	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
756		error = EROFS;
757		goto bad2;
758	}
759	/* ASSERT(dvp == ndp->ni_startdir) */
760	if (cnp->cn_flags & SAVESTART)
761		VREF(dvp);
762
763	if (!wantparent)
764		vrele(dvp);
765
766	if (vn_canvmio(dp) == TRUE &&
767		((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
768		vfs_object_create(dp, td, cnp->cn_cred);
769
770	if ((cnp->cn_flags & LOCKLEAF) == 0)
771		VOP_UNLOCK(dp, 0, td);
772	return (0);
773
774bad2:
775	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
776		VOP_UNLOCK(dvp, 0, td);
777	vrele(dvp);
778bad:
779	vput(dp);
780	*vpp = NULL;
781	return (error);
782}
783