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 * 4. Neither the name of the University nor the names of its contributors 19df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 20df8bae1dSRodney W. Grimes * without specific prior written permission. 21df8bae1dSRodney W. Grimes * 22df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df8bae1dSRodney W. Grimes * SUCH DAMAGE. 33df8bae1dSRodney W. Grimes * 34df8bae1dSRodney W. Grimes * @(#)cd9660_node.c 8.2 (Berkeley) 1/23/94 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 378c9bbf48SDavid E. O'Brien #include <sys/cdefs.h> 388c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$"); 398c9bbf48SDavid E. O'Brien 40df8bae1dSRodney W. Grimes #include <sys/param.h> 41df8bae1dSRodney W. Grimes #include <sys/systm.h> 42df8bae1dSRodney W. Grimes #include <sys/mount.h> 439626b608SPoul-Henning Kamp #include <sys/bio.h> 44df8bae1dSRodney W. Grimes #include <sys/buf.h> 45df8bae1dSRodney W. Grimes #include <sys/vnode.h> 46df8bae1dSRodney W. Grimes #include <sys/malloc.h> 47df8bae1dSRodney W. Grimes #include <sys/stat.h> 481b367556SJason Evans #include <sys/mutex.h> 49a18b1f1dSJason Evans 50df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso.h> 51df8bae1dSRodney W. Grimes #include <isofs/cd9660/cd9660_node.h> 52996c772fSJohn Dyson #include <isofs/cd9660/cd9660_mount.h> 53df8bae1dSRodney W. Grimes 54996c772fSJohn Dyson /* 55996c772fSJohn Dyson * Structures associated with iso_node caching. 56996c772fSJohn Dyson */ 57303b270bSEivind Eklund static struct iso_node **isohashtbl; 58303b270bSEivind Eklund static u_long isohash; 59bfbb9ce6SPoul-Henning Kamp #define INOHASH(device, inum) ((minor(device) + ((inum)>>12)) & isohash) 601b367556SJason Evans static struct mtx cd9660_ihash_mtx; 61df8bae1dSRodney W. Grimes 6289c9a483SAlfred Perlstein static void cd9660_ihashrem(struct iso_node *); 6389c9a483SAlfred Perlstein static unsigned cd9660_chars2ui(unsigned char *begin, int len); 6410dd32cdSBruce Evans 65df8bae1dSRodney W. Grimes /* 66df8bae1dSRodney W. Grimes * Initialize hash links for inodes and dnodes. 67df8bae1dSRodney W. Grimes */ 6826f9a767SRodney W. Grimes int 69996c772fSJohn Dyson cd9660_init(vfsp) 70996c772fSJohn Dyson struct vfsconf *vfsp; 71df8bae1dSRodney W. Grimes { 72df8bae1dSRodney W. Grimes 73996c772fSJohn Dyson isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash); 746008862bSJohn Baldwin mtx_init(&cd9660_ihash_mtx, "cd9660_ihash", NULL, MTX_DEF); 7526f9a767SRodney W. Grimes return (0); 76df8bae1dSRodney W. Grimes } 77df8bae1dSRodney W. Grimes 786843189aSBoris Popov int 796843189aSBoris Popov cd9660_uninit(vfsp) 806843189aSBoris Popov struct vfsconf *vfsp; 816843189aSBoris Popov { 826843189aSBoris Popov 836843189aSBoris Popov if (isohashtbl != NULL) 846843189aSBoris Popov free(isohashtbl, M_ISOFSMNT); 856843189aSBoris Popov return (0); 866843189aSBoris Popov } 876843189aSBoris Popov 88df8bae1dSRodney W. Grimes 89df8bae1dSRodney W. Grimes /* 90996c772fSJohn Dyson * Use the device/inum pair to find the incore inode, and return a pointer 91996c772fSJohn Dyson * to it. If it is in core, but locked, wait for it. 92df8bae1dSRodney W. Grimes */ 93a0595d02SKirk McKusick int 94a0595d02SKirk McKusick cd9660_ihashget(dev, inum, flags, vpp) 9589c9c53dSPoul-Henning Kamp struct cdev *dev; 96996c772fSJohn Dyson ino_t inum; 97a0595d02SKirk McKusick int flags; 98a0595d02SKirk McKusick struct vnode **vpp; 99df8bae1dSRodney W. Grimes { 100b40ce416SJulian Elischer struct thread *td = curthread; /* XXX */ 101996c772fSJohn Dyson struct iso_node *ip; 102996c772fSJohn Dyson struct vnode *vp; 103a0595d02SKirk McKusick int error; 104df8bae1dSRodney W. Grimes 105a0595d02SKirk McKusick *vpp = NULL; 106df8bae1dSRodney W. Grimes loop: 1079ed346baSBosko Milekic mtx_lock(&cd9660_ihash_mtx); 108996c772fSJohn Dyson for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) { 109996c772fSJohn Dyson if (inum == ip->i_number && dev == ip->i_dev) { 110df8bae1dSRodney W. Grimes vp = ITOV(ip); 1119ed346baSBosko Milekic mtx_lock(&vp->v_interlock); 1129ed346baSBosko Milekic mtx_unlock(&cd9660_ihash_mtx); 113a0595d02SKirk McKusick error = vget(vp, flags | LK_INTERLOCK, td); 114a0595d02SKirk McKusick if (error == ENOENT) 115996c772fSJohn Dyson goto loop; 116a0595d02SKirk McKusick if (error) 117a0595d02SKirk McKusick return (error); 118a0595d02SKirk McKusick *vpp = vp; 119a0595d02SKirk McKusick return (0); 120df8bae1dSRodney W. Grimes } 121df8bae1dSRodney W. Grimes } 1229ed346baSBosko Milekic mtx_unlock(&cd9660_ihash_mtx); 123a0595d02SKirk McKusick return (0); 124996c772fSJohn Dyson } 125df8bae1dSRodney W. Grimes 126996c772fSJohn Dyson /* 127996c772fSJohn Dyson * Insert the inode into the hash table, and return it locked. 128996c772fSJohn Dyson */ 129996c772fSJohn Dyson void 130996c772fSJohn Dyson cd9660_ihashins(ip) 131996c772fSJohn Dyson struct iso_node *ip; 132996c772fSJohn Dyson { 133996c772fSJohn Dyson struct iso_node **ipp, *iq; 134df8bae1dSRodney W. Grimes 1359ed346baSBosko Milekic mtx_lock(&cd9660_ihash_mtx); 136996c772fSJohn Dyson ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)]; 137d254af07SMatthew Dillon if ((iq = *ipp) != NULL) 138996c772fSJohn Dyson iq->i_prev = &ip->i_next; 139996c772fSJohn Dyson ip->i_next = iq; 140996c772fSJohn Dyson ip->i_prev = ipp; 141df8bae1dSRodney W. Grimes *ipp = ip; 1429ed346baSBosko Milekic mtx_unlock(&cd9660_ihash_mtx); 143996c772fSJohn Dyson 144a5b65058SKirk McKusick vn_lock(ITOV(ip), LK_EXCLUSIVE | LK_RETRY, curthread); 145df8bae1dSRodney W. Grimes } 146df8bae1dSRodney W. Grimes 147df8bae1dSRodney W. Grimes /* 148996c772fSJohn Dyson * Remove the inode from the hash table. 149df8bae1dSRodney W. Grimes */ 150f041a9bdSPoul-Henning Kamp static void 151996c772fSJohn Dyson cd9660_ihashrem(ip) 152bffd1b7aSPoul-Henning Kamp struct iso_node *ip; 153df8bae1dSRodney W. Grimes { 154bffd1b7aSPoul-Henning Kamp struct iso_node *iq; 155df8bae1dSRodney W. Grimes 1569ed346baSBosko Milekic mtx_lock(&cd9660_ihash_mtx); 157d254af07SMatthew Dillon if ((iq = ip->i_next) != NULL) 158996c772fSJohn Dyson iq->i_prev = ip->i_prev; 159996c772fSJohn Dyson *ip->i_prev = iq; 160996c772fSJohn Dyson #ifdef DIAGNOSTIC 161996c772fSJohn Dyson ip->i_next = NULL; 162996c772fSJohn Dyson ip->i_prev = NULL; 163996c772fSJohn Dyson #endif 1649ed346baSBosko Milekic mtx_unlock(&cd9660_ihash_mtx); 165df8bae1dSRodney W. Grimes } 166df8bae1dSRodney W. Grimes 167df8bae1dSRodney W. Grimes /* 168df8bae1dSRodney W. Grimes * Last reference to an inode, write the inode out and if necessary, 169df8bae1dSRodney W. Grimes * truncate and deallocate the file. 170df8bae1dSRodney W. Grimes */ 171df8bae1dSRodney W. Grimes int 172df8bae1dSRodney W. Grimes cd9660_inactive(ap) 173df8bae1dSRodney W. Grimes struct vop_inactive_args /* { 174df8bae1dSRodney W. Grimes struct vnode *a_vp; 175b40ce416SJulian Elischer struct thread *a_td; 176df8bae1dSRodney W. Grimes } */ *ap; 177df8bae1dSRodney W. Grimes { 178df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 179b40ce416SJulian Elischer struct thread *td = ap->a_td; 180bffd1b7aSPoul-Henning Kamp struct iso_node *ip = VTOI(vp); 1811295d82eSGary Palmer int error = 0; 182df8bae1dSRodney W. Grimes 18337ab0e0dSJeff Roberson if (prtactive && vrefcnt(vp) != 0) 184df8bae1dSRodney W. Grimes vprint("cd9660_inactive: pushing active", vp); 185df8bae1dSRodney W. Grimes 186df8bae1dSRodney W. Grimes ip->i_flag = 0; 187b40ce416SJulian Elischer VOP_UNLOCK(vp, 0, td); 188df8bae1dSRodney W. Grimes /* 189df8bae1dSRodney W. Grimes * If we are done with the inode, reclaim it 190df8bae1dSRodney W. Grimes * so that it can be reused immediately. 191df8bae1dSRodney W. Grimes */ 192996c772fSJohn Dyson if (ip->inode.iso_mode == 0) 193b40ce416SJulian Elischer vrecycle(vp, NULL, td); 194df8bae1dSRodney W. Grimes return error; 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes /* 198df8bae1dSRodney W. Grimes * Reclaim an inode so that it can be used for other purposes. 199df8bae1dSRodney W. Grimes */ 200df8bae1dSRodney W. Grimes int 201df8bae1dSRodney W. Grimes cd9660_reclaim(ap) 202df8bae1dSRodney W. Grimes struct vop_reclaim_args /* { 203df8bae1dSRodney W. Grimes struct vnode *a_vp; 204b40ce416SJulian Elischer struct thread *a_td; 205df8bae1dSRodney W. Grimes } */ *ap; 206df8bae1dSRodney W. Grimes { 207bffd1b7aSPoul-Henning Kamp struct vnode *vp = ap->a_vp; 208bffd1b7aSPoul-Henning Kamp struct iso_node *ip = VTOI(vp); 209df8bae1dSRodney W. Grimes 21037ab0e0dSJeff Roberson if (prtactive && vrefcnt(vp) != 0) 211df8bae1dSRodney W. Grimes vprint("cd9660_reclaim: pushing active", vp); 212df8bae1dSRodney W. Grimes /* 213df8bae1dSRodney W. Grimes * Remove the inode from its hash chain. 214df8bae1dSRodney W. Grimes */ 215996c772fSJohn Dyson cd9660_ihashrem(ip); 216df8bae1dSRodney W. Grimes /* 217df8bae1dSRodney W. Grimes * Purge old data structures associated with the inode. 218df8bae1dSRodney W. Grimes */ 219df8bae1dSRodney W. Grimes if (ip->i_devvp) { 220df8bae1dSRodney W. Grimes vrele(ip->i_devvp); 221df8bae1dSRodney W. Grimes ip->i_devvp = 0; 222df8bae1dSRodney W. Grimes } 223df8bae1dSRodney W. Grimes FREE(vp->v_data, M_ISOFSNODE); 224df8bae1dSRodney W. Grimes vp->v_data = NULL; 22526f9a767SRodney W. Grimes return (0); 226df8bae1dSRodney W. Grimes } 227df8bae1dSRodney W. Grimes 228df8bae1dSRodney W. Grimes /* 229df8bae1dSRodney W. Grimes * File attributes 230df8bae1dSRodney W. Grimes */ 231df8bae1dSRodney W. Grimes void 232988fa8efSJoerg Wunsch cd9660_defattr(isodir, inop, bp, ftype) 233df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 234df8bae1dSRodney W. Grimes struct iso_node *inop; 235df8bae1dSRodney W. Grimes struct buf *bp; 236988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 237df8bae1dSRodney W. Grimes { 238df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 239df8bae1dSRodney W. Grimes struct iso_mnt *imp; 240df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 241df8bae1dSRodney W. Grimes int off; 242df8bae1dSRodney W. Grimes 243988fa8efSJoerg Wunsch /* high sierra does not have timezone data, flag is one byte ahead */ 244988fa8efSJoerg Wunsch if (isonum_711(ftype == ISO_FTYPE_HIGH_SIERRA? 245988fa8efSJoerg Wunsch &isodir->date[6]: isodir->flags)&2) { 246df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFDIR; 247df8bae1dSRodney W. Grimes /* 248df8bae1dSRodney W. Grimes * If we return 2, fts() will assume there are no subdirectories 249df8bae1dSRodney W. Grimes * (just links for the path and .), so instead we return 1. 250df8bae1dSRodney W. Grimes */ 251df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 252df8bae1dSRodney W. Grimes } else { 253df8bae1dSRodney W. Grimes inop->inode.iso_mode = S_IFREG; 254df8bae1dSRodney W. Grimes inop->inode.iso_links = 1; 255df8bae1dSRodney W. Grimes } 256df8bae1dSRodney W. Grimes if (!bp 257df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) 258df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 259cec0f20cSPoul-Henning Kamp cd9660_blkatoff(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, 260996c772fSJohn Dyson &bp2); 261df8bae1dSRodney W. Grimes bp = bp2; 262df8bae1dSRodney W. Grimes } 263df8bae1dSRodney W. Grimes if (bp) { 264996c772fSJohn Dyson ap = (struct iso_extended_attributes *)bp->b_data; 265df8bae1dSRodney W. Grimes 266df8bae1dSRodney W. Grimes if (isonum_711(ap->version) == 1) { 267df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x40)) 268df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 6; 269df8bae1dSRodney W. Grimes if (!(ap->perm[0]&0x10)) 270df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 6; 271df8bae1dSRodney W. Grimes if (!(ap->perm[0]&4)) 272df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC >> 3; 273df8bae1dSRodney W. Grimes if (!(ap->perm[0]&1)) 274df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD >> 3; 275df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x40)) 276df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VEXEC; 277df8bae1dSRodney W. Grimes if (!(ap->perm[1]&0x10)) 278df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD; 279df8bae1dSRodney W. Grimes inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 280df8bae1dSRodney W. Grimes inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 281df8bae1dSRodney W. Grimes } else 282df8bae1dSRodney W. Grimes ap = NULL; 283df8bae1dSRodney W. Grimes } 284df8bae1dSRodney W. Grimes if (!ap) { 285df8bae1dSRodney W. Grimes inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 286df8bae1dSRodney W. Grimes inop->inode.iso_uid = (uid_t)0; 287df8bae1dSRodney W. Grimes inop->inode.iso_gid = (gid_t)0; 288df8bae1dSRodney W. Grimes } 289df8bae1dSRodney W. Grimes if (bp2) 290df8bae1dSRodney W. Grimes brelse(bp2); 291df8bae1dSRodney W. Grimes } 292df8bae1dSRodney W. Grimes 293df8bae1dSRodney W. Grimes /* 294df8bae1dSRodney W. Grimes * Time stamps 295df8bae1dSRodney W. Grimes */ 296df8bae1dSRodney W. Grimes void 297988fa8efSJoerg Wunsch cd9660_deftstamp(isodir,inop,bp,ftype) 298df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 299df8bae1dSRodney W. Grimes struct iso_node *inop; 300df8bae1dSRodney W. Grimes struct buf *bp; 301988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 302df8bae1dSRodney W. Grimes { 303df8bae1dSRodney W. Grimes struct buf *bp2 = NULL; 304df8bae1dSRodney W. Grimes struct iso_mnt *imp; 305df8bae1dSRodney W. Grimes struct iso_extended_attributes *ap = NULL; 306df8bae1dSRodney W. Grimes int off; 307df8bae1dSRodney W. Grimes 308df8bae1dSRodney W. Grimes if (!bp 309df8bae1dSRodney W. Grimes && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT) 310df8bae1dSRodney W. Grimes && (off = isonum_711(isodir->ext_attr_length))) { 311cec0f20cSPoul-Henning Kamp cd9660_blkatoff(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL, 312996c772fSJohn Dyson &bp2); 313df8bae1dSRodney W. Grimes bp = bp2; 314df8bae1dSRodney W. Grimes } 315df8bae1dSRodney W. Grimes if (bp) { 316996c772fSJohn Dyson ap = (struct iso_extended_attributes *)bp->b_data; 317df8bae1dSRodney W. Grimes 318596d40b9SBruce Evans if (ftype != ISO_FTYPE_HIGH_SIERRA 319596d40b9SBruce Evans && isonum_711(ap->version) == 1) { 320df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 321df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 322df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 323df8bae1dSRodney W. Grimes inop->inode.iso_ctime = inop->inode.iso_atime; 324df8bae1dSRodney W. Grimes if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 325df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 326df8bae1dSRodney W. Grimes } else 327df8bae1dSRodney W. Grimes ap = NULL; 328df8bae1dSRodney W. Grimes } 329df8bae1dSRodney W. Grimes if (!ap) { 330988fa8efSJoerg Wunsch cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime,ftype); 331df8bae1dSRodney W. Grimes inop->inode.iso_atime = inop->inode.iso_ctime; 332df8bae1dSRodney W. Grimes inop->inode.iso_mtime = inop->inode.iso_ctime; 333df8bae1dSRodney W. Grimes } 334df8bae1dSRodney W. Grimes if (bp2) 335df8bae1dSRodney W. Grimes brelse(bp2); 336df8bae1dSRodney W. Grimes } 337df8bae1dSRodney W. Grimes 338df8bae1dSRodney W. Grimes int 339988fa8efSJoerg Wunsch cd9660_tstamp_conv7(pi,pu,ftype) 340996c772fSJohn Dyson u_char *pi; 3411dbaf90cSBruce Evans struct timespec *pu; 342988fa8efSJoerg Wunsch enum ISO_FTYPE ftype; 343df8bae1dSRodney W. Grimes { 344df8bae1dSRodney W. Grimes int crtime, days; 345df8bae1dSRodney W. Grimes int y, m, d, hour, minute, second, tz; 346df8bae1dSRodney W. Grimes 347df8bae1dSRodney W. Grimes y = pi[0] + 1900; 348df8bae1dSRodney W. Grimes m = pi[1]; 349df8bae1dSRodney W. Grimes d = pi[2]; 350df8bae1dSRodney W. Grimes hour = pi[3]; 351df8bae1dSRodney W. Grimes minute = pi[4]; 352df8bae1dSRodney W. Grimes second = pi[5]; 353988fa8efSJoerg Wunsch if(ftype != ISO_FTYPE_HIGH_SIERRA) 354df8bae1dSRodney W. Grimes tz = pi[6]; 355988fa8efSJoerg Wunsch else 356988fa8efSJoerg Wunsch /* original high sierra misses timezone data */ 357988fa8efSJoerg Wunsch tz = 0; 358df8bae1dSRodney W. Grimes 359df8bae1dSRodney W. Grimes if (y < 1970) { 36095a1574eSNate Williams pu->tv_sec = 0; 36195a1574eSNate Williams pu->tv_nsec = 0; 362df8bae1dSRodney W. Grimes return 0; 363df8bae1dSRodney W. Grimes } else { 364df8bae1dSRodney W. Grimes #ifdef ORIGINAL 365df8bae1dSRodney W. Grimes /* computes day number relative to Sept. 19th,1989 */ 366df8bae1dSRodney W. Grimes /* don't even *THINK* about changing formula. It works! */ 367df8bae1dSRodney 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; 368df8bae1dSRodney W. Grimes #else 369df8bae1dSRodney W. Grimes /* 370df8bae1dSRodney W. Grimes * Changed :-) to make it relative to Jan. 1st, 1970 371df8bae1dSRodney W. Grimes * and to disambiguate negative division 372df8bae1dSRodney W. Grimes */ 373df8bae1dSRodney 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; 374df8bae1dSRodney W. Grimes #endif 375df8bae1dSRodney W. Grimes crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 376df8bae1dSRodney W. Grimes 377df8bae1dSRodney W. Grimes /* timezone offset is unreliable on some disks */ 378df8bae1dSRodney W. Grimes if (-48 <= tz && tz <= 52) 3792d091ecfSBruce Evans crtime -= tz * 15 * 60; 380df8bae1dSRodney W. Grimes } 38195a1574eSNate Williams pu->tv_sec = crtime; 38295a1574eSNate Williams pu->tv_nsec = 0; 383df8bae1dSRodney W. Grimes return 1; 384df8bae1dSRodney W. Grimes } 385df8bae1dSRodney W. Grimes 386996c772fSJohn Dyson static u_int 387df8bae1dSRodney W. Grimes cd9660_chars2ui(begin,len) 388996c772fSJohn Dyson u_char *begin; 389df8bae1dSRodney W. Grimes int len; 390df8bae1dSRodney W. Grimes { 391996c772fSJohn Dyson u_int rc; 392df8bae1dSRodney W. Grimes 393df8bae1dSRodney W. Grimes for (rc = 0; --len >= 0;) { 394df8bae1dSRodney W. Grimes rc *= 10; 395df8bae1dSRodney W. Grimes rc += *begin++ - '0'; 396df8bae1dSRodney W. Grimes } 397df8bae1dSRodney W. Grimes return rc; 398df8bae1dSRodney W. Grimes } 399df8bae1dSRodney W. Grimes 400df8bae1dSRodney W. Grimes int 401df8bae1dSRodney W. Grimes cd9660_tstamp_conv17(pi,pu) 402996c772fSJohn Dyson u_char *pi; 4031dbaf90cSBruce Evans struct timespec *pu; 404df8bae1dSRodney W. Grimes { 405996c772fSJohn Dyson u_char buf[7]; 406df8bae1dSRodney W. Grimes 407df8bae1dSRodney W. Grimes /* year:"0001"-"9999" -> -1900 */ 408df8bae1dSRodney W. Grimes buf[0] = cd9660_chars2ui(pi,4) - 1900; 409df8bae1dSRodney W. Grimes 410df8bae1dSRodney W. Grimes /* month: " 1"-"12" -> 1 - 12 */ 411df8bae1dSRodney W. Grimes buf[1] = cd9660_chars2ui(pi + 4,2); 412df8bae1dSRodney W. Grimes 413df8bae1dSRodney W. Grimes /* day: " 1"-"31" -> 1 - 31 */ 414df8bae1dSRodney W. Grimes buf[2] = cd9660_chars2ui(pi + 6,2); 415df8bae1dSRodney W. Grimes 416df8bae1dSRodney W. Grimes /* hour: " 0"-"23" -> 0 - 23 */ 417df8bae1dSRodney W. Grimes buf[3] = cd9660_chars2ui(pi + 8,2); 418df8bae1dSRodney W. Grimes 419df8bae1dSRodney W. Grimes /* minute:" 0"-"59" -> 0 - 59 */ 420df8bae1dSRodney W. Grimes buf[4] = cd9660_chars2ui(pi + 10,2); 421df8bae1dSRodney W. Grimes 422df8bae1dSRodney W. Grimes /* second:" 0"-"59" -> 0 - 59 */ 423df8bae1dSRodney W. Grimes buf[5] = cd9660_chars2ui(pi + 12,2); 424df8bae1dSRodney W. Grimes 425df8bae1dSRodney W. Grimes /* difference of GMT */ 426df8bae1dSRodney W. Grimes buf[6] = pi[16]; 427df8bae1dSRodney W. Grimes 428988fa8efSJoerg Wunsch return cd9660_tstamp_conv7(buf, pu, ISO_FTYPE_DEFAULT); 429df8bae1dSRodney W. Grimes } 430df8bae1dSRodney W. Grimes 431996c772fSJohn Dyson ino_t 432996c772fSJohn Dyson isodirino(isodir, imp) 433df8bae1dSRodney W. Grimes struct iso_directory_record *isodir; 434df8bae1dSRodney W. Grimes struct iso_mnt *imp; 435df8bae1dSRodney W. Grimes { 436996c772fSJohn Dyson ino_t ino; 437996c772fSJohn Dyson 438996c772fSJohn Dyson ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 439996c772fSJohn Dyson << imp->im_bshift; 440996c772fSJohn Dyson return (ino); 441df8bae1dSRodney W. Grimes } 442