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