1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 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 * @(#)ufs_lookup.c 8.15 (Berkeley) 6/16/95 37 */ 38 39 #include <sys/cdefs.h> 40 __FBSDID("$FreeBSD$"); 41 42 #include "opt_ufs.h" 43 #include "opt_quota.h" 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/namei.h> 49 #include <sys/bio.h> 50 #include <sys/buf.h> 51 #include <sys/proc.h> 52 #include <sys/stat.h> 53 #include <sys/mount.h> 54 #include <sys/vnode.h> 55 #include <sys/sysctl.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_extern.h> 59 60 #include <ufs/ufs/extattr.h> 61 #include <ufs/ufs/quota.h> 62 #include <ufs/ufs/inode.h> 63 #include <ufs/ufs/dir.h> 64 #ifdef UFS_DIRHASH 65 #include <ufs/ufs/dirhash.h> 66 #endif 67 #include <ufs/ufs/ufsmount.h> 68 #include <ufs/ufs/ufs_extern.h> 69 70 #ifdef DIAGNOSTIC 71 static int dirchk = 1; 72 #else 73 static int dirchk = 0; 74 #endif 75 76 SYSCTL_INT(_debug, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, ""); 77 78 /* true if old FS format...*/ 79 #define OFSFMT(vp) ((vp)->v_mount->mnt_maxsymlinklen <= 0) 80 81 static int 82 ufs_delete_denied(struct vnode *vdp, struct vnode *tdp, struct ucred *cred, 83 struct thread *td) 84 { 85 int error; 86 87 #ifdef UFS_ACL 88 /* 89 * NFSv4 Minor Version 1, draft-ietf-nfsv4-minorversion1-03.txt 90 * 91 * 3.16.2.1. ACE4_DELETE vs. ACE4_DELETE_CHILD 92 */ 93 94 /* 95 * XXX: Is this check required? 96 */ 97 error = VOP_ACCESS(vdp, VEXEC, cred, td); 98 if (error) 99 return (error); 100 101 error = VOP_ACCESSX(tdp, VDELETE, cred, td); 102 if (error == 0) 103 return (0); 104 105 error = VOP_ACCESSX(vdp, VDELETE_CHILD, cred, td); 106 if (error == 0) 107 return (0); 108 109 error = VOP_ACCESSX(vdp, VEXPLICIT_DENY | VDELETE_CHILD, cred, td); 110 if (error) 111 return (error); 112 113 #endif /* !UFS_ACL */ 114 115 /* 116 * Standard Unix access control - delete access requires VWRITE. 117 */ 118 error = VOP_ACCESS(vdp, VWRITE, cred, td); 119 if (error) 120 return (error); 121 122 /* 123 * If directory is "sticky", then user must own 124 * the directory, or the file in it, else she 125 * may not delete it (unless she's root). This 126 * implements append-only directories. 127 */ 128 if ((VTOI(vdp)->i_mode & ISVTX) && 129 VOP_ACCESS(vdp, VADMIN, cred, td) && 130 VOP_ACCESS(tdp, VADMIN, cred, td)) 131 return (EPERM); 132 133 return (0); 134 } 135 136 /* 137 * Convert a component of a pathname into a pointer to a locked inode. 138 * This is a very central and rather complicated routine. 139 * If the filesystem is not maintained in a strict tree hierarchy, 140 * this can result in a deadlock situation (see comments in code below). 141 * 142 * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending 143 * on whether the name is to be looked up, created, renamed, or deleted. 144 * When CREATE, RENAME, or DELETE is specified, information usable in 145 * creating, renaming, or deleting a directory entry may be calculated. 146 * If flag has LOCKPARENT or'ed into it and the target of the pathname 147 * exists, lookup returns both the target and its parent directory locked. 148 * When creating or renaming and LOCKPARENT is specified, the target may 149 * not be ".". When deleting and LOCKPARENT is specified, the target may 150 * be "."., but the caller must check to ensure it does an vrele and vput 151 * instead of two vputs. 152 * 153 * This routine is actually used as VOP_CACHEDLOOKUP method, and the 154 * filesystem employs the generic vfs_cache_lookup() as VOP_LOOKUP 155 * method. 156 * 157 * vfs_cache_lookup() performs the following for us: 158 * check that it is a directory 159 * check accessibility of directory 160 * check for modification attempts on read-only mounts 161 * if name found in cache 162 * if at end of path and deleting or creating 163 * drop it 164 * else 165 * return name. 166 * return VOP_CACHEDLOOKUP() 167 * 168 * Overall outline of ufs_lookup: 169 * 170 * search for name in directory, to found or notfound 171 * notfound: 172 * if creating, return locked directory, leaving info on available slots 173 * else return error 174 * found: 175 * if at end of path and deleting, return information to allow delete 176 * if at end of path and rewriting (RENAME and LOCKPARENT), lock target 177 * inode and return info to allow rewrite 178 * if not at end, add name to cache; if at end and neither creating 179 * nor deleting, add name to cache 180 */ 181 int 182 ufs_lookup(ap) 183 struct vop_cachedlookup_args /* { 184 struct vnode *a_dvp; 185 struct vnode **a_vpp; 186 struct componentname *a_cnp; 187 } */ *ap; 188 { 189 190 return (ufs_lookup_ino(ap->a_dvp, ap->a_vpp, ap->a_cnp, NULL)); 191 } 192 193 int 194 ufs_lookup_ino(struct vnode *vdp, struct vnode **vpp, struct componentname *cnp, 195 ino_t *dd_ino) 196 { 197 struct inode *dp; /* inode for directory being searched */ 198 struct buf *bp; /* a buffer of directory entries */ 199 struct direct *ep; /* the current directory entry */ 200 int entryoffsetinblock; /* offset of ep in bp's buffer */ 201 enum {NONE, COMPACT, FOUND} slotstatus; 202 doff_t slotoffset; /* offset of area with free space */ 203 doff_t i_diroff; /* cached i_diroff value. */ 204 doff_t i_offset; /* cached i_offset value. */ 205 int slotsize; /* size of area at slotoffset */ 206 int slotfreespace; /* amount of space free in slot */ 207 int slotneeded; /* size of the entry we're seeking */ 208 int numdirpasses; /* strategy for directory search */ 209 doff_t endsearch; /* offset to end directory search */ 210 doff_t prevoff; /* prev entry dp->i_offset */ 211 struct vnode *pdp; /* saved dp during symlink work */ 212 struct vnode *tdp; /* returned by VFS_VGET */ 213 doff_t enduseful; /* pointer past last used dir slot */ 214 u_long bmask; /* block offset mask */ 215 int namlen, error; 216 struct ucred *cred = cnp->cn_cred; 217 int flags = cnp->cn_flags; 218 int nameiop = cnp->cn_nameiop; 219 ino_t ino, ino1; 220 int ltype; 221 222 if (vpp != NULL) 223 *vpp = NULL; 224 225 dp = VTOI(vdp); 226 if (dp->i_effnlink == 0) 227 return (ENOENT); 228 229 /* 230 * Create a vm object if vmiodirenable is enabled. 231 * Alternatively we could call vnode_create_vobject 232 * in VFS_VGET but we could end up creating objects 233 * that are never used. 234 */ 235 vnode_create_vobject(vdp, DIP(dp, i_size), cnp->cn_thread); 236 237 bmask = VFSTOUFS(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; 238 239 #ifdef DEBUG_VFS_LOCKS 240 /* 241 * Assert that the directory vnode is locked, and locked 242 * exclusively for the last component lookup for modifying 243 * operations. 244 * 245 * The directory-modifying operations need to save 246 * intermediate state in the inode between namei() call and 247 * actual directory manipulations. See fields in the struct 248 * inode marked as 'used during directory lookup'. We must 249 * ensure that upgrade in namei() does not happen, since 250 * upgrade might need to unlock vdp. If quotas are enabled, 251 * getinoquota() also requires exclusive lock to modify inode. 252 */ 253 ASSERT_VOP_LOCKED(vdp, "ufs_lookup1"); 254 if ((nameiop == CREATE || nameiop == DELETE || nameiop == RENAME) && 255 (flags & (LOCKPARENT | ISLASTCN)) == (LOCKPARENT | ISLASTCN)) 256 ASSERT_VOP_ELOCKED(vdp, "ufs_lookup2"); 257 #endif 258 259 restart: 260 bp = NULL; 261 slotoffset = -1; 262 263 /* 264 * We now have a segment name to search for, and a directory to search. 265 * 266 * Suppress search for slots unless creating 267 * file and at end of pathname, in which case 268 * we watch for a place to put the new file in 269 * case it doesn't already exist. 270 */ 271 ino = 0; 272 i_diroff = dp->i_diroff; 273 slotstatus = FOUND; 274 slotfreespace = slotsize = slotneeded = 0; 275 if ((nameiop == CREATE || nameiop == RENAME) && 276 (flags & ISLASTCN)) { 277 slotstatus = NONE; 278 slotneeded = DIRECTSIZ(cnp->cn_namelen); 279 } 280 281 #ifdef UFS_DIRHASH 282 /* 283 * Use dirhash for fast operations on large directories. The logic 284 * to determine whether to hash the directory is contained within 285 * ufsdirhash_build(); a zero return means that it decided to hash 286 * this directory and it successfully built up the hash table. 287 */ 288 if (ufsdirhash_build(dp) == 0) { 289 /* Look for a free slot if needed. */ 290 enduseful = dp->i_size; 291 if (slotstatus != FOUND) { 292 slotoffset = ufsdirhash_findfree(dp, slotneeded, 293 &slotsize); 294 if (slotoffset >= 0) { 295 slotstatus = COMPACT; 296 enduseful = ufsdirhash_enduseful(dp); 297 if (enduseful < 0) 298 enduseful = dp->i_size; 299 } 300 } 301 /* Look up the component. */ 302 numdirpasses = 1; 303 entryoffsetinblock = 0; /* silence compiler warning */ 304 switch (ufsdirhash_lookup(dp, cnp->cn_nameptr, cnp->cn_namelen, 305 &i_offset, &bp, nameiop == DELETE ? &prevoff : NULL)) { 306 case 0: 307 ep = (struct direct *)((char *)bp->b_data + 308 (i_offset & bmask)); 309 goto foundentry; 310 case ENOENT: 311 i_offset = roundup2(dp->i_size, DIRBLKSIZ); 312 goto notfound; 313 default: 314 /* Something failed; just do a linear search. */ 315 break; 316 } 317 } 318 #endif /* UFS_DIRHASH */ 319 /* 320 * If there is cached information on a previous search of 321 * this directory, pick up where we last left off. 322 * We cache only lookups as these are the most common 323 * and have the greatest payoff. Caching CREATE has little 324 * benefit as it usually must search the entire directory 325 * to determine that the entry does not exist. Caching the 326 * location of the last DELETE or RENAME has not reduced 327 * profiling time and hence has been removed in the interest 328 * of simplicity. 329 */ 330 if (nameiop != LOOKUP || i_diroff == 0 || i_diroff >= dp->i_size) { 331 entryoffsetinblock = 0; 332 i_offset = 0; 333 numdirpasses = 1; 334 } else { 335 i_offset = i_diroff; 336 if ((entryoffsetinblock = i_offset & bmask) && 337 (error = UFS_BLKATOFF(vdp, (off_t)i_offset, NULL, &bp))) 338 return (error); 339 numdirpasses = 2; 340 nchstats.ncs_2passes++; 341 } 342 prevoff = i_offset; 343 endsearch = roundup2(dp->i_size, DIRBLKSIZ); 344 enduseful = 0; 345 346 searchloop: 347 while (i_offset < endsearch) { 348 /* 349 * If necessary, get the next directory block. 350 */ 351 if ((i_offset & bmask) == 0) { 352 if (bp != NULL) 353 brelse(bp); 354 error = 355 UFS_BLKATOFF(vdp, (off_t)i_offset, NULL, &bp); 356 if (error) 357 return (error); 358 entryoffsetinblock = 0; 359 } 360 /* 361 * If still looking for a slot, and at a DIRBLKSIZE 362 * boundary, have to start looking for free space again. 363 */ 364 if (slotstatus == NONE && 365 (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) { 366 slotoffset = -1; 367 slotfreespace = 0; 368 } 369 /* 370 * Get pointer to next entry. 371 * Full validation checks are slow, so we only check 372 * enough to insure forward progress through the 373 * directory. Complete checks can be run by patching 374 * "dirchk" to be true. 375 */ 376 ep = (struct direct *)((char *)bp->b_data + entryoffsetinblock); 377 if (ep->d_reclen == 0 || ep->d_reclen > 378 DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || 379 (dirchk && ufs_dirbadentry(vdp, ep, entryoffsetinblock))) { 380 int i; 381 382 ufs_dirbad(dp, i_offset, "mangled entry"); 383 i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); 384 i_offset += i; 385 entryoffsetinblock += i; 386 continue; 387 } 388 389 /* 390 * If an appropriate sized slot has not yet been found, 391 * check to see if one is available. Also accumulate space 392 * in the current block so that we can determine if 393 * compaction is viable. 394 */ 395 if (slotstatus != FOUND) { 396 int size = ep->d_reclen; 397 398 if (ep->d_ino != 0) 399 size -= DIRSIZ(OFSFMT(vdp), ep); 400 if (size > 0) { 401 if (size >= slotneeded) { 402 slotstatus = FOUND; 403 slotoffset = i_offset; 404 slotsize = ep->d_reclen; 405 } else if (slotstatus == NONE) { 406 slotfreespace += size; 407 if (slotoffset == -1) 408 slotoffset = i_offset; 409 if (slotfreespace >= slotneeded) { 410 slotstatus = COMPACT; 411 slotsize = i_offset + 412 ep->d_reclen - slotoffset; 413 } 414 } 415 } 416 } 417 418 /* 419 * Check for a name match. 420 */ 421 if (ep->d_ino) { 422 # if (BYTE_ORDER == LITTLE_ENDIAN) 423 if (OFSFMT(vdp)) 424 namlen = ep->d_type; 425 else 426 namlen = ep->d_namlen; 427 # else 428 namlen = ep->d_namlen; 429 # endif 430 if (namlen == cnp->cn_namelen && 431 (cnp->cn_nameptr[0] == ep->d_name[0]) && 432 !bcmp(cnp->cn_nameptr, ep->d_name, 433 (unsigned)namlen)) { 434 #ifdef UFS_DIRHASH 435 foundentry: 436 #endif 437 /* 438 * Save directory entry's inode number and 439 * reclen in ndp->ni_ufs area, and release 440 * directory buffer. 441 */ 442 if (vdp->v_mount->mnt_maxsymlinklen > 0 && 443 ep->d_type == DT_WHT) { 444 slotstatus = FOUND; 445 slotoffset = i_offset; 446 slotsize = ep->d_reclen; 447 enduseful = dp->i_size; 448 cnp->cn_flags |= ISWHITEOUT; 449 numdirpasses--; 450 goto notfound; 451 } 452 ino = ep->d_ino; 453 goto found; 454 } 455 } 456 prevoff = i_offset; 457 i_offset += ep->d_reclen; 458 entryoffsetinblock += ep->d_reclen; 459 if (ep->d_ino) 460 enduseful = i_offset; 461 } 462 notfound: 463 /* 464 * If we started in the middle of the directory and failed 465 * to find our target, we must check the beginning as well. 466 */ 467 if (numdirpasses == 2) { 468 numdirpasses--; 469 i_offset = 0; 470 endsearch = i_diroff; 471 goto searchloop; 472 } 473 if (bp != NULL) 474 brelse(bp); 475 /* 476 * If creating, and at end of pathname and current 477 * directory has not been removed, then can consider 478 * allowing file to be created. 479 */ 480 if ((nameiop == CREATE || nameiop == RENAME || 481 (nameiop == DELETE && 482 (cnp->cn_flags & DOWHITEOUT) && 483 (cnp->cn_flags & ISWHITEOUT))) && 484 (flags & ISLASTCN) && dp->i_effnlink != 0) { 485 /* 486 * Access for write is interpreted as allowing 487 * creation of files in the directory. 488 * 489 * XXX: Fix the comment above. 490 */ 491 if (flags & WILLBEDIR) 492 error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); 493 else 494 error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); 495 if (error) 496 return (error); 497 /* 498 * Return an indication of where the new directory 499 * entry should be put. If we didn't find a slot, 500 * then set dp->i_count to 0 indicating 501 * that the new slot belongs at the end of the 502 * directory. If we found a slot, then the new entry 503 * can be put in the range from dp->i_offset to 504 * dp->i_offset + dp->i_count. 505 */ 506 if (slotstatus == NONE) { 507 dp->i_offset = roundup2(dp->i_size, DIRBLKSIZ); 508 dp->i_count = 0; 509 enduseful = dp->i_offset; 510 } else if (nameiop == DELETE) { 511 dp->i_offset = slotoffset; 512 if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) 513 dp->i_count = 0; 514 else 515 dp->i_count = dp->i_offset - prevoff; 516 } else { 517 dp->i_offset = slotoffset; 518 dp->i_count = slotsize; 519 if (enduseful < slotoffset + slotsize) 520 enduseful = slotoffset + slotsize; 521 } 522 dp->i_endoff = roundup2(enduseful, DIRBLKSIZ); 523 /* 524 * We return with the directory locked, so that 525 * the parameters we set up above will still be 526 * valid if we actually decide to do a direnter(). 527 * We return ni_vp == NULL to indicate that the entry 528 * does not currently exist; we leave a pointer to 529 * the (locked) directory inode in ndp->ni_dvp. 530 * The pathname buffer is saved so that the name 531 * can be obtained later. 532 * 533 * NB - if the directory is unlocked, then this 534 * information cannot be used. 535 */ 536 cnp->cn_flags |= SAVENAME; 537 return (EJUSTRETURN); 538 } 539 /* 540 * Insert name into cache (as non-existent) if appropriate. 541 */ 542 if ((cnp->cn_flags & MAKEENTRY) != 0) 543 cache_enter(vdp, NULL, cnp); 544 return (ENOENT); 545 546 found: 547 if (dd_ino != NULL) 548 *dd_ino = ino; 549 if (numdirpasses == 2) 550 nchstats.ncs_pass2++; 551 /* 552 * Check that directory length properly reflects presence 553 * of this entry. 554 */ 555 if (i_offset + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) { 556 ufs_dirbad(dp, i_offset, "i_size too small"); 557 dp->i_size = i_offset + DIRSIZ(OFSFMT(vdp), ep); 558 DIP_SET(dp, i_size, dp->i_size); 559 dp->i_flag |= IN_CHANGE | IN_UPDATE; 560 } 561 brelse(bp); 562 563 /* 564 * Found component in pathname. 565 * If the final component of path name, save information 566 * in the cache as to where the entry was found. 567 */ 568 if ((flags & ISLASTCN) && nameiop == LOOKUP) 569 dp->i_diroff = rounddown2(i_offset, DIRBLKSIZ); 570 571 /* 572 * If deleting, and at end of pathname, return 573 * parameters which can be used to remove file. 574 */ 575 if (nameiop == DELETE && (flags & ISLASTCN)) { 576 if (flags & LOCKPARENT) 577 ASSERT_VOP_ELOCKED(vdp, __FUNCTION__); 578 /* 579 * Return pointer to current entry in dp->i_offset, 580 * and distance past previous entry (if there 581 * is a previous entry in this block) in dp->i_count. 582 * Save directory inode pointer in ndp->ni_dvp for dirremove(). 583 * 584 * Technically we shouldn't be setting these in the 585 * WANTPARENT case (first lookup in rename()), but any 586 * lookups that will result in directory changes will 587 * overwrite these. 588 */ 589 dp->i_offset = i_offset; 590 if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) 591 dp->i_count = 0; 592 else 593 dp->i_count = dp->i_offset - prevoff; 594 if (dd_ino != NULL) 595 return (0); 596 if ((error = VFS_VGET(vdp->v_mount, ino, 597 LK_EXCLUSIVE, &tdp)) != 0) 598 return (error); 599 error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread); 600 if (error) { 601 vput(tdp); 602 return (error); 603 } 604 if (dp->i_number == ino) { 605 VREF(vdp); 606 *vpp = vdp; 607 vput(tdp); 608 return (0); 609 } 610 611 *vpp = tdp; 612 return (0); 613 } 614 615 /* 616 * If rewriting (RENAME), return the inode and the 617 * information required to rewrite the present directory 618 * Must get inode of directory entry to verify it's a 619 * regular file, or empty directory. 620 */ 621 if (nameiop == RENAME && (flags & ISLASTCN)) { 622 if (flags & WILLBEDIR) 623 error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); 624 else 625 error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); 626 if (error) 627 return (error); 628 /* 629 * Careful about locking second inode. 630 * This can only occur if the target is ".". 631 */ 632 dp->i_offset = i_offset; 633 if (dp->i_number == ino) 634 return (EISDIR); 635 if (dd_ino != NULL) 636 return (0); 637 if ((error = VFS_VGET(vdp->v_mount, ino, 638 LK_EXCLUSIVE, &tdp)) != 0) 639 return (error); 640 641 error = ufs_delete_denied(vdp, tdp, cred, cnp->cn_thread); 642 if (error) { 643 vput(tdp); 644 return (error); 645 } 646 647 #ifdef SunOS_doesnt_do_that 648 /* 649 * The only purpose of this check is to return the correct 650 * error. Assume that we want to rename directory "a" 651 * to a file "b", and that we have no ACL_WRITE_DATA on 652 * a containing directory, but we _do_ have ACL_APPEND_DATA. 653 * In that case, the VOP_ACCESS check above will return 0, 654 * and the operation will fail with ENOTDIR instead 655 * of EACCESS. 656 */ 657 if (tdp->v_type == VDIR) 658 error = VOP_ACCESSX(vdp, VWRITE | VAPPEND, cred, cnp->cn_thread); 659 else 660 error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread); 661 if (error) { 662 vput(tdp); 663 return (error); 664 } 665 #endif 666 667 *vpp = tdp; 668 cnp->cn_flags |= SAVENAME; 669 return (0); 670 } 671 if (dd_ino != NULL) 672 return (0); 673 674 /* 675 * Step through the translation in the name. We do not `vput' the 676 * directory because we may need it again if a symbolic link 677 * is relative to the current directory. Instead we save it 678 * unlocked as "pdp". We must get the target inode before unlocking 679 * the directory to insure that the inode will not be removed 680 * before we get it. We prevent deadlock by always fetching 681 * inodes from the root, moving down the directory tree. Thus 682 * when following backward pointers ".." we must unlock the 683 * parent directory before getting the requested directory. 684 * There is a potential race condition here if both the current 685 * and parent directories are removed before the VFS_VGET for the 686 * inode associated with ".." returns. We hope that this occurs 687 * infrequently since we cannot avoid this race condition without 688 * implementing a sophisticated deadlock detection algorithm. 689 * Note also that this simple deadlock detection scheme will not 690 * work if the filesystem has any hard links other than ".." 691 * that point backwards in the directory structure. 692 */ 693 pdp = vdp; 694 if (flags & ISDOTDOT) { 695 error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp); 696 if (error) 697 return (error); 698 699 /* 700 * Recheck that ".." entry in the vdp directory points 701 * to the inode we looked up before vdp lock was 702 * dropped. 703 */ 704 error = ufs_lookup_ino(pdp, NULL, cnp, &ino1); 705 if (error) { 706 vput(tdp); 707 return (error); 708 } 709 if (ino1 != ino) { 710 vput(tdp); 711 goto restart; 712 } 713 714 *vpp = tdp; 715 } else if (dp->i_number == ino) { 716 VREF(vdp); /* we want ourself, ie "." */ 717 /* 718 * When we lookup "." we still can be asked to lock it 719 * differently. 720 */ 721 ltype = cnp->cn_lkflags & LK_TYPE_MASK; 722 if (ltype != VOP_ISLOCKED(vdp)) { 723 if (ltype == LK_EXCLUSIVE) 724 vn_lock(vdp, LK_UPGRADE | LK_RETRY); 725 else /* if (ltype == LK_SHARED) */ 726 vn_lock(vdp, LK_DOWNGRADE | LK_RETRY); 727 /* 728 * Relock for the "." case may left us with 729 * reclaimed vnode. 730 */ 731 if (vdp->v_iflag & VI_DOOMED) { 732 vrele(vdp); 733 return (ENOENT); 734 } 735 } 736 *vpp = vdp; 737 } else { 738 error = VFS_VGET(pdp->v_mount, ino, cnp->cn_lkflags, &tdp); 739 if (error) 740 return (error); 741 *vpp = tdp; 742 } 743 744 /* 745 * Insert name into cache if appropriate. 746 */ 747 if (cnp->cn_flags & MAKEENTRY) 748 cache_enter(vdp, *vpp, cnp); 749 return (0); 750 } 751 752 void 753 ufs_dirbad(ip, offset, how) 754 struct inode *ip; 755 doff_t offset; 756 char *how; 757 { 758 struct mount *mp; 759 760 mp = ITOV(ip)->v_mount; 761 if ((mp->mnt_flag & MNT_RDONLY) == 0) 762 panic("ufs_dirbad: %s: bad dir ino %ju at offset %ld: %s", 763 mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, 764 (long)offset, how); 765 else 766 (void)printf("%s: bad dir ino %ju at offset %ld: %s\n", 767 mp->mnt_stat.f_mntonname, (uintmax_t)ip->i_number, 768 (long)offset, how); 769 } 770 771 /* 772 * Do consistency checking on a directory entry: 773 * record length must be multiple of 4 774 * entry must fit in rest of its DIRBLKSIZ block 775 * record must be large enough to contain entry 776 * name is not longer than UFS_MAXNAMLEN 777 * name must be as long as advertised, and null terminated 778 */ 779 int 780 ufs_dirbadentry(dp, ep, entryoffsetinblock) 781 struct vnode *dp; 782 struct direct *ep; 783 int entryoffsetinblock; 784 { 785 int i, namlen; 786 787 # if (BYTE_ORDER == LITTLE_ENDIAN) 788 if (OFSFMT(dp)) 789 namlen = ep->d_type; 790 else 791 namlen = ep->d_namlen; 792 # else 793 namlen = ep->d_namlen; 794 # endif 795 if ((ep->d_reclen & 0x3) != 0 || 796 ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) || 797 ep->d_reclen < DIRSIZ(OFSFMT(dp), ep) || namlen > UFS_MAXNAMLEN) { 798 /*return (1); */ 799 printf("First bad\n"); 800 goto bad; 801 } 802 if (ep->d_ino == 0) 803 return (0); 804 for (i = 0; i < namlen; i++) 805 if (ep->d_name[i] == '\0') { 806 /*return (1); */ 807 printf("Second bad\n"); 808 goto bad; 809 } 810 if (ep->d_name[i]) 811 goto bad; 812 return (0); 813 bad: 814 return (1); 815 } 816 817 /* 818 * Construct a new directory entry after a call to namei, using the 819 * parameters that it left in the componentname argument cnp. The 820 * argument ip is the inode to which the new directory entry will refer. 821 */ 822 void 823 ufs_makedirentry(ip, cnp, newdirp) 824 struct inode *ip; 825 struct componentname *cnp; 826 struct direct *newdirp; 827 { 828 829 #ifdef INVARIANTS 830 if ((cnp->cn_flags & SAVENAME) == 0) 831 panic("ufs_makedirentry: missing name"); 832 #endif 833 newdirp->d_ino = ip->i_number; 834 newdirp->d_namlen = cnp->cn_namelen; 835 bcopy(cnp->cn_nameptr, newdirp->d_name, (unsigned)cnp->cn_namelen + 1); 836 if (ITOV(ip)->v_mount->mnt_maxsymlinklen > 0) 837 newdirp->d_type = IFTODT(ip->i_mode); 838 else { 839 newdirp->d_type = 0; 840 # if (BYTE_ORDER == LITTLE_ENDIAN) 841 { u_char tmp = newdirp->d_namlen; 842 newdirp->d_namlen = newdirp->d_type; 843 newdirp->d_type = tmp; } 844 # endif 845 } 846 } 847 848 /* 849 * Write a directory entry after a call to namei, using the parameters 850 * that it left in nameidata. The argument dirp is the new directory 851 * entry contents. Dvp is a pointer to the directory to be written, 852 * which was left locked by namei. Remaining parameters (dp->i_offset, 853 * dp->i_count) indicate how the space for the new entry is to be obtained. 854 * Non-null bp indicates that a directory is being created (for the 855 * soft dependency code). 856 */ 857 int 858 ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename) 859 struct vnode *dvp; 860 struct vnode *tvp; 861 struct direct *dirp; 862 struct componentname *cnp; 863 struct buf *newdirbp; 864 int isrename; 865 { 866 struct ucred *cr; 867 struct thread *td; 868 int newentrysize; 869 struct inode *dp; 870 struct buf *bp; 871 u_int dsize; 872 struct direct *ep, *nep; 873 u_int64_t old_isize; 874 int error, ret, blkoff, loc, spacefree, flags, namlen; 875 char *dirbuf; 876 877 td = curthread; /* XXX */ 878 cr = td->td_ucred; 879 880 dp = VTOI(dvp); 881 newentrysize = DIRSIZ(OFSFMT(dvp), dirp); 882 883 if (dp->i_count == 0) { 884 /* 885 * If dp->i_count is 0, then namei could find no 886 * space in the directory. Here, dp->i_offset will 887 * be on a directory block boundary and we will write the 888 * new entry into a fresh block. 889 */ 890 if (dp->i_offset & (DIRBLKSIZ - 1)) 891 panic("ufs_direnter: newblk"); 892 flags = BA_CLRBUF; 893 if (!DOINGSOFTDEP(dvp) && !DOINGASYNC(dvp)) 894 flags |= IO_SYNC; 895 #ifdef QUOTA 896 if ((error = getinoquota(dp)) != 0) { 897 if (DOINGSOFTDEP(dvp) && newdirbp != NULL) 898 bdwrite(newdirbp); 899 return (error); 900 } 901 #endif 902 old_isize = dp->i_size; 903 vnode_pager_setsize(dvp, (u_long)dp->i_offset + DIRBLKSIZ); 904 if ((error = UFS_BALLOC(dvp, (off_t)dp->i_offset, DIRBLKSIZ, 905 cr, flags, &bp)) != 0) { 906 if (DOINGSOFTDEP(dvp) && newdirbp != NULL) 907 bdwrite(newdirbp); 908 vnode_pager_setsize(dvp, (u_long)old_isize); 909 return (error); 910 } 911 dp->i_size = dp->i_offset + DIRBLKSIZ; 912 DIP_SET(dp, i_size, dp->i_size); 913 dp->i_endoff = dp->i_size; 914 dp->i_flag |= IN_CHANGE | IN_UPDATE; 915 dirp->d_reclen = DIRBLKSIZ; 916 blkoff = dp->i_offset & 917 (VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1); 918 bcopy((caddr_t)dirp, (caddr_t)bp->b_data + blkoff,newentrysize); 919 #ifdef UFS_DIRHASH 920 if (dp->i_dirhash != NULL) { 921 ufsdirhash_newblk(dp, dp->i_offset); 922 ufsdirhash_add(dp, dirp, dp->i_offset); 923 ufsdirhash_checkblock(dp, (char *)bp->b_data + blkoff, 924 dp->i_offset); 925 } 926 #endif 927 if (DOINGSOFTDEP(dvp)) { 928 /* 929 * Ensure that the entire newly allocated block is a 930 * valid directory so that future growth within the 931 * block does not have to ensure that the block is 932 * written before the inode. 933 */ 934 blkoff += DIRBLKSIZ; 935 while (blkoff < bp->b_bcount) { 936 ((struct direct *) 937 (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ; 938 blkoff += DIRBLKSIZ; 939 } 940 if (softdep_setup_directory_add(bp, dp, dp->i_offset, 941 dirp->d_ino, newdirbp, 1)) 942 dp->i_flag |= IN_NEEDSYNC; 943 if (newdirbp) 944 bdwrite(newdirbp); 945 bdwrite(bp); 946 if ((dp->i_flag & IN_NEEDSYNC) == 0) 947 return (UFS_UPDATE(dvp, 0)); 948 /* 949 * We have just allocated a directory block in an 950 * indirect block. We must prevent holes in the 951 * directory created if directory entries are 952 * written out of order. To accomplish this we 953 * fsync when we extend a directory into indirects. 954 * During rename it's not safe to drop the tvp lock 955 * so sync must be delayed until it is. 956 * 957 * This synchronous step could be removed if fsck and 958 * the kernel were taught to fill in sparse 959 * directories rather than panic. 960 */ 961 if (isrename) 962 return (0); 963 if (tvp != NULL) 964 VOP_UNLOCK(tvp, 0); 965 (void) VOP_FSYNC(dvp, MNT_WAIT, td); 966 if (tvp != NULL) 967 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); 968 return (error); 969 } 970 if (DOINGASYNC(dvp)) { 971 bdwrite(bp); 972 return (UFS_UPDATE(dvp, 0)); 973 } 974 error = bwrite(bp); 975 ret = UFS_UPDATE(dvp, 1); 976 if (error == 0) 977 return (ret); 978 return (error); 979 } 980 981 /* 982 * If dp->i_count is non-zero, then namei found space for the new 983 * entry in the range dp->i_offset to dp->i_offset + dp->i_count 984 * in the directory. To use this space, we may have to compact 985 * the entries located there, by copying them together towards the 986 * beginning of the block, leaving the free space in one usable 987 * chunk at the end. 988 */ 989 990 /* 991 * Increase size of directory if entry eats into new space. 992 * This should never push the size past a new multiple of 993 * DIRBLKSIZE. 994 * 995 * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. 996 */ 997 if (dp->i_offset + dp->i_count > dp->i_size) { 998 dp->i_size = dp->i_offset + dp->i_count; 999 DIP_SET(dp, i_size, dp->i_size); 1000 } 1001 /* 1002 * Get the block containing the space for the new directory entry. 1003 */ 1004 error = UFS_BLKATOFF(dvp, (off_t)dp->i_offset, &dirbuf, &bp); 1005 if (error) { 1006 if (DOINGSOFTDEP(dvp) && newdirbp != NULL) 1007 bdwrite(newdirbp); 1008 return (error); 1009 } 1010 /* 1011 * Find space for the new entry. In the simple case, the entry at 1012 * offset base will have the space. If it does not, then namei 1013 * arranged that compacting the region dp->i_offset to 1014 * dp->i_offset + dp->i_count would yield the space. 1015 */ 1016 ep = (struct direct *)dirbuf; 1017 dsize = ep->d_ino ? DIRSIZ(OFSFMT(dvp), ep) : 0; 1018 spacefree = ep->d_reclen - dsize; 1019 for (loc = ep->d_reclen; loc < dp->i_count; ) { 1020 nep = (struct direct *)(dirbuf + loc); 1021 1022 /* Trim the existing slot (NB: dsize may be zero). */ 1023 ep->d_reclen = dsize; 1024 ep = (struct direct *)((char *)ep + dsize); 1025 1026 /* Read nep->d_reclen now as the bcopy() may clobber it. */ 1027 loc += nep->d_reclen; 1028 if (nep->d_ino == 0) { 1029 /* 1030 * A mid-block unused entry. Such entries are 1031 * never created by the kernel, but fsck_ffs 1032 * can create them (and it doesn't fix them). 1033 * 1034 * Add up the free space, and initialise the 1035 * relocated entry since we don't bcopy it. 1036 */ 1037 spacefree += nep->d_reclen; 1038 ep->d_ino = 0; 1039 dsize = 0; 1040 continue; 1041 } 1042 dsize = DIRSIZ(OFSFMT(dvp), nep); 1043 spacefree += nep->d_reclen - dsize; 1044 #ifdef UFS_DIRHASH 1045 if (dp->i_dirhash != NULL) 1046 ufsdirhash_move(dp, nep, 1047 dp->i_offset + ((char *)nep - dirbuf), 1048 dp->i_offset + ((char *)ep - dirbuf)); 1049 #endif 1050 if (DOINGSOFTDEP(dvp)) 1051 softdep_change_directoryentry_offset(bp, dp, dirbuf, 1052 (caddr_t)nep, (caddr_t)ep, dsize); 1053 else 1054 bcopy((caddr_t)nep, (caddr_t)ep, dsize); 1055 } 1056 /* 1057 * Here, `ep' points to a directory entry containing `dsize' in-use 1058 * bytes followed by `spacefree' unused bytes. If ep->d_ino == 0, 1059 * then the entry is completely unused (dsize == 0). The value 1060 * of ep->d_reclen is always indeterminate. 1061 * 1062 * Update the pointer fields in the previous entry (if any), 1063 * copy in the new entry, and write out the block. 1064 */ 1065 # if (BYTE_ORDER == LITTLE_ENDIAN) 1066 if (OFSFMT(dvp)) 1067 namlen = ep->d_type; 1068 else 1069 namlen = ep->d_namlen; 1070 # else 1071 namlen = ep->d_namlen; 1072 # endif 1073 if (ep->d_ino == 0 || 1074 (ep->d_ino == UFS_WINO && namlen == dirp->d_namlen && 1075 bcmp(ep->d_name, dirp->d_name, dirp->d_namlen) == 0)) { 1076 if (spacefree + dsize < newentrysize) 1077 panic("ufs_direnter: compact1"); 1078 dirp->d_reclen = spacefree + dsize; 1079 } else { 1080 if (spacefree < newentrysize) 1081 panic("ufs_direnter: compact2"); 1082 dirp->d_reclen = spacefree; 1083 ep->d_reclen = dsize; 1084 ep = (struct direct *)((char *)ep + dsize); 1085 } 1086 #ifdef UFS_DIRHASH 1087 if (dp->i_dirhash != NULL && (ep->d_ino == 0 || 1088 dirp->d_reclen == spacefree)) 1089 ufsdirhash_add(dp, dirp, dp->i_offset + ((char *)ep - dirbuf)); 1090 #endif 1091 bcopy((caddr_t)dirp, (caddr_t)ep, (u_int)newentrysize); 1092 #ifdef UFS_DIRHASH 1093 if (dp->i_dirhash != NULL) 1094 ufsdirhash_checkblock(dp, dirbuf - 1095 (dp->i_offset & (DIRBLKSIZ - 1)), 1096 rounddown2(dp->i_offset, DIRBLKSIZ)); 1097 #endif 1098 1099 if (DOINGSOFTDEP(dvp)) { 1100 (void) softdep_setup_directory_add(bp, dp, 1101 dp->i_offset + (caddr_t)ep - dirbuf, 1102 dirp->d_ino, newdirbp, 0); 1103 if (newdirbp != NULL) 1104 bdwrite(newdirbp); 1105 bdwrite(bp); 1106 } else { 1107 if (DOINGASYNC(dvp)) { 1108 bdwrite(bp); 1109 error = 0; 1110 } else { 1111 error = bwrite(bp); 1112 } 1113 } 1114 dp->i_flag |= IN_CHANGE | IN_UPDATE; 1115 /* 1116 * If all went well, and the directory can be shortened, proceed 1117 * with the truncation. Note that we have to unlock the inode for 1118 * the entry that we just entered, as the truncation may need to 1119 * lock other inodes which can lead to deadlock if we also hold a 1120 * lock on the newly entered node. 1121 */ 1122 if (isrename == 0 && error == 0 && 1123 dp->i_endoff && dp->i_endoff < dp->i_size) { 1124 if (tvp != NULL) 1125 VOP_UNLOCK(tvp, 0); 1126 error = UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, 1127 IO_NORMAL | (DOINGASYNC(dvp) ? 0 : IO_SYNC), cr); 1128 if (error != 0) 1129 vn_printf(dvp, 1130 "ufs_direnter: failed to truncate, error %d\n", 1131 error); 1132 #ifdef UFS_DIRHASH 1133 if (error == 0 && dp->i_dirhash != NULL) 1134 ufsdirhash_dirtrunc(dp, dp->i_endoff); 1135 #endif 1136 error = 0; 1137 if (tvp != NULL) 1138 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); 1139 } 1140 return (error); 1141 } 1142 1143 /* 1144 * Remove a directory entry after a call to namei, using 1145 * the parameters which it left in nameidata. The entry 1146 * dp->i_offset contains the offset into the directory of the 1147 * entry to be eliminated. The dp->i_count field contains the 1148 * size of the previous record in the directory. If this 1149 * is 0, the first entry is being deleted, so we need only 1150 * zero the inode number to mark the entry as free. If the 1151 * entry is not the first in the directory, we must reclaim 1152 * the space of the now empty record by adding the record size 1153 * to the size of the previous entry. 1154 */ 1155 int 1156 ufs_dirremove(dvp, ip, flags, isrmdir) 1157 struct vnode *dvp; 1158 struct inode *ip; 1159 int flags; 1160 int isrmdir; 1161 { 1162 struct inode *dp; 1163 struct direct *ep, *rep; 1164 struct buf *bp; 1165 int error; 1166 1167 dp = VTOI(dvp); 1168 1169 /* 1170 * Adjust the link count early so softdep can block if necessary. 1171 */ 1172 if (ip) { 1173 ip->i_effnlink--; 1174 if (DOINGSOFTDEP(dvp)) { 1175 softdep_setup_unlink(dp, ip); 1176 } else { 1177 ip->i_nlink--; 1178 DIP_SET(ip, i_nlink, ip->i_nlink); 1179 ip->i_flag |= IN_CHANGE; 1180 } 1181 } 1182 if (flags & DOWHITEOUT) { 1183 /* 1184 * Whiteout entry: set d_ino to UFS_WINO. 1185 */ 1186 if ((error = 1187 UFS_BLKATOFF(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) 1188 return (error); 1189 ep->d_ino = UFS_WINO; 1190 ep->d_type = DT_WHT; 1191 goto out; 1192 } 1193 1194 if ((error = UFS_BLKATOFF(dvp, 1195 (off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0) 1196 return (error); 1197 1198 /* Set 'rep' to the entry being removed. */ 1199 if (dp->i_count == 0) 1200 rep = ep; 1201 else 1202 rep = (struct direct *)((char *)ep + ep->d_reclen); 1203 #ifdef UFS_DIRHASH 1204 /* 1205 * Remove the dirhash entry. This is complicated by the fact 1206 * that `ep' is the previous entry when dp->i_count != 0. 1207 */ 1208 if (dp->i_dirhash != NULL) 1209 ufsdirhash_remove(dp, rep, dp->i_offset); 1210 #endif 1211 if (ip && rep->d_ino != ip->i_number) 1212 panic("ufs_dirremove: ip %ju does not match dirent ino %ju\n", 1213 (uintmax_t)ip->i_number, (uintmax_t)rep->d_ino); 1214 if (dp->i_count == 0) { 1215 /* 1216 * First entry in block: set d_ino to zero. 1217 */ 1218 ep->d_ino = 0; 1219 } else { 1220 /* 1221 * Collapse new free space into previous entry. 1222 */ 1223 ep->d_reclen += rep->d_reclen; 1224 } 1225 #ifdef UFS_DIRHASH 1226 if (dp->i_dirhash != NULL) 1227 ufsdirhash_checkblock(dp, (char *)ep - 1228 ((dp->i_offset - dp->i_count) & (DIRBLKSIZ - 1)), 1229 rounddown2(dp->i_offset, DIRBLKSIZ)); 1230 #endif 1231 out: 1232 error = 0; 1233 if (DOINGSOFTDEP(dvp)) { 1234 if (ip) 1235 softdep_setup_remove(bp, dp, ip, isrmdir); 1236 if (softdep_slowdown(dvp)) 1237 error = bwrite(bp); 1238 else 1239 bdwrite(bp); 1240 } else { 1241 if (flags & DOWHITEOUT) 1242 error = bwrite(bp); 1243 else if (DOINGASYNC(dvp)) 1244 bdwrite(bp); 1245 else 1246 error = bwrite(bp); 1247 } 1248 dp->i_flag |= IN_CHANGE | IN_UPDATE; 1249 /* 1250 * If the last named reference to a snapshot goes away, 1251 * drop its snapshot reference so that it will be reclaimed 1252 * when last open reference goes away. 1253 */ 1254 if (ip != NULL && (ip->i_flags & SF_SNAPSHOT) != 0 && 1255 ip->i_effnlink == 0) 1256 UFS_SNAPGONE(ip); 1257 return (error); 1258 } 1259 1260 /* 1261 * Rewrite an existing directory entry to point at the inode 1262 * supplied. The parameters describing the directory entry are 1263 * set up by a call to namei. 1264 */ 1265 int 1266 ufs_dirrewrite(dp, oip, newinum, newtype, isrmdir) 1267 struct inode *dp, *oip; 1268 ino_t newinum; 1269 int newtype; 1270 int isrmdir; 1271 { 1272 struct buf *bp; 1273 struct direct *ep; 1274 struct vnode *vdp = ITOV(dp); 1275 int error; 1276 1277 /* 1278 * Drop the link before we lock the buf so softdep can block if 1279 * necessary. 1280 */ 1281 oip->i_effnlink--; 1282 if (DOINGSOFTDEP(vdp)) { 1283 softdep_setup_unlink(dp, oip); 1284 } else { 1285 oip->i_nlink--; 1286 DIP_SET(oip, i_nlink, oip->i_nlink); 1287 oip->i_flag |= IN_CHANGE; 1288 } 1289 1290 error = UFS_BLKATOFF(vdp, (off_t)dp->i_offset, (char **)&ep, &bp); 1291 if (error) 1292 return (error); 1293 if (ep->d_namlen == 2 && ep->d_name[1] == '.' && ep->d_name[0] == '.' && 1294 ep->d_ino != oip->i_number) { 1295 brelse(bp); 1296 return (EIDRM); 1297 } 1298 ep->d_ino = newinum; 1299 if (!OFSFMT(vdp)) 1300 ep->d_type = newtype; 1301 if (DOINGSOFTDEP(vdp)) { 1302 softdep_setup_directory_change(bp, dp, oip, newinum, isrmdir); 1303 bdwrite(bp); 1304 } else { 1305 if (DOINGASYNC(vdp)) { 1306 bdwrite(bp); 1307 error = 0; 1308 } else { 1309 error = bwrite(bp); 1310 } 1311 } 1312 dp->i_flag |= IN_CHANGE | IN_UPDATE; 1313 /* 1314 * If the last named reference to a snapshot goes away, 1315 * drop its snapshot reference so that it will be reclaimed 1316 * when last open reference goes away. 1317 */ 1318 if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_effnlink == 0) 1319 UFS_SNAPGONE(oip); 1320 return (error); 1321 } 1322 1323 /* 1324 * Check if a directory is empty or not. 1325 * Inode supplied must be locked. 1326 * 1327 * Using a struct dirtemplate here is not precisely 1328 * what we want, but better than using a struct direct. 1329 * 1330 * NB: does not handle corrupted directories. 1331 */ 1332 int 1333 ufs_dirempty(ip, parentino, cred) 1334 struct inode *ip; 1335 ino_t parentino; 1336 struct ucred *cred; 1337 { 1338 doff_t off; 1339 struct dirtemplate dbuf; 1340 struct direct *dp = (struct direct *)&dbuf; 1341 int error, namlen; 1342 ssize_t count; 1343 #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) 1344 1345 for (off = 0; off < ip->i_size; off += dp->d_reclen) { 1346 error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, 1347 off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, 1348 NOCRED, &count, (struct thread *)0); 1349 /* 1350 * Since we read MINDIRSIZ, residual must 1351 * be 0 unless we're at end of file. 1352 */ 1353 if (error || count != 0) 1354 return (0); 1355 /* avoid infinite loops */ 1356 if (dp->d_reclen == 0) 1357 return (0); 1358 /* skip empty entries */ 1359 if (dp->d_ino == 0 || dp->d_ino == UFS_WINO) 1360 continue; 1361 /* accept only "." and ".." */ 1362 # if (BYTE_ORDER == LITTLE_ENDIAN) 1363 if (OFSFMT(ITOV(ip))) 1364 namlen = dp->d_type; 1365 else 1366 namlen = dp->d_namlen; 1367 # else 1368 namlen = dp->d_namlen; 1369 # endif 1370 if (namlen > 2) 1371 return (0); 1372 if (dp->d_name[0] != '.') 1373 return (0); 1374 /* 1375 * At this point namlen must be 1 or 2. 1376 * 1 implies ".", 2 implies ".." if second 1377 * char is also "." 1378 */ 1379 if (namlen == 1 && dp->d_ino == ip->i_number) 1380 continue; 1381 if (dp->d_name[1] == '.' && dp->d_ino == parentino) 1382 continue; 1383 return (0); 1384 } 1385 return (1); 1386 } 1387 1388 static int 1389 ufs_dir_dd_ino(struct vnode *vp, struct ucred *cred, ino_t *dd_ino, 1390 struct vnode **dd_vp) 1391 { 1392 struct dirtemplate dirbuf; 1393 struct vnode *ddvp; 1394 int error, namlen; 1395 1396 ASSERT_VOP_LOCKED(vp, "ufs_dir_dd_ino"); 1397 if (vp->v_type != VDIR) 1398 return (ENOTDIR); 1399 /* 1400 * First check to see if we have it in the name cache. 1401 */ 1402 if ((ddvp = vn_dir_dd_ino(vp)) != NULL) { 1403 KASSERT(ddvp->v_mount == vp->v_mount, 1404 ("ufs_dir_dd_ino: Unexpected mount point crossing")); 1405 *dd_ino = VTOI(ddvp)->i_number; 1406 *dd_vp = ddvp; 1407 return (0); 1408 } 1409 /* 1410 * Have to read the directory. 1411 */ 1412 error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, 1413 sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, 1414 IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, NULL, NULL); 1415 if (error != 0) 1416 return (error); 1417 #if (BYTE_ORDER == LITTLE_ENDIAN) 1418 if (OFSFMT(vp)) 1419 namlen = dirbuf.dotdot_type; 1420 else 1421 namlen = dirbuf.dotdot_namlen; 1422 #else 1423 namlen = dirbuf.dotdot_namlen; 1424 #endif 1425 if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || 1426 dirbuf.dotdot_name[1] != '.') 1427 return (ENOTDIR); 1428 *dd_ino = dirbuf.dotdot_ino; 1429 *dd_vp = NULL; 1430 return (0); 1431 } 1432 1433 /* 1434 * Check if source directory is in the path of the target directory. 1435 */ 1436 int 1437 ufs_checkpath(ino_t source_ino, ino_t parent_ino, struct inode *target, struct ucred *cred, ino_t *wait_ino) 1438 { 1439 struct mount *mp; 1440 struct vnode *tvp, *vp, *vp1; 1441 int error; 1442 ino_t dd_ino; 1443 1444 vp = tvp = ITOV(target); 1445 mp = vp->v_mount; 1446 *wait_ino = 0; 1447 if (target->i_number == source_ino) 1448 return (EEXIST); 1449 if (target->i_number == parent_ino) 1450 return (0); 1451 if (target->i_number == UFS_ROOTINO) 1452 return (0); 1453 for (;;) { 1454 error = ufs_dir_dd_ino(vp, cred, &dd_ino, &vp1); 1455 if (error != 0) 1456 break; 1457 if (dd_ino == source_ino) { 1458 error = EINVAL; 1459 break; 1460 } 1461 if (dd_ino == UFS_ROOTINO) 1462 break; 1463 if (dd_ino == parent_ino) 1464 break; 1465 if (vp1 == NULL) { 1466 error = VFS_VGET(mp, dd_ino, LK_SHARED | LK_NOWAIT, 1467 &vp1); 1468 if (error != 0) { 1469 *wait_ino = dd_ino; 1470 break; 1471 } 1472 } 1473 KASSERT(dd_ino == VTOI(vp1)->i_number, 1474 ("directory %ju reparented\n", 1475 (uintmax_t)VTOI(vp1)->i_number)); 1476 if (vp != tvp) 1477 vput(vp); 1478 vp = vp1; 1479 } 1480 1481 if (error == ENOTDIR) 1482 panic("checkpath: .. not a directory\n"); 1483 if (vp1 != NULL) 1484 vput(vp1); 1485 if (vp != tvp) 1486 vput(vp); 1487 return (error); 1488 } 1489