vfs_lookup.c revision 154690
1139804Simp/*-
21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes * (c) UNIX System Laboratories, Inc.
51541Srgrimes * All or some portions of this file are derived from material licensed
61541Srgrimes * to the University of California by American Telephone and Telegraph
71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81541Srgrimes * the permission of UNIX System Laboratories, Inc.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 4. Neither the name of the University nor the names of its contributors
191541Srgrimes *    may be used to endorse or promote products derived from this software
201541Srgrimes *    without specific prior written permission.
211541Srgrimes *
221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321541Srgrimes * SUCH DAMAGE.
331541Srgrimes *
341541Srgrimes *	@(#)vfs_lookup.c	8.4 (Berkeley) 2/16/94
351541Srgrimes */
361541Srgrimes
37116182Sobrien#include <sys/cdefs.h>
38116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/vfs_lookup.c 154690 2006-01-22 19:37:02Z truckman $");
39116182Sobrien
4013203Swollman#include "opt_ktrace.h"
41101127Srwatson#include "opt_mac.h"
42144613Sjeff#include "opt_vfs.h"
4313203Swollman
441541Srgrimes#include <sys/param.h>
452112Swollman#include <sys/systm.h>
4669664Speter#include <sys/kernel.h>
4776166Smarkm#include <sys/lock.h>
48101127Srwatson#include <sys/mac.h>
4989316Salfred#include <sys/mutex.h>
501541Srgrimes#include <sys/namei.h>
511541Srgrimes#include <sys/vnode.h>
521541Srgrimes#include <sys/mount.h>
531541Srgrimes#include <sys/filedesc.h>
541541Srgrimes#include <sys/proc.h>
55141471Sjhb#include <sys/syscallsubr.h>
56144613Sjeff#include <sys/sysctl.h>
571541Srgrimes#ifdef KTRACE
581541Srgrimes#include <sys/ktrace.h>
591541Srgrimes#endif
601541Srgrimes
6192751Sjeff#include <vm/uma.h>
6232011Sbde
63138345Sphk#define NAMEI_DIAGNOSTIC 1
64138345Sphk#undef NAMEI_DIAGNOSTIC
65138345Sphk
661541Srgrimes/*
6769664Speter * Allocation zone for namei
6869664Speter */
6992751Sjeffuma_zone_t namei_zone;
7069664Speter
7169664Speterstatic void
7269664Speternameiinit(void *dummy __unused)
7369664Speter{
7492654Sjeff	namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL,
7592654Sjeff	    UMA_ALIGN_PTR, 0);
7669664Speter
7769664Speter}
7869664SpeterSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL)
7969664Speter
80144613Sjeff#ifdef LOOKUP_SHARED
81144613Sjeffstatic int lookup_shared = 1;
82144613Sjeff#else
83144613Sjeffstatic int lookup_shared = 0;
84144613Sjeff#endif
85144613SjeffSYSCTL_INT(_vfs, OID_AUTO, lookup_shared, CTLFLAG_RW, &lookup_shared, 0,
86144613Sjeff    "Enables/Disables shared locks for path name translation");
87144613Sjeff
8869664Speter/*
891541Srgrimes * Convert a pathname into a pointer to a locked inode.
901541Srgrimes *
911541Srgrimes * The FOLLOW flag is set when symbolic links are to be followed
921541Srgrimes * when they occur at the end of the name translation process.
931541Srgrimes * Symbolic links are always followed for all other pathname
941541Srgrimes * components other than the last.
951541Srgrimes *
961541Srgrimes * The segflg defines whether the name is to be copied from user
971541Srgrimes * space or kernel space.
981541Srgrimes *
991541Srgrimes * Overall outline of namei:
1001541Srgrimes *
1011541Srgrimes *	copy in name
1021541Srgrimes *	get starting directory
1031541Srgrimes *	while (!done && !error) {
1041541Srgrimes *		call lookup to search path.
1051541Srgrimes *		if symbolic link, massage name in buffer and continue
1061541Srgrimes *	}
1071541Srgrimes */
1081541Srgrimesint
1091541Srgrimesnamei(ndp)
1101541Srgrimes	register struct nameidata *ndp;
1111541Srgrimes{
1121541Srgrimes	register struct filedesc *fdp;	/* pointer to file descriptor state */
1131541Srgrimes	register char *cp;		/* pointer into pathname argument */
1141541Srgrimes	register struct vnode *dp;	/* the directory we are searching */
1151541Srgrimes	struct iovec aiov;		/* uio for reading symbolic links */
1161541Srgrimes	struct uio auio;
1171541Srgrimes	int error, linklen;
1181541Srgrimes	struct componentname *cnp = &ndp->ni_cnd;
11983366Sjulian	struct thread *td = cnp->cn_thread;
12083366Sjulian	struct proc *p = td->td_proc;
121140714Sjeff	int vfslocked;
1221541Srgrimes
123150164Scsjp	KASSERT((cnp->cn_flags & MPSAFE) != 0 || mtx_owned(&Giant) != 0,
124150164Scsjp	    ("NOT MPSAFE and Giant not held"));
12591419Sjhb	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred;
12683366Sjulian	KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc"));
12742408Seivind	KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0,
12842453Seivind	    ("namei: nameiop contaminated with flags"));
12942408Seivind	KASSERT((cnp->cn_flags & OPMASK) == 0,
13042453Seivind	    ("namei: flags contaminated with nameiops"));
131144613Sjeff	if (!lookup_shared)
132144613Sjeff		cnp->cn_flags &= ~LOCKSHARED;
13383366Sjulian	fdp = p->p_fd;
1341541Srgrimes
1351541Srgrimes	/*
1361541Srgrimes	 * Get a buffer for the name to be translated, and copy the
1371541Srgrimes	 * name into the buffer.
1381541Srgrimes	 */
1391541Srgrimes	if ((cnp->cn_flags & HASBUF) == 0)
140111119Simp		cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
1411541Srgrimes	if (ndp->ni_segflg == UIO_SYSSPACE)
1421541Srgrimes		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
14336735Sdfr			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
1441541Srgrimes	else
1451541Srgrimes		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
14636735Sdfr			    MAXPATHLEN, (size_t *)&ndp->ni_pathlen);
14720069Sbde
14820069Sbde	/*
14920069Sbde	 * Don't allow empty pathnames.
15020069Sbde	 */
15120069Sbde	if (!error && *cnp->cn_pnbuf == '\0')
15220069Sbde		error = ENOENT;
15320069Sbde
1541541Srgrimes	if (error) {
15592751Sjeff		uma_zfree(namei_zone, cnp->cn_pnbuf);
156100613Srwatson#ifdef DIAGNOSTIC
157100613Srwatson		cnp->cn_pnbuf = NULL;
158100613Srwatson		cnp->cn_nameptr = NULL;
159100613Srwatson#endif
1601541Srgrimes		ndp->ni_vp = NULL;
1611541Srgrimes		return (error);
1621541Srgrimes	}
1631541Srgrimes	ndp->ni_loopcnt = 0;
1641541Srgrimes#ifdef KTRACE
16597994Sjhb	if (KTRPOINT(td, KTR_NAMEI)) {
16697994Sjhb		KASSERT(cnp->cn_thread == curthread,
16797994Sjhb		    ("namei not using curthread"));
16897994Sjhb		ktrnamei(cnp->cn_pnbuf);
16997994Sjhb	}
1701541Srgrimes#endif
1711541Srgrimes
1721541Srgrimes	/*
1731541Srgrimes	 * Get starting point for the translation.
1741541Srgrimes	 */
17589306Salfred	FILEDESC_LOCK(fdp);
17633360Sdyson	ndp->ni_rootdir = fdp->fd_rdir;
17751649Sphk	ndp->ni_topdir = fdp->fd_jdir;
17833360Sdyson
1791541Srgrimes	dp = fdp->fd_cdir;
180140714Sjeff	vfslocked = VFS_LOCK_GIANT(dp->v_mount);
1811541Srgrimes	VREF(dp);
18289306Salfred	FILEDESC_UNLOCK(fdp);
1831541Srgrimes	for (;;) {
1841541Srgrimes		/*
1851541Srgrimes		 * Check if root directory should replace current directory.
1861541Srgrimes		 * Done at start of translation and after symbolic link.
1871541Srgrimes		 */
1881541Srgrimes		cnp->cn_nameptr = cnp->cn_pnbuf;
1891541Srgrimes		if (*(cnp->cn_nameptr) == '/') {
1901541Srgrimes			vrele(dp);
191140714Sjeff			VFS_UNLOCK_GIANT(vfslocked);
1921541Srgrimes			while (*(cnp->cn_nameptr) == '/') {
1931541Srgrimes				cnp->cn_nameptr++;
1941541Srgrimes				ndp->ni_pathlen--;
1951541Srgrimes			}
1961541Srgrimes			dp = ndp->ni_rootdir;
197140714Sjeff			vfslocked = VFS_LOCK_GIANT(dp->v_mount);
1981541Srgrimes			VREF(dp);
1991541Srgrimes		}
200140714Sjeff		if (vfslocked)
201140714Sjeff			ndp->ni_cnd.cn_flags |= GIANTHELD;
2021541Srgrimes		ndp->ni_startdir = dp;
2033148Sphk		error = lookup(ndp);
2043148Sphk		if (error) {
20592751Sjeff			uma_zfree(namei_zone, cnp->cn_pnbuf);
206100613Srwatson#ifdef DIAGNOSTIC
207100613Srwatson			cnp->cn_pnbuf = NULL;
208100613Srwatson			cnp->cn_nameptr = NULL;
209100613Srwatson#endif
2101541Srgrimes			return (error);
2111541Srgrimes		}
212140714Sjeff		vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
213140714Sjeff		ndp->ni_cnd.cn_flags &= ~GIANTHELD;
2141541Srgrimes		/*
2151541Srgrimes		 * Check for symbolic link
2161541Srgrimes		 */
2171541Srgrimes		if ((cnp->cn_flags & ISSYMLINK) == 0) {
218100613Srwatson			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) {
21992751Sjeff				uma_zfree(namei_zone, cnp->cn_pnbuf);
220100613Srwatson#ifdef DIAGNOSTIC
221100613Srwatson				cnp->cn_pnbuf = NULL;
222100613Srwatson				cnp->cn_nameptr = NULL;
223100613Srwatson#endif
224100613Srwatson			} else
2251541Srgrimes				cnp->cn_flags |= HASBUF;
22632286Sdyson
227140714Sjeff			if ((cnp->cn_flags & MPSAFE) == 0) {
228140714Sjeff				VFS_UNLOCK_GIANT(vfslocked);
229140714Sjeff			} else if (vfslocked)
230140714Sjeff				ndp->ni_cnd.cn_flags |= GIANTHELD;
2311541Srgrimes			return (0);
2321541Srgrimes		}
2331541Srgrimes		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
2341541Srgrimes			error = ELOOP;
2351541Srgrimes			break;
2361541Srgrimes		}
237101127Srwatson#ifdef MAC
238105479Srwatson		if ((cnp->cn_flags & NOMACCHECK) == 0) {
239105479Srwatson			error = mac_check_vnode_readlink(td->td_ucred,
240105479Srwatson			    ndp->ni_vp);
241105479Srwatson			if (error)
242105479Srwatson				break;
243105479Srwatson		}
244101127Srwatson#endif
2451541Srgrimes		if (ndp->ni_pathlen > 1)
246111119Simp			cp = uma_zalloc(namei_zone, M_WAITOK);
2471541Srgrimes		else
2481541Srgrimes			cp = cnp->cn_pnbuf;
2491541Srgrimes		aiov.iov_base = cp;
2501541Srgrimes		aiov.iov_len = MAXPATHLEN;
2511541Srgrimes		auio.uio_iov = &aiov;
2521541Srgrimes		auio.uio_iovcnt = 1;
2531541Srgrimes		auio.uio_offset = 0;
2541541Srgrimes		auio.uio_rw = UIO_READ;
2551541Srgrimes		auio.uio_segflg = UIO_SYSSPACE;
25683366Sjulian		auio.uio_td = (struct thread *)0;
2571541Srgrimes		auio.uio_resid = MAXPATHLEN;
2583148Sphk		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
2593148Sphk		if (error) {
2601541Srgrimes			if (ndp->ni_pathlen > 1)
26192751Sjeff				uma_zfree(namei_zone, cp);
2621541Srgrimes			break;
2631541Srgrimes		}
2641541Srgrimes		linklen = MAXPATHLEN - auio.uio_resid;
26578692Sdillon		if (linklen == 0) {
26678692Sdillon			if (ndp->ni_pathlen > 1)
26792751Sjeff				uma_zfree(namei_zone, cp);
26878692Sdillon			error = ENOENT;
26978692Sdillon			break;
27078692Sdillon		}
2711541Srgrimes		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
2721541Srgrimes			if (ndp->ni_pathlen > 1)
27392751Sjeff				uma_zfree(namei_zone, cp);
2741541Srgrimes			error = ENAMETOOLONG;
2751541Srgrimes			break;
2761541Srgrimes		}
2771541Srgrimes		if (ndp->ni_pathlen > 1) {
2781541Srgrimes			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
27992751Sjeff			uma_zfree(namei_zone, cnp->cn_pnbuf);
2801541Srgrimes			cnp->cn_pnbuf = cp;
2811541Srgrimes		} else
2821541Srgrimes			cnp->cn_pnbuf[linklen] = '\0';
2831541Srgrimes		ndp->ni_pathlen += linklen;
2841541Srgrimes		vput(ndp->ni_vp);
2851541Srgrimes		dp = ndp->ni_dvp;
2861541Srgrimes	}
28792751Sjeff	uma_zfree(namei_zone, cnp->cn_pnbuf);
288100613Srwatson#ifdef DIAGNOSTIC
289100613Srwatson	cnp->cn_pnbuf = NULL;
290100613Srwatson	cnp->cn_nameptr = NULL;
291100613Srwatson#endif
292144833Sjeff	vput(ndp->ni_vp);
293144833Sjeff	ndp->ni_vp = NULL;
2941541Srgrimes	vrele(ndp->ni_dvp);
295140714Sjeff	VFS_UNLOCK_GIANT(vfslocked);
2961541Srgrimes	return (error);
2971541Srgrimes}
2981541Srgrimes
2991541Srgrimes/*
3001541Srgrimes * Search a pathname.
3011541Srgrimes * This is a very central and rather complicated routine.
3021541Srgrimes *
3031541Srgrimes * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
3041541Srgrimes * The starting directory is taken from ni_startdir. The pathname is
3051541Srgrimes * descended until done, or a symbolic link is encountered. The variable
3061541Srgrimes * ni_more is clear if the path is completed; it is set to one if a
3071541Srgrimes * symbolic link needing interpretation is encountered.
3081541Srgrimes *
3091541Srgrimes * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
3101541Srgrimes * whether the name is to be looked up, created, renamed, or deleted.
3111541Srgrimes * When CREATE, RENAME, or DELETE is specified, information usable in
3121541Srgrimes * creating, renaming, or deleting a directory entry may be calculated.
3131541Srgrimes * If flag has LOCKPARENT or'ed into it, the parent directory is returned
3141541Srgrimes * locked. If flag has WANTPARENT or'ed into it, the parent directory is
3151541Srgrimes * returned unlocked. Otherwise the parent directory is not returned. If
3161541Srgrimes * the target of the pathname exists and LOCKLEAF is or'ed into the flag
3171541Srgrimes * the target is returned locked, otherwise it is returned unlocked.
3181541Srgrimes * When creating or renaming and LOCKPARENT is specified, the target may not
3191541Srgrimes * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
3208876Srgrimes *
3211541Srgrimes * Overall outline of lookup:
3221541Srgrimes *
3231541Srgrimes * dirloop:
3241541Srgrimes *	identify next component of name at ndp->ni_ptr
3251541Srgrimes *	handle degenerate case where name is null string
3261541Srgrimes *	if .. and crossing mount points and on mounted filesys, find parent
3271541Srgrimes *	call VOP_LOOKUP routine for next component name
3281541Srgrimes *	    directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
3291541Srgrimes *	    component vnode returned in ni_vp (if it exists), locked.
3301541Srgrimes *	if result vnode is mounted on and crossing mount points,
3311541Srgrimes *	    find mounted on vnode
3321541Srgrimes *	if more components of name, do next level at dirloop
3331541Srgrimes *	return the answer in ni_vp, locked if LOCKLEAF set
3341541Srgrimes *	    if LOCKPARENT set, return locked parent in ni_dvp
3351541Srgrimes *	    if WANTPARENT set, return unlocked parent in ni_dvp
3361541Srgrimes */
3371541Srgrimesint
3381541Srgrimeslookup(ndp)
3391541Srgrimes	register struct nameidata *ndp;
3401541Srgrimes{
3411541Srgrimes	register char *cp;		/* pointer into pathname argument */
3421541Srgrimes	register struct vnode *dp = 0;	/* the directory we are searching */
3431541Srgrimes	struct vnode *tdp;		/* saved dp */
3441541Srgrimes	struct mount *mp;		/* mount table entry */
3451541Srgrimes	int docache;			/* == 0 do not cache last component */
3461541Srgrimes	int wantparent;			/* 1 => wantparent or lockparent flag */
3471541Srgrimes	int rdonly;			/* lookup read-only flag bit */
3489804Sbde	int trailing_slash;
3491541Srgrimes	int error = 0;
35065805Sbp	int dpunlocked = 0;		/* dp has already been unlocked */
3511541Srgrimes	struct componentname *cnp = &ndp->ni_cnd;
35283366Sjulian	struct thread *td = cnp->cn_thread;
353140714Sjeff	int vfslocked;
354140714Sjeff	int tvfslocked;
3551541Srgrimes
3561541Srgrimes	/*
3571541Srgrimes	 * Setup: break out flag bits into variables.
3581541Srgrimes	 */
359140714Sjeff	vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
360140714Sjeff	ndp->ni_cnd.cn_flags &= ~GIANTHELD;
3611541Srgrimes	wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
362144229Sjeff	KASSERT(cnp->cn_nameiop == LOOKUP || wantparent,
363144229Sjeff	    ("CREATE, DELETE, RENAME require LOCKPARENT or WANTPARENT."));
3641541Srgrimes	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
3651541Srgrimes	if (cnp->cn_nameiop == DELETE ||
36622874Sbde	    (wantparent && cnp->cn_nameiop != CREATE &&
36722874Sbde	     cnp->cn_nameiop != LOOKUP))
3681541Srgrimes		docache = 0;
3691541Srgrimes	rdonly = cnp->cn_flags & RDONLY;
370144286Sjeff	cnp->cn_flags &= ~ISSYMLINK;
3711541Srgrimes	ndp->ni_dvp = NULL;
372144286Sjeff	/*
373144286Sjeff	 * We use shared locks until we hit the parent of the last cn then
374144286Sjeff	 * we adjust based on the requesting flags.
375144286Sjeff	 */
376144613Sjeff	if (lookup_shared)
377144613Sjeff		cnp->cn_lkflags = LK_SHARED;
378144613Sjeff	else
379144613Sjeff		cnp->cn_lkflags = LK_EXCLUSIVE;
3801541Srgrimes	dp = ndp->ni_startdir;
3811541Srgrimes	ndp->ni_startdir = NULLVP;
382144286Sjeff	vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
3831541Srgrimes
3841541Srgrimesdirloop:
3851541Srgrimes	/*
3861541Srgrimes	 * Search a new directory.
3871541Srgrimes	 *
3881541Srgrimes	 * The last component of the filename is left accessible via
3891541Srgrimes	 * cnp->cn_nameptr for callers that need the name. Callers needing
3901541Srgrimes	 * the name set the SAVENAME flag. When done, they assume
3911541Srgrimes	 * responsibility for freeing the pathname buffer.
3921541Srgrimes	 */
3931541Srgrimes	cnp->cn_consume = 0;
3941541Srgrimes	for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
39551906Sphk		continue;
3961541Srgrimes	cnp->cn_namelen = cp - cnp->cn_nameptr;
3971541Srgrimes	if (cnp->cn_namelen > NAME_MAX) {
3981541Srgrimes		error = ENAMETOOLONG;
3991541Srgrimes		goto bad;
4001541Srgrimes	}
4011541Srgrimes#ifdef NAMEI_DIAGNOSTIC
4021541Srgrimes	{ char c = *cp;
4031541Srgrimes	*cp = '\0';
4041541Srgrimes	printf("{%s}: ", cnp->cn_nameptr);
4051541Srgrimes	*cp = c; }
4061541Srgrimes#endif
4071541Srgrimes	ndp->ni_pathlen -= cnp->cn_namelen;
4081541Srgrimes	ndp->ni_next = cp;
4099804Sbde
4109804Sbde	/*
4119804Sbde	 * Replace multiple slashes by a single slash and trailing slashes
4129804Sbde	 * by a null.  This must be done before VOP_LOOKUP() because some
4139804Sbde	 * fs's don't know about trailing slashes.  Remember if there were
4149804Sbde	 * trailing slashes to handle symlinks, existing non-directories
4159804Sbde	 * and non-existing files that won't be directories specially later.
4169804Sbde	 */
4179804Sbde	trailing_slash = 0;
4189804Sbde	while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
4199804Sbde		cp++;
4209804Sbde		ndp->ni_pathlen--;
4219804Sbde		if (*cp == '\0') {
4229804Sbde			trailing_slash = 1;
4239804Sbde			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
4249804Sbde		}
4259804Sbde	}
4269804Sbde	ndp->ni_next = cp;
4279804Sbde
4281541Srgrimes	cnp->cn_flags |= MAKEENTRY;
4291541Srgrimes	if (*cp == '\0' && docache == 0)
4301541Srgrimes		cnp->cn_flags &= ~MAKEENTRY;
4311541Srgrimes	if (cnp->cn_namelen == 2 &&
4321541Srgrimes	    cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
4331541Srgrimes		cnp->cn_flags |= ISDOTDOT;
4341541Srgrimes	else
4351541Srgrimes		cnp->cn_flags &= ~ISDOTDOT;
4361541Srgrimes	if (*ndp->ni_next == 0)
4371541Srgrimes		cnp->cn_flags |= ISLASTCN;
4381541Srgrimes	else
4391541Srgrimes		cnp->cn_flags &= ~ISLASTCN;
4401541Srgrimes
4411541Srgrimes
4421541Srgrimes	/*
4431541Srgrimes	 * Check for degenerate name (e.g. / or "")
4441541Srgrimes	 * which is a way of talking about a directory,
4451541Srgrimes	 * e.g. like "/." or ".".
4461541Srgrimes	 */
4471541Srgrimes	if (cnp->cn_nameptr[0] == '\0') {
44822521Sdyson		if (dp->v_type != VDIR) {
44922521Sdyson			error = ENOTDIR;
45022521Sdyson			goto bad;
45122521Sdyson		}
4521541Srgrimes		if (cnp->cn_nameiop != LOOKUP) {
4531541Srgrimes			error = EISDIR;
4541541Srgrimes			goto bad;
4551541Srgrimes		}
4561541Srgrimes		if (wantparent) {
4571541Srgrimes			ndp->ni_dvp = dp;
4581541Srgrimes			VREF(dp);
4591541Srgrimes		}
4601541Srgrimes		ndp->ni_vp = dp;
4611541Srgrimes		if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
46283366Sjulian			VOP_UNLOCK(dp, 0, td);
46354655Seivind		/* XXX This should probably move to the top of function. */
4641541Srgrimes		if (cnp->cn_flags & SAVESTART)
4651541Srgrimes			panic("lookup: SAVESTART");
466140714Sjeff		goto success;
4671541Srgrimes	}
4681541Srgrimes
4691541Srgrimes	/*
470154649Struckman	 * Handle "..": four special cases.
471154649Struckman	 * 1. Return an error if this is the last component of
472154649Struckman	 *    the name and the operation is DELETE or RENAME.
473154649Struckman	 * 2. If at root directory (e.g. after chroot)
4741541Srgrimes	 *    or at absolute root directory
4751541Srgrimes	 *    then ignore it so can't get out.
476154649Struckman	 * 3. If this vnode is the root of a mounted
4771541Srgrimes	 *    filesystem, then replace it with the
4781541Srgrimes	 *    vnode which was mounted on so we take the
47996755Strhodes	 *    .. in the other filesystem.
480154649Struckman	 * 4. If the vnode is the top directory of
48151649Sphk	 *    the jail or chroot, don't let them out.
4821541Srgrimes	 */
4831541Srgrimes	if (cnp->cn_flags & ISDOTDOT) {
484154649Struckman		if ((cnp->cn_flags & ISLASTCN) != 0 &&
485154649Struckman		    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
486154690Struckman			error = EINVAL;
487154649Struckman			goto bad;
488154649Struckman		}
4891541Srgrimes		for (;;) {
49051649Sphk			if (dp == ndp->ni_rootdir ||
49151649Sphk			    dp == ndp->ni_topdir ||
49251649Sphk			    dp == rootvnode) {
4931541Srgrimes				ndp->ni_dvp = dp;
4941541Srgrimes				ndp->ni_vp = dp;
4951541Srgrimes				VREF(dp);
4961541Srgrimes				goto nextname;
4971541Srgrimes			}
498101308Sjeff			if ((dp->v_vflag & VV_ROOT) == 0 ||
4991541Srgrimes			    (cnp->cn_flags & NOCROSSMOUNT))
5001541Srgrimes				break;
50169405Salfred			if (dp->v_mount == NULL) {	/* forced unmount */
50269405Salfred				error = EBADF;
50369405Salfred				goto bad;
50469405Salfred			}
5051541Srgrimes			tdp = dp;
506144833Sjeff			dp = dp->v_mount->mnt_vnodecovered;
507140714Sjeff			tvfslocked = vfslocked;
508144833Sjeff			vfslocked = VFS_LOCK_GIANT(dp->v_mount);
509144833Sjeff			VREF(dp);
5101541Srgrimes			vput(tdp);
511140714Sjeff			VFS_UNLOCK_GIANT(tvfslocked);
512144286Sjeff			vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
5131541Srgrimes		}
5141541Srgrimes	}
5151541Srgrimes
5161541Srgrimes	/*
5171541Srgrimes	 * We now have a segment name to search for, and a directory to search.
5181541Srgrimes	 */
5191541Srgrimesunionlookup:
520101127Srwatson#ifdef MAC
521105479Srwatson	if ((cnp->cn_flags & NOMACCHECK) == 0) {
522105479Srwatson		error = mac_check_vnode_lookup(td->td_ucred, dp, cnp);
523105479Srwatson		if (error)
524105479Srwatson			goto bad;
525105479Srwatson	}
526101127Srwatson#endif
5271541Srgrimes	ndp->ni_dvp = dp;
52822521Sdyson	ndp->ni_vp = NULL;
52924624Sdfr	ASSERT_VOP_LOCKED(dp, "lookup");
530144286Sjeff	/*
531144286Sjeff	 * If we have a shared lock we may need to upgrade the lock for the
532144286Sjeff	 * last operation.
533144286Sjeff	 */
534144286Sjeff	if (VOP_ISLOCKED(dp, td) == LK_SHARED &&
535144286Sjeff	    (cnp->cn_flags & ISLASTCN) && (cnp->cn_flags & LOCKPARENT))
536144286Sjeff		vn_lock(dp, LK_UPGRADE|LK_RETRY, td);
537144286Sjeff	/*
538144286Sjeff	 * If we're looking up the last component and we need an exclusive
539144286Sjeff	 * lock, adjust our lkflags.
540144286Sjeff	 */
541144286Sjeff	if ((cnp->cn_flags & (ISLASTCN|LOCKSHARED|LOCKLEAF)) ==
542144286Sjeff	    (ISLASTCN|LOCKLEAF))
543144286Sjeff		cnp->cn_lkflags = LK_EXCLUSIVE;
544138345Sphk#ifdef NAMEI_DIAGNOSTIC
545138345Sphk	vprint("lookup in", dp);
546138345Sphk#endif
54743301Sdillon	if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
54842408Seivind		KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
5491541Srgrimes#ifdef NAMEI_DIAGNOSTIC
5501541Srgrimes		printf("not found\n");
5511541Srgrimes#endif
5521541Srgrimes		if ((error == ENOENT) &&
553101308Sjeff		    (dp->v_vflag & VV_ROOT) && (dp->v_mount != NULL) &&
5541541Srgrimes		    (dp->v_mount->mnt_flag & MNT_UNION)) {
5551541Srgrimes			tdp = dp;
556144833Sjeff			dp = dp->v_mount->mnt_vnodecovered;
557140714Sjeff			tvfslocked = vfslocked;
558144833Sjeff			vfslocked = VFS_LOCK_GIANT(dp->v_mount);
559144833Sjeff			VREF(dp);
560144203Sjeff			vput(tdp);
561140714Sjeff			VFS_UNLOCK_GIANT(tvfslocked);
562144286Sjeff			vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
5631541Srgrimes			goto unionlookup;
5641541Srgrimes		}
5651541Srgrimes
5661541Srgrimes		if (error != EJUSTRETURN)
5671541Srgrimes			goto bad;
5681541Srgrimes		/*
5691541Srgrimes		 * If creating and at end of pathname, then can consider
5701541Srgrimes		 * allowing file to be created.
5711541Srgrimes		 */
57211644Sdg		if (rdonly) {
5731541Srgrimes			error = EROFS;
5741541Srgrimes			goto bad;
5751541Srgrimes		}
5769804Sbde		if (*cp == '\0' && trailing_slash &&
5779804Sbde		     !(cnp->cn_flags & WILLBEDIR)) {
5789804Sbde			error = ENOENT;
5799804Sbde			goto bad;
5809804Sbde		}
581144203Sjeff		if ((cnp->cn_flags & LOCKPARENT) == 0)
582144203Sjeff			VOP_UNLOCK(dp, 0, td);
5831541Srgrimes		/*
584144203Sjeff		 * This is a temporary assert to make sure I know what the
585144203Sjeff		 * behavior here was.
586144203Sjeff		 */
587144203Sjeff		KASSERT((cnp->cn_flags & (WANTPARENT|LOCKPARENT)) != 0,
588144203Sjeff		   ("lookup: Unhandled case."));
589144203Sjeff		/*
5901541Srgrimes		 * We return with ni_vp NULL to indicate that the entry
5911541Srgrimes		 * doesn't currently exist, leaving a pointer to the
5921541Srgrimes		 * (possibly locked) directory inode in ndp->ni_dvp.
5931541Srgrimes		 */
5941541Srgrimes		if (cnp->cn_flags & SAVESTART) {
5951541Srgrimes			ndp->ni_startdir = ndp->ni_dvp;
5961541Srgrimes			VREF(ndp->ni_startdir);
5971541Srgrimes		}
598140714Sjeff		goto success;
5991541Srgrimes	}
6001541Srgrimes#ifdef NAMEI_DIAGNOSTIC
6011541Srgrimes	printf("found\n");
6021541Srgrimes#endif
603144203Sjeff	/*
6041541Srgrimes	 * Take into account any additional components consumed by
6051541Srgrimes	 * the underlying filesystem.
6061541Srgrimes	 */
6071541Srgrimes	if (cnp->cn_consume > 0) {
6081541Srgrimes		cnp->cn_nameptr += cnp->cn_consume;
6091541Srgrimes		ndp->ni_next += cnp->cn_consume;
6101541Srgrimes		ndp->ni_pathlen -= cnp->cn_consume;
6111541Srgrimes		cnp->cn_consume = 0;
6121541Srgrimes	}
6131541Srgrimes
6141541Srgrimes	dp = ndp->ni_vp;
6151541Srgrimes
6161541Srgrimes	/*
6171541Srgrimes	 * Check to see if the vnode has been mounted on;
61896755Strhodes	 * if so find the root of the mounted filesystem.
6191541Srgrimes	 */
6201541Srgrimes	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
6211541Srgrimes	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
622144833Sjeff		KASSERT(dp != ndp->ni_dvp, ("XXX"));
62383366Sjulian		if (vfs_busy(mp, 0, 0, td))
6241541Srgrimes			continue;
625144833Sjeff		vput(dp);
626140714Sjeff		tvfslocked = VFS_LOCK_GIANT(mp);
627144833Sjeff		VFS_UNLOCK_GIANT(vfslocked);
628144833Sjeff		vfslocked = tvfslocked;
629149051Skan		VOP_UNLOCK(ndp->ni_dvp, 0, td);
630144286Sjeff		error = VFS_ROOT(mp, cnp->cn_lkflags, &tdp, td);
631149051Skan		VOP_LOCK(ndp->ni_dvp, cnp->cn_lkflags | LK_RETRY, td);
63283366Sjulian		vfs_unbusy(mp, td);
63365805Sbp		if (error) {
63465805Sbp			dpunlocked = 1;
6351541Srgrimes			goto bad2;
63665805Sbp		}
6371541Srgrimes		ndp->ni_vp = dp = tdp;
6381541Srgrimes	}
6391541Srgrimes
64010219Sdfr	/*
64110219Sdfr	 * Check for symbolic link
64210219Sdfr	 */
64310219Sdfr	if ((dp->v_type == VLNK) &&
64410219Sdfr	    ((cnp->cn_flags & FOLLOW) || trailing_slash ||
64510219Sdfr	     *ndp->ni_next == '/')) {
64610219Sdfr		cnp->cn_flags |= ISSYMLINK;
64769405Salfred		if (dp->v_mount == NULL) {
64869405Salfred			/* We can't know whether the directory was mounted with
64969405Salfred			 * NOSYMFOLLOW, so we can't follow safely. */
65069405Salfred			error = EBADF;
65169405Salfred			goto bad2;
65269405Salfred		}
65335105Swosch		if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) {
65435105Swosch			error = EACCES;
65535105Swosch			goto bad2;
65635105Swosch		}
657144833Sjeff		/*
658144833Sjeff		 * Symlink code always expects an unlocked dvp.
659144833Sjeff		 */
660144833Sjeff		if (ndp->ni_dvp != ndp->ni_vp)
661144833Sjeff			VOP_UNLOCK(ndp->ni_dvp, 0, td);
662140714Sjeff		goto success;
66310219Sdfr	}
66410219Sdfr
66510219Sdfr	/*
66610219Sdfr	 * Check for bogus trailing slashes.
66710219Sdfr	 */
66810219Sdfr	if (trailing_slash && dp->v_type != VDIR) {
66910219Sdfr		error = ENOTDIR;
67010219Sdfr		goto bad2;
67110219Sdfr	}
67210219Sdfr
6731541Srgrimesnextname:
6741541Srgrimes	/*
6751541Srgrimes	 * Not a symbolic link.  If more pathname,
6761541Srgrimes	 * continue at next component, else return.
6771541Srgrimes	 */
678144203Sjeff	KASSERT((cnp->cn_flags & ISLASTCN) || *ndp->ni_next == '/',
679144203Sjeff	    ("lookup: invalid path state."));
6801541Srgrimes	if (*ndp->ni_next == '/') {
6811541Srgrimes		cnp->cn_nameptr = ndp->ni_next;
6821541Srgrimes		while (*cnp->cn_nameptr == '/') {
6831541Srgrimes			cnp->cn_nameptr++;
6841541Srgrimes			ndp->ni_pathlen--;
6851541Srgrimes		}
686144833Sjeff		if (ndp->ni_dvp != dp)
687144833Sjeff			vput(ndp->ni_dvp);
688144833Sjeff		else
689144833Sjeff			vrele(ndp->ni_dvp);
6901541Srgrimes		goto dirloop;
6911541Srgrimes	}
6921541Srgrimes	/*
69396755Strhodes	 * Disallow directory write attempts on read-only filesystems.
6941541Srgrimes	 */
69511644Sdg	if (rdonly &&
69611644Sdg	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
69711644Sdg		error = EROFS;
69811644Sdg		goto bad2;
6991541Srgrimes	}
7001541Srgrimes	if (cnp->cn_flags & SAVESTART) {
7011541Srgrimes		ndp->ni_startdir = ndp->ni_dvp;
7021541Srgrimes		VREF(ndp->ni_startdir);
7031541Srgrimes	}
704144833Sjeff	if (!wantparent) {
705144833Sjeff		if (ndp->ni_dvp != dp)
706144833Sjeff			vput(ndp->ni_dvp);
707144833Sjeff		else
708144833Sjeff			vrele(ndp->ni_dvp);
709144833Sjeff	} else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp)
710144833Sjeff		VOP_UNLOCK(ndp->ni_dvp, 0, td);
71132071Sdyson
7121541Srgrimes	if ((cnp->cn_flags & LOCKLEAF) == 0)
71383366Sjulian		VOP_UNLOCK(dp, 0, td);
714140714Sjeffsuccess:
715140714Sjeff	if (vfslocked)
716140714Sjeff		ndp->ni_cnd.cn_flags |= GIANTHELD;
7171541Srgrimes	return (0);
7181541Srgrimes
7191541Srgrimesbad2:
720144833Sjeff	if (dp != ndp->ni_dvp)
721144203Sjeff		vput(ndp->ni_dvp);
722144203Sjeff	else
723144203Sjeff		vrele(ndp->ni_dvp);
7241541Srgrimesbad:
725144833Sjeff	if (!dpunlocked)
72665805Sbp		vput(dp);
727140714Sjeff	VFS_UNLOCK_GIANT(vfslocked);
728140714Sjeff	ndp->ni_cnd.cn_flags &= ~GIANTHELD;
7291541Srgrimes	ndp->ni_vp = NULL;
7301541Srgrimes	return (error);
7311541Srgrimes}
7321541Srgrimes
7333148Sphk/*
7343148Sphk * relookup - lookup a path name component
7353148Sphk *    Used by lookup to re-aquire things.
7363148Sphk */
7373148Sphkint
7383148Sphkrelookup(dvp, vpp, cnp)
7393148Sphk	struct vnode *dvp, **vpp;
7403148Sphk	struct componentname *cnp;
7413148Sphk{
74283366Sjulian	struct thread *td = cnp->cn_thread;
74322521Sdyson	struct vnode *dp = 0;		/* the directory we are searching */
7443148Sphk	int wantparent;			/* 1 => wantparent or lockparent flag */
7453148Sphk	int rdonly;			/* lookup read-only flag bit */
7463148Sphk	int error = 0;
7471541Srgrimes
748144203Sjeff	KASSERT(cnp->cn_flags & ISLASTCN,
749144203Sjeff	    ("relookup: Not given last component."));
7503148Sphk	/*
7513148Sphk	 * Setup: break out flag bits into variables.
7523148Sphk	 */
7533148Sphk	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
754145004Sjeff	KASSERT(wantparent, ("relookup: parent not wanted."));
7553148Sphk	rdonly = cnp->cn_flags & RDONLY;
7563148Sphk	cnp->cn_flags &= ~ISSYMLINK;
7573148Sphk	dp = dvp;
758144286Sjeff	cnp->cn_lkflags = LK_EXCLUSIVE;
75983366Sjulian	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
7603148Sphk
7613148Sphk	/*
7623148Sphk	 * Search a new directory.
7633148Sphk	 *
7643148Sphk	 * The last component of the filename is left accessible via
7653148Sphk	 * cnp->cn_nameptr for callers that need the name. Callers needing
7663148Sphk	 * the name set the SAVENAME flag. When done, they assume
7673148Sphk	 * responsibility for freeing the pathname buffer.
7683148Sphk	 */
7693148Sphk#ifdef NAMEI_DIAGNOSTIC
7703148Sphk	printf("{%s}: ", cnp->cn_nameptr);
7713148Sphk#endif
7723148Sphk
7733148Sphk	/*
7743148Sphk	 * Check for degenerate name (e.g. / or "")
7753148Sphk	 * which is a way of talking about a directory,
7763148Sphk	 * e.g. like "/." or ".".
7773148Sphk	 */
7783148Sphk	if (cnp->cn_nameptr[0] == '\0') {
7793148Sphk		if (cnp->cn_nameiop != LOOKUP || wantparent) {
7803148Sphk			error = EISDIR;
7813148Sphk			goto bad;
7823148Sphk		}
7833148Sphk		if (dp->v_type != VDIR) {
7843148Sphk			error = ENOTDIR;
7853148Sphk			goto bad;
7863148Sphk		}
7873148Sphk		if (!(cnp->cn_flags & LOCKLEAF))
78883366Sjulian			VOP_UNLOCK(dp, 0, td);
7893148Sphk		*vpp = dp;
79054655Seivind		/* XXX This should probably move to the top of function. */
7913148Sphk		if (cnp->cn_flags & SAVESTART)
7923148Sphk			panic("lookup: SAVESTART");
7933148Sphk		return (0);
7943148Sphk	}
7953148Sphk
7963148Sphk	if (cnp->cn_flags & ISDOTDOT)
7973148Sphk		panic ("relookup: lookup on dot-dot");
7983148Sphk
7993148Sphk	/*
8003148Sphk	 * We now have a segment name to search for, and a directory to search.
8013148Sphk	 */
802138345Sphk#ifdef NAMEI_DIAGNOSTIC
803138345Sphk	vprint("search in:", dp);
804138345Sphk#endif
80543311Sdillon	if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) {
80642408Seivind		KASSERT(*vpp == NULL, ("leaf should be empty"));
8073148Sphk		if (error != EJUSTRETURN)
8083148Sphk			goto bad;
8093148Sphk		/*
8103148Sphk		 * If creating and at end of pathname, then can consider
8113148Sphk		 * allowing file to be created.
8123148Sphk		 */
81311644Sdg		if (rdonly) {
8143148Sphk			error = EROFS;
8153148Sphk			goto bad;
8163148Sphk		}
8173148Sphk		/* ASSERT(dvp == ndp->ni_startdir) */
8183148Sphk		if (cnp->cn_flags & SAVESTART)
8193148Sphk			VREF(dvp);
820144203Sjeff		if ((cnp->cn_flags & LOCKPARENT) == 0)
821144203Sjeff			VOP_UNLOCK(dp, 0, td);
8223148Sphk		/*
823144203Sjeff		 * This is a temporary assert to make sure I know what the
824144203Sjeff		 * behavior here was.
825144203Sjeff		 */
826144203Sjeff		KASSERT((cnp->cn_flags & (WANTPARENT|LOCKPARENT)) != 0,
827144203Sjeff		   ("relookup: Unhandled case."));
828144203Sjeff		/*
8293148Sphk		 * We return with ni_vp NULL to indicate that the entry
8303148Sphk		 * doesn't currently exist, leaving a pointer to the
8313148Sphk		 * (possibly locked) directory inode in ndp->ni_dvp.
8323148Sphk		 */
8333148Sphk		return (0);
8343148Sphk	}
8353148Sphk	dp = *vpp;
8363148Sphk
8373148Sphk	/*
83896755Strhodes	 * Disallow directory write attempts on read-only filesystems.
8393148Sphk	 */
84011644Sdg	if (rdonly &&
84111644Sdg	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
842145004Sjeff		if (dvp == dp)
843145004Sjeff			vrele(dvp);
844145004Sjeff		else
845145004Sjeff			vput(dvp);
84611644Sdg		error = EROFS;
847145004Sjeff		goto bad;
8483148Sphk	}
849145004Sjeff	/*
850145004Sjeff	 * Set the parent lock/ref state to the requested state.
851145004Sjeff	 */
852145004Sjeff	if ((cnp->cn_flags & LOCKPARENT) == 0 && dvp != dp) {
853145004Sjeff		if (wantparent)
854145004Sjeff			VOP_UNLOCK(dvp, 0, td);
855145004Sjeff		else
856145004Sjeff			vput(dvp);
857145004Sjeff	} else if (!wantparent)
858145004Sjeff		vrele(dvp);
859145004Sjeff	/*
860145004Sjeff	 * Check for symbolic link
861145004Sjeff	 */
862145004Sjeff	KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW),
863145004Sjeff	    ("relookup: symlink found.\n"));
864145004Sjeff
8653148Sphk	/* ASSERT(dvp == ndp->ni_startdir) */
8663148Sphk	if (cnp->cn_flags & SAVESTART)
8673148Sphk		VREF(dvp);
86822521Sdyson
8693148Sphk	if ((cnp->cn_flags & LOCKLEAF) == 0)
87083366Sjulian		VOP_UNLOCK(dp, 0, td);
8713148Sphk	return (0);
8723148Sphkbad:
8733148Sphk	vput(dp);
8743148Sphk	*vpp = NULL;
8753148Sphk	return (error);
8763148Sphk}
877141471Sjhb
878141471Sjhb/*
879144661Sjeff * Free data allocated by namei(); see namei(9) for details.
880144661Sjeff */
881144661Sjeffvoid
882144661SjeffNDFREE(ndp, flags)
883144661Sjeff     struct nameidata *ndp;
884144661Sjeff     const u_int flags;
885144661Sjeff{
886144833Sjeff	int unlock_dvp;
887144833Sjeff	int unlock_vp;
888144661Sjeff
889144833Sjeff	unlock_dvp = 0;
890144833Sjeff	unlock_vp = 0;
891144833Sjeff
892144661Sjeff	if (!(flags & NDF_NO_FREE_PNBUF) &&
893144661Sjeff	    (ndp->ni_cnd.cn_flags & HASBUF)) {
894144661Sjeff		uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf);
895144661Sjeff		ndp->ni_cnd.cn_flags &= ~HASBUF;
896144661Sjeff	}
897144833Sjeff	if (!(flags & NDF_NO_VP_UNLOCK) &&
898144833Sjeff	    (ndp->ni_cnd.cn_flags & LOCKLEAF) && ndp->ni_vp)
899144833Sjeff		unlock_vp = 1;
900144833Sjeff	if (!(flags & NDF_NO_VP_RELE) && ndp->ni_vp) {
901144833Sjeff		if (unlock_vp) {
902144833Sjeff			vput(ndp->ni_vp);
903144833Sjeff			unlock_vp = 0;
904144833Sjeff		} else
905144833Sjeff			vrele(ndp->ni_vp);
906144833Sjeff		ndp->ni_vp = NULL;
907144833Sjeff	}
908144833Sjeff	if (unlock_vp)
909144833Sjeff		VOP_UNLOCK(ndp->ni_vp, 0, ndp->ni_cnd.cn_thread);
910144661Sjeff	if (!(flags & NDF_NO_DVP_UNLOCK) &&
911144661Sjeff	    (ndp->ni_cnd.cn_flags & LOCKPARENT) &&
912144661Sjeff	    ndp->ni_dvp != ndp->ni_vp)
913144833Sjeff		unlock_dvp = 1;
914144661Sjeff	if (!(flags & NDF_NO_DVP_RELE) &&
915144661Sjeff	    (ndp->ni_cnd.cn_flags & (LOCKPARENT|WANTPARENT))) {
916144833Sjeff		if (unlock_dvp) {
917144833Sjeff			vput(ndp->ni_dvp);
918144833Sjeff			unlock_dvp = 0;
919144833Sjeff		} else
920144833Sjeff			vrele(ndp->ni_dvp);
921144661Sjeff		ndp->ni_dvp = NULL;
922144661Sjeff	}
923144833Sjeff	if (unlock_dvp)
924144833Sjeff		VOP_UNLOCK(ndp->ni_dvp, 0, ndp->ni_cnd.cn_thread);
925144661Sjeff	if (!(flags & NDF_NO_STARTDIR_RELE) &&
926144661Sjeff	    (ndp->ni_cnd.cn_flags & SAVESTART)) {
927144661Sjeff		vrele(ndp->ni_startdir);
928144661Sjeff		ndp->ni_startdir = NULL;
929144661Sjeff	}
930144661Sjeff}
931144661Sjeff
932144661Sjeff/*
933141471Sjhb * Determine if there is a suitable alternate filename under the specified
934141471Sjhb * prefix for the specified path.  If the create flag is set, then the
935141471Sjhb * alternate prefix will be used so long as the parent directory exists.
936141471Sjhb * This is used by the various compatiblity ABIs so that Linux binaries prefer
937141471Sjhb * files under /compat/linux for example.  The chosen path (whether under
938141471Sjhb * the prefix or under /) is returned in a kernel malloc'd buffer pointed
939141471Sjhb * to by pathbuf.  The caller is responsible for free'ing the buffer from
940141471Sjhb * the M_TEMP bucket if one is returned.
941141471Sjhb */
942141471Sjhbint
943141471Sjhbkern_alternate_path(struct thread *td, const char *prefix, char *path,
944141471Sjhb    enum uio_seg pathseg, char **pathbuf, int create)
945141471Sjhb{
946141471Sjhb	struct nameidata nd, ndroot;
947141471Sjhb	char *ptr, *buf, *cp;
948141471Sjhb	size_t len, sz;
949141471Sjhb	int error;
950141471Sjhb
951141471Sjhb	buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
952141471Sjhb	*pathbuf = buf;
953141471Sjhb
954141471Sjhb	/* Copy the prefix into the new pathname as a starting point. */
955141471Sjhb	len = strlcpy(buf, prefix, MAXPATHLEN);
956141471Sjhb	if (len >= MAXPATHLEN) {
957141471Sjhb		*pathbuf = NULL;
958141471Sjhb		free(buf, M_TEMP);
959141471Sjhb		return (EINVAL);
960141471Sjhb	}
961141471Sjhb	sz = MAXPATHLEN - len;
962141471Sjhb	ptr = buf + len;
963141471Sjhb
964141471Sjhb	/* Append the filename to the prefix. */
965141471Sjhb	if (pathseg == UIO_SYSSPACE)
966141471Sjhb		error = copystr(path, ptr, sz, &len);
967141471Sjhb	else
968141471Sjhb		error = copyinstr(path, ptr, sz, &len);
969141471Sjhb
970141471Sjhb	if (error) {
971141471Sjhb		*pathbuf = NULL;
972141471Sjhb		free(buf, M_TEMP);
973141471Sjhb		return (error);
974141471Sjhb	}
975141471Sjhb
976141471Sjhb	/* Only use a prefix with absolute pathnames. */
977141471Sjhb	if (*ptr != '/') {
978141471Sjhb		error = EINVAL;
979141471Sjhb		goto keeporig;
980141471Sjhb	}
981141471Sjhb
982141471Sjhb	/*
983141471Sjhb	 * We know that there is a / somewhere in this pathname.
984141471Sjhb	 * Search backwards for it, to find the file's parent dir
985141471Sjhb	 * to see if it exists in the alternate tree. If it does,
986141471Sjhb	 * and we want to create a file (cflag is set). We don't
987141471Sjhb	 * need to worry about the root comparison in this case.
988141471Sjhb	 */
989141471Sjhb
990141471Sjhb	if (create) {
991141471Sjhb		for (cp = &ptr[len] - 1; *cp != '/'; cp--);
992141471Sjhb		*cp = '\0';
993141471Sjhb
994150431Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td);
995141471Sjhb		error = namei(&nd);
996141471Sjhb		*cp = '/';
997141471Sjhb		if (error != 0)
998150431Sjhb			goto keeporig;
999141471Sjhb	} else {
1000150431Sjhb		NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, buf, td);
1001141471Sjhb
1002141471Sjhb		error = namei(&nd);
1003141471Sjhb		if (error != 0)
1004150431Sjhb			goto keeporig;
1005141471Sjhb
1006141471Sjhb		/*
1007141471Sjhb		 * We now compare the vnode of the prefix to the one
1008141471Sjhb		 * vnode asked. If they resolve to be the same, then we
1009141471Sjhb		 * ignore the match so that the real root gets used.
1010141471Sjhb		 * This avoids the problem of traversing "../.." to find the
1011141471Sjhb		 * root directory and never finding it, because "/" resolves
1012141471Sjhb		 * to the emulation root directory. This is expensive :-(
1013141471Sjhb		 */
1014150431Sjhb		NDINIT(&ndroot, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, prefix,
1015150431Sjhb		    td);
1016141471Sjhb
1017141471Sjhb		/* We shouldn't ever get an error from this namei(). */
1018141471Sjhb		error = namei(&ndroot);
1019141471Sjhb		if (error == 0) {
1020141471Sjhb			if (nd.ni_vp == ndroot.ni_vp)
1021141471Sjhb				error = ENOENT;
1022141471Sjhb
1023141471Sjhb			NDFREE(&ndroot, NDF_ONLY_PNBUF);
1024141471Sjhb			vrele(ndroot.ni_vp);
1025150431Sjhb			VFS_UNLOCK_GIANT(NDHASGIANT(&ndroot));
1026141471Sjhb		}
1027141471Sjhb	}
1028141471Sjhb
1029141471Sjhb	NDFREE(&nd, NDF_ONLY_PNBUF);
1030141471Sjhb	vrele(nd.ni_vp);
1031150431Sjhb	VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
1032141471Sjhb
1033141471Sjhbkeeporig:
1034141471Sjhb	/* If there was an error, use the original path name. */
1035141471Sjhb	if (error)
1036141471Sjhb		bcopy(ptr, buf, len);
1037141471Sjhb	return (error);
1038141471Sjhb}
1039