1*5a0ec814Smiod /* $OpenBSD: cd9660_vnops.c,v 1.97 2024/10/18 05:52:32 miod Exp $ */ 2053e05a2Sniklas /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /*- 5df930be7Sderaadt * Copyright (c) 1994 6df930be7Sderaadt * The Regents of the University of California. All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * This code is derived from software contributed to Berkeley 9df930be7Sderaadt * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 10df930be7Sderaadt * Support code is derived from software contributed to Berkeley 11df930be7Sderaadt * by Atsushi Murai (amurai@spec.co.jp). 12df930be7Sderaadt * 13df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 14df930be7Sderaadt * modification, are permitted provided that the following conditions 15df930be7Sderaadt * are met: 16df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 17df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 18df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 19df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 20df930be7Sderaadt * documentation and/or other materials provided with the distribution. 2129295d1cSmillert * 3. Neither the name of the University nor the names of its contributors 22df930be7Sderaadt * may be used to endorse or promote products derived from this software 23df930be7Sderaadt * without specific prior written permission. 24df930be7Sderaadt * 25df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35df930be7Sderaadt * SUCH DAMAGE. 36df930be7Sderaadt * 37df930be7Sderaadt * @(#)cd9660_vnops.c 8.15 (Berkeley) 12/5/94 38df930be7Sderaadt */ 39df930be7Sderaadt 40df930be7Sderaadt #include <sys/param.h> 41df930be7Sderaadt #include <sys/systm.h> 42df930be7Sderaadt #include <sys/namei.h> 43df930be7Sderaadt #include <sys/resourcevar.h> 44df930be7Sderaadt #include <sys/kernel.h> 45df930be7Sderaadt #include <sys/file.h> 46df930be7Sderaadt #include <sys/stat.h> 47df930be7Sderaadt #include <sys/buf.h> 48df930be7Sderaadt #include <sys/conf.h> 49df930be7Sderaadt #include <sys/mount.h> 50df930be7Sderaadt #include <sys/vnode.h> 51fde894e5Stedu #include <sys/lock.h> 52df930be7Sderaadt #include <sys/malloc.h> 53dbe27ba0Stedu #include <sys/pool.h> 540c0430f8Sniklas #include <sys/dirent.h> 55e6ab5f15Sangelos #include <sys/ioctl.h> 56e6ab5f15Sangelos #include <sys/ioccom.h> 57544451c3Sderaadt #include <sys/specdev.h> 58782ebdf8Stedu #include <sys/unistd.h> 59df930be7Sderaadt 60053e05a2Sniklas #include <miscfs/fifofs/fifo.h> 61053e05a2Sniklas 62df930be7Sderaadt #include <isofs/cd9660/iso.h> 63053e05a2Sniklas #include <isofs/cd9660/cd9660_extern.h> 64df930be7Sderaadt #include <isofs/cd9660/cd9660_node.h> 65df930be7Sderaadt #include <isofs/cd9660/iso_rrip.h> 66df930be7Sderaadt 67e04616ffStedu int cd9660_kqfilter(void *v); 68e04616ffStedu 69e04616ffStedu 709d71829cSniklas /* 719d71829cSniklas * Structure for reading directories 729d71829cSniklas */ 739d71829cSniklas struct isoreaddir { 749d71829cSniklas struct dirent saveent; 759d71829cSniklas struct dirent assocent; 769d71829cSniklas struct dirent current; 779d71829cSniklas off_t saveoff; 789d71829cSniklas off_t assocoff; 799d71829cSniklas off_t curroff; 809d71829cSniklas struct uio *uio; 819d71829cSniklas off_t uio_off; 829d71829cSniklas int eofflag; 839d71829cSniklas }; 849d71829cSniklas 85c4071fd1Smillert int iso_uiodir(struct isoreaddir *, struct dirent *, off_t); 86c4071fd1Smillert int iso_shipdir(struct isoreaddir *); 879d71829cSniklas 88df930be7Sderaadt /* 8907feb63cScsapuntz * Setattr call. Only allowed for block and character special devices. 9007feb63cScsapuntz */ 9107feb63cScsapuntz int 92edf63aa4Smatthew cd9660_setattr(void *v) 9307feb63cScsapuntz { 9499bc9d31Sderaadt struct vop_setattr_args *ap = v; 9507feb63cScsapuntz struct vnode *vp = ap->a_vp; 9607feb63cScsapuntz struct vattr *vap = ap->a_vap; 9707feb63cScsapuntz 9807feb63cScsapuntz if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 994707cbe3Sguenther vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_nsec != VNOVAL || 1004707cbe3Sguenther vap->va_mtime.tv_nsec != VNOVAL || vap->va_mode != (mode_t)VNOVAL || 1014707cbe3Sguenther (vap->va_vaflags & VA_UTIMES_CHANGE)) 10207feb63cScsapuntz return (EROFS); 10307feb63cScsapuntz if (vap->va_size != VNOVAL) { 10407feb63cScsapuntz switch (vp->v_type) { 10507feb63cScsapuntz case VDIR: 10607feb63cScsapuntz return (EISDIR); 10707feb63cScsapuntz case VLNK: 10807feb63cScsapuntz case VREG: 10907feb63cScsapuntz return (EROFS); 11007feb63cScsapuntz case VCHR: 11107feb63cScsapuntz case VBLK: 11207feb63cScsapuntz case VSOCK: 11307feb63cScsapuntz case VFIFO: 11407feb63cScsapuntz return (0); 11507feb63cScsapuntz default: 11607feb63cScsapuntz return (EINVAL); 11707feb63cScsapuntz } 11807feb63cScsapuntz } 11907feb63cScsapuntz 12007feb63cScsapuntz return (EINVAL); 12107feb63cScsapuntz } 12207feb63cScsapuntz 12307feb63cScsapuntz /* 124df930be7Sderaadt * Open called. 125df930be7Sderaadt * 126df930be7Sderaadt * Nothing to do. 127df930be7Sderaadt */ 128df930be7Sderaadt int 129edf63aa4Smatthew cd9660_open(void *v) 130df930be7Sderaadt { 131df930be7Sderaadt return (0); 132df930be7Sderaadt } 133df930be7Sderaadt 134df930be7Sderaadt /* 135df930be7Sderaadt * Close called 136df930be7Sderaadt * 137df930be7Sderaadt * Update the times on the inode on writeable file systems. 138df930be7Sderaadt */ 139df930be7Sderaadt int 140edf63aa4Smatthew cd9660_close(void *v) 141df930be7Sderaadt { 142df930be7Sderaadt return (0); 143df930be7Sderaadt } 144df930be7Sderaadt 145df930be7Sderaadt /* 146df930be7Sderaadt * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 147df930be7Sderaadt * The mode is shifted to select the owner/group/other fields. The 148df930be7Sderaadt * super user is granted all permissions. 149df930be7Sderaadt */ 150df930be7Sderaadt int 151edf63aa4Smatthew cd9660_access(void *v) 1529d71829cSniklas { 15399bc9d31Sderaadt struct vop_access_args *ap = v; 154df930be7Sderaadt struct iso_node *ip = VTOI(ap->a_vp); 155df930be7Sderaadt 156141c07a8Smillert return (vaccess(ap->a_vp->v_type, ip->inode.iso_mode & ALLPERMS, 157141c07a8Smillert ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred)); 158df930be7Sderaadt } 159df930be7Sderaadt 160df930be7Sderaadt int 161edf63aa4Smatthew cd9660_getattr(void *v) 1629d71829cSniklas { 16399bc9d31Sderaadt struct vop_getattr_args *ap = v; 164df930be7Sderaadt struct vnode *vp = ap->a_vp; 165b2acc587Sjsg struct vattr *vap = ap->a_vap; 166b2acc587Sjsg struct iso_node *ip = VTOI(vp); 167df930be7Sderaadt 168df930be7Sderaadt vap->va_fsid = ip->i_dev; 169df930be7Sderaadt vap->va_fileid = ip->i_number; 170df930be7Sderaadt 171053e05a2Sniklas vap->va_mode = ip->inode.iso_mode & ALLPERMS; 172df930be7Sderaadt vap->va_nlink = ip->inode.iso_links; 173df930be7Sderaadt vap->va_uid = ip->inode.iso_uid; 174df930be7Sderaadt vap->va_gid = ip->inode.iso_gid; 175df930be7Sderaadt vap->va_atime = ip->inode.iso_atime; 176df930be7Sderaadt vap->va_mtime = ip->inode.iso_mtime; 177df930be7Sderaadt vap->va_ctime = ip->inode.iso_ctime; 178df930be7Sderaadt vap->va_rdev = ip->inode.iso_rdev; 179df930be7Sderaadt 180df930be7Sderaadt vap->va_size = (u_quad_t) ip->i_size; 181053e05a2Sniklas if (ip->i_size == 0 && vp->v_type == VLNK) { 182df930be7Sderaadt struct vop_readlink_args rdlnk; 183df930be7Sderaadt struct iovec aiov; 184df930be7Sderaadt struct uio auio; 185df930be7Sderaadt char *cp; 186df930be7Sderaadt 187808d1e2bSchl cp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 188df930be7Sderaadt aiov.iov_base = cp; 189df930be7Sderaadt aiov.iov_len = MAXPATHLEN; 190df930be7Sderaadt auio.uio_iov = &aiov; 191df930be7Sderaadt auio.uio_iovcnt = 1; 192df930be7Sderaadt auio.uio_offset = 0; 193df930be7Sderaadt auio.uio_rw = UIO_READ; 194df930be7Sderaadt auio.uio_segflg = UIO_SYSSPACE; 195df930be7Sderaadt auio.uio_procp = ap->a_p; 196df930be7Sderaadt auio.uio_resid = MAXPATHLEN; 197df930be7Sderaadt rdlnk.a_uio = &auio; 198df930be7Sderaadt rdlnk.a_vp = ap->a_vp; 199df930be7Sderaadt rdlnk.a_cred = ap->a_cred; 200df930be7Sderaadt if (cd9660_readlink(&rdlnk) == 0) 201df930be7Sderaadt vap->va_size = MAXPATHLEN - auio.uio_resid; 2020e5ae731Stedu free(cp, M_TEMP, 0); 203df930be7Sderaadt } 204df930be7Sderaadt vap->va_flags = 0; 205df930be7Sderaadt vap->va_gen = 1; 206df930be7Sderaadt vap->va_blocksize = ip->i_mnt->logical_block_size; 207df930be7Sderaadt vap->va_bytes = (u_quad_t) ip->i_size; 208df930be7Sderaadt vap->va_type = vp->v_type; 209df930be7Sderaadt return (0); 210df930be7Sderaadt } 211df930be7Sderaadt 212df930be7Sderaadt /* 213df930be7Sderaadt * Vnode op for reading. 214df930be7Sderaadt */ 215df930be7Sderaadt int 216edf63aa4Smatthew cd9660_read(void *v) 2179d71829cSniklas { 21899bc9d31Sderaadt struct vop_read_args *ap = v; 219df930be7Sderaadt struct vnode *vp = ap->a_vp; 220b2acc587Sjsg struct uio *uio = ap->a_uio; 221b2acc587Sjsg struct iso_node *ip = VTOI(vp); 222b2acc587Sjsg struct iso_mnt *imp; 2231414b0faSart struct buf *bp; 2241abdbfdeSderaadt daddr_t lbn, rablock; 2251414b0faSart off_t diff; 2268de3a2c5Sart int error = 0; 227b52c98b0Sstefan long size, on; 228b52c98b0Sstefan size_t n; 229df930be7Sderaadt 230df930be7Sderaadt if (uio->uio_resid == 0) 231df930be7Sderaadt return (0); 232df930be7Sderaadt if (uio->uio_offset < 0) 233df930be7Sderaadt return (EINVAL); 234dd910b73Sart ip->i_flag |= IN_ACCESS; 2351414b0faSart imp = ip->i_mnt; 2361414b0faSart do { 2378de3a2c5Sart struct cluster_info *ci = &ip->i_ci; 2388de3a2c5Sart 2391414b0faSart lbn = lblkno(imp, uio->uio_offset); 2401414b0faSart on = blkoff(imp, uio->uio_offset); 241b52c98b0Sstefan n = ulmin(imp->logical_block_size - on, uio->uio_resid); 2421414b0faSart diff = (off_t)ip->i_size - uio->uio_offset; 2431414b0faSart if (diff <= 0) 2441414b0faSart return (0); 2451414b0faSart if (diff < n) 2461414b0faSart n = diff; 2471414b0faSart size = blksize(imp, ip, lbn); 2481414b0faSart rablock = lbn + 1; 2498de3a2c5Sart #define MAX_RA 32 2508de3a2c5Sart if (ci->ci_lastr + 1 == lbn) { 2518f6e076eSmickey struct ra { 2521abdbfdeSderaadt daddr_t blks[MAX_RA]; 2538f6e076eSmickey int sizes[MAX_RA]; 2548f6e076eSmickey } *ra; 2558de3a2c5Sart int i; 2568de3a2c5Sart 257808d1e2bSchl ra = malloc(sizeof *ra, M_TEMP, M_WAITOK); 2588de3a2c5Sart for (i = 0; i < MAX_RA && 2598de3a2c5Sart lblktosize(imp, (rablock + i)) < ip->i_size; 2608de3a2c5Sart i++) { 2618f6e076eSmickey ra->blks[i] = rablock + i; 2628f6e076eSmickey ra->sizes[i] = blksize(imp, ip, rablock + i); 2638de3a2c5Sart } 2648f6e076eSmickey error = breadn(vp, lbn, size, ra->blks, 26593f62a9eStedu ra->sizes, i, &bp); 2660e5ae731Stedu free(ra, M_TEMP, 0); 2671414b0faSart } else 26893f62a9eStedu error = bread(vp, lbn, size, &bp); 2698de3a2c5Sart ci->ci_lastr = lbn; 270b52c98b0Sstefan n = ulmin(n, size - bp->b_resid); 2711414b0faSart if (error) { 2721414b0faSart brelse(bp); 273dd910b73Sart return (error); 2745af79db2Sart } 2755af79db2Sart 276b52c98b0Sstefan error = uiomove(bp->b_data + on, n, uio); 2771414b0faSart 2781414b0faSart brelse(bp); 2791414b0faSart } while (error == 0 && uio->uio_resid > 0 && n != 0); 2801414b0faSart return (error); 281df930be7Sderaadt } 282df930be7Sderaadt 283df930be7Sderaadt int 284edf63aa4Smatthew cd9660_ioctl(void *v) 285df930be7Sderaadt { 286df930be7Sderaadt return (ENOTTY); 287df930be7Sderaadt } 288df930be7Sderaadt 289df930be7Sderaadt /* 290df930be7Sderaadt * Mmap a file 291df930be7Sderaadt * 292df930be7Sderaadt * NB Currently unsupported. 293df930be7Sderaadt */ 294df930be7Sderaadt int 295edf63aa4Smatthew cd9660_mmap(void *v) 296df930be7Sderaadt { 297df930be7Sderaadt 298df930be7Sderaadt return (EINVAL); 299df930be7Sderaadt } 300df930be7Sderaadt 301df930be7Sderaadt /* 302df930be7Sderaadt * Seek on a file 303df930be7Sderaadt * 304df930be7Sderaadt * Nothing to do, so just return. 305df930be7Sderaadt */ 306df930be7Sderaadt int 307edf63aa4Smatthew cd9660_seek(void *v) 308df930be7Sderaadt { 309df930be7Sderaadt return (0); 310df930be7Sderaadt } 311df930be7Sderaadt 312df930be7Sderaadt int 3131bf87d88Sjsg iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off) 314df930be7Sderaadt { 315df930be7Sderaadt int error; 316df930be7Sderaadt 317df930be7Sderaadt dp->d_name[dp->d_namlen] = 0; 3180c0430f8Sniklas dp->d_reclen = DIRENT_SIZE(dp); 319df930be7Sderaadt 32046f7109aSclaudio if (memchr(dp->d_name, '/', dp->d_namlen) != NULL) { 32146f7109aSclaudio /* illegal file name */ 32246f7109aSclaudio return (EINVAL); 32346f7109aSclaudio } 32446f7109aSclaudio 325df930be7Sderaadt if (idp->uio->uio_resid < dp->d_reclen) { 326df930be7Sderaadt idp->eofflag = 0; 327df930be7Sderaadt return (-1); 328df930be7Sderaadt } 329df930be7Sderaadt 33091a535ffSguenther dp->d_off = off; 331b52c98b0Sstefan if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0) 332df930be7Sderaadt return (error); 333df930be7Sderaadt idp->uio_off = off; 334df930be7Sderaadt return (0); 335df930be7Sderaadt } 336df930be7Sderaadt 337df930be7Sderaadt int 3381bf87d88Sjsg iso_shipdir(struct isoreaddir *idp) 339df930be7Sderaadt { 340df930be7Sderaadt struct dirent *dp; 341df930be7Sderaadt int cl, sl, assoc; 342df930be7Sderaadt int error; 343df930be7Sderaadt char *cname, *sname; 344df930be7Sderaadt 345df930be7Sderaadt cl = idp->current.d_namlen; 346df930be7Sderaadt cname = idp->current.d_name; 3479d71829cSniklas 348d724e01aSderaadt if ((assoc = cl > 1 && *cname == ASSOCCHAR)) { 349df930be7Sderaadt cl--; 350df930be7Sderaadt cname++; 351df930be7Sderaadt } 352df930be7Sderaadt 353df930be7Sderaadt dp = &idp->saveent; 354df930be7Sderaadt sname = dp->d_name; 355df930be7Sderaadt if (!(sl = dp->d_namlen)) { 356df930be7Sderaadt dp = &idp->assocent; 357df930be7Sderaadt sname = dp->d_name + 1; 358df930be7Sderaadt sl = dp->d_namlen - 1; 359df930be7Sderaadt } 360df930be7Sderaadt if (sl > 0) { 361df930be7Sderaadt if (sl != cl 362df930be7Sderaadt || bcmp(sname,cname,sl)) { 363df930be7Sderaadt if (idp->assocent.d_namlen) { 3649d71829cSniklas error = iso_uiodir(idp, &idp->assocent, 3659d71829cSniklas idp->assocoff); 3669d71829cSniklas if (error) 367df930be7Sderaadt return (error); 368df930be7Sderaadt idp->assocent.d_namlen = 0; 369df930be7Sderaadt } 370df930be7Sderaadt if (idp->saveent.d_namlen) { 3719d71829cSniklas error = iso_uiodir(idp, &idp->saveent, 3729d71829cSniklas idp->saveoff); 3739d71829cSniklas if (error) 374df930be7Sderaadt return (error); 375df930be7Sderaadt idp->saveent.d_namlen = 0; 376df930be7Sderaadt } 377df930be7Sderaadt } 378df930be7Sderaadt } 3790c0430f8Sniklas idp->current.d_reclen = DIRENT_SIZE(&idp->current); 380df930be7Sderaadt if (assoc) { 381df930be7Sderaadt idp->assocoff = idp->curroff; 382df930be7Sderaadt bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 383df930be7Sderaadt } else { 384df930be7Sderaadt idp->saveoff = idp->curroff; 385df930be7Sderaadt bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 386df930be7Sderaadt } 387df930be7Sderaadt return (0); 388df930be7Sderaadt } 389df930be7Sderaadt 390df930be7Sderaadt /* 391df930be7Sderaadt * Vnode op for readdir 392df930be7Sderaadt */ 393df930be7Sderaadt int 394edf63aa4Smatthew cd9660_readdir(void *v) 3959d71829cSniklas { 39699bc9d31Sderaadt struct vop_readdir_args *ap = v; 397b2acc587Sjsg struct uio *uio = ap->a_uio; 398df930be7Sderaadt struct isoreaddir *idp; 399df930be7Sderaadt struct vnode *vdp = ap->a_vp; 400df930be7Sderaadt struct iso_node *dp; 401df930be7Sderaadt struct iso_mnt *imp; 402df930be7Sderaadt struct buf *bp = NULL; 403df930be7Sderaadt struct iso_directory_record *ep; 404df930be7Sderaadt int entryoffsetinblock; 405df930be7Sderaadt doff_t endsearch; 406df930be7Sderaadt u_long bmask; 407df930be7Sderaadt int error = 0; 408df930be7Sderaadt int reclen; 409df930be7Sderaadt u_short namelen; 4100cad8b22Sguenther cdino_t ino; 411df930be7Sderaadt 412df930be7Sderaadt dp = VTOI(vdp); 413df930be7Sderaadt imp = dp->i_mnt; 414df930be7Sderaadt bmask = imp->im_bmask; 415df930be7Sderaadt 416808d1e2bSchl idp = malloc(sizeof(*idp), M_TEMP, M_WAITOK); 417ebee68f3Sguenther 418ebee68f3Sguenther /* 419ebee68f3Sguenther * These are passed to copyout(), so make sure there's no garbage 420ebee68f3Sguenther * being leaked in padding or after short names. 421ebee68f3Sguenther */ 422ebee68f3Sguenther memset(&idp->saveent, 0, sizeof(idp->saveent)); 423ebee68f3Sguenther memset(&idp->assocent, 0, sizeof(idp->assocent)); 424ebee68f3Sguenther memset(&idp->current, 0, sizeof(idp->current)); 425ebee68f3Sguenther 426df930be7Sderaadt /* 427df930be7Sderaadt * XXX 428df930be7Sderaadt * Is it worth trying to figure out the type? 429df930be7Sderaadt */ 430df930be7Sderaadt idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 431df930be7Sderaadt DT_UNKNOWN; 432df930be7Sderaadt idp->uio = uio; 433df930be7Sderaadt idp->eofflag = 1; 434df930be7Sderaadt idp->curroff = uio->uio_offset; 435c8609118Skrw idp->uio_off = uio->uio_offset; 436df930be7Sderaadt 437df930be7Sderaadt if ((entryoffsetinblock = idp->curroff & bmask) && 438574066a2Scsapuntz (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) { 4390e5ae731Stedu free(idp, M_TEMP, 0); 440df930be7Sderaadt return (error); 441df930be7Sderaadt } 442df930be7Sderaadt endsearch = dp->i_size; 443df930be7Sderaadt 444df930be7Sderaadt while (idp->curroff < endsearch) { 445df930be7Sderaadt /* 446df930be7Sderaadt * If offset is on a block boundary, 447df930be7Sderaadt * read the next directory block. 448df930be7Sderaadt * Release previous if it exists. 449df930be7Sderaadt */ 450df930be7Sderaadt if ((idp->curroff & bmask) == 0) { 451df930be7Sderaadt if (bp != NULL) 452df930be7Sderaadt brelse(bp); 453574066a2Scsapuntz error = cd9660_bufatoff(dp, (off_t)idp->curroff, 4549d71829cSniklas NULL, &bp); 4559d71829cSniklas if (error) 456df930be7Sderaadt break; 457df930be7Sderaadt entryoffsetinblock = 0; 458df930be7Sderaadt } 459df930be7Sderaadt /* 460df930be7Sderaadt * Get pointer to next entry. 461df930be7Sderaadt */ 462df930be7Sderaadt ep = (struct iso_directory_record *) 463df930be7Sderaadt ((char *)bp->b_data + entryoffsetinblock); 464df930be7Sderaadt 465df930be7Sderaadt reclen = isonum_711(ep->length); 466df930be7Sderaadt if (reclen == 0) { 467df930be7Sderaadt /* skip to next block, if any */ 468df930be7Sderaadt idp->curroff = 469df930be7Sderaadt (idp->curroff & ~bmask) + imp->logical_block_size; 470df930be7Sderaadt continue; 471df930be7Sderaadt } 472df930be7Sderaadt 473df930be7Sderaadt if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 474df930be7Sderaadt error = EINVAL; 475df930be7Sderaadt /* illegal entry, stop */ 476df930be7Sderaadt break; 477df930be7Sderaadt } 478df930be7Sderaadt 479df930be7Sderaadt if (entryoffsetinblock + reclen > imp->logical_block_size) { 480df930be7Sderaadt error = EINVAL; 481df930be7Sderaadt /* illegal directory, so stop looking */ 482df930be7Sderaadt break; 483df930be7Sderaadt } 484df930be7Sderaadt 485df930be7Sderaadt idp->current.d_namlen = isonum_711(ep->name_len); 486df930be7Sderaadt 487df930be7Sderaadt if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 488df930be7Sderaadt error = EINVAL; 489df930be7Sderaadt /* illegal entry, stop */ 490df930be7Sderaadt break; 491df930be7Sderaadt } 492df930be7Sderaadt 493df930be7Sderaadt if (isonum_711(ep->flags)&2) 4940cad8b22Sguenther ino = isodirino(ep, imp); 495df930be7Sderaadt else 4960cad8b22Sguenther ino = dbtob(bp->b_blkno) + entryoffsetinblock; 497df930be7Sderaadt 498df930be7Sderaadt idp->curroff += reclen; 499df930be7Sderaadt 500df930be7Sderaadt switch (imp->iso_ftype) { 501df930be7Sderaadt case ISO_FTYPE_RRIP: 502df930be7Sderaadt cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 5030cad8b22Sguenther &ino, imp); 5040cad8b22Sguenther idp->current.d_fileno = ino; 505df930be7Sderaadt idp->current.d_namlen = (u_char)namelen; 506df930be7Sderaadt if (idp->current.d_namlen) 507df930be7Sderaadt error = iso_uiodir(idp,&idp->current,idp->curroff); 508df930be7Sderaadt break; 509df930be7Sderaadt default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 5100cad8b22Sguenther idp->current.d_fileno = ino; 511e615ec19Sderaadt strlcpy(idp->current.d_name,"..", 512e615ec19Sderaadt sizeof idp->current.d_name); 51349f343b7Sd if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 514df930be7Sderaadt idp->current.d_namlen = 1; 515df930be7Sderaadt error = iso_uiodir(idp,&idp->current,idp->curroff); 51649f343b7Sd } else if (idp->current.d_namlen == 1 && 51749f343b7Sd ep->name[0] == 1) { 518df930be7Sderaadt idp->current.d_namlen = 2; 519df930be7Sderaadt error = iso_uiodir(idp,&idp->current,idp->curroff); 52049f343b7Sd } else { 521df930be7Sderaadt isofntrans(ep->name,idp->current.d_namlen, 522df930be7Sderaadt idp->current.d_name, &namelen, 523df930be7Sderaadt imp->iso_ftype == ISO_FTYPE_9660, 52449f343b7Sd isonum_711(ep->flags) & 4, 52549f343b7Sd imp->joliet_level); 526df930be7Sderaadt idp->current.d_namlen = (u_char)namelen; 527df930be7Sderaadt if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 528df930be7Sderaadt error = iso_shipdir(idp); 529df930be7Sderaadt else 530df930be7Sderaadt error = iso_uiodir(idp,&idp->current,idp->curroff); 531df930be7Sderaadt } 532df930be7Sderaadt } 533df930be7Sderaadt if (error) 534df930be7Sderaadt break; 535df930be7Sderaadt 536df930be7Sderaadt entryoffsetinblock += reclen; 537df930be7Sderaadt } 538df930be7Sderaadt 539df930be7Sderaadt if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 540df930be7Sderaadt idp->current.d_namlen = 0; 541df930be7Sderaadt error = iso_shipdir(idp); 542df930be7Sderaadt } 543df930be7Sderaadt if (error < 0) 544df930be7Sderaadt error = 0; 545df930be7Sderaadt 546df930be7Sderaadt if (bp) 547df930be7Sderaadt brelse (bp); 548df930be7Sderaadt 549df930be7Sderaadt uio->uio_offset = idp->uio_off; 550df930be7Sderaadt *ap->a_eofflag = idp->eofflag; 551df930be7Sderaadt 5520e5ae731Stedu free(idp, M_TEMP, 0); 553df930be7Sderaadt 554df930be7Sderaadt return (error); 555df930be7Sderaadt } 556df930be7Sderaadt 557df930be7Sderaadt /* 558df930be7Sderaadt * Return target name of a symbolic link 559df930be7Sderaadt * Shouldn't we get the parent vnode and read the data from there? 560df930be7Sderaadt * This could eventually result in deadlocks in cd9660_lookup. 561df930be7Sderaadt * But otherwise the block read here is in the block buffer two times. 562df930be7Sderaadt */ 563df930be7Sderaadt typedef struct iso_directory_record ISODIR; 564df930be7Sderaadt typedef struct iso_node ISONODE; 565df930be7Sderaadt typedef struct iso_mnt ISOMNT; 566df930be7Sderaadt int 567edf63aa4Smatthew cd9660_readlink(void *v) 5689d71829cSniklas { 56999bc9d31Sderaadt struct vop_readlink_args *ap = v; 570df930be7Sderaadt ISONODE *ip; 571df930be7Sderaadt ISODIR *dirp; 572df930be7Sderaadt ISOMNT *imp; 573df930be7Sderaadt struct buf *bp; 574df930be7Sderaadt struct uio *uio; 575df930be7Sderaadt u_short symlen; 576df930be7Sderaadt int error; 577df930be7Sderaadt char *symname; 578df930be7Sderaadt 579df930be7Sderaadt ip = VTOI(ap->a_vp); 580df930be7Sderaadt imp = ip->i_mnt; 581df930be7Sderaadt uio = ap->a_uio; 582df930be7Sderaadt 583df930be7Sderaadt if (imp->iso_ftype != ISO_FTYPE_RRIP) 584df930be7Sderaadt return (EINVAL); 585df930be7Sderaadt 586df930be7Sderaadt /* 587df930be7Sderaadt * Get parents directory record block that this inode included. 588df930be7Sderaadt */ 589df930be7Sderaadt error = bread(imp->im_devvp, 590df930be7Sderaadt (ip->i_number >> imp->im_bshift) << 591df930be7Sderaadt (imp->im_bshift - DEV_BSHIFT), 59293f62a9eStedu imp->logical_block_size, &bp); 593df930be7Sderaadt if (error) { 594df930be7Sderaadt brelse(bp); 595df930be7Sderaadt return (EINVAL); 596df930be7Sderaadt } 597df930be7Sderaadt 598df930be7Sderaadt /* 599df930be7Sderaadt * Setup the directory pointer for this inode 600df930be7Sderaadt */ 601df930be7Sderaadt dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 602df930be7Sderaadt 603df930be7Sderaadt /* 604df930be7Sderaadt * Just make sure, we have a right one.... 605df930be7Sderaadt * 1: Check not cross boundary on block 606df930be7Sderaadt */ 607df930be7Sderaadt if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 608df930be7Sderaadt > imp->logical_block_size) { 609df930be7Sderaadt brelse(bp); 610df930be7Sderaadt return (EINVAL); 611df930be7Sderaadt } 612df930be7Sderaadt 613df930be7Sderaadt /* 614df930be7Sderaadt * Now get a buffer 615df930be7Sderaadt * Abuse a namei buffer for now. 616df930be7Sderaadt */ 6178c4185c5Stdeval if (uio->uio_segflg == UIO_SYSSPACE && 6188c4185c5Stdeval uio->uio_iov->iov_len >= MAXPATHLEN) 619df930be7Sderaadt symname = uio->uio_iov->iov_base; 620df930be7Sderaadt else 621dbe27ba0Stedu symname = pool_get(&namei_pool, PR_WAITOK); 622df930be7Sderaadt 623df930be7Sderaadt /* 624df930be7Sderaadt * Ok, we just gathering a symbolic name in SL record. 625df930be7Sderaadt */ 626df930be7Sderaadt if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 6278c4185c5Stdeval if (uio->uio_segflg != UIO_SYSSPACE || 628d293fc99Stdeval uio->uio_iov->iov_len < MAXPATHLEN) 629dbe27ba0Stedu pool_put(&namei_pool, symname); 630df930be7Sderaadt brelse(bp); 631df930be7Sderaadt return (EINVAL); 632df930be7Sderaadt } 633df930be7Sderaadt /* 634df930be7Sderaadt * Don't forget before you leave from home ;-) 635df930be7Sderaadt */ 636df930be7Sderaadt brelse(bp); 637df930be7Sderaadt 638df930be7Sderaadt /* 639df930be7Sderaadt * return with the symbolic name to caller's. 640df930be7Sderaadt */ 6418c4185c5Stdeval if (uio->uio_segflg != UIO_SYSSPACE || 6428c4185c5Stdeval uio->uio_iov->iov_len < MAXPATHLEN) { 643b52c98b0Sstefan error = uiomove(symname, symlen, uio); 644dbe27ba0Stedu pool_put(&namei_pool, symname); 645df930be7Sderaadt return (error); 646df930be7Sderaadt } 647df930be7Sderaadt uio->uio_resid -= symlen; 648ab8fb65aSgrange uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 649df930be7Sderaadt uio->uio_iov->iov_len -= symlen; 650df930be7Sderaadt return (0); 651df930be7Sderaadt } 652df930be7Sderaadt 6539d71829cSniklas int 654edf63aa4Smatthew cd9660_link(void *v) 6559d71829cSniklas { 65699bc9d31Sderaadt struct vop_link_args *ap = v; 6579d71829cSniklas 6589d71829cSniklas VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 6599d71829cSniklas vput(ap->a_dvp); 6609d71829cSniklas return (EROFS); 6619d71829cSniklas } 6629d71829cSniklas 6639d71829cSniklas int 664edf63aa4Smatthew cd9660_symlink(void *v) 6659d71829cSniklas { 66699bc9d31Sderaadt struct vop_symlink_args *ap = v; 6679d71829cSniklas 6689d71829cSniklas VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 6699d71829cSniklas vput(ap->a_dvp); 6709d71829cSniklas return (EROFS); 6719d71829cSniklas } 6729d71829cSniklas 673df930be7Sderaadt /* 674df930be7Sderaadt * Lock an inode. 675df930be7Sderaadt */ 676df930be7Sderaadt int 677edf63aa4Smatthew cd9660_lock(void *v) 6789d71829cSniklas { 67999bc9d31Sderaadt struct vop_lock_args *ap = v; 68007feb63cScsapuntz struct vnode *vp = ap->a_vp; 681df930be7Sderaadt 68226b8ec94Snatano return rrw_enter(&VTOI(vp)->i_lock, ap->a_flags & LK_RWFLAGS); 683df930be7Sderaadt } 684df930be7Sderaadt 685df930be7Sderaadt /* 686df930be7Sderaadt * Unlock an inode. 687df930be7Sderaadt */ 688df930be7Sderaadt int 689edf63aa4Smatthew cd9660_unlock(void *v) 6909d71829cSniklas { 69199bc9d31Sderaadt struct vop_unlock_args *ap = v; 69207feb63cScsapuntz struct vnode *vp = ap->a_vp; 693df930be7Sderaadt 69426b8ec94Snatano rrw_exit(&VTOI(vp)->i_lock); 69526b8ec94Snatano return 0; 696df930be7Sderaadt } 697df930be7Sderaadt 698df930be7Sderaadt /* 699df930be7Sderaadt * Calculate the logical to physical mapping if not done already, 700df930be7Sderaadt * then call the device strategy routine. 701df930be7Sderaadt */ 702df930be7Sderaadt int 703edf63aa4Smatthew cd9660_strategy(void *v) 7049d71829cSniklas { 70599bc9d31Sderaadt struct vop_strategy_args *ap = v; 7068235abd6Sart struct buf *bp = ap->a_bp; 7078235abd6Sart struct vnode *vp = bp->b_vp; 7088235abd6Sart struct iso_node *ip; 709df930be7Sderaadt int error; 7108235abd6Sart int s; 711df930be7Sderaadt 712df930be7Sderaadt ip = VTOI(vp); 713df930be7Sderaadt if (vp->v_type == VBLK || vp->v_type == VCHR) 714df930be7Sderaadt panic("cd9660_strategy: spec"); 715df930be7Sderaadt if (bp->b_blkno == bp->b_lblkno) { 7169d71829cSniklas error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 7179d71829cSniklas if (error) { 718df930be7Sderaadt bp->b_error = error; 719df930be7Sderaadt bp->b_flags |= B_ERROR; 7208235abd6Sart s = splbio(); 721df930be7Sderaadt biodone(bp); 7228235abd6Sart splx(s); 723df930be7Sderaadt return (error); 724df930be7Sderaadt } 725df930be7Sderaadt if ((long)bp->b_blkno == -1) 726df930be7Sderaadt clrbuf(bp); 727df930be7Sderaadt } 728df930be7Sderaadt if ((long)bp->b_blkno == -1) { 7298235abd6Sart s = splbio(); 730df930be7Sderaadt biodone(bp); 7318235abd6Sart splx(s); 732df930be7Sderaadt return (0); 733df930be7Sderaadt } 734df930be7Sderaadt vp = ip->i_devvp; 735df930be7Sderaadt bp->b_dev = vp->v_rdev; 736f1993be3Svisa VOP_STRATEGY(vp, bp); 737df930be7Sderaadt return (0); 738df930be7Sderaadt } 739df930be7Sderaadt 740df930be7Sderaadt /* 741df930be7Sderaadt * Print out the contents of an inode. 742df930be7Sderaadt */ 743df930be7Sderaadt int 744edf63aa4Smatthew cd9660_print(void *v) 745df930be7Sderaadt { 746*5a0ec814Smiod #if defined(DEBUG) || defined(DIAGNOSTIC) || defined(VFSLCKDEBUG) 747df930be7Sderaadt printf("tag VT_ISOFS, isofs vnode\n"); 748*5a0ec814Smiod #endif 749df930be7Sderaadt return (0); 750df930be7Sderaadt } 751df930be7Sderaadt 752df930be7Sderaadt /* 753df930be7Sderaadt * Check for a locked inode. 754df930be7Sderaadt */ 755df930be7Sderaadt int 756edf63aa4Smatthew cd9660_islocked(void *v) 7579d71829cSniklas { 75899bc9d31Sderaadt struct vop_islocked_args *ap = v; 759df930be7Sderaadt 76026b8ec94Snatano return rrw_status(&VTOI(ap->a_vp)->i_lock); 761df930be7Sderaadt } 762df930be7Sderaadt 763df930be7Sderaadt /* 764df930be7Sderaadt * Return POSIX pathconf information applicable to cd9660 filesystems. 765df930be7Sderaadt */ 766df930be7Sderaadt int 767edf63aa4Smatthew cd9660_pathconf(void *v) 7689d71829cSniklas { 76999bc9d31Sderaadt struct vop_pathconf_args *ap = v; 77017497195Sbrad int error = 0; 77117497195Sbrad 772df930be7Sderaadt switch (ap->a_name) { 773df930be7Sderaadt case _PC_LINK_MAX: 774df930be7Sderaadt *ap->a_retval = 1; 77517497195Sbrad break; 776df930be7Sderaadt case _PC_NAME_MAX: 777df930be7Sderaadt if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 778df930be7Sderaadt *ap->a_retval = NAME_MAX; 779df930be7Sderaadt else 780df930be7Sderaadt *ap->a_retval = 37; 78117497195Sbrad break; 782df930be7Sderaadt case _PC_CHOWN_RESTRICTED: 783df930be7Sderaadt *ap->a_retval = 1; 78417497195Sbrad break; 785df930be7Sderaadt case _PC_NO_TRUNC: 786df930be7Sderaadt *ap->a_retval = 1; 78717497195Sbrad break; 788d4648cd6Sguenther case _PC_TIMESTAMP_RESOLUTION: 789d4648cd6Sguenther *ap->a_retval = 1000000000; /* one billion nanoseconds */ 790d4648cd6Sguenther break; 791df930be7Sderaadt default: 79217497195Sbrad error = EINVAL; 79317497195Sbrad break; 794df930be7Sderaadt } 79517497195Sbrad 79617497195Sbrad return (error); 797df930be7Sderaadt } 798df930be7Sderaadt 799df930be7Sderaadt /* 800df930be7Sderaadt * Global vfs data structures for isofs 801df930be7Sderaadt */ 802df930be7Sderaadt 803dc81e71aSthib /* Global vfs data structures for cd9660. */ 8042d6b9e38Sclaudio const struct vops cd9660_vops = { 805dc81e71aSthib .vop_lookup = cd9660_lookup, 80641019245Ssemarie .vop_create = eopnotsupp, 80741019245Ssemarie .vop_mknod = eopnotsupp, 808dc81e71aSthib .vop_open = cd9660_open, 809dc81e71aSthib .vop_close = cd9660_close, 810dc81e71aSthib .vop_access = cd9660_access, 811dc81e71aSthib .vop_getattr = cd9660_getattr, 812dc81e71aSthib .vop_setattr = cd9660_setattr, 813dc81e71aSthib .vop_read = cd9660_read, 81441019245Ssemarie .vop_write = eopnotsupp, 815dc81e71aSthib .vop_ioctl = cd9660_ioctl, 816e04616ffStedu .vop_kqfilter = cd9660_kqfilter, 81741019245Ssemarie .vop_revoke = vop_generic_revoke, 81841019245Ssemarie .vop_fsync = nullop, 81941019245Ssemarie .vop_remove = eopnotsupp, 820dc81e71aSthib .vop_link = cd9660_link, 82141019245Ssemarie .vop_rename = eopnotsupp, 82241019245Ssemarie .vop_mkdir = eopnotsupp, 82341019245Ssemarie .vop_rmdir = eopnotsupp, 824dc81e71aSthib .vop_symlink = cd9660_symlink, 825dc81e71aSthib .vop_readdir = cd9660_readdir, 826dc81e71aSthib .vop_readlink = cd9660_readlink, 827dc81e71aSthib .vop_abortop = vop_generic_abortop, 828dc81e71aSthib .vop_inactive = cd9660_inactive, 829dc81e71aSthib .vop_reclaim = cd9660_reclaim, 830dc81e71aSthib .vop_lock = cd9660_lock, 831dc81e71aSthib .vop_unlock = cd9660_unlock, 832dc81e71aSthib .vop_bmap = cd9660_bmap, 833dc81e71aSthib .vop_strategy = cd9660_strategy, 834dc81e71aSthib .vop_print = cd9660_print, 835dc81e71aSthib .vop_islocked = cd9660_islocked, 836dc81e71aSthib .vop_pathconf = cd9660_pathconf, 83741019245Ssemarie .vop_advlock = eopnotsupp, 83841019245Ssemarie .vop_bwrite = vop_generic_bwrite, 839df930be7Sderaadt }; 840df930be7Sderaadt 841dc81e71aSthib /* Special device vnode ops */ 8422d6b9e38Sclaudio const struct vops cd9660_specvops = { 843dc81e71aSthib .vop_access = cd9660_access, 844dc81e71aSthib .vop_getattr = cd9660_getattr, 845dc81e71aSthib .vop_setattr = cd9660_setattr, 846dc81e71aSthib .vop_inactive = cd9660_inactive, 847dc81e71aSthib .vop_reclaim = cd9660_reclaim, 848dc81e71aSthib .vop_lock = cd9660_lock, 849dc81e71aSthib .vop_unlock = cd9660_unlock, 850dc81e71aSthib .vop_print = cd9660_print, 851dc81e71aSthib .vop_islocked = cd9660_islocked, 852dc81e71aSthib 853dc81e71aSthib /* XXX: Keep in sync with spec_vops. */ 854dc81e71aSthib .vop_lookup = vop_generic_lookup, 8559aafff14Ssemarie .vop_create = vop_generic_badop, 8569aafff14Ssemarie .vop_mknod = vop_generic_badop, 857dc81e71aSthib .vop_open = spec_open, 858dc81e71aSthib .vop_close = spec_close, 859dc81e71aSthib .vop_read = spec_read, 860dc81e71aSthib .vop_write = spec_write, 861dc81e71aSthib .vop_ioctl = spec_ioctl, 862dc81e71aSthib .vop_kqfilter = spec_kqfilter, 863dc81e71aSthib .vop_revoke = vop_generic_revoke, 864dc81e71aSthib .vop_fsync = spec_fsync, 8659aafff14Ssemarie .vop_remove = vop_generic_badop, 8669aafff14Ssemarie .vop_link = vop_generic_badop, 8679aafff14Ssemarie .vop_rename = vop_generic_badop, 8689aafff14Ssemarie .vop_mkdir = vop_generic_badop, 8699aafff14Ssemarie .vop_rmdir = vop_generic_badop, 8709aafff14Ssemarie .vop_symlink = vop_generic_badop, 8719aafff14Ssemarie .vop_readdir = vop_generic_badop, 8729aafff14Ssemarie .vop_readlink = vop_generic_badop, 8739aafff14Ssemarie .vop_abortop = vop_generic_badop, 874dc81e71aSthib .vop_bmap = vop_generic_bmap, 875dc81e71aSthib .vop_strategy = spec_strategy, 876dc81e71aSthib .vop_pathconf = spec_pathconf, 877dc81e71aSthib .vop_advlock = spec_advlock, 878dc81e71aSthib .vop_bwrite = vop_generic_bwrite, 879df930be7Sderaadt }; 880df930be7Sderaadt 881df930be7Sderaadt #ifdef FIFO 8822d6b9e38Sclaudio const struct vops cd9660_fifovops = { 883dc81e71aSthib .vop_access = cd9660_access, 884dc81e71aSthib .vop_getattr = cd9660_getattr, 885dc81e71aSthib .vop_setattr = cd9660_setattr, 886dc81e71aSthib .vop_inactive = cd9660_inactive, 887dc81e71aSthib .vop_reclaim = cd9660_reclaim, 888dc81e71aSthib .vop_lock = cd9660_lock, 889dc81e71aSthib .vop_unlock = cd9660_unlock, 890dc81e71aSthib .vop_print = cd9660_print, 891dc81e71aSthib .vop_islocked = cd9660_islocked, 892dc81e71aSthib .vop_bwrite = vop_generic_bwrite, 893dc81e71aSthib 894dc81e71aSthib /* XXX: Keep in sync with fifo_vops. */ 895dc81e71aSthib .vop_lookup = vop_generic_lookup, 8969aafff14Ssemarie .vop_create = vop_generic_badop, 8979aafff14Ssemarie .vop_mknod = vop_generic_badop, 898dc81e71aSthib .vop_open = fifo_open, 899dc81e71aSthib .vop_close = fifo_close, 900dc81e71aSthib .vop_read = fifo_read, 901dc81e71aSthib .vop_write = fifo_write, 902dc81e71aSthib .vop_ioctl = fifo_ioctl, 903dc81e71aSthib .vop_kqfilter = fifo_kqfilter, 904dc81e71aSthib .vop_revoke = vop_generic_revoke, 905dc81e71aSthib .vop_fsync = nullop, 9069aafff14Ssemarie .vop_remove = vop_generic_badop, 9079aafff14Ssemarie .vop_link = vop_generic_badop, 9089aafff14Ssemarie .vop_rename = vop_generic_badop, 9099aafff14Ssemarie .vop_mkdir = vop_generic_badop, 9109aafff14Ssemarie .vop_rmdir = vop_generic_badop, 9119aafff14Ssemarie .vop_symlink = vop_generic_badop, 9129aafff14Ssemarie .vop_readdir = vop_generic_badop, 9139aafff14Ssemarie .vop_readlink = vop_generic_badop, 9149aafff14Ssemarie .vop_abortop = vop_generic_badop, 915dc81e71aSthib .vop_bmap = vop_generic_bmap, 9169aafff14Ssemarie .vop_strategy = vop_generic_badop, 917dc81e71aSthib .vop_pathconf = fifo_pathconf, 918dc81e71aSthib .vop_advlock = fifo_advlock, 919df930be7Sderaadt }; 920df930be7Sderaadt #endif /* FIFO */ 921e04616ffStedu 922e04616ffStedu void filt_cd9660detach(struct knote *kn); 923e04616ffStedu int filt_cd9660read(struct knote *kn, long hint); 924e04616ffStedu int filt_cd9660write(struct knote *kn, long hint); 925e04616ffStedu int filt_cd9660vnode(struct knote *kn, long hint); 926e04616ffStedu 92794321eb4Svisa const struct filterops cd9660read_filtops = { 928b8213689Svisa .f_flags = FILTEROP_ISFD, 92994321eb4Svisa .f_attach = NULL, 93094321eb4Svisa .f_detach = filt_cd9660detach, 93194321eb4Svisa .f_event = filt_cd9660read, 93294321eb4Svisa }; 93394321eb4Svisa 93494321eb4Svisa const struct filterops cd9660write_filtops = { 935b8213689Svisa .f_flags = FILTEROP_ISFD, 93694321eb4Svisa .f_attach = NULL, 93794321eb4Svisa .f_detach = filt_cd9660detach, 93894321eb4Svisa .f_event = filt_cd9660write, 93994321eb4Svisa }; 94094321eb4Svisa 94194321eb4Svisa const struct filterops cd9660vnode_filtops = { 942b8213689Svisa .f_flags = FILTEROP_ISFD, 94394321eb4Svisa .f_attach = NULL, 94494321eb4Svisa .f_detach = filt_cd9660detach, 94594321eb4Svisa .f_event = filt_cd9660vnode, 94694321eb4Svisa }; 947e04616ffStedu 948e04616ffStedu int 949e04616ffStedu cd9660_kqfilter(void *v) 950e04616ffStedu { 951e04616ffStedu struct vop_kqfilter_args *ap = v; 952e04616ffStedu struct vnode *vp = ap->a_vp; 953e04616ffStedu struct knote *kn = ap->a_kn; 954e04616ffStedu 955e04616ffStedu switch (kn->kn_filter) { 956e04616ffStedu case EVFILT_READ: 957e04616ffStedu kn->kn_fop = &cd9660read_filtops; 958e04616ffStedu break; 959e04616ffStedu case EVFILT_WRITE: 960e04616ffStedu kn->kn_fop = &cd9660write_filtops; 961e04616ffStedu break; 962e04616ffStedu case EVFILT_VNODE: 963e04616ffStedu kn->kn_fop = &cd9660vnode_filtops; 964e04616ffStedu break; 965e04616ffStedu default: 966e04616ffStedu return (EINVAL); 967e04616ffStedu } 968e04616ffStedu 969e04616ffStedu kn->kn_hook = (caddr_t)vp; 970e04616ffStedu 971cc53a24cSmvs klist_insert_locked(&vp->v_klist, kn); 972e04616ffStedu 973e04616ffStedu return (0); 974e04616ffStedu } 975e04616ffStedu 976e04616ffStedu void 977e04616ffStedu filt_cd9660detach(struct knote *kn) 978e04616ffStedu { 979e04616ffStedu struct vnode *vp = (struct vnode *)kn->kn_hook; 980e04616ffStedu 981cc53a24cSmvs klist_remove_locked(&vp->v_klist, kn); 982e04616ffStedu } 983e04616ffStedu 984e04616ffStedu int 985e04616ffStedu filt_cd9660read(struct knote *kn, long hint) 986e04616ffStedu { 987e04616ffStedu struct vnode *vp = (struct vnode *)kn->kn_hook; 988e04616ffStedu struct iso_node *node = VTOI(vp); 989e04616ffStedu 990e04616ffStedu /* 991e04616ffStedu * filesystem is gone, so set the EOF flag and schedule 992e04616ffStedu * the knote for deletion. 993e04616ffStedu */ 994e04616ffStedu if (hint == NOTE_REVOKE) { 995e04616ffStedu kn->kn_flags |= (EV_EOF | EV_ONESHOT); 996e04616ffStedu return (1); 997e04616ffStedu } 998e04616ffStedu 999836f297bSanton kn->kn_data = node->i_size - foffset(kn->kn_fp); 1000e04616ffStedu if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { 1001e04616ffStedu kn->kn_fflags |= NOTE_EOF; 1002e04616ffStedu return (1); 1003e04616ffStedu } 1004e04616ffStedu 10056ecc0d7fSvisa if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) 10066e29a944Smpi return (1); 10076e29a944Smpi 1008e04616ffStedu return (kn->kn_data != 0); 1009e04616ffStedu } 1010e04616ffStedu 1011e04616ffStedu int 1012e04616ffStedu filt_cd9660write(struct knote *kn, long hint) 1013e04616ffStedu { 1014e04616ffStedu /* 1015e04616ffStedu * filesystem is gone, so set the EOF flag and schedule 1016e04616ffStedu * the knote for deletion. 1017e04616ffStedu */ 1018e04616ffStedu if (hint == NOTE_REVOKE) { 1019e04616ffStedu kn->kn_flags |= (EV_EOF | EV_ONESHOT); 1020e04616ffStedu return (1); 1021e04616ffStedu } 1022e04616ffStedu 1023e04616ffStedu kn->kn_data = 0; 1024e04616ffStedu return (1); 1025e04616ffStedu } 1026e04616ffStedu 1027e04616ffStedu int 1028e04616ffStedu filt_cd9660vnode(struct knote *kn, long hint) 1029e04616ffStedu { 1030e04616ffStedu if (kn->kn_sfflags & hint) 1031e04616ffStedu kn->kn_fflags |= hint; 1032e04616ffStedu if (hint == NOTE_REVOKE) { 1033e04616ffStedu kn->kn_flags |= EV_EOF; 1034e04616ffStedu return (1); 1035e04616ffStedu } 1036e04616ffStedu return (kn->kn_fflags != 0); 1037e04616ffStedu } 1038