10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12196SMilan.Cermak@Sun.COM * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/types.h>
260Sstevel@tonic-gate #include <sys/t_lock.h>
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/time.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/sysmacros.h>
310Sstevel@tonic-gate #include <sys/resource.h>
320Sstevel@tonic-gate #include <sys/signal.h>
330Sstevel@tonic-gate #include <sys/cred.h>
340Sstevel@tonic-gate #include <sys/user.h>
350Sstevel@tonic-gate #include <sys/buf.h>
360Sstevel@tonic-gate #include <sys/vfs.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <sys/vnode.h>
390Sstevel@tonic-gate #include <sys/mode.h>
400Sstevel@tonic-gate #include <sys/proc.h>
410Sstevel@tonic-gate #include <sys/disp.h>
420Sstevel@tonic-gate #include <sys/file.h>
430Sstevel@tonic-gate #include <sys/fcntl.h>
440Sstevel@tonic-gate #include <sys/flock.h>
450Sstevel@tonic-gate #include <sys/kmem.h>
460Sstevel@tonic-gate #include <sys/uio.h>
470Sstevel@tonic-gate #include <sys/dnlc.h>
480Sstevel@tonic-gate #include <sys/conf.h>
490Sstevel@tonic-gate #include <sys/errno.h>
500Sstevel@tonic-gate #include <sys/mman.h>
510Sstevel@tonic-gate #include <sys/fbuf.h>
520Sstevel@tonic-gate #include <sys/pathname.h>
530Sstevel@tonic-gate #include <sys/debug.h>
540Sstevel@tonic-gate #include <sys/vmsystm.h>
550Sstevel@tonic-gate #include <sys/cmn_err.h>
560Sstevel@tonic-gate #include <sys/dirent.h>
570Sstevel@tonic-gate #include <sys/errno.h>
580Sstevel@tonic-gate #include <sys/modctl.h>
590Sstevel@tonic-gate #include <sys/statvfs.h>
600Sstevel@tonic-gate #include <sys/mount.h>
610Sstevel@tonic-gate #include <sys/sunddi.h>
620Sstevel@tonic-gate #include <sys/bootconf.h>
630Sstevel@tonic-gate #include <sys/policy.h>
640Sstevel@tonic-gate
650Sstevel@tonic-gate #include <vm/hat.h>
660Sstevel@tonic-gate #include <vm/page.h>
670Sstevel@tonic-gate #include <vm/pvn.h>
680Sstevel@tonic-gate #include <vm/as.h>
690Sstevel@tonic-gate #include <vm/seg.h>
700Sstevel@tonic-gate #include <vm/seg_map.h>
710Sstevel@tonic-gate #include <vm/seg_kmem.h>
720Sstevel@tonic-gate #include <vm/seg_vn.h>
730Sstevel@tonic-gate #include <vm/rm.h>
740Sstevel@tonic-gate #include <vm/page.h>
750Sstevel@tonic-gate #include <sys/swap.h>
760Sstevel@tonic-gate
770Sstevel@tonic-gate
780Sstevel@tonic-gate #include <fs/fs_subr.h>
790Sstevel@tonic-gate
800Sstevel@tonic-gate
810Sstevel@tonic-gate #include <sys/fs/udf_volume.h>
820Sstevel@tonic-gate #include <sys/fs/udf_inode.h>
830Sstevel@tonic-gate
840Sstevel@tonic-gate int32_t ud_trace;
850Sstevel@tonic-gate
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate * HASH chains and mutex
880Sstevel@tonic-gate */
890Sstevel@tonic-gate extern union ihead ud_ihead[UD_HASH_SZ];
900Sstevel@tonic-gate extern kmutex_t ud_icache_lock;
910Sstevel@tonic-gate
920Sstevel@tonic-gate
930Sstevel@tonic-gate extern kmutex_t ud_sync_busy;
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate * udf_vfs list manipulation routines
960Sstevel@tonic-gate */
970Sstevel@tonic-gate extern kmutex_t udf_vfs_mutex;
980Sstevel@tonic-gate extern struct udf_vfs *udf_vfs_instances;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * Used to verify that a given entry on the udf_instances list (see below)
1020Sstevel@tonic-gate * still refers to a mounted file system.
1030Sstevel@tonic-gate *
1040Sstevel@tonic-gate * XXX: This is a crock that substitutes for proper locking to coordinate
1050Sstevel@tonic-gate * updates to and uses of the entries in udf_instances.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate struct check_node {
1080Sstevel@tonic-gate struct vfs *vfsp;
1090Sstevel@tonic-gate struct udf_vfs *udf_vfs;
1100Sstevel@tonic-gate dev_t vfs_dev;
1110Sstevel@tonic-gate };
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate vfs_t *ud_still_mounted(struct check_node *);
1140Sstevel@tonic-gate void ud_checkclean(struct vfs *,
1150Sstevel@tonic-gate struct udf_vfs *, dev_t, time_t);
1160Sstevel@tonic-gate int32_t ud_icheck(struct udf_vfs *);
1170Sstevel@tonic-gate void ud_flushi(int32_t);
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * Link udf_vfsp in at the head of the list of udf_vfs_instances.
1210Sstevel@tonic-gate */
1220Sstevel@tonic-gate void
ud_vfs_add(struct udf_vfs * udf_vfsp)1230Sstevel@tonic-gate ud_vfs_add(struct udf_vfs *udf_vfsp)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex);
1260Sstevel@tonic-gate udf_vfsp->udf_next = udf_vfs_instances;
1270Sstevel@tonic-gate udf_vfs_instances = udf_vfsp;
1280Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate * Remove udf_vfsp from the list of udf_vfs_instances.
1330Sstevel@tonic-gate *
1340Sstevel@tonic-gate * Does no error checking; udf_vfsp is assumed to actually be on the list.
1350Sstevel@tonic-gate */
1360Sstevel@tonic-gate void
ud_vfs_remove(struct udf_vfs * udf_vfsp)1370Sstevel@tonic-gate ud_vfs_remove(struct udf_vfs *udf_vfsp)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate struct udf_vfs **delpt = &udf_vfs_instances;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex);
1420Sstevel@tonic-gate for (; *delpt != NULL; delpt = &((*delpt)->udf_next)) {
1430Sstevel@tonic-gate if (*delpt == udf_vfsp) {
1440Sstevel@tonic-gate *delpt = udf_vfsp->udf_next;
1450Sstevel@tonic-gate udf_vfsp->udf_next = NULL;
1460Sstevel@tonic-gate break;
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate }
1490Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate * Search for the prn in the array
1540Sstevel@tonic-gate * of partitions and translate
1550Sstevel@tonic-gate * to the disk block number
1560Sstevel@tonic-gate */
1570Sstevel@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)1580Sstevel@tonic-gate ud_xlate_to_daddr(struct udf_vfs *udf_vfsp,
1590Sstevel@tonic-gate uint16_t prn, uint32_t blkno, int32_t nblks, uint32_t *count)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate int32_t i;
1620Sstevel@tonic-gate struct ud_map *map;
1630Sstevel@tonic-gate struct ud_part *ud_parts;
1640Sstevel@tonic-gate uint32_t lblkno, retblkno = 0, *addr;
1650Sstevel@tonic-gate uint32_t begin_req, end_req;
1660Sstevel@tonic-gate uint32_t begin_bad, end_bad;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate ud_printf("ud_xlate_to_daddr\n");
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /* Is prn valid */
1710Sstevel@tonic-gate if (prn < udf_vfsp->udf_nmaps) {
1720Sstevel@tonic-gate map = &(udf_vfsp->udf_maps[prn]);
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate if (map->udm_flags == UDM_MAP_VPM) {
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate * Map is Virtual Parition Map
1770Sstevel@tonic-gate * first check for the appropriate
1780Sstevel@tonic-gate * table and then return the converted
1790Sstevel@tonic-gate * block number
1800Sstevel@tonic-gate */
1810Sstevel@tonic-gate for (i = 0; i < map->udm_nent; i++) {
1820Sstevel@tonic-gate if (blkno < map->udm_count[i]) {
1830Sstevel@tonic-gate addr = map->udm_addr[i];
1840Sstevel@tonic-gate lblkno = SWAP_32(addr[blkno]);
1850Sstevel@tonic-gate *count = 1;
1860Sstevel@tonic-gate break;
1870Sstevel@tonic-gate } else {
1880Sstevel@tonic-gate blkno -= map->udm_count[i];
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate } else if (map->udm_flags == UDM_MAP_SPM) {
1920Sstevel@tonic-gate struct stbl *stbl;
1930Sstevel@tonic-gate struct stbl_entry *te;
1940Sstevel@tonic-gate int32_t entry_count;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate /*
1970Sstevel@tonic-gate * Map type is Sparable Parition Map
1980Sstevel@tonic-gate * if the block is in the map
1990Sstevel@tonic-gate * return the translated block
2000Sstevel@tonic-gate * other wise use the regular
2010Sstevel@tonic-gate * partition stuff
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate begin_req = blkno;
2040Sstevel@tonic-gate end_req = begin_req + nblks;
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate stbl = (struct stbl *)map->udm_spaddr[0];
2070Sstevel@tonic-gate te = (struct stbl_entry *)&stbl->stbl_entry;
2080Sstevel@tonic-gate entry_count = SWAP_16(stbl->stbl_len);
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate for (i = 0; i < entry_count; i++, te++) {
2110Sstevel@tonic-gate begin_bad = SWAP_32(te->sent_ol);
2120Sstevel@tonic-gate end_bad = begin_bad + map->udm_plen;
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate * Either unmapped or reserved
2160Sstevel@tonic-gate * or defective. need not consider
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate if (begin_bad >= (uint32_t)0xFFFFFFF0) {
2190Sstevel@tonic-gate continue;
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate if ((end_req < begin_bad) ||
2225331Samw (begin_req >= end_bad)) {
2230Sstevel@tonic-gate continue;
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate if (begin_req < begin_bad) {
2270Sstevel@tonic-gate ASSERT(end_req >= begin_bad);
2280Sstevel@tonic-gate end_req = begin_bad;
2290Sstevel@tonic-gate } else {
2300Sstevel@tonic-gate retblkno = SWAP_32(te->sent_ml) +
2315331Samw begin_req - begin_bad;
2320Sstevel@tonic-gate if (end_req < end_bad) {
2330Sstevel@tonic-gate *count = end_req - begin_req;
2340Sstevel@tonic-gate } else {
2350Sstevel@tonic-gate *count = end_bad - begin_req;
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate goto end;
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate lblkno = blkno;
2420Sstevel@tonic-gate *count = end_req - begin_req;
2430Sstevel@tonic-gate } else {
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate * regular partition
2460Sstevel@tonic-gate */
2470Sstevel@tonic-gate lblkno = blkno;
2480Sstevel@tonic-gate *count = nblks;
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate ud_parts = udf_vfsp->udf_parts;
2510Sstevel@tonic-gate for (i = 0; i < udf_vfsp->udf_npart; i++) {
2520Sstevel@tonic-gate if (map->udm_pn == ud_parts->udp_number) {
2530Sstevel@tonic-gate /*
2540Sstevel@tonic-gate * Check if the block is inside
2550Sstevel@tonic-gate * the partition or not
2560Sstevel@tonic-gate */
2570Sstevel@tonic-gate if (lblkno >= ud_parts->udp_length) {
2580Sstevel@tonic-gate retblkno = 0;
2590Sstevel@tonic-gate } else {
2600Sstevel@tonic-gate retblkno = ud_parts->udp_start + lblkno;
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate goto end;
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate ud_parts ++;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate end:
2690Sstevel@tonic-gate return (retblkno);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate #ifdef UNDEF
2730Sstevel@tonic-gate uint32_t
ud_xlate_to_addr(struct udf_vfs * udf_vfsp,uint16_t prn,daddr_t blkno,int32_t lad)2740Sstevel@tonic-gate ud_xlate_to_addr(struct udf_vfs *udf_vfsp,
2750Sstevel@tonic-gate uint16_t prn, daddr_t blkno, int32_t lad)
2760Sstevel@tonic-gate {
2770Sstevel@tonic-gate int32_t i;
2780Sstevel@tonic-gate struct ud_part *ud_parts;
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate ud_printf("ud_xlate_to_addr\n");
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate if (lad == 0) {
2830Sstevel@tonic-gate return (blkno);
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate ud_parts = udf_vfsp->udf_parts;
2860Sstevel@tonic-gate for (i = 0; i < udf_vfsp->udf_npart; i++) {
2870Sstevel@tonic-gate if (prn == ud_parts->udp_number) {
2880Sstevel@tonic-gate return (blkno - ud_parts->udp_start);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate return (0);
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate #endif
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * Directories do not have holes
2970Sstevel@tonic-gate */
2980Sstevel@tonic-gate int32_t
ud_ip_off2bno(struct ud_inode * ip,uint32_t offset,uint32_t * bno)2990Sstevel@tonic-gate ud_ip_off2bno(struct ud_inode *ip, uint32_t offset, uint32_t *bno)
3000Sstevel@tonic-gate {
3010Sstevel@tonic-gate int32_t i, error;
3020Sstevel@tonic-gate struct icb_ext *iext;
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate ASSERT(ip->i_type == VDIR);
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
3070Sstevel@tonic-gate *bno = ip->i_icb_block;
3080Sstevel@tonic-gate return (0);
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate if ((error = ud_read_icb_till_off(ip, (u_offset_t)offset)) != 0) {
3120Sstevel@tonic-gate return (error);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate for (i = 0; i < ip->i_ext_used; i++) {
3160Sstevel@tonic-gate iext = &ip->i_ext[i];
3170Sstevel@tonic-gate if ((iext->ib_offset <= offset) &&
3185331Samw (offset < (iext->ib_offset + iext->ib_count))) {
3190Sstevel@tonic-gate *bno = iext->ib_block +
3205331Samw ((offset - iext->ib_offset) >>
3215331Samw ip->i_udf->udf_l2b_shift);
3220Sstevel@tonic-gate break;
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate return (0);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate static uint32_t cum_sec[] = {
3290Sstevel@tonic-gate 0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280,
3300Sstevel@tonic-gate 0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500
3310Sstevel@tonic-gate };
3320Sstevel@tonic-gate static uint32_t cum_sec_leap[] = {
3330Sstevel@tonic-gate 0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400,
3340Sstevel@tonic-gate 0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680
3350Sstevel@tonic-gate };
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate #define DAYS_PER_YEAR 365
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate #define SEC_PER_DAY 0x15180
3400Sstevel@tonic-gate #define SEC_PER_YEAR 0x1e13380
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate /* This holds good till yr 2100 */
3440Sstevel@tonic-gate void
ud_dtime2utime(struct timespec32 * utime,struct tstamp const * dtime)3450Sstevel@tonic-gate ud_dtime2utime(struct timespec32 *utime,
3460Sstevel@tonic-gate struct tstamp const *dtime)
3470Sstevel@tonic-gate {
3480Sstevel@tonic-gate int16_t year, tzone;
3490Sstevel@tonic-gate int32_t sec;
3500Sstevel@tonic-gate uint32_t *cp;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate ud_printf("ud_dtime2utime\n");
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate year = SWAP_16(dtime->ts_year);
3550Sstevel@tonic-gate cp = (year % 4) ? cum_sec : cum_sec_leap;
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate utime->tv_sec = cp[dtime->ts_month - 1];
3580Sstevel@tonic-gate utime->tv_sec += (dtime->ts_day - 1) * SEC_PER_DAY;
3590Sstevel@tonic-gate utime->tv_sec += ((dtime->ts_hour * 60) +
3605331Samw dtime->ts_min) * 60 +
3615331Samw dtime->ts_sec;
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate tzone = SWAP_16(dtime->ts_tzone);
3640Sstevel@tonic-gate if ((tzone & TMODE) == 0x1000) {
3650Sstevel@tonic-gate /* Local time */
3660Sstevel@tonic-gate if ((tzone & TINVALID) != TINVALID) {
3670Sstevel@tonic-gate if (tzone & TSIGN) {
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * Sign extend the tzone
3700Sstevel@tonic-gate */
3710Sstevel@tonic-gate sec = tzone | 0xFFFFF000;
3720Sstevel@tonic-gate } else {
3730Sstevel@tonic-gate sec = tzone & TOFFSET;
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate sec *= 60;
3760Sstevel@tonic-gate utime->tv_sec -= sec;
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate utime->tv_nsec = ((((dtime->ts_csec * 100) +
3815331Samw dtime->ts_husec) * 100) +
3825331Samw dtime->ts_usec) * 1000;
3830Sstevel@tonic-gate if (year >= 1970) {
3840Sstevel@tonic-gate utime->tv_sec += (year - 1970) * SEC_PER_YEAR;
3850Sstevel@tonic-gate utime->tv_sec += ((year - 1969) / 4) * SEC_PER_DAY;
3860Sstevel@tonic-gate } else {
3870Sstevel@tonic-gate utime->tv_sec = ((1970 - year) * SEC_PER_YEAR +
3885331Samw ((1972 - year) / 4) * SEC_PER_DAY -
3895331Samw utime->tv_sec) * -1;
3900Sstevel@tonic-gate if (utime->tv_nsec) {
3910Sstevel@tonic-gate utime->tv_sec++;
3920Sstevel@tonic-gate utime->tv_nsec = 1000 * 1000 * 1000 - utime->tv_nsec;
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate void
ud_utime2dtime(struct timespec32 const * utime,struct tstamp * dtime)3980Sstevel@tonic-gate ud_utime2dtime(struct timespec32 const *utime,
3990Sstevel@tonic-gate struct tstamp *dtime)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate time32_t sec = utime->tv_sec;
4020Sstevel@tonic-gate int32_t usec = utime->tv_nsec / 1000;
4030Sstevel@tonic-gate uint32_t lyrs, nyrs, dummy;
4040Sstevel@tonic-gate uint32_t *cp;
4050Sstevel@tonic-gate int32_t before = 0;
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate ud_printf("ud_utime2dtime\n");
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate if (sec < 0) {
4100Sstevel@tonic-gate before = 1;
4110Sstevel@tonic-gate sec = sec * -1;
4120Sstevel@tonic-gate if (usec) {
4130Sstevel@tonic-gate sec = sec + 1;
4140Sstevel@tonic-gate usec = 1000 * 1000 - usec;
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate dtime->ts_csec = usec / 10000;
4190Sstevel@tonic-gate usec %= 10000;
4200Sstevel@tonic-gate dtime->ts_husec = usec / 100;
4210Sstevel@tonic-gate dtime->ts_usec = usec % 100;
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate nyrs = sec / SEC_PER_YEAR;
4240Sstevel@tonic-gate if (before == 0) {
4250Sstevel@tonic-gate lyrs = (nyrs + 1) / 4;
4260Sstevel@tonic-gate } else {
4270Sstevel@tonic-gate lyrs = (nyrs + 2) / 4;
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate if (nyrs != ((sec - (lyrs * SEC_PER_DAY)) / SEC_PER_YEAR)) {
4300Sstevel@tonic-gate nyrs--;
4310Sstevel@tonic-gate if (before == 0) {
4320Sstevel@tonic-gate lyrs = (nyrs + 1) / 4;
4330Sstevel@tonic-gate } else {
4340Sstevel@tonic-gate lyrs = (nyrs + 2) / 4;
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate }
4370Sstevel@tonic-gate sec -= nyrs * SEC_PER_YEAR + lyrs * SEC_PER_DAY;
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate if (before == 1) {
4400Sstevel@tonic-gate nyrs = 1970 - nyrs;
4410Sstevel@tonic-gate if (sec != 0) {
4420Sstevel@tonic-gate nyrs --;
4430Sstevel@tonic-gate if ((nyrs % 4) == 0) {
4440Sstevel@tonic-gate sec = SEC_PER_YEAR + SEC_PER_DAY - sec;
4450Sstevel@tonic-gate } else {
4460Sstevel@tonic-gate sec = SEC_PER_YEAR - sec;
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate } else {
4500Sstevel@tonic-gate nyrs += 1970;
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate cp = (nyrs % 4) ? cum_sec : cum_sec_leap;
4530Sstevel@tonic-gate dummy = sec / (SEC_PER_DAY * 29);
4540Sstevel@tonic-gate if (dummy > 11) {
4550Sstevel@tonic-gate dummy = 11;
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate if (sec < cp[dummy]) {
4580Sstevel@tonic-gate dummy--;
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate dtime->ts_year = SWAP_16(nyrs);
4610Sstevel@tonic-gate dtime->ts_month = dummy;
4620Sstevel@tonic-gate sec -= cp[dtime->ts_month];
4630Sstevel@tonic-gate dtime->ts_month++;
4640Sstevel@tonic-gate dtime->ts_day = sec / SEC_PER_DAY;
4650Sstevel@tonic-gate sec -= dtime->ts_day * SEC_PER_DAY;
4660Sstevel@tonic-gate dtime->ts_day++;
4670Sstevel@tonic-gate dtime->ts_hour = sec / SECS_PER_HOUR;
4680Sstevel@tonic-gate sec -= dtime->ts_hour * SECS_PER_HOUR;
4690Sstevel@tonic-gate dtime->ts_min = sec / SECS_PER_MIN;
4700Sstevel@tonic-gate sec -= dtime->ts_min * SECS_PER_MIN;
4710Sstevel@tonic-gate dtime->ts_sec = (uint8_t)sec;
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* GMT offset is 0 */
4740Sstevel@tonic-gate dtime->ts_tzone = SWAP_16(0x1000);
4750Sstevel@tonic-gate }
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate int32_t
ud_syncip(struct ud_inode * ip,int32_t flags,int32_t waitfor)4790Sstevel@tonic-gate ud_syncip(struct ud_inode *ip, int32_t flags, int32_t waitfor)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate int32_t error;
4820Sstevel@tonic-gate struct vnode *vp = ITOV(ip);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate ud_printf("ud_syncip\n");
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate if (ip->i_udf == NULL) {
4870Sstevel@tonic-gate return (0);
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate if (!vn_has_cached_data(vp) || (vp->v_type == VCHR)) {
4910Sstevel@tonic-gate error = 0;
4920Sstevel@tonic-gate } else {
4930Sstevel@tonic-gate rw_exit(&ip->i_contents);
4940Sstevel@tonic-gate error = VOP_PUTPAGE(vp, (offset_t)0,
4955331Samw (uint32_t)0, flags, CRED(), NULL);
4960Sstevel@tonic-gate rw_enter(&ip->i_contents, RW_WRITER);
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate
4990Sstevel@tonic-gate if (ip->i_flag & (IUPD |IACC | ICHG | IMOD)) {
5000Sstevel@tonic-gate ud_iupdat(ip, waitfor);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate return (error);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate /* ARGSUSED */
5080Sstevel@tonic-gate int32_t
ud_fbwrite(struct fbuf * fbp,struct ud_inode * ip)5090Sstevel@tonic-gate ud_fbwrite(struct fbuf *fbp, struct ud_inode *ip)
5100Sstevel@tonic-gate {
5110Sstevel@tonic-gate ud_printf("ud_fbwrite\n");
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate ASSERT(fbp != NULL);
5140Sstevel@tonic-gate
5150Sstevel@tonic-gate return (fbwrite(fbp));
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate void
ud_sbwrite(struct udf_vfs * udf_vfsp)5200Sstevel@tonic-gate ud_sbwrite(struct udf_vfs *udf_vfsp)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate struct log_vol_int_desc *lvid;
5230Sstevel@tonic-gate struct ud_part *ud_part;
5240Sstevel@tonic-gate struct lvid_iu *iu;
5250Sstevel@tonic-gate uint32_t *temp;
5260Sstevel@tonic-gate int32_t i, c;
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate ud_printf("ud_sbwrite\n");
5290Sstevel@tonic-gate ASSERT(udf_vfsp);
5300Sstevel@tonic-gate ASSERT(MUTEX_HELD(&udf_vfsp->udf_lock));
5310Sstevel@tonic-gate
5320Sstevel@tonic-gate /*
5330Sstevel@tonic-gate * updatable information in the superblock
5340Sstevel@tonic-gate * integrity type, udf_maxuniq, udf_nfiles, udf_ndirs
5350Sstevel@tonic-gate * udp_nfree in lvid
5360Sstevel@tonic-gate */
5370Sstevel@tonic-gate lvid = (struct log_vol_int_desc *)udf_vfsp->udf_lvid;
5380Sstevel@tonic-gate if (udf_vfsp->udf_clean == UDF_DIRTY) {
5390Sstevel@tonic-gate lvid->lvid_int_type = SWAP_32(LOG_VOL_OPEN_INT);
5400Sstevel@tonic-gate } else {
5410Sstevel@tonic-gate lvid->lvid_int_type = SWAP_32(LOG_VOL_CLOSE_INT);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate lvid->lvid_uniqid = SWAP_64(udf_vfsp->udf_maxuniq);
5440Sstevel@tonic-gate temp = lvid->lvid_fst;
5450Sstevel@tonic-gate c = SWAP_32(lvid->lvid_npart);
5460Sstevel@tonic-gate ud_part = udf_vfsp->udf_parts;
5470Sstevel@tonic-gate for (i = 0; i < c; i++) {
5480Sstevel@tonic-gate temp[i] = SWAP_32(ud_part->udp_nfree);
5490Sstevel@tonic-gate ud_part++;
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate iu = (struct lvid_iu *)(temp + c * 2);
5520Sstevel@tonic-gate iu->lvidiu_nfiles = SWAP_32(udf_vfsp->udf_nfiles);
5530Sstevel@tonic-gate iu->lvidiu_ndirs = SWAP_32(udf_vfsp->udf_ndirs);
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate ud_update_regid(&iu->lvidiu_regid);
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate ud_make_tag(udf_vfsp, &lvid->lvid_tag,
5585331Samw UD_LOG_VOL_INT, udf_vfsp->udf_iseq_loc,
5595331Samw sizeof (struct log_vol_int_desc) - 8 +
5605331Samw 8 * udf_vfsp->udf_npart +
5615331Samw SWAP_32(lvid->lvid_liu));
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate * Don't release the buffer after writing to the disk
5650Sstevel@tonic-gate */
5660Sstevel@tonic-gate bwrite2(udf_vfsp->udf_iseq);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate int32_t
ud_sync_indir(struct ud_inode * ip)5710Sstevel@tonic-gate ud_sync_indir(struct ud_inode *ip)
5720Sstevel@tonic-gate {
5730Sstevel@tonic-gate int32_t elen;
5740Sstevel@tonic-gate
5750Sstevel@tonic-gate ud_printf("ud_sync_indir\n");
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
5780Sstevel@tonic-gate return (0);
5790Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
5800Sstevel@tonic-gate elen = sizeof (struct short_ad);
5810Sstevel@tonic-gate } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
5820Sstevel@tonic-gate elen = sizeof (struct long_ad);
5830Sstevel@tonic-gate } else {
5840Sstevel@tonic-gate return (EINVAL);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate if (ip->i_astrat == STRAT_TYPE4) {
5880Sstevel@tonic-gate int32_t ndentry;
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate ndentry = ip->i_max_emb / elen;
5910Sstevel@tonic-gate if (ip->i_ext_used < ndentry) {
5920Sstevel@tonic-gate return (0);
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate ASSERT(ip->i_con);
5950Sstevel@tonic-gate } else {
5960Sstevel@tonic-gate cmn_err(CE_WARN, "unsupported strategy type\n");
5970Sstevel@tonic-gate return (EINVAL);
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate return (0);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate
6030Sstevel@tonic-gate void
ud_update(int32_t flag)6040Sstevel@tonic-gate ud_update(int32_t flag)
6050Sstevel@tonic-gate {
6060Sstevel@tonic-gate struct vfs *vfsp;
6070Sstevel@tonic-gate struct udf_vfs *udfsp, *udfsnext, *update_list = NULL;
6080Sstevel@tonic-gate int32_t check_cnt = 0;
6090Sstevel@tonic-gate size_t check_size;
6100Sstevel@tonic-gate struct check_node *check_list, *ptr;
6110Sstevel@tonic-gate time_t start_time;
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate ud_printf("ud_update\n");
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate mutex_enter(&ud_sync_busy);
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate * Examine all udf_vfs structures and add those that we can lock to the
6180Sstevel@tonic-gate * update list. This is so that we don't hold the list lock for a
6190Sstevel@tonic-gate * long time. If vfs_lock fails for a file system instance, then skip
6200Sstevel@tonic-gate * it because somebody is doing a unmount on it.
6210Sstevel@tonic-gate */
6220Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex);
6230Sstevel@tonic-gate for (udfsp = udf_vfs_instances;
6245331Samw udfsp != NULL; udfsp = udfsp->udf_next) {
6250Sstevel@tonic-gate vfsp = udfsp->udf_vfs;
6260Sstevel@tonic-gate if (vfs_lock(vfsp) != 0) {
6270Sstevel@tonic-gate continue;
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate udfsp->udf_wnext = update_list;
6300Sstevel@tonic-gate update_list = udfsp;
6310Sstevel@tonic-gate check_cnt++;
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex);
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate if (update_list == NULL) {
6360Sstevel@tonic-gate mutex_exit(&ud_sync_busy);
6370Sstevel@tonic-gate return;
6380Sstevel@tonic-gate }
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate check_size = sizeof (struct check_node) * check_cnt;
6410Sstevel@tonic-gate check_list = ptr = kmem_alloc(check_size, KM_NOSLEEP);
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate * Write back modified superblocks.
6450Sstevel@tonic-gate * Consistency check that the superblock of
6460Sstevel@tonic-gate * each file system is still in the buffer cache.
6470Sstevel@tonic-gate *
6480Sstevel@tonic-gate * Note that the update_list traversal is done without the protection
6490Sstevel@tonic-gate * of an overall list lock, so it's necessary to rely on the fact that
6500Sstevel@tonic-gate * each entry of the list is vfs_locked when moving from one entry to
6510Sstevel@tonic-gate * the next. This works because a concurrent attempt to add an entry
6520Sstevel@tonic-gate * to another thread's update_list won't find it, since it'll already
6530Sstevel@tonic-gate * be locked.
6540Sstevel@tonic-gate */
6550Sstevel@tonic-gate check_cnt = 0;
6560Sstevel@tonic-gate for (udfsp = update_list; udfsp != NULL; udfsp = udfsnext) {
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * Need to grab the next ptr before we unlock this one so
6590Sstevel@tonic-gate * another thread doesn't grab it and change it before we move
6600Sstevel@tonic-gate * on to the next vfs. (Once we unlock it, it's ok if another
6610Sstevel@tonic-gate * thread finds it to add it to its own update_list; we don't
6620Sstevel@tonic-gate * attempt to refer to it through our list any more.)
6630Sstevel@tonic-gate */
6640Sstevel@tonic-gate udfsnext = udfsp->udf_wnext;
6650Sstevel@tonic-gate vfsp = udfsp->udf_vfs;
6660Sstevel@tonic-gate
6670Sstevel@tonic-gate if (!vfsp->vfs_data) {
6680Sstevel@tonic-gate vfs_unlock(vfsp);
6690Sstevel@tonic-gate continue;
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate mutex_enter(&udfsp->udf_lock);
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate /*
6740Sstevel@tonic-gate * Build up the STABLE check list, so we can unlock the vfs
6750Sstevel@tonic-gate * until we do the actual checking.
6760Sstevel@tonic-gate */
6770Sstevel@tonic-gate if (check_list != NULL) {
6780Sstevel@tonic-gate if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) {
6790Sstevel@tonic-gate ptr->vfsp = vfsp;
6800Sstevel@tonic-gate ptr->udf_vfs = udfsp;
6810Sstevel@tonic-gate ptr->vfs_dev = vfsp->vfs_dev;
6820Sstevel@tonic-gate ptr++;
6830Sstevel@tonic-gate check_cnt++;
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /*
6880Sstevel@tonic-gate * superblock is not modified
6890Sstevel@tonic-gate */
6900Sstevel@tonic-gate if (udfsp->udf_mod == 0) {
6910Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock);
6920Sstevel@tonic-gate vfs_unlock(vfsp);
6930Sstevel@tonic-gate continue;
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) {
6960Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock);
6970Sstevel@tonic-gate mutex_exit(&ud_sync_busy);
6980Sstevel@tonic-gate cmn_err(CE_WARN, "update ro udfs mod\n");
6990Sstevel@tonic-gate return;
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate udfsp->udf_mod = 0;
7020Sstevel@tonic-gate mutex_exit(&udfsp->udf_lock);
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate ud_update_superblock(vfsp);
7050Sstevel@tonic-gate vfs_unlock(vfsp);
7060Sstevel@tonic-gate }
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate ud_flushi(flag);
7090Sstevel@tonic-gate /*
7100Sstevel@tonic-gate * Force stale buffer cache information to be flushed,
7110Sstevel@tonic-gate * for all devices. This should cause any remaining control
7120Sstevel@tonic-gate * information (e.g., inode info) to be flushed back.
7130Sstevel@tonic-gate */
7140Sstevel@tonic-gate bflush((dev_t)NODEV);
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate if (check_list == NULL) {
7170Sstevel@tonic-gate mutex_exit(&ud_sync_busy);
7180Sstevel@tonic-gate return;
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate /*
7220Sstevel@tonic-gate * For each udf filesystem in the STABLE check_list, update
7230Sstevel@tonic-gate * the clean flag if warranted.
7240Sstevel@tonic-gate */
7250Sstevel@tonic-gate start_time = gethrestime_sec();
7260Sstevel@tonic-gate for (ptr = check_list; check_cnt > 0; check_cnt--, ptr++) {
7270Sstevel@tonic-gate /*
7280Sstevel@tonic-gate * ud_still_mounted() returns with vfsp and the vfs_reflock
7290Sstevel@tonic-gate * held if ptr refers to a vfs that is still mounted.
7300Sstevel@tonic-gate */
7310Sstevel@tonic-gate if ((vfsp = ud_still_mounted(ptr)) == NULL) {
7320Sstevel@tonic-gate continue;
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate ud_checkclean(vfsp, ptr->udf_vfs, ptr->vfs_dev, start_time);
7350Sstevel@tonic-gate vfs_unlock(vfsp);
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate mutex_exit(&ud_sync_busy);
7380Sstevel@tonic-gate kmem_free(check_list, check_size);
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate
7410Sstevel@tonic-gate
7420Sstevel@tonic-gate /*
7430Sstevel@tonic-gate * Returns vfsp and hold the lock if the vfs is still being mounted.
7440Sstevel@tonic-gate * Otherwise, returns 0.
7450Sstevel@tonic-gate *
7460Sstevel@tonic-gate * For our purposes, "still mounted" means that the file system still appears
7470Sstevel@tonic-gate * on the list of UFS file system instances.
7480Sstevel@tonic-gate */
7490Sstevel@tonic-gate vfs_t *
ud_still_mounted(struct check_node * checkp)7500Sstevel@tonic-gate ud_still_mounted(struct check_node *checkp)
7510Sstevel@tonic-gate {
7520Sstevel@tonic-gate struct vfs *vfsp;
7530Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate ud_printf("ud_still_mounted\n");
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate mutex_enter(&udf_vfs_mutex);
7580Sstevel@tonic-gate for (udf_vfsp = udf_vfs_instances;
7595331Samw udf_vfsp != NULL; udf_vfsp = udf_vfsp->udf_next) {
7600Sstevel@tonic-gate if (udf_vfsp != checkp->udf_vfs) {
7610Sstevel@tonic-gate continue;
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate /*
7640Sstevel@tonic-gate * Tentative match: verify it and try to lock. (It's not at
7650Sstevel@tonic-gate * all clear how the verification could fail, given that we've
7660Sstevel@tonic-gate * gotten this far. We would have had to reallocate the
7670Sstevel@tonic-gate * ufsvfs struct at hand for a new incarnation; is that really
7680Sstevel@tonic-gate * possible in the interval from constructing the check_node
7690Sstevel@tonic-gate * to here?)
7700Sstevel@tonic-gate */
7710Sstevel@tonic-gate vfsp = udf_vfsp->udf_vfs;
7720Sstevel@tonic-gate if (vfsp != checkp->vfsp) {
7730Sstevel@tonic-gate continue;
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate if (vfsp->vfs_dev != checkp->vfs_dev) {
7760Sstevel@tonic-gate continue;
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate if (vfs_lock(vfsp) != 0) {
7790Sstevel@tonic-gate continue;
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex);
7820Sstevel@tonic-gate return (vfsp);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate mutex_exit(&udf_vfs_mutex);
7850Sstevel@tonic-gate return (NULL);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate /* ARGSUSED */
7890Sstevel@tonic-gate void
ud_checkclean(struct vfs * vfsp,struct udf_vfs * udf_vfsp,dev_t dev,time_t timev)7900Sstevel@tonic-gate ud_checkclean(struct vfs *vfsp,
7910Sstevel@tonic-gate struct udf_vfs *udf_vfsp, dev_t dev, time_t timev)
7920Sstevel@tonic-gate {
7930Sstevel@tonic-gate ud_printf("ud_checkclean\n");
7940Sstevel@tonic-gate udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
7950Sstevel@tonic-gate /*
7960Sstevel@tonic-gate * ignore if buffers or inodes are busy
7970Sstevel@tonic-gate */
7980Sstevel@tonic-gate if ((bcheck(dev, udf_vfsp->udf_iseq)) ||
7995331Samw (ud_icheck(udf_vfsp))) {
8000Sstevel@tonic-gate return;
8010Sstevel@tonic-gate }
8020Sstevel@tonic-gate mutex_enter(&udf_vfsp->udf_lock);
8030Sstevel@tonic-gate ud_sbwrite(udf_vfsp);
8040Sstevel@tonic-gate mutex_exit(&udf_vfsp->udf_lock);
8050Sstevel@tonic-gate }
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate int32_t
ud_icheck(struct udf_vfs * udf_vfsp)8080Sstevel@tonic-gate ud_icheck(struct udf_vfs *udf_vfsp)
8090Sstevel@tonic-gate {
8100Sstevel@tonic-gate int32_t index, error = 0;
8110Sstevel@tonic-gate union ihead *ih;
8120Sstevel@tonic-gate struct ud_inode *ip;
8130Sstevel@tonic-gate
8140Sstevel@tonic-gate mutex_enter(&ud_icache_lock);
8150Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++) {
8160Sstevel@tonic-gate ih = &ud_ihead[index];
8170Sstevel@tonic-gate for (ip = ih->ih_chain[0];
8180Sstevel@tonic-gate ip != (struct ud_inode *)ih; ip = ip->i_forw) {
8190Sstevel@tonic-gate if ((ip->i_udf == udf_vfsp) &&
8200Sstevel@tonic-gate ((ip->i_flag & (IMOD|IUPD|ICHG)) ||
8210Sstevel@tonic-gate (RW_ISWRITER(&ip->i_rwlock)) ||
8220Sstevel@tonic-gate ((ip->i_nlink <= 0) && (ip->i_flag & IREF)))) {
8230Sstevel@tonic-gate error = 1;
8240Sstevel@tonic-gate goto end;
8250Sstevel@tonic-gate }
8260Sstevel@tonic-gate }
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate end:
8290Sstevel@tonic-gate mutex_exit(&ud_icache_lock);
8300Sstevel@tonic-gate return (error);
8310Sstevel@tonic-gate }
8320Sstevel@tonic-gate
8330Sstevel@tonic-gate void
ud_flushi(int32_t flag)8340Sstevel@tonic-gate ud_flushi(int32_t flag)
8350Sstevel@tonic-gate {
8360Sstevel@tonic-gate struct ud_inode *ip, *lip;
8370Sstevel@tonic-gate struct vnode *vp;
8380Sstevel@tonic-gate int cheap = flag & SYNC_ATTR;
8390Sstevel@tonic-gate int32_t index;
8400Sstevel@tonic-gate union ihead *ih;
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate /*
8430Sstevel@tonic-gate * Write back each (modified) inode,
8440Sstevel@tonic-gate * but don't sync back pages if vnode is
8450Sstevel@tonic-gate * part of the virtual swap device.
8460Sstevel@tonic-gate */
8470Sstevel@tonic-gate mutex_enter(&ud_icache_lock);
8480Sstevel@tonic-gate for (index = 0; index < UD_HASH_SZ; index++) {
8490Sstevel@tonic-gate ih = &ud_ihead[index];
8500Sstevel@tonic-gate lip = NULL;
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate for (ip = ih->ih_chain[0], lip = NULL;
8535331Samw ip && ip != (struct ud_inode *)ih;
8545331Samw ip = ip->i_forw) {
8550Sstevel@tonic-gate int flag = ip->i_flag;
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate vp = ITOV(ip);
8580Sstevel@tonic-gate /*
8590Sstevel@tonic-gate * Skip locked & inactive inodes.
8600Sstevel@tonic-gate * Skip vnodes w/ no cached data and no inode changes.
8610Sstevel@tonic-gate * Skip read-only vnodes
8620Sstevel@tonic-gate */
8630Sstevel@tonic-gate if ((flag & IREF) == 0 ||
8645331Samw (!vn_has_cached_data(vp) &&
8655331Samw ((flag & (IMOD|IACC|IUPD|ICHG)) == 0)) ||
8665331Samw (vp->v_vfsp == NULL) || vn_is_readonly(vp)) {
8670Sstevel@tonic-gate continue;
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate if (!rw_tryenter(&ip->i_contents, RW_WRITER)) {
8710Sstevel@tonic-gate continue;
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate VN_HOLD(vp);
8750Sstevel@tonic-gate
8760Sstevel@tonic-gate if (lip != NULL) {
8770Sstevel@tonic-gate ITIMES(lip);
8780Sstevel@tonic-gate VN_RELE(ITOV(lip));
8790Sstevel@tonic-gate }
8800Sstevel@tonic-gate lip = ip;
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate /*
8830Sstevel@tonic-gate * If this is an inode sync for file system hardening
8840Sstevel@tonic-gate * or this is a full sync but file is a swap file,
8850Sstevel@tonic-gate * don't sync pages but make sure the inode is up
8860Sstevel@tonic-gate * to date. In other cases, push everything out.
8870Sstevel@tonic-gate */
8880Sstevel@tonic-gate if (cheap || IS_SWAPVP(vp)) {
8890Sstevel@tonic-gate ud_iupdat(ip, 0);
8900Sstevel@tonic-gate } else {
8910Sstevel@tonic-gate (void) ud_syncip(ip, B_ASYNC, I_SYNC);
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate rw_exit(&ip->i_contents);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate if (lip != NULL) {
8960Sstevel@tonic-gate ITIMES(lip);
8970Sstevel@tonic-gate VN_RELE(ITOV(lip));
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate mutex_exit(&ud_icache_lock);
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate void
ud_update_regid(struct regid * reg)9050Sstevel@tonic-gate ud_update_regid(struct regid *reg)
9060Sstevel@tonic-gate {
9070Sstevel@tonic-gate ud_printf("ud_update_regid\n");
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate bzero(reg->reg_id, 23);
9100Sstevel@tonic-gate (void) strncpy(reg->reg_id, SUN_IMPL_ID, SUN_IMPL_ID_LEN);
9110Sstevel@tonic-gate reg->reg_ids[0] = SUN_OS_CLASS;
9120Sstevel@tonic-gate reg->reg_ids[1] = SUN_OS_ID;
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate /* ARGSUSED4 */
9160Sstevel@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)9170Sstevel@tonic-gate ud_make_tag(struct udf_vfs *udf_vfsp,
9180Sstevel@tonic-gate struct tag *tag, uint16_t tag_id, uint32_t blkno, uint16_t crc_len)
9190Sstevel@tonic-gate {
9200Sstevel@tonic-gate int32_t i;
9210Sstevel@tonic-gate uint16_t crc;
9220Sstevel@tonic-gate uint8_t *addr, cksum = 0;
9230Sstevel@tonic-gate
9240Sstevel@tonic-gate ud_printf("ud_make_tag\n");
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate ASSERT(crc_len > 0x10);
9270Sstevel@tonic-gate addr = (uint8_t *)tag;
9280Sstevel@tonic-gate crc_len -= sizeof (struct tag);
9290Sstevel@tonic-gate crc = ud_crc(addr + 0x10, crc_len);
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate tag->tag_id = SWAP_16(tag_id);
9320Sstevel@tonic-gate tag->tag_desc_ver = SWAP_16(2);
9330Sstevel@tonic-gate tag->tag_cksum = 0;
9340Sstevel@tonic-gate tag->tag_res = 0;
9350Sstevel@tonic-gate tag->tag_sno = SWAP_16(udf_vfsp->udf_tsno);
9360Sstevel@tonic-gate tag->tag_crc = SWAP_16(crc);
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate tag->tag_crc_len = SWAP_16(crc_len);
9390Sstevel@tonic-gate tag->tag_loc = SWAP_32(blkno);
9400Sstevel@tonic-gate
9410Sstevel@tonic-gate addr = (uint8_t *)tag;
9420Sstevel@tonic-gate for (i = 0; i <= 15; i++) {
9430Sstevel@tonic-gate cksum += addr[i];
9440Sstevel@tonic-gate }
9450Sstevel@tonic-gate tag->tag_cksum = cksum;
9460Sstevel@tonic-gate }
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate int32_t
ud_make_dev_spec_ear(struct dev_spec_ear * ds,major_t major,minor_t minor)9490Sstevel@tonic-gate ud_make_dev_spec_ear(struct dev_spec_ear *ds,
9500Sstevel@tonic-gate major_t major, minor_t minor)
9510Sstevel@tonic-gate {
9520Sstevel@tonic-gate int32_t attr_len;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate ud_printf("ud_make_dev_spec_ear\n");
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate bzero(ds, sizeof (struct dev_spec_ear));
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate attr_len = sizeof (struct dev_spec_ear);
9590Sstevel@tonic-gate ds->ds_atype = SWAP_32(12);
9600Sstevel@tonic-gate ds->ds_astype = 1;
9610Sstevel@tonic-gate ds->ds_attr_len = SWAP_32(attr_len);
9620Sstevel@tonic-gate ds->ds_iu_len = 0;
9630Sstevel@tonic-gate ds->ds_major_id = SWAP_32(major);
9640Sstevel@tonic-gate ds->ds_minor_id = SWAP_32(minor);
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate return (attr_len);
9670Sstevel@tonic-gate }
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate
9700Sstevel@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)9710Sstevel@tonic-gate ud_get_next_fid(struct ud_inode *ip, struct fbuf **fbp, uint32_t offset,
9720Sstevel@tonic-gate struct file_id **fid, uint8_t **name, uint8_t *buf)
9730Sstevel@tonic-gate {
9740Sstevel@tonic-gate struct vnode *vp = ITOV(ip);
9750Sstevel@tonic-gate caddr_t beg, end;
9760Sstevel@tonic-gate int32_t error, lbsize, lbmask, sz, iulen, idlen, copied = 0;
9770Sstevel@tonic-gate struct udf_vfs *udf_vfsp;
9780Sstevel@tonic-gate uint8_t *obuf;
9790Sstevel@tonic-gate int32_t count;
9800Sstevel@tonic-gate uint32_t tbno;
9810Sstevel@tonic-gate uint16_t crc_len;
9820Sstevel@tonic-gate uint32_t len;
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate ud_printf("ud_get_next_fid\n");
9850Sstevel@tonic-gate
9860Sstevel@tonic-gate obuf = buf;
9870Sstevel@tonic-gate udf_vfsp = ip->i_udf;
9880Sstevel@tonic-gate lbsize = udf_vfsp->udf_lbsize;
9890Sstevel@tonic-gate lbmask = udf_vfsp->udf_lbmask;
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate if ((error = ud_ip_off2bno(ip, offset, &tbno)) != 0) {
9920Sstevel@tonic-gate return (error);
9930Sstevel@tonic-gate }
9940Sstevel@tonic-gate /* First time read */
9950Sstevel@tonic-gate if (*fbp == NULL) {
9960Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)(offset & ~lbmask),
9970Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) {
9980Sstevel@tonic-gate return (error);
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate }
10010Sstevel@tonic-gate
10020Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count;
10030Sstevel@tonic-gate beg = (*fbp)->fb_addr + (offset & lbmask);
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate
10060Sstevel@tonic-gate if ((offset % lbsize) ||
10075331Samw (offset == 0)) {
10080Sstevel@tonic-gate sz = end - beg;
10090Sstevel@tonic-gate } else {
10100Sstevel@tonic-gate sz = 0;
10110Sstevel@tonic-gate }
10120Sstevel@tonic-gate
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate if (F_LEN <= sz) {
10150Sstevel@tonic-gate *fid = (struct file_id *)beg;
10160Sstevel@tonic-gate beg += F_LEN;
10170Sstevel@tonic-gate } else {
10180Sstevel@tonic-gate copied = 1;
10190Sstevel@tonic-gate bcopy(beg, buf, sz);
10200Sstevel@tonic-gate fbrelse(*fbp, S_OTHER);
10210Sstevel@tonic-gate *fbp = NULL;
10220Sstevel@tonic-gate
10230Sstevel@tonic-gate /* Skip to next block */
10240Sstevel@tonic-gate if (offset & lbmask) {
10250Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize;
10260Sstevel@tonic-gate }
10270Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset,
10280Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) {
10290Sstevel@tonic-gate return (error);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count;
10320Sstevel@tonic-gate beg = (*fbp)->fb_addr;
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate bcopy(beg, buf + sz, F_LEN - sz);
10350Sstevel@tonic-gate beg = beg + F_LEN - sz;
10360Sstevel@tonic-gate *fid = (struct file_id *)buf;
10370Sstevel@tonic-gate
10380Sstevel@tonic-gate buf += F_LEN;
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate /*
10430Sstevel@tonic-gate * Check if this a valid file_identifier
10440Sstevel@tonic-gate */
10450Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
10460Sstevel@tonic-gate tbno, 0, lbsize) != 0) {
10470Sstevel@tonic-gate /*
10480Sstevel@tonic-gate * Either end of directory or corrupted
10490Sstevel@tonic-gate */
10500Sstevel@tonic-gate return (EINVAL);
10510Sstevel@tonic-gate }
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate crc_len = SWAP_16((*fid)->fid_tag.tag_crc_len);
10540Sstevel@tonic-gate if (crc_len > udf_vfsp->udf_lbsize) {
10550Sstevel@tonic-gate /*
10560Sstevel@tonic-gate * Entries cannot be larger than
10570Sstevel@tonic-gate * blocksize
10580Sstevel@tonic-gate */
10590Sstevel@tonic-gate return (EINVAL);
10600Sstevel@tonic-gate }
10610Sstevel@tonic-gate
10620Sstevel@tonic-gate if (crc_len < (F_LEN - sizeof (struct tag))) {
10630Sstevel@tonic-gate iulen = SWAP_16((*fid)->fid_iulen);
10640Sstevel@tonic-gate idlen = FID_LEN(*fid) - F_LEN;
10650Sstevel@tonic-gate goto use_id_iu_len;
10660Sstevel@tonic-gate }
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate /*
10690Sstevel@tonic-gate * By now beg points to the start fo the file name
10700Sstevel@tonic-gate */
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate sz = end - beg;
10730Sstevel@tonic-gate len = crc_len + sizeof (struct tag) - (F_LEN);
10740Sstevel@tonic-gate if (len <= sz) {
10750Sstevel@tonic-gate if (copied == 1) {
10760Sstevel@tonic-gate bcopy(beg, buf, len);
10770Sstevel@tonic-gate buf += len;
10780Sstevel@tonic-gate }
10790Sstevel@tonic-gate beg += len;
10800Sstevel@tonic-gate } else {
10810Sstevel@tonic-gate copied = 1;
10820Sstevel@tonic-gate /*
10830Sstevel@tonic-gate * We are releasing the
10840Sstevel@tonic-gate * old buffer so copy fid to buf
10850Sstevel@tonic-gate */
10860Sstevel@tonic-gate if (obuf == buf) {
10870Sstevel@tonic-gate count = F_LEN + sz;
10880Sstevel@tonic-gate bcopy(*fid, buf, count);
10890Sstevel@tonic-gate *fid = (struct file_id *)buf;
10900Sstevel@tonic-gate buf += count;
10910Sstevel@tonic-gate } else {
10920Sstevel@tonic-gate bcopy(beg, buf, sz);
10930Sstevel@tonic-gate *fid = (struct file_id *)buf;
10940Sstevel@tonic-gate buf += sz;
10950Sstevel@tonic-gate }
10960Sstevel@tonic-gate fbrelse(*fbp, S_OTHER);
10970Sstevel@tonic-gate *fbp = NULL;
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate /* Skip to next block */
11000Sstevel@tonic-gate if (offset & lbmask) {
11010Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize;
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset,
11040Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) {
11050Sstevel@tonic-gate return (error);
11060Sstevel@tonic-gate }
11070Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count;
11080Sstevel@tonic-gate beg = (*fbp)->fb_addr;
11090Sstevel@tonic-gate count = len - sz;
11100Sstevel@tonic-gate bcopy(beg, buf, count);
11110Sstevel@tonic-gate beg += count;
11120Sstevel@tonic-gate }
11130Sstevel@tonic-gate
11140Sstevel@tonic-gate /*
11150Sstevel@tonic-gate * First we verify that the tag id and the FID_LEN are valid.
11160Sstevel@tonic-gate * Next we verify the crc of the descriptor.
11170Sstevel@tonic-gate */
11180Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
11190Sstevel@tonic-gate tbno, 0, lbsize) != 0) {
11200Sstevel@tonic-gate /* directory is corrupted */
11210Sstevel@tonic-gate return (EINVAL);
11220Sstevel@tonic-gate }
11230Sstevel@tonic-gate if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
11240Sstevel@tonic-gate tbno, 1, FID_LEN(*fid)) != 0) {
11250Sstevel@tonic-gate /* directory is corrupted */
11260Sstevel@tonic-gate return (EINVAL);
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate idlen = FID_LEN(*fid);
11300Sstevel@tonic-gate
11310Sstevel@tonic-gate idlen -= F_LEN;
11320Sstevel@tonic-gate iulen = SWAP_16((*fid)->fid_iulen);
11330Sstevel@tonic-gate if (crc_len < (F_LEN - sizeof (struct tag) + idlen)) {
11340Sstevel@tonic-gate use_id_iu_len:
11350Sstevel@tonic-gate len = (F_LEN - sizeof (struct tag) + idlen) - crc_len;
11360Sstevel@tonic-gate sz = end - beg;
11370Sstevel@tonic-gate if (len <= sz) {
11380Sstevel@tonic-gate if (copied == 1) {
11390Sstevel@tonic-gate bcopy(beg, buf, len);
11400Sstevel@tonic-gate }
11410Sstevel@tonic-gate } else {
11420Sstevel@tonic-gate if (obuf == buf) {
11430Sstevel@tonic-gate count = crc_len + sizeof (struct tag);
11440Sstevel@tonic-gate bcopy(*fid, buf, count);
11450Sstevel@tonic-gate *fid = (struct file_id *)buf;
11460Sstevel@tonic-gate buf += count;
11470Sstevel@tonic-gate } else {
11480Sstevel@tonic-gate bcopy(beg, buf, sz);
11490Sstevel@tonic-gate *fid = (struct file_id *)buf;
11500Sstevel@tonic-gate buf += sz;
11510Sstevel@tonic-gate }
11520Sstevel@tonic-gate fbrelse(*fbp, S_OTHER);
11530Sstevel@tonic-gate *fbp = NULL;
11540Sstevel@tonic-gate
11550Sstevel@tonic-gate /* Skip to next block */
11560Sstevel@tonic-gate if (offset & lbmask) {
11570Sstevel@tonic-gate offset = (offset & ~lbmask) + lbsize;
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate if ((error = fbread(vp, (offset_t)offset,
11600Sstevel@tonic-gate lbsize, S_READ, fbp)) != 0) {
11610Sstevel@tonic-gate return (error);
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate end = (*fbp)->fb_addr + (*fbp)->fb_count;
11640Sstevel@tonic-gate beg = (*fbp)->fb_addr;
11650Sstevel@tonic-gate count = len - sz;
11660Sstevel@tonic-gate bcopy(beg, buf, count);
11670Sstevel@tonic-gate beg += count;
11680Sstevel@tonic-gate }
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate *name = ((uint8_t *)*fid) + F_LEN + iulen;
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate return (0);
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate
11770Sstevel@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)11780Sstevel@tonic-gate ud_verify_tag_and_desc(struct tag *tag, uint16_t id, uint32_t blockno,
11790Sstevel@tonic-gate int32_t verify_desc, int32_t desc_len)
11800Sstevel@tonic-gate {
11810Sstevel@tonic-gate int32_t i;
11820Sstevel@tonic-gate uint8_t *addr, cksum = 0;
11830Sstevel@tonic-gate uint16_t crc;
11840Sstevel@tonic-gate file_entry_t *fe;
11850Sstevel@tonic-gate struct ext_attr_hdr *eah;
11860Sstevel@tonic-gate struct file_id *fid;
11870Sstevel@tonic-gate int32_t fidlen, ea_off;
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate if (tag->tag_id != SWAP_16(id)) {
11900Sstevel@tonic-gate return (1);
11910Sstevel@tonic-gate }
11920Sstevel@tonic-gate addr = (uint8_t *)tag;
11930Sstevel@tonic-gate eah = (struct ext_attr_hdr *)tag;
11940Sstevel@tonic-gate for (i = 0; i < 4; i++) {
11950Sstevel@tonic-gate cksum += addr[i];
11960Sstevel@tonic-gate }
11970Sstevel@tonic-gate for (i = 5; i <= 15; i++) {
11980Sstevel@tonic-gate cksum += addr[i];
11990Sstevel@tonic-gate }
12000Sstevel@tonic-gate if (cksum != tag->tag_cksum) {
12010Sstevel@tonic-gate cmn_err(CE_NOTE,
12020Sstevel@tonic-gate "Checksum Does not Verify TAG %x CALC %x blockno 0x%x\n",
12030Sstevel@tonic-gate tag->tag_cksum, cksum, blockno);
12040Sstevel@tonic-gate return (1);
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate /*
12070Sstevel@tonic-gate * Validate the meta data for UD_FILE_ID_DESC.
12080Sstevel@tonic-gate * The FID_LEN should not exceed the desc_len.
12090Sstevel@tonic-gate * This validation is done before the entire descriptor is read.
12100Sstevel@tonic-gate * A call to this routine is made initially with verify_desc set as 0
12110Sstevel@tonic-gate * but a non zero value in desc_len.
12120Sstevel@tonic-gate */
12130Sstevel@tonic-gate if (id == UD_FILE_ID_DESC) {
12140Sstevel@tonic-gate fid = (struct file_id *)tag;
12150Sstevel@tonic-gate fidlen = FID_LEN(fid);
12160Sstevel@tonic-gate if (fidlen > desc_len) {
12170Sstevel@tonic-gate cmn_err(CE_NOTE,
12180Sstevel@tonic-gate "Invalid FID_LEN(0x%x). Greater than expected(0x%x) blockno 0x%x\n",
12190Sstevel@tonic-gate fidlen, desc_len, blockno);
12200Sstevel@tonic-gate return (1);
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate }
12230Sstevel@tonic-gate if (verify_desc == 0)
12240Sstevel@tonic-gate return (0);
12250Sstevel@tonic-gate /*
12260Sstevel@tonic-gate * We are done verifying the tag. We proceed with verifying the
12270Sstevel@tonic-gate * the descriptor. desc_len indicates the size of the structure
12280Sstevel@tonic-gate * pointed to by argument tag. It includes the size of struct tag.
12290Sstevel@tonic-gate * We first check the tag_crc_len since we use this to compute the
12300Sstevel@tonic-gate * crc of the descriptor.
12310Sstevel@tonic-gate * Verifying the crc is normally sufficient to ensure the integrity
12320Sstevel@tonic-gate * of the meta data in the descriptor. However given the paranoia
12330Sstevel@tonic-gate * about the panic caused by illegal meta data values we do an
12340Sstevel@tonic-gate * additional check of the meta data for decriptor UD_FILE_ENTRY.
12350Sstevel@tonic-gate * (The original panic was caused because this routine was not called
12360Sstevel@tonic-gate * to verify the integrity of the tag and descriptor.)
12370Sstevel@tonic-gate */
12380Sstevel@tonic-gate if (SWAP_16(tag->tag_crc_len) > (desc_len - sizeof (struct tag))) {
12390Sstevel@tonic-gate cmn_err(CE_NOTE,
12400Sstevel@tonic-gate "tag_crc_len(0x%x) is greater than expected len(0x%x) blockno 0x%x\n",
12410Sstevel@tonic-gate SWAP_16(tag->tag_crc_len),
12420Sstevel@tonic-gate desc_len, blockno);
12430Sstevel@tonic-gate return (1);
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate if (tag->tag_crc_len) {
12460Sstevel@tonic-gate crc = ud_crc(addr + 0x10, SWAP_16(tag->tag_crc_len));
12470Sstevel@tonic-gate if (crc != SWAP_16(tag->tag_crc)) {
12480Sstevel@tonic-gate cmn_err(CE_NOTE, "CRC mismatch TAG_ID 0x%x TAG_CRC 0x%x"
12490Sstevel@tonic-gate " Computed crc 0x%x tag_loc %x blockno 0x%x\n",
12500Sstevel@tonic-gate id, SWAP_16(tag->tag_crc), crc,
12510Sstevel@tonic-gate SWAP_32(tag->tag_loc), blockno);
12520Sstevel@tonic-gate return (1);
12530Sstevel@tonic-gate }
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate switch (id) {
12560Sstevel@tonic-gate case UD_FILE_ENTRY:
12570Sstevel@tonic-gate fe = (file_entry_t *)tag;
12580Sstevel@tonic-gate if ((offsetof(struct file_entry, fe_spec) +
12590Sstevel@tonic-gate SWAP_32(fe->fe_len_ear) +
12600Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc)) > desc_len) {
12610Sstevel@tonic-gate cmn_err(CE_NOTE,
12620Sstevel@tonic-gate "fe_len_ear(0x%x) fe_len_adesc(0x%x) fields are not OK. blockno 0x%x\n",
12630Sstevel@tonic-gate SWAP_32(fe->fe_len_ear),
12640Sstevel@tonic-gate SWAP_32(fe->fe_len_adesc),
12650Sstevel@tonic-gate blockno);
12660Sstevel@tonic-gate return (1);
12670Sstevel@tonic-gate }
12680Sstevel@tonic-gate break;
12690Sstevel@tonic-gate case UD_EXT_ATTR_HDR:
12700Sstevel@tonic-gate eah = (struct ext_attr_hdr *)tag;
12710Sstevel@tonic-gate if (SWAP_32(eah->eah_aal) > desc_len) {
12720Sstevel@tonic-gate cmn_err(CE_NOTE,
12735331Samw "eah_all(0x%x) exceeds desc. len(0x%x) blockno 0x%x\n",
12740Sstevel@tonic-gate SWAP_32(eah->eah_aal), desc_len, blockno);
12755331Samw return (1);
12760Sstevel@tonic-gate }
12770Sstevel@tonic-gate ea_off = GET_32(&eah->eah_ial);
12780Sstevel@tonic-gate if (ea_off >= desc_len) {
12790Sstevel@tonic-gate cmn_err(CE_NOTE,
12805331Samw "ea_off(0x%x) is not less than ea_len(0x%x) blockno 0x%x\n",
12810Sstevel@tonic-gate ea_off, desc_len, blockno);
12820Sstevel@tonic-gate return (1);
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate break;
12850Sstevel@tonic-gate default:
12860Sstevel@tonic-gate break;
12870Sstevel@tonic-gate }
12880Sstevel@tonic-gate if (SWAP_32(blockno) != tag->tag_loc) {
12890Sstevel@tonic-gate cmn_err(CE_NOTE,
12905331Samw "Tag Location mismatch blockno %x tag_blockno %x\n",
12915331Samw blockno, SWAP_32(tag->tag_loc));
12920Sstevel@tonic-gate return (1);
12930Sstevel@tonic-gate }
12940Sstevel@tonic-gate return (0);
12950Sstevel@tonic-gate }
12960Sstevel@tonic-gate
12970Sstevel@tonic-gate /* **************** udf specific subroutines *********************** */
12980Sstevel@tonic-gate
12990Sstevel@tonic-gate uint16_t ud_crc_table[256] = {
13000Sstevel@tonic-gate 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
13010Sstevel@tonic-gate 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
13020Sstevel@tonic-gate 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
13030Sstevel@tonic-gate 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
13040Sstevel@tonic-gate 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
13050Sstevel@tonic-gate 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
13060Sstevel@tonic-gate 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
13070Sstevel@tonic-gate 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
13080Sstevel@tonic-gate 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
13090Sstevel@tonic-gate 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
13100Sstevel@tonic-gate 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
13110Sstevel@tonic-gate 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
13120Sstevel@tonic-gate 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
13130Sstevel@tonic-gate 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
13140Sstevel@tonic-gate 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
13150Sstevel@tonic-gate 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
13160Sstevel@tonic-gate 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
13170Sstevel@tonic-gate 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
13180Sstevel@tonic-gate 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
13190Sstevel@tonic-gate 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
13200Sstevel@tonic-gate 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
13210Sstevel@tonic-gate 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
13220Sstevel@tonic-gate 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
13230Sstevel@tonic-gate 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
13240Sstevel@tonic-gate 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
13250Sstevel@tonic-gate 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
13260Sstevel@tonic-gate 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
13270Sstevel@tonic-gate 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
13280Sstevel@tonic-gate 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
13290Sstevel@tonic-gate 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
13300Sstevel@tonic-gate 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
13310Sstevel@tonic-gate 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
13320Sstevel@tonic-gate };
13330Sstevel@tonic-gate
13340Sstevel@tonic-gate uint16_t
ud_crc(uint8_t * addr,int32_t len)13350Sstevel@tonic-gate ud_crc(uint8_t *addr, int32_t len)
13360Sstevel@tonic-gate {
13370Sstevel@tonic-gate uint16_t crc = 0;
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate while (len-- > 0) {
13400Sstevel@tonic-gate crc = ud_crc_table[(crc >> 8 ^ *addr++) & 0xff] ^ (crc<<8);
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate
13430Sstevel@tonic-gate return (crc);
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate typedef unsigned short unicode_t;
13470Sstevel@tonic-gate
13480Sstevel@tonic-gate #define POUND 0x0023
13490Sstevel@tonic-gate #define DOT 0x002E
13500Sstevel@tonic-gate #define SLASH 0x002F
13510Sstevel@tonic-gate #define UNDERBAR 0x005F
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate static uint16_t htoc[16] = {'0', '1', '2', '3',
13550Sstevel@tonic-gate '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
13560Sstevel@tonic-gate
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate /*
13590Sstevel@tonic-gate * An unrecorded block will return all
13600Sstevel@tonic-gate * 0's on a WORM media. to simulate
13610Sstevel@tonic-gate * a unrecorded block on a rw media
13620Sstevel@tonic-gate * we fill it with all zero's
13630Sstevel@tonic-gate * return 0 : If unrecorded
13640Sstevel@tonic-gate * return 1 : If recorded.
13650Sstevel@tonic-gate */
13660Sstevel@tonic-gate uint32_t
ud_check_te_unrec(struct udf_vfs * udf_vfsp,caddr_t addr,uint32_t blkno)13670Sstevel@tonic-gate ud_check_te_unrec(struct udf_vfs *udf_vfsp, caddr_t addr, uint32_t blkno)
13680Sstevel@tonic-gate {
13690Sstevel@tonic-gate int32_t i, lbsize;
13700Sstevel@tonic-gate struct term_entry *te;
13710Sstevel@tonic-gate
13720Sstevel@tonic-gate ASSERT(udf_vfsp);
13730Sstevel@tonic-gate ASSERT(addr);
13740Sstevel@tonic-gate
13750Sstevel@tonic-gate te = (struct term_entry *)addr;
13760Sstevel@tonic-gate if (ud_verify_tag_and_desc(&te->te_tag, UD_TERMINAL_ENT,
13770Sstevel@tonic-gate blkno, 1, udf_vfsp->udf_lbsize) != 0) {
13780Sstevel@tonic-gate lbsize = udf_vfsp->udf_lbsize;
13790Sstevel@tonic-gate for (i = 0; i < lbsize; i++) {
13800Sstevel@tonic-gate if (addr[i] != 0) {
13810Sstevel@tonic-gate return (1);
13820Sstevel@tonic-gate }
13830Sstevel@tonic-gate }
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate return (0);
13860Sstevel@tonic-gate }
13870Sstevel@tonic-gate
13880Sstevel@tonic-gate
13890Sstevel@tonic-gate /*
13900Sstevel@tonic-gate * The algorithms ud_utf82utf16 and ud_utf162utf8
13910Sstevel@tonic-gate * donot handle surrogates. This is unicode 1.1 as I
13920Sstevel@tonic-gate * understand. When writing udf2.0 this code has
13930Sstevel@tonic-gate * to be changed to process surrogates also
13940Sstevel@tonic-gate * (Dont ask me what is a surrogate character)
13950Sstevel@tonic-gate */
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate /*
13980Sstevel@tonic-gate * This will take a utf8 string convert the first character
13990Sstevel@tonic-gate * to utf16 and return the number of bytes consumed in this
14000Sstevel@tonic-gate * process. A 0 will be returned if the character is invalid
14010Sstevel@tonic-gate */
14020Sstevel@tonic-gate uint8_t bytes_from_utf8[] = {
14030Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14040Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14050Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14060Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14070Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14080Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14090Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14100Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14110Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14120Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14130Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14140Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
14150Sstevel@tonic-gate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
14160Sstevel@tonic-gate 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
14170Sstevel@tonic-gate 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
14180Sstevel@tonic-gate 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
14190Sstevel@tonic-gate };
14200Sstevel@tonic-gate int32_t
ud_utf82utf16(uint8_t * s_8,uint16_t * c_16,int32_t count)14210Sstevel@tonic-gate ud_utf82utf16(uint8_t *s_8, uint16_t *c_16, int32_t count)
14220Sstevel@tonic-gate {
14230Sstevel@tonic-gate int32_t extra_bytes;
14240Sstevel@tonic-gate uint32_t c_32;
14250Sstevel@tonic-gate ASSERT(s_8);
14260Sstevel@tonic-gate ASSERT(c_16);
14270Sstevel@tonic-gate
14280Sstevel@tonic-gate /*
14290Sstevel@tonic-gate * First convert to a 32-bit
14300Sstevel@tonic-gate * character
14310Sstevel@tonic-gate */
14320Sstevel@tonic-gate c_32 = 0;
14330Sstevel@tonic-gate extra_bytes = bytes_from_utf8[*s_8];
14340Sstevel@tonic-gate if (extra_bytes > count) {
14350Sstevel@tonic-gate return (0);
14360Sstevel@tonic-gate }
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate /*
14390Sstevel@tonic-gate * verify if the string is a valid
14400Sstevel@tonic-gate * utf8 string
14410Sstevel@tonic-gate */
14420Sstevel@tonic-gate if (extra_bytes == 0) {
14430Sstevel@tonic-gate /*
14440Sstevel@tonic-gate * Apply one byte rule
14450Sstevel@tonic-gate */
14460Sstevel@tonic-gate if (*s_8 & 0x80) {
14470Sstevel@tonic-gate return (0);
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate c_32 = *s_8 & 0x7F;
14500Sstevel@tonic-gate } else if (extra_bytes == 1) {
14510Sstevel@tonic-gate if (((*s_8 & 0xE0) != 0xC0) ||
14525331Samw ((*(s_8 + 1) & 0xC0) != 0x80)) {
14530Sstevel@tonic-gate return (0);
14540Sstevel@tonic-gate }
14550Sstevel@tonic-gate c_32 = *s_8 & 0x1F;
14560Sstevel@tonic-gate } else if (extra_bytes == 2) {
14570Sstevel@tonic-gate if (((*s_8 & 0xF0) != 0xE0) ||
14585331Samw ((*(s_8 + 1) & 0xC0) != 0x80) ||
14595331Samw ((*(s_8 + 2) & 0xC0) != 0x80)) {
14600Sstevel@tonic-gate return (0);
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate c_32 = *s_8 & 0x0F;
14630Sstevel@tonic-gate } else if (extra_bytes == 3) {
14640Sstevel@tonic-gate if (((*s_8 & 0xF8) != 0xF0) ||
14655331Samw ((*(s_8 + 1) & 0xC0) != 0x80) ||
14665331Samw ((*(s_8 + 2) & 0xC0) != 0x80) ||
14675331Samw ((*(s_8 + 3) & 0xC0) != 0x80)) {
14680Sstevel@tonic-gate return (0);
14690Sstevel@tonic-gate }
14700Sstevel@tonic-gate c_32 = *s_8 & 0x07;
14710Sstevel@tonic-gate } else if (extra_bytes == 4) {
14720Sstevel@tonic-gate if (((*s_8 & 0xFC) != 0xF8) ||
14735331Samw ((*(s_8 + 1) & 0xC0) != 0x80) ||
14745331Samw ((*(s_8 + 2) & 0xC0) != 0x80) ||
14755331Samw ((*(s_8 + 3) & 0xC0) != 0x80) ||
14765331Samw ((*(s_8 + 4) & 0xC0) != 0x80)) {
14770Sstevel@tonic-gate return (0);
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate c_32 = *s_8 & 0x03;
14800Sstevel@tonic-gate } else if (extra_bytes == 5) {
14810Sstevel@tonic-gate if (((*s_8 & 0xFE) != 0xFC) ||
14825331Samw ((*(s_8 + 1) & 0xC0) != 0x80) ||
14835331Samw ((*(s_8 + 2) & 0xC0) != 0x80) ||
14845331Samw ((*(s_8 + 3) & 0xC0) != 0x80) ||
14855331Samw ((*(s_8 + 4) & 0xC0) != 0x80) ||
14865331Samw ((*(s_8 + 5) & 0xC0) != 0x80)) {
14870Sstevel@tonic-gate return (0);
14880Sstevel@tonic-gate }
14890Sstevel@tonic-gate c_32 = *s_8 & 0x01;
14900Sstevel@tonic-gate } else {
14910Sstevel@tonic-gate return (0);
14920Sstevel@tonic-gate }
14930Sstevel@tonic-gate s_8++;
14940Sstevel@tonic-gate
14950Sstevel@tonic-gate /*
14960Sstevel@tonic-gate * Convert to 32-bit character
14970Sstevel@tonic-gate */
14980Sstevel@tonic-gate switch (extra_bytes) {
14990Sstevel@tonic-gate case 5 :
15000Sstevel@tonic-gate c_32 <<= 6;
15010Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F);
15020Sstevel@tonic-gate /* FALLTHROUGH */
15030Sstevel@tonic-gate case 4 :
15040Sstevel@tonic-gate c_32 <<= 6;
15050Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F);
15060Sstevel@tonic-gate /* FALLTHROUGH */
15070Sstevel@tonic-gate case 3 :
15080Sstevel@tonic-gate c_32 <<= 6;
15090Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F);
15100Sstevel@tonic-gate /* FALLTHROUGH */
15110Sstevel@tonic-gate case 2 :
15120Sstevel@tonic-gate c_32 <<= 6;
15130Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F);
15140Sstevel@tonic-gate /* FALLTHROUGH */
15150Sstevel@tonic-gate case 1 :
15160Sstevel@tonic-gate c_32 <<= 6;
15170Sstevel@tonic-gate c_32 += (*s_8++ & 0x3F);
15180Sstevel@tonic-gate /* FALLTHROUGH */
15190Sstevel@tonic-gate case 0 :
15200Sstevel@tonic-gate break;
15210Sstevel@tonic-gate }
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate /*
15240Sstevel@tonic-gate * now convert the 32-bit
15250Sstevel@tonic-gate * character into a 16-bit character
15260Sstevel@tonic-gate */
15270Sstevel@tonic-gate *c_16 = c_32;
15280Sstevel@tonic-gate return (extra_bytes + 1);
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate /*
15320Sstevel@tonic-gate * Convert to a form that can be put on the media
15330Sstevel@tonic-gate * out_len has the size of out_str when we are called.
15340Sstevel@tonic-gate * This routine will set out_len to actual bytes written to out_str.
15350Sstevel@tonic-gate * We make sure that we will not attempt to write beyond the out_str_len.
15360Sstevel@tonic-gate */
15370Sstevel@tonic-gate int32_t
ud_compress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)15380Sstevel@tonic-gate ud_compress(int32_t in_len, int32_t *out_len,
15390Sstevel@tonic-gate uint8_t *in_str, uint8_t *out_str)
15400Sstevel@tonic-gate {
15410Sstevel@tonic-gate int32_t error, in_index, out_index, index, c_tx_sz, out_str_len;
15420Sstevel@tonic-gate uint16_t w2_char, *w2_str;
15430Sstevel@tonic-gate uint8_t comp_id;
15440Sstevel@tonic-gate
15450Sstevel@tonic-gate out_str_len = *out_len;
15460Sstevel@tonic-gate if (in_len > (out_str_len - 2)) {
15470Sstevel@tonic-gate return (ENAMETOOLONG);
15480Sstevel@tonic-gate }
15490Sstevel@tonic-gate
15500Sstevel@tonic-gate *out_len = 0;
15510Sstevel@tonic-gate w2_str = (uint16_t *)kmem_zalloc(512, KM_SLEEP);
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate error = in_index = out_index = c_tx_sz = 0;
15540Sstevel@tonic-gate comp_id = 8;
15550Sstevel@tonic-gate for (in_index = 0; in_index < in_len; in_index += c_tx_sz) {
15560Sstevel@tonic-gate if ((c_tx_sz = ud_utf82utf16(&in_str[in_index],
15575331Samw &w2_char, in_len - in_index)) == 0) {
15580Sstevel@tonic-gate error = EINVAL;
15590Sstevel@tonic-gate goto end;
15600Sstevel@tonic-gate }
15610Sstevel@tonic-gate /*
15620Sstevel@tonic-gate * utf-8 characters can be
15630Sstevel@tonic-gate * of 1 - 6 bytes in length
15640Sstevel@tonic-gate */
15650Sstevel@tonic-gate ASSERT(c_tx_sz > 0);
15660Sstevel@tonic-gate ASSERT(c_tx_sz < 7);
15670Sstevel@tonic-gate if ((comp_id == 8) && (w2_char & 0xff00)) {
15680Sstevel@tonic-gate comp_id = 0x10;
15690Sstevel@tonic-gate }
15700Sstevel@tonic-gate w2_str[out_index++] = w2_char;
15710Sstevel@tonic-gate }
15720Sstevel@tonic-gate if (((comp_id == 0x10) && (out_index > ((out_str_len - 2)/2))) ||
15735331Samw ((comp_id == 0x8) && (out_index > (out_str_len - 2)))) {
15740Sstevel@tonic-gate error = ENAMETOOLONG;
15750Sstevel@tonic-gate goto end;
15760Sstevel@tonic-gate }
15770Sstevel@tonic-gate
15780Sstevel@tonic-gate in_index = out_index;
15790Sstevel@tonic-gate out_index = 0;
15800Sstevel@tonic-gate out_str[out_index++] = comp_id;
15810Sstevel@tonic-gate for (index = 0; index < in_index; index++) {
15820Sstevel@tonic-gate if (comp_id == 0x10) {
15830Sstevel@tonic-gate out_str[out_index++] = (w2_str[index] & 0xFF00) >> 8;
15840Sstevel@tonic-gate }
15850Sstevel@tonic-gate out_str[out_index++] = w2_str[index] & 0xFF;
15860Sstevel@tonic-gate }
15870Sstevel@tonic-gate ASSERT(out_index <= (out_str_len - 1));
15880Sstevel@tonic-gate *out_len = out_index;
15890Sstevel@tonic-gate end:
15900Sstevel@tonic-gate if (w2_str != NULL) {
15910Sstevel@tonic-gate kmem_free((caddr_t)w2_str, 512);
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate return (error);
15940Sstevel@tonic-gate }
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate /*
15970Sstevel@tonic-gate * Take a utf16 character and convert
15980Sstevel@tonic-gate * it into a utf8 character.
15990Sstevel@tonic-gate * A 0 will be returned if the conversion fails
16000Sstevel@tonic-gate */
16010Sstevel@tonic-gate uint8_t first_byte_mark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
16020Sstevel@tonic-gate int32_t
ud_utf162utf8(uint16_t c_16,uint8_t * s_8)16030Sstevel@tonic-gate ud_utf162utf8(uint16_t c_16, uint8_t *s_8)
16040Sstevel@tonic-gate {
16050Sstevel@tonic-gate int32_t nc;
16060Sstevel@tonic-gate uint32_t c_32;
16070Sstevel@tonic-gate uint32_t byte_mask = 0xBF;
16080Sstevel@tonic-gate uint32_t byte_mark = 0x80;
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate ASSERT(s_8);
16110Sstevel@tonic-gate
16120Sstevel@tonic-gate /*
16130Sstevel@tonic-gate * Convert the 16-bit character to
16140Sstevel@tonic-gate * a 32-bit character
16150Sstevel@tonic-gate */
16160Sstevel@tonic-gate c_32 = c_16;
16170Sstevel@tonic-gate
16180Sstevel@tonic-gate /*
16190Sstevel@tonic-gate * By here the 16-bit character is converted
16200Sstevel@tonic-gate * to a 32-bit wide character
16210Sstevel@tonic-gate */
16220Sstevel@tonic-gate if (c_32 < 0x80) {
16230Sstevel@tonic-gate nc = 1;
16240Sstevel@tonic-gate } else if (c_32 < 0x800) {
16250Sstevel@tonic-gate nc = 2;
16260Sstevel@tonic-gate } else if (c_32 < 0x10000) {
16270Sstevel@tonic-gate nc = 3;
16280Sstevel@tonic-gate } else if (c_32 < 0x200000) {
16290Sstevel@tonic-gate nc = 4;
16300Sstevel@tonic-gate } else if (c_32 < 0x4000000) {
16310Sstevel@tonic-gate nc = 5;
16320Sstevel@tonic-gate } else if (c_32 < (uint32_t)0x80000000) {
16330Sstevel@tonic-gate nc = 6;
16340Sstevel@tonic-gate } else {
16350Sstevel@tonic-gate nc = 0;
16360Sstevel@tonic-gate }
16370Sstevel@tonic-gate s_8 += nc;
16380Sstevel@tonic-gate switch (nc) {
16390Sstevel@tonic-gate case 6 :
16400Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask;
16410Sstevel@tonic-gate c_32 >>= 6;
16420Sstevel@tonic-gate /* FALLTHROUGH */
16430Sstevel@tonic-gate case 5 :
16440Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask;
16450Sstevel@tonic-gate c_32 >>= 6;
16460Sstevel@tonic-gate /* FALLTHROUGH */
16470Sstevel@tonic-gate case 4 :
16480Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask;
16490Sstevel@tonic-gate c_32 >>= 6;
16500Sstevel@tonic-gate /* FALLTHROUGH */
16510Sstevel@tonic-gate case 3 :
16520Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask;
16530Sstevel@tonic-gate c_32 >>= 6;
16540Sstevel@tonic-gate /* FALLTHROUGH */
16550Sstevel@tonic-gate case 2 :
16560Sstevel@tonic-gate *(--s_8) = (c_32 | byte_mark) & byte_mask;
16570Sstevel@tonic-gate c_32 >>= 6;
16580Sstevel@tonic-gate /* FALLTHROUGH */
16590Sstevel@tonic-gate case 1 :
16600Sstevel@tonic-gate *(--s_8) = c_32 | first_byte_mark[nc];
16610Sstevel@tonic-gate }
16620Sstevel@tonic-gate return (nc);
16630Sstevel@tonic-gate }
16640Sstevel@tonic-gate
16650Sstevel@tonic-gate /*
16665331Samw * Convert to a form that can be transferred to the user
16670Sstevel@tonic-gate * Assumption's
16685331Samw * in_length < 256, out_str is at least 255 bytes long
16690Sstevel@tonic-gate * The converted byte stream length is returned in out_len
16700Sstevel@tonic-gate */
16710Sstevel@tonic-gate #define MAX_ALLOWABLE_STRING 250
16720Sstevel@tonic-gate
16730Sstevel@tonic-gate int32_t
ud_uncompress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)16740Sstevel@tonic-gate ud_uncompress(int32_t in_len, int32_t *out_len,
16750Sstevel@tonic-gate uint8_t *in_str, uint8_t *out_str)
16760Sstevel@tonic-gate {
16770Sstevel@tonic-gate uint8_t comp_id, utf8[6];
16780Sstevel@tonic-gate uint16_t w2_char, crc;
16790Sstevel@tonic-gate int32_t error, index, c_tx_sz, len_till_now;
16800Sstevel@tonic-gate int32_t make_crc, lic, dot_loc, crc_start_loc = 0, k = 0;
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate if (in_len == 0) {
16830Sstevel@tonic-gate *out_len = 0;
16840Sstevel@tonic-gate out_str[0] = '\0';
16850Sstevel@tonic-gate return (0);
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate
16880Sstevel@tonic-gate error = len_till_now = make_crc = 0;
16890Sstevel@tonic-gate dot_loc = lic = -2;
16900Sstevel@tonic-gate *out_len = 0;
16910Sstevel@tonic-gate crc = 0;
16920Sstevel@tonic-gate comp_id = in_str[0];
16930Sstevel@tonic-gate
16940Sstevel@tonic-gate /*
16950Sstevel@tonic-gate * File names "." and ".." are invalid under unix.
16960Sstevel@tonic-gate * Transform them into something
16970Sstevel@tonic-gate */
16980Sstevel@tonic-gate if (comp_id == 8) {
16990Sstevel@tonic-gate if ((in_str[1] == DOT) &&
17005331Samw ((in_len == 2) || ((in_len == 3) &&
17015331Samw (in_str[2] == DOT)))) {
17020Sstevel@tonic-gate out_str[k++] = UNDERBAR;
17030Sstevel@tonic-gate len_till_now = 1;
17040Sstevel@tonic-gate goto make_append_crc;
17050Sstevel@tonic-gate }
17060Sstevel@tonic-gate } else if (comp_id == 0x10) {
17070Sstevel@tonic-gate if (((in_str[1] << 8 | in_str[2]) == DOT) &&
17085331Samw ((in_len == 3) || ((in_len == 5) &&
17095331Samw ((in_str[3] << 8 | in_str[4]) == DOT)))) {
17100Sstevel@tonic-gate out_str[k++] = UNDERBAR;
17110Sstevel@tonic-gate len_till_now = 1;
17120Sstevel@tonic-gate goto make_append_crc;
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate } else {
17150Sstevel@tonic-gate *out_len = 0;
17160Sstevel@tonic-gate return (EINVAL);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate for (index = 1; index < in_len; ) {
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate /*
17220Sstevel@tonic-gate * Uncompress each character
17230Sstevel@tonic-gate */
17240Sstevel@tonic-gate if (comp_id == 0x10) {
17250Sstevel@tonic-gate w2_char = in_str[index++] << 8;
17260Sstevel@tonic-gate w2_char |= in_str[index++];
17270Sstevel@tonic-gate } else {
17280Sstevel@tonic-gate w2_char = in_str[index++];
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate if (make_crc != 0) {
17320Sstevel@tonic-gate crc += w2_char;
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate if (w2_char == DOT) {
17360Sstevel@tonic-gate dot_loc = len_till_now;
17370Sstevel@tonic-gate }
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate /*
17400Sstevel@tonic-gate * Get rid of invalid characters
17410Sstevel@tonic-gate */
17420Sstevel@tonic-gate if ((w2_char == SLASH) ||
17435331Samw (w2_char == NULL)) {
17440Sstevel@tonic-gate make_crc = 1;
17450Sstevel@tonic-gate if (((comp_id == 8) &&
17465331Samw (lic != (index - 1))) ||
17475331Samw (comp_id == 0x10) &&
17485331Samw (lic != (index - 2))) {
17490Sstevel@tonic-gate w2_char = UNDERBAR;
17500Sstevel@tonic-gate lic = index;
17510Sstevel@tonic-gate } else {
17520Sstevel@tonic-gate lic = index;
17530Sstevel@tonic-gate continue;
17540Sstevel@tonic-gate }
17550Sstevel@tonic-gate }
17560Sstevel@tonic-gate
17570Sstevel@tonic-gate /*
17580Sstevel@tonic-gate * Conver a 16bit character to a
17590Sstevel@tonic-gate * utf8 byte stream
17600Sstevel@tonic-gate */
17610Sstevel@tonic-gate if ((c_tx_sz = ud_utf162utf8(w2_char, utf8)) == 0) {
17620Sstevel@tonic-gate error = EINVAL;
17630Sstevel@tonic-gate goto end;
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate ASSERT(c_tx_sz > 0);
17660Sstevel@tonic-gate ASSERT(c_tx_sz < 7);
17670Sstevel@tonic-gate
17680Sstevel@tonic-gate /*
17690Sstevel@tonic-gate * The output string is larger than
17700Sstevel@tonic-gate * the maximum allowed string length
17710Sstevel@tonic-gate */
17720Sstevel@tonic-gate if ((crc_start_loc == 0) &&
17735331Samw ((len_till_now + c_tx_sz) > MAX_ALLOWABLE_STRING)) {
17740Sstevel@tonic-gate crc_start_loc = len_till_now;
17750Sstevel@tonic-gate }
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate if ((len_till_now + c_tx_sz) < MAXNAMELEN) {
17780Sstevel@tonic-gate (void) strncpy((caddr_t)&out_str[len_till_now],
17795331Samw (caddr_t)utf8, c_tx_sz);
17800Sstevel@tonic-gate len_till_now += c_tx_sz;
17810Sstevel@tonic-gate } else {
17820Sstevel@tonic-gate break;
17830Sstevel@tonic-gate }
17840Sstevel@tonic-gate }
17850Sstevel@tonic-gate
17860Sstevel@tonic-gate /*
17870Sstevel@tonic-gate * If we need to append CRC do it now
17880Sstevel@tonic-gate */
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate if (make_crc) {
17910Sstevel@tonic-gate
17920Sstevel@tonic-gate if (len_till_now > MAX_ALLOWABLE_STRING) {
17930Sstevel@tonic-gate len_till_now = crc_start_loc;
17940Sstevel@tonic-gate }
17950Sstevel@tonic-gate
17960Sstevel@tonic-gate if (dot_loc > 0) {
17970Sstevel@tonic-gate /*
17980Sstevel@tonic-gate * Make space for crc before the DOT
17990Sstevel@tonic-gate * move the rest of the file name to the end
18000Sstevel@tonic-gate */
18010Sstevel@tonic-gate for (k = len_till_now - 1; k >= dot_loc; k--) {
18020Sstevel@tonic-gate out_str[k + 5] = out_str[k];
18030Sstevel@tonic-gate }
18040Sstevel@tonic-gate k = dot_loc;
18050Sstevel@tonic-gate } else {
18060Sstevel@tonic-gate k = len_till_now;
18070Sstevel@tonic-gate }
18080Sstevel@tonic-gate make_append_crc:
18090Sstevel@tonic-gate crc = ud_crc(in_str, in_len);
18100Sstevel@tonic-gate out_str[k++] = POUND;
18110Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf000) >> 12];
18120Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf00) >> 8];
18130Sstevel@tonic-gate out_str[k++] = htoc[(uint16_t)(crc & 0xf0) >> 4];
18140Sstevel@tonic-gate out_str[k++] = htoc[crc & 0xf];
18150Sstevel@tonic-gate len_till_now += 5;
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate *out_len = len_till_now;
18180Sstevel@tonic-gate end:
18190Sstevel@tonic-gate return (error);
18200Sstevel@tonic-gate }
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate struct buf *
ud_bread(dev_t dev,daddr_t blkno,long bsize)18240Sstevel@tonic-gate ud_bread(dev_t dev, daddr_t blkno, long bsize)
18250Sstevel@tonic-gate {
18260Sstevel@tonic-gate struct buf *bp;
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate begin:
18290Sstevel@tonic-gate bp = bread(dev, blkno, bsize);
18300Sstevel@tonic-gate
18310Sstevel@tonic-gate if (((bp->b_flags & B_ERROR) == 0) &&
18325331Samw (bp->b_bcount != bsize)) {
18330Sstevel@tonic-gate /*
18340Sstevel@tonic-gate * Buffer cache returned a
18350Sstevel@tonic-gate * wrong number of bytes
18360Sstevel@tonic-gate * flush the old buffer and
18370Sstevel@tonic-gate * reread it again
18380Sstevel@tonic-gate */
18390Sstevel@tonic-gate if (bp->b_flags & B_DELWRI) {
18400Sstevel@tonic-gate bwrite(bp);
18410Sstevel@tonic-gate } else {
18420Sstevel@tonic-gate bp->b_flags |= (B_AGE | B_STALE);
18430Sstevel@tonic-gate brelse(bp);
18440Sstevel@tonic-gate }
18450Sstevel@tonic-gate goto begin;
18460Sstevel@tonic-gate }
18470Sstevel@tonic-gate
18480Sstevel@tonic-gate return (bp);
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate /*
18520Sstevel@tonic-gate * Decide whether it is okay to remove within a sticky directory.
18530Sstevel@tonic-gate * Two conditions need to be met: write access to the directory
18540Sstevel@tonic-gate * is needed. In sticky directories, write access is not sufficient;
18550Sstevel@tonic-gate * you can remove entries from a directory only if you own the directory,
18560Sstevel@tonic-gate * if you are privileged, if you own the entry or if they entry is
18570Sstevel@tonic-gate * a plain file and you have write access to that file.
18580Sstevel@tonic-gate * Function returns 0 if remove access is granted.
18590Sstevel@tonic-gate */
18600Sstevel@tonic-gate int
ud_sticky_remove_access(struct ud_inode * dir,struct ud_inode * entry,struct cred * cr)18610Sstevel@tonic-gate ud_sticky_remove_access(struct ud_inode *dir, struct ud_inode *entry,
18620Sstevel@tonic-gate struct cred *cr)
18630Sstevel@tonic-gate {
18640Sstevel@tonic-gate uid_t uid;
18650Sstevel@tonic-gate
1866*12196SMilan.Cermak@Sun.COM ASSERT(RW_LOCK_HELD(&entry->i_contents));
1867*12196SMilan.Cermak@Sun.COM
18680Sstevel@tonic-gate if ((dir->i_char & ISVTX) &&
18690Sstevel@tonic-gate (uid = crgetuid(cr)) != dir->i_uid &&
18700Sstevel@tonic-gate uid != entry->i_uid &&
18710Sstevel@tonic-gate (entry->i_type != VREG ||
1872*12196SMilan.Cermak@Sun.COM ud_iaccess(entry, IWRITE, cr, 0) != 0))
18730Sstevel@tonic-gate return (secpolicy_vnode_remove(cr));
18740Sstevel@tonic-gate
18750Sstevel@tonic-gate return (0);
18760Sstevel@tonic-gate }
1877