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*69742Smckusick  *	@(#)cd9660_vnops.c	8.19 (Berkeley) 05/27/95
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);
5167379Smkm 	return (EINVAL);
5265789Smckusick #else
5365789Smckusick 	register struct vnode *vp;
5465789Smckusick 	struct iso_node *ip;
5565789Smckusick 	struct iso_dnode *dp;
5665789Smckusick 	int error;
5768052Smckusick 
5865789Smckusick 	vp = ndp->ni_vp;
5965789Smckusick 	ip = VTOI(vp);
6068052Smckusick 
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);
6767379Smkm 		return (EINVAL);
6865789Smckusick 	}
6968052Smckusick 
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;
7868052Smckusick 
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 /*
93*69742Smckusick  * Setattr call. Only allowed for block and character special devices.
94*69742Smckusick  */
95*69742Smckusick int
cd9660_setattr(ap)96*69742Smckusick cd9660_setattr(ap)
97*69742Smckusick 	struct vop_setattr_args /* {
98*69742Smckusick 		struct vnodeop_desc *a_desc;
99*69742Smckusick 		struct vnode *a_vp;
100*69742Smckusick 		struct vattr *a_vap;
101*69742Smckusick 		struct ucred *a_cred;
102*69742Smckusick 		struct proc *a_p;
103*69742Smckusick 	} */ *ap;
104*69742Smckusick {
105*69742Smckusick 	struct vnode *vp = ap->a_vp;
106*69742Smckusick 	struct vattr *vap = ap->a_vap;
107*69742Smckusick 
108*69742Smckusick   	if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
109*69742Smckusick 	    vap->va_gid != (gid_t)VNOVAL || vap->va_atime.ts_sec != VNOVAL ||
110*69742Smckusick 	    vap->va_mtime.ts_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
111*69742Smckusick 		return (EROFS);
112*69742Smckusick 	if (vap->va_size != VNOVAL) {
113*69742Smckusick  		switch (vp->v_type) {
114*69742Smckusick  		case VDIR:
115*69742Smckusick  			return (EISDIR);
116*69742Smckusick 		case VLNK:
117*69742Smckusick 		case VREG:
118*69742Smckusick 			return (EROFS);
119*69742Smckusick  		case VCHR:
120*69742Smckusick  		case VBLK:
121*69742Smckusick  		case VSOCK:
122*69742Smckusick  		case VFIFO:
123*69742Smckusick 			return (0);
124*69742Smckusick 		}
125*69742Smckusick 	}
126*69742Smckusick }
127*69742Smckusick 
128*69742Smckusick /*
12965789Smckusick  * Open called.
13065789Smckusick  *
13165789Smckusick  * Nothing to do.
13265789Smckusick  */
13365789Smckusick /* ARGSUSED */
13465789Smckusick int
cd9660_open(ap)13565855Smckusick cd9660_open(ap)
13665789Smckusick 	struct vop_open_args /* {
13765789Smckusick 		struct vnode *a_vp;
13865789Smckusick 		int  a_mode;
13965789Smckusick 		struct ucred *a_cred;
14065789Smckusick 		struct proc *a_p;
14165789Smckusick 	} */ *ap;
14265789Smckusick {
14365789Smckusick 	return (0);
14465789Smckusick }
14565789Smckusick 
14665789Smckusick /*
14765789Smckusick  * Close called
14865789Smckusick  *
14965789Smckusick  * Update the times on the inode on writeable file systems.
15065789Smckusick  */
15165789Smckusick /* ARGSUSED */
15265789Smckusick int
cd9660_close(ap)15365855Smckusick cd9660_close(ap)
15465789Smckusick 	struct vop_close_args /* {
15565789Smckusick 		struct vnode *a_vp;
15665789Smckusick 		int  a_fflag;
15765789Smckusick 		struct ucred *a_cred;
15865789Smckusick 		struct proc *a_p;
15965789Smckusick 	} */ *ap;
16065789Smckusick {
16165789Smckusick 	return (0);
16265789Smckusick }
16365789Smckusick 
16465789Smckusick /*
16565789Smckusick  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
16665789Smckusick  * The mode is shifted to select the owner/group/other fields. The
16765789Smckusick  * super user is granted all permissions.
16865789Smckusick  */
16965789Smckusick /* ARGSUSED */
17065855Smckusick cd9660_access(ap)
17165789Smckusick 	struct vop_access_args /* {
17265789Smckusick 		struct vnode *a_vp;
17365789Smckusick 		int  a_mode;
17465789Smckusick 		struct ucred *a_cred;
17565789Smckusick 		struct proc *a_p;
17665789Smckusick 	} */ *ap;
17765789Smckusick {
178*69742Smckusick 	struct vnode *vp = ap->a_vp;
179*69742Smckusick 	struct iso_node *ip = VTOI(vp);
18067379Smkm 	struct ucred *cred = ap->a_cred;
18167379Smkm 	mode_t mask, mode = ap->a_mode;
18267379Smkm 	gid_t *gp;
18368052Smckusick 	int i;
18467379Smkm 
185*69742Smckusick 	/*
186*69742Smckusick 	 * Disallow write attempts unless the file is a socket,
187*69742Smckusick 	 * fifo, or a block or character device resident on the
188*69742Smckusick 	 * file system.
189*69742Smckusick 	 */
190*69742Smckusick 	if (mode & VWRITE) {
191*69742Smckusick 		switch (vp->v_type) {
192*69742Smckusick 		case VDIR:
193*69742Smckusick 		case VLNK:
194*69742Smckusick 		case VREG:
195*69742Smckusick 			return (EROFS);
196*69742Smckusick 		}
197*69742Smckusick 	}
198*69742Smckusick 
19967379Smkm 	/* User id 0 always gets access. */
20067379Smkm 	if (cred->cr_uid == 0)
20167379Smkm 		return (0);
20267379Smkm 
20367379Smkm 	mask = 0;
20467379Smkm 
20567379Smkm 	/* Otherwise, check the owner. */
20667379Smkm 	if (cred->cr_uid == ip->inode.iso_uid) {
20767379Smkm 		if (mode & VEXEC)
20867379Smkm 			mask |= S_IXUSR;
20967379Smkm 		if (mode & VREAD)
21067379Smkm 			mask |= S_IRUSR;
21167379Smkm 		if (mode & VWRITE)
21267379Smkm 			mask |= S_IWUSR;
21367379Smkm 		return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
21467379Smkm 	}
21567379Smkm 
21667379Smkm 	/* Otherwise, check the groups. */
21767379Smkm 	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
21867379Smkm 		if (ip->inode.iso_gid == *gp) {
21967379Smkm 			if (mode & VEXEC)
22067379Smkm 				mask |= S_IXGRP;
22167379Smkm 			if (mode & VREAD)
22267379Smkm 				mask |= S_IRGRP;
22367379Smkm 			if (mode & VWRITE)
22467379Smkm 				mask |= S_IWGRP;
22567379Smkm 			return ((ip->inode.iso_mode & mask) == mask ?
22667379Smkm 			    0 : EACCES);
22767379Smkm 		}
22867379Smkm 
22967379Smkm 	/* Otherwise, check everyone else. */
23067379Smkm 	if (mode & VEXEC)
23167379Smkm 		mask |= S_IXOTH;
23267379Smkm 	if (mode & VREAD)
23367379Smkm 		mask |= S_IROTH;
23467379Smkm 	if (mode & VWRITE)
23567379Smkm 		mask |= S_IWOTH;
23667379Smkm 	return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
23765789Smckusick }
23865789Smckusick 
23965855Smckusick cd9660_getattr(ap)
24065789Smckusick 	struct vop_getattr_args /* {
24165789Smckusick 		struct vnode *a_vp;
24265789Smckusick 		struct vattr *a_vap;
24365789Smckusick 		struct ucred *a_cred;
24465789Smckusick 		struct proc *a_p;
24565789Smckusick 	} */ *ap;
24665789Smckusick 
24765789Smckusick {
24865789Smckusick 	struct vnode *vp = ap->a_vp;
24965789Smckusick 	register struct vattr *vap = ap->a_vap;
25065789Smckusick 	register struct iso_node *ip = VTOI(vp);
25165789Smckusick 	int i;
25265789Smckusick 
25365789Smckusick 	vap->va_fsid	= ip->i_dev;
25465789Smckusick 	vap->va_fileid	= ip->i_number;
25565789Smckusick 
25665789Smckusick 	vap->va_mode	= ip->inode.iso_mode;
25765789Smckusick 	vap->va_nlink	= ip->inode.iso_links;
25865789Smckusick 	vap->va_uid	= ip->inode.iso_uid;
25965789Smckusick 	vap->va_gid	= ip->inode.iso_gid;
26065789Smckusick 	vap->va_atime	= ip->inode.iso_atime;
26165789Smckusick 	vap->va_mtime	= ip->inode.iso_mtime;
26265789Smckusick 	vap->va_ctime	= ip->inode.iso_ctime;
26365789Smckusick 	vap->va_rdev	= ip->inode.iso_rdev;
26465789Smckusick 
26565789Smckusick 	vap->va_size	= (u_quad_t) ip->i_size;
26667703Smckusick 	if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
26767703Smckusick 		struct vop_readlink_args rdlnk;
26867703Smckusick 		struct iovec aiov;
26967703Smckusick 		struct uio auio;
27067703Smckusick 		char *cp;
27167703Smckusick 
27267703Smckusick 		MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
27367703Smckusick 		aiov.iov_base = cp;
27467703Smckusick 		aiov.iov_len = MAXPATHLEN;
27567703Smckusick 		auio.uio_iov = &aiov;
27667703Smckusick 		auio.uio_iovcnt = 1;
27767703Smckusick 		auio.uio_offset = 0;
27867703Smckusick 		auio.uio_rw = UIO_READ;
27967703Smckusick 		auio.uio_segflg = UIO_SYSSPACE;
28067703Smckusick 		auio.uio_procp = ap->a_p;
28167703Smckusick 		auio.uio_resid = MAXPATHLEN;
28267703Smckusick 		rdlnk.a_uio = &auio;
28367703Smckusick 		rdlnk.a_vp = ap->a_vp;
28467703Smckusick 		rdlnk.a_cred = ap->a_cred;
28567703Smckusick 		if (cd9660_readlink(&rdlnk) == 0)
28667703Smckusick 			vap->va_size = MAXPATHLEN - auio.uio_resid;
28767703Smckusick 		FREE(cp, M_TEMP);
28867703Smckusick 	}
28965789Smckusick 	vap->va_flags	= 0;
29065789Smckusick 	vap->va_gen = 1;
29165789Smckusick 	vap->va_blocksize = ip->i_mnt->logical_block_size;
29265789Smckusick 	vap->va_bytes	= (u_quad_t) ip->i_size;
29365789Smckusick 	vap->va_type	= vp->v_type;
29465789Smckusick 	return (0);
29565789Smckusick }
29665789Smckusick 
29765789Smckusick #if ISO_DEFAULT_BLOCK_SIZE >= NBPG
29865789Smckusick #ifdef DEBUG
29965789Smckusick extern int doclusterread;
30065789Smckusick #else
30165789Smckusick #define doclusterread 1
30265789Smckusick #endif
30365789Smckusick #else
30465789Smckusick /* XXX until cluster routines can handle block sizes less than one page */
30565789Smckusick #define doclusterread 0
30665789Smckusick #endif
30765789Smckusick 
30865789Smckusick /*
30965789Smckusick  * Vnode op for reading.
31065789Smckusick  */
31165855Smckusick cd9660_read(ap)
31265789Smckusick 	struct vop_read_args /* {
31365789Smckusick 		struct vnode *a_vp;
31465789Smckusick 		struct uio *a_uio;
31565789Smckusick 		int a_ioflag;
31665789Smckusick 		struct ucred *a_cred;
31765789Smckusick 	} */ *ap;
31865789Smckusick {
31965789Smckusick 	struct vnode *vp = ap->a_vp;
32065789Smckusick 	register struct uio *uio = ap->a_uio;
32165789Smckusick 	register struct iso_node *ip = VTOI(vp);
32265789Smckusick 	register struct iso_mnt *imp;
32365789Smckusick 	struct buf *bp;
32465789Smckusick 	daddr_t lbn, bn, rablock;
32565789Smckusick 	off_t diff;
32665789Smckusick 	int rasize, error = 0;
32765789Smckusick 	long size, n, on;
32868052Smckusick 
32965789Smckusick 	if (uio->uio_resid == 0)
33065789Smckusick 		return (0);
33165789Smckusick 	if (uio->uio_offset < 0)
33265789Smckusick 		return (EINVAL);
33367526Smckusick 	ip->i_flag |= IN_ACCESS;
33465789Smckusick 	imp = ip->i_mnt;
33565789Smckusick 	do {
33668052Smckusick 		lbn = lblkno(imp, uio->uio_offset);
33768052Smckusick 		on = blkoff(imp, uio->uio_offset);
33868052Smckusick 		n = min((u_int)(imp->logical_block_size - on),
33965789Smckusick 			uio->uio_resid);
34065789Smckusick 		diff = (off_t)ip->i_size - uio->uio_offset;
34165789Smckusick 		if (diff <= 0)
34265789Smckusick 			return (0);
34365789Smckusick 		if (diff < n)
34465789Smckusick 			n = diff;
34568052Smckusick 		size = blksize(imp, ip, lbn);
34665789Smckusick 		rablock = lbn + 1;
34765789Smckusick 		if (doclusterread) {
34868052Smckusick 			if (lblktosize(imp, rablock) <= ip->i_size)
34965789Smckusick 				error = cluster_read(vp, (off_t)ip->i_size,
35065789Smckusick 						     lbn, size, NOCRED, &bp);
35168052Smckusick 			else
35265789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
35365789Smckusick 		} else {
35465789Smckusick 			if (vp->v_lastr + 1 == lbn &&
35568052Smckusick 			    lblktosize(imp, rablock) < ip->i_size) {
35668052Smckusick 				rasize = blksize(imp, ip, rablock);
35765789Smckusick 				error = breadn(vp, lbn, size, &rablock,
35865789Smckusick 					       &rasize, 1, NOCRED, &bp);
35965789Smckusick 			} else
36065789Smckusick 				error = bread(vp, lbn, size, NOCRED, &bp);
36165789Smckusick 		}
36265789Smckusick 		vp->v_lastr = lbn;
36365789Smckusick 		n = min(n, size - bp->b_resid);
36465789Smckusick 		if (error) {
36565789Smckusick 			brelse(bp);
36665789Smckusick 			return (error);
36765789Smckusick 		}
36865789Smckusick 
36968052Smckusick 		error = uiomove(bp->b_data + on, (int)n, uio);
37065789Smckusick 		if (n + on == imp->logical_block_size ||
37165789Smckusick 		    uio->uio_offset == (off_t)ip->i_size)
37265789Smckusick 			bp->b_flags |= B_AGE;
37365789Smckusick 		brelse(bp);
37465789Smckusick 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
37565789Smckusick 	return (error);
37665789Smckusick }
37765789Smckusick 
37865789Smckusick /* ARGSUSED */
37965789Smckusick int
cd9660_ioctl(ap)38065855Smckusick cd9660_ioctl(ap)
38165789Smckusick 	struct vop_ioctl_args /* {
38265789Smckusick 		struct vnode *a_vp;
38368052Smckusick 		u_long a_command;
38465789Smckusick 		caddr_t  a_data;
38565789Smckusick 		int  a_fflag;
38665789Smckusick 		struct ucred *a_cred;
38765789Smckusick 		struct proc *a_p;
38865789Smckusick 	} */ *ap;
38965789Smckusick {
39065789Smckusick 	printf("You did ioctl for isofs !!\n");
39165789Smckusick 	return (ENOTTY);
39265789Smckusick }
39365789Smckusick 
39465789Smckusick /* ARGSUSED */
39565789Smckusick int
cd9660_select(ap)39665855Smckusick cd9660_select(ap)
39765789Smckusick 	struct vop_select_args /* {
39865789Smckusick 		struct vnode *a_vp;
39965789Smckusick 		int  a_which;
40065789Smckusick 		int  a_fflags;
40165789Smckusick 		struct ucred *a_cred;
40265789Smckusick 		struct proc *a_p;
40365789Smckusick 	} */ *ap;
40465789Smckusick {
40565789Smckusick 
40665789Smckusick 	/*
40765789Smckusick 	 * We should really check to see if I/O is possible.
40865789Smckusick 	 */
40965789Smckusick 	return (1);
41065789Smckusick }
41165789Smckusick 
41265789Smckusick /*
41365789Smckusick  * Mmap a file
41465789Smckusick  *
41565789Smckusick  * NB Currently unsupported.
41665789Smckusick  */
41765789Smckusick /* ARGSUSED */
41865789Smckusick int
cd9660_mmap(ap)41965855Smckusick cd9660_mmap(ap)
42065789Smckusick 	struct vop_mmap_args /* {
42165789Smckusick 		struct vnode *a_vp;
42265789Smckusick 		int  a_fflags;
42365789Smckusick 		struct ucred *a_cred;
42465789Smckusick 		struct proc *a_p;
42565789Smckusick 	} */ *ap;
42665789Smckusick {
42765789Smckusick 
42865789Smckusick 	return (EINVAL);
42965789Smckusick }
43065789Smckusick 
43165789Smckusick /*
43265789Smckusick  * Seek on a file
43365789Smckusick  *
43465789Smckusick  * Nothing to do, so just return.
43565789Smckusick  */
43665789Smckusick /* ARGSUSED */
43765789Smckusick int
cd9660_seek(ap)43865855Smckusick cd9660_seek(ap)
43965789Smckusick 	struct vop_seek_args /* {
44065789Smckusick 		struct vnode *a_vp;
44165789Smckusick 		off_t  a_oldoff;
44265789Smckusick 		off_t  a_newoff;
44365789Smckusick 		struct ucred *a_cred;
44465789Smckusick 	} */ *ap;
44565789Smckusick {
44665789Smckusick 
44765789Smckusick 	return (0);
44865789Smckusick }
44965789Smckusick 
45065789Smckusick /*
45165789Smckusick  * Structure for reading directories
45265789Smckusick  */
45365789Smckusick struct isoreaddir {
45465789Smckusick 	struct dirent saveent;
45565789Smckusick 	struct dirent assocent;
45665789Smckusick 	struct dirent current;
45765789Smckusick 	off_t saveoff;
45865789Smckusick 	off_t assocoff;
45965789Smckusick 	off_t curroff;
46065789Smckusick 	struct uio *uio;
46165789Smckusick 	off_t uio_off;
46267370Smckusick 	int eofflag;
46367370Smckusick 	u_long *cookies;
46465789Smckusick 	int ncookies;
46565789Smckusick };
46665789Smckusick 
46768052Smckusick int
iso_uiodir(idp,dp,off)46865789Smckusick iso_uiodir(idp,dp,off)
46965789Smckusick 	struct isoreaddir *idp;
47065789Smckusick 	struct dirent *dp;
47165789Smckusick 	off_t off;
47265789Smckusick {
47365789Smckusick 	int error;
47468052Smckusick 
47565789Smckusick 	dp->d_name[dp->d_namlen] = 0;
47665789Smckusick 	dp->d_reclen = DIRSIZ(dp);
47768052Smckusick 
47865789Smckusick 	if (idp->uio->uio_resid < dp->d_reclen) {
47967370Smckusick 		idp->eofflag = 0;
48067370Smckusick 		return (-1);
48165789Smckusick 	}
48268052Smckusick 
48367370Smckusick 	if (idp->cookies) {
48465789Smckusick 		if (idp->ncookies <= 0) {
48567370Smckusick 			idp->eofflag = 0;
48667370Smckusick 			return (-1);
48765789Smckusick 		}
48868052Smckusick 
48967370Smckusick 		*idp->cookies++ = off;
49065789Smckusick 		--idp->ncookies;
49165789Smckusick 	}
49268052Smckusick 
49365789Smckusick 	if (error = uiomove(dp,dp->d_reclen,idp->uio))
49467370Smckusick 		return (error);
49565789Smckusick 	idp->uio_off = off;
49667370Smckusick 	return (0);
49765789Smckusick }
49865789Smckusick 
49968052Smckusick int
iso_shipdir(idp)50065789Smckusick iso_shipdir(idp)
50165789Smckusick 	struct isoreaddir *idp;
50265789Smckusick {
50365789Smckusick 	struct dirent *dp;
50465789Smckusick 	int cl, sl, assoc;
50565789Smckusick 	int error;
50665789Smckusick 	char *cname, *sname;
50768052Smckusick 
50865789Smckusick 	cl = idp->current.d_namlen;
50965789Smckusick 	cname = idp->current.d_name;
51065789Smckusick 	if (assoc = cl > 1 && *cname == ASSOCCHAR) {
51165789Smckusick 		cl--;
51265789Smckusick 		cname++;
51365789Smckusick 	}
51468052Smckusick 
51565789Smckusick 	dp = &idp->saveent;
51665789Smckusick 	sname = dp->d_name;
51765789Smckusick 	if (!(sl = dp->d_namlen)) {
51865789Smckusick 		dp = &idp->assocent;
51965789Smckusick 		sname = dp->d_name + 1;
52065789Smckusick 		sl = dp->d_namlen - 1;
52165789Smckusick 	}
52265789Smckusick 	if (sl > 0) {
52365789Smckusick 		if (sl != cl
52465789Smckusick 		    || bcmp(sname,cname,sl)) {
52565789Smckusick 			if (idp->assocent.d_namlen) {
52665789Smckusick 				if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff))
52767379Smkm 					return (error);
52865789Smckusick 				idp->assocent.d_namlen = 0;
52965789Smckusick 			}
53065789Smckusick 			if (idp->saveent.d_namlen) {
53165789Smckusick 				if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff))
53267379Smkm 					return (error);
53365789Smckusick 				idp->saveent.d_namlen = 0;
53465789Smckusick 			}
53565789Smckusick 		}
53665789Smckusick 	}
53765789Smckusick 	idp->current.d_reclen = DIRSIZ(&idp->current);
53865789Smckusick 	if (assoc) {
53965789Smckusick 		idp->assocoff = idp->curroff;
54065789Smckusick 		bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
54165789Smckusick 	} else {
54265789Smckusick 		idp->saveoff = idp->curroff;
54365789Smckusick 		bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
54465789Smckusick 	}
54567379Smkm 	return (0);
54665789Smckusick }
54765789Smckusick 
54865789Smckusick /*
54965789Smckusick  * Vnode op for readdir
55065789Smckusick  */
55165789Smckusick int
cd9660_readdir(ap)55265855Smckusick cd9660_readdir(ap)
55365789Smckusick 	struct vop_readdir_args /* {
55465789Smckusick 		struct vnode *a_vp;
55565789Smckusick 		struct uio *a_uio;
55665789Smckusick 		struct ucred *a_cred;
55767370Smckusick 		int *a_eofflag;
55868681Smckusick 		int *a_ncookies;
55967370Smckusick 		u_long *a_cookies;
56065789Smckusick 	} */ *ap;
56165789Smckusick {
56265789Smckusick 	register struct uio *uio = ap->a_uio;
56365789Smckusick 	struct isoreaddir *idp;
56468052Smckusick 	struct vnode *vdp = ap->a_vp;
56568052Smckusick 	struct iso_node *dp;
56668052Smckusick 	struct iso_mnt *imp;
56768052Smckusick 	struct buf *bp = NULL;
56868052Smckusick 	struct iso_directory_record *ep;
56965789Smckusick 	int entryoffsetinblock;
57068052Smckusick 	doff_t endsearch;
57168052Smckusick 	u_long bmask;
57265789Smckusick 	int error = 0;
57365789Smckusick 	int reclen;
57468052Smckusick 	u_short namelen;
57568681Smckusick 	int ncookies = 0;
57668681Smckusick 	u_long *cookies = NULL;
57768052Smckusick 
57868052Smckusick 	dp = VTOI(vdp);
57968052Smckusick 	imp = dp->i_mnt;
58068052Smckusick 	bmask = imp->im_bmask;
58168052Smckusick 
58267529Smckusick 	MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
58367529Smckusick 	idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
58467529Smckusick 	/*
58567529Smckusick 	 * XXX
58667529Smckusick 	 * Is it worth trying to figure out the type?
58767529Smckusick 	 */
58867529Smckusick 	idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
58967529Smckusick 	    DT_UNKNOWN;
59065789Smckusick 	idp->uio = uio;
59168681Smckusick 	if (ap->a_ncookies == NULL) {
59268681Smckusick 		idp->cookies = NULL;
59368681Smckusick 	} else {
59468681Smckusick 		/*
59568681Smckusick 		 * Guess the number of cookies needed.
59668681Smckusick 		 */
59768681Smckusick 		ncookies = uio->uio_resid / 16;
59868681Smckusick 		MALLOC(cookies, u_int *, ncookies * sizeof(u_int), M_TEMP,
59968681Smckusick 		    M_WAITOK);
60068681Smckusick 		idp->cookies = cookies;
60168681Smckusick 		idp->ncookies = ncookies;
60268681Smckusick 	}
60367370Smckusick 	idp->eofflag = 1;
60465789Smckusick 	idp->curroff = uio->uio_offset;
60568052Smckusick 
60668052Smckusick 	if ((entryoffsetinblock = idp->curroff & bmask) &&
60768052Smckusick 	    (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
60868052Smckusick 		FREE(idp, M_TEMP);
60968052Smckusick 		return (error);
61065789Smckusick 	}
61168052Smckusick 	endsearch = dp->i_size;
61268052Smckusick 
61365789Smckusick 	while (idp->curroff < endsearch) {
61465789Smckusick 		/*
61565789Smckusick 		 * If offset is on a block boundary,
61665789Smckusick 		 * read the next directory block.
61765789Smckusick 		 * Release previous if it exists.
61865789Smckusick 		 */
61968052Smckusick 		if ((idp->curroff & bmask) == 0) {
62065789Smckusick 			if (bp != NULL)
62165789Smckusick 				brelse(bp);
62268052Smckusick 			if (error =
62368052Smckusick 			    VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))
62465789Smckusick 				break;
62565789Smckusick 			entryoffsetinblock = 0;
62665789Smckusick 		}
62765789Smckusick 		/*
62865789Smckusick 		 * Get pointer to next entry.
62965789Smckusick 		 */
63065789Smckusick 		ep = (struct iso_directory_record *)
63168052Smckusick 			((char *)bp->b_data + entryoffsetinblock);
63268052Smckusick 
63368052Smckusick 		reclen = isonum_711(ep->length);
63465789Smckusick 		if (reclen == 0) {
63565789Smckusick 			/* skip to next block, if any */
63667559Smckusick 			idp->curroff =
63768052Smckusick 			    (idp->curroff & ~bmask) + imp->logical_block_size;
63865789Smckusick 			continue;
63965789Smckusick 		}
64068052Smckusick 
64165789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
64265789Smckusick 			error = EINVAL;
64365789Smckusick 			/* illegal entry, stop */
64465789Smckusick 			break;
64565789Smckusick 		}
64668052Smckusick 
64765789Smckusick 		if (entryoffsetinblock + reclen > imp->logical_block_size) {
64865789Smckusick 			error = EINVAL;
64965789Smckusick 			/* illegal directory, so stop looking */
65065789Smckusick 			break;
65165789Smckusick 		}
65268052Smckusick 
65367559Smckusick 		idp->current.d_namlen = isonum_711(ep->name_len);
65467559Smckusick 
65565789Smckusick 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
65665789Smckusick 			error = EINVAL;
65765789Smckusick 			/* illegal entry, stop */
65865789Smckusick 			break;
65965789Smckusick 		}
66068052Smckusick 
66167559Smckusick 		if (isonum_711(ep->flags)&2)
66268052Smckusick 			idp->current.d_fileno = isodirino(ep, imp);
66367559Smckusick 		else
66467559Smckusick 			idp->current.d_fileno = dbtob(bp->b_blkno) +
66567559Smckusick 				entryoffsetinblock;
66668052Smckusick 
66765789Smckusick 		idp->curroff += reclen;
66867559Smckusick 
66965789Smckusick 		switch (imp->iso_ftype) {
67065789Smckusick 		case ISO_FTYPE_RRIP:
67168052Smckusick 			cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
67265789Smckusick 					   &idp->current.d_fileno,imp);
67368052Smckusick 			idp->current.d_namlen = (u_char)namelen;
67465789Smckusick 			if (idp->current.d_namlen)
67565789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
67665789Smckusick 			break;
67765789Smckusick 		default:	/* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
67865789Smckusick 			strcpy(idp->current.d_name,"..");
67965789Smckusick 			switch (ep->name[0]) {
68065789Smckusick 			case 0:
68165789Smckusick 				idp->current.d_namlen = 1;
68265789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
68365789Smckusick 				break;
68465789Smckusick 			case 1:
68565789Smckusick 				idp->current.d_namlen = 2;
68665789Smckusick 				error = iso_uiodir(idp,&idp->current,idp->curroff);
68765789Smckusick 				break;
68865789Smckusick 			default:
68965789Smckusick 				isofntrans(ep->name,idp->current.d_namlen,
69068052Smckusick 					   idp->current.d_name, &namelen,
69165789Smckusick 					   imp->iso_ftype == ISO_FTYPE_9660,
69265789Smckusick 					   isonum_711(ep->flags)&4);
69368052Smckusick 				idp->current.d_namlen = (u_char)namelen;
69465789Smckusick 				if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
69565789Smckusick 					error = iso_shipdir(idp);
69665789Smckusick 				else
69765789Smckusick 					error = iso_uiodir(idp,&idp->current,idp->curroff);
69865789Smckusick 				break;
69965789Smckusick 			}
70065789Smckusick 		}
70165789Smckusick 		if (error)
70265789Smckusick 			break;
70368052Smckusick 
70465789Smckusick 		entryoffsetinblock += reclen;
70565789Smckusick 	}
70668052Smckusick 
70765789Smckusick 	if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
70865789Smckusick 		idp->current.d_namlen = 0;
70965789Smckusick 		error = iso_shipdir(idp);
71065789Smckusick 	}
71165789Smckusick 	if (error < 0)
71265789Smckusick 		error = 0;
71368052Smckusick 
71468681Smckusick 	if (ap->a_ncookies != NULL) {
71568681Smckusick 		if (error)
71668681Smckusick 			free(cookies, M_TEMP);
71768681Smckusick 		else {
71868681Smckusick 			/*
71968681Smckusick 			 * Work out the number of cookies actually used.
72068681Smckusick 			 */
72168681Smckusick 			*ap->a_ncookies = ncookies - idp->ncookies;
72268681Smckusick 			*ap->a_cookies = cookies;
72368681Smckusick 		}
72468681Smckusick 	}
72568681Smckusick 
72665789Smckusick 	if (bp)
72765789Smckusick 		brelse (bp);
72868052Smckusick 
72965789Smckusick 	uio->uio_offset = idp->uio_off;
73067370Smckusick 	*ap->a_eofflag = idp->eofflag;
73168052Smckusick 
73268052Smckusick 	FREE(idp, M_TEMP);
73368052Smckusick 
73465789Smckusick 	return (error);
73565789Smckusick }
73668052Smckusick 
73765789Smckusick /*
73865789Smckusick  * Return target name of a symbolic link
73965789Smckusick  * Shouldn't we get the parent vnode and read the data from there?
74065855Smckusick  * This could eventually result in deadlocks in cd9660_lookup.
74165789Smckusick  * But otherwise the block read here is in the block buffer two times.
74265789Smckusick  */
74365789Smckusick typedef struct iso_directory_record ISODIR;
74465789Smckusick typedef struct iso_node             ISONODE;
74565789Smckusick typedef struct iso_mnt              ISOMNT;
74665789Smckusick int
cd9660_readlink(ap)74765855Smckusick cd9660_readlink(ap)
74865789Smckusick 	struct vop_readlink_args /* {
74965789Smckusick 		struct vnode *a_vp;
75065789Smckusick 		struct uio *a_uio;
75165789Smckusick 		struct ucred *a_cred;
75265789Smckusick 	} */ *ap;
75365789Smckusick {
75465789Smckusick 	ISONODE	*ip;
75568052Smckusick 	ISODIR	*dirp;
75665789Smckusick 	ISOMNT	*imp;
75765789Smckusick 	struct	buf *bp;
75868054Smckusick 	struct	uio *uio;
75965789Smckusick 	u_short	symlen;
76065789Smckusick 	int	error;
76165789Smckusick 	char	*symname;
76265789Smckusick 	ino_t	ino;
76368052Smckusick 
76465789Smckusick 	ip  = VTOI(ap->a_vp);
76565789Smckusick 	imp = ip->i_mnt;
76668054Smckusick 	uio = ap->a_uio;
76768052Smckusick 
76865789Smckusick 	if (imp->iso_ftype != ISO_FTYPE_RRIP)
76967379Smkm 		return (EINVAL);
77068052Smckusick 
77165789Smckusick 	/*
77265789Smckusick 	 * Get parents directory record block that this inode included.
77365789Smckusick 	 */
77465789Smckusick 	error = bread(imp->im_devvp,
77568052Smckusick 		      (ip->i_number >> imp->im_bshift) <<
77668052Smckusick 		      (imp->im_bshift - DEV_BSHIFT),
77768052Smckusick 		      imp->logical_block_size, NOCRED, &bp);
77865789Smckusick 	if (error) {
77965789Smckusick 		brelse(bp);
78067379Smkm 		return (EINVAL);
78165789Smckusick 	}
78265789Smckusick 
78365789Smckusick 	/*
78465789Smckusick 	 * Setup the directory pointer for this inode
78565789Smckusick 	 */
78668052Smckusick 	dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
78767379Smkm 
78865789Smckusick 	/*
78965789Smckusick 	 * Just make sure, we have a right one....
79065789Smckusick 	 *   1: Check not cross boundary on block
79165789Smckusick 	 */
79265789Smckusick 	if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
79365789Smckusick 	    > imp->logical_block_size) {
79465789Smckusick 		brelse(bp);
79567379Smkm 		return (EINVAL);
79665789Smckusick 	}
79768052Smckusick 
79865789Smckusick 	/*
79965789Smckusick 	 * Now get a buffer
80065789Smckusick 	 * Abuse a namei buffer for now.
80165789Smckusick 	 */
80267710Smckusick 	if (uio->uio_segflg == UIO_SYSSPACE)
80367710Smckusick 		symname = uio->uio_iov->iov_base;
80467710Smckusick 	else
80567710Smckusick 		MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
80665789Smckusick 
80765789Smckusick 	/*
80865789Smckusick 	 * Ok, we just gathering a symbolic name in SL record.
80965789Smckusick 	 */
81067710Smckusick 	if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
81167710Smckusick 		if (uio->uio_segflg != UIO_SYSSPACE)
81267710Smckusick 			FREE(symname, M_NAMEI);
81365789Smckusick 		brelse(bp);
81467379Smkm 		return (EINVAL);
81565789Smckusick 	}
81665789Smckusick 	/*
81765789Smckusick 	 * Don't forget before you leave from home ;-)
81865789Smckusick 	 */
81965789Smckusick 	brelse(bp);
82065789Smckusick 
82165789Smckusick 	/*
82265789Smckusick 	 * return with the symbolic name to caller's.
82365789Smckusick 	 */
82467710Smckusick 	if (uio->uio_segflg != UIO_SYSSPACE) {
82567710Smckusick 		error = uiomove(symname, symlen, uio);
82667710Smckusick 		FREE(symname, M_NAMEI);
82767710Smckusick 		return (error);
82867710Smckusick 	}
82967710Smckusick 	uio->uio_resid -= symlen;
83067710Smckusick 	uio->uio_iov->iov_base += symlen;
83167710Smckusick 	uio->uio_iov->iov_len -= symlen;
83267710Smckusick 	return (0);
83365789Smckusick }
83465789Smckusick 
83565789Smckusick /*
83665789Smckusick  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
83765789Smckusick  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
83865789Smckusick  */
83965789Smckusick int
cd9660_abortop(ap)84065855Smckusick cd9660_abortop(ap)
84165789Smckusick 	struct vop_abortop_args /* {
84265789Smckusick 		struct vnode *a_dvp;
84365789Smckusick 		struct componentname *a_cnp;
84465789Smckusick 	} */ *ap;
84565789Smckusick {
84665789Smckusick 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
84765789Smckusick 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
84867379Smkm 	return (0);
84965789Smckusick }
85065789Smckusick 
85165789Smckusick /*
85265789Smckusick  * Lock an inode.
85365789Smckusick  */
85465789Smckusick int
cd9660_lock(ap)85565855Smckusick cd9660_lock(ap)
85665789Smckusick 	struct vop_lock_args /* {
85765789Smckusick 		struct vnode *a_vp;
85869427Smckusick 		int a_flags;
85969427Smckusick 		struct proc *a_p;
86065789Smckusick 	} */ *ap;
86165789Smckusick {
86269427Smckusick 	struct vnode *vp = ap->a_vp;
86365789Smckusick 
86469427Smckusick 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
86569427Smckusick 		ap->a_p));
86665789Smckusick }
86765789Smckusick 
86865789Smckusick /*
86965789Smckusick  * Unlock an inode.
87065789Smckusick  */
87165789Smckusick int
cd9660_unlock(ap)87265855Smckusick cd9660_unlock(ap)
87365789Smckusick 	struct vop_unlock_args /* {
87465789Smckusick 		struct vnode *a_vp;
87569427Smckusick 		int a_flags;
87669427Smckusick 		struct proc *a_p;
87765789Smckusick 	} */ *ap;
87865789Smckusick {
87969427Smckusick 	struct vnode *vp = ap->a_vp;
88065789Smckusick 
88169427Smckusick 	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
88269427Smckusick 		&vp->v_interlock, ap->a_p));
88365789Smckusick }
88465789Smckusick 
88565789Smckusick /*
88665789Smckusick  * Calculate the logical to physical mapping if not done already,
88765789Smckusick  * then call the device strategy routine.
88865789Smckusick  */
88965789Smckusick int
cd9660_strategy(ap)89065855Smckusick cd9660_strategy(ap)
89165789Smckusick 	struct vop_strategy_args /* {
89265789Smckusick 		struct buf *a_bp;
89365789Smckusick 	} */ *ap;
89465789Smckusick {
89565789Smckusick 	register struct buf *bp = ap->a_bp;
89665789Smckusick 	register struct vnode *vp = bp->b_vp;
89765789Smckusick 	register struct iso_node *ip;
89865789Smckusick 	int error;
89965789Smckusick 
90065789Smckusick 	ip = VTOI(vp);
90165789Smckusick 	if (vp->v_type == VBLK || vp->v_type == VCHR)
90265855Smckusick 		panic("cd9660_strategy: spec");
90365789Smckusick 	if (bp->b_blkno == bp->b_lblkno) {
90465789Smckusick 		if (error =
90565789Smckusick 		    VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) {
90665789Smckusick 			bp->b_error = error;
90765789Smckusick 			bp->b_flags |= B_ERROR;
90865789Smckusick 			biodone(bp);
90965789Smckusick 			return (error);
91065789Smckusick 		}
91165789Smckusick 		if ((long)bp->b_blkno == -1)
91265789Smckusick 			clrbuf(bp);
91365789Smckusick 	}
91465789Smckusick 	if ((long)bp->b_blkno == -1) {
91565789Smckusick 		biodone(bp);
91665789Smckusick 		return (0);
91765789Smckusick 	}
91865789Smckusick 	vp = ip->i_devvp;
91965789Smckusick 	bp->b_dev = vp->v_rdev;
92065789Smckusick 	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
92165789Smckusick 	return (0);
92265789Smckusick }
92365789Smckusick 
92465789Smckusick /*
92565789Smckusick  * Print out the contents of an inode.
92665789Smckusick  */
92765789Smckusick int
cd9660_print(ap)92865855Smckusick cd9660_print(ap)
92965789Smckusick 	struct vop_print_args /* {
93065789Smckusick 		struct vnode *a_vp;
93165789Smckusick 	} */ *ap;
93265789Smckusick {
93368052Smckusick 
93465789Smckusick 	printf("tag VT_ISOFS, isofs vnode\n");
93567379Smkm 	return (0);
93665789Smckusick }
93765789Smckusick 
93865789Smckusick /*
93968052Smckusick  * Check for a locked inode.
94068052Smckusick  */
94168052Smckusick int
cd9660_islocked(ap)94268052Smckusick cd9660_islocked(ap)
94368052Smckusick 	struct vop_islocked_args /* {
94468052Smckusick 		struct vnode *a_vp;
94568052Smckusick 	} */ *ap;
94668052Smckusick {
94768052Smckusick 
94869427Smckusick 	return (lockstatus(&VTOI(ap->a_vp)->i_lock));
94968052Smckusick }
95068052Smckusick 
95168052Smckusick /*
95268052Smckusick  * Return POSIX pathconf information applicable to cd9660 filesystems.
95368052Smckusick  */
95468052Smckusick int
cd9660_pathconf(ap)95568052Smckusick cd9660_pathconf(ap)
95668052Smckusick 	struct vop_pathconf_args /* {
95768052Smckusick 		struct vnode *a_vp;
95868052Smckusick 		int a_name;
95968052Smckusick 		register_t *a_retval;
96068052Smckusick 	} */ *ap;
96168052Smckusick {
96268052Smckusick 
96368052Smckusick 	switch (ap->a_name) {
96468052Smckusick 	case _PC_LINK_MAX:
96568052Smckusick 		*ap->a_retval = 1;
96668052Smckusick 		return (0);
96768052Smckusick 	case _PC_NAME_MAX:
96868052Smckusick 		if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
96968052Smckusick 			*ap->a_retval = NAME_MAX;
97068052Smckusick 		else
97168052Smckusick 			*ap->a_retval = 37;
97268052Smckusick 		return (0);
97368052Smckusick 	case _PC_PATH_MAX:
97468052Smckusick 		*ap->a_retval = PATH_MAX;
97568052Smckusick 		return (0);
97668052Smckusick 	case _PC_PIPE_BUF:
97768052Smckusick 		*ap->a_retval = PIPE_BUF;
97868052Smckusick 		return (0);
97968052Smckusick 	case _PC_CHOWN_RESTRICTED:
98068052Smckusick 		*ap->a_retval = 1;
98168052Smckusick 		return (0);
98268052Smckusick 	case _PC_NO_TRUNC:
98368052Smckusick 		*ap->a_retval = 1;
98468052Smckusick 		return (0);
98568052Smckusick 	default:
98668052Smckusick 		return (EINVAL);
98768052Smckusick 	}
98868052Smckusick 	/* NOTREACHED */
98968052Smckusick }
99068052Smckusick 
99168052Smckusick /*
99265789Smckusick  * Global vfs data structures for isofs
99365789Smckusick  */
99465855Smckusick #define cd9660_create \
99568681Smckusick 	((int (*) __P((struct  vop_create_args *)))eopnotsupp)
99668681Smckusick #define cd9660_mknod ((int (*) __P((struct  vop_mknod_args *)))eopnotsupp)
99768681Smckusick #define cd9660_write ((int (*) __P((struct  vop_write_args *)))eopnotsupp)
99867652Smckusick #ifdef NFS
99967652Smckusick int	 lease_check __P((struct vop_lease_args *));
100067652Smckusick #define	 cd9660_lease_check lease_check
100167652Smckusick #else
100267652Smckusick #define	 cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
100367652Smckusick #endif
100465855Smckusick #define cd9660_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
100565855Smckusick #define cd9660_remove \
100668681Smckusick 	((int (*) __P((struct  vop_remove_args *)))eopnotsupp)
100768681Smckusick #define cd9660_link ((int (*) __P((struct  vop_link_args *)))eopnotsupp)
100865855Smckusick #define cd9660_rename \
100968681Smckusick 	((int (*) __P((struct  vop_rename_args *)))eopnotsupp)
101068681Smckusick #define cd9660_mkdir ((int (*) __P((struct  vop_mkdir_args *)))eopnotsupp)
101168681Smckusick #define cd9660_rmdir ((int (*) __P((struct  vop_rmdir_args *)))eopnotsupp)
101265855Smckusick #define cd9660_symlink \
101368681Smckusick 	((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
101465855Smckusick #define cd9660_advlock \
101568681Smckusick 	((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
101665855Smckusick #define cd9660_valloc ((int(*) __P(( \
101765789Smckusick 		struct vnode *pvp, \
101865789Smckusick 		int mode, \
101965789Smckusick 		struct ucred *cred, \
102068681Smckusick 		struct vnode **vpp))) eopnotsupp)
102168681Smckusick #define cd9660_vfree ((int (*) __P((struct  vop_vfree_args *)))eopnotsupp)
102265855Smckusick #define cd9660_truncate \
102368681Smckusick 	((int (*) __P((struct  vop_truncate_args *)))eopnotsupp)
102465855Smckusick #define cd9660_update \
102568681Smckusick 	((int (*) __P((struct  vop_update_args *)))eopnotsupp)
102665855Smckusick #define cd9660_bwrite \
102768681Smckusick 	((int (*) __P((struct  vop_bwrite_args *)))eopnotsupp)
102865789Smckusick 
102965789Smckusick /*
103068052Smckusick  * Global vfs data structures for cd9660
103165789Smckusick  */
103265855Smckusick int (**cd9660_vnodeop_p)();
103365855Smckusick struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
103465789Smckusick 	{ &vop_default_desc, vn_default_error },
103565855Smckusick 	{ &vop_lookup_desc, cd9660_lookup },	/* lookup */
103665855Smckusick 	{ &vop_create_desc, cd9660_create },	/* create */
103765855Smckusick 	{ &vop_mknod_desc, cd9660_mknod },	/* mknod */
103865855Smckusick 	{ &vop_open_desc, cd9660_open },	/* open */
103965855Smckusick 	{ &vop_close_desc, cd9660_close },	/* close */
104065855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
104165855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
104265855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
104365855Smckusick 	{ &vop_read_desc, cd9660_read },	/* read */
104465855Smckusick 	{ &vop_write_desc, cd9660_write },	/* write */
104567652Smckusick 	{ &vop_lease_desc, cd9660_lease_check },/* lease */
104665855Smckusick 	{ &vop_ioctl_desc, cd9660_ioctl },	/* ioctl */
104765855Smckusick 	{ &vop_select_desc, cd9660_select },	/* select */
104868454Smckusick 	{ &vop_revoke_desc, cd9660_revoke },	/* revoke */
104965855Smckusick 	{ &vop_mmap_desc, cd9660_mmap },	/* mmap */
105065855Smckusick 	{ &vop_fsync_desc, cd9660_fsync },	/* fsync */
105165855Smckusick 	{ &vop_seek_desc, cd9660_seek },	/* seek */
105265855Smckusick 	{ &vop_remove_desc, cd9660_remove },	/* remove */
105365855Smckusick 	{ &vop_link_desc, cd9660_link },	/* link */
105465855Smckusick 	{ &vop_rename_desc, cd9660_rename },	/* rename */
105565855Smckusick 	{ &vop_mkdir_desc, cd9660_mkdir },	/* mkdir */
105665855Smckusick 	{ &vop_rmdir_desc, cd9660_rmdir },	/* rmdir */
105765855Smckusick 	{ &vop_symlink_desc, cd9660_symlink },	/* symlink */
105865855Smckusick 	{ &vop_readdir_desc, cd9660_readdir },	/* readdir */
105965855Smckusick 	{ &vop_readlink_desc, cd9660_readlink },/* readlink */
106065855Smckusick 	{ &vop_abortop_desc, cd9660_abortop },	/* abortop */
106165855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
106265855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
106365855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
106465855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
106565855Smckusick 	{ &vop_bmap_desc, cd9660_bmap },	/* bmap */
106665855Smckusick 	{ &vop_strategy_desc, cd9660_strategy },/* strategy */
106765855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
106865855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
106965855Smckusick 	{ &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
107065855Smckusick 	{ &vop_advlock_desc, cd9660_advlock },	/* advlock */
107165855Smckusick 	{ &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */
107265855Smckusick 	{ &vop_valloc_desc, cd9660_valloc },	/* valloc */
107365855Smckusick 	{ &vop_vfree_desc, cd9660_vfree },	/* vfree */
107465855Smckusick 	{ &vop_truncate_desc, cd9660_truncate },/* truncate */
107565855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
107665789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
107765789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
107865789Smckusick };
107965855Smckusick struct vnodeopv_desc cd9660_vnodeop_opv_desc =
108065855Smckusick 	{ &cd9660_vnodeop_p, cd9660_vnodeop_entries };
108165789Smckusick 
108265789Smckusick /*
108365789Smckusick  * Special device vnode ops
108465789Smckusick  */
108565855Smckusick int (**cd9660_specop_p)();
108665855Smckusick struct vnodeopv_entry_desc cd9660_specop_entries[] = {
108765789Smckusick 	{ &vop_default_desc, vn_default_error },
108865789Smckusick 	{ &vop_lookup_desc, spec_lookup },	/* lookup */
108967891Smckusick 	{ &vop_create_desc, spec_create },	/* create */
109067891Smckusick 	{ &vop_mknod_desc, spec_mknod },	/* mknod */
109165789Smckusick 	{ &vop_open_desc, spec_open },		/* open */
109265789Smckusick 	{ &vop_close_desc, spec_close },	/* close */
109365855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
109465855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
109565855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
109665789Smckusick 	{ &vop_read_desc, spec_read },		/* read */
109765789Smckusick 	{ &vop_write_desc, spec_write },	/* write */
109867652Smckusick 	{ &vop_lease_desc, spec_lease_check },	/* lease */
109965789Smckusick 	{ &vop_ioctl_desc, spec_ioctl },	/* ioctl */
110065789Smckusick 	{ &vop_select_desc, spec_select },	/* select */
110168454Smckusick 	{ &vop_revoke_desc, spec_revoke },	/* revoke */
110265789Smckusick 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
110365789Smckusick 	{ &vop_fsync_desc, spec_fsync },	/* fsync */
110465789Smckusick 	{ &vop_seek_desc, spec_seek },		/* seek */
110567891Smckusick 	{ &vop_remove_desc, spec_remove },	/* remove */
110667891Smckusick 	{ &vop_link_desc, spec_link },		/* link */
110767891Smckusick 	{ &vop_rename_desc, spec_rename },	/* rename */
110867891Smckusick 	{ &vop_mkdir_desc, spec_mkdir },	/* mkdir */
110967891Smckusick 	{ &vop_rmdir_desc, spec_rmdir },	/* rmdir */
111067891Smckusick 	{ &vop_symlink_desc, spec_symlink },	/* symlink */
111165789Smckusick 	{ &vop_readdir_desc, spec_readdir },	/* readdir */
111265789Smckusick 	{ &vop_readlink_desc, spec_readlink },	/* readlink */
111365789Smckusick 	{ &vop_abortop_desc, spec_abortop },	/* abortop */
111465855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
111565855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
111665855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
111765855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
111865789Smckusick 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
111967891Smckusick 	{ &vop_strategy_desc, spec_strategy },	/* strategy */
112065855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
112165855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
112265789Smckusick 	{ &vop_pathconf_desc, spec_pathconf },	/* pathconf */
112365789Smckusick 	{ &vop_advlock_desc, spec_advlock },	/* advlock */
112465789Smckusick 	{ &vop_blkatoff_desc, spec_blkatoff },	/* blkatoff */
112565789Smckusick 	{ &vop_valloc_desc, spec_valloc },	/* valloc */
112665789Smckusick 	{ &vop_vfree_desc, spec_vfree },	/* vfree */
112765789Smckusick 	{ &vop_truncate_desc, spec_truncate },	/* truncate */
112865855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
112965789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
113065789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
113165789Smckusick };
113265855Smckusick struct vnodeopv_desc cd9660_specop_opv_desc =
113365855Smckusick 	{ &cd9660_specop_p, cd9660_specop_entries };
113465789Smckusick 
113565789Smckusick #ifdef FIFO
113665855Smckusick int (**cd9660_fifoop_p)();
113765855Smckusick struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
113865789Smckusick 	{ &vop_default_desc, vn_default_error },
113965789Smckusick 	{ &vop_lookup_desc, fifo_lookup },	/* lookup */
114067891Smckusick 	{ &vop_create_desc, fifo_create },	/* create */
114167891Smckusick 	{ &vop_mknod_desc, fifo_mknod },	/* mknod */
114265789Smckusick 	{ &vop_open_desc, fifo_open },		/* open */
114365789Smckusick 	{ &vop_close_desc, fifo_close },	/* close */
114465855Smckusick 	{ &vop_access_desc, cd9660_access },	/* access */
114565855Smckusick 	{ &vop_getattr_desc, cd9660_getattr },	/* getattr */
114665855Smckusick 	{ &vop_setattr_desc, cd9660_setattr },	/* setattr */
114765789Smckusick 	{ &vop_read_desc, fifo_read },		/* read */
114865789Smckusick 	{ &vop_write_desc, fifo_write },	/* write */
114967652Smckusick 	{ &vop_lease_desc, fifo_lease_check },	/* lease */
115065789Smckusick 	{ &vop_ioctl_desc, fifo_ioctl },	/* ioctl */
115165789Smckusick 	{ &vop_select_desc, fifo_select },	/* select */
115268454Smckusick 	{ &vop_revoke_desc, fifo_revoke },	/* revoke */
115365789Smckusick 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
115465789Smckusick 	{ &vop_fsync_desc, fifo_fsync },	/* fsync */
115565789Smckusick 	{ &vop_seek_desc, fifo_seek },		/* seek */
115667891Smckusick 	{ &vop_remove_desc, fifo_remove },	/* remove */
115767891Smckusick 	{ &vop_link_desc, fifo_link }	,	/* link */
115867891Smckusick 	{ &vop_rename_desc, fifo_rename },	/* rename */
115967891Smckusick 	{ &vop_mkdir_desc, fifo_mkdir },	/* mkdir */
116067891Smckusick 	{ &vop_rmdir_desc, fifo_rmdir },	/* rmdir */
116167891Smckusick 	{ &vop_symlink_desc, fifo_symlink },	/* symlink */
116265789Smckusick 	{ &vop_readdir_desc, fifo_readdir },	/* readdir */
116365789Smckusick 	{ &vop_readlink_desc, fifo_readlink },	/* readlink */
116465789Smckusick 	{ &vop_abortop_desc, fifo_abortop },	/* abortop */
116565855Smckusick 	{ &vop_inactive_desc, cd9660_inactive },/* inactive */
116665855Smckusick 	{ &vop_reclaim_desc, cd9660_reclaim },	/* reclaim */
116765855Smckusick 	{ &vop_lock_desc, cd9660_lock },	/* lock */
116865855Smckusick 	{ &vop_unlock_desc, cd9660_unlock },	/* unlock */
116965789Smckusick 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
117067891Smckusick 	{ &vop_strategy_desc, fifo_strategy },	/* strategy */
117165855Smckusick 	{ &vop_print_desc, cd9660_print },	/* print */
117265855Smckusick 	{ &vop_islocked_desc, cd9660_islocked },/* islocked */
117365789Smckusick 	{ &vop_pathconf_desc, fifo_pathconf },	/* pathconf */
117465789Smckusick 	{ &vop_advlock_desc, fifo_advlock },	/* advlock */
117565789Smckusick 	{ &vop_blkatoff_desc, fifo_blkatoff },	/* blkatoff */
117665789Smckusick 	{ &vop_valloc_desc, fifo_valloc },	/* valloc */
117765789Smckusick 	{ &vop_vfree_desc, fifo_vfree },	/* vfree */
117865789Smckusick 	{ &vop_truncate_desc, fifo_truncate },	/* truncate */
117965855Smckusick 	{ &vop_update_desc, cd9660_update },	/* update */
118065789Smckusick 	{ &vop_bwrite_desc, vn_bwrite },
118165789Smckusick 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
118265789Smckusick };
118365855Smckusick struct vnodeopv_desc cd9660_fifoop_opv_desc =
118465855Smckusick 	{ &cd9660_fifoop_p, cd9660_fifoop_entries };
118565789Smckusick #endif /* FIFO */
1186