1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_lookup.c 7.23 (Berkeley) 01/10/91 8 */ 9 10 #include "param.h" 11 #include "time.h" 12 #include "namei.h" 13 #include "vnode.h" 14 #include "mount.h" 15 #include "errno.h" 16 #include "malloc.h" 17 #include "filedesc.h" 18 19 #ifdef KTRACE 20 #include "user.h" 21 #include "proc.h" 22 #include "ktrace.h" 23 #endif 24 25 /* 26 * Convert a pathname into a pointer to a locked inode. 27 * This is a very central and rather complicated routine. 28 * 29 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 30 * whether the name is to be looked up, created, renamed, or deleted. 31 * When CREATE, RENAME, or DELETE is specified, information usable in 32 * creating, renaming, or deleting a directory entry may be calculated. 33 * If flag has LOCKPARENT or'ed into it and the target of the pathname 34 * exists, namei returns both the target and its parent directory locked. 35 * When creating or renaming and LOCKPARENT is specified, the target may not 36 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 37 * 38 * The FOLLOW flag is set when symbolic links are to be followed 39 * when they occur at the end of the name translation process. 40 * Symbolic links are always followed for all other pathname 41 * components other than the last. 42 * 43 * The segflg defines whether the name is to be copied from user 44 * space or kernel space. 45 * 46 * Overall outline of namei: 47 * 48 * copy in name 49 * get starting directory 50 * dirloop: 51 * copy next component of name to ndp->ni_dent 52 * handle degenerate case where name is null string 53 * if .. and on mounted filesys, find parent 54 * call lookup routine for next component name 55 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 56 * component vnode returned in ni_vp (if it exists), locked. 57 * if symbolic link, massage name in buffer and continue at dirloop 58 * if result inode is mounted on, find mounted on vnode 59 * if more components of name, do next level at dirloop 60 * return the answer in ni_vp as locked vnode; 61 * if LOCKPARENT set, return locked parent in ni_dvp 62 * 63 * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent vnode unlocked. 64 */ 65 namei(ndp) 66 register struct nameidata *ndp; 67 { 68 struct proc *p = u.u_procp; /* XXX */ 69 register struct filedesc *fdp; /* pointer to file descriptor state */ 70 register char *cp; /* pointer into pathname argument */ 71 register struct vnode *dp = 0; /* the directory we are searching */ 72 register int i; /* Temp counter */ 73 struct vnode *tdp; /* saved dp */ 74 struct mount *mp; /* mount table entry */ 75 int docache; /* == 0 do not cache last component */ 76 int flag; /* LOOKUP, CREATE, RENAME or DELETE */ 77 int wantparent; /* 1 => wantparent or lockparent flag */ 78 int lockparent; /* 1 => lockparent flag */ 79 int getbuf; /* 1 => Malloc a pathname buffer */ 80 int rdonly; /* mounted read-only flag bit(s) */ 81 int error = 0; 82 83 /* 84 * Setup: break out flag bits into variables. 85 */ 86 fdp = p->p_fd; 87 ndp->ni_dvp = NULL; 88 flag = ndp->ni_nameiop & OPFLAG; 89 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 90 lockparent = ndp->ni_nameiop & LOCKPARENT; 91 docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE; 92 getbuf = (ndp->ni_nameiop & HASBUF) ^ HASBUF; 93 if (flag == DELETE || wantparent) 94 docache = 0; 95 rdonly = MNT_RDONLY; 96 if (ndp->ni_nameiop & REMOTE) 97 rdonly |= MNT_EXRDONLY; 98 /* 99 * Get a buffer for the name to be translated, and copy the 100 * name into the buffer. 101 */ 102 if (getbuf) { 103 MALLOC(ndp->ni_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 104 if (ndp->ni_segflg == UIO_SYSSPACE) 105 error = copystr(ndp->ni_dirp, ndp->ni_pnbuf, 106 MAXPATHLEN, &ndp->ni_pathlen); 107 else 108 error = copyinstr(ndp->ni_dirp, ndp->ni_pnbuf, 109 MAXPATHLEN, &ndp->ni_pathlen); 110 if (error) { 111 free(ndp->ni_pnbuf, M_NAMEI); 112 ndp->ni_vp = NULL; 113 return (error); 114 } 115 ndp->ni_ptr = ndp->ni_pnbuf; 116 } 117 ndp->ni_loopcnt = 0; 118 dp = fdp->fd_cdir; 119 VREF(dp); 120 #ifdef KTRACE 121 if (KTRPOINT(u.u_procp, KTR_NAMEI)) 122 ktrnamei(u.u_procp->p_tracep, ndp->ni_pnbuf); 123 #endif 124 125 start: 126 /* 127 * Get starting directory. 128 * Done at start of translation and after symbolic link. 129 */ 130 if (*ndp->ni_ptr == '/') { 131 vrele(dp); 132 while (*ndp->ni_ptr == '/') { 133 ndp->ni_ptr++; 134 ndp->ni_pathlen--; 135 } 136 if ((dp = fdp->fd_rdir) == NULL) 137 dp = rootdir; 138 VREF(dp); 139 } 140 VOP_LOCK(dp); 141 ndp->ni_endoff = 0; 142 143 /* 144 * We come to dirloop to search a new directory. 145 */ 146 dirloop: 147 /* 148 * Copy next component of name to ndp->ni_dent. 149 * XXX kern_exec looks at d_name 150 * ??? The ni_hash value may be useful for vfs_cache 151 * XXX There must be the last component of the filename left 152 * somewhere accessible via. ndp for NFS (and any other stateless file 153 * systems) in case they are doing a CREATE. The "Towards a..." noted 154 * that ni_ptr would be left pointing to the last component, but since 155 * the ni_pnbuf gets free'd, that is not a good idea. 156 */ 157 if (getbuf) { 158 ndp->ni_hash = 0; 159 for (cp = ndp->ni_ptr, i = 0; *cp != 0 && *cp != '/'; cp++) { 160 if (i >= MAXNAMLEN) { 161 error = ENAMETOOLONG; 162 goto bad; 163 } 164 if (*cp & 0200) 165 if ((*cp&0377) == ('/'|0200) || 166 flag != DELETE) { 167 error = EINVAL; 168 goto bad; 169 } 170 ndp->ni_dent.d_name[i++] = *cp; 171 ndp->ni_hash += (unsigned char)*cp * i; 172 } 173 ndp->ni_namelen = i; 174 ndp->ni_dent.d_namlen = i; 175 ndp->ni_dent.d_name[i] = '\0'; 176 ndp->ni_pathlen -= i; 177 ndp->ni_next = cp; 178 #ifdef NAMEI_DIAGNOSTIC 179 printf("{%s}: ", ndp->ni_dent.d_name); 180 #endif 181 } 182 cp = ndp->ni_next; 183 ndp->ni_makeentry = 1; 184 if (*cp == '\0' && docache == 0) 185 ndp->ni_makeentry = 0; 186 ndp->ni_isdotdot = (ndp->ni_namelen == 2 && 187 ndp->ni_dent.d_name[1] == '.' && ndp->ni_dent.d_name[0] == '.'); 188 189 /* 190 * Check for degenerate name (e.g. / or "") 191 * which is a way of talking about a directory, 192 * e.g. like "/." or ".". 193 */ 194 if (ndp->ni_ptr[0] == '\0') { 195 if (flag != LOOKUP || wantparent) { 196 error = EISDIR; 197 goto bad; 198 } 199 if (getbuf) 200 free(ndp->ni_pnbuf, M_NAMEI); 201 if (!(ndp->ni_nameiop & LOCKLEAF)) 202 VOP_UNLOCK(dp); 203 ndp->ni_vp = dp; 204 return (0); 205 } 206 207 /* 208 * Handle "..": two special cases. 209 * 1. If at root directory (e.g. after chroot) 210 * then ignore it so can't get out. 211 * 2. If this vnode is the root of a mounted 212 * file system, then replace it with the 213 * vnode which was mounted on so we take the 214 * .. in the other file system. 215 */ 216 if (ndp->ni_isdotdot) { 217 for (;;) { 218 if (dp == fdp->fd_rdir || dp == rootdir) { 219 ndp->ni_dvp = dp; 220 ndp->ni_vp = dp; 221 VREF(dp); 222 goto nextname; 223 } 224 if ((dp->v_flag & VROOT) == 0 || 225 (ndp->ni_nameiop & NOCROSSMOUNT)) 226 break; 227 tdp = dp; 228 dp = dp->v_mount->mnt_vnodecovered; 229 vput(tdp); 230 VREF(dp); 231 VOP_LOCK(dp); 232 } 233 } 234 235 /* 236 * We now have a segment name to search for, and a directory to search. 237 */ 238 if (error = VOP_LOOKUP(dp, ndp)) { 239 if (ndp->ni_vp != NULL) 240 panic("leaf should be empty"); 241 #ifdef NAMEI_DIAGNOSTIC 242 printf("not found\n"); 243 #endif 244 if (flag == LOOKUP || flag == DELETE || 245 error != ENOENT || *cp != 0) 246 goto bad; 247 /* 248 * If creating and at end of pathname, then can consider 249 * allowing file to be created. 250 */ 251 if (ndp->ni_dvp->v_mount->mnt_flag & rdonly) { 252 error = EROFS; 253 goto bad; 254 } 255 /* 256 * We return with ni_vp NULL to indicate that the entry 257 * doesn't currently exist, leaving a pointer to the 258 * (possibly locked) directory inode in ndp->ni_dvp. 259 */ 260 if (getbuf) 261 FREE(ndp->ni_pnbuf, M_NAMEI); 262 return (0); /* should this be ENOENT? */ 263 } 264 #ifdef NAMEI_DIAGNOSTIC 265 printf("found\n"); 266 #endif 267 268 /* 269 * Check for symbolic link 270 */ 271 dp = ndp->ni_vp; 272 if ((dp->v_type == VLNK) && 273 ((ndp->ni_nameiop & FOLLOW) || *ndp->ni_next == '/')) { 274 struct iovec aiov; 275 struct uio auio; 276 int linklen; 277 278 if (!getbuf) 279 panic("namei: unexpected symlink"); 280 if (++ndp->ni_loopcnt > MAXSYMLINKS) { 281 error = ELOOP; 282 goto bad2; 283 } 284 if (ndp->ni_pathlen > 1) 285 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 286 else 287 cp = ndp->ni_pnbuf; 288 aiov.iov_base = cp; 289 aiov.iov_len = MAXPATHLEN; 290 auio.uio_iov = &aiov; 291 auio.uio_iovcnt = 1; 292 auio.uio_offset = 0; 293 auio.uio_rw = UIO_READ; 294 auio.uio_segflg = UIO_SYSSPACE; 295 auio.uio_resid = MAXPATHLEN; 296 if (error = VOP_READLINK(dp, &auio, ndp->ni_cred)) { 297 if (ndp->ni_pathlen > 1) 298 free(cp, M_NAMEI); 299 goto bad2; 300 } 301 linklen = MAXPATHLEN - auio.uio_resid; 302 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 303 if (ndp->ni_pathlen > 1) 304 free(cp, M_NAMEI); 305 error = ENAMETOOLONG; 306 goto bad2; 307 } 308 if (ndp->ni_pathlen > 1) { 309 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 310 FREE(ndp->ni_pnbuf, M_NAMEI); 311 ndp->ni_pnbuf = cp; 312 } else 313 ndp->ni_pnbuf[linklen] = '\0'; 314 ndp->ni_ptr = cp; 315 vput(dp); 316 dp = ndp->ni_dvp; 317 if (lockparent && ndp->ni_pathlen == 1) 318 VOP_UNLOCK(dp); 319 ndp->ni_pathlen += linklen; 320 goto start; 321 } 322 323 /* 324 * Check to see if the vnode has been mounted on; 325 * if so find the root of the mounted file system. 326 */ 327 mntloop: 328 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 329 (ndp->ni_nameiop & NOCROSSMOUNT) == 0) { 330 while(mp->mnt_flag & MNT_MLOCK) { 331 mp->mnt_flag |= MNT_MWAIT; 332 sleep((caddr_t)mp, PVFS); 333 goto mntloop; 334 } 335 error = VFS_ROOT(dp->v_mountedhere, &tdp); 336 if (error) 337 goto bad2; 338 vput(dp); 339 ndp->ni_vp = dp = tdp; 340 } 341 342 nextname: 343 /* 344 * Not a symbolic link. If more pathname, 345 * continue at next component, else return. 346 */ 347 ndp->ni_ptr = ndp->ni_next; 348 if (*ndp->ni_ptr == '/') { 349 while (*ndp->ni_ptr == '/') { 350 ndp->ni_ptr++; 351 ndp->ni_pathlen--; 352 } 353 vrele(ndp->ni_dvp); 354 goto dirloop; 355 } 356 /* 357 * Check for read-only file systems. 358 */ 359 if (flag == DELETE || flag == RENAME) { 360 /* 361 * Disallow directory write attempts on read-only 362 * file systems. 363 */ 364 if ((dp->v_mount->mnt_flag & rdonly) || 365 (wantparent && (ndp->ni_dvp->v_mount->mnt_flag & rdonly))) { 366 error = EROFS; 367 goto bad2; 368 } 369 } 370 if (!wantparent) 371 vrele(ndp->ni_dvp); 372 if ((ndp->ni_nameiop & LOCKLEAF) == 0) 373 VOP_UNLOCK(dp); 374 if (getbuf) 375 FREE(ndp->ni_pnbuf, M_NAMEI); 376 return (0); 377 378 bad2: 379 if (lockparent && *ndp->ni_next == '\0') 380 VOP_UNLOCK(ndp->ni_dvp); 381 vrele(ndp->ni_dvp); 382 bad: 383 vput(dp); 384 ndp->ni_vp = NULL; 385 if (getbuf) 386 FREE(ndp->ni_pnbuf, M_NAMEI); 387 return (error); 388 } 389