165789Smckusick /*- 265789Smckusick * Copyright (c) 1982, 1986, 1989, 1994 365789Smckusick * The Regents of the University of California. All rights reserved. 465789Smckusick * 565789Smckusick * This code is derived from software contributed to Berkeley 665789Smckusick * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 765789Smckusick * Support code is derived from software contributed to Berkeley 865789Smckusick * by Atsushi Murai (amurai@spec.co.jp). 965789Smckusick * 1065789Smckusick * %sccs.include.redist.c% 1165789Smckusick * 12*67376Smkm * @(#)cd9660_node.c 8.3 (Berkeley) 06/14/94 1365789Smckusick */ 1465789Smckusick 1565789Smckusick #include <sys/param.h> 1665789Smckusick #include <sys/systm.h> 1765789Smckusick #include <sys/mount.h> 1865789Smckusick #include <sys/proc.h> 1965789Smckusick #include <sys/file.h> 2065789Smckusick #include <sys/buf.h> 2165789Smckusick #include <sys/vnode.h> 2265789Smckusick #include <sys/kernel.h> 2365789Smckusick #include <sys/malloc.h> 2465789Smckusick #include <sys/stat.h> 2565789Smckusick 2665789Smckusick #include <isofs/cd9660/iso.h> 2765855Smckusick #include <isofs/cd9660/cd9660_node.h> 2865789Smckusick #include <isofs/cd9660/iso_rrip.h> 2965789Smckusick 3065789Smckusick #define INOHSZ 512 3165789Smckusick #if ((INOHSZ&(INOHSZ-1)) == 0) 3265789Smckusick #define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1)) 3365789Smckusick #else 3465789Smckusick #define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ) 3565789Smckusick #endif 3665789Smckusick 3765789Smckusick union iso_ihead { 3865789Smckusick union iso_ihead *ih_head[2]; 3965789Smckusick struct iso_node *ih_chain[2]; 4065789Smckusick } iso_ihead[INOHSZ]; 4165789Smckusick 4265789Smckusick #ifdef ISODEVMAP 4365789Smckusick #define DNOHSZ 64 4465789Smckusick #if ((DNOHSZ&(DNOHSZ-1)) == 0) 4565789Smckusick #define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1)) 4665789Smckusick #else 4765789Smckusick #define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ) 4865789Smckusick #endif 4965789Smckusick 5065789Smckusick union iso_dhead { 5165789Smckusick union iso_dhead *dh_head[2]; 5265789Smckusick struct iso_dnode *dh_chain[2]; 5365789Smckusick } iso_dhead[DNOHSZ]; 5465789Smckusick #endif 5565789Smckusick 5665789Smckusick int prtactive; /* 1 => print out reclaim of active vnodes */ 5765789Smckusick 5865789Smckusick /* 5965789Smckusick * Initialize hash links for inodes and dnodes. 6065789Smckusick */ 6165855Smckusick cd9660_init() 6265789Smckusick { 6365789Smckusick register int i; 6465789Smckusick register union iso_ihead *ih = iso_ihead; 6565789Smckusick #ifdef ISODEVMAP 6665789Smckusick register union iso_dhead *dh = iso_dhead; 6765789Smckusick #endif 6865789Smckusick 6965789Smckusick for (i = INOHSZ; --i >= 0; ih++) { 7065789Smckusick ih->ih_head[0] = ih; 7165789Smckusick ih->ih_head[1] = ih; 7265789Smckusick } 7365789Smckusick #ifdef ISODEVMAP 7465789Smckusick for (i = DNOHSZ; --i >= 0; dh++) { 7565789Smckusick dh->dh_head[0] = dh; 7665789Smckusick dh->dh_head[1] = dh; 7765789Smckusick } 7865789Smckusick #endif 7965789Smckusick } 8065789Smckusick 8165789Smckusick #ifdef ISODEVMAP 8265789Smckusick /* 8365789Smckusick * Enter a new node into the device hash list 8465789Smckusick */ 8565789Smckusick struct iso_dnode * 8665789Smckusick iso_dmap(dev,ino,create) 8765789Smckusick dev_t dev; 8865789Smckusick ino_t ino; 8965789Smckusick int create; 9065789Smckusick { 9165789Smckusick struct iso_dnode *dp; 9265789Smckusick union iso_dhead *dh; 9365789Smckusick 9465789Smckusick dh = &iso_dhead[DNOHASH(dev, ino)]; 9565789Smckusick for (dp = dh->dh_chain[0]; 9665789Smckusick dp != (struct iso_dnode *)dh; 9765789Smckusick dp = dp->d_forw) 9865789Smckusick if (ino == dp->i_number && dev == dp->i_dev) 9965789Smckusick return dp; 10065789Smckusick 10165789Smckusick if (!create) 10265789Smckusick return (struct iso_dnode *)0; 10365789Smckusick 10465789Smckusick MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK); 10565789Smckusick dp->i_dev = dev; 10665789Smckusick dp->i_number = ino; 10765789Smckusick insque(dp,dh); 10865789Smckusick 10965789Smckusick return dp; 11065789Smckusick } 11165789Smckusick 11265789Smckusick void 11365789Smckusick iso_dunmap(dev) 11465789Smckusick dev_t dev; 11565789Smckusick { 11665789Smckusick struct iso_dnode *dp, *dq; 11765789Smckusick union iso_dhead *dh; 11865789Smckusick 11965789Smckusick for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) { 12065789Smckusick for (dp = dh->dh_chain[0]; 12165789Smckusick dp != (struct iso_dnode *)dh; 12265789Smckusick dp = dq) { 12365789Smckusick dq = dp->d_forw; 12465789Smckusick if (dev == dp->i_dev) { 12565789Smckusick remque(dp); 12665789Smckusick FREE(dp,M_CACHE); 12765789Smckusick } 12865789Smckusick } 12965789Smckusick } 13065789Smckusick } 13165789Smckusick #endif 13265789Smckusick 13365789Smckusick /* 13465789Smckusick * Look up a ISOFS dinode number to find its incore vnode. 13565789Smckusick * If it is not in core, read it in from the specified device. 13665789Smckusick * If it is in core, wait for the lock bit to clear, then 13765789Smckusick * return the inode locked. Detection and handling of mount 13865789Smckusick * points must be done by the calling routine. 13965789Smckusick */ 14065789Smckusick iso_iget(xp, ino, relocated, ipp, isodir) 14165789Smckusick struct iso_node *xp; 14265789Smckusick ino_t ino; 14365789Smckusick struct iso_node **ipp; 14465789Smckusick struct iso_directory_record *isodir; 14565789Smckusick { 14665789Smckusick dev_t dev = xp->i_dev; 14765789Smckusick struct mount *mntp = ITOV(xp)->v_mount; 14865789Smckusick register struct iso_node *ip, *iq; 14965789Smckusick register struct vnode *vp; 15065789Smckusick register struct iso_dnode *dp; 15165789Smckusick struct vnode *nvp; 15265789Smckusick struct buf *bp = NULL, *bp2 = NULL; 15365789Smckusick union iso_ihead *ih; 15465789Smckusick union iso_dhead *dh; 15565789Smckusick int i, error, result; 15665789Smckusick struct iso_mnt *imp; 15765789Smckusick ino_t defino; 15865789Smckusick 15965789Smckusick ih = &iso_ihead[INOHASH(dev, ino)]; 16065789Smckusick loop: 16165789Smckusick for (ip = ih->ih_chain[0]; 16265789Smckusick ip != (struct iso_node *)ih; 16365789Smckusick ip = ip->i_forw) { 16465789Smckusick if (ino != ip->i_number || dev != ip->i_dev) 16565789Smckusick continue; 16665789Smckusick if ((ip->i_flag&ILOCKED) != 0) { 16765789Smckusick ip->i_flag |= IWANT; 16865789Smckusick sleep((caddr_t)ip, PINOD); 16965789Smckusick goto loop; 17065789Smckusick } 17165789Smckusick if (vget(ITOV(ip), 1)) 17265789Smckusick goto loop; 17365789Smckusick *ipp = ip; 17465789Smckusick return 0; 17565789Smckusick } 17665789Smckusick /* 17765789Smckusick * Allocate a new vnode/iso_node. 17865789Smckusick */ 17965855Smckusick if (error = getnewvnode(VT_ISOFS, mntp, cd9660_vnodeop_p, &nvp)) { 18065789Smckusick *ipp = 0; 18165789Smckusick return error; 18265789Smckusick } 18365789Smckusick MALLOC(ip, struct iso_node *, sizeof(struct iso_node), 18465789Smckusick M_ISOFSNODE, M_WAITOK); 18565789Smckusick bzero((caddr_t)ip, sizeof(struct iso_node)); 18665789Smckusick nvp->v_data = ip; 18765789Smckusick ip->i_vnode = nvp; 18865789Smckusick ip->i_flag = 0; 18965789Smckusick ip->i_devvp = 0; 19065789Smckusick ip->i_diroff = 0; 19165789Smckusick ip->i_lockf = 0; 19265789Smckusick 19365789Smckusick /* 19465789Smckusick * Put it onto its hash chain and lock it so that other requests for 19565789Smckusick * this inode will block if they arrive while we are sleeping waiting 19665789Smckusick * for old data structures to be purged or for the contents of the 19765789Smckusick * disk portion of this inode to be read. 19865789Smckusick */ 19965789Smckusick ip->i_dev = dev; 20065789Smckusick ip->i_number = ino; 20165789Smckusick insque(ip, ih); 20265789Smckusick ISO_ILOCK(ip); 20365789Smckusick 20465789Smckusick imp = VFSTOISOFS (mntp); 20565789Smckusick ip->i_mnt = imp; 20665789Smckusick ip->i_devvp = imp->im_devvp; 20765789Smckusick VREF(ip->i_devvp); 20865789Smckusick 20965789Smckusick if (relocated) { 21065789Smckusick /* 21165789Smckusick * On relocated directories we must 21265789Smckusick * read the `.' entry out of a dir. 21365789Smckusick */ 21465789Smckusick ip->iso_start = ino >> imp->im_bshift; 21565789Smckusick if (error = iso_blkatoff(ip,0,&bp)) { 21665789Smckusick vrele(ip->i_devvp); 21765789Smckusick remque(ip); 21865789Smckusick ip->i_forw = ip; 21965789Smckusick ip->i_back = ip; 22065789Smckusick iso_iput(ip); 22165789Smckusick *ipp = 0; 22265789Smckusick return error; 22365789Smckusick } 22465789Smckusick isodir = (struct iso_directory_record *)bp->b_un.b_addr; 22565789Smckusick } 22665789Smckusick 22765789Smckusick ip->iso_extent = isonum_733(isodir->extent); 22865789Smckusick ip->i_size = isonum_733(isodir->size); 22965789Smckusick ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 23065789Smckusick 23165789Smckusick vp = ITOV(ip); 23265789Smckusick 23365789Smckusick /* 23465789Smckusick * Setup time stamp, attribute 23565789Smckusick */ 23665789Smckusick vp->v_type = VNON; 23765789Smckusick switch (imp->iso_ftype) { 23865789Smckusick default: /* ISO_FTYPE_9660 */ 23965789Smckusick if ((imp->im_flags&ISOFSMNT_EXTATT) 24065789Smckusick && isonum_711(isodir->ext_attr_length)) 24165789Smckusick iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length), 24265789Smckusick &bp2); 24365855Smckusick cd9660_defattr(isodir,ip,bp2 ); 24465855Smckusick cd9660_deftstamp(isodir,ip,bp2 ); 24565789Smckusick break; 24665789Smckusick case ISO_FTYPE_RRIP: 24765855Smckusick result = cd9660_rrip_analyze(isodir,ip,imp); 24865789Smckusick break; 24965789Smckusick } 25065789Smckusick if (bp2) 25165789Smckusick brelse(bp2); 25265789Smckusick if (bp) 25365789Smckusick brelse(bp); 25465789Smckusick 25565789Smckusick /* 25665789Smckusick * Initialize the associated vnode 25765789Smckusick */ 25865789Smckusick vp->v_type = IFTOVT(ip->inode.iso_mode); 25965789Smckusick 26065789Smckusick if ( vp->v_type == VFIFO ) { 26165789Smckusick #ifdef FIFO 26265855Smckusick extern int (**cd9660_fifoop_p)(); 26365855Smckusick vp->v_op = cd9660_fifoop_p; 26465789Smckusick #else 26565789Smckusick iso_iput(ip); 26665789Smckusick *ipp = 0; 26765789Smckusick return EOPNOTSUPP; 26865789Smckusick #endif /* FIFO */ 26965789Smckusick } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) { 27065855Smckusick extern int (**cd9660_specop_p)(); 27165789Smckusick 27265789Smckusick /* 27365789Smckusick * if device, look at device number table for translation 27465789Smckusick */ 27565789Smckusick #ifdef ISODEVMAP 27665789Smckusick if (dp = iso_dmap(dev,ino,0)) 27765789Smckusick ip->inode.iso_rdev = dp->d_dev; 27865789Smckusick #endif 27965855Smckusick vp->v_op = cd9660_specop_p; 28065789Smckusick if (nvp = checkalias(vp, ip->inode.iso_rdev, mntp)) { 28165789Smckusick /* 28265789Smckusick * Reinitialize aliased inode. 28365789Smckusick */ 28465789Smckusick vp = nvp; 28565789Smckusick iq = VTOI(vp); 28665789Smckusick iq->i_vnode = vp; 28765789Smckusick iq->i_flag = 0; 28865789Smckusick ISO_ILOCK(iq); 28965789Smckusick iq->i_dev = dev; 29065789Smckusick iq->i_number = ino; 29165789Smckusick iq->i_mnt = ip->i_mnt; 29265789Smckusick bcopy(&ip->iso_extent,&iq->iso_extent, 29365789Smckusick (char *)(ip + 1) - (char *)&ip->iso_extent); 29465789Smckusick insque(iq, ih); 29565789Smckusick /* 29665789Smckusick * Discard unneeded vnode 29765789Smckusick * (This introduces the need of INACTIVE modification) 29865789Smckusick */ 29965789Smckusick ip->inode.iso_mode = 0; 30065789Smckusick iso_iput(ip); 30165789Smckusick ip = iq; 30265789Smckusick } 30365789Smckusick } 30465789Smckusick 30565789Smckusick if (ip->iso_extent == imp->root_extent) 30665789Smckusick vp->v_flag |= VROOT; 30765789Smckusick 30865789Smckusick *ipp = ip; 30965789Smckusick return 0; 31065789Smckusick } 31165789Smckusick 31265789Smckusick /* 31365789Smckusick * Unlock and decrement the reference count of an inode structure. 31465789Smckusick */ 31565789Smckusick iso_iput(ip) 31665789Smckusick register struct iso_node *ip; 31765789Smckusick { 31865789Smckusick 31965789Smckusick if ((ip->i_flag & ILOCKED) == 0) 32065789Smckusick panic("iso_iput"); 32165789Smckusick ISO_IUNLOCK(ip); 32265789Smckusick vrele(ITOV(ip)); 32365789Smckusick } 32465789Smckusick 32565789Smckusick /* 32665789Smckusick * Last reference to an inode, write the inode out and if necessary, 32765789Smckusick * truncate and deallocate the file. 32865789Smckusick */ 32965789Smckusick int 33065855Smckusick cd9660_inactive(ap) 33165789Smckusick struct vop_inactive_args /* { 33265789Smckusick struct vnode *a_vp; 33365789Smckusick } */ *ap; 33465789Smckusick { 33565789Smckusick struct vnode *vp = ap->a_vp; 33665789Smckusick register struct iso_node *ip = VTOI(vp); 33765789Smckusick int mode, error = 0; 33865789Smckusick 33965789Smckusick if (prtactive && vp->v_usecount != 0) 34065855Smckusick vprint("cd9660_inactive: pushing active", vp); 34165789Smckusick 34265789Smckusick ip->i_flag = 0; 34365789Smckusick /* 34465789Smckusick * If we are done with the inode, reclaim it 34565789Smckusick * so that it can be reused immediately. 34665789Smckusick */ 34765789Smckusick if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) 34865789Smckusick vgone(vp); 34965789Smckusick return error; 35065789Smckusick } 35165789Smckusick 35265789Smckusick /* 35365789Smckusick * Reclaim an inode so that it can be used for other purposes. 35465789Smckusick */ 35565789Smckusick int 35665855Smckusick cd9660_reclaim(ap) 35765789Smckusick struct vop_reclaim_args /* { 35865789Smckusick struct vnode *a_vp; 35965789Smckusick } */ *ap; 36065789Smckusick { 36165789Smckusick register struct vnode *vp = ap->a_vp; 36265789Smckusick register struct iso_node *ip = VTOI(vp); 36365789Smckusick int i; 36465789Smckusick 36565789Smckusick if (prtactive && vp->v_usecount != 0) 36665855Smckusick vprint("cd9660_reclaim: pushing active", vp); 36765789Smckusick /* 36865789Smckusick * Remove the inode from its hash chain. 36965789Smckusick */ 37065789Smckusick remque(ip); 37165789Smckusick ip->i_forw = ip; 37265789Smckusick ip->i_back = ip; 37365789Smckusick /* 37465789Smckusick * Purge old data structures associated with the inode. 37565789Smckusick */ 37665789Smckusick cache_purge(vp); 37765789Smckusick if (ip->i_devvp) { 37865789Smckusick vrele(ip->i_devvp); 37965789Smckusick ip->i_devvp = 0; 38065789Smckusick } 38165789Smckusick FREE(vp->v_data, M_ISOFSNODE); 38265789Smckusick vp->v_data = NULL; 38365789Smckusick return 0; 38465789Smckusick } 38565789Smckusick 38665789Smckusick /* 38765789Smckusick * Lock an inode. If its already locked, set the WANT bit and sleep. 38865789Smckusick */ 38965789Smckusick iso_ilock(ip) 39065789Smckusick register struct iso_node *ip; 39165789Smckusick { 39265789Smckusick 39365789Smckusick while (ip->i_flag & ILOCKED) { 39465789Smckusick ip->i_flag |= IWANT; 39565789Smckusick if (ip->i_spare0 == curproc->p_pid) 39665789Smckusick panic("locking against myself"); 39765789Smckusick ip->i_spare1 = curproc->p_pid; 39865789Smckusick (void) sleep((caddr_t)ip, PINOD); 39965789Smckusick } 40065789Smckusick ip->i_spare1 = 0; 40165789Smckusick ip->i_spare0 = curproc->p_pid; 40265789Smckusick ip->i_flag |= ILOCKED; 40365789Smckusick } 40465789Smckusick 40565789Smckusick /* 40665789Smckusick * Unlock an inode. If WANT bit is on, wakeup. 40765789Smckusick */ 40865789Smckusick iso_iunlock(ip) 40965789Smckusick register struct iso_node *ip; 41065789Smckusick { 41165789Smckusick 41265789Smckusick if ((ip->i_flag & ILOCKED) == 0) 41365789Smckusick vprint("iso_iunlock: unlocked inode", ITOV(ip)); 41465789Smckusick ip->i_spare0 = 0; 41565789Smckusick ip->i_flag &= ~ILOCKED; 41665789Smckusick if (ip->i_flag&IWANT) { 41765789Smckusick ip->i_flag &= ~IWANT; 41865789Smckusick wakeup((caddr_t)ip); 41965789Smckusick } 42065789Smckusick } 42165789Smckusick 42265789Smckusick /* 42365789Smckusick * File attributes 42465789Smckusick */ 42565789Smckusick void 42665855Smckusick cd9660_defattr(isodir,inop,bp) 42765789Smckusick struct iso_directory_record *isodir; 42865789Smckusick struct iso_node *inop; 42965789Smckusick struct buf *bp; 43065789Smckusick { 43165789Smckusick struct buf *bp2 = NULL; 43265789Smckusick struct iso_mnt *imp; 43365789Smckusick struct iso_extended_attributes *ap = NULL; 43465789Smckusick int off; 43565789Smckusick 43665789Smckusick if (isonum_711(isodir->flags)&2) { 43765789Smckusick inop->inode.iso_mode = S_IFDIR; 43865789Smckusick /* 43965789Smckusick * If we return 2, fts() will assume there are no subdirectories 44065789Smckusick * (just links for the path and .), so instead we return 1. 44165789Smckusick */ 44265789Smckusick inop->inode.iso_links = 1; 44365789Smckusick } else { 44465789Smckusick inop->inode.iso_mode = S_IFREG; 44565789Smckusick inop->inode.iso_links = 1; 44665789Smckusick } 44765789Smckusick if (!bp 44865789Smckusick && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 44965789Smckusick && (off = isonum_711(isodir->ext_attr_length))) { 45065789Smckusick iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 45165789Smckusick bp = bp2; 45265789Smckusick } 45365789Smckusick if (bp) { 45465789Smckusick ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 45565789Smckusick 45665789Smckusick if (isonum_711(ap->version) == 1) { 45765789Smckusick if (!(ap->perm[0]&0x40)) 45865789Smckusick inop->inode.iso_mode |= VEXEC >> 6; 45965789Smckusick if (!(ap->perm[0]&0x10)) 46065789Smckusick inop->inode.iso_mode |= VREAD >> 6; 46165789Smckusick if (!(ap->perm[0]&4)) 46265789Smckusick inop->inode.iso_mode |= VEXEC >> 3; 46365789Smckusick if (!(ap->perm[0]&1)) 46465789Smckusick inop->inode.iso_mode |= VREAD >> 3; 46565789Smckusick if (!(ap->perm[1]&0x40)) 46665789Smckusick inop->inode.iso_mode |= VEXEC; 46765789Smckusick if (!(ap->perm[1]&0x10)) 46865789Smckusick inop->inode.iso_mode |= VREAD; 46965789Smckusick inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 47065789Smckusick inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 47165789Smckusick } else 47265789Smckusick ap = NULL; 47365789Smckusick } 47465789Smckusick if (!ap) { 47565789Smckusick inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 47665789Smckusick inop->inode.iso_uid = (uid_t)0; 47765789Smckusick inop->inode.iso_gid = (gid_t)0; 47865789Smckusick } 47965789Smckusick if (bp2) 48065789Smckusick brelse(bp2); 48165789Smckusick } 48265789Smckusick 48365789Smckusick /* 48465789Smckusick * Time stamps 48565789Smckusick */ 48665789Smckusick void 48765855Smckusick cd9660_deftstamp(isodir,inop,bp) 48865789Smckusick struct iso_directory_record *isodir; 48965789Smckusick struct iso_node *inop; 49065789Smckusick struct buf *bp; 49165789Smckusick { 49265789Smckusick struct buf *bp2 = NULL; 49365789Smckusick struct iso_mnt *imp; 49465789Smckusick struct iso_extended_attributes *ap = NULL; 49565789Smckusick int off; 49665789Smckusick 49765789Smckusick if (!bp 49865789Smckusick && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 49965789Smckusick && (off = isonum_711(isodir->ext_attr_length))) { 50065789Smckusick iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 50165789Smckusick bp = bp2; 50265789Smckusick } 50365789Smckusick if (bp) { 50465789Smckusick ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 50565789Smckusick 50665789Smckusick if (isonum_711(ap->version) == 1) { 50765855Smckusick if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 50865855Smckusick cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 50965855Smckusick if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 51065789Smckusick inop->inode.iso_ctime = inop->inode.iso_atime; 51165855Smckusick if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 51265789Smckusick inop->inode.iso_mtime = inop->inode.iso_ctime; 51365789Smckusick } else 51465789Smckusick ap = NULL; 51565789Smckusick } 51665789Smckusick if (!ap) { 51765855Smckusick cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime); 51865789Smckusick inop->inode.iso_atime = inop->inode.iso_ctime; 51965789Smckusick inop->inode.iso_mtime = inop->inode.iso_ctime; 52065789Smckusick } 52165789Smckusick if (bp2) 52265789Smckusick brelse(bp2); 52365789Smckusick } 52465789Smckusick 52565789Smckusick int 52665855Smckusick cd9660_tstamp_conv7(pi,pu) 52765789Smckusick char *pi; 52865789Smckusick struct timeval *pu; 52965789Smckusick { 53065789Smckusick int i; 53165789Smckusick int crtime, days; 53265789Smckusick int y, m, d, hour, minute, second, tz; 53365789Smckusick 53465789Smckusick y = pi[0] + 1900; 53565789Smckusick m = pi[1]; 53665789Smckusick d = pi[2]; 53765789Smckusick hour = pi[3]; 53865789Smckusick minute = pi[4]; 53965789Smckusick second = pi[5]; 54065789Smckusick tz = pi[6]; 54165789Smckusick 54265789Smckusick if (y < 1970) { 54365789Smckusick pu->tv_sec = 0; 54465789Smckusick pu->tv_usec = 0; 54565789Smckusick return 0; 54665789Smckusick } else { 54765789Smckusick #ifdef ORIGINAL 54865789Smckusick /* computes day number relative to Sept. 19th,1989 */ 54965789Smckusick /* don't even *THINK* about changing formula. It works! */ 55065789Smckusick days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; 55165789Smckusick #else 55265789Smckusick /* 55365789Smckusick * Changed :-) to make it relative to Jan. 1st, 1970 55465789Smckusick * and to disambiguate negative division 55565789Smckusick */ 55665789Smckusick days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; 55765789Smckusick #endif 55865789Smckusick crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 55965789Smckusick 56065789Smckusick /* timezone offset is unreliable on some disks */ 56165789Smckusick if (-48 <= tz && tz <= 52) 562*67376Smkm crtime -= tz * 15 * 60; 56365789Smckusick } 56465789Smckusick pu->tv_sec = crtime; 56565789Smckusick pu->tv_usec = 0; 56665789Smckusick return 1; 56765789Smckusick } 56865789Smckusick 56965789Smckusick static unsigned 57065855Smckusick cd9660_chars2ui(begin,len) 57165789Smckusick unsigned char *begin; 57265789Smckusick int len; 57365789Smckusick { 57465789Smckusick unsigned rc; 57565789Smckusick 57665789Smckusick for (rc = 0; --len >= 0;) { 57765789Smckusick rc *= 10; 57865789Smckusick rc += *begin++ - '0'; 57965789Smckusick } 58065789Smckusick return rc; 58165789Smckusick } 58265789Smckusick 58365789Smckusick int 58465855Smckusick cd9660_tstamp_conv17(pi,pu) 58565789Smckusick unsigned char *pi; 58665789Smckusick struct timeval *pu; 58765789Smckusick { 58865789Smckusick unsigned char buf[7]; 58965789Smckusick 59065789Smckusick /* year:"0001"-"9999" -> -1900 */ 59165855Smckusick buf[0] = cd9660_chars2ui(pi,4) - 1900; 59265789Smckusick 59365789Smckusick /* month: " 1"-"12" -> 1 - 12 */ 59465855Smckusick buf[1] = cd9660_chars2ui(pi + 4,2); 59565789Smckusick 59665789Smckusick /* day: " 1"-"31" -> 1 - 31 */ 59765855Smckusick buf[2] = cd9660_chars2ui(pi + 6,2); 59865789Smckusick 59965789Smckusick /* hour: " 0"-"23" -> 0 - 23 */ 60065855Smckusick buf[3] = cd9660_chars2ui(pi + 8,2); 60165789Smckusick 60265789Smckusick /* minute:" 0"-"59" -> 0 - 59 */ 60365855Smckusick buf[4] = cd9660_chars2ui(pi + 10,2); 60465789Smckusick 60565789Smckusick /* second:" 0"-"59" -> 0 - 59 */ 60665855Smckusick buf[5] = cd9660_chars2ui(pi + 12,2); 60765789Smckusick 60865789Smckusick /* difference of GMT */ 60965789Smckusick buf[6] = pi[16]; 61065789Smckusick 61165855Smckusick return cd9660_tstamp_conv7(buf,pu); 61265789Smckusick } 61365789Smckusick 61465789Smckusick void 61565789Smckusick isodirino(inump,isodir,imp) 61665789Smckusick ino_t *inump; 61765789Smckusick struct iso_directory_record *isodir; 61865789Smckusick struct iso_mnt *imp; 61965789Smckusick { 62065789Smckusick *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 62165789Smckusick * imp->logical_block_size; 62265789Smckusick } 623