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