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