xref: /csrg-svn/sys/isofs/cd9660/cd9660_node.c (revision 65789)
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