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