1df8bae1dSRodney W. Grimes /*- 2df8bae1dSRodney W. Grimes * Copyright (c) 1994 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley 6df8bae1dSRodney W. Grimes * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7df8bae1dSRodney W. Grimes * Support code is derived from software contributed to Berkeley 8df8bae1dSRodney W. Grimes * by Atsushi Murai (amurai@spec.co.jp). 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38996c772fSJohn Dyson * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 39dba3870cSPoul-Henning Kamp * $Id: cd9660_vnops.c,v 1.46 1997/10/17 12:36:11 phk Exp $ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 42df8bae1dSRodney W. Grimes #include <sys/param.h> 43df8bae1dSRodney W. Grimes #include <sys/systm.h> 44df8bae1dSRodney W. Grimes #include <sys/namei.h> 45df8bae1dSRodney W. Grimes #include <sys/kernel.h> 46df8bae1dSRodney W. Grimes #include <sys/stat.h> 479d322006SKATO Takenori #include <sys/sysctl.h> 48df8bae1dSRodney W. Grimes #include <sys/buf.h> 49df8bae1dSRodney W. Grimes #include <sys/mount.h> 50df8bae1dSRodney W. Grimes #include <sys/vnode.h> 51df8bae1dSRodney W. Grimes #include <miscfs/specfs/specdev.h> 52df8bae1dSRodney W. Grimes #include <miscfs/fifofs/fifo.h> 53df8bae1dSRodney W. Grimes #include <sys/malloc.h> 54c90607baSBruce Evans #include <sys/dirent.h> 55996c772fSJohn Dyson #include <sys/unistd.h> 56df8bae1dSRodney W. Grimes 57df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso.h> 58df8bae1dSRodney W. Grimes #include <isofs/cd9660/cd9660_node.h> 59df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso_rrip.h> 60df8bae1dSRodney W. Grimes 6110dd32cdSBruce Evans static int cd9660_setattr __P((struct vop_setattr_args *)); 62605e9724SPoul-Henning Kamp static int cd9660_access __P((struct vop_access_args *)); 63605e9724SPoul-Henning Kamp static int cd9660_getattr __P((struct vop_getattr_args *)); 64605e9724SPoul-Henning Kamp static int cd9660_read __P((struct vop_read_args *)); 6510dd32cdSBruce Evans struct isoreaddir; 6610dd32cdSBruce Evans static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp, 6710dd32cdSBruce Evans off_t off)); 6810dd32cdSBruce Evans static int iso_shipdir __P((struct isoreaddir *idp)); 69605e9724SPoul-Henning Kamp static int cd9660_readdir __P((struct vop_readdir_args *)); 7010dd32cdSBruce Evans static int cd9660_readlink __P((struct vop_readlink_args *ap)); 71605e9724SPoul-Henning Kamp static int cd9660_abortop __P((struct vop_abortop_args *)); 72605e9724SPoul-Henning Kamp static int cd9660_strategy __P((struct vop_strategy_args *)); 73605e9724SPoul-Henning Kamp static int cd9660_print __P((struct vop_print_args *)); 7410dd32cdSBruce Evans 75df8bae1dSRodney W. Grimes /* 76de8583ceSDavid Greenman * Setattr call. Only allowed for block and character special devices. 77de8583ceSDavid Greenman */ 78996c772fSJohn Dyson int 79de8583ceSDavid Greenman cd9660_setattr(ap) 80de8583ceSDavid Greenman struct vop_setattr_args /* { 81de8583ceSDavid Greenman struct vnodeop_desc *a_desc; 82de8583ceSDavid Greenman struct vnode *a_vp; 83de8583ceSDavid Greenman struct vattr *a_vap; 84de8583ceSDavid Greenman struct ucred *a_cred; 85de8583ceSDavid Greenman struct proc *a_p; 86de8583ceSDavid Greenman } */ *ap; 87de8583ceSDavid Greenman { 88de8583ceSDavid Greenman struct vnode *vp = ap->a_vp; 89de8583ceSDavid Greenman struct vattr *vap = ap->a_vap; 90de8583ceSDavid Greenman 9192579404SAlexander Langer if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 9295a1574eSNate Williams vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 9395a1574eSNate Williams vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 94de8583ceSDavid Greenman return (EROFS); 9592579404SAlexander Langer if (vap->va_size != (u_quad_t)VNOVAL) { 96de8583ceSDavid Greenman switch (vp->v_type) { 97de8583ceSDavid Greenman case VDIR: 98de8583ceSDavid Greenman return (EISDIR); 99de8583ceSDavid Greenman case VLNK: 100de8583ceSDavid Greenman case VREG: 101de8583ceSDavid Greenman return (EROFS); 102de8583ceSDavid Greenman case VCHR: 103de8583ceSDavid Greenman case VBLK: 104de8583ceSDavid Greenman case VSOCK: 105de8583ceSDavid Greenman case VFIFO: 106de8583ceSDavid Greenman return (0); 107de8583ceSDavid Greenman } 108de8583ceSDavid Greenman } 109996c772fSJohn Dyson return (0); 110de8583ceSDavid Greenman } 111de8583ceSDavid Greenman 112de8583ceSDavid Greenman /* 113df8bae1dSRodney W. Grimes * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 114df8bae1dSRodney W. Grimes * The mode is shifted to select the owner/group/other fields. The 115df8bae1dSRodney W. Grimes * super user is granted all permissions. 116df8bae1dSRodney W. Grimes */ 117df8bae1dSRodney W. Grimes /* ARGSUSED */ 118605e9724SPoul-Henning Kamp static int 119df8bae1dSRodney W. Grimes cd9660_access(ap) 120df8bae1dSRodney W. Grimes struct vop_access_args /* { 121df8bae1dSRodney W. Grimes struct vnode *a_vp; 122df8bae1dSRodney W. Grimes int a_mode; 123df8bae1dSRodney W. Grimes struct ucred *a_cred; 124df8bae1dSRodney W. Grimes struct proc *a_p; 125df8bae1dSRodney W. Grimes } */ *ap; 126df8bae1dSRodney W. Grimes { 127996c772fSJohn Dyson struct vnode *vp = ap->a_vp; 128996c772fSJohn Dyson struct iso_node *ip = VTOI(vp); 129996c772fSJohn Dyson struct ucred *cred = ap->a_cred; 130996c772fSJohn Dyson mode_t mask, mode = ap->a_mode; 131996c772fSJohn Dyson gid_t *gp; 132996c772fSJohn Dyson int i; 133996c772fSJohn Dyson 134ba14c327SDavid Greenman /* 135996c772fSJohn Dyson * Disallow write attempts unless the file is a socket, 136996c772fSJohn Dyson * fifo, or a block or character device resident on the 137996c772fSJohn Dyson * file system. 138ba14c327SDavid Greenman */ 139996c772fSJohn Dyson if (mode & VWRITE) { 140996c772fSJohn Dyson switch (vp->v_type) { 141ba14c327SDavid Greenman case VDIR: 142ba14c327SDavid Greenman case VLNK: 143ba14c327SDavid Greenman case VREG: 144ba14c327SDavid Greenman return (EROFS); 145ba14c327SDavid Greenman } 146ba14c327SDavid Greenman } 147ba14c327SDavid Greenman 148996c772fSJohn Dyson /* User id 0 always gets access. */ 149996c772fSJohn Dyson if (cred->cr_uid == 0) 150df8bae1dSRodney W. Grimes return (0); 151996c772fSJohn Dyson 152996c772fSJohn Dyson mask = 0; 153996c772fSJohn Dyson 154996c772fSJohn Dyson /* Otherwise, check the owner. */ 155996c772fSJohn Dyson if (cred->cr_uid == ip->inode.iso_uid) { 156996c772fSJohn Dyson if (mode & VEXEC) 157996c772fSJohn Dyson mask |= S_IXUSR; 158996c772fSJohn Dyson if (mode & VREAD) 159996c772fSJohn Dyson mask |= S_IRUSR; 160996c772fSJohn Dyson if (mode & VWRITE) 161996c772fSJohn Dyson mask |= S_IWUSR; 162996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 163996c772fSJohn Dyson } 164996c772fSJohn Dyson 165996c772fSJohn Dyson /* Otherwise, check the groups. */ 166996c772fSJohn Dyson for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 167996c772fSJohn Dyson if (ip->inode.iso_gid == *gp) { 168996c772fSJohn Dyson if (mode & VEXEC) 169996c772fSJohn Dyson mask |= S_IXGRP; 170996c772fSJohn Dyson if (mode & VREAD) 171996c772fSJohn Dyson mask |= S_IRGRP; 172996c772fSJohn Dyson if (mode & VWRITE) 173996c772fSJohn Dyson mask |= S_IWGRP; 174996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 175996c772fSJohn Dyson 0 : EACCES); 176996c772fSJohn Dyson } 177996c772fSJohn Dyson 178996c772fSJohn Dyson /* Otherwise, check everyone else. */ 179996c772fSJohn Dyson if (mode & VEXEC) 180996c772fSJohn Dyson mask |= S_IXOTH; 181996c772fSJohn Dyson if (mode & VREAD) 182996c772fSJohn Dyson mask |= S_IROTH; 183996c772fSJohn Dyson if (mode & VWRITE) 184996c772fSJohn Dyson mask |= S_IWOTH; 185996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 186df8bae1dSRodney W. Grimes } 187df8bae1dSRodney W. Grimes 188605e9724SPoul-Henning Kamp static int 189df8bae1dSRodney W. Grimes cd9660_getattr(ap) 190df8bae1dSRodney W. Grimes struct vop_getattr_args /* { 191df8bae1dSRodney W. Grimes struct vnode *a_vp; 192df8bae1dSRodney W. Grimes struct vattr *a_vap; 193df8bae1dSRodney W. Grimes struct ucred *a_cred; 194df8bae1dSRodney W. Grimes struct proc *a_p; 195df8bae1dSRodney W. Grimes } */ *ap; 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes { 198df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 199df8bae1dSRodney W. Grimes register struct vattr *vap = ap->a_vap; 200df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 201df8bae1dSRodney W. Grimes 202df8bae1dSRodney W. Grimes vap->va_fsid = ip->i_dev; 203df8bae1dSRodney W. Grimes vap->va_fileid = ip->i_number; 204df8bae1dSRodney W. Grimes 205df8bae1dSRodney W. Grimes vap->va_mode = ip->inode.iso_mode; 206df8bae1dSRodney W. Grimes vap->va_nlink = ip->inode.iso_links; 207df8bae1dSRodney W. Grimes vap->va_uid = ip->inode.iso_uid; 208df8bae1dSRodney W. Grimes vap->va_gid = ip->inode.iso_gid; 209df8bae1dSRodney W. Grimes vap->va_atime = ip->inode.iso_atime; 210df8bae1dSRodney W. Grimes vap->va_mtime = ip->inode.iso_mtime; 211df8bae1dSRodney W. Grimes vap->va_ctime = ip->inode.iso_ctime; 212df8bae1dSRodney W. Grimes vap->va_rdev = ip->inode.iso_rdev; 213df8bae1dSRodney W. Grimes 214df8bae1dSRodney W. Grimes vap->va_size = (u_quad_t) ip->i_size; 215996c772fSJohn Dyson if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 216996c772fSJohn Dyson struct vop_readlink_args rdlnk; 217996c772fSJohn Dyson struct iovec aiov; 218996c772fSJohn Dyson struct uio auio; 219996c772fSJohn Dyson char *cp; 220996c772fSJohn Dyson 221996c772fSJohn Dyson MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 222996c772fSJohn Dyson aiov.iov_base = cp; 223996c772fSJohn Dyson aiov.iov_len = MAXPATHLEN; 224996c772fSJohn Dyson auio.uio_iov = &aiov; 225996c772fSJohn Dyson auio.uio_iovcnt = 1; 226996c772fSJohn Dyson auio.uio_offset = 0; 227996c772fSJohn Dyson auio.uio_rw = UIO_READ; 228996c772fSJohn Dyson auio.uio_segflg = UIO_SYSSPACE; 229996c772fSJohn Dyson auio.uio_procp = ap->a_p; 230996c772fSJohn Dyson auio.uio_resid = MAXPATHLEN; 231996c772fSJohn Dyson rdlnk.a_uio = &auio; 232996c772fSJohn Dyson rdlnk.a_vp = ap->a_vp; 233996c772fSJohn Dyson rdlnk.a_cred = ap->a_cred; 234996c772fSJohn Dyson if (cd9660_readlink(&rdlnk) == 0) 235996c772fSJohn Dyson vap->va_size = MAXPATHLEN - auio.uio_resid; 236996c772fSJohn Dyson FREE(cp, M_TEMP); 237996c772fSJohn Dyson } 238df8bae1dSRodney W. Grimes vap->va_flags = 0; 239df8bae1dSRodney W. Grimes vap->va_gen = 1; 240df8bae1dSRodney W. Grimes vap->va_blocksize = ip->i_mnt->logical_block_size; 241df8bae1dSRodney W. Grimes vap->va_bytes = (u_quad_t) ip->i_size; 242df8bae1dSRodney W. Grimes vap->va_type = vp->v_type; 24394a8606fSDoug Rabson vap->va_filerev = 0; 244df8bae1dSRodney W. Grimes return (0); 245df8bae1dSRodney W. Grimes } 246df8bae1dSRodney W. Grimes 247df8bae1dSRodney W. Grimes /* 248df8bae1dSRodney W. Grimes * Vnode op for reading. 249df8bae1dSRodney W. Grimes */ 250605e9724SPoul-Henning Kamp static int 251df8bae1dSRodney W. Grimes cd9660_read(ap) 252df8bae1dSRodney W. Grimes struct vop_read_args /* { 253df8bae1dSRodney W. Grimes struct vnode *a_vp; 254df8bae1dSRodney W. Grimes struct uio *a_uio; 255df8bae1dSRodney W. Grimes int a_ioflag; 256df8bae1dSRodney W. Grimes struct ucred *a_cred; 257df8bae1dSRodney W. Grimes } */ *ap; 258df8bae1dSRodney W. Grimes { 259df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 260df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 261df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 262df8bae1dSRodney W. Grimes register struct iso_mnt *imp; 263df8bae1dSRodney W. Grimes struct buf *bp; 2641295d82eSGary Palmer daddr_t lbn, rablock; 265df8bae1dSRodney W. Grimes off_t diff; 266df8bae1dSRodney W. Grimes int rasize, error = 0; 267df8bae1dSRodney W. Grimes long size, n, on; 268df8bae1dSRodney W. Grimes 269df8bae1dSRodney W. Grimes if (uio->uio_resid == 0) 270df8bae1dSRodney W. Grimes return (0); 271df8bae1dSRodney W. Grimes if (uio->uio_offset < 0) 272df8bae1dSRodney W. Grimes return (EINVAL); 273996c772fSJohn Dyson ip->i_flag |= IN_ACCESS; 274df8bae1dSRodney W. Grimes imp = ip->i_mnt; 275df8bae1dSRodney W. Grimes do { 276996c772fSJohn Dyson lbn = lblkno(imp, uio->uio_offset); 277996c772fSJohn Dyson on = blkoff(imp, uio->uio_offset); 278996c772fSJohn Dyson n = min((u_int)(imp->logical_block_size - on), 279df8bae1dSRodney W. Grimes uio->uio_resid); 280df8bae1dSRodney W. Grimes diff = (off_t)ip->i_size - uio->uio_offset; 281df8bae1dSRodney W. Grimes if (diff <= 0) 282df8bae1dSRodney W. Grimes return (0); 283df8bae1dSRodney W. Grimes if (diff < n) 284df8bae1dSRodney W. Grimes n = diff; 285996c772fSJohn Dyson size = blksize(imp, ip, lbn); 286df8bae1dSRodney W. Grimes rablock = lbn + 1; 28781bca6ddSKATO Takenori if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 288996c772fSJohn Dyson if (lblktosize(imp, rablock) <= ip->i_size) 289996c772fSJohn Dyson error = cluster_read(vp, (off_t)ip->i_size, 2908b612c4bSJohn Dyson lbn, size, NOCRED, uio->uio_resid, 2918b612c4bSJohn Dyson (ap->a_ioflag >> 16), &bp); 292df8bae1dSRodney W. Grimes else 293df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 294df8bae1dSRodney W. Grimes } else { 295df8bae1dSRodney W. Grimes if (vp->v_lastr + 1 == lbn && 296996c772fSJohn Dyson lblktosize(imp, rablock) < ip->i_size) { 297996c772fSJohn Dyson rasize = blksize(imp, ip, rablock); 298df8bae1dSRodney W. Grimes error = breadn(vp, lbn, size, &rablock, 299df8bae1dSRodney W. Grimes &rasize, 1, NOCRED, &bp); 300df8bae1dSRodney W. Grimes } else 301df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 302df8bae1dSRodney W. Grimes } 303df8bae1dSRodney W. Grimes vp->v_lastr = lbn; 304df8bae1dSRodney W. Grimes n = min(n, size - bp->b_resid); 305df8bae1dSRodney W. Grimes if (error) { 306df8bae1dSRodney W. Grimes brelse(bp); 307df8bae1dSRodney W. Grimes return (error); 308df8bae1dSRodney W. Grimes } 309df8bae1dSRodney W. Grimes 310996c772fSJohn Dyson error = uiomove(bp->b_data + on, (int)n, uio); 311df8bae1dSRodney W. Grimes brelse(bp); 312df8bae1dSRodney W. Grimes } while (error == 0 && uio->uio_resid > 0 && n != 0); 313df8bae1dSRodney W. Grimes return (error); 314df8bae1dSRodney W. Grimes } 315df8bae1dSRodney W. Grimes 316df8bae1dSRodney W. Grimes /* 317df8bae1dSRodney W. Grimes * Structure for reading directories 318df8bae1dSRodney W. Grimes */ 319df8bae1dSRodney W. Grimes struct isoreaddir { 320df8bae1dSRodney W. Grimes struct dirent saveent; 321df8bae1dSRodney W. Grimes struct dirent assocent; 322df8bae1dSRodney W. Grimes struct dirent current; 323df8bae1dSRodney W. Grimes off_t saveoff; 324df8bae1dSRodney W. Grimes off_t assocoff; 325df8bae1dSRodney W. Grimes off_t curroff; 326df8bae1dSRodney W. Grimes struct uio *uio; 327df8bae1dSRodney W. Grimes off_t uio_off; 328996c772fSJohn Dyson int eofflag; 329996c772fSJohn Dyson u_long *cookies; 330df8bae1dSRodney W. Grimes int ncookies; 331df8bae1dSRodney W. Grimes }; 332df8bae1dSRodney W. Grimes 333996c772fSJohn Dyson int 334df8bae1dSRodney W. Grimes iso_uiodir(idp,dp,off) 335df8bae1dSRodney W. Grimes struct isoreaddir *idp; 336df8bae1dSRodney W. Grimes struct dirent *dp; 337df8bae1dSRodney W. Grimes off_t off; 338df8bae1dSRodney W. Grimes { 339df8bae1dSRodney W. Grimes int error; 340df8bae1dSRodney W. Grimes 341df8bae1dSRodney W. Grimes dp->d_name[dp->d_namlen] = 0; 342c90607baSBruce Evans dp->d_reclen = GENERIC_DIRSIZ(dp); 343df8bae1dSRodney W. Grimes 344df8bae1dSRodney W. Grimes if (idp->uio->uio_resid < dp->d_reclen) { 345996c772fSJohn Dyson idp->eofflag = 0; 346996c772fSJohn Dyson return (-1); 347df8bae1dSRodney W. Grimes } 348df8bae1dSRodney W. Grimes 349996c772fSJohn Dyson if (idp->cookies) { 350df8bae1dSRodney W. Grimes if (idp->ncookies <= 0) { 351996c772fSJohn Dyson idp->eofflag = 0; 352996c772fSJohn Dyson return (-1); 353df8bae1dSRodney W. Grimes } 354df8bae1dSRodney W. Grimes 355996c772fSJohn Dyson *idp->cookies++ = off; 356df8bae1dSRodney W. Grimes --idp->ncookies; 357df8bae1dSRodney W. Grimes } 358df8bae1dSRodney W. Grimes 359996c772fSJohn Dyson if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) 360996c772fSJohn Dyson return (error); 361df8bae1dSRodney W. Grimes idp->uio_off = off; 362996c772fSJohn Dyson return (0); 363df8bae1dSRodney W. Grimes } 364df8bae1dSRodney W. Grimes 365996c772fSJohn Dyson int 366df8bae1dSRodney W. Grimes iso_shipdir(idp) 367df8bae1dSRodney W. Grimes struct isoreaddir *idp; 368df8bae1dSRodney W. Grimes { 369df8bae1dSRodney W. Grimes struct dirent *dp; 370df8bae1dSRodney W. Grimes int cl, sl, assoc; 371df8bae1dSRodney W. Grimes int error; 372df8bae1dSRodney W. Grimes char *cname, *sname; 373df8bae1dSRodney W. Grimes 374df8bae1dSRodney W. Grimes cl = idp->current.d_namlen; 375df8bae1dSRodney W. Grimes cname = idp->current.d_name; 3761295d82eSGary Palmer assoc = (cl > 1) && (*cname == ASSOCCHAR); 3771295d82eSGary Palmer if (assoc) { 378df8bae1dSRodney W. Grimes cl--; 379df8bae1dSRodney W. Grimes cname++; 380df8bae1dSRodney W. Grimes } 381df8bae1dSRodney W. Grimes 382df8bae1dSRodney W. Grimes dp = &idp->saveent; 383df8bae1dSRodney W. Grimes sname = dp->d_name; 384df8bae1dSRodney W. Grimes if (!(sl = dp->d_namlen)) { 385df8bae1dSRodney W. Grimes dp = &idp->assocent; 386df8bae1dSRodney W. Grimes sname = dp->d_name + 1; 387df8bae1dSRodney W. Grimes sl = dp->d_namlen - 1; 388df8bae1dSRodney W. Grimes } 389df8bae1dSRodney W. Grimes if (sl > 0) { 390df8bae1dSRodney W. Grimes if (sl != cl 391df8bae1dSRodney W. Grimes || bcmp(sname,cname,sl)) { 392df8bae1dSRodney W. Grimes if (idp->assocent.d_namlen) { 393996c772fSJohn Dyson if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) 394996c772fSJohn Dyson return (error); 395df8bae1dSRodney W. Grimes idp->assocent.d_namlen = 0; 396df8bae1dSRodney W. Grimes } 397df8bae1dSRodney W. Grimes if (idp->saveent.d_namlen) { 398996c772fSJohn Dyson if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) 399996c772fSJohn Dyson return (error); 400df8bae1dSRodney W. Grimes idp->saveent.d_namlen = 0; 401df8bae1dSRodney W. Grimes } 402df8bae1dSRodney W. Grimes } 403df8bae1dSRodney W. Grimes } 404c90607baSBruce Evans idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 405df8bae1dSRodney W. Grimes if (assoc) { 406df8bae1dSRodney W. Grimes idp->assocoff = idp->curroff; 407df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 408df8bae1dSRodney W. Grimes } else { 409df8bae1dSRodney W. Grimes idp->saveoff = idp->curroff; 410df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 411df8bae1dSRodney W. Grimes } 412996c772fSJohn Dyson return (0); 413df8bae1dSRodney W. Grimes } 414df8bae1dSRodney W. Grimes 415df8bae1dSRodney W. Grimes /* 416df8bae1dSRodney W. Grimes * Vnode op for readdir 417df8bae1dSRodney W. Grimes */ 418605e9724SPoul-Henning Kamp static int 419df8bae1dSRodney W. Grimes cd9660_readdir(ap) 420df8bae1dSRodney W. Grimes struct vop_readdir_args /* { 421df8bae1dSRodney W. Grimes struct vnode *a_vp; 422df8bae1dSRodney W. Grimes struct uio *a_uio; 423df8bae1dSRodney W. Grimes struct ucred *a_cred; 424996c772fSJohn Dyson int *a_eofflag; 425996c772fSJohn Dyson int *a_ncookies; 426996c772fSJohn Dyson u_long *a_cookies; 427df8bae1dSRodney W. Grimes } */ *ap; 428df8bae1dSRodney W. Grimes { 429df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 430df8bae1dSRodney W. Grimes struct isoreaddir *idp; 431996c772fSJohn Dyson struct vnode *vdp = ap->a_vp; 432996c772fSJohn Dyson struct iso_node *dp; 433df8bae1dSRodney W. Grimes struct iso_mnt *imp; 434df8bae1dSRodney W. Grimes struct buf *bp = NULL; 435996c772fSJohn Dyson struct iso_directory_record *ep; 436996c772fSJohn Dyson int entryoffsetinblock; 437996c772fSJohn Dyson doff_t endsearch; 438996c772fSJohn Dyson u_long bmask; 439996c772fSJohn Dyson int error = 0; 440996c772fSJohn Dyson int reclen; 441996c772fSJohn Dyson u_short namelen; 4429abf4d6eSDoug Rabson int ncookies = 0; 443996c772fSJohn Dyson u_long *cookies = NULL; 444df8bae1dSRodney W. Grimes 445996c772fSJohn Dyson dp = VTOI(vdp); 446996c772fSJohn Dyson imp = dp->i_mnt; 447996c772fSJohn Dyson bmask = imp->im_bmask; 448df8bae1dSRodney W. Grimes 449df8bae1dSRodney W. Grimes MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 450996c772fSJohn Dyson idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 451996c772fSJohn Dyson /* 452996c772fSJohn Dyson * XXX 453996c772fSJohn Dyson * Is it worth trying to figure out the type? 454996c772fSJohn Dyson */ 455996c772fSJohn Dyson idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 456996c772fSJohn Dyson DT_UNKNOWN; 457df8bae1dSRodney W. Grimes idp->uio = uio; 458996c772fSJohn Dyson if (ap->a_ncookies == NULL) { 459996c772fSJohn Dyson idp->cookies = NULL; 460996c772fSJohn Dyson } else { 4619abf4d6eSDoug Rabson /* 4629abf4d6eSDoug Rabson * Guess the number of cookies needed. 4639abf4d6eSDoug Rabson */ 4649abf4d6eSDoug Rabson ncookies = uio->uio_resid / 16; 465996c772fSJohn Dyson MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 466996c772fSJohn Dyson M_WAITOK); 467996c772fSJohn Dyson idp->cookies = cookies; 468df8bae1dSRodney W. Grimes idp->ncookies = ncookies; 469996c772fSJohn Dyson } 470996c772fSJohn Dyson idp->eofflag = 1; 471df8bae1dSRodney W. Grimes idp->curroff = uio->uio_offset; 472df8bae1dSRodney W. Grimes 473996c772fSJohn Dyson if ((entryoffsetinblock = idp->curroff & bmask) && 474cec0f20cSPoul-Henning Kamp (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 475df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 476df8bae1dSRodney W. Grimes return (error); 477df8bae1dSRodney W. Grimes } 478996c772fSJohn Dyson endsearch = dp->i_size; 479df8bae1dSRodney W. Grimes 480df8bae1dSRodney W. Grimes while (idp->curroff < endsearch) { 481df8bae1dSRodney W. Grimes /* 482df8bae1dSRodney W. Grimes * If offset is on a block boundary, 483df8bae1dSRodney W. Grimes * read the next directory block. 484df8bae1dSRodney W. Grimes * Release previous if it exists. 485df8bae1dSRodney W. Grimes */ 486996c772fSJohn Dyson if ((idp->curroff & bmask) == 0) { 487df8bae1dSRodney W. Grimes if (bp != NULL) 488df8bae1dSRodney W. Grimes brelse(bp); 489996c772fSJohn Dyson if (error = 490cec0f20cSPoul-Henning Kamp cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) 491df8bae1dSRodney W. Grimes break; 492df8bae1dSRodney W. Grimes entryoffsetinblock = 0; 493df8bae1dSRodney W. Grimes } 494df8bae1dSRodney W. Grimes /* 495df8bae1dSRodney W. Grimes * Get pointer to next entry. 496df8bae1dSRodney W. Grimes */ 497df8bae1dSRodney W. Grimes ep = (struct iso_directory_record *) 498996c772fSJohn Dyson ((char *)bp->b_data + entryoffsetinblock); 499df8bae1dSRodney W. Grimes 500df8bae1dSRodney W. Grimes reclen = isonum_711(ep->length); 501df8bae1dSRodney W. Grimes if (reclen == 0) { 502df8bae1dSRodney W. Grimes /* skip to next block, if any */ 503996c772fSJohn Dyson idp->curroff = 504996c772fSJohn Dyson (idp->curroff & ~bmask) + imp->logical_block_size; 505df8bae1dSRodney W. Grimes continue; 506df8bae1dSRodney W. Grimes } 507df8bae1dSRodney W. Grimes 508df8bae1dSRodney W. Grimes if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 509df8bae1dSRodney W. Grimes error = EINVAL; 510df8bae1dSRodney W. Grimes /* illegal entry, stop */ 511df8bae1dSRodney W. Grimes break; 512df8bae1dSRodney W. Grimes } 513df8bae1dSRodney W. Grimes 514df8bae1dSRodney W. Grimes if (entryoffsetinblock + reclen > imp->logical_block_size) { 515df8bae1dSRodney W. Grimes error = EINVAL; 516df8bae1dSRodney W. Grimes /* illegal directory, so stop looking */ 517df8bae1dSRodney W. Grimes break; 518df8bae1dSRodney W. Grimes } 519df8bae1dSRodney W. Grimes 520996c772fSJohn Dyson idp->current.d_namlen = isonum_711(ep->name_len); 521996c772fSJohn Dyson 522996c772fSJohn Dyson if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 52381ec856aSJoerg Wunsch error = EINVAL; 52481ec856aSJoerg Wunsch /* illegal entry, stop */ 52581ec856aSJoerg Wunsch break; 52681ec856aSJoerg Wunsch } 52781ec856aSJoerg Wunsch 528996c772fSJohn Dyson if (isonum_711(ep->flags)&2) 529996c772fSJohn Dyson idp->current.d_fileno = isodirino(ep, imp); 530df8bae1dSRodney W. Grimes else 531df8bae1dSRodney W. Grimes idp->current.d_fileno = dbtob(bp->b_blkno) + 532996c772fSJohn Dyson entryoffsetinblock; 533df8bae1dSRodney W. Grimes 534df8bae1dSRodney W. Grimes idp->curroff += reclen; 535996c772fSJohn Dyson 536df8bae1dSRodney W. Grimes switch (imp->iso_ftype) { 537df8bae1dSRodney W. Grimes case ISO_FTYPE_RRIP: 538996c772fSJohn Dyson cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 539df8bae1dSRodney W. Grimes &idp->current.d_fileno,imp); 540996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 541df8bae1dSRodney W. Grimes if (idp->current.d_namlen) 542df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 543df8bae1dSRodney W. Grimes break; 544988fa8efSJoerg Wunsch default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 545df8bae1dSRodney W. Grimes strcpy(idp->current.d_name,".."); 546df8bae1dSRodney W. Grimes switch (ep->name[0]) { 547df8bae1dSRodney W. Grimes case 0: 548df8bae1dSRodney W. Grimes idp->current.d_namlen = 1; 549df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 550df8bae1dSRodney W. Grimes break; 551df8bae1dSRodney W. Grimes case 1: 552df8bae1dSRodney W. Grimes idp->current.d_namlen = 2; 553df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 554df8bae1dSRodney W. Grimes break; 555df8bae1dSRodney W. Grimes default: 556df8bae1dSRodney W. Grimes isofntrans(ep->name,idp->current.d_namlen, 557996c772fSJohn Dyson idp->current.d_name, &namelen, 558df8bae1dSRodney W. Grimes imp->iso_ftype == ISO_FTYPE_9660, 559996c772fSJohn Dyson isonum_711(ep->flags)&4); 560996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 561df8bae1dSRodney W. Grimes if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 562df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 563df8bae1dSRodney W. Grimes else 564df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 565df8bae1dSRodney W. Grimes break; 566df8bae1dSRodney W. Grimes } 567df8bae1dSRodney W. Grimes } 568df8bae1dSRodney W. Grimes if (error) 569df8bae1dSRodney W. Grimes break; 570df8bae1dSRodney W. Grimes 571df8bae1dSRodney W. Grimes entryoffsetinblock += reclen; 572df8bae1dSRodney W. Grimes } 573df8bae1dSRodney W. Grimes 574df8bae1dSRodney W. Grimes if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 575df8bae1dSRodney W. Grimes idp->current.d_namlen = 0; 576df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 577df8bae1dSRodney W. Grimes } 578df8bae1dSRodney W. Grimes if (error < 0) 579df8bae1dSRodney W. Grimes error = 0; 580df8bae1dSRodney W. Grimes 5819abf4d6eSDoug Rabson if (ap->a_ncookies != NULL) { 5829abf4d6eSDoug Rabson if (error) 583996c772fSJohn Dyson free(cookies, M_TEMP); 5849abf4d6eSDoug Rabson else { 5859abf4d6eSDoug Rabson /* 5869abf4d6eSDoug Rabson * Work out the number of cookies actually used. 5879abf4d6eSDoug Rabson */ 5889abf4d6eSDoug Rabson *ap->a_ncookies = ncookies - idp->ncookies; 5899abf4d6eSDoug Rabson *ap->a_cookies = cookies; 5909abf4d6eSDoug Rabson } 5919abf4d6eSDoug Rabson } 5929abf4d6eSDoug Rabson 593df8bae1dSRodney W. Grimes if (bp) 594df8bae1dSRodney W. Grimes brelse (bp); 595df8bae1dSRodney W. Grimes 596df8bae1dSRodney W. Grimes uio->uio_offset = idp->uio_off; 597996c772fSJohn Dyson *ap->a_eofflag = idp->eofflag; 598df8bae1dSRodney W. Grimes 599df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 600df8bae1dSRodney W. Grimes 601df8bae1dSRodney W. Grimes return (error); 602df8bae1dSRodney W. Grimes } 603df8bae1dSRodney W. Grimes 604df8bae1dSRodney W. Grimes /* 605df8bae1dSRodney W. Grimes * Return target name of a symbolic link 606df8bae1dSRodney W. Grimes * Shouldn't we get the parent vnode and read the data from there? 607df8bae1dSRodney W. Grimes * This could eventually result in deadlocks in cd9660_lookup. 608df8bae1dSRodney W. Grimes * But otherwise the block read here is in the block buffer two times. 609df8bae1dSRodney W. Grimes */ 610df8bae1dSRodney W. Grimes typedef struct iso_directory_record ISODIR; 611df8bae1dSRodney W. Grimes typedef struct iso_node ISONODE; 612df8bae1dSRodney W. Grimes typedef struct iso_mnt ISOMNT; 613605e9724SPoul-Henning Kamp static int 614df8bae1dSRodney W. Grimes cd9660_readlink(ap) 615df8bae1dSRodney W. Grimes struct vop_readlink_args /* { 616df8bae1dSRodney W. Grimes struct vnode *a_vp; 617df8bae1dSRodney W. Grimes struct uio *a_uio; 618df8bae1dSRodney W. Grimes struct ucred *a_cred; 619df8bae1dSRodney W. Grimes } */ *ap; 620df8bae1dSRodney W. Grimes { 621df8bae1dSRodney W. Grimes ISONODE *ip; 622df8bae1dSRodney W. Grimes ISODIR *dirp; 623df8bae1dSRodney W. Grimes ISOMNT *imp; 624df8bae1dSRodney W. Grimes struct buf *bp; 625996c772fSJohn Dyson struct uio *uio; 626df8bae1dSRodney W. Grimes u_short symlen; 627df8bae1dSRodney W. Grimes int error; 628df8bae1dSRodney W. Grimes char *symname; 629df8bae1dSRodney W. Grimes 630df8bae1dSRodney W. Grimes ip = VTOI(ap->a_vp); 631df8bae1dSRodney W. Grimes imp = ip->i_mnt; 632996c772fSJohn Dyson uio = ap->a_uio; 633df8bae1dSRodney W. Grimes 634df8bae1dSRodney W. Grimes if (imp->iso_ftype != ISO_FTYPE_RRIP) 635996c772fSJohn Dyson return (EINVAL); 636df8bae1dSRodney W. Grimes 637df8bae1dSRodney W. Grimes /* 638df8bae1dSRodney W. Grimes * Get parents directory record block that this inode included. 639df8bae1dSRodney W. Grimes */ 640df8bae1dSRodney W. Grimes error = bread(imp->im_devvp, 641996c772fSJohn Dyson (ip->i_number >> imp->im_bshift) << 642996c772fSJohn Dyson (imp->im_bshift - DEV_BSHIFT), 643996c772fSJohn Dyson imp->logical_block_size, NOCRED, &bp); 644df8bae1dSRodney W. Grimes if (error) { 645df8bae1dSRodney W. Grimes brelse(bp); 646996c772fSJohn Dyson return (EINVAL); 647df8bae1dSRodney W. Grimes } 648df8bae1dSRodney W. Grimes 649df8bae1dSRodney W. Grimes /* 650df8bae1dSRodney W. Grimes * Setup the directory pointer for this inode 651df8bae1dSRodney W. Grimes */ 652996c772fSJohn Dyson dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 653df8bae1dSRodney W. Grimes 654df8bae1dSRodney W. Grimes /* 655df8bae1dSRodney W. Grimes * Just make sure, we have a right one.... 656df8bae1dSRodney W. Grimes * 1: Check not cross boundary on block 657df8bae1dSRodney W. Grimes */ 658df8bae1dSRodney W. Grimes if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 65992579404SAlexander Langer > (unsigned)imp->logical_block_size) { 660df8bae1dSRodney W. Grimes brelse(bp); 661996c772fSJohn Dyson return (EINVAL); 662df8bae1dSRodney W. Grimes } 663df8bae1dSRodney W. Grimes 664df8bae1dSRodney W. Grimes /* 665df8bae1dSRodney W. Grimes * Now get a buffer 666df8bae1dSRodney W. Grimes * Abuse a namei buffer for now. 667df8bae1dSRodney W. Grimes */ 668996c772fSJohn Dyson if (uio->uio_segflg == UIO_SYSSPACE) 669996c772fSJohn Dyson symname = uio->uio_iov->iov_base; 670996c772fSJohn Dyson else 67199448ed1SJohn Dyson symname = zalloc(namei_zone); 672df8bae1dSRodney W. Grimes 673df8bae1dSRodney W. Grimes /* 674df8bae1dSRodney W. Grimes * Ok, we just gathering a symbolic name in SL record. 675df8bae1dSRodney W. Grimes */ 676df8bae1dSRodney W. Grimes if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 677996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) 67899448ed1SJohn Dyson zfree(namei_zone, symname); 679df8bae1dSRodney W. Grimes brelse(bp); 680996c772fSJohn Dyson return (EINVAL); 681df8bae1dSRodney W. Grimes } 682df8bae1dSRodney W. Grimes /* 683df8bae1dSRodney W. Grimes * Don't forget before you leave from home ;-) 684df8bae1dSRodney W. Grimes */ 685df8bae1dSRodney W. Grimes brelse(bp); 686df8bae1dSRodney W. Grimes 687df8bae1dSRodney W. Grimes /* 688df8bae1dSRodney W. Grimes * return with the symbolic name to caller's. 689df8bae1dSRodney W. Grimes */ 690996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) { 691996c772fSJohn Dyson error = uiomove(symname, symlen, uio); 69299448ed1SJohn Dyson zfree(namei_zone, symname); 693996c772fSJohn Dyson return (error); 694996c772fSJohn Dyson } 695996c772fSJohn Dyson uio->uio_resid -= symlen; 696996c772fSJohn Dyson uio->uio_iov->iov_base += symlen; 697996c772fSJohn Dyson uio->uio_iov->iov_len -= symlen; 698996c772fSJohn Dyson return (0); 699df8bae1dSRodney W. Grimes } 700df8bae1dSRodney W. Grimes 701df8bae1dSRodney W. Grimes /* 702df8bae1dSRodney W. Grimes * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 703df8bae1dSRodney W. Grimes * done. If a buffer has been saved in anticipation of a CREATE, delete it. 704df8bae1dSRodney W. Grimes */ 705605e9724SPoul-Henning Kamp static int 706df8bae1dSRodney W. Grimes cd9660_abortop(ap) 707df8bae1dSRodney W. Grimes struct vop_abortop_args /* { 708df8bae1dSRodney W. Grimes struct vnode *a_dvp; 709df8bae1dSRodney W. Grimes struct componentname *a_cnp; 710df8bae1dSRodney W. Grimes } */ *ap; 711df8bae1dSRodney W. Grimes { 712df8bae1dSRodney W. Grimes if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 71399448ed1SJohn Dyson zfree(namei_zone, ap->a_cnp->cn_pnbuf); 714996c772fSJohn Dyson return (0); 715df8bae1dSRodney W. Grimes } 716df8bae1dSRodney W. Grimes 717df8bae1dSRodney W. Grimes /* 718df8bae1dSRodney W. Grimes * Calculate the logical to physical mapping if not done already, 719df8bae1dSRodney W. Grimes * then call the device strategy routine. 720df8bae1dSRodney W. Grimes */ 721605e9724SPoul-Henning Kamp static int 722df8bae1dSRodney W. Grimes cd9660_strategy(ap) 723df8bae1dSRodney W. Grimes struct vop_strategy_args /* { 724df8bae1dSRodney W. Grimes struct buf *a_bp; 725df8bae1dSRodney W. Grimes } */ *ap; 726df8bae1dSRodney W. Grimes { 727df8bae1dSRodney W. Grimes register struct buf *bp = ap->a_bp; 728df8bae1dSRodney W. Grimes register struct vnode *vp = bp->b_vp; 729df8bae1dSRodney W. Grimes register struct iso_node *ip; 730df8bae1dSRodney W. Grimes int error; 731df8bae1dSRodney W. Grimes 732df8bae1dSRodney W. Grimes ip = VTOI(vp); 733df8bae1dSRodney W. Grimes if (vp->v_type == VBLK || vp->v_type == VCHR) 734df8bae1dSRodney W. Grimes panic("cd9660_strategy: spec"); 735df8bae1dSRodney W. Grimes if (bp->b_blkno == bp->b_lblkno) { 7361295d82eSGary Palmer if ((error = 737c83ebe77SJohn Dyson VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) { 738df8bae1dSRodney W. Grimes bp->b_error = error; 739df8bae1dSRodney W. Grimes bp->b_flags |= B_ERROR; 740df8bae1dSRodney W. Grimes biodone(bp); 741df8bae1dSRodney W. Grimes return (error); 742df8bae1dSRodney W. Grimes } 743df8bae1dSRodney W. Grimes if ((long)bp->b_blkno == -1) 744df8bae1dSRodney W. Grimes clrbuf(bp); 745df8bae1dSRodney W. Grimes } 746df8bae1dSRodney W. Grimes if ((long)bp->b_blkno == -1) { 747df8bae1dSRodney W. Grimes biodone(bp); 748df8bae1dSRodney W. Grimes return (0); 749df8bae1dSRodney W. Grimes } 750df8bae1dSRodney W. Grimes vp = ip->i_devvp; 751df8bae1dSRodney W. Grimes bp->b_dev = vp->v_rdev; 752df8bae1dSRodney W. Grimes VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 753df8bae1dSRodney W. Grimes return (0); 754df8bae1dSRodney W. Grimes } 755df8bae1dSRodney W. Grimes 756df8bae1dSRodney W. Grimes /* 757df8bae1dSRodney W. Grimes * Print out the contents of an inode. 758df8bae1dSRodney W. Grimes */ 759605e9724SPoul-Henning Kamp static int 760df8bae1dSRodney W. Grimes cd9660_print(ap) 761df8bae1dSRodney W. Grimes struct vop_print_args /* { 762df8bae1dSRodney W. Grimes struct vnode *a_vp; 763df8bae1dSRodney W. Grimes } */ *ap; 764df8bae1dSRodney W. Grimes { 765996c772fSJohn Dyson 766df8bae1dSRodney W. Grimes printf("tag VT_ISOFS, isofs vnode\n"); 767996c772fSJohn Dyson return (0); 768df8bae1dSRodney W. Grimes } 769df8bae1dSRodney W. Grimes 770df8bae1dSRodney W. Grimes /* 771996c772fSJohn Dyson * Return POSIX pathconf information applicable to cd9660 filesystems. 772996c772fSJohn Dyson */ 773996c772fSJohn Dyson int 774996c772fSJohn Dyson cd9660_pathconf(ap) 775996c772fSJohn Dyson struct vop_pathconf_args /* { 776996c772fSJohn Dyson struct vnode *a_vp; 777996c772fSJohn Dyson int a_name; 778996c772fSJohn Dyson register_t *a_retval; 779996c772fSJohn Dyson } */ *ap; 780996c772fSJohn Dyson { 781996c772fSJohn Dyson 782996c772fSJohn Dyson switch (ap->a_name) { 783996c772fSJohn Dyson case _PC_LINK_MAX: 784996c772fSJohn Dyson *ap->a_retval = 1; 785996c772fSJohn Dyson return (0); 786996c772fSJohn Dyson case _PC_NAME_MAX: 787996c772fSJohn Dyson if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 788996c772fSJohn Dyson *ap->a_retval = NAME_MAX; 789996c772fSJohn Dyson else 790996c772fSJohn Dyson *ap->a_retval = 37; 791996c772fSJohn Dyson return (0); 792996c772fSJohn Dyson case _PC_PATH_MAX: 793996c772fSJohn Dyson *ap->a_retval = PATH_MAX; 794996c772fSJohn Dyson return (0); 795996c772fSJohn Dyson case _PC_PIPE_BUF: 796996c772fSJohn Dyson *ap->a_retval = PIPE_BUF; 797996c772fSJohn Dyson return (0); 798996c772fSJohn Dyson case _PC_CHOWN_RESTRICTED: 799996c772fSJohn Dyson *ap->a_retval = 1; 800996c772fSJohn Dyson return (0); 801996c772fSJohn Dyson case _PC_NO_TRUNC: 802996c772fSJohn Dyson *ap->a_retval = 1; 803996c772fSJohn Dyson return (0); 804996c772fSJohn Dyson default: 805996c772fSJohn Dyson return (EINVAL); 806996c772fSJohn Dyson } 807996c772fSJohn Dyson /* NOTREACHED */ 808df8bae1dSRodney W. Grimes } 809df8bae1dSRodney W. Grimes 810df8bae1dSRodney W. Grimes /* 811996c772fSJohn Dyson * Global vfs data structures for cd9660 812df8bae1dSRodney W. Grimes */ 813f57e6547SBruce Evans vop_t **cd9660_vnodeop_p; 814996c772fSJohn Dyson struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 815dba3870cSPoul-Henning Kamp { &vop_default_desc, (vop_t *) vop_defaultop }, 816539ef70cSPoul-Henning Kamp { &vop_abortop_desc, (vop_t *) cd9660_abortop }, 817539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 818539ef70cSPoul-Henning Kamp { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 819539ef70cSPoul-Henning Kamp { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 820539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 821539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 822d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 823d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 824539ef70cSPoul-Henning Kamp { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 825539ef70cSPoul-Henning Kamp { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 826539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 827539ef70cSPoul-Henning Kamp { &vop_read_desc, (vop_t *) cd9660_read }, 828539ef70cSPoul-Henning Kamp { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 829539ef70cSPoul-Henning Kamp { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 830539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 831539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 832539ef70cSPoul-Henning Kamp { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 833d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 834f57e6547SBruce Evans { NULL, NULL } 835df8bae1dSRodney W. Grimes }; 836605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 837df8bae1dSRodney W. Grimes { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 838c901836cSGarrett Wollman VNODEOP_SET(cd9660_vnodeop_opv_desc); 839df8bae1dSRodney W. Grimes 840df8bae1dSRodney W. Grimes /* 841df8bae1dSRodney W. Grimes * Special device vnode ops 842df8bae1dSRodney W. Grimes */ 843f57e6547SBruce Evans vop_t **cd9660_specop_p; 844996c772fSJohn Dyson struct vnodeopv_entry_desc cd9660_specop_entries[] = { 845138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) spec_vnoperate }, 846539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 847539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 848539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 849d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 850d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 851539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 852539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 853539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 854d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 855f57e6547SBruce Evans { NULL, NULL } 856df8bae1dSRodney W. Grimes }; 857605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_specop_opv_desc = 858df8bae1dSRodney W. Grimes { &cd9660_specop_p, cd9660_specop_entries }; 859c901836cSGarrett Wollman VNODEOP_SET(cd9660_specop_opv_desc); 860df8bae1dSRodney W. Grimes 861f57e6547SBruce Evans vop_t **cd9660_fifoop_p; 862996c772fSJohn Dyson struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 863138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) fifo_vnoperate }, 864539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 865539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 866539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 867d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 868d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 869539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 870539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 871539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 872d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 873f57e6547SBruce Evans { NULL, NULL } 874df8bae1dSRodney W. Grimes }; 875605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_fifoop_opv_desc = 876df8bae1dSRodney W. Grimes { &cd9660_fifoop_p, cd9660_fifoop_entries }; 877c901836cSGarrett Wollman 878c901836cSGarrett Wollman VNODEOP_SET(cd9660_fifoop_opv_desc); 879