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