vfs_lookup.c revision 33360
1121986Sjhb/* 2121986Sjhb * Copyright (c) 1982, 1986, 1989, 1993 3121986Sjhb * The Regents of the University of California. All rights reserved. 4121986Sjhb * (c) UNIX System Laboratories, Inc. 5121986Sjhb * All or some portions of this file are derived from material licensed 6121986Sjhb * to the University of California by American Telephone and Telegraph 7121986Sjhb * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8121986Sjhb * the permission of UNIX System Laboratories, Inc. 9121986Sjhb * 10121986Sjhb * Redistribution and use in source and binary forms, with or without 11121986Sjhb * modification, are permitted provided that the following conditions 12121986Sjhb * are met: 13121986Sjhb * 1. Redistributions of source code must retain the above copyright 14121986Sjhb * notice, this list of conditions and the following disclaimer. 15121986Sjhb * 2. Redistributions in binary form must reproduce the above copyright 16121986Sjhb * notice, this list of conditions and the following disclaimer in the 17121986Sjhb * documentation and/or other materials provided with the distribution. 18121986Sjhb * 3. All advertising materials mentioning features or use of this software 19121986Sjhb * must display the following acknowledgement: 20121986Sjhb * This product includes software developed by the University of 21121986Sjhb * California, Berkeley and its contributors. 22121986Sjhb * 4. Neither the name of the University nor the names of its contributors 23121986Sjhb * may be used to endorse or promote products derived from this software 24121986Sjhb * without specific prior written permission. 25121986Sjhb * 26121986Sjhb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27121986Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28121986Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29121986Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30121986Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31121986Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32121986Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33121986Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34121986Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35121986Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36121986Sjhb * SUCH DAMAGE. 37147565Speter * 38147565Speter * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 39151979Sjhb * $Id: vfs_lookup.c,v 1.25 1998/02/06 12:13:30 eivind Exp $ 40151979Sjhb */ 41121986Sjhb 42121986Sjhb#include "opt_ktrace.h" 43121986Sjhb 44121986Sjhb#include <sys/param.h> 45151979Sjhb#include <sys/systm.h> 46151979Sjhb#include <sys/namei.h> 47121986Sjhb#include <sys/vnode.h> 48141538Sjhb#include <sys/mount.h> 49121986Sjhb#include <sys/filedesc.h> 50121986Sjhb#include <sys/proc.h> 51121986Sjhb 52121986Sjhb#ifdef KTRACE 53121986Sjhb#include <sys/ktrace.h> 54153666Sjhb#endif 55121986Sjhb 56121986Sjhb#include <vm/vm_zone.h> 57121986Sjhb 58121986Sjhb/* 59121986Sjhb * Convert a pathname into a pointer to a locked inode. 60121986Sjhb * 61121986Sjhb * The FOLLOW flag is set when symbolic links are to be followed 62121986Sjhb * when they occur at the end of the name translation process. 63151979Sjhb * Symbolic links are always followed for all other pathname 64151979Sjhb * components other than the last. 65151979Sjhb * 66151979Sjhb * The segflg defines whether the name is to be copied from user 67151979Sjhb * space or kernel space. 68121986Sjhb * 69121986Sjhb * Overall outline of namei: 70121986Sjhb * 71121986Sjhb * copy in name 72121986Sjhb * get starting directory 73121986Sjhb * while (!done && !error) { 74121986Sjhb * call lookup to search path. 75122690Sjhb * if symbolic link, massage name in buffer and continue 76139240Sjhb * } 77139240Sjhb */ 78139240Sjhbint 79122690Sjhbnamei(ndp) 80122690Sjhb register struct nameidata *ndp; 81143034Sjhb{ 82143034Sjhb register struct filedesc *fdp; /* pointer to file descriptor state */ 83143034Sjhb register char *cp; /* pointer into pathname argument */ 84141538Sjhb register struct vnode *dp; /* the directory we are searching */ 85151979Sjhb struct iovec aiov; /* uio for reading symbolic links */ 86151979Sjhb struct uio auio; 87151979Sjhb int error, linklen; 88151979Sjhb struct componentname *cnp = &ndp->ni_cnd; 89121986Sjhb struct proc *p = cnp->cn_proc; 90121986Sjhb 91121986Sjhb ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; 92121986Sjhb#ifdef DIAGNOSTIC 93121986Sjhb if (!cnp->cn_cred || !cnp->cn_proc) 94121986Sjhb panic ("namei: bad cred/proc"); 95121986Sjhb if (cnp->cn_nameiop & (~OPMASK)) 96121986Sjhb panic ("namei: nameiop contaminated with flags"); 97121986Sjhb if (cnp->cn_flags & OPMASK) 98121986Sjhb panic ("namei: flags contaminated with nameiops"); 99121986Sjhb#endif 100121986Sjhb fdp = cnp->cn_proc->p_fd; 101121986Sjhb 102121986Sjhb /* 103121986Sjhb * Get a buffer for the name to be translated, and copy the 104121986Sjhb * name into the buffer. 105121986Sjhb */ 106121986Sjhb if ((cnp->cn_flags & HASBUF) == 0) 107121986Sjhb cnp->cn_pnbuf = zalloc(namei_zone); 108121986Sjhb if (ndp->ni_segflg == UIO_SYSSPACE) 109121986Sjhb error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 110121986Sjhb MAXPATHLEN, (u_int *)&ndp->ni_pathlen); 111121986Sjhb else 112121986Sjhb error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 113141538Sjhb MAXPATHLEN, (u_int *)&ndp->ni_pathlen); 114141538Sjhb 115141538Sjhb /* 116141538Sjhb * Don't allow empty pathnames. 117121986Sjhb */ 118121986Sjhb if (!error && *cnp->cn_pnbuf == '\0') 119121986Sjhb error = ENOENT; 120121986Sjhb 121121986Sjhb if (error) { 122121986Sjhb zfree(namei_zone, cnp->cn_pnbuf); 123121986Sjhb ndp->ni_vp = NULL; 124121986Sjhb return (error); 125139245Sjhb } 126139245Sjhb ndp->ni_loopcnt = 0; 127145256Sjkoshy#ifdef KTRACE 128139245Sjhb if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) 129121986Sjhb ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf); 130121986Sjhb#endif 131121986Sjhb 132121986Sjhb /* 133121986Sjhb * Get starting point for the translation. 134121986Sjhb */ 135121986Sjhb ndp->ni_rootdir = fdp->fd_rdir; 136121986Sjhb 137121986Sjhb dp = fdp->fd_cdir; 138122690Sjhb VREF(dp); 139122690Sjhb for (;;) { 140121986Sjhb /* 141121986Sjhb * Check if root directory should replace current directory. 142151979Sjhb * Done at start of translation and after symbolic link. 143151979Sjhb */ 144151979Sjhb cnp->cn_nameptr = cnp->cn_pnbuf; 145141538Sjhb if (*(cnp->cn_nameptr) == '/') { 146141538Sjhb vrele(dp); 147141538Sjhb while (*(cnp->cn_nameptr) == '/') { 148141538Sjhb cnp->cn_nameptr++; 149141538Sjhb ndp->ni_pathlen--; 150121986Sjhb } 151141538Sjhb dp = ndp->ni_rootdir; 152121986Sjhb VREF(dp); 153139245Sjhb } 154163219Sjhb ndp->ni_startdir = dp; 155141538Sjhb error = lookup(ndp); 156141538Sjhb if (error) { 157141538Sjhb zfree(namei_zone, cnp->cn_pnbuf); 158141538Sjhb return (error); 159139245Sjhb } 160139245Sjhb /* 161163219Sjhb * Check for symbolic link 162163219Sjhb */ 163121986Sjhb if ((cnp->cn_flags & ISSYMLINK) == 0) { 164121986Sjhb if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 165121986Sjhb zfree(namei_zone, cnp->cn_pnbuf); 166121986Sjhb else 167121986Sjhb cnp->cn_flags |= HASBUF; 168121986Sjhb 169121986Sjhb if (ndp->ni_vp && ndp->ni_vp->v_type == VREG && 170121986Sjhb (cnp->cn_nameiop != DELETE) && 171121986Sjhb ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF)) 172121986Sjhb vfs_object_create(ndp->ni_vp, 173121986Sjhb ndp->ni_cnd.cn_proc, ndp->ni_cnd.cn_cred, 1); 174121986Sjhb 175121986Sjhb return (0); 176121986Sjhb } 177121986Sjhb if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 178121986Sjhb VOP_UNLOCK(ndp->ni_dvp, 0, p); 179121986Sjhb if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 180121986Sjhb error = ELOOP; 181121986Sjhb break; 182121986Sjhb } 183121986Sjhb if (ndp->ni_pathlen > 1) 184121986Sjhb cp = zalloc(namei_zone); 185121986Sjhb else 186121986Sjhb cp = cnp->cn_pnbuf; 187121986Sjhb aiov.iov_base = cp; 188121986Sjhb aiov.iov_len = MAXPATHLEN; 189121986Sjhb auio.uio_iov = &aiov; 190121986Sjhb auio.uio_iovcnt = 1; 191121986Sjhb auio.uio_offset = 0; 192121986Sjhb auio.uio_rw = UIO_READ; 193121986Sjhb auio.uio_segflg = UIO_SYSSPACE; 194121986Sjhb auio.uio_procp = (struct proc *)0; 195121986Sjhb auio.uio_resid = MAXPATHLEN; 196121986Sjhb error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 197121986Sjhb if (error) { 198121986Sjhb if (ndp->ni_pathlen > 1) 199121986Sjhb zfree(namei_zone, cp); 200121986Sjhb break; 201121986Sjhb } 202121986Sjhb linklen = MAXPATHLEN - auio.uio_resid; 203121986Sjhb if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 204121986Sjhb if (ndp->ni_pathlen > 1) 205121986Sjhb zfree(namei_zone, cp); 206121986Sjhb error = ENAMETOOLONG; 207121986Sjhb break; 208121986Sjhb } 209121986Sjhb if (ndp->ni_pathlen > 1) { 210121986Sjhb bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 211121986Sjhb zfree(namei_zone, cnp->cn_pnbuf); 212121986Sjhb cnp->cn_pnbuf = cp; 213121986Sjhb } else 214156920Sjhb cnp->cn_pnbuf[linklen] = '\0'; 215121986Sjhb ndp->ni_pathlen += linklen; 216121986Sjhb vput(ndp->ni_vp); 217121986Sjhb dp = ndp->ni_dvp; 218121986Sjhb } 219139245Sjhb zfree(namei_zone, cnp->cn_pnbuf); 220151979Sjhb vrele(ndp->ni_dvp); 221121986Sjhb vput(ndp->ni_vp); 222121986Sjhb ndp->ni_vp = NULL; 223121986Sjhb return (error); 224156124Sjhb} 225121986Sjhb 226141538Sjhb/* 227141538Sjhb * Search a pathname. 228141538Sjhb * This is a very central and rather complicated routine. 229151979Sjhb * 230141538Sjhb * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 231141538Sjhb * The starting directory is taken from ni_startdir. The pathname is 232121986Sjhb * descended until done, or a symbolic link is encountered. The variable 233121986Sjhb * ni_more is clear if the path is completed; it is set to one if a 234121986Sjhb * symbolic link needing interpretation is encountered. 235121986Sjhb * 236121986Sjhb * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 237121986Sjhb * whether the name is to be looked up, created, renamed, or deleted. 238121986Sjhb * When CREATE, RENAME, or DELETE is specified, information usable in 239121986Sjhb * creating, renaming, or deleting a directory entry may be calculated. 240121986Sjhb * If flag has LOCKPARENT or'ed into it, the parent directory is returned 241121986Sjhb * locked. If flag has WANTPARENT or'ed into it, the parent directory is 242132156Sjhb * returned unlocked. Otherwise the parent directory is not returned. If 243121986Sjhb * the target of the pathname exists and LOCKLEAF is or'ed into the flag 244121986Sjhb * the target is returned locked, otherwise it is returned unlocked. 245121986Sjhb * When creating or renaming and LOCKPARENT is specified, the target may not 246121986Sjhb * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 247121986Sjhb * 248121986Sjhb * Overall outline of lookup: 249121986Sjhb * 250121986Sjhb * dirloop: 251121986Sjhb * identify next component of name at ndp->ni_ptr 252121986Sjhb * handle degenerate case where name is null string 253121986Sjhb * if .. and crossing mount points and on mounted filesys, find parent 254121986Sjhb * call VOP_LOOKUP routine for next component name 255121986Sjhb * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 256121986Sjhb * component vnode returned in ni_vp (if it exists), locked. 257121986Sjhb * if result vnode is mounted on and crossing mount points, 258121986Sjhb * find mounted on vnode 259121986Sjhb * if more components of name, do next level at dirloop 260121986Sjhb * return the answer in ni_vp, locked if LOCKLEAF set 261121986Sjhb * if LOCKPARENT set, return locked parent in ni_dvp 262121986Sjhb * if WANTPARENT set, return unlocked parent in ni_dvp 263121986Sjhb */ 264121986Sjhbint 265121986Sjhblookup(ndp) 266121986Sjhb register struct nameidata *ndp; 267121986Sjhb{ 268121986Sjhb register char *cp; /* pointer into pathname argument */ 269121986Sjhb register struct vnode *dp = 0; /* the directory we are searching */ 270121986Sjhb struct vnode *tdp; /* saved dp */ 271121986Sjhb struct mount *mp; /* mount table entry */ 272121986Sjhb int docache; /* == 0 do not cache last component */ 273121986Sjhb int wantparent; /* 1 => wantparent or lockparent flag */ 274121986Sjhb int rdonly; /* lookup read-only flag bit */ 275121986Sjhb int trailing_slash; 276121986Sjhb int error = 0; 277121986Sjhb struct componentname *cnp = &ndp->ni_cnd; 278121986Sjhb struct proc *p = cnp->cn_proc; 279139245Sjhb 280139245Sjhb /* 281139245Sjhb * Setup: break out flag bits into variables. 282121986Sjhb */ 283121986Sjhb wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 284121986Sjhb docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 285163219Sjhb if (cnp->cn_nameiop == DELETE || 286121986Sjhb (wantparent && cnp->cn_nameiop != CREATE && 287121986Sjhb cnp->cn_nameiop != LOOKUP)) 288156124Sjhb docache = 0; 289121986Sjhb rdonly = cnp->cn_flags & RDONLY; 290141538Sjhb ndp->ni_dvp = NULL; 291121986Sjhb cnp->cn_flags &= ~ISSYMLINK; 292121986Sjhb dp = ndp->ni_startdir; 293121986Sjhb ndp->ni_startdir = NULLVP; 294121986Sjhb vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 295121986Sjhb 296121986Sjhbdirloop: 297139240Sjhb /* 298139240Sjhb * Search a new directory. 299121986Sjhb * 300121986Sjhb * The cn_hash value is for use by vfs_cache. 301139245Sjhb * The last component of the filename is left accessible via 302139245Sjhb * cnp->cn_nameptr for callers that need the name. Callers needing 303139245Sjhb * the name set the SAVENAME flag. When done, they assume 304139245Sjhb * responsibility for freeing the pathname buffer. 305139245Sjhb */ 306145256Sjkoshy cnp->cn_consume = 0; 307145256Sjkoshy cnp->cn_hash = 0; 308145256Sjkoshy for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 309145256Sjkoshy cnp->cn_hash += (unsigned char)*cp; 310145256Sjkoshy cnp->cn_namelen = cp - cnp->cn_nameptr; 311139245Sjhb if (cnp->cn_namelen > NAME_MAX) { 312141538Sjhb error = ENAMETOOLONG; 313141538Sjhb goto bad; 314163219Sjhb } 315163219Sjhb#ifdef NAMEI_DIAGNOSTIC 316163219Sjhb { char c = *cp; 317163219Sjhb *cp = '\0'; 318163219Sjhb printf("{%s}: ", cnp->cn_nameptr); 319163219Sjhb *cp = c; } 320163219Sjhb#endif 321141538Sjhb ndp->ni_pathlen -= cnp->cn_namelen; 322141538Sjhb ndp->ni_next = cp; 323141538Sjhb 324141538Sjhb /* 325141538Sjhb * Replace multiple slashes by a single slash and trailing slashes 326141538Sjhb * by a null. This must be done before VOP_LOOKUP() because some 327139245Sjhb * fs's don't know about trailing slashes. Remember if there were 328150176Sjhb * trailing slashes to handle symlinks, existing non-directories 329141538Sjhb * and non-existing files that won't be directories specially later. 330121986Sjhb */ 331121986Sjhb trailing_slash = 0; 332121986Sjhb while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) { 333141538Sjhb cp++; 334141538Sjhb ndp->ni_pathlen--; 335141538Sjhb if (*cp == '\0') { 336141538Sjhb trailing_slash = 1; 337141538Sjhb *ndp->ni_next = '\0'; /* XXX for direnter() ... */ 338141538Sjhb } 339141538Sjhb } 340141538Sjhb ndp->ni_next = cp; 341141538Sjhb 342141538Sjhb cnp->cn_flags |= MAKEENTRY; 343141538Sjhb if (*cp == '\0' && docache == 0) 344141538Sjhb cnp->cn_flags &= ~MAKEENTRY; 345141538Sjhb if (cnp->cn_namelen == 2 && 346141538Sjhb cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 347141538Sjhb cnp->cn_flags |= ISDOTDOT; 348141538Sjhb else 349141538Sjhb cnp->cn_flags &= ~ISDOTDOT; 350141538Sjhb if (*ndp->ni_next == 0) 351141538Sjhb cnp->cn_flags |= ISLASTCN; 352141538Sjhb else 353141538Sjhb cnp->cn_flags &= ~ISLASTCN; 354141538Sjhb 355141538Sjhb 356141538Sjhb /* 357141538Sjhb * Check for degenerate name (e.g. / or "") 358141538Sjhb * which is a way of talking about a directory, 359141538Sjhb * e.g. like "/." or ".". 360141538Sjhb */ 361141538Sjhb if (cnp->cn_nameptr[0] == '\0') { 362141538Sjhb if (dp->v_type != VDIR) { 363141538Sjhb error = ENOTDIR; 364141538Sjhb goto bad; 365141538Sjhb } 366141538Sjhb if (cnp->cn_nameiop != LOOKUP) { 367141538Sjhb error = EISDIR; 368141538Sjhb goto bad; 369141538Sjhb } 370141538Sjhb if (wantparent) { 371141538Sjhb ndp->ni_dvp = dp; 372141538Sjhb VREF(dp); 373141538Sjhb } 374141538Sjhb ndp->ni_vp = dp; 375141538Sjhb if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) 376141538Sjhb VOP_UNLOCK(dp, 0, p); 377141538Sjhb if (cnp->cn_flags & SAVESTART) 378141538Sjhb panic("lookup: SAVESTART"); 379141538Sjhb return (0); 380141538Sjhb } 381141538Sjhb 382141538Sjhb /* 383141538Sjhb * Handle "..": two special cases. 384141538Sjhb * 1. If at root directory (e.g. after chroot) 385141538Sjhb * or at absolute root directory 386141538Sjhb * then ignore it so can't get out. 387121986Sjhb * 2. If this vnode is the root of a mounted 388121986Sjhb * filesystem, then replace it with the 389121986Sjhb * vnode which was mounted on so we take the 390121986Sjhb * .. in the other file system. 391121986Sjhb */ 392121986Sjhb if (cnp->cn_flags & ISDOTDOT) { 393121986Sjhb for (;;) { 394121986Sjhb if (dp == ndp->ni_rootdir || dp == rootvnode) { 395121986Sjhb ndp->ni_dvp = dp; 396121986Sjhb ndp->ni_vp = dp; 397121986Sjhb VREF(dp); 398139245Sjhb goto nextname; 399139245Sjhb } 400139245Sjhb if ((dp->v_flag & VROOT) == 0 || 401139245Sjhb (cnp->cn_flags & NOCROSSMOUNT)) 402139245Sjhb break; 403139245Sjhb tdp = dp; 404139245Sjhb dp = dp->v_mount->mnt_vnodecovered; 405139245Sjhb vput(tdp); 406139245Sjhb VREF(dp); 407139245Sjhb vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 408139245Sjhb } 409139245Sjhb } 410163219Sjhb 411163219Sjhb /* 412163219Sjhb * We now have a segment name to search for, and a directory to search. 413163219Sjhb */ 414163219Sjhbunionlookup: 415163219Sjhb ndp->ni_dvp = dp; 416163219Sjhb ndp->ni_vp = NULL; 417163219Sjhb ASSERT_VOP_LOCKED(dp, "lookup"); 418121986Sjhb if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) { 419121986Sjhb#ifdef DIAGNOSTIC 420121986Sjhb if (ndp->ni_vp != NULL) 421121986Sjhb panic("leaf should be empty"); 422121986Sjhb#endif 423121986Sjhb#ifdef NAMEI_DIAGNOSTIC 424121986Sjhb printf("not found\n"); 425121986Sjhb#endif 426121986Sjhb if ((error == ENOENT) && 427121986Sjhb (dp->v_flag & VROOT) && 428121986Sjhb (dp->v_mount->mnt_flag & MNT_UNION)) { 429121986Sjhb tdp = dp; 430121986Sjhb dp = dp->v_mount->mnt_vnodecovered; 431121986Sjhb vput(tdp); 432121986Sjhb VREF(dp); 433121986Sjhb vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 434121986Sjhb goto unionlookup; 435121986Sjhb } 436121986Sjhb 437121986Sjhb if (error != EJUSTRETURN) 438121986Sjhb goto bad; 439121986Sjhb /* 440121986Sjhb * If creating and at end of pathname, then can consider 441121986Sjhb * allowing file to be created. 442121986Sjhb */ 443121986Sjhb if (rdonly) { 444121986Sjhb error = EROFS; 445121986Sjhb goto bad; 446121986Sjhb } 447121986Sjhb if (*cp == '\0' && trailing_slash && 448121986Sjhb !(cnp->cn_flags & WILLBEDIR)) { 449121986Sjhb error = ENOENT; 450121986Sjhb goto bad; 451121986Sjhb } 452121986Sjhb /* 453121986Sjhb * We return with ni_vp NULL to indicate that the entry 454121986Sjhb * doesn't currently exist, leaving a pointer to the 455121986Sjhb * (possibly locked) directory inode in ndp->ni_dvp. 456121986Sjhb */ 457121986Sjhb if (cnp->cn_flags & SAVESTART) { 458121986Sjhb ndp->ni_startdir = ndp->ni_dvp; 459121986Sjhb VREF(ndp->ni_startdir); 460121986Sjhb } 461121986Sjhb return (0); 462121986Sjhb } 463121986Sjhb#ifdef NAMEI_DIAGNOSTIC 464121986Sjhb printf("found\n"); 465121986Sjhb#endif 466121986Sjhb 467121986Sjhb ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup"); 468121986Sjhb 469121986Sjhb /* 470121986Sjhb * Take into account any additional components consumed by 471121986Sjhb * the underlying filesystem. 472121986Sjhb */ 473121986Sjhb if (cnp->cn_consume > 0) { 474121986Sjhb cnp->cn_nameptr += cnp->cn_consume; 475121986Sjhb ndp->ni_next += cnp->cn_consume; 476121986Sjhb ndp->ni_pathlen -= cnp->cn_consume; 477121986Sjhb cnp->cn_consume = 0; 478121986Sjhb } 479121986Sjhb 480121986Sjhb dp = ndp->ni_vp; 481121986Sjhb 482121986Sjhb /* 483121986Sjhb * Check to see if the vnode has been mounted on; 484121986Sjhb * if so find the root of the mounted file system. 485121986Sjhb */ 486121986Sjhb while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 487121986Sjhb (cnp->cn_flags & NOCROSSMOUNT) == 0) { 488121986Sjhb if (vfs_busy(mp, 0, 0, p)) 489121986Sjhb continue; 490121986Sjhb error = VFS_ROOT(mp, &tdp); 491121986Sjhb vfs_unbusy(mp, p); 492121986Sjhb if (error) 493121986Sjhb goto bad2; 494121986Sjhb vput(dp); 495121986Sjhb ndp->ni_vp = dp = tdp; 496121986Sjhb } 497121986Sjhb 498121986Sjhb /* 499121986Sjhb * Check for symbolic link 500121986Sjhb */ 501121986Sjhb if ((dp->v_type == VLNK) && 502121986Sjhb ((cnp->cn_flags & FOLLOW) || trailing_slash || 503121986Sjhb *ndp->ni_next == '/')) { 504121986Sjhb cnp->cn_flags |= ISSYMLINK; 505121986Sjhb return (0); 506121986Sjhb } 507121986Sjhb 508121986Sjhb /* 509121986Sjhb * Check for bogus trailing slashes. 510121986Sjhb */ 511121986Sjhb if (trailing_slash && dp->v_type != VDIR) { 512121986Sjhb error = ENOTDIR; 513121986Sjhb goto bad2; 514121986Sjhb } 515121986Sjhb 516121986Sjhbnextname: 517121986Sjhb /* 518121986Sjhb * Not a symbolic link. If more pathname, 519121986Sjhb * continue at next component, else return. 520121986Sjhb */ 521121986Sjhb if (*ndp->ni_next == '/') { 522121986Sjhb cnp->cn_nameptr = ndp->ni_next; 523121986Sjhb while (*cnp->cn_nameptr == '/') { 524121986Sjhb cnp->cn_nameptr++; 525121986Sjhb ndp->ni_pathlen--; 526121986Sjhb } 527121986Sjhb if (ndp->ni_dvp != ndp->ni_vp) { 528121986Sjhb ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup"); 529121986Sjhb } 530121986Sjhb vrele(ndp->ni_dvp); 531121986Sjhb goto dirloop; 532121986Sjhb } 533121986Sjhb /* 534121986Sjhb * Disallow directory write attempts on read-only file systems. 535121986Sjhb */ 536121986Sjhb if (rdonly && 537121986Sjhb (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 538121986Sjhb error = EROFS; 539121986Sjhb goto bad2; 540128930Sjhb } 541121986Sjhb if (cnp->cn_flags & SAVESTART) { 542121986Sjhb ndp->ni_startdir = ndp->ni_dvp; 543128930Sjhb VREF(ndp->ni_startdir); 544121986Sjhb } 545121986Sjhb if (!wantparent) 546128930Sjhb vrele(ndp->ni_dvp); 547121986Sjhb 548121986Sjhb if ((cnp->cn_flags & LOCKLEAF) == 0) 549121986Sjhb VOP_UNLOCK(dp, 0, p); 550121986Sjhb return (0); 551121986Sjhb 552121986Sjhbbad2: 553128930Sjhb if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') 554128930Sjhb VOP_UNLOCK(ndp->ni_dvp, 0, p); 555121986Sjhb vrele(ndp->ni_dvp); 556121986Sjhbbad: 557121986Sjhb vput(dp); 558121986Sjhb ndp->ni_vp = NULL; 559140254Sjhb return (error); 560128930Sjhb} 561121986Sjhb 562121986Sjhb/* 563121986Sjhb * relookup - lookup a path name component 564121986Sjhb * Used by lookup to re-aquire things. 565128930Sjhb */ 566121986Sjhbint 567121986Sjhbrelookup(dvp, vpp, cnp) 568128930Sjhb struct vnode *dvp, **vpp; 569121986Sjhb struct componentname *cnp; 570121986Sjhb{ 571128930Sjhb struct proc *p = cnp->cn_proc; 572121986Sjhb struct vnode *dp = 0; /* the directory we are searching */ 573121986Sjhb int docache; /* == 0 do not cache last component */ 574121986Sjhb int wantparent; /* 1 => wantparent or lockparent flag */ 575121986Sjhb int rdonly; /* lookup read-only flag bit */ 576121986Sjhb int error = 0; 577128930Sjhb#ifdef NAMEI_DIAGNOSTIC 578128930Sjhb int newhash; /* DEBUG: check name hash */ 579121986Sjhb char *cp; /* DEBUG: check name ptr/len */ 580121986Sjhb#endif 581121986Sjhb 582121986Sjhb /* 583121986Sjhb * Setup: break out flag bits into variables. 584121986Sjhb */ 585128930Sjhb wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); 586121986Sjhb docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 587121986Sjhb if (cnp->cn_nameiop == DELETE || 588121986Sjhb (wantparent && cnp->cn_nameiop != CREATE)) 589139240Sjhb docache = 0; 590139240Sjhb rdonly = cnp->cn_flags & RDONLY; 591139240Sjhb cnp->cn_flags &= ~ISSYMLINK; 592139240Sjhb dp = dvp; 593121986Sjhb vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 594139240Sjhb 595139240Sjhb/* dirloop: */ 596139240Sjhb /* 597139240Sjhb * Search a new directory. 598139240Sjhb * 599139240Sjhb * The cn_hash value is for use by vfs_cache. 600139240Sjhb * The last component of the filename is left accessible via 601139240Sjhb * cnp->cn_nameptr for callers that need the name. Callers needing 602139240Sjhb * the name set the SAVENAME flag. When done, they assume 603139240Sjhb * responsibility for freeing the pathname buffer. 604139240Sjhb */ 605139240Sjhb#ifdef NAMEI_DIAGNOSTIC 606139240Sjhb for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 607139240Sjhb newhash += (unsigned char)*cp; 608122572Sjhb if (newhash != cnp->cn_hash) 609122572Sjhb panic("relookup: bad hash"); 610122572Sjhb if (cnp->cn_namelen != cp - cnp->cn_nameptr) 611122572Sjhb panic ("relookup: bad len"); 612122572Sjhb if (*cp != 0) 613122572Sjhb panic("relookup: not last component"); 614122572Sjhb printf("{%s}: ", cnp->cn_nameptr); 615153146Sjhb#endif 616121986Sjhb 617121986Sjhb /* 618121986Sjhb * Check for degenerate name (e.g. / or "") 619153146Sjhb * which is a way of talking about a directory, 620121986Sjhb * e.g. like "/." or ".". 621153146Sjhb */ 622121986Sjhb if (cnp->cn_nameptr[0] == '\0') { 623121986Sjhb if (cnp->cn_nameiop != LOOKUP || wantparent) { 624121986Sjhb error = EISDIR; 625141538Sjhb goto bad; 626153666Sjhb } 627141538Sjhb if (dp->v_type != VDIR) { 628141538Sjhb error = ENOTDIR; 629141538Sjhb goto bad; 630153141Sjhb } 631153141Sjhb if (!(cnp->cn_flags & LOCKLEAF)) 632153141Sjhb VOP_UNLOCK(dp, 0, p); 633162708Ssobomax *vpp = dp; 634162042Ssobomax if (cnp->cn_flags & SAVESTART) 635162042Ssobomax panic("lookup: SAVESTART"); 636162042Ssobomax return (0); 637162042Ssobomax } 638162042Ssobomax 639162042Ssobomax if (cnp->cn_flags & ISDOTDOT) 640162713Ssobomax panic ("relookup: lookup on dot-dot"); 641162713Ssobomax 642162713Ssobomax /* 643162713Ssobomax * We now have a segment name to search for, and a directory to search. 644162042Ssobomax */ 645162042Ssobomax if (error = VOP_LOOKUP(dp, vpp, cnp)) { 646162042Ssobomax#ifdef DIAGNOSTIC 647162087Ssobomax if (*vpp != NULL) 648162042Ssobomax panic("leaf should be empty"); 649153141Sjhb#endif 650141538Sjhb if (error != EJUSTRETURN) 651141538Sjhb goto bad; 652141538Sjhb /* 653141538Sjhb * If creating and at end of pathname, then can consider 654141538Sjhb * allowing file to be created. 655141538Sjhb */ 656141538Sjhb if (rdonly) { 657141538Sjhb error = EROFS; 658143034Sjhb goto bad; 659153666Sjhb } 660143034Sjhb /* ASSERT(dvp == ndp->ni_startdir) */ 661153666Sjhb if (cnp->cn_flags & SAVESTART) 662141538Sjhb VREF(dvp); 663141538Sjhb /* 664141538Sjhb * We return with ni_vp NULL to indicate that the entry 665141538Sjhb * doesn't currently exist, leaving a pointer to the 666141538Sjhb * (possibly locked) directory inode in ndp->ni_dvp. 667141538Sjhb */ 668153666Sjhb return (0); 669141538Sjhb } 670141538Sjhb dp = *vpp; 671141538Sjhb 672141538Sjhb#ifdef DIAGNOSTIC 673141538Sjhb /* 674141538Sjhb * Check for symbolic link 675141538Sjhb */ 676153666Sjhb if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) 677141538Sjhb panic ("relookup: symlink found.\n"); 678141538Sjhb#endif 679141538Sjhb 680141538Sjhb /* 681141538Sjhb * Disallow directory write attempts on read-only file systems. 682141538Sjhb */ 683141538Sjhb if (rdonly && 684141538Sjhb (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 685141538Sjhb error = EROFS; 686141538Sjhb goto bad2; 687141538Sjhb } 688141538Sjhb /* ASSERT(dvp == ndp->ni_startdir) */ 689141538Sjhb if (cnp->cn_flags & SAVESTART) 690141538Sjhb VREF(dvp); 691141538Sjhb 692141538Sjhb if (!wantparent) 693141538Sjhb vrele(dvp); 694141538Sjhb 695141538Sjhb if (dp->v_type == VREG && 696141538Sjhb ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF)) 697141538Sjhb vfs_object_create(dp, cnp->cn_proc, cnp->cn_cred, 1); 698141538Sjhb 699141538Sjhb if ((cnp->cn_flags & LOCKLEAF) == 0) 700141538Sjhb VOP_UNLOCK(dp, 0, p); 701141538Sjhb return (0); 702141538Sjhb 703141538Sjhbbad2: 704141538Sjhb if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) 705141538Sjhb VOP_UNLOCK(dvp, 0, p); 706141538Sjhb vrele(dvp); 707141538Sjhbbad: 708141538Sjhb vput(dp); 709141538Sjhb *vpp = NULL; 710141538Sjhb return (error); 711141538Sjhb} 712141538Sjhb