1 1.63 christos /* $NetBSD: cd9660_vnops.c,v 1.63 2024/02/02 20:27:26 christos Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 1994 5 1.1 jdolecek * The Regents of the University of California. All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * This code is derived from software contributed to Berkeley 8 1.1 jdolecek * by Pace Willisson (pace (at) blitz.com). The Rock Ridge Extension 9 1.1 jdolecek * Support code is derived from software contributed to Berkeley 10 1.1 jdolecek * by Atsushi Murai (amurai (at) spec.co.jp). 11 1.1 jdolecek * 12 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 13 1.1 jdolecek * modification, are permitted provided that the following conditions 14 1.1 jdolecek * are met: 15 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 16 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 17 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 19 1.1 jdolecek * documentation and/or other materials provided with the distribution. 20 1.6 agc * 3. Neither the name of the University nor the names of its contributors 21 1.1 jdolecek * may be used to endorse or promote products derived from this software 22 1.1 jdolecek * without specific prior written permission. 23 1.1 jdolecek * 24 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.1 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.1 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.1 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.1 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.1 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.1 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.1 jdolecek * SUCH DAMAGE. 35 1.1 jdolecek * 36 1.1 jdolecek * @(#)cd9660_vnops.c 8.15 (Berkeley) 5/27/95 37 1.1 jdolecek */ 38 1.1 jdolecek 39 1.1 jdolecek #include <sys/cdefs.h> 40 1.63 christos __KERNEL_RCSID(0, "$NetBSD: cd9660_vnops.c,v 1.63 2024/02/02 20:27:26 christos Exp $"); 41 1.1 jdolecek 42 1.1 jdolecek #include <sys/param.h> 43 1.1 jdolecek #include <sys/systm.h> 44 1.1 jdolecek #include <sys/namei.h> 45 1.1 jdolecek #include <sys/resourcevar.h> 46 1.1 jdolecek #include <sys/kernel.h> 47 1.1 jdolecek #include <sys/file.h> 48 1.1 jdolecek #include <sys/stat.h> 49 1.1 jdolecek #include <sys/buf.h> 50 1.1 jdolecek #include <sys/proc.h> 51 1.1 jdolecek #include <sys/mount.h> 52 1.1 jdolecek #include <sys/vnode.h> 53 1.1 jdolecek #include <sys/malloc.h> 54 1.1 jdolecek #include <sys/dirent.h> 55 1.22 elad #include <sys/kauth.h> 56 1.1 jdolecek 57 1.1 jdolecek #include <miscfs/fifofs/fifo.h> 58 1.1 jdolecek #include <miscfs/genfs/genfs.h> 59 1.1 jdolecek #include <miscfs/specfs/specdev.h> 60 1.1 jdolecek 61 1.1 jdolecek #include <fs/cd9660/iso.h> 62 1.1 jdolecek #include <fs/cd9660/cd9660_extern.h> 63 1.1 jdolecek #include <fs/cd9660/cd9660_node.h> 64 1.63 christos #include <fs/cd9660/cd9660_mount.h> 65 1.1 jdolecek #include <fs/cd9660/iso_rrip.h> 66 1.1 jdolecek #include <fs/cd9660/cd9660_mount.h> 67 1.1 jdolecek 68 1.1 jdolecek /* 69 1.1 jdolecek * Structure for reading directories 70 1.1 jdolecek */ 71 1.1 jdolecek struct isoreaddir { 72 1.1 jdolecek struct dirent saveent; 73 1.1 jdolecek struct dirent assocent; 74 1.1 jdolecek struct dirent current; 75 1.1 jdolecek off_t saveoff; 76 1.1 jdolecek off_t assocoff; 77 1.1 jdolecek off_t curroff; 78 1.1 jdolecek struct uio *uio; 79 1.1 jdolecek off_t uio_off; 80 1.1 jdolecek int eofflag; 81 1.1 jdolecek off_t *cookies; 82 1.1 jdolecek int ncookies; 83 1.1 jdolecek }; 84 1.1 jdolecek 85 1.15 xtraeme int iso_uiodir(struct isoreaddir *, struct dirent *, off_t); 86 1.15 xtraeme int iso_shipdir(struct isoreaddir *); 87 1.1 jdolecek 88 1.38 elad static int 89 1.57 christos cd9660_check_possible(struct vnode *vp, struct iso_node *ip, accmode_t accmode) 90 1.38 elad { 91 1.38 elad 92 1.38 elad /* 93 1.38 elad * Disallow write attempts unless the file is a socket, 94 1.38 elad * fifo, or a block or character device resident on the 95 1.38 elad * file system. 96 1.38 elad */ 97 1.57 christos if (accmode & VWRITE) { 98 1.38 elad switch (vp->v_type) { 99 1.38 elad case VDIR: 100 1.38 elad case VLNK: 101 1.38 elad case VREG: 102 1.38 elad return (EROFS); 103 1.38 elad default: 104 1.38 elad break; 105 1.38 elad } 106 1.38 elad } 107 1.38 elad 108 1.38 elad return 0; 109 1.38 elad } 110 1.38 elad 111 1.1 jdolecek /* 112 1.1 jdolecek * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 113 1.1 jdolecek * The mode is shifted to select the owner/group/other fields. The 114 1.1 jdolecek * super user is granted all permissions. 115 1.1 jdolecek */ 116 1.38 elad static int 117 1.57 christos cd9660_check_permitted(struct vnode *vp, struct iso_node *ip, accmode_t accmode, 118 1.38 elad kauth_cred_t cred) 119 1.38 elad { 120 1.63 christos accmode_t file_mode; 121 1.63 christos uid_t uid; 122 1.63 christos gid_t gid; 123 1.63 christos 124 1.63 christos file_mode = ip->inode.iso_mode & ALLPERMS; 125 1.63 christos file_mode &= (vp->v_type == VDIR) ? ip->i_mnt->im_dmask : ip->i_mnt->im_fmask; 126 1.63 christos 127 1.63 christos uid = (ip->i_mnt->im_flags & ISOFSMNT_UID) ? 128 1.63 christos ip->i_mnt->im_uid : ip->inode.iso_uid; 129 1.63 christos gid = (ip->i_mnt->im_flags & ISOFSMNT_GID) ? 130 1.63 christos ip->i_mnt->im_gid : ip->inode.iso_gid; 131 1.38 elad 132 1.57 christos return kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(accmode, 133 1.63 christos vp->v_type, file_mode), vp, NULL, 134 1.63 christos genfs_can_access(vp, cred, uid, gid, 135 1.63 christos file_mode, NULL, accmode)); 136 1.38 elad } 137 1.38 elad 138 1.1 jdolecek int 139 1.33 matt cd9660_access(void *v) 140 1.1 jdolecek { 141 1.1 jdolecek struct vop_access_args /* { 142 1.1 jdolecek struct vnode *a_vp; 143 1.57 christos accmode_t a_accmode; 144 1.22 elad kauth_cred_t a_cred; 145 1.1 jdolecek } */ *ap = v; 146 1.1 jdolecek struct vnode *vp = ap->a_vp; 147 1.1 jdolecek struct iso_node *ip = VTOI(vp); 148 1.38 elad int error; 149 1.1 jdolecek 150 1.57 christos error = cd9660_check_possible(vp, ip, ap->a_accmode); 151 1.38 elad if (error) 152 1.38 elad return error; 153 1.38 elad 154 1.57 christos error = cd9660_check_permitted(vp, ip, ap->a_accmode, ap->a_cred); 155 1.1 jdolecek 156 1.38 elad return error; 157 1.1 jdolecek } 158 1.1 jdolecek 159 1.1 jdolecek int 160 1.33 matt cd9660_getattr(void *v) 161 1.1 jdolecek { 162 1.1 jdolecek struct vop_getattr_args /* { 163 1.1 jdolecek struct vnode *a_vp; 164 1.1 jdolecek struct vattr *a_vap; 165 1.22 elad kauth_cred_t a_cred; 166 1.1 jdolecek } */ *ap = v; 167 1.1 jdolecek struct vnode *vp = ap->a_vp; 168 1.1 jdolecek struct iso_node *ip = VTOI(vp); 169 1.1 jdolecek struct vattr *vap = ap->a_vap; 170 1.1 jdolecek 171 1.1 jdolecek vap->va_fsid = ip->i_dev; 172 1.1 jdolecek vap->va_fileid = ip->i_number; 173 1.1 jdolecek 174 1.1 jdolecek vap->va_mode = ip->inode.iso_mode & ALLPERMS; 175 1.63 christos vap->va_mode &= (vp->v_type == VDIR) ? ip->i_mnt->im_dmask : ip->i_mnt->im_fmask; 176 1.1 jdolecek vap->va_nlink = ip->inode.iso_links; 177 1.63 christos vap->va_uid = (ip->i_mnt->im_flags & ISOFSMNT_UID) ? 178 1.63 christos ip->i_mnt->im_uid : ip->inode.iso_uid; 179 1.63 christos vap->va_gid = (ip->i_mnt->im_flags & ISOFSMNT_GID) ? 180 1.63 christos ip->i_mnt->im_gid : ip->inode.iso_gid; 181 1.1 jdolecek vap->va_atime = ip->inode.iso_atime; 182 1.1 jdolecek vap->va_mtime = ip->inode.iso_mtime; 183 1.1 jdolecek vap->va_ctime = ip->inode.iso_ctime; 184 1.1 jdolecek vap->va_rdev = ip->inode.iso_rdev; 185 1.1 jdolecek 186 1.1 jdolecek vap->va_size = (u_quad_t) ip->i_size; 187 1.1 jdolecek if (ip->i_size == 0 && vp->v_type == VLNK) { 188 1.1 jdolecek struct vop_readlink_args rdlnk; 189 1.1 jdolecek struct iovec aiov; 190 1.1 jdolecek struct uio auio; 191 1.1 jdolecek char *cp; 192 1.1 jdolecek 193 1.36 cegger cp = (char *)malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 194 1.1 jdolecek aiov.iov_base = cp; 195 1.1 jdolecek aiov.iov_len = MAXPATHLEN; 196 1.1 jdolecek auio.uio_iov = &aiov; 197 1.1 jdolecek auio.uio_iovcnt = 1; 198 1.1 jdolecek auio.uio_offset = 0; 199 1.1 jdolecek auio.uio_rw = UIO_READ; 200 1.1 jdolecek auio.uio_resid = MAXPATHLEN; 201 1.20 yamt UIO_SETUP_SYSSPACE(&auio); 202 1.1 jdolecek rdlnk.a_uio = &auio; 203 1.1 jdolecek rdlnk.a_vp = ap->a_vp; 204 1.1 jdolecek rdlnk.a_cred = ap->a_cred; 205 1.1 jdolecek if (cd9660_readlink(&rdlnk) == 0) 206 1.1 jdolecek vap->va_size = MAXPATHLEN - auio.uio_resid; 207 1.36 cegger free(cp, M_TEMP); 208 1.1 jdolecek } 209 1.1 jdolecek vap->va_flags = 0; 210 1.1 jdolecek vap->va_gen = 1; 211 1.1 jdolecek vap->va_blocksize = ip->i_mnt->logical_block_size; 212 1.1 jdolecek vap->va_bytes = (u_quad_t) ip->i_size; 213 1.1 jdolecek vap->va_type = vp->v_type; 214 1.1 jdolecek return (0); 215 1.1 jdolecek } 216 1.1 jdolecek 217 1.1 jdolecek /* 218 1.1 jdolecek * Vnode op for reading. 219 1.1 jdolecek */ 220 1.1 jdolecek int 221 1.33 matt cd9660_read(void *v) 222 1.1 jdolecek { 223 1.1 jdolecek struct vop_read_args /* { 224 1.1 jdolecek struct vnode *a_vp; 225 1.1 jdolecek struct uio *a_uio; 226 1.1 jdolecek int a_ioflag; 227 1.22 elad kauth_cred_t a_cred; 228 1.1 jdolecek } */ *ap = v; 229 1.1 jdolecek struct vnode *vp = ap->a_vp; 230 1.1 jdolecek struct uio *uio = ap->a_uio; 231 1.1 jdolecek struct iso_node *ip = VTOI(vp); 232 1.1 jdolecek struct iso_mnt *imp; 233 1.1 jdolecek struct buf *bp; 234 1.1 jdolecek daddr_t lbn, rablock; 235 1.1 jdolecek off_t diff; 236 1.1 jdolecek int rasize, error = 0; 237 1.1 jdolecek long size, n, on; 238 1.1 jdolecek 239 1.1 jdolecek if (uio->uio_resid == 0) 240 1.1 jdolecek return (0); 241 1.1 jdolecek if (uio->uio_offset < 0) 242 1.1 jdolecek return (EINVAL); 243 1.1 jdolecek if (uio->uio_offset >= ip->i_size) 244 1.1 jdolecek return 0; 245 1.1 jdolecek ip->i_flag |= IN_ACCESS; 246 1.1 jdolecek imp = ip->i_mnt; 247 1.1 jdolecek 248 1.1 jdolecek if (vp->v_type == VREG) { 249 1.18 yamt const int advice = IO_ADV_DECODE(ap->a_ioflag); 250 1.1 jdolecek error = 0; 251 1.18 yamt 252 1.1 jdolecek while (uio->uio_resid > 0) { 253 1.1 jdolecek vsize_t bytelen = MIN(ip->i_size - uio->uio_offset, 254 1.1 jdolecek uio->uio_resid); 255 1.1 jdolecek 256 1.1 jdolecek if (bytelen == 0) 257 1.1 jdolecek break; 258 1.35 pooka error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, 259 1.56 ad UBC_READ | UBC_PARTIALOK | UBC_VNODE_FLAGS(vp)); 260 1.1 jdolecek if (error) 261 1.1 jdolecek break; 262 1.1 jdolecek } 263 1.1 jdolecek goto out; 264 1.1 jdolecek } 265 1.1 jdolecek 266 1.1 jdolecek do { 267 1.45 dholland lbn = cd9660_lblkno(imp, uio->uio_offset); 268 1.44 dholland on = cd9660_blkoff(imp, uio->uio_offset); 269 1.1 jdolecek n = MIN(imp->logical_block_size - on, uio->uio_resid); 270 1.1 jdolecek diff = (off_t)ip->i_size - uio->uio_offset; 271 1.1 jdolecek if (diff <= 0) 272 1.1 jdolecek return (0); 273 1.1 jdolecek if (diff < n) 274 1.1 jdolecek n = diff; 275 1.44 dholland size = cd9660_blksize(imp, ip, lbn); 276 1.1 jdolecek rablock = lbn + 1; 277 1.45 dholland if (cd9660_lblktosize(imp, rablock) < ip->i_size) { 278 1.44 dholland rasize = cd9660_blksize(imp, ip, rablock); 279 1.1 jdolecek error = breadn(vp, lbn, size, &rablock, 280 1.50 maxv &rasize, 1, 0, &bp); 281 1.1 jdolecek } else { 282 1.51 maxv error = bread(vp, lbn, size, 0, &bp); 283 1.1 jdolecek } 284 1.1 jdolecek if (error) { 285 1.1 jdolecek return (error); 286 1.1 jdolecek } 287 1.42 hannken n = MIN(n, size - bp->b_resid); 288 1.1 jdolecek 289 1.26 christos error = uiomove((char *)bp->b_data + on, (int)n, uio); 290 1.29 ad brelse(bp, 0); 291 1.1 jdolecek } while (error == 0 && uio->uio_resid > 0 && n != 0); 292 1.1 jdolecek 293 1.1 jdolecek out: 294 1.1 jdolecek return (error); 295 1.1 jdolecek } 296 1.1 jdolecek 297 1.1 jdolecek int 298 1.33 matt iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off) 299 1.1 jdolecek { 300 1.1 jdolecek int error; 301 1.1 jdolecek 302 1.1 jdolecek dp->d_name[dp->d_namlen] = 0; 303 1.14 christos dp->d_reclen = _DIRENT_SIZE(dp); 304 1.1 jdolecek 305 1.1 jdolecek if (idp->uio->uio_resid < dp->d_reclen) { 306 1.1 jdolecek idp->eofflag = 0; 307 1.1 jdolecek return (-1); 308 1.1 jdolecek } 309 1.1 jdolecek 310 1.1 jdolecek if (idp->cookies) { 311 1.1 jdolecek if (idp->ncookies <= 0) { 312 1.1 jdolecek idp->eofflag = 0; 313 1.1 jdolecek return (-1); 314 1.1 jdolecek } 315 1.1 jdolecek 316 1.1 jdolecek *idp->cookies++ = off; 317 1.1 jdolecek --idp->ncookies; 318 1.1 jdolecek } 319 1.1 jdolecek 320 1.9 jrf if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0) 321 1.1 jdolecek return (error); 322 1.1 jdolecek idp->uio_off = off; 323 1.1 jdolecek return (0); 324 1.1 jdolecek } 325 1.1 jdolecek 326 1.1 jdolecek int 327 1.33 matt iso_shipdir(struct isoreaddir *idp) 328 1.1 jdolecek { 329 1.1 jdolecek struct dirent *dp; 330 1.1 jdolecek int cl, sl, assoc; 331 1.1 jdolecek int error; 332 1.1 jdolecek char *cname, *sname; 333 1.1 jdolecek 334 1.1 jdolecek cl = idp->current.d_namlen; 335 1.1 jdolecek cname = idp->current.d_name; 336 1.1 jdolecek 337 1.54 christos assoc = (cl > 1) && (*cname == ASSOCCHAR); 338 1.54 christos if (assoc) { 339 1.1 jdolecek cl--; 340 1.1 jdolecek cname++; 341 1.1 jdolecek } 342 1.1 jdolecek 343 1.1 jdolecek dp = &idp->saveent; 344 1.1 jdolecek sname = dp->d_name; 345 1.1 jdolecek if (!(sl = dp->d_namlen)) { 346 1.1 jdolecek dp = &idp->assocent; 347 1.1 jdolecek sname = dp->d_name + 1; 348 1.1 jdolecek sl = dp->d_namlen - 1; 349 1.1 jdolecek } 350 1.1 jdolecek if (sl > 0) { 351 1.1 jdolecek if (sl != cl 352 1.1 jdolecek || memcmp(sname, cname, sl)) { 353 1.1 jdolecek if (idp->assocent.d_namlen) { 354 1.1 jdolecek error = iso_uiodir(idp, &idp->assocent, 355 1.1 jdolecek idp->assocoff); 356 1.1 jdolecek if (error) 357 1.1 jdolecek return (error); 358 1.1 jdolecek idp->assocent.d_namlen = 0; 359 1.1 jdolecek } 360 1.1 jdolecek if (idp->saveent.d_namlen) { 361 1.1 jdolecek error = iso_uiodir(idp, &idp->saveent, 362 1.1 jdolecek idp->saveoff); 363 1.1 jdolecek if (error) 364 1.1 jdolecek return (error); 365 1.1 jdolecek idp->saveent.d_namlen = 0; 366 1.1 jdolecek } 367 1.1 jdolecek } 368 1.1 jdolecek } 369 1.14 christos idp->current.d_reclen = _DIRENT_SIZE(&idp->current); 370 1.1 jdolecek if (assoc) { 371 1.1 jdolecek idp->assocoff = idp->curroff; 372 1.1 jdolecek memcpy(&idp->assocent, &idp->current, idp->current.d_reclen); 373 1.1 jdolecek } else { 374 1.1 jdolecek idp->saveoff = idp->curroff; 375 1.1 jdolecek memcpy(&idp->saveent, &idp->current, idp->current.d_reclen); 376 1.1 jdolecek } 377 1.1 jdolecek return (0); 378 1.1 jdolecek } 379 1.1 jdolecek 380 1.1 jdolecek /* 381 1.1 jdolecek * Vnode op for readdir 382 1.1 jdolecek */ 383 1.1 jdolecek int 384 1.33 matt cd9660_readdir(void *v) 385 1.1 jdolecek { 386 1.1 jdolecek struct vop_readdir_args /* { 387 1.1 jdolecek struct vnode *a_vp; 388 1.1 jdolecek struct uio *a_uio; 389 1.22 elad kauth_cred_t a_cred; 390 1.1 jdolecek int *a_eofflag; 391 1.1 jdolecek off_t **a_cookies; 392 1.1 jdolecek int *a_ncookies; 393 1.1 jdolecek } */ *ap = v; 394 1.1 jdolecek struct uio *uio = ap->a_uio; 395 1.1 jdolecek struct isoreaddir *idp; 396 1.1 jdolecek struct vnode *vdp = ap->a_vp; 397 1.1 jdolecek struct iso_node *dp; 398 1.1 jdolecek struct iso_mnt *imp; 399 1.1 jdolecek struct buf *bp = NULL; 400 1.1 jdolecek struct iso_directory_record *ep; 401 1.1 jdolecek int entryoffsetinblock; 402 1.1 jdolecek doff_t endsearch; 403 1.1 jdolecek u_long bmask; 404 1.1 jdolecek int error = 0; 405 1.1 jdolecek int reclen; 406 1.1 jdolecek u_short namelen; 407 1.1 jdolecek off_t *cookies = NULL; 408 1.1 jdolecek int ncookies = 0; 409 1.1 jdolecek 410 1.1 jdolecek if (vdp->v_type != VDIR) 411 1.1 jdolecek return (ENOTDIR); 412 1.1 jdolecek 413 1.1 jdolecek dp = VTOI(vdp); 414 1.1 jdolecek imp = dp->i_mnt; 415 1.1 jdolecek bmask = imp->im_bmask; 416 1.1 jdolecek 417 1.55 maxv idp = malloc(sizeof(*idp), M_TEMP, M_WAITOK | M_ZERO); 418 1.1 jdolecek idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 419 1.1 jdolecek /* 420 1.1 jdolecek * XXX 421 1.1 jdolecek * Is it worth trying to figure out the type? 422 1.1 jdolecek */ 423 1.1 jdolecek idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 424 1.1 jdolecek DT_UNKNOWN; 425 1.1 jdolecek idp->uio = uio; 426 1.1 jdolecek if (ap->a_ncookies == NULL) 427 1.1 jdolecek idp->cookies = NULL; 428 1.1 jdolecek else { 429 1.28 rumble ncookies = uio->uio_resid / _DIRENT_MINSIZE((struct dirent *)0); 430 1.1 jdolecek cookies = malloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); 431 1.1 jdolecek idp->cookies = cookies; 432 1.1 jdolecek idp->ncookies = ncookies; 433 1.1 jdolecek } 434 1.1 jdolecek idp->eofflag = 1; 435 1.1 jdolecek idp->curroff = uio->uio_offset; 436 1.1 jdolecek 437 1.1 jdolecek if ((entryoffsetinblock = idp->curroff & bmask) && 438 1.16 yamt (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 439 1.36 cegger free(idp, M_TEMP); 440 1.1 jdolecek return (error); 441 1.1 jdolecek } 442 1.1 jdolecek endsearch = dp->i_size; 443 1.1 jdolecek 444 1.1 jdolecek while (idp->curroff < endsearch) { 445 1.1 jdolecek /* 446 1.1 jdolecek * If offset is on a block boundary, 447 1.1 jdolecek * read the next directory block. 448 1.1 jdolecek * Release previous if it exists. 449 1.1 jdolecek */ 450 1.1 jdolecek if ((idp->curroff & bmask) == 0) { 451 1.1 jdolecek if (bp != NULL) 452 1.29 ad brelse(bp, 0); 453 1.16 yamt error = cd9660_blkatoff(vdp, (off_t)idp->curroff, 454 1.1 jdolecek NULL, &bp); 455 1.1 jdolecek if (error) 456 1.1 jdolecek break; 457 1.1 jdolecek entryoffsetinblock = 0; 458 1.1 jdolecek } 459 1.1 jdolecek /* 460 1.1 jdolecek * Get pointer to next entry. 461 1.1 jdolecek */ 462 1.21 christos KASSERT(bp != NULL); 463 1.1 jdolecek ep = (struct iso_directory_record *) 464 1.1 jdolecek ((char *)bp->b_data + entryoffsetinblock); 465 1.1 jdolecek 466 1.1 jdolecek reclen = isonum_711(ep->length); 467 1.1 jdolecek if (reclen == 0) { 468 1.1 jdolecek /* skip to next block, if any */ 469 1.1 jdolecek idp->curroff = 470 1.1 jdolecek (idp->curroff & ~bmask) + imp->logical_block_size; 471 1.1 jdolecek continue; 472 1.1 jdolecek } 473 1.1 jdolecek 474 1.1 jdolecek if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 475 1.1 jdolecek error = EINVAL; 476 1.1 jdolecek /* illegal entry, stop */ 477 1.1 jdolecek break; 478 1.1 jdolecek } 479 1.1 jdolecek 480 1.1 jdolecek if (entryoffsetinblock + reclen > imp->logical_block_size) { 481 1.1 jdolecek error = EINVAL; 482 1.1 jdolecek /* illegal directory, so stop looking */ 483 1.1 jdolecek break; 484 1.1 jdolecek } 485 1.1 jdolecek 486 1.1 jdolecek idp->current.d_namlen = isonum_711(ep->name_len); 487 1.1 jdolecek 488 1.1 jdolecek if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 489 1.1 jdolecek error = EINVAL; 490 1.1 jdolecek /* illegal entry, stop */ 491 1.1 jdolecek break; 492 1.1 jdolecek } 493 1.1 jdolecek 494 1.1 jdolecek if (isonum_711(ep->flags)&2) 495 1.1 jdolecek idp->current.d_fileno = isodirino(ep, imp); 496 1.1 jdolecek else 497 1.1 jdolecek idp->current.d_fileno = dbtob(bp->b_blkno) + 498 1.1 jdolecek entryoffsetinblock; 499 1.1 jdolecek 500 1.1 jdolecek idp->curroff += reclen; 501 1.1 jdolecek 502 1.1 jdolecek switch (imp->iso_ftype) { 503 1.1 jdolecek case ISO_FTYPE_RRIP: 504 1.2 itojun cd9660_rrip_getname(ep, idp->current.d_name, &namelen, 505 1.2 itojun &idp->current.d_fileno, imp); 506 1.1 jdolecek idp->current.d_namlen = (u_char)namelen; 507 1.1 jdolecek if (idp->current.d_namlen) 508 1.2 itojun error = iso_uiodir(idp, &idp->current, 509 1.2 itojun idp->curroff); 510 1.1 jdolecek break; 511 1.1 jdolecek default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 512 1.2 itojun isofntrans(ep->name, idp->current.d_namlen, 513 1.1 jdolecek idp->current.d_name, &namelen, 514 1.1 jdolecek imp->iso_ftype == ISO_FTYPE_9660, 515 1.1 jdolecek (imp->im_flags & ISOFSMNT_NOCASETRANS) == 0, 516 1.1 jdolecek isonum_711(ep->flags)&4, 517 1.1 jdolecek imp->im_joliet_level); 518 1.1 jdolecek switch (idp->current.d_name[0]) { 519 1.1 jdolecek case 0: 520 1.1 jdolecek idp->current.d_name[0] = '.'; 521 1.1 jdolecek idp->current.d_namlen = 1; 522 1.2 itojun error = iso_uiodir(idp, &idp->current, 523 1.2 itojun idp->curroff); 524 1.1 jdolecek break; 525 1.1 jdolecek case 1: 526 1.2 itojun strlcpy(idp->current.d_name, "..", 527 1.2 itojun sizeof(idp->current.d_name)); 528 1.1 jdolecek idp->current.d_namlen = 2; 529 1.2 itojun error = iso_uiodir(idp, &idp->current, 530 1.2 itojun idp->curroff); 531 1.1 jdolecek break; 532 1.1 jdolecek default: 533 1.1 jdolecek idp->current.d_namlen = (u_char)namelen; 534 1.1 jdolecek if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 535 1.1 jdolecek error = iso_shipdir(idp); 536 1.1 jdolecek else 537 1.2 itojun error = iso_uiodir(idp, &idp->current, 538 1.2 itojun idp->curroff); 539 1.1 jdolecek break; 540 1.1 jdolecek } 541 1.1 jdolecek } 542 1.1 jdolecek if (error) 543 1.1 jdolecek break; 544 1.1 jdolecek 545 1.1 jdolecek entryoffsetinblock += reclen; 546 1.1 jdolecek } 547 1.1 jdolecek 548 1.1 jdolecek if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 549 1.1 jdolecek idp->current.d_namlen = 0; 550 1.1 jdolecek error = iso_shipdir(idp); 551 1.1 jdolecek } 552 1.1 jdolecek if (error < 0) 553 1.1 jdolecek error = 0; 554 1.1 jdolecek 555 1.1 jdolecek if (ap->a_ncookies != NULL) { 556 1.1 jdolecek if (error) 557 1.1 jdolecek free(cookies, M_TEMP); 558 1.1 jdolecek else { 559 1.1 jdolecek /* 560 1.1 jdolecek * Work out the number of cookies actually used. 561 1.1 jdolecek */ 562 1.1 jdolecek *ap->a_ncookies = ncookies - idp->ncookies; 563 1.1 jdolecek *ap->a_cookies = cookies; 564 1.1 jdolecek } 565 1.1 jdolecek } 566 1.1 jdolecek 567 1.1 jdolecek if (bp) 568 1.29 ad brelse(bp, 0); 569 1.1 jdolecek 570 1.1 jdolecek uio->uio_offset = idp->uio_off; 571 1.1 jdolecek *ap->a_eofflag = idp->eofflag; 572 1.1 jdolecek 573 1.36 cegger free(idp, M_TEMP); 574 1.1 jdolecek 575 1.1 jdolecek return (error); 576 1.1 jdolecek } 577 1.1 jdolecek 578 1.1 jdolecek /* 579 1.1 jdolecek * Return target name of a symbolic link 580 1.1 jdolecek * Shouldn't we get the parent vnode and read the data from there? 581 1.1 jdolecek * This could eventually result in deadlocks in cd9660_lookup. 582 1.1 jdolecek * But otherwise the block read here is in the block buffer two times. 583 1.1 jdolecek */ 584 1.1 jdolecek typedef struct iso_directory_record ISODIR; 585 1.1 jdolecek typedef struct iso_node ISONODE; 586 1.1 jdolecek typedef struct iso_mnt ISOMNT; 587 1.33 matt 588 1.1 jdolecek int 589 1.33 matt cd9660_readlink(void *v) 590 1.1 jdolecek { 591 1.1 jdolecek struct vop_readlink_args /* { 592 1.1 jdolecek struct vnode *a_vp; 593 1.1 jdolecek struct uio *a_uio; 594 1.22 elad kauth_cred_t a_cred; 595 1.1 jdolecek } */ *ap = v; 596 1.1 jdolecek ISONODE *ip; 597 1.1 jdolecek ISODIR *dirp; 598 1.1 jdolecek ISOMNT *imp; 599 1.1 jdolecek struct buf *bp; 600 1.1 jdolecek struct uio *uio; 601 1.1 jdolecek u_short symlen; 602 1.1 jdolecek int error; 603 1.1 jdolecek char *symname; 604 1.25 thorpej bool use_pnbuf; 605 1.1 jdolecek 606 1.1 jdolecek ip = VTOI(ap->a_vp); 607 1.1 jdolecek imp = ip->i_mnt; 608 1.1 jdolecek uio = ap->a_uio; 609 1.1 jdolecek 610 1.1 jdolecek if (imp->iso_ftype != ISO_FTYPE_RRIP) 611 1.1 jdolecek return (EINVAL); 612 1.1 jdolecek 613 1.1 jdolecek /* 614 1.1 jdolecek * Get parents directory record block that this inode included. 615 1.1 jdolecek */ 616 1.1 jdolecek error = bread(imp->im_devvp, 617 1.1 jdolecek (ip->i_number >> imp->im_bshift) << 618 1.1 jdolecek (imp->im_bshift - DEV_BSHIFT), 619 1.51 maxv imp->logical_block_size, 0, &bp); 620 1.1 jdolecek if (error) { 621 1.1 jdolecek return (EINVAL); 622 1.1 jdolecek } 623 1.1 jdolecek 624 1.1 jdolecek /* 625 1.1 jdolecek * Setup the directory pointer for this inode 626 1.1 jdolecek */ 627 1.26 christos dirp = (ISODIR *)((char *)bp->b_data + (ip->i_number & imp->im_bmask)); 628 1.1 jdolecek 629 1.1 jdolecek /* 630 1.1 jdolecek * Just make sure, we have a right one.... 631 1.1 jdolecek * 1: Check not cross boundary on block 632 1.1 jdolecek */ 633 1.1 jdolecek if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 634 1.1 jdolecek > imp->logical_block_size) { 635 1.29 ad brelse(bp, 0); 636 1.1 jdolecek return (EINVAL); 637 1.1 jdolecek } 638 1.1 jdolecek 639 1.1 jdolecek /* 640 1.1 jdolecek * Now get a buffer 641 1.1 jdolecek * Abuse a namei buffer for now. 642 1.1 jdolecek */ 643 1.20 yamt use_pnbuf = !VMSPACE_IS_KERNEL_P(uio->uio_vmspace) || 644 1.20 yamt uio->uio_iov->iov_len < MAXPATHLEN; 645 1.20 yamt if (use_pnbuf) { 646 1.20 yamt symname = PNBUF_GET(); 647 1.20 yamt } else { 648 1.1 jdolecek symname = uio->uio_iov->iov_base; 649 1.20 yamt } 650 1.12 perry 651 1.1 jdolecek /* 652 1.1 jdolecek * Ok, we just gathering a symbolic name in SL record. 653 1.1 jdolecek */ 654 1.1 jdolecek if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 655 1.20 yamt if (use_pnbuf) { 656 1.13 thorpej PNBUF_PUT(symname); 657 1.20 yamt } 658 1.29 ad brelse(bp, 0); 659 1.1 jdolecek return (EINVAL); 660 1.1 jdolecek } 661 1.1 jdolecek /* 662 1.1 jdolecek * Don't forget before you leave from home ;-) 663 1.1 jdolecek */ 664 1.29 ad brelse(bp, 0); 665 1.1 jdolecek 666 1.1 jdolecek /* 667 1.1 jdolecek * return with the symbolic name to caller's. 668 1.1 jdolecek */ 669 1.20 yamt if (use_pnbuf) { 670 1.1 jdolecek error = uiomove(symname, symlen, uio); 671 1.13 thorpej PNBUF_PUT(symname); 672 1.1 jdolecek return (error); 673 1.1 jdolecek } 674 1.1 jdolecek uio->uio_resid -= symlen; 675 1.1 jdolecek uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 676 1.1 jdolecek uio->uio_iov->iov_len -= symlen; 677 1.1 jdolecek return (0); 678 1.1 jdolecek } 679 1.1 jdolecek 680 1.1 jdolecek /* 681 1.1 jdolecek * Calculate the logical to physical mapping if not done already, 682 1.1 jdolecek * then call the device strategy routine. 683 1.1 jdolecek */ 684 1.1 jdolecek int 685 1.33 matt cd9660_strategy(void *v) 686 1.1 jdolecek { 687 1.1 jdolecek struct vop_strategy_args /* { 688 1.8 hannken struct vnode *a_vp; 689 1.1 jdolecek struct buf *a_bp; 690 1.1 jdolecek } */ *ap = v; 691 1.1 jdolecek struct buf *bp = ap->a_bp; 692 1.8 hannken struct vnode *vp = ap->a_vp; 693 1.1 jdolecek struct iso_node *ip; 694 1.1 jdolecek int error; 695 1.1 jdolecek 696 1.1 jdolecek ip = VTOI(vp); 697 1.1 jdolecek if (vp->v_type == VBLK || vp->v_type == VCHR) 698 1.1 jdolecek panic("cd9660_strategy: spec"); 699 1.1 jdolecek if (bp->b_blkno == bp->b_lblkno) { 700 1.1 jdolecek error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 701 1.1 jdolecek if (error) { 702 1.1 jdolecek bp->b_error = error; 703 1.1 jdolecek biodone(bp); 704 1.1 jdolecek return (error); 705 1.1 jdolecek } 706 1.1 jdolecek if ((long)bp->b_blkno == -1) 707 1.1 jdolecek clrbuf(bp); 708 1.1 jdolecek } 709 1.1 jdolecek if ((long)bp->b_blkno == -1) { 710 1.1 jdolecek biodone(bp); 711 1.1 jdolecek return (0); 712 1.1 jdolecek } 713 1.48 hannken vp = ip->i_mnt->im_devvp; 714 1.7 hannken return (VOP_STRATEGY(vp, bp)); 715 1.1 jdolecek } 716 1.1 jdolecek 717 1.1 jdolecek /* 718 1.1 jdolecek * Print out the contents of an inode. 719 1.1 jdolecek */ 720 1.1 jdolecek /*ARGSUSED*/ 721 1.1 jdolecek int 722 1.24 christos cd9660_print(void *v) 723 1.1 jdolecek { 724 1.1 jdolecek 725 1.1 jdolecek printf("tag VT_ISOFS, isofs vnode\n"); 726 1.1 jdolecek return (0); 727 1.1 jdolecek } 728 1.1 jdolecek 729 1.1 jdolecek /* 730 1.1 jdolecek * Return POSIX pathconf information applicable to cd9660 filesystems. 731 1.1 jdolecek */ 732 1.1 jdolecek int 733 1.33 matt cd9660_pathconf(void *v) 734 1.1 jdolecek { 735 1.1 jdolecek struct vop_pathconf_args /* { 736 1.1 jdolecek struct vnode *a_vp; 737 1.1 jdolecek int a_name; 738 1.1 jdolecek register_t *a_retval; 739 1.1 jdolecek } */ *ap = v; 740 1.1 jdolecek switch (ap->a_name) { 741 1.1 jdolecek case _PC_LINK_MAX: 742 1.1 jdolecek *ap->a_retval = 1; 743 1.1 jdolecek return (0); 744 1.1 jdolecek case _PC_NAME_MAX: 745 1.1 jdolecek if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 746 1.40 christos *ap->a_retval = ISO_MAXNAMLEN; 747 1.1 jdolecek else 748 1.1 jdolecek *ap->a_retval = 37; 749 1.1 jdolecek return (0); 750 1.1 jdolecek case _PC_PATH_MAX: 751 1.1 jdolecek *ap->a_retval = PATH_MAX; 752 1.1 jdolecek return (0); 753 1.1 jdolecek case _PC_PIPE_BUF: 754 1.1 jdolecek *ap->a_retval = PIPE_BUF; 755 1.1 jdolecek return (0); 756 1.1 jdolecek case _PC_CHOWN_RESTRICTED: 757 1.1 jdolecek *ap->a_retval = 1; 758 1.1 jdolecek return (0); 759 1.1 jdolecek case _PC_NO_TRUNC: 760 1.1 jdolecek *ap->a_retval = 1; 761 1.1 jdolecek return (0); 762 1.1 jdolecek case _PC_SYNC_IO: 763 1.1 jdolecek *ap->a_retval = 1; 764 1.1 jdolecek return (0); 765 1.1 jdolecek case _PC_FILESIZEBITS: 766 1.1 jdolecek *ap->a_retval = 32; 767 1.1 jdolecek return (0); 768 1.1 jdolecek default: 769 1.58 christos return genfs_pathconf(ap); 770 1.1 jdolecek } 771 1.1 jdolecek /* NOTREACHED */ 772 1.1 jdolecek } 773 1.1 jdolecek 774 1.1 jdolecek /* 775 1.17 yamt * Allow changing the size for special files (and fifos). 776 1.17 yamt */ 777 1.17 yamt int 778 1.33 matt cd9660_setattr(void *v) 779 1.17 yamt { 780 1.17 yamt struct vop_setattr_args /* { 781 1.17 yamt struct vnodeop_desc *a_desc; 782 1.17 yamt struct vnode *a_vp; 783 1.17 yamt struct vattr *a_vap; 784 1.22 elad kauth_cred_t a_cred; 785 1.17 yamt struct proc *a_p; 786 1.17 yamt } */ *ap = v; 787 1.17 yamt struct vattr *vap = ap->a_vap; 788 1.17 yamt struct vnode *vp = ap->a_vp; 789 1.17 yamt 790 1.17 yamt /* 791 1.17 yamt * Only size is changeable. 792 1.17 yamt */ 793 1.17 yamt if (vap->va_type != VNON 794 1.17 yamt || vap->va_nlink != (nlink_t)VNOVAL 795 1.17 yamt || vap->va_fsid != VNOVAL 796 1.17 yamt || vap->va_fileid != VNOVAL 797 1.17 yamt || vap->va_blocksize != VNOVAL 798 1.17 yamt || vap->va_rdev != (dev_t)VNOVAL 799 1.17 yamt || (int)vap->va_bytes != VNOVAL 800 1.17 yamt || vap->va_gen != VNOVAL 801 1.17 yamt || vap->va_flags != VNOVAL 802 1.17 yamt || vap->va_uid != (uid_t)VNOVAL 803 1.17 yamt || vap->va_gid != (gid_t)VNOVAL 804 1.17 yamt || vap->va_atime.tv_sec != VNOVAL 805 1.17 yamt || vap->va_mtime.tv_sec != VNOVAL 806 1.17 yamt || vap->va_mode != (mode_t)VNOVAL) 807 1.17 yamt return EOPNOTSUPP; 808 1.17 yamt 809 1.17 yamt if (vap->va_size != VNOVAL 810 1.17 yamt && vp->v_type != VCHR 811 1.17 yamt && vp->v_type != VBLK 812 1.17 yamt && vp->v_type != VFIFO) 813 1.17 yamt return EOPNOTSUPP; 814 1.17 yamt 815 1.17 yamt return 0; 816 1.17 yamt } 817 1.17 yamt 818 1.17 yamt /* 819 1.1 jdolecek * Global vfs data structures for cd9660 820 1.1 jdolecek */ 821 1.15 xtraeme int (**cd9660_vnodeop_p)(void *); 822 1.1 jdolecek const struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 823 1.1 jdolecek { &vop_default_desc, vn_default_error }, 824 1.59 dholland { &vop_parsepath_desc, genfs_parsepath }, /* parsepath */ 825 1.1 jdolecek { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 826 1.61 dholland { &vop_create_desc, genfs_eopnotsupp }, /* create */ 827 1.61 dholland { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */ 828 1.61 dholland { &vop_open_desc, genfs_nullop }, /* open */ 829 1.61 dholland { &vop_close_desc, genfs_nullop }, /* close */ 830 1.1 jdolecek { &vop_access_desc, cd9660_access }, /* access */ 831 1.57 christos { &vop_accessx_desc, genfs_accessx }, /* accessx */ 832 1.1 jdolecek { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 833 1.1 jdolecek { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 834 1.1 jdolecek { &vop_read_desc, cd9660_read }, /* read */ 835 1.61 dholland { &vop_write_desc, genfs_eopnotsupp }, /* write */ 836 1.49 dholland { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 837 1.49 dholland { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 838 1.1 jdolecek { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 839 1.61 dholland { &vop_ioctl_desc, genfs_enoioctl }, /* ioctl */ 840 1.61 dholland { &vop_poll_desc, genfs_poll }, /* poll */ 841 1.61 dholland { &vop_revoke_desc, genfs_revoke }, /* revoke */ 842 1.61 dholland { &vop_mmap_desc, genfs_mmap }, /* mmap */ 843 1.61 dholland { &vop_fsync_desc, genfs_nullop }, /* fsync */ 844 1.61 dholland { &vop_seek_desc, genfs_seek }, /* seek */ 845 1.61 dholland { &vop_remove_desc, genfs_eopnotsupp }, /* remove */ 846 1.62 christos { &vop_link_desc, genfs_erofs_link }, /* link */ 847 1.61 dholland { &vop_rename_desc, genfs_eopnotsupp }, /* rename */ 848 1.61 dholland { &vop_mkdir_desc, genfs_eopnotsupp }, /* mkdir */ 849 1.61 dholland { &vop_rmdir_desc, genfs_eopnotsupp }, /* rmdir */ 850 1.62 christos { &vop_symlink_desc, genfs_erofs_symlink }, /* symlink */ 851 1.1 jdolecek { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 852 1.1 jdolecek { &vop_readlink_desc, cd9660_readlink }, /* readlink */ 853 1.61 dholland { &vop_abortop_desc, genfs_abortop }, /* abortop */ 854 1.1 jdolecek { &vop_inactive_desc, cd9660_inactive }, /* inactive */ 855 1.1 jdolecek { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 856 1.1 jdolecek { &vop_lock_desc, genfs_lock }, /* lock */ 857 1.1 jdolecek { &vop_unlock_desc, genfs_unlock }, /* unlock */ 858 1.1 jdolecek { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 859 1.1 jdolecek { &vop_strategy_desc, cd9660_strategy }, /* strategy */ 860 1.1 jdolecek { &vop_print_desc, cd9660_print }, /* print */ 861 1.1 jdolecek { &vop_islocked_desc, genfs_islocked }, /* islocked */ 862 1.1 jdolecek { &vop_pathconf_desc, cd9660_pathconf }, /* pathconf */ 863 1.61 dholland { &vop_advlock_desc, genfs_einval }, /* advlock */ 864 1.1 jdolecek { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 865 1.1 jdolecek { &vop_getpages_desc, genfs_getpages }, /* getpages */ 866 1.1 jdolecek { &vop_putpages_desc, genfs_putpages }, /* putpages */ 867 1.1 jdolecek { NULL, NULL } 868 1.1 jdolecek }; 869 1.1 jdolecek const struct vnodeopv_desc cd9660_vnodeop_opv_desc = 870 1.1 jdolecek { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 871 1.1 jdolecek 872 1.1 jdolecek /* 873 1.1 jdolecek * Special device vnode ops 874 1.1 jdolecek */ 875 1.15 xtraeme int (**cd9660_specop_p)(void *); 876 1.1 jdolecek const struct vnodeopv_entry_desc cd9660_specop_entries[] = { 877 1.1 jdolecek { &vop_default_desc, vn_default_error }, 878 1.60 dholland GENFS_SPECOP_ENTRIES, 879 1.1 jdolecek { &vop_close_desc, spec_close }, /* close */ 880 1.1 jdolecek { &vop_access_desc, cd9660_access }, /* access */ 881 1.57 christos { &vop_accessx_desc, genfs_accessx }, /* accessx */ 882 1.1 jdolecek { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 883 1.1 jdolecek { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 884 1.1 jdolecek { &vop_read_desc, spec_read }, /* read */ 885 1.1 jdolecek { &vop_write_desc, spec_write }, /* write */ 886 1.1 jdolecek { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 887 1.1 jdolecek { &vop_fsync_desc, spec_fsync }, /* fsync */ 888 1.1 jdolecek { &vop_inactive_desc, cd9660_inactive }, /* inactive */ 889 1.1 jdolecek { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 890 1.1 jdolecek { &vop_lock_desc, genfs_lock }, /* lock */ 891 1.1 jdolecek { &vop_unlock_desc, genfs_unlock }, /* unlock */ 892 1.1 jdolecek { &vop_print_desc, cd9660_print }, /* print */ 893 1.1 jdolecek { &vop_islocked_desc, genfs_islocked }, /* islocked */ 894 1.1 jdolecek { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 895 1.1 jdolecek { NULL, NULL } 896 1.1 jdolecek }; 897 1.1 jdolecek const struct vnodeopv_desc cd9660_specop_opv_desc = 898 1.1 jdolecek { &cd9660_specop_p, cd9660_specop_entries }; 899 1.1 jdolecek 900 1.15 xtraeme int (**cd9660_fifoop_p)(void *); 901 1.1 jdolecek const struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 902 1.1 jdolecek { &vop_default_desc, vn_default_error }, 903 1.60 dholland GENFS_FIFOOP_ENTRIES, 904 1.39 pooka { &vop_close_desc, vn_fifo_bypass }, /* close */ 905 1.1 jdolecek { &vop_access_desc, cd9660_access }, /* access */ 906 1.57 christos { &vop_accessx_desc, genfs_accessx }, /* accessx */ 907 1.1 jdolecek { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 908 1.1 jdolecek { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 909 1.39 pooka { &vop_read_desc, vn_fifo_bypass }, /* read */ 910 1.39 pooka { &vop_write_desc, vn_fifo_bypass }, /* write */ 911 1.1 jdolecek { &vop_fcntl_desc, genfs_fcntl }, /* fcntl */ 912 1.39 pooka { &vop_fsync_desc, vn_fifo_bypass }, /* fsync */ 913 1.1 jdolecek { &vop_inactive_desc, cd9660_inactive }, /* inactive */ 914 1.1 jdolecek { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 915 1.1 jdolecek { &vop_lock_desc, genfs_lock }, /* lock */ 916 1.1 jdolecek { &vop_unlock_desc, genfs_unlock }, /* unlock */ 917 1.39 pooka { &vop_strategy_desc, vn_fifo_bypass }, /* strategy */ 918 1.1 jdolecek { &vop_print_desc, cd9660_print }, /* print */ 919 1.1 jdolecek { &vop_islocked_desc, genfs_islocked }, /* islocked */ 920 1.1 jdolecek { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ 921 1.1 jdolecek { NULL, NULL } 922 1.1 jdolecek }; 923 1.1 jdolecek const struct vnodeopv_desc cd9660_fifoop_opv_desc = 924 1.1 jdolecek { &cd9660_fifoop_p, cd9660_fifoop_entries }; 925