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