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 * 4. Neither the name of the University nor the names of its contributors 19df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 20df8bae1dSRodney W. Grimes * without specific prior written permission. 21df8bae1dSRodney W. Grimes * 22df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df8bae1dSRodney W. Grimes * SUCH DAMAGE. 33df8bae1dSRodney W. Grimes * 34996c772fSJohn Dyson * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 378c9bbf48SDavid E. O'Brien #include <sys/cdefs.h> 388c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$"); 398c9bbf48SDavid E. O'Brien 40df8bae1dSRodney W. Grimes #include <sys/param.h> 41df8bae1dSRodney W. Grimes #include <sys/systm.h> 42df8bae1dSRodney W. Grimes #include <sys/namei.h> 43df8bae1dSRodney W. Grimes #include <sys/kernel.h> 44dfb9f846SPoul-Henning Kamp #include <sys/conf.h> 45df8bae1dSRodney W. Grimes #include <sys/stat.h> 469626b608SPoul-Henning Kamp #include <sys/bio.h> 47df8bae1dSRodney W. Grimes #include <sys/buf.h> 48df8bae1dSRodney W. Grimes #include <sys/mount.h> 49df8bae1dSRodney W. Grimes #include <sys/vnode.h> 5099d300a1SRuslan Ermilov #include <fs/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> 57651ae11eSMike Smith #include <vm/vnode_pager.h> 582684b6afSJeff Roberson #include <vm/uma.h> 59675ea6f0SBruce Evans 60a8d36d0dSCraig Rodrigues #include <fs/cd9660/iso.h> 61a8d36d0dSCraig Rodrigues #include <fs/cd9660/cd9660_node.h> 62a8d36d0dSCraig Rodrigues #include <fs/cd9660/iso_rrip.h> 63df8bae1dSRodney W. Grimes 646fde64c7SPoul-Henning Kamp static vop_setattr_t cd9660_setattr; 6572b3e305SPeter Edwards static vop_open_t cd9660_open; 666fde64c7SPoul-Henning Kamp static vop_access_t cd9660_access; 676fde64c7SPoul-Henning Kamp static vop_getattr_t cd9660_getattr; 686fde64c7SPoul-Henning Kamp static vop_ioctl_t cd9660_ioctl; 696fde64c7SPoul-Henning Kamp static vop_pathconf_t cd9660_pathconf; 706fde64c7SPoul-Henning Kamp static vop_read_t cd9660_read; 7110dd32cdSBruce Evans struct isoreaddir; 7289c9a483SAlfred Perlstein static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 7389c9a483SAlfred Perlstein static int iso_shipdir(struct isoreaddir *idp); 746fde64c7SPoul-Henning Kamp static vop_readdir_t cd9660_readdir; 756fde64c7SPoul-Henning Kamp static vop_readlink_t cd9660_readlink; 766fde64c7SPoul-Henning Kamp static vop_strategy_t cd9660_strategy; 7710bcafe9SPawel Jakub Dawidek static vop_vptofh_t cd9660_vptofh; 7810dd32cdSBruce Evans 79df8bae1dSRodney W. Grimes /* 80de8583ceSDavid Greenman * Setattr call. Only allowed for block and character special devices. 81de8583ceSDavid Greenman */ 8237c84183SPoul-Henning Kamp static int 83de8583ceSDavid Greenman cd9660_setattr(ap) 84de8583ceSDavid Greenman struct vop_setattr_args /* { 85de8583ceSDavid Greenman struct vnodeop_desc *a_desc; 86de8583ceSDavid Greenman struct vnode *a_vp; 87de8583ceSDavid Greenman struct vattr *a_vap; 88de8583ceSDavid Greenman struct ucred *a_cred; 89de8583ceSDavid Greenman } */ *ap; 90de8583ceSDavid Greenman { 91de8583ceSDavid Greenman struct vnode *vp = ap->a_vp; 92de8583ceSDavid Greenman struct vattr *vap = ap->a_vap; 93de8583ceSDavid Greenman 9492579404SAlexander Langer if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 9595a1574eSNate Williams vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 9695a1574eSNate Williams vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 97de8583ceSDavid Greenman return (EROFS); 9892579404SAlexander Langer if (vap->va_size != (u_quad_t)VNOVAL) { 99de8583ceSDavid Greenman switch (vp->v_type) { 100de8583ceSDavid Greenman case VDIR: 101de8583ceSDavid Greenman return (EISDIR); 102de8583ceSDavid Greenman case VLNK: 103de8583ceSDavid Greenman case VREG: 104de8583ceSDavid Greenman return (EROFS); 105de8583ceSDavid Greenman case VCHR: 106de8583ceSDavid Greenman case VBLK: 107de8583ceSDavid Greenman case VSOCK: 108de8583ceSDavid Greenman case VFIFO: 109d254af07SMatthew Dillon case VNON: 110d254af07SMatthew Dillon case VBAD: 11182be0a5aSTor Egge case VMARKER: 112de8583ceSDavid Greenman return (0); 113de8583ceSDavid Greenman } 114de8583ceSDavid Greenman } 115996c772fSJohn Dyson return (0); 116de8583ceSDavid Greenman } 117de8583ceSDavid Greenman 118de8583ceSDavid Greenman /* 119df8bae1dSRodney W. Grimes * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 120df8bae1dSRodney W. Grimes * The mode is shifted to select the owner/group/other fields. The 121df8bae1dSRodney W. Grimes * super user is granted all permissions. 122df8bae1dSRodney W. Grimes */ 123df8bae1dSRodney W. Grimes /* ARGSUSED */ 124605e9724SPoul-Henning Kamp static int 125df8bae1dSRodney W. Grimes cd9660_access(ap) 126df8bae1dSRodney W. Grimes struct vop_access_args /* { 127df8bae1dSRodney W. Grimes struct vnode *a_vp; 12815bc6b2bSEdward Tomasz Napierala accmode_t a_accmode; 129df8bae1dSRodney W. Grimes struct ucred *a_cred; 130b40ce416SJulian Elischer struct thread *a_td; 131df8bae1dSRodney W. Grimes } */ *ap; 132df8bae1dSRodney W. Grimes { 133996c772fSJohn Dyson struct vnode *vp = ap->a_vp; 134996c772fSJohn Dyson struct iso_node *ip = VTOI(vp); 13515bc6b2bSEdward Tomasz Napierala accmode_t accmode = ap->a_accmode; 136996c772fSJohn Dyson 137bc710003SPoul-Henning Kamp if (vp->v_type == VCHR || vp->v_type == VBLK) 138a3679878SPoul-Henning Kamp return (EOPNOTSUPP); 139a3679878SPoul-Henning Kamp 140ba14c327SDavid Greenman /* 141996c772fSJohn Dyson * Disallow write attempts unless the file is a socket, 142996c772fSJohn Dyson * fifo, or a block or character device resident on the 143996c772fSJohn Dyson * filesystem. 144ba14c327SDavid Greenman */ 14515bc6b2bSEdward Tomasz Napierala if (accmode & VWRITE) { 146996c772fSJohn Dyson switch (vp->v_type) { 147ba14c327SDavid Greenman case VDIR: 148ba14c327SDavid Greenman case VLNK: 149ba14c327SDavid Greenman case VREG: 150ba14c327SDavid Greenman return (EROFS); 151d254af07SMatthew Dillon /* NOT REACHED */ 152d254af07SMatthew Dillon default: 153d254af07SMatthew Dillon break; 154ba14c327SDavid Greenman } 155ba14c327SDavid Greenman } 156ba14c327SDavid Greenman 157e39c53edSPoul-Henning Kamp return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid, 15815bc6b2bSEdward Tomasz Napierala ip->inode.iso_gid, ap->a_accmode, ap->a_cred, NULL)); 159df8bae1dSRodney W. Grimes } 160df8bae1dSRodney W. Grimes 161605e9724SPoul-Henning Kamp static int 16272b3e305SPeter Edwards cd9660_open(ap) 16372b3e305SPeter Edwards struct vop_open_args /* { 16472b3e305SPeter Edwards struct vnode *a_vp; 16572b3e305SPeter Edwards int a_mode; 16672b3e305SPeter Edwards struct ucred *a_cred; 16772b3e305SPeter Edwards struct thread *a_td; 168d6da6408SKonstantin Belousov struct file *a_fp; 16972b3e305SPeter Edwards } */ *ap; 17072b3e305SPeter Edwards { 17104c98d46SJohn Baldwin struct vnode *vp = ap->a_vp; 17204c98d46SJohn Baldwin struct iso_node *ip = VTOI(vp); 17372b3e305SPeter Edwards 17404c98d46SJohn Baldwin if (vp->v_type == VCHR || vp->v_type == VBLK) 17504c98d46SJohn Baldwin return (EOPNOTSUPP); 17604c98d46SJohn Baldwin 17704c98d46SJohn Baldwin vnode_create_vobject(vp, ip->i_size, ap->a_td); 17804c98d46SJohn Baldwin return (0); 17972b3e305SPeter Edwards } 18072b3e305SPeter Edwards 18172b3e305SPeter Edwards 18272b3e305SPeter Edwards static int 183df8bae1dSRodney W. Grimes cd9660_getattr(ap) 184df8bae1dSRodney W. Grimes struct vop_getattr_args /* { 185df8bae1dSRodney W. Grimes struct vnode *a_vp; 186df8bae1dSRodney W. Grimes struct vattr *a_vap; 187df8bae1dSRodney W. Grimes struct ucred *a_cred; 188df8bae1dSRodney W. Grimes } */ *ap; 189df8bae1dSRodney W. Grimes 190df8bae1dSRodney W. Grimes { 191df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 1928994a245SDag-Erling Smørgrav struct vattr *vap = ap->a_vap; 1938994a245SDag-Erling Smørgrav struct iso_node *ip = VTOI(vp); 194df8bae1dSRodney W. Grimes 195e3b803b1SPoul-Henning Kamp vap->va_fsid = dev2udev(ip->i_mnt->im_dev); 19682c0aec8STim J. Robbins vap->va_fileid = ip->i_number; 197df8bae1dSRodney W. Grimes 198df8bae1dSRodney W. Grimes vap->va_mode = ip->inode.iso_mode; 199df8bae1dSRodney W. Grimes vap->va_nlink = ip->inode.iso_links; 200df8bae1dSRodney W. Grimes vap->va_uid = ip->inode.iso_uid; 201df8bae1dSRodney W. Grimes vap->va_gid = ip->inode.iso_gid; 202df8bae1dSRodney W. Grimes vap->va_atime = ip->inode.iso_atime; 203df8bae1dSRodney W. Grimes vap->va_mtime = ip->inode.iso_mtime; 204df8bae1dSRodney W. Grimes vap->va_ctime = ip->inode.iso_ctime; 205df8bae1dSRodney W. Grimes vap->va_rdev = ip->inode.iso_rdev; 206df8bae1dSRodney W. Grimes 207df8bae1dSRodney W. Grimes vap->va_size = (u_quad_t) ip->i_size; 208996c772fSJohn Dyson if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 209996c772fSJohn Dyson struct vop_readlink_args rdlnk; 210996c772fSJohn Dyson struct iovec aiov; 211996c772fSJohn Dyson struct uio auio; 212996c772fSJohn Dyson char *cp; 213996c772fSJohn Dyson 2141ede983cSDag-Erling Smørgrav cp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 215996c772fSJohn Dyson aiov.iov_base = cp; 216996c772fSJohn Dyson aiov.iov_len = MAXPATHLEN; 217996c772fSJohn Dyson auio.uio_iov = &aiov; 218996c772fSJohn Dyson auio.uio_iovcnt = 1; 219996c772fSJohn Dyson auio.uio_offset = 0; 220996c772fSJohn Dyson auio.uio_rw = UIO_READ; 221996c772fSJohn Dyson auio.uio_segflg = UIO_SYSSPACE; 2220359a12eSAttilio Rao auio.uio_td = curthread; 223996c772fSJohn Dyson auio.uio_resid = MAXPATHLEN; 224996c772fSJohn Dyson rdlnk.a_uio = &auio; 225996c772fSJohn Dyson rdlnk.a_vp = ap->a_vp; 226996c772fSJohn Dyson rdlnk.a_cred = ap->a_cred; 227996c772fSJohn Dyson if (cd9660_readlink(&rdlnk) == 0) 228996c772fSJohn Dyson vap->va_size = MAXPATHLEN - auio.uio_resid; 2291ede983cSDag-Erling Smørgrav free(cp, M_TEMP); 230996c772fSJohn Dyson } 231df8bae1dSRodney W. Grimes vap->va_flags = 0; 232df8bae1dSRodney W. Grimes vap->va_gen = 1; 233df8bae1dSRodney W. Grimes vap->va_blocksize = ip->i_mnt->logical_block_size; 234df8bae1dSRodney W. Grimes vap->va_bytes = (u_quad_t) ip->i_size; 235df8bae1dSRodney W. Grimes vap->va_type = vp->v_type; 23694a8606fSDoug Rabson vap->va_filerev = 0; 237df8bae1dSRodney W. Grimes return (0); 238df8bae1dSRodney W. Grimes } 239df8bae1dSRodney W. Grimes 240df8bae1dSRodney W. Grimes /* 241cb2a8dffSSøren Schmidt * Vnode op for ioctl. 242cb2a8dffSSøren Schmidt */ 243cb2a8dffSSøren Schmidt static int 244cb2a8dffSSøren Schmidt cd9660_ioctl(ap) 245cb2a8dffSSøren Schmidt struct vop_ioctl_args /* { 246cb2a8dffSSøren Schmidt struct vnode *a_vp; 247bc9d8a9aSPoul-Henning Kamp u_long a_command; 248cb2a8dffSSøren Schmidt caddr_t a_data; 249cb2a8dffSSøren Schmidt int a_fflag; 250cb2a8dffSSøren Schmidt struct ucred *a_cred; 251b40ce416SJulian Elischer struct thread *a_td; 252cb2a8dffSSøren Schmidt } */ *ap; 253cb2a8dffSSøren Schmidt { 254c4df27d5SKonstantin Belousov struct vnode *vp; 255c4df27d5SKonstantin Belousov struct iso_node *ip; 256c4df27d5SKonstantin Belousov int error; 257cb2a8dffSSøren Schmidt 258c4df27d5SKonstantin Belousov vp = ap->a_vp; 259c4df27d5SKonstantin Belousov vn_lock(vp, LK_SHARED | LK_RETRY); 260c4df27d5SKonstantin Belousov if (vp->v_type == VCHR || vp->v_type == VBLK) { 261c4df27d5SKonstantin Belousov VOP_UNLOCK(vp, 0); 262a3679878SPoul-Henning Kamp return (EOPNOTSUPP); 263c4df27d5SKonstantin Belousov } 264c4df27d5SKonstantin Belousov 265c4df27d5SKonstantin Belousov ip = VTOI(vp); 266c4df27d5SKonstantin Belousov error = 0; 267a3679878SPoul-Henning Kamp 268cb2a8dffSSøren Schmidt switch (ap->a_command) { 269cb2a8dffSSøren Schmidt case FIOGETLBA: 270cb2a8dffSSøren Schmidt *(int *)(ap->a_data) = ip->iso_start; 271c4df27d5SKonstantin Belousov break; 272cb2a8dffSSøren Schmidt default: 273c4df27d5SKonstantin Belousov error = ENOTTY; 274c4df27d5SKonstantin Belousov break; 275cb2a8dffSSøren Schmidt } 276c4df27d5SKonstantin Belousov 277c4df27d5SKonstantin Belousov VOP_UNLOCK(vp, 0); 278c4df27d5SKonstantin Belousov return (error); 279cb2a8dffSSøren Schmidt } 280cb2a8dffSSøren Schmidt 281cb2a8dffSSøren Schmidt /* 282df8bae1dSRodney W. Grimes * Vnode op for reading. 283df8bae1dSRodney W. Grimes */ 284605e9724SPoul-Henning Kamp static int 285df8bae1dSRodney W. Grimes cd9660_read(ap) 286df8bae1dSRodney W. Grimes struct vop_read_args /* { 287df8bae1dSRodney W. Grimes struct vnode *a_vp; 288df8bae1dSRodney W. Grimes struct uio *a_uio; 289df8bae1dSRodney W. Grimes int a_ioflag; 290df8bae1dSRodney W. Grimes struct ucred *a_cred; 291df8bae1dSRodney W. Grimes } */ *ap; 292df8bae1dSRodney W. Grimes { 293df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 2948994a245SDag-Erling Smørgrav struct uio *uio = ap->a_uio; 2958994a245SDag-Erling Smørgrav struct iso_node *ip = VTOI(vp); 2968994a245SDag-Erling Smørgrav struct iso_mnt *imp; 297df8bae1dSRodney W. Grimes struct buf *bp; 2981295d82eSGary Palmer daddr_t lbn, rablock; 299df8bae1dSRodney W. Grimes off_t diff; 300df8bae1dSRodney W. Grimes int rasize, error = 0; 30167ddfcafSMatthew Dillon int seqcount; 302df8bae1dSRodney W. Grimes long size, n, on; 303df8bae1dSRodney W. Grimes 304bc710003SPoul-Henning Kamp if (vp->v_type == VCHR || vp->v_type == VBLK) 305a3679878SPoul-Henning Kamp return (EOPNOTSUPP); 306a3679878SPoul-Henning Kamp 3076bd39fe9SAlexander Kabaev seqcount = ap->a_ioflag >> IO_SEQSHIFT; 30867ddfcafSMatthew Dillon 309df8bae1dSRodney W. Grimes if (uio->uio_resid == 0) 310df8bae1dSRodney W. Grimes return (0); 311df8bae1dSRodney W. Grimes if (uio->uio_offset < 0) 312df8bae1dSRodney W. Grimes return (EINVAL); 313df8bae1dSRodney W. Grimes imp = ip->i_mnt; 314df8bae1dSRodney W. Grimes do { 315996c772fSJohn Dyson lbn = lblkno(imp, uio->uio_offset); 316996c772fSJohn Dyson on = blkoff(imp, uio->uio_offset); 317996c772fSJohn Dyson n = min((u_int)(imp->logical_block_size - on), 318df8bae1dSRodney W. Grimes uio->uio_resid); 319df8bae1dSRodney W. Grimes diff = (off_t)ip->i_size - uio->uio_offset; 320df8bae1dSRodney W. Grimes if (diff <= 0) 321df8bae1dSRodney W. Grimes return (0); 322df8bae1dSRodney W. Grimes if (diff < n) 323df8bae1dSRodney W. Grimes n = diff; 324996c772fSJohn Dyson size = blksize(imp, ip, lbn); 325df8bae1dSRodney W. Grimes rablock = lbn + 1; 32681bca6ddSKATO Takenori if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 3275a5573fdSBruce Evans if (lblktosize(imp, rablock) < ip->i_size) 328996c772fSJohn Dyson error = cluster_read(vp, (off_t)ip->i_size, 3298b612c4bSJohn Dyson lbn, size, NOCRED, uio->uio_resid, 3308b612c4bSJohn Dyson (ap->a_ioflag >> 16), &bp); 331df8bae1dSRodney W. Grimes else 332df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 333df8bae1dSRodney W. Grimes } else { 33467ddfcafSMatthew Dillon if (seqcount > 1 && 335996c772fSJohn Dyson lblktosize(imp, rablock) < ip->i_size) { 336996c772fSJohn Dyson rasize = blksize(imp, ip, rablock); 337df8bae1dSRodney W. Grimes error = breadn(vp, lbn, size, &rablock, 338df8bae1dSRodney W. Grimes &rasize, 1, NOCRED, &bp); 339df8bae1dSRodney W. Grimes } else 340df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 341df8bae1dSRodney W. Grimes } 342df8bae1dSRodney W. Grimes n = min(n, size - bp->b_resid); 343df8bae1dSRodney W. Grimes if (error) { 344df8bae1dSRodney W. Grimes brelse(bp); 345df8bae1dSRodney W. Grimes return (error); 346df8bae1dSRodney W. Grimes } 347df8bae1dSRodney W. Grimes 348996c772fSJohn Dyson error = uiomove(bp->b_data + on, (int)n, uio); 349df8bae1dSRodney W. Grimes brelse(bp); 350df8bae1dSRodney W. Grimes } while (error == 0 && uio->uio_resid > 0 && n != 0); 351df8bae1dSRodney W. Grimes return (error); 352df8bae1dSRodney W. Grimes } 353df8bae1dSRodney W. Grimes 354df8bae1dSRodney W. Grimes /* 355df8bae1dSRodney W. Grimes * Structure for reading directories 356df8bae1dSRodney W. Grimes */ 357df8bae1dSRodney W. Grimes struct isoreaddir { 358df8bae1dSRodney W. Grimes struct dirent saveent; 359df8bae1dSRodney W. Grimes struct dirent assocent; 360df8bae1dSRodney W. Grimes struct dirent current; 361df8bae1dSRodney W. Grimes off_t saveoff; 362df8bae1dSRodney W. Grimes off_t assocoff; 363df8bae1dSRodney W. Grimes off_t curroff; 364df8bae1dSRodney W. Grimes struct uio *uio; 365df8bae1dSRodney W. Grimes off_t uio_off; 366996c772fSJohn Dyson int eofflag; 367996c772fSJohn Dyson u_long *cookies; 368df8bae1dSRodney W. Grimes int ncookies; 369df8bae1dSRodney W. Grimes }; 370df8bae1dSRodney W. Grimes 37137c84183SPoul-Henning Kamp static int 372df8bae1dSRodney W. Grimes iso_uiodir(idp,dp,off) 373df8bae1dSRodney W. Grimes struct isoreaddir *idp; 374df8bae1dSRodney W. Grimes struct dirent *dp; 375df8bae1dSRodney W. Grimes off_t off; 376df8bae1dSRodney W. Grimes { 377df8bae1dSRodney W. Grimes int error; 378df8bae1dSRodney W. Grimes 379df8bae1dSRodney W. Grimes dp->d_name[dp->d_namlen] = 0; 380c90607baSBruce Evans dp->d_reclen = GENERIC_DIRSIZ(dp); 381df8bae1dSRodney W. Grimes 382df8bae1dSRodney W. Grimes if (idp->uio->uio_resid < dp->d_reclen) { 383996c772fSJohn Dyson idp->eofflag = 0; 384996c772fSJohn Dyson return (-1); 385df8bae1dSRodney W. Grimes } 386df8bae1dSRodney W. Grimes 387996c772fSJohn Dyson if (idp->cookies) { 388df8bae1dSRodney W. Grimes if (idp->ncookies <= 0) { 389996c772fSJohn Dyson idp->eofflag = 0; 390996c772fSJohn Dyson return (-1); 391df8bae1dSRodney W. Grimes } 392df8bae1dSRodney W. Grimes 393996c772fSJohn Dyson *idp->cookies++ = off; 394df8bae1dSRodney W. Grimes --idp->ncookies; 395df8bae1dSRodney W. Grimes } 396df8bae1dSRodney W. Grimes 397c9524588SDag-Erling Smørgrav if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0) 398996c772fSJohn Dyson return (error); 399df8bae1dSRodney W. Grimes idp->uio_off = off; 400996c772fSJohn Dyson return (0); 401df8bae1dSRodney W. Grimes } 402df8bae1dSRodney W. Grimes 40337c84183SPoul-Henning Kamp static int 404df8bae1dSRodney W. Grimes iso_shipdir(idp) 405df8bae1dSRodney W. Grimes struct isoreaddir *idp; 406df8bae1dSRodney W. Grimes { 407df8bae1dSRodney W. Grimes struct dirent *dp; 408df8bae1dSRodney W. Grimes int cl, sl, assoc; 409df8bae1dSRodney W. Grimes int error; 410df8bae1dSRodney W. Grimes char *cname, *sname; 411df8bae1dSRodney W. Grimes 412df8bae1dSRodney W. Grimes cl = idp->current.d_namlen; 413df8bae1dSRodney W. Grimes cname = idp->current.d_name; 4141295d82eSGary Palmer assoc = (cl > 1) && (*cname == ASSOCCHAR); 4151295d82eSGary Palmer if (assoc) { 416df8bae1dSRodney W. Grimes cl--; 417df8bae1dSRodney W. Grimes cname++; 418df8bae1dSRodney W. Grimes } 419df8bae1dSRodney W. Grimes 420df8bae1dSRodney W. Grimes dp = &idp->saveent; 421df8bae1dSRodney W. Grimes sname = dp->d_name; 422df8bae1dSRodney W. Grimes if (!(sl = dp->d_namlen)) { 423df8bae1dSRodney W. Grimes dp = &idp->assocent; 424df8bae1dSRodney W. Grimes sname = dp->d_name + 1; 425df8bae1dSRodney W. Grimes sl = dp->d_namlen - 1; 426df8bae1dSRodney W. Grimes } 427df8bae1dSRodney W. Grimes if (sl > 0) { 428df8bae1dSRodney W. Grimes if (sl != cl 429df8bae1dSRodney W. Grimes || bcmp(sname,cname,sl)) { 430df8bae1dSRodney W. Grimes if (idp->assocent.d_namlen) { 431d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) 432996c772fSJohn Dyson return (error); 433df8bae1dSRodney W. Grimes idp->assocent.d_namlen = 0; 434df8bae1dSRodney W. Grimes } 435df8bae1dSRodney W. Grimes if (idp->saveent.d_namlen) { 436d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) 437996c772fSJohn Dyson return (error); 438df8bae1dSRodney W. Grimes idp->saveent.d_namlen = 0; 439df8bae1dSRodney W. Grimes } 440df8bae1dSRodney W. Grimes } 441df8bae1dSRodney W. Grimes } 442c90607baSBruce Evans idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 443df8bae1dSRodney W. Grimes if (assoc) { 444df8bae1dSRodney W. Grimes idp->assocoff = idp->curroff; 445df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 446df8bae1dSRodney W. Grimes } else { 447df8bae1dSRodney W. Grimes idp->saveoff = idp->curroff; 448df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 449df8bae1dSRodney W. Grimes } 450996c772fSJohn Dyson return (0); 451df8bae1dSRodney W. Grimes } 452df8bae1dSRodney W. Grimes 453df8bae1dSRodney W. Grimes /* 454df8bae1dSRodney W. Grimes * Vnode op for readdir 455df8bae1dSRodney W. Grimes */ 456605e9724SPoul-Henning Kamp static int 457df8bae1dSRodney W. Grimes cd9660_readdir(ap) 458df8bae1dSRodney W. Grimes struct vop_readdir_args /* { 459df8bae1dSRodney W. Grimes struct vnode *a_vp; 460df8bae1dSRodney W. Grimes struct uio *a_uio; 461df8bae1dSRodney W. Grimes struct ucred *a_cred; 462996c772fSJohn Dyson int *a_eofflag; 463996c772fSJohn Dyson int *a_ncookies; 464f71cc868STim J. Robbins u_long **a_cookies; 465df8bae1dSRodney W. Grimes } */ *ap; 466df8bae1dSRodney W. Grimes { 4678994a245SDag-Erling Smørgrav struct uio *uio = ap->a_uio; 468df8bae1dSRodney W. Grimes struct isoreaddir *idp; 469996c772fSJohn Dyson struct vnode *vdp = ap->a_vp; 470996c772fSJohn Dyson struct iso_node *dp; 471df8bae1dSRodney W. Grimes struct iso_mnt *imp; 472df8bae1dSRodney W. Grimes struct buf *bp = NULL; 473996c772fSJohn Dyson struct iso_directory_record *ep; 474996c772fSJohn Dyson int entryoffsetinblock; 475996c772fSJohn Dyson doff_t endsearch; 476996c772fSJohn Dyson u_long bmask; 477996c772fSJohn Dyson int error = 0; 478996c772fSJohn Dyson int reclen; 479996c772fSJohn Dyson u_short namelen; 4809abf4d6eSDoug Rabson int ncookies = 0; 481996c772fSJohn Dyson u_long *cookies = NULL; 482df8bae1dSRodney W. Grimes 483996c772fSJohn Dyson dp = VTOI(vdp); 484996c772fSJohn Dyson imp = dp->i_mnt; 485996c772fSJohn Dyson bmask = imp->im_bmask; 486df8bae1dSRodney W. Grimes 4871ede983cSDag-Erling Smørgrav idp = malloc(sizeof(*idp), M_TEMP, M_WAITOK); 488996c772fSJohn Dyson idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 489996c772fSJohn Dyson /* 490996c772fSJohn Dyson * XXX 491996c772fSJohn Dyson * Is it worth trying to figure out the type? 492996c772fSJohn Dyson */ 493996c772fSJohn Dyson idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 494996c772fSJohn Dyson DT_UNKNOWN; 495df8bae1dSRodney W. Grimes idp->uio = uio; 496996c772fSJohn Dyson if (ap->a_ncookies == NULL) { 497996c772fSJohn Dyson idp->cookies = NULL; 498996c772fSJohn Dyson } else { 4999abf4d6eSDoug Rabson /* 5009abf4d6eSDoug Rabson * Guess the number of cookies needed. 5019abf4d6eSDoug Rabson */ 5029abf4d6eSDoug Rabson ncookies = uio->uio_resid / 16; 5031ede983cSDag-Erling Smørgrav cookies = malloc(ncookies * sizeof(u_long), 504224f219bSTim J. Robbins M_TEMP, M_WAITOK); 505996c772fSJohn Dyson idp->cookies = cookies; 506df8bae1dSRodney W. Grimes idp->ncookies = ncookies; 507996c772fSJohn Dyson } 508996c772fSJohn Dyson idp->eofflag = 1; 509df8bae1dSRodney W. Grimes idp->curroff = uio->uio_offset; 510ac8b6eddSKonstantin Belousov idp->uio_off = uio->uio_offset; 511df8bae1dSRodney W. Grimes 512996c772fSJohn Dyson if ((entryoffsetinblock = idp->curroff & bmask) && 513cec0f20cSPoul-Henning Kamp (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 5141ede983cSDag-Erling Smørgrav free(idp, M_TEMP); 515df8bae1dSRodney W. Grimes return (error); 516df8bae1dSRodney W. Grimes } 517996c772fSJohn Dyson endsearch = dp->i_size; 518df8bae1dSRodney W. Grimes 519df8bae1dSRodney W. Grimes while (idp->curroff < endsearch) { 520df8bae1dSRodney W. Grimes /* 521df8bae1dSRodney W. Grimes * If offset is on a block boundary, 522df8bae1dSRodney W. Grimes * read the next directory block. 523df8bae1dSRodney W. Grimes * Release previous if it exists. 524df8bae1dSRodney W. Grimes */ 525996c772fSJohn Dyson if ((idp->curroff & bmask) == 0) { 526df8bae1dSRodney W. Grimes if (bp != NULL) 527df8bae1dSRodney W. Grimes brelse(bp); 528d254af07SMatthew Dillon if ((error = 529d254af07SMatthew Dillon cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) 530df8bae1dSRodney W. Grimes break; 531df8bae1dSRodney W. Grimes entryoffsetinblock = 0; 532df8bae1dSRodney W. Grimes } 533df8bae1dSRodney W. Grimes /* 534df8bae1dSRodney W. Grimes * Get pointer to next entry. 535df8bae1dSRodney W. Grimes */ 536df8bae1dSRodney W. Grimes ep = (struct iso_directory_record *) 537996c772fSJohn Dyson ((char *)bp->b_data + entryoffsetinblock); 538df8bae1dSRodney W. Grimes 539df8bae1dSRodney W. Grimes reclen = isonum_711(ep->length); 540df8bae1dSRodney W. Grimes if (reclen == 0) { 541df8bae1dSRodney W. Grimes /* skip to next block, if any */ 542996c772fSJohn Dyson idp->curroff = 543996c772fSJohn Dyson (idp->curroff & ~bmask) + imp->logical_block_size; 544df8bae1dSRodney W. Grimes continue; 545df8bae1dSRodney W. Grimes } 546df8bae1dSRodney W. Grimes 547df8bae1dSRodney W. Grimes if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 548df8bae1dSRodney W. Grimes error = EINVAL; 549df8bae1dSRodney W. Grimes /* illegal entry, stop */ 550df8bae1dSRodney W. Grimes break; 551df8bae1dSRodney W. Grimes } 552df8bae1dSRodney W. Grimes 553df8bae1dSRodney W. Grimes if (entryoffsetinblock + reclen > imp->logical_block_size) { 554df8bae1dSRodney W. Grimes error = EINVAL; 555df8bae1dSRodney W. Grimes /* illegal directory, so stop looking */ 556df8bae1dSRodney W. Grimes break; 557df8bae1dSRodney W. Grimes } 558df8bae1dSRodney W. Grimes 559996c772fSJohn Dyson idp->current.d_namlen = isonum_711(ep->name_len); 560996c772fSJohn Dyson 561996c772fSJohn Dyson if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 56281ec856aSJoerg Wunsch error = EINVAL; 56381ec856aSJoerg Wunsch /* illegal entry, stop */ 56481ec856aSJoerg Wunsch break; 56581ec856aSJoerg Wunsch } 56681ec856aSJoerg Wunsch 56782c0aec8STim J. Robbins if (isonum_711(ep->flags)&2) 56882c0aec8STim J. Robbins idp->current.d_fileno = isodirino(ep, imp); 56982c0aec8STim J. Robbins else 57082c0aec8STim J. Robbins idp->current.d_fileno = dbtob(bp->b_blkno) + 57182c0aec8STim J. Robbins entryoffsetinblock; 572df8bae1dSRodney W. Grimes 573df8bae1dSRodney W. Grimes idp->curroff += reclen; 574996c772fSJohn Dyson 575df8bae1dSRodney W. Grimes switch (imp->iso_ftype) { 576df8bae1dSRodney W. Grimes case ISO_FTYPE_RRIP: 577996c772fSJohn Dyson cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 578df8bae1dSRodney W. Grimes &idp->current.d_fileno,imp); 579996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 580df8bae1dSRodney W. Grimes if (idp->current.d_namlen) 581df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 582df8bae1dSRodney W. Grimes break; 583988fa8efSJoerg Wunsch default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 584df8bae1dSRodney W. Grimes strcpy(idp->current.d_name,".."); 58544e568e2SDaniel C. Sobral if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 586df8bae1dSRodney W. Grimes idp->current.d_namlen = 1; 587df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 58844e568e2SDaniel C. Sobral } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 589df8bae1dSRodney W. Grimes idp->current.d_namlen = 2; 590df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 59144e568e2SDaniel C. Sobral } else { 592df8bae1dSRodney W. Grimes isofntrans(ep->name,idp->current.d_namlen, 593996c772fSJohn Dyson idp->current.d_name, &namelen, 594df8bae1dSRodney W. Grimes imp->iso_ftype == ISO_FTYPE_9660, 59544e568e2SDaniel C. Sobral isonum_711(ep->flags)&4, 596c4f02a89SMax Khon imp->joliet_level, 597c4f02a89SMax Khon imp->im_flags, 598c4f02a89SMax Khon imp->im_d2l); 599996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 600df8bae1dSRodney W. Grimes if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 601df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 602df8bae1dSRodney W. Grimes else 603df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 604df8bae1dSRodney W. Grimes } 605df8bae1dSRodney W. Grimes } 606df8bae1dSRodney W. Grimes if (error) 607df8bae1dSRodney W. Grimes break; 608df8bae1dSRodney W. Grimes 609df8bae1dSRodney W. Grimes entryoffsetinblock += reclen; 610df8bae1dSRodney W. Grimes } 611df8bae1dSRodney W. Grimes 612df8bae1dSRodney W. Grimes if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 613df8bae1dSRodney W. Grimes idp->current.d_namlen = 0; 614df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 615df8bae1dSRodney W. Grimes } 616df8bae1dSRodney W. Grimes if (error < 0) 617df8bae1dSRodney W. Grimes error = 0; 618df8bae1dSRodney W. Grimes 6199abf4d6eSDoug Rabson if (ap->a_ncookies != NULL) { 6209abf4d6eSDoug Rabson if (error) 621996c772fSJohn Dyson free(cookies, M_TEMP); 6229abf4d6eSDoug Rabson else { 6239abf4d6eSDoug Rabson /* 6249abf4d6eSDoug Rabson * Work out the number of cookies actually used. 6259abf4d6eSDoug Rabson */ 6269abf4d6eSDoug Rabson *ap->a_ncookies = ncookies - idp->ncookies; 6279abf4d6eSDoug Rabson *ap->a_cookies = cookies; 6289abf4d6eSDoug Rabson } 6299abf4d6eSDoug Rabson } 6309abf4d6eSDoug Rabson 631df8bae1dSRodney W. Grimes if (bp) 632df8bae1dSRodney W. Grimes brelse (bp); 633df8bae1dSRodney W. Grimes 634df8bae1dSRodney W. Grimes uio->uio_offset = idp->uio_off; 635996c772fSJohn Dyson *ap->a_eofflag = idp->eofflag; 636df8bae1dSRodney W. Grimes 6371ede983cSDag-Erling Smørgrav free(idp, M_TEMP); 638df8bae1dSRodney W. Grimes 639df8bae1dSRodney W. Grimes return (error); 640df8bae1dSRodney W. Grimes } 641df8bae1dSRodney W. Grimes 642df8bae1dSRodney W. Grimes /* 643df8bae1dSRodney W. Grimes * Return target name of a symbolic link 644df8bae1dSRodney W. Grimes * Shouldn't we get the parent vnode and read the data from there? 645df8bae1dSRodney W. Grimes * This could eventually result in deadlocks in cd9660_lookup. 646df8bae1dSRodney W. Grimes * But otherwise the block read here is in the block buffer two times. 647df8bae1dSRodney W. Grimes */ 648df8bae1dSRodney W. Grimes typedef struct iso_directory_record ISODIR; 649df8bae1dSRodney W. Grimes typedef struct iso_node ISONODE; 650df8bae1dSRodney W. Grimes typedef struct iso_mnt ISOMNT; 651605e9724SPoul-Henning Kamp static int 652df8bae1dSRodney W. Grimes cd9660_readlink(ap) 653df8bae1dSRodney W. Grimes struct vop_readlink_args /* { 654df8bae1dSRodney W. Grimes struct vnode *a_vp; 655df8bae1dSRodney W. Grimes struct uio *a_uio; 656df8bae1dSRodney W. Grimes struct ucred *a_cred; 657df8bae1dSRodney W. Grimes } */ *ap; 658df8bae1dSRodney W. Grimes { 659df8bae1dSRodney W. Grimes ISONODE *ip; 660df8bae1dSRodney W. Grimes ISODIR *dirp; 661df8bae1dSRodney W. Grimes ISOMNT *imp; 662df8bae1dSRodney W. Grimes struct buf *bp; 663996c772fSJohn Dyson struct uio *uio; 664df8bae1dSRodney W. Grimes u_short symlen; 665df8bae1dSRodney W. Grimes int error; 666df8bae1dSRodney W. Grimes char *symname; 667df8bae1dSRodney W. Grimes 668df8bae1dSRodney W. Grimes ip = VTOI(ap->a_vp); 669df8bae1dSRodney W. Grimes imp = ip->i_mnt; 670996c772fSJohn Dyson uio = ap->a_uio; 671df8bae1dSRodney W. Grimes 672df8bae1dSRodney W. Grimes if (imp->iso_ftype != ISO_FTYPE_RRIP) 673996c772fSJohn Dyson return (EINVAL); 674df8bae1dSRodney W. Grimes 675df8bae1dSRodney W. Grimes /* 676df8bae1dSRodney W. Grimes * Get parents directory record block that this inode included. 677df8bae1dSRodney W. Grimes */ 678df8bae1dSRodney W. Grimes error = bread(imp->im_devvp, 679996c772fSJohn Dyson (ip->i_number >> imp->im_bshift) << 680996c772fSJohn Dyson (imp->im_bshift - DEV_BSHIFT), 681996c772fSJohn Dyson imp->logical_block_size, NOCRED, &bp); 682df8bae1dSRodney W. Grimes if (error) { 683df8bae1dSRodney W. Grimes brelse(bp); 684996c772fSJohn Dyson return (EINVAL); 685df8bae1dSRodney W. Grimes } 686df8bae1dSRodney W. Grimes 687df8bae1dSRodney W. Grimes /* 688df8bae1dSRodney W. Grimes * Setup the directory pointer for this inode 689df8bae1dSRodney W. Grimes */ 690996c772fSJohn Dyson dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 691df8bae1dSRodney W. Grimes 692df8bae1dSRodney W. Grimes /* 693df8bae1dSRodney W. Grimes * Just make sure, we have a right one.... 694df8bae1dSRodney W. Grimes * 1: Check not cross boundary on block 695df8bae1dSRodney W. Grimes */ 696df8bae1dSRodney W. Grimes if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 69792579404SAlexander Langer > (unsigned)imp->logical_block_size) { 698df8bae1dSRodney W. Grimes brelse(bp); 699996c772fSJohn Dyson return (EINVAL); 700df8bae1dSRodney W. Grimes } 701df8bae1dSRodney W. Grimes 702df8bae1dSRodney W. Grimes /* 703df8bae1dSRodney W. Grimes * Now get a buffer 704df8bae1dSRodney W. Grimes * Abuse a namei buffer for now. 705df8bae1dSRodney W. Grimes */ 706996c772fSJohn Dyson if (uio->uio_segflg == UIO_SYSSPACE) 707996c772fSJohn Dyson symname = uio->uio_iov->iov_base; 708996c772fSJohn Dyson else 709a163d034SWarner Losh symname = uma_zalloc(namei_zone, M_WAITOK); 710df8bae1dSRodney W. Grimes 711df8bae1dSRodney W. Grimes /* 712df8bae1dSRodney W. Grimes * Ok, we just gathering a symbolic name in SL record. 713df8bae1dSRodney W. Grimes */ 714df8bae1dSRodney W. Grimes if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 715996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) 7162684b6afSJeff Roberson uma_zfree(namei_zone, symname); 717df8bae1dSRodney W. Grimes brelse(bp); 718996c772fSJohn Dyson return (EINVAL); 719df8bae1dSRodney W. Grimes } 720df8bae1dSRodney W. Grimes /* 721df8bae1dSRodney W. Grimes * Don't forget before you leave from home ;-) 722df8bae1dSRodney W. Grimes */ 723df8bae1dSRodney W. Grimes brelse(bp); 724df8bae1dSRodney W. Grimes 725df8bae1dSRodney W. Grimes /* 726df8bae1dSRodney W. Grimes * return with the symbolic name to caller's. 727df8bae1dSRodney W. Grimes */ 728996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) { 729996c772fSJohn Dyson error = uiomove(symname, symlen, uio); 7302684b6afSJeff Roberson uma_zfree(namei_zone, symname); 731996c772fSJohn Dyson return (error); 732996c772fSJohn Dyson } 733996c772fSJohn Dyson uio->uio_resid -= symlen; 7342b7f24d2SMike Barcroft uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 735996c772fSJohn Dyson uio->uio_iov->iov_len -= symlen; 736996c772fSJohn Dyson return (0); 737df8bae1dSRodney W. Grimes } 738df8bae1dSRodney W. Grimes 739df8bae1dSRodney W. Grimes /* 740df8bae1dSRodney W. Grimes * Calculate the logical to physical mapping if not done already, 741df8bae1dSRodney W. Grimes * then call the device strategy routine. 742df8bae1dSRodney W. Grimes */ 743605e9724SPoul-Henning Kamp static int 744df8bae1dSRodney W. Grimes cd9660_strategy(ap) 745df8bae1dSRodney W. Grimes struct vop_strategy_args /* { 746fd5d1124SJulian Elischer struct buf *a_vp; 747df8bae1dSRodney W. Grimes struct buf *a_bp; 748df8bae1dSRodney W. Grimes } */ *ap; 749df8bae1dSRodney W. Grimes { 7508994a245SDag-Erling Smørgrav struct buf *bp = ap->a_bp; 751d83b7498SPoul-Henning Kamp struct vnode *vp = ap->a_vp; 7528994a245SDag-Erling Smørgrav struct iso_node *ip; 753bf7e2ae1SPoul-Henning Kamp struct bufobj *bo; 754df8bae1dSRodney W. Grimes 755df8bae1dSRodney W. Grimes ip = VTOI(vp); 756df8bae1dSRodney W. Grimes if (vp->v_type == VBLK || vp->v_type == VCHR) 757df8bae1dSRodney W. Grimes panic("cd9660_strategy: spec"); 758df8bae1dSRodney W. Grimes if (bp->b_blkno == bp->b_lblkno) { 759e9d19a11SPoul-Henning Kamp bp->b_blkno = (ip->iso_start + bp->b_lblkno) << 760e9d19a11SPoul-Henning Kamp (ip->i_mnt->im_bshift - DEV_BSHIFT); 761df8bae1dSRodney W. Grimes } 7622c18019fSPoul-Henning Kamp bp->b_iooffset = dbtob(bp->b_blkno); 763bf7e2ae1SPoul-Henning Kamp bo = ip->i_mnt->im_bo; 7640391e5a1SPoul-Henning Kamp BO_STRATEGY(bo, bp); 765df8bae1dSRodney W. Grimes return (0); 766df8bae1dSRodney W. Grimes } 767df8bae1dSRodney W. Grimes 768df8bae1dSRodney W. Grimes /* 769996c772fSJohn Dyson * Return POSIX pathconf information applicable to cd9660 filesystems. 770996c772fSJohn Dyson */ 771f041a9bdSPoul-Henning Kamp static int 772996c772fSJohn Dyson cd9660_pathconf(ap) 773996c772fSJohn Dyson struct vop_pathconf_args /* { 774996c772fSJohn Dyson struct vnode *a_vp; 775996c772fSJohn Dyson int a_name; 776996c772fSJohn Dyson register_t *a_retval; 777996c772fSJohn Dyson } */ *ap; 778996c772fSJohn Dyson { 779996c772fSJohn Dyson 780996c772fSJohn Dyson switch (ap->a_name) { 781996c772fSJohn Dyson case _PC_LINK_MAX: 782996c772fSJohn Dyson *ap->a_retval = 1; 783996c772fSJohn Dyson return (0); 784996c772fSJohn Dyson case _PC_NAME_MAX: 785996c772fSJohn Dyson if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 786996c772fSJohn Dyson *ap->a_retval = NAME_MAX; 787996c772fSJohn Dyson else 788996c772fSJohn Dyson *ap->a_retval = 37; 789996c772fSJohn Dyson return (0); 790996c772fSJohn Dyson case _PC_PATH_MAX: 791996c772fSJohn Dyson *ap->a_retval = PATH_MAX; 792996c772fSJohn Dyson return (0); 793996c772fSJohn Dyson case _PC_PIPE_BUF: 794996c772fSJohn Dyson *ap->a_retval = PIPE_BUF; 795996c772fSJohn Dyson return (0); 796996c772fSJohn Dyson case _PC_CHOWN_RESTRICTED: 797996c772fSJohn Dyson *ap->a_retval = 1; 798996c772fSJohn Dyson return (0); 799996c772fSJohn Dyson case _PC_NO_TRUNC: 800996c772fSJohn Dyson *ap->a_retval = 1; 801996c772fSJohn Dyson return (0); 802996c772fSJohn Dyson default: 803996c772fSJohn Dyson return (EINVAL); 804996c772fSJohn Dyson } 805996c772fSJohn Dyson /* NOTREACHED */ 806df8bae1dSRodney W. Grimes } 807df8bae1dSRodney W. Grimes 808df8bae1dSRodney W. Grimes /* 80910bcafe9SPawel Jakub Dawidek * Vnode pointer to File handle 81010bcafe9SPawel Jakub Dawidek */ 81110bcafe9SPawel Jakub Dawidek static int 81210bcafe9SPawel Jakub Dawidek cd9660_vptofh(ap) 81310bcafe9SPawel Jakub Dawidek struct vop_vptofh_args /* { 81410bcafe9SPawel Jakub Dawidek struct vnode *a_vp; 81510bcafe9SPawel Jakub Dawidek struct fid *a_fhp; 81610bcafe9SPawel Jakub Dawidek } */ *ap; 81710bcafe9SPawel Jakub Dawidek { 81810bcafe9SPawel Jakub Dawidek struct iso_node *ip = VTOI(ap->a_vp); 81910bcafe9SPawel Jakub Dawidek struct ifid *ifhp; 82010bcafe9SPawel Jakub Dawidek 82110bcafe9SPawel Jakub Dawidek ifhp = (struct ifid *)ap->a_fhp; 82210bcafe9SPawel Jakub Dawidek ifhp->ifid_len = sizeof(struct ifid); 82310bcafe9SPawel Jakub Dawidek 82410bcafe9SPawel Jakub Dawidek ifhp->ifid_ino = ip->i_number; 82510bcafe9SPawel Jakub Dawidek ifhp->ifid_start = ip->iso_start; 82610bcafe9SPawel Jakub Dawidek 82710bcafe9SPawel Jakub Dawidek #ifdef ISOFS_DBG 82810bcafe9SPawel Jakub Dawidek printf("vptofh: ino %d, start %ld\n", 82910bcafe9SPawel Jakub Dawidek ifhp->ifid_ino,ifhp->ifid_start); 83010bcafe9SPawel Jakub Dawidek #endif 83110bcafe9SPawel Jakub Dawidek return 0; 83210bcafe9SPawel Jakub Dawidek } 83310bcafe9SPawel Jakub Dawidek 83410bcafe9SPawel Jakub Dawidek /* 835996c772fSJohn Dyson * Global vfs data structures for cd9660 836df8bae1dSRodney W. Grimes */ 837aec0fb7bSPoul-Henning Kamp struct vop_vector cd9660_vnodeops = { 838aec0fb7bSPoul-Henning Kamp .vop_default = &default_vnodeops, 83972b3e305SPeter Edwards .vop_open = cd9660_open, 840aec0fb7bSPoul-Henning Kamp .vop_access = cd9660_access, 841aec0fb7bSPoul-Henning Kamp .vop_bmap = cd9660_bmap, 842aec0fb7bSPoul-Henning Kamp .vop_cachedlookup = cd9660_lookup, 843aec0fb7bSPoul-Henning Kamp .vop_getattr = cd9660_getattr, 844aec0fb7bSPoul-Henning Kamp .vop_inactive = cd9660_inactive, 845aec0fb7bSPoul-Henning Kamp .vop_ioctl = cd9660_ioctl, 846aec0fb7bSPoul-Henning Kamp .vop_lookup = vfs_cache_lookup, 847aec0fb7bSPoul-Henning Kamp .vop_pathconf = cd9660_pathconf, 848aec0fb7bSPoul-Henning Kamp .vop_read = cd9660_read, 849aec0fb7bSPoul-Henning Kamp .vop_readdir = cd9660_readdir, 850aec0fb7bSPoul-Henning Kamp .vop_readlink = cd9660_readlink, 851aec0fb7bSPoul-Henning Kamp .vop_reclaim = cd9660_reclaim, 852aec0fb7bSPoul-Henning Kamp .vop_setattr = cd9660_setattr, 853aec0fb7bSPoul-Henning Kamp .vop_strategy = cd9660_strategy, 85410bcafe9SPawel Jakub Dawidek .vop_vptofh = cd9660_vptofh, 855df8bae1dSRodney W. Grimes }; 856df8bae1dSRodney W. Grimes 857df8bae1dSRodney W. Grimes /* 858df8bae1dSRodney W. Grimes * Special device vnode ops 859df8bae1dSRodney W. Grimes */ 860df8bae1dSRodney W. Grimes 861aec0fb7bSPoul-Henning Kamp struct vop_vector cd9660_fifoops = { 862aec0fb7bSPoul-Henning Kamp .vop_default = &fifo_specops, 863aec0fb7bSPoul-Henning Kamp .vop_access = cd9660_access, 864aec0fb7bSPoul-Henning Kamp .vop_getattr = cd9660_getattr, 865aec0fb7bSPoul-Henning Kamp .vop_inactive = cd9660_inactive, 866aec0fb7bSPoul-Henning Kamp .vop_reclaim = cd9660_reclaim, 867aec0fb7bSPoul-Henning Kamp .vop_setattr = cd9660_setattr, 86810bcafe9SPawel Jakub Dawidek .vop_vptofh = cd9660_vptofh, 869df8bae1dSRodney W. Grimes }; 870