123401Smckusick /* 237715Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337715Smckusick * All rights reserved. 423401Smckusick * 544457Sbostic * %sccs.include.redist.c% 637715Smckusick * 7*49736Smckusick * @(#)vfs_lookup.c 7.30 (Berkeley) 05/15/91 823401Smckusick */ 930Sbill 1017100Sbloom #include "param.h" 11*49736Smckusick #include "syslimits.h" 1237715Smckusick #include "time.h" 1337715Smckusick #include "namei.h" 1437715Smckusick #include "vnode.h" 1517100Sbloom #include "mount.h" 1637715Smckusick #include "errno.h" 1731650Smckusick #include "malloc.h" 1845914Smckusick #include "filedesc.h" 1945924Smckusick #include "proc.h" 2037715Smckusick 2137582Smarc #ifdef KTRACE 2237582Smarc #include "ktrace.h" 2337582Smarc #endif 2430Sbill 2530Sbill /* 2627268Smckusick * Convert a pathname into a pointer to a locked inode. 2730Sbill * 2816688Smckusick * The FOLLOW flag is set when symbolic links are to be followed 299166Ssam * when they occur at the end of the name translation process. 3027268Smckusick * Symbolic links are always followed for all other pathname 3127268Smckusick * components other than the last. 329166Ssam * 3327268Smckusick * The segflg defines whether the name is to be copied from user 3427268Smckusick * space or kernel space. 3527268Smckusick * 3615798Smckusick * Overall outline of namei: 3715798Smckusick * 387534Sroot * copy in name 397534Sroot * get starting directory 40*49736Smckusick * while (!done && !error) { 41*49736Smckusick * call lookup to search path. 42*49736Smckusick * if symbolic link, massage name in buffer and continue 43*49736Smckusick * } 44*49736Smckusick */ 45*49736Smckusick namei(ndp, p) 46*49736Smckusick register struct nameidata *ndp; 47*49736Smckusick struct proc *p; 48*49736Smckusick { 49*49736Smckusick register struct filedesc *fdp; /* pointer to file descriptor state */ 50*49736Smckusick register char *cp; /* pointer into pathname argument */ 51*49736Smckusick register struct vnode *dp; /* the directory we are searching */ 52*49736Smckusick struct iovec aiov; /* uio for reading symbolic links */ 53*49736Smckusick struct uio auio; 54*49736Smckusick int error, linklen; 55*49736Smckusick 56*49736Smckusick ndp->ni_cred = p->p_ucred; 57*49736Smckusick fdp = p->p_fd; 58*49736Smckusick 59*49736Smckusick /* 60*49736Smckusick * Get a buffer for the name to be translated, and copy the 61*49736Smckusick * name into the buffer. 62*49736Smckusick */ 63*49736Smckusick #ifdef DIAGNOSTIC 64*49736Smckusick if (ndp->ni_nameiop & HASBUF) 65*49736Smckusick panic("namei: reentered"); 66*49736Smckusick #endif 67*49736Smckusick MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 68*49736Smckusick if (ndp->ni_segflg == UIO_SYSSPACE) 69*49736Smckusick error = copystr(ndp->ni_dirp, ndp->ni_pnbuf, 70*49736Smckusick MAXPATHLEN, &ndp->ni_pathlen); 71*49736Smckusick else 72*49736Smckusick error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, 73*49736Smckusick MAXPATHLEN, &ndp->ni_pathlen); 74*49736Smckusick if (error) { 75*49736Smckusick free(ndp->ni_pnbuf, M_NAMEI); 76*49736Smckusick ndp->ni_vp = NULL; 77*49736Smckusick return (error); 78*49736Smckusick } 79*49736Smckusick ndp->ni_loopcnt = 0; 80*49736Smckusick #ifdef KTRACE 81*49736Smckusick if (KTRPOINT(p, KTR_NAMEI)) 82*49736Smckusick ktrnamei(p->p_tracep, ndp->ni_pnbuf); 83*49736Smckusick #endif 84*49736Smckusick 85*49736Smckusick /* 86*49736Smckusick * Get starting point for the translation. 87*49736Smckusick */ 88*49736Smckusick if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) 89*49736Smckusick ndp->ni_rootdir = rootdir; 90*49736Smckusick dp = fdp->fd_cdir; 91*49736Smckusick VREF(dp); 92*49736Smckusick for (;;) { 93*49736Smckusick /* 94*49736Smckusick * Check if root directory should replace current directory. 95*49736Smckusick * Done at start of translation and after symbolic link. 96*49736Smckusick */ 97*49736Smckusick ndp->ni_ptr = ndp->ni_pnbuf; 98*49736Smckusick if (*ndp->ni_ptr == '/') { 99*49736Smckusick vrele(dp); 100*49736Smckusick while (*ndp->ni_ptr == '/') { 101*49736Smckusick ndp->ni_ptr++; 102*49736Smckusick ndp->ni_pathlen--; 103*49736Smckusick } 104*49736Smckusick dp = ndp->ni_rootdir; 105*49736Smckusick VREF(dp); 106*49736Smckusick } 107*49736Smckusick ndp->ni_startdir = dp; 108*49736Smckusick if (error = lookup(ndp, p)) { 109*49736Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 110*49736Smckusick return (error); 111*49736Smckusick } 112*49736Smckusick /* 113*49736Smckusick * Check for symbolic link 114*49736Smckusick */ 115*49736Smckusick if (ndp->ni_more == 0) { 116*49736Smckusick if ((ndp->ni_nameiop & (SAVENAME | SAVESTART)) == 0) 117*49736Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 118*49736Smckusick else 119*49736Smckusick ndp->ni_nameiop |= HASBUF; 120*49736Smckusick return (0); 121*49736Smckusick } 122*49736Smckusick if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1) 123*49736Smckusick VOP_UNLOCK(ndp->ni_dvp); 124*49736Smckusick if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 125*49736Smckusick error = ELOOP; 126*49736Smckusick break; 127*49736Smckusick } 128*49736Smckusick if (ndp->ni_pathlen > 1) 129*49736Smckusick MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 130*49736Smckusick else 131*49736Smckusick cp = ndp->ni_pnbuf; 132*49736Smckusick aiov.iov_base = cp; 133*49736Smckusick aiov.iov_len = MAXPATHLEN; 134*49736Smckusick auio.uio_iov = &aiov; 135*49736Smckusick auio.uio_iovcnt = 1; 136*49736Smckusick auio.uio_offset = 0; 137*49736Smckusick auio.uio_rw = UIO_READ; 138*49736Smckusick auio.uio_segflg = UIO_SYSSPACE; 139*49736Smckusick auio.uio_procp = (struct proc *)0; 140*49736Smckusick auio.uio_resid = MAXPATHLEN; 141*49736Smckusick if (error = VOP_READLINK(ndp->ni_vp, &auio, p->p_ucred)) { 142*49736Smckusick if (ndp->ni_pathlen > 1) 143*49736Smckusick free(cp, M_NAMEI); 144*49736Smckusick break; 145*49736Smckusick } 146*49736Smckusick linklen = MAXPATHLEN - auio.uio_resid; 147*49736Smckusick if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 148*49736Smckusick if (ndp->ni_pathlen > 1) 149*49736Smckusick free(cp, M_NAMEI); 150*49736Smckusick error = ENAMETOOLONG; 151*49736Smckusick break; 152*49736Smckusick } 153*49736Smckusick if (ndp->ni_pathlen > 1) { 154*49736Smckusick bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 155*49736Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 156*49736Smckusick ndp->ni_pnbuf = cp; 157*49736Smckusick } else 158*49736Smckusick ndp->ni_pnbuf[linklen] = '\0'; 159*49736Smckusick ndp->ni_pathlen += linklen; 160*49736Smckusick vput(ndp->ni_vp); 161*49736Smckusick dp = ndp->ni_dvp; 162*49736Smckusick } 163*49736Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 164*49736Smckusick vrele(ndp->ni_dvp); 165*49736Smckusick vput(ndp->ni_vp); 166*49736Smckusick ndp->ni_vp = NULL; 167*49736Smckusick return (error); 168*49736Smckusick } 169*49736Smckusick 170*49736Smckusick /* 171*49736Smckusick * Search a pathname. 172*49736Smckusick * This is a very central and rather complicated routine. 173*49736Smckusick * 174*49736Smckusick * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 175*49736Smckusick * The starting directory is taken from ni_startdir. The pathname is 176*49736Smckusick * descended until done, or a symbolic link is encountered. The variable 177*49736Smckusick * ni_more is clear if the path is completed; it is set to one if a 178*49736Smckusick * symbolic link needing interpretation is encountered. 179*49736Smckusick * 180*49736Smckusick * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 181*49736Smckusick * whether the name is to be looked up, created, renamed, or deleted. 182*49736Smckusick * When CREATE, RENAME, or DELETE is specified, information usable in 183*49736Smckusick * creating, renaming, or deleting a directory entry may be calculated. 184*49736Smckusick * If flag has LOCKPARENT or'ed into it, the parent directory is returned 185*49736Smckusick * locked. If flag has WANTPARENT or'ed into it, the parent directory is 186*49736Smckusick * returned unlocked. Otherwise the parent directory is not returned. If 187*49736Smckusick * the target of the pathname exists and LOCKLEAF is or'ed into the flag 188*49736Smckusick * the target is returned locked, otherwise it is returned unlocked. 189*49736Smckusick * When creating or renaming and LOCKPARENT is specified, the target may not 190*49736Smckusick * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 191*49736Smckusick * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked. 192*49736Smckusick * 193*49736Smckusick * Overall outline of lookup: 194*49736Smckusick * 1957534Sroot * dirloop: 196*49736Smckusick * identify next component of name at ndp->ni_ptr 1977534Sroot * handle degenerate case where name is null string 198*49736Smckusick * if .. and crossing mount points and on mounted filesys, find parent 199*49736Smckusick * call VOP_LOOKUP routine for next component name 200*49736Smckusick * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 201*49736Smckusick * component vnode returned in ni_vp (if it exists), locked. 202*49736Smckusick * if result vnode is mounted on and crossing mount points, 203*49736Smckusick * find mounted on vnode 2047534Sroot * if more components of name, do next level at dirloop 205*49736Smckusick * return the answer in ni_vp, locked if LOCKLEAF set 206*49736Smckusick * if LOCKPARENT set, return locked parent in ni_dvp 207*49736Smckusick * if WANTPARENT set, return unlocked parent in ni_dvp 20830Sbill */ 209*49736Smckusick lookup(ndp, p) 21016688Smckusick register struct nameidata *ndp; 21147540Skarels struct proc *p; 21230Sbill { 2137534Sroot register char *cp; /* pointer into pathname argument */ 21437715Smckusick register struct vnode *dp = 0; /* the directory we are searching */ 21537715Smckusick struct vnode *tdp; /* saved dp */ 21637715Smckusick struct mount *mp; /* mount table entry */ 21718109Smckusick int docache; /* == 0 do not cache last component */ 21837715Smckusick int flag; /* LOOKUP, CREATE, RENAME or DELETE */ 21937715Smckusick int wantparent; /* 1 => wantparent or lockparent flag */ 22041337Smckusick int rdonly; /* mounted read-only flag bit(s) */ 22137715Smckusick int error = 0; 22230Sbill 22341337Smckusick /* 22441337Smckusick * Setup: break out flag bits into variables. 22541337Smckusick */ 22646508Smckusick flag = ndp->ni_nameiop & OPMASK; 22737715Smckusick wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 22816688Smckusick docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; 22946746Smckusick if (flag == DELETE || (wantparent && flag != CREATE)) 23015798Smckusick docache = 0; 23141400Smckusick rdonly = MNT_RDONLY; 23241337Smckusick if (ndp->ni_nameiop & REMOTE) 23341400Smckusick rdonly |= MNT_EXRDONLY; 234*49736Smckusick ndp->ni_dvp = NULL; 235*49736Smckusick ndp->ni_more = 0; 236*49736Smckusick dp = ndp->ni_startdir; 237*49736Smckusick ndp->ni_startdir = NULLVP; 23837715Smckusick VOP_LOCK(dp); 2397534Sroot 2406571Smckusic dirloop: 24130Sbill /* 242*49736Smckusick * Search a new directory. 243*49736Smckusick * 244*49736Smckusick * The ni_hash value is for use by vfs_cache. 245*49736Smckusick * The last component of the filename is left accessible via 246*49736Smckusick * ndp->ptr for callers that need the name. Callers needing 247*49736Smckusick * the name set the SAVENAME flag. When done, they assume 248*49736Smckusick * responsibility for freeing the pathname buffer. 2497534Sroot */ 250*49736Smckusick ndp->ni_hash = 0; 251*49736Smckusick for (cp = ndp->ni_ptr; *cp != 0 && *cp != '/'; cp++) { 252*49736Smckusick ndp->ni_hash += (unsigned char)*cp; 253*49736Smckusick if ((*cp & 0200) == 0) 254*49736Smckusick continue; 255*49736Smckusick if ((*cp & 0377) == ('/' | 0200) || flag != DELETE) { 256*49736Smckusick error = EINVAL; 257*49736Smckusick goto bad; 25837743Smckusick } 259*49736Smckusick } 260*49736Smckusick ndp->ni_namelen = cp - ndp->ni_ptr; 261*49736Smckusick if (ndp->ni_namelen >= NAME_MAX) { 262*49736Smckusick error = ENAMETOOLONG; 263*49736Smckusick goto bad; 264*49736Smckusick } 26537743Smckusick #ifdef NAMEI_DIAGNOSTIC 266*49736Smckusick { char c = *cp; 267*49736Smckusick *cp = '\0'; 268*49736Smckusick printf("{%s}: ", ndp->ni_ptr); 269*49736Smckusick *cp = c; } 27037743Smckusick #endif 271*49736Smckusick ndp->ni_pathlen -= ndp->ni_namelen; 272*49736Smckusick ndp->ni_next = cp; 27337715Smckusick ndp->ni_makeentry = 1; 27418109Smckusick if (*cp == '\0' && docache == 0) 27537715Smckusick ndp->ni_makeentry = 0; 27637715Smckusick ndp->ni_isdotdot = (ndp->ni_namelen == 2 && 277*49736Smckusick ndp->ni_ptr[1] == '.' && ndp->ni_ptr[0] == '.'); 2787534Sroot 2797534Sroot /* 2807534Sroot * Check for degenerate name (e.g. / or "") 2817534Sroot * which is a way of talking about a directory, 2827534Sroot * e.g. like "/." or ".". 2837534Sroot */ 28437715Smckusick if (ndp->ni_ptr[0] == '\0') { 28537715Smckusick if (flag != LOOKUP || wantparent) { 28637715Smckusick error = EISDIR; 2877534Sroot goto bad; 2885972Swnj } 289*49736Smckusick if (dp->v_type != VDIR) { 290*49736Smckusick error = ENOTDIR; 291*49736Smckusick goto bad; 292*49736Smckusick } 29337715Smckusick if (!(ndp->ni_nameiop & LOCKLEAF)) 29437715Smckusick VOP_UNLOCK(dp); 29537715Smckusick ndp->ni_vp = dp; 296*49736Smckusick if (ndp->ni_nameiop & SAVESTART) 297*49736Smckusick panic("lookup: SAVESTART"); 29837715Smckusick return (0); 2995972Swnj } 3007534Sroot 3016571Smckusic /* 30237715Smckusick * Handle "..": two special cases. 30337715Smckusick * 1. If at root directory (e.g. after chroot) 30437715Smckusick * then ignore it so can't get out. 30537715Smckusick * 2. If this vnode is the root of a mounted 306*49736Smckusick * filesystem, then replace it with the 30737715Smckusick * vnode which was mounted on so we take the 30837715Smckusick * .. in the other file system. 30936547Smckusick */ 31037715Smckusick if (ndp->ni_isdotdot) { 31136547Smckusick for (;;) { 312*49736Smckusick if (dp == ndp->ni_rootdir) { 31337715Smckusick ndp->ni_dvp = dp; 31438390Smckusick ndp->ni_vp = dp; 31538347Smckusick VREF(dp); 31637715Smckusick goto nextname; 31736547Smckusick } 31841337Smckusick if ((dp->v_flag & VROOT) == 0 || 319*49736Smckusick (ndp->ni_nameiop & NOCROSSMOUNT)) 32036547Smckusick break; 32137715Smckusick tdp = dp; 32241400Smckusick dp = dp->v_mount->mnt_vnodecovered; 32337715Smckusick vput(tdp); 32438390Smckusick VREF(dp); 32537715Smckusick VOP_LOCK(dp); 32636547Smckusick } 32736547Smckusick } 32836547Smckusick 32936547Smckusick /* 33015798Smckusick * We now have a segment name to search for, and a directory to search. 33115798Smckusick */ 33248025Smckusick if (error = VOP_LOOKUP(dp, ndp, p)) { 333*49736Smckusick #ifdef DIAGNOSTIC 33437715Smckusick if (ndp->ni_vp != NULL) 33537715Smckusick panic("leaf should be empty"); 336*49736Smckusick #endif 33737582Smarc #ifdef NAMEI_DIAGNOSTIC 33837715Smckusick printf("not found\n"); 33937582Smarc #endif 34038581Smckusick if (flag == LOOKUP || flag == DELETE || 34138581Smckusick error != ENOENT || *cp != 0) 34238581Smckusick goto bad; 3435972Swnj /* 34437715Smckusick * If creating and at end of pathname, then can consider 34537715Smckusick * allowing file to be created. 3465972Swnj */ 34741400Smckusick if (ndp->ni_dvp->v_mount->mnt_flag & rdonly) { 34837715Smckusick error = EROFS; 3497534Sroot goto bad; 35038581Smckusick } 3515972Swnj /* 35237715Smckusick * We return with ni_vp NULL to indicate that the entry 35337715Smckusick * doesn't currently exist, leaving a pointer to the 35437715Smckusick * (possibly locked) directory inode in ndp->ni_dvp. 3555972Swnj */ 356*49736Smckusick if (ndp->ni_nameiop & SAVESTART) { 357*49736Smckusick ndp->ni_startdir = ndp->ni_dvp; 358*49736Smckusick VREF(ndp->ni_startdir); 359*49736Smckusick } 360*49736Smckusick return (0); 3617534Sroot } 36237582Smarc #ifdef NAMEI_DIAGNOSTIC 36337715Smckusick printf("found\n"); 36437582Smarc #endif 3657534Sroot 366*49736Smckusick dp = ndp->ni_vp; 3677534Sroot /* 36837715Smckusick * Check for symbolic link 3697534Sroot */ 37037715Smckusick if ((dp->v_type == VLNK) && 37137715Smckusick ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) { 372*49736Smckusick ndp->ni_more = 1; 373*49736Smckusick return (0); 37415798Smckusick } 37515798Smckusick 3767534Sroot /* 37737715Smckusick * Check to see if the vnode has been mounted on; 37837715Smckusick * if so find the root of the mounted file system. 3797534Sroot */ 38037715Smckusick mntloop: 38141337Smckusick while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 38241337Smckusick (ndp->ni_nameiop & NOCROSSMOUNT) == 0) { 38341400Smckusick while(mp->mnt_flag & MNT_MLOCK) { 38441400Smckusick mp->mnt_flag |= MNT_MWAIT; 38537715Smckusick sleep((caddr_t)mp, PVFS); 38637715Smckusick goto mntloop; 38721014Smckusick } 388*49736Smckusick if (error = VFS_ROOT(dp->v_mountedhere, &tdp)) 3897534Sroot goto bad2; 39037715Smckusick vput(dp); 39137715Smckusick ndp->ni_vp = dp = tdp; 39230Sbill } 3937534Sroot 39437715Smckusick nextname: 39530Sbill /* 3967534Sroot * Not a symbolic link. If more pathname, 3977534Sroot * continue at next component, else return. 39830Sbill */ 399*49736Smckusick if (*ndp->ni_next == '/') { 400*49736Smckusick ndp->ni_ptr = ndp->ni_next; 40137715Smckusick while (*ndp->ni_ptr == '/') { 40237715Smckusick ndp->ni_ptr++; 40337715Smckusick ndp->ni_pathlen--; 40437715Smckusick } 40537715Smckusick vrele(ndp->ni_dvp); 4067534Sroot goto dirloop; 40730Sbill } 4087534Sroot /* 40938400Smckusick * Check for read-only file systems. 4107534Sroot */ 41138400Smckusick if (flag == DELETE || flag == RENAME) { 41238267Smckusick /* 41338400Smckusick * Disallow directory write attempts on read-only 41438400Smckusick * file systems. 41538267Smckusick */ 41641400Smckusick if ((dp->v_mount->mnt_flag & rdonly) || 41741400Smckusick (wantparent && (ndp->ni_dvp->v_mount->mnt_flag & rdonly))) { 41838267Smckusick error = EROFS; 41938267Smckusick goto bad2; 42038267Smckusick } 42138267Smckusick } 422*49736Smckusick if (ndp->ni_nameiop & SAVESTART) { 423*49736Smckusick ndp->ni_startdir = ndp->ni_dvp; 424*49736Smckusick VREF(ndp->ni_startdir); 425*49736Smckusick } 42637715Smckusick if (!wantparent) 42737715Smckusick vrele(ndp->ni_dvp); 42837715Smckusick if ((ndp->ni_nameiop & LOCKLEAF) == 0) 42937715Smckusick VOP_UNLOCK(dp); 43037715Smckusick return (0); 4317534Sroot 43237715Smckusick bad2: 433*49736Smckusick if ((ndp->ni_nameiop & LOCKPARENT) && *ndp->ni_next == '\0') 43438001Smckusick VOP_UNLOCK(ndp->ni_dvp); 43537715Smckusick vrele(ndp->ni_dvp); 43637715Smckusick bad: 43737715Smckusick vput(dp); 43837715Smckusick ndp->ni_vp = NULL; 43910849Ssam return (error); 4405972Swnj } 441