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