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