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) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * Directory operations for High Sierra filesystem 27 */ 28 29 #include <sys/types.h> 30 #include <sys/t_lock.h> 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/cred.h> 34 #include <sys/user.h> 35 #include <sys/vfs.h> 36 #include <sys/stat.h> 37 #include <sys/vnode.h> 38 #include <sys/mode.h> 39 #include <sys/dnlc.h> 40 #include <sys/cmn_err.h> 41 #include <sys/fbuf.h> 42 #include <sys/kmem.h> 43 #include <sys/policy.h> 44 #include <sys/sunddi.h> 45 #include <vm/hat.h> 46 #include <vm/as.h> 47 #include <vm/pvn.h> 48 #include <vm/seg.h> 49 #include <vm/seg_map.h> 50 #include <vm/seg_kmem.h> 51 #include <vm/page.h> 52 53 #include <sys/fs/hsfs_spec.h> 54 #include <sys/fs/hsfs_isospec.h> 55 #include <sys/fs/hsfs_node.h> 56 #include <sys/fs/hsfs_impl.h> 57 #include <sys/fs/hsfs_susp.h> 58 #include <sys/fs/hsfs_rrip.h> 59 60 #include <sys/sysinfo.h> 61 #include <sys/sysmacros.h> 62 #include <sys/errno.h> 63 #include <sys/debug.h> 64 #include <fs/fs_subr.h> 65 66 /* 67 * This macro expects a name that ends in '.' and returns TRUE if the 68 * name is not "." or ".." 69 */ 70 #define CAN_TRUNCATE_DOT(name, namelen) \ 71 (namelen > 1 && (namelen > 2 || name[0] != '.')) 72 73 enum dirblock_result { FOUND_ENTRY, WENT_PAST, HIT_END }; 74 75 /* 76 * These values determine whether we will try to read a file or dir; 77 * they may be patched via /etc/system to allow users to read 78 * record-oriented files. 79 */ 80 int ide_prohibited = IDE_PROHIBITED; 81 int hde_prohibited = HDE_PROHIBITED; 82 83 /* 84 * This variable determines if the HSFS code will use the 85 * directory name lookup cache. The default is for the cache to be used. 86 */ 87 static int hsfs_use_dnlc = 1; 88 89 /* 90 * This variable determines whether strict ISO-9660 directory ordering 91 * is to be assumed. If false (which it is by default), then when 92 * searching a directory of an ISO-9660 disk, we do not expect the 93 * entries to be sorted (as the spec requires), and so cannot terminate 94 * the search early. Unfortunately, some vendors are producing 95 * non-compliant disks. This variable exists to revert to the old 96 * behavior in case someone relies on this. This option is expected to be 97 * removed at some point in the future. 98 * 99 * Use "set hsfs:strict_iso9660_ordering = 1" in /etc/system to override. 100 */ 101 static int strict_iso9660_ordering = 0; 102 103 /* 104 * This tunable allows us to ignore inode numbers from rrip-1.12. 105 * In this case, we fall back to our default inode algorithm. 106 */ 107 int use_rrip_inodes = 1; 108 109 static void hs_hsnode_cache_reclaim(void *unused); 110 static void hs_addfreeb(struct hsfs *fsp, struct hsnode *hp); 111 static enum dirblock_result process_dirblock(struct fbuf *fbp, uint_t *offset, 112 uint_t last_offset, char *nm, int nmlen, struct hsfs *fsp, 113 struct hsnode *dhp, struct vnode *dvp, struct vnode **vpp, 114 int *error); 115 static int strip_trailing(struct hsfs *fsp, char *nm, int len); 116 static int hs_namelen(struct hsfs *fsp, char *nm, int len); 117 static int uppercase_cp(char *from, char *to, int size); 118 static void hs_log_bogus_joliet_warning(void); 119 static int hs_iso_copy(char *from, char *to, int size); 120 static int32_t hs_ucs2_2_utf8(uint16_t c_16, uint8_t *s_8); 121 static int hs_utf8_trunc(uint8_t *str, int len); 122 123 /* 124 * hs_access 125 * Return 0 if the desired access may be granted. 126 * Otherwise return error code. 127 */ 128 int 129 hs_access(struct vnode *vp, mode_t m, struct cred *cred) 130 { 131 struct hsnode *hp; 132 int shift = 0; 133 134 /* 135 * Write access cannot be granted for a read-only medium 136 */ 137 if ((m & VWRITE) && !IS_DEVVP(vp)) 138 return (EROFS); 139 140 hp = VTOH(vp); 141 142 /* 143 * XXX - For now, use volume protections. 144 * Also, always grant EXEC access for directories 145 * if READ access is granted. 146 */ 147 if ((vp->v_type == VDIR) && (m & VEXEC)) { 148 m &= ~VEXEC; 149 m |= VREAD; 150 } 151 152 if (crgetuid(cred) != hp->hs_dirent.uid) { 153 shift += 3; 154 if (!groupmember((uid_t)hp->hs_dirent.gid, cred)) 155 shift += 3; 156 } 157 return (secpolicy_vnode_access2(cred, vp, hp->hs_dirent.uid, 158 hp->hs_dirent.mode << shift, m)); 159 } 160 161 #if ((HS_HASHSIZE & (HS_HASHSIZE - 1)) == 0) 162 #define HS_HASH(l) ((uint_t)(l) & (HS_HASHSIZE - 1)) 163 #else 164 #define HS_HASH(l) ((uint_t)(l) % HS_HASHSIZE) 165 #endif 166 #define HS_HPASH(hp) HS_HASH((hp)->hs_nodeid) 167 168 /* 169 * The tunable nhsnode is now a threshold for a dynamically allocated 170 * pool of hsnodes, not the size of a statically allocated table. 171 * When the number of hsnodes for a particular file system exceeds 172 * nhsnode, the allocate and free logic will try to reduce the number 173 * of allocated nodes by returning unreferenced nodes to the kmem_cache 174 * instead of putting them on the file system's private free list. 175 */ 176 int nhsnode = HS_HSNODESPACE / sizeof (struct hsnode); 177 178 struct kmem_cache *hsnode_cache; /* free hsnode cache */ 179 180 /* 181 * Initialize the cache of free hsnodes. 182 */ 183 void 184 hs_init_hsnode_cache(void) 185 { 186 /* 187 * A kmem_cache is used for the hsnodes 188 * No constructor because hsnodes are initialised by bzeroing. 189 */ 190 hsnode_cache = kmem_cache_create("hsfs_hsnode_cache", 191 sizeof (struct hsnode), 0, NULL, 192 NULL, hs_hsnode_cache_reclaim, NULL, NULL, 0); 193 } 194 195 /* 196 * Destroy the cache of free hsnodes. 197 */ 198 void 199 hs_fini_hsnode_cache(void) 200 { 201 kmem_cache_destroy(hsnode_cache); 202 } 203 204 /* 205 * System is short on memory, free up as much as possible 206 */ 207 /*ARGSUSED*/ 208 static void 209 hs_hsnode_cache_reclaim(void *unused) 210 { 211 struct hsfs *fsp; 212 struct hsnode *hp; 213 214 /* 215 * For each vfs in the hs_mounttab list 216 */ 217 mutex_enter(&hs_mounttab_lock); 218 for (fsp = hs_mounttab; fsp != NULL; fsp = fsp->hsfs_next) { 219 /* 220 * Purge the dnlc of all hsfs entries 221 */ 222 (void) dnlc_purge_vfsp(fsp->hsfs_vfs, 0); 223 224 /* 225 * For each entry in the free chain 226 */ 227 rw_enter(&fsp->hsfs_hash_lock, RW_WRITER); 228 mutex_enter(&fsp->hsfs_free_lock); 229 for (hp = fsp->hsfs_free_f; hp != NULL; hp = fsp->hsfs_free_f) { 230 /* 231 * Remove from chain 232 */ 233 fsp->hsfs_free_f = hp->hs_freef; 234 if (fsp->hsfs_free_f != NULL) { 235 fsp->hsfs_free_f->hs_freeb = NULL; 236 } else { 237 fsp->hsfs_free_b = NULL; 238 } 239 /* 240 * Free the node. Force it to be fully freed 241 * by setting the 3rd arg (nopage) to 1. 242 */ 243 hs_freenode(HTOV(hp), fsp, 1); 244 } 245 mutex_exit(&fsp->hsfs_free_lock); 246 rw_exit(&fsp->hsfs_hash_lock); 247 } 248 mutex_exit(&hs_mounttab_lock); 249 } 250 251 /* 252 * Add an hsnode to the end of the free list. 253 */ 254 static void 255 hs_addfreeb(struct hsfs *fsp, struct hsnode *hp) 256 { 257 struct hsnode *ep; 258 259 vn_invalid(HTOV(hp)); 260 mutex_enter(&fsp->hsfs_free_lock); 261 ep = fsp->hsfs_free_b; 262 fsp->hsfs_free_b = hp; /* hp is the last entry in free list */ 263 hp->hs_freef = NULL; 264 hp->hs_freeb = ep; /* point at previous last entry */ 265 if (ep == NULL) 266 fsp->hsfs_free_f = hp; /* hp is only entry in free list */ 267 else 268 ep->hs_freef = hp; /* point previous last entry at hp */ 269 270 mutex_exit(&fsp->hsfs_free_lock); 271 } 272 273 /* 274 * Get an hsnode from the front of the free list. 275 * Must be called with write hsfs_hash_lock held. 276 */ 277 static struct hsnode * 278 hs_getfree(struct hsfs *fsp) 279 { 280 struct hsnode *hp, **tp; 281 282 ASSERT(RW_WRITE_HELD(&fsp->hsfs_hash_lock)); 283 284 /* 285 * If the number of currently-allocated hsnodes is less than 286 * the hsnode count threshold (nhsnode), or if there are no 287 * nodes on the file system's local free list (which acts as a 288 * cache), call kmem_cache_alloc to get a new hsnode from 289 * kernel memory. 290 */ 291 mutex_enter(&fsp->hsfs_free_lock); 292 if ((fsp->hsfs_nohsnode < nhsnode) || (fsp->hsfs_free_f == NULL)) { 293 mutex_exit(&fsp->hsfs_free_lock); 294 hp = kmem_cache_alloc(hsnode_cache, KM_SLEEP); 295 fsp->hsfs_nohsnode++; 296 bzero((caddr_t)hp, sizeof (*hp)); 297 hp->hs_vnode = vn_alloc(KM_SLEEP); 298 return (hp); 299 } 300 hp = fsp->hsfs_free_f; 301 /* hp cannot be NULL, since we already checked this above */ 302 fsp->hsfs_free_f = hp->hs_freef; 303 if (fsp->hsfs_free_f != NULL) 304 fsp->hsfs_free_f->hs_freeb = NULL; 305 else 306 fsp->hsfs_free_b = NULL; 307 mutex_exit(&fsp->hsfs_free_lock); 308 309 for (tp = &fsp->hsfs_hash[HS_HPASH(hp)]; *tp != NULL; 310 tp = &(*tp)->hs_hash) { 311 if (*tp == hp) { 312 struct vnode *vp; 313 314 vp = HTOV(hp); 315 316 /* 317 * file is no longer referenced, destroy all old pages 318 */ 319 if (vn_has_cached_data(vp)) 320 /* 321 * pvn_vplist_dirty will abort all old pages 322 */ 323 (void) pvn_vplist_dirty(vp, (u_offset_t)0, 324 hsfs_putapage, B_INVAL, 325 (struct cred *)NULL); 326 *tp = hp->hs_hash; 327 break; 328 } 329 } 330 if (hp->hs_dirent.sym_link != (char *)NULL) { 331 kmem_free(hp->hs_dirent.sym_link, 332 (size_t)(hp->hs_dirent.ext_size + 1)); 333 } 334 335 mutex_destroy(&hp->hs_contents_lock); 336 { 337 vnode_t *vp; 338 339 vp = hp->hs_vnode; 340 bzero((caddr_t)hp, sizeof (*hp)); 341 hp->hs_vnode = vp; 342 vn_reinit(vp); 343 } 344 return (hp); 345 } 346 347 /* 348 * Remove an hsnode from the free list. 349 */ 350 static void 351 hs_remfree(struct hsfs *fsp, struct hsnode *hp) 352 { 353 mutex_enter(&fsp->hsfs_free_lock); 354 if (hp->hs_freef != NULL) 355 hp->hs_freef->hs_freeb = hp->hs_freeb; 356 else 357 fsp->hsfs_free_b = hp->hs_freeb; 358 if (hp->hs_freeb != NULL) 359 hp->hs_freeb->hs_freef = hp->hs_freef; 360 else 361 fsp->hsfs_free_f = hp->hs_freef; 362 mutex_exit(&fsp->hsfs_free_lock); 363 } 364 365 /* 366 * Look for hsnode in hash list. 367 * If the inode number is != HS_DUMMY_INO (16), then only the inode 368 * number is used for the check. 369 * If the inode number is == HS_DUMMY_INO, we additionally always 370 * check the directory offset for the file to avoid caching the 371 * meta data for all zero sized to the first zero sized file that 372 * was touched. 373 * 374 * If found, reactivate it if inactive. 375 * 376 * Must be entered with hsfs_hash_lock held. 377 */ 378 struct vnode * 379 hs_findhash(ino64_t nodeid, uint_t lbn, uint_t off, struct vfs *vfsp) 380 { 381 struct hsnode *tp; 382 struct hsfs *fsp; 383 384 fsp = VFS_TO_HSFS(vfsp); 385 386 ASSERT(RW_LOCK_HELD(&fsp->hsfs_hash_lock)); 387 388 for (tp = fsp->hsfs_hash[HS_HASH(nodeid)]; tp != NULL; 389 tp = tp->hs_hash) { 390 if (tp->hs_nodeid == nodeid) { 391 struct vnode *vp; 392 393 if (nodeid == HS_DUMMY_INO) { 394 /* 395 * If this is the dummy inode number, look for 396 * matching dir_lbn and dir_off. 397 */ 398 for (; tp != NULL; tp = tp->hs_hash) { 399 if (tp->hs_nodeid == nodeid && 400 tp->hs_dir_lbn == lbn && 401 tp->hs_dir_off == off) 402 break; 403 } 404 if (tp == NULL) 405 return (NULL); 406 } 407 408 mutex_enter(&tp->hs_contents_lock); 409 vp = HTOV(tp); 410 VN_HOLD(vp); 411 if ((tp->hs_flags & HREF) == 0) { 412 tp->hs_flags |= HREF; 413 /* 414 * reactivating a free hsnode: 415 * remove from free list 416 */ 417 hs_remfree(fsp, tp); 418 } 419 mutex_exit(&tp->hs_contents_lock); 420 return (vp); 421 } 422 } 423 return (NULL); 424 } 425 426 static void 427 hs_addhash(struct hsfs *fsp, struct hsnode *hp) 428 { 429 ulong_t hashno; 430 431 ASSERT(RW_WRITE_HELD(&fsp->hsfs_hash_lock)); 432 433 hashno = HS_HPASH(hp); 434 hp->hs_hash = fsp->hsfs_hash[hashno]; 435 fsp->hsfs_hash[hashno] = hp; 436 } 437 438 /* 439 * Destroy all old pages and free the hsnodes 440 * Return 1 if busy (a hsnode is still referenced). 441 */ 442 int 443 hs_synchash(struct vfs *vfsp) 444 { 445 struct hsfs *fsp; 446 int i; 447 struct hsnode *hp, *nhp; 448 int busy = 0; 449 struct vnode *vp, *rvp; 450 451 fsp = VFS_TO_HSFS(vfsp); 452 rvp = fsp->hsfs_rootvp; 453 /* make sure no one can come in */ 454 rw_enter(&fsp->hsfs_hash_lock, RW_WRITER); 455 for (i = 0; i < HS_HASHSIZE; i++) { 456 for (hp = fsp->hsfs_hash[i]; hp != NULL; hp = hp->hs_hash) { 457 vp = HTOV(hp); 458 if ((hp->hs_flags & HREF) && (vp != rvp || 459 (vp == rvp && vp->v_count > 1))) { 460 busy = 1; 461 continue; 462 } 463 if (vn_has_cached_data(vp)) 464 (void) pvn_vplist_dirty(vp, (u_offset_t)0, 465 hsfs_putapage, B_INVAL, 466 (struct cred *)NULL); 467 } 468 } 469 if (busy) { 470 rw_exit(&fsp->hsfs_hash_lock); 471 return (1); 472 } 473 474 /* now free the hsnodes */ 475 for (i = 0; i < HS_HASHSIZE; i++) { 476 for (hp = fsp->hsfs_hash[i]; hp != NULL; hp = nhp) { 477 nhp = hp->hs_hash; 478 /* 479 * We know there are no pages associated with 480 * all the hsnodes (they've all been released 481 * above). So remove from free list and 482 * free the entry with nopage set. 483 */ 484 vp = HTOV(hp); 485 if (vp != rvp) { 486 hs_remfree(fsp, hp); 487 hs_freenode(vp, fsp, 1); 488 } 489 } 490 } 491 492 ASSERT(fsp->hsfs_nohsnode == 1); 493 rw_exit(&fsp->hsfs_hash_lock); 494 /* release the root hsnode, this should free the final hsnode */ 495 VN_RELE(rvp); 496 497 return (0); 498 } 499 500 /* 501 * hs_makenode 502 * 503 * Construct an hsnode. 504 * Caller specifies the directory entry, the block number and offset 505 * of the directory entry, and the vfs pointer. 506 * note: off is the sector offset, not lbn offset 507 * if NULL is returned implies file system hsnode table full 508 */ 509 struct vnode * 510 hs_makenode( 511 struct hs_direntry *dp, 512 uint_t lbn, 513 uint_t off, 514 struct vfs *vfsp) 515 { 516 struct hsnode *hp; 517 struct vnode *vp; 518 struct hs_volume *hvp; 519 struct vnode *newvp; 520 struct hsfs *fsp; 521 ino64_t nodeid; 522 523 fsp = VFS_TO_HSFS(vfsp); 524 525 /* 526 * Construct the data that allows us to re-read the meta data without 527 * knowing the name of the file: in the case of a directory 528 * entry, this should point to the canonical dirent, the "." 529 * directory entry for the directory. This dirent is pointed 530 * to by all directory entries for that dir (including the ".") 531 * entry itself. 532 * In the case of a file, simply point to the dirent for that 533 * file (there are hard links in Rock Ridge, so we need to use 534 * different data to contruct the node id). 535 */ 536 if (dp->type == VDIR) { 537 lbn = dp->ext_lbn; 538 off = 0; 539 } 540 541 /* 542 * Normalize lbn and off before creating a nodeid 543 * and before storing them in a hs_node structure 544 */ 545 hvp = &fsp->hsfs_vol; 546 lbn += off >> hvp->lbn_shift; 547 off &= hvp->lbn_maxoffset; 548 /* 549 * If the media carries rrip-v1.12 or newer, and we trust the inodes 550 * from the rrip data (use_rrip_inodes != 0), use that data. If the 551 * media has been created by a recent mkisofs version, we may trust 552 * all numbers in the starting extent number; otherwise, we cannot 553 * do this for zero sized files and symlinks, because if we did we'd 554 * end up mapping all of them to the same node. 555 * We use HS_DUMMY_INO in this case and make sure that we will not 556 * map all files to the same meta data. 557 */ 558 if (dp->inode != 0 && use_rrip_inodes) { 559 nodeid = dp->inode; 560 } else if ((dp->ext_size == 0 || dp->sym_link != (char *)NULL) && 561 (fsp->hsfs_flags & HSFSMNT_INODE) == 0) { 562 nodeid = HS_DUMMY_INO; 563 } else { 564 nodeid = dp->ext_lbn; 565 } 566 567 /* look for hsnode in cache first */ 568 569 rw_enter(&fsp->hsfs_hash_lock, RW_READER); 570 571 if ((vp = hs_findhash(nodeid, lbn, off, vfsp)) == NULL) { 572 573 /* 574 * Not in cache. However, someone else may have come 575 * to the same conclusion and just put one in. Upgrade 576 * our lock to a write lock and look again. 577 */ 578 rw_exit(&fsp->hsfs_hash_lock); 579 rw_enter(&fsp->hsfs_hash_lock, RW_WRITER); 580 581 if ((vp = hs_findhash(nodeid, lbn, off, vfsp)) == NULL) { 582 /* 583 * Now we are really sure that the hsnode is not 584 * in the cache. Get one off freelist or else 585 * allocate one. Either way get a bzeroed hsnode. 586 */ 587 hp = hs_getfree(fsp); 588 589 bcopy((caddr_t)dp, (caddr_t)&hp->hs_dirent, 590 sizeof (*dp)); 591 /* 592 * We've just copied this pointer into hs_dirent, 593 * and don't want 2 references to same symlink. 594 */ 595 dp->sym_link = (char *)NULL; 596 597 /* 598 * No need to hold any lock because hsnode is not 599 * yet in the hash chain. 600 */ 601 mutex_init(&hp->hs_contents_lock, NULL, MUTEX_DEFAULT, 602 NULL); 603 hp->hs_dir_lbn = lbn; 604 hp->hs_dir_off = off; 605 hp->hs_nodeid = nodeid; 606 hp->hs_seq = 0; 607 hp->hs_prev_offset = 0; 608 hp->hs_num_contig = 0; 609 hp->hs_ra_bytes = 0; 610 hp->hs_flags = HREF; 611 if (off > HS_SECTOR_SIZE) 612 cmn_err(CE_WARN, "hs_makenode: bad offset"); 613 614 vp = HTOV(hp); 615 vp->v_vfsp = vfsp; 616 vp->v_type = dp->type; 617 vp->v_rdev = dp->r_dev; 618 vn_setops(vp, hsfs_vnodeops); 619 vp->v_data = (caddr_t)hp; 620 vn_exists(vp); 621 /* 622 * if it's a device, call specvp 623 */ 624 if (IS_DEVVP(vp)) { 625 rw_exit(&fsp->hsfs_hash_lock); 626 newvp = specvp(vp, vp->v_rdev, vp->v_type, 627 CRED()); 628 if (newvp == NULL) 629 cmn_err(CE_NOTE, 630 "hs_makenode: specvp failed"); 631 VN_RELE(vp); 632 return (newvp); 633 } 634 635 hs_addhash(fsp, hp); 636 637 } 638 } 639 640 if (dp->sym_link != (char *)NULL) { 641 kmem_free(dp->sym_link, (size_t)(dp->ext_size + 1)); 642 dp->sym_link = (char *)NULL; 643 } 644 645 rw_exit(&fsp->hsfs_hash_lock); 646 return (vp); 647 } 648 649 /* 650 * hs_freenode 651 * 652 * Deactivate an hsnode. 653 * Leave it on the hash list but put it on the free list. 654 * If the vnode does not have any pages, release the hsnode to the 655 * kmem_cache using kmem_cache_free, else put in back of the free list. 656 * 657 * This function can be called with the hsfs_free_lock held, but only 658 * when the code is guaranteed to go through the path where the 659 * node is freed entirely, and not the path where the node could go back 660 * on the free list (and where the free lock would need to be acquired). 661 */ 662 void 663 hs_freenode(vnode_t *vp, struct hsfs *fsp, int nopage) 664 { 665 struct hsnode **tp; 666 struct hsnode *hp = VTOH(vp); 667 668 ASSERT(RW_LOCK_HELD(&fsp->hsfs_hash_lock)); 669 670 if (nopage || (fsp->hsfs_nohsnode >= nhsnode)) { 671 /* remove this node from the hash list, if it's there */ 672 for (tp = &fsp->hsfs_hash[HS_HPASH(hp)]; *tp != NULL; 673 tp = &(*tp)->hs_hash) { 674 675 if (*tp == hp) { 676 *tp = hp->hs_hash; 677 break; 678 } 679 } 680 681 if (hp->hs_dirent.sym_link != (char *)NULL) { 682 kmem_free(hp->hs_dirent.sym_link, 683 (size_t)(hp->hs_dirent.ext_size + 1)); 684 hp->hs_dirent.sym_link = NULL; 685 } 686 if (vn_has_cached_data(vp)) { 687 /* clean all old pages */ 688 (void) pvn_vplist_dirty(vp, (u_offset_t)0, 689 hsfs_putapage, B_INVAL, (struct cred *)NULL); 690 /* XXX - can we remove pages by fiat like this??? */ 691 vp->v_pages = NULL; 692 } 693 mutex_destroy(&hp->hs_contents_lock); 694 vn_invalid(vp); 695 vn_free(vp); 696 kmem_cache_free(hsnode_cache, hp); 697 fsp->hsfs_nohsnode--; 698 return; 699 } 700 hs_addfreeb(fsp, hp); /* add to back of free list */ 701 } 702 703 /* 704 * hs_remakenode 705 * 706 * Reconstruct a vnode given the location of its directory entry. 707 * Caller specifies the the block number and offset 708 * of the directory entry, and the vfs pointer. 709 * Returns an error code or 0. 710 */ 711 int 712 hs_remakenode(uint_t lbn, uint_t off, struct vfs *vfsp, 713 struct vnode **vpp) 714 { 715 struct buf *secbp; 716 struct hsfs *fsp; 717 uint_t secno; 718 uchar_t *dirp; 719 struct hs_direntry hd; 720 int error; 721 722 /* Convert to sector and offset */ 723 fsp = VFS_TO_HSFS(vfsp); 724 if (off > HS_SECTOR_SIZE) { 725 cmn_err(CE_WARN, "hs_remakenode: bad offset"); 726 error = EINVAL; 727 goto end; 728 } 729 secno = LBN_TO_SEC(lbn, vfsp); 730 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 731 732 error = geterror(secbp); 733 if (error != 0) { 734 cmn_err(CE_NOTE, "hs_remakenode: bread: error=(%d)", error); 735 goto end; 736 } 737 738 dirp = (uchar_t *)secbp->b_un.b_addr; 739 error = hs_parsedir(fsp, &dirp[off], &hd, (char *)NULL, (int *)NULL, 740 HS_SECTOR_SIZE - off); 741 if (!error) { 742 *vpp = hs_makenode(&hd, lbn, off, vfsp); 743 if (*vpp == NULL) 744 error = ENFILE; 745 } 746 747 end: 748 brelse(secbp); 749 return (error); 750 } 751 752 753 /* 754 * hs_dirlook 755 * 756 * Look for a given name in a given directory. 757 * If found, construct an hsnode for it. 758 */ 759 int 760 hs_dirlook( 761 struct vnode *dvp, 762 char *name, 763 int namlen, /* length of 'name' */ 764 struct vnode **vpp, 765 struct cred *cred) 766 { 767 struct hsnode *dhp; 768 struct hsfs *fsp; 769 int error = 0; 770 uint_t offset; /* real offset in directory */ 771 uint_t last_offset; /* last index in directory */ 772 char *cmpname; /* case-folded name */ 773 int cmpname_size; /* how much memory we allocate for it */ 774 int cmpnamelen; 775 int adhoc_search; /* did we start at begin of dir? */ 776 int end; 777 uint_t hsoffset; 778 struct fbuf *fbp; 779 int bytes_wanted; 780 int dirsiz; 781 int is_rrip; 782 783 if (dvp->v_type != VDIR) 784 return (ENOTDIR); 785 786 if (error = hs_access(dvp, (mode_t)VEXEC, cred)) 787 return (error); 788 789 if (hsfs_use_dnlc && (*vpp = dnlc_lookup(dvp, name))) 790 return (0); 791 792 dhp = VTOH(dvp); 793 fsp = VFS_TO_HSFS(dvp->v_vfsp); 794 is_rrip = IS_RRIP_IMPLEMENTED(fsp); 795 796 /* 797 * name == "^A" is illegal for ISO-9660 and Joliet as '..' is '\1' on 798 * disk. It is no problem for Rock Ridge as RR uses '.' and '..'. 799 * XXX It could be OK for Joliet also (because namelen == 1 is 800 * XXX impossible for UCS-2) but then we need a better compare algorith. 801 */ 802 if (!is_rrip && *name == '\1' && namlen == 1) 803 return (EINVAL); 804 805 cmpname_size = (int)(fsp->hsfs_namemax + 1); 806 cmpname = kmem_alloc((size_t)cmpname_size, KM_SLEEP); 807 808 if (namlen >= cmpname_size) 809 namlen = cmpname_size - 1; 810 /* 811 * For the purposes of comparing the name against dir entries, 812 * fold it to upper case. 813 */ 814 if (is_rrip) { 815 (void) strlcpy(cmpname, name, cmpname_size); 816 cmpnamelen = namlen; 817 } else { 818 /* 819 * If we don't consider a trailing dot as part of the filename, 820 * remove it from the specified name 821 */ 822 if ((fsp->hsfs_flags & HSFSMNT_NOTRAILDOT) && 823 name[namlen-1] == '.' && 824 CAN_TRUNCATE_DOT(name, namlen)) 825 name[--namlen] = '\0'; 826 if (fsp->hsfs_vol_type == HS_VOL_TYPE_ISO_V2 || 827 fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET) { 828 cmpnamelen = hs_iso_copy(name, cmpname, namlen); 829 } else { 830 cmpnamelen = hs_uppercase_copy(name, cmpname, namlen); 831 } 832 } 833 834 /* make sure dirent is filled up with all info */ 835 if (dhp->hs_dirent.ext_size == 0) 836 hs_filldirent(dvp, &dhp->hs_dirent); 837 838 /* 839 * No lock is needed - hs_offset is used as starting 840 * point for searching the directory. 841 */ 842 offset = dhp->hs_offset; 843 hsoffset = offset; 844 adhoc_search = (offset != 0); 845 846 end = dhp->hs_dirent.ext_size; 847 dirsiz = end; 848 849 tryagain: 850 851 while (offset < end) { 852 bytes_wanted = MIN(MAXBSIZE, dirsiz - (offset & MAXBMASK)); 853 854 error = fbread(dvp, (offset_t)(offset & MAXBMASK), 855 (unsigned int)bytes_wanted, S_READ, &fbp); 856 if (error) 857 goto done; 858 859 last_offset = (offset & MAXBMASK) + fbp->fb_count; 860 861 switch (process_dirblock(fbp, &offset, last_offset, 862 cmpname, cmpnamelen, fsp, dhp, dvp, vpp, &error)) { 863 case FOUND_ENTRY: 864 /* found an entry, either correct or not */ 865 goto done; 866 867 case WENT_PAST: 868 /* 869 * If we get here we know we didn't find it on the 870 * first pass. If adhoc_search, then we started a 871 * bit into the dir, and need to wrap around and 872 * search the first entries. If not, then we started 873 * at the beginning and didn't find it. 874 */ 875 if (adhoc_search) { 876 offset = 0; 877 end = hsoffset; 878 adhoc_search = 0; 879 goto tryagain; 880 } 881 error = ENOENT; 882 goto done; 883 884 case HIT_END: 885 goto tryagain; 886 } 887 } 888 /* 889 * End of all dir blocks, didn't find entry. 890 */ 891 if (adhoc_search) { 892 offset = 0; 893 end = hsoffset; 894 adhoc_search = 0; 895 goto tryagain; 896 } 897 error = ENOENT; 898 done: 899 /* 900 * If we found the entry, add it to the DNLC 901 * If the entry is a device file (assuming we support Rock Ridge), 902 * we enter the device vnode to the cache since that is what 903 * is in *vpp. 904 * That is ok since the CD-ROM is read-only, so (dvp,name) will 905 * always point to the same device. 906 */ 907 if (hsfs_use_dnlc && !error) 908 dnlc_enter(dvp, name, *vpp); 909 910 kmem_free(cmpname, (size_t)cmpname_size); 911 912 return (error); 913 } 914 915 /* 916 * hs_parsedir 917 * 918 * Parse a Directory Record into an hs_direntry structure. 919 * High Sierra and ISO directory are almost the same 920 * except the flag and date 921 */ 922 int 923 hs_parsedir( 924 struct hsfs *fsp, 925 uchar_t *dirp, 926 struct hs_direntry *hdp, 927 char *dnp, 928 int *dnlen, 929 int last_offset) /* last offset in dirp */ 930 { 931 char *on_disk_name; 932 int on_disk_namelen; 933 int on_disk_dirlen; 934 uchar_t flags; 935 int namelen; 936 int error; 937 int name_change_flag = 0; /* set if name was gotten in SUA */ 938 939 hdp->ext_lbn = HDE_EXT_LBN(dirp); 940 hdp->ext_size = HDE_EXT_SIZE(dirp); 941 hdp->xar_len = HDE_XAR_LEN(dirp); 942 hdp->intlf_sz = HDE_INTRLV_SIZE(dirp); 943 hdp->intlf_sk = HDE_INTRLV_SKIP(dirp); 944 hdp->sym_link = (char *)NULL; 945 946 if (fsp->hsfs_vol_type == HS_VOL_TYPE_HS) { 947 flags = HDE_FLAGS(dirp); 948 hs_parse_dirdate(HDE_cdate(dirp), &hdp->cdate); 949 hs_parse_dirdate(HDE_cdate(dirp), &hdp->adate); 950 hs_parse_dirdate(HDE_cdate(dirp), &hdp->mdate); 951 if ((flags & hde_prohibited) == 0) { 952 /* 953 * Skip files with the associated bit set. 954 */ 955 if (flags & HDE_ASSOCIATED) 956 return (EAGAIN); 957 hdp->type = VREG; 958 hdp->mode = HFREG; 959 hdp->nlink = 1; 960 } else if ((flags & hde_prohibited) == HDE_DIRECTORY) { 961 hdp->type = VDIR; 962 hdp->mode = HFDIR; 963 hdp->nlink = 2; 964 } else { 965 hs_log_bogus_disk_warning(fsp, 966 HSFS_ERR_UNSUP_TYPE, flags); 967 return (EINVAL); 968 } 969 hdp->uid = fsp -> hsfs_vol.vol_uid; 970 hdp->gid = fsp -> hsfs_vol.vol_gid; 971 hdp->mode = hdp-> mode | (fsp -> hsfs_vol.vol_prot & 0777); 972 } else if ((fsp->hsfs_vol_type == HS_VOL_TYPE_ISO) || 973 (fsp->hsfs_vol_type == HS_VOL_TYPE_ISO_V2) || 974 (fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET)) { 975 976 flags = IDE_FLAGS(dirp); 977 hs_parse_dirdate(IDE_cdate(dirp), &hdp->cdate); 978 hs_parse_dirdate(IDE_cdate(dirp), &hdp->adate); 979 hs_parse_dirdate(IDE_cdate(dirp), &hdp->mdate); 980 981 if ((flags & ide_prohibited) == 0) { 982 /* 983 * Skip files with the associated bit set. 984 */ 985 if (flags & IDE_ASSOCIATED) 986 return (EAGAIN); 987 hdp->type = VREG; 988 hdp->mode = HFREG; 989 hdp->nlink = 1; 990 } else if ((flags & ide_prohibited) == IDE_DIRECTORY) { 991 hdp->type = VDIR; 992 hdp->mode = HFDIR; 993 hdp->nlink = 2; 994 } else { 995 hs_log_bogus_disk_warning(fsp, 996 HSFS_ERR_UNSUP_TYPE, flags); 997 return (EINVAL); 998 } 999 hdp->uid = fsp -> hsfs_vol.vol_uid; 1000 hdp->gid = fsp -> hsfs_vol.vol_gid; 1001 hdp->mode = hdp-> mode | (fsp -> hsfs_vol.vol_prot & 0777); 1002 hdp->inode = 0; /* initialize with 0, then check rrip */ 1003 1004 /* 1005 * Having this all filled in, let's see if we have any 1006 * SUA susp to look at. 1007 */ 1008 if (IS_SUSP_IMPLEMENTED(fsp)) { 1009 error = parse_sua((uchar_t *)dnp, dnlen, 1010 &name_change_flag, dirp, last_offset, 1011 hdp, fsp, NULL, 0); 1012 if (error) { 1013 if (hdp->sym_link) { 1014 kmem_free(hdp->sym_link, 1015 (size_t)(hdp->ext_size + 1)); 1016 hdp->sym_link = (char *)NULL; 1017 } 1018 return (error); 1019 } 1020 } 1021 } 1022 hdp->xar_prot = (HDE_PROTECTION & flags) != 0; 1023 1024 #if dontskip 1025 if (hdp->xar_len > 0) { 1026 cmn_err(CE_NOTE, "hsfs: extended attributes not supported"); 1027 return (EINVAL); 1028 } 1029 #endif 1030 1031 /* check interleaf size and skip factor */ 1032 /* must both be zero or non-zero */ 1033 if (hdp->intlf_sz + hdp->intlf_sk) { 1034 if ((hdp->intlf_sz == 0) || (hdp->intlf_sk == 0)) { 1035 cmn_err(CE_NOTE, 1036 "hsfs: interleaf size or skip factor error"); 1037 return (EINVAL); 1038 } 1039 if (hdp->ext_size == 0) { 1040 cmn_err(CE_NOTE, 1041 "hsfs: interleaving specified on zero length file"); 1042 return (EINVAL); 1043 } 1044 } 1045 1046 if (HDE_VOL_SET(dirp) != 1) { 1047 if (fsp->hsfs_vol.vol_set_size != 1 && 1048 fsp->hsfs_vol.vol_set_size != HDE_VOL_SET(dirp)) { 1049 cmn_err(CE_NOTE, "hsfs: multivolume file?"); 1050 return (EINVAL); 1051 } 1052 } 1053 1054 /* 1055 * If the name changed, then the NM field for RRIP was hit and 1056 * we should not copy the name again, just return. 1057 */ 1058 if (NAME_HAS_CHANGED(name_change_flag)) 1059 return (0); 1060 1061 /* 1062 * Fall back to the ISO name. Note that as in process_dirblock, 1063 * the on-disk filename length must be validated against ISO 1064 * limits - which, in case of RR present but no RR name found, 1065 * are NOT identical to fsp->hsfs_namemax on this filesystem. 1066 */ 1067 on_disk_name = (char *)HDE_name(dirp); 1068 on_disk_namelen = (int)HDE_NAME_LEN(dirp); 1069 on_disk_dirlen = (int)HDE_DIR_LEN(dirp); 1070 1071 if (on_disk_dirlen < HDE_ROOT_DIR_REC_SIZE || 1072 ((on_disk_dirlen > last_offset) || 1073 ((HDE_FDESIZE + on_disk_namelen) > on_disk_dirlen))) { 1074 hs_log_bogus_disk_warning(fsp, 1075 HSFS_ERR_BAD_DIR_ENTRY, 0); 1076 return (EINVAL); 1077 } 1078 1079 if (on_disk_namelen > fsp->hsfs_namelen && 1080 hs_namelen(fsp, on_disk_name, on_disk_namelen) > 1081 fsp->hsfs_namelen) { 1082 hs_log_bogus_disk_warning(fsp, 1083 fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET ? 1084 HSFS_ERR_BAD_JOLIET_FILE_LEN : 1085 HSFS_ERR_BAD_FILE_LEN, 0); 1086 } 1087 if (on_disk_namelen > ISO_NAMELEN_V2_MAX) 1088 on_disk_namelen = fsp->hsfs_namemax; /* Paranoia */ 1089 1090 if (dnp != NULL) { 1091 if (fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET) { 1092 namelen = hs_jnamecopy(on_disk_name, dnp, 1093 on_disk_namelen, fsp->hsfs_namemax, 1094 fsp->hsfs_flags); 1095 /* 1096 * A negative return value means that the file name 1097 * has been truncated to fsp->hsfs_namemax. 1098 */ 1099 if (namelen < 0) { 1100 namelen = -namelen; 1101 hs_log_bogus_disk_warning(fsp, 1102 HSFS_ERR_TRUNC_JOLIET_FILE_LEN, 0); 1103 } 1104 } else { 1105 /* 1106 * HS_VOL_TYPE_ISO && HS_VOL_TYPE_ISO_V2 1107 */ 1108 namelen = hs_namecopy(on_disk_name, dnp, 1109 on_disk_namelen, fsp->hsfs_flags); 1110 } 1111 if (namelen == 0) 1112 return (EINVAL); 1113 if ((fsp->hsfs_flags & HSFSMNT_NOTRAILDOT) && 1114 dnp[ namelen-1 ] == '.' && CAN_TRUNCATE_DOT(dnp, namelen)) 1115 dnp[ --namelen ] = '\0'; 1116 } else 1117 namelen = on_disk_namelen; 1118 if (dnlen != NULL) 1119 *dnlen = namelen; 1120 1121 return (0); 1122 } 1123 1124 /* 1125 * hs_namecopy 1126 * 1127 * Parse a file/directory name into UNIX form. 1128 * Delete trailing blanks, upper-to-lower case, add NULL terminator. 1129 * Returns the (possibly new) length. 1130 * 1131 * Called from hsfs_readdir() via hs_parsedir() 1132 */ 1133 int 1134 hs_namecopy(char *from, char *to, int size, ulong_t flags) 1135 { 1136 uint_t i; 1137 uchar_t c; 1138 int lastspace; 1139 int maplc; 1140 int trailspace; 1141 int version; 1142 1143 /* special handling for '.' and '..' */ 1144 if (size == 1) { 1145 if (*from == '\0') { 1146 *to++ = '.'; 1147 *to = '\0'; 1148 return (1); 1149 } else if (*from == '\1') { 1150 *to++ = '.'; 1151 *to++ = '.'; 1152 *to = '\0'; 1153 return (2); 1154 } 1155 } 1156 1157 maplc = (flags & HSFSMNT_NOMAPLCASE) == 0; 1158 trailspace = (flags & HSFSMNT_NOTRAILSPACE) == 0; 1159 version = (flags & HSFSMNT_NOVERSION) == 0; 1160 for (i = 0, lastspace = -1; i < size; i++) { 1161 c = from[i]; 1162 if (c == ';' && version) 1163 break; 1164 if (c <= ' ' && !trailspace) { 1165 if (lastspace == -1) 1166 lastspace = i; 1167 } else 1168 lastspace = -1; 1169 if (maplc && (c >= 'A') && (c <= 'Z')) 1170 c += 'a' - 'A'; 1171 to[i] = c; 1172 } 1173 if (lastspace != -1) 1174 i = lastspace; 1175 to[i] = '\0'; 1176 return (i); 1177 } 1178 1179 /* 1180 * hs_jnamecopy 1181 * 1182 * This is the Joliet variant of hs_namecopy() 1183 * 1184 * Parse a UCS-2 Joliet file/directory name into UNIX form. 1185 * Add NULL terminator. 1186 * Returns the new length. 1187 * 1188 * Called from hsfs_readdir() via hs_parsedir() 1189 */ 1190 int 1191 hs_jnamecopy(char *from, char *to, int size, int maxsize, ulong_t flags) 1192 { 1193 uint_t i; 1194 uint_t len; 1195 uint16_t c; 1196 int amt; 1197 int version; 1198 1199 /* special handling for '.' and '..' */ 1200 if (size == 1) { 1201 if (*from == '\0') { 1202 *to++ = '.'; 1203 *to = '\0'; 1204 return (1); 1205 } else if (*from == '\1') { 1206 *to++ = '.'; 1207 *to++ = '.'; 1208 *to = '\0'; 1209 return (2); 1210 } 1211 } 1212 1213 version = (flags & HSFSMNT_NOVERSION) == 0; 1214 for (i = 0, len = 0; i < size; i++) { 1215 c = (from[i++] & 0xFF) << 8; 1216 c |= from[i] & 0xFF; 1217 if (c == ';' && version) 1218 break; 1219 1220 if (len > (maxsize-3)) { 1221 if (c < 0x80) 1222 amt = 1; 1223 else if (c < 0x800) 1224 amt = 2; 1225 else 1226 amt = 3; 1227 if ((len+amt) > maxsize) { 1228 to[len] = '\0'; 1229 return (-len); 1230 } 1231 } 1232 amt = hs_ucs2_2_utf8(c, (uint8_t *)&to[len]); 1233 if (amt == 0) { 1234 hs_log_bogus_joliet_warning(); /* should never happen */ 1235 return (0); 1236 } 1237 len += amt; 1238 } 1239 to[len] = '\0'; 1240 return (len); 1241 } 1242 1243 /* 1244 * map a filename to upper case; 1245 * return 1 if found lowercase character 1246 * 1247 * Called from process_dirblock() 1248 * via hsfs_lookup() -> hs_dirlook() -> process_dirblock() 1249 * to create an intermedia name from on disk file names for 1250 * comparing names. 1251 */ 1252 static int 1253 uppercase_cp(char *from, char *to, int size) 1254 { 1255 uint_t i; 1256 uchar_t c; 1257 uchar_t had_lc = 0; 1258 1259 for (i = 0; i < size; i++) { 1260 c = *from++; 1261 if ((c >= 'a') && (c <= 'z')) { 1262 c -= ('a' - 'A'); 1263 had_lc = 1; 1264 } 1265 *to++ = c; 1266 } 1267 return (had_lc); 1268 } 1269 1270 /* 1271 * This is the Joliet variant of uppercase_cp() 1272 * 1273 * map a UCS-2 filename to UTF-8; 1274 * return new length 1275 * 1276 * Called from process_dirblock() 1277 * via hsfs_lookup() -> hs_dirlook() -> process_dirblock() 1278 * to create an intermedia name from on disk file names for 1279 * comparing names. 1280 */ 1281 int 1282 hs_joliet_cp(char *from, char *to, int size) 1283 { 1284 uint_t i; 1285 uint16_t c; 1286 int len = 0; 1287 int amt; 1288 1289 /* special handling for '\0' and '\1' */ 1290 if (size == 1) { 1291 *to = *from; 1292 return (1); 1293 } 1294 for (i = 0; i < size; i += 2) { 1295 c = (*from++ & 0xFF) << 8; 1296 c |= *from++ & 0xFF; 1297 1298 amt = hs_ucs2_2_utf8(c, (uint8_t *)to); 1299 if (amt == 0) { 1300 hs_log_bogus_joliet_warning(); /* should never happen */ 1301 return (0); 1302 } 1303 1304 to += amt; 1305 len += amt; 1306 } 1307 return (len); 1308 } 1309 1310 static void 1311 hs_log_bogus_joliet_warning(void) 1312 { 1313 static int warned = 0; 1314 1315 if (warned) 1316 return; 1317 warned = 1; 1318 cmn_err(CE_CONT, "hsfs: Warning: " 1319 "file name contains bad UCS-2 chacarter\n"); 1320 } 1321 1322 1323 /* 1324 * hs_uppercase_copy 1325 * 1326 * Convert a UNIX-style name into its HSFS equivalent 1327 * replacing '.' and '..' with '\0' and '\1'. 1328 * Map to upper case. 1329 * Returns the (possibly new) length. 1330 * 1331 * Called from hs_dirlook() and rrip_namecopy() 1332 * to create an intermediate name from the callers name from hsfs_lookup() 1333 * XXX Is the call from rrip_namecopy() OK? 1334 */ 1335 int 1336 hs_uppercase_copy(char *from, char *to, int size) 1337 { 1338 uint_t i; 1339 uchar_t c; 1340 1341 /* special handling for '.' and '..' */ 1342 1343 if (size == 1 && *from == '.') { 1344 *to = '\0'; 1345 return (1); 1346 } else if (size == 2 && *from == '.' && *(from+1) == '.') { 1347 *to = '\1'; 1348 return (1); 1349 } 1350 1351 for (i = 0; i < size; i++) { 1352 c = *from++; 1353 if ((c >= 'a') && (c <= 'z')) 1354 c = c - 'a' + 'A'; 1355 *to++ = c; 1356 } 1357 return (size); 1358 } 1359 1360 /* 1361 * hs_iso_copy 1362 * 1363 * This is the Joliet/ISO-9660:1999 variant of hs_uppercase_copy() 1364 * 1365 * Convert a UTF-8 UNIX-style name into its UTF-8 Joliet/ISO equivalent 1366 * replacing '.' and '..' with '\0' and '\1'. 1367 * Returns the (possibly new) length. 1368 * 1369 * Called from hs_dirlook() 1370 * to create an intermediate name from the callers name from hsfs_lookup() 1371 */ 1372 static int 1373 hs_iso_copy(char *from, char *to, int size) 1374 { 1375 uint_t i; 1376 uchar_t c; 1377 1378 /* special handling for '.' and '..' */ 1379 1380 if (size == 1 && *from == '.') { 1381 *to = '\0'; 1382 return (1); 1383 } else if (size == 2 && *from == '.' && *(from+1) == '.') { 1384 *to = '\1'; 1385 return (1); 1386 } 1387 1388 for (i = 0; i < size; i++) { 1389 c = *from++; 1390 *to++ = c; 1391 } 1392 return (size); 1393 } 1394 1395 void 1396 hs_filldirent(struct vnode *vp, struct hs_direntry *hdp) 1397 { 1398 struct buf *secbp; 1399 uint_t secno; 1400 offset_t secoff; 1401 struct hsfs *fsp; 1402 uchar_t *secp; 1403 int error; 1404 1405 if (vp->v_type != VDIR) { 1406 cmn_err(CE_WARN, "hsfs_filldirent: vp (0x%p) not a directory", 1407 (void *)vp); 1408 return; 1409 } 1410 1411 fsp = VFS_TO_HSFS(vp ->v_vfsp); 1412 secno = LBN_TO_SEC(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp); 1413 secoff = LBN_TO_BYTE(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp) & 1414 MAXHSOFFSET; 1415 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 1416 error = geterror(secbp); 1417 if (error != 0) { 1418 cmn_err(CE_NOTE, "hs_filldirent: bread: error=(%d)", error); 1419 goto end; 1420 } 1421 1422 secp = (uchar_t *)secbp->b_un.b_addr; 1423 1424 /* quick check */ 1425 if (hdp->ext_lbn != HDE_EXT_LBN(&secp[secoff])) { 1426 cmn_err(CE_NOTE, "hsfs_filldirent: dirent not match"); 1427 /* keep on going */ 1428 } 1429 (void) hs_parsedir(fsp, &secp[secoff], hdp, (char *)NULL, 1430 (int *)NULL, HS_SECTOR_SIZE - secoff); 1431 1432 end: 1433 brelse(secbp); 1434 } 1435 1436 /* 1437 * Look through a directory block for a matching entry. 1438 * Note: this routine does an fbrelse() on the buffer passed in. 1439 */ 1440 static enum dirblock_result 1441 process_dirblock( 1442 struct fbuf *fbp, /* buffer containing dirblk */ 1443 uint_t *offset, /* lower index */ 1444 uint_t last_offset, /* upper index */ 1445 char *nm, /* upcase nm to compare against */ 1446 int nmlen, /* length of name */ 1447 struct hsfs *fsp, 1448 struct hsnode *dhp, 1449 struct vnode *dvp, 1450 struct vnode **vpp, 1451 int *error) /* return value: errno */ 1452 { 1453 uchar_t *blkp = (uchar_t *)fbp->fb_addr; /* dir block */ 1454 char *dname; /* name in directory entry */ 1455 int dnamelen; /* length of name */ 1456 struct hs_direntry hd; 1457 int hdlen; 1458 uchar_t *dirp; /* the directory entry */ 1459 int res; 1460 int parsedir_res; 1461 int is_rrip; 1462 size_t rrip_name_size; 1463 int rr_namelen = 0; 1464 char *rrip_name_str = NULL; 1465 char *rrip_tmp_name = NULL; 1466 enum dirblock_result err = 0; 1467 int did_fbrelse = 0; 1468 char uppercase_name[JOLIET_NAMELEN_MAX*3 + 1]; /* 331 */ 1469 1470 #define PD_return(retval) \ 1471 { err = retval; goto do_ret; } /* return after cleanup */ 1472 #define rel_offset(offset) \ 1473 ((offset) & MAXBOFFSET) /* index into cur blk */ 1474 #define RESTORE_NM(tmp, orig) \ 1475 if (is_rrip && *(tmp) != '\0') \ 1476 (void) strcpy((orig), (tmp)) 1477 1478 is_rrip = IS_RRIP_IMPLEMENTED(fsp); 1479 if (is_rrip) { 1480 rrip_name_size = RRIP_FILE_NAMELEN + 1; 1481 rrip_name_str = kmem_alloc(rrip_name_size, KM_SLEEP); 1482 rrip_tmp_name = kmem_alloc(rrip_name_size, KM_SLEEP); 1483 rrip_name_str[0] = '\0'; 1484 rrip_tmp_name[0] = '\0'; 1485 } 1486 1487 while (*offset < last_offset) { 1488 1489 /* 1490 * Directory Entries cannot span sectors. 1491 * 1492 * Unused bytes at the end of each sector are zeroed 1493 * according to ISO9660, but we cannot rely on this 1494 * since both media failures and maliciously corrupted 1495 * media may return arbitrary values. 1496 * We therefore have to check for consistency: 1497 * The size of a directory entry must be at least 1498 * 34 bytes (the size of the directory entry metadata), 1499 * or zero (indicating the end-of-sector condition). 1500 * For a non-zero directory entry size of less than 1501 * 34 Bytes, log a warning. 1502 * In any case, skip the rest of this sector and 1503 * continue with the next. 1504 */ 1505 hdlen = (int)((uchar_t) 1506 HDE_DIR_LEN(&blkp[rel_offset(*offset)])); 1507 1508 if (hdlen < HDE_ROOT_DIR_REC_SIZE || 1509 *offset + hdlen > last_offset) { 1510 /* 1511 * Advance to the next sector boundary 1512 */ 1513 *offset = roundup(*offset + 1, HS_SECTOR_SIZE); 1514 if (hdlen) 1515 hs_log_bogus_disk_warning(fsp, 1516 HSFS_ERR_TRAILING_JUNK, 0); 1517 continue; 1518 } 1519 1520 bzero(&hd, sizeof (hd)); 1521 1522 /* 1523 * Check the filename length in the ISO record for 1524 * plausibility and reset it to a safe value, in case 1525 * the name length byte is out of range. Since the ISO 1526 * name will be used as fallback if the rockridge name 1527 * is invalid/nonexistant, we must make sure not to 1528 * blow the bounds and initialize dnamelen to a sensible 1529 * value within the limits of ISO9660. 1530 * In addition to that, the ISO filename is part of the 1531 * directory entry. If the filename length is too large 1532 * to fit, the record is invalid and we'll advance to 1533 * the next. 1534 */ 1535 dirp = &blkp[rel_offset(*offset)]; 1536 dname = (char *)HDE_name(dirp); 1537 dnamelen = (int)((uchar_t)HDE_NAME_LEN(dirp)); 1538 /* 1539 * If the directory entry extends beyond the end of the 1540 * block, it must be invalid. Skip it. 1541 */ 1542 if (dnamelen > hdlen - HDE_FDESIZE) { 1543 hs_log_bogus_disk_warning(fsp, 1544 HSFS_ERR_BAD_DIR_ENTRY, 0); 1545 goto skip_rec; 1546 } else if (dnamelen > fsp->hsfs_namelen && 1547 hs_namelen(fsp, dname, dnamelen) > fsp->hsfs_namelen) { 1548 hs_log_bogus_disk_warning(fsp, 1549 fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET ? 1550 HSFS_ERR_BAD_JOLIET_FILE_LEN : 1551 HSFS_ERR_BAD_FILE_LEN, 0); 1552 } 1553 if (dnamelen > ISO_NAMELEN_V2_MAX) 1554 dnamelen = fsp->hsfs_namemax; /* Paranoia */ 1555 1556 /* 1557 * If the rock ridge is implemented, then we copy the name 1558 * from the SUA area to rrip_name_str. If no Alternate 1559 * name is found, then use the uppercase NM in the 1560 * rrip_name_str char array. 1561 */ 1562 if (is_rrip) { 1563 1564 rrip_name_str[0] = '\0'; 1565 rr_namelen = rrip_namecopy(nm, &rrip_name_str[0], 1566 &rrip_tmp_name[0], dirp, last_offset - *offset, 1567 fsp, &hd); 1568 if (hd.sym_link) { 1569 kmem_free(hd.sym_link, 1570 (size_t)(hd.ext_size+1)); 1571 hd.sym_link = (char *)NULL; 1572 } 1573 1574 if (rr_namelen != -1) { 1575 dname = (char *)&rrip_name_str[0]; 1576 dnamelen = rr_namelen; 1577 } 1578 } 1579 1580 if (!is_rrip || rr_namelen == -1) { 1581 /* use iso name instead */ 1582 1583 int i = -1; 1584 /* 1585 * make sure that we get rid of ';' in the dname of 1586 * an iso direntry, as we should have no knowledge 1587 * of file versions. 1588 * 1589 * XXX This is done the wrong way: it does not take 1590 * XXX care of the fact that the version string is 1591 * XXX a decimal number in the range 1 to 32767. 1592 */ 1593 if ((fsp->hsfs_flags & HSFSMNT_NOVERSION) == 0) { 1594 if (fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET) { 1595 for (i = dnamelen - 1; i > 0; i -= 2) { 1596 if (dname[i] == ';' && 1597 dname[i-1] == '\0') { 1598 --i; 1599 break; 1600 } 1601 } 1602 } else { 1603 for (i = dnamelen - 1; i > 0; i--) { 1604 if (dname[i] == ';') 1605 break; 1606 } 1607 } 1608 } 1609 if (i > 0) { 1610 dnamelen = i; 1611 } else if (fsp->hsfs_vol_type != HS_VOL_TYPE_ISO_V2 && 1612 fsp->hsfs_vol_type != HS_VOL_TYPE_JOLIET) { 1613 dnamelen = strip_trailing(fsp, dname, dnamelen); 1614 } 1615 1616 ASSERT(dnamelen < sizeof (uppercase_name)); 1617 1618 if (fsp->hsfs_vol_type == HS_VOL_TYPE_ISO_V2) { 1619 (void) strncpy(uppercase_name, dname, dnamelen); 1620 } else if (fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET) { 1621 dnamelen = hs_joliet_cp(dname, uppercase_name, 1622 dnamelen); 1623 } else if (uppercase_cp(dname, uppercase_name, 1624 dnamelen)) { 1625 hs_log_bogus_disk_warning(fsp, 1626 HSFS_ERR_LOWER_CASE_NM, 0); 1627 } 1628 dname = uppercase_name; 1629 if (!is_rrip && 1630 (fsp->hsfs_flags & HSFSMNT_NOTRAILDOT) && 1631 dname[dnamelen - 1] == '.' && 1632 CAN_TRUNCATE_DOT(dname, dnamelen)) 1633 dname[--dnamelen] = '\0'; 1634 } 1635 1636 /* 1637 * Quickly screen for a non-matching entry, but not for RRIP. 1638 * This test doesn't work for lowercase vs. uppercase names. 1639 */ 1640 1641 /* if we saw a lower case name we can't do this test either */ 1642 if (strict_iso9660_ordering && !is_rrip && 1643 !HSFS_HAVE_LOWER_CASE(fsp) && *nm < *dname) { 1644 RESTORE_NM(rrip_tmp_name, nm); 1645 PD_return(WENT_PAST) 1646 } 1647 1648 if (*nm != *dname || nmlen != dnamelen) 1649 goto skip_rec; 1650 1651 if ((res = bcmp(dname, nm, nmlen)) == 0) { 1652 /* name matches */ 1653 parsedir_res = hs_parsedir(fsp, dirp, &hd, 1654 (char *)NULL, (int *)NULL, 1655 last_offset - *offset); 1656 if (!parsedir_res) { 1657 uint_t lbn; /* logical block number */ 1658 1659 lbn = dhp->hs_dirent.ext_lbn + 1660 dhp->hs_dirent.xar_len; 1661 /* 1662 * Need to do an fbrelse() on the buffer, 1663 * as hs_makenode() may try to acquire 1664 * hs_hashlock, which may not be required 1665 * while a page is locked. 1666 */ 1667 fbrelse(fbp, S_READ); 1668 did_fbrelse = 1; 1669 *vpp = hs_makenode(&hd, lbn, *offset, 1670 dvp->v_vfsp); 1671 if (*vpp == NULL) { 1672 *error = ENFILE; 1673 RESTORE_NM(rrip_tmp_name, nm); 1674 PD_return(FOUND_ENTRY) 1675 } 1676 1677 dhp->hs_offset = *offset; 1678 RESTORE_NM(rrip_tmp_name, nm); 1679 PD_return(FOUND_ENTRY) 1680 } else if (parsedir_res != EAGAIN) { 1681 /* improper dir entry */ 1682 *error = parsedir_res; 1683 RESTORE_NM(rrip_tmp_name, nm); 1684 PD_return(FOUND_ENTRY) 1685 } 1686 } else if (strict_iso9660_ordering && !is_rrip && 1687 !HSFS_HAVE_LOWER_CASE(fsp) && res < 0) { 1688 /* name < dir entry */ 1689 RESTORE_NM(rrip_tmp_name, nm); 1690 PD_return(WENT_PAST) 1691 } 1692 /* 1693 * name > dir entry, 1694 * look at next one. 1695 */ 1696 skip_rec: 1697 *offset += hdlen; 1698 RESTORE_NM(rrip_tmp_name, nm); 1699 } 1700 PD_return(HIT_END) 1701 1702 do_ret: 1703 if (rrip_name_str) 1704 kmem_free(rrip_name_str, rrip_name_size); 1705 if (rrip_tmp_name) 1706 kmem_free(rrip_tmp_name, rrip_name_size); 1707 if (!did_fbrelse) 1708 fbrelse(fbp, S_READ); 1709 return (err); 1710 #undef PD_return 1711 #undef RESTORE_NM 1712 } 1713 1714 /* 1715 * Strip trailing nulls or spaces from the name; 1716 * return adjusted length. If we find such junk, 1717 * log a non-conformant disk message. 1718 */ 1719 static int 1720 strip_trailing(struct hsfs *fsp, char *nm, int len) 1721 { 1722 char *c; 1723 int trailing_junk = 0; 1724 1725 for (c = nm + len - 1; c > nm; c--) { 1726 if (*c == ' ' || *c == '\0') 1727 trailing_junk = 1; 1728 else 1729 break; 1730 } 1731 1732 if (trailing_junk) 1733 hs_log_bogus_disk_warning(fsp, HSFS_ERR_TRAILING_JUNK, 0); 1734 1735 return ((int)(c - nm + 1)); 1736 } 1737 1738 static int 1739 hs_namelen(struct hsfs *fsp, char *nm, int len) 1740 { 1741 char *p = nm + len; 1742 1743 if (fsp->hsfs_vol_type == HS_VOL_TYPE_ISO_V2) { 1744 return (len); 1745 } else if (fsp->hsfs_vol_type == HS_VOL_TYPE_JOLIET) { 1746 uint16_t c; 1747 1748 while (--p > &nm[1]) { 1749 c = *p; 1750 c |= *--p * 256; 1751 if (c == ';') 1752 return (p - nm); 1753 if (c < '0' || c > '9') { 1754 p++; 1755 return (p - nm); 1756 } 1757 } 1758 } else { 1759 char c; 1760 1761 while (--p > nm) { 1762 c = *p; 1763 if (c == ';') 1764 return (p - nm); 1765 if (c < '0' || c > '9') { 1766 p++; 1767 return (p - nm); 1768 } 1769 } 1770 } 1771 return (len); 1772 } 1773 1774 /* 1775 * Take a UCS-2 character and convert 1776 * it into a utf8 character. 1777 * A 0 will be returned if the conversion fails 1778 * 1779 * See http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 1780 * 1781 * The code has been taken from udfs/udf_subr.c 1782 */ 1783 static uint8_t hs_first_byte_mark[7] = 1784 { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 1785 static int32_t 1786 hs_ucs2_2_utf8(uint16_t c_16, uint8_t *s_8) 1787 { 1788 int32_t nc; 1789 uint32_t c_32; 1790 uint32_t byte_mask = 0xBF; 1791 uint32_t byte_mark = 0x80; 1792 1793 /* 1794 * Convert the 16-bit character to a 32-bit character 1795 */ 1796 c_32 = c_16; 1797 1798 /* 1799 * By here the 16-bit character is converted 1800 * to a 32-bit wide character 1801 */ 1802 if (c_32 < 0x80) { 1803 nc = 1; 1804 } else if (c_32 < 0x800) { 1805 nc = 2; 1806 } else if (c_32 < 0x10000) { 1807 nc = 3; 1808 } else if (c_32 < 0x200000) { 1809 nc = 4; 1810 } else if (c_32 < 0x4000000) { 1811 nc = 5; 1812 } else if (c_32 <= 0x7FFFFFFF) { /* avoid signed overflow */ 1813 nc = 6; 1814 } else { 1815 nc = 0; 1816 } 1817 s_8 += nc; 1818 switch (nc) { 1819 case 6 : 1820 *(--s_8) = (c_32 | byte_mark) & byte_mask; 1821 c_32 >>= 6; 1822 /* FALLTHROUGH */ 1823 case 5 : 1824 *(--s_8) = (c_32 | byte_mark) & byte_mask; 1825 c_32 >>= 6; 1826 /* FALLTHROUGH */ 1827 case 4 : 1828 *(--s_8) = (c_32 | byte_mark) & byte_mask; 1829 c_32 >>= 6; 1830 /* FALLTHROUGH */ 1831 case 3 : 1832 *(--s_8) = (c_32 | byte_mark) & byte_mask; 1833 c_32 >>= 6; 1834 /* FALLTHROUGH */ 1835 case 2 : 1836 *(--s_8) = (c_32 | byte_mark) & byte_mask; 1837 c_32 >>= 6; 1838 /* FALLTHROUGH */ 1839 case 1 : 1840 *(--s_8) = c_32 | hs_first_byte_mark[nc]; 1841 } 1842 return (nc); 1843 } 1844