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