1df8bae1dSRodney W. Grimes /*- 2996c772fSJohn Dyson * Copyright (c) 1982, 1986, 1989, 1994, 1995 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 391130b656SJordan K. Hubbard * $FreeBSD$ 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> 55996c772fSJohn Dyson #include <isofs/cd9660/cd9660_mount.h> 56df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso_rrip.h> 57df8bae1dSRodney W. Grimes 58996c772fSJohn Dyson /* 59996c772fSJohn Dyson * Structures associated with iso_node caching. 60996c772fSJohn Dyson */ 61996c772fSJohn Dyson struct iso_node **isohashtbl; 62996c772fSJohn Dyson u_long isohash; 63996c772fSJohn Dyson #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash) 64996c772fSJohn Dyson struct simplelock cd9660_ihash_slock; 65df8bae1dSRodney W. Grimes 66df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 67996c772fSJohn Dyson struct iso_node **idvhashtbl; 68996c772fSJohn Dyson u_long idvhash; 69996c772fSJohn Dyson #define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash) 70df8bae1dSRodney W. Grimes #endif 71df8bae1dSRodney W. Grimes 7210dd32cdSBruce Evans static unsigned cd9660_chars2ui __P((unsigned char *begin, int len)); 7310dd32cdSBruce Evans 74df8bae1dSRodney W. Grimes /* 75df8bae1dSRodney W. Grimes * Initialize hash links for inodes and dnodes. 76df8bae1dSRodney W. Grimes */ 7726f9a767SRodney W. Grimes int 78996c772fSJohn Dyson cd9660_init(vfsp) 79996c772fSJohn Dyson struct vfsconf *vfsp; 80df8bae1dSRodney W. Grimes { 81df8bae1dSRodney W. Grimes 82996c772fSJohn Dyson isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash); 83996c772fSJohn Dyson simple_lock_init(&cd9660_ihash_slock); 84df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 85996c772fSJohn Dyson idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash); 86df8bae1dSRodney W. Grimes #endif 8726f9a767SRodney W. Grimes return (0); 88df8bae1dSRodney W. Grimes } 89df8bae1dSRodney W. Grimes 90df8bae1dSRodney W. Grimes #ifdef ISODEVMAP 91df8bae1dSRodney W. Grimes /* 92df8bae1dSRodney W. Grimes * Enter a new node into the device hash list 93df8bae1dSRodney W. Grimes */ 94df8bae1dSRodney W. Grimes struct iso_dnode * 95996c772fSJohn Dyson iso_dmap(device, inum, create) 96996c772fSJohn Dyson dev_t device; 97996c772fSJohn Dyson ino_t inum; 98df8bae1dSRodney W. Grimes int create; 99df8bae1dSRodney W. Grimes { 100996c772fSJohn Dyson register struct iso_dnode **dpp, *dp, *dq; 101df8bae1dSRodney W. Grimes 102996c772fSJohn Dyson dpp = &idvhashtbl[DNOHASH(device, inum)]; 103996c772fSJohn Dyson for (dp = *dpp;; dp = dp->d_next) { 104996c772fSJohn Dyson if (dp == NULL) 105996c772fSJohn Dyson return (NULL); 106996c772fSJohn Dyson if (inum == dp->i_number && device == dp->i_dev) 107996c772fSJohn Dyson return (dp); 108df8bae1dSRodney W. Grimes 109df8bae1dSRodney W. Grimes if (!create) 110996c772fSJohn Dyson return (NULL); 111df8bae1dSRodney W. Grimes 112996c772fSJohn Dyson MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE, 113996c772fSJohn Dyson M_WAITOK); 114df8bae1dSRodney W. Grimes dp->i_dev = dev; 115df8bae1dSRodney W. Grimes dp->i_number = ino; 116df8bae1dSRodney W. Grimes 117996c772fSJohn Dyson if (dq = *dpp) 118996c772fSJohn Dyson dq->d_prev = dp->d_next; 119996c772fSJohn Dyson dp->d_next = dq; 120996c772fSJohn Dyson dp->d_prev = dpp; 121996c772fSJohn Dyson *dpp = dp; 122996c772fSJohn Dyson 123996c772fSJohn Dyson return (dp); 124df8bae1dSRodney W. Grimes } 125df8bae1dSRodney W. Grimes 126df8bae1dSRodney W. Grimes void 127996c772fSJohn Dyson iso_dunmap(device) 128996c772fSJohn Dyson dev_t device; 129df8bae1dSRodney W. Grimes { 130996c772fSJohn Dyson struct iso_dnode **dpp, *dp, *dq; 131df8bae1dSRodney W. Grimes 132996c772fSJohn Dyson for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) { 133996c772fSJohn Dyson for (dp = *dpp; dp != NULL; dp = dq) 134996c772fSJohn Dyson dq = dp->d_next; 135996c772fSJohn Dyson if (device == dp->i_dev) { 136996c772fSJohn Dyson if (dq) 137996c772fSJohn Dyson dq->d_prev = dp->d_prev; 138996c772fSJohn Dyson *dp->d_prev = dq; 139df8bae1dSRodney W. Grimes FREE(dp, M_CACHE); 140df8bae1dSRodney W. Grimes } 141df8bae1dSRodney W. Grimes } 142df8bae1dSRodney W. Grimes } 143df8bae1dSRodney W. Grimes } 144df8bae1dSRodney W. Grimes #endif 145df8bae1dSRodney W. Grimes 146df8bae1dSRodney W. Grimes /* 147996c772fSJohn Dyson * Use the device/inum pair to find the incore inode, and return a pointer 148996c772fSJohn Dyson * to it. If it is in core, but locked, wait for it. 149df8bae1dSRodney W. Grimes */ 150996c772fSJohn Dyson struct vnode * 151996c772fSJohn Dyson cd9660_ihashget(dev, inum) 152996c772fSJohn Dyson dev_t dev; 153996c772fSJohn Dyson ino_t inum; 154df8bae1dSRodney W. Grimes { 155996c772fSJohn Dyson struct proc *p = curproc; /* XXX */ 156996c772fSJohn Dyson struct iso_node *ip; 157996c772fSJohn Dyson struct vnode *vp; 158df8bae1dSRodney W. Grimes 159df8bae1dSRodney W. Grimes loop: 160996c772fSJohn Dyson simple_lock(&cd9660_ihash_slock); 161996c772fSJohn Dyson for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) { 162996c772fSJohn Dyson if (inum == ip->i_number && dev == ip->i_dev) { 163df8bae1dSRodney W. Grimes vp = ITOV(ip); 164996c772fSJohn Dyson simple_lock(&vp->v_interlock); 165996c772fSJohn Dyson simple_unlock(&cd9660_ihash_slock); 166996c772fSJohn Dyson if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) 167996c772fSJohn Dyson goto loop; 168996c772fSJohn Dyson return (vp); 169df8bae1dSRodney W. Grimes } 170df8bae1dSRodney W. Grimes } 171996c772fSJohn Dyson simple_unlock(&cd9660_ihash_slock); 172996c772fSJohn Dyson return (NULL); 173996c772fSJohn Dyson } 174df8bae1dSRodney W. Grimes 175996c772fSJohn Dyson /* 176996c772fSJohn Dyson * Insert the inode into the hash table, and return it locked. 177996c772fSJohn Dyson */ 178996c772fSJohn Dyson void 179996c772fSJohn Dyson cd9660_ihashins(ip) 180996c772fSJohn Dyson struct iso_node *ip; 181996c772fSJohn Dyson { 182996c772fSJohn Dyson struct proc *p = curproc; /* XXX */ 183996c772fSJohn Dyson struct iso_node **ipp, *iq; 184df8bae1dSRodney W. Grimes 185996c772fSJohn Dyson simple_lock(&cd9660_ihash_slock); 186996c772fSJohn Dyson ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)]; 187996c772fSJohn Dyson if (iq = *ipp) 188996c772fSJohn Dyson iq->i_prev = &ip->i_next; 189996c772fSJohn Dyson ip->i_next = iq; 190996c772fSJohn Dyson ip->i_prev = ipp; 191df8bae1dSRodney W. Grimes *ipp = ip; 192996c772fSJohn Dyson simple_unlock(&cd9660_ihash_slock); 193996c772fSJohn Dyson 194996c772fSJohn Dyson lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct simplelock *)0, p); 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes /* 198996c772fSJohn Dyson * Remove the inode from the hash table. 199df8bae1dSRodney W. Grimes */ 200996c772fSJohn Dyson void 201996c772fSJohn Dyson cd9660_ihashrem(ip) 202df8bae1dSRodney W. Grimes register struct iso_node *ip; 203df8bae1dSRodney W. Grimes { 204996c772fSJohn Dyson register struct iso_node *iq; 205df8bae1dSRodney W. Grimes 206996c772fSJohn Dyson simple_lock(&cd9660_ihash_slock); 207996c772fSJohn Dyson if (iq = ip->i_next) 208996c772fSJohn Dyson iq->i_prev = ip->i_prev; 209996c772fSJohn Dyson *ip->i_prev = iq; 210996c772fSJohn Dyson #ifdef DIAGNOSTIC 211996c772fSJohn Dyson ip->i_next = NULL; 212996c772fSJohn Dyson ip->i_prev = NULL; 213996c772fSJohn Dyson #endif 214996c772fSJohn Dyson simple_unlock(&cd9660_ihash_slock); 215df8bae1dSRodney W. Grimes } 216df8bae1dSRodney W. Grimes 217df8bae1dSRodney W. Grimes /* 218df8bae1dSRodney W. Grimes * Last reference to an inode, write the inode out and if necessary, 219df8bae1dSRodney W. Grimes * truncate and deallocate the file. 220df8bae1dSRodney W. Grimes */ 221df8bae1dSRodney W. Grimes int 222df8bae1dSRodney W. Grimes cd9660_inactive(ap) 223df8bae1dSRodney W. Grimes struct vop_inactive_args /* { 224df8bae1dSRodney W. Grimes struct vnode *a_vp; 225996c772fSJohn Dyson struct proc *a_p; 226df8bae1dSRodney W. Grimes } */ *ap; 227df8bae1dSRodney W. Grimes { 228df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 229996c772fSJohn Dyson struct proc *p = ap->a_p; 230df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 2311295d82eSGary Palmer int error = 0; 232df8bae1dSRodney W. Grimes 233df8bae1dSRodney W. Grimes if (prtactive && vp->v_usecount != 0) 234df8bae1dSRodney W. Grimes vprint("cd9660_inactive: pushing active", vp); 235df8bae1dSRodney W. Grimes 236df8bae1dSRodney W. Grimes ip->i_flag = 0; 237996c772fSJohn Dyson VOP_UNLOCK(vp, 0, p); 238df8bae1dSRodney W. Grimes /* 239df8bae1dSRodney W. Grimes * If we are done with the inode, reclaim it 240df8bae1dSRodney W. Grimes * so that it can be reused immediately. 241df8bae1dSRodney W. Grimes */ 242996c772fSJohn Dyson if (ip->inode.iso_mode == 0) 243996c772fSJohn Dyson vrecycle(vp, (struct simplelock *)0, p); 244df8bae1dSRodney W. Grimes return error; 245df8bae1dSRodney W. Grimes } 246df8bae1dSRodney W. Grimes 247df8bae1dSRodney W. Grimes /* 248df8bae1dSRodney W. Grimes * Reclaim an inode so that it can be used for other purposes. 249df8bae1dSRodney W. Grimes */ 250df8bae1dSRodney W. Grimes int 251df8bae1dSRodney W. Grimes cd9660_reclaim(ap) 252df8bae1dSRodney W. Grimes struct vop_reclaim_args /* { 253df8bae1dSRodney W. Grimes struct vnode *a_vp; 254996c772fSJohn Dyson struct proc *a_p; 255df8bae1dSRodney W. Grimes } */ *ap; 256df8bae1dSRodney W. Grimes { 257df8bae1dSRodney W. Grimes register struct vnode *vp = ap->a_vp; 258df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 259df8bae1dSRodney W. Grimes 260df8bae1dSRodney W. Grimes if (prtactive && vp->v_usecount != 0) 261df8bae1dSRodney W. Grimes vprint("cd9660_reclaim: pushing active", vp); 262df8bae1dSRodney W. Grimes /* 263df8bae1dSRodney W. Grimes * Remove the inode from its hash chain. 264df8bae1dSRodney W. Grimes */ 265996c772fSJohn Dyson cd9660_ihashrem(ip); 266df8bae1dSRodney W. Grimes /* 267df8bae1dSRodney W. Grimes * Purge old data structures associated with the inode. 268df8bae1dSRodney W. Grimes */ 269df8bae1dSRodney W. Grimes cache_purge(vp); 270df8bae1dSRodney W. Grimes if (ip->i_devvp) { 271df8bae1dSRodney W. Grimes vrele(ip->i_devvp); 272df8bae1dSRodney W. Grimes ip->i_devvp = 0; 273df8bae1dSRodney W. Grimes } 274df8bae1dSRodney W. Grimes FREE(vp->v_data, M_ISOFSNODE); 275df8bae1dSRodney W. Grimes vp->v_data = NULL; 27626f9a767SRodney W. Grimes return (0); 277df8bae1dSRodney W. Grimes } 278df8bae1dSRodney W. Grimes 279df8bae1dSRodney W. Grimes /* 280df8bae1dSRodney W. Grimes * File attributes 281df8bae1dSRodney W. Grimes */ 282df8bae1dSRodney W. Grimes void 283988fa8efSJoerg Wunsch cd9660_defattr(isodir, inop, bp, ftype) 284df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 285df8bae1dSRodney W. Grimes struct iso_node *inop; 286df8bae1dSRodney W. Grimes struct buf *bp; 287988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 288df8bae1dSRodney W. Grimes { 289df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 290df8bae1dSRodney W. Grimes struct iso_mnt *imp; 291df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 292df8bae1dSRodney W. Grimes int off; 293df8bae1dSRodney W. Grimes 294988fa8efSJoerg Wunsch /* high sierra does not have timezone data, flag is one byte ahead */ 295988fa8efSJoerg Wunsch if (isonum_711(ftype == ISO_FTYPE_HIGH_SIERRA? 296988fa8efSJoerg Wunsch &isodir->date[6]: isodir->flags)&2) { 297df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFDIR; 298df8bae1dSRodney W. Grimes /* 299df8bae1dSRodney W. Grimes * If we return 2, fts() will assume there are no subdirectories 300df8bae1dSRodney W. Grimes * (just links for the path and .), so instead we return 1. 301df8bae1dSRodney W. Grimes */ 302df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 303df8bae1dSRodney W. Grimes } else { 304df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFREG; 305df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 306df8bae1dSRodney W. Grimes } 307df8bae1dSRodney W. Grimes if (!bp 308df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) 309df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 310996c772fSJohn Dyson VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, 311996c772fSJohn Dyson &bp2); 312df8bae1dSRodney W. Grimes bp = bp2; 313df8bae1dSRodney W. Grimes } 314df8bae1dSRodney W. Grimes if (bp) { 315996c772fSJohn Dyson ap = (struct iso_extended_attributes *)bp->b_data; 316df8bae1dSRodney W. Grimes 317df8bae1dSRodney W. Grimes if (isonum_711(ap->version) == 1) { 318df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x40)) 319df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 6; 320df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x10)) 321df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 6; 322df8bae1dSRodney W. Grimes if (!(ap->perm[0]&4)) 323df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 3; 324df8bae1dSRodney W. Grimes if (!(ap->perm[0]&1)) 325df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 3; 326df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x40)) 327df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC; 328df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x10)) 329df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD; 330df8bae1dSRodney W. Grimes inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 331df8bae1dSRodney W. Grimes inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 332df8bae1dSRodney W. Grimes } else 333df8bae1dSRodney W. Grimes ap = NULL; 334df8bae1dSRodney W. Grimes } 335df8bae1dSRodney W. Grimes if (!ap) { 336df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 337df8bae1dSRodney W. Grimes inop->inode.iso_uid = (uid_t)0; 338df8bae1dSRodney W. Grimes inop->inode.iso_gid = (gid_t)0; 339df8bae1dSRodney W. Grimes } 340df8bae1dSRodney W. Grimes if (bp2) 341df8bae1dSRodney W. Grimes brelse(bp2); 342df8bae1dSRodney W. Grimes } 343df8bae1dSRodney W. Grimes 344df8bae1dSRodney W. Grimes /* 345df8bae1dSRodney W. Grimes * Time stamps 346df8bae1dSRodney W. Grimes */ 347df8bae1dSRodney W. Grimes void 348988fa8efSJoerg Wunsch cd9660_deftstamp(isodir,inop,bp,ftype) 349df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 350df8bae1dSRodney W. Grimes struct iso_node *inop; 351df8bae1dSRodney W. Grimes struct buf *bp; 352988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 353df8bae1dSRodney W. Grimes { 354df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 355df8bae1dSRodney W. Grimes struct iso_mnt *imp; 356df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 357df8bae1dSRodney W. Grimes int off; 358df8bae1dSRodney W. Grimes 359df8bae1dSRodney W. Grimes if (!bp 360df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) 361df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 362996c772fSJohn Dyson VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, 363996c772fSJohn Dyson &bp2); 364df8bae1dSRodney W. Grimes bp = bp2; 365df8bae1dSRodney W. Grimes } 366df8bae1dSRodney W. Grimes if (bp) { 367996c772fSJohn Dyson ap = (struct iso_extended_attributes *)bp->b_data; 368df8bae1dSRodney W. Grimes 369596d40b9SBruce Evans if (ftype != ISO_FTYPE_HIGH_SIERRA 370596d40b9SBruce Evans && isonum_711(ap->version) == 1) { 371df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 372df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 373df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 374df8bae1dSRodney W. Grimes inop->inode.iso_ctime = inop->inode.iso_atime; 375df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 376df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 377df8bae1dSRodney W. Grimes } else 378df8bae1dSRodney W. Grimes ap = NULL; 379df8bae1dSRodney W. Grimes } 380df8bae1dSRodney W. Grimes if (!ap) { 381988fa8efSJoerg Wunsch cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime,ftype); 382df8bae1dSRodney W. Grimes inop->inode.iso_atime = inop->inode.iso_ctime; 383df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 384df8bae1dSRodney W. Grimes } 385df8bae1dSRodney W. Grimes if (bp2) 386df8bae1dSRodney W. Grimes brelse(bp2); 387df8bae1dSRodney W. Grimes } 388df8bae1dSRodney W. Grimes 389df8bae1dSRodney W. Grimes int 390988fa8efSJoerg Wunsch cd9660_tstamp_conv7(pi,pu,ftype) 391996c772fSJohn Dyson u_char *pi; 3921dbaf90cSBruce Evans struct timespec *pu; 393988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 394df8bae1dSRodney W. Grimes { 395df8bae1dSRodney W. Grimes int crtime, days; 396df8bae1dSRodney W. Grimes int y, m, d, hour, minute, second, tz; 397df8bae1dSRodney W. Grimes 398df8bae1dSRodney W. Grimes y = pi[0] + 1900; 399df8bae1dSRodney W. Grimes m = pi[1]; 400df8bae1dSRodney W. Grimes d = pi[2]; 401df8bae1dSRodney W. Grimes hour = pi[3]; 402df8bae1dSRodney W. Grimes minute = pi[4]; 403df8bae1dSRodney W. Grimes second = pi[5]; 404988fa8efSJoerg Wunsch if(ftype != ISO_FTYPE_HIGH_SIERRA) 405df8bae1dSRodney W. Grimes tz = pi[6]; 406988fa8efSJoerg Wunsch else 407988fa8efSJoerg Wunsch /* original high sierra misses timezone data */ 408988fa8efSJoerg Wunsch tz = 0; 409df8bae1dSRodney W. Grimes 410df8bae1dSRodney W. Grimes if (y < 1970) { 41195a1574eSNate Williams pu->tv_sec = 0; 41295a1574eSNate Williams pu->tv_nsec = 0; 413df8bae1dSRodney W. Grimes return 0; 414df8bae1dSRodney W. Grimes } else { 415df8bae1dSRodney W. Grimes #ifdef ORIGINAL 416df8bae1dSRodney W. Grimes /* computes day number relative to Sept. 19th,1989 */ 417df8bae1dSRodney W. Grimes /* don't even *THINK* about changing formula. It works! */ 418df8bae1dSRodney 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; 419df8bae1dSRodney W. Grimes #else 420df8bae1dSRodney W. Grimes /* 421df8bae1dSRodney W. Grimes * Changed :-) to make it relative to Jan. 1st, 1970 422df8bae1dSRodney W. Grimes * and to disambiguate negative division 423df8bae1dSRodney W. Grimes */ 424df8bae1dSRodney 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; 425df8bae1dSRodney W. Grimes #endif 426df8bae1dSRodney W. Grimes crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 427df8bae1dSRodney W. Grimes 428df8bae1dSRodney W. Grimes /* timezone offset is unreliable on some disks */ 429df8bae1dSRodney W. Grimes if (-48 <= tz && tz <= 52) 4302d091ecfSBruce Evans crtime -= tz * 15 * 60; 431df8bae1dSRodney W. Grimes } 43295a1574eSNate Williams pu->tv_sec = crtime; 43395a1574eSNate Williams pu->tv_nsec = 0; 434df8bae1dSRodney W. Grimes return 1; 435df8bae1dSRodney W. Grimes } 436df8bae1dSRodney W. Grimes 437996c772fSJohn Dyson static u_int 438df8bae1dSRodney W. Grimes cd9660_chars2ui(begin,len) 439996c772fSJohn Dyson u_char *begin; 440df8bae1dSRodney W. Grimes int len; 441df8bae1dSRodney W. Grimes { 442996c772fSJohn Dyson u_int rc; 443df8bae1dSRodney W. Grimes 444df8bae1dSRodney W. Grimes for (rc = 0; --len >= 0;) { 445df8bae1dSRodney W. Grimes rc *= 10; 446df8bae1dSRodney W. Grimes rc += *begin++ - '0'; 447df8bae1dSRodney W. Grimes } 448df8bae1dSRodney W. Grimes return rc; 449df8bae1dSRodney W. Grimes } 450df8bae1dSRodney W. Grimes 451df8bae1dSRodney W. Grimes int 452df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(pi,pu) 453996c772fSJohn Dyson u_char *pi; 4541dbaf90cSBruce Evans struct timespec *pu; 455df8bae1dSRodney W. Grimes { 456996c772fSJohn Dyson u_char buf[7]; 457df8bae1dSRodney W. Grimes 458df8bae1dSRodney W. Grimes /* year:"0001"-"9999" -> -1900 */ 459df8bae1dSRodney W. Grimes buf[0] = cd9660_chars2ui(pi,4) - 1900; 460df8bae1dSRodney W. Grimes 461df8bae1dSRodney W. Grimes /* month: " 1"-"12" -> 1 - 12 */ 462df8bae1dSRodney W. Grimes buf[1] = cd9660_chars2ui(pi + 4,2); 463df8bae1dSRodney W. Grimes 464df8bae1dSRodney W. Grimes /* day: " 1"-"31" -> 1 - 31 */ 465df8bae1dSRodney W. Grimes buf[2] = cd9660_chars2ui(pi + 6,2); 466df8bae1dSRodney W. Grimes 467df8bae1dSRodney W. Grimes /* hour: " 0"-"23" -> 0 - 23 */ 468df8bae1dSRodney W. Grimes buf[3] = cd9660_chars2ui(pi + 8,2); 469df8bae1dSRodney W. Grimes 470df8bae1dSRodney W. Grimes /* minute:" 0"-"59" -> 0 - 59 */ 471df8bae1dSRodney W. Grimes buf[4] = cd9660_chars2ui(pi + 10,2); 472df8bae1dSRodney W. Grimes 473df8bae1dSRodney W. Grimes /* second:" 0"-"59" -> 0 - 59 */ 474df8bae1dSRodney W. Grimes buf[5] = cd9660_chars2ui(pi + 12,2); 475df8bae1dSRodney W. Grimes 476df8bae1dSRodney W. Grimes /* difference of GMT */ 477df8bae1dSRodney W. Grimes buf[6] = pi[16]; 478df8bae1dSRodney W. Grimes 479988fa8efSJoerg Wunsch return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT); 480df8bae1dSRodney W. Grimes } 481df8bae1dSRodney W. Grimes 482996c772fSJohn Dyson ino_t 483996c772fSJohn Dyson isodirino(isodir, imp) 484df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 485df8bae1dSRodney W. Grimes struct iso_mnt *imp; 486df8bae1dSRodney W. Grimes { 487996c772fSJohn Dyson ino_t ino; 488996c772fSJohn Dyson 489996c772fSJohn Dyson ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 490996c772fSJohn Dyson << imp->im_bshift; 491996c772fSJohn Dyson return (ino); 492df8bae1dSRodney W. Grimes } 493