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