17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*b39a0235SMilan Cermak * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <sys/types.h> 267c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 277c478bd9Sstevel@tonic-gate #include <sys/param.h> 287c478bd9Sstevel@tonic-gate #include <sys/time.h> 297c478bd9Sstevel@tonic-gate #include <sys/systm.h> 307c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 317c478bd9Sstevel@tonic-gate #include <sys/resource.h> 327c478bd9Sstevel@tonic-gate #include <sys/signal.h> 337c478bd9Sstevel@tonic-gate #include <sys/cred.h> 347c478bd9Sstevel@tonic-gate #include <sys/user.h> 357c478bd9Sstevel@tonic-gate #include <sys/buf.h> 367c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 397c478bd9Sstevel@tonic-gate #include <sys/mode.h> 407c478bd9Sstevel@tonic-gate #include <sys/proc.h> 417c478bd9Sstevel@tonic-gate #include <sys/disp.h> 427c478bd9Sstevel@tonic-gate #include <sys/file.h> 437c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 447c478bd9Sstevel@tonic-gate #include <sys/flock.h> 457c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 467c478bd9Sstevel@tonic-gate #include <sys/uio.h> 477c478bd9Sstevel@tonic-gate #include <sys/dnlc.h> 487c478bd9Sstevel@tonic-gate #include <sys/conf.h> 497c478bd9Sstevel@tonic-gate #include <sys/errno.h> 507c478bd9Sstevel@tonic-gate #include <sys/mman.h> 517c478bd9Sstevel@tonic-gate #include <sys/fbuf.h> 527c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 537c478bd9Sstevel@tonic-gate #include <sys/debug.h> 547c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 557c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 567c478bd9Sstevel@tonic-gate #include <sys/dirent.h> 577c478bd9Sstevel@tonic-gate #include <sys/errno.h> 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 607c478bd9Sstevel@tonic-gate #include <sys/mount.h> 617c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 627c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 637c478bd9Sstevel@tonic-gate #include <sys/policy.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #include <vm/hat.h> 667c478bd9Sstevel@tonic-gate #include <vm/page.h> 677c478bd9Sstevel@tonic-gate #include <vm/pvn.h> 687c478bd9Sstevel@tonic-gate #include <vm/as.h> 697c478bd9Sstevel@tonic-gate #include <vm/seg.h> 707c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 717c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 727c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h> 737c478bd9Sstevel@tonic-gate #include <vm/rm.h> 747c478bd9Sstevel@tonic-gate #include <vm/page.h> 757c478bd9Sstevel@tonic-gate #include <sys/swap.h> 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate #include <sys/fs/udf_volume.h> 827c478bd9Sstevel@tonic-gate #include <sys/fs/udf_inode.h> 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate int32_t ud_trace; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * HASH chains and mutex 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate extern union ihead ud_ihead[UD_HASH_SZ]; 907c478bd9Sstevel@tonic-gate extern kmutex_t ud_icache_lock; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate extern kmutex_t ud_sync_busy; 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * udf_vfs list manipulation routines 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate extern kmutex_t udf_vfs_mutex; 987c478bd9Sstevel@tonic-gate extern struct udf_vfs *udf_vfs_instances; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * Used to verify that a given entry on the udf_instances list (see below) 1027c478bd9Sstevel@tonic-gate * still refers to a mounted file system. 1037c478bd9Sstevel@tonic-gate * 1047c478bd9Sstevel@tonic-gate * XXX: This is a crock that substitutes for proper locking to coordinate 1057c478bd9Sstevel@tonic-gate * updates to and uses of the entries in udf_instances. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate struct check_node { 1087c478bd9Sstevel@tonic-gate struct vfs *vfsp; 1097c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfs; 1107c478bd9Sstevel@tonic-gate dev_t vfs_dev; 1117c478bd9Sstevel@tonic-gate }; 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate vfs_t *ud_still_mounted(struct check_node *); 1147c478bd9Sstevel@tonic-gate void ud_checkclean(struct vfs *, 1157c478bd9Sstevel@tonic-gate struct udf_vfs *, dev_t, time_t); 1167c478bd9Sstevel@tonic-gate int32_t ud_icheck(struct udf_vfs *); 1177c478bd9Sstevel@tonic-gate void ud_flushi(int32_t); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Link udf_vfsp in at the head of the list of udf_vfs_instances. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate void 1237c478bd9Sstevel@tonic-gate ud_vfs_add(struct udf_vfs *udf_vfsp) 1247c478bd9Sstevel@tonic-gate { 1257c478bd9Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex); 1267c478bd9Sstevel@tonic-gate udf_vfsp->udf_next = udf_vfs_instances; 1277c478bd9Sstevel@tonic-gate udf_vfs_instances = udf_vfsp; 1287c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Remove udf_vfsp from the list of udf_vfs_instances. 1337c478bd9Sstevel@tonic-gate * 1347c478bd9Sstevel@tonic-gate * Does no error checking; udf_vfsp is assumed to actually be on the list. 1357c478bd9Sstevel@tonic-gate */ 1367c478bd9Sstevel@tonic-gate void 1377c478bd9Sstevel@tonic-gate ud_vfs_remove(struct udf_vfs *udf_vfsp) 1387c478bd9Sstevel@tonic-gate { 1397c478bd9Sstevel@tonic-gate struct udf_vfs **delpt = &udf_vfs_instances; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex); 1427c478bd9Sstevel@tonic-gate for (; *delpt != NULL; delpt = &((*delpt)->udf_next)) { 1437c478bd9Sstevel@tonic-gate if (*delpt == udf_vfsp) { 1447c478bd9Sstevel@tonic-gate *delpt = udf_vfsp->udf_next; 1457c478bd9Sstevel@tonic-gate udf_vfsp->udf_next = NULL; 1467c478bd9Sstevel@tonic-gate break; 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * Search for the prn in the array 1547c478bd9Sstevel@tonic-gate * of partitions and translate 1557c478bd9Sstevel@tonic-gate * to the disk block number 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate daddr_t 1587c478bd9Sstevel@tonic-gate ud_xlate_to_daddr(struct udf_vfs *udf_vfsp, 1597c478bd9Sstevel@tonic-gate uint16_t prn, uint32_t blkno, int32_t nblks, uint32_t *count) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate int32_t i; 1627c478bd9Sstevel@tonic-gate struct ud_map *map; 1637c478bd9Sstevel@tonic-gate struct ud_part *ud_parts; 1647c478bd9Sstevel@tonic-gate uint32_t lblkno, retblkno = 0, *addr; 1657c478bd9Sstevel@tonic-gate uint32_t begin_req, end_req; 1667c478bd9Sstevel@tonic-gate uint32_t begin_bad, end_bad; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate ud_printf("ud_xlate_to_daddr\n"); 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* Is prn valid */ 1717c478bd9Sstevel@tonic-gate if (prn < udf_vfsp->udf_nmaps) { 1727c478bd9Sstevel@tonic-gate map = &(udf_vfsp->udf_maps[prn]); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if (map->udm_flags == UDM_MAP_VPM) { 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Map is Virtual Parition Map 1777c478bd9Sstevel@tonic-gate * first check for the appropriate 1787c478bd9Sstevel@tonic-gate * table and then return the converted 1797c478bd9Sstevel@tonic-gate * block number 1807c478bd9Sstevel@tonic-gate */ 1817c478bd9Sstevel@tonic-gate for (i = 0; i < map->udm_nent; i++) { 1827c478bd9Sstevel@tonic-gate if (blkno < map->udm_count[i]) { 1837c478bd9Sstevel@tonic-gate addr = map->udm_addr[i]; 1847c478bd9Sstevel@tonic-gate lblkno = SWAP_32(addr[blkno]); 1857c478bd9Sstevel@tonic-gate *count = 1; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate } else { 1887c478bd9Sstevel@tonic-gate blkno -= map->udm_count[i]; 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate } else if (map->udm_flags == UDM_MAP_SPM) { 1927c478bd9Sstevel@tonic-gate struct stbl *stbl; 1937c478bd9Sstevel@tonic-gate struct stbl_entry *te; 1947c478bd9Sstevel@tonic-gate int32_t entry_count; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * Map type is Sparable Parition Map 1987c478bd9Sstevel@tonic-gate * if the block is in the map 1997c478bd9Sstevel@tonic-gate * return the translated block 2007c478bd9Sstevel@tonic-gate * other wise use the regular 2017c478bd9Sstevel@tonic-gate * partition stuff 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate begin_req = blkno; 2047c478bd9Sstevel@tonic-gate end_req = begin_req + nblks; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate stbl = (struct stbl *)map->udm_spaddr[0]; 2077c478bd9Sstevel@tonic-gate te = (struct stbl_entry *)&stbl->stbl_entry; 2087c478bd9Sstevel@tonic-gate entry_count = SWAP_16(stbl->stbl_len); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate for (i = 0; i < entry_count; i++, te++) { 2117c478bd9Sstevel@tonic-gate begin_bad = SWAP_32(te->sent_ol); 2127c478bd9Sstevel@tonic-gate end_bad = begin_bad + map->udm_plen; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Either unmapped or reserved 2167c478bd9Sstevel@tonic-gate * or defective. need not consider 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate if (begin_bad >= (uint32_t)0xFFFFFFF0) { 2197c478bd9Sstevel@tonic-gate continue; 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate if ((end_req < begin_bad) || 2227c478bd9Sstevel@tonic-gate (begin_req >= end_bad)) { 2237c478bd9Sstevel@tonic-gate continue; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (begin_req < begin_bad) { 2277c478bd9Sstevel@tonic-gate ASSERT(end_req >= begin_bad); 2287c478bd9Sstevel@tonic-gate end_req = begin_bad; 2297c478bd9Sstevel@tonic-gate } else { 2307c478bd9Sstevel@tonic-gate retblkno = SWAP_32(te->sent_ml) + 2317c478bd9Sstevel@tonic-gate begin_req - begin_bad; 2327c478bd9Sstevel@tonic-gate if (end_req < end_bad) { 2337c478bd9Sstevel@tonic-gate *count = end_req - begin_req; 2347c478bd9Sstevel@tonic-gate } else { 2357c478bd9Sstevel@tonic-gate *count = end_bad - begin_req; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate goto end; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate lblkno = blkno; 2427c478bd9Sstevel@tonic-gate *count = end_req - begin_req; 2437c478bd9Sstevel@tonic-gate } else { 2447c478bd9Sstevel@tonic-gate /* 2457c478bd9Sstevel@tonic-gate * regular partition 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate lblkno = blkno; 2487c478bd9Sstevel@tonic-gate *count = nblks; 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate ud_parts = udf_vfsp->udf_parts; 2517c478bd9Sstevel@tonic-gate for (i = 0; i < udf_vfsp->udf_npart; i++) { 2527c478bd9Sstevel@tonic-gate if (map->udm_pn == ud_parts->udp_number) { 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Check if the block is inside 2557c478bd9Sstevel@tonic-gate * the partition or not 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate if (lblkno >= ud_parts->udp_length) { 2587c478bd9Sstevel@tonic-gate retblkno = 0; 2597c478bd9Sstevel@tonic-gate } else { 2607c478bd9Sstevel@tonic-gate retblkno = ud_parts->udp_start + lblkno; 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate goto end; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate ud_parts ++; 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate end: 2697c478bd9Sstevel@tonic-gate return (retblkno); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate #ifdef UNDEF 2737c478bd9Sstevel@tonic-gate uint32_t 2747c478bd9Sstevel@tonic-gate ud_xlate_to_addr(struct udf_vfs *udf_vfsp, 2757c478bd9Sstevel@tonic-gate uint16_t prn, daddr_t blkno, int32_t lad) 2767c478bd9Sstevel@tonic-gate { 2777c478bd9Sstevel@tonic-gate int32_t i; 2787c478bd9Sstevel@tonic-gate struct ud_part *ud_parts; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate ud_printf("ud_xlate_to_addr\n"); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate if (lad == 0) { 2837c478bd9Sstevel@tonic-gate return (blkno); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate ud_parts = udf_vfsp->udf_parts; 2867c478bd9Sstevel@tonic-gate for (i = 0; i < udf_vfsp->udf_npart; i++) { 2877c478bd9Sstevel@tonic-gate if (prn == ud_parts->udp_number) { 2887c478bd9Sstevel@tonic-gate return (blkno - ud_parts->udp_start); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate return (0); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate #endif 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Directories do not have holes 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate int32_t 2997c478bd9Sstevel@tonic-gate ud_ip_off2bno(struct ud_inode *ip, uint32_t offset, uint32_t *bno) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate int32_t i, error; 3027c478bd9Sstevel@tonic-gate struct icb_ext *iext; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate ASSERT(ip->i_type == VDIR); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 3077c478bd9Sstevel@tonic-gate *bno = ip->i_icb_block; 3087c478bd9Sstevel@tonic-gate return (0); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, (u_offset_t)offset)) != 0) { 3127c478bd9Sstevel@tonic-gate return (error); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) { 3167c478bd9Sstevel@tonic-gate iext = &ip->i_ext[i]; 3177c478bd9Sstevel@tonic-gate if ((iext->ib_offset <= offset) && 3187c478bd9Sstevel@tonic-gate (offset < (iext->ib_offset + iext->ib_count))) { 3197c478bd9Sstevel@tonic-gate *bno = iext->ib_block + 3207c478bd9Sstevel@tonic-gate ((offset - iext->ib_offset) >> 3217c478bd9Sstevel@tonic-gate ip->i_udf->udf_l2b_shift); 3227c478bd9Sstevel@tonic-gate break; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate return (0); 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate static uint32_t cum_sec[] = { 3297c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280, 3307c478bd9Sstevel@tonic-gate 0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500 3317c478bd9Sstevel@tonic-gate }; 3327c478bd9Sstevel@tonic-gate static uint32_t cum_sec_leap[] = { 3337c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400, 3347c478bd9Sstevel@tonic-gate 0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680 3357c478bd9Sstevel@tonic-gate }; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate #define DAYS_PER_YEAR 365 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate #define SEC_PER_DAY 0x15180 3407c478bd9Sstevel@tonic-gate #define SEC_PER_YEAR 0x1e13380 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /* This holds good till yr 2100 */ 3447c478bd9Sstevel@tonic-gate void 3457c478bd9Sstevel@tonic-gate ud_dtime2utime(struct timespec32 *utime, 3467c478bd9Sstevel@tonic-gate struct tstamp const *dtime) 3477c478bd9Sstevel@tonic-gate { 3487c478bd9Sstevel@tonic-gate int16_t year, tzone; 3497c478bd9Sstevel@tonic-gate int32_t sec; 3507c478bd9Sstevel@tonic-gate uint32_t *cp; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate ud_printf("ud_dtime2utime\n"); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate year = SWAP_16(dtime->ts_year); 3557c478bd9Sstevel@tonic-gate cp = (year % 4) ? cum_sec : cum_sec_leap; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate utime->tv_sec = cp[dtime->ts_month - 1]; 3587c478bd9Sstevel@tonic-gate utime->tv_sec += (dtime->ts_day - 1) * SEC_PER_DAY; 3597c478bd9Sstevel@tonic-gate utime->tv_sec += ((dtime->ts_hour * 60) + 3607c478bd9Sstevel@tonic-gate dtime->ts_min) * 60 + 3617c478bd9Sstevel@tonic-gate dtime->ts_sec; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate tzone = SWAP_16(dtime->ts_tzone); 3647c478bd9Sstevel@tonic-gate if ((tzone & TMODE) == 0x1000) { 3657c478bd9Sstevel@tonic-gate /* Local time */ 3667c478bd9Sstevel@tonic-gate if ((tzone & TINVALID) != TINVALID) { 3677c478bd9Sstevel@tonic-gate if (tzone & TSIGN) { 3687c478bd9Sstevel@tonic-gate /* 3697c478bd9Sstevel@tonic-gate * Sign extend the tzone 3707c478bd9Sstevel@tonic-gate */ 3717c478bd9Sstevel@tonic-gate sec = tzone | 0xFFFFF000; 3727c478bd9Sstevel@tonic-gate } else { 3737c478bd9Sstevel@tonic-gate sec = tzone & TOFFSET; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate sec *= 60; 3767c478bd9Sstevel@tonic-gate utime->tv_sec -= sec; 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate utime->tv_nsec = ((((dtime->ts_csec * 100) + 3817c478bd9Sstevel@tonic-gate dtime->ts_husec) * 100) + 3827c478bd9Sstevel@tonic-gate dtime->ts_usec) * 1000; 3837c478bd9Sstevel@tonic-gate if (year >= 1970) { 3847c478bd9Sstevel@tonic-gate utime->tv_sec += (year - 1970) * SEC_PER_YEAR; 3857c478bd9Sstevel@tonic-gate utime->tv_sec += ((year - 1969) / 4) * SEC_PER_DAY; 3867c478bd9Sstevel@tonic-gate } else { 3877c478bd9Sstevel@tonic-gate utime->tv_sec = ((1970 - year) * SEC_PER_YEAR + 3887c478bd9Sstevel@tonic-gate ((1972 - year) / 4) * SEC_PER_DAY - 3897c478bd9Sstevel@tonic-gate utime->tv_sec) * -1; 3907c478bd9Sstevel@tonic-gate if (utime->tv_nsec) { 3917c478bd9Sstevel@tonic-gate utime->tv_sec++; 3927c478bd9Sstevel@tonic-gate utime->tv_nsec = 1000 * 1000 * 1000 - utime->tv_nsec; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate void 3987c478bd9Sstevel@tonic-gate ud_utime2dtime(struct timespec32 const *utime, 3997c478bd9Sstevel@tonic-gate struct tstamp *dtime) 4007c478bd9Sstevel@tonic-gate { 4017c478bd9Sstevel@tonic-gate time32_t sec = utime->tv_sec; 4027c478bd9Sstevel@tonic-gate int32_t usec = utime->tv_nsec / 1000; 4037c478bd9Sstevel@tonic-gate uint32_t lyrs, nyrs, dummy; 4047c478bd9Sstevel@tonic-gate uint32_t *cp; 4057c478bd9Sstevel@tonic-gate int32_t before = 0; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate ud_printf("ud_utime2dtime\n"); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate if (sec < 0) { 4107c478bd9Sstevel@tonic-gate before = 1; 4117c478bd9Sstevel@tonic-gate sec = sec * -1; 4127c478bd9Sstevel@tonic-gate if (usec) { 4137c478bd9Sstevel@tonic-gate sec = sec + 1; 4147c478bd9Sstevel@tonic-gate usec = 1000 * 1000 - usec; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate dtime->ts_csec = usec / 10000; 4197c478bd9Sstevel@tonic-gate usec %= 10000; 4207c478bd9Sstevel@tonic-gate dtime->ts_husec = usec / 100; 4217c478bd9Sstevel@tonic-gate dtime->ts_usec = usec % 100; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate nyrs = sec / SEC_PER_YEAR; 4247c478bd9Sstevel@tonic-gate if (before == 0) { 4257c478bd9Sstevel@tonic-gate lyrs = (nyrs + 1) / 4; 4267c478bd9Sstevel@tonic-gate } else { 4277c478bd9Sstevel@tonic-gate lyrs = (nyrs + 2) / 4; 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate if (nyrs != ((sec - (lyrs * SEC_PER_DAY)) / SEC_PER_YEAR)) { 4307c478bd9Sstevel@tonic-gate nyrs--; 4317c478bd9Sstevel@tonic-gate if (before == 0) { 4327c478bd9Sstevel@tonic-gate lyrs = (nyrs + 1) / 4; 4337c478bd9Sstevel@tonic-gate } else { 4347c478bd9Sstevel@tonic-gate lyrs = (nyrs + 2) / 4; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate sec -= nyrs * SEC_PER_YEAR + lyrs * SEC_PER_DAY; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate if (before == 1) { 4407c478bd9Sstevel@tonic-gate nyrs = 1970 - nyrs; 4417c478bd9Sstevel@tonic-gate if (sec != 0) { 4427c478bd9Sstevel@tonic-gate nyrs --; 4437c478bd9Sstevel@tonic-gate if ((nyrs % 4) == 0) { 4447c478bd9Sstevel@tonic-gate sec = SEC_PER_YEAR + SEC_PER_DAY - sec; 4457c478bd9Sstevel@tonic-gate } else { 4467c478bd9Sstevel@tonic-gate sec = SEC_PER_YEAR - sec; 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate } else { 4507c478bd9Sstevel@tonic-gate nyrs += 1970; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate cp = (nyrs % 4) ? cum_sec : cum_sec_leap; 4537c478bd9Sstevel@tonic-gate dummy = sec / (SEC_PER_DAY * 29); 4547c478bd9Sstevel@tonic-gate if (dummy > 11) { 4557c478bd9Sstevel@tonic-gate dummy = 11; 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate if (sec < cp[dummy]) { 4587c478bd9Sstevel@tonic-gate dummy--; 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate dtime->ts_year = SWAP_16(nyrs); 4617c478bd9Sstevel@tonic-gate dtime->ts_month = dummy; 4627c478bd9Sstevel@tonic-gate sec -= cp[dtime->ts_month]; 4637c478bd9Sstevel@tonic-gate dtime->ts_month++; 4647c478bd9Sstevel@tonic-gate dtime->ts_day = sec / SEC_PER_DAY; 4657c478bd9Sstevel@tonic-gate sec -= dtime->ts_day * SEC_PER_DAY; 4667c478bd9Sstevel@tonic-gate dtime->ts_day++; 4677c478bd9Sstevel@tonic-gate dtime->ts_hour = sec / SECS_PER_HOUR; 4687c478bd9Sstevel@tonic-gate sec -= dtime->ts_hour * SECS_PER_HOUR; 4697c478bd9Sstevel@tonic-gate dtime->ts_min = sec / SECS_PER_MIN; 4707c478bd9Sstevel@tonic-gate sec -= dtime->ts_min * SECS_PER_MIN; 4717c478bd9Sstevel@tonic-gate dtime->ts_sec = (uint8_t)sec; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* GMT offset is 0 */ 4747c478bd9Sstevel@tonic-gate dtime->ts_tzone = SWAP_16(0x1000); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate int32_t 4797c478bd9Sstevel@tonic-gate ud_syncip(struct ud_inode *ip, int32_t flags, int32_t waitfor) 4807c478bd9Sstevel@tonic-gate { 4817c478bd9Sstevel@tonic-gate int32_t error; 4827c478bd9Sstevel@tonic-gate struct vnode *vp = ITOV(ip); 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate ud_printf("ud_syncip\n"); 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate if (ip->i_udf == NULL) { 4877c478bd9Sstevel@tonic-gate return (0); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate if (!vn_has_cached_data(vp) || (vp->v_type == VCHR)) { 4917c478bd9Sstevel@tonic-gate error = 0; 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 4947c478bd9Sstevel@tonic-gate error = VOP_PUTPAGE(vp, (offset_t)0, 495da6c28aaSamw (uint32_t)0, flags, CRED(), NULL); 4967c478bd9Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate if (ip->i_flag & (IUPD |IACC | ICHG | IMOD)) { 5007c478bd9Sstevel@tonic-gate ud_iupdat(ip, waitfor); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate return (error); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5087c478bd9Sstevel@tonic-gate int32_t 5097c478bd9Sstevel@tonic-gate ud_fbwrite(struct fbuf *fbp, struct ud_inode *ip) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate ud_printf("ud_fbwrite\n"); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate ASSERT(fbp != NULL); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate return (fbwrite(fbp)); 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate void 5207c478bd9Sstevel@tonic-gate ud_sbwrite(struct udf_vfs *udf_vfsp) 5217c478bd9Sstevel@tonic-gate { 5227c478bd9Sstevel@tonic-gate struct log_vol_int_desc *lvid; 5237c478bd9Sstevel@tonic-gate struct ud_part *ud_part; 5247c478bd9Sstevel@tonic-gate struct lvid_iu *iu; 5257c478bd9Sstevel@tonic-gate uint32_t *temp; 5267c478bd9Sstevel@tonic-gate int32_t i, c; 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate ud_printf("ud_sbwrite\n"); 5297c478bd9Sstevel@tonic-gate ASSERT(udf_vfsp); 5307c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&udf_vfsp->udf_lock)); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * updatable information in the superblock 5347c478bd9Sstevel@tonic-gate * integrity type, udf_maxuniq, udf_nfiles, udf_ndirs 5357c478bd9Sstevel@tonic-gate * udp_nfree in lvid 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate lvid = (struct log_vol_int_desc *)udf_vfsp->udf_lvid; 5387c478bd9Sstevel@tonic-gate if (udf_vfsp->udf_clean == UDF_DIRTY) { 5397c478bd9Sstevel@tonic-gate lvid->lvid_int_type = SWAP_32(LOG_VOL_OPEN_INT); 5407c478bd9Sstevel@tonic-gate } else { 5417c478bd9Sstevel@tonic-gate lvid->lvid_int_type = SWAP_32(LOG_VOL_CLOSE_INT); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate lvid->lvid_uniqid = SWAP_64(udf_vfsp->udf_maxuniq); 5447c478bd9Sstevel@tonic-gate temp = lvid->lvid_fst; 5457c478bd9Sstevel@tonic-gate c = SWAP_32(lvid->lvid_npart); 5467c478bd9Sstevel@tonic-gate ud_part = udf_vfsp->udf_parts; 5477c478bd9Sstevel@tonic-gate for (i = 0; i < c; i++) { 5487c478bd9Sstevel@tonic-gate temp[i] = SWAP_32(ud_part->udp_nfree); 5497c478bd9Sstevel@tonic-gate ud_part++; 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate iu = (struct lvid_iu *)(temp + c * 2); 5527c478bd9Sstevel@tonic-gate iu->lvidiu_nfiles = SWAP_32(udf_vfsp->udf_nfiles); 5537c478bd9Sstevel@tonic-gate iu->lvidiu_ndirs = SWAP_32(udf_vfsp->udf_ndirs); 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate ud_update_regid(&iu->lvidiu_regid); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate ud_make_tag(udf_vfsp, &lvid->lvid_tag, 5587c478bd9Sstevel@tonic-gate UD_LOG_VOL_INT, udf_vfsp->udf_iseq_loc, 5597c478bd9Sstevel@tonic-gate sizeof (struct log_vol_int_desc) - 8 + 5607c478bd9Sstevel@tonic-gate 8 * udf_vfsp->udf_npart + 5617c478bd9Sstevel@tonic-gate SWAP_32(lvid->lvid_liu)); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * Don't release the buffer after writing to the disk 5657c478bd9Sstevel@tonic-gate */ 5667c478bd9Sstevel@tonic-gate bwrite2(udf_vfsp->udf_iseq); 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate 5707c478bd9Sstevel@tonic-gate int32_t 5717c478bd9Sstevel@tonic-gate ud_sync_indir(struct ud_inode *ip) 5727c478bd9Sstevel@tonic-gate { 5737c478bd9Sstevel@tonic-gate int32_t elen; 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate ud_printf("ud_sync_indir\n"); 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) { 5787c478bd9Sstevel@tonic-gate return (0); 5797c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_SHORT_AD) { 5807c478bd9Sstevel@tonic-gate elen = sizeof (struct short_ad); 5817c478bd9Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) { 5827c478bd9Sstevel@tonic-gate elen = sizeof (struct long_ad); 5837c478bd9Sstevel@tonic-gate } else { 5847c478bd9Sstevel@tonic-gate return (EINVAL); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate if (ip->i_astrat == STRAT_TYPE4) { 5887c478bd9Sstevel@tonic-gate int32_t ndentry; 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate ndentry = ip->i_max_emb / elen; 5917c478bd9Sstevel@tonic-gate if (ip->i_ext_used < ndentry) { 5927c478bd9Sstevel@tonic-gate return (0); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate ASSERT(ip->i_con); 5957c478bd9Sstevel@tonic-gate } else { 5967c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "unsupported strategy type\n"); 5977c478bd9Sstevel@tonic-gate return (EINVAL); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate return (0); 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate void 6047c478bd9Sstevel@tonic-gate ud_update(int32_t flag) 6057c478bd9Sstevel@tonic-gate { 6067c478bd9Sstevel@tonic-gate struct vfs *vfsp; 6077c478bd9Sstevel@tonic-gate struct udf_vfs *udfsp, *udfsnext, *update_list = NULL; 6087c478bd9Sstevel@tonic-gate int32_t check_cnt = 0; 6097c478bd9Sstevel@tonic-gate size_t check_size; 6107c478bd9Sstevel@tonic-gate struct check_node *check_list, *ptr; 6117c478bd9Sstevel@tonic-gate time_t start_time; 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate ud_printf("ud_update\n"); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate mutex_enter(&ud_sync_busy); 6167c478bd9Sstevel@tonic-gate /* 6177c478bd9Sstevel@tonic-gate * Examine all udf_vfs structures and add those that we can lock to the 6187c478bd9Sstevel@tonic-gate * update list. This is so that we don't hold the list lock for a 6197c478bd9Sstevel@tonic-gate * long time. If vfs_lock fails for a file system instance, then skip 6207c478bd9Sstevel@tonic-gate * it because somebody is doing a unmount on it. 6217c478bd9Sstevel@tonic-gate */ 6227c478bd9Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex); 6237c478bd9Sstevel@tonic-gate for (udfsp = udf_vfs_instances; 6247c478bd9Sstevel@tonic-gate udfsp != NULL; udfsp = udfsp->udf_next) { 6257c478bd9Sstevel@tonic-gate vfsp = udfsp->udf_vfs; 6267c478bd9Sstevel@tonic-gate if (vfs_lock(vfsp) != 0) { 6277c478bd9Sstevel@tonic-gate continue; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate udfsp->udf_wnext = update_list; 6307c478bd9Sstevel@tonic-gate update_list = udfsp; 6317c478bd9Sstevel@tonic-gate check_cnt++; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex); 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate if (update_list == NULL) { 6367c478bd9Sstevel@tonic-gate mutex_exit(&ud_sync_busy); 6377c478bd9Sstevel@tonic-gate return; 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate check_size = sizeof (struct check_node) * check_cnt; 6417c478bd9Sstevel@tonic-gate check_list = ptr = kmem_alloc(check_size, KM_NOSLEEP); 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* 6447c478bd9Sstevel@tonic-gate * Write back modified superblocks. 6457c478bd9Sstevel@tonic-gate * Consistency check that the superblock of 6467c478bd9Sstevel@tonic-gate * each file system is still in the buffer cache. 6477c478bd9Sstevel@tonic-gate * 6487c478bd9Sstevel@tonic-gate * Note that the update_list traversal is done without the protection 6497c478bd9Sstevel@tonic-gate * of an overall list lock, so it's necessary to rely on the fact that 6507c478bd9Sstevel@tonic-gate * each entry of the list is vfs_locked when moving from one entry to 6517c478bd9Sstevel@tonic-gate * the next. This works because a concurrent attempt to add an entry 6527c478bd9Sstevel@tonic-gate * to another thread's update_list won't find it, since it'll already 6537c478bd9Sstevel@tonic-gate * be locked. 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate check_cnt = 0; 6567c478bd9Sstevel@tonic-gate for (udfsp = update_list; udfsp != NULL; udfsp = udfsnext) { 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * Need to grab the next ptr before we unlock this one so 6597c478bd9Sstevel@tonic-gate * another thread doesn't grab it and change it before we move 6607c478bd9Sstevel@tonic-gate * on to the next vfs. (Once we unlock it, it's ok if another 6617c478bd9Sstevel@tonic-gate * thread finds it to add it to its own update_list; we don't 6627c478bd9Sstevel@tonic-gate * attempt to refer to it through our list any more.) 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate udfsnext = udfsp->udf_wnext; 6657c478bd9Sstevel@tonic-gate vfsp = udfsp->udf_vfs; 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate if (!vfsp->vfs_data) { 6687c478bd9Sstevel@tonic-gate vfs_unlock(vfsp); 6697c478bd9Sstevel@tonic-gate continue; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate mutex_enter(&udfsp->udf_lock); 6727c478bd9Sstevel@tonic-gate 6737c478bd9Sstevel@tonic-gate /* 6747c478bd9Sstevel@tonic-gate * Build up the STABLE check list, so we can unlock the vfs 6757c478bd9Sstevel@tonic-gate * until we do the actual checking. 6767c478bd9Sstevel@tonic-gate */ 6777c478bd9Sstevel@tonic-gate if (check_list != NULL) { 6787c478bd9Sstevel@tonic-gate if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) { 6797c478bd9Sstevel@tonic-gate ptr->vfsp = vfsp; 6807c478bd9Sstevel@tonic-gate ptr->udf_vfs = udfsp; 6817c478bd9Sstevel@tonic-gate ptr->vfs_dev = vfsp->vfs_dev; 6827c478bd9Sstevel@tonic-gate ptr++; 6837c478bd9Sstevel@tonic-gate check_cnt++; 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate /* 6887c478bd9Sstevel@tonic-gate * superblock is not modified 6897c478bd9Sstevel@tonic-gate */ 6907c478bd9Sstevel@tonic-gate if (udfsp->udf_mod == 0) { 6917c478bd9Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock); 6927c478bd9Sstevel@tonic-gate vfs_unlock(vfsp); 6937c478bd9Sstevel@tonic-gate continue; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) { 6967c478bd9Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock); 6977c478bd9Sstevel@tonic-gate mutex_exit(&ud_sync_busy); 6987c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "update ro udfs mod\n"); 6997c478bd9Sstevel@tonic-gate return; 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate udfsp->udf_mod = 0; 7027c478bd9Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate ud_update_superblock(vfsp); 7057c478bd9Sstevel@tonic-gate vfs_unlock(vfsp); 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate ud_flushi(flag); 7097c478bd9Sstevel@tonic-gate /* 7107c478bd9Sstevel@tonic-gate * Force stale buffer cache information to be flushed, 7117c478bd9Sstevel@tonic-gate * for all devices. This should cause any remaining control 7127c478bd9Sstevel@tonic-gate * information (e.g., inode info) to be flushed back. 7137c478bd9Sstevel@tonic-gate */ 7147c478bd9Sstevel@tonic-gate bflush((dev_t)NODEV); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate if (check_list == NULL) { 7177c478bd9Sstevel@tonic-gate mutex_exit(&ud_sync_busy); 7187c478bd9Sstevel@tonic-gate return; 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate /* 7227c478bd9Sstevel@tonic-gate * For each udf filesystem in the STABLE check_list, update 7237c478bd9Sstevel@tonic-gate * the clean flag if warranted. 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate start_time = gethrestime_sec(); 7267c478bd9Sstevel@tonic-gate for (ptr = check_list; check_cnt > 0; check_cnt--, ptr++) { 7277c478bd9Sstevel@tonic-gate /* 7287c478bd9Sstevel@tonic-gate * ud_still_mounted() returns with vfsp and the vfs_reflock 7297c478bd9Sstevel@tonic-gate * held if ptr refers to a vfs that is still mounted. 7307c478bd9Sstevel@tonic-gate */ 7317c478bd9Sstevel@tonic-gate if ((vfsp = ud_still_mounted(ptr)) == NULL) { 7327c478bd9Sstevel@tonic-gate continue; 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate ud_checkclean(vfsp, ptr->udf_vfs, ptr->vfs_dev, start_time); 7357c478bd9Sstevel@tonic-gate vfs_unlock(vfsp); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate mutex_exit(&ud_sync_busy); 7387c478bd9Sstevel@tonic-gate kmem_free(check_list, check_size); 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* 7437c478bd9Sstevel@tonic-gate * Returns vfsp and hold the lock if the vfs is still being mounted. 7447c478bd9Sstevel@tonic-gate * Otherwise, returns 0. 7457c478bd9Sstevel@tonic-gate * 7467c478bd9Sstevel@tonic-gate * For our purposes, "still mounted" means that the file system still appears 7477c478bd9Sstevel@tonic-gate * on the list of UFS file system instances. 7487c478bd9Sstevel@tonic-gate */ 7497c478bd9Sstevel@tonic-gate vfs_t * 7507c478bd9Sstevel@tonic-gate ud_still_mounted(struct check_node *checkp) 7517c478bd9Sstevel@tonic-gate { 7527c478bd9Sstevel@tonic-gate struct vfs *vfsp; 7537c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate ud_printf("ud_still_mounted\n"); 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex); 7587c478bd9Sstevel@tonic-gate for (udf_vfsp = udf_vfs_instances; 7597c478bd9Sstevel@tonic-gate udf_vfsp != NULL; udf_vfsp = udf_vfsp->udf_next) { 7607c478bd9Sstevel@tonic-gate if (udf_vfsp != checkp->udf_vfs) { 7617c478bd9Sstevel@tonic-gate continue; 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * Tentative match: verify it and try to lock. (It's not at 7657c478bd9Sstevel@tonic-gate * all clear how the verification could fail, given that we've 7667c478bd9Sstevel@tonic-gate * gotten this far. We would have had to reallocate the 7677c478bd9Sstevel@tonic-gate * ufsvfs struct at hand for a new incarnation; is that really 7687c478bd9Sstevel@tonic-gate * possible in the interval from constructing the check_node 7697c478bd9Sstevel@tonic-gate * to here?) 7707c478bd9Sstevel@tonic-gate */ 7717c478bd9Sstevel@tonic-gate vfsp = udf_vfsp->udf_vfs; 7727c478bd9Sstevel@tonic-gate if (vfsp != checkp->vfsp) { 7737c478bd9Sstevel@tonic-gate continue; 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate if (vfsp->vfs_dev != checkp->vfs_dev) { 7767c478bd9Sstevel@tonic-gate continue; 7777c478bd9Sstevel@tonic-gate } 7787c478bd9Sstevel@tonic-gate if (vfs_lock(vfsp) != 0) { 7797c478bd9Sstevel@tonic-gate continue; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex); 7827c478bd9Sstevel@tonic-gate return (vfsp); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex); 7857c478bd9Sstevel@tonic-gate return (NULL); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7897c478bd9Sstevel@tonic-gate void 7907c478bd9Sstevel@tonic-gate ud_checkclean(struct vfs *vfsp, 7917c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp, dev_t dev, time_t timev) 7927c478bd9Sstevel@tonic-gate { 7937c478bd9Sstevel@tonic-gate ud_printf("ud_checkclean\n"); 7947c478bd9Sstevel@tonic-gate udf_vfsp = (struct udf_vfs *)vfsp->vfs_data; 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * ignore if buffers or inodes are busy 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate if ((bcheck(dev, udf_vfsp->udf_iseq)) || 7997c478bd9Sstevel@tonic-gate (ud_icheck(udf_vfsp))) { 8007c478bd9Sstevel@tonic-gate return; 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate mutex_enter(&udf_vfsp->udf_lock); 8037c478bd9Sstevel@tonic-gate ud_sbwrite(udf_vfsp); 8047c478bd9Sstevel@tonic-gate mutex_exit(&udf_vfsp->udf_lock); 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate int32_t 8087c478bd9Sstevel@tonic-gate ud_icheck(struct udf_vfs *udf_vfsp) 8097c478bd9Sstevel@tonic-gate { 8107c478bd9Sstevel@tonic-gate int32_t index, error = 0; 8117c478bd9Sstevel@tonic-gate union ihead *ih; 8127c478bd9Sstevel@tonic-gate struct ud_inode *ip; 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 8157c478bd9Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++) { 8167c478bd9Sstevel@tonic-gate ih = &ud_ihead[index]; 8177c478bd9Sstevel@tonic-gate for (ip = ih->ih_chain[0]; 8187c478bd9Sstevel@tonic-gate ip != (struct ud_inode *)ih; ip = ip->i_forw) { 8197c478bd9Sstevel@tonic-gate if ((ip->i_udf == udf_vfsp) && 8207c478bd9Sstevel@tonic-gate ((ip->i_flag & (IMOD|IUPD|ICHG)) || 8217c478bd9Sstevel@tonic-gate (RW_ISWRITER(&ip->i_rwlock)) || 8227c478bd9Sstevel@tonic-gate ((ip->i_nlink <= 0) && (ip->i_flag & IREF)))) { 8237c478bd9Sstevel@tonic-gate error = 1; 8247c478bd9Sstevel@tonic-gate goto end; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate end: 8297c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 8307c478bd9Sstevel@tonic-gate return (error); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate void 8347c478bd9Sstevel@tonic-gate ud_flushi(int32_t flag) 8357c478bd9Sstevel@tonic-gate { 8367c478bd9Sstevel@tonic-gate struct ud_inode *ip, *lip; 8377c478bd9Sstevel@tonic-gate struct vnode *vp; 8387c478bd9Sstevel@tonic-gate int cheap = flag & SYNC_ATTR; 8397c478bd9Sstevel@tonic-gate int32_t index; 8407c478bd9Sstevel@tonic-gate union ihead *ih; 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * Write back each (modified) inode, 8447c478bd9Sstevel@tonic-gate * but don't sync back pages if vnode is 8457c478bd9Sstevel@tonic-gate * part of the virtual swap device. 8467c478bd9Sstevel@tonic-gate */ 8477c478bd9Sstevel@tonic-gate mutex_enter(&ud_icache_lock); 8487c478bd9Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++) { 8497c478bd9Sstevel@tonic-gate ih = &ud_ihead[index]; 8507c478bd9Sstevel@tonic-gate lip = NULL; 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate for (ip = ih->ih_chain[0], lip = NULL; 8537c478bd9Sstevel@tonic-gate ip && ip != (struct ud_inode *)ih; 8547c478bd9Sstevel@tonic-gate ip = ip->i_forw) { 8557c478bd9Sstevel@tonic-gate int flag = ip->i_flag; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate vp = ITOV(ip); 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Skip locked & inactive inodes. 8607c478bd9Sstevel@tonic-gate * Skip vnodes w/ no cached data and no inode changes. 8617c478bd9Sstevel@tonic-gate * Skip read-only vnodes 8627c478bd9Sstevel@tonic-gate */ 8637c478bd9Sstevel@tonic-gate if ((flag & IREF) == 0 || 8647c478bd9Sstevel@tonic-gate (!vn_has_cached_data(vp) && 8657c478bd9Sstevel@tonic-gate ((flag & (IMOD|IACC|IUPD|ICHG)) == 0)) || 8667c478bd9Sstevel@tonic-gate (vp->v_vfsp == NULL) || vn_is_readonly(vp)) { 8677c478bd9Sstevel@tonic-gate continue; 8687c478bd9Sstevel@tonic-gate } 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate if (!rw_tryenter(&ip->i_contents, RW_WRITER)) { 8717c478bd9Sstevel@tonic-gate continue; 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate VN_HOLD(vp); 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (lip != NULL) { 8777c478bd9Sstevel@tonic-gate ITIMES(lip); 8787c478bd9Sstevel@tonic-gate VN_RELE(ITOV(lip)); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate lip = ip; 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * If this is an inode sync for file system hardening 8847c478bd9Sstevel@tonic-gate * or this is a full sync but file is a swap file, 8857c478bd9Sstevel@tonic-gate * don't sync pages but make sure the inode is up 8867c478bd9Sstevel@tonic-gate * to date. In other cases, push everything out. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate if (cheap || IS_SWAPVP(vp)) { 8897c478bd9Sstevel@tonic-gate ud_iupdat(ip, 0); 8907c478bd9Sstevel@tonic-gate } else { 8917c478bd9Sstevel@tonic-gate (void) ud_syncip(ip, B_ASYNC, I_SYNC); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate rw_exit(&ip->i_contents); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate if (lip != NULL) { 8967c478bd9Sstevel@tonic-gate ITIMES(lip); 8977c478bd9Sstevel@tonic-gate VN_RELE(ITOV(lip)); 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate mutex_exit(&ud_icache_lock); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate void 9057c478bd9Sstevel@tonic-gate ud_update_regid(struct regid *reg) 9067c478bd9Sstevel@tonic-gate { 9077c478bd9Sstevel@tonic-gate ud_printf("ud_update_regid\n"); 9087c478bd9Sstevel@tonic-gate 9097c478bd9Sstevel@tonic-gate bzero(reg->reg_id, 23); 9107c478bd9Sstevel@tonic-gate (void) strncpy(reg->reg_id, SUN_IMPL_ID, SUN_IMPL_ID_LEN); 9117c478bd9Sstevel@tonic-gate reg->reg_ids[0] = SUN_OS_CLASS; 9127c478bd9Sstevel@tonic-gate reg->reg_ids[1] = SUN_OS_ID; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate /* ARGSUSED4 */ 9167c478bd9Sstevel@tonic-gate void 9177c478bd9Sstevel@tonic-gate ud_make_tag(struct udf_vfs *udf_vfsp, 9187c478bd9Sstevel@tonic-gate struct tag *tag, uint16_t tag_id, uint32_t blkno, uint16_t crc_len) 9197c478bd9Sstevel@tonic-gate { 9207c478bd9Sstevel@tonic-gate int32_t i; 9217c478bd9Sstevel@tonic-gate uint16_t crc; 9227c478bd9Sstevel@tonic-gate uint8_t *addr, cksum = 0; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate ud_printf("ud_make_tag\n"); 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate ASSERT(crc_len > 0x10); 9277c478bd9Sstevel@tonic-gate addr = (uint8_t *)tag; 9287c478bd9Sstevel@tonic-gate crc_len -= sizeof (struct tag); 9297c478bd9Sstevel@tonic-gate crc = ud_crc(addr + 0x10, crc_len); 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate tag->tag_id = SWAP_16(tag_id); 9327c478bd9Sstevel@tonic-gate tag->tag_desc_ver = SWAP_16(2); 9337c478bd9Sstevel@tonic-gate tag->tag_cksum = 0; 9347c478bd9Sstevel@tonic-gate tag->tag_res = 0; 9357c478bd9Sstevel@tonic-gate tag->tag_sno = SWAP_16(udf_vfsp->udf_tsno); 9367c478bd9Sstevel@tonic-gate tag->tag_crc = SWAP_16(crc); 9377c478bd9Sstevel@tonic-gate 9387c478bd9Sstevel@tonic-gate tag->tag_crc_len = SWAP_16(crc_len); 9397c478bd9Sstevel@tonic-gate tag->tag_loc = SWAP_32(blkno); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate addr = (uint8_t *)tag; 9427c478bd9Sstevel@tonic-gate for (i = 0; i <= 15; i++) { 9437c478bd9Sstevel@tonic-gate cksum += addr[i]; 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate tag->tag_cksum = cksum; 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate int32_t 9497c478bd9Sstevel@tonic-gate ud_make_dev_spec_ear(struct dev_spec_ear *ds, 9507c478bd9Sstevel@tonic-gate major_t major, minor_t minor) 9517c478bd9Sstevel@tonic-gate { 9527c478bd9Sstevel@tonic-gate int32_t attr_len; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate ud_printf("ud_make_dev_spec_ear\n"); 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate bzero(ds, sizeof (struct dev_spec_ear)); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate attr_len = sizeof (struct dev_spec_ear); 9597c478bd9Sstevel@tonic-gate ds->ds_atype = SWAP_32(12); 9607c478bd9Sstevel@tonic-gate ds->ds_astype = 1; 9617c478bd9Sstevel@tonic-gate ds->ds_attr_len = SWAP_32(attr_len); 9627c478bd9Sstevel@tonic-gate ds->ds_iu_len = 0; 9637c478bd9Sstevel@tonic-gate ds->ds_major_id = SWAP_32(major); 9647c478bd9Sstevel@tonic-gate ds->ds_minor_id = SWAP_32(minor); 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate return (attr_len); 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate int32_t 9717c478bd9Sstevel@tonic-gate ud_get_next_fid(struct ud_inode *ip, struct fbuf **fbp, uint32_t offset, 9727c478bd9Sstevel@tonic-gate struct file_id **fid, uint8_t **name, uint8_t *buf) 9737c478bd9Sstevel@tonic-gate { 9747c478bd9Sstevel@tonic-gate struct vnode *vp = ITOV(ip); 9757c478bd9Sstevel@tonic-gate caddr_t beg, end; 9767c478bd9Sstevel@tonic-gate int32_t error, lbsize, lbmask, sz, iulen, idlen, copied = 0; 9777c478bd9Sstevel@tonic-gate struct udf_vfs *udf_vfsp; 9787c478bd9Sstevel@tonic-gate uint8_t *obuf; 9797c478bd9Sstevel@tonic-gate int32_t count; 9807c478bd9Sstevel@tonic-gate uint32_t tbno; 9817c478bd9Sstevel@tonic-gate uint16_t crc_len; 9827c478bd9Sstevel@tonic-gate uint32_t len; 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate ud_printf("ud_get_next_fid\n"); 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate obuf = buf; 9877c478bd9Sstevel@tonic-gate udf_vfsp = ip->i_udf; 9887c478bd9Sstevel@tonic-gate lbsize = udf_vfsp->udf_lbsize; 9897c478bd9Sstevel@tonic-gate lbmask = udf_vfsp->udf_lbmask; 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate if ((error = ud_ip_off2bno(ip, offset, &tbno)) != 0) { 9927c478bd9Sstevel@tonic-gate return (error); 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate /* First time read */ 9957c478bd9Sstevel@tonic-gate if (*fbp == NULL) { 9967c478bd9Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)(offset & ~lbmask), 9977c478bd9Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) { 9987c478bd9Sstevel@tonic-gate return (error); 9997c478bd9Sstevel@tonic-gate } 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count; 10037c478bd9Sstevel@tonic-gate beg = (*fbp)->fb_addr + (offset & lbmask); 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate if ((offset % lbsize) || 10077c478bd9Sstevel@tonic-gate (offset == 0)) { 10087c478bd9Sstevel@tonic-gate sz = end - beg; 10097c478bd9Sstevel@tonic-gate } else { 10107c478bd9Sstevel@tonic-gate sz = 0; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate if (F_LEN <= sz) { 10157c478bd9Sstevel@tonic-gate *fid = (struct file_id *)beg; 10167c478bd9Sstevel@tonic-gate beg += F_LEN; 10177c478bd9Sstevel@tonic-gate } else { 10187c478bd9Sstevel@tonic-gate copied = 1; 10197c478bd9Sstevel@tonic-gate bcopy(beg, buf, sz); 10207c478bd9Sstevel@tonic-gate fbrelse(*fbp, S_OTHER); 10217c478bd9Sstevel@tonic-gate *fbp = NULL; 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate /* Skip to next block */ 10247c478bd9Sstevel@tonic-gate if (offset & lbmask) { 10257c478bd9Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize; 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset, 10287c478bd9Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) { 10297c478bd9Sstevel@tonic-gate return (error); 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count; 10327c478bd9Sstevel@tonic-gate beg = (*fbp)->fb_addr; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate bcopy(beg, buf + sz, F_LEN - sz); 10357c478bd9Sstevel@tonic-gate beg = beg + F_LEN - sz; 10367c478bd9Sstevel@tonic-gate *fid = (struct file_id *)buf; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate buf += F_LEN; 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate /* 10437c478bd9Sstevel@tonic-gate * Check if this a valid file_identifier 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC, 10467c478bd9Sstevel@tonic-gate tbno, 0, lbsize) != 0) { 10477c478bd9Sstevel@tonic-gate /* 10487c478bd9Sstevel@tonic-gate * Either end of directory or corrupted 10497c478bd9Sstevel@tonic-gate */ 10507c478bd9Sstevel@tonic-gate return (EINVAL); 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate crc_len = SWAP_16((*fid)->fid_tag.tag_crc_len); 10547c478bd9Sstevel@tonic-gate if (crc_len > udf_vfsp->udf_lbsize) { 10557c478bd9Sstevel@tonic-gate /* 10567c478bd9Sstevel@tonic-gate * Entries cannot be larger than 10577c478bd9Sstevel@tonic-gate * blocksize 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate return (EINVAL); 10607c478bd9Sstevel@tonic-gate } 10617c478bd9Sstevel@tonic-gate 10627c478bd9Sstevel@tonic-gate if (crc_len < (F_LEN - sizeof (struct tag))) { 10637c478bd9Sstevel@tonic-gate iulen = SWAP_16((*fid)->fid_iulen); 10647c478bd9Sstevel@tonic-gate idlen = FID_LEN(*fid) - F_LEN; 10657c478bd9Sstevel@tonic-gate goto use_id_iu_len; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * By now beg points to the start fo the file name 10707c478bd9Sstevel@tonic-gate */ 10717c478bd9Sstevel@tonic-gate 10727c478bd9Sstevel@tonic-gate sz = end - beg; 10737c478bd9Sstevel@tonic-gate len = crc_len + sizeof (struct tag) - (F_LEN); 10747c478bd9Sstevel@tonic-gate if (len <= sz) { 10757c478bd9Sstevel@tonic-gate if (copied == 1) { 10767c478bd9Sstevel@tonic-gate bcopy(beg, buf, len); 10777c478bd9Sstevel@tonic-gate buf += len; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate beg += len; 10807c478bd9Sstevel@tonic-gate } else { 10817c478bd9Sstevel@tonic-gate copied = 1; 10827c478bd9Sstevel@tonic-gate /* 10837c478bd9Sstevel@tonic-gate * We are releasing the 10847c478bd9Sstevel@tonic-gate * old buffer so copy fid to buf 10857c478bd9Sstevel@tonic-gate */ 10867c478bd9Sstevel@tonic-gate if (obuf == buf) { 10877c478bd9Sstevel@tonic-gate count = F_LEN + sz; 10887c478bd9Sstevel@tonic-gate bcopy(*fid, buf, count); 10897c478bd9Sstevel@tonic-gate *fid = (struct file_id *)buf; 10907c478bd9Sstevel@tonic-gate buf += count; 10917c478bd9Sstevel@tonic-gate } else { 10927c478bd9Sstevel@tonic-gate bcopy(beg, buf, sz); 10937c478bd9Sstevel@tonic-gate *fid = (struct file_id *)buf; 10947c478bd9Sstevel@tonic-gate buf += sz; 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate fbrelse(*fbp, S_OTHER); 10977c478bd9Sstevel@tonic-gate *fbp = NULL; 10987c478bd9Sstevel@tonic-gate 10997c478bd9Sstevel@tonic-gate /* Skip to next block */ 11007c478bd9Sstevel@tonic-gate if (offset & lbmask) { 11017c478bd9Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize; 11027c478bd9Sstevel@tonic-gate } 11037c478bd9Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset, 11047c478bd9Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) { 11057c478bd9Sstevel@tonic-gate return (error); 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count; 11087c478bd9Sstevel@tonic-gate beg = (*fbp)->fb_addr; 11097c478bd9Sstevel@tonic-gate count = len - sz; 11107c478bd9Sstevel@tonic-gate bcopy(beg, buf, count); 11117c478bd9Sstevel@tonic-gate beg += count; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate /* 11157c478bd9Sstevel@tonic-gate * First we verify that the tag id and the FID_LEN are valid. 11167c478bd9Sstevel@tonic-gate * Next we verify the crc of the descriptor. 11177c478bd9Sstevel@tonic-gate */ 11187c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC, 11197c478bd9Sstevel@tonic-gate tbno, 0, lbsize) != 0) { 11207c478bd9Sstevel@tonic-gate /* directory is corrupted */ 11217c478bd9Sstevel@tonic-gate return (EINVAL); 11227c478bd9Sstevel@tonic-gate } 11237c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC, 11247c478bd9Sstevel@tonic-gate tbno, 1, FID_LEN(*fid)) != 0) { 11257c478bd9Sstevel@tonic-gate /* directory is corrupted */ 11267c478bd9Sstevel@tonic-gate return (EINVAL); 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate idlen = FID_LEN(*fid); 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate idlen -= F_LEN; 11327c478bd9Sstevel@tonic-gate iulen = SWAP_16((*fid)->fid_iulen); 11337c478bd9Sstevel@tonic-gate if (crc_len < (F_LEN - sizeof (struct tag) + idlen)) { 11347c478bd9Sstevel@tonic-gate use_id_iu_len: 11357c478bd9Sstevel@tonic-gate len = (F_LEN - sizeof (struct tag) + idlen) - crc_len; 11367c478bd9Sstevel@tonic-gate sz = end - beg; 11377c478bd9Sstevel@tonic-gate if (len <= sz) { 11387c478bd9Sstevel@tonic-gate if (copied == 1) { 11397c478bd9Sstevel@tonic-gate bcopy(beg, buf, len); 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate } else { 11427c478bd9Sstevel@tonic-gate if (obuf == buf) { 11437c478bd9Sstevel@tonic-gate count = crc_len + sizeof (struct tag); 11447c478bd9Sstevel@tonic-gate bcopy(*fid, buf, count); 11457c478bd9Sstevel@tonic-gate *fid = (struct file_id *)buf; 11467c478bd9Sstevel@tonic-gate buf += count; 11477c478bd9Sstevel@tonic-gate } else { 11487c478bd9Sstevel@tonic-gate bcopy(beg, buf, sz); 11497c478bd9Sstevel@tonic-gate *fid = (struct file_id *)buf; 11507c478bd9Sstevel@tonic-gate buf += sz; 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate fbrelse(*fbp, S_OTHER); 11537c478bd9Sstevel@tonic-gate *fbp = NULL; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate /* Skip to next block */ 11567c478bd9Sstevel@tonic-gate if (offset & lbmask) { 11577c478bd9Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize; 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset, 11607c478bd9Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) { 11617c478bd9Sstevel@tonic-gate return (error); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count; 11647c478bd9Sstevel@tonic-gate beg = (*fbp)->fb_addr; 11657c478bd9Sstevel@tonic-gate count = len - sz; 11667c478bd9Sstevel@tonic-gate bcopy(beg, buf, count); 11677c478bd9Sstevel@tonic-gate beg += count; 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate *name = ((uint8_t *)*fid) + F_LEN + iulen; 11727c478bd9Sstevel@tonic-gate 11737c478bd9Sstevel@tonic-gate return (0); 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate int32_t 11787c478bd9Sstevel@tonic-gate ud_verify_tag_and_desc(struct tag *tag, uint16_t id, uint32_t blockno, 11797c478bd9Sstevel@tonic-gate int32_t verify_desc, int32_t desc_len) 11807c478bd9Sstevel@tonic-gate { 11817c478bd9Sstevel@tonic-gate int32_t i; 11827c478bd9Sstevel@tonic-gate uint8_t *addr, cksum = 0; 11837c478bd9Sstevel@tonic-gate uint16_t crc; 11847c478bd9Sstevel@tonic-gate file_entry_t *fe; 11857c478bd9Sstevel@tonic-gate struct ext_attr_hdr *eah; 11867c478bd9Sstevel@tonic-gate struct file_id *fid; 11877c478bd9Sstevel@tonic-gate int32_t fidlen, ea_off; 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (tag->tag_id != SWAP_16(id)) { 11907c478bd9Sstevel@tonic-gate return (1); 11917c478bd9Sstevel@tonic-gate } 11927c478bd9Sstevel@tonic-gate addr = (uint8_t *)tag; 11937c478bd9Sstevel@tonic-gate eah = (struct ext_attr_hdr *)tag; 11947c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) { 11957c478bd9Sstevel@tonic-gate cksum += addr[i]; 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate for (i = 5; i <= 15; i++) { 11987c478bd9Sstevel@tonic-gate cksum += addr[i]; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate if (cksum != tag->tag_cksum) { 12017c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12027c478bd9Sstevel@tonic-gate "Checksum Does not Verify TAG %x CALC %x blockno 0x%x\n", 12037c478bd9Sstevel@tonic-gate tag->tag_cksum, cksum, blockno); 12047c478bd9Sstevel@tonic-gate return (1); 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate /* 12077c478bd9Sstevel@tonic-gate * Validate the meta data for UD_FILE_ID_DESC. 12087c478bd9Sstevel@tonic-gate * The FID_LEN should not exceed the desc_len. 12097c478bd9Sstevel@tonic-gate * This validation is done before the entire descriptor is read. 12107c478bd9Sstevel@tonic-gate * A call to this routine is made initially with verify_desc set as 0 12117c478bd9Sstevel@tonic-gate * but a non zero value in desc_len. 12127c478bd9Sstevel@tonic-gate */ 12137c478bd9Sstevel@tonic-gate if (id == UD_FILE_ID_DESC) { 12147c478bd9Sstevel@tonic-gate fid = (struct file_id *)tag; 12157c478bd9Sstevel@tonic-gate fidlen = FID_LEN(fid); 12167c478bd9Sstevel@tonic-gate if (fidlen > desc_len) { 12177c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12187c478bd9Sstevel@tonic-gate "Invalid FID_LEN(0x%x). Greater than expected(0x%x) blockno 0x%x\n", 12197c478bd9Sstevel@tonic-gate fidlen, desc_len, blockno); 12207c478bd9Sstevel@tonic-gate return (1); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate } 12237c478bd9Sstevel@tonic-gate if (verify_desc == 0) 12247c478bd9Sstevel@tonic-gate return (0); 12257c478bd9Sstevel@tonic-gate /* 12267c478bd9Sstevel@tonic-gate * We are done verifying the tag. We proceed with verifying the 12277c478bd9Sstevel@tonic-gate * the descriptor. desc_len indicates the size of the structure 12287c478bd9Sstevel@tonic-gate * pointed to by argument tag. It includes the size of struct tag. 12297c478bd9Sstevel@tonic-gate * We first check the tag_crc_len since we use this to compute the 12307c478bd9Sstevel@tonic-gate * crc of the descriptor. 12317c478bd9Sstevel@tonic-gate * Verifying the crc is normally sufficient to ensure the integrity 12327c478bd9Sstevel@tonic-gate * of the meta data in the descriptor. However given the paranoia 12337c478bd9Sstevel@tonic-gate * about the panic caused by illegal meta data values we do an 12347c478bd9Sstevel@tonic-gate * additional check of the meta data for decriptor UD_FILE_ENTRY. 12357c478bd9Sstevel@tonic-gate * (The original panic was caused because this routine was not called 12367c478bd9Sstevel@tonic-gate * to verify the integrity of the tag and descriptor.) 12377c478bd9Sstevel@tonic-gate */ 12387c478bd9Sstevel@tonic-gate if (SWAP_16(tag->tag_crc_len) > (desc_len - sizeof (struct tag))) { 12397c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12407c478bd9Sstevel@tonic-gate "tag_crc_len(0x%x) is greater than expected len(0x%x) blockno 0x%x\n", 12417c478bd9Sstevel@tonic-gate SWAP_16(tag->tag_crc_len), 12427c478bd9Sstevel@tonic-gate desc_len, blockno); 12437c478bd9Sstevel@tonic-gate return (1); 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate if (tag->tag_crc_len) { 12467c478bd9Sstevel@tonic-gate crc = ud_crc(addr + 0x10, SWAP_16(tag->tag_crc_len)); 12477c478bd9Sstevel@tonic-gate if (crc != SWAP_16(tag->tag_crc)) { 12487c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "CRC mismatch TAG_ID 0x%x TAG_CRC 0x%x" 12497c478bd9Sstevel@tonic-gate " Computed crc 0x%x tag_loc %x blockno 0x%x\n", 12507c478bd9Sstevel@tonic-gate id, SWAP_16(tag->tag_crc), crc, 12517c478bd9Sstevel@tonic-gate SWAP_32(tag->tag_loc), blockno); 12527c478bd9Sstevel@tonic-gate return (1); 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate switch (id) { 12567c478bd9Sstevel@tonic-gate case UD_FILE_ENTRY: 12577c478bd9Sstevel@tonic-gate fe = (file_entry_t *)tag; 12587c478bd9Sstevel@tonic-gate if ((offsetof(struct file_entry, fe_spec) + 12597c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_ear) + 12607c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc)) > desc_len) { 12617c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12627c478bd9Sstevel@tonic-gate "fe_len_ear(0x%x) fe_len_adesc(0x%x) fields are not OK. blockno 0x%x\n", 12637c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_ear), 12647c478bd9Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc), 12657c478bd9Sstevel@tonic-gate blockno); 12667c478bd9Sstevel@tonic-gate return (1); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate break; 12697c478bd9Sstevel@tonic-gate case UD_EXT_ATTR_HDR: 12707c478bd9Sstevel@tonic-gate eah = (struct ext_attr_hdr *)tag; 12717c478bd9Sstevel@tonic-gate if (SWAP_32(eah->eah_aal) > desc_len) { 12727c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12737c478bd9Sstevel@tonic-gate "eah_all(0x%x) exceeds desc. len(0x%x) blockno 0x%x\n", 12747c478bd9Sstevel@tonic-gate SWAP_32(eah->eah_aal), desc_len, blockno); 12757c478bd9Sstevel@tonic-gate return (1); 12767c478bd9Sstevel@tonic-gate } 12777c478bd9Sstevel@tonic-gate ea_off = GET_32(&eah->eah_ial); 12787c478bd9Sstevel@tonic-gate if (ea_off >= desc_len) { 12797c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12807c478bd9Sstevel@tonic-gate "ea_off(0x%x) is not less than ea_len(0x%x) blockno 0x%x\n", 12817c478bd9Sstevel@tonic-gate ea_off, desc_len, blockno); 12827c478bd9Sstevel@tonic-gate return (1); 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate break; 12857c478bd9Sstevel@tonic-gate default: 12867c478bd9Sstevel@tonic-gate break; 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate if (SWAP_32(blockno) != tag->tag_loc) { 12897c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 12907c478bd9Sstevel@tonic-gate "Tag Location mismatch blockno %x tag_blockno %x\n", 12917c478bd9Sstevel@tonic-gate blockno, SWAP_32(tag->tag_loc)); 12927c478bd9Sstevel@tonic-gate return (1); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate return (0); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate /* **************** udf specific subroutines *********************** */ 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate uint16_t ud_crc_table[256] = { 13007c478bd9Sstevel@tonic-gate 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 13017c478bd9Sstevel@tonic-gate 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 13027c478bd9Sstevel@tonic-gate 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 13037c478bd9Sstevel@tonic-gate 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 13047c478bd9Sstevel@tonic-gate 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 13057c478bd9Sstevel@tonic-gate 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 13067c478bd9Sstevel@tonic-gate 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 13077c478bd9Sstevel@tonic-gate 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 13087c478bd9Sstevel@tonic-gate 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 13097c478bd9Sstevel@tonic-gate 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 13107c478bd9Sstevel@tonic-gate 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 13117c478bd9Sstevel@tonic-gate 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 13127c478bd9Sstevel@tonic-gate 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 13137c478bd9Sstevel@tonic-gate 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 13147c478bd9Sstevel@tonic-gate 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 13157c478bd9Sstevel@tonic-gate 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 13167c478bd9Sstevel@tonic-gate 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 13177c478bd9Sstevel@tonic-gate 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 13187c478bd9Sstevel@tonic-gate 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 13197c478bd9Sstevel@tonic-gate 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 13207c478bd9Sstevel@tonic-gate 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 13217c478bd9Sstevel@tonic-gate 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 13227c478bd9Sstevel@tonic-gate 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 13237c478bd9Sstevel@tonic-gate 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 13247c478bd9Sstevel@tonic-gate 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 13257c478bd9Sstevel@tonic-gate 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 13267c478bd9Sstevel@tonic-gate 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 13277c478bd9Sstevel@tonic-gate 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 13287c478bd9Sstevel@tonic-gate 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 13297c478bd9Sstevel@tonic-gate 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 13307c478bd9Sstevel@tonic-gate 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 13317c478bd9Sstevel@tonic-gate 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 13327c478bd9Sstevel@tonic-gate }; 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate uint16_t 13357c478bd9Sstevel@tonic-gate ud_crc(uint8_t *addr, int32_t len) 13367c478bd9Sstevel@tonic-gate { 13377c478bd9Sstevel@tonic-gate uint16_t crc = 0; 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate while (len-- > 0) { 13407c478bd9Sstevel@tonic-gate crc = ud_crc_table[(crc >> 8 ^ *addr++) & 0xff] ^ (crc<<8); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate 13437c478bd9Sstevel@tonic-gate return (crc); 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate typedef unsigned short unicode_t; 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate #define POUND 0x0023 13497c478bd9Sstevel@tonic-gate #define DOT 0x002E 13507c478bd9Sstevel@tonic-gate #define SLASH 0x002F 13517c478bd9Sstevel@tonic-gate #define UNDERBAR 0x005F 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate static uint16_t htoc[16] = {'0', '1', '2', '3', 13557c478bd9Sstevel@tonic-gate '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 13567c478bd9Sstevel@tonic-gate 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate /* 13597c478bd9Sstevel@tonic-gate * An unrecorded block will return all 13607c478bd9Sstevel@tonic-gate * 0's on a WORM media. to simulate 13617c478bd9Sstevel@tonic-gate * a unrecorded block on a rw media 13627c478bd9Sstevel@tonic-gate * we fill it with all zero's 13637c478bd9Sstevel@tonic-gate * return 0 : If unrecorded 13647c478bd9Sstevel@tonic-gate * return 1 : If recorded. 13657c478bd9Sstevel@tonic-gate */ 13667c478bd9Sstevel@tonic-gate uint32_t 13677c478bd9Sstevel@tonic-gate ud_check_te_unrec(struct udf_vfs *udf_vfsp, caddr_t addr, uint32_t blkno) 13687c478bd9Sstevel@tonic-gate { 13697c478bd9Sstevel@tonic-gate int32_t i, lbsize; 13707c478bd9Sstevel@tonic-gate struct term_entry *te; 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate ASSERT(udf_vfsp); 13737c478bd9Sstevel@tonic-gate ASSERT(addr); 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate te = (struct term_entry *)addr; 13767c478bd9Sstevel@tonic-gate if (ud_verify_tag_and_desc(&te->te_tag, UD_TERMINAL_ENT, 13777c478bd9Sstevel@tonic-gate blkno, 1, udf_vfsp->udf_lbsize) != 0) { 13787c478bd9Sstevel@tonic-gate lbsize = udf_vfsp->udf_lbsize; 13797c478bd9Sstevel@tonic-gate for (i = 0; i < lbsize; i++) { 13807c478bd9Sstevel@tonic-gate if (addr[i] != 0) { 13817c478bd9Sstevel@tonic-gate return (1); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate } 13857c478bd9Sstevel@tonic-gate return (0); 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate 13897c478bd9Sstevel@tonic-gate /* 13907c478bd9Sstevel@tonic-gate * The algorithms ud_utf82utf16 and ud_utf162utf8 13917c478bd9Sstevel@tonic-gate * donot handle surrogates. This is unicode 1.1 as I 13927c478bd9Sstevel@tonic-gate * understand. When writing udf2.0 this code has 13937c478bd9Sstevel@tonic-gate * to be changed to process surrogates also 13947c478bd9Sstevel@tonic-gate * (Dont ask me what is a surrogate character) 13957c478bd9Sstevel@tonic-gate */ 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* 13987c478bd9Sstevel@tonic-gate * This will take a utf8 string convert the first character 13997c478bd9Sstevel@tonic-gate * to utf16 and return the number of bytes consumed in this 14007c478bd9Sstevel@tonic-gate * process. A 0 will be returned if the character is invalid 14017c478bd9Sstevel@tonic-gate */ 14027c478bd9Sstevel@tonic-gate uint8_t bytes_from_utf8[] = { 14037c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14047c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14057c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14067c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14077c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14087c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14097c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14107c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14117c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14127c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14137c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14147c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14157c478bd9Sstevel@tonic-gate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14167c478bd9Sstevel@tonic-gate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14177c478bd9Sstevel@tonic-gate 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 14187c478bd9Sstevel@tonic-gate 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 14197c478bd9Sstevel@tonic-gate }; 14207c478bd9Sstevel@tonic-gate int32_t 14217c478bd9Sstevel@tonic-gate ud_utf82utf16(uint8_t *s_8, uint16_t *c_16, int32_t count) 14227c478bd9Sstevel@tonic-gate { 14237c478bd9Sstevel@tonic-gate int32_t extra_bytes; 14247c478bd9Sstevel@tonic-gate uint32_t c_32; 14257c478bd9Sstevel@tonic-gate ASSERT(s_8); 14267c478bd9Sstevel@tonic-gate ASSERT(c_16); 14277c478bd9Sstevel@tonic-gate 14287c478bd9Sstevel@tonic-gate /* 14297c478bd9Sstevel@tonic-gate * First convert to a 32-bit 14307c478bd9Sstevel@tonic-gate * character 14317c478bd9Sstevel@tonic-gate */ 14327c478bd9Sstevel@tonic-gate c_32 = 0; 14337c478bd9Sstevel@tonic-gate extra_bytes = bytes_from_utf8[*s_8]; 14347c478bd9Sstevel@tonic-gate if (extra_bytes > count) { 14357c478bd9Sstevel@tonic-gate return (0); 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate /* 14397c478bd9Sstevel@tonic-gate * verify if the string is a valid 14407c478bd9Sstevel@tonic-gate * utf8 string 14417c478bd9Sstevel@tonic-gate */ 14427c478bd9Sstevel@tonic-gate if (extra_bytes == 0) { 14437c478bd9Sstevel@tonic-gate /* 14447c478bd9Sstevel@tonic-gate * Apply one byte rule 14457c478bd9Sstevel@tonic-gate */ 14467c478bd9Sstevel@tonic-gate if (*s_8 & 0x80) { 14477c478bd9Sstevel@tonic-gate return (0); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x7F; 14507c478bd9Sstevel@tonic-gate } else if (extra_bytes == 1) { 14517c478bd9Sstevel@tonic-gate if (((*s_8 & 0xE0) != 0xC0) || 14527c478bd9Sstevel@tonic-gate ((*(s_8 + 1) & 0xC0) != 0x80)) { 14537c478bd9Sstevel@tonic-gate return (0); 14547c478bd9Sstevel@tonic-gate } 14557c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x1F; 14567c478bd9Sstevel@tonic-gate } else if (extra_bytes == 2) { 14577c478bd9Sstevel@tonic-gate if (((*s_8 & 0xF0) != 0xE0) || 14587c478bd9Sstevel@tonic-gate ((*(s_8 + 1) & 0xC0) != 0x80) || 14597c478bd9Sstevel@tonic-gate ((*(s_8 + 2) & 0xC0) != 0x80)) { 14607c478bd9Sstevel@tonic-gate return (0); 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x0F; 14637c478bd9Sstevel@tonic-gate } else if (extra_bytes == 3) { 14647c478bd9Sstevel@tonic-gate if (((*s_8 & 0xF8) != 0xF0) || 14657c478bd9Sstevel@tonic-gate ((*(s_8 + 1) & 0xC0) != 0x80) || 14667c478bd9Sstevel@tonic-gate ((*(s_8 + 2) & 0xC0) != 0x80) || 14677c478bd9Sstevel@tonic-gate ((*(s_8 + 3) & 0xC0) != 0x80)) { 14687c478bd9Sstevel@tonic-gate return (0); 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x07; 14717c478bd9Sstevel@tonic-gate } else if (extra_bytes == 4) { 14727c478bd9Sstevel@tonic-gate if (((*s_8 & 0xFC) != 0xF8) || 14737c478bd9Sstevel@tonic-gate ((*(s_8 + 1) & 0xC0) != 0x80) || 14747c478bd9Sstevel@tonic-gate ((*(s_8 + 2) & 0xC0) != 0x80) || 14757c478bd9Sstevel@tonic-gate ((*(s_8 + 3) & 0xC0) != 0x80) || 14767c478bd9Sstevel@tonic-gate ((*(s_8 + 4) & 0xC0) != 0x80)) { 14777c478bd9Sstevel@tonic-gate return (0); 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x03; 14807c478bd9Sstevel@tonic-gate } else if (extra_bytes == 5) { 14817c478bd9Sstevel@tonic-gate if (((*s_8 & 0xFE) != 0xFC) || 14827c478bd9Sstevel@tonic-gate ((*(s_8 + 1) & 0xC0) != 0x80) || 14837c478bd9Sstevel@tonic-gate ((*(s_8 + 2) & 0xC0) != 0x80) || 14847c478bd9Sstevel@tonic-gate ((*(s_8 + 3) & 0xC0) != 0x80) || 14857c478bd9Sstevel@tonic-gate ((*(s_8 + 4) & 0xC0) != 0x80) || 14867c478bd9Sstevel@tonic-gate ((*(s_8 + 5) & 0xC0) != 0x80)) { 14877c478bd9Sstevel@tonic-gate return (0); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate c_32 = *s_8 & 0x01; 14907c478bd9Sstevel@tonic-gate } else { 14917c478bd9Sstevel@tonic-gate return (0); 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate s_8++; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate /* 14967c478bd9Sstevel@tonic-gate * Convert to 32-bit character 14977c478bd9Sstevel@tonic-gate */ 14987c478bd9Sstevel@tonic-gate switch (extra_bytes) { 14997c478bd9Sstevel@tonic-gate case 5 : 15007c478bd9Sstevel@tonic-gate c_32 <<= 6; 15017c478bd9Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F); 15027c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15037c478bd9Sstevel@tonic-gate case 4 : 15047c478bd9Sstevel@tonic-gate c_32 <<= 6; 15057c478bd9Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F); 15067c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15077c478bd9Sstevel@tonic-gate case 3 : 15087c478bd9Sstevel@tonic-gate c_32 <<= 6; 15097c478bd9Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F); 15107c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15117c478bd9Sstevel@tonic-gate case 2 : 15127c478bd9Sstevel@tonic-gate c_32 <<= 6; 15137c478bd9Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F); 15147c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15157c478bd9Sstevel@tonic-gate case 1 : 15167c478bd9Sstevel@tonic-gate c_32 <<= 6; 15177c478bd9Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F); 15187c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15197c478bd9Sstevel@tonic-gate case 0 : 15207c478bd9Sstevel@tonic-gate break; 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate /* 15247c478bd9Sstevel@tonic-gate * now convert the 32-bit 15257c478bd9Sstevel@tonic-gate * character into a 16-bit character 15267c478bd9Sstevel@tonic-gate */ 15277c478bd9Sstevel@tonic-gate *c_16 = c_32; 15287c478bd9Sstevel@tonic-gate return (extra_bytes + 1); 15297c478bd9Sstevel@tonic-gate } 15307c478bd9Sstevel@tonic-gate 15317c478bd9Sstevel@tonic-gate /* 15327c478bd9Sstevel@tonic-gate * Convert to a form that can be put on the media 15337c478bd9Sstevel@tonic-gate * out_len has the size of out_str when we are called. 15347c478bd9Sstevel@tonic-gate * This routine will set out_len to actual bytes written to out_str. 15357c478bd9Sstevel@tonic-gate * We make sure that we will not attempt to write beyond the out_str_len. 15367c478bd9Sstevel@tonic-gate */ 15377c478bd9Sstevel@tonic-gate int32_t 15387c478bd9Sstevel@tonic-gate ud_compress(int32_t in_len, int32_t *out_len, 15397c478bd9Sstevel@tonic-gate uint8_t *in_str, uint8_t *out_str) 15407c478bd9Sstevel@tonic-gate { 15417c478bd9Sstevel@tonic-gate int32_t error, in_index, out_index, index, c_tx_sz, out_str_len; 15427c478bd9Sstevel@tonic-gate uint16_t w2_char, *w2_str; 15437c478bd9Sstevel@tonic-gate uint8_t comp_id; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate out_str_len = *out_len; 15467c478bd9Sstevel@tonic-gate if (in_len > (out_str_len - 2)) { 15477c478bd9Sstevel@tonic-gate return (ENAMETOOLONG); 15487c478bd9Sstevel@tonic-gate } 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate *out_len = 0; 15517c478bd9Sstevel@tonic-gate w2_str = (uint16_t *)kmem_zalloc(512, KM_SLEEP); 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate error = in_index = out_index = c_tx_sz = 0; 15547c478bd9Sstevel@tonic-gate comp_id = 8; 15557c478bd9Sstevel@tonic-gate for (in_index = 0; in_index < in_len; in_index += c_tx_sz) { 15567c478bd9Sstevel@tonic-gate if ((c_tx_sz = ud_utf82utf16(&in_str[in_index], 15577c478bd9Sstevel@tonic-gate &w2_char, in_len - in_index)) == 0) { 15587c478bd9Sstevel@tonic-gate error = EINVAL; 15597c478bd9Sstevel@tonic-gate goto end; 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate /* 15627c478bd9Sstevel@tonic-gate * utf-8 characters can be 15637c478bd9Sstevel@tonic-gate * of 1 - 6 bytes in length 15647c478bd9Sstevel@tonic-gate */ 15657c478bd9Sstevel@tonic-gate ASSERT(c_tx_sz > 0); 15667c478bd9Sstevel@tonic-gate ASSERT(c_tx_sz < 7); 15677c478bd9Sstevel@tonic-gate if ((comp_id == 8) && (w2_char & 0xff00)) { 15687c478bd9Sstevel@tonic-gate comp_id = 0x10; 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate w2_str[out_index++] = w2_char; 15717c478bd9Sstevel@tonic-gate } 15727c478bd9Sstevel@tonic-gate if (((comp_id == 0x10) && (out_index > ((out_str_len - 2)/2))) || 15737c478bd9Sstevel@tonic-gate ((comp_id == 0x8) && (out_index > (out_str_len - 2)))) { 15747c478bd9Sstevel@tonic-gate error = ENAMETOOLONG; 15757c478bd9Sstevel@tonic-gate goto end; 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate in_index = out_index; 15797c478bd9Sstevel@tonic-gate out_index = 0; 15807c478bd9Sstevel@tonic-gate out_str[out_index++] = comp_id; 15817c478bd9Sstevel@tonic-gate for (index = 0; index < in_index; index++) { 15827c478bd9Sstevel@tonic-gate if (comp_id == 0x10) { 15837c478bd9Sstevel@tonic-gate out_str[out_index++] = (w2_str[index] & 0xFF00) >> 8; 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate out_str[out_index++] = w2_str[index] & 0xFF; 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate ASSERT(out_index <= (out_str_len - 1)); 15887c478bd9Sstevel@tonic-gate *out_len = out_index; 15897c478bd9Sstevel@tonic-gate end: 15907c478bd9Sstevel@tonic-gate if (w2_str != NULL) { 15917c478bd9Sstevel@tonic-gate kmem_free((caddr_t)w2_str, 512); 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate return (error); 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate /* 15977c478bd9Sstevel@tonic-gate * Take a utf16 character and convert 15987c478bd9Sstevel@tonic-gate * it into a utf8 character. 15997c478bd9Sstevel@tonic-gate * A 0 will be returned if the conversion fails 16007c478bd9Sstevel@tonic-gate */ 16017c478bd9Sstevel@tonic-gate uint8_t first_byte_mark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC}; 16027c478bd9Sstevel@tonic-gate int32_t 16037c478bd9Sstevel@tonic-gate ud_utf162utf8(uint16_t c_16, uint8_t *s_8) 16047c478bd9Sstevel@tonic-gate { 16057c478bd9Sstevel@tonic-gate int32_t nc; 16067c478bd9Sstevel@tonic-gate uint32_t c_32; 16077c478bd9Sstevel@tonic-gate uint32_t byte_mask = 0xBF; 16087c478bd9Sstevel@tonic-gate uint32_t byte_mark = 0x80; 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate ASSERT(s_8); 16117c478bd9Sstevel@tonic-gate 16127c478bd9Sstevel@tonic-gate /* 16137c478bd9Sstevel@tonic-gate * Convert the 16-bit character to 16147c478bd9Sstevel@tonic-gate * a 32-bit character 16157c478bd9Sstevel@tonic-gate */ 16167c478bd9Sstevel@tonic-gate c_32 = c_16; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* 16197c478bd9Sstevel@tonic-gate * By here the 16-bit character is converted 16207c478bd9Sstevel@tonic-gate * to a 32-bit wide character 16217c478bd9Sstevel@tonic-gate */ 16227c478bd9Sstevel@tonic-gate if (c_32 < 0x80) { 16237c478bd9Sstevel@tonic-gate nc = 1; 16247c478bd9Sstevel@tonic-gate } else if (c_32 < 0x800) { 16257c478bd9Sstevel@tonic-gate nc = 2; 16267c478bd9Sstevel@tonic-gate } else if (c_32 < 0x10000) { 16277c478bd9Sstevel@tonic-gate nc = 3; 16287c478bd9Sstevel@tonic-gate } else if (c_32 < 0x200000) { 16297c478bd9Sstevel@tonic-gate nc = 4; 16307c478bd9Sstevel@tonic-gate } else if (c_32 < 0x4000000) { 16317c478bd9Sstevel@tonic-gate nc = 5; 16327c478bd9Sstevel@tonic-gate } else if (c_32 < (uint32_t)0x80000000) { 16337c478bd9Sstevel@tonic-gate nc = 6; 16347c478bd9Sstevel@tonic-gate } else { 16357c478bd9Sstevel@tonic-gate nc = 0; 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate s_8 += nc; 16387c478bd9Sstevel@tonic-gate switch (nc) { 16397c478bd9Sstevel@tonic-gate case 6 : 16407c478bd9Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask; 16417c478bd9Sstevel@tonic-gate c_32 >>= 6; 16427c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16437c478bd9Sstevel@tonic-gate case 5 : 16447c478bd9Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask; 16457c478bd9Sstevel@tonic-gate c_32 >>= 6; 16467c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16477c478bd9Sstevel@tonic-gate case 4 : 16487c478bd9Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask; 16497c478bd9Sstevel@tonic-gate c_32 >>= 6; 16507c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16517c478bd9Sstevel@tonic-gate case 3 : 16527c478bd9Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask; 16537c478bd9Sstevel@tonic-gate c_32 >>= 6; 16547c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16557c478bd9Sstevel@tonic-gate case 2 : 16567c478bd9Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask; 16577c478bd9Sstevel@tonic-gate c_32 >>= 6; 16587c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16597c478bd9Sstevel@tonic-gate case 1 : 16607c478bd9Sstevel@tonic-gate *(--s_8) = c_32 | first_byte_mark[nc]; 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate return (nc); 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate /* 1666da6c28aaSamw * Convert to a form that can be transferred to the user 16677c478bd9Sstevel@tonic-gate * Assumption's 16687c478bd9Sstevel@tonic-gate * in_length < 256, out_str is at least 255 bytes long 16697c478bd9Sstevel@tonic-gate * The converted byte stream length is returned in out_len 16707c478bd9Sstevel@tonic-gate */ 16717c478bd9Sstevel@tonic-gate #define MAX_ALLOWABLE_STRING 250 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate int32_t 16747c478bd9Sstevel@tonic-gate ud_uncompress(int32_t in_len, int32_t *out_len, 16757c478bd9Sstevel@tonic-gate uint8_t *in_str, uint8_t *out_str) 16767c478bd9Sstevel@tonic-gate { 16777c478bd9Sstevel@tonic-gate uint8_t comp_id, utf8[6]; 16787c478bd9Sstevel@tonic-gate uint16_t w2_char, crc; 16797c478bd9Sstevel@tonic-gate int32_t error, index, c_tx_sz, len_till_now; 16807c478bd9Sstevel@tonic-gate int32_t make_crc, lic, dot_loc, crc_start_loc = 0, k = 0; 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate if (in_len == 0) { 16837c478bd9Sstevel@tonic-gate *out_len = 0; 16847c478bd9Sstevel@tonic-gate out_str[0] = '\0'; 16857c478bd9Sstevel@tonic-gate return (0); 16867c478bd9Sstevel@tonic-gate } 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate error = len_till_now = make_crc = 0; 16897c478bd9Sstevel@tonic-gate dot_loc = lic = -2; 16907c478bd9Sstevel@tonic-gate *out_len = 0; 16917c478bd9Sstevel@tonic-gate crc = 0; 16927c478bd9Sstevel@tonic-gate comp_id = in_str[0]; 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* 16957c478bd9Sstevel@tonic-gate * File names "." and ".." are invalid under unix. 16967c478bd9Sstevel@tonic-gate * Transform them into something 16977c478bd9Sstevel@tonic-gate */ 16987c478bd9Sstevel@tonic-gate if (comp_id == 8) { 16997c478bd9Sstevel@tonic-gate if ((in_str[1] == DOT) && 17007c478bd9Sstevel@tonic-gate ((in_len == 2) || ((in_len == 3) && 17017c478bd9Sstevel@tonic-gate (in_str[2] == DOT)))) { 17027c478bd9Sstevel@tonic-gate out_str[k++] = UNDERBAR; 17037c478bd9Sstevel@tonic-gate len_till_now = 1; 17047c478bd9Sstevel@tonic-gate goto make_append_crc; 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate } else if (comp_id == 0x10) { 17077c478bd9Sstevel@tonic-gate if (((in_str[1] << 8 | in_str[2]) == DOT) && 17087c478bd9Sstevel@tonic-gate ((in_len == 3) || ((in_len == 5) && 17097c478bd9Sstevel@tonic-gate ((in_str[3] << 8 | in_str[4]) == DOT)))) { 17107c478bd9Sstevel@tonic-gate out_str[k++] = UNDERBAR; 17117c478bd9Sstevel@tonic-gate len_till_now = 1; 17127c478bd9Sstevel@tonic-gate goto make_append_crc; 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate } else { 17157c478bd9Sstevel@tonic-gate *out_len = 0; 17167c478bd9Sstevel@tonic-gate return (EINVAL); 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate for (index = 1; index < in_len; ) { 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* 17227c478bd9Sstevel@tonic-gate * Uncompress each character 17237c478bd9Sstevel@tonic-gate */ 17247c478bd9Sstevel@tonic-gate if (comp_id == 0x10) { 17257c478bd9Sstevel@tonic-gate w2_char = in_str[index++] << 8; 17267c478bd9Sstevel@tonic-gate w2_char |= in_str[index++]; 17277c478bd9Sstevel@tonic-gate } else { 17287c478bd9Sstevel@tonic-gate w2_char = in_str[index++]; 17297c478bd9Sstevel@tonic-gate } 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate if (make_crc != 0) { 17327c478bd9Sstevel@tonic-gate crc += w2_char; 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate 17357c478bd9Sstevel@tonic-gate if (w2_char == DOT) { 17367c478bd9Sstevel@tonic-gate dot_loc = len_till_now; 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate /* 17407c478bd9Sstevel@tonic-gate * Get rid of invalid characters 17417c478bd9Sstevel@tonic-gate */ 17427c478bd9Sstevel@tonic-gate if ((w2_char == SLASH) || 17437c478bd9Sstevel@tonic-gate (w2_char == NULL)) { 17447c478bd9Sstevel@tonic-gate make_crc = 1; 17457c478bd9Sstevel@tonic-gate if (((comp_id == 8) && 17467c478bd9Sstevel@tonic-gate (lic != (index - 1))) || 17477c478bd9Sstevel@tonic-gate (comp_id == 0x10) && 17487c478bd9Sstevel@tonic-gate (lic != (index - 2))) { 17497c478bd9Sstevel@tonic-gate w2_char = UNDERBAR; 17507c478bd9Sstevel@tonic-gate lic = index; 17517c478bd9Sstevel@tonic-gate } else { 17527c478bd9Sstevel@tonic-gate lic = index; 17537c478bd9Sstevel@tonic-gate continue; 17547c478bd9Sstevel@tonic-gate } 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate /* 17587c478bd9Sstevel@tonic-gate * Conver a 16bit character to a 17597c478bd9Sstevel@tonic-gate * utf8 byte stream 17607c478bd9Sstevel@tonic-gate */ 17617c478bd9Sstevel@tonic-gate if ((c_tx_sz = ud_utf162utf8(w2_char, utf8)) == 0) { 17627c478bd9Sstevel@tonic-gate error = EINVAL; 17637c478bd9Sstevel@tonic-gate goto end; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate ASSERT(c_tx_sz > 0); 17667c478bd9Sstevel@tonic-gate ASSERT(c_tx_sz < 7); 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate /* 17697c478bd9Sstevel@tonic-gate * The output string is larger than 17707c478bd9Sstevel@tonic-gate * the maximum allowed string length 17717c478bd9Sstevel@tonic-gate */ 17727c478bd9Sstevel@tonic-gate if ((crc_start_loc == 0) && 17737c478bd9Sstevel@tonic-gate ((len_till_now + c_tx_sz) > MAX_ALLOWABLE_STRING)) { 17747c478bd9Sstevel@tonic-gate crc_start_loc = len_till_now; 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate if ((len_till_now + c_tx_sz) < MAXNAMELEN) { 17787c478bd9Sstevel@tonic-gate (void) strncpy((caddr_t)&out_str[len_till_now], 17797c478bd9Sstevel@tonic-gate (caddr_t)utf8, c_tx_sz); 17807c478bd9Sstevel@tonic-gate len_till_now += c_tx_sz; 17817c478bd9Sstevel@tonic-gate } else { 17827c478bd9Sstevel@tonic-gate break; 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate } 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate /* 17877c478bd9Sstevel@tonic-gate * If we need to append CRC do it now 17887c478bd9Sstevel@tonic-gate */ 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate if (make_crc) { 17917c478bd9Sstevel@tonic-gate 17927c478bd9Sstevel@tonic-gate if (len_till_now > MAX_ALLOWABLE_STRING) { 17937c478bd9Sstevel@tonic-gate len_till_now = crc_start_loc; 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate 17967c478bd9Sstevel@tonic-gate if (dot_loc > 0) { 17977c478bd9Sstevel@tonic-gate /* 17987c478bd9Sstevel@tonic-gate * Make space for crc before the DOT 17997c478bd9Sstevel@tonic-gate * move the rest of the file name to the end 18007c478bd9Sstevel@tonic-gate */ 18017c478bd9Sstevel@tonic-gate for (k = len_till_now - 1; k >= dot_loc; k--) { 18027c478bd9Sstevel@tonic-gate out_str[k + 5] = out_str[k]; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate k = dot_loc; 18057c478bd9Sstevel@tonic-gate } else { 18067c478bd9Sstevel@tonic-gate k = len_till_now; 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate make_append_crc: 18097c478bd9Sstevel@tonic-gate crc = ud_crc(in_str, in_len); 18107c478bd9Sstevel@tonic-gate out_str[k++] = POUND; 18117c478bd9Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf000) >> 12]; 18127c478bd9Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf00) >> 8]; 18137c478bd9Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf0) >> 4]; 18147c478bd9Sstevel@tonic-gate out_str[k++] = htoc[crc & 0xf]; 18157c478bd9Sstevel@tonic-gate len_till_now += 5; 18167c478bd9Sstevel@tonic-gate } 18177c478bd9Sstevel@tonic-gate *out_len = len_till_now; 18187c478bd9Sstevel@tonic-gate end: 18197c478bd9Sstevel@tonic-gate return (error); 18207c478bd9Sstevel@tonic-gate } 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate struct buf * 18247c478bd9Sstevel@tonic-gate ud_bread(dev_t dev, daddr_t blkno, long bsize) 18257c478bd9Sstevel@tonic-gate { 18267c478bd9Sstevel@tonic-gate struct buf *bp; 18277c478bd9Sstevel@tonic-gate 18287c478bd9Sstevel@tonic-gate begin: 18297c478bd9Sstevel@tonic-gate bp = bread(dev, blkno, bsize); 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate if (((bp->b_flags & B_ERROR) == 0) && 18327c478bd9Sstevel@tonic-gate (bp->b_bcount != bsize)) { 18337c478bd9Sstevel@tonic-gate /* 18347c478bd9Sstevel@tonic-gate * Buffer cache returned a 18357c478bd9Sstevel@tonic-gate * wrong number of bytes 18367c478bd9Sstevel@tonic-gate * flush the old buffer and 18377c478bd9Sstevel@tonic-gate * reread it again 18387c478bd9Sstevel@tonic-gate */ 18397c478bd9Sstevel@tonic-gate if (bp->b_flags & B_DELWRI) { 18407c478bd9Sstevel@tonic-gate bwrite(bp); 18417c478bd9Sstevel@tonic-gate } else { 18427c478bd9Sstevel@tonic-gate bp->b_flags |= (B_AGE | B_STALE); 18437c478bd9Sstevel@tonic-gate brelse(bp); 18447c478bd9Sstevel@tonic-gate } 18457c478bd9Sstevel@tonic-gate goto begin; 18467c478bd9Sstevel@tonic-gate } 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate return (bp); 18497c478bd9Sstevel@tonic-gate } 18507c478bd9Sstevel@tonic-gate 18517c478bd9Sstevel@tonic-gate /* 18527c478bd9Sstevel@tonic-gate * Decide whether it is okay to remove within a sticky directory. 18537c478bd9Sstevel@tonic-gate * Two conditions need to be met: write access to the directory 18547c478bd9Sstevel@tonic-gate * is needed. In sticky directories, write access is not sufficient; 18557c478bd9Sstevel@tonic-gate * you can remove entries from a directory only if you own the directory, 18567c478bd9Sstevel@tonic-gate * if you are privileged, if you own the entry or if they entry is 18577c478bd9Sstevel@tonic-gate * a plain file and you have write access to that file. 18587c478bd9Sstevel@tonic-gate * Function returns 0 if remove access is granted. 18597c478bd9Sstevel@tonic-gate */ 18607c478bd9Sstevel@tonic-gate int 18617c478bd9Sstevel@tonic-gate ud_sticky_remove_access(struct ud_inode *dir, struct ud_inode *entry, 18627c478bd9Sstevel@tonic-gate struct cred *cr) 18637c478bd9Sstevel@tonic-gate { 18647c478bd9Sstevel@tonic-gate uid_t uid; 18657c478bd9Sstevel@tonic-gate 1866*b39a0235SMilan Cermak ASSERT(RW_LOCK_HELD(&entry->i_contents)); 1867*b39a0235SMilan Cermak 18687c478bd9Sstevel@tonic-gate if ((dir->i_char & ISVTX) && 18697c478bd9Sstevel@tonic-gate (uid = crgetuid(cr)) != dir->i_uid && 18707c478bd9Sstevel@tonic-gate uid != entry->i_uid && 18717c478bd9Sstevel@tonic-gate (entry->i_type != VREG || 1872*b39a0235SMilan Cermak ud_iaccess(entry, IWRITE, cr, 0) != 0)) 18737c478bd9Sstevel@tonic-gate return (secpolicy_vnode_remove(cr)); 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate return (0); 18767c478bd9Sstevel@tonic-gate } 1877