123401Smckusick /* 237715Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337715Smckusick * All rights reserved. 423401Smckusick * 537715Smckusick * Redistribution and use in source and binary forms are permitted 637715Smckusick * provided that the above copyright notice and this paragraph are 737715Smckusick * duplicated in all such forms and that any documentation, 837715Smckusick * advertising materials, and other materials related to such 937715Smckusick * distribution and use acknowledge that the software was developed 1037715Smckusick * by the University of California, Berkeley. The name of the 1137715Smckusick * University may not be used to endorse or promote products derived 1237715Smckusick * from this software without specific prior written permission. 1337715Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437715Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537715Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637715Smckusick * 17*41337Smckusick * @(#)vfs_lookup.c 7.20 (Berkeley) 05/03/90 1823401Smckusick */ 1930Sbill 2017100Sbloom #include "param.h" 2137715Smckusick #include "time.h" 2237715Smckusick #include "namei.h" 2337715Smckusick #include "vnode.h" 2417100Sbloom #include "mount.h" 2537715Smckusick #include "errno.h" 2631650Smckusick #include "malloc.h" 2737715Smckusick 2837582Smarc #ifdef KTRACE 2937715Smckusick #include "user.h" 3037582Smarc #include "proc.h" 3137582Smarc #include "ktrace.h" 3237582Smarc #endif 3330Sbill 3430Sbill /* 3527268Smckusick * Convert a pathname into a pointer to a locked inode. 367534Sroot * This is a very central and rather complicated routine. 3730Sbill * 3837715Smckusick * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 3937715Smckusick * whether the name is to be looked up, created, renamed, or deleted. 4037715Smckusick * When CREATE, RENAME, or DELETE is specified, information usable in 4137715Smckusick * creating, renaming, or deleting a directory entry may be calculated. 4237715Smckusick * If flag has LOCKPARENT or'ed into it and the target of the pathname 4337715Smckusick * exists, namei returns both the target and its parent directory locked. 4437715Smckusick * When creating or renaming and LOCKPARENT is specified, the target may not 4537715Smckusick * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 469166Ssam * 4716688Smckusick * The FOLLOW flag is set when symbolic links are to be followed 489166Ssam * when they occur at the end of the name translation process. 4927268Smckusick * Symbolic links are always followed for all other pathname 5027268Smckusick * components other than the last. 519166Ssam * 5227268Smckusick * The segflg defines whether the name is to be copied from user 5327268Smckusick * space or kernel space. 5427268Smckusick * 5515798Smckusick * Overall outline of namei: 5615798Smckusick * 577534Sroot * copy in name 587534Sroot * get starting directory 597534Sroot * dirloop: 6016688Smckusick * copy next component of name to ndp->ni_dent 617534Sroot * handle degenerate case where name is null string 6237715Smckusick * if .. and on mounted filesys, find parent 6337715Smckusick * call lookup routine for next component name 6437715Smckusick * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 6537715Smckusick * component vnode returned in ni_vp (if it exists), locked. 667534Sroot * if symbolic link, massage name in buffer and continue at dirloop 6737715Smckusick * if result inode is mounted on, find mounted on vnode 687534Sroot * if more components of name, do next level at dirloop 6937715Smckusick * return the answer in ni_vp as locked vnode; 7037715Smckusick * if LOCKPARENT set, return locked parent in ni_dvp 719166Ssam * 7237715Smckusick * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked. 7330Sbill */ 7416688Smckusick namei(ndp) 7516688Smckusick register struct nameidata *ndp; 7630Sbill { 777534Sroot register char *cp; /* pointer into pathname argument */ 7837715Smckusick register struct vnode *dp = 0; /* the directory we are searching */ 7937715Smckusick register int i; /* Temp counter */ 8037715Smckusick struct vnode *tdp; /* saved dp */ 8137715Smckusick struct mount *mp; /* mount table entry */ 8218109Smckusick int docache; /* == 0 do not cache last component */ 8337715Smckusick int flag; /* LOOKUP, CREATE, RENAME or DELETE */ 8437715Smckusick int wantparent; /* 1 => wantparent or lockparent flag */ 8538001Smckusick int lockparent; /* 1 => lockparent flag */ 86*41337Smckusick int getbuf; /* 1 => Malloc a pathname buffer */ 87*41337Smckusick int rdonly; /* mounted read-only flag bit(s) */ 8837715Smckusick int error = 0; 8930Sbill 90*41337Smckusick /* 91*41337Smckusick * Setup: break out flag bits into variables. 92*41337Smckusick */ 9339758Smckusick ndp->ni_dvp = NULL; 9437715Smckusick flag = ndp->ni_nameiop & OPFLAG; 9537715Smckusick wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 9638001Smckusick lockparent = ndp->ni_nameiop & LOCKPARENT; 9716688Smckusick docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; 98*41337Smckusick getbuf = (ndp->ni_nameiop & HASBUF) ^ HASBUF; 9937715Smckusick if (flag == DELETE || wantparent) 10015798Smckusick docache = 0; 101*41337Smckusick rdonly = M_RDONLY; 102*41337Smckusick if (ndp->ni_nameiop & REMOTE) 103*41337Smckusick rdonly |= M_EXRDONLY; 10430Sbill /* 1057534Sroot * Get a buffer for the name to be translated, and copy the 1067534Sroot * name into the buffer. 1075972Swnj */ 108*41337Smckusick if (getbuf) { 109*41337Smckusick MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 110*41337Smckusick if (ndp->ni_segflg == UIO_SYSSPACE) 111*41337Smckusick error = copystr(ndp->ni_dirp, ndp->ni_pnbuf, 112*41337Smckusick MAXPATHLEN, &ndp->ni_pathlen); 113*41337Smckusick else 114*41337Smckusick error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, 115*41337Smckusick MAXPATHLEN, &ndp->ni_pathlen); 116*41337Smckusick if (error) { 117*41337Smckusick free(ndp->ni_pnbuf, M_NAMEI); 118*41337Smckusick ndp->ni_vp = NULL; 119*41337Smckusick return (error); 120*41337Smckusick } 121*41337Smckusick ndp->ni_ptr = ndp->ni_pnbuf; 1225972Swnj } 12337715Smckusick ndp->ni_loopcnt = 0; 12437715Smckusick dp = ndp->ni_cdir; 12538347Smckusick VREF(dp); 12637582Smarc #ifdef KTRACE 12737582Smarc if (KTRPOINT(u.u_procp, KTR_NAMEI)) 12837715Smckusick ktrnamei(u.u_procp->p_tracep, ndp->ni_pnbuf); 12937582Smarc #endif 1307534Sroot 13137715Smckusick start: 1325972Swnj /* 1337534Sroot * Get starting directory. 13437715Smckusick * Done at start of translation and after symbolic link. 13530Sbill */ 13637715Smckusick if (*ndp->ni_ptr == '/') { 13737715Smckusick vrele(dp); 13837715Smckusick while (*ndp->ni_ptr == '/') { 13937715Smckusick ndp->ni_ptr++; 14037715Smckusick ndp->ni_pathlen--; 14137715Smckusick } 14237715Smckusick if ((dp = ndp->ni_rdir) == NULL) 14330Sbill dp = rootdir; 14438347Smckusick VREF(dp); 14537715Smckusick } 14637715Smckusick VOP_LOCK(dp); 14718027Smckusick ndp->ni_endoff = 0; 1487534Sroot 1497534Sroot /* 1507534Sroot * We come to dirloop to search a new directory. 1517534Sroot */ 1526571Smckusic dirloop: 15330Sbill /* 15416688Smckusick * Copy next component of name to ndp->ni_dent. 15537715Smckusick * XXX kern_exec looks at d_name 15637715Smckusick * ??? The ni_hash value may be useful for vfs_cache 15737715Smckusick * XXX There must be the last component of the filename left 15837715Smckusick * somewhere accessible via. ndp for NFS (and any other stateless file 15937715Smckusick * systems) in case they are doing a CREATE. The "Towards a..." noted 16037715Smckusick * that ni_ptr would be left pointing to the last component, but since 16137715Smckusick * the ni_pnbuf gets free'd, that is not a good idea. 1627534Sroot */ 163*41337Smckusick if (getbuf) { 164*41337Smckusick ndp->ni_hash = 0; 165*41337Smckusick for (cp = ndp->ni_ptr, i = 0; *cp != 0 && *cp != '/'; cp++) { 166*41337Smckusick if (i >= MAXNAMLEN) { 167*41337Smckusick error = ENAMETOOLONG; 168*41337Smckusick goto bad; 169*41337Smckusick } 170*41337Smckusick if (*cp & 0200) 171*41337Smckusick if ((*cp&0377) == ('/'|0200) || 172*41337Smckusick flag != DELETE) { 173*41337Smckusick error = EINVAL; 174*41337Smckusick goto bad; 175*41337Smckusick } 176*41337Smckusick ndp->ni_dent.d_name[i++] = *cp; 177*41337Smckusick ndp->ni_hash += (unsigned char)*cp * i; 17837743Smckusick } 179*41337Smckusick ndp->ni_namelen = i; 180*41337Smckusick ndp->ni_dent.d_namlen = i; 181*41337Smckusick ndp->ni_dent.d_name[i] = '\0'; 182*41337Smckusick ndp->ni_pathlen -= i; 183*41337Smckusick ndp->ni_next = cp; 18437743Smckusick #ifdef NAMEI_DIAGNOSTIC 185*41337Smckusick printf("{%s}: ", ndp->ni_dent.d_name); 18637743Smckusick #endif 1875972Swnj } 188*41337Smckusick cp = ndp->ni_next; 18937715Smckusick ndp->ni_makeentry = 1; 19018109Smckusick if (*cp == '\0' && docache == 0) 19137715Smckusick ndp->ni_makeentry = 0; 19237715Smckusick ndp->ni_isdotdot = (ndp->ni_namelen == 2 && 19337715Smckusick ndp->ni_dent.d_name[1] == '.' && ndp->ni_dent.d_name[0] == '.'); 1947534Sroot 1957534Sroot /* 1967534Sroot * Check for degenerate name (e.g. / or "") 1977534Sroot * which is a way of talking about a directory, 1987534Sroot * e.g. like "/." or ".". 1997534Sroot */ 20037715Smckusick if (ndp->ni_ptr[0] == '\0') { 20137715Smckusick if (flag != LOOKUP || wantparent) { 20237715Smckusick error = EISDIR; 2037534Sroot goto bad; 2045972Swnj } 205*41337Smckusick if (getbuf) 206*41337Smckusick free(ndp->ni_pnbuf, M_NAMEI); 20737715Smckusick if (!(ndp->ni_nameiop & LOCKLEAF)) 20837715Smckusick VOP_UNLOCK(dp); 20937715Smckusick ndp->ni_vp = dp; 21037715Smckusick return (0); 2115972Swnj } 2127534Sroot 2136571Smckusic /* 21437715Smckusick * Handle "..": two special cases. 21537715Smckusick * 1. If at root directory (e.g. after chroot) 21637715Smckusick * then ignore it so can't get out. 21737715Smckusick * 2. If this vnode is the root of a mounted 21837715Smckusick * file system, then replace it with the 21937715Smckusick * vnode which was mounted on so we take the 22037715Smckusick * .. in the other file system. 22136547Smckusick */ 22237715Smckusick if (ndp->ni_isdotdot) { 22336547Smckusick for (;;) { 22437715Smckusick if (dp == ndp->ni_rdir || dp == rootdir) { 22537715Smckusick ndp->ni_dvp = dp; 22638390Smckusick ndp->ni_vp = dp; 22738347Smckusick VREF(dp); 22837715Smckusick goto nextname; 22936547Smckusick } 230*41337Smckusick if ((dp->v_flag & VROOT) == 0 || 231*41337Smckusick (ndp->ni_nameiop & NOCROSSMOUNT)) 23236547Smckusick break; 23337715Smckusick tdp = dp; 23437715Smckusick dp = dp->v_mount->m_vnodecovered; 23537715Smckusick vput(tdp); 23638390Smckusick VREF(dp); 23737715Smckusick VOP_LOCK(dp); 23836547Smckusick } 23936547Smckusick } 24036547Smckusick 24136547Smckusick /* 24215798Smckusick * We now have a segment name to search for, and a directory to search. 24315798Smckusick */ 24437715Smckusick if (error = VOP_LOOKUP(dp, ndp)) { 24537715Smckusick if (ndp->ni_vp != NULL) 24637715Smckusick panic("leaf should be empty"); 24737582Smarc #ifdef NAMEI_DIAGNOSTIC 24837715Smckusick printf("not found\n"); 24937582Smarc #endif 25038581Smckusick if (flag == LOOKUP || flag == DELETE || 25138581Smckusick error != ENOENT || *cp != 0) 25238581Smckusick goto bad; 2535972Swnj /* 25437715Smckusick * If creating and at end of pathname, then can consider 25537715Smckusick * allowing file to be created. 2565972Swnj */ 257*41337Smckusick if (ndp->ni_dvp->v_mount->m_flag & rdonly) { 25837715Smckusick error = EROFS; 2597534Sroot goto bad; 26038581Smckusick } 2615972Swnj /* 26237715Smckusick * We return with ni_vp NULL to indicate that the entry 26337715Smckusick * doesn't currently exist, leaving a pointer to the 26437715Smckusick * (possibly locked) directory inode in ndp->ni_dvp. 2655972Swnj */ 266*41337Smckusick if (getbuf) 267*41337Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 26837715Smckusick return (0); /* should this be ENOENT? */ 2697534Sroot } 27037582Smarc #ifdef NAMEI_DIAGNOSTIC 27137715Smckusick printf("found\n"); 27237582Smarc #endif 2737534Sroot 2747534Sroot /* 27537715Smckusick * Check for symbolic link 2767534Sroot */ 27737715Smckusick dp = ndp->ni_vp; 27837715Smckusick if ((dp->v_type == VLNK) && 27937715Smckusick ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) { 28037715Smckusick struct iovec aiov; 28137715Smckusick struct uio auio; 28237715Smckusick int linklen; 2837534Sroot 284*41337Smckusick if (!getbuf) 285*41337Smckusick panic("namei: unexpected symlink"); 28637715Smckusick if (++ndp->ni_loopcnt > MAXSYMLINKS) { 28737715Smckusick error = ELOOP; 28837715Smckusick goto bad2; 28937715Smckusick } 29038215Smckusick if (ndp->ni_pathlen > 1) 29137715Smckusick MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 2927534Sroot else 29337715Smckusick cp = ndp->ni_pnbuf; 29437715Smckusick aiov.iov_base = cp; 29537715Smckusick aiov.iov_len = MAXPATHLEN; 29637715Smckusick auio.uio_iov = &aiov; 29737715Smckusick auio.uio_iovcnt = 1; 29837715Smckusick auio.uio_offset = 0; 29937715Smckusick auio.uio_rw = UIO_READ; 30037715Smckusick auio.uio_segflg = UIO_SYSSPACE; 30137715Smckusick auio.uio_resid = MAXPATHLEN; 30237715Smckusick if (error = VOP_READLINK(dp, &auio, ndp->ni_cred)) { 30338215Smckusick if (ndp->ni_pathlen > 1) 30437715Smckusick free(cp, M_NAMEI); 30537715Smckusick goto bad2; 3069166Ssam } 30737715Smckusick linklen = MAXPATHLEN - auio.uio_resid; 30837715Smckusick if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 30938215Smckusick if (ndp->ni_pathlen > 1) 31037715Smckusick free(cp, M_NAMEI); 31137715Smckusick error = ENAMETOOLONG; 31212011Smckusick goto bad2; 31315798Smckusick } 31438215Smckusick if (ndp->ni_pathlen > 1) { 31538215Smckusick bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 31637715Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 31737715Smckusick ndp->ni_pnbuf = cp; 31838215Smckusick } else 31938001Smckusick ndp->ni_pnbuf[linklen] = '\0'; 32037715Smckusick ndp->ni_ptr = cp; 32137715Smckusick vput(dp); 32237715Smckusick dp = ndp->ni_dvp; 32338393Smckusick if (lockparent && ndp->ni_pathlen == 1) 32438001Smckusick VOP_UNLOCK(dp); 32538393Smckusick ndp->ni_pathlen += linklen; 32637715Smckusick goto start; 32715798Smckusick } 32815798Smckusick 3297534Sroot /* 33037715Smckusick * Check to see if the vnode has been mounted on; 33137715Smckusick * if so find the root of the mounted file system. 3327534Sroot */ 33337715Smckusick mntloop: 334*41337Smckusick while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 335*41337Smckusick (ndp->ni_nameiop & NOCROSSMOUNT) == 0) { 33637715Smckusick while(mp->m_flag & M_MLOCK) { 33737715Smckusick mp->m_flag |= M_MWAIT; 33837715Smckusick sleep((caddr_t)mp, PVFS); 33937715Smckusick goto mntloop; 34021014Smckusick } 34137715Smckusick error = VFS_ROOT(dp->v_mountedhere, &tdp); 34237715Smckusick if (error) 3437534Sroot goto bad2; 34437715Smckusick vput(dp); 34537715Smckusick ndp->ni_vp = dp = tdp; 34630Sbill } 3477534Sroot 34837715Smckusick nextname: 34930Sbill /* 3507534Sroot * Not a symbolic link. If more pathname, 3517534Sroot * continue at next component, else return. 35230Sbill */ 35337715Smckusick ndp->ni_ptr = ndp->ni_next; 35437715Smckusick if (*ndp->ni_ptr == '/') { 35537715Smckusick while (*ndp->ni_ptr == '/') { 35637715Smckusick ndp->ni_ptr++; 35737715Smckusick ndp->ni_pathlen--; 35837715Smckusick } 35937715Smckusick vrele(ndp->ni_dvp); 3607534Sroot goto dirloop; 36130Sbill } 3627534Sroot /* 36338400Smckusick * Check for read-only file systems. 3647534Sroot */ 36538400Smckusick if (flag == DELETE || flag == RENAME) { 36638267Smckusick /* 36738400Smckusick * Disallow directory write attempts on read-only 36838400Smckusick * file systems. 36938267Smckusick */ 370*41337Smckusick if ((dp->v_mount->m_flag & rdonly) || 371*41337Smckusick (wantparent && (ndp->ni_dvp->v_mount->m_flag & rdonly))) { 37238267Smckusick error = EROFS; 37338267Smckusick goto bad2; 37438267Smckusick } 37538267Smckusick } 37637715Smckusick if (!wantparent) 37737715Smckusick vrele(ndp->ni_dvp); 37837715Smckusick if ((ndp->ni_nameiop & LOCKLEAF) == 0) 37937715Smckusick VOP_UNLOCK(dp); 380*41337Smckusick if (getbuf) 381*41337Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 38237715Smckusick return (0); 3837534Sroot 38437715Smckusick bad2: 38538001Smckusick if (lockparent && *ndp->ni_next == '\0') 38638001Smckusick VOP_UNLOCK(ndp->ni_dvp); 38737715Smckusick vrele(ndp->ni_dvp); 38837715Smckusick bad: 38937715Smckusick vput(dp); 39037715Smckusick ndp->ni_vp = NULL; 391*41337Smckusick if (getbuf) 392*41337Smckusick FREE(ndp->ni_pnbuf, M_NAMEI); 39310849Ssam return (error); 3945972Swnj } 395