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