165789Smckusick /*-
265789Smckusick  * Copyright (c) 1994
365789Smckusick  *	The Regents of the University of California.  All rights reserved.
465789Smckusick  *
565789Smckusick  * This code is derived from software contributed to Berkeley
665789Smckusick  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
765789Smckusick  * Support code is derived from software contributed to Berkeley
865789Smckusick  * by Atsushi Murai (amurai@spec.co.jp).
965789Smckusick  *
1065789Smckusick  * %sccs.include.redist.c%
1165789Smckusick  *
12*67379Smkm  *	@(#)cd9660_vnops.c	8.6 (Berkeley) 06/14/94
1365789Smckusick  */
1465789Smckusick 
1565789Smckusick #include <sys/param.h>
1665789Smckusick #include <sys/systm.h>
1765789Smckusick #include <sys/namei.h>
1865789Smckusick #include <sys/resourcevar.h>
1965789Smckusick #include <sys/kernel.h>
2065789Smckusick #include <sys/file.h>
2165789Smckusick #include <sys/stat.h>
2265789Smckusick #include <sys/buf.h>
2365789Smckusick #include <sys/proc.h>
2465789Smckusick #include <sys/conf.h>
2565789Smckusick #include <sys/mount.h>
2665789Smckusick #include <sys/vnode.h>
2765789Smckusick #include <miscfs/specfs/specdev.h>
2865789Smckusick #include <miscfs/fifofs/fifo.h>
2965789Smckusick #include <sys/malloc.h>
3065789Smckusick #include <sys/dir.h>
3165789Smckusick 
3265789Smckusick #include <isofs/cd9660/iso.h>
3365855Smckusick #include <isofs/cd9660/cd9660_node.h>
3465789Smckusick #include <isofs/cd9660/iso_rrip.h>
3565789Smckusick 
3665789Smckusick #if 0
3765789Smckusick /*
3865789Smckusick  * Mknod vnode call
3965789Smckusick  *  Actually remap the device number
4065789Smckusick  */
4165855Smckusick cd9660_mknod(ndp, vap, cred, p)
4265789Smckusick 	struct nameidata *ndp;
4365789Smckusick 	struct ucred *cred;
4465789Smckusick 	struct vattr *vap;
4565789Smckusick 	struct proc *p;
4665789Smckusick {
4765789Smckusick #ifndef	ISODEVMAP
4865789Smckusick 	free(ndp->ni_pnbuf, M_NAMEI);
4965789Smckusick 	vput(ndp->ni_dvp);
5065789Smckusick 	vput(ndp->ni_vp);
51*67379Smkm 	return (EINVAL);
5265789Smckusick #else
5365789Smckusick 	register struct vnode *vp;
5465789Smckusick 	struct iso_node *ip;
5565789Smckusick 	struct iso_dnode *dp;
5665789Smckusick 	int error;
5765789Smckusick 
5865789Smckusick 	vp = ndp->ni_vp;
5965789Smckusick 	ip = VTOI(vp);
6065789Smckusick 
6165789Smckusick 	if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
6265789Smckusick 	    || vap->va_type != vp->v_type
6365789Smckusick 	    || (vap->va_type != VCHR && vap->va_type != VBLK)) {
6465789Smckusick 		free(ndp->ni_pnbuf, M_NAMEI);
6565789Smckusick 		vput(ndp->ni_dvp);
6665789Smckusick 		vput(ndp->ni_vp);
67*67379Smkm 		return (EINVAL);
6865789Smckusick 	}
6965789Smckusick 
7065789Smckusick 	dp = iso_dmap(ip->i_dev,ip->i_number,1);
7165789Smckusick 	if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
7265789Smckusick 		/* same as the unmapped one, delete the mapping */
7365789Smckusick 		remque(dp);
7465789Smckusick 		FREE(dp,M_CACHE);
7565789Smckusick 	} else
7665789Smckusick 		/* enter new mapping */
7765789Smckusick 		dp->d_dev = vap->va_rdev;
7865789Smckusick 
7965789Smckusick 	/*
8065789Smckusick 	 * Remove inode so that it will be reloaded by iget and
8165789Smckusick 	 * checked to see if it is an alias of an existing entry
8265789Smckusick 	 * in the inode cache.
8365789Smckusick 	 */
8465789Smckusick 	vput(vp);
8565789Smckusick 	vp->v_type = VNON;
8665789Smckusick 	vgone(vp);
8765789Smckusick 	return (0);
8865789Smckusick #endif
8965789Smckusick }
9065789Smckusick #endif
9165789Smckusick 
9265789Smckusick /*
9365789Smckusick  * Open called.
9465789Smckusick  *
9565789Smckusick  * Nothing to do.
9665789Smckusick  */
9765789Smckusick /* ARGSUSED */
9865789Smckusick int
9965855Smckusick cd9660_open(ap)
10065789Smckusick 	struct vop_open_args /* {
10165789Smckusick 		struct vnode *a_vp;
10265789Smckusick 		int  a_mode;
10365789Smckusick 		struct ucred *a_cred;
10465789Smckusick 		struct proc *a_p;
10565789Smckusick 	} */ *ap;
10665789Smckusick {
10765789Smckusick 	return (0);
10865789Smckusick }
10965789Smckusick 
11065789Smckusick /*
11165789Smckusick  * Close called
11265789Smckusick  *
11365789Smckusick  * Update the times on the inode on writeable file systems.
11465789Smckusick  */
11565789Smckusick /* ARGSUSED */
11665789Smckusick int
11765855Smckusick cd9660_close(ap)
11865789Smckusick 	struct vop_close_args /* {
11965789Smckusick 		struct vnode *a_vp;
12065789Smckusick 		int  a_fflag;
12165789Smckusick 		struct ucred *a_cred;
12265789Smckusick 		struct proc *a_p;
12365789Smckusick 	} */ *ap;
12465789Smckusick {
12565789Smckusick 	return (0);
12665789Smckusick }
12765789Smckusick 
12865789Smckusick /*
12965789Smckusick  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
13065789Smckusick  * The mode is shifted to select the owner/group/other fields. The
13165789Smckusick  * super user is granted all permissions.
13265789Smckusick  */
13365789Smckusick /* ARGSUSED */
13465855Smckusick cd9660_access(ap)
13565789Smckusick 	struct vop_access_args /* {
13665789Smckusick 		struct vnode *a_vp;
13765789Smckusick 		int  a_mode;
13865789Smckusick 		struct ucred *a_cred;
13965789Smckusick 		struct proc *a_p;
14065789Smckusick 	} */ *ap;
14165789Smckusick {
142*67379Smkm 	struct iso_node *ip = VTOI(ap->a_vp);
143*67379Smkm 	struct ucred *cred = ap->a_cred;
144*67379Smkm 	mode_t mask, mode = ap->a_mode;
145*67379Smkm 	gid_t *gp;
146*67379Smkm 	int i, error;
147*67379Smkm 
148*67379Smkm 	/* User id 0 always gets access. */
149*67379Smkm 	if (cred->cr_uid == 0)
150*67379Smkm 		return (0);
151*67379Smkm 
152*67379Smkm 	mask = 0;
153*67379Smkm 
154*67379Smkm 	/* Otherwise, check the owner. */
155*67379Smkm 	if (cred->cr_uid == ip->inode.iso_uid) {
156*67379Smkm 		if (mode & VEXEC)
157*67379Smkm 			mask |= S_IXUSR;
158*67379Smkm 		if (mode & VREAD)
159*67379Smkm 			mask |= S_IRUSR;
160*67379Smkm 		if (mode & VWRITE)
161*67379Smkm 			mask |= S_IWUSR;
162*67379Smkm 		return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
163*67379Smkm 	}
164*67379Smkm 
165*67379Smkm 	/* Otherwise, check the groups. */
166*67379Smkm 	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
167*67379Smkm 		if (ip->inode.iso_gid == *gp) {
168*67379Smkm 			if (mode & VEXEC)
169*67379Smkm 				mask |= S_IXGRP;
170*67379Smkm 			if (mode & VREAD)
171*67379Smkm 				mask |= S_IRGRP;
172*67379Smkm 			if (mode & VWRITE)
173*67379Smkm 				mask |= S_IWGRP;
174*67379Smkm 			return ((ip->inode.iso_mode & mask) == mask ?
175*67379Smkm 			    0 : EACCES);
176*67379Smkm 		}
177*67379Smkm 
178*67379Smkm 	/* Otherwise, check everyone else. */
179*67379Smkm 	if (mode & VEXEC)
180*67379Smkm 		mask |= S_IXOTH;
181*67379Smkm 	if (mode & VREAD)
182*67379Smkm 		mask |= S_IROTH;
183*67379Smkm 	if (mode & VWRITE)
184*67379Smkm 		mask |= S_IWOTH;
185*67379Smkm 	return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
18665789Smckusick }
18765789Smckusick 
18865855Smckusick cd9660_getattr(ap)
18965789Smckusick 	struct vop_getattr_args /* {
19065789Smckusick 		struct vnode *a_vp;
19165789Smckusick 		struct vattr *a_vap;
19265789Smckusick 		struct ucred *a_cred;
19365789Smckusick 		struct proc *a_p;
19465789Smckusick 	} */ *ap;
19565789Smckusick 
19665789Smckusick {
19765789Smckusick 	struct vnode *vp = ap->a_vp;
19865789Smckusick 	register struct vattr *vap = ap->a_vap;
19965789Smckusick 	register struct iso_node *ip = VTOI(vp);
20065789Smckusick 	int i;
20165789Smckusick 
20265789Smckusick 	vap->va_fsid	= ip->i_dev;
20365789Smckusick 	vap->va_fileid	= ip->i_number;
20465789Smckusick 
20565789Smckusick 	vap->va_mode	= ip->inode.iso_mode;
20665789Smckusick 	vap->va_nlink	= ip->inode.iso_links;
20765789Smckusick 	vap->va_uid	= ip->inode.iso_uid;
20865789Smckusick 	vap->va_gid	= ip->inode.iso_gid;
20965789Smckusick 	vap->va_atime	= ip->inode.iso_atime;
21065789Smckusick 	vap->va_mtime	= ip->inode.iso_mtime;
21165789Smckusick 	vap->va_ctime	= ip->inode.iso_ctime;
21265789Smckusick 	vap->va_rdev	= ip->inode.iso_rdev;
21365789Smckusick 
21465789Smckusick 	vap->va_size	= (u_quad_t) ip->i_size;
21565789Smckusick 	vap->va_flags	= 0;
21665789Smckusick 	vap->va_gen = 1;
21765789Smckusick 	vap->va_blocksize = ip->i_mnt->logical_block_size;
21865789Smckusick 	vap->va_bytes	= (u_quad_t) ip->i_size;
21965789Smckusick 	vap->va_type	= vp->v_type;
22065789Smckusick 	return (0);
22165789Smckusick }
22265789Smckusick 
22365789Smckusick #if ISO_DEFAULT_BLOCK_SIZE >= NBPG
22465789Smckusick #ifdef DEBUG
22565789Smckusick extern int doclusterread;
22665789Smckusick #else
22765789Smckusick #define doclusterread 1
22865789Smckusick #endif
22965789Smckusick #else
23065789Smckusick /* XXX until cluster routines can handle block sizes less than one page */
23165789Smckusick #define doclusterread 0
23265789Smckusick #endif
23365789Smckusick 
23465789Smckusick /*
23565789Smckusick  * Vnode op for reading.
23665789Smckusick  */
23765855Smckusick cd9660_read(ap)
23865789Smckusick 	struct vop_read_args /* {
23965789Smckusick 		struct vnode *a_vp;
24065789Smckusick 		struct uio *a_uio;
24165789Smckusick 		int a_ioflag;
24265789Smckusick 		struct ucred *a_cred;
24365789Smckusick 	} */ *ap;
24465789Smckusick {
24565789Smckusick 	struct vnode *vp = ap->a_vp;
24665789Smckusick 	register struct uio *uio = ap->a_uio;
24765789Smckusick 	register struct iso_node *ip = VTOI(vp);
24865789Smckusick 	register struct iso_mnt *imp;
24965789Smckusick 	struct buf *bp;
25065789Smckusick 	daddr_t lbn, bn, rablock;
25165789Smckusick 	off_t diff;
25265789Smckusick 	int rasize, error = 0;
25365789Smckusick 	long size, n, on;
25465789Smckusick 
25565789Smckusick 	if (uio->uio_resid == 0)
25665789Smckusick 		return (0);
25765789Smckusick 	if (uio->uio_offset < 0)
25865789Smckusick 		return (EINVAL);
25965789Smckusick 	ip->i_flag |= IACC;
26065789Smckusick 	imp = ip->i_mnt;
26165789Smckusick 	do {
26265789Smckusick 		lbn = iso_lblkno(imp, uio->uio_offset);
26365789Smckusick 		on = iso_blkoff(imp, uio->uio_offset);
26465789Smckusick 		n = min((unsigned)(imp->logical_block_size - on),
26565789Smckusick 			uio->uio_resid);
26665789Smckusick 		diff = (off_t)ip->i_size - uio->uio_offset;
26765789Smckusick 		if (diff <= 0)
26865789Smckusick 			return (0);
26965789Smckusick 		if (diff < n)
27065789Smckusick 			n = diff;
27165789Smckusick 		size = iso_blksize(imp, ip, lbn);
27265789Smckusick 		rablock = lbn + 1;
27365789Smckusick 		if (doclusterread) {
27465789Smckusick 			if (iso_lblktosize(imp, rablock) <= ip->i_size)
27565789Smckusick 				error = cluster_read(vp, (off_t)ip->i_size,
27665789Smckusick 						     lbn, size, NOCRED, &bp);
27765789Smckusick 			else
27865789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
27965789Smckusick 		} else {
28065789Smckusick 			if (vp->v_lastr + 1 == lbn &&
28165789Smckusick 			    iso_lblktosize(imp, rablock) < ip->i_size) {
28265789Smckusick 				rasize = iso_blksize(imp, ip, rablock);
28365789Smckusick 				error = breadn(vp, lbn, size, &rablock,
28465789Smckusick 					       &rasize, 1, NOCRED, &bp);
28565789Smckusick 			} else
28665789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
28765789Smckusick 		}
28865789Smckusick 		vp->v_lastr = lbn;
28965789Smckusick 		n = min(n, size - bp->b_resid);
29065789Smckusick 		if (error) {
29165789Smckusick 			brelse(bp);
29265789Smckusick 			return (error);
29365789Smckusick 		}
29465789Smckusick 
29565789Smckusick 		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
29665789Smckusick 		if (n + on == imp->logical_block_size ||
29765789Smckusick 		    uio->uio_offset == (off_t)ip->i_size)
29865789Smckusick 			bp->b_flags |= B_AGE;
29965789Smckusick 		brelse(bp);
30065789Smckusick 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
30165789Smckusick 	return (error);
30265789Smckusick }
30365789Smckusick 
30465789Smckusick /* ARGSUSED */
30565789Smckusick int
30665855Smckusick cd9660_ioctl(ap)
30765789Smckusick 	struct vop_ioctl_args /* {
30865789Smckusick 		struct vnode *a_vp;
30965789Smckusick 		int  a_command;
31065789Smckusick 		caddr_t  a_data;
31165789Smckusick 		int  a_fflag;
31265789Smckusick 		struct ucred *a_cred;
31365789Smckusick 		struct proc *a_p;
31465789Smckusick 	} */ *ap;
31565789Smckusick {
31665789Smckusick 	printf("You did ioctl for isofs !!\n");
31765789Smckusick 	return (ENOTTY);
31865789Smckusick }
31965789Smckusick 
32065789Smckusick /* ARGSUSED */
32165789Smckusick int
32265855Smckusick cd9660_select(ap)
32365789Smckusick 	struct vop_select_args /* {
32465789Smckusick 		struct vnode *a_vp;
32565789Smckusick 		int  a_which;
32665789Smckusick 		int  a_fflags;
32765789Smckusick 		struct ucred *a_cred;
32865789Smckusick 		struct proc *a_p;
32965789Smckusick 	} */ *ap;
33065789Smckusick {
33165789Smckusick 
33265789Smckusick 	/*
33365789Smckusick 	 * We should really check to see if I/O is possible.
33465789Smckusick 	 */
33565789Smckusick 	return (1);
33665789Smckusick }
33765789Smckusick 
33865789Smckusick /*
33965789Smckusick  * Mmap a file
34065789Smckusick  *
34165789Smckusick  * NB Currently unsupported.
34265789Smckusick  */
34365789Smckusick /* ARGSUSED */
34465789Smckusick int
34565855Smckusick cd9660_mmap(ap)
34665789Smckusick 	struct vop_mmap_args /* {
34765789Smckusick 		struct vnode *a_vp;
34865789Smckusick 		int  a_fflags;
34965789Smckusick 		struct ucred *a_cred;
35065789Smckusick 		struct proc *a_p;
35165789Smckusick 	} */ *ap;
35265789Smckusick {
35365789Smckusick 
35465789Smckusick 	return (EINVAL);
35565789Smckusick }
35665789Smckusick 
35765789Smckusick /*
35865789Smckusick  * Seek on a file
35965789Smckusick  *
36065789Smckusick  * Nothing to do, so just return.
36165789Smckusick  */
36265789Smckusick /* ARGSUSED */
36365789Smckusick int
36465855Smckusick cd9660_seek(ap)
36565789Smckusick 	struct vop_seek_args /* {
36665789Smckusick 		struct vnode *a_vp;
36765789Smckusick 		off_t  a_oldoff;
36865789Smckusick 		off_t  a_newoff;
36965789Smckusick 		struct ucred *a_cred;
37065789Smckusick 	} */ *ap;
37165789Smckusick {
37265789Smckusick 
37365789Smckusick 	return (0);
37465789Smckusick }
37565789Smckusick 
37665789Smckusick /*
37765789Smckusick  * Structure for reading directories
37865789Smckusick  */
37965789Smckusick struct isoreaddir {
38065789Smckusick 	struct dirent saveent;
38165789Smckusick 	struct dirent assocent;
38265789Smckusick 	struct dirent current;
38365789Smckusick 	off_t saveoff;
38465789Smckusick 	off_t assocoff;
38565789Smckusick 	off_t curroff;
38665789Smckusick 	struct uio *uio;
38765789Smckusick 	off_t uio_off;
38867370Smckusick 	int eofflag;
38967370Smckusick 	u_long *cookies;
39065789Smckusick 	int ncookies;
39165789Smckusick };
39265789Smckusick 
39365789Smckusick static int
39465789Smckusick iso_uiodir(idp,dp,off)
39565789Smckusick 	struct isoreaddir *idp;
39665789Smckusick 	struct dirent *dp;
39765789Smckusick 	off_t off;
39865789Smckusick {
39965789Smckusick 	int error;
40065789Smckusick 
40165789Smckusick 	dp->d_name[dp->d_namlen] = 0;
40265789Smckusick 	dp->d_reclen = DIRSIZ(dp);
40365789Smckusick 
40465789Smckusick 	if (idp->uio->uio_resid < dp->d_reclen) {
40567370Smckusick 		idp->eofflag = 0;
40667370Smckusick 		return (-1);
40765789Smckusick 	}
40865789Smckusick 
40967370Smckusick 	if (idp->cookies) {
41065789Smckusick 		if (idp->ncookies <= 0) {
41167370Smckusick 			idp->eofflag = 0;
41267370Smckusick 			return (-1);
41365789Smckusick 		}
41465789Smckusick 
41567370Smckusick 		*idp->cookies++ = off;
41665789Smckusick 		--idp->ncookies;
41765789Smckusick 	}
41865789Smckusick 
41965789Smckusick 	if (error = uiomove(dp,dp->d_reclen,idp->uio))
42067370Smckusick 		return (error);
42165789Smckusick 	idp->uio_off = off;
42267370Smckusick 	return (0);
42365789Smckusick }
42465789Smckusick 
42565789Smckusick static int
42665789Smckusick iso_shipdir(idp)
42765789Smckusick 	struct isoreaddir *idp;
42865789Smckusick {
42965789Smckusick 	struct dirent *dp;
43065789Smckusick 	int cl, sl, assoc;
43165789Smckusick 	int error;
43265789Smckusick 	char *cname, *sname;
43365789Smckusick 
43465789Smckusick 	cl = idp->current.d_namlen;
43565789Smckusick 	cname = idp->current.d_name;
43665789Smckusick 	if (assoc = cl > 1 && *cname == ASSOCCHAR) {
43765789Smckusick 		cl--;
43865789Smckusick 		cname++;
43965789Smckusick 	}
44065789Smckusick 
44165789Smckusick 	dp = &idp->saveent;
44265789Smckusick 	sname = dp->d_name;
44365789Smckusick 	if (!(sl = dp->d_namlen)) {
44465789Smckusick 		dp = &idp->assocent;
44565789Smckusick 		sname = dp->d_name + 1;
44665789Smckusick 		sl = dp->d_namlen - 1;
44765789Smckusick 	}
44865789Smckusick 	if (sl > 0) {
44965789Smckusick 		if (sl != cl
45065789Smckusick 		    || bcmp(sname,cname,sl)) {
45165789Smckusick 			if (idp->assocent.d_namlen) {
45265789Smckusick 				if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
453*67379Smkm 					return (error);
45465789Smckusick 				idp->assocent.d_namlen = 0;
45565789Smckusick 			}
45665789Smckusick 			if (idp->saveent.d_namlen) {
45765789Smckusick 				if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
458*67379Smkm 					return (error);
45965789Smckusick 				idp->saveent.d_namlen = 0;
46065789Smckusick 			}
46165789Smckusick 		}
46265789Smckusick 	}
46365789Smckusick 	idp->current.d_reclen = DIRSIZ(&idp->current);
46465789Smckusick 	if (assoc) {
46565789Smckusick 		idp->assocoff = idp->curroff;
46665789Smckusick 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
46765789Smckusick 	} else {
46865789Smckusick 		idp->saveoff = idp->curroff;
46965789Smckusick 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
47065789Smckusick 	}
471*67379Smkm 	return (0);
47265789Smckusick }
47365789Smckusick 
47465789Smckusick /*
47565789Smckusick  * Vnode op for readdir
476*67379Smkm  * XXX make sure everything still works now that eofflagp and cookies
47765789Smckusick  * are no longer args.
47865789Smckusick  */
47965789Smckusick int
48065855Smckusick cd9660_readdir(ap)
48165789Smckusick 	struct vop_readdir_args /* {
48265789Smckusick 		struct vnode *a_vp;
48365789Smckusick 		struct uio *a_uio;
48465789Smckusick 		struct ucred *a_cred;
48567370Smckusick 		int *a_eofflag;
48667370Smckusick 		u_long *a_cookies;
48767370Smckusick 		int a_ncookies;
48865789Smckusick 	} */ *ap;
48965789Smckusick {
49065789Smckusick 	register struct uio *uio = ap->a_uio;
49165789Smckusick 	struct isoreaddir *idp;
49265789Smckusick 	int entryoffsetinblock;
49365789Smckusick 	int error = 0;
49465789Smckusick 	int endsearch;
49565789Smckusick 	struct iso_directory_record *ep;
49665789Smckusick 	u_short elen;
49765789Smckusick 	int reclen;
49865789Smckusick 	struct iso_mnt *imp;
49965789Smckusick 	struct iso_node *ip;
50065789Smckusick 	struct buf *bp = NULL;
50165789Smckusick 
50265789Smckusick 	ip = VTOI(ap->a_vp);
50365789Smckusick 	imp = ip->i_mnt;
50465789Smckusick 
50565789Smckusick 	MALLOC(idp,struct isoreaddir *,sizeof(*idp),M_TEMP,M_WAITOK);
50665789Smckusick 	idp->saveent.d_namlen = 0;
50765789Smckusick 	idp->assocent.d_namlen = 0;
50865789Smckusick 	idp->uio = uio;
50967370Smckusick 	idp->eofflag = 1;
51067370Smckusick 	idp->cookies = ap->a_cookies;
51167370Smckusick 	idp->ncookies = ap->a_ncookies;
51265789Smckusick 	idp->curroff = uio->uio_offset;
51365789Smckusick 
51465789Smckusick 	entryoffsetinblock = iso_blkoff(imp, idp->curroff);
51565789Smckusick 	if (entryoffsetinblock != 0) {
51665789Smckusick 		if (error = iso_blkatoff(ip, idp->curroff, &bp)) {
51765789Smckusick 			FREE(idp,M_TEMP);
51865789Smckusick 			return (error);
51965789Smckusick 		}
52065789Smckusick 	}
52165789Smckusick 
52265789Smckusick 	endsearch = ip->i_size;
52365789Smckusick 
52465789Smckusick 	while (idp->curroff < endsearch) {
52565789Smckusick 		/*
52665789Smckusick 		 * If offset is on a block boundary,
52765789Smckusick 		 * read the next directory block.
52865789Smckusick 		 * Release previous if it exists.
52965789Smckusick 		 */
53065789Smckusick 
53165789Smckusick 		if (iso_blkoff(imp, idp->curroff) == 0) {
53265789Smckusick 			if (bp != NULL)
53365789Smckusick 				brelse(bp);
53465789Smckusick 			if (error = iso_blkatoff(ip, idp->curroff, &bp))
53565789Smckusick 				break;
53665789Smckusick 			entryoffsetinblock = 0;
53765789Smckusick 		}
53865789Smckusick 		/*
53965789Smckusick 		 * Get pointer to next entry.
54065789Smckusick 		 */
54165789Smckusick 
54265789Smckusick 		ep = (struct iso_directory_record *)
54365789Smckusick 			(bp->b_un.b_addr + entryoffsetinblock);
54465789Smckusick 
54565789Smckusick 		reclen = isonum_711 (ep->length);
54665789Smckusick 		if (reclen == 0) {
54765789Smckusick 			/* skip to next block, if any */
54865789Smckusick 			idp->curroff = roundup (idp->curroff,
54965789Smckusick 						imp->logical_block_size);
55065789Smckusick 			continue;
55165789Smckusick 		}
55265789Smckusick 
55365789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
55465789Smckusick 			error = EINVAL;
55565789Smckusick 			/* illegal entry, stop */
55665789Smckusick 			break;
55765789Smckusick 		}
55865789Smckusick 
55965789Smckusick 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
56065789Smckusick 			error = EINVAL;
56165789Smckusick 			/* illegal directory, so stop looking */
56265789Smckusick 			break;
56365789Smckusick 		}
56465789Smckusick 
56565789Smckusick 		idp->current.d_namlen = isonum_711 (ep->name_len);
56665789Smckusick 		if (isonum_711(ep->flags)&2)
56765789Smckusick 			isodirino(&idp->current.d_fileno,ep,imp);
56865789Smckusick 		else
56965789Smckusick 			idp->current.d_fileno = dbtob(bp->b_blkno) +
57065789Smckusick 				idp->curroff;
57165789Smckusick 
57265789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
57365789Smckusick 			error = EINVAL;
57465789Smckusick 			/* illegal entry, stop */
57565789Smckusick 			break;
57665789Smckusick 		}
57765789Smckusick 
57865789Smckusick 		idp->curroff += reclen;
57965789Smckusick 		/*
58065789Smckusick 		 *
58165789Smckusick 		 */
58265789Smckusick 		switch (imp->iso_ftype) {
58365789Smckusick 		case ISO_FTYPE_RRIP:
58467114Smckusick 			cd9660_rrip_getname(ep,idp->current.d_name, &elen,
58565789Smckusick 					   &idp->current.d_fileno,imp);
58667114Smckusick 			idp->current.d_namlen = (u_char)elen;
58765789Smckusick 			if (idp->current.d_namlen)
58865789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
58965789Smckusick 			break;
59065789Smckusick 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
59165789Smckusick 			strcpy(idp->current.d_name,"..");
59265789Smckusick 			switch (ep->name[0]) {
59365789Smckusick 			case 0:
59465789Smckusick 				idp->current.d_namlen = 1;
59565789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
59665789Smckusick 				break;
59765789Smckusick 			case 1:
59865789Smckusick 				idp->current.d_namlen = 2;
59965789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
60065789Smckusick 				break;
60165789Smckusick 			default:
60265789Smckusick 				isofntrans(ep->name,idp->current.d_namlen,
60365789Smckusick 					   idp->current.d_name, &elen,
60465789Smckusick 					   imp->iso_ftype == ISO_FTYPE_9660,
60565789Smckusick 					   isonum_711(ep->flags)&4);
60665789Smckusick 				idp->current.d_namlen = (u_char)elen;
60765789Smckusick 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
60865789Smckusick 					error = iso_shipdir(idp);
60965789Smckusick 				else
61065789Smckusick 					error = iso_uiodir(idp,&idp->current,idp->curroff);
61165789Smckusick 				break;
61265789Smckusick 			}
61365789Smckusick 		}
61465789Smckusick 		if (error)
61565789Smckusick 			break;
61665789Smckusick 
61765789Smckusick 		entryoffsetinblock += reclen;
61865789Smckusick 	}
61965789Smckusick 
62065789Smckusick 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
62165789Smckusick 		idp->current.d_namlen = 0;
62265789Smckusick 		error = iso_shipdir(idp);
62365789Smckusick 	}
62465789Smckusick 	if (error < 0)
62565789Smckusick 		error = 0;
62665789Smckusick 
62765789Smckusick 	if (bp)
62865789Smckusick 		brelse (bp);
62965789Smckusick 
63065789Smckusick 	uio->uio_offset = idp->uio_off;
63167370Smckusick 	*ap->a_eofflag = idp->eofflag;
63265789Smckusick 
63365789Smckusick 	FREE(idp,M_TEMP);
63465789Smckusick 
63565789Smckusick 	return (error);
63665789Smckusick }
63765789Smckusick 
63865789Smckusick /*
63965789Smckusick  * Return target name of a symbolic link
64065789Smckusick  * Shouldn't we get the parent vnode and read the data from there?
64165855Smckusick  * This could eventually result in deadlocks in cd9660_lookup.
64265789Smckusick  * But otherwise the block read here is in the block buffer two times.
64365789Smckusick  */
64465789Smckusick typedef struct iso_directory_record ISODIR;
64565789Smckusick typedef struct iso_node             ISONODE;
64665789Smckusick typedef struct iso_mnt              ISOMNT;
64765789Smckusick int
64865855Smckusick cd9660_readlink(ap)
64965789Smckusick 	struct vop_readlink_args /* {
65065789Smckusick 		struct vnode *a_vp;
65165789Smckusick 		struct uio *a_uio;
65265789Smckusick 		struct ucred *a_cred;
65365789Smckusick 	} */ *ap;
65465789Smckusick {
65565789Smckusick 	ISONODE	*ip;
65665789Smckusick 	ISODIR	*dirp;
65765789Smckusick 	ISOMNT	*imp;
65865789Smckusick 	struct	buf *bp;
65965789Smckusick 	u_short	symlen;
66065789Smckusick 	int	error;
66165789Smckusick 	char	*symname;
66265789Smckusick 	ino_t	ino;
66365789Smckusick 
66465789Smckusick 	ip  = VTOI(ap->a_vp);
66565789Smckusick 	imp = ip->i_mnt;
66665789Smckusick 
66765789Smckusick 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
668*67379Smkm 		return (EINVAL);
66965789Smckusick 
67065789Smckusick 	/*
67165789Smckusick 	 * Get parents directory record block that this inode included.
67265789Smckusick 	 */
67365789Smckusick 	error = bread(imp->im_devvp,
674*67379Smkm 		      (daddr_t)((ip->i_number&~imp->im_bmask) / DEV_BSIZE),
67565789Smckusick 		      imp->logical_block_size,
67665789Smckusick 		      NOCRED,
67765789Smckusick 		      &bp);
67865789Smckusick 	if (error) {
67965789Smckusick 		brelse(bp);
680*67379Smkm 		return (EINVAL);
68165789Smckusick 	}
68265789Smckusick 
68365789Smckusick 	/*
68465789Smckusick 	 * Setup the directory pointer for this inode
68565789Smckusick 	 */
68665789Smckusick 	dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask));
687*67379Smkm 
68865789Smckusick 	/*
68965789Smckusick 	 * Just make sure, we have a right one....
69065789Smckusick 	 *   1: Check not cross boundary on block
69165789Smckusick 	 */
69265789Smckusick 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
69365789Smckusick 	    > imp->logical_block_size) {
69465789Smckusick 		brelse(bp);
695*67379Smkm 		return (EINVAL);
69665789Smckusick 	}
69765789Smckusick 
69865789Smckusick 	/*
69965789Smckusick 	 * Now get a buffer
70065789Smckusick 	 * Abuse a namei buffer for now.
70165789Smckusick 	 */
70265789Smckusick 	MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK);
70365789Smckusick 
70465789Smckusick 	/*
70565789Smckusick 	 * Ok, we just gathering a symbolic name in SL record.
70665789Smckusick 	 */
70765855Smckusick 	if (cd9660_rrip_getsymname(dirp,symname,&symlen,imp) == 0) {
70865789Smckusick 		FREE(symname,M_NAMEI);
70965789Smckusick 		brelse(bp);
710*67379Smkm 		return (EINVAL);
71165789Smckusick 	}
71265789Smckusick 	/*
71365789Smckusick 	 * Don't forget before you leave from home ;-)
71465789Smckusick 	 */
71565789Smckusick 	brelse(bp);
71665789Smckusick 
71765789Smckusick 	/*
71865789Smckusick 	 * return with the symbolic name to caller's.
71965789Smckusick 	 */
72065789Smckusick 	error = uiomove(symname,symlen,ap->a_uio);
72165789Smckusick 
72265789Smckusick 	FREE(symname,M_NAMEI);
72365789Smckusick 
724*67379Smkm 	return (error);
72565789Smckusick }
72665789Smckusick 
72765789Smckusick /*
72865789Smckusick  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
72965789Smckusick  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
73065789Smckusick  */
73165789Smckusick int
73265855Smckusick cd9660_abortop(ap)
73365789Smckusick 	struct vop_abortop_args /* {
73465789Smckusick 		struct vnode *a_dvp;
73565789Smckusick 		struct componentname *a_cnp;
73665789Smckusick 	} */ *ap;
73765789Smckusick {
73865789Smckusick 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
73965789Smckusick 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
740*67379Smkm 	return (0);
74165789Smckusick }
74265789Smckusick 
74365789Smckusick /*
74465789Smckusick  * Lock an inode.
74565789Smckusick  */
74665789Smckusick int
74765855Smckusick cd9660_lock(ap)
74865789Smckusick 	struct vop_lock_args /* {
74965789Smckusick 		struct vnode *a_vp;
75065789Smckusick 	} */ *ap;
75165789Smckusick {
75265789Smckusick 	register struct iso_node *ip = VTOI(ap->a_vp);
75365789Smckusick 
75465789Smckusick 	ISO_ILOCK(ip);
755*67379Smkm 	return (0);
75665789Smckusick }
75765789Smckusick 
75865789Smckusick /*
75965789Smckusick  * Unlock an inode.
76065789Smckusick  */
76165789Smckusick int
76265855Smckusick cd9660_unlock(ap)
76365789Smckusick 	struct vop_unlock_args /* {
76465789Smckusick 		struct vnode *a_vp;
76565789Smckusick 	} */ *ap;
76665789Smckusick {
76765789Smckusick 	register struct iso_node *ip = VTOI(ap->a_vp);
76865789Smckusick 
76965789Smckusick 	if (!(ip->i_flag & ILOCKED))
77065855Smckusick 		panic("cd9660_unlock NOT LOCKED");
77165789Smckusick 	ISO_IUNLOCK(ip);
772*67379Smkm 	return (0);
77365789Smckusick }
77465789Smckusick 
77565789Smckusick /*
77665789Smckusick  * Check for a locked inode.
77765789Smckusick  */
77865789Smckusick int
77965855Smckusick cd9660_islocked(ap)
78065789Smckusick 	struct vop_islocked_args /* {
78165789Smckusick 		struct vnode *a_vp;
78265789Smckusick 	} */ *ap;
78365789Smckusick {
78465789Smckusick 
78565789Smckusick 	if (VTOI(ap->a_vp)->i_flag & ILOCKED)
786*67379Smkm 		return (1);
787*67379Smkm 	return (0);
78865789Smckusick }
78965789Smckusick 
79065789Smckusick /*
79165789Smckusick  * Calculate the logical to physical mapping if not done already,
79265789Smckusick  * then call the device strategy routine.
79365789Smckusick  */
79465789Smckusick int
79565855Smckusick cd9660_strategy(ap)
79665789Smckusick 	struct vop_strategy_args /* {
79765789Smckusick 		struct buf *a_bp;
79865789Smckusick 	} */ *ap;
79965789Smckusick {
80065789Smckusick 	register struct buf *bp = ap->a_bp;
80165789Smckusick 	register struct vnode *vp = bp->b_vp;
80265789Smckusick 	register struct iso_node *ip;
80365789Smckusick 	int error;
80465789Smckusick 
80565789Smckusick 	ip = VTOI(vp);
80665789Smckusick 	if (vp->v_type == VBLK || vp->v_type == VCHR)
80765855Smckusick 		panic("cd9660_strategy: spec");
80865789Smckusick 	if (bp->b_blkno == bp->b_lblkno) {
80965789Smckusick 		if (error =
81065789Smckusick 		    VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) {
81165789Smckusick 			bp->b_error = error;
81265789Smckusick 			bp->b_flags |= B_ERROR;
81365789Smckusick 			biodone(bp);
81465789Smckusick 			return (error);
81565789Smckusick 		}
81665789Smckusick 		if ((long)bp->b_blkno == -1)
81765789Smckusick 			clrbuf(bp);
81865789Smckusick 	}
81965789Smckusick 	if ((long)bp->b_blkno == -1) {
82065789Smckusick 		biodone(bp);
82165789Smckusick 		return (0);
82265789Smckusick 	}
82365789Smckusick 	vp = ip->i_devvp;
82465789Smckusick 	bp->b_dev = vp->v_rdev;
82565789Smckusick 	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
82665789Smckusick 	return (0);
82765789Smckusick }
82865789Smckusick 
82965789Smckusick /*
83065789Smckusick  * Print out the contents of an inode.
83165789Smckusick  */
83265789Smckusick int
83365855Smckusick cd9660_print(ap)
83465789Smckusick 	struct vop_print_args /* {
83565789Smckusick 		struct vnode *a_vp;
83665789Smckusick 	} */ *ap;
83765789Smckusick {
83865789Smckusick 	printf("tag VT_ISOFS, isofs vnode\n");
839*67379Smkm 	return (0);
84065789Smckusick }
84165789Smckusick 
84265789Smckusick /*
84365789Smckusick  * Unsupported operation
84465789Smckusick  */
84565789Smckusick int
84665855Smckusick cd9660_enotsupp()
84765789Smckusick {
84865789Smckusick 
84965789Smckusick 	return (EOPNOTSUPP);
85065789Smckusick }
85165789Smckusick 
85265789Smckusick /*
85365789Smckusick  * Global vfs data structures for isofs
85465789Smckusick  */
85565855Smckusick #define cd9660_create \
85665855Smckusick 	((int (*) __P((struct  vop_create_args *)))cd9660_enotsupp)
85765855Smckusick #define cd9660_mknod ((int (*) __P((struct  vop_mknod_args *)))cd9660_enotsupp)
85865855Smckusick #define cd9660_setattr \
85965855Smckusick 	((int (*) __P((struct  vop_setattr_args *)))cd9660_enotsupp)
86065855Smckusick #define cd9660_write ((int (*) __P((struct  vop_write_args *)))cd9660_enotsupp)
86165855Smckusick #define cd9660_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
86265855Smckusick #define cd9660_remove \
86365855Smckusick 	((int (*) __P((struct  vop_remove_args *)))cd9660_enotsupp)
86465855Smckusick #define cd9660_link ((int (*) __P((struct  vop_link_args *)))cd9660_enotsupp)
86565855Smckusick #define cd9660_rename \
86665855Smckusick 	((int (*) __P((struct  vop_rename_args *)))cd9660_enotsupp)
86765855Smckusick #define cd9660_mkdir ((int (*) __P((struct  vop_mkdir_args *)))cd9660_enotsupp)
86865855Smckusick #define cd9660_rmdir ((int (*) __P((struct  vop_rmdir_args *)))cd9660_enotsupp)
86965855Smckusick #define cd9660_symlink \
87065855Smckusick 	((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp)
87165855Smckusick #define cd9660_pathconf \
87265855Smckusick 	((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp)
87365855Smckusick #define cd9660_advlock \
87465855Smckusick 	((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
87565855Smckusick #define cd9660_blkatoff \
87665855Smckusick 	((int (*) __P((struct  vop_blkatoff_args *)))cd9660_enotsupp)
87765855Smckusick #define cd9660_valloc ((int(*) __P(( \
87865789Smckusick 		struct vnode *pvp, \
87965789Smckusick 		int mode, \
88065789Smckusick 		struct ucred *cred, \
88165855Smckusick 		struct vnode **vpp))) cd9660_enotsupp)
88265855Smckusick #define cd9660_vfree ((int (*) __P((struct  vop_vfree_args *)))cd9660_enotsupp)
88365855Smckusick #define cd9660_truncate \
88465855Smckusick 	((int (*) __P((struct  vop_truncate_args *)))cd9660_enotsupp)
88565855Smckusick #define cd9660_update \
88665855Smckusick 	((int (*) __P((struct  vop_update_args *)))cd9660_enotsupp)
88765855Smckusick #define cd9660_bwrite \
88865855Smckusick 	((int (*) __P((struct  vop_bwrite_args *)))cd9660_enotsupp)
88965789Smckusick 
89065789Smckusick /*
89165789Smckusick  * Global vfs data structures for nfs
89265789Smckusick  */
89365855Smckusick int (**cd9660_vnodeop_p)();
89465855Smckusick struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
89565789Smckusick 	{ &vop_default_desc, vn_default_error },
89665855Smckusick 	{ &vop_lookup_desc, cd9660_lookup },	/* lookup */
89765855Smckusick 	{ &vop_create_desc, cd9660_create },	/* create */
89865855Smckusick 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
89965855Smckusick 	{ &vop_open_desc, cd9660_open },	/* open */
90065855Smckusick 	{ &vop_close_desc, cd9660_close },	/* close */
90165855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
90265855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
90365855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
90465855Smckusick 	{ &vop_read_desc, cd9660_read },	/* read */
90565855Smckusick 	{ &vop_write_desc, cd9660_write },	/* write */
90665855Smckusick 	{ &vop_ioctl_desc, cd9660_ioctl },	/* ioctl */
90765855Smckusick 	{ &vop_select_desc, cd9660_select },	/* select */
90865855Smckusick 	{ &vop_mmap_desc, cd9660_mmap },	/* mmap */
90965855Smckusick 	{ &vop_fsync_desc, cd9660_fsync },	/* fsync */
91065855Smckusick 	{ &vop_seek_desc, cd9660_seek },	/* seek */
91165855Smckusick 	{ &vop_remove_desc, cd9660_remove },	/* remove */
91265855Smckusick 	{ &vop_link_desc, cd9660_link },	/* link */
91365855Smckusick 	{ &vop_rename_desc, cd9660_rename },	/* rename */
91465855Smckusick 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
91565855Smckusick 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
91665855Smckusick 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
91765855Smckusick 	{ &vop_readdir_desc, cd9660_readdir },	/* readdir */
91865855Smckusick 	{ &vop_readlink_desc, cd9660_readlink },/* readlink */
91965855Smckusick 	{ &vop_abortop_desc, cd9660_abortop },	/* abortop */
92065855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
92165855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
92265855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
92365855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
92465855Smckusick 	{ &vop_bmap_desc, cd9660_bmap },	/* bmap */
92565855Smckusick 	{ &vop_strategy_desc, cd9660_strategy },/* strategy */
92665855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
92765855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
92865855Smckusick 	{ &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
92965855Smckusick 	{ &vop_advlock_desc, cd9660_advlock },	/* advlock */
93065855Smckusick 	{ &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */
93165855Smckusick 	{ &vop_valloc_desc, cd9660_valloc },	/* valloc */
93265855Smckusick 	{ &vop_vfree_desc, cd9660_vfree },	/* vfree */
93365855Smckusick 	{ &vop_truncate_desc, cd9660_truncate },/* truncate */
93465855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
93565789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
93665789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
93765789Smckusick };
93865855Smckusick struct vnodeopv_desc cd9660_vnodeop_opv_desc =
93965855Smckusick 	{ &cd9660_vnodeop_p, cd9660_vnodeop_entries };
94065789Smckusick 
94165789Smckusick /*
94265789Smckusick  * Special device vnode ops
94365789Smckusick  */
94465855Smckusick int (**cd9660_specop_p)();
94565855Smckusick struct vnodeopv_entry_desc cd9660_specop_entries[] = {
94665789Smckusick 	{ &vop_default_desc, vn_default_error },
94765789Smckusick 	{ &vop_lookup_desc, spec_lookup },	/* lookup */
94865855Smckusick 	{ &vop_create_desc, cd9660_create },	/* create */
94965855Smckusick 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
95065789Smckusick 	{ &vop_open_desc, spec_open },		/* open */
95165789Smckusick 	{ &vop_close_desc, spec_close },	/* close */
95265855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
95365855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
95465855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
95565789Smckusick 	{ &vop_read_desc, spec_read },		/* read */
95665789Smckusick 	{ &vop_write_desc, spec_write },	/* write */
95765789Smckusick 	{ &vop_ioctl_desc, spec_ioctl },	/* ioctl */
95865789Smckusick 	{ &vop_select_desc, spec_select },	/* select */
95965789Smckusick 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
96065789Smckusick 	{ &vop_fsync_desc, spec_fsync },	/* fsync */
96165789Smckusick 	{ &vop_seek_desc, spec_seek },		/* seek */
96265855Smckusick 	{ &vop_remove_desc, cd9660_remove },	/* remove */
96365855Smckusick 	{ &vop_link_desc, cd9660_link },	/* link */
96465855Smckusick 	{ &vop_rename_desc, cd9660_rename },	/* rename */
96565855Smckusick 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
96665855Smckusick 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
96765855Smckusick 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
96865789Smckusick 	{ &vop_readdir_desc, spec_readdir },	/* readdir */
96965789Smckusick 	{ &vop_readlink_desc, spec_readlink },	/* readlink */
97065789Smckusick 	{ &vop_abortop_desc, spec_abortop },	/* abortop */
97165855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
97265855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
97365855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
97465855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
97565789Smckusick 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
97665789Smckusick 		/* XXX strategy: panics, should be notsupp instead? */
97765855Smckusick 	{ &vop_strategy_desc, cd9660_strategy },/* strategy */
97865855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
97965855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
98065789Smckusick 	{ &vop_pathconf_desc, spec_pathconf },	/* pathconf */
98165789Smckusick 	{ &vop_advlock_desc, spec_advlock },	/* advlock */
98265789Smckusick 	{ &vop_blkatoff_desc, spec_blkatoff },	/* blkatoff */
98365789Smckusick 	{ &vop_valloc_desc, spec_valloc },	/* valloc */
98465789Smckusick 	{ &vop_vfree_desc, spec_vfree },	/* vfree */
98565789Smckusick 	{ &vop_truncate_desc, spec_truncate },	/* truncate */
98665855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
98765789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
98865789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
98965789Smckusick };
99065855Smckusick struct vnodeopv_desc cd9660_specop_opv_desc =
99165855Smckusick 	{ &cd9660_specop_p, cd9660_specop_entries };
99265789Smckusick 
99365789Smckusick #ifdef FIFO
99465855Smckusick int (**cd9660_fifoop_p)();
99565855Smckusick struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
99665789Smckusick 	{ &vop_default_desc, vn_default_error },
99765789Smckusick 	{ &vop_lookup_desc, fifo_lookup },	/* lookup */
99865855Smckusick 	{ &vop_create_desc, cd9660_create },	/* create */
99965855Smckusick 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
100065789Smckusick 	{ &vop_open_desc, fifo_open },		/* open */
100165789Smckusick 	{ &vop_close_desc, fifo_close },	/* close */
100265855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
100365855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
100465855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
100565789Smckusick 	{ &vop_read_desc, fifo_read },		/* read */
100665789Smckusick 	{ &vop_write_desc, fifo_write },	/* write */
100765789Smckusick 	{ &vop_ioctl_desc, fifo_ioctl },	/* ioctl */
100865789Smckusick 	{ &vop_select_desc, fifo_select },	/* select */
100965789Smckusick 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
101065789Smckusick 	{ &vop_fsync_desc, fifo_fsync },	/* fsync */
101165789Smckusick 	{ &vop_seek_desc, fifo_seek },		/* seek */
101265855Smckusick 	{ &vop_remove_desc, cd9660_remove },	/* remove */
101365855Smckusick 	{ &vop_link_desc, cd9660_link },	/* link */
101465855Smckusick 	{ &vop_rename_desc, cd9660_rename },	/* rename */
101565855Smckusick 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
101665855Smckusick 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
101765855Smckusick 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
101865789Smckusick 	{ &vop_readdir_desc, fifo_readdir },	/* readdir */
101965789Smckusick 	{ &vop_readlink_desc, fifo_readlink },	/* readlink */
102065789Smckusick 	{ &vop_abortop_desc, fifo_abortop },	/* abortop */
102165855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
102265855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
102365855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
102465855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
102565789Smckusick 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
102665789Smckusick 	{ &vop_strategy_desc, fifo_badop },	/* strategy */
102765855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
102865855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
102965789Smckusick 	{ &vop_pathconf_desc, fifo_pathconf },	/* pathconf */
103065789Smckusick 	{ &vop_advlock_desc, fifo_advlock },	/* advlock */
103165789Smckusick 	{ &vop_blkatoff_desc, fifo_blkatoff },	/* blkatoff */
103265789Smckusick 	{ &vop_valloc_desc, fifo_valloc },	/* valloc */
103365789Smckusick 	{ &vop_vfree_desc, fifo_vfree },	/* vfree */
103465789Smckusick 	{ &vop_truncate_desc, fifo_truncate },	/* truncate */
103565855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
103665789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
103765789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
103865789Smckusick };
103965855Smckusick struct vnodeopv_desc cd9660_fifoop_opv_desc =
104065855Smckusick 	{ &cd9660_fifoop_p, cd9660_fifoop_entries };
104165789Smckusick #endif /* FIFO */
1042