vfs_lookup.c revision 33360
1121986Sjhb/*
2121986Sjhb * Copyright (c) 1982, 1986, 1989, 1993
3121986Sjhb *	The Regents of the University of California.  All rights reserved.
4121986Sjhb * (c) UNIX System Laboratories, Inc.
5121986Sjhb * All or some portions of this file are derived from material licensed
6121986Sjhb * to the University of California by American Telephone and Telegraph
7121986Sjhb * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8121986Sjhb * the permission of UNIX System Laboratories, Inc.
9121986Sjhb *
10121986Sjhb * Redistribution and use in source and binary forms, with or without
11121986Sjhb * modification, are permitted provided that the following conditions
12121986Sjhb * are met:
13121986Sjhb * 1. Redistributions of source code must retain the above copyright
14121986Sjhb *    notice, this list of conditions and the following disclaimer.
15121986Sjhb * 2. Redistributions in binary form must reproduce the above copyright
16121986Sjhb *    notice, this list of conditions and the following disclaimer in the
17121986Sjhb *    documentation and/or other materials provided with the distribution.
18121986Sjhb * 3. All advertising materials mentioning features or use of this software
19121986Sjhb *    must display the following acknowledgement:
20121986Sjhb *	This product includes software developed by the University of
21121986Sjhb *	California, Berkeley and its contributors.
22121986Sjhb * 4. Neither the name of the University nor the names of its contributors
23121986Sjhb *    may be used to endorse or promote products derived from this software
24121986Sjhb *    without specific prior written permission.
25121986Sjhb *
26121986Sjhb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27121986Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28121986Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29121986Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30121986Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31121986Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32121986Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33121986Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34121986Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35121986Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36121986Sjhb * SUCH DAMAGE.
37147565Speter *
38147565Speter *	@(#)vfs_lookup.c	8.4 (Berkeley) 2/16/94
39151979Sjhb * $Id: vfs_lookup.c,v 1.25 1998/02/06 12:13:30 eivind Exp $
40151979Sjhb */
41121986Sjhb
42121986Sjhb#include "opt_ktrace.h"
43121986Sjhb
44121986Sjhb#include <sys/param.h>
45151979Sjhb#include <sys/systm.h>
46151979Sjhb#include <sys/namei.h>
47121986Sjhb#include <sys/vnode.h>
48141538Sjhb#include <sys/mount.h>
49121986Sjhb#include <sys/filedesc.h>
50121986Sjhb#include <sys/proc.h>
51121986Sjhb
52121986Sjhb#ifdef KTRACE
53121986Sjhb#include <sys/ktrace.h>
54153666Sjhb#endif
55121986Sjhb
56121986Sjhb#include <vm/vm_zone.h>
57121986Sjhb
58121986Sjhb/*
59121986Sjhb * Convert a pathname into a pointer to a locked inode.
60121986Sjhb *
61121986Sjhb * The FOLLOW flag is set when symbolic links are to be followed
62121986Sjhb * when they occur at the end of the name translation process.
63151979Sjhb * Symbolic links are always followed for all other pathname
64151979Sjhb * components other than the last.
65151979Sjhb *
66151979Sjhb * The segflg defines whether the name is to be copied from user
67151979Sjhb * space or kernel space.
68121986Sjhb *
69121986Sjhb * Overall outline of namei:
70121986Sjhb *
71121986Sjhb *	copy in name
72121986Sjhb *	get starting directory
73121986Sjhb *	while (!done && !error) {
74121986Sjhb *		call lookup to search path.
75122690Sjhb *		if symbolic link, massage name in buffer and continue
76139240Sjhb *	}
77139240Sjhb */
78139240Sjhbint
79122690Sjhbnamei(ndp)
80122690Sjhb	register struct nameidata *ndp;
81143034Sjhb{
82143034Sjhb	register struct filedesc *fdp;	/* pointer to file descriptor state */
83143034Sjhb	register char *cp;		/* pointer into pathname argument */
84141538Sjhb	register struct vnode *dp;	/* the directory we are searching */
85151979Sjhb	struct iovec aiov;		/* uio for reading symbolic links */
86151979Sjhb	struct uio auio;
87151979Sjhb	int error, linklen;
88151979Sjhb	struct componentname *cnp = &ndp->ni_cnd;
89121986Sjhb	struct proc *p = cnp->cn_proc;
90121986Sjhb
91121986Sjhb	ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred;
92121986Sjhb#ifdef DIAGNOSTIC
93121986Sjhb	if (!cnp->cn_cred || !cnp->cn_proc)
94121986Sjhb		panic ("namei: bad cred/proc");
95121986Sjhb	if (cnp->cn_nameiop & (~OPMASK))
96121986Sjhb		panic ("namei: nameiop contaminated with flags");
97121986Sjhb	if (cnp->cn_flags & OPMASK)
98121986Sjhb		panic ("namei: flags contaminated with nameiops");
99121986Sjhb#endif
100121986Sjhb	fdp = cnp->cn_proc->p_fd;
101121986Sjhb
102121986Sjhb	/*
103121986Sjhb	 * Get a buffer for the name to be translated, and copy the
104121986Sjhb	 * name into the buffer.
105121986Sjhb	 */
106121986Sjhb	if ((cnp->cn_flags & HASBUF) == 0)
107121986Sjhb		cnp->cn_pnbuf = zalloc(namei_zone);
108121986Sjhb	if (ndp->ni_segflg == UIO_SYSSPACE)
109121986Sjhb		error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
110121986Sjhb			    MAXPATHLEN, (u_int *)&ndp->ni_pathlen);
111121986Sjhb	else
112121986Sjhb		error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
113141538Sjhb			    MAXPATHLEN, (u_int *)&ndp->ni_pathlen);
114141538Sjhb
115141538Sjhb	/*
116141538Sjhb	 * Don't allow empty pathnames.
117121986Sjhb	 */
118121986Sjhb	if (!error && *cnp->cn_pnbuf == '\0')
119121986Sjhb		error = ENOENT;
120121986Sjhb
121121986Sjhb	if (error) {
122121986Sjhb		zfree(namei_zone, cnp->cn_pnbuf);
123121986Sjhb		ndp->ni_vp = NULL;
124121986Sjhb		return (error);
125139245Sjhb	}
126139245Sjhb	ndp->ni_loopcnt = 0;
127145256Sjkoshy#ifdef KTRACE
128139245Sjhb	if (KTRPOINT(cnp->cn_proc, KTR_NAMEI))
129121986Sjhb		ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf);
130121986Sjhb#endif
131121986Sjhb
132121986Sjhb	/*
133121986Sjhb	 * Get starting point for the translation.
134121986Sjhb	 */
135121986Sjhb	ndp->ni_rootdir = fdp->fd_rdir;
136121986Sjhb
137121986Sjhb	dp = fdp->fd_cdir;
138122690Sjhb	VREF(dp);
139122690Sjhb	for (;;) {
140121986Sjhb		/*
141121986Sjhb		 * Check if root directory should replace current directory.
142151979Sjhb		 * Done at start of translation and after symbolic link.
143151979Sjhb		 */
144151979Sjhb		cnp->cn_nameptr = cnp->cn_pnbuf;
145141538Sjhb		if (*(cnp->cn_nameptr) == '/') {
146141538Sjhb			vrele(dp);
147141538Sjhb			while (*(cnp->cn_nameptr) == '/') {
148141538Sjhb				cnp->cn_nameptr++;
149141538Sjhb				ndp->ni_pathlen--;
150121986Sjhb			}
151141538Sjhb			dp = ndp->ni_rootdir;
152121986Sjhb			VREF(dp);
153139245Sjhb		}
154163219Sjhb		ndp->ni_startdir = dp;
155141538Sjhb		error = lookup(ndp);
156141538Sjhb		if (error) {
157141538Sjhb			zfree(namei_zone, cnp->cn_pnbuf);
158141538Sjhb			return (error);
159139245Sjhb		}
160139245Sjhb		/*
161163219Sjhb		 * Check for symbolic link
162163219Sjhb		 */
163121986Sjhb		if ((cnp->cn_flags & ISSYMLINK) == 0) {
164121986Sjhb			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
165121986Sjhb				zfree(namei_zone, cnp->cn_pnbuf);
166121986Sjhb			else
167121986Sjhb				cnp->cn_flags |= HASBUF;
168121986Sjhb
169121986Sjhb			if (ndp->ni_vp && ndp->ni_vp->v_type == VREG &&
170121986Sjhb				(cnp->cn_nameiop != DELETE) &&
171121986Sjhb				((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
172121986Sjhb				vfs_object_create(ndp->ni_vp,
173121986Sjhb					ndp->ni_cnd.cn_proc, ndp->ni_cnd.cn_cred, 1);
174121986Sjhb
175121986Sjhb			return (0);
176121986Sjhb		}
177121986Sjhb		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
178121986Sjhb			VOP_UNLOCK(ndp->ni_dvp, 0, p);
179121986Sjhb		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
180121986Sjhb			error = ELOOP;
181121986Sjhb			break;
182121986Sjhb		}
183121986Sjhb		if (ndp->ni_pathlen > 1)
184121986Sjhb			cp = zalloc(namei_zone);
185121986Sjhb		else
186121986Sjhb			cp = cnp->cn_pnbuf;
187121986Sjhb		aiov.iov_base = cp;
188121986Sjhb		aiov.iov_len = MAXPATHLEN;
189121986Sjhb		auio.uio_iov = &aiov;
190121986Sjhb		auio.uio_iovcnt = 1;
191121986Sjhb		auio.uio_offset = 0;
192121986Sjhb		auio.uio_rw = UIO_READ;
193121986Sjhb		auio.uio_segflg = UIO_SYSSPACE;
194121986Sjhb		auio.uio_procp = (struct proc *)0;
195121986Sjhb		auio.uio_resid = MAXPATHLEN;
196121986Sjhb		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
197121986Sjhb		if (error) {
198121986Sjhb			if (ndp->ni_pathlen > 1)
199121986Sjhb				zfree(namei_zone, cp);
200121986Sjhb			break;
201121986Sjhb		}
202121986Sjhb		linklen = MAXPATHLEN - auio.uio_resid;
203121986Sjhb		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
204121986Sjhb			if (ndp->ni_pathlen > 1)
205121986Sjhb				zfree(namei_zone, cp);
206121986Sjhb			error = ENAMETOOLONG;
207121986Sjhb			break;
208121986Sjhb		}
209121986Sjhb		if (ndp->ni_pathlen > 1) {
210121986Sjhb			bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
211121986Sjhb			zfree(namei_zone, cnp->cn_pnbuf);
212121986Sjhb			cnp->cn_pnbuf = cp;
213121986Sjhb		} else
214156920Sjhb			cnp->cn_pnbuf[linklen] = '\0';
215121986Sjhb		ndp->ni_pathlen += linklen;
216121986Sjhb		vput(ndp->ni_vp);
217121986Sjhb		dp = ndp->ni_dvp;
218121986Sjhb	}
219139245Sjhb	zfree(namei_zone, cnp->cn_pnbuf);
220151979Sjhb	vrele(ndp->ni_dvp);
221121986Sjhb	vput(ndp->ni_vp);
222121986Sjhb	ndp->ni_vp = NULL;
223121986Sjhb	return (error);
224156124Sjhb}
225121986Sjhb
226141538Sjhb/*
227141538Sjhb * Search a pathname.
228141538Sjhb * This is a very central and rather complicated routine.
229151979Sjhb *
230141538Sjhb * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
231141538Sjhb * The starting directory is taken from ni_startdir. The pathname is
232121986Sjhb * descended until done, or a symbolic link is encountered. The variable
233121986Sjhb * ni_more is clear if the path is completed; it is set to one if a
234121986Sjhb * symbolic link needing interpretation is encountered.
235121986Sjhb *
236121986Sjhb * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
237121986Sjhb * whether the name is to be looked up, created, renamed, or deleted.
238121986Sjhb * When CREATE, RENAME, or DELETE is specified, information usable in
239121986Sjhb * creating, renaming, or deleting a directory entry may be calculated.
240121986Sjhb * If flag has LOCKPARENT or'ed into it, the parent directory is returned
241121986Sjhb * locked. If flag has WANTPARENT or'ed into it, the parent directory is
242132156Sjhb * returned unlocked. Otherwise the parent directory is not returned. If
243121986Sjhb * the target of the pathname exists and LOCKLEAF is or'ed into the flag
244121986Sjhb * the target is returned locked, otherwise it is returned unlocked.
245121986Sjhb * When creating or renaming and LOCKPARENT is specified, the target may not
246121986Sjhb * be ".".  When deleting and LOCKPARENT is specified, the target may be ".".
247121986Sjhb *
248121986Sjhb * Overall outline of lookup:
249121986Sjhb *
250121986Sjhb * dirloop:
251121986Sjhb *	identify next component of name at ndp->ni_ptr
252121986Sjhb *	handle degenerate case where name is null string
253121986Sjhb *	if .. and crossing mount points and on mounted filesys, find parent
254121986Sjhb *	call VOP_LOOKUP routine for next component name
255121986Sjhb *	    directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
256121986Sjhb *	    component vnode returned in ni_vp (if it exists), locked.
257121986Sjhb *	if result vnode is mounted on and crossing mount points,
258121986Sjhb *	    find mounted on vnode
259121986Sjhb *	if more components of name, do next level at dirloop
260121986Sjhb *	return the answer in ni_vp, locked if LOCKLEAF set
261121986Sjhb *	    if LOCKPARENT set, return locked parent in ni_dvp
262121986Sjhb *	    if WANTPARENT set, return unlocked parent in ni_dvp
263121986Sjhb */
264121986Sjhbint
265121986Sjhblookup(ndp)
266121986Sjhb	register struct nameidata *ndp;
267121986Sjhb{
268121986Sjhb	register char *cp;		/* pointer into pathname argument */
269121986Sjhb	register struct vnode *dp = 0;	/* the directory we are searching */
270121986Sjhb	struct vnode *tdp;		/* saved dp */
271121986Sjhb	struct mount *mp;		/* mount table entry */
272121986Sjhb	int docache;			/* == 0 do not cache last component */
273121986Sjhb	int wantparent;			/* 1 => wantparent or lockparent flag */
274121986Sjhb	int rdonly;			/* lookup read-only flag bit */
275121986Sjhb	int trailing_slash;
276121986Sjhb	int error = 0;
277121986Sjhb	struct componentname *cnp = &ndp->ni_cnd;
278121986Sjhb	struct proc *p = cnp->cn_proc;
279139245Sjhb
280139245Sjhb	/*
281139245Sjhb	 * Setup: break out flag bits into variables.
282121986Sjhb	 */
283121986Sjhb	wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
284121986Sjhb	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
285163219Sjhb	if (cnp->cn_nameiop == DELETE ||
286121986Sjhb	    (wantparent && cnp->cn_nameiop != CREATE &&
287121986Sjhb	     cnp->cn_nameiop != LOOKUP))
288156124Sjhb		docache = 0;
289121986Sjhb	rdonly = cnp->cn_flags & RDONLY;
290141538Sjhb	ndp->ni_dvp = NULL;
291121986Sjhb	cnp->cn_flags &= ~ISSYMLINK;
292121986Sjhb	dp = ndp->ni_startdir;
293121986Sjhb	ndp->ni_startdir = NULLVP;
294121986Sjhb	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
295121986Sjhb
296121986Sjhbdirloop:
297139240Sjhb	/*
298139240Sjhb	 * Search a new directory.
299121986Sjhb	 *
300121986Sjhb	 * The cn_hash value is for use by vfs_cache.
301139245Sjhb	 * The last component of the filename is left accessible via
302139245Sjhb	 * cnp->cn_nameptr for callers that need the name. Callers needing
303139245Sjhb	 * the name set the SAVENAME flag. When done, they assume
304139245Sjhb	 * responsibility for freeing the pathname buffer.
305139245Sjhb	 */
306145256Sjkoshy	cnp->cn_consume = 0;
307145256Sjkoshy	cnp->cn_hash = 0;
308145256Sjkoshy	for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
309145256Sjkoshy		cnp->cn_hash += (unsigned char)*cp;
310145256Sjkoshy	cnp->cn_namelen = cp - cnp->cn_nameptr;
311139245Sjhb	if (cnp->cn_namelen > NAME_MAX) {
312141538Sjhb		error = ENAMETOOLONG;
313141538Sjhb		goto bad;
314163219Sjhb	}
315163219Sjhb#ifdef NAMEI_DIAGNOSTIC
316163219Sjhb	{ char c = *cp;
317163219Sjhb	*cp = '\0';
318163219Sjhb	printf("{%s}: ", cnp->cn_nameptr);
319163219Sjhb	*cp = c; }
320163219Sjhb#endif
321141538Sjhb	ndp->ni_pathlen -= cnp->cn_namelen;
322141538Sjhb	ndp->ni_next = cp;
323141538Sjhb
324141538Sjhb	/*
325141538Sjhb	 * Replace multiple slashes by a single slash and trailing slashes
326141538Sjhb	 * by a null.  This must be done before VOP_LOOKUP() because some
327139245Sjhb	 * fs's don't know about trailing slashes.  Remember if there were
328150176Sjhb	 * trailing slashes to handle symlinks, existing non-directories
329141538Sjhb	 * and non-existing files that won't be directories specially later.
330121986Sjhb	 */
331121986Sjhb	trailing_slash = 0;
332121986Sjhb	while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
333141538Sjhb		cp++;
334141538Sjhb		ndp->ni_pathlen--;
335141538Sjhb		if (*cp == '\0') {
336141538Sjhb			trailing_slash = 1;
337141538Sjhb			*ndp->ni_next = '\0';	/* XXX for direnter() ... */
338141538Sjhb		}
339141538Sjhb	}
340141538Sjhb	ndp->ni_next = cp;
341141538Sjhb
342141538Sjhb	cnp->cn_flags |= MAKEENTRY;
343141538Sjhb	if (*cp == '\0' && docache == 0)
344141538Sjhb		cnp->cn_flags &= ~MAKEENTRY;
345141538Sjhb	if (cnp->cn_namelen == 2 &&
346141538Sjhb	    cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
347141538Sjhb		cnp->cn_flags |= ISDOTDOT;
348141538Sjhb	else
349141538Sjhb		cnp->cn_flags &= ~ISDOTDOT;
350141538Sjhb	if (*ndp->ni_next == 0)
351141538Sjhb		cnp->cn_flags |= ISLASTCN;
352141538Sjhb	else
353141538Sjhb		cnp->cn_flags &= ~ISLASTCN;
354141538Sjhb
355141538Sjhb
356141538Sjhb	/*
357141538Sjhb	 * Check for degenerate name (e.g. / or "")
358141538Sjhb	 * which is a way of talking about a directory,
359141538Sjhb	 * e.g. like "/." or ".".
360141538Sjhb	 */
361141538Sjhb	if (cnp->cn_nameptr[0] == '\0') {
362141538Sjhb		if (dp->v_type != VDIR) {
363141538Sjhb			error = ENOTDIR;
364141538Sjhb			goto bad;
365141538Sjhb		}
366141538Sjhb		if (cnp->cn_nameiop != LOOKUP) {
367141538Sjhb			error = EISDIR;
368141538Sjhb			goto bad;
369141538Sjhb		}
370141538Sjhb		if (wantparent) {
371141538Sjhb			ndp->ni_dvp = dp;
372141538Sjhb			VREF(dp);
373141538Sjhb		}
374141538Sjhb		ndp->ni_vp = dp;
375141538Sjhb		if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
376141538Sjhb			VOP_UNLOCK(dp, 0, p);
377141538Sjhb		if (cnp->cn_flags & SAVESTART)
378141538Sjhb			panic("lookup: SAVESTART");
379141538Sjhb		return (0);
380141538Sjhb	}
381141538Sjhb
382141538Sjhb	/*
383141538Sjhb	 * Handle "..": two special cases.
384141538Sjhb	 * 1. If at root directory (e.g. after chroot)
385141538Sjhb	 *    or at absolute root directory
386141538Sjhb	 *    then ignore it so can't get out.
387121986Sjhb	 * 2. If this vnode is the root of a mounted
388121986Sjhb	 *    filesystem, then replace it with the
389121986Sjhb	 *    vnode which was mounted on so we take the
390121986Sjhb	 *    .. in the other file system.
391121986Sjhb	 */
392121986Sjhb	if (cnp->cn_flags & ISDOTDOT) {
393121986Sjhb		for (;;) {
394121986Sjhb			if (dp == ndp->ni_rootdir || dp == rootvnode) {
395121986Sjhb				ndp->ni_dvp = dp;
396121986Sjhb				ndp->ni_vp = dp;
397121986Sjhb				VREF(dp);
398139245Sjhb				goto nextname;
399139245Sjhb			}
400139245Sjhb			if ((dp->v_flag & VROOT) == 0 ||
401139245Sjhb			    (cnp->cn_flags & NOCROSSMOUNT))
402139245Sjhb				break;
403139245Sjhb			tdp = dp;
404139245Sjhb			dp = dp->v_mount->mnt_vnodecovered;
405139245Sjhb			vput(tdp);
406139245Sjhb			VREF(dp);
407139245Sjhb			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
408139245Sjhb		}
409139245Sjhb	}
410163219Sjhb
411163219Sjhb	/*
412163219Sjhb	 * We now have a segment name to search for, and a directory to search.
413163219Sjhb	 */
414163219Sjhbunionlookup:
415163219Sjhb	ndp->ni_dvp = dp;
416163219Sjhb	ndp->ni_vp = NULL;
417163219Sjhb	ASSERT_VOP_LOCKED(dp, "lookup");
418121986Sjhb	if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) {
419121986Sjhb#ifdef DIAGNOSTIC
420121986Sjhb		if (ndp->ni_vp != NULL)
421121986Sjhb			panic("leaf should be empty");
422121986Sjhb#endif
423121986Sjhb#ifdef NAMEI_DIAGNOSTIC
424121986Sjhb		printf("not found\n");
425121986Sjhb#endif
426121986Sjhb		if ((error == ENOENT) &&
427121986Sjhb		    (dp->v_flag & VROOT) &&
428121986Sjhb		    (dp->v_mount->mnt_flag & MNT_UNION)) {
429121986Sjhb			tdp = dp;
430121986Sjhb			dp = dp->v_mount->mnt_vnodecovered;
431121986Sjhb			vput(tdp);
432121986Sjhb			VREF(dp);
433121986Sjhb			vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
434121986Sjhb			goto unionlookup;
435121986Sjhb		}
436121986Sjhb
437121986Sjhb		if (error != EJUSTRETURN)
438121986Sjhb			goto bad;
439121986Sjhb		/*
440121986Sjhb		 * If creating and at end of pathname, then can consider
441121986Sjhb		 * allowing file to be created.
442121986Sjhb		 */
443121986Sjhb		if (rdonly) {
444121986Sjhb			error = EROFS;
445121986Sjhb			goto bad;
446121986Sjhb		}
447121986Sjhb		if (*cp == '\0' && trailing_slash &&
448121986Sjhb		     !(cnp->cn_flags & WILLBEDIR)) {
449121986Sjhb			error = ENOENT;
450121986Sjhb			goto bad;
451121986Sjhb		}
452121986Sjhb		/*
453121986Sjhb		 * We return with ni_vp NULL to indicate that the entry
454121986Sjhb		 * doesn't currently exist, leaving a pointer to the
455121986Sjhb		 * (possibly locked) directory inode in ndp->ni_dvp.
456121986Sjhb		 */
457121986Sjhb		if (cnp->cn_flags & SAVESTART) {
458121986Sjhb			ndp->ni_startdir = ndp->ni_dvp;
459121986Sjhb			VREF(ndp->ni_startdir);
460121986Sjhb		}
461121986Sjhb		return (0);
462121986Sjhb	}
463121986Sjhb#ifdef NAMEI_DIAGNOSTIC
464121986Sjhb	printf("found\n");
465121986Sjhb#endif
466121986Sjhb
467121986Sjhb	ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup");
468121986Sjhb
469121986Sjhb	/*
470121986Sjhb	 * Take into account any additional components consumed by
471121986Sjhb	 * the underlying filesystem.
472121986Sjhb	 */
473121986Sjhb	if (cnp->cn_consume > 0) {
474121986Sjhb		cnp->cn_nameptr += cnp->cn_consume;
475121986Sjhb		ndp->ni_next += cnp->cn_consume;
476121986Sjhb		ndp->ni_pathlen -= cnp->cn_consume;
477121986Sjhb		cnp->cn_consume = 0;
478121986Sjhb	}
479121986Sjhb
480121986Sjhb	dp = ndp->ni_vp;
481121986Sjhb
482121986Sjhb	/*
483121986Sjhb	 * Check to see if the vnode has been mounted on;
484121986Sjhb	 * if so find the root of the mounted file system.
485121986Sjhb	 */
486121986Sjhb	while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
487121986Sjhb	       (cnp->cn_flags & NOCROSSMOUNT) == 0) {
488121986Sjhb		if (vfs_busy(mp, 0, 0, p))
489121986Sjhb			continue;
490121986Sjhb		error = VFS_ROOT(mp, &tdp);
491121986Sjhb		vfs_unbusy(mp, p);
492121986Sjhb		if (error)
493121986Sjhb			goto bad2;
494121986Sjhb		vput(dp);
495121986Sjhb		ndp->ni_vp = dp = tdp;
496121986Sjhb	}
497121986Sjhb
498121986Sjhb	/*
499121986Sjhb	 * Check for symbolic link
500121986Sjhb	 */
501121986Sjhb	if ((dp->v_type == VLNK) &&
502121986Sjhb	    ((cnp->cn_flags & FOLLOW) || trailing_slash ||
503121986Sjhb	     *ndp->ni_next == '/')) {
504121986Sjhb		cnp->cn_flags |= ISSYMLINK;
505121986Sjhb		return (0);
506121986Sjhb	}
507121986Sjhb
508121986Sjhb	/*
509121986Sjhb	 * Check for bogus trailing slashes.
510121986Sjhb	 */
511121986Sjhb	if (trailing_slash && dp->v_type != VDIR) {
512121986Sjhb		error = ENOTDIR;
513121986Sjhb		goto bad2;
514121986Sjhb	}
515121986Sjhb
516121986Sjhbnextname:
517121986Sjhb	/*
518121986Sjhb	 * Not a symbolic link.  If more pathname,
519121986Sjhb	 * continue at next component, else return.
520121986Sjhb	 */
521121986Sjhb	if (*ndp->ni_next == '/') {
522121986Sjhb		cnp->cn_nameptr = ndp->ni_next;
523121986Sjhb		while (*cnp->cn_nameptr == '/') {
524121986Sjhb			cnp->cn_nameptr++;
525121986Sjhb			ndp->ni_pathlen--;
526121986Sjhb		}
527121986Sjhb		if (ndp->ni_dvp != ndp->ni_vp) {
528121986Sjhb		    ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup");
529121986Sjhb		}
530121986Sjhb		vrele(ndp->ni_dvp);
531121986Sjhb		goto dirloop;
532121986Sjhb	}
533121986Sjhb	/*
534121986Sjhb	 * Disallow directory write attempts on read-only file systems.
535121986Sjhb	 */
536121986Sjhb	if (rdonly &&
537121986Sjhb	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
538121986Sjhb		error = EROFS;
539121986Sjhb		goto bad2;
540128930Sjhb	}
541121986Sjhb	if (cnp->cn_flags & SAVESTART) {
542121986Sjhb		ndp->ni_startdir = ndp->ni_dvp;
543128930Sjhb		VREF(ndp->ni_startdir);
544121986Sjhb	}
545121986Sjhb	if (!wantparent)
546128930Sjhb		vrele(ndp->ni_dvp);
547121986Sjhb
548121986Sjhb	if ((cnp->cn_flags & LOCKLEAF) == 0)
549121986Sjhb		VOP_UNLOCK(dp, 0, p);
550121986Sjhb	return (0);
551121986Sjhb
552121986Sjhbbad2:
553128930Sjhb	if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
554128930Sjhb		VOP_UNLOCK(ndp->ni_dvp, 0, p);
555121986Sjhb	vrele(ndp->ni_dvp);
556121986Sjhbbad:
557121986Sjhb	vput(dp);
558121986Sjhb	ndp->ni_vp = NULL;
559140254Sjhb	return (error);
560128930Sjhb}
561121986Sjhb
562121986Sjhb/*
563121986Sjhb * relookup - lookup a path name component
564121986Sjhb *    Used by lookup to re-aquire things.
565128930Sjhb */
566121986Sjhbint
567121986Sjhbrelookup(dvp, vpp, cnp)
568128930Sjhb	struct vnode *dvp, **vpp;
569121986Sjhb	struct componentname *cnp;
570121986Sjhb{
571128930Sjhb	struct proc *p = cnp->cn_proc;
572121986Sjhb	struct vnode *dp = 0;		/* the directory we are searching */
573121986Sjhb	int docache;			/* == 0 do not cache last component */
574121986Sjhb	int wantparent;			/* 1 => wantparent or lockparent flag */
575121986Sjhb	int rdonly;			/* lookup read-only flag bit */
576121986Sjhb	int error = 0;
577128930Sjhb#ifdef NAMEI_DIAGNOSTIC
578128930Sjhb	int newhash;			/* DEBUG: check name hash */
579121986Sjhb	char *cp;			/* DEBUG: check name ptr/len */
580121986Sjhb#endif
581121986Sjhb
582121986Sjhb	/*
583121986Sjhb	 * Setup: break out flag bits into variables.
584121986Sjhb	 */
585128930Sjhb	wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT);
586121986Sjhb	docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
587121986Sjhb	if (cnp->cn_nameiop == DELETE ||
588121986Sjhb	    (wantparent && cnp->cn_nameiop != CREATE))
589139240Sjhb		docache = 0;
590139240Sjhb	rdonly = cnp->cn_flags & RDONLY;
591139240Sjhb	cnp->cn_flags &= ~ISSYMLINK;
592139240Sjhb	dp = dvp;
593121986Sjhb	vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
594139240Sjhb
595139240Sjhb/* dirloop: */
596139240Sjhb	/*
597139240Sjhb	 * Search a new directory.
598139240Sjhb	 *
599139240Sjhb	 * The cn_hash value is for use by vfs_cache.
600139240Sjhb	 * The last component of the filename is left accessible via
601139240Sjhb	 * cnp->cn_nameptr for callers that need the name. Callers needing
602139240Sjhb	 * the name set the SAVENAME flag. When done, they assume
603139240Sjhb	 * responsibility for freeing the pathname buffer.
604139240Sjhb	 */
605139240Sjhb#ifdef NAMEI_DIAGNOSTIC
606139240Sjhb	for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++)
607139240Sjhb		newhash += (unsigned char)*cp;
608122572Sjhb	if (newhash != cnp->cn_hash)
609122572Sjhb		panic("relookup: bad hash");
610122572Sjhb	if (cnp->cn_namelen != cp - cnp->cn_nameptr)
611122572Sjhb		panic ("relookup: bad len");
612122572Sjhb	if (*cp != 0)
613122572Sjhb		panic("relookup: not last component");
614122572Sjhb	printf("{%s}: ", cnp->cn_nameptr);
615153146Sjhb#endif
616121986Sjhb
617121986Sjhb	/*
618121986Sjhb	 * Check for degenerate name (e.g. / or "")
619153146Sjhb	 * which is a way of talking about a directory,
620121986Sjhb	 * e.g. like "/." or ".".
621153146Sjhb	 */
622121986Sjhb	if (cnp->cn_nameptr[0] == '\0') {
623121986Sjhb		if (cnp->cn_nameiop != LOOKUP || wantparent) {
624121986Sjhb			error = EISDIR;
625141538Sjhb			goto bad;
626153666Sjhb		}
627141538Sjhb		if (dp->v_type != VDIR) {
628141538Sjhb			error = ENOTDIR;
629141538Sjhb			goto bad;
630153141Sjhb		}
631153141Sjhb		if (!(cnp->cn_flags & LOCKLEAF))
632153141Sjhb			VOP_UNLOCK(dp, 0, p);
633162708Ssobomax		*vpp = dp;
634162042Ssobomax		if (cnp->cn_flags & SAVESTART)
635162042Ssobomax			panic("lookup: SAVESTART");
636162042Ssobomax		return (0);
637162042Ssobomax	}
638162042Ssobomax
639162042Ssobomax	if (cnp->cn_flags & ISDOTDOT)
640162713Ssobomax		panic ("relookup: lookup on dot-dot");
641162713Ssobomax
642162713Ssobomax	/*
643162713Ssobomax	 * We now have a segment name to search for, and a directory to search.
644162042Ssobomax	 */
645162042Ssobomax	if (error = VOP_LOOKUP(dp, vpp, cnp)) {
646162042Ssobomax#ifdef DIAGNOSTIC
647162087Ssobomax		if (*vpp != NULL)
648162042Ssobomax			panic("leaf should be empty");
649153141Sjhb#endif
650141538Sjhb		if (error != EJUSTRETURN)
651141538Sjhb			goto bad;
652141538Sjhb		/*
653141538Sjhb		 * If creating and at end of pathname, then can consider
654141538Sjhb		 * allowing file to be created.
655141538Sjhb		 */
656141538Sjhb		if (rdonly) {
657141538Sjhb			error = EROFS;
658143034Sjhb			goto bad;
659153666Sjhb		}
660143034Sjhb		/* ASSERT(dvp == ndp->ni_startdir) */
661153666Sjhb		if (cnp->cn_flags & SAVESTART)
662141538Sjhb			VREF(dvp);
663141538Sjhb		/*
664141538Sjhb		 * We return with ni_vp NULL to indicate that the entry
665141538Sjhb		 * doesn't currently exist, leaving a pointer to the
666141538Sjhb		 * (possibly locked) directory inode in ndp->ni_dvp.
667141538Sjhb		 */
668153666Sjhb		return (0);
669141538Sjhb	}
670141538Sjhb	dp = *vpp;
671141538Sjhb
672141538Sjhb#ifdef DIAGNOSTIC
673141538Sjhb	/*
674141538Sjhb	 * Check for symbolic link
675141538Sjhb	 */
676153666Sjhb	if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW))
677141538Sjhb		panic ("relookup: symlink found.\n");
678141538Sjhb#endif
679141538Sjhb
680141538Sjhb	/*
681141538Sjhb	 * Disallow directory write attempts on read-only file systems.
682141538Sjhb	 */
683141538Sjhb	if (rdonly &&
684141538Sjhb	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
685141538Sjhb		error = EROFS;
686141538Sjhb		goto bad2;
687141538Sjhb	}
688141538Sjhb	/* ASSERT(dvp == ndp->ni_startdir) */
689141538Sjhb	if (cnp->cn_flags & SAVESTART)
690141538Sjhb		VREF(dvp);
691141538Sjhb
692141538Sjhb	if (!wantparent)
693141538Sjhb		vrele(dvp);
694141538Sjhb
695141538Sjhb	if (dp->v_type == VREG &&
696141538Sjhb		((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF))
697141538Sjhb		vfs_object_create(dp, cnp->cn_proc, cnp->cn_cred, 1);
698141538Sjhb
699141538Sjhb	if ((cnp->cn_flags & LOCKLEAF) == 0)
700141538Sjhb		VOP_UNLOCK(dp, 0, p);
701141538Sjhb	return (0);
702141538Sjhb
703141538Sjhbbad2:
704141538Sjhb	if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN))
705141538Sjhb		VOP_UNLOCK(dvp, 0, p);
706141538Sjhb	vrele(dvp);
707141538Sjhbbad:
708141538Sjhb	vput(dp);
709141538Sjhb	*vpp = NULL;
710141538Sjhb	return (error);
711141538Sjhb}
712141538Sjhb