1*65789Smckusick /*- 2*65789Smckusick * Copyright (c) 1982, 1986, 1989, 1994 3*65789Smckusick * The Regents of the University of California. All rights reserved. 4*65789Smckusick * 5*65789Smckusick * This code is derived from software contributed to Berkeley 6*65789Smckusick * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7*65789Smckusick * Support code is derived from software contributed to Berkeley 8*65789Smckusick * by Atsushi Murai (amurai@spec.co.jp). 9*65789Smckusick * 10*65789Smckusick * %sccs.include.redist.c% 11*65789Smckusick * 12*65789Smckusick * @(#)cd9660_node.c 8.1 (Berkeley) 01/21/94 13*65789Smckusick */ 14*65789Smckusick 15*65789Smckusick #include <sys/param.h> 16*65789Smckusick #include <sys/systm.h> 17*65789Smckusick #include <sys/mount.h> 18*65789Smckusick #include <sys/proc.h> 19*65789Smckusick #include <sys/file.h> 20*65789Smckusick #include <sys/buf.h> 21*65789Smckusick #include <sys/vnode.h> 22*65789Smckusick #include <sys/kernel.h> 23*65789Smckusick #include <sys/malloc.h> 24*65789Smckusick #include <sys/stat.h> 25*65789Smckusick 26*65789Smckusick #include <isofs/cd9660/iso.h> 27*65789Smckusick #include <isofs/cd9660/isofs_node.h> 28*65789Smckusick #include <isofs/cd9660/iso_rrip.h> 29*65789Smckusick 30*65789Smckusick #define INOHSZ 512 31*65789Smckusick #if ((INOHSZ&(INOHSZ-1)) == 0) 32*65789Smckusick #define INOHASH(dev,ino) (((dev)+((ino)>>12))&(INOHSZ-1)) 33*65789Smckusick #else 34*65789Smckusick #define INOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%INOHSZ) 35*65789Smckusick #endif 36*65789Smckusick 37*65789Smckusick union iso_ihead { 38*65789Smckusick union iso_ihead *ih_head[2]; 39*65789Smckusick struct iso_node *ih_chain[2]; 40*65789Smckusick } iso_ihead[INOHSZ]; 41*65789Smckusick 42*65789Smckusick #ifdef ISODEVMAP 43*65789Smckusick #define DNOHSZ 64 44*65789Smckusick #if ((DNOHSZ&(DNOHSZ-1)) == 0) 45*65789Smckusick #define DNOHASH(dev,ino) (((dev)+((ino)>>12))&(DNOHSZ-1)) 46*65789Smckusick #else 47*65789Smckusick #define DNOHASH(dev,ino) (((unsigned)((dev)+((ino)>>12)))%DNOHSZ) 48*65789Smckusick #endif 49*65789Smckusick 50*65789Smckusick union iso_dhead { 51*65789Smckusick union iso_dhead *dh_head[2]; 52*65789Smckusick struct iso_dnode *dh_chain[2]; 53*65789Smckusick } iso_dhead[DNOHSZ]; 54*65789Smckusick #endif 55*65789Smckusick 56*65789Smckusick int prtactive; /* 1 => print out reclaim of active vnodes */ 57*65789Smckusick 58*65789Smckusick /* 59*65789Smckusick * Initialize hash links for inodes and dnodes. 60*65789Smckusick */ 61*65789Smckusick isofs_init() 62*65789Smckusick { 63*65789Smckusick register int i; 64*65789Smckusick register union iso_ihead *ih = iso_ihead; 65*65789Smckusick #ifdef ISODEVMAP 66*65789Smckusick register union iso_dhead *dh = iso_dhead; 67*65789Smckusick #endif 68*65789Smckusick 69*65789Smckusick for (i = INOHSZ; --i >= 0; ih++) { 70*65789Smckusick ih->ih_head[0] = ih; 71*65789Smckusick ih->ih_head[1] = ih; 72*65789Smckusick } 73*65789Smckusick #ifdef ISODEVMAP 74*65789Smckusick for (i = DNOHSZ; --i >= 0; dh++) { 75*65789Smckusick dh->dh_head[0] = dh; 76*65789Smckusick dh->dh_head[1] = dh; 77*65789Smckusick } 78*65789Smckusick #endif 79*65789Smckusick } 80*65789Smckusick 81*65789Smckusick #ifdef ISODEVMAP 82*65789Smckusick /* 83*65789Smckusick * Enter a new node into the device hash list 84*65789Smckusick */ 85*65789Smckusick struct iso_dnode * 86*65789Smckusick iso_dmap(dev,ino,create) 87*65789Smckusick dev_t dev; 88*65789Smckusick ino_t ino; 89*65789Smckusick int create; 90*65789Smckusick { 91*65789Smckusick struct iso_dnode *dp; 92*65789Smckusick union iso_dhead *dh; 93*65789Smckusick 94*65789Smckusick dh = &iso_dhead[DNOHASH(dev, ino)]; 95*65789Smckusick for (dp = dh->dh_chain[0]; 96*65789Smckusick dp != (struct iso_dnode *)dh; 97*65789Smckusick dp = dp->d_forw) 98*65789Smckusick if (ino == dp->i_number && dev == dp->i_dev) 99*65789Smckusick return dp; 100*65789Smckusick 101*65789Smckusick if (!create) 102*65789Smckusick return (struct iso_dnode *)0; 103*65789Smckusick 104*65789Smckusick MALLOC(dp,struct iso_dnode *,sizeof(struct iso_dnode),M_CACHE,M_WAITOK); 105*65789Smckusick dp->i_dev = dev; 106*65789Smckusick dp->i_number = ino; 107*65789Smckusick insque(dp,dh); 108*65789Smckusick 109*65789Smckusick return dp; 110*65789Smckusick } 111*65789Smckusick 112*65789Smckusick void 113*65789Smckusick iso_dunmap(dev) 114*65789Smckusick dev_t dev; 115*65789Smckusick { 116*65789Smckusick struct iso_dnode *dp, *dq; 117*65789Smckusick union iso_dhead *dh; 118*65789Smckusick 119*65789Smckusick for (dh = iso_dhead; dh < iso_dhead + DNOHSZ; dh++) { 120*65789Smckusick for (dp = dh->dh_chain[0]; 121*65789Smckusick dp != (struct iso_dnode *)dh; 122*65789Smckusick dp = dq) { 123*65789Smckusick dq = dp->d_forw; 124*65789Smckusick if (dev == dp->i_dev) { 125*65789Smckusick remque(dp); 126*65789Smckusick FREE(dp,M_CACHE); 127*65789Smckusick } 128*65789Smckusick } 129*65789Smckusick } 130*65789Smckusick } 131*65789Smckusick #endif 132*65789Smckusick 133*65789Smckusick /* 134*65789Smckusick * Look up a ISOFS dinode number to find its incore vnode. 135*65789Smckusick * If it is not in core, read it in from the specified device. 136*65789Smckusick * If it is in core, wait for the lock bit to clear, then 137*65789Smckusick * return the inode locked. Detection and handling of mount 138*65789Smckusick * points must be done by the calling routine. 139*65789Smckusick */ 140*65789Smckusick iso_iget(xp, ino, relocated, ipp, isodir) 141*65789Smckusick struct iso_node *xp; 142*65789Smckusick ino_t ino; 143*65789Smckusick struct iso_node **ipp; 144*65789Smckusick struct iso_directory_record *isodir; 145*65789Smckusick { 146*65789Smckusick dev_t dev = xp->i_dev; 147*65789Smckusick struct mount *mntp = ITOV(xp)->v_mount; 148*65789Smckusick register struct iso_node *ip, *iq; 149*65789Smckusick register struct vnode *vp; 150*65789Smckusick register struct iso_dnode *dp; 151*65789Smckusick struct vnode *nvp; 152*65789Smckusick struct buf *bp = NULL, *bp2 = NULL; 153*65789Smckusick union iso_ihead *ih; 154*65789Smckusick union iso_dhead *dh; 155*65789Smckusick int i, error, result; 156*65789Smckusick struct iso_mnt *imp; 157*65789Smckusick ino_t defino; 158*65789Smckusick 159*65789Smckusick ih = &iso_ihead[INOHASH(dev, ino)]; 160*65789Smckusick loop: 161*65789Smckusick for (ip = ih->ih_chain[0]; 162*65789Smckusick ip != (struct iso_node *)ih; 163*65789Smckusick ip = ip->i_forw) { 164*65789Smckusick if (ino != ip->i_number || dev != ip->i_dev) 165*65789Smckusick continue; 166*65789Smckusick if ((ip->i_flag&ILOCKED) != 0) { 167*65789Smckusick ip->i_flag |= IWANT; 168*65789Smckusick sleep((caddr_t)ip, PINOD); 169*65789Smckusick goto loop; 170*65789Smckusick } 171*65789Smckusick if (vget(ITOV(ip), 1)) 172*65789Smckusick goto loop; 173*65789Smckusick *ipp = ip; 174*65789Smckusick return 0; 175*65789Smckusick } 176*65789Smckusick /* 177*65789Smckusick * Allocate a new vnode/iso_node. 178*65789Smckusick */ 179*65789Smckusick if (error = getnewvnode(VT_ISOFS, mntp, isofs_vnodeop_p, &nvp)) { 180*65789Smckusick *ipp = 0; 181*65789Smckusick return error; 182*65789Smckusick } 183*65789Smckusick MALLOC(ip, struct iso_node *, sizeof(struct iso_node), 184*65789Smckusick M_ISOFSNODE, M_WAITOK); 185*65789Smckusick bzero((caddr_t)ip, sizeof(struct iso_node)); 186*65789Smckusick nvp->v_data = ip; 187*65789Smckusick ip->i_vnode = nvp; 188*65789Smckusick ip->i_flag = 0; 189*65789Smckusick ip->i_devvp = 0; 190*65789Smckusick ip->i_diroff = 0; 191*65789Smckusick ip->i_lockf = 0; 192*65789Smckusick 193*65789Smckusick /* 194*65789Smckusick * Put it onto its hash chain and lock it so that other requests for 195*65789Smckusick * this inode will block if they arrive while we are sleeping waiting 196*65789Smckusick * for old data structures to be purged or for the contents of the 197*65789Smckusick * disk portion of this inode to be read. 198*65789Smckusick */ 199*65789Smckusick ip->i_dev = dev; 200*65789Smckusick ip->i_number = ino; 201*65789Smckusick insque(ip, ih); 202*65789Smckusick ISO_ILOCK(ip); 203*65789Smckusick 204*65789Smckusick imp = VFSTOISOFS (mntp); 205*65789Smckusick ip->i_mnt = imp; 206*65789Smckusick ip->i_devvp = imp->im_devvp; 207*65789Smckusick VREF(ip->i_devvp); 208*65789Smckusick 209*65789Smckusick if (relocated) { 210*65789Smckusick /* 211*65789Smckusick * On relocated directories we must 212*65789Smckusick * read the `.' entry out of a dir. 213*65789Smckusick */ 214*65789Smckusick ip->iso_start = ino >> imp->im_bshift; 215*65789Smckusick if (error = iso_blkatoff(ip,0,&bp)) { 216*65789Smckusick vrele(ip->i_devvp); 217*65789Smckusick remque(ip); 218*65789Smckusick ip->i_forw = ip; 219*65789Smckusick ip->i_back = ip; 220*65789Smckusick iso_iput(ip); 221*65789Smckusick *ipp = 0; 222*65789Smckusick return error; 223*65789Smckusick } 224*65789Smckusick isodir = (struct iso_directory_record *)bp->b_un.b_addr; 225*65789Smckusick } 226*65789Smckusick 227*65789Smckusick ip->iso_extent = isonum_733(isodir->extent); 228*65789Smckusick ip->i_size = isonum_733(isodir->size); 229*65789Smckusick ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent; 230*65789Smckusick 231*65789Smckusick vp = ITOV(ip); 232*65789Smckusick 233*65789Smckusick /* 234*65789Smckusick * Setup time stamp, attribute 235*65789Smckusick */ 236*65789Smckusick vp->v_type = VNON; 237*65789Smckusick switch (imp->iso_ftype) { 238*65789Smckusick default: /* ISO_FTYPE_9660 */ 239*65789Smckusick if ((imp->im_flags&ISOFSMNT_EXTATT) 240*65789Smckusick && isonum_711(isodir->ext_attr_length)) 241*65789Smckusick iso_blkatoff(ip,-isonum_711(isodir->ext_attr_length), 242*65789Smckusick &bp2); 243*65789Smckusick isofs_defattr(isodir,ip,bp2 ); 244*65789Smckusick isofs_deftstamp(isodir,ip,bp2 ); 245*65789Smckusick break; 246*65789Smckusick case ISO_FTYPE_RRIP: 247*65789Smckusick result = isofs_rrip_analyze(isodir,ip,imp); 248*65789Smckusick break; 249*65789Smckusick } 250*65789Smckusick if (bp2) 251*65789Smckusick brelse(bp2); 252*65789Smckusick if (bp) 253*65789Smckusick brelse(bp); 254*65789Smckusick 255*65789Smckusick /* 256*65789Smckusick * Initialize the associated vnode 257*65789Smckusick */ 258*65789Smckusick vp->v_type = IFTOVT(ip->inode.iso_mode); 259*65789Smckusick 260*65789Smckusick if ( vp->v_type == VFIFO ) { 261*65789Smckusick #ifdef FIFO 262*65789Smckusick extern int (**isofs_fifoop_p)(); 263*65789Smckusick vp->v_op = isofs_fifoop_p; 264*65789Smckusick #else 265*65789Smckusick iso_iput(ip); 266*65789Smckusick *ipp = 0; 267*65789Smckusick return EOPNOTSUPP; 268*65789Smckusick #endif /* FIFO */ 269*65789Smckusick } else if ( vp->v_type == VCHR || vp->v_type == VBLK ) { 270*65789Smckusick extern int (**isofs_specop_p)(); 271*65789Smckusick 272*65789Smckusick /* 273*65789Smckusick * if device, look at device number table for translation 274*65789Smckusick */ 275*65789Smckusick #ifdef ISODEVMAP 276*65789Smckusick if (dp = iso_dmap(dev,ino,0)) 277*65789Smckusick ip->inode.iso_rdev = dp->d_dev; 278*65789Smckusick #endif 279*65789Smckusick vp->v_op = isofs_specop_p; 280*65789Smckusick if (nvp = checkalias(vp, ip->inode.iso_rdev, mntp)) { 281*65789Smckusick /* 282*65789Smckusick * Reinitialize aliased inode. 283*65789Smckusick */ 284*65789Smckusick vp = nvp; 285*65789Smckusick iq = VTOI(vp); 286*65789Smckusick iq->i_vnode = vp; 287*65789Smckusick iq->i_flag = 0; 288*65789Smckusick ISO_ILOCK(iq); 289*65789Smckusick iq->i_dev = dev; 290*65789Smckusick iq->i_number = ino; 291*65789Smckusick iq->i_mnt = ip->i_mnt; 292*65789Smckusick bcopy(&ip->iso_extent,&iq->iso_extent, 293*65789Smckusick (char *)(ip + 1) - (char *)&ip->iso_extent); 294*65789Smckusick insque(iq, ih); 295*65789Smckusick /* 296*65789Smckusick * Discard unneeded vnode 297*65789Smckusick * (This introduces the need of INACTIVE modification) 298*65789Smckusick */ 299*65789Smckusick ip->inode.iso_mode = 0; 300*65789Smckusick iso_iput(ip); 301*65789Smckusick ip = iq; 302*65789Smckusick } 303*65789Smckusick } 304*65789Smckusick 305*65789Smckusick if (ip->iso_extent == imp->root_extent) 306*65789Smckusick vp->v_flag |= VROOT; 307*65789Smckusick 308*65789Smckusick *ipp = ip; 309*65789Smckusick return 0; 310*65789Smckusick } 311*65789Smckusick 312*65789Smckusick /* 313*65789Smckusick * Unlock and decrement the reference count of an inode structure. 314*65789Smckusick */ 315*65789Smckusick iso_iput(ip) 316*65789Smckusick register struct iso_node *ip; 317*65789Smckusick { 318*65789Smckusick 319*65789Smckusick if ((ip->i_flag & ILOCKED) == 0) 320*65789Smckusick panic("iso_iput"); 321*65789Smckusick ISO_IUNLOCK(ip); 322*65789Smckusick vrele(ITOV(ip)); 323*65789Smckusick } 324*65789Smckusick 325*65789Smckusick /* 326*65789Smckusick * Last reference to an inode, write the inode out and if necessary, 327*65789Smckusick * truncate and deallocate the file. 328*65789Smckusick */ 329*65789Smckusick int 330*65789Smckusick isofs_inactive(ap) 331*65789Smckusick struct vop_inactive_args /* { 332*65789Smckusick struct vnode *a_vp; 333*65789Smckusick } */ *ap; 334*65789Smckusick { 335*65789Smckusick struct vnode *vp = ap->a_vp; 336*65789Smckusick register struct iso_node *ip = VTOI(vp); 337*65789Smckusick int mode, error = 0; 338*65789Smckusick 339*65789Smckusick if (prtactive && vp->v_usecount != 0) 340*65789Smckusick vprint("isofs_inactive: pushing active", vp); 341*65789Smckusick 342*65789Smckusick ip->i_flag = 0; 343*65789Smckusick /* 344*65789Smckusick * If we are done with the inode, reclaim it 345*65789Smckusick * so that it can be reused immediately. 346*65789Smckusick */ 347*65789Smckusick if (vp->v_usecount == 0 && ip->inode.iso_mode == 0) 348*65789Smckusick vgone(vp); 349*65789Smckusick return error; 350*65789Smckusick } 351*65789Smckusick 352*65789Smckusick /* 353*65789Smckusick * Reclaim an inode so that it can be used for other purposes. 354*65789Smckusick */ 355*65789Smckusick int 356*65789Smckusick isofs_reclaim(ap) 357*65789Smckusick struct vop_reclaim_args /* { 358*65789Smckusick struct vnode *a_vp; 359*65789Smckusick } */ *ap; 360*65789Smckusick { 361*65789Smckusick register struct vnode *vp = ap->a_vp; 362*65789Smckusick register struct iso_node *ip = VTOI(vp); 363*65789Smckusick int i; 364*65789Smckusick 365*65789Smckusick if (prtactive && vp->v_usecount != 0) 366*65789Smckusick vprint("isofs_reclaim: pushing active", vp); 367*65789Smckusick /* 368*65789Smckusick * Remove the inode from its hash chain. 369*65789Smckusick */ 370*65789Smckusick remque(ip); 371*65789Smckusick ip->i_forw = ip; 372*65789Smckusick ip->i_back = ip; 373*65789Smckusick /* 374*65789Smckusick * Purge old data structures associated with the inode. 375*65789Smckusick */ 376*65789Smckusick cache_purge(vp); 377*65789Smckusick if (ip->i_devvp) { 378*65789Smckusick vrele(ip->i_devvp); 379*65789Smckusick ip->i_devvp = 0; 380*65789Smckusick } 381*65789Smckusick FREE(vp->v_data, M_ISOFSNODE); 382*65789Smckusick vp->v_data = NULL; 383*65789Smckusick return 0; 384*65789Smckusick } 385*65789Smckusick 386*65789Smckusick /* 387*65789Smckusick * Lock an inode. If its already locked, set the WANT bit and sleep. 388*65789Smckusick */ 389*65789Smckusick iso_ilock(ip) 390*65789Smckusick register struct iso_node *ip; 391*65789Smckusick { 392*65789Smckusick 393*65789Smckusick while (ip->i_flag & ILOCKED) { 394*65789Smckusick ip->i_flag |= IWANT; 395*65789Smckusick if (ip->i_spare0 == curproc->p_pid) 396*65789Smckusick panic("locking against myself"); 397*65789Smckusick ip->i_spare1 = curproc->p_pid; 398*65789Smckusick (void) sleep((caddr_t)ip, PINOD); 399*65789Smckusick } 400*65789Smckusick ip->i_spare1 = 0; 401*65789Smckusick ip->i_spare0 = curproc->p_pid; 402*65789Smckusick ip->i_flag |= ILOCKED; 403*65789Smckusick } 404*65789Smckusick 405*65789Smckusick /* 406*65789Smckusick * Unlock an inode. If WANT bit is on, wakeup. 407*65789Smckusick */ 408*65789Smckusick iso_iunlock(ip) 409*65789Smckusick register struct iso_node *ip; 410*65789Smckusick { 411*65789Smckusick 412*65789Smckusick if ((ip->i_flag & ILOCKED) == 0) 413*65789Smckusick vprint("iso_iunlock: unlocked inode", ITOV(ip)); 414*65789Smckusick ip->i_spare0 = 0; 415*65789Smckusick ip->i_flag &= ~ILOCKED; 416*65789Smckusick if (ip->i_flag&IWANT) { 417*65789Smckusick ip->i_flag &= ~IWANT; 418*65789Smckusick wakeup((caddr_t)ip); 419*65789Smckusick } 420*65789Smckusick } 421*65789Smckusick 422*65789Smckusick /* 423*65789Smckusick * File attributes 424*65789Smckusick */ 425*65789Smckusick void 426*65789Smckusick isofs_defattr(isodir,inop,bp) 427*65789Smckusick struct iso_directory_record *isodir; 428*65789Smckusick struct iso_node *inop; 429*65789Smckusick struct buf *bp; 430*65789Smckusick { 431*65789Smckusick struct buf *bp2 = NULL; 432*65789Smckusick struct iso_mnt *imp; 433*65789Smckusick struct iso_extended_attributes *ap = NULL; 434*65789Smckusick int off; 435*65789Smckusick 436*65789Smckusick if (isonum_711(isodir->flags)&2) { 437*65789Smckusick inop->inode.iso_mode = S_IFDIR; 438*65789Smckusick /* 439*65789Smckusick * If we return 2, fts() will assume there are no subdirectories 440*65789Smckusick * (just links for the path and .), so instead we return 1. 441*65789Smckusick */ 442*65789Smckusick inop->inode.iso_links = 1; 443*65789Smckusick } else { 444*65789Smckusick inop->inode.iso_mode = S_IFREG; 445*65789Smckusick inop->inode.iso_links = 1; 446*65789Smckusick } 447*65789Smckusick if (!bp 448*65789Smckusick && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 449*65789Smckusick && (off = isonum_711(isodir->ext_attr_length))) { 450*65789Smckusick iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 451*65789Smckusick bp = bp2; 452*65789Smckusick } 453*65789Smckusick if (bp) { 454*65789Smckusick ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 455*65789Smckusick 456*65789Smckusick if (isonum_711(ap->version) == 1) { 457*65789Smckusick if (!(ap->perm[0]&0x40)) 458*65789Smckusick inop->inode.iso_mode |= VEXEC >> 6; 459*65789Smckusick if (!(ap->perm[0]&0x10)) 460*65789Smckusick inop->inode.iso_mode |= VREAD >> 6; 461*65789Smckusick if (!(ap->perm[0]&4)) 462*65789Smckusick inop->inode.iso_mode |= VEXEC >> 3; 463*65789Smckusick if (!(ap->perm[0]&1)) 464*65789Smckusick inop->inode.iso_mode |= VREAD >> 3; 465*65789Smckusick if (!(ap->perm[1]&0x40)) 466*65789Smckusick inop->inode.iso_mode |= VEXEC; 467*65789Smckusick if (!(ap->perm[1]&0x10)) 468*65789Smckusick inop->inode.iso_mode |= VREAD; 469*65789Smckusick inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */ 470*65789Smckusick inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */ 471*65789Smckusick } else 472*65789Smckusick ap = NULL; 473*65789Smckusick } 474*65789Smckusick if (!ap) { 475*65789Smckusick inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6; 476*65789Smckusick inop->inode.iso_uid = (uid_t)0; 477*65789Smckusick inop->inode.iso_gid = (gid_t)0; 478*65789Smckusick } 479*65789Smckusick if (bp2) 480*65789Smckusick brelse(bp2); 481*65789Smckusick } 482*65789Smckusick 483*65789Smckusick /* 484*65789Smckusick * Time stamps 485*65789Smckusick */ 486*65789Smckusick void 487*65789Smckusick isofs_deftstamp(isodir,inop,bp) 488*65789Smckusick struct iso_directory_record *isodir; 489*65789Smckusick struct iso_node *inop; 490*65789Smckusick struct buf *bp; 491*65789Smckusick { 492*65789Smckusick struct buf *bp2 = NULL; 493*65789Smckusick struct iso_mnt *imp; 494*65789Smckusick struct iso_extended_attributes *ap = NULL; 495*65789Smckusick int off; 496*65789Smckusick 497*65789Smckusick if (!bp 498*65789Smckusick && ((imp = inop->i_mnt)->im_flags&ISOFSMNT_EXTATT) 499*65789Smckusick && (off = isonum_711(isodir->ext_attr_length))) { 500*65789Smckusick iso_blkatoff(inop,-off * imp->logical_block_size,&bp2); 501*65789Smckusick bp = bp2; 502*65789Smckusick } 503*65789Smckusick if (bp) { 504*65789Smckusick ap = (struct iso_extended_attributes *)bp->b_un.b_addr; 505*65789Smckusick 506*65789Smckusick if (isonum_711(ap->version) == 1) { 507*65789Smckusick if (!isofs_tstamp_conv17(ap->ftime,&inop->inode.iso_atime)) 508*65789Smckusick isofs_tstamp_conv17(ap->ctime,&inop->inode.iso_atime); 509*65789Smckusick if (!isofs_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime)) 510*65789Smckusick inop->inode.iso_ctime = inop->inode.iso_atime; 511*65789Smckusick if (!isofs_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime)) 512*65789Smckusick inop->inode.iso_mtime = inop->inode.iso_ctime; 513*65789Smckusick } else 514*65789Smckusick ap = NULL; 515*65789Smckusick } 516*65789Smckusick if (!ap) { 517*65789Smckusick isofs_tstamp_conv7(isodir->date,&inop->inode.iso_ctime); 518*65789Smckusick inop->inode.iso_atime = inop->inode.iso_ctime; 519*65789Smckusick inop->inode.iso_mtime = inop->inode.iso_ctime; 520*65789Smckusick } 521*65789Smckusick if (bp2) 522*65789Smckusick brelse(bp2); 523*65789Smckusick } 524*65789Smckusick 525*65789Smckusick int 526*65789Smckusick isofs_tstamp_conv7(pi,pu) 527*65789Smckusick char *pi; 528*65789Smckusick struct timeval *pu; 529*65789Smckusick { 530*65789Smckusick int i; 531*65789Smckusick int crtime, days; 532*65789Smckusick int y, m, d, hour, minute, second, tz; 533*65789Smckusick 534*65789Smckusick y = pi[0] + 1900; 535*65789Smckusick m = pi[1]; 536*65789Smckusick d = pi[2]; 537*65789Smckusick hour = pi[3]; 538*65789Smckusick minute = pi[4]; 539*65789Smckusick second = pi[5]; 540*65789Smckusick tz = pi[6]; 541*65789Smckusick 542*65789Smckusick if (y < 1970) { 543*65789Smckusick pu->tv_sec = 0; 544*65789Smckusick pu->tv_usec = 0; 545*65789Smckusick return 0; 546*65789Smckusick } else { 547*65789Smckusick #ifdef ORIGINAL 548*65789Smckusick /* computes day number relative to Sept. 19th,1989 */ 549*65789Smckusick /* don't even *THINK* about changing formula. It works! */ 550*65789Smckusick days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100; 551*65789Smckusick #else 552*65789Smckusick /* 553*65789Smckusick * Changed :-) to make it relative to Jan. 1st, 1970 554*65789Smckusick * and to disambiguate negative division 555*65789Smckusick */ 556*65789Smckusick days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239; 557*65789Smckusick #endif 558*65789Smckusick crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second; 559*65789Smckusick 560*65789Smckusick /* timezone offset is unreliable on some disks */ 561*65789Smckusick if (-48 <= tz && tz <= 52) 562*65789Smckusick crtime += tz * 15 * 60; 563*65789Smckusick } 564*65789Smckusick pu->tv_sec = crtime; 565*65789Smckusick pu->tv_usec = 0; 566*65789Smckusick return 1; 567*65789Smckusick } 568*65789Smckusick 569*65789Smckusick static unsigned 570*65789Smckusick isofs_chars2ui(begin,len) 571*65789Smckusick unsigned char *begin; 572*65789Smckusick int len; 573*65789Smckusick { 574*65789Smckusick unsigned rc; 575*65789Smckusick 576*65789Smckusick for (rc = 0; --len >= 0;) { 577*65789Smckusick rc *= 10; 578*65789Smckusick rc += *begin++ - '0'; 579*65789Smckusick } 580*65789Smckusick return rc; 581*65789Smckusick } 582*65789Smckusick 583*65789Smckusick int 584*65789Smckusick isofs_tstamp_conv17(pi,pu) 585*65789Smckusick unsigned char *pi; 586*65789Smckusick struct timeval *pu; 587*65789Smckusick { 588*65789Smckusick unsigned char buf[7]; 589*65789Smckusick 590*65789Smckusick /* year:"0001"-"9999" -> -1900 */ 591*65789Smckusick buf[0] = isofs_chars2ui(pi,4) - 1900; 592*65789Smckusick 593*65789Smckusick /* month: " 1"-"12" -> 1 - 12 */ 594*65789Smckusick buf[1] = isofs_chars2ui(pi + 4,2); 595*65789Smckusick 596*65789Smckusick /* day: " 1"-"31" -> 1 - 31 */ 597*65789Smckusick buf[2] = isofs_chars2ui(pi + 6,2); 598*65789Smckusick 599*65789Smckusick /* hour: " 0"-"23" -> 0 - 23 */ 600*65789Smckusick buf[3] = isofs_chars2ui(pi + 8,2); 601*65789Smckusick 602*65789Smckusick /* minute:" 0"-"59" -> 0 - 59 */ 603*65789Smckusick buf[4] = isofs_chars2ui(pi + 10,2); 604*65789Smckusick 605*65789Smckusick /* second:" 0"-"59" -> 0 - 59 */ 606*65789Smckusick buf[5] = isofs_chars2ui(pi + 12,2); 607*65789Smckusick 608*65789Smckusick /* difference of GMT */ 609*65789Smckusick buf[6] = pi[16]; 610*65789Smckusick 611*65789Smckusick return isofs_tstamp_conv7(buf,pu); 612*65789Smckusick } 613*65789Smckusick 614*65789Smckusick void 615*65789Smckusick isodirino(inump,isodir,imp) 616*65789Smckusick ino_t *inump; 617*65789Smckusick struct iso_directory_record *isodir; 618*65789Smckusick struct iso_mnt *imp; 619*65789Smckusick { 620*65789Smckusick *inump = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length)) 621*65789Smckusick * imp->logical_block_size; 622*65789Smckusick } 623