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