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 * %sccs.include.redist.c% 11 * 12 * @(#)vfs_lookup.c 8.3 (Berkeley) 01/21/94 13 */ 14 15 #include <sys/param.h> 16 #include <sys/syslimits.h> 17 #include <sys/time.h> 18 #include <sys/namei.h> 19 #include <sys/vnode.h> 20 #include <sys/mount.h> 21 #include <sys/errno.h> 22 #include <sys/malloc.h> 23 #include <sys/filedesc.h> 24 #include <sys/proc.h> 25 26 #ifdef KTRACE 27 #include <sys/ktrace.h> 28 #endif 29 30 /* 31 * Convert a pathname into a pointer to a locked inode. 32 * 33 * The FOLLOW flag is set when symbolic links are to be followed 34 * when they occur at the end of the name translation process. 35 * Symbolic links are always followed for all other pathname 36 * components other than the last. 37 * 38 * The segflg defines whether the name is to be copied from user 39 * space or kernel space. 40 * 41 * Overall outline of namei: 42 * 43 * copy in name 44 * get starting directory 45 * while (!done && !error) { 46 * call lookup to search path. 47 * if symbolic link, massage name in buffer and continue 48 * } 49 */ 50 int 51 namei(ndp) 52 register struct nameidata *ndp; 53 { 54 register struct filedesc *fdp; /* pointer to file descriptor state */ 55 register char *cp; /* pointer into pathname argument */ 56 register struct vnode *dp; /* the directory we are searching */ 57 struct iovec aiov; /* uio for reading symbolic links */ 58 struct uio auio; 59 int error, linklen; 60 struct componentname *cnp = &ndp->ni_cnd; 61 62 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; 63 #ifdef DIAGNOSTIC 64 if (!cnp->cn_cred || !cnp->cn_proc) 65 panic ("namei: bad cred/proc"); 66 if (cnp->cn_nameiop & (~OPMASK)) 67 panic ("namei: nameiop contaminated with flags"); 68 if (cnp->cn_flags & OPMASK) 69 panic ("namei: flags contaminated with nameiops"); 70 #endif 71 fdp = cnp->cn_proc->p_fd; 72 73 /* 74 * Get a buffer for the name to be translated, and copy the 75 * name into the buffer. 76 */ 77 if ((cnp->cn_flags & HASBUF) == 0) 78 MALLOC(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 79 if (ndp->ni_segflg == UIO_SYSSPACE) 80 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 81 MAXPATHLEN, &ndp->ni_pathlen); 82 else 83 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 84 MAXPATHLEN, &ndp->ni_pathlen); 85 if (error) { 86 free(cnp->cn_pnbuf, M_NAMEI); 87 ndp->ni_vp = NULL; 88 return (error); 89 } 90 ndp->ni_loopcnt = 0; 91 #ifdef KTRACE 92 if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) 93 ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf); 94 #endif 95 96 /* 97 * Get starting point for the translation. 98 */ 99 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) 100 ndp->ni_rootdir = rootvnode; 101 dp = fdp->fd_cdir; 102 VREF(dp); 103 for (;;) { 104 /* 105 * Check if root directory should replace current directory. 106 * Done at start of translation and after symbolic link. 107 */ 108 cnp->cn_nameptr = cnp->cn_pnbuf; 109 if (*(cnp->cn_nameptr) == '/') { 110 vrele(dp); 111 while (*(cnp->cn_nameptr) == '/') { 112 cnp->cn_nameptr++; 113 ndp->ni_pathlen--; 114 } 115 dp = ndp->ni_rootdir; 116 VREF(dp); 117 } 118 ndp->ni_startdir = dp; 119 if (error = lookup(ndp)) { 120 FREE(cnp->cn_pnbuf, M_NAMEI); 121 return (error); 122 } 123 /* 124 * Check for symbolic link 125 */ 126 if ((cnp->cn_flags & ISSYMLINK) == 0) { 127 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 128 FREE(cnp->cn_pnbuf, M_NAMEI); 129 else 130 cnp->cn_flags |= HASBUF; 131 return (0); 132 } 133 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 134 VOP_UNLOCK(ndp->ni_dvp); 135 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 136 error = ELOOP; 137 break; 138 } 139 if (ndp->ni_pathlen > 1) 140 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 141 else 142 cp = cnp->cn_pnbuf; 143 aiov.iov_base = cp; 144 aiov.iov_len = MAXPATHLEN; 145 auio.uio_iov = &aiov; 146 auio.uio_iovcnt = 1; 147 auio.uio_offset = 0; 148 auio.uio_rw = UIO_READ; 149 auio.uio_segflg = UIO_SYSSPACE; 150 auio.uio_procp = (struct proc *)0; 151 auio.uio_resid = MAXPATHLEN; 152 if (error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred)) { 153 if (ndp->ni_pathlen > 1) 154 free(cp, M_NAMEI); 155 break; 156 } 157 linklen = MAXPATHLEN - auio.uio_resid; 158 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 159 if (ndp->ni_pathlen > 1) 160 free(cp, M_NAMEI); 161 error = ENAMETOOLONG; 162 break; 163 } 164 if (ndp->ni_pathlen > 1) { 165 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 166 FREE(cnp->cn_pnbuf, M_NAMEI); 167 cnp->cn_pnbuf = cp; 168 } else 169 cnp->cn_pnbuf[linklen] = '\0'; 170 ndp->ni_pathlen += linklen; 171 vput(ndp->ni_vp); 172 dp = ndp->ni_dvp; 173 } 174 FREE(cnp->cn_pnbuf, M_NAMEI); 175 vrele(ndp->ni_dvp); 176 vput(ndp->ni_vp); 177 ndp->ni_vp = NULL; 178 return (error); 179 } 180 181 /* 182 * Search a pathname. 183 * This is a very central and rather complicated routine. 184 * 185 * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 186 * The starting directory is taken from ni_startdir. The pathname is 187 * descended until done, or a symbolic link is encountered. The variable 188 * ni_more is clear if the path is completed; it is set to one if a 189 * symbolic link needing interpretation is encountered. 190 * 191 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 192 * whether the name is to be looked up, created, renamed, or deleted. 193 * When CREATE, RENAME, or DELETE is specified, information usable in 194 * creating, renaming, or deleting a directory entry may be calculated. 195 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 196 * locked. If flag has WANTPARENT or'ed into it, the parent directory is 197 * returned unlocked. Otherwise the parent directory is not returned. If 198 * the target of the pathname exists and LOCKLEAF is or'ed into the flag 199 * the target is returned locked, otherwise it is returned unlocked. 200 * When creating or renaming and LOCKPARENT is specified, the target may not 201 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 202 * 203 * Overall outline of lookup: 204 * 205 * dirloop: 206 * identify next component of name at ndp->ni_ptr 207 * handle degenerate case where name is null string 208 * if .. and crossing mount points and on mounted filesys, find parent 209 * call VOP_LOOKUP routine for next component name 210 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 211 * component vnode returned in ni_vp (if it exists), locked. 212 * if result vnode is mounted on and crossing mount points, 213 * find mounted on vnode 214 * if more components of name, do next level at dirloop 215 * return the answer in ni_vp, locked if LOCKLEAF set 216 * if LOCKPARENT set, return locked parent in ni_dvp 217 * if WANTPARENT set, return unlocked parent in ni_dvp 218 */ 219 int 220 lookup(ndp) 221 register struct nameidata *ndp; 222 { 223 register char *cp; /* pointer into pathname argument */ 224 register struct vnode *dp = 0; /* the directory we are searching */ 225 struct vnode *tdp; /* saved dp */ 226 struct mount *mp; /* mount table entry */ 227 int docache; /* == 0 do not cache last component */ 228 int wantparent; /* 1 => wantparent or lockparent flag */ 229 int rdonly; /* lookup read-only flag bit */ 230 int error = 0; 231 struct componentname *cnp = &ndp->ni_cnd; 232 233 /* 234 * Setup: break out flag bits into variables. 235 */ 236 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 237 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 238 if (cnp->cn_nameiop == DELETE || 239 (wantparent && cnp->cn_nameiop != CREATE)) 240 docache = 0; 241 rdonly = cnp->cn_flags & RDONLY; 242 ndp->ni_dvp = NULL; 243 cnp->cn_flags &= ~ISSYMLINK; 244 dp = ndp->ni_startdir; 245 ndp->ni_startdir = NULLVP; 246 VOP_LOCK(dp); 247 248 dirloop: 249 /* 250 * Search a new directory. 251 * 252 * The cn_hash value is for use by vfs_cache. 253 * The last component of the filename is left accessible via 254 * cnp->cn_nameptr for callers that need the name. Callers needing 255 * the name set the SAVENAME flag. When done, they assume 256 * responsibility for freeing the pathname buffer. 257 */ 258 cnp->cn_consume = 0; 259 cnp->cn_hash = 0; 260 for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 261 cnp->cn_hash += (unsigned char)*cp; 262 cnp->cn_namelen = cp - cnp->cn_nameptr; 263 if (cnp->cn_namelen > NAME_MAX) { 264 error = ENAMETOOLONG; 265 goto bad; 266 } 267 #ifdef NAMEI_DIAGNOSTIC 268 { char c = *cp; 269 *cp = '\0'; 270 printf("{%s}: ", cnp->cn_nameptr); 271 *cp = c; } 272 #endif 273 ndp->ni_pathlen -= cnp->cn_namelen; 274 ndp->ni_next = cp; 275 cnp->cn_flags |= MAKEENTRY; 276 if (*cp == '\0' && docache == 0) 277 cnp->cn_flags &= ~MAKEENTRY; 278 if (cnp->cn_namelen == 2 && 279 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 280 cnp->cn_flags |= ISDOTDOT; 281 else 282 cnp->cn_flags &= ~ISDOTDOT; 283 if (*ndp->ni_next == 0) 284 cnp->cn_flags |= ISLASTCN; 285 else 286 cnp->cn_flags &= ~ISLASTCN; 287 288 289 /* 290 * Check for degenerate name (e.g. / or "") 291 * which is a way of talking about a directory, 292 * e.g. like "/." or ".". 293 */ 294 if (cnp->cn_nameptr[0] == '\0') { 295 if (cnp->cn_nameiop != LOOKUP) { 296 error = EISDIR; 297 goto bad; 298 } 299 if (dp->v_type != VDIR) { 300 error = ENOTDIR; 301 goto bad; 302 } 303 if (wantparent) { 304 ndp->ni_dvp = dp; 305 vref(dp); 306 } 307 ndp->ni_vp = dp; 308 if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) 309 VOP_UNLOCK(dp); 310 if (cnp->cn_flags & SAVESTART) 311 panic("lookup: SAVESTART"); 312 return (0); 313 } 314 315 /* 316 * Handle "..": two special cases. 317 * 1. If at root directory (e.g. after chroot) 318 * or at absolute root directory 319 * then ignore it so can't get out. 320 * 2. If this vnode is the root of a mounted 321 * filesystem, then replace it with the 322 * vnode which was mounted on so we take the 323 * .. in the other file system. 324 */ 325 if (cnp->cn_flags & ISDOTDOT) { 326 for (;;) { 327 if (dp == ndp->ni_rootdir || dp == rootvnode) { 328 ndp->ni_dvp = dp; 329 ndp->ni_vp = dp; 330 VREF(dp); 331 goto nextname; 332 } 333 if ((dp->v_flag & VROOT) == 0 || 334 (cnp->cn_flags & NOCROSSMOUNT)) 335 break; 336 tdp = dp; 337 dp = dp->v_mount->mnt_vnodecovered; 338 vput(tdp); 339 VREF(dp); 340 VOP_LOCK(dp); 341 } 342 } 343 344 /* 345 * We now have a segment name to search for, and a directory to search. 346 */ 347 unionlookup: 348 ndp->ni_dvp = dp; 349 if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) { 350 #ifdef DIAGNOSTIC 351 if (ndp->ni_vp != NULL) 352 panic("leaf should be empty"); 353 #endif 354 #ifdef NAMEI_DIAGNOSTIC 355 printf("not found\n"); 356 #endif 357 if ((error == ENOENT) && 358 (dp->v_flag & VROOT) && 359 (dp->v_mount->mnt_flag & MNT_UNION)) { 360 tdp = dp; 361 dp = dp->v_mount->mnt_vnodecovered; 362 vput(tdp); 363 VREF(dp); 364 VOP_LOCK(dp); 365 goto unionlookup; 366 } 367 368 if (error != EJUSTRETURN) 369 goto bad; 370 /* 371 * If creating and at end of pathname, then can consider 372 * allowing file to be created. 373 */ 374 if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { 375 error = EROFS; 376 goto bad; 377 } 378 /* 379 * We return with ni_vp NULL to indicate that the entry 380 * doesn't currently exist, leaving a pointer to the 381 * (possibly locked) directory inode in ndp->ni_dvp. 382 */ 383 if (cnp->cn_flags & SAVESTART) { 384 ndp->ni_startdir = ndp->ni_dvp; 385 VREF(ndp->ni_startdir); 386 } 387 return (0); 388 } 389 #ifdef NAMEI_DIAGNOSTIC 390 printf("found\n"); 391 #endif 392 393 /* 394 * Take into account any additional components consumed by 395 * the underlying filesystem. 396 */ 397 if (cnp->cn_consume > 0) { 398 cnp->cn_nameptr += cnp->cn_consume; 399 ndp->ni_next += cnp->cn_consume; 400 ndp->ni_pathlen -= cnp->cn_consume; 401 cnp->cn_consume = 0; 402 } 403 404 dp = ndp->ni_vp; 405 /* 406 * Check for symbolic link 407 */ 408 if ((dp->v_type == VLNK) && 409 ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { 410 cnp->cn_flags |= ISSYMLINK; 411 return (0); 412 } 413 414 /* 415 * Check to see if the vnode has been mounted on; 416 * if so find the root of the mounted file system. 417 */ 418 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 419 (cnp->cn_flags & NOCROSSMOUNT) == 0) { 420 if (mp->mnt_flag & MNT_MLOCK) { 421 mp->mnt_flag |= MNT_MWAIT; 422 sleep((caddr_t)mp, PVFS); 423 continue; 424 } 425 if (error = VFS_ROOT(dp->v_mountedhere, &tdp)) 426 goto bad2; 427 vput(dp); 428 ndp->ni_vp = dp = tdp; 429 } 430 431 nextname: 432 /* 433 * Not a symbolic link. If more pathname, 434 * continue at next component, else return. 435 */ 436 if (*ndp->ni_next == '/') { 437 cnp->cn_nameptr = ndp->ni_next; 438 while (*cnp->cn_nameptr == '/') { 439 cnp->cn_nameptr++; 440 ndp->ni_pathlen--; 441 } 442 vrele(ndp->ni_dvp); 443 goto dirloop; 444 } 445 /* 446 * Check for read-only file systems. 447 */ 448 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 449 /* 450 * Disallow directory write attempts on read-only 451 * file systems. 452 */ 453 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 454 (wantparent && 455 (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { 456 error = EROFS; 457 goto bad2; 458 } 459 } 460 if (cnp->cn_flags & SAVESTART) { 461 ndp->ni_startdir = ndp->ni_dvp; 462 VREF(ndp->ni_startdir); 463 } 464 if (!wantparent) 465 vrele(ndp->ni_dvp); 466 if ((cnp->cn_flags & LOCKLEAF) == 0) 467 VOP_UNLOCK(dp); 468 return (0); 469 470 bad2: 471 if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') 472 VOP_UNLOCK(ndp->ni_dvp); 473 vrele(ndp->ni_dvp); 474 bad: 475 vput(dp); 476 ndp->ni_vp = NULL; 477 return (error); 478 } 479 480 481