xref: /illumos-gate/usr/src/uts/common/fs/udfs/udf_subr.c (revision 06042525)
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 /*
22b39a0235SMilan 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
ud_vfs_add(struct udf_vfs * udf_vfsp)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
ud_vfs_remove(struct udf_vfs * udf_vfsp)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
ud_xlate_to_daddr(struct udf_vfs * udf_vfsp,uint16_t prn,uint32_t blkno,int32_t nblks,uint32_t * count)1587c478bd9Sstevel@tonic-gate ud_xlate_to_daddr(struct udf_vfs *udf_vfsp,
159*06042525SToomas Soome     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) ||
222da6c28aaSamw 				    (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) +
231da6c28aaSamw 					    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
ud_xlate_to_addr(struct udf_vfs * udf_vfsp,uint16_t prn,daddr_t blkno,int32_t lad)2747c478bd9Sstevel@tonic-gate ud_xlate_to_addr(struct udf_vfs *udf_vfsp,
275*06042525SToomas Soome     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
ud_ip_off2bno(struct ud_inode * ip,uint32_t offset,uint32_t * bno)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) &&
318da6c28aaSamw 		    (offset < (iext->ib_offset + iext->ib_count))) {
3197c478bd9Sstevel@tonic-gate 			*bno = iext->ib_block +
320da6c28aaSamw 			    ((offset - iext->ib_offset) >>
321da6c28aaSamw 			    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
ud_dtime2utime(struct timespec32 * utime,struct tstamp const * dtime)3457c478bd9Sstevel@tonic-gate ud_dtime2utime(struct timespec32 *utime,
346*06042525SToomas Soome     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) +
360da6c28aaSamw 	    dtime->ts_min) * 60 +
361da6c28aaSamw 	    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) +
381da6c28aaSamw 	    dtime->ts_husec) * 100) +
382da6c28aaSamw 	    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 +
388da6c28aaSamw 		    ((1972 - year) / 4) * SEC_PER_DAY -
389da6c28aaSamw 		    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
ud_utime2dtime(struct timespec32 const * utime,struct tstamp * dtime)3987c478bd9Sstevel@tonic-gate ud_utime2dtime(struct timespec32 const *utime,
399*06042525SToomas Soome     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
ud_syncip(struct ud_inode * ip,int32_t flags,int32_t waitfor)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
ud_fbwrite(struct fbuf * fbp,struct ud_inode * ip)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
ud_sbwrite(struct udf_vfs * udf_vfsp)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,
558da6c28aaSamw 	    UD_LOG_VOL_INT, udf_vfsp->udf_iseq_loc,
559da6c28aaSamw 	    sizeof (struct log_vol_int_desc) - 8 +
560da6c28aaSamw 	    8 * udf_vfsp->udf_npart +
561da6c28aaSamw 	    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
ud_sync_indir(struct ud_inode * ip)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
ud_update(int32_t flag)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;
624da6c28aaSamw 	    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 *
ud_still_mounted(struct check_node * checkp)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;
759da6c28aaSamw 	    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
ud_checkclean(struct vfs * vfsp,struct udf_vfs * udf_vfsp,dev_t dev,time_t timev)7907c478bd9Sstevel@tonic-gate ud_checkclean(struct vfs *vfsp,
791*06042525SToomas Soome     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)) ||
799da6c28aaSamw 	    (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
ud_icheck(struct udf_vfs * udf_vfsp)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
ud_flushi(int32_t flag)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;
853da6c28aaSamw 		    ip && ip != (struct ud_inode *)ih;
854da6c28aaSamw 		    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 ||
864da6c28aaSamw 			    (!vn_has_cached_data(vp) &&
865da6c28aaSamw 			    ((flag & (IMOD|IACC|IUPD|ICHG)) == 0)) ||
866da6c28aaSamw 			    (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
ud_update_regid(struct regid * reg)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
ud_make_tag(struct udf_vfs * udf_vfsp,struct tag * tag,uint16_t tag_id,uint32_t blkno,uint16_t crc_len)9177c478bd9Sstevel@tonic-gate ud_make_tag(struct udf_vfs *udf_vfsp,
918*06042525SToomas Soome     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
ud_make_dev_spec_ear(struct dev_spec_ear * ds,major_t major,minor_t minor)9497c478bd9Sstevel@tonic-gate ud_make_dev_spec_ear(struct dev_spec_ear *ds,
950*06042525SToomas Soome     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
ud_get_next_fid(struct ud_inode * ip,struct fbuf ** fbp,uint32_t offset,struct file_id ** fid,uint8_t ** name,uint8_t * buf)9717c478bd9Sstevel@tonic-gate ud_get_next_fid(struct ud_inode *ip, struct fbuf **fbp, uint32_t offset,
972*06042525SToomas Soome     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) ||
1007da6c28aaSamw 	    (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
ud_verify_tag_and_desc(struct tag * tag,uint16_t id,uint32_t blockno,int32_t verify_desc,int32_t desc_len)11787c478bd9Sstevel@tonic-gate ud_verify_tag_and_desc(struct tag *tag, uint16_t id, uint32_t blockno,
1179*06042525SToomas Soome     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,
1273da6c28aaSamw 		    "eah_all(0x%x) exceeds desc. len(0x%x) blockno 0x%x\n",
12747c478bd9Sstevel@tonic-gate 				    SWAP_32(eah->eah_aal), desc_len, blockno);
1275da6c28aaSamw 				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,
1280da6c28aaSamw 		    "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,
1290da6c28aaSamw 		    "Tag Location mismatch blockno %x tag_blockno %x\n",
1291da6c28aaSamw 		    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
ud_crc(uint8_t * addr,int32_t len)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
ud_check_te_unrec(struct udf_vfs * udf_vfsp,caddr_t addr,uint32_t blkno)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
ud_utf82utf16(uint8_t * s_8,uint16_t * c_16,int32_t count)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) ||
1452da6c28aaSamw 		    ((*(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) ||
1458da6c28aaSamw 		    ((*(s_8 + 1) & 0xC0) != 0x80) ||
1459da6c28aaSamw 		    ((*(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) ||
1465da6c28aaSamw 		    ((*(s_8 + 1) & 0xC0) != 0x80) ||
1466da6c28aaSamw 		    ((*(s_8 + 2) & 0xC0) != 0x80) ||
1467da6c28aaSamw 		    ((*(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) ||
1473da6c28aaSamw 		    ((*(s_8 + 1) & 0xC0) != 0x80) ||
1474da6c28aaSamw 		    ((*(s_8 + 2) & 0xC0) != 0x80) ||
1475da6c28aaSamw 		    ((*(s_8 + 3) & 0xC0) != 0x80) ||
1476da6c28aaSamw 		    ((*(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) ||
1482da6c28aaSamw 		    ((*(s_8 + 1) & 0xC0) != 0x80) ||
1483da6c28aaSamw 		    ((*(s_8 + 2) & 0xC0) != 0x80) ||
1484da6c28aaSamw 		    ((*(s_8 + 3) & 0xC0) != 0x80) ||
1485da6c28aaSamw 		    ((*(s_8 + 4) & 0xC0) != 0x80) ||
1486da6c28aaSamw 		    ((*(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
ud_compress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)15387c478bd9Sstevel@tonic-gate ud_compress(int32_t in_len, int32_t *out_len,
1539*06042525SToomas Soome     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],
1557da6c28aaSamw 		    &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))) ||
1573da6c28aaSamw 	    ((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
ud_utf162utf8(uint16_t c_16,uint8_t * s_8)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
1668da6c28aaSamw  * 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
ud_uncompress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)16747c478bd9Sstevel@tonic-gate ud_uncompress(int32_t in_len, int32_t *out_len,
1675*06042525SToomas Soome     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) &&
1700da6c28aaSamw 		    ((in_len == 2) || ((in_len == 3) &&
1701da6c28aaSamw 		    (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) &&
1708da6c28aaSamw 		    ((in_len == 3) || ((in_len == 5) &&
1709da6c28aaSamw 		    ((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) ||
1743*06042525SToomas Soome 		    (w2_char == 0)) {
17447c478bd9Sstevel@tonic-gate 			make_crc = 1;
17457c478bd9Sstevel@tonic-gate 			if (((comp_id == 8) &&
1746da6c28aaSamw 			    (lic != (index - 1))) ||
1747da6c28aaSamw 			    (comp_id == 0x10) &&
1748da6c28aaSamw 			    (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) &&
1773da6c28aaSamw 		    ((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],
1779da6c28aaSamw 			    (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 *
ud_bread(dev_t dev,daddr_t blkno,long bsize)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) &&
1832da6c28aaSamw 	    (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
ud_sticky_remove_access(struct ud_inode * dir,struct ud_inode * entry,struct cred * cr)18617c478bd9Sstevel@tonic-gate ud_sticky_remove_access(struct ud_inode *dir, struct ud_inode *entry,
1862*06042525SToomas Soome     struct cred *cr)
18637c478bd9Sstevel@tonic-gate {
18647c478bd9Sstevel@tonic-gate 	uid_t uid;
18657c478bd9Sstevel@tonic-gate 
1866b39a0235SMilan Cermak 	ASSERT(RW_LOCK_HELD(&entry->i_contents));
1867b39a0235SMilan 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 ||
1872b39a0235SMilan 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