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