diff options
Diffstat (limited to 'sys/fs/cd9660/cd9660_vnops.c')
-rw-r--r-- | sys/fs/cd9660/cd9660_vnops.c | 930 |
1 files changed, 930 insertions, 0 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c new file mode 100644 index 0000000..65ad938 --- /dev/null +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -0,0 +1,930 @@ +/*- + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley + * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension + * Support code is derived from software contributed to Berkeley + * by Atsushi Murai (amurai@spec.co.jp). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/kernel.h> +#include <sys/stat.h> +#include <sys/buf.h> +#include <sys/mount.h> +#include <sys/vnode.h> +#include <miscfs/fifofs/fifo.h> +#include <sys/malloc.h> +#include <sys/dirent.h> +#include <sys/unistd.h> +#include <sys/filio.h> + +#include <vm/vm.h> +#include <vm/vm_zone.h> +#include <vm/vnode_pager.h> + +#include <isofs/cd9660/iso.h> +#include <isofs/cd9660/cd9660_node.h> +#include <isofs/cd9660/iso_rrip.h> + +static int cd9660_setattr __P((struct vop_setattr_args *)); +static int cd9660_access __P((struct vop_access_args *)); +static int cd9660_getattr __P((struct vop_getattr_args *)); +static int cd9660_ioctl __P((struct vop_ioctl_args *)); +static int cd9660_pathconf __P((struct vop_pathconf_args *)); +static int cd9660_read __P((struct vop_read_args *)); +struct isoreaddir; +static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp, + off_t off)); +static int iso_shipdir __P((struct isoreaddir *idp)); +static int cd9660_readdir __P((struct vop_readdir_args *)); +static int cd9660_readlink __P((struct vop_readlink_args *ap)); +static int cd9660_strategy __P((struct vop_strategy_args *)); +static int cd9660_print __P((struct vop_print_args *)); +static int cd9660_getpages __P((struct vop_getpages_args *)); +static int cd9660_putpages __P((struct vop_putpages_args *)); + +/* + * Setattr call. Only allowed for block and character special devices. + */ +int +cd9660_setattr(ap) + struct vop_setattr_args /* { + struct vnodeop_desc *a_desc; + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct vattr *vap = ap->a_vap; + + if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || + vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || + vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) + return (EROFS); + if (vap->va_size != (u_quad_t)VNOVAL) { + switch (vp->v_type) { + case VDIR: + return (EISDIR); + case VLNK: + case VREG: + return (EROFS); + case VCHR: + case VBLK: + case VSOCK: + case VFIFO: + case VNON: + case VBAD: + return (0); + } + } + return (0); +} + +/* + * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. + * The mode is shifted to select the owner/group/other fields. The + * super user is granted all permissions. + */ +/* ARGSUSED */ +static int +cd9660_access(ap) + struct vop_access_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct iso_node *ip = VTOI(vp); + struct ucred *cred = ap->a_cred; + mode_t mask, mode = ap->a_mode; + gid_t *gp; + int i; + + /* + * Disallow write attempts unless the file is a socket, + * fifo, or a block or character device resident on the + * file system. + */ + if (mode & VWRITE) { + switch (vp->v_type) { + case VDIR: + case VLNK: + case VREG: + return (EROFS); + /* NOT REACHED */ + default: + break; + } + } + + /* User id 0 always gets access. */ + if (cred->cr_uid == 0) + return (0); + + mask = 0; + + /* Otherwise, check the owner. */ + if (cred->cr_uid == ip->inode.iso_uid) { + if (mode & VEXEC) + mask |= S_IXUSR; + if (mode & VREAD) + mask |= S_IRUSR; + if (mode & VWRITE) + mask |= S_IWUSR; + return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); + } + + /* Otherwise, check the groups. */ + for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) + if (ip->inode.iso_gid == *gp) { + if (mode & VEXEC) + mask |= S_IXGRP; + if (mode & VREAD) + mask |= S_IRGRP; + if (mode & VWRITE) + mask |= S_IWGRP; + return ((ip->inode.iso_mode & mask) == mask ? + 0 : EACCES); + } + + /* Otherwise, check everyone else. */ + if (mode & VEXEC) + mask |= S_IXOTH; + if (mode & VREAD) + mask |= S_IROTH; + if (mode & VWRITE) + mask |= S_IWOTH; + return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); +} + +static int +cd9660_getattr(ap) + struct vop_getattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; + +{ + struct vnode *vp = ap->a_vp; + register struct vattr *vap = ap->a_vap; + register struct iso_node *ip = VTOI(vp); + + vap->va_fsid = dev2udev(ip->i_dev); + vap->va_fileid = ip->i_number; + + vap->va_mode = ip->inode.iso_mode; + vap->va_nlink = ip->inode.iso_links; + vap->va_uid = ip->inode.iso_uid; + vap->va_gid = ip->inode.iso_gid; + vap->va_atime = ip->inode.iso_atime; + vap->va_mtime = ip->inode.iso_mtime; + vap->va_ctime = ip->inode.iso_ctime; + vap->va_rdev = ip->inode.iso_rdev; + + vap->va_size = (u_quad_t) ip->i_size; + if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { + struct vop_readlink_args rdlnk; + struct iovec aiov; + struct uio auio; + char *cp; + + MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); + aiov.iov_base = cp; + aiov.iov_len = MAXPATHLEN; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_procp = ap->a_p; + auio.uio_resid = MAXPATHLEN; + rdlnk.a_uio = &auio; + rdlnk.a_vp = ap->a_vp; + rdlnk.a_cred = ap->a_cred; + if (cd9660_readlink(&rdlnk) == 0) + vap->va_size = MAXPATHLEN - auio.uio_resid; + FREE(cp, M_TEMP); + } + vap->va_flags = 0; + vap->va_gen = 1; + vap->va_blocksize = ip->i_mnt->logical_block_size; + vap->va_bytes = (u_quad_t) ip->i_size; + vap->va_type = vp->v_type; + vap->va_filerev = 0; + return (0); +} + +/* + * Vnode op for ioctl. + */ +static int +cd9660_ioctl(ap) + struct vop_ioctl_args /* { + struct vnode *a_vp; + int a_command; + caddr_t a_data; + int a_fflag; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct iso_node *ip = VTOI(vp); + + switch (ap->a_command) { + + case FIOGETLBA: + *(int *)(ap->a_data) = ip->iso_start; + return 0; + default: + return (ENOTTY); + } +} + +/* + * Vnode op for reading. + */ +static int +cd9660_read(ap) + struct vop_read_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + register struct uio *uio = ap->a_uio; + register struct iso_node *ip = VTOI(vp); + register struct iso_mnt *imp; + struct buf *bp; + daddr_t lbn, rablock; + off_t diff; + int rasize, error = 0; + int seqcount; + long size, n, on; + + seqcount = ap->a_ioflag >> 16; + + if (uio->uio_resid == 0) + return (0); + if (uio->uio_offset < 0) + return (EINVAL); + ip->i_flag |= IN_ACCESS; + imp = ip->i_mnt; + do { + lbn = lblkno(imp, uio->uio_offset); + on = blkoff(imp, uio->uio_offset); + n = min((u_int)(imp->logical_block_size - on), + uio->uio_resid); + diff = (off_t)ip->i_size - uio->uio_offset; + if (diff <= 0) + return (0); + if (diff < n) + n = diff; + size = blksize(imp, ip, lbn); + rablock = lbn + 1; + if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { + if (lblktosize(imp, rablock) < ip->i_size) + error = cluster_read(vp, (off_t)ip->i_size, + lbn, size, NOCRED, uio->uio_resid, + (ap->a_ioflag >> 16), &bp); + else + error = bread(vp, lbn, size, NOCRED, &bp); + } else { + if (seqcount > 1 && + lblktosize(imp, rablock) < ip->i_size) { + rasize = blksize(imp, ip, rablock); + error = breadn(vp, lbn, size, &rablock, + &rasize, 1, NOCRED, &bp); + } else + error = bread(vp, lbn, size, NOCRED, &bp); + } + n = min(n, size - bp->b_resid); + if (error) { + brelse(bp); + return (error); + } + + error = uiomove(bp->b_data + on, (int)n, uio); + brelse(bp); + } while (error == 0 && uio->uio_resid > 0 && n != 0); + return (error); +} + +/* + * Structure for reading directories + */ +struct isoreaddir { + struct dirent saveent; + struct dirent assocent; + struct dirent current; + off_t saveoff; + off_t assocoff; + off_t curroff; + struct uio *uio; + off_t uio_off; + int eofflag; + u_long *cookies; + int ncookies; +}; + +int +iso_uiodir(idp,dp,off) + struct isoreaddir *idp; + struct dirent *dp; + off_t off; +{ + int error; + + dp->d_name[dp->d_namlen] = 0; + dp->d_reclen = GENERIC_DIRSIZ(dp); + + if (idp->uio->uio_resid < dp->d_reclen) { + idp->eofflag = 0; + return (-1); + } + + if (idp->cookies) { + if (idp->ncookies <= 0) { + idp->eofflag = 0; + return (-1); + } + + *idp->cookies++ = off; + --idp->ncookies; + } + + if ((error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) != 0) + return (error); + idp->uio_off = off; + return (0); +} + +int +iso_shipdir(idp) + struct isoreaddir *idp; +{ + struct dirent *dp; + int cl, sl, assoc; + int error; + char *cname, *sname; + + cl = idp->current.d_namlen; + cname = idp->current.d_name; +assoc = (cl > 1) && (*cname == ASSOCCHAR); + if (assoc) { + cl--; + cname++; + } + + dp = &idp->saveent; + sname = dp->d_name; + if (!(sl = dp->d_namlen)) { + dp = &idp->assocent; + sname = dp->d_name + 1; + sl = dp->d_namlen - 1; + } + if (sl > 0) { + if (sl != cl + || bcmp(sname,cname,sl)) { + if (idp->assocent.d_namlen) { + if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) + return (error); + idp->assocent.d_namlen = 0; + } + if (idp->saveent.d_namlen) { + if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) + return (error); + idp->saveent.d_namlen = 0; + } + } + } + idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); + if (assoc) { + idp->assocoff = idp->curroff; + bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); + } else { + idp->saveoff = idp->curroff; + bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); + } + return (0); +} + +/* + * Vnode op for readdir + */ +static int +cd9660_readdir(ap) + struct vop_readdir_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + int *a_eofflag; + int *a_ncookies; + u_long *a_cookies; + } */ *ap; +{ + register struct uio *uio = ap->a_uio; + struct isoreaddir *idp; + struct vnode *vdp = ap->a_vp; + struct iso_node *dp; + struct iso_mnt *imp; + struct buf *bp = NULL; + struct iso_directory_record *ep; + int entryoffsetinblock; + doff_t endsearch; + u_long bmask; + int error = 0; + int reclen; + u_short namelen; + int ncookies = 0; + u_long *cookies = NULL; + + dp = VTOI(vdp); + imp = dp->i_mnt; + bmask = imp->im_bmask; + + MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); + idp->saveent.d_namlen = idp->assocent.d_namlen = 0; + /* + * XXX + * Is it worth trying to figure out the type? + */ + idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = + DT_UNKNOWN; + idp->uio = uio; + if (ap->a_ncookies == NULL) { + idp->cookies = NULL; + } else { + /* + * Guess the number of cookies needed. + */ + ncookies = uio->uio_resid / 16; + MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, + M_WAITOK); + idp->cookies = cookies; + idp->ncookies = ncookies; + } + idp->eofflag = 1; + idp->curroff = uio->uio_offset; + + if ((entryoffsetinblock = idp->curroff & bmask) && + (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { + FREE(idp, M_TEMP); + return (error); + } + endsearch = dp->i_size; + + while (idp->curroff < endsearch) { + /* + * If offset is on a block boundary, + * read the next directory block. + * Release previous if it exists. + */ + if ((idp->curroff & bmask) == 0) { + if (bp != NULL) + brelse(bp); + if ((error = + cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) + break; + entryoffsetinblock = 0; + } + /* + * Get pointer to next entry. + */ + ep = (struct iso_directory_record *) + ((char *)bp->b_data + entryoffsetinblock); + + reclen = isonum_711(ep->length); + if (reclen == 0) { + /* skip to next block, if any */ + idp->curroff = + (idp->curroff & ~bmask) + imp->logical_block_size; + continue; + } + + if (reclen < ISO_DIRECTORY_RECORD_SIZE) { + error = EINVAL; + /* illegal entry, stop */ + break; + } + + if (entryoffsetinblock + reclen > imp->logical_block_size) { + error = EINVAL; + /* illegal directory, so stop looking */ + break; + } + + idp->current.d_namlen = isonum_711(ep->name_len); + + if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { + error = EINVAL; + /* illegal entry, stop */ + break; + } + + if (isonum_711(ep->flags)&2) + idp->current.d_fileno = isodirino(ep, imp); + else + idp->current.d_fileno = dbtob(bp->b_blkno) + + entryoffsetinblock; + + idp->curroff += reclen; + + switch (imp->iso_ftype) { + case ISO_FTYPE_RRIP: + cd9660_rrip_getname(ep,idp->current.d_name, &namelen, + &idp->current.d_fileno,imp); + idp->current.d_namlen = (u_char)namelen; + if (idp->current.d_namlen) + error = iso_uiodir(idp,&idp->current,idp->curroff); + break; + default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ + strcpy(idp->current.d_name,".."); + if (idp->current.d_namlen == 1 && ep->name[0] == 0) { + idp->current.d_namlen = 1; + error = iso_uiodir(idp,&idp->current,idp->curroff); + } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { + idp->current.d_namlen = 2; + error = iso_uiodir(idp,&idp->current,idp->curroff); + } else { + isofntrans(ep->name,idp->current.d_namlen, + idp->current.d_name, &namelen, + imp->iso_ftype == ISO_FTYPE_9660, + isonum_711(ep->flags)&4, + imp->joliet_level); + idp->current.d_namlen = (u_char)namelen; + if (imp->iso_ftype == ISO_FTYPE_DEFAULT) + error = iso_shipdir(idp); + else + error = iso_uiodir(idp,&idp->current,idp->curroff); + } + } + if (error) + break; + + entryoffsetinblock += reclen; + } + + if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { + idp->current.d_namlen = 0; + error = iso_shipdir(idp); + } + if (error < 0) + error = 0; + + if (ap->a_ncookies != NULL) { + if (error) + free(cookies, M_TEMP); + else { + /* + * Work out the number of cookies actually used. + */ + *ap->a_ncookies = ncookies - idp->ncookies; + *ap->a_cookies = cookies; + } + } + + if (bp) + brelse (bp); + + uio->uio_offset = idp->uio_off; + *ap->a_eofflag = idp->eofflag; + + FREE(idp, M_TEMP); + + return (error); +} + +/* + * Return target name of a symbolic link + * Shouldn't we get the parent vnode and read the data from there? + * This could eventually result in deadlocks in cd9660_lookup. + * But otherwise the block read here is in the block buffer two times. + */ +typedef struct iso_directory_record ISODIR; +typedef struct iso_node ISONODE; +typedef struct iso_mnt ISOMNT; +static int +cd9660_readlink(ap) + struct vop_readlink_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + } */ *ap; +{ + ISONODE *ip; + ISODIR *dirp; + ISOMNT *imp; + struct buf *bp; + struct uio *uio; + u_short symlen; + int error; + char *symname; + + ip = VTOI(ap->a_vp); + imp = ip->i_mnt; + uio = ap->a_uio; + + if (imp->iso_ftype != ISO_FTYPE_RRIP) + return (EINVAL); + + /* + * Get parents directory record block that this inode included. + */ + error = bread(imp->im_devvp, + (ip->i_number >> imp->im_bshift) << + (imp->im_bshift - DEV_BSHIFT), + imp->logical_block_size, NOCRED, &bp); + if (error) { + brelse(bp); + return (EINVAL); + } + + /* + * Setup the directory pointer for this inode + */ + dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); + + /* + * Just make sure, we have a right one.... + * 1: Check not cross boundary on block + */ + if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) + > (unsigned)imp->logical_block_size) { + brelse(bp); + return (EINVAL); + } + + /* + * Now get a buffer + * Abuse a namei buffer for now. + */ + if (uio->uio_segflg == UIO_SYSSPACE) + symname = uio->uio_iov->iov_base; + else + symname = zalloc(namei_zone); + + /* + * Ok, we just gathering a symbolic name in SL record. + */ + if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { + if (uio->uio_segflg != UIO_SYSSPACE) + zfree(namei_zone, symname); + brelse(bp); + return (EINVAL); + } + /* + * Don't forget before you leave from home ;-) + */ + brelse(bp); + + /* + * return with the symbolic name to caller's. + */ + if (uio->uio_segflg != UIO_SYSSPACE) { + error = uiomove(symname, symlen, uio); + zfree(namei_zone, symname); + return (error); + } + uio->uio_resid -= symlen; + uio->uio_iov->iov_base += symlen; + uio->uio_iov->iov_len -= symlen; + return (0); +} + +/* + * Calculate the logical to physical mapping if not done already, + * then call the device strategy routine. + */ +static int +cd9660_strategy(ap) + struct vop_strategy_args /* { + struct buf *a_vp; + struct buf *a_bp; + } */ *ap; +{ + register struct buf *bp = ap->a_bp; + register struct vnode *vp = bp->b_vp; + register struct iso_node *ip; + int error; + + ip = VTOI(vp); + if (vp->v_type == VBLK || vp->v_type == VCHR) + panic("cd9660_strategy: spec"); + if (bp->b_blkno == bp->b_lblkno) { + if ((error = + VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) { + bp->b_error = error; + bp->b_flags |= B_ERROR; + biodone(bp); + return (error); + } + if ((long)bp->b_blkno == -1) + clrbuf(bp); + } + if ((long)bp->b_blkno == -1) { + biodone(bp); + return (0); + } + vp = ip->i_devvp; + bp->b_dev = vp->v_rdev; + VOP_STRATEGY(vp, bp); + return (0); +} + +/* + * Print out the contents of an inode. + */ +static int +cd9660_print(ap) + struct vop_print_args /* { + struct vnode *a_vp; + } */ *ap; +{ + + printf("tag VT_ISOFS, isofs vnode\n"); + return (0); +} + +/* + * Return POSIX pathconf information applicable to cd9660 filesystems. + */ +static int +cd9660_pathconf(ap) + struct vop_pathconf_args /* { + struct vnode *a_vp; + int a_name; + register_t *a_retval; + } */ *ap; +{ + + switch (ap->a_name) { + case _PC_LINK_MAX: + *ap->a_retval = 1; + return (0); + case _PC_NAME_MAX: + if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) + *ap->a_retval = NAME_MAX; + else + *ap->a_retval = 37; + return (0); + case _PC_PATH_MAX: + *ap->a_retval = PATH_MAX; + return (0); + case _PC_PIPE_BUF: + *ap->a_retval = PIPE_BUF; + return (0); + case _PC_CHOWN_RESTRICTED: + *ap->a_retval = 1; + return (0); + case _PC_NO_TRUNC: + *ap->a_retval = 1; + return (0); + default: + return (EINVAL); + } + /* NOTREACHED */ +} + +/* + * get page routine + * + * XXX By default, wimp out... note that a_offset is ignored (and always + * XXX has been). + */ +int +cd9660_getpages(ap) + struct vop_getpages_args *ap; +{ + return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_reqpage); +} + +/* + * put page routine + * + * XXX By default, wimp out... note that a_offset is ignored (and always + * XXX has been). + */ +int +cd9660_putpages(ap) + struct vop_putpages_args *ap; +{ + return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, + ap->a_sync, ap->a_rtvals); +} + +/* + * Global vfs data structures for cd9660 + */ +vop_t **cd9660_vnodeop_p; +static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { + { &vop_default_desc, (vop_t *) vop_defaultop }, + { &vop_access_desc, (vop_t *) cd9660_access }, + { &vop_bmap_desc, (vop_t *) cd9660_bmap }, + { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, + { &vop_getattr_desc, (vop_t *) cd9660_getattr }, + { &vop_inactive_desc, (vop_t *) cd9660_inactive }, + { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, + { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, + { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, + { &vop_print_desc, (vop_t *) cd9660_print }, + { &vop_read_desc, (vop_t *) cd9660_read }, + { &vop_readdir_desc, (vop_t *) cd9660_readdir }, + { &vop_readlink_desc, (vop_t *) cd9660_readlink }, + { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, + { &vop_setattr_desc, (vop_t *) cd9660_setattr }, + { &vop_strategy_desc, (vop_t *) cd9660_strategy }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, + { &vop_getpages_desc, (vop_t *) cd9660_getpages }, + { &vop_putpages_desc, (vop_t *) cd9660_putpages }, + { NULL, NULL } +}; +static struct vnodeopv_desc cd9660_vnodeop_opv_desc = + { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; +VNODEOP_SET(cd9660_vnodeop_opv_desc); + +/* + * Special device vnode ops + */ +vop_t **cd9660_specop_p; +static struct vnodeopv_entry_desc cd9660_specop_entries[] = { + { &vop_default_desc, (vop_t *) spec_vnoperate }, + { &vop_access_desc, (vop_t *) cd9660_access }, + { &vop_getattr_desc, (vop_t *) cd9660_getattr }, + { &vop_inactive_desc, (vop_t *) cd9660_inactive }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, + { &vop_print_desc, (vop_t *) cd9660_print }, + { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, + { &vop_setattr_desc, (vop_t *) cd9660_setattr }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, + { NULL, NULL } +}; +static struct vnodeopv_desc cd9660_specop_opv_desc = + { &cd9660_specop_p, cd9660_specop_entries }; +VNODEOP_SET(cd9660_specop_opv_desc); + +vop_t **cd9660_fifoop_p; +static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { + { &vop_default_desc, (vop_t *) fifo_vnoperate }, + { &vop_access_desc, (vop_t *) cd9660_access }, + { &vop_getattr_desc, (vop_t *) cd9660_getattr }, + { &vop_inactive_desc, (vop_t *) cd9660_inactive }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, + { &vop_print_desc, (vop_t *) cd9660_print }, + { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, + { &vop_setattr_desc, (vop_t *) cd9660_setattr }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, + { NULL, NULL } +}; +static struct vnodeopv_desc cd9660_fifoop_opv_desc = + { &cd9660_fifoop_p, cd9660_fifoop_entries }; + +VNODEOP_SET(cd9660_fifoop_opv_desc); |