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> 479626b608SPoul-Henning Kamp #include <sys/bio.h> 48df8bae1dSRodney W. Grimes #include <sys/buf.h> 49df8bae1dSRodney W. Grimes #include <sys/mount.h> 50df8bae1dSRodney W. Grimes #include <sys/vnode.h> 5199d300a1SRuslan Ermilov #include <fs/fifofs/fifo.h> 52df8bae1dSRodney W. Grimes #include <sys/malloc.h> 53c90607baSBruce Evans #include <sys/dirent.h> 54996c772fSJohn Dyson #include <sys/unistd.h> 55cb2a8dffSSøren Schmidt #include <sys/filio.h> 56df8bae1dSRodney W. Grimes 57651ae11eSMike Smith #include <vm/vm.h> 58651ae11eSMike Smith #include <vm/vnode_pager.h> 592684b6afSJeff Roberson #include <vm/uma.h> 60675ea6f0SBruce Evans 61df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso.h> 62df8bae1dSRodney W. Grimes #include <isofs/cd9660/cd9660_node.h> 63df8bae1dSRodney W. Grimes #include <isofs/cd9660/iso_rrip.h> 64df8bae1dSRodney W. Grimes 6589c9a483SAlfred Perlstein static int cd9660_setattr(struct vop_setattr_args *); 6689c9a483SAlfred Perlstein static int cd9660_access(struct vop_access_args *); 6789c9a483SAlfred Perlstein static int cd9660_getattr(struct vop_getattr_args *); 6889c9a483SAlfred Perlstein static int cd9660_ioctl(struct vop_ioctl_args *); 6989c9a483SAlfred Perlstein static int cd9660_pathconf(struct vop_pathconf_args *); 7089c9a483SAlfred Perlstein static int cd9660_read(struct vop_read_args *); 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); 7489c9a483SAlfred Perlstein static int cd9660_readdir(struct vop_readdir_args *); 7589c9a483SAlfred Perlstein static int cd9660_readlink(struct vop_readlink_args *ap); 7689c9a483SAlfred Perlstein static int cd9660_strategy(struct vop_strategy_args *); 7710dd32cdSBruce Evans 78df8bae1dSRodney W. Grimes /* 79de8583ceSDavid Greenman * Setattr call. Only allowed for block and character special devices. 80de8583ceSDavid Greenman */ 8137c84183SPoul-Henning Kamp static int 82de8583ceSDavid Greenman cd9660_setattr(ap) 83de8583ceSDavid Greenman struct vop_setattr_args /* { 84de8583ceSDavid Greenman struct vnodeop_desc *a_desc; 85de8583ceSDavid Greenman struct vnode *a_vp; 86de8583ceSDavid Greenman struct vattr *a_vap; 87de8583ceSDavid Greenman struct ucred *a_cred; 88b40ce416SJulian Elischer struct thread *a_td; 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: 111de8583ceSDavid Greenman return (0); 112de8583ceSDavid Greenman } 113de8583ceSDavid Greenman } 114996c772fSJohn Dyson return (0); 115de8583ceSDavid Greenman } 116de8583ceSDavid Greenman 117de8583ceSDavid Greenman /* 118df8bae1dSRodney W. Grimes * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 119df8bae1dSRodney W. Grimes * The mode is shifted to select the owner/group/other fields. The 120df8bae1dSRodney W. Grimes * super user is granted all permissions. 121df8bae1dSRodney W. Grimes */ 122df8bae1dSRodney W. Grimes /* ARGSUSED */ 123605e9724SPoul-Henning Kamp static int 124df8bae1dSRodney W. Grimes cd9660_access(ap) 125df8bae1dSRodney W. Grimes struct vop_access_args /* { 126df8bae1dSRodney W. Grimes struct vnode *a_vp; 127df8bae1dSRodney W. Grimes int a_mode; 128df8bae1dSRodney W. Grimes struct ucred *a_cred; 129b40ce416SJulian Elischer struct thread *a_td; 130df8bae1dSRodney W. Grimes } */ *ap; 131df8bae1dSRodney W. Grimes { 132996c772fSJohn Dyson struct vnode *vp = ap->a_vp; 133996c772fSJohn Dyson struct iso_node *ip = VTOI(vp); 134e39c53edSPoul-Henning Kamp mode_t mode = ap->a_mode; 135996c772fSJohn Dyson 136ba14c327SDavid Greenman /* 137996c772fSJohn Dyson * Disallow write attempts unless the file is a socket, 138996c772fSJohn Dyson * fifo, or a block or character device resident on the 139996c772fSJohn Dyson * filesystem. 140ba14c327SDavid Greenman */ 141996c772fSJohn Dyson if (mode & VWRITE) { 142996c772fSJohn Dyson switch (vp->v_type) { 143ba14c327SDavid Greenman case VDIR: 144ba14c327SDavid Greenman case VLNK: 145ba14c327SDavid Greenman case VREG: 146ba14c327SDavid Greenman return (EROFS); 147d254af07SMatthew Dillon /* NOT REACHED */ 148d254af07SMatthew Dillon default: 149d254af07SMatthew Dillon break; 150ba14c327SDavid Greenman } 151ba14c327SDavid Greenman } 152ba14c327SDavid Greenman 153e39c53edSPoul-Henning Kamp return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid, 154012c643dSRobert Watson ip->inode.iso_gid, ap->a_mode, ap->a_cred, NULL)); 155df8bae1dSRodney W. Grimes } 156df8bae1dSRodney W. Grimes 157605e9724SPoul-Henning Kamp static int 158df8bae1dSRodney W. Grimes cd9660_getattr(ap) 159df8bae1dSRodney W. Grimes struct vop_getattr_args /* { 160df8bae1dSRodney W. Grimes struct vnode *a_vp; 161df8bae1dSRodney W. Grimes struct vattr *a_vap; 162df8bae1dSRodney W. Grimes struct ucred *a_cred; 163b40ce416SJulian Elischer struct thread *a_td; 164df8bae1dSRodney W. Grimes } */ *ap; 165df8bae1dSRodney W. Grimes 166df8bae1dSRodney W. Grimes { 167df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 168df8bae1dSRodney W. Grimes register struct vattr *vap = ap->a_vap; 169df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 170df8bae1dSRodney W. Grimes 171bfbb9ce6SPoul-Henning Kamp vap->va_fsid = dev2udev(ip->i_dev); 172fba2e610SBruce Evans 173fba2e610SBruce Evans /* 174fba2e610SBruce Evans * Don't use ip->i_ino for this since it is wrong for hard links. 175fba2e610SBruce Evans * ip->i_ino should be the same as ip->iso_start (or not exist), 176fba2e610SBruce Evans * but this currently doesn't work since we abuse it to look up 177fba2e610SBruce Evans * parent directories from inodes. 178fba2e610SBruce Evans */ 179fba2e610SBruce Evans vap->va_fileid = ip->iso_start; 180df8bae1dSRodney W. Grimes 181df8bae1dSRodney W. Grimes vap->va_mode = ip->inode.iso_mode; 182df8bae1dSRodney W. Grimes vap->va_nlink = ip->inode.iso_links; 183df8bae1dSRodney W. Grimes vap->va_uid = ip->inode.iso_uid; 184df8bae1dSRodney W. Grimes vap->va_gid = ip->inode.iso_gid; 185df8bae1dSRodney W. Grimes vap->va_atime = ip->inode.iso_atime; 186df8bae1dSRodney W. Grimes vap->va_mtime = ip->inode.iso_mtime; 187df8bae1dSRodney W. Grimes vap->va_ctime = ip->inode.iso_ctime; 188df8bae1dSRodney W. Grimes vap->va_rdev = ip->inode.iso_rdev; 189df8bae1dSRodney W. Grimes 190df8bae1dSRodney W. Grimes vap->va_size = (u_quad_t) ip->i_size; 191996c772fSJohn Dyson if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 192996c772fSJohn Dyson struct vop_readlink_args rdlnk; 193996c772fSJohn Dyson struct iovec aiov; 194996c772fSJohn Dyson struct uio auio; 195996c772fSJohn Dyson char *cp; 196996c772fSJohn Dyson 197996c772fSJohn Dyson MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 198996c772fSJohn Dyson aiov.iov_base = cp; 199996c772fSJohn Dyson aiov.iov_len = MAXPATHLEN; 200996c772fSJohn Dyson auio.uio_iov = &aiov; 201996c772fSJohn Dyson auio.uio_iovcnt = 1; 202996c772fSJohn Dyson auio.uio_offset = 0; 203996c772fSJohn Dyson auio.uio_rw = UIO_READ; 204996c772fSJohn Dyson auio.uio_segflg = UIO_SYSSPACE; 205b40ce416SJulian Elischer auio.uio_td = ap->a_td; 206996c772fSJohn Dyson auio.uio_resid = MAXPATHLEN; 207996c772fSJohn Dyson rdlnk.a_uio = &auio; 208996c772fSJohn Dyson rdlnk.a_vp = ap->a_vp; 209996c772fSJohn Dyson rdlnk.a_cred = ap->a_cred; 210996c772fSJohn Dyson if (cd9660_readlink(&rdlnk) == 0) 211996c772fSJohn Dyson vap->va_size = MAXPATHLEN - auio.uio_resid; 212996c772fSJohn Dyson FREE(cp, M_TEMP); 213996c772fSJohn Dyson } 214df8bae1dSRodney W. Grimes vap->va_flags = 0; 215df8bae1dSRodney W. Grimes vap->va_gen = 1; 216df8bae1dSRodney W. Grimes vap->va_blocksize = ip->i_mnt->logical_block_size; 217df8bae1dSRodney W. Grimes vap->va_bytes = (u_quad_t) ip->i_size; 218df8bae1dSRodney W. Grimes vap->va_type = vp->v_type; 21994a8606fSDoug Rabson vap->va_filerev = 0; 220df8bae1dSRodney W. Grimes return (0); 221df8bae1dSRodney W. Grimes } 222df8bae1dSRodney W. Grimes 223df8bae1dSRodney W. Grimes /* 224cb2a8dffSSøren Schmidt * Vnode op for ioctl. 225cb2a8dffSSøren Schmidt */ 226cb2a8dffSSøren Schmidt static int 227cb2a8dffSSøren Schmidt cd9660_ioctl(ap) 228cb2a8dffSSøren Schmidt struct vop_ioctl_args /* { 229cb2a8dffSSøren Schmidt struct vnode *a_vp; 230bc9d8a9aSPoul-Henning Kamp u_long a_command; 231cb2a8dffSSøren Schmidt caddr_t a_data; 232cb2a8dffSSøren Schmidt int a_fflag; 233cb2a8dffSSøren Schmidt struct ucred *a_cred; 234b40ce416SJulian Elischer struct thread *a_td; 235cb2a8dffSSøren Schmidt } */ *ap; 236cb2a8dffSSøren Schmidt { 237cb2a8dffSSøren Schmidt struct vnode *vp = ap->a_vp; 238cb2a8dffSSøren Schmidt struct iso_node *ip = VTOI(vp); 239cb2a8dffSSøren Schmidt 240cb2a8dffSSøren Schmidt switch (ap->a_command) { 241cb2a8dffSSøren Schmidt 242cb2a8dffSSøren Schmidt case FIOGETLBA: 243cb2a8dffSSøren Schmidt *(int *)(ap->a_data) = ip->iso_start; 244cb2a8dffSSøren Schmidt return 0; 245cb2a8dffSSøren Schmidt default: 246cb2a8dffSSøren Schmidt return (ENOTTY); 247cb2a8dffSSøren Schmidt } 248cb2a8dffSSøren Schmidt } 249cb2a8dffSSøren Schmidt 250cb2a8dffSSøren Schmidt /* 251df8bae1dSRodney W. Grimes * Vnode op for reading. 252df8bae1dSRodney W. Grimes */ 253605e9724SPoul-Henning Kamp static int 254df8bae1dSRodney W. Grimes cd9660_read(ap) 255df8bae1dSRodney W. Grimes struct vop_read_args /* { 256df8bae1dSRodney W. Grimes struct vnode *a_vp; 257df8bae1dSRodney W. Grimes struct uio *a_uio; 258df8bae1dSRodney W. Grimes int a_ioflag; 259df8bae1dSRodney W. Grimes struct ucred *a_cred; 260df8bae1dSRodney W. Grimes } */ *ap; 261df8bae1dSRodney W. Grimes { 262df8bae1dSRodney W. Grimes struct vnode *vp = ap->a_vp; 263df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 264df8bae1dSRodney W. Grimes register struct iso_node *ip = VTOI(vp); 265df8bae1dSRodney W. Grimes register struct iso_mnt *imp; 266df8bae1dSRodney W. Grimes struct buf *bp; 2671295d82eSGary Palmer daddr_t lbn, rablock; 268df8bae1dSRodney W. Grimes off_t diff; 269df8bae1dSRodney W. Grimes int rasize, error = 0; 27067ddfcafSMatthew Dillon int seqcount; 271df8bae1dSRodney W. Grimes long size, n, on; 272df8bae1dSRodney W. Grimes 27367ddfcafSMatthew Dillon seqcount = ap->a_ioflag >> 16; 27467ddfcafSMatthew Dillon 275df8bae1dSRodney W. Grimes if (uio->uio_resid == 0) 276df8bae1dSRodney W. Grimes return (0); 277df8bae1dSRodney W. Grimes if (uio->uio_offset < 0) 278df8bae1dSRodney W. Grimes return (EINVAL); 279996c772fSJohn Dyson ip->i_flag |= IN_ACCESS; 280df8bae1dSRodney W. Grimes imp = ip->i_mnt; 281df8bae1dSRodney W. Grimes do { 282996c772fSJohn Dyson lbn = lblkno(imp, uio->uio_offset); 283996c772fSJohn Dyson on = blkoff(imp, uio->uio_offset); 284996c772fSJohn Dyson n = min((u_int)(imp->logical_block_size - on), 285df8bae1dSRodney W. Grimes uio->uio_resid); 286df8bae1dSRodney W. Grimes diff = (off_t)ip->i_size - uio->uio_offset; 287df8bae1dSRodney W. Grimes if (diff <= 0) 288df8bae1dSRodney W. Grimes return (0); 289df8bae1dSRodney W. Grimes if (diff < n) 290df8bae1dSRodney W. Grimes n = diff; 291996c772fSJohn Dyson size = blksize(imp, ip, lbn); 292df8bae1dSRodney W. Grimes rablock = lbn + 1; 29381bca6ddSKATO Takenori if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 2945a5573fdSBruce Evans if (lblktosize(imp, rablock) < ip->i_size) 295996c772fSJohn Dyson error = cluster_read(vp, (off_t)ip->i_size, 2968b612c4bSJohn Dyson lbn, size, NOCRED, uio->uio_resid, 2978b612c4bSJohn Dyson (ap->a_ioflag >> 16), &bp); 298df8bae1dSRodney W. Grimes else 299df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 300df8bae1dSRodney W. Grimes } else { 30167ddfcafSMatthew Dillon if (seqcount > 1 && 302996c772fSJohn Dyson lblktosize(imp, rablock) < ip->i_size) { 303996c772fSJohn Dyson rasize = blksize(imp, ip, rablock); 304df8bae1dSRodney W. Grimes error = breadn(vp, lbn, size, &rablock, 305df8bae1dSRodney W. Grimes &rasize, 1, NOCRED, &bp); 306df8bae1dSRodney W. Grimes } else 307df8bae1dSRodney W. Grimes error = bread(vp, lbn, size, NOCRED, &bp); 308df8bae1dSRodney W. Grimes } 309df8bae1dSRodney W. Grimes n = min(n, size - bp->b_resid); 310df8bae1dSRodney W. Grimes if (error) { 311df8bae1dSRodney W. Grimes brelse(bp); 312df8bae1dSRodney W. Grimes return (error); 313df8bae1dSRodney W. Grimes } 314df8bae1dSRodney W. Grimes 315996c772fSJohn Dyson error = uiomove(bp->b_data + on, (int)n, uio); 316df8bae1dSRodney W. Grimes brelse(bp); 317df8bae1dSRodney W. Grimes } while (error == 0 && uio->uio_resid > 0 && n != 0); 318df8bae1dSRodney W. Grimes return (error); 319df8bae1dSRodney W. Grimes } 320df8bae1dSRodney W. Grimes 321df8bae1dSRodney W. Grimes /* 322df8bae1dSRodney W. Grimes * Structure for reading directories 323df8bae1dSRodney W. Grimes */ 324df8bae1dSRodney W. Grimes struct isoreaddir { 325df8bae1dSRodney W. Grimes struct dirent saveent; 326df8bae1dSRodney W. Grimes struct dirent assocent; 327df8bae1dSRodney W. Grimes struct dirent current; 328df8bae1dSRodney W. Grimes off_t saveoff; 329df8bae1dSRodney W. Grimes off_t assocoff; 330df8bae1dSRodney W. Grimes off_t curroff; 331df8bae1dSRodney W. Grimes struct uio *uio; 332df8bae1dSRodney W. Grimes off_t uio_off; 333996c772fSJohn Dyson int eofflag; 334996c772fSJohn Dyson u_long *cookies; 335df8bae1dSRodney W. Grimes int ncookies; 336df8bae1dSRodney W. Grimes }; 337df8bae1dSRodney W. Grimes 33837c84183SPoul-Henning Kamp static int 339df8bae1dSRodney W. Grimes iso_uiodir(idp,dp,off) 340df8bae1dSRodney W. Grimes struct isoreaddir *idp; 341df8bae1dSRodney W. Grimes struct dirent *dp; 342df8bae1dSRodney W. Grimes off_t off; 343df8bae1dSRodney W. Grimes { 344df8bae1dSRodney W. Grimes int error; 345df8bae1dSRodney W. Grimes 346df8bae1dSRodney W. Grimes dp->d_name[dp->d_namlen] = 0; 347c90607baSBruce Evans dp->d_reclen = GENERIC_DIRSIZ(dp); 348df8bae1dSRodney W. Grimes 349df8bae1dSRodney W. Grimes if (idp->uio->uio_resid < dp->d_reclen) { 350996c772fSJohn Dyson idp->eofflag = 0; 351996c772fSJohn Dyson return (-1); 352df8bae1dSRodney W. Grimes } 353df8bae1dSRodney W. Grimes 354996c772fSJohn Dyson if (idp->cookies) { 355df8bae1dSRodney W. Grimes if (idp->ncookies <= 0) { 356996c772fSJohn Dyson idp->eofflag = 0; 357996c772fSJohn Dyson return (-1); 358df8bae1dSRodney W. Grimes } 359df8bae1dSRodney W. Grimes 360996c772fSJohn Dyson *idp->cookies++ = off; 361df8bae1dSRodney W. Grimes --idp->ncookies; 362df8bae1dSRodney W. Grimes } 363df8bae1dSRodney W. Grimes 364d254af07SMatthew Dillon if ((error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) != 0) 365996c772fSJohn Dyson return (error); 366df8bae1dSRodney W. Grimes idp->uio_off = off; 367996c772fSJohn Dyson return (0); 368df8bae1dSRodney W. Grimes } 369df8bae1dSRodney W. Grimes 37037c84183SPoul-Henning Kamp static int 371df8bae1dSRodney W. Grimes iso_shipdir(idp) 372df8bae1dSRodney W. Grimes struct isoreaddir *idp; 373df8bae1dSRodney W. Grimes { 374df8bae1dSRodney W. Grimes struct dirent *dp; 375df8bae1dSRodney W. Grimes int cl, sl, assoc; 376df8bae1dSRodney W. Grimes int error; 377df8bae1dSRodney W. Grimes char *cname, *sname; 378df8bae1dSRodney W. Grimes 379df8bae1dSRodney W. Grimes cl = idp->current.d_namlen; 380df8bae1dSRodney W. Grimes cname = idp->current.d_name; 3811295d82eSGary Palmer assoc = (cl > 1) && (*cname == ASSOCCHAR); 3821295d82eSGary Palmer if (assoc) { 383df8bae1dSRodney W. Grimes cl--; 384df8bae1dSRodney W. Grimes cname++; 385df8bae1dSRodney W. Grimes } 386df8bae1dSRodney W. Grimes 387df8bae1dSRodney W. Grimes dp = &idp->saveent; 388df8bae1dSRodney W. Grimes sname = dp->d_name; 389df8bae1dSRodney W. Grimes if (!(sl = dp->d_namlen)) { 390df8bae1dSRodney W. Grimes dp = &idp->assocent; 391df8bae1dSRodney W. Grimes sname = dp->d_name + 1; 392df8bae1dSRodney W. Grimes sl = dp->d_namlen - 1; 393df8bae1dSRodney W. Grimes } 394df8bae1dSRodney W. Grimes if (sl > 0) { 395df8bae1dSRodney W. Grimes if (sl != cl 396df8bae1dSRodney W. Grimes || bcmp(sname,cname,sl)) { 397df8bae1dSRodney W. Grimes if (idp->assocent.d_namlen) { 398d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) 399996c772fSJohn Dyson return (error); 400df8bae1dSRodney W. Grimes idp->assocent.d_namlen = 0; 401df8bae1dSRodney W. Grimes } 402df8bae1dSRodney W. Grimes if (idp->saveent.d_namlen) { 403d254af07SMatthew Dillon if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) 404996c772fSJohn Dyson return (error); 405df8bae1dSRodney W. Grimes idp->saveent.d_namlen = 0; 406df8bae1dSRodney W. Grimes } 407df8bae1dSRodney W. Grimes } 408df8bae1dSRodney W. Grimes } 409c90607baSBruce Evans idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 410df8bae1dSRodney W. Grimes if (assoc) { 411df8bae1dSRodney W. Grimes idp->assocoff = idp->curroff; 412df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 413df8bae1dSRodney W. Grimes } else { 414df8bae1dSRodney W. Grimes idp->saveoff = idp->curroff; 415df8bae1dSRodney W. Grimes bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 416df8bae1dSRodney W. Grimes } 417996c772fSJohn Dyson return (0); 418df8bae1dSRodney W. Grimes } 419df8bae1dSRodney W. Grimes 420df8bae1dSRodney W. Grimes /* 421df8bae1dSRodney W. Grimes * Vnode op for readdir 422df8bae1dSRodney W. Grimes */ 423605e9724SPoul-Henning Kamp static int 424df8bae1dSRodney W. Grimes cd9660_readdir(ap) 425df8bae1dSRodney W. Grimes struct vop_readdir_args /* { 426df8bae1dSRodney W. Grimes struct vnode *a_vp; 427df8bae1dSRodney W. Grimes struct uio *a_uio; 428df8bae1dSRodney W. Grimes struct ucred *a_cred; 429996c772fSJohn Dyson int *a_eofflag; 430996c772fSJohn Dyson int *a_ncookies; 431996c772fSJohn Dyson u_long *a_cookies; 432df8bae1dSRodney W. Grimes } */ *ap; 433df8bae1dSRodney W. Grimes { 434df8bae1dSRodney W. Grimes register struct uio *uio = ap->a_uio; 435df8bae1dSRodney W. Grimes struct isoreaddir *idp; 436996c772fSJohn Dyson struct vnode *vdp = ap->a_vp; 437996c772fSJohn Dyson struct iso_node *dp; 438df8bae1dSRodney W. Grimes struct iso_mnt *imp; 439df8bae1dSRodney W. Grimes struct buf *bp = NULL; 440996c772fSJohn Dyson struct iso_directory_record *ep; 441996c772fSJohn Dyson int entryoffsetinblock; 442996c772fSJohn Dyson doff_t endsearch; 443996c772fSJohn Dyson u_long bmask; 444996c772fSJohn Dyson int error = 0; 445996c772fSJohn Dyson int reclen; 446996c772fSJohn Dyson u_short namelen; 4479abf4d6eSDoug Rabson int ncookies = 0; 448996c772fSJohn Dyson u_long *cookies = NULL; 449df8bae1dSRodney W. Grimes 450996c772fSJohn Dyson dp = VTOI(vdp); 451996c772fSJohn Dyson imp = dp->i_mnt; 452996c772fSJohn Dyson bmask = imp->im_bmask; 453df8bae1dSRodney W. Grimes 454df8bae1dSRodney W. Grimes MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 455996c772fSJohn Dyson idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 456996c772fSJohn Dyson /* 457996c772fSJohn Dyson * XXX 458996c772fSJohn Dyson * Is it worth trying to figure out the type? 459996c772fSJohn Dyson */ 460996c772fSJohn Dyson idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 461996c772fSJohn Dyson DT_UNKNOWN; 462df8bae1dSRodney W. Grimes idp->uio = uio; 463996c772fSJohn Dyson if (ap->a_ncookies == NULL) { 464996c772fSJohn Dyson idp->cookies = NULL; 465996c772fSJohn Dyson } else { 4669abf4d6eSDoug Rabson /* 4679abf4d6eSDoug Rabson * Guess the number of cookies needed. 4689abf4d6eSDoug Rabson */ 4699abf4d6eSDoug Rabson ncookies = uio->uio_resid / 16; 470996c772fSJohn Dyson MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 471996c772fSJohn Dyson M_WAITOK); 472996c772fSJohn Dyson idp->cookies = cookies; 473df8bae1dSRodney W. Grimes idp->ncookies = ncookies; 474996c772fSJohn Dyson } 475996c772fSJohn Dyson idp->eofflag = 1; 476df8bae1dSRodney W. Grimes idp->curroff = uio->uio_offset; 477df8bae1dSRodney W. Grimes 478996c772fSJohn Dyson if ((entryoffsetinblock = idp->curroff & bmask) && 479cec0f20cSPoul-Henning Kamp (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 480df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 481df8bae1dSRodney W. Grimes return (error); 482df8bae1dSRodney W. Grimes } 483996c772fSJohn Dyson endsearch = dp->i_size; 484df8bae1dSRodney W. Grimes 485df8bae1dSRodney W. Grimes while (idp->curroff < endsearch) { 486df8bae1dSRodney W. Grimes /* 487df8bae1dSRodney W. Grimes * If offset is on a block boundary, 488df8bae1dSRodney W. Grimes * read the next directory block. 489df8bae1dSRodney W. Grimes * Release previous if it exists. 490df8bae1dSRodney W. Grimes */ 491996c772fSJohn Dyson if ((idp->curroff & bmask) == 0) { 492df8bae1dSRodney W. Grimes if (bp != NULL) 493df8bae1dSRodney W. Grimes brelse(bp); 494d254af07SMatthew Dillon if ((error = 495d254af07SMatthew Dillon cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) 496df8bae1dSRodney W. Grimes break; 497df8bae1dSRodney W. Grimes entryoffsetinblock = 0; 498df8bae1dSRodney W. Grimes } 499df8bae1dSRodney W. Grimes /* 500df8bae1dSRodney W. Grimes * Get pointer to next entry. 501df8bae1dSRodney W. Grimes */ 502df8bae1dSRodney W. Grimes ep = (struct iso_directory_record *) 503996c772fSJohn Dyson ((char *)bp->b_data + entryoffsetinblock); 504df8bae1dSRodney W. Grimes 505df8bae1dSRodney W. Grimes reclen = isonum_711(ep->length); 506df8bae1dSRodney W. Grimes if (reclen == 0) { 507df8bae1dSRodney W. Grimes /* skip to next block, if any */ 508996c772fSJohn Dyson idp->curroff = 509996c772fSJohn Dyson (idp->curroff & ~bmask) + imp->logical_block_size; 510df8bae1dSRodney W. Grimes continue; 511df8bae1dSRodney W. Grimes } 512df8bae1dSRodney W. Grimes 513df8bae1dSRodney W. Grimes if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 514df8bae1dSRodney W. Grimes error = EINVAL; 515df8bae1dSRodney W. Grimes /* illegal entry, stop */ 516df8bae1dSRodney W. Grimes break; 517df8bae1dSRodney W. Grimes } 518df8bae1dSRodney W. Grimes 519df8bae1dSRodney W. Grimes if (entryoffsetinblock + reclen > imp->logical_block_size) { 520df8bae1dSRodney W. Grimes error = EINVAL; 521df8bae1dSRodney W. Grimes /* illegal directory, so stop looking */ 522df8bae1dSRodney W. Grimes break; 523df8bae1dSRodney W. Grimes } 524df8bae1dSRodney W. Grimes 525996c772fSJohn Dyson idp->current.d_namlen = isonum_711(ep->name_len); 526996c772fSJohn Dyson 527996c772fSJohn Dyson if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 52881ec856aSJoerg Wunsch error = EINVAL; 52981ec856aSJoerg Wunsch /* illegal entry, stop */ 53081ec856aSJoerg Wunsch break; 53181ec856aSJoerg Wunsch } 53281ec856aSJoerg Wunsch 533fba2e610SBruce Evans /* 534fba2e610SBruce Evans * The "inode number" is iso_start, not i_ino, as in 535fba2e610SBruce Evans * cd9660_getattr(). 536fba2e610SBruce Evans */ 537fba2e610SBruce Evans idp->current.d_fileno = isonum_711(ep->ext_attr_length) + 538fba2e610SBruce Evans isonum_733(ep->extent); 539df8bae1dSRodney W. Grimes 540df8bae1dSRodney W. Grimes idp->curroff += reclen; 541996c772fSJohn Dyson 542df8bae1dSRodney W. Grimes switch (imp->iso_ftype) { 543df8bae1dSRodney W. Grimes case ISO_FTYPE_RRIP: 544996c772fSJohn Dyson cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 545df8bae1dSRodney W. Grimes &idp->current.d_fileno,imp); 546996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 547df8bae1dSRodney W. Grimes if (idp->current.d_namlen) 548df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 549df8bae1dSRodney W. Grimes break; 550988fa8efSJoerg Wunsch default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 551df8bae1dSRodney W. Grimes strcpy(idp->current.d_name,".."); 55244e568e2SDaniel C. Sobral if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 553df8bae1dSRodney W. Grimes idp->current.d_namlen = 1; 554df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 55544e568e2SDaniel C. Sobral } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 556df8bae1dSRodney W. Grimes idp->current.d_namlen = 2; 557df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 55844e568e2SDaniel C. Sobral } else { 559df8bae1dSRodney W. Grimes isofntrans(ep->name,idp->current.d_namlen, 560996c772fSJohn Dyson idp->current.d_name, &namelen, 561df8bae1dSRodney W. Grimes imp->iso_ftype == ISO_FTYPE_9660, 56244e568e2SDaniel C. Sobral isonum_711(ep->flags)&4, 56344e568e2SDaniel C. Sobral imp->joliet_level); 564996c772fSJohn Dyson idp->current.d_namlen = (u_char)namelen; 565df8bae1dSRodney W. Grimes if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 566df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 567df8bae1dSRodney W. Grimes else 568df8bae1dSRodney W. Grimes error = iso_uiodir(idp,&idp->current,idp->curroff); 569df8bae1dSRodney W. Grimes } 570df8bae1dSRodney W. Grimes } 571df8bae1dSRodney W. Grimes if (error) 572df8bae1dSRodney W. Grimes break; 573df8bae1dSRodney W. Grimes 574df8bae1dSRodney W. Grimes entryoffsetinblock += reclen; 575df8bae1dSRodney W. Grimes } 576df8bae1dSRodney W. Grimes 577df8bae1dSRodney W. Grimes if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 578df8bae1dSRodney W. Grimes idp->current.d_namlen = 0; 579df8bae1dSRodney W. Grimes error = iso_shipdir(idp); 580df8bae1dSRodney W. Grimes } 581df8bae1dSRodney W. Grimes if (error < 0) 582df8bae1dSRodney W. Grimes error = 0; 583df8bae1dSRodney W. Grimes 5849abf4d6eSDoug Rabson if (ap->a_ncookies != NULL) { 5859abf4d6eSDoug Rabson if (error) 586996c772fSJohn Dyson free(cookies, M_TEMP); 5879abf4d6eSDoug Rabson else { 5889abf4d6eSDoug Rabson /* 5899abf4d6eSDoug Rabson * Work out the number of cookies actually used. 5909abf4d6eSDoug Rabson */ 5919abf4d6eSDoug Rabson *ap->a_ncookies = ncookies - idp->ncookies; 5929abf4d6eSDoug Rabson *ap->a_cookies = cookies; 5939abf4d6eSDoug Rabson } 5949abf4d6eSDoug Rabson } 5959abf4d6eSDoug Rabson 596df8bae1dSRodney W. Grimes if (bp) 597df8bae1dSRodney W. Grimes brelse (bp); 598df8bae1dSRodney W. Grimes 599df8bae1dSRodney W. Grimes uio->uio_offset = idp->uio_off; 600996c772fSJohn Dyson *ap->a_eofflag = idp->eofflag; 601df8bae1dSRodney W. Grimes 602df8bae1dSRodney W. Grimes FREE(idp, M_TEMP); 603df8bae1dSRodney W. Grimes 604df8bae1dSRodney W. Grimes return (error); 605df8bae1dSRodney W. Grimes } 606df8bae1dSRodney W. Grimes 607df8bae1dSRodney W. Grimes /* 608df8bae1dSRodney W. Grimes * Return target name of a symbolic link 609df8bae1dSRodney W. Grimes * Shouldn't we get the parent vnode and read the data from there? 610df8bae1dSRodney W. Grimes * This could eventually result in deadlocks in cd9660_lookup. 611df8bae1dSRodney W. Grimes * But otherwise the block read here is in the block buffer two times. 612df8bae1dSRodney W. Grimes */ 613df8bae1dSRodney W. Grimes typedef struct iso_directory_record ISODIR; 614df8bae1dSRodney W. Grimes typedef struct iso_node ISONODE; 615df8bae1dSRodney W. Grimes typedef struct iso_mnt ISOMNT; 616605e9724SPoul-Henning Kamp static int 617df8bae1dSRodney W. Grimes cd9660_readlink(ap) 618df8bae1dSRodney W. Grimes struct vop_readlink_args /* { 619df8bae1dSRodney W. Grimes struct vnode *a_vp; 620df8bae1dSRodney W. Grimes struct uio *a_uio; 621df8bae1dSRodney W. Grimes struct ucred *a_cred; 622df8bae1dSRodney W. Grimes } */ *ap; 623df8bae1dSRodney W. Grimes { 624df8bae1dSRodney W. Grimes ISONODE *ip; 625df8bae1dSRodney W. Grimes ISODIR *dirp; 626df8bae1dSRodney W. Grimes ISOMNT *imp; 627df8bae1dSRodney W. Grimes struct buf *bp; 628996c772fSJohn Dyson struct uio *uio; 629df8bae1dSRodney W. Grimes u_short symlen; 630df8bae1dSRodney W. Grimes int error; 631df8bae1dSRodney W. Grimes char *symname; 632df8bae1dSRodney W. Grimes 633df8bae1dSRodney W. Grimes ip = VTOI(ap->a_vp); 634df8bae1dSRodney W. Grimes imp = ip->i_mnt; 635996c772fSJohn Dyson uio = ap->a_uio; 636df8bae1dSRodney W. Grimes 637df8bae1dSRodney W. Grimes if (imp->iso_ftype != ISO_FTYPE_RRIP) 638996c772fSJohn Dyson return (EINVAL); 639df8bae1dSRodney W. Grimes 640df8bae1dSRodney W. Grimes /* 641df8bae1dSRodney W. Grimes * Get parents directory record block that this inode included. 642df8bae1dSRodney W. Grimes */ 643df8bae1dSRodney W. Grimes error = bread(imp->im_devvp, 644996c772fSJohn Dyson (ip->i_number >> imp->im_bshift) << 645996c772fSJohn Dyson (imp->im_bshift - DEV_BSHIFT), 646996c772fSJohn Dyson imp->logical_block_size, NOCRED, &bp); 647df8bae1dSRodney W. Grimes if (error) { 648df8bae1dSRodney W. Grimes brelse(bp); 649996c772fSJohn Dyson return (EINVAL); 650df8bae1dSRodney W. Grimes } 651df8bae1dSRodney W. Grimes 652df8bae1dSRodney W. Grimes /* 653df8bae1dSRodney W. Grimes * Setup the directory pointer for this inode 654df8bae1dSRodney W. Grimes */ 655996c772fSJohn Dyson dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 656df8bae1dSRodney W. Grimes 657df8bae1dSRodney W. Grimes /* 658df8bae1dSRodney W. Grimes * Just make sure, we have a right one.... 659df8bae1dSRodney W. Grimes * 1: Check not cross boundary on block 660df8bae1dSRodney W. Grimes */ 661df8bae1dSRodney W. Grimes if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 66292579404SAlexander Langer > (unsigned)imp->logical_block_size) { 663df8bae1dSRodney W. Grimes brelse(bp); 664996c772fSJohn Dyson return (EINVAL); 665df8bae1dSRodney W. Grimes } 666df8bae1dSRodney W. Grimes 667df8bae1dSRodney W. Grimes /* 668df8bae1dSRodney W. Grimes * Now get a buffer 669df8bae1dSRodney W. Grimes * Abuse a namei buffer for now. 670df8bae1dSRodney W. Grimes */ 671996c772fSJohn Dyson if (uio->uio_segflg == UIO_SYSSPACE) 672996c772fSJohn Dyson symname = uio->uio_iov->iov_base; 673996c772fSJohn Dyson else 6742684b6afSJeff Roberson symname = uma_zalloc(namei_zone, M_WAITOK); 675df8bae1dSRodney W. Grimes 676df8bae1dSRodney W. Grimes /* 677df8bae1dSRodney W. Grimes * Ok, we just gathering a symbolic name in SL record. 678df8bae1dSRodney W. Grimes */ 679df8bae1dSRodney W. Grimes if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 680996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) 6812684b6afSJeff Roberson uma_zfree(namei_zone, symname); 682df8bae1dSRodney W. Grimes brelse(bp); 683996c772fSJohn Dyson return (EINVAL); 684df8bae1dSRodney W. Grimes } 685df8bae1dSRodney W. Grimes /* 686df8bae1dSRodney W. Grimes * Don't forget before you leave from home ;-) 687df8bae1dSRodney W. Grimes */ 688df8bae1dSRodney W. Grimes brelse(bp); 689df8bae1dSRodney W. Grimes 690df8bae1dSRodney W. Grimes /* 691df8bae1dSRodney W. Grimes * return with the symbolic name to caller's. 692df8bae1dSRodney W. Grimes */ 693996c772fSJohn Dyson if (uio->uio_segflg != UIO_SYSSPACE) { 694996c772fSJohn Dyson error = uiomove(symname, symlen, uio); 6952684b6afSJeff Roberson uma_zfree(namei_zone, symname); 696996c772fSJohn Dyson return (error); 697996c772fSJohn Dyson } 698996c772fSJohn Dyson uio->uio_resid -= symlen; 6992b7f24d2SMike Barcroft uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 700996c772fSJohn Dyson uio->uio_iov->iov_len -= symlen; 701996c772fSJohn Dyson return (0); 702df8bae1dSRodney W. Grimes } 703df8bae1dSRodney W. Grimes 704df8bae1dSRodney W. Grimes /* 705df8bae1dSRodney W. Grimes * Calculate the logical to physical mapping if not done already, 706df8bae1dSRodney W. Grimes * then call the device strategy routine. 707df8bae1dSRodney W. Grimes */ 708605e9724SPoul-Henning Kamp static int 709df8bae1dSRodney W. Grimes cd9660_strategy(ap) 710df8bae1dSRodney W. Grimes struct vop_strategy_args /* { 711fd5d1124SJulian Elischer struct buf *a_vp; 712df8bae1dSRodney W. Grimes struct buf *a_bp; 713df8bae1dSRodney W. Grimes } */ *ap; 714df8bae1dSRodney W. Grimes { 715df8bae1dSRodney W. Grimes register struct buf *bp = ap->a_bp; 716df8bae1dSRodney W. Grimes register struct vnode *vp = bp->b_vp; 717df8bae1dSRodney W. Grimes register struct iso_node *ip; 718df8bae1dSRodney W. Grimes 719df8bae1dSRodney W. Grimes ip = VTOI(vp); 720df8bae1dSRodney W. Grimes if (vp->v_type == VBLK || vp->v_type == VCHR) 721df8bae1dSRodney W. Grimes panic("cd9660_strategy: spec"); 722df8bae1dSRodney W. Grimes if (bp->b_blkno == bp->b_lblkno) { 723e9d19a11SPoul-Henning Kamp bp->b_blkno = (ip->iso_start + bp->b_lblkno) << 724e9d19a11SPoul-Henning Kamp (ip->i_mnt->im_bshift - DEV_BSHIFT); 725e9d19a11SPoul-Henning Kamp if ((long)bp->b_blkno == -1) /* XXX: cut&paste junk ? */ 726df8bae1dSRodney W. Grimes clrbuf(bp); 727df8bae1dSRodney W. Grimes } 728e9d19a11SPoul-Henning Kamp if ((long)bp->b_blkno == -1) { /* XXX: cut&paste junk ? */ 7298177437dSPoul-Henning Kamp bufdone(bp); 730df8bae1dSRodney W. Grimes return (0); 731df8bae1dSRodney W. Grimes } 732df8bae1dSRodney W. Grimes vp = ip->i_devvp; 733df8bae1dSRodney W. Grimes bp->b_dev = vp->v_rdev; 734fd5d1124SJulian Elischer VOP_STRATEGY(vp, bp); 735df8bae1dSRodney W. Grimes return (0); 736df8bae1dSRodney W. Grimes } 737df8bae1dSRodney W. Grimes 738df8bae1dSRodney W. Grimes /* 739996c772fSJohn Dyson * Return POSIX pathconf information applicable to cd9660 filesystems. 740996c772fSJohn Dyson */ 741f041a9bdSPoul-Henning Kamp static int 742996c772fSJohn Dyson cd9660_pathconf(ap) 743996c772fSJohn Dyson struct vop_pathconf_args /* { 744996c772fSJohn Dyson struct vnode *a_vp; 745996c772fSJohn Dyson int a_name; 746996c772fSJohn Dyson register_t *a_retval; 747996c772fSJohn Dyson } */ *ap; 748996c772fSJohn Dyson { 749996c772fSJohn Dyson 750996c772fSJohn Dyson switch (ap->a_name) { 751996c772fSJohn Dyson case _PC_LINK_MAX: 752996c772fSJohn Dyson *ap->a_retval = 1; 753996c772fSJohn Dyson return (0); 754996c772fSJohn Dyson case _PC_NAME_MAX: 755996c772fSJohn Dyson if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 756996c772fSJohn Dyson *ap->a_retval = NAME_MAX; 757996c772fSJohn Dyson else 758996c772fSJohn Dyson *ap->a_retval = 37; 759996c772fSJohn Dyson return (0); 760996c772fSJohn Dyson case _PC_PATH_MAX: 761996c772fSJohn Dyson *ap->a_retval = PATH_MAX; 762996c772fSJohn Dyson return (0); 763996c772fSJohn Dyson case _PC_PIPE_BUF: 764996c772fSJohn Dyson *ap->a_retval = PIPE_BUF; 765996c772fSJohn Dyson return (0); 766996c772fSJohn Dyson case _PC_CHOWN_RESTRICTED: 767996c772fSJohn Dyson *ap->a_retval = 1; 768996c772fSJohn Dyson return (0); 769996c772fSJohn Dyson case _PC_NO_TRUNC: 770996c772fSJohn Dyson *ap->a_retval = 1; 771996c772fSJohn Dyson return (0); 772996c772fSJohn Dyson default: 773996c772fSJohn Dyson return (EINVAL); 774996c772fSJohn Dyson } 775996c772fSJohn Dyson /* NOTREACHED */ 776df8bae1dSRodney W. Grimes } 777df8bae1dSRodney W. Grimes 778df8bae1dSRodney W. Grimes /* 779996c772fSJohn Dyson * Global vfs data structures for cd9660 780df8bae1dSRodney W. Grimes */ 781f57e6547SBruce Evans vop_t **cd9660_vnodeop_p; 782f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 783dba3870cSPoul-Henning Kamp { &vop_default_desc, (vop_t *) vop_defaultop }, 784539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 785539ef70cSPoul-Henning Kamp { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 786539ef70cSPoul-Henning Kamp { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 787539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 788539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 789cb2a8dffSSøren Schmidt { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, 790d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 791d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 792539ef70cSPoul-Henning Kamp { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 793539ef70cSPoul-Henning Kamp { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 79486ed6d45SNate Lawson { &vop_print_desc, (vop_t *) vop_null }, 795539ef70cSPoul-Henning Kamp { &vop_read_desc, (vop_t *) cd9660_read }, 796539ef70cSPoul-Henning Kamp { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 797539ef70cSPoul-Henning Kamp { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 798539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 799539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 800539ef70cSPoul-Henning Kamp { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 801d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 802f57e6547SBruce Evans { NULL, NULL } 803df8bae1dSRodney W. Grimes }; 804605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 805df8bae1dSRodney W. Grimes { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 806c901836cSGarrett Wollman VNODEOP_SET(cd9660_vnodeop_opv_desc); 807df8bae1dSRodney W. Grimes 808df8bae1dSRodney W. Grimes /* 809df8bae1dSRodney W. Grimes * Special device vnode ops 810df8bae1dSRodney W. Grimes */ 811f57e6547SBruce Evans vop_t **cd9660_specop_p; 812f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 813138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) spec_vnoperate }, 814539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 815539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 816539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 817d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 818d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 81986ed6d45SNate Lawson { &vop_print_desc, (vop_t *) vop_null }, 820539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 821539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 822d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 823f57e6547SBruce Evans { NULL, NULL } 824df8bae1dSRodney W. Grimes }; 825605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_specop_opv_desc = 826df8bae1dSRodney W. Grimes { &cd9660_specop_p, cd9660_specop_entries }; 827c901836cSGarrett Wollman VNODEOP_SET(cd9660_specop_opv_desc); 828df8bae1dSRodney W. Grimes 829f57e6547SBruce Evans vop_t **cd9660_fifoop_p; 830f041a9bdSPoul-Henning Kamp static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 831138ec1f7SPoul-Henning Kamp { &vop_default_desc, (vop_t *) fifo_vnoperate }, 832539ef70cSPoul-Henning Kamp { &vop_access_desc, (vop_t *) cd9660_access }, 833539ef70cSPoul-Henning Kamp { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 834539ef70cSPoul-Henning Kamp { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 835d54d34b5SPoul-Henning Kamp { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 836d54d34b5SPoul-Henning Kamp { &vop_lock_desc, (vop_t *) vop_stdlock }, 83786ed6d45SNate Lawson { &vop_print_desc, (vop_t *) vop_null }, 838539ef70cSPoul-Henning Kamp { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 839539ef70cSPoul-Henning Kamp { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 840d54d34b5SPoul-Henning Kamp { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 841f57e6547SBruce Evans { NULL, NULL } 842df8bae1dSRodney W. Grimes }; 843605e9724SPoul-Henning Kamp static struct vnodeopv_desc cd9660_fifoop_opv_desc = 844df8bae1dSRodney W. Grimes { &cd9660_fifoop_p, cd9660_fifoop_entries }; 845c901836cSGarrett Wollman 846c901836cSGarrett Wollman VNODEOP_SET(cd9660_fifoop_opv_desc); 847