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 39c3aac50fSPeter Wemm * $FreeBSD$ 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> 47df8bae1dSRodney W. Grimes #include <sys/buf.h> 48df8bae1dSRodney W. Grimes #include <sys/mount.h> 49df8bae1dSRodney W. Grimes #include <sys/vnode.h> 50df8bae1dSRodney W. Grimes #include <miscfs/fifofs/fifo.h> 51df8bae1dSRodney W. Grimes #include <sys/malloc.h> 52c90607baSBruce Evans #include <sys/dirent.h> 53996c772fSJohn Dyson #include <sys/unistd.h> 54cb2a8dffSSøren Schmidt #include <sys/filio.h> 55df8bae1dSRodney W. Grimes 56651ae11eSMike Smith #include <vm/vm.h> 57675ea6f0SBruce Evans #include <vm/vm_zone.h> 58651ae11eSMike Smith #include <vm/vnode_pager.h> 59675ea6f0SBruce Evans 60df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso.h> 61df8bae1dSRodney W. Grimes #include <isofs/cd9660/cd9660_node.h> 62df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso_rrip.h> 63df8bae1dSRodney W. Grimes 6410dd32cdSBruce Evans static int cd9660_setattr __P((struct vop_setattr_args *)); 65605e9724SPoul-Henning Kamp static int cd9660_access __P((struct vop_access_args *)); 66605e9724SPoul-Henning Kamp static int cd9660_getattr __P((struct vop_getattr_args *)); 67cb2a8dffSSøren Schmidt static int cd9660_ioctl __P((struct vop_ioctl_args *)); 68f041a9bdSPoul-Henning Kamp static int cd9660_pathconf __P((struct vop_pathconf_args *)); 69605e9724SPoul-Henning Kamp static int cd9660_read __P((struct vop_read_args *)); 7010dd32cdSBruce Evans struct isoreaddir; 7110dd32cdSBruce Evans static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp, 7210dd32cdSBruce Evans off_t off)); 7310dd32cdSBruce Evans static int iso_shipdir __P((struct isoreaddir *idp)); 74605e9724SPoul-Henning Kamp static int cd9660_readdir __P((struct vop_readdir_args *)); 7510dd32cdSBruce Evans static int cd9660_readlink __P((struct vop_readlink_args *ap)); 76605e9724SPoul-Henning Kamp static int cd9660_strategy __P((struct vop_strategy_args *)); 77605e9724SPoul-Henning Kamp static int cd9660_print __P((struct vop_print_args *)); 78651ae11eSMike Smith static int cd9660_getpages __P((struct vop_getpages_args *)); 79651ae11eSMike Smith static int cd9660_putpages __P((struct vop_putpages_args *)); 8010dd32cdSBruce Evans 81df8bae1dSRodney W. Grimes /* 82de8583ceSDavid Greenman * Setattr call. Only allowed for block and character special devices. 83de8583ceSDavid Greenman */ 84996c772fSJohn Dyson int 85de8583ceSDavid Greenman cd9660_setattr(ap) 86de8583ceSDavid Greenman struct vop_setattr_args /* { 87de8583ceSDavid Greenman struct vnodeop_desc *a_desc; 88de8583ceSDavid Greenman struct vnode *a_vp; 89de8583ceSDavid Greenman struct vattr *a_vap; 90de8583ceSDavid Greenman struct ucred *a_cred; 91de8583ceSDavid Greenman struct proc *a_p; 92de8583ceSDavid Greenman } */ *ap; 93de8583ceSDavid Greenman { 94de8583ceSDavid Greenman struct vnode *vp = ap->a_vp; 95de8583ceSDavid Greenman struct vattr *vap = ap->a_vap; 96de8583ceSDavid Greenman 9792579404SAlexander Langer if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 9895a1574eSNate Williams vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 9995a1574eSNate Williams vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 100de8583ceSDavid Greenman return (EROFS); 10192579404SAlexander Langer if (vap->va_size != (u_quad_t)VNOVAL) { 102de8583ceSDavid Greenman switch (vp->v_type) { 103de8583ceSDavid Greenman case VDIR: 104de8583ceSDavid Greenman return (EISDIR); 105de8583ceSDavid Greenman case VLNK: 106de8583ceSDavid Greenman case VREG: 107de8583ceSDavid Greenman return (EROFS); 108de8583ceSDavid Greenman case VCHR: 109de8583ceSDavid Greenman case VBLK: 110de8583ceSDavid Greenman case VSOCK: 111de8583ceSDavid Greenman case VFIFO: 112d254af07SMatthew Dillon case VNON: 113d254af07SMatthew Dillon case VBAD: 114de8583ceSDavid Greenman return (0); 115de8583ceSDavid Greenman } 116de8583ceSDavid Greenman } 117996c772fSJohn Dyson return (0); 118de8583ceSDavid Greenman } 119de8583ceSDavid Greenman 120de8583ceSDavid Greenman /* 121df8bae1dSRodney W. Grimes * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 122df8bae1dSRodney W. Grimes * The mode is shifted to select the owner/group/other fields. The 123df8bae1dSRodney W. Grimes * super user is granted all permissions. 124df8bae1dSRodney W. Grimes */ 125df8bae1dSRodney W. Grimes /* ARGSUSED */ 126605e9724SPoul-Henning Kamp static int 127df8bae1dSRodney W. Grimes cd9660_access(ap) 128df8bae1dSRodney W. Grimes struct vop_access_args /* { 129df8bae1dSRodney W. Grimes struct vnode *a_vp; 130df8bae1dSRodney W. Grimes int a_mode; 131df8bae1dSRodney W. Grimes struct ucred *a_cred; 132df8bae1dSRodney W. Grimes struct proc *a_p; 133df8bae1dSRodney W. Grimes } */ *ap; 134df8bae1dSRodney W. Grimes { 135996c772fSJohn Dyson struct vnode *vp = ap->a_vp; 136996c772fSJohn Dyson struct iso_node *ip = VTOI(vp); 137996c772fSJohn Dyson struct ucred *cred = ap->a_cred; 138996c772fSJohn Dyson mode_t mask, mode = ap->a_mode; 139996c772fSJohn Dyson gid_t *gp; 140996c772fSJohn Dyson int i; 141996c772fSJohn Dyson 142ba14c327SDavid Greenman /* 143996c772fSJohn Dyson * Disallow write attempts unless the file is a socket, 144996c772fSJohn Dyson * fifo, or a block or character device resident on the 145996c772fSJohn Dyson * file system. 146ba14c327SDavid Greenman */ 147996c772fSJohn Dyson if (mode & VWRITE) { 148996c772fSJohn Dyson switch (vp->v_type) { 149ba14c327SDavid Greenman case VDIR: 150ba14c327SDavid Greenman case VLNK: 151ba14c327SDavid Greenman case VREG: 152ba14c327SDavid Greenman return (EROFS); 153d254af07SMatthew Dillon /* NOT REACHED */ 154d254af07SMatthew Dillon default: 155d254af07SMatthew Dillon break; 156ba14c327SDavid Greenman } 157ba14c327SDavid Greenman } 158ba14c327SDavid Greenman 159996c772fSJohn Dyson /* User id 0 always gets access. */ 160996c772fSJohn Dyson if (cred->cr_uid == 0) 161df8bae1dSRodney W. Grimes return (0); 162996c772fSJohn Dyson 163996c772fSJohn Dyson mask = 0; 164996c772fSJohn Dyson 165996c772fSJohn Dyson /* Otherwise, check the owner. */ 166996c772fSJohn Dyson if (cred->cr_uid == ip->inode.iso_uid) { 167996c772fSJohn Dyson if (mode & VEXEC) 168996c772fSJohn Dyson mask |= S_IXUSR; 169996c772fSJohn Dyson if (mode & VREAD) 170996c772fSJohn Dyson mask |= S_IRUSR; 171996c772fSJohn Dyson if (mode & VWRITE) 172996c772fSJohn Dyson mask |= S_IWUSR; 173996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 174996c772fSJohn Dyson } 175996c772fSJohn Dyson 176996c772fSJohn Dyson /* Otherwise, check the groups. */ 177996c772fSJohn Dyson for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 178996c772fSJohn Dyson if (ip->inode.iso_gid == *gp) { 179996c772fSJohn Dyson if (mode & VEXEC) 180996c772fSJohn Dyson mask |= S_IXGRP; 181996c772fSJohn Dyson if (mode & VREAD) 182996c772fSJohn Dyson mask |= S_IRGRP; 183996c772fSJohn Dyson if (mode & VWRITE) 184996c772fSJohn Dyson mask |= S_IWGRP; 185996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 186996c772fSJohn Dyson 0 : EACCES); 187996c772fSJohn Dyson } 188996c772fSJohn Dyson 189996c772fSJohn Dyson /* Otherwise, check everyone else. */ 190996c772fSJohn Dyson if (mode & VEXEC) 191996c772fSJohn Dyson mask |= S_IXOTH; 192996c772fSJohn Dyson if (mode & VREAD) 193996c772fSJohn Dyson mask |= S_IROTH; 194996c772fSJohn Dyson if (mode & VWRITE) 195996c772fSJohn Dyson mask |= S_IWOTH; 196996c772fSJohn Dyson return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 197df8bae1dSRodney W. Grimes } 198df8bae1dSRodney W. Grimes 199605e9724SPoul-Henning Kamp static int 200df8bae1dSRodney W. Grimes cd9660_getattr(ap) 201df8bae1dSRodney W. Grimes struct vop_getattr_args /* { 202df8bae1dSRodney W. Grimes struct vnode *a_vp; 203df8bae1dSRodney W. Grimes struct vattr *a_vap; 204df8bae1dSRodney W. Grimes struct ucred *a_cred; 205df8bae1dSRodney W. Grimes struct proc *a_p; 206df8bae1dSRodney W. Grimes } */ *ap; 207df8bae1dSRodney W. Grimes 208df8bae1dSRodney W. Grimes { 209df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 210df8bae1dSRodney W. Grimes register struct vattr *vap = ap->a_vap; 211df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 212df8bae1dSRodney W. Grimes 213bfbb9ce6SPoul-Henning Kamp vap->va_fsid = dev2udev(ip->i_dev); 214df8bae1dSRodney W. Grimes vap->va_fileid = ip->i_number; 215df8bae1dSRodney W. Grimes 216df8bae1dSRodney W. Grimes vap->va_mode = ip->inode.iso_mode; 217df8bae1dSRodney W. Grimes vap->va_nlink = ip->inode.iso_links; 218df8bae1dSRodney W. Grimes vap->va_uid = ip->inode.iso_uid; 219df8bae1dSRodney W. Grimes vap->va_gid = ip->inode.iso_gid; 220df8bae1dSRodney W. Grimes vap->va_atime = ip->inode.iso_atime; 221df8bae1dSRodney W. Grimes vap->va_mtime = ip->inode.iso_mtime; 222df8bae1dSRodney W. Grimes vap->va_ctime = ip->inode.iso_ctime; 223df8bae1dSRodney W. Grimes vap->va_rdev = ip->inode.iso_rdev; 224df8bae1dSRodney W. Grimes 225df8bae1dSRodney W. Grimes vap->va_size = (u_quad_t) ip->i_size; 226996c772fSJohn Dyson if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 227996c772fSJohn Dyson struct vop_readlink_args rdlnk; 228996c772fSJohn Dyson struct iovec aiov; 229996c772fSJohn Dyson struct uio auio; 230996c772fSJohn Dyson char *cp; 231996c772fSJohn Dyson 232996c772fSJohn Dyson MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 233996c772fSJohn Dyson aiov.iov_base = cp; 234996c772fSJohn Dyson aiov.iov_len = MAXPATHLEN; 235996c772fSJohn Dyson auio.uio_iov = &aiov; 236996c772fSJohn Dyson auio.uio_iovcnt = 1; 237996c772fSJohn Dyson auio.uio_offset = 0; 238996c772fSJohn Dyson auio.uio_rw = UIO_READ; 239996c772fSJohn Dyson auio.uio_segflg = UIO_SYSSPACE; 240996c772fSJohn Dyson auio.uio_procp = ap->a_p; 241996c772fSJohn Dyson auio.uio_resid = MAXPATHLEN; 242996c772fSJohn Dyson rdlnk.a_uio = &auio; 243996c772fSJohn Dyson rdlnk.a_vp = ap->a_vp; 244996c772fSJohn Dyson rdlnk.a_cred = ap->a_cred; 245996c772fSJohn Dyson if (cd9660_readlink(&rdlnk) == 0) 246996c772fSJohn Dyson vap->va_size = MAXPATHLEN - auio.uio_resid; 247996c772fSJohn Dyson FREE(cp, M_TEMP); 248996c772fSJohn Dyson } 249df8bae1dSRodney W. Grimes vap->va_flags = 0; 250df8bae1dSRodney W. Grimes vap->va_gen = 1; 251df8bae1dSRodney W. Grimes vap->va_blocksize = ip->i_mnt->logical_block_size; 252df8bae1dSRodney W. Grimes vap->va_bytes = (u_quad_t) ip->i_size; 253df8bae1dSRodney W. Grimes vap->va_type = vp->v_type; 25494a8606fSDoug Rabson vap->va_filerev = 0; 255df8bae1dSRodney W. Grimes return (0); 256df8bae1dSRodney W. Grimes } 257df8bae1dSRodney W. Grimes 258df8bae1dSRodney W. Grimes /* 259cb2a8dffSSøren Schmidt * Vnode op for ioctl. 260cb2a8dffSSøren Schmidt */ 261cb2a8dffSSøren Schmidt static int 262cb2a8dffSSøren Schmidt cd9660_ioctl(ap) 263cb2a8dffSSøren Schmidt struct vop_ioctl_args /* { 264cb2a8dffSSøren Schmidt struct vnode *a_vp; 265cb2a8dffSSøren Schmidt int a_command; 266cb2a8dffSSøren Schmidt caddr_t a_data; 267cb2a8dffSSøren Schmidt int a_fflag; 268cb2a8dffSSøren Schmidt struct ucred *a_cred; 269cb2a8dffSSøren Schmidt struct proc *a_p; 270cb2a8dffSSøren Schmidt } */ *ap; 271cb2a8dffSSøren Schmidt { 272cb2a8dffSSøren Schmidt struct vnode *vp = ap->a_vp; 273cb2a8dffSSøren Schmidt struct iso_node *ip = VTOI(vp); 274cb2a8dffSSøren Schmidt 275cb2a8dffSSøren Schmidt switch (ap->a_command) { 276cb2a8dffSSøren Schmidt 277cb2a8dffSSøren Schmidt case FIOGETLBA: 278cb2a8dffSSøren Schmidt *(int *)(ap->a_data) = ip->iso_start; 279cb2a8dffSSøren Schmidt return 0; 280cb2a8dffSSøren Schmidt default: 281cb2a8dffSSøren Schmidt return (ENOTTY); 282cb2a8dffSSøren Schmidt } 283cb2a8dffSSøren Schmidt } 284cb2a8dffSSøren Schmidt 285cb2a8dffSSøren Schmidt /* 286df8bae1dSRodney W. Grimes * Vnode op for reading. 287df8bae1dSRodney W. Grimes */ 288605e9724SPoul-Henning Kamp static int 289df8bae1dSRodney W. Grimes cd9660_read(ap) 290df8bae1dSRodney W. Grimes struct vop_read_args /* { 291df8bae1dSRodney W. Grimes struct vnode *a_vp; 292df8bae1dSRodney W. Grimes struct uio *a_uio; 293df8bae1dSRodney W. Grimes int a_ioflag; 294df8bae1dSRodney W. Grimes struct ucred *a_cred; 295df8bae1dSRodney W. Grimes } */ *ap; 296df8bae1dSRodney W. Grimes { 297df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 298df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 299df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 300df8bae1dSRodney W. Grimes register struct iso_mnt *imp; 301df8bae1dSRodney W. Grimes struct buf *bp; 3021295d82eSGary Palmer daddr_t lbn, rablock; 303df8bae1dSRodney W. Grimes off_t diff; 304df8bae1dSRodney W. Grimes int rasize, error = 0; 30567ddfcafSMatthew Dillon int seqcount; 306df8bae1dSRodney W. Grimes long size, n, on; 307df8bae1dSRodney W. Grimes 30867ddfcafSMatthew Dillon seqcount = ap->a_ioflag >> 16; 30967ddfcafSMatthew Dillon 310df8bae1dSRodney W. Grimes if (uio->uio_resid == 0) 311df8bae1dSRodney W. Grimes return (0); 312df8bae1dSRodney W. Grimes if (uio->uio_offset < 0) 313df8bae1dSRodney W. Grimes return (EINVAL); 314996c772fSJohn Dyson ip->i_flag |= IN_ACCESS; 315df8bae1dSRodney W. Grimes imp = ip->i_mnt; 316df8bae1dSRodney W. Grimes do { 317996c772fSJohn Dyson lbn = lblkno(imp, uio->uio_offset); 318996c772fSJohn Dyson on = blkoff(imp, uio->uio_offset); 319996c772fSJohn Dyson n = min((u_int)(imp->logical_block_size - on), 320df8bae1dSRodney W. Grimes uio->uio_resid); 321df8bae1dSRodney W. Grimes diff = (off_t)ip->i_size - uio->uio_offset; 322df8bae1dSRodney W. Grimes if (diff <= 0) 323df8bae1dSRodney W. Grimes return (0); 324df8bae1dSRodney W. Grimes if (diff < n) 325df8bae1dSRodney W. Grimes n = diff; 326996c772fSJohn Dyson size = blksize(imp, ip, lbn); 327df8bae1dSRodney W. Grimes rablock = lbn + 1; 32881bca6ddSKATO Takenori if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 3295a5573fdSBruce Evans if (lblktosize(imp, rablock) < ip->i_size) 330996c772fSJohn Dyson error = cluster_read(vp, (off_t)ip->i_size, 3318b612c4bSJohn Dyson lbn, size, NOCRED, uio->uio_resid, 3328b612c4bSJohn Dyson (ap->a_ioflag >> 16), &bp); 333df8bae1dSRodney W. Grimes else 334df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 335df8bae1dSRodney W. Grimes } else { 33667ddfcafSMatthew Dillon if (seqcount > 1 && 337996c772fSJohn Dyson lblktosize(imp, rablock) < ip->i_size) { 338996c772fSJohn Dyson rasize = blksize(imp, ip, rablock); 339df8bae1dSRodney W. Grimes error = breadn(vp, lbn, size, &rablock, 340df8bae1dSRodney W. Grimes &rasize, 1, NOCRED, &bp); 341df8bae1dSRodney W. Grimes } else 342df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 343df8bae1dSRodney W. Grimes } 344df8bae1dSRodney W. Grimes n = min(n, size - bp->b_resid); 345df8bae1dSRodney W. Grimes if (error) { 346df8bae1dSRodney W. Grimes brelse(bp); 347df8bae1dSRodney W. Grimes return (error); 348df8bae1dSRodney W. Grimes } 349df8bae1dSRodney W. Grimes 350996c772fSJohn Dyson error = uiomove(bp->b_data + on, (int)n, uio); 351df8bae1dSRodney W. Grimes brelse(bp); 352df8bae1dSRodney W. Grimes } while (error == 0 && uio->uio_resid > 0 && n != 0); 353df8bae1dSRodney W. Grimes return (error); 354df8bae1dSRodney W. Grimes } 355df8bae1dSRodney W. Grimes 356df8bae1dSRodney W. Grimes /* 357df8bae1dSRodney W. Grimes * Structure for reading directories 358df8bae1dSRodney W. Grimes */ 359df8bae1dSRodney W. Grimes struct isoreaddir { 360df8bae1dSRodney W. Grimes struct dirent saveent; 361df8bae1dSRodney W. Grimes struct dirent assocent; 362df8bae1dSRodney W. Grimes struct dirent current; 363df8bae1dSRodney W. Grimes off_t saveoff; 364df8bae1dSRodney W. Grimes off_t assocoff; 365df8bae1dSRodney W. Grimes off_t curroff; 366df8bae1dSRodney W. Grimes struct uio *uio; 367df8bae1dSRodney W. Grimes off_t uio_off; 368996c772fSJohn Dyson int eofflag; 369996c772fSJohn Dyson u_long *cookies; 370df8bae1dSRodney W. Grimes int ncookies; 371df8bae1dSRodney W. Grimes }; 372df8bae1dSRodney W. Grimes 373996c772fSJohn Dyson int 374df8bae1dSRodney W. Grimes iso_uiodir(idp,dp,off) 375df8bae1dSRodney W. Grimes struct isoreaddir *idp; 376df8bae1dSRodney W. Grimes struct dirent *dp; 377df8bae1dSRodney W. Grimes off_t off; 378df8bae1dSRodney W. Grimes { 379df8bae1dSRodney W. Grimes int error; 380df8bae1dSRodney W. Grimes 381df8bae1dSRodney W. Grimes dp->d_name[dp->d_namlen] = 0; 382c90607baSBruce Evans dp->d_reclen = GENERIC_DIRSIZ(dp); 383df8bae1dSRodney W. Grimes 384df8bae1dSRodney W. Grimes if (idp->uio->uio_resid < dp->d_reclen) { 385996c772fSJohn Dyson idp->eofflag = 0; 386996c772fSJohn Dyson return (-1); 387df8bae1dSRodney W. Grimes } 388df8bae1dSRodney W. Grimes 389996c772fSJohn Dyson if (idp->cookies) { 390df8bae1dSRodney W. Grimes if (idp->ncookies <= 0) { 391996c772fSJohn Dyson idp->eofflag = 0; 392996c772fSJohn Dyson return (-1); 393df8bae1dSRodney W. Grimes } 394df8bae1dSRodney W. Grimes 395996c772fSJohn Dyson *idp->cookies++ = off; 396df8bae1dSRodney W. Grimes --idp->ncookies; 397df8bae1dSRodney W. Grimes } 398df8bae1dSRodney W. Grimes 399d254af07SMatthew Dillon if ((error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) != 0) 400996c772fSJohn Dyson return (error); 401df8bae1dSRodney W. Grimes idp->uio_off = off; 402996c772fSJohn Dyson return (0); 403df8bae1dSRodney W. Grimes } 404df8bae1dSRodney W. Grimes 405996c772fSJohn Dyson int 406df8bae1dSRodney W. Grimes iso_shipdir(idp) 407df8bae1dSRodney W. Grimes struct isoreaddir *idp; 408df8bae1dSRodney W. Grimes { 409df8bae1dSRodney W. Grimes struct dirent *dp; 410df8bae1dSRodney W. Grimes int cl, sl, assoc; 411df8bae1dSRodney W. Grimes int error; 412df8bae1dSRodney W. Grimes char *cname, *sname; 413df8bae1dSRodney W. Grimes 414df8bae1dSRodney W. Grimes cl = idp->current.d_namlen; 415df8bae1dSRodney W. Grimes cname = idp->current.d_name; 4161295d82eSGary Palmer assoc = (cl > 1) && (*cname == ASSOCCHAR); 4171295d82eSGary Palmer if (assoc) { 418df8bae1dSRodney W. Grimes cl--; 419df8bae1dSRodney W. Grimes cname++; 420df8bae1dSRodney W. Grimes } 421df8bae1dSRodney W. Grimes 422df8bae1dSRodney W. Grimes dp = &idp->saveent; 423df8bae1dSRodney W. Grimes sname = dp->d_name; 424df8bae1dSRodney W. Grimes if (!(sl = dp->d_namlen)) { 425df8bae1dSRodney W. Grimes dp = &idp->assocent; 426df8bae1dSRodney W. Grimes sname = dp->d_name + 1; 427df8bae1dSRodney W. Grimes sl = dp->d_namlen - 1; 428df8bae1dSRodney W. Grimes } 429df8bae1dSRodney W. Grimes if (sl > 0) { 430df8bae1dSRodney W. Grimes if (sl != cl 431df8bae1dSRodney W. Grimes || bcmp(sname,cname,sl)) { 432df8bae1dSRodney W. Grimes if (idp->assocent.d_namlen) { 433d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) 434996c772fSJohn Dyson return (error); 435df8bae1dSRodney W. Grimes idp->assocent.d_namlen = 0; 436df8bae1dSRodney W. Grimes } 437df8bae1dSRodney W. Grimes if (idp->saveent.d_namlen) { 438d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) 439996c772fSJohn Dyson return (error); 440df8bae1dSRodney W. Grimes idp->saveent.d_namlen = 0; 441df8bae1dSRodney W. Grimes } 442df8bae1dSRodney W. Grimes } 443df8bae1dSRodney W. Grimes } 444c90607baSBruce Evans idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 445df8bae1dSRodney W. Grimes if (assoc) { 446df8bae1dSRodney W. Grimes idp->assocoff = idp->curroff; 447df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 448df8bae1dSRodney W. Grimes } else { 449df8bae1dSRodney W. Grimes idp->saveoff = idp->curroff; 450df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 451df8bae1dSRodney W. Grimes } 452996c772fSJohn Dyson return (0); 453df8bae1dSRodney W. Grimes } 454df8bae1dSRodney W. Grimes 455df8bae1dSRodney W. Grimes /* 456df8bae1dSRodney W. Grimes * Vnode op for readdir 457df8bae1dSRodney W. Grimes */ 458605e9724SPoul-Henning Kamp static int 459df8bae1dSRodney W. Grimes cd9660_readdir(ap) 460df8bae1dSRodney W. Grimes struct vop_readdir_args /* { 461df8bae1dSRodney W. Grimes struct vnode *a_vp; 462df8bae1dSRodney W. Grimes struct uio *a_uio; 463df8bae1dSRodney W. Grimes struct ucred *a_cred; 464996c772fSJohn Dyson int *a_eofflag; 465996c772fSJohn Dyson int *a_ncookies; 466996c772fSJohn Dyson u_long *a_cookies; 467df8bae1dSRodney W. Grimes } */ *ap; 468df8bae1dSRodney W. Grimes { 469df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 470df8bae1dSRodney W. Grimes struct isoreaddir *idp; 471996c772fSJohn Dyson struct vnode *vdp = ap->a_vp; 472996c772fSJohn Dyson struct iso_node *dp; 473df8bae1dSRodney W. Grimes struct iso_mnt *imp; 474df8bae1dSRodney W. Grimes struct buf *bp = NULL; 475996c772fSJohn Dyson struct iso_directory_record *ep; 476996c772fSJohn Dyson int entryoffsetinblock; 477996c772fSJohn Dyson doff_t endsearch; 478996c772fSJohn Dyson u_long bmask; 479996c772fSJohn Dyson int error = 0; 480996c772fSJohn Dyson int reclen; 481996c772fSJohn Dyson u_short namelen; 4829abf4d6eSDoug Rabson int ncookies = 0; 483996c772fSJohn Dyson u_long *cookies = NULL; 484df8bae1dSRodney W. Grimes 485996c772fSJohn Dyson dp = VTOI(vdp); 486996c772fSJohn Dyson imp = dp->i_mnt; 487996c772fSJohn Dyson bmask = imp->im_bmask; 488df8bae1dSRodney W. Grimes 489df8bae1dSRodney W. Grimes MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 490996c772fSJohn Dyson idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 491996c772fSJohn Dyson /* 492996c772fSJohn Dyson * XXX 493996c772fSJohn Dyson * Is it worth trying to figure out the type? 494996c772fSJohn Dyson */ 495996c772fSJohn Dyson idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 496996c772fSJohn Dyson DT_UNKNOWN; 497df8bae1dSRodney W. Grimes idp->uio = uio; 498996c772fSJohn Dyson if (ap->a_ncookies == NULL) { 499996c772fSJohn Dyson idp->cookies = NULL; 500996c772fSJohn Dyson } else { 5019abf4d6eSDoug Rabson /* 5029abf4d6eSDoug Rabson * Guess the number of cookies needed. 5039abf4d6eSDoug Rabson */ 5049abf4d6eSDoug Rabson ncookies = uio->uio_resid / 16; 505996c772fSJohn Dyson MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 506996c772fSJohn Dyson M_WAITOK); 507996c772fSJohn Dyson idp->cookies = cookies; 508df8bae1dSRodney W. Grimes idp->ncookies = ncookies; 509996c772fSJohn Dyson } 510996c772fSJohn Dyson idp->eofflag = 1; 511df8bae1dSRodney W. Grimes idp->curroff = uio->uio_offset; 512df8bae1dSRodney W. Grimes 513996c772fSJohn Dyson if ((entryoffsetinblock = idp->curroff & bmask) && 514cec0f20cSPoul-Henning Kamp (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 515df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 516df8bae1dSRodney W. Grimes return (error); 517df8bae1dSRodney W. Grimes } 518996c772fSJohn Dyson endsearch = dp->i_size; 519df8bae1dSRodney W. Grimes 520df8bae1dSRodney W. Grimes while (idp->curroff < endsearch) { 521df8bae1dSRodney W. Grimes /* 522df8bae1dSRodney W. Grimes * If offset is on a block boundary, 523df8bae1dSRodney W. Grimes * read the next directory block. 524df8bae1dSRodney W. Grimes * Release previous if it exists. 525df8bae1dSRodney W. Grimes */ 526996c772fSJohn Dyson if ((idp->curroff & bmask) == 0) { 527df8bae1dSRodney W. Grimes if (bp != NULL) 528df8bae1dSRodney W. Grimes brelse(bp); 529d254af07SMatthew Dillon if ((error = 530d254af07SMatthew Dillon cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) 531df8bae1dSRodney W. Grimes break; 532df8bae1dSRodney W. Grimes entryoffsetinblock = 0; 533df8bae1dSRodney W. Grimes } 534df8bae1dSRodney W. Grimes /* 535df8bae1dSRodney W. Grimes * Get pointer to next entry. 536df8bae1dSRodney W. Grimes */ 537df8bae1dSRodney W. Grimes ep = (struct iso_directory_record *) 538996c772fSJohn Dyson ((char *)bp->b_data + entryoffsetinblock); 539df8bae1dSRodney W. Grimes 540df8bae1dSRodney W. Grimes reclen = isonum_711(ep->length); 541df8bae1dSRodney W. Grimes if (reclen == 0) { 542df8bae1dSRodney W. Grimes /* skip to next block, if any */ 543996c772fSJohn Dyson idp->curroff = 544996c772fSJohn Dyson (idp->curroff & ~bmask) + imp->logical_block_size; 545df8bae1dSRodney W. Grimes continue; 546df8bae1dSRodney W. Grimes } 547df8bae1dSRodney W. Grimes 548df8bae1dSRodney W. Grimes if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 549df8bae1dSRodney W. Grimes error = EINVAL; 550df8bae1dSRodney W. Grimes /* illegal entry, stop */ 551df8bae1dSRodney W. Grimes break; 552df8bae1dSRodney W. Grimes } 553df8bae1dSRodney W. Grimes 554df8bae1dSRodney W. Grimes if (entryoffsetinblock + reclen > imp->logical_block_size) { 555df8bae1dSRodney W. Grimes error = EINVAL; 556df8bae1dSRodney W. Grimes /* illegal directory, so stop looking */ 557df8bae1dSRodney W. Grimes break; 558df8bae1dSRodney W. Grimes } 559df8bae1dSRodney W. Grimes 560996c772fSJohn Dyson idp->current.d_namlen = isonum_711(ep->name_len); 561996c772fSJohn Dyson 562996c772fSJohn Dyson if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 56381ec856aSJoerg Wunsch error = EINVAL; 56481ec856aSJoerg Wunsch /* illegal entry, stop */ 56581ec856aSJoerg Wunsch break; 56681ec856aSJoerg Wunsch } 56781ec856aSJoerg Wunsch 568996c772fSJohn Dyson if (isonum_711(ep->flags)&2) 569996c772fSJohn Dyson idp->current.d_fileno = isodirino(ep, imp); 570df8bae1dSRodney W. Grimes else 571df8bae1dSRodney W. Grimes idp->current.d_fileno = dbtob(bp->b_blkno) + 572996c772fSJohn Dyson entryoffsetinblock; 573df8bae1dSRodney W. Grimes 574df8bae1dSRodney W. Grimes idp->curroff += reclen; 575996c772fSJohn Dyson 576df8bae1dSRodney W. Grimes switch (imp->iso_ftype) { 577df8bae1dSRodney W. Grimes case ISO_FTYPE_RRIP: 578996c772fSJohn Dyson cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 579df8bae1dSRodney W. Grimes &idp->current.d_fileno,imp); 580996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 581df8bae1dSRodney W. Grimes if (idp->current.d_namlen) 582df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 583df8bae1dSRodney W. Grimes break; 584988fa8efSJoerg Wunsch default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 585df8bae1dSRodney W. Grimes strcpy(idp->current.d_name,".."); 58644e568e2SDaniel C. Sobral if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 587df8bae1dSRodney W. Grimes idp->current.d_namlen = 1; 588df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 58944e568e2SDaniel C. Sobral } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 590df8bae1dSRodney W. Grimes idp->current.d_namlen = 2; 591df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 59244e568e2SDaniel C. Sobral } else { 593df8bae1dSRodney W. Grimes isofntrans(ep->name,idp->current.d_namlen, 594996c772fSJohn Dyson idp->current.d_name, &namelen, 595df8bae1dSRodney W. Grimes imp->iso_ftype == ISO_FTYPE_9660, 59644e568e2SDaniel C. Sobral isonum_711(ep->flags)&4, 59744e568e2SDaniel C. Sobral imp->joliet_level); 598996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 599df8bae1dSRodney W. Grimes if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 600df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 601df8bae1dSRodney W. Grimes else 602df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 603df8bae1dSRodney W. Grimes } 604df8bae1dSRodney W. Grimes } 605df8bae1dSRodney W. Grimes if (error) 606df8bae1dSRodney W. Grimes break; 607df8bae1dSRodney W. Grimes 608df8bae1dSRodney W. Grimes entryoffsetinblock += reclen; 609df8bae1dSRodney W. Grimes } 610df8bae1dSRodney W. Grimes 611df8bae1dSRodney W. Grimes if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 612df8bae1dSRodney W. Grimes idp->current.d_namlen = 0; 613df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 614df8bae1dSRodney W. Grimes } 615df8bae1dSRodney W. Grimes if (error < 0) 616df8bae1dSRodney W. Grimes error = 0; 617df8bae1dSRodney W. Grimes 6189abf4d6eSDoug Rabson if (ap->a_ncookies != NULL) { 6199abf4d6eSDoug Rabson if (error) 620996c772fSJohn Dyson free(cookies, M_TEMP); 6219abf4d6eSDoug Rabson else { 6229abf4d6eSDoug Rabson /* 6239abf4d6eSDoug Rabson * Work out the number of cookies actually used. 6249abf4d6eSDoug Rabson */ 6259abf4d6eSDoug Rabson *ap->a_ncookies = ncookies - idp->ncookies; 6269abf4d6eSDoug Rabson *ap->a_cookies = cookies; 6279abf4d6eSDoug Rabson } 6289abf4d6eSDoug Rabson } 6299abf4d6eSDoug Rabson 630df8bae1dSRodney W. Grimes if (bp) 631df8bae1dSRodney W. Grimes brelse (bp); 632df8bae1dSRodney W. Grimes 633df8bae1dSRodney W. Grimes uio->uio_offset = idp->uio_off; 634996c772fSJohn Dyson *ap->a_eofflag = idp->eofflag; 635df8bae1dSRodney W. Grimes 636df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 637df8bae1dSRodney W. Grimes 638df8bae1dSRodney W. Grimes return (error); 639df8bae1dSRodney W. Grimes } 640df8bae1dSRodney W. Grimes 641df8bae1dSRodney W. Grimes /* 642df8bae1dSRodney W. Grimes * Return target name of a symbolic link 643df8bae1dSRodney W. Grimes * Shouldn't we get the parent vnode and read the data from there? 644df8bae1dSRodney W. Grimes * This could eventually result in deadlocks in cd9660_lookup. 645df8bae1dSRodney W. Grimes * But otherwise the block read here is in the block buffer two times. 646df8bae1dSRodney W. Grimes */ 647df8bae1dSRodney W. Grimes typedef struct iso_directory_record ISODIR; 648df8bae1dSRodney W. Grimes typedef struct iso_node ISONODE; 649df8bae1dSRodney W. Grimes typedef struct iso_mnt ISOMNT; 650605e9724SPoul-Henning Kamp static int 651df8bae1dSRodney W. Grimes cd9660_readlink(ap) 652df8bae1dSRodney W. Grimes struct vop_readlink_args /* { 653df8bae1dSRodney W. Grimes struct vnode *a_vp; 654df8bae1dSRodney W. Grimes struct uio *a_uio; 655df8bae1dSRodney W. Grimes struct ucred *a_cred; 656df8bae1dSRodney W. Grimes } */ *ap; 657df8bae1dSRodney W. Grimes { 658df8bae1dSRodney W. Grimes ISONODE *ip; 659df8bae1dSRodney W. Grimes ISODIR *dirp; 660df8bae1dSRodney W. Grimes ISOMNT *imp; 661df8bae1dSRodney W. Grimes struct buf *bp; 662996c772fSJohn Dyson struct uio *uio; 663df8bae1dSRodney W. Grimes u_short symlen; 664df8bae1dSRodney W. Grimes int error; 665df8bae1dSRodney W. Grimes char *symname; 666df8bae1dSRodney W. Grimes 667df8bae1dSRodney W. Grimes ip = VTOI(ap->a_vp); 668df8bae1dSRodney W. Grimes imp = ip->i_mnt; 669996c772fSJohn Dyson uio = ap->a_uio; 670df8bae1dSRodney W. Grimes 671df8bae1dSRodney W. Grimes if (imp->iso_ftype != ISO_FTYPE_RRIP) 672996c772fSJohn Dyson return (EINVAL); 673df8bae1dSRodney W. Grimes 674df8bae1dSRodney W. Grimes /* 675df8bae1dSRodney W. Grimes * Get parents directory record block that this inode included. 676df8bae1dSRodney W. Grimes */ 677df8bae1dSRodney W. Grimes error = bread(imp->im_devvp, 678996c772fSJohn Dyson (ip->i_number >> imp->im_bshift) << 679996c772fSJohn Dyson (imp->im_bshift - DEV_BSHIFT), 680996c772fSJohn Dyson imp->logical_block_size, NOCRED, &bp); 681df8bae1dSRodney W. Grimes if (error) { 682df8bae1dSRodney W. Grimes brelse(bp); 683996c772fSJohn Dyson return (EINVAL); 684df8bae1dSRodney W. Grimes } 685df8bae1dSRodney W. Grimes 686df8bae1dSRodney W. Grimes /* 687df8bae1dSRodney W. Grimes * Setup the directory pointer for this inode 688df8bae1dSRodney W. Grimes */ 689996c772fSJohn Dyson dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 690df8bae1dSRodney W. Grimes 691df8bae1dSRodney W. Grimes /* 692df8bae1dSRodney W. Grimes * Just make sure, we have a right one.... 693df8bae1dSRodney W. Grimes * 1: Check not cross boundary on block 694df8bae1dSRodney W. Grimes */ 695df8bae1dSRodney W. Grimes if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 69692579404SAlexander Langer > (unsigned)imp->logical_block_size) { 697df8bae1dSRodney W. Grimes brelse(bp); 698996c772fSJohn Dyson return (EINVAL); 699df8bae1dSRodney W. Grimes } 700df8bae1dSRodney W. Grimes 701df8bae1dSRodney W. Grimes /* 702df8bae1dSRodney W. Grimes * Now get a buffer 703df8bae1dSRodney W. Grimes * Abuse a namei buffer for now. 704df8bae1dSRodney W. Grimes */ 705996c772fSJohn Dyson if (uio->uio_segflg == UIO_SYSSPACE) 706996c772fSJohn Dyson symname = uio->uio_iov->iov_base; 707996c772fSJohn Dyson else 70899448ed1SJohn Dyson symname = zalloc(namei_zone); 709df8bae1dSRodney W. Grimes 710df8bae1dSRodney W. Grimes /* 711df8bae1dSRodney W. Grimes * Ok, we just gathering a symbolic name in SL record. 712df8bae1dSRodney W. Grimes */ 713df8bae1dSRodney W. Grimes if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 714996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) 71599448ed1SJohn Dyson zfree(namei_zone, symname); 716df8bae1dSRodney W. Grimes brelse(bp); 717996c772fSJohn Dyson return (EINVAL); 718df8bae1dSRodney W. Grimes } 719df8bae1dSRodney W. Grimes /* 720df8bae1dSRodney W. Grimes * Don't forget before you leave from home ;-) 721df8bae1dSRodney W. Grimes */ 722df8bae1dSRodney W. Grimes brelse(bp); 723df8bae1dSRodney W. Grimes 724df8bae1dSRodney W. Grimes /* 725df8bae1dSRodney W. Grimes * return with the symbolic name to caller's. 726df8bae1dSRodney W. Grimes */ 727996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) { 728996c772fSJohn Dyson error = uiomove(symname, symlen, uio); 72999448ed1SJohn Dyson zfree(namei_zone, symname); 730996c772fSJohn Dyson return (error); 731996c772fSJohn Dyson } 732996c772fSJohn Dyson uio->uio_resid -= symlen; 733996c772fSJohn Dyson uio->uio_iov->iov_base += symlen; 734996c772fSJohn Dyson uio->uio_iov->iov_len -= symlen; 735996c772fSJohn Dyson return (0); 736df8bae1dSRodney W. Grimes } 737df8bae1dSRodney W. Grimes 738df8bae1dSRodney W. Grimes /* 739df8bae1dSRodney W. Grimes * Calculate the logical to physical mapping if not done already, 740df8bae1dSRodney W. Grimes * then call the device strategy routine. 741df8bae1dSRodney W. Grimes */ 742605e9724SPoul-Henning Kamp static int 743df8bae1dSRodney W. Grimes cd9660_strategy(ap) 744df8bae1dSRodney W. Grimes struct vop_strategy_args /* { 745fd5d1124SJulian Elischer struct buf *a_vp; 746df8bae1dSRodney W. Grimes struct buf *a_bp; 747df8bae1dSRodney W. Grimes } */ *ap; 748df8bae1dSRodney W. Grimes { 749df8bae1dSRodney W. Grimes register struct buf *bp = ap->a_bp; 750df8bae1dSRodney W. Grimes register struct vnode *vp = bp->b_vp; 751df8bae1dSRodney W. Grimes register struct iso_node *ip; 752df8bae1dSRodney W. Grimes int error; 753df8bae1dSRodney W. Grimes 754df8bae1dSRodney W. Grimes ip = VTOI(vp); 755df8bae1dSRodney W. Grimes if (vp->v_type == VBLK || vp->v_type == VCHR) 756df8bae1dSRodney W. Grimes panic("cd9660_strategy: spec"); 757df8bae1dSRodney W. Grimes if (bp->b_blkno == bp->b_lblkno) { 7581295d82eSGary Palmer if ((error = 759c83ebe77SJohn Dyson VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) { 760df8bae1dSRodney W. Grimes bp->b_error = error; 761c244d2deSPoul-Henning Kamp bp->b_ioflags |= BIO_ERROR; 7628177437dSPoul-Henning Kamp bufdone(bp); 763df8bae1dSRodney W. Grimes return (error); 764df8bae1dSRodney W. Grimes } 765df8bae1dSRodney W. Grimes if ((long)bp->b_blkno == -1) 766df8bae1dSRodney W. Grimes clrbuf(bp); 767df8bae1dSRodney W. Grimes } 768df8bae1dSRodney W. Grimes if ((long)bp->b_blkno == -1) { 7698177437dSPoul-Henning Kamp bufdone(bp); 770df8bae1dSRodney W. Grimes return (0); 771df8bae1dSRodney W. Grimes } 772df8bae1dSRodney W. Grimes vp = ip->i_devvp; 773df8bae1dSRodney W. Grimes bp->b_dev = vp->v_rdev; 774fd5d1124SJulian Elischer VOP_STRATEGY(vp, bp); 775df8bae1dSRodney W. Grimes return (0); 776df8bae1dSRodney W. Grimes } 777df8bae1dSRodney W. Grimes 778df8bae1dSRodney W. Grimes /* 779df8bae1dSRodney W. Grimes * Print out the contents of an inode. 780df8bae1dSRodney W. Grimes */ 781605e9724SPoul-Henning Kamp static int 782df8bae1dSRodney W. Grimes cd9660_print(ap) 783df8bae1dSRodney W. Grimes struct vop_print_args /* { 784df8bae1dSRodney W. Grimes struct vnode *a_vp; 785df8bae1dSRodney W. Grimes } */ *ap; 786df8bae1dSRodney W. Grimes { 787996c772fSJohn Dyson 788df8bae1dSRodney W. Grimes printf("tag VT_ISOFS, isofs vnode\n"); 789996c772fSJohn Dyson return (0); 790df8bae1dSRodney W. Grimes } 791df8bae1dSRodney W. Grimes 792df8bae1dSRodney W. Grimes /* 793996c772fSJohn Dyson * Return POSIX pathconf information applicable to cd9660 filesystems. 794996c772fSJohn Dyson */ 795f041a9bdSPoul-Henning Kamp static int 796996c772fSJohn Dyson cd9660_pathconf(ap) 797996c772fSJohn Dyson struct vop_pathconf_args /* { 798996c772fSJohn Dyson struct vnode *a_vp; 799996c772fSJohn Dyson int a_name; 800996c772fSJohn Dyson register_t *a_retval; 801996c772fSJohn Dyson } */ *ap; 802996c772fSJohn Dyson { 803996c772fSJohn Dyson 804996c772fSJohn Dyson switch (ap->a_name) { 805996c772fSJohn Dyson case _PC_LINK_MAX: 806996c772fSJohn Dyson *ap->a_retval = 1; 807996c772fSJohn Dyson return (0); 808996c772fSJohn Dyson case _PC_NAME_MAX: 809996c772fSJohn Dyson if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 810996c772fSJohn Dyson *ap->a_retval = NAME_MAX; 811996c772fSJohn Dyson else 812996c772fSJohn Dyson *ap->a_retval = 37; 813996c772fSJohn Dyson return (0); 814996c772fSJohn Dyson case _PC_PATH_MAX: 815996c772fSJohn Dyson *ap->a_retval = PATH_MAX; 816996c772fSJohn Dyson return (0); 817996c772fSJohn Dyson case _PC_PIPE_BUF: 818996c772fSJohn Dyson *ap->a_retval = PIPE_BUF; 819996c772fSJohn Dyson return (0); 820996c772fSJohn Dyson case _PC_CHOWN_RESTRICTED: 821996c772fSJohn Dyson *ap->a_retval = 1; 822996c772fSJohn Dyson return (0); 823996c772fSJohn Dyson case _PC_NO_TRUNC: 824996c772fSJohn Dyson *ap->a_retval = 1; 825996c772fSJohn Dyson return (0); 826996c772fSJohn Dyson default: 827996c772fSJohn Dyson return (EINVAL); 828996c772fSJohn Dyson } 829996c772fSJohn Dyson /* NOTREACHED */ 830df8bae1dSRodney W. Grimes } 831df8bae1dSRodney W. Grimes 832df8bae1dSRodney W. Grimes /* 833651ae11eSMike Smith * get page routine 834651ae11eSMike Smith * 835651ae11eSMike Smith * XXX By default, wimp out... note that a_offset is ignored (and always 836651ae11eSMike Smith * XXX has been). 837651ae11eSMike Smith */ 838651ae11eSMike Smith int 839651ae11eSMike Smith cd9660_getpages(ap) 840651ae11eSMike Smith struct vop_getpages_args *ap; 841651ae11eSMike Smith { 842651ae11eSMike Smith return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, 843651ae11eSMike Smith ap->a_reqpage); 844651ae11eSMike Smith } 845651ae11eSMike Smith 846651ae11eSMike Smith /* 847651ae11eSMike Smith * put page routine 848651ae11eSMike Smith * 849651ae11eSMike Smith * XXX By default, wimp out... note that a_offset is ignored (and always 850651ae11eSMike Smith * XXX has been). 851651ae11eSMike Smith */ 852651ae11eSMike Smith int 853651ae11eSMike Smith cd9660_putpages(ap) 854651ae11eSMike Smith struct vop_putpages_args *ap; 855651ae11eSMike Smith { 856651ae11eSMike Smith return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, 857651ae11eSMike Smith ap->a_sync, ap->a_rtvals); 858651ae11eSMike Smith } 859651ae11eSMike Smith 860651ae11eSMike Smith /* 861996c772fSJohn Dyson * Global vfs data structures for cd9660 862df8bae1dSRodney W. Grimes */ 863f57e6547SBruce Evans vop_t **cd9660_vnodeop_p; 864f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 865dba3870cSPoul-Henning Kamp { &vop_default_desc, (vop_t *) vop_defaultop }, 866539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 867539ef70cSPoul-Henning Kamp { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 868539ef70cSPoul-Henning Kamp { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 869539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 870539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 871cb2a8dffSSøren Schmidt { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, 872d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 873d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 874539ef70cSPoul-Henning Kamp { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 875539ef70cSPoul-Henning Kamp { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 876539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 877539ef70cSPoul-Henning Kamp { &vop_read_desc, (vop_t *) cd9660_read }, 878539ef70cSPoul-Henning Kamp { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 879539ef70cSPoul-Henning Kamp { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 880539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 881539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 882539ef70cSPoul-Henning Kamp { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 883d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 884651ae11eSMike Smith { &vop_getpages_desc, (vop_t *) cd9660_getpages }, 885651ae11eSMike Smith { &vop_putpages_desc, (vop_t *) cd9660_putpages }, 886f57e6547SBruce Evans { NULL, NULL } 887df8bae1dSRodney W. Grimes }; 888605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 889df8bae1dSRodney W. Grimes { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 890c901836cSGarrett Wollman VNODEOP_SET(cd9660_vnodeop_opv_desc); 891df8bae1dSRodney W. Grimes 892df8bae1dSRodney W. Grimes /* 893df8bae1dSRodney W. Grimes * Special device vnode ops 894df8bae1dSRodney W. Grimes */ 895f57e6547SBruce Evans vop_t **cd9660_specop_p; 896f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 897138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) spec_vnoperate }, 898539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 899539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 900539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 901d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 902d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 903539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 904539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 905539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 906d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 907f57e6547SBruce Evans { NULL, NULL } 908df8bae1dSRodney W. Grimes }; 909605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_specop_opv_desc = 910df8bae1dSRodney W. Grimes { &cd9660_specop_p, cd9660_specop_entries }; 911c901836cSGarrett Wollman VNODEOP_SET(cd9660_specop_opv_desc); 912df8bae1dSRodney W. Grimes 913f57e6547SBruce Evans vop_t **cd9660_fifoop_p; 914f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 915138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) fifo_vnoperate }, 916539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 917539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 918539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 919d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 920d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 921539ef70cSPoul-Henning Kamp { &vop_print_desc, (vop_t *) cd9660_print }, 922539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 923539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 924d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 925f57e6547SBruce Evans { NULL, NULL } 926df8bae1dSRodney W. Grimes }; 927605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_fifoop_opv_desc = 928df8bae1dSRodney W. Grimes { &cd9660_fifoop_p, cd9660_fifoop_entries }; 929c901836cSGarrett Wollman 930c901836cSGarrett Wollman VNODEOP_SET(cd9660_fifoop_opv_desc); 931