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