1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/t_lock.h> 30 #include <sys/param.h> 31 #include <sys/time.h> 32 #include <sys/systm.h> 33 #include <sys/sysmacros.h> 34 #include <sys/resource.h> 35 #include <sys/signal.h> 36 #include <sys/cred.h> 37 #include <sys/user.h> 38 #include <sys/buf.h> 39 #include <sys/vfs.h> 40 #include <sys/stat.h> 41 #include <sys/vnode.h> 42 #include <sys/mode.h> 43 #include <sys/proc.h> 44 #include <sys/disp.h> 45 #include <sys/file.h> 46 #include <sys/fcntl.h> 47 #include <sys/flock.h> 48 #include <sys/kmem.h> 49 #include <sys/uio.h> 50 #include <sys/dnlc.h> 51 #include <sys/conf.h> 52 #include <sys/errno.h> 53 #include <sys/mman.h> 54 #include <sys/fbuf.h> 55 #include <sys/pathname.h> 56 #include <sys/debug.h> 57 #include <sys/vmsystm.h> 58 #include <sys/cmn_err.h> 59 #include <sys/dirent.h> 60 #include <sys/errno.h> 61 #include <sys/modctl.h> 62 #include <sys/statvfs.h> 63 #include <sys/mount.h> 64 #include <sys/sunddi.h> 65 #include <sys/bootconf.h> 66 #include <sys/policy.h> 67 68 #include <vm/hat.h> 69 #include <vm/page.h> 70 #include <vm/pvn.h> 71 #include <vm/as.h> 72 #include <vm/seg.h> 73 #include <vm/seg_map.h> 74 #include <vm/seg_kmem.h> 75 #include <vm/seg_vn.h> 76 #include <vm/rm.h> 77 #include <vm/page.h> 78 #include <sys/swap.h> 79 80 81 #include <fs/fs_subr.h> 82 83 84 #include <sys/fs/udf_volume.h> 85 #include <sys/fs/udf_inode.h> 86 87 88 struct slot { 89 enum {NONE, COMPACT, FOUND, EXIST} status; 90 off_t offset; /* offset of area with free space */ 91 int size; /* size of area at slotoffset */ 92 struct fbuf *fbp; /* dir buf where slot is */ 93 struct file_id *ep; /* pointer to slot */ 94 off_t endoff; /* last useful location found in search */ 95 }; 96 97 98 int32_t ud_dircheckforname(struct ud_inode *, char *, int, 99 struct slot *, struct ud_inode **, uint8_t *, struct cred *); 100 int32_t ud_dirempty(struct ud_inode *, uint64_t, struct cred *); 101 int32_t str2cmp(char *, int32_t, char *, int32_t, char *, int32_t); 102 int32_t ud_dircheckpath(int32_t, struct ud_inode *, struct cred *); 103 int32_t ud_dirmakeinode(struct ud_inode *, struct ud_inode **, 104 struct vattr *, enum de_op, struct cred *); 105 int32_t ud_diraddentry(struct ud_inode *, char *, 106 enum de_op, int, struct slot *, struct ud_inode *, 107 struct ud_inode *, struct cred *); 108 int32_t ud_dirmakedirect(struct ud_inode *, struct ud_inode *, struct cred *); 109 int32_t ud_dirrename(struct ud_inode *, struct ud_inode *, 110 struct ud_inode *, struct ud_inode *, char *, uint8_t *, 111 struct slot *, struct cred *); 112 int32_t ud_dirprepareentry(struct ud_inode *, 113 struct slot *, uint8_t *, struct cred *); 114 int32_t ud_dirfixdotdot(struct ud_inode *, struct ud_inode *, 115 struct ud_inode *); 116 int32_t ud_write_fid(struct ud_inode *, struct slot *, uint8_t *); 117 118 int 119 ud_dirlook(struct ud_inode *dip, 120 char *namep, struct ud_inode **ipp, struct cred *cr, int32_t skipdnlc) 121 { 122 struct udf_vfs *udf_vfsp; 123 int32_t error = 0, namelen, adhoc_search; 124 u_offset_t offset, adhoc_offset, dirsize, end; 125 struct vnode *dvp, *vp; 126 struct fbuf *fbp; 127 struct file_id *fid; 128 uint8_t *fname, dummy[3]; 129 int32_t id_len, doingchk; 130 uint32_t old_loc; 131 uint16_t old_prn; 132 133 uint8_t *dname; 134 uint8_t *buf = NULL; 135 136 ud_printf("ud_dirlook\n"); 137 138 udf_vfsp = dip->i_udf; 139 140 restart: 141 doingchk = 0; 142 old_prn = 0xFFFF; 143 old_loc = 0; 144 dvp = ITOV(dip); 145 /* 146 * Check accessibility of directory. 147 */ 148 if (dip->i_type != VDIR) { 149 return (ENOTDIR); 150 } 151 if (error = ud_iaccess(dip, IEXEC, cr)) { 152 return (error); 153 } 154 155 /* 156 * Null component name is synonym for directory being searched. 157 */ 158 if (*namep == '\0') { 159 VN_HOLD(dvp); 160 *ipp = dip; 161 return (0); 162 } 163 namelen = strlen(namep); 164 if ((namelen == 1) && 165 (namep[0] == '.') && (namep[1] == '\0')) { 166 /* Current directory */ 167 VN_HOLD(dvp); 168 *ipp = dip; 169 dnlc_enter(dvp, namep, ITOV(*ipp)); 170 return (0); 171 } 172 173 if ((!skipdnlc) && (vp = dnlc_lookup(dvp, namep))) { 174 /* vp is already held from dnlc_lookup */ 175 176 *ipp = VTOI(vp); 177 return (0); 178 } 179 180 dname = kmem_zalloc(1024, KM_SLEEP); 181 buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 182 183 /* 184 * Read lock the inode we are searching. You will notice that we 185 * didn't hold the read lock while searching the dnlc. This means 186 * that the entry could now be in the dnlc. This doesn't cause any 187 * problems because dnlc_enter won't add an entry if it is already 188 * there. 189 */ 190 rw_enter(&dip->i_rwlock, RW_READER); 191 192 /* 193 * Take care to look at dip->i_diroff only once, as it 194 * may be changing due to other threads/cpus. 195 */ 196 197 recheck: 198 offset = dip->i_diroff; 199 end = dirsize = dip->i_size; 200 201 if (offset > dirsize) { 202 offset = 0; 203 } 204 adhoc_offset = offset; 205 adhoc_search = (offset == 0) ? 1 : 2; 206 207 fbp = NULL; 208 209 while (adhoc_search--) { 210 while (offset < end) { 211 error = ud_get_next_fid(dip, &fbp, 212 offset, &fid, &fname, buf); 213 if (error != 0) { 214 break; 215 } 216 if ((fid->fid_flags & FID_DELETED) == 0) { 217 if (fid->fid_flags & FID_PARENT) { 218 id_len = 2; 219 fname = dummy; 220 dummy[0] = '.'; 221 dummy[1] = '.'; 222 dummy[2] = '\0'; 223 } else { 224 if ((error = ud_uncompress( 225 fid->fid_idlen, &id_len, 226 fname, dname)) != 0) { 227 break; 228 } 229 fname = (uint8_t *)dname; 230 fname[id_len] = '\0'; 231 } 232 if ((namelen == id_len) && 233 (strncmp(namep, (caddr_t)fname, 234 namelen) == 0)) { 235 uint32_t loc; 236 uint16_t prn; 237 238 239 loc = SWAP_32(fid->fid_icb.lad_ext_loc); 240 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 241 dip->i_diroff = offset + 242 FID_LEN(fid); 243 244 if (doingchk) { 245 if ((loc == old_loc) && 246 (prn == old_prn)) { 247 goto checkok; 248 } else { 249 if (fbp != NULL) { 250 fbrelse(fbp, 251 S_READ); 252 fbp = NULL; 253 } 254 VN_RELE(ITOV(*ipp)); 255 rw_exit(&dip->i_rwlock); 256 goto restart; 257 } 258 /* NOTREACHED */ 259 } 260 261 if (namelen == 2 && 262 fname[0] == '.' && 263 fname[1] == '.') { 264 265 struct timespec32 omtime; 266 267 omtime = dip->i_mtime; 268 rw_exit(&dip->i_rwlock); 269 270 error = ud_iget(dip->i_vfs, prn, 271 loc, ipp, NULL, cr); 272 273 rw_enter(&dip->i_rwlock, 274 RW_READER); 275 276 if (error) { 277 goto done; 278 } 279 280 if ((omtime.tv_sec != 281 dip->i_mtime.tv_sec) || 282 (omtime.tv_nsec != 283 dip->i_mtime.tv_nsec)) { 284 285 doingchk = 1; 286 old_prn = prn; 287 old_loc = loc; 288 dip->i_diroff = 0; 289 if (fbp != NULL) { 290 fbrelse(fbp, 291 S_READ); 292 fbp = NULL; 293 } 294 goto recheck; 295 } 296 } else { 297 298 error = ud_iget(dip->i_vfs, prn, 299 loc, ipp, NULL, cr); 300 } 301 checkok: 302 if (error == 0) { 303 dnlc_enter(dvp, namep, 304 ITOV(*ipp)); 305 } 306 goto done; 307 } 308 } 309 offset += FID_LEN(fid); 310 } 311 if (fbp != NULL) { 312 fbrelse(fbp, S_READ); 313 fbp = NULL; 314 } 315 end = adhoc_offset; 316 offset = 0; 317 } 318 error = ENOENT; 319 done: 320 kmem_free(buf, udf_vfsp->udf_lbsize); 321 kmem_free(dname, 1024); 322 if (fbp != NULL) { 323 fbrelse(fbp, S_READ); 324 } 325 rw_exit(&dip->i_rwlock); 326 return (error); 327 } 328 329 int 330 ud_direnter( 331 struct ud_inode *tdp, 332 char *namep, 333 enum de_op op, 334 struct ud_inode *sdp, 335 struct ud_inode *sip, 336 struct vattr *vap, 337 struct ud_inode **ipp, 338 struct cred *cr, 339 caller_context_t *ctp) 340 { 341 struct udf_vfs *udf_vfsp; 342 struct ud_inode *tip; 343 struct slot slot; 344 int32_t namlen, err; 345 char *s; 346 347 uint8_t *buf = NULL; 348 349 ud_printf("ud_direnter\n"); 350 351 udf_vfsp = tdp->i_udf; 352 /* don't allow '/' characters in pathname component */ 353 for (s = namep, namlen = 0; *s; s++, namlen++) { 354 if (*s == '/') { 355 return (EACCES); 356 } 357 } 358 359 if (namlen == 0) { 360 cmn_err(CE_WARN, "name length == 0 in ud_direnter"); 361 return (EINVAL); 362 } 363 364 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 365 /* 366 * If name is "." or ".." then if this is a create look it up 367 * and return EEXIST. Rename or link TO "." or ".." is forbidden. 368 */ 369 if (namep[0] == '.' && 370 (namlen == 1 || (namlen == 2 && namep[1] == '.'))) { 371 if (op == DE_RENAME) { 372 return (EINVAL); /* *SIGH* should be ENOTEMPTY */ 373 } 374 if (ipp) { 375 /* 376 * ud_dirlook will acquire the i_rwlock 377 */ 378 rw_exit(&tdp->i_rwlock); 379 if (err = ud_dirlook(tdp, namep, ipp, cr, 0)) { 380 rw_enter(&tdp->i_rwlock, RW_WRITER); 381 return (err); 382 } 383 rw_enter(&tdp->i_rwlock, RW_WRITER); 384 } 385 return (EEXIST); 386 } 387 388 tip = NULL; 389 slot.status = NONE; 390 slot.offset = 0; 391 slot.size = 0; 392 slot.fbp = NULL; 393 slot.ep = NULL; 394 slot.endoff = 0; 395 396 /* 397 * For link and rename lock the source entry and check the link count 398 * to see if it has been removed while it was unlocked. If not, we 399 * increment the link count and force the inode to disk to make sure 400 * that it is there before any directory entry that points to it. 401 */ 402 if (op == DE_LINK || op == DE_RENAME) { 403 rw_enter(&sip->i_contents, RW_WRITER); 404 if (sip->i_nlink == 0) { 405 rw_exit(&sip->i_contents); 406 return (ENOENT); 407 } 408 if (sip->i_nlink == MAXLINK) { 409 rw_exit(&sip->i_contents); 410 return (EMLINK); 411 } 412 413 sip->i_nlink++; 414 mutex_enter(&sip->i_tlock); 415 sip->i_flag |= ICHG; 416 mutex_exit(&sip->i_tlock); 417 ud_iupdat(sip, 1); 418 rw_exit(&sip->i_contents); 419 } 420 /* 421 * If target directory has not been removed, then we can consider 422 * allowing file to be created. 423 */ 424 if (tdp->i_nlink == 0) { 425 err = ENOENT; 426 goto out2; 427 } 428 /* 429 * Check accessibility of directory. 430 */ 431 if (tdp->i_type != VDIR) { 432 err = ENOTDIR; 433 goto out2; 434 } 435 /* 436 * Execute access is required to search the directory. 437 */ 438 if (err = ud_iaccess(tdp, IEXEC, cr)) { 439 goto out2; 440 } 441 /* 442 * If this is a rename of a directory and the parent is 443 * different (".." must be changed), then the source 444 * directory must not be in the directory hierarchy 445 * above the target, as this would orphan everything 446 * below the source directory. Also the user must have 447 * write permission in the source so as to be able to 448 * change "..". 449 */ 450 if (op == DE_RENAME) { 451 if (sip == tdp) { 452 err = EINVAL; 453 goto out2; 454 } 455 rw_enter(&sip->i_contents, RW_READER); 456 if ((sip->i_type == VDIR) && (sdp != tdp)) { 457 uint32_t blkno; 458 459 if ((err = ud_iaccess(sip, IWRITE, cr))) { 460 rw_exit(&sip->i_contents); 461 goto out2; 462 } 463 blkno = sip->i_icb_lbano; 464 rw_exit(&sip->i_contents); 465 if ((err = ud_dircheckpath(blkno, tdp, cr))) { 466 goto out2; 467 } 468 } else { 469 rw_exit(&sip->i_contents); 470 } 471 } 472 473 /* 474 * Search for the entry. Return VN_HELD tip if found. 475 */ 476 buf = kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 477 rw_enter(&tdp->i_contents, RW_WRITER); 478 if (err = ud_dircheckforname(tdp, 479 namep, namlen, &slot, &tip, buf, cr)) { 480 goto out; 481 } 482 if (tip) { 483 switch (op) { 484 case DE_CREATE : 485 case DE_MKDIR : 486 if (ipp) { 487 *ipp = tip; 488 err = EEXIST; 489 } else { 490 VN_RELE(ITOV(tip)); 491 } 492 break; 493 case DE_RENAME : 494 err = ud_dirrename(sdp, sip, tdp, tip, 495 namep, buf, &slot, cr); 496 /* 497 * We used to VN_RELE() here, but this 498 * was moved down so that we could send 499 * a vnevent after the locks were dropped. 500 */ 501 break; 502 case DE_LINK : 503 /* 504 * Can't link to an existing file. 505 */ 506 VN_RELE(ITOV(tip)); 507 err = EEXIST; 508 break; 509 } 510 } else { 511 /* 512 * The entry does not exist. Check write permission in 513 * directory to see if entry can be created. 514 */ 515 if (err = ud_iaccess(tdp, IWRITE, cr)) { 516 goto out; 517 } 518 if ((op == DE_CREATE) || (op == DE_MKDIR)) { 519 /* 520 * Make new inode and directory entry as required. 521 */ 522 if (err = ud_dirmakeinode(tdp, &sip, vap, op, cr)) 523 goto out; 524 } 525 if (err = ud_diraddentry(tdp, namep, op, 526 namlen, &slot, sip, sdp, cr)) { 527 if ((op == DE_CREATE) || (op == DE_MKDIR)) { 528 /* 529 * Unmake the inode we just made. 530 */ 531 rw_enter(&sip->i_contents, RW_WRITER); 532 if (sip->i_type == VDIR) { 533 tdp->i_nlink--; 534 } 535 sip->i_nlink = 0; 536 mutex_enter(&sip->i_tlock); 537 sip->i_flag |= ICHG; 538 mutex_exit(&sip->i_tlock); 539 rw_exit(&sip->i_contents); 540 VN_RELE(ITOV(sip)); 541 sip = NULL; 542 } 543 } else if (ipp) { 544 *ipp = sip; 545 } else if ((op == DE_CREATE) || (op == DE_MKDIR)) { 546 VN_RELE(ITOV(sip)); 547 } 548 } 549 out: 550 if (buf != NULL) { 551 kmem_free(buf, udf_vfsp->udf_lbsize); 552 } 553 if (slot.fbp) { 554 fbrelse(slot.fbp, S_OTHER); 555 } 556 rw_exit(&tdp->i_contents); 557 558 if (op == DE_RENAME) { 559 /* 560 * If it's all good, send events after locks are dropped 561 * but before vnodes are released. 562 */ 563 if (err == 0) { 564 if (tip) { 565 vnevent_rename_dest(ITOV(tip), ITOV(tdp), 566 namep, ctp); 567 } 568 569 if (sdp != tdp) { 570 vnevent_rename_dest_dir(ITOV(tdp), ctp); 571 } 572 } 573 574 /* 575 * The following VN_RELE() was moved from the 576 * DE_RENAME case above 577 */ 578 if (tip) { 579 VN_RELE(ITOV(tip)); 580 } 581 } 582 583 out2: 584 if (err && ((op == DE_LINK) || (op == DE_RENAME))) { 585 /* 586 * Undo bumped link count. 587 */ 588 rw_enter(&sip->i_contents, RW_WRITER); 589 sip->i_nlink--; 590 rw_exit(&sip->i_contents); 591 592 mutex_enter(&sip->i_tlock); 593 sip->i_flag |= ICHG; 594 mutex_exit(&sip->i_tlock); 595 } 596 return (err); 597 } 598 599 /* 600 * Locking i_contents in this 601 * function seems to be really weird 602 */ 603 int 604 ud_dirremove( 605 struct ud_inode *dp, 606 char *namep, 607 struct ud_inode *oip, 608 struct vnode *cdir, 609 enum dr_op op, 610 struct cred *cr, 611 caller_context_t *ctp) 612 { 613 struct udf_vfs *udf_vfsp; 614 int32_t namelen, err = 0; 615 struct slot slot; 616 struct ud_inode *ip; 617 mode_t mode; 618 struct file_id *fid; 619 uint8_t *buf = NULL; 620 uint32_t tbno; 621 622 ud_printf("ud_dirremove\n"); 623 624 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 625 626 udf_vfsp = dp->i_udf; 627 namelen = (int)strlen(namep); 628 if (namelen == 0) { 629 cmn_err(CE_WARN, "name length == 0 in ud_dirremove"); 630 return (EINVAL); 631 } 632 633 /* 634 * return err when removing . and .. 635 */ 636 if (namep[0] == '.') { 637 if (namelen == 1) { 638 return (EINVAL); 639 } else if (namelen == 2 && namep[1] == '.') { 640 return (EEXIST); /* SIGH should be ENOTEMPTY */ 641 } 642 } 643 644 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 645 646 /* 647 * Check accessibility of directory. 648 */ 649 if (dp->i_type != VDIR) { 650 return (ENOTDIR); 651 } 652 653 ip = NULL; 654 slot.status = FOUND; /* don't need to look for empty slot */ 655 slot.offset = 0; 656 slot.size = 0; 657 slot.fbp = NULL; 658 slot.ep = NULL; 659 slot.endoff = 0; 660 /* 661 * Execute access is required to search the directory. 662 * Access for write is interpreted as allowing 663 * deletion of files in the directory. 664 */ 665 if (err = ud_iaccess(dp, IEXEC|IWRITE, cr)) { 666 return (err); 667 } 668 669 buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 670 671 rw_enter(&dp->i_contents, RW_WRITER); 672 673 if (err = ud_dircheckforname(dp, 674 namep, namelen, &slot, &ip, buf, cr)) { 675 goto out_novfs; 676 } 677 if (ip == NULL) { 678 err = ENOENT; 679 goto out_novfs; 680 } 681 if (oip && oip != ip) { 682 err = ENOENT; 683 goto out_novfs; 684 } 685 686 if ((mode = ip->i_type) == VDIR) { 687 /* 688 * vn_vfswlock() prevents races between mount and rmdir. 689 */ 690 if (vn_vfswlock(ITOV(ip))) { 691 err = EBUSY; 692 goto out_novfs; 693 } 694 if (vn_mountedvfs(ITOV(ip)) != NULL && op != DR_RENAME) { 695 err = EBUSY; 696 goto out; 697 } 698 /* 699 * If we are removing a directory, get a lock on it. 700 * If the directory is empty, it will stay empty until 701 * we can remove it. 702 */ 703 rw_enter(&ip->i_rwlock, RW_READER); 704 } 705 /* We must be holding i_contents */ 706 rw_enter(&ip->i_contents, RW_READER); 707 708 if (err = ud_sticky_remove_access(dp, ip, cr)) { 709 rw_exit(&ip->i_contents); 710 if (mode == VDIR) { 711 rw_exit(&ip->i_rwlock); 712 } 713 goto out; 714 } 715 if (op == DR_RMDIR) { 716 /* 717 * For rmdir(2), some special checks are required. 718 * (a) Don't remove any alias of the parent (e.g. "."). 719 * (b) Don't remove the current directory. 720 * (c) Make sure the entry is (still) a directory. 721 * (d) Make sure the directory is empty. 722 */ 723 724 if (dp == ip || ITOV(ip) == cdir) { 725 err = EINVAL; 726 } else if (ip->i_type != VDIR) { 727 err = ENOTDIR; 728 } else if ((ip->i_nlink != 1) || 729 (!ud_dirempty(ip, dp->i_uniqid, cr))) { 730 /* 731 * Directories do not have an 732 * entry for "." so only one link 733 * will be there 734 */ 735 err = EEXIST; /* SIGH should be ENOTEMPTY */ 736 } 737 if (err) { 738 rw_exit(&ip->i_contents); 739 if (mode == VDIR) { 740 rw_exit(&ip->i_rwlock); 741 } 742 goto out; 743 } 744 } else if (op == DR_REMOVE) { 745 /* 746 * unlink(2) requires a different check: allow only 747 * privileged processes to unlink a directory. 748 */ 749 struct vnode *vp = ITOV(ip); 750 751 if (vp->v_type == VDIR && 752 secpolicy_fs_linkdir(cr, vp->v_vfsp)) { 753 err = EPERM; 754 rw_exit(&ip->i_contents); 755 rw_exit(&ip->i_rwlock); 756 goto out; 757 } 758 } 759 rw_exit(&ip->i_contents); 760 761 /* 762 * Remove the cache'd entry, if any. 763 */ 764 dnlc_remove(ITOV(dp), namep); 765 766 /* 767 * We can collapse all the directory 768 * entries that are deleted into one big entry 769 * but the better way is to 770 * defer it till next directory entry 771 * creation. where we can do this 772 * in a more efficient way 773 */ 774 fid = slot.ep; 775 776 /* 777 * If this is the last entry 778 * just truncate the file instead 779 * of marking it deleted 780 */ 781 if ((slot.offset + FID_LEN(fid)) == dp->i_size) { 782 fbrelse(slot.fbp, S_OTHER); 783 if ((err = ud_itrunc(dp, slot.offset, 0, cr)) != 0) { 784 goto out; 785 } 786 } else { 787 fid->fid_flags |= FID_DELETED; 788 789 if ((err = ud_ip_off2bno(dp, slot.offset, &tbno)) != 0) { 790 goto out; 791 } 792 793 ud_make_tag(dp->i_udf, &fid->fid_tag, 794 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 795 796 err = ud_write_fid(dp, &slot, buf); 797 } 798 799 slot.fbp = NULL; 800 801 /* 802 * If we were removing a directory, it is 'gone' now so we can 803 * unlock it. 804 */ 805 if (mode == VDIR) { 806 rw_exit(&ip->i_rwlock); 807 } 808 809 mutex_enter(&dp->i_tlock); 810 dp->i_flag |= IUPD|ICHG; 811 mutex_exit(&dp->i_tlock); 812 mutex_enter(&ip->i_tlock); 813 ip->i_flag |= ICHG; 814 mutex_exit(&ip->i_tlock); 815 816 if (err != 0) { 817 goto out; 818 } 819 820 rw_enter(&ip->i_contents, RW_WRITER); 821 822 /* 823 * Now dispose of the inode. 824 */ 825 if (ip->i_nlink > 0) { 826 if ((op == DR_RMDIR) && (ip->i_type == VDIR)) { 827 /* 828 * Decrement by 1 because there is no "." 829 * Clear the inode, but there may be other hard 830 * links so don't free the inode. 831 * Decrement the dp linkcount because we're 832 * trashing the ".." entry. 833 */ 834 ip->i_nlink --; 835 dp->i_nlink--; 836 dnlc_remove(ITOV(ip), "."); 837 dnlc_remove(ITOV(ip), ".."); 838 /* 839 * (void) ud_itrunc(ip, 0, 0, cr); 840 */ 841 } else { 842 ip->i_nlink--; 843 } 844 } 845 ITIMES_NOLOCK(dp); 846 ITIMES_NOLOCK(ip); 847 rw_exit(&ip->i_contents); 848 out: 849 if (mode == VDIR) { 850 vn_vfsunlock(ITOV(ip)); 851 } 852 out_novfs: 853 ASSERT(RW_WRITE_HELD(&dp->i_contents)); 854 855 if (slot.fbp != NULL) { 856 fbrelse(slot.fbp, S_OTHER); 857 } 858 rw_exit(&dp->i_contents); 859 860 if (ip) { 861 /* 862 * If no errors, send any events after locks are dropped, 863 * but before the VN_RELE(). 864 */ 865 if (err == 0) { 866 if (op == DR_REMOVE) { 867 vnevent_remove(ITOV(ip), ITOV(dp), namep, ctp); 868 } else if (op == DR_RMDIR) { 869 vnevent_rmdir(ITOV(ip), ITOV(dp), namep, ctp); 870 } 871 } 872 VN_RELE(ITOV(ip)); 873 } 874 875 kmem_free(buf, udf_vfsp->udf_lbsize); 876 return (err); 877 } 878 879 int 880 ud_dircheckforname(struct ud_inode *tdp, 881 char *namep, int32_t namelen, struct slot *slotp, 882 struct ud_inode **ipp, uint8_t *buf, struct cred *cr) 883 { 884 struct udf_vfs *udf_vfsp; 885 uint32_t dirsize, offset; 886 struct fbuf *fbp; 887 struct file_id *fid; 888 int32_t sz, error = 0, sz_req, matched = 0; 889 uint8_t *nm; 890 891 uint8_t *dname; 892 int32_t id_len; 893 894 ud_printf("ud_dircheckforname\n"); 895 896 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 897 fbp = NULL; 898 899 dname = (uint8_t *)kmem_zalloc(1024, KM_SLEEP); 900 901 udf_vfsp = tdp->i_udf; 902 903 offset = 0; 904 dirsize = tdp->i_size; 905 906 if (slotp->status != FOUND) { 907 int32_t temp; 908 909 temp = 1024; /* set to size of dname allocated above */ 910 if ((error = ud_compress(namelen, &temp, 911 (uint8_t *)namep, dname)) != 0) { 912 goto end; 913 } 914 sz_req = F_LEN + temp; 915 sz_req = (sz_req + 3) & ~3; 916 } 917 918 while (offset < dirsize) { 919 if ((error = ud_get_next_fid(tdp, &fbp, 920 offset, &fid, &nm, buf)) != 0) { 921 break; 922 } 923 if ((error = ud_uncompress(fid->fid_idlen, 924 &id_len, nm, dname)) != 0) { 925 break; 926 } 927 if ((fid->fid_flags & FID_DELETED) == 0) { 928 /* Check for name match */ 929 if (((namelen == id_len) && 930 (strncmp(namep, (caddr_t)dname, namelen) == 931 0)) || 932 ((fid->fid_flags & FID_PARENT) && 933 (namep[0] == '.' && 934 (namelen == 1 || 935 (namelen == 2 && namep[1] == '.'))))) { 936 937 tdp->i_diroff = offset; 938 if ((fid->fid_flags & FID_PARENT) && 939 (namelen == 1) && (namep[0] == '.')) { 940 struct vnode *vp = ITOV(tdp); 941 942 *ipp = tdp; 943 VN_HOLD(vp); 944 } else { 945 uint16_t prn; 946 uint32_t loc; 947 948 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 949 loc = SWAP_32(fid->fid_icb.lad_ext_loc); 950 if ((error = ud_iget(tdp->i_vfs, prn, 951 loc, ipp, NULL, cr)) != 0) { 952 953 fbrelse(fbp, S_OTHER); 954 goto end; 955 } 956 } 957 slotp->status = EXIST; 958 slotp->offset = offset; 959 slotp->size = FID_LEN(fid); 960 slotp->fbp = fbp; 961 slotp->ep = fid; 962 slotp->endoff = 0; 963 goto end; 964 } 965 } else { 966 /* 967 * see if we need to find an 968 * empty slot and the current slot 969 * matches 970 */ 971 if ((slotp->status != FOUND) || 972 (matched == 0)) { 973 sz = FID_LEN(fid); 974 if (sz == sz_req) { 975 slotp->status = FOUND; 976 slotp->offset = offset; 977 slotp->size = sz; 978 } 979 if (matched == 0) { 980 if ((namelen == id_len) && 981 (strncmp(namep, (caddr_t)dname, 982 namelen) == 0)) { 983 matched = 1; 984 slotp->status = FOUND; 985 slotp->offset = offset; 986 slotp->size = sz; 987 } 988 } 989 } 990 } 991 offset += FID_LEN(fid); 992 } 993 if (fbp) { 994 fbrelse(fbp, S_OTHER); 995 } 996 if (slotp->status == NONE) { 997 /* 998 * We didn't find a slot; the new directory entry should be put 999 * at the end of the directory. Return an indication of where 1000 * this is, and set "endoff" to zero; since we're going to have 1001 * to extend the directory, we're certainly not going to 1002 * trucate it. 1003 */ 1004 slotp->offset = dirsize; 1005 if (tdp->i_desc_type == ICB_FLAG_ONE_AD) { 1006 slotp->size = tdp->i_max_emb - tdp->i_size; 1007 } else { 1008 slotp->size = udf_vfsp->udf_lbsize - 1009 slotp->offset & udf_vfsp->udf_lbmask; 1010 } 1011 slotp->endoff = 0; 1012 } 1013 1014 *ipp = NULL; 1015 end: 1016 kmem_free((caddr_t)dname, 1024); 1017 return (error); 1018 } 1019 1020 /* 1021 * Return 1 if the dir has all files 1022 * deleted except the parent 1023 * else return 0 1024 */ 1025 /* ARGSUSED */ 1026 int 1027 ud_dirempty(struct ud_inode *ip, uint64_t ino, struct cred *cr) 1028 { 1029 offset_t off; 1030 int32_t empty = 1, error, count, entry_len, rcount; 1031 struct file_id *fid; 1032 caddr_t addr; 1033 uint32_t tbno; 1034 int32_t desc_len; 1035 1036 ud_printf("ud_dirempty\n"); 1037 1038 ASSERT(RW_LOCK_HELD(&ip->i_contents)); 1039 1040 if (ip->i_size == 0) { 1041 return (empty); 1042 } 1043 1044 desc_len = 1024; 1045 addr = kmem_zalloc(desc_len, KM_SLEEP); 1046 fid = (struct file_id *)addr; 1047 1048 for (off = 0; off < ip->i_size; off += entry_len) { 1049 1050 /* 1051 * First read fid 1052 * and verify checksum 1053 */ 1054 1055 rcount = sizeof (struct file_id); 1056 error = ud_rdwri(UIO_READ, FREAD, 1057 ip, addr, rcount, off, 1058 UIO_SYSSPACE, &count, cr); 1059 if ((error != 0) || (count != 0)) { 1060 empty = 0; 1061 break; 1062 } 1063 1064 if ((error = ud_ip_off2bno(ip, off, &tbno)) != 0) { 1065 empty = 0; 1066 break; 1067 } 1068 1069 /* 1070 * We verify the tag id and also the FID_LEN. 1071 * FID_LEN should be <= desc_len. 1072 */ 1073 if (ud_verify_tag_and_desc(&fid->fid_tag, 1074 UD_FILE_ID_DESC, 1075 tbno, 0, desc_len) != 0) { 1076 /* Corrupted directory */ 1077 empty = 0; 1078 break; 1079 } 1080 1081 /* 1082 * Read the fid + iulen + len 1083 * Now verify both checksum andCRC 1084 */ 1085 1086 rcount = FID_LEN(fid); 1087 error = ud_rdwri(UIO_READ, FREAD, 1088 ip, addr, rcount, off, 1089 UIO_SYSSPACE, &count, cr); 1090 if ((error != 0) || (count != 0)) { 1091 empty = 0; 1092 break; 1093 } 1094 /* 1095 * Now that the entire decsriptor is read we verify the 1096 * crc. 1097 */ 1098 if (ud_verify_tag_and_desc(&fid->fid_tag, 1099 UD_FILE_ID_DESC, 1100 tbno, 1101 1, rcount) != 0) { 1102 /* Corrupted directory */ 1103 empty = 0; 1104 break; 1105 } 1106 1107 /* 1108 * Is the file deleted 1109 */ 1110 1111 if ((fid->fid_flags & FID_DELETED) == 0) { 1112 if ((fid->fid_flags & FID_PARENT) == 0) { 1113 empty = 0; 1114 break; 1115 } 1116 } 1117 entry_len = FID_LEN(fid); 1118 } 1119 1120 kmem_free(addr, 1024); 1121 1122 return (empty); 1123 } 1124 1125 1126 int 1127 ud_dircheckpath(int32_t blkno, 1128 struct ud_inode *target, struct cred *cr) 1129 { 1130 int32_t err = 0; 1131 struct vfs *vfsp; 1132 struct udf_vfs *udf_vfsp; 1133 struct fbuf *fbp; 1134 struct file_id *fid; 1135 struct ud_inode *ip, *tip; 1136 uint16_t prn; 1137 uint32_t lbno, dummy, tbno; 1138 daddr_t parent_icb_loc; 1139 1140 ud_printf("ud_dircheckpath\n"); 1141 1142 udf_vfsp = target->i_udf; 1143 ip = target; 1144 1145 ASSERT(udf_vfsp != NULL); 1146 ASSERT(MUTEX_HELD(&target->i_udf->udf_rename_lck)); 1147 ASSERT(RW_WRITE_HELD(&ip->i_rwlock)); 1148 1149 if (ip->i_icb_lbano == blkno) { 1150 err = EINVAL; 1151 goto out; 1152 } 1153 if (ip->i_icb_lbano == udf_vfsp->udf_root_blkno) { 1154 goto out; 1155 } 1156 1157 /* 1158 * Search back through the directory tree, using the PARENT entries 1159 * Fail any attempt to move a directory into an ancestor directory. 1160 */ 1161 for (;;) { 1162 if ((err = fbread(ITOV(ip), 0, 1163 udf_vfsp->udf_lbsize, S_READ, &fbp)) != 0) { 1164 break; 1165 } 1166 1167 if ((err = ud_ip_off2bno(ip, 0, &tbno)) != 0) { 1168 break; 1169 } 1170 fid = (struct file_id *)fbp->fb_addr; 1171 /* IS this a valid file_identifier */ 1172 if (ud_verify_tag_and_desc(&fid->fid_tag, 1173 UD_FILE_ID_DESC, 1174 tbno, 1175 1, udf_vfsp->udf_lbsize) != 0) { 1176 break; 1177 } 1178 if ((fid->fid_flags & FID_DELETED) != 0) { 1179 break; 1180 } 1181 if ((fid->fid_flags & FID_PARENT) == 0) { 1182 /* 1183 * This cannot happen unless 1184 * something is grossly wrong 1185 * First entry has to be parent 1186 */ 1187 break; 1188 } 1189 prn = SWAP_16(fid->fid_icb.lad_ext_prn); 1190 lbno = SWAP_32(fid->fid_icb.lad_ext_loc); 1191 parent_icb_loc = ud_xlate_to_daddr(udf_vfsp, 1192 prn, lbno, 1, &dummy); 1193 ASSERT(dummy == 1); 1194 if (parent_icb_loc == blkno) { 1195 err = EINVAL; 1196 break; 1197 } 1198 vfsp = ip->i_vfs; 1199 udf_vfsp = ip->i_udf; 1200 if (parent_icb_loc == udf_vfsp->udf_root_blkno) { 1201 break; 1202 } 1203 if (fbp != NULL) { 1204 fbrelse(fbp, S_OTHER); 1205 fbp = NULL; 1206 } 1207 if (ip != target) { 1208 rw_exit(&ip->i_rwlock); 1209 VN_RELE(ITOV(ip)); 1210 } 1211 1212 /* 1213 * Race to get the inode. 1214 */ 1215 if (err = ud_iget(vfsp, prn, lbno, &tip, NULL, cr)) { 1216 ip = NULL; 1217 break; 1218 } 1219 ip = tip; 1220 rw_enter(&ip->i_rwlock, RW_READER); 1221 } 1222 if (fbp) { 1223 fbrelse(fbp, S_OTHER); 1224 } 1225 out: 1226 if (ip) { 1227 if (ip != target) { 1228 rw_exit(&ip->i_rwlock); 1229 VN_RELE(ITOV(ip)); 1230 } 1231 } 1232 return (err); 1233 } 1234 1235 int 1236 ud_dirmakeinode(struct ud_inode *tdp, struct ud_inode **ipp, 1237 struct vattr *vap, enum de_op op, struct cred *cr) 1238 { 1239 struct ud_inode *ip; 1240 int32_t error; 1241 1242 ASSERT(vap != NULL); 1243 ASSERT(op == DE_CREATE || op == DE_MKDIR); 1244 ASSERT((vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE)); 1245 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1246 1247 /* 1248 * Allocate a new inode. 1249 */ 1250 if ((error = ud_ialloc(tdp, &ip, vap, cr)) != 0) { 1251 return (error); 1252 } 1253 1254 ASSERT(ip != NULL); 1255 1256 rw_enter(&ip->i_contents, RW_WRITER); 1257 1258 if (op == DE_MKDIR) { 1259 error = ud_dirmakedirect(ip, tdp, cr); 1260 } 1261 1262 ip->i_flag |= IACC|IUPD|ICHG; 1263 /* 1264 * Clear IACC and/or IUPD if the caller specified the atime and/or 1265 * mtime fields. They were set from the passed in attributes in 1266 * ud_ialloc(). 1267 */ 1268 if (vap->va_mask & AT_ATIME) 1269 ip->i_flag &= ~IACC; 1270 if (vap->va_mask & AT_MTIME) 1271 ip->i_flag &= ~IUPD; 1272 /* 1273 * push inode before it's name appears in a directory 1274 */ 1275 ud_iupdat(ip, 1); 1276 *ipp = ip; 1277 rw_exit(&ip->i_contents); 1278 return (error); 1279 } 1280 1281 /* 1282 * Enter the file sip in the directory tdp with name namep. 1283 */ 1284 int 1285 ud_diraddentry(struct ud_inode *tdp, char *namep, 1286 enum de_op op, int32_t namelen, struct slot *slotp, 1287 struct ud_inode *sip, struct ud_inode *sdp, struct cred *cr) 1288 { 1289 struct udf_vfs *udf_vfsp; 1290 int32_t error, temp; 1291 struct file_id *fid; 1292 uint8_t *buf = NULL; 1293 1294 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1295 1296 ud_printf("ud_diraddentry\n"); 1297 1298 udf_vfsp = sip->i_udf; 1299 1300 /* 1301 * Check inode to be linked to see if it is in the 1302 * same filesystem. 1303 */ 1304 if (ITOV(tdp)->v_vfsp != ITOV(sip)->v_vfsp) { 1305 error = EXDEV; 1306 goto bad; 1307 } 1308 1309 if ((op == DE_RENAME) && (sip->i_type == VDIR)) { 1310 if ((error = ud_dirfixdotdot(sip, sdp, tdp)) != 0) { 1311 goto bad; 1312 } 1313 } 1314 1315 buf = (uint8_t *)kmem_zalloc(udf_vfsp->udf_lbsize, KM_SLEEP); 1316 1317 /* 1318 * Fill in entry data. 1319 */ 1320 fid = (struct file_id *)buf; 1321 fid->fid_ver = SWAP_16(1); 1322 if (sip->i_type == VDIR) { 1323 fid->fid_flags = FID_DIR; 1324 } else { 1325 fid->fid_flags = 0; 1326 } 1327 fid->fid_iulen = 0; 1328 1329 fid->fid_icb.lad_ext_len = SWAP_32(sip->i_udf->udf_lbsize); 1330 fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block); 1331 fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn); 1332 fid->fid_iulen = 0; 1333 1334 temp = udf_vfsp->udf_lbsize - F_LEN; 1335 if ((error = ud_compress(namelen, &temp, 1336 (uint8_t *)namep, fid->fid_spec)) == 0) { 1337 fid->fid_idlen = (uint8_t)temp; 1338 error = ud_dirprepareentry(tdp, slotp, buf, cr); 1339 } 1340 1341 kmem_free(buf, udf_vfsp->udf_lbsize); 1342 1343 bad: 1344 return (error); 1345 } 1346 1347 /* 1348 * Write a prototype directory into the empty inode ip, whose parent is dp. 1349 */ 1350 /* ARGSUSED2 */ 1351 int 1352 ud_dirmakedirect(struct ud_inode *ip, 1353 struct ud_inode *dp, struct cred *cr) 1354 { 1355 int32_t err; 1356 uint32_t blkno, size, parent_len, tbno; 1357 struct fbuf *fbp; 1358 struct file_id *fid; 1359 struct icb_ext *iext; 1360 1361 ud_printf("ud_dirmakedirect\n"); 1362 1363 ASSERT(RW_WRITE_HELD(&ip->i_contents)); 1364 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 1365 1366 parent_len = sizeof (struct file_id); 1367 1368 if ((ip->i_desc_type != ICB_FLAG_ONE_AD) || 1369 (parent_len > ip->i_max_emb)) { 1370 ASSERT(ip->i_ext); 1371 /* 1372 * Allocate space for the directory we're creating. 1373 */ 1374 if ((err = ud_alloc_space(ip->i_vfs, ip->i_icb_prn, 1375 0, 1, &blkno, &size, 0, 0)) != 0) { 1376 return (err); 1377 } 1378 /* 1379 * init with the size of 1380 * directory with just the 1381 * parent 1382 */ 1383 ip->i_size = sizeof (struct file_id); 1384 ip->i_flag |= IUPD|ICHG|IATTCHG; 1385 iext = ip->i_ext; 1386 iext->ib_prn = ip->i_icb_prn; 1387 iext->ib_block = blkno; 1388 iext->ib_count = ip->i_size; 1389 iext->ib_offset = 0; 1390 ip->i_ext_used = 1; 1391 } else { 1392 ip->i_size = sizeof (struct file_id); 1393 ip->i_flag |= IUPD|ICHG|IATTCHG; 1394 } 1395 1396 ITIMES_NOLOCK(ip); 1397 1398 /* 1399 * Update the dp link count and write out the change. 1400 * This reflects the ".." entry we'll soon write. 1401 */ 1402 if (dp->i_nlink == MAXLINK) { 1403 return (EMLINK); 1404 } 1405 dp->i_nlink++; 1406 dp->i_flag |= ICHG; 1407 ud_iupdat(dp, 1); 1408 1409 /* 1410 * Initialize directory with ".." 1411 * Since the parent directory is locked, we don't have to 1412 * worry about anything changing when we drop the write 1413 * lock on (ip). 1414 */ 1415 rw_exit(&ip->i_contents); 1416 if ((err = fbread(ITOV(ip), (offset_t)0, 1417 ip->i_udf->udf_lbsize, S_WRITE, &fbp)) != 0) { 1418 rw_enter(&ip->i_contents, RW_WRITER); 1419 return (err); 1420 } 1421 1422 bzero(fbp->fb_addr, ip->i_udf->udf_lbsize); 1423 1424 fid = (struct file_id *)fbp->fb_addr; 1425 fid->fid_ver = SWAP_16(1); 1426 fid->fid_flags = FID_DIR | FID_PARENT; 1427 fid->fid_icb.lad_ext_len = SWAP_32(dp->i_udf->udf_lbsize); 1428 fid->fid_icb.lad_ext_loc = SWAP_32(dp->i_icb_block); 1429 fid->fid_icb.lad_ext_prn = SWAP_16(dp->i_icb_prn); 1430 1431 /* 1432 * fid_idlen, fid_iulen and fid_spec are zero 1433 * due to bzero above 1434 */ 1435 1436 if ((err = ud_ip_off2bno(ip, 0, &tbno)) == 0) { 1437 ud_make_tag(ip->i_udf, &fid->fid_tag, 1438 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1439 } 1440 1441 err = ud_fbwrite(fbp, ip); 1442 rw_enter(&ip->i_contents, RW_WRITER); 1443 1444 return (err); 1445 } 1446 1447 int 1448 ud_dirrename(struct ud_inode *sdp, struct ud_inode *sip, 1449 struct ud_inode *tdp, struct ud_inode *tip, char *namep, 1450 uint8_t *buf, struct slot *slotp, struct cred *cr) 1451 { 1452 int32_t error = 0, doingdirectory; 1453 struct file_id *fid; 1454 1455 ud_printf("ud_dirrename\n"); 1456 ASSERT(sdp->i_udf != NULL); 1457 ASSERT(MUTEX_HELD(&sdp->i_udf->udf_rename_lck)); 1458 ASSERT(RW_WRITE_HELD(&tdp->i_rwlock)); 1459 ASSERT(buf); 1460 ASSERT(slotp->ep); 1461 1462 fid = slotp->ep; 1463 1464 /* 1465 * Short circuit rename of something to itself. 1466 */ 1467 if (sip->i_icb_lbano == tip->i_icb_lbano) { 1468 return (ESAME); /* special KLUDGE error code */ 1469 } 1470 /* 1471 * Everything is protected under the vfs_rename_lock so the ordering 1472 * of i_contents locks doesn't matter here. 1473 */ 1474 rw_enter(&sip->i_contents, RW_READER); 1475 rw_enter(&tip->i_contents, RW_READER); 1476 1477 /* 1478 * Check that everything is on the same filesystem. 1479 */ 1480 if ((ITOV(tip)->v_vfsp != ITOV(tdp)->v_vfsp) || 1481 (ITOV(tip)->v_vfsp != ITOV(sip)->v_vfsp)) { 1482 error = EXDEV; /* XXX archaic */ 1483 goto out; 1484 } 1485 1486 /* 1487 * Must have write permission to rewrite target entry. 1488 */ 1489 if ((error = ud_iaccess(tdp, IWRITE, cr)) != 0 || 1490 (error = ud_sticky_remove_access(tdp, tip, cr)) != 0) 1491 goto out; 1492 1493 /* 1494 * Ensure source and target are compatible (both directories 1495 * or both not directories). If target is a directory it must 1496 * be empty and have no links to it; in addition it must not 1497 * be a mount point, and both the source and target must be 1498 * writable. 1499 */ 1500 doingdirectory = (sip->i_type == VDIR); 1501 if (tip->i_type == VDIR) { 1502 if (!doingdirectory) { 1503 error = EISDIR; 1504 goto out; 1505 } 1506 /* 1507 * vn_vfswlock will prevent mounts from using the directory 1508 * until we are done. 1509 */ 1510 if (vn_vfswlock(ITOV(tip))) { 1511 error = EBUSY; 1512 goto out; 1513 } 1514 if (vn_mountedvfs(ITOV(tip)) != NULL) { 1515 vn_vfsunlock(ITOV(tip)); 1516 error = EBUSY; 1517 goto out; 1518 } 1519 if (!ud_dirempty(tip, tdp->i_uniqid, cr) || tip->i_nlink > 2) { 1520 vn_vfsunlock(ITOV(tip)); 1521 error = EEXIST; /* SIGH should be ENOTEMPTY */ 1522 goto out; 1523 } 1524 } else if (doingdirectory) { 1525 error = ENOTDIR; 1526 goto out; 1527 } 1528 1529 /* 1530 * Rewrite the inode pointer for target name entry 1531 * from the target inode (ip) to the source inode (sip). 1532 * This prevents the target entry from disappearing 1533 * during a crash. Mark the directory inode to reflect the changes. 1534 */ 1535 dnlc_remove(ITOV(tdp), namep); 1536 fid->fid_icb.lad_ext_prn = SWAP_16(sip->i_icb_prn); 1537 fid->fid_icb.lad_ext_loc = SWAP_32(sip->i_icb_block); 1538 dnlc_enter(ITOV(tdp), namep, ITOV(sip)); 1539 1540 ud_make_tag(tdp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC, 1541 SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid)); 1542 1543 error = ud_write_fid(tdp, slotp, buf); 1544 1545 if (error) { 1546 if (doingdirectory) { 1547 vn_vfsunlock(ITOV(tip)); 1548 } 1549 goto out; 1550 } 1551 1552 /* 1553 * Upgrade to write lock on tip 1554 */ 1555 rw_exit(&tip->i_contents); 1556 rw_enter(&tip->i_contents, RW_WRITER); 1557 1558 mutex_enter(&tdp->i_tlock); 1559 tdp->i_flag |= IUPD|ICHG; 1560 mutex_exit(&tdp->i_tlock); 1561 /* 1562 * Decrement the link count of the target inode. 1563 * Fix the ".." entry in sip to point to dp. 1564 * This is done after the new entry is on the disk. 1565 */ 1566 tip->i_nlink--; 1567 mutex_enter(&tip->i_tlock); 1568 tip->i_flag |= ICHG; 1569 mutex_exit(&tip->i_tlock); 1570 1571 if (doingdirectory) { 1572 /* 1573 * The entry for tip no longer exists so I can unlock the 1574 * vfslock. 1575 */ 1576 vn_vfsunlock(ITOV(tip)); 1577 /* 1578 * Decrement target link count once more if it was a directory. 1579 */ 1580 if (tip->i_nlink != 0) { 1581 cmn_err(CE_WARN, 1582 "ud_direnter: target directory link count != 0"); 1583 rw_exit(&tip->i_contents); 1584 rw_exit(&sip->i_contents); 1585 return (EINVAL); 1586 } 1587 /* 1588 * Renaming a directory with the parent different 1589 * requires that ".." be rewritten. The window is 1590 * still there for ".." to be inconsistent, but this 1591 * is unavoidable, and a lot shorter than when it was 1592 * done in a user process. We decrement the link 1593 * count in the new parent as appropriate to reflect 1594 * the just-removed target. If the parent is the 1595 * same, this is appropriate since the original 1596 * directory is going away. If the new parent is 1597 * different, dirfixdotdot() will bump the link count 1598 * back. 1599 */ 1600 tdp->i_nlink--; 1601 mutex_enter(&tdp->i_tlock); 1602 tdp->i_flag |= ICHG; 1603 mutex_exit(&tdp->i_tlock); 1604 ITIMES_NOLOCK(tdp); 1605 if (sdp != tdp) { 1606 rw_exit(&tip->i_contents); 1607 rw_exit(&sip->i_contents); 1608 error = ud_dirfixdotdot(sip, sdp, tdp); 1609 return (error); 1610 } 1611 } 1612 1613 out: 1614 rw_exit(&tip->i_contents); 1615 rw_exit(&sip->i_contents); 1616 return (error); 1617 } 1618 1619 1620 /* 1621 * 1. When we find a slot that belonged to a file which was deleted 1622 * and is in the middle of the directory 1623 * 2. There is not empty slot available. The new entry 1624 * will be at the end of the directory and fits in the same block. 1625 * 3. There is no empty slot available. The new 1626 * entry will not fit the left over directory 1627 * so we need to allocate a new block. If 1628 * we cannot allocate a proximity block we need 1629 * to allocate a new icb, and data block. 1630 */ 1631 int 1632 ud_dirprepareentry(struct ud_inode *dp, 1633 struct slot *slotp, uint8_t *buf, struct cred *cr) 1634 { 1635 struct fbuf *fbp; 1636 uint16_t old_dtype; 1637 int32_t error = 0; 1638 uint32_t entrysize, count, offset, tbno, old_size, off; 1639 struct file_id *fid; 1640 int32_t lbsize, lbmask, mask; 1641 1642 ASSERT(RW_WRITE_HELD(&dp->i_rwlock)); 1643 1644 ASSERT((slotp->status == NONE) || 1645 (slotp->status == FOUND)); 1646 1647 ud_printf("ud_dirprepareentry\n"); 1648 lbsize = dp->i_udf->udf_lbsize; 1649 lbmask = dp->i_udf->udf_lbmask; 1650 mask = ~lbmask; 1651 1652 fid = (struct file_id *)buf; 1653 entrysize = FID_LEN(fid); 1654 1655 /* 1656 * If we didn't find a slot, then indicate that the 1657 * new slot belongs at the end of the directory. 1658 * If we found a slot, then the new entry can be 1659 * put at slotp->offset. 1660 */ 1661 if (slotp->status == NONE) { 1662 /* 1663 * We did not find a slot, the next 1664 * entry will be in the end of the directory 1665 * see if we can fit the new entry inside 1666 * the old block. If not allocate a new block. 1667 */ 1668 if (entrysize > slotp->size) { 1669 /* 1670 * extend the directory 1671 * size by one new block 1672 */ 1673 old_dtype = dp->i_desc_type; 1674 old_size = (uint32_t)dp->i_size; 1675 error = ud_bmap_write(dp, slotp->offset, 1676 blkoff(dp->i_udf, slotp->offset) + entrysize, 1677 0, cr); 1678 if (error != 0) { 1679 return (error); 1680 } 1681 if (old_dtype != dp->i_desc_type) { 1682 /* 1683 * oops we changed the astrat 1684 * of the file, we have to 1685 * recaliculate tags 1686 * fortunately we donot have more 1687 * than one lbsize to handle here 1688 */ 1689 if ((error = ud_ip_off2bno(dp, 1690 0, &tbno)) != 0) { 1691 return (error); 1692 } 1693 if ((error = fbread(ITOV(dp), 0, 1694 dp->i_udf->udf_lbsize, 1695 S_WRITE, &fbp)) != 0) { 1696 return (error); 1697 } 1698 off = 0; 1699 while (off < old_size) { 1700 struct file_id *tfid; 1701 1702 tfid = (struct file_id *) 1703 (fbp->fb_addr + off); 1704 1705 ud_make_tag(dp->i_udf, &tfid->fid_tag, 1706 UD_FILE_ID_DESC, tbno, FID_LEN(tfid)); 1707 1708 off += FID_LEN(tfid); 1709 } 1710 if (error = ud_fbwrite(fbp, dp)) { 1711 return (error); 1712 } 1713 } 1714 } else { 1715 /* Extend the directory size */ 1716 if (dp->i_desc_type != ICB_FLAG_ONE_AD) { 1717 ASSERT(dp->i_ext); 1718 dp->i_ext[dp->i_ext_used - 1].ib_count += 1719 entrysize; 1720 } 1721 } 1722 dp->i_size += entrysize; 1723 dp->i_flag |= IUPD|ICHG|IATTCHG; 1724 ITIMES_NOLOCK(dp); 1725 } else if (slotp->status != FOUND) { 1726 cmn_err(CE_WARN, "status is not NONE/FOUND"); 1727 return (EINVAL); 1728 } 1729 1730 if ((error = ud_ip_off2bno(dp, slotp->offset, &tbno)) != 0) { 1731 return (error); 1732 } 1733 ud_make_tag(dp->i_udf, &fid->fid_tag, 1734 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1735 1736 /* 1737 * fbread cannot cross a 1738 * MAXBSIZE boundary so handle it here 1739 */ 1740 offset = slotp->offset; 1741 if ((error = fbread(ITOV(dp), offset & mask, lbsize, 1742 S_WRITE, &fbp)) != 0) { 1743 return (error); 1744 } 1745 if ((offset & mask) != ((offset + entrysize) & mask)) { 1746 count = entrysize - ((offset + entrysize) & lbmask); 1747 } else { 1748 count = entrysize; 1749 } 1750 bcopy((caddr_t)buf, fbp->fb_addr + (offset & lbmask), count); 1751 1752 if (error = ud_fbwrite(fbp, dp)) { 1753 return (error); 1754 } 1755 1756 if (entrysize > count) { 1757 if ((error = fbread(ITOV(dp), (offset + entrysize) & mask, 1758 lbsize, S_WRITE, &fbp)) != 0) { 1759 return (error); 1760 } 1761 bcopy((caddr_t)(buf + count), fbp->fb_addr, entrysize - count); 1762 if (error = ud_fbwrite(fbp, dp)) { 1763 return (error); 1764 } 1765 } 1766 1767 dp->i_flag |= IUPD|ICHG|IATTCHG; 1768 ITIMES_NOLOCK(dp); 1769 return (error); 1770 } 1771 1772 1773 /* 1774 * Fix the FID_PARENT entry of the child directory so that it points 1775 * to the new parent directory instead of the old one. Routine 1776 * assumes that dp is a directory and that all the inodes are on 1777 * the same file system. 1778 */ 1779 int 1780 ud_dirfixdotdot(struct ud_inode *dp, 1781 struct ud_inode *opdp, struct ud_inode *npdp) 1782 { 1783 int32_t err = 0; 1784 struct fbuf *fbp; 1785 struct file_id *fid; 1786 uint32_t loc, dummy, tbno; 1787 1788 ud_printf("ud_dirfixdotdot\n"); 1789 1790 ASSERT(opdp->i_type == VDIR); 1791 ASSERT(npdp->i_type == VDIR); 1792 1793 ASSERT(RW_WRITE_HELD(&npdp->i_rwlock)); 1794 1795 err = fbread(ITOV(dp), (offset_t)0, 1796 dp->i_udf->udf_lbsize, S_WRITE, &fbp); 1797 1798 if (err || dp->i_nlink == 0 || 1799 dp->i_size < sizeof (struct file_id)) { 1800 goto bad; 1801 } 1802 1803 if ((err = ud_ip_off2bno(dp, 0, &tbno)) != 0) { 1804 goto bad; 1805 } 1806 1807 fid = (struct file_id *)fbp->fb_addr; 1808 if ((ud_verify_tag_and_desc(&fid->fid_tag, UD_FILE_ID_DESC, 1809 tbno, 1810 1, dp->i_udf->udf_lbsize) != 0) || 1811 ((fid->fid_flags & (FID_DIR | FID_PARENT)) != 1812 (FID_DIR | FID_PARENT))) { 1813 err = ENOTDIR; 1814 goto bad; 1815 } 1816 1817 loc = ud_xlate_to_daddr(dp->i_udf, 1818 SWAP_16(fid->fid_icb.lad_ext_prn), 1819 SWAP_32(fid->fid_icb.lad_ext_loc), 1, &dummy); 1820 ASSERT(dummy == 1); 1821 if (loc == npdp->i_icb_lbano) { 1822 goto bad; 1823 } 1824 1825 /* 1826 * Increment the link count in the new parent inode and force it out. 1827 */ 1828 if (npdp->i_nlink == MAXLINK) { 1829 err = EMLINK; 1830 goto bad; 1831 } 1832 1833 npdp->i_nlink++; 1834 mutex_enter(&npdp->i_tlock); 1835 npdp->i_flag |= ICHG; 1836 mutex_exit(&npdp->i_tlock); 1837 ud_iupdat(npdp, 1); 1838 1839 /* 1840 * Rewrite the child FID_PARENT entry and force it out. 1841 */ 1842 dnlc_remove(ITOV(dp), ".."); 1843 fid->fid_icb.lad_ext_loc = SWAP_32(npdp->i_icb_block); 1844 fid->fid_icb.lad_ext_prn = SWAP_16(npdp->i_icb_prn); 1845 ud_make_tag(npdp->i_udf, &fid->fid_tag, 1846 UD_FILE_ID_DESC, tbno, FID_LEN(fid)); 1847 dnlc_enter(ITOV(dp), "..", ITOV(npdp)); 1848 1849 err = ud_fbwrite(fbp, dp); 1850 fbp = NULL; 1851 if (err != 0) { 1852 goto bad; 1853 } 1854 1855 /* 1856 * Decrement the link count of the old parent inode and force 1857 * it out. If opdp is NULL, then this is a new directory link; 1858 * it has no parent, so we need not do anything. 1859 */ 1860 if (opdp != NULL) { 1861 rw_enter(&opdp->i_contents, RW_WRITER); 1862 if (opdp->i_nlink != 0) { 1863 opdp->i_nlink--; 1864 mutex_enter(&opdp->i_tlock); 1865 opdp->i_flag |= ICHG; 1866 mutex_exit(&opdp->i_tlock); 1867 ud_iupdat(opdp, 1); 1868 } 1869 rw_exit(&opdp->i_contents); 1870 } 1871 return (0); 1872 1873 bad: 1874 if (fbp) { 1875 fbrelse(fbp, S_OTHER); 1876 } 1877 return (err); 1878 } 1879 1880 int32_t 1881 ud_write_fid(struct ud_inode *dp, struct slot *slot, uint8_t *buf) 1882 { 1883 struct udf_vfs *udf_vfsp; 1884 struct fbuf *lfbp; 1885 struct file_id *fid; 1886 int32_t error = 0; 1887 uint32_t lbsize, lbmask, count, old_count; 1888 1889 1890 ASSERT(slot->fbp); 1891 ASSERT(slot->ep); 1892 1893 udf_vfsp = dp->i_udf; 1894 fid = slot->ep; 1895 lbsize = dp->i_udf->udf_lbsize; 1896 lbmask = dp->i_udf->udf_lbmask; 1897 1898 if (((uint8_t *)fid >= buf) && 1899 ((uint8_t *)fid < &buf[udf_vfsp->udf_lbsize])) { 1900 1901 1902 if ((error = fbread(ITOV(dp), 1903 (offset_t)(slot->offset & ~lbmask), 1904 lbsize, S_WRITE, &lfbp)) != 0) { 1905 goto out; 1906 } 1907 1908 1909 /* 1910 * We do not need to write the 1911 * file name. So check if the entry 1912 * does not cross a block boundary 1913 * and write only required portions 1914 */ 1915 if (((slot->offset & lbmask) + 1916 sizeof (struct file_id)) > lbsize) { 1917 1918 if ((slot->offset & lbmask) != 0) { 1919 old_count = lbsize - 1920 (slot->offset & lbmask); 1921 count = (slot->offset + 1922 sizeof (struct file_id)) & 1923 lbmask; 1924 } else { 1925 old_count = 0; 1926 count = sizeof (struct file_id); 1927 } 1928 1929 bcopy(buf, lfbp->fb_addr + 1930 (slot->offset & lbmask), old_count); 1931 bcopy(buf + old_count, 1932 slot->fbp->fb_addr, count); 1933 1934 error = ud_fbwrite(lfbp, dp); 1935 1936 error = ud_fbwrite(slot->fbp, dp); 1937 } else { 1938 bcopy(buf, lfbp->fb_addr + 1939 (slot->offset & lbmask), 1940 sizeof (struct file_id)); 1941 1942 error = ud_fbwrite(lfbp, dp); 1943 1944 fbrelse(slot->fbp, S_OTHER); 1945 } 1946 } else { 1947 if ((error = ud_fbwrite(slot->fbp, dp)) != 0) { 1948 fid->fid_flags &= ~FID_DELETED; 1949 ud_make_tag(dp->i_udf, &fid->fid_tag, UD_FILE_ID_DESC, 1950 SWAP_32(fid->fid_tag.tag_loc), FID_LEN(fid)); 1951 } 1952 } 1953 slot->fbp = NULL; 1954 1955 out: 1956 return (error); 1957 } 1958