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 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)vfs_lookup.c 8.4 (Berkeley) 2/16/94 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_ktrace.h" 41 #include "opt_mac.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/lock.h> 47 #include <sys/mac.h> 48 #include <sys/mutex.h> 49 #include <sys/namei.h> 50 #include <sys/vnode.h> 51 #include <sys/mount.h> 52 #include <sys/filedesc.h> 53 #include <sys/proc.h> 54 #ifdef KTRACE 55 #include <sys/ktrace.h> 56 #endif 57 58 #include <vm/uma.h> 59 60 /* 61 * Allocation zone for namei 62 */ 63 uma_zone_t namei_zone; 64 65 static void 66 nameiinit(void *dummy __unused) 67 { 68 namei_zone = uma_zcreate("NAMEI", MAXPATHLEN, NULL, NULL, NULL, NULL, 69 UMA_ALIGN_PTR, 0); 70 71 } 72 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_SECOND, nameiinit, NULL) 73 74 /* 75 * Convert a pathname into a pointer to a locked inode. 76 * 77 * The FOLLOW flag is set when symbolic links are to be followed 78 * when they occur at the end of the name translation process. 79 * Symbolic links are always followed for all other pathname 80 * components other than the last. 81 * 82 * The segflg defines whether the name is to be copied from user 83 * space or kernel space. 84 * 85 * Overall outline of namei: 86 * 87 * copy in name 88 * get starting directory 89 * while (!done && !error) { 90 * call lookup to search path. 91 * if symbolic link, massage name in buffer and continue 92 * } 93 */ 94 int 95 namei(ndp) 96 register struct nameidata *ndp; 97 { 98 register struct filedesc *fdp; /* pointer to file descriptor state */ 99 register char *cp; /* pointer into pathname argument */ 100 register struct vnode *dp; /* the directory we are searching */ 101 struct iovec aiov; /* uio for reading symbolic links */ 102 struct uio auio; 103 int error, linklen; 104 struct componentname *cnp = &ndp->ni_cnd; 105 struct thread *td = cnp->cn_thread; 106 struct proc *p = td->td_proc; 107 108 GIANT_REQUIRED; 109 110 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; 111 KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc")); 112 KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0, 113 ("namei: nameiop contaminated with flags")); 114 KASSERT((cnp->cn_flags & OPMASK) == 0, 115 ("namei: flags contaminated with nameiops")); 116 fdp = p->p_fd; 117 118 /* 119 * Get a buffer for the name to be translated, and copy the 120 * name into the buffer. 121 */ 122 if ((cnp->cn_flags & HASBUF) == 0) 123 cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); 124 if (ndp->ni_segflg == UIO_SYSSPACE) 125 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 126 MAXPATHLEN, (size_t *)&ndp->ni_pathlen); 127 else 128 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 129 MAXPATHLEN, (size_t *)&ndp->ni_pathlen); 130 131 /* 132 * Don't allow empty pathnames. 133 */ 134 if (!error && *cnp->cn_pnbuf == '\0') 135 error = ENOENT; 136 137 if (error) { 138 uma_zfree(namei_zone, cnp->cn_pnbuf); 139 #ifdef DIAGNOSTIC 140 cnp->cn_pnbuf = NULL; 141 cnp->cn_nameptr = NULL; 142 #endif 143 ndp->ni_vp = NULL; 144 return (error); 145 } 146 ndp->ni_loopcnt = 0; 147 #ifdef KTRACE 148 if (KTRPOINT(td, KTR_NAMEI)) { 149 KASSERT(cnp->cn_thread == curthread, 150 ("namei not using curthread")); 151 ktrnamei(cnp->cn_pnbuf); 152 } 153 #endif 154 155 /* 156 * Get starting point for the translation. 157 */ 158 FILEDESC_LOCK(fdp); 159 ndp->ni_rootdir = fdp->fd_rdir; 160 ndp->ni_topdir = fdp->fd_jdir; 161 162 dp = fdp->fd_cdir; 163 VREF(dp); 164 FILEDESC_UNLOCK(fdp); 165 for (;;) { 166 /* 167 * Check if root directory should replace current directory. 168 * Done at start of translation and after symbolic link. 169 */ 170 cnp->cn_nameptr = cnp->cn_pnbuf; 171 if (*(cnp->cn_nameptr) == '/') { 172 vrele(dp); 173 while (*(cnp->cn_nameptr) == '/') { 174 cnp->cn_nameptr++; 175 ndp->ni_pathlen--; 176 } 177 dp = ndp->ni_rootdir; 178 VREF(dp); 179 } 180 ndp->ni_startdir = dp; 181 error = lookup(ndp); 182 if (error) { 183 uma_zfree(namei_zone, cnp->cn_pnbuf); 184 #ifdef DIAGNOSTIC 185 cnp->cn_pnbuf = NULL; 186 cnp->cn_nameptr = NULL; 187 #endif 188 return (error); 189 } 190 /* 191 * Check for symbolic link 192 */ 193 if ((cnp->cn_flags & ISSYMLINK) == 0) { 194 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) { 195 uma_zfree(namei_zone, cnp->cn_pnbuf); 196 #ifdef DIAGNOSTIC 197 cnp->cn_pnbuf = NULL; 198 cnp->cn_nameptr = NULL; 199 #endif 200 } else 201 cnp->cn_flags |= HASBUF; 202 203 if (vn_canvmio(ndp->ni_vp) == TRUE && 204 (cnp->cn_nameiop != DELETE) && 205 ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == 206 LOCKLEAF)) 207 vfs_object_create(ndp->ni_vp, td, 208 ndp->ni_cnd.cn_cred); 209 210 return (0); 211 } 212 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 213 VOP_UNLOCK(ndp->ni_dvp, 0, td); 214 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 215 error = ELOOP; 216 break; 217 } 218 #ifdef MAC 219 if ((cnp->cn_flags & NOMACCHECK) == 0) { 220 error = mac_check_vnode_readlink(td->td_ucred, 221 ndp->ni_vp); 222 if (error) 223 break; 224 } 225 #endif 226 if (ndp->ni_pathlen > 1) 227 cp = uma_zalloc(namei_zone, M_WAITOK); 228 else 229 cp = cnp->cn_pnbuf; 230 aiov.iov_base = cp; 231 aiov.iov_len = MAXPATHLEN; 232 auio.uio_iov = &aiov; 233 auio.uio_iovcnt = 1; 234 auio.uio_offset = 0; 235 auio.uio_rw = UIO_READ; 236 auio.uio_segflg = UIO_SYSSPACE; 237 auio.uio_td = (struct thread *)0; 238 auio.uio_resid = MAXPATHLEN; 239 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 240 if (error) { 241 if (ndp->ni_pathlen > 1) 242 uma_zfree(namei_zone, cp); 243 break; 244 } 245 linklen = MAXPATHLEN - auio.uio_resid; 246 if (linklen == 0) { 247 if (ndp->ni_pathlen > 1) 248 uma_zfree(namei_zone, cp); 249 error = ENOENT; 250 break; 251 } 252 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 253 if (ndp->ni_pathlen > 1) 254 uma_zfree(namei_zone, cp); 255 error = ENAMETOOLONG; 256 break; 257 } 258 if (ndp->ni_pathlen > 1) { 259 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 260 uma_zfree(namei_zone, cnp->cn_pnbuf); 261 cnp->cn_pnbuf = cp; 262 } else 263 cnp->cn_pnbuf[linklen] = '\0'; 264 ndp->ni_pathlen += linklen; 265 vput(ndp->ni_vp); 266 dp = ndp->ni_dvp; 267 } 268 uma_zfree(namei_zone, cnp->cn_pnbuf); 269 #ifdef DIAGNOSTIC 270 cnp->cn_pnbuf = NULL; 271 cnp->cn_nameptr = NULL; 272 #endif 273 vrele(ndp->ni_dvp); 274 vput(ndp->ni_vp); 275 ndp->ni_vp = NULL; 276 return (error); 277 } 278 279 /* 280 * Search a pathname. 281 * This is a very central and rather complicated routine. 282 * 283 * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 284 * The starting directory is taken from ni_startdir. The pathname is 285 * descended until done, or a symbolic link is encountered. The variable 286 * ni_more is clear if the path is completed; it is set to one if a 287 * symbolic link needing interpretation is encountered. 288 * 289 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 290 * whether the name is to be looked up, created, renamed, or deleted. 291 * When CREATE, RENAME, or DELETE is specified, information usable in 292 * creating, renaming, or deleting a directory entry may be calculated. 293 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 294 * locked. If flag has WANTPARENT or'ed into it, the parent directory is 295 * returned unlocked. Otherwise the parent directory is not returned. If 296 * the target of the pathname exists and LOCKLEAF is or'ed into the flag 297 * the target is returned locked, otherwise it is returned unlocked. 298 * When creating or renaming and LOCKPARENT is specified, the target may not 299 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 300 * 301 * Overall outline of lookup: 302 * 303 * dirloop: 304 * identify next component of name at ndp->ni_ptr 305 * handle degenerate case where name is null string 306 * if .. and crossing mount points and on mounted filesys, find parent 307 * call VOP_LOOKUP routine for next component name 308 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 309 * component vnode returned in ni_vp (if it exists), locked. 310 * if result vnode is mounted on and crossing mount points, 311 * find mounted on vnode 312 * if more components of name, do next level at dirloop 313 * return the answer in ni_vp, locked if LOCKLEAF set 314 * if LOCKPARENT set, return locked parent in ni_dvp 315 * if WANTPARENT set, return unlocked parent in ni_dvp 316 */ 317 int 318 lookup(ndp) 319 register struct nameidata *ndp; 320 { 321 register char *cp; /* pointer into pathname argument */ 322 register struct vnode *dp = 0; /* the directory we are searching */ 323 struct vnode *tdp; /* saved dp */ 324 struct mount *mp; /* mount table entry */ 325 int docache; /* == 0 do not cache last component */ 326 int wantparent; /* 1 => wantparent or lockparent flag */ 327 int rdonly; /* lookup read-only flag bit */ 328 int trailing_slash; 329 int error = 0; 330 int dpunlocked = 0; /* dp has already been unlocked */ 331 struct componentname *cnp = &ndp->ni_cnd; 332 struct thread *td = cnp->cn_thread; 333 334 /* 335 * Setup: break out flag bits into variables. 336 */ 337 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 338 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 339 if (cnp->cn_nameiop == DELETE || 340 (wantparent && cnp->cn_nameiop != CREATE && 341 cnp->cn_nameiop != LOOKUP)) 342 docache = 0; 343 rdonly = cnp->cn_flags & RDONLY; 344 ndp->ni_dvp = NULL; 345 cnp->cn_flags &= ~ISSYMLINK; 346 dp = ndp->ni_startdir; 347 ndp->ni_startdir = NULLVP; 348 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); 349 350 dirloop: 351 /* 352 * Search a new directory. 353 * 354 * The last component of the filename is left accessible via 355 * cnp->cn_nameptr for callers that need the name. Callers needing 356 * the name set the SAVENAME flag. When done, they assume 357 * responsibility for freeing the pathname buffer. 358 */ 359 cnp->cn_consume = 0; 360 for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 361 continue; 362 cnp->cn_namelen = cp - cnp->cn_nameptr; 363 if (cnp->cn_namelen > NAME_MAX) { 364 error = ENAMETOOLONG; 365 goto bad; 366 } 367 #ifdef NAMEI_DIAGNOSTIC 368 { char c = *cp; 369 *cp = '\0'; 370 printf("{%s}: ", cnp->cn_nameptr); 371 *cp = c; } 372 #endif 373 ndp->ni_pathlen -= cnp->cn_namelen; 374 ndp->ni_next = cp; 375 376 /* 377 * Replace multiple slashes by a single slash and trailing slashes 378 * by a null. This must be done before VOP_LOOKUP() because some 379 * fs's don't know about trailing slashes. Remember if there were 380 * trailing slashes to handle symlinks, existing non-directories 381 * and non-existing files that won't be directories specially later. 382 */ 383 trailing_slash = 0; 384 while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) { 385 cp++; 386 ndp->ni_pathlen--; 387 if (*cp == '\0') { 388 trailing_slash = 1; 389 *ndp->ni_next = '\0'; /* XXX for direnter() ... */ 390 } 391 } 392 ndp->ni_next = cp; 393 394 cnp->cn_flags |= MAKEENTRY; 395 if (*cp == '\0' && docache == 0) 396 cnp->cn_flags &= ~MAKEENTRY; 397 if (cnp->cn_namelen == 2 && 398 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 399 cnp->cn_flags |= ISDOTDOT; 400 else 401 cnp->cn_flags &= ~ISDOTDOT; 402 if (*ndp->ni_next == 0) 403 cnp->cn_flags |= ISLASTCN; 404 else 405 cnp->cn_flags &= ~ISLASTCN; 406 407 408 /* 409 * Check for degenerate name (e.g. / or "") 410 * which is a way of talking about a directory, 411 * e.g. like "/." or ".". 412 */ 413 if (cnp->cn_nameptr[0] == '\0') { 414 if (dp->v_type != VDIR) { 415 error = ENOTDIR; 416 goto bad; 417 } 418 if (cnp->cn_nameiop != LOOKUP) { 419 error = EISDIR; 420 goto bad; 421 } 422 if (wantparent) { 423 ndp->ni_dvp = dp; 424 VREF(dp); 425 } 426 ndp->ni_vp = dp; 427 if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) 428 VOP_UNLOCK(dp, 0, td); 429 /* XXX This should probably move to the top of function. */ 430 if (cnp->cn_flags & SAVESTART) 431 panic("lookup: SAVESTART"); 432 return (0); 433 } 434 435 /* 436 * Handle "..": two special cases. 437 * 1. If at root directory (e.g. after chroot) 438 * or at absolute root directory 439 * then ignore it so can't get out. 440 * 2. If this vnode is the root of a mounted 441 * filesystem, then replace it with the 442 * vnode which was mounted on so we take the 443 * .. in the other filesystem. 444 * 3. If the vnode is the top directory of 445 * the jail or chroot, don't let them out. 446 */ 447 if (cnp->cn_flags & ISDOTDOT) { 448 for (;;) { 449 if (dp == ndp->ni_rootdir || 450 dp == ndp->ni_topdir || 451 dp == rootvnode) { 452 ndp->ni_dvp = dp; 453 ndp->ni_vp = dp; 454 VREF(dp); 455 goto nextname; 456 } 457 if ((dp->v_vflag & VV_ROOT) == 0 || 458 (cnp->cn_flags & NOCROSSMOUNT)) 459 break; 460 if (dp->v_mount == NULL) { /* forced unmount */ 461 error = EBADF; 462 goto bad; 463 } 464 tdp = dp; 465 dp = dp->v_mount->mnt_vnodecovered; 466 vput(tdp); 467 VREF(dp); 468 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); 469 } 470 } 471 472 /* 473 * We now have a segment name to search for, and a directory to search. 474 */ 475 unionlookup: 476 #ifdef MAC 477 if ((cnp->cn_flags & NOMACCHECK) == 0) { 478 error = mac_check_vnode_lookup(td->td_ucred, dp, cnp); 479 if (error) 480 goto bad; 481 } 482 #endif 483 ndp->ni_dvp = dp; 484 ndp->ni_vp = NULL; 485 cnp->cn_flags &= ~PDIRUNLOCK; 486 ASSERT_VOP_LOCKED(dp, "lookup"); 487 if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) { 488 KASSERT(ndp->ni_vp == NULL, ("leaf should be empty")); 489 #ifdef NAMEI_DIAGNOSTIC 490 printf("not found\n"); 491 #endif 492 if ((error == ENOENT) && 493 (dp->v_vflag & VV_ROOT) && (dp->v_mount != NULL) && 494 (dp->v_mount->mnt_flag & MNT_UNION)) { 495 tdp = dp; 496 dp = dp->v_mount->mnt_vnodecovered; 497 if (cnp->cn_flags & PDIRUNLOCK) 498 vrele(tdp); 499 else 500 vput(tdp); 501 VREF(dp); 502 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); 503 goto unionlookup; 504 } 505 506 if (error != EJUSTRETURN) 507 goto bad; 508 /* 509 * If creating and at end of pathname, then can consider 510 * allowing file to be created. 511 */ 512 if (rdonly) { 513 error = EROFS; 514 goto bad; 515 } 516 if (*cp == '\0' && trailing_slash && 517 !(cnp->cn_flags & WILLBEDIR)) { 518 error = ENOENT; 519 goto bad; 520 } 521 /* 522 * We return with ni_vp NULL to indicate that the entry 523 * doesn't currently exist, leaving a pointer to the 524 * (possibly locked) directory inode in ndp->ni_dvp. 525 */ 526 if (cnp->cn_flags & SAVESTART) { 527 ndp->ni_startdir = ndp->ni_dvp; 528 VREF(ndp->ni_startdir); 529 } 530 return (0); 531 } 532 #ifdef NAMEI_DIAGNOSTIC 533 printf("found\n"); 534 #endif 535 536 ASSERT_VOP_LOCKED(ndp->ni_vp, "lookup"); 537 538 /* 539 * Take into account any additional components consumed by 540 * the underlying filesystem. 541 */ 542 if (cnp->cn_consume > 0) { 543 cnp->cn_nameptr += cnp->cn_consume; 544 ndp->ni_next += cnp->cn_consume; 545 ndp->ni_pathlen -= cnp->cn_consume; 546 cnp->cn_consume = 0; 547 } 548 549 dp = ndp->ni_vp; 550 551 /* 552 * Check to see if the vnode has been mounted on; 553 * if so find the root of the mounted filesystem. 554 */ 555 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 556 (cnp->cn_flags & NOCROSSMOUNT) == 0) { 557 if (vfs_busy(mp, 0, 0, td)) 558 continue; 559 VOP_UNLOCK(dp, 0, td); 560 error = VFS_ROOT(mp, &tdp, td); 561 vfs_unbusy(mp, td); 562 if (error) { 563 dpunlocked = 1; 564 goto bad2; 565 } 566 vrele(dp); 567 ndp->ni_vp = dp = tdp; 568 } 569 570 /* 571 * Check for symbolic link 572 */ 573 if ((dp->v_type == VLNK) && 574 ((cnp->cn_flags & FOLLOW) || trailing_slash || 575 *ndp->ni_next == '/')) { 576 cnp->cn_flags |= ISSYMLINK; 577 if (dp->v_mount == NULL) { 578 /* We can't know whether the directory was mounted with 579 * NOSYMFOLLOW, so we can't follow safely. */ 580 error = EBADF; 581 goto bad2; 582 } 583 if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) { 584 error = EACCES; 585 goto bad2; 586 } 587 return (0); 588 } 589 590 /* 591 * Check for bogus trailing slashes. 592 */ 593 if (trailing_slash && dp->v_type != VDIR) { 594 error = ENOTDIR; 595 goto bad2; 596 } 597 598 nextname: 599 /* 600 * Not a symbolic link. If more pathname, 601 * continue at next component, else return. 602 */ 603 if (*ndp->ni_next == '/') { 604 cnp->cn_nameptr = ndp->ni_next; 605 while (*cnp->cn_nameptr == '/') { 606 cnp->cn_nameptr++; 607 ndp->ni_pathlen--; 608 } 609 if (ndp->ni_dvp != ndp->ni_vp) 610 ASSERT_VOP_UNLOCKED(ndp->ni_dvp, "lookup"); 611 vrele(ndp->ni_dvp); 612 goto dirloop; 613 } 614 /* 615 * Disallow directory write attempts on read-only filesystems. 616 */ 617 if (rdonly && 618 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 619 error = EROFS; 620 goto bad2; 621 } 622 if (cnp->cn_flags & SAVESTART) { 623 ndp->ni_startdir = ndp->ni_dvp; 624 VREF(ndp->ni_startdir); 625 } 626 if (!wantparent) 627 vrele(ndp->ni_dvp); 628 629 if ((cnp->cn_flags & LOCKLEAF) == 0) 630 VOP_UNLOCK(dp, 0, td); 631 return (0); 632 633 bad2: 634 if ((cnp->cn_flags & (LOCKPARENT | PDIRUNLOCK)) == LOCKPARENT && 635 *ndp->ni_next == '\0') 636 VOP_UNLOCK(ndp->ni_dvp, 0, td); 637 vrele(ndp->ni_dvp); 638 bad: 639 if (dpunlocked) 640 vrele(dp); 641 else 642 vput(dp); 643 ndp->ni_vp = NULL; 644 return (error); 645 } 646 647 /* 648 * relookup - lookup a path name component 649 * Used by lookup to re-aquire things. 650 */ 651 int 652 relookup(dvp, vpp, cnp) 653 struct vnode *dvp, **vpp; 654 struct componentname *cnp; 655 { 656 struct thread *td = cnp->cn_thread; 657 struct vnode *dp = 0; /* the directory we are searching */ 658 int docache; /* == 0 do not cache last component */ 659 int wantparent; /* 1 => wantparent or lockparent flag */ 660 int rdonly; /* lookup read-only flag bit */ 661 int error = 0; 662 #ifdef NAMEI_DIAGNOSTIC 663 int newhash; /* DEBUG: check name hash */ 664 char *cp; /* DEBUG: check name ptr/len */ 665 #endif 666 667 /* 668 * Setup: break out flag bits into variables. 669 */ 670 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); 671 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 672 if (cnp->cn_nameiop == DELETE || 673 (wantparent && cnp->cn_nameiop != CREATE)) 674 docache = 0; 675 rdonly = cnp->cn_flags & RDONLY; 676 cnp->cn_flags &= ~ISSYMLINK; 677 dp = dvp; 678 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td); 679 680 /* dirloop: */ 681 /* 682 * Search a new directory. 683 * 684 * The last component of the filename is left accessible via 685 * cnp->cn_nameptr for callers that need the name. Callers needing 686 * the name set the SAVENAME flag. When done, they assume 687 * responsibility for freeing the pathname buffer. 688 */ 689 #ifdef NAMEI_DIAGNOSTIC 690 if (cnp->cn_namelen != cp - cnp->cn_nameptr) 691 panic ("relookup: bad len"); 692 if (*cp != 0) 693 panic("relookup: not last component"); 694 printf("{%s}: ", cnp->cn_nameptr); 695 #endif 696 697 /* 698 * Check for degenerate name (e.g. / or "") 699 * which is a way of talking about a directory, 700 * e.g. like "/." or ".". 701 */ 702 if (cnp->cn_nameptr[0] == '\0') { 703 if (cnp->cn_nameiop != LOOKUP || wantparent) { 704 error = EISDIR; 705 goto bad; 706 } 707 if (dp->v_type != VDIR) { 708 error = ENOTDIR; 709 goto bad; 710 } 711 if (!(cnp->cn_flags & LOCKLEAF)) 712 VOP_UNLOCK(dp, 0, td); 713 *vpp = dp; 714 /* XXX This should probably move to the top of function. */ 715 if (cnp->cn_flags & SAVESTART) 716 panic("lookup: SAVESTART"); 717 return (0); 718 } 719 720 if (cnp->cn_flags & ISDOTDOT) 721 panic ("relookup: lookup on dot-dot"); 722 723 /* 724 * We now have a segment name to search for, and a directory to search. 725 */ 726 if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) { 727 KASSERT(*vpp == NULL, ("leaf should be empty")); 728 if (error != EJUSTRETURN) 729 goto bad; 730 /* 731 * If creating and at end of pathname, then can consider 732 * allowing file to be created. 733 */ 734 if (rdonly) { 735 error = EROFS; 736 goto bad; 737 } 738 /* ASSERT(dvp == ndp->ni_startdir) */ 739 if (cnp->cn_flags & SAVESTART) 740 VREF(dvp); 741 /* 742 * We return with ni_vp NULL to indicate that the entry 743 * doesn't currently exist, leaving a pointer to the 744 * (possibly locked) directory inode in ndp->ni_dvp. 745 */ 746 return (0); 747 } 748 dp = *vpp; 749 750 /* 751 * Check for symbolic link 752 */ 753 KASSERT(dp->v_type != VLNK || !(cnp->cn_flags & FOLLOW), 754 ("relookup: symlink found.\n")); 755 756 /* 757 * Disallow directory write attempts on read-only filesystems. 758 */ 759 if (rdonly && 760 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) { 761 error = EROFS; 762 goto bad2; 763 } 764 /* ASSERT(dvp == ndp->ni_startdir) */ 765 if (cnp->cn_flags & SAVESTART) 766 VREF(dvp); 767 768 if (!wantparent) 769 vrele(dvp); 770 771 if (vn_canvmio(dp) == TRUE && 772 ((cnp->cn_flags & (NOOBJ|LOCKLEAF)) == LOCKLEAF)) 773 vfs_object_create(dp, td, cnp->cn_cred); 774 775 if ((cnp->cn_flags & LOCKLEAF) == 0) 776 VOP_UNLOCK(dp, 0, td); 777 return (0); 778 779 bad2: 780 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) 781 VOP_UNLOCK(dvp, 0, td); 782 vrele(dvp); 783 bad: 784 vput(dp); 785 *vpp = NULL; 786 return (error); 787 } 788