1df8bae1dSRodney W. Grimes /*- 2df8bae1dSRodney W. Grimes * Copyright (c) 1982, 1986, 1989, 1994 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley 6df8bae1dSRodney W. Grimes * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7df8bae1dSRodney W. Grimes * Support code is derived from software contributed to Berkeley 8df8bae1dSRodney W. Grimes * by Atsushi Murai (amurai@spec.co.jp). 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)cd9660_node.c 8.2 (Berkeley) 1/23/94 3910dd32cdSBruce Evans * $Id: cd9660_node.c,v 1.11 1995/05/30 08:04:59 rgrimes Exp $ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 42df8bae1dSRodney W. Grimes #include <sys/param.h> 43df8bae1dSRodney W. Grimes #include <sys/systm.h> 44df8bae1dSRodney W. Grimes #include <sys/mount.h> 45df8bae1dSRodney W. Grimes #include <sys/proc.h> 46df8bae1dSRodney W. Grimes #include <sys/file.h> 47df8bae1dSRodney W. Grimes #include <sys/buf.h> 48df8bae1dSRodney W. Grimes #include <sys/vnode.h> 49df8bae1dSRodney W. Grimes #include <sys/kernel.h> 50df8bae1dSRodney W. Grimes #include <sys/malloc.h> 51df8bae1dSRodney W. Grimes #include <sys/stat.h> 52df8bae1dSRodney W. Grimes 53df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso.h> 54df8bae1dSRodney W. Grimes #include <isofs/cd9660/cd9660_node.h> 55df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso_rrip.h> 56df8bae1dSRodney W. Grimes 57df8bae1dSRodney W. Grimes #define INOHSZ 512 58df8bae1dSRodney W. Grimes #if ((INOHSZ&(INOHSZ-1)) == 0) 59df8bae1dSRodney W. Grimes #define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1)) 60df8bae1dSRodney W. Grimes #else 61df8bae1dSRodney W. Grimes #define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ) 62df8bae1dSRodney W. Grimes #endif 63df8bae1dSRodney W. Grimes 64df8bae1dSRodney W. Grimes union iso_ihead { 65df8bae1dSRodney W. Grimes union iso_ihead *ih_head[2]; 66df8bae1dSRodney W. Grimes struct iso_node *ih_chain[2]; 67df8bae1dSRodney W. Grimes } iso_ihead[INOHSZ]; 68df8bae1dSRodney W. Grimes 69df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 70df8bae1dSRodney W. Grimes #define DNOHSZ 64 71df8bae1dSRodney W. Grimes #if ((DNOHSZ&(DNOHSZ-1)) == 0) 72df8bae1dSRodney W. Grimes #define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1)) 73df8bae1dSRodney W. Grimes #else 74df8bae1dSRodney W. Grimes #define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ) 75df8bae1dSRodney W. Grimes #endif 76df8bae1dSRodney W. Grimes 77df8bae1dSRodney W. Grimes union iso_dhead { 78df8bae1dSRodney W. Grimes union iso_dhead *dh_head[2]; 79df8bae1dSRodney W. Grimes struct iso_dnode *dh_chain[2]; 80df8bae1dSRodney W. Grimes } iso_dhead[DNOHSZ]; 81df8bae1dSRodney W. Grimes #endif 82df8bae1dSRodney W. Grimes 8310dd32cdSBruce Evans static unsigned cd9660_chars2ui __P((unsigned char *begin, int len)); 8410dd32cdSBruce Evans 85df8bae1dSRodney W. Grimes /* 86df8bae1dSRodney W. Grimes * Initialize hash links for inodes and dnodes. 87df8bae1dSRodney W. Grimes */ 8826f9a767SRodney W. Grimes int 89df8bae1dSRodney W. Grimes cd9660_init() 90df8bae1dSRodney W. Grimes { 91df8bae1dSRodney W. Grimes register int i; 92df8bae1dSRodney W. Grimes register union iso_ihead *ih = iso_ihead; 93df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 94df8bae1dSRodney W. Grimes register union iso_dhead *dh = iso_dhead; 95df8bae1dSRodney W. Grimes #endif 96df8bae1dSRodney W. Grimes 97df8bae1dSRodney W. Grimes for (i = INOHSZ; --i >= 0; ih++) { 98df8bae1dSRodney W. Grimes ih->ih_head[0] = ih; 99df8bae1dSRodney W. Grimes ih->ih_head[1] = ih; 100df8bae1dSRodney W. Grimes } 101df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 102df8bae1dSRodney W. Grimes for (i = DNOHSZ; --i >= 0; dh++) { 103df8bae1dSRodney W. Grimes dh->dh_head[0] = dh; 104df8bae1dSRodney W. Grimes dh->dh_head[1] = dh; 105df8bae1dSRodney W. Grimes } 106df8bae1dSRodney W. Grimes #endif 10726f9a767SRodney W. Grimes return (0); 108df8bae1dSRodney W. Grimes } 109df8bae1dSRodney W. Grimes 110df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 111df8bae1dSRodney W. Grimes /* 112df8bae1dSRodney W. Grimes * Enter a new node into the device hash list 113df8bae1dSRodney W. Grimes */ 114df8bae1dSRodney W. Grimes struct iso_dnode * 115df8bae1dSRodney W. Grimes iso_dmap(dev,ino,create) 116df8bae1dSRodney W. Grimes dev_t dev; 117df8bae1dSRodney W. Grimes ino_t ino; 118df8bae1dSRodney W. Grimes int create; 119df8bae1dSRodney W. Grimes { 120df8bae1dSRodney W. Grimes struct iso_dnode *dp; 121df8bae1dSRodney W. Grimes union iso_dhead *dh; 122df8bae1dSRodney W. Grimes 123df8bae1dSRodney W. Grimes dh = &iso_dhead[DNOHASH(dev, ino)]; 124df8bae1dSRodney W. Grimes for (dp = dh->dh_chain[0]; 125df8bae1dSRodney W. Grimes dp != (struct iso_dnode *)dh; 126df8bae1dSRodney W. Grimes dp = dp->d_forw) 127df8bae1dSRodney W. Grimes if (ino == dp->i_number && dev == dp->i_dev) 128df8bae1dSRodney W. Grimes return dp; 129df8bae1dSRodney W. Grimes 130df8bae1dSRodney W. Grimes if (!create) 131df8bae1dSRodney W. Grimes return (struct iso_dnode *)0; 132df8bae1dSRodney W. Grimes 133df8bae1dSRodney W. Grimes MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK); 134df8bae1dSRodney W. Grimes dp->i_dev = dev; 135df8bae1dSRodney W. Grimes dp->i_number = ino; 136df8bae1dSRodney W. Grimes insque(dp,dh); 137df8bae1dSRodney W. Grimes 138df8bae1dSRodney W. Grimes return dp; 139df8bae1dSRodney W. Grimes } 140df8bae1dSRodney W. Grimes 141df8bae1dSRodney W. Grimes void 142df8bae1dSRodney W. Grimes iso_dunmap(dev) 143df8bae1dSRodney W. Grimes dev_t dev; 144df8bae1dSRodney W. Grimes { 145df8bae1dSRodney W. Grimes struct iso_dnode *dp, *dq; 146df8bae1dSRodney W. Grimes union iso_dhead *dh; 147df8bae1dSRodney W. Grimes 148df8bae1dSRodney W. Grimes for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) { 149df8bae1dSRodney W. Grimes for (dp = dh->dh_chain[0]; 150df8bae1dSRodney W. Grimes dp != (struct iso_dnode *)dh; 151df8bae1dSRodney W. Grimes dp = dq) { 152df8bae1dSRodney W. Grimes dq = dp->d_forw; 153df8bae1dSRodney W. Grimes if (dev == dp->i_dev) { 154df8bae1dSRodney W. Grimes remque(dp); 155df8bae1dSRodney W. Grimes FREE(dp,M_CACHE); 156df8bae1dSRodney W. Grimes } 157df8bae1dSRodney W. Grimes } 158df8bae1dSRodney W. Grimes } 159df8bae1dSRodney W. Grimes } 160df8bae1dSRodney W. Grimes #endif 161df8bae1dSRodney W. Grimes 162df8bae1dSRodney W. Grimes /* 163df8bae1dSRodney W. Grimes * Look up a ISOFS dinode number to find its incore vnode. 164df8bae1dSRodney W. Grimes * If it is not in core, read it in from the specified device. 165df8bae1dSRodney W. Grimes * If it is in core, wait for the lock bit to clear, then 166df8bae1dSRodney W. Grimes * return the inode locked. Detection and handling of mount 167df8bae1dSRodney W. Grimes * points must be done by the calling routine. 168df8bae1dSRodney W. Grimes */ 16926f9a767SRodney W. Grimes int 170df8bae1dSRodney W. Grimes iso_iget(xp, ino, relocated, ipp, isodir) 171df8bae1dSRodney W. Grimes struct iso_node *xp; 172df8bae1dSRodney W. Grimes ino_t ino; 17326f9a767SRodney W. Grimes int relocated; 174df8bae1dSRodney W. Grimes struct iso_node **ipp; 175df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 176df8bae1dSRodney W. Grimes { 177df8bae1dSRodney W. Grimes dev_t dev = xp->i_dev; 178df8bae1dSRodney W. Grimes struct mount *mntp = ITOV(xp)->v_mount; 179df8bae1dSRodney W. Grimes register struct iso_node *ip, *iq; 180df8bae1dSRodney W. Grimes register struct vnode *vp; 1811295d82eSGary Palmer #ifdef ISODEVMAP 182df8bae1dSRodney W. Grimes register struct iso_dnode *dp; 1831295d82eSGary Palmer #endif 184df8bae1dSRodney W. Grimes struct vnode *nvp; 185df8bae1dSRodney W. Grimes struct buf *bp = NULL, *bp2 = NULL; 186df8bae1dSRodney W. Grimes union iso_ihead *ih; 1871295d82eSGary Palmer int error, result; 188df8bae1dSRodney W. Grimes struct iso_mnt *imp; 189df8bae1dSRodney W. Grimes 190df8bae1dSRodney W. Grimes ih = &iso_ihead[INOHASH(dev, ino)]; 191df8bae1dSRodney W. Grimes loop: 192df8bae1dSRodney W. Grimes for (ip = ih->ih_chain[0]; 193df8bae1dSRodney W. Grimes ip != (struct iso_node *)ih; 194df8bae1dSRodney W. Grimes ip = ip->i_forw) { 195df8bae1dSRodney W. Grimes if (ino != ip->i_number || dev != ip->i_dev) 196df8bae1dSRodney W. Grimes continue; 197df8bae1dSRodney W. Grimes if ((ip->i_flag&ILOCKED) != 0) { 198df8bae1dSRodney W. Grimes ip->i_flag |= IWANT; 19982478919SDavid Greenman (void) tsleep((caddr_t)ip, PINOD, "isoigt", 0); 200df8bae1dSRodney W. Grimes goto loop; 201df8bae1dSRodney W. Grimes } 202df8bae1dSRodney W. Grimes if (vget(ITOV(ip), 1)) 203df8bae1dSRodney W. Grimes goto loop; 204df8bae1dSRodney W. Grimes *ipp = ip; 205df8bae1dSRodney W. Grimes return 0; 206df8bae1dSRodney W. Grimes } 207df8bae1dSRodney W. Grimes /* 208df8bae1dSRodney W. Grimes * Allocate a new vnode/iso_node. 209df8bae1dSRodney W. Grimes */ 2101295d82eSGary Palmer if ((error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp))) { 211df8bae1dSRodney W. Grimes *ipp = 0; 212df8bae1dSRodney W. Grimes return error; 213df8bae1dSRodney W. Grimes } 214df8bae1dSRodney W. Grimes MALLOC(ip, struct iso_node *, sizeof(struct iso_node), 215df8bae1dSRodney W. Grimes M_ISOFSNODE, M_WAITOK); 216df8bae1dSRodney W. Grimes bzero((caddr_t)ip, sizeof(struct iso_node)); 217df8bae1dSRodney W. Grimes nvp->v_data = ip; 218df8bae1dSRodney W. Grimes ip->i_vnode = nvp; 219df8bae1dSRodney W. Grimes ip->i_flag = 0; 220df8bae1dSRodney W. Grimes ip->i_devvp = 0; 221df8bae1dSRodney W. Grimes ip->i_diroff = 0; 222df8bae1dSRodney W. Grimes ip->i_lockf = 0; 223df8bae1dSRodney W. Grimes 224df8bae1dSRodney W. Grimes /* 225df8bae1dSRodney W. Grimes * Put it onto its hash chain and lock it so that other requests for 226df8bae1dSRodney W. Grimes * this inode will block if they arrive while we are sleeping waiting 227df8bae1dSRodney W. Grimes * for old data structures to be purged or for the contents of the 228df8bae1dSRodney W. Grimes * disk portion of this inode to be read. 229df8bae1dSRodney W. Grimes */ 230df8bae1dSRodney W. Grimes ip->i_dev = dev; 231df8bae1dSRodney W. Grimes ip->i_number = ino; 232df8bae1dSRodney W. Grimes insque(ip, ih); 233df8bae1dSRodney W. Grimes ISO_ILOCK(ip); 234df8bae1dSRodney W. Grimes 235df8bae1dSRodney W. Grimes imp = VFSTOISOFS (mntp); 236df8bae1dSRodney W. Grimes ip->i_mnt = imp; 237df8bae1dSRodney W. Grimes ip->i_devvp = imp->im_devvp; 238df8bae1dSRodney W. Grimes VREF(ip->i_devvp); 239df8bae1dSRodney W. Grimes 240df8bae1dSRodney W. Grimes if (relocated) { 241df8bae1dSRodney W. Grimes /* 242df8bae1dSRodney W. Grimes * On relocated directories we must 243df8bae1dSRodney W. Grimes * read the `.' entry out of a dir. 244df8bae1dSRodney W. Grimes */ 245df8bae1dSRodney W. Grimes ip->iso_start = ino >> imp->im_bshift; 2461295d82eSGary Palmer if ((error = iso_blkatoff(ip,0,&bp))) { 247df8bae1dSRodney W. Grimes vrele(ip->i_devvp); 248df8bae1dSRodney W. Grimes remque(ip); 249df8bae1dSRodney W. Grimes ip->i_forw = ip; 250df8bae1dSRodney W. Grimes ip->i_back = ip; 251df8bae1dSRodney W. Grimes iso_iput(ip); 252df8bae1dSRodney W. Grimes *ipp = 0; 253df8bae1dSRodney W. Grimes return error; 254df8bae1dSRodney W. Grimes } 255df8bae1dSRodney W. Grimes isodir = (struct iso_directory_record *)bp->b_un.b_addr; 256df8bae1dSRodney W. Grimes } 257df8bae1dSRodney W. Grimes 258df8bae1dSRodney W. Grimes ip->iso_extent = isonum_733(isodir->extent); 259df8bae1dSRodney W. Grimes ip->i_size = isonum_733(isodir->size); 260df8bae1dSRodney W. Grimes ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 261df8bae1dSRodney W. Grimes 262df8bae1dSRodney W. Grimes vp = ITOV(ip); 263df8bae1dSRodney W. Grimes 264df8bae1dSRodney W. Grimes /* 265df8bae1dSRodney W. Grimes * Setup time stamp, attribute 266df8bae1dSRodney W. Grimes */ 267df8bae1dSRodney W. Grimes vp->v_type = VNON; 268df8bae1dSRodney W. Grimes switch (imp->iso_ftype) { 269988fa8efSJoerg Wunsch default: /* ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA */ 270df8bae1dSRodney W. Grimes if ((imp->im_flags&ISOFSMNT_EXTATT) 271df8bae1dSRodney W. Grimes && isonum_711(isodir->ext_attr_length)) 272df8bae1dSRodney W. Grimes iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length), 273df8bae1dSRodney W. Grimes &bp2); 274988fa8efSJoerg Wunsch cd9660_defattr(isodir,ip,bp2,imp->iso_ftype ); 275988fa8efSJoerg Wunsch cd9660_deftstamp(isodir,ip,bp2,imp->iso_ftype ); 276df8bae1dSRodney W. Grimes break; 277df8bae1dSRodney W. Grimes case ISO_FTYPE_RRIP: 278df8bae1dSRodney W. Grimes result = cd9660_rrip_analyze(isodir,ip,imp); 279df8bae1dSRodney W. Grimes break; 280df8bae1dSRodney W. Grimes } 281df8bae1dSRodney W. Grimes if (bp2) 282df8bae1dSRodney W. Grimes brelse(bp2); 283df8bae1dSRodney W. Grimes if (bp) 284df8bae1dSRodney W. Grimes brelse(bp); 285df8bae1dSRodney W. Grimes 286df8bae1dSRodney W. Grimes /* 287df8bae1dSRodney W. Grimes * Initialize the associated vnode 288df8bae1dSRodney W. Grimes */ 289df8bae1dSRodney W. Grimes vp->v_type = IFTOVT(ip->inode.iso_mode); 290df8bae1dSRodney W. Grimes 291df8bae1dSRodney W. Grimes if ( vp->v_type == VFIFO ) { 292df8bae1dSRodney W. Grimes vp->v_op = cd9660_fifoop_p; 293df8bae1dSRodney W. Grimes } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) { 294df8bae1dSRodney W. Grimes /* 295df8bae1dSRodney W. Grimes * if device, look at device number table for translation 296df8bae1dSRodney W. Grimes */ 297df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 298df8bae1dSRodney W. Grimes if (dp = iso_dmap(dev,ino,0)) 299df8bae1dSRodney W. Grimes ip->inode.iso_rdev = dp->d_dev; 300df8bae1dSRodney W. Grimes #endif 301df8bae1dSRodney W. Grimes vp->v_op = cd9660_specop_p; 3021295d82eSGary Palmer if ((nvp = checkalias(vp, ip->inode.iso_rdev, mntp))) { 303df8bae1dSRodney W. Grimes /* 304df8bae1dSRodney W. Grimes * Reinitialize aliased inode. 305df8bae1dSRodney W. Grimes */ 306df8bae1dSRodney W. Grimes vp = nvp; 307df8bae1dSRodney W. Grimes iq = VTOI(vp); 308df8bae1dSRodney W. Grimes iq->i_vnode = vp; 309df8bae1dSRodney W. Grimes iq->i_flag = 0; 310df8bae1dSRodney W. Grimes ISO_ILOCK(iq); 311df8bae1dSRodney W. Grimes iq->i_dev = dev; 312df8bae1dSRodney W. Grimes iq->i_number = ino; 313df8bae1dSRodney W. Grimes iq->i_mnt = ip->i_mnt; 314df8bae1dSRodney W. Grimes bcopy(&ip->iso_extent,&iq->iso_extent, 315df8bae1dSRodney W. Grimes (char *)(ip + 1) - (char *)&ip->iso_extent); 316df8bae1dSRodney W. Grimes insque(iq, ih); 317df8bae1dSRodney W. Grimes /* 318df8bae1dSRodney W. Grimes * Discard unneeded vnode 319df8bae1dSRodney W. Grimes * (This introduces the need of INACTIVE modification) 320df8bae1dSRodney W. Grimes */ 321df8bae1dSRodney W. Grimes ip->inode.iso_mode = 0; 322df8bae1dSRodney W. Grimes iso_iput(ip); 323df8bae1dSRodney W. Grimes ip = iq; 324df8bae1dSRodney W. Grimes } 325df8bae1dSRodney W. Grimes } 326df8bae1dSRodney W. Grimes 327df8bae1dSRodney W. Grimes if (ip->iso_extent == imp->root_extent) 328df8bae1dSRodney W. Grimes vp->v_flag |= VROOT; 329df8bae1dSRodney W. Grimes 330df8bae1dSRodney W. Grimes *ipp = ip; 331df8bae1dSRodney W. Grimes return 0; 332df8bae1dSRodney W. Grimes } 333df8bae1dSRodney W. Grimes 334df8bae1dSRodney W. Grimes /* 335df8bae1dSRodney W. Grimes * Unlock and decrement the reference count of an inode structure. 336df8bae1dSRodney W. Grimes */ 33726f9a767SRodney W. Grimes int 338df8bae1dSRodney W. Grimes iso_iput(ip) 339df8bae1dSRodney W. Grimes register struct iso_node *ip; 340df8bae1dSRodney W. Grimes { 341df8bae1dSRodney W. Grimes 342df8bae1dSRodney W. Grimes if ((ip->i_flag & ILOCKED) == 0) 343df8bae1dSRodney W. Grimes panic("iso_iput"); 344df8bae1dSRodney W. Grimes ISO_IUNLOCK(ip); 345df8bae1dSRodney W. Grimes vrele(ITOV(ip)); 34626f9a767SRodney W. Grimes return (0); 347df8bae1dSRodney W. Grimes } 348df8bae1dSRodney W. Grimes 349df8bae1dSRodney W. Grimes /* 350df8bae1dSRodney W. Grimes * Last reference to an inode, write the inode out and if necessary, 351df8bae1dSRodney W. Grimes * truncate and deallocate the file. 352df8bae1dSRodney W. Grimes */ 353df8bae1dSRodney W. Grimes int 354df8bae1dSRodney W. Grimes cd9660_inactive(ap) 355df8bae1dSRodney W. Grimes struct vop_inactive_args /* { 356df8bae1dSRodney W. Grimes struct vnode *a_vp; 357df8bae1dSRodney W. Grimes } */ *ap; 358df8bae1dSRodney W. Grimes { 359df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 360df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 3611295d82eSGary Palmer int error = 0; 362df8bae1dSRodney W. Grimes 363df8bae1dSRodney W. Grimes if (prtactive && vp->v_usecount != 0) 364df8bae1dSRodney W. Grimes vprint("cd9660_inactive: pushing active", vp); 365df8bae1dSRodney W. Grimes 366df8bae1dSRodney W. Grimes ip->i_flag = 0; 367df8bae1dSRodney W. Grimes /* 368df8bae1dSRodney W. Grimes * If we are done with the inode, reclaim it 369df8bae1dSRodney W. Grimes * so that it can be reused immediately. 370df8bae1dSRodney W. Grimes */ 371df8bae1dSRodney W. Grimes if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) 372df8bae1dSRodney W. Grimes vgone(vp); 373df8bae1dSRodney W. Grimes return error; 374df8bae1dSRodney W. Grimes } 375df8bae1dSRodney W. Grimes 376df8bae1dSRodney W. Grimes /* 377df8bae1dSRodney W. Grimes * Reclaim an inode so that it can be used for other purposes. 378df8bae1dSRodney W. Grimes */ 379df8bae1dSRodney W. Grimes int 380df8bae1dSRodney W. Grimes cd9660_reclaim(ap) 381df8bae1dSRodney W. Grimes struct vop_reclaim_args /* { 382df8bae1dSRodney W. Grimes struct vnode *a_vp; 383df8bae1dSRodney W. Grimes } */ *ap; 384df8bae1dSRodney W. Grimes { 385df8bae1dSRodney W. Grimes register struct vnode *vp = ap->a_vp; 386df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 387df8bae1dSRodney W. Grimes 388df8bae1dSRodney W. Grimes if (prtactive && vp->v_usecount != 0) 389df8bae1dSRodney W. Grimes vprint("cd9660_reclaim: pushing active", vp); 390df8bae1dSRodney W. Grimes /* 391df8bae1dSRodney W. Grimes * Remove the inode from its hash chain. 392df8bae1dSRodney W. Grimes */ 393df8bae1dSRodney W. Grimes remque(ip); 394df8bae1dSRodney W. Grimes ip->i_forw = ip; 395df8bae1dSRodney W. Grimes ip->i_back = ip; 396df8bae1dSRodney W. Grimes /* 397df8bae1dSRodney W. Grimes * Purge old data structures associated with the inode. 398df8bae1dSRodney W. Grimes */ 399df8bae1dSRodney W. Grimes cache_purge(vp); 400df8bae1dSRodney W. Grimes if (ip->i_devvp) { 401df8bae1dSRodney W. Grimes vrele(ip->i_devvp); 402df8bae1dSRodney W. Grimes ip->i_devvp = 0; 403df8bae1dSRodney W. Grimes } 404df8bae1dSRodney W. Grimes FREE(vp->v_data, M_ISOFSNODE); 405df8bae1dSRodney W. Grimes vp->v_data = NULL; 406df8bae1dSRodney W. Grimes return 0; 407df8bae1dSRodney W. Grimes } 408df8bae1dSRodney W. Grimes 409df8bae1dSRodney W. Grimes /* 410df8bae1dSRodney W. Grimes * Lock an inode. If its already locked, set the WANT bit and sleep. 411df8bae1dSRodney W. Grimes */ 41226f9a767SRodney W. Grimes int 413df8bae1dSRodney W. Grimes iso_ilock(ip) 414df8bae1dSRodney W. Grimes register struct iso_node *ip; 415df8bae1dSRodney W. Grimes { 416df8bae1dSRodney W. Grimes 417df8bae1dSRodney W. Grimes while (ip->i_flag & ILOCKED) { 418df8bae1dSRodney W. Grimes ip->i_flag |= IWANT; 419df8bae1dSRodney W. Grimes if (ip->i_spare0 == curproc->p_pid) 420df8bae1dSRodney W. Grimes panic("locking against myself"); 421df8bae1dSRodney W. Grimes ip->i_spare1 = curproc->p_pid; 42282478919SDavid Greenman (void) tsleep((caddr_t)ip, PINOD, "isoilk", 0); 423df8bae1dSRodney W. Grimes } 424df8bae1dSRodney W. Grimes ip->i_spare1 = 0; 425df8bae1dSRodney W. Grimes ip->i_spare0 = curproc->p_pid; 426df8bae1dSRodney W. Grimes ip->i_flag |= ILOCKED; 42726f9a767SRodney W. Grimes return (0); 428df8bae1dSRodney W. Grimes } 429df8bae1dSRodney W. Grimes 430df8bae1dSRodney W. Grimes /* 431df8bae1dSRodney W. Grimes * Unlock an inode. If WANT bit is on, wakeup. 432df8bae1dSRodney W. Grimes */ 43326f9a767SRodney W. Grimes int 434df8bae1dSRodney W. Grimes iso_iunlock(ip) 435df8bae1dSRodney W. Grimes register struct iso_node *ip; 436df8bae1dSRodney W. Grimes { 437df8bae1dSRodney W. Grimes 438df8bae1dSRodney W. Grimes if ((ip->i_flag & ILOCKED) == 0) 439df8bae1dSRodney W. Grimes vprint("iso_iunlock: unlocked inode", ITOV(ip)); 440df8bae1dSRodney W. Grimes ip->i_spare0 = 0; 441df8bae1dSRodney W. Grimes ip->i_flag &= ~ILOCKED; 442df8bae1dSRodney W. Grimes if (ip->i_flag&IWANT) { 443df8bae1dSRodney W. Grimes ip->i_flag &= ~IWANT; 444df8bae1dSRodney W. Grimes wakeup((caddr_t)ip); 445df8bae1dSRodney W. Grimes } 44626f9a767SRodney W. Grimes return (0); 447df8bae1dSRodney W. Grimes } 448df8bae1dSRodney W. Grimes 449df8bae1dSRodney W. Grimes /* 450df8bae1dSRodney W. Grimes * File attributes 451df8bae1dSRodney W. Grimes */ 452df8bae1dSRodney W. Grimes void 453988fa8efSJoerg Wunsch cd9660_defattr(isodir,inop,bp,ftype) 454df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 455df8bae1dSRodney W. Grimes struct iso_node *inop; 456df8bae1dSRodney W. Grimes struct buf *bp; 457988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 458df8bae1dSRodney W. Grimes { 459df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 460df8bae1dSRodney W. Grimes struct iso_mnt *imp; 461df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 462df8bae1dSRodney W. Grimes int off; 463df8bae1dSRodney W. Grimes 464988fa8efSJoerg Wunsch /* high sierra does not have timezone data, flag is one byte ahead */ 465988fa8efSJoerg Wunsch if (isonum_711(ftype == ISO_FTYPE_HIGH_SIERRA? 466988fa8efSJoerg Wunsch &isodir->date[6]: isodir->flags)&2) { 467df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFDIR; 468df8bae1dSRodney W. Grimes /* 469df8bae1dSRodney W. Grimes * If we return 2, fts() will assume there are no subdirectories 470df8bae1dSRodney W. Grimes * (just links for the path and .), so instead we return 1. 471df8bae1dSRodney W. Grimes */ 472df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 473df8bae1dSRodney W. Grimes } else { 474df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFREG; 475df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 476df8bae1dSRodney W. Grimes } 477df8bae1dSRodney W. Grimes if (!bp 478df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 479df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 480df8bae1dSRodney W. Grimes iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 481df8bae1dSRodney W. Grimes bp = bp2; 482df8bae1dSRodney W. Grimes } 483df8bae1dSRodney W. Grimes if (bp) { 484df8bae1dSRodney W. Grimes ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 485df8bae1dSRodney W. Grimes 486df8bae1dSRodney W. Grimes if (isonum_711(ap->version) == 1) { 487df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x40)) 488df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 6; 489df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x10)) 490df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 6; 491df8bae1dSRodney W. Grimes if (!(ap->perm[0]&4)) 492df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 3; 493df8bae1dSRodney W. Grimes if (!(ap->perm[0]&1)) 494df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 3; 495df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x40)) 496df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC; 497df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x10)) 498df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD; 499df8bae1dSRodney W. Grimes inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 500df8bae1dSRodney W. Grimes inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 501df8bae1dSRodney W. Grimes } else 502df8bae1dSRodney W. Grimes ap = NULL; 503df8bae1dSRodney W. Grimes } 504df8bae1dSRodney W. Grimes if (!ap) { 505df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 506df8bae1dSRodney W. Grimes inop->inode.iso_uid = (uid_t)0; 507df8bae1dSRodney W. Grimes inop->inode.iso_gid = (gid_t)0; 508df8bae1dSRodney W. Grimes } 509df8bae1dSRodney W. Grimes if (bp2) 510df8bae1dSRodney W. Grimes brelse(bp2); 511df8bae1dSRodney W. Grimes } 512df8bae1dSRodney W. Grimes 513df8bae1dSRodney W. Grimes /* 514df8bae1dSRodney W. Grimes * Time stamps 515df8bae1dSRodney W. Grimes */ 516df8bae1dSRodney W. Grimes void 517988fa8efSJoerg Wunsch cd9660_deftstamp(isodir,inop,bp,ftype) 518df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 519df8bae1dSRodney W. Grimes struct iso_node *inop; 520df8bae1dSRodney W. Grimes struct buf *bp; 521988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 522df8bae1dSRodney W. Grimes { 523df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 524df8bae1dSRodney W. Grimes struct iso_mnt *imp; 525df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 526df8bae1dSRodney W. Grimes int off; 527df8bae1dSRodney W. Grimes 528df8bae1dSRodney W. Grimes if (!bp 529df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 530df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 531df8bae1dSRodney W. Grimes iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 532df8bae1dSRodney W. Grimes bp = bp2; 533df8bae1dSRodney W. Grimes } 534df8bae1dSRodney W. Grimes if (bp) { 535df8bae1dSRodney W. Grimes ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 536df8bae1dSRodney W. Grimes 537988fa8efSJoerg Wunsch if (ftype != ISO_FTYPE_HIGH_SIERRA 538988fa8efSJoerg Wunsch && isonum_711(ap->version) == 1) { 539df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 540df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 541df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 542df8bae1dSRodney W. Grimes inop->inode.iso_ctime = inop->inode.iso_atime; 543df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 544df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 545df8bae1dSRodney W. Grimes } else 546df8bae1dSRodney W. Grimes ap = NULL; 547df8bae1dSRodney W. Grimes } 548df8bae1dSRodney W. Grimes if (!ap) { 549988fa8efSJoerg Wunsch cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime,ftype); 550df8bae1dSRodney W. Grimes inop->inode.iso_atime = inop->inode.iso_ctime; 551df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 552df8bae1dSRodney W. Grimes } 553df8bae1dSRodney W. Grimes if (bp2) 554df8bae1dSRodney W. Grimes brelse(bp2); 555df8bae1dSRodney W. Grimes } 556df8bae1dSRodney W. Grimes 557df8bae1dSRodney W. Grimes int 558988fa8efSJoerg Wunsch cd9660_tstamp_conv7(pi,pu,ftype) 559df8bae1dSRodney W. Grimes char *pi; 5601dbaf90cSBruce Evans struct timespec *pu; 561988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 562df8bae1dSRodney W. Grimes { 563df8bae1dSRodney W. Grimes int crtime, days; 564df8bae1dSRodney W. Grimes int y, m, d, hour, minute, second, tz; 565df8bae1dSRodney W. Grimes 566df8bae1dSRodney W. Grimes y = pi[0] + 1900; 567df8bae1dSRodney W. Grimes m = pi[1]; 568df8bae1dSRodney W. Grimes d = pi[2]; 569df8bae1dSRodney W. Grimes hour = pi[3]; 570df8bae1dSRodney W. Grimes minute = pi[4]; 571df8bae1dSRodney W. Grimes second = pi[5]; 572988fa8efSJoerg Wunsch if(ftype != ISO_FTYPE_HIGH_SIERRA) 573df8bae1dSRodney W. Grimes tz = pi[6]; 574988fa8efSJoerg Wunsch else 575988fa8efSJoerg Wunsch /* original high sierra misses timezone data */ 576988fa8efSJoerg Wunsch tz = 0; 577df8bae1dSRodney W. Grimes 578df8bae1dSRodney W. Grimes if (y < 1970) { 5791dbaf90cSBruce Evans pu->ts_sec = 0; 5801dbaf90cSBruce Evans pu->ts_nsec = 0; 581df8bae1dSRodney W. Grimes return 0; 582df8bae1dSRodney W. Grimes } else { 583df8bae1dSRodney W. Grimes #ifdef ORIGINAL 584df8bae1dSRodney W. Grimes /* computes day number relative to Sept. 19th,1989 */ 585df8bae1dSRodney W. Grimes /* don't even *THINK* about changing formula. It works! */ 586df8bae1dSRodney W. Grimes days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; 587df8bae1dSRodney W. Grimes #else 588df8bae1dSRodney W. Grimes /* 589df8bae1dSRodney W. Grimes * Changed :-) to make it relative to Jan. 1st, 1970 590df8bae1dSRodney W. Grimes * and to disambiguate negative division 591df8bae1dSRodney W. Grimes */ 592df8bae1dSRodney W. Grimes days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; 593df8bae1dSRodney W. Grimes #endif 594df8bae1dSRodney W. Grimes crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 595df8bae1dSRodney W. Grimes 596df8bae1dSRodney W. Grimes /* timezone offset is unreliable on some disks */ 597df8bae1dSRodney W. Grimes if (-48 <= tz && tz <= 52) 5982d091ecfSBruce Evans crtime -= tz * 15 * 60; 599df8bae1dSRodney W. Grimes } 6001dbaf90cSBruce Evans pu->ts_sec = crtime; 6011dbaf90cSBruce Evans pu->ts_nsec = 0; 602df8bae1dSRodney W. Grimes return 1; 603df8bae1dSRodney W. Grimes } 604df8bae1dSRodney W. Grimes 605df8bae1dSRodney W. Grimes static unsigned 606df8bae1dSRodney W. Grimes cd9660_chars2ui(begin,len) 607df8bae1dSRodney W. Grimes unsigned char *begin; 608df8bae1dSRodney W. Grimes int len; 609df8bae1dSRodney W. Grimes { 610df8bae1dSRodney W. Grimes unsigned rc; 611df8bae1dSRodney W. Grimes 612df8bae1dSRodney W. Grimes for (rc = 0; --len >= 0;) { 613df8bae1dSRodney W. Grimes rc *= 10; 614df8bae1dSRodney W. Grimes rc += *begin++ - '0'; 615df8bae1dSRodney W. Grimes } 616df8bae1dSRodney W. Grimes return rc; 617df8bae1dSRodney W. Grimes } 618df8bae1dSRodney W. Grimes 619df8bae1dSRodney W. Grimes int 620df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(pi,pu) 621df8bae1dSRodney W. Grimes unsigned char *pi; 6221dbaf90cSBruce Evans struct timespec *pu; 623df8bae1dSRodney W. Grimes { 624df8bae1dSRodney W. Grimes unsigned char buf[7]; 625df8bae1dSRodney W. Grimes 626df8bae1dSRodney W. Grimes /* year:"0001"-"9999" -> -1900 */ 627df8bae1dSRodney W. Grimes buf[0] = cd9660_chars2ui(pi,4) - 1900; 628df8bae1dSRodney W. Grimes 629df8bae1dSRodney W. Grimes /* month: " 1"-"12" -> 1 - 12 */ 630df8bae1dSRodney W. Grimes buf[1] = cd9660_chars2ui(pi + 4,2); 631df8bae1dSRodney W. Grimes 632df8bae1dSRodney W. Grimes /* day: " 1"-"31" -> 1 - 31 */ 633df8bae1dSRodney W. Grimes buf[2] = cd9660_chars2ui(pi + 6,2); 634df8bae1dSRodney W. Grimes 635df8bae1dSRodney W. Grimes /* hour: " 0"-"23" -> 0 - 23 */ 636df8bae1dSRodney W. Grimes buf[3] = cd9660_chars2ui(pi + 8,2); 637df8bae1dSRodney W. Grimes 638df8bae1dSRodney W. Grimes /* minute:" 0"-"59" -> 0 - 59 */ 639df8bae1dSRodney W. Grimes buf[4] = cd9660_chars2ui(pi + 10,2); 640df8bae1dSRodney W. Grimes 641df8bae1dSRodney W. Grimes /* second:" 0"-"59" -> 0 - 59 */ 642df8bae1dSRodney W. Grimes buf[5] = cd9660_chars2ui(pi + 12,2); 643df8bae1dSRodney W. Grimes 644df8bae1dSRodney W. Grimes /* difference of GMT */ 645df8bae1dSRodney W. Grimes buf[6] = pi[16]; 646df8bae1dSRodney W. Grimes 647988fa8efSJoerg Wunsch return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT); 648df8bae1dSRodney W. Grimes } 649df8bae1dSRodney W. Grimes 650df8bae1dSRodney W. Grimes void 651df8bae1dSRodney W. Grimes isodirino(inump,isodir,imp) 652df8bae1dSRodney W. Grimes ino_t *inump; 653df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 654df8bae1dSRodney W. Grimes struct iso_mnt *imp; 655df8bae1dSRodney W. Grimes { 656df8bae1dSRodney W. Grimes *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 657df8bae1dSRodney W. Grimes * imp->logical_block_size; 658df8bae1dSRodney W. Grimes } 659