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