vfs_lookup.c revision 105479
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 105479 2002-10-19 21:25:51Z 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		if ((cnp->cn_flags & NOMACCHECK) == 0) {
220			error = mac_check_vnode_readlink(td->td_ucred,
221			    ndp->ni_vp);
222			if (error)
223				break;
224		}
225#endif
226		if (ndp->ni_pathlen > 1)
227			cp = uma_zalloc(namei_zone, M_WAITOK);
228		else
229			cp = cnp->cn_pnbuf;
230		aiov.iov_base = cp;
231		aiov.iov_len = MAXPATHLEN;
232		auio.uio_iov = &aiov;
233		auio.uio_iovcnt = 1;
234		auio.uio_offset = 0;
235		auio.uio_rw = UIO_READ;
236		auio.uio_segflg = UIO_SYSSPACE;
237		auio.uio_td = (struct thread *)0;
238		auio.uio_resid = MAXPATHLEN;
239		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
240		if (error) {
241			if (ndp->ni_pathlen > 1)
242				uma_zfree(namei_zone, cp);
243			break;
244		}
245		linklen = MAXPATHLEN - auio.uio_resid;
246		if (linklen == 0) {
247			if (ndp->ni_pathlen > 1)
248				uma_zfree(namei_zone, cp);
249			error = ENOENT;
250			break;
251		}
252		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
253			if (ndp->ni_pathlen > 1)
254				uma_zfree(namei_zone, cp);
255			error = ENAMETOOLONG;
256			break;
257		}
258		if (ndp->ni_pathlen > 1) {
259			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
260			uma_zfree(namei_zone, cnp->cn_pnbuf);
261			cnp->cn_pnbuf = cp;
262		} else
263			cnp->cn_pnbuf[linklen] = '\0';
264		ndp->ni_pathlen += linklen;
265		vput(ndp->ni_vp);
266		dp = ndp->ni_dvp;
267	}
268	uma_zfree(namei_zone, cnp->cn_pnbuf);
269#ifdef DIAGNOSTIC
270	cnp->cn_pnbuf = NULL;
271	cnp->cn_nameptr = NULL;
272#endif
273	vrele(ndp->ni_dvp);
274	vput(ndp->ni_vp);
275	ndp->ni_vp = NULL;
276	return (error);
277}
278
279/*
280 * Search a pathname.
281 * This is a very central and rather complicated routine.
282 *
283 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
284 * The starting directory is taken from ni_startdir. The pathname is
285 * descended until done, or a symbolic link is encountered. The variable
286 * ni_more is clear if the path is completed; it is set to one if a
287 * symbolic link needing interpretation is encountered.
288 *
289 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
290 * whether the name is to be looked up, created, renamed, or deleted.
291 * When CREATE, RENAME, or DELETE is specified, information usable in
292 * creating, renaming, or deleting a directory entry may be calculated.
293 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
294 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
295 * returned unlocked. Otherwise the parent directory is not returned. If
296 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
297 * the target is returned locked, otherwise it is returned unlocked.
298 * When creating or renaming and LOCKPARENT is specified, the target may not
299 * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
300 *
301 * Overall outline of lookup:
302 *
303 * dirloop:
304 *	identify next component of name at ndp->ni_ptr
305 *	handle degenerate case where name is null string
306 *	if .. and crossing mount points and on mounted filesys, find parent
307 *	call VOP_LOOKUP routine for next component name
308 *	    directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
309 *	    component vnode returned in ni_vp (if it exists), locked.
310 *	if result vnode is mounted on and crossing mount points,
311 *	    find mounted on vnode
312 *	if more components of name, do next level at dirloop
313 *	return the answer in ni_vp, locked if LOCKLEAF set
314 *	    if LOCKPARENT set, return locked parent in ni_dvp
315 *	    if WANTPARENT set, return unlocked parent in ni_dvp
316 */
317int
318lookup(ndp)
319	register struct nameidata *ndp;
320{
321	register char *cp;		/* pointer into pathname argument */
322	register struct vnode *dp = 0;	/* the directory we are searching */
323	struct vnode *tdp;		/* saved dp */
324	struct mount *mp;		/* mount table entry */
325	int docache;			/* == 0 do not cache last component */
326	int wantparent;			/* 1 => wantparent or lockparent flag */
327	int rdonly;			/* lookup read-only flag bit */
328	int trailing_slash;
329	int error = 0;
330	int dpunlocked = 0;		/* dp has already been unlocked */
331	struct componentname *cnp = &ndp->ni_cnd;
332	struct thread *td = cnp->cn_thread;
333
334	/*
335	 * Setup: break out flag bits into variables.
336	 */
337	wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
338	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
339	if (cnp->cn_nameiop == DELETE ||
340	    (wantparent && cnp->cn_nameiop != CREATE &&
341	     cnp->cn_nameiop != LOOKUP))
342		docache = 0;
343	rdonly = cnp->cn_flags & RDONLY;
344	ndp->ni_dvp = NULL;
345	cnp->cn_flags &= ~ISSYMLINK;
346	dp = ndp->ni_startdir;
347	ndp->ni_startdir = NULLVP;
348	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
349
350dirloop:
351	/*
352	 * Search a new directory.
353	 *
354	 * The last component of the filename is left accessible via
355	 * cnp->cn_nameptr for callers that need the name. Callers needing
356	 * the name set the SAVENAME flag. When done, they assume
357	 * responsibility for freeing the pathname buffer.
358	 */
359	cnp->cn_consume = 0;
360	for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
361		continue;
362	cnp->cn_namelen = cp - cnp->cn_nameptr;
363	if (cnp->cn_namelen > NAME_MAX) {
364		error = ENAMETOOLONG;
365		goto bad;
366	}
367#ifdef NAMEI_DIAGNOSTIC
368	{ char c = *cp;
369	*cp = '\0';
370	printf("{%s}: ", cnp->cn_nameptr);
371	*cp = c; }
372#endif
373	ndp->ni_pathlen -= cnp->cn_namelen;
374	ndp->ni_next = cp;
375
376	/*
377	 * Replace multiple slashes by a single slash and trailing slashes
378	 * by a null.  This must be done before VOP_LOOKUP() because some
379	 * fs's don't know about trailing slashes.  Remember if there were
380	 * trailing slashes to handle symlinks, existing non-directories
381	 * and non-existing files that won't be directories specially later.
382	 */
383	trailing_slash = 0;
384	while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
385		cp++;
386		ndp->ni_pathlen--;
387		if (*cp == '\0') {
388			trailing_slash = 1;
389			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
390		}
391	}
392	ndp->ni_next = cp;
393
394	cnp->cn_flags |= MAKEENTRY;
395	if (*cp == '\0' && docache == 0)
396		cnp->cn_flags &= ~MAKEENTRY;
397	if (cnp->cn_namelen == 2 &&
398	    cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
399		cnp->cn_flags |= ISDOTDOT;
400	else
401		cnp->cn_flags &= ~ISDOTDOT;
402	if (*ndp->ni_next == 0)
403		cnp->cn_flags |= ISLASTCN;
404	else
405		cnp->cn_flags &= ~ISLASTCN;
406
407
408	/*
409	 * Check for degenerate name (e.g. / or "")
410	 * which is a way of talking about a directory,
411	 * e.g. like "/." or ".".
412	 */
413	if (cnp->cn_nameptr[0] == '\0') {
414		if (dp->v_type != VDIR) {
415			error = ENOTDIR;
416			goto bad;
417		}
418		if (cnp->cn_nameiop != LOOKUP) {
419			error = EISDIR;
420			goto bad;
421		}
422		if (wantparent) {
423			ndp->ni_dvp = dp;
424			VREF(dp);
425		}
426		ndp->ni_vp = dp;
427		if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
428			VOP_UNLOCK(dp, 0, td);
429		/* XXX This should probably move to the top of function. */
430		if (cnp->cn_flags & SAVESTART)
431			panic("lookup: SAVESTART");
432		return (0);
433	}
434
435	/*
436	 * Handle "..": two special cases.
437	 * 1. If at root directory (e.g. after chroot)
438	 *    or at absolute root directory
439	 *    then ignore it so can't get out.
440	 * 2. If this vnode is the root of a mounted
441	 *    filesystem, then replace it with the
442	 *    vnode which was mounted on so we take the
443	 *    .. in the other filesystem.
444	 * 3. If the vnode is the top directory of
445	 *    the jail or chroot, don't let them out.
446	 */
447	if (cnp->cn_flags & ISDOTDOT) {
448		for (;;) {
449			if (dp == ndp->ni_rootdir ||
450			    dp == ndp->ni_topdir ||
451			    dp == rootvnode) {
452				ndp->ni_dvp = dp;
453				ndp->ni_vp = dp;
454				VREF(dp);
455				goto nextname;
456			}
457			if ((dp->v_vflag & VV_ROOT) == 0 ||
458			    (cnp->cn_flags & NOCROSSMOUNT))
459				break;
460			if (dp->v_mount == NULL) {	/* forced unmount */
461				error = EBADF;
462				goto bad;
463			}
464			tdp = dp;
465			dp = dp->v_mount->mnt_vnodecovered;
466			vput(tdp);
467			VREF(dp);
468			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
469		}
470	}
471
472	/*
473	 * We now have a segment name to search for, and a directory to search.
474	 */
475unionlookup:
476#ifdef MAC
477	if ((cnp->cn_flags & NOMACCHECK) == 0) {
478		error = mac_check_vnode_lookup(td->td_ucred, dp, cnp);
479		if (error)
480			goto bad;
481	}
482#endif
483	ndp->ni_dvp = dp;
484	ndp->ni_vp = NULL;
485	cnp->cn_flags &= ~PDIRUNLOCK;
486	ASSERT_VOP_LOCKED(dp, "lookup");
487	if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
488		KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
489#ifdef NAMEI_DIAGNOSTIC
490		printf("not found\n");
491#endif
492		if ((error == ENOENT) &&
493		    (dp->v_vflag & VV_ROOT) && (dp->v_mount != NULL) &&
494		    (dp->v_mount->mnt_flag & MNT_UNION)) {
495			tdp = dp;
496			dp = dp->v_mount->mnt_vnodecovered;
497			if (cnp->cn_flags & PDIRUNLOCK)
498				vrele(tdp);
499			else
500				vput(tdp);
501			VREF(dp);
502			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
503			goto unionlookup;
504		}
505
506		if (error != EJUSTRETURN)
507			goto bad;
508		/*
509		 * If creating and at end of pathname, then can consider
510		 * allowing file to be created.
511		 */
512		if (rdonly) {
513			error = EROFS;
514			goto bad;
515		}
516		if (*cp == '\0' && trailing_slash &&
517		     !(cnp->cn_flags & WILLBEDIR)) {
518			error = ENOENT;
519			goto bad;
520		}
521		/*
522		 * We return with ni_vp NULL to indicate that the entry
523		 * doesn't currently exist, leaving a pointer to the
524		 * (possibly locked) directory inode in ndp->ni_dvp.
525		 */
526		if (cnp->cn_flags & SAVESTART) {
527			ndp->ni_startdir = ndp->ni_dvp;
528			VREF(ndp->ni_startdir);
529		}
530		return (0);
531	}
532#ifdef NAMEI_DIAGNOSTIC
533	printf("found\n");
534#endif
535
536	ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup");
537
538	/*
539	 * Take into account any additional components consumed by
540	 * the underlying filesystem.
541	 */
542	if (cnp->cn_consume > 0) {
543		cnp->cn_nameptr += cnp->cn_consume;
544		ndp->ni_next += cnp->cn_consume;
545		ndp->ni_pathlen -= cnp->cn_consume;
546		cnp->cn_consume = 0;
547	}
548
549	dp = ndp->ni_vp;
550
551	/*
552	 * Check to see if the vnode has been mounted on;
553	 * if so find the root of the mounted filesystem.
554	 */
555	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
556	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
557		if (vfs_busy(mp, 0, 0, td))
558			continue;
559		VOP_UNLOCK(dp, 0, td);
560		error = VFS_ROOT(mp, &tdp);
561		vfs_unbusy(mp, td);
562		if (error) {
563			dpunlocked = 1;
564			goto bad2;
565		}
566		vrele(dp);
567		ndp->ni_vp = dp = tdp;
568	}
569
570	/*
571	 * Check for symbolic link
572	 */
573	if ((dp->v_type == VLNK) &&
574	    ((cnp->cn_flags & FOLLOW) || trailing_slash ||
575	     *ndp->ni_next == '/')) {
576		cnp->cn_flags |= ISSYMLINK;
577		if (dp->v_mount == NULL) {
578			/* We can't know whether the directory was mounted with
579			 * NOSYMFOLLOW, so we can't follow safely. */
580			error = EBADF;
581			goto bad2;
582		}
583		if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) {
584			error = EACCES;
585			goto bad2;
586		}
587		return (0);
588	}
589
590	/*
591	 * Check for bogus trailing slashes.
592	 */
593	if (trailing_slash && dp->v_type != VDIR) {
594		error = ENOTDIR;
595		goto bad2;
596	}
597
598nextname:
599	/*
600	 * Not a symbolic link.  If more pathname,
601	 * continue at next component, else return.
602	 */
603	if (*ndp->ni_next == '/') {
604		cnp->cn_nameptr = ndp->ni_next;
605		while (*cnp->cn_nameptr == '/') {
606			cnp->cn_nameptr++;
607			ndp->ni_pathlen--;
608		}
609		if (ndp->ni_dvp != ndp->ni_vp)
610			ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup");
611		vrele(ndp->ni_dvp);
612		goto dirloop;
613	}
614	/*
615	 * Disallow directory write attempts on read-only filesystems.
616	 */
617	if (rdonly &&
618	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
619		error = EROFS;
620		goto bad2;
621	}
622	if (cnp->cn_flags & SAVESTART) {
623		ndp->ni_startdir = ndp->ni_dvp;
624		VREF(ndp->ni_startdir);
625	}
626	if (!wantparent)
627		vrele(ndp->ni_dvp);
628
629	if ((cnp->cn_flags & LOCKLEAF) == 0)
630		VOP_UNLOCK(dp, 0, td);
631	return (0);
632
633bad2:
634	if ((cnp->cn_flags & (LOCKPARENT | PDIRUNLOCK)) == LOCKPARENT &&
635	    *ndp->ni_next == '\0')
636		VOP_UNLOCK(ndp->ni_dvp, 0, td);
637	vrele(ndp->ni_dvp);
638bad:
639	if (dpunlocked)
640		vrele(dp);
641	else
642		vput(dp);
643	ndp->ni_vp = NULL;
644	return (error);
645}
646
647/*
648 * relookup - lookup a path name component
649 *    Used by lookup to re-aquire things.
650 */
651int
652relookup(dvp, vpp, cnp)
653	struct vnode *dvp, **vpp;
654	struct componentname *cnp;
655{
656	struct thread *td = cnp->cn_thread;
657	struct vnode *dp = 0;		/* the directory we are searching */
658	int docache;			/* == 0 do not cache last component */
659	int wantparent;			/* 1 => wantparent or lockparent flag */
660	int rdonly;			/* lookup read-only flag bit */
661	int error = 0;
662#ifdef NAMEI_DIAGNOSTIC
663	int newhash;			/* DEBUG: check name hash */
664	char *cp;			/* DEBUG: check name ptr/len */
665#endif
666
667	/*
668	 * Setup: break out flag bits into variables.
669	 */
670	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
671	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
672	if (cnp->cn_nameiop == DELETE ||
673	    (wantparent && cnp->cn_nameiop != CREATE))
674		docache = 0;
675	rdonly = cnp->cn_flags & RDONLY;
676	cnp->cn_flags &= ~ISSYMLINK;
677	dp = dvp;
678	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
679
680/* dirloop: */
681	/*
682	 * Search a new directory.
683	 *
684	 * The last component of the filename is left accessible via
685	 * cnp->cn_nameptr for callers that need the name. Callers needing
686	 * the name set the SAVENAME flag. When done, they assume
687	 * responsibility for freeing the pathname buffer.
688	 */
689#ifdef NAMEI_DIAGNOSTIC
690	if (cnp->cn_namelen != cp - cnp->cn_nameptr)
691		panic ("relookup: bad len");
692	if (*cp != 0)
693		panic("relookup: not last component");
694	printf("{%s}: ", cnp->cn_nameptr);
695#endif
696
697	/*
698	 * Check for degenerate name (e.g. / or "")
699	 * which is a way of talking about a directory,
700	 * e.g. like "/." or ".".
701	 */
702	if (cnp->cn_nameptr[0] == '\0') {
703		if (cnp->cn_nameiop != LOOKUP || wantparent) {
704			error = EISDIR;
705			goto bad;
706		}
707		if (dp->v_type != VDIR) {
708			error = ENOTDIR;
709			goto bad;
710		}
711		if (!(cnp->cn_flags & LOCKLEAF))
712			VOP_UNLOCK(dp, 0, td);
713		*vpp = dp;
714		/* XXX This should probably move to the top of function. */
715		if (cnp->cn_flags & SAVESTART)
716			panic("lookup: SAVESTART");
717		return (0);
718	}
719
720	if (cnp->cn_flags & ISDOTDOT)
721		panic ("relookup: lookup on dot-dot");
722
723	/*
724	 * We now have a segment name to search for, and a directory to search.
725	 */
726	if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {
727		KASSERT(*vpp == NULL, ("leaf should be empty"));
728		if (error != EJUSTRETURN)
729			goto bad;
730		/*
731		 * If creating and at end of pathname, then can consider
732		 * allowing file to be created.
733		 */
734		if (rdonly) {
735			error = EROFS;
736			goto bad;
737		}
738		/* ASSERT(dvp == ndp->ni_startdir) */
739		if (cnp->cn_flags & SAVESTART)
740			VREF(dvp);
741		/*
742		 * We return with ni_vp NULL to indicate that the entry
743		 * doesn't currently exist, leaving a pointer to the
744		 * (possibly locked) directory inode in ndp->ni_dvp.
745		 */
746		return (0);
747	}
748	dp = *vpp;
749
750	/*
751	 * Check for symbolic link
752	 */
753	KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW),
754	    ("relookup: symlink found.\n"));
755
756	/*
757	 * Disallow directory write attempts on read-only filesystems.
758	 */
759	if (rdonly &&
760	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
761		error = EROFS;
762		goto bad2;
763	}
764	/* ASSERT(dvp == ndp->ni_startdir) */
765	if (cnp->cn_flags & SAVESTART)
766		VREF(dvp);
767
768	if (!wantparent)
769		vrele(dvp);
770
771	if (vn_canvmio(dp) == TRUE &&
772		((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
773		vfs_object_create(dp, td, cnp->cn_cred);
774
775	if ((cnp->cn_flags & LOCKLEAF) == 0)
776		VOP_UNLOCK(dp, 0, td);
777	return (0);
778
779bad2:
780	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
781		VOP_UNLOCK(dvp, 0, td);
782	vrele(dvp);
783bad:
784	vput(dp);
785	*vpp = NULL;
786	return (error);
787}
788