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