1*65789Smckusick /*-
2*65789Smckusick  * Copyright (c) 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_vnops.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/namei.h>
18*65789Smckusick #include <sys/resourcevar.h>
19*65789Smckusick #include <sys/kernel.h>
20*65789Smckusick #include <sys/file.h>
21*65789Smckusick #include <sys/stat.h>
22*65789Smckusick #include <sys/buf.h>
23*65789Smckusick #include <sys/proc.h>
24*65789Smckusick #include <sys/conf.h>
25*65789Smckusick #include <sys/mount.h>
26*65789Smckusick #include <sys/vnode.h>
27*65789Smckusick #include <miscfs/specfs/specdev.h>
28*65789Smckusick #include <miscfs/fifofs/fifo.h>
29*65789Smckusick #include <sys/malloc.h>
30*65789Smckusick #include <sys/dir.h>
31*65789Smckusick 
32*65789Smckusick #include <isofs/cd9660/iso.h>
33*65789Smckusick #include <isofs/cd9660/isofs_node.h>
34*65789Smckusick #include <isofs/cd9660/iso_rrip.h>
35*65789Smckusick 
36*65789Smckusick #if 0
37*65789Smckusick /*
38*65789Smckusick  * Mknod vnode call
39*65789Smckusick  *  Actually remap the device number
40*65789Smckusick  */
41*65789Smckusick isofs_mknod(ndp, vap, cred, p)
42*65789Smckusick 	struct nameidata *ndp;
43*65789Smckusick 	struct ucred *cred;
44*65789Smckusick 	struct vattr *vap;
45*65789Smckusick 	struct proc *p;
46*65789Smckusick {
47*65789Smckusick #ifndef	ISODEVMAP
48*65789Smckusick 	free(ndp->ni_pnbuf, M_NAMEI);
49*65789Smckusick 	vput(ndp->ni_dvp);
50*65789Smckusick 	vput(ndp->ni_vp);
51*65789Smckusick 	return EINVAL;
52*65789Smckusick #else
53*65789Smckusick 	register struct vnode *vp;
54*65789Smckusick 	struct iso_node *ip;
55*65789Smckusick 	struct iso_dnode *dp;
56*65789Smckusick 	int error;
57*65789Smckusick 
58*65789Smckusick 	vp = ndp->ni_vp;
59*65789Smckusick 	ip = VTOI(vp);
60*65789Smckusick 
61*65789Smckusick 	if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
62*65789Smckusick 	    || vap->va_type != vp->v_type
63*65789Smckusick 	    || (vap->va_type != VCHR && vap->va_type != VBLK)) {
64*65789Smckusick 		free(ndp->ni_pnbuf, M_NAMEI);
65*65789Smckusick 		vput(ndp->ni_dvp);
66*65789Smckusick 		vput(ndp->ni_vp);
67*65789Smckusick 		return EINVAL;
68*65789Smckusick 	}
69*65789Smckusick 
70*65789Smckusick 	dp = iso_dmap(ip->i_dev,ip->i_number,1);
71*65789Smckusick 	if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
72*65789Smckusick 		/* same as the unmapped one, delete the mapping */
73*65789Smckusick 		remque(dp);
74*65789Smckusick 		FREE(dp,M_CACHE);
75*65789Smckusick 	} else
76*65789Smckusick 		/* enter new mapping */
77*65789Smckusick 		dp->d_dev = vap->va_rdev;
78*65789Smckusick 
79*65789Smckusick 	/*
80*65789Smckusick 	 * Remove inode so that it will be reloaded by iget and
81*65789Smckusick 	 * checked to see if it is an alias of an existing entry
82*65789Smckusick 	 * in the inode cache.
83*65789Smckusick 	 */
84*65789Smckusick 	vput(vp);
85*65789Smckusick 	vp->v_type = VNON;
86*65789Smckusick 	vgone(vp);
87*65789Smckusick 	return (0);
88*65789Smckusick #endif
89*65789Smckusick }
90*65789Smckusick #endif
91*65789Smckusick 
92*65789Smckusick /*
93*65789Smckusick  * Open called.
94*65789Smckusick  *
95*65789Smckusick  * Nothing to do.
96*65789Smckusick  */
97*65789Smckusick /* ARGSUSED */
98*65789Smckusick int
99*65789Smckusick isofs_open(ap)
100*65789Smckusick 	struct vop_open_args /* {
101*65789Smckusick 		struct vnode *a_vp;
102*65789Smckusick 		int  a_mode;
103*65789Smckusick 		struct ucred *a_cred;
104*65789Smckusick 		struct proc *a_p;
105*65789Smckusick 	} */ *ap;
106*65789Smckusick {
107*65789Smckusick 	return (0);
108*65789Smckusick }
109*65789Smckusick 
110*65789Smckusick /*
111*65789Smckusick  * Close called
112*65789Smckusick  *
113*65789Smckusick  * Update the times on the inode on writeable file systems.
114*65789Smckusick  */
115*65789Smckusick /* ARGSUSED */
116*65789Smckusick int
117*65789Smckusick isofs_close(ap)
118*65789Smckusick 	struct vop_close_args /* {
119*65789Smckusick 		struct vnode *a_vp;
120*65789Smckusick 		int  a_fflag;
121*65789Smckusick 		struct ucred *a_cred;
122*65789Smckusick 		struct proc *a_p;
123*65789Smckusick 	} */ *ap;
124*65789Smckusick {
125*65789Smckusick 	return (0);
126*65789Smckusick }
127*65789Smckusick 
128*65789Smckusick /*
129*65789Smckusick  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
130*65789Smckusick  * The mode is shifted to select the owner/group/other fields. The
131*65789Smckusick  * super user is granted all permissions.
132*65789Smckusick  */
133*65789Smckusick /* ARGSUSED */
134*65789Smckusick isofs_access(ap)
135*65789Smckusick 	struct vop_access_args /* {
136*65789Smckusick 		struct vnode *a_vp;
137*65789Smckusick 		int  a_mode;
138*65789Smckusick 		struct ucred *a_cred;
139*65789Smckusick 		struct proc *a_p;
140*65789Smckusick 	} */ *ap;
141*65789Smckusick {
142*65789Smckusick 	return (0);
143*65789Smckusick }
144*65789Smckusick 
145*65789Smckusick isofs_getattr(ap)
146*65789Smckusick 	struct vop_getattr_args /* {
147*65789Smckusick 		struct vnode *a_vp;
148*65789Smckusick 		struct vattr *a_vap;
149*65789Smckusick 		struct ucred *a_cred;
150*65789Smckusick 		struct proc *a_p;
151*65789Smckusick 	} */ *ap;
152*65789Smckusick 
153*65789Smckusick {
154*65789Smckusick 	struct vnode *vp = ap->a_vp;
155*65789Smckusick 	register struct vattr *vap = ap->a_vap;
156*65789Smckusick 	register struct iso_node *ip = VTOI(vp);
157*65789Smckusick 	int i;
158*65789Smckusick 
159*65789Smckusick 	vap->va_fsid	= ip->i_dev;
160*65789Smckusick 	vap->va_fileid	= ip->i_number;
161*65789Smckusick 
162*65789Smckusick 	vap->va_mode	= ip->inode.iso_mode;
163*65789Smckusick 	vap->va_nlink	= ip->inode.iso_links;
164*65789Smckusick 	vap->va_uid	= ip->inode.iso_uid;
165*65789Smckusick 	vap->va_gid	= ip->inode.iso_gid;
166*65789Smckusick 	vap->va_atime	= ip->inode.iso_atime;
167*65789Smckusick 	vap->va_mtime	= ip->inode.iso_mtime;
168*65789Smckusick 	vap->va_ctime	= ip->inode.iso_ctime;
169*65789Smckusick 	vap->va_rdev	= ip->inode.iso_rdev;
170*65789Smckusick 
171*65789Smckusick 	vap->va_size	= (u_quad_t) ip->i_size;
172*65789Smckusick 	vap->va_flags	= 0;
173*65789Smckusick 	vap->va_gen = 1;
174*65789Smckusick 	vap->va_blocksize = ip->i_mnt->logical_block_size;
175*65789Smckusick 	vap->va_bytes	= (u_quad_t) ip->i_size;
176*65789Smckusick 	vap->va_type	= vp->v_type;
177*65789Smckusick 	return (0);
178*65789Smckusick }
179*65789Smckusick 
180*65789Smckusick #if ISO_DEFAULT_BLOCK_SIZE >= NBPG
181*65789Smckusick #ifdef DEBUG
182*65789Smckusick extern int doclusterread;
183*65789Smckusick #else
184*65789Smckusick #define doclusterread 1
185*65789Smckusick #endif
186*65789Smckusick #else
187*65789Smckusick /* XXX until cluster routines can handle block sizes less than one page */
188*65789Smckusick #define doclusterread 0
189*65789Smckusick #endif
190*65789Smckusick 
191*65789Smckusick /*
192*65789Smckusick  * Vnode op for reading.
193*65789Smckusick  */
194*65789Smckusick isofs_read(ap)
195*65789Smckusick 	struct vop_read_args /* {
196*65789Smckusick 		struct vnode *a_vp;
197*65789Smckusick 		struct uio *a_uio;
198*65789Smckusick 		int a_ioflag;
199*65789Smckusick 		struct ucred *a_cred;
200*65789Smckusick 	} */ *ap;
201*65789Smckusick {
202*65789Smckusick 	struct vnode *vp = ap->a_vp;
203*65789Smckusick 	register struct uio *uio = ap->a_uio;
204*65789Smckusick 	register struct iso_node *ip = VTOI(vp);
205*65789Smckusick 	register struct iso_mnt *imp;
206*65789Smckusick 	struct buf *bp;
207*65789Smckusick 	daddr_t lbn, bn, rablock;
208*65789Smckusick 	off_t diff;
209*65789Smckusick 	int rasize, error = 0;
210*65789Smckusick 	long size, n, on;
211*65789Smckusick 
212*65789Smckusick 	if (uio->uio_resid == 0)
213*65789Smckusick 		return (0);
214*65789Smckusick 	if (uio->uio_offset < 0)
215*65789Smckusick 		return (EINVAL);
216*65789Smckusick 	ip->i_flag |= IACC;
217*65789Smckusick 	imp = ip->i_mnt;
218*65789Smckusick 	do {
219*65789Smckusick 		lbn = iso_lblkno(imp, uio->uio_offset);
220*65789Smckusick 		on = iso_blkoff(imp, uio->uio_offset);
221*65789Smckusick 		n = min((unsigned)(imp->logical_block_size - on),
222*65789Smckusick 			uio->uio_resid);
223*65789Smckusick 		diff = (off_t)ip->i_size - uio->uio_offset;
224*65789Smckusick 		if (diff <= 0)
225*65789Smckusick 			return (0);
226*65789Smckusick 		if (diff < n)
227*65789Smckusick 			n = diff;
228*65789Smckusick 		size = iso_blksize(imp, ip, lbn);
229*65789Smckusick 		rablock = lbn + 1;
230*65789Smckusick #if 1
231*65789Smckusick 		if (doclusterread) {
232*65789Smckusick 			if (iso_lblktosize(imp, rablock) <= ip->i_size)
233*65789Smckusick 				error = cluster_read(vp, (off_t)ip->i_size,
234*65789Smckusick 						     lbn, size, NOCRED, &bp);
235*65789Smckusick 			else
236*65789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
237*65789Smckusick 		} else {
238*65789Smckusick 			if (vp->v_lastr + 1 == lbn &&
239*65789Smckusick 			    iso_lblktosize(imp, rablock) < ip->i_size) {
240*65789Smckusick 				rasize = iso_blksize(imp, ip, rablock);
241*65789Smckusick 				error = breadn(vp, lbn, size, &rablock,
242*65789Smckusick 					       &rasize, 1, NOCRED, &bp);
243*65789Smckusick 			} else
244*65789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
245*65789Smckusick 		}
246*65789Smckusick #endif
247*65789Smckusick 		vp->v_lastr = lbn;
248*65789Smckusick 		n = min(n, size - bp->b_resid);
249*65789Smckusick 		if (error) {
250*65789Smckusick 			brelse(bp);
251*65789Smckusick 			return (error);
252*65789Smckusick 		}
253*65789Smckusick 
254*65789Smckusick 		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
255*65789Smckusick 		if (n + on == imp->logical_block_size ||
256*65789Smckusick 		    uio->uio_offset == (off_t)ip->i_size)
257*65789Smckusick 			bp->b_flags |= B_AGE;
258*65789Smckusick 		brelse(bp);
259*65789Smckusick 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
260*65789Smckusick 	return (error);
261*65789Smckusick }
262*65789Smckusick 
263*65789Smckusick /* ARGSUSED */
264*65789Smckusick int
265*65789Smckusick isofs_ioctl(ap)
266*65789Smckusick 	struct vop_ioctl_args /* {
267*65789Smckusick 		struct vnode *a_vp;
268*65789Smckusick 		int  a_command;
269*65789Smckusick 		caddr_t  a_data;
270*65789Smckusick 		int  a_fflag;
271*65789Smckusick 		struct ucred *a_cred;
272*65789Smckusick 		struct proc *a_p;
273*65789Smckusick 	} */ *ap;
274*65789Smckusick {
275*65789Smckusick 	printf("You did ioctl for isofs !!\n");
276*65789Smckusick 	return (ENOTTY);
277*65789Smckusick }
278*65789Smckusick 
279*65789Smckusick /* ARGSUSED */
280*65789Smckusick int
281*65789Smckusick isofs_select(ap)
282*65789Smckusick 	struct vop_select_args /* {
283*65789Smckusick 		struct vnode *a_vp;
284*65789Smckusick 		int  a_which;
285*65789Smckusick 		int  a_fflags;
286*65789Smckusick 		struct ucred *a_cred;
287*65789Smckusick 		struct proc *a_p;
288*65789Smckusick 	} */ *ap;
289*65789Smckusick {
290*65789Smckusick 
291*65789Smckusick 	/*
292*65789Smckusick 	 * We should really check to see if I/O is possible.
293*65789Smckusick 	 */
294*65789Smckusick 	return (1);
295*65789Smckusick }
296*65789Smckusick 
297*65789Smckusick /*
298*65789Smckusick  * Mmap a file
299*65789Smckusick  *
300*65789Smckusick  * NB Currently unsupported.
301*65789Smckusick  */
302*65789Smckusick /* ARGSUSED */
303*65789Smckusick int
304*65789Smckusick isofs_mmap(ap)
305*65789Smckusick 	struct vop_mmap_args /* {
306*65789Smckusick 		struct vnode *a_vp;
307*65789Smckusick 		int  a_fflags;
308*65789Smckusick 		struct ucred *a_cred;
309*65789Smckusick 		struct proc *a_p;
310*65789Smckusick 	} */ *ap;
311*65789Smckusick {
312*65789Smckusick 
313*65789Smckusick 	return (EINVAL);
314*65789Smckusick }
315*65789Smckusick 
316*65789Smckusick /*
317*65789Smckusick  * Seek on a file
318*65789Smckusick  *
319*65789Smckusick  * Nothing to do, so just return.
320*65789Smckusick  */
321*65789Smckusick /* ARGSUSED */
322*65789Smckusick int
323*65789Smckusick isofs_seek(ap)
324*65789Smckusick 	struct vop_seek_args /* {
325*65789Smckusick 		struct vnode *a_vp;
326*65789Smckusick 		off_t  a_oldoff;
327*65789Smckusick 		off_t  a_newoff;
328*65789Smckusick 		struct ucred *a_cred;
329*65789Smckusick 	} */ *ap;
330*65789Smckusick {
331*65789Smckusick 
332*65789Smckusick 	return (0);
333*65789Smckusick }
334*65789Smckusick 
335*65789Smckusick /*
336*65789Smckusick  * Structure for reading directories
337*65789Smckusick  */
338*65789Smckusick struct isoreaddir {
339*65789Smckusick 	struct dirent saveent;
340*65789Smckusick 	struct dirent assocent;
341*65789Smckusick 	struct dirent current;
342*65789Smckusick 	off_t saveoff;
343*65789Smckusick 	off_t assocoff;
344*65789Smckusick 	off_t curroff;
345*65789Smckusick 	struct uio *uio;
346*65789Smckusick 	off_t uio_off;
347*65789Smckusick 	u_int *cookiep;
348*65789Smckusick 	int ncookies;
349*65789Smckusick 	int eof;
350*65789Smckusick };
351*65789Smckusick 
352*65789Smckusick static int
353*65789Smckusick iso_uiodir(idp,dp,off)
354*65789Smckusick 	struct isoreaddir *idp;
355*65789Smckusick 	struct dirent *dp;
356*65789Smckusick 	off_t off;
357*65789Smckusick {
358*65789Smckusick 	int error;
359*65789Smckusick 
360*65789Smckusick 	dp->d_name[dp->d_namlen] = 0;
361*65789Smckusick 	dp->d_reclen = DIRSIZ(dp);
362*65789Smckusick 
363*65789Smckusick 	if (idp->uio->uio_resid < dp->d_reclen) {
364*65789Smckusick 		idp->eof = 0;
365*65789Smckusick 		return -1;
366*65789Smckusick 	}
367*65789Smckusick 
368*65789Smckusick 	if (idp->cookiep) {
369*65789Smckusick 		if (idp->ncookies <= 0) {
370*65789Smckusick 			idp->eof = 0;
371*65789Smckusick 			return -1;
372*65789Smckusick 		}
373*65789Smckusick 
374*65789Smckusick 		*idp->cookiep++ = off;
375*65789Smckusick 		--idp->ncookies;
376*65789Smckusick 	}
377*65789Smckusick 
378*65789Smckusick 	if (error = uiomove(dp,dp->d_reclen,idp->uio))
379*65789Smckusick 		return error;
380*65789Smckusick 	idp->uio_off = off;
381*65789Smckusick 	return 0;
382*65789Smckusick }
383*65789Smckusick 
384*65789Smckusick static int
385*65789Smckusick iso_shipdir(idp)
386*65789Smckusick 	struct isoreaddir *idp;
387*65789Smckusick {
388*65789Smckusick 	struct dirent *dp;
389*65789Smckusick 	int cl, sl, assoc;
390*65789Smckusick 	int error;
391*65789Smckusick 	char *cname, *sname;
392*65789Smckusick 
393*65789Smckusick 	cl = idp->current.d_namlen;
394*65789Smckusick 	cname = idp->current.d_name;
395*65789Smckusick 	if (assoc = cl > 1 && *cname == ASSOCCHAR) {
396*65789Smckusick 		cl--;
397*65789Smckusick 		cname++;
398*65789Smckusick 	}
399*65789Smckusick 
400*65789Smckusick 	dp = &idp->saveent;
401*65789Smckusick 	sname = dp->d_name;
402*65789Smckusick 	if (!(sl = dp->d_namlen)) {
403*65789Smckusick 		dp = &idp->assocent;
404*65789Smckusick 		sname = dp->d_name + 1;
405*65789Smckusick 		sl = dp->d_namlen - 1;
406*65789Smckusick 	}
407*65789Smckusick 	if (sl > 0) {
408*65789Smckusick 		if (sl != cl
409*65789Smckusick 		    || bcmp(sname,cname,sl)) {
410*65789Smckusick 			if (idp->assocent.d_namlen) {
411*65789Smckusick 				if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
412*65789Smckusick 					return error;
413*65789Smckusick 				idp->assocent.d_namlen = 0;
414*65789Smckusick 			}
415*65789Smckusick 			if (idp->saveent.d_namlen) {
416*65789Smckusick 				if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
417*65789Smckusick 					return error;
418*65789Smckusick 				idp->saveent.d_namlen = 0;
419*65789Smckusick 			}
420*65789Smckusick 		}
421*65789Smckusick 	}
422*65789Smckusick 	idp->current.d_reclen = DIRSIZ(&idp->current);
423*65789Smckusick 	if (assoc) {
424*65789Smckusick 		idp->assocoff = idp->curroff;
425*65789Smckusick 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
426*65789Smckusick 	} else {
427*65789Smckusick 		idp->saveoff = idp->curroff;
428*65789Smckusick 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
429*65789Smckusick 	}
430*65789Smckusick 	return 0;
431*65789Smckusick }
432*65789Smckusick 
433*65789Smckusick /*
434*65789Smckusick  * Vnode op for readdir
435*65789Smckusick  * XXX make sure everything still works now that eofflagp and cookiep
436*65789Smckusick  * are no longer args.
437*65789Smckusick  */
438*65789Smckusick int
439*65789Smckusick isofs_readdir(ap)
440*65789Smckusick 	struct vop_readdir_args /* {
441*65789Smckusick 		struct vnode *a_vp;
442*65789Smckusick 		struct uio *a_uio;
443*65789Smckusick 		struct ucred *a_cred;
444*65789Smckusick 	} */ *ap;
445*65789Smckusick {
446*65789Smckusick 	register struct uio *uio = ap->a_uio;
447*65789Smckusick 	struct isoreaddir *idp;
448*65789Smckusick 	int entryoffsetinblock;
449*65789Smckusick 	int error = 0;
450*65789Smckusick 	int endsearch;
451*65789Smckusick 	struct iso_directory_record *ep;
452*65789Smckusick 	u_short elen;
453*65789Smckusick 	int reclen;
454*65789Smckusick 	struct iso_mnt *imp;
455*65789Smckusick 	struct iso_node *ip;
456*65789Smckusick 	struct buf *bp = NULL;
457*65789Smckusick 
458*65789Smckusick 	ip = VTOI(ap->a_vp);
459*65789Smckusick 	imp = ip->i_mnt;
460*65789Smckusick 
461*65789Smckusick 	MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
462*65789Smckusick 	idp->saveent.d_namlen = 0;
463*65789Smckusick 	idp->assocent.d_namlen = 0;
464*65789Smckusick 	idp->uio = uio;
465*65789Smckusick #if 0
466*65789Smckusick 	idp->cookiep = cookies;
467*65789Smckusick 	idp->ncookies = ncookies;
468*65789Smckusick 	idp->eof = 1;
469*65789Smckusick #else
470*65789Smckusick 	idp->cookiep = 0;
471*65789Smckusick #endif
472*65789Smckusick 	idp->curroff = uio->uio_offset;
473*65789Smckusick 
474*65789Smckusick 	entryoffsetinblock = iso_blkoff(imp, idp->curroff);
475*65789Smckusick 	if (entryoffsetinblock != 0) {
476*65789Smckusick 		if (error = iso_blkatoff(ip, idp->curroff, &bp)) {
477*65789Smckusick 			FREE(idp,M_TEMP);
478*65789Smckusick 			return (error);
479*65789Smckusick 		}
480*65789Smckusick 	}
481*65789Smckusick 
482*65789Smckusick 	endsearch = ip->i_size;
483*65789Smckusick 
484*65789Smckusick 	while (idp->curroff < endsearch) {
485*65789Smckusick 		/*
486*65789Smckusick 		 * If offset is on a block boundary,
487*65789Smckusick 		 * read the next directory block.
488*65789Smckusick 		 * Release previous if it exists.
489*65789Smckusick 		 */
490*65789Smckusick 
491*65789Smckusick 		if (iso_blkoff(imp, idp->curroff) == 0) {
492*65789Smckusick 			if (bp != NULL)
493*65789Smckusick 				brelse(bp);
494*65789Smckusick 			if (error = iso_blkatoff(ip, idp->curroff, &bp))
495*65789Smckusick 				break;
496*65789Smckusick 			entryoffsetinblock = 0;
497*65789Smckusick 		}
498*65789Smckusick 		/*
499*65789Smckusick 		 * Get pointer to next entry.
500*65789Smckusick 		 */
501*65789Smckusick 
502*65789Smckusick 		ep = (struct iso_directory_record *)
503*65789Smckusick 			(bp->b_un.b_addr + entryoffsetinblock);
504*65789Smckusick 
505*65789Smckusick 		reclen = isonum_711 (ep->length);
506*65789Smckusick 		if (reclen == 0) {
507*65789Smckusick 			/* skip to next block, if any */
508*65789Smckusick 			idp->curroff = roundup (idp->curroff,
509*65789Smckusick 						imp->logical_block_size);
510*65789Smckusick 			continue;
511*65789Smckusick 		}
512*65789Smckusick 
513*65789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
514*65789Smckusick 			error = EINVAL;
515*65789Smckusick 			/* illegal entry, stop */
516*65789Smckusick 			break;
517*65789Smckusick 		}
518*65789Smckusick 
519*65789Smckusick 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
520*65789Smckusick 			error = EINVAL;
521*65789Smckusick 			/* illegal directory, so stop looking */
522*65789Smckusick 			break;
523*65789Smckusick 		}
524*65789Smckusick 
525*65789Smckusick 		idp->current.d_namlen = isonum_711 (ep->name_len);
526*65789Smckusick 		if (isonum_711(ep->flags)&2)
527*65789Smckusick 			isodirino(&idp->current.d_fileno,ep,imp);
528*65789Smckusick 		else
529*65789Smckusick 			idp->current.d_fileno = dbtob(bp->b_blkno) +
530*65789Smckusick 				idp->curroff;
531*65789Smckusick 
532*65789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
533*65789Smckusick 			error = EINVAL;
534*65789Smckusick 			/* illegal entry, stop */
535*65789Smckusick 			break;
536*65789Smckusick 		}
537*65789Smckusick 
538*65789Smckusick 		idp->curroff += reclen;
539*65789Smckusick 		/*
540*65789Smckusick 		 *
541*65789Smckusick 		 */
542*65789Smckusick 		switch (imp->iso_ftype) {
543*65789Smckusick 		case ISO_FTYPE_RRIP:
544*65789Smckusick 			isofs_rrip_getname(ep,idp->current.d_name,
545*65789Smckusick 					   (u_short *)&idp->current.d_namlen,
546*65789Smckusick 					   &idp->current.d_fileno,imp);
547*65789Smckusick 			if (idp->current.d_namlen)
548*65789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
549*65789Smckusick 			break;
550*65789Smckusick 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
551*65789Smckusick 			strcpy(idp->current.d_name,"..");
552*65789Smckusick 			switch (ep->name[0]) {
553*65789Smckusick 			case 0:
554*65789Smckusick 				idp->current.d_namlen = 1;
555*65789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
556*65789Smckusick 				break;
557*65789Smckusick 			case 1:
558*65789Smckusick 				idp->current.d_namlen = 2;
559*65789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
560*65789Smckusick 				break;
561*65789Smckusick 			default:
562*65789Smckusick 				isofntrans(ep->name,idp->current.d_namlen,
563*65789Smckusick 					   idp->current.d_name, &elen,
564*65789Smckusick 					   imp->iso_ftype == ISO_FTYPE_9660,
565*65789Smckusick 					   isonum_711(ep->flags)&4);
566*65789Smckusick 				idp->current.d_namlen = (u_char)elen;
567*65789Smckusick 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
568*65789Smckusick 					error = iso_shipdir(idp);
569*65789Smckusick 				else
570*65789Smckusick 					error = iso_uiodir(idp,&idp->current,idp->curroff);
571*65789Smckusick 				break;
572*65789Smckusick 			}
573*65789Smckusick 		}
574*65789Smckusick 		if (error)
575*65789Smckusick 			break;
576*65789Smckusick 
577*65789Smckusick 		entryoffsetinblock += reclen;
578*65789Smckusick 	}
579*65789Smckusick 
580*65789Smckusick 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
581*65789Smckusick 		idp->current.d_namlen = 0;
582*65789Smckusick 		error = iso_shipdir(idp);
583*65789Smckusick 	}
584*65789Smckusick 	if (error < 0)
585*65789Smckusick 		error = 0;
586*65789Smckusick 
587*65789Smckusick 	if (bp)
588*65789Smckusick 		brelse (bp);
589*65789Smckusick 
590*65789Smckusick 	uio->uio_offset = idp->uio_off;
591*65789Smckusick #if 0
592*65789Smckusick 	*eofflagp = idp->eof;
593*65789Smckusick #endif
594*65789Smckusick 
595*65789Smckusick 	FREE(idp,M_TEMP);
596*65789Smckusick 
597*65789Smckusick 	return (error);
598*65789Smckusick }
599*65789Smckusick 
600*65789Smckusick /*
601*65789Smckusick  * Return target name of a symbolic link
602*65789Smckusick  * Shouldn't we get the parent vnode and read the data from there?
603*65789Smckusick  * This could eventually result in deadlocks in isofs_lookup.
604*65789Smckusick  * But otherwise the block read here is in the block buffer two times.
605*65789Smckusick  */
606*65789Smckusick typedef struct iso_directory_record ISODIR;
607*65789Smckusick typedef struct iso_node             ISONODE;
608*65789Smckusick typedef struct iso_mnt              ISOMNT;
609*65789Smckusick int
610*65789Smckusick isofs_readlink(ap)
611*65789Smckusick 	struct vop_readlink_args /* {
612*65789Smckusick 		struct vnode *a_vp;
613*65789Smckusick 		struct uio *a_uio;
614*65789Smckusick 		struct ucred *a_cred;
615*65789Smckusick 	} */ *ap;
616*65789Smckusick {
617*65789Smckusick 	ISONODE	*ip;
618*65789Smckusick 	ISODIR	*dirp;
619*65789Smckusick 	ISOMNT	*imp;
620*65789Smckusick 	struct	buf *bp;
621*65789Smckusick 	u_short	symlen;
622*65789Smckusick 	int	error;
623*65789Smckusick 	char	*symname;
624*65789Smckusick 	ino_t	ino;
625*65789Smckusick 
626*65789Smckusick 	ip  = VTOI(ap->a_vp);
627*65789Smckusick 	imp = ip->i_mnt;
628*65789Smckusick 
629*65789Smckusick 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
630*65789Smckusick 		return EINVAL;
631*65789Smckusick 
632*65789Smckusick 	/*
633*65789Smckusick 	 * Get parents directory record block that this inode included.
634*65789Smckusick 	 */
635*65789Smckusick 	error = bread(imp->im_devvp,
636*65789Smckusick 		      (daddr_t)(ip->i_number / DEV_BSIZE),
637*65789Smckusick 		      imp->logical_block_size,
638*65789Smckusick 		      NOCRED,
639*65789Smckusick 		      &bp);
640*65789Smckusick 	if (error) {
641*65789Smckusick 		brelse(bp);
642*65789Smckusick 		return EINVAL;
643*65789Smckusick 	}
644*65789Smckusick 
645*65789Smckusick 	/*
646*65789Smckusick 	 * Setup the directory pointer for this inode
647*65789Smckusick 	 */
648*65789Smckusick 	dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
649*65789Smckusick #ifdef DEBUG
650*65789Smckusick 	printf("lbn=%d,off=%d,bsize=%d,DEV_BSIZE=%d, dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
651*65789Smckusick 	       (daddr_t)(ip->i_number >> imp->im_bshift),
652*65789Smckusick 	       ip->i_number & imp->im_bmask,
653*65789Smckusick 	       imp->logical_block_size,
654*65789Smckusick 	       DEV_BSIZE,
655*65789Smckusick 	       dirp,
656*65789Smckusick 	       bp->b_un.b_addr,
657*65789Smckusick 	       ip->i_number,
658*65789Smckusick 	       ip->i_number & imp->im_bmask );
659*65789Smckusick #endif
660*65789Smckusick 
661*65789Smckusick 	/*
662*65789Smckusick 	 * Just make sure, we have a right one....
663*65789Smckusick 	 *   1: Check not cross boundary on block
664*65789Smckusick 	 */
665*65789Smckusick 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
666*65789Smckusick 	    > imp->logical_block_size) {
667*65789Smckusick 		brelse(bp);
668*65789Smckusick 		return EINVAL;
669*65789Smckusick 	}
670*65789Smckusick 
671*65789Smckusick 	/*
672*65789Smckusick 	 * Now get a buffer
673*65789Smckusick 	 * Abuse a namei buffer for now.
674*65789Smckusick 	 */
675*65789Smckusick 	MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
676*65789Smckusick 
677*65789Smckusick 	/*
678*65789Smckusick 	 * Ok, we just gathering a symbolic name in SL record.
679*65789Smckusick 	 */
680*65789Smckusick 	if (isofs_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
681*65789Smckusick 		FREE(symname,M_NAMEI);
682*65789Smckusick 		brelse(bp);
683*65789Smckusick 		return EINVAL;
684*65789Smckusick 	}
685*65789Smckusick 	/*
686*65789Smckusick 	 * Don't forget before you leave from home ;-)
687*65789Smckusick 	 */
688*65789Smckusick 	brelse(bp);
689*65789Smckusick 
690*65789Smckusick 	/*
691*65789Smckusick 	 * return with the symbolic name to caller's.
692*65789Smckusick 	 */
693*65789Smckusick 	error = uiomove(symname,symlen,ap->a_uio);
694*65789Smckusick 
695*65789Smckusick 	FREE(symname,M_NAMEI);
696*65789Smckusick 
697*65789Smckusick 	return error;
698*65789Smckusick }
699*65789Smckusick 
700*65789Smckusick /*
701*65789Smckusick  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
702*65789Smckusick  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
703*65789Smckusick  */
704*65789Smckusick int
705*65789Smckusick isofs_abortop(ap)
706*65789Smckusick 	struct vop_abortop_args /* {
707*65789Smckusick 		struct vnode *a_dvp;
708*65789Smckusick 		struct componentname *a_cnp;
709*65789Smckusick 	} */ *ap;
710*65789Smckusick {
711*65789Smckusick 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
712*65789Smckusick 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
713*65789Smckusick 	return 0;
714*65789Smckusick }
715*65789Smckusick 
716*65789Smckusick /*
717*65789Smckusick  * Lock an inode.
718*65789Smckusick  */
719*65789Smckusick int
720*65789Smckusick isofs_lock(ap)
721*65789Smckusick 	struct vop_lock_args /* {
722*65789Smckusick 		struct vnode *a_vp;
723*65789Smckusick 	} */ *ap;
724*65789Smckusick {
725*65789Smckusick 	register struct iso_node *ip = VTOI(ap->a_vp);
726*65789Smckusick 
727*65789Smckusick 	ISO_ILOCK(ip);
728*65789Smckusick 	return 0;
729*65789Smckusick }
730*65789Smckusick 
731*65789Smckusick /*
732*65789Smckusick  * Unlock an inode.
733*65789Smckusick  */
734*65789Smckusick int
735*65789Smckusick isofs_unlock(ap)
736*65789Smckusick 	struct vop_unlock_args /* {
737*65789Smckusick 		struct vnode *a_vp;
738*65789Smckusick 	} */ *ap;
739*65789Smckusick {
740*65789Smckusick 	register struct iso_node *ip = VTOI(ap->a_vp);
741*65789Smckusick 
742*65789Smckusick 	if (!(ip->i_flag & ILOCKED))
743*65789Smckusick 		panic("isofs_unlock NOT LOCKED");
744*65789Smckusick 	ISO_IUNLOCK(ip);
745*65789Smckusick 	return 0;
746*65789Smckusick }
747*65789Smckusick 
748*65789Smckusick /*
749*65789Smckusick  * Check for a locked inode.
750*65789Smckusick  */
751*65789Smckusick int
752*65789Smckusick isofs_islocked(ap)
753*65789Smckusick 	struct vop_islocked_args /* {
754*65789Smckusick 		struct vnode *a_vp;
755*65789Smckusick 	} */ *ap;
756*65789Smckusick {
757*65789Smckusick 
758*65789Smckusick 	if (VTOI(ap->a_vp)->i_flag & ILOCKED)
759*65789Smckusick 		return 1;
760*65789Smckusick 	return 0;
761*65789Smckusick }
762*65789Smckusick 
763*65789Smckusick /*
764*65789Smckusick  * Calculate the logical to physical mapping if not done already,
765*65789Smckusick  * then call the device strategy routine.
766*65789Smckusick  */
767*65789Smckusick int
768*65789Smckusick isofs_strategy(ap)
769*65789Smckusick 	struct vop_strategy_args /* {
770*65789Smckusick 		struct buf *a_bp;
771*65789Smckusick 	} */ *ap;
772*65789Smckusick {
773*65789Smckusick 	register struct buf *bp = ap->a_bp;
774*65789Smckusick 	register struct vnode *vp = bp->b_vp;
775*65789Smckusick 	register struct iso_node *ip;
776*65789Smckusick 	int error;
777*65789Smckusick 
778*65789Smckusick 	ip = VTOI(vp);
779*65789Smckusick 	if (vp->v_type == VBLK || vp->v_type == VCHR)
780*65789Smckusick 		panic("isofs_strategy: spec");
781*65789Smckusick 	if (bp->b_blkno == bp->b_lblkno) {
782*65789Smckusick 		if (error =
783*65789Smckusick 		    VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) {
784*65789Smckusick 			bp->b_error = error;
785*65789Smckusick 			bp->b_flags |= B_ERROR;
786*65789Smckusick 			biodone(bp);
787*65789Smckusick 			return (error);
788*65789Smckusick 		}
789*65789Smckusick 		if ((long)bp->b_blkno == -1)
790*65789Smckusick 			clrbuf(bp);
791*65789Smckusick 	}
792*65789Smckusick 	if ((long)bp->b_blkno == -1) {
793*65789Smckusick 		biodone(bp);
794*65789Smckusick 		return (0);
795*65789Smckusick 	}
796*65789Smckusick 	vp = ip->i_devvp;
797*65789Smckusick 	bp->b_dev = vp->v_rdev;
798*65789Smckusick 	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
799*65789Smckusick 	return (0);
800*65789Smckusick }
801*65789Smckusick 
802*65789Smckusick /*
803*65789Smckusick  * Print out the contents of an inode.
804*65789Smckusick  */
805*65789Smckusick int
806*65789Smckusick isofs_print(ap)
807*65789Smckusick 	struct vop_print_args /* {
808*65789Smckusick 		struct vnode *a_vp;
809*65789Smckusick 	} */ *ap;
810*65789Smckusick {
811*65789Smckusick 	printf("tag VT_ISOFS, isofs vnode\n");
812*65789Smckusick 	return 0;
813*65789Smckusick }
814*65789Smckusick 
815*65789Smckusick /*
816*65789Smckusick  * Unsupported operation
817*65789Smckusick  */
818*65789Smckusick int
819*65789Smckusick isofs_enotsupp()
820*65789Smckusick {
821*65789Smckusick 
822*65789Smckusick 	return (EOPNOTSUPP);
823*65789Smckusick }
824*65789Smckusick 
825*65789Smckusick /*
826*65789Smckusick  * Global vfs data structures for isofs
827*65789Smckusick  */
828*65789Smckusick #define isofs_create ((int (*) __P((struct  vop_create_args *)))isofs_enotsupp)
829*65789Smckusick #define isofs_mknod ((int (*) __P((struct  vop_mknod_args *)))isofs_enotsupp)
830*65789Smckusick #define isofs_setattr \
831*65789Smckusick 	((int (*) __P((struct  vop_setattr_args *)))isofs_enotsupp)
832*65789Smckusick #define isofs_write ((int (*) __P((struct  vop_write_args *)))isofs_enotsupp)
833*65789Smckusick #define isofs_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
834*65789Smckusick #define isofs_remove ((int (*) __P((struct  vop_remove_args *)))isofs_enotsupp)
835*65789Smckusick #define isofs_link ((int (*) __P((struct  vop_link_args *)))isofs_enotsupp)
836*65789Smckusick #define isofs_rename ((int (*) __P((struct  vop_rename_args *)))isofs_enotsupp)
837*65789Smckusick #define isofs_mkdir ((int (*) __P((struct  vop_mkdir_args *)))isofs_enotsupp)
838*65789Smckusick #define isofs_rmdir ((int (*) __P((struct  vop_rmdir_args *)))isofs_enotsupp)
839*65789Smckusick #define isofs_symlink \
840*65789Smckusick 	((int (*) __P((struct vop_symlink_args *)))isofs_enotsupp)
841*65789Smckusick #define isofs_pathconf \
842*65789Smckusick 	((int (*) __P((struct vop_pathconf_args *)))isofs_enotsupp)
843*65789Smckusick #define isofs_advlock \
844*65789Smckusick 	((int (*) __P((struct vop_advlock_args *)))isofs_enotsupp)
845*65789Smckusick #define isofs_blkatoff \
846*65789Smckusick 	((int (*) __P((struct  vop_blkatoff_args *)))isofs_enotsupp)
847*65789Smckusick #define isofs_valloc ((int(*) __P(( \
848*65789Smckusick 		struct vnode *pvp, \
849*65789Smckusick 		int mode, \
850*65789Smckusick 		struct ucred *cred, \
851*65789Smckusick 		struct vnode **vpp))) isofs_enotsupp)
852*65789Smckusick #define isofs_vfree ((int (*) __P((struct  vop_vfree_args *)))isofs_enotsupp)
853*65789Smckusick #define isofs_truncate \
854*65789Smckusick 	((int (*) __P((struct  vop_truncate_args *)))isofs_enotsupp)
855*65789Smckusick #define isofs_update ((int (*) __P((struct  vop_update_args *)))isofs_enotsupp)
856*65789Smckusick #define isofs_bwrite ((int (*) __P((struct  vop_bwrite_args *)))isofs_enotsupp)
857*65789Smckusick 
858*65789Smckusick /*
859*65789Smckusick  * Global vfs data structures for nfs
860*65789Smckusick  */
861*65789Smckusick int (**isofs_vnodeop_p)();
862*65789Smckusick struct vnodeopv_entry_desc isofs_vnodeop_entries[] = {
863*65789Smckusick 	{ &vop_default_desc, vn_default_error },
864*65789Smckusick 	{ &vop_lookup_desc, isofs_lookup },	/* lookup */
865*65789Smckusick 	{ &vop_create_desc, isofs_create },	/* create */
866*65789Smckusick 	{ &vop_mknod_desc, isofs_mknod },	/* mknod */
867*65789Smckusick 	{ &vop_open_desc, isofs_open },		/* open */
868*65789Smckusick 	{ &vop_close_desc, isofs_close },	/* close */
869*65789Smckusick 	{ &vop_access_desc, isofs_access },	/* access */
870*65789Smckusick 	{ &vop_getattr_desc, isofs_getattr },	/* getattr */
871*65789Smckusick 	{ &vop_setattr_desc, isofs_setattr },	/* setattr */
872*65789Smckusick 	{ &vop_read_desc, isofs_read },		/* read */
873*65789Smckusick 	{ &vop_write_desc, isofs_write },	/* write */
874*65789Smckusick 	{ &vop_ioctl_desc, isofs_ioctl },	/* ioctl */
875*65789Smckusick 	{ &vop_select_desc, isofs_select },	/* select */
876*65789Smckusick 	{ &vop_mmap_desc, isofs_mmap },		/* mmap */
877*65789Smckusick 	{ &vop_fsync_desc, isofs_fsync },	/* fsync */
878*65789Smckusick 	{ &vop_seek_desc, isofs_seek },		/* seek */
879*65789Smckusick 	{ &vop_remove_desc, isofs_remove },	/* remove */
880*65789Smckusick 	{ &vop_link_desc, isofs_link },		/* link */
881*65789Smckusick 	{ &vop_rename_desc, isofs_rename },	/* rename */
882*65789Smckusick 	{ &vop_mkdir_desc, isofs_mkdir },	/* mkdir */
883*65789Smckusick 	{ &vop_rmdir_desc, isofs_rmdir },	/* rmdir */
884*65789Smckusick 	{ &vop_symlink_desc, isofs_symlink },	/* symlink */
885*65789Smckusick 	{ &vop_readdir_desc, isofs_readdir },	/* readdir */
886*65789Smckusick 	{ &vop_readlink_desc, isofs_readlink },	/* readlink */
887*65789Smckusick 	{ &vop_abortop_desc, isofs_abortop },	/* abortop */
888*65789Smckusick 	{ &vop_inactive_desc, isofs_inactive },	/* inactive */
889*65789Smckusick 	{ &vop_reclaim_desc, isofs_reclaim },	/* reclaim */
890*65789Smckusick 	{ &vop_lock_desc, isofs_lock },		/* lock */
891*65789Smckusick 	{ &vop_unlock_desc, isofs_unlock },	/* unlock */
892*65789Smckusick 	{ &vop_bmap_desc, isofs_bmap },		/* bmap */
893*65789Smckusick 	{ &vop_strategy_desc, isofs_strategy },	/* strategy */
894*65789Smckusick 	{ &vop_print_desc, isofs_print },	/* print */
895*65789Smckusick 	{ &vop_islocked_desc, isofs_islocked },	/* islocked */
896*65789Smckusick 	{ &vop_pathconf_desc, isofs_pathconf },	/* pathconf */
897*65789Smckusick 	{ &vop_advlock_desc, isofs_advlock },	/* advlock */
898*65789Smckusick 	{ &vop_blkatoff_desc, isofs_blkatoff },	/* blkatoff */
899*65789Smckusick 	{ &vop_valloc_desc, isofs_valloc },	/* valloc */
900*65789Smckusick 	{ &vop_vfree_desc, isofs_vfree },	/* vfree */
901*65789Smckusick 	{ &vop_truncate_desc, isofs_truncate },	/* truncate */
902*65789Smckusick 	{ &vop_update_desc, isofs_update },	/* update */
903*65789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
904*65789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
905*65789Smckusick };
906*65789Smckusick struct vnodeopv_desc isofs_vnodeop_opv_desc =
907*65789Smckusick 	{ &isofs_vnodeop_p, isofs_vnodeop_entries };
908*65789Smckusick 
909*65789Smckusick /*
910*65789Smckusick  * Special device vnode ops
911*65789Smckusick  */
912*65789Smckusick int (**isofs_specop_p)();
913*65789Smckusick struct vnodeopv_entry_desc isofs_specop_entries[] = {
914*65789Smckusick 	{ &vop_default_desc, vn_default_error },
915*65789Smckusick 	{ &vop_lookup_desc, spec_lookup },	/* lookup */
916*65789Smckusick 	{ &vop_create_desc, isofs_create },	/* create */
917*65789Smckusick 	{ &vop_mknod_desc, isofs_mknod },	/* mknod */
918*65789Smckusick 	{ &vop_open_desc, spec_open },		/* open */
919*65789Smckusick 	{ &vop_close_desc, spec_close },	/* close */
920*65789Smckusick 	{ &vop_access_desc, isofs_access },	/* access */
921*65789Smckusick 	{ &vop_getattr_desc, isofs_getattr },	/* getattr */
922*65789Smckusick 	{ &vop_setattr_desc, isofs_setattr },	/* setattr */
923*65789Smckusick 	{ &vop_read_desc, spec_read },		/* read */
924*65789Smckusick 	{ &vop_write_desc, spec_write },	/* write */
925*65789Smckusick 	{ &vop_ioctl_desc, spec_ioctl },	/* ioctl */
926*65789Smckusick 	{ &vop_select_desc, spec_select },	/* select */
927*65789Smckusick 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
928*65789Smckusick 	{ &vop_fsync_desc, spec_fsync },	/* fsync */
929*65789Smckusick 	{ &vop_seek_desc, spec_seek },		/* seek */
930*65789Smckusick 	{ &vop_remove_desc, isofs_remove },	/* remove */
931*65789Smckusick 	{ &vop_link_desc, isofs_link },		/* link */
932*65789Smckusick 	{ &vop_rename_desc, isofs_rename },	/* rename */
933*65789Smckusick 	{ &vop_mkdir_desc, isofs_mkdir },	/* mkdir */
934*65789Smckusick 	{ &vop_rmdir_desc, isofs_rmdir },	/* rmdir */
935*65789Smckusick 	{ &vop_symlink_desc, isofs_symlink },	/* symlink */
936*65789Smckusick 	{ &vop_readdir_desc, spec_readdir },	/* readdir */
937*65789Smckusick 	{ &vop_readlink_desc, spec_readlink },	/* readlink */
938*65789Smckusick 	{ &vop_abortop_desc, spec_abortop },	/* abortop */
939*65789Smckusick 	{ &vop_inactive_desc, isofs_inactive },	/* inactive */
940*65789Smckusick 	{ &vop_reclaim_desc, isofs_reclaim },	/* reclaim */
941*65789Smckusick 	{ &vop_lock_desc, isofs_lock },		/* lock */
942*65789Smckusick 	{ &vop_unlock_desc, isofs_unlock },	/* unlock */
943*65789Smckusick 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
944*65789Smckusick 		/* XXX strategy: panics, should be notsupp instead? */
945*65789Smckusick 	{ &vop_strategy_desc, isofs_strategy },	/* strategy */
946*65789Smckusick 	{ &vop_print_desc, isofs_print },	/* print */
947*65789Smckusick 	{ &vop_islocked_desc, isofs_islocked },	/* islocked */
948*65789Smckusick 	{ &vop_pathconf_desc, spec_pathconf },	/* pathconf */
949*65789Smckusick 	{ &vop_advlock_desc, spec_advlock },	/* advlock */
950*65789Smckusick 	{ &vop_blkatoff_desc, spec_blkatoff },	/* blkatoff */
951*65789Smckusick 	{ &vop_valloc_desc, spec_valloc },	/* valloc */
952*65789Smckusick 	{ &vop_vfree_desc, spec_vfree },	/* vfree */
953*65789Smckusick 	{ &vop_truncate_desc, spec_truncate },	/* truncate */
954*65789Smckusick 	{ &vop_update_desc, isofs_update },	/* update */
955*65789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
956*65789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
957*65789Smckusick };
958*65789Smckusick struct vnodeopv_desc isofs_specop_opv_desc =
959*65789Smckusick 	{ &isofs_specop_p, isofs_specop_entries };
960*65789Smckusick 
961*65789Smckusick #ifdef FIFO
962*65789Smckusick int (**isofs_fifoop_p)();
963*65789Smckusick struct vnodeopv_entry_desc isofs_fifoop_entries[] = {
964*65789Smckusick 	{ &vop_default_desc, vn_default_error },
965*65789Smckusick 	{ &vop_lookup_desc, fifo_lookup },	/* lookup */
966*65789Smckusick 	{ &vop_create_desc, isofs_create },	/* create */
967*65789Smckusick 	{ &vop_mknod_desc, isofs_mknod },	/* mknod */
968*65789Smckusick 	{ &vop_open_desc, fifo_open },		/* open */
969*65789Smckusick 	{ &vop_close_desc, fifo_close },	/* close */
970*65789Smckusick 	{ &vop_access_desc, isofs_access },	/* access */
971*65789Smckusick 	{ &vop_getattr_desc, isofs_getattr },	/* getattr */
972*65789Smckusick 	{ &vop_setattr_desc, isofs_setattr },	/* setattr */
973*65789Smckusick 	{ &vop_read_desc, fifo_read },		/* read */
974*65789Smckusick 	{ &vop_write_desc, fifo_write },	/* write */
975*65789Smckusick 	{ &vop_ioctl_desc, fifo_ioctl },	/* ioctl */
976*65789Smckusick 	{ &vop_select_desc, fifo_select },	/* select */
977*65789Smckusick 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
978*65789Smckusick 	{ &vop_fsync_desc, fifo_fsync },	/* fsync */
979*65789Smckusick 	{ &vop_seek_desc, fifo_seek },		/* seek */
980*65789Smckusick 	{ &vop_remove_desc, isofs_remove },	/* remove */
981*65789Smckusick 	{ &vop_link_desc, isofs_link },		/* link */
982*65789Smckusick 	{ &vop_rename_desc, isofs_rename },	/* rename */
983*65789Smckusick 	{ &vop_mkdir_desc, isofs_mkdir },	/* mkdir */
984*65789Smckusick 	{ &vop_rmdir_desc, isofs_rmdir },	/* rmdir */
985*65789Smckusick 	{ &vop_symlink_desc, isofs_symlink },	/* symlink */
986*65789Smckusick 	{ &vop_readdir_desc, fifo_readdir },	/* readdir */
987*65789Smckusick 	{ &vop_readlink_desc, fifo_readlink },	/* readlink */
988*65789Smckusick 	{ &vop_abortop_desc, fifo_abortop },	/* abortop */
989*65789Smckusick 	{ &vop_inactive_desc, isofs_inactive },	/* inactive */
990*65789Smckusick 	{ &vop_reclaim_desc, isofs_reclaim },	/* reclaim */
991*65789Smckusick 	{ &vop_lock_desc, isofs_lock },		/* lock */
992*65789Smckusick 	{ &vop_unlock_desc, isofs_unlock },	/* unlock */
993*65789Smckusick 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
994*65789Smckusick 	{ &vop_strategy_desc, fifo_badop },	/* strategy */
995*65789Smckusick 	{ &vop_print_desc, isofs_print },	/* print */
996*65789Smckusick 	{ &vop_islocked_desc, isofs_islocked },	/* islocked */
997*65789Smckusick 	{ &vop_pathconf_desc, fifo_pathconf },	/* pathconf */
998*65789Smckusick 	{ &vop_advlock_desc, fifo_advlock },	/* advlock */
999*65789Smckusick 	{ &vop_blkatoff_desc, fifo_blkatoff },	/* blkatoff */
1000*65789Smckusick 	{ &vop_valloc_desc, fifo_valloc },	/* valloc */
1001*65789Smckusick 	{ &vop_vfree_desc, fifo_vfree },	/* vfree */
1002*65789Smckusick 	{ &vop_truncate_desc, fifo_truncate },	/* truncate */
1003*65789Smckusick 	{ &vop_update_desc, isofs_update },	/* update */
1004*65789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
1005*65789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
1006*65789Smckusick };
1007*65789Smckusick struct vnodeopv_desc isofs_fifoop_opv_desc =
1008*65789Smckusick 	{ &isofs_fifoop_p, isofs_fifoop_entries };
1009*65789Smckusick #endif /* FIFO */
1010