1 /*- 2 * Copyright (c) 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley 6 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 7 * Support code is derived from software contributed to Berkeley 8 * by Atsushi Murai (amurai@spec.co.jp). 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 35 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vnops.c,v 1.62 1999/12/15 23:01:51 eivind Exp $ 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/proc.h> 41 #include <sys/namei.h> 42 #include <sys/kernel.h> 43 #include <sys/stat.h> 44 #include <sys/buf.h> 45 #include <sys/mount.h> 46 #include <sys/vnode.h> 47 #include <vfs/fifofs/fifo.h> 48 #include <sys/malloc.h> 49 #include <sys/dirent.h> 50 #include <sys/unistd.h> 51 #include <sys/filio.h> 52 #include <sys/lockf.h> 53 #include <sys/objcache.h> 54 55 #include <vm/vm.h> 56 #include <vm/vnode_pager.h> 57 58 #include <sys/buf2.h> 59 60 #include "iso.h" 61 #include "cd9660_node.h" 62 #include "iso_rrip.h" 63 64 static int cd9660_access(struct vop_access_args *); 65 static int cd9660_advlock(struct vop_advlock_args *); 66 static int cd9660_getattr(struct vop_getattr_args *); 67 static int cd9660_ioctl(struct vop_ioctl_args *); 68 static int cd9660_pathconf(struct vop_pathconf_args *); 69 static int cd9660_open(struct vop_open_args *); 70 static int cd9660_read(struct vop_read_args *); 71 static int cd9660_setattr(struct vop_setattr_args *); 72 struct isoreaddir; 73 static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 74 static int iso_shipdir(struct isoreaddir *idp); 75 static int cd9660_readdir(struct vop_readdir_args *); 76 static int cd9660_readlink(struct vop_readlink_args *ap); 77 static int cd9660_strategy(struct vop_strategy_args *); 78 static int cd9660_print(struct vop_print_args *); 79 80 /* 81 * Setattr call. Only allowed for block and character special devices. 82 * 83 * cd9660_setattr(struct vnode *a_vp, struct vattr *a_vap, 84 * struct ucred *a_cred, struct proc *a_p) 85 */ 86 int 87 cd9660_setattr(struct vop_setattr_args *ap) 88 { 89 struct vnode *vp = ap->a_vp; 90 struct vattr *vap = ap->a_vap; 91 92 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 93 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 94 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 95 return (EROFS); 96 if (vap->va_size != (u_quad_t)VNOVAL) { 97 switch (vp->v_type) { 98 case VDIR: 99 return (EISDIR); 100 case VLNK: 101 case VREG: 102 case VDATABASE: 103 return (EROFS); 104 case VCHR: 105 case VBLK: 106 case VSOCK: 107 case VFIFO: 108 default: 109 return (0); 110 } 111 } 112 return (0); 113 } 114 115 /* 116 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 117 * The mode is shifted to select the owner/group/other fields. The 118 * super user is granted all permissions. 119 * 120 * cd9660_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred, 121 * struct proc *a_p) 122 */ 123 /* ARGSUSED */ 124 static int 125 cd9660_access(struct vop_access_args *ap) 126 { 127 struct vnode *vp = ap->a_vp; 128 struct iso_node *ip = VTOI(vp); 129 130 KKASSERT(vp->v_mount->mnt_flag & MNT_RDONLY); 131 return (vop_helper_access(ap, ip->inode.iso_uid, ip->inode.iso_gid, 132 ip->inode.iso_mode, 0)); 133 } 134 135 /* 136 * cd9660_getattr(struct vnode *a_vp, struct vattr *a_vap) 137 */ 138 static int 139 cd9660_getattr(struct vop_getattr_args *ap) 140 { 141 struct vnode *vp = ap->a_vp; 142 struct vattr *vap = ap->a_vap; 143 struct iso_node *ip = VTOI(vp); 144 145 vap->va_fsid = dev2udev(ip->i_dev); 146 vap->va_fileid = ip->i_number; 147 148 vap->va_mode = ip->inode.iso_mode; 149 vap->va_nlink = ip->inode.iso_links; 150 vap->va_uid = ip->inode.iso_uid; 151 vap->va_gid = ip->inode.iso_gid; 152 vap->va_atime = ip->inode.iso_atime; 153 vap->va_mtime = ip->inode.iso_mtime; 154 vap->va_ctime = ip->inode.iso_ctime; 155 vap->va_rmajor = umajor(ip->inode.iso_rdev); 156 vap->va_rminor = uminor(ip->inode.iso_rdev); 157 158 vap->va_size = (u_quad_t)(unsigned long)ip->i_size; 159 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 160 struct vop_readlink_args rdlnk; 161 struct iovec aiov; 162 struct uio auio; 163 char *cp; 164 165 cp = kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK); 166 aiov.iov_base = cp; 167 aiov.iov_len = MAXPATHLEN; 168 auio.uio_iov = &aiov; 169 auio.uio_iovcnt = 1; 170 auio.uio_offset = 0; 171 auio.uio_rw = UIO_READ; 172 auio.uio_segflg = UIO_SYSSPACE; 173 auio.uio_td = curthread; 174 auio.uio_resid = MAXPATHLEN; 175 rdlnk.a_uio = &auio; 176 rdlnk.a_vp = ap->a_vp; 177 rdlnk.a_cred = proc0.p_ucred; /* use root cred */ 178 if (cd9660_readlink(&rdlnk) == 0) 179 vap->va_size = MAXPATHLEN - auio.uio_resid; 180 kfree(cp, M_TEMP); 181 } 182 vap->va_flags = 0; 183 vap->va_gen = 1; 184 vap->va_blocksize = ip->i_mnt->logical_block_size; 185 vap->va_bytes = (u_quad_t) ip->i_size; 186 vap->va_type = vp->v_type; 187 vap->va_filerev = 0; 188 return (0); 189 } 190 191 /* 192 * Vnode op for ioctl. 193 * 194 * cd9660_ioctl(struct vnode *a_vp, int a_command, caddr_t a_data, 195 * int a_fflag, struct ucred *a_cred, struct proc *a_p) 196 */ 197 static int 198 cd9660_ioctl(struct vop_ioctl_args *ap) 199 { 200 struct vnode *vp = ap->a_vp; 201 struct iso_node *ip = VTOI(vp); 202 203 switch (ap->a_command) { 204 205 case FIOGETLBA: 206 *(int *)(ap->a_data) = ip->iso_start; 207 return 0; 208 default: 209 return (ENOTTY); 210 } 211 } 212 213 /* 214 * open is called when the kernel intends to read or memory map a vnode. 215 */ 216 static int 217 cd9660_open(struct vop_open_args *ap) 218 { 219 return(vop_stdopen(ap)); 220 } 221 222 /* 223 * Vnode op for reading. 224 * 225 * cd9660_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag, 226 * struct ucred *a_cred) 227 */ 228 static int 229 cd9660_read(struct vop_read_args *ap) 230 { 231 struct vnode *vp = ap->a_vp; 232 struct uio *uio = ap->a_uio; 233 struct iso_node *ip = VTOI(vp); 234 struct iso_mnt *imp; 235 struct buf *bp; 236 daddr_t lbn, rablock; 237 off_t raoffset; 238 off_t loffset; 239 off_t diff; 240 int rasize, error = 0; 241 int seqcount; 242 long size, n, on; 243 244 seqcount = ap->a_ioflag >> 16; 245 246 if (uio->uio_resid == 0) 247 return (0); 248 if (uio->uio_offset < 0) 249 return (EINVAL); 250 ip->i_flag |= IN_ACCESS; 251 imp = ip->i_mnt; 252 do { 253 lbn = lblkno(imp, uio->uio_offset); 254 loffset = lblktooff(imp, lbn); 255 on = blkoff(imp, uio->uio_offset); 256 n = szmin((u_int)(imp->logical_block_size - on), 257 uio->uio_resid); 258 diff = (off_t)ip->i_size - uio->uio_offset; 259 if (diff <= 0) 260 return (0); 261 if (diff < n) 262 n = diff; 263 size = blksize(imp, ip, lbn); 264 rablock = lbn + 1; 265 raoffset = lblktooff(imp, rablock); 266 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 267 if (raoffset < ip->i_size) { 268 error = cluster_read(vp, (off_t)ip->i_size, 269 loffset, size, 270 uio->uio_resid, 271 (ap->a_ioflag >> 16) * 272 BKVASIZE, 273 &bp); 274 } else { 275 error = bread(vp, loffset, size, &bp); 276 } 277 } else { 278 if (seqcount > 1 && 279 lblktosize(imp, rablock) < ip->i_size) { 280 rasize = blksize(imp, ip, rablock); 281 error = breadn(vp, loffset, size, &raoffset, 282 &rasize, 1, &bp); 283 } else 284 error = bread(vp, loffset, size, &bp); 285 } 286 n = imin(n, size - bp->b_resid); 287 if (error) { 288 brelse(bp); 289 return (error); 290 } 291 292 error = uiomove(bp->b_data + on, (int)n, uio); 293 brelse(bp); 294 } while (error == 0 && uio->uio_resid > 0 && n != 0); 295 return (error); 296 } 297 298 /* struct dirent + enough space for the maximum supported size */ 299 struct iso_dirent { 300 struct dirent de; 301 char de_name[_DIRENT_RECLEN(NAME_MAX) - sizeof(struct dirent)]; 302 }; 303 304 /* 305 * Structure for reading directories 306 */ 307 struct isoreaddir { 308 struct iso_dirent saveent; 309 struct iso_dirent assocent; 310 struct iso_dirent current; 311 off_t saveoff; 312 off_t assocoff; 313 off_t curroff; 314 struct uio *uio; 315 off_t uio_off; 316 int eofflag; 317 off_t *cookies; 318 int ncookies; 319 }; 320 321 int 322 iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off) 323 { 324 int error; 325 326 dp->d_name[dp->d_namlen] = 0; 327 328 if (idp->uio->uio_resid < _DIRENT_DIRSIZ(dp)) { 329 idp->eofflag = 0; 330 return (-1); 331 } 332 333 if (idp->cookies) { 334 if (idp->ncookies <= 0) { 335 idp->eofflag = 0; 336 return (-1); 337 } 338 339 *idp->cookies++ = off; 340 --idp->ncookies; 341 } 342 343 if ((error = uiomove((caddr_t) dp,_DIRENT_DIRSIZ(dp),idp->uio)) != 0) 344 return (error); 345 idp->uio_off = off; 346 return (0); 347 } 348 349 int 350 iso_shipdir(struct isoreaddir *idp) 351 { 352 struct dirent *dp; 353 int cl, sl, assoc; 354 int error; 355 char *cname, *sname; 356 357 cl = idp->current.de.d_namlen; 358 cname = idp->current.de.d_name; 359 assoc = (cl > 1) && (*cname == ASSOCCHAR); 360 if (assoc) { 361 cl--; 362 cname++; 363 } 364 365 dp = &idp->saveent.de; 366 sname = dp->d_name; 367 if (!(sl = dp->d_namlen)) { 368 dp = &idp->assocent.de; 369 sname = dp->d_name + 1; 370 sl = dp->d_namlen - 1; 371 } 372 if (sl > 0) { 373 if (sl != cl 374 || bcmp(sname,cname,sl)) { 375 if (idp->assocent.de.d_namlen) { 376 if ((error = iso_uiodir(idp,&idp->assocent.de,idp->assocoff)) != 0) 377 return (error); 378 idp->assocent.de.d_namlen = 0; 379 } 380 if (idp->saveent.de.d_namlen) { 381 if ((error = iso_uiodir(idp,&idp->saveent.de,idp->saveoff)) != 0) 382 return (error); 383 idp->saveent.de.d_namlen = 0; 384 } 385 } 386 } 387 if (assoc) { 388 idp->assocoff = idp->curroff; 389 bcopy(&idp->current,&idp->assocent,_DIRENT_DIRSIZ(&idp->current.de)); 390 } else { 391 idp->saveoff = idp->curroff; 392 bcopy(&idp->current,&idp->saveent,_DIRENT_DIRSIZ(&idp->current.de)); 393 } 394 return (0); 395 } 396 397 /* 398 * Vnode op for readdir 399 * 400 * cd9660_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred, 401 * int *a_eofflag, int *a_ncookies, off_t *a_cookies) 402 */ 403 static int 404 cd9660_readdir(struct vop_readdir_args *ap) 405 { 406 struct uio *uio = ap->a_uio; 407 struct isoreaddir *idp; 408 struct vnode *vdp = ap->a_vp; 409 struct iso_node *dp; 410 struct iso_mnt *imp; 411 struct buf *bp = NULL; 412 struct iso_directory_record *ep; 413 int entryoffsetinblock; 414 doff_t endsearch; 415 u_long bmask; 416 int error = 0; 417 int reclen; 418 u_short namelen; 419 int ncookies = 0; 420 off_t *cookies = NULL; 421 422 dp = VTOI(vdp); 423 imp = dp->i_mnt; 424 bmask = imp->im_bmask; 425 426 error = vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY | LK_FAILRECLAIM); 427 if (error) 428 return (error); 429 430 idp = kmalloc(sizeof(*idp), M_TEMP, M_WAITOK); 431 idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0; 432 /* 433 * XXX 434 * Is it worth trying to figure out the type? 435 */ 436 idp->saveent.de.d_type = DT_UNKNOWN; 437 idp->assocent.de.d_type = DT_UNKNOWN; 438 idp->current.de.d_type = DT_UNKNOWN; 439 idp->uio = uio; 440 if (ap->a_ncookies == NULL) { 441 idp->cookies = NULL; 442 } else { 443 /* 444 * Guess the number of cookies needed. Guess at least 445 * 1 to avoid a degenerate case in malloc, and cap at 446 * a reasonable limit. 447 */ 448 ncookies = uio->uio_resid / 16 + 1; 449 if (ncookies > 1024) 450 ncookies = 1024; 451 cookies = kmalloc(ncookies * sizeof(off_t), M_TEMP, M_WAITOK); 452 idp->cookies = cookies; 453 idp->ncookies = ncookies; 454 } 455 idp->eofflag = 1; 456 idp->curroff = uio->uio_offset; 457 458 if ((entryoffsetinblock = idp->curroff & bmask) && 459 (error = cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp))) { 460 kfree(idp, M_TEMP); 461 goto done; 462 } 463 endsearch = dp->i_size; 464 465 while (idp->curroff < endsearch) { 466 /* 467 * If offset is on a block boundary, 468 * read the next directory block. 469 * Release previous if it exists. 470 */ 471 if ((idp->curroff & bmask) == 0) { 472 if (bp != NULL) 473 brelse(bp); 474 if ((error = 475 cd9660_devblkatoff(vdp, idp->curroff, NULL, &bp)) != 0) 476 break; 477 entryoffsetinblock = 0; 478 } 479 /* 480 * Get pointer to next entry. 481 */ 482 ep = (struct iso_directory_record *) 483 ((char *)bp->b_data + entryoffsetinblock); 484 485 reclen = isonum_711(ep->length); 486 if (reclen == 0) { 487 /* skip to next block, if any */ 488 idp->curroff = 489 (idp->curroff & ~bmask) + imp->logical_block_size; 490 continue; 491 } 492 493 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 494 error = EINVAL; 495 /* illegal entry, stop */ 496 break; 497 } 498 499 if (entryoffsetinblock + reclen > imp->logical_block_size) { 500 error = EINVAL; 501 /* illegal directory, so stop looking */ 502 break; 503 } 504 505 idp->current.de.d_namlen = isonum_711(ep->name_len); 506 507 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.de.d_namlen) { 508 error = EINVAL; 509 /* illegal entry, stop */ 510 break; 511 } 512 513 if (isonum_711(ep->flags)&2) 514 idp->current.de.d_ino = isodirino(ep, imp); 515 else 516 idp->current.de.d_ino = bp->b_bio1.bio_offset + 517 entryoffsetinblock; 518 519 idp->curroff += reclen; 520 521 switch (imp->iso_ftype) { 522 case ISO_FTYPE_RRIP: 523 { 524 ino_t cur_fileno = idp->current.de.d_ino; 525 cd9660_rrip_getname(ep,idp->current.de.d_name, &namelen, 526 &cur_fileno,imp); 527 idp->current.de.d_ino = cur_fileno; 528 idp->current.de.d_namlen = namelen; 529 if (idp->current.de.d_namlen) 530 error = iso_uiodir(idp,&idp->current.de,idp->curroff); 531 break; 532 } 533 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 534 strcpy(idp->current.de.d_name,".."); 535 if (idp->current.de.d_namlen == 1 && ep->name[0] == 0) { 536 idp->current.de.d_namlen = 1; 537 error = iso_uiodir(idp,&idp->current.de,idp->curroff); 538 } else if (idp->current.de.d_namlen == 1 && ep->name[0] == 1) { 539 idp->current.de.d_namlen = 2; 540 error = iso_uiodir(idp,&idp->current.de,idp->curroff); 541 } else { 542 isofntrans(ep->name,idp->current.de.d_namlen, 543 idp->current.de.d_name, &namelen, 544 imp->iso_ftype == ISO_FTYPE_9660, 545 isonum_711(ep->flags)&4, 546 imp->joliet_level, 547 imp->im_flags, 548 imp->im_d2l); 549 idp->current.de.d_namlen = namelen; 550 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 551 error = iso_shipdir(idp); 552 else 553 error = iso_uiodir(idp,&idp->current.de,idp->curroff); 554 } 555 } 556 if (error) 557 break; 558 559 entryoffsetinblock += reclen; 560 } 561 562 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 563 idp->current.de.d_namlen = 0; 564 error = iso_shipdir(idp); 565 } 566 if (error < 0) 567 error = 0; 568 569 if (ap->a_ncookies != NULL) { 570 if (error) 571 kfree(cookies, M_TEMP); 572 else { 573 /* 574 * Work out the number of cookies actually used. 575 */ 576 *ap->a_ncookies = ncookies - idp->ncookies; 577 *ap->a_cookies = cookies; 578 } 579 } 580 581 if (bp) 582 brelse (bp); 583 584 uio->uio_offset = idp->uio_off; 585 *ap->a_eofflag = idp->eofflag; 586 587 kfree(idp, M_TEMP); 588 589 done: 590 vn_unlock(vdp); 591 return (error); 592 } 593 594 /* 595 * Return target name of a symbolic link 596 * Shouldn't we get the parent vnode and read the data from there? 597 * This could eventually result in deadlocks in cd9660_lookup. 598 * But otherwise the block read here is in the block buffer two times. 599 */ 600 typedef struct iso_directory_record ISODIR; 601 typedef struct iso_node ISONODE; 602 typedef struct iso_mnt ISOMNT; 603 /* 604 * cd9660_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred) 605 */ 606 static int 607 cd9660_readlink(struct vop_readlink_args *ap) 608 { 609 ISONODE *ip; 610 ISODIR *dirp; 611 ISOMNT *imp; 612 struct buf *bp; 613 struct uio *uio; 614 u_short symlen; 615 int error; 616 char *symname; 617 618 ip = VTOI(ap->a_vp); 619 imp = ip->i_mnt; 620 uio = ap->a_uio; 621 622 if (imp->iso_ftype != ISO_FTYPE_RRIP) 623 return (EINVAL); 624 625 /* 626 * Get parents directory record block that this inode included. 627 */ 628 error = bread(imp->im_devvp, 629 (off_t)ip->i_number & ~((1 << imp->im_bshift) - 1), 630 imp->logical_block_size, &bp); 631 if (error) { 632 brelse(bp); 633 return (EINVAL); 634 } 635 636 /* 637 * Setup the directory pointer for this inode 638 */ 639 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 640 641 /* 642 * Just make sure, we have a right one.... 643 * 1: Check not cross boundary on block 644 */ 645 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 646 > (unsigned)imp->logical_block_size) { 647 brelse(bp); 648 return (EINVAL); 649 } 650 651 /* 652 * Now get a buffer 653 * Abuse a namei buffer for now. 654 */ 655 if (uio->uio_segflg == UIO_SYSSPACE) 656 symname = uio->uio_iov->iov_base; 657 else 658 symname = objcache_get(namei_oc, M_WAITOK); 659 660 /* 661 * Ok, we just gathering a symbolic name in SL record. 662 */ 663 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 664 if (uio->uio_segflg != UIO_SYSSPACE) 665 objcache_put(namei_oc, symname); 666 brelse(bp); 667 return (EINVAL); 668 } 669 /* 670 * Don't forget before you leave from home ;-) 671 */ 672 brelse(bp); 673 674 /* 675 * return with the symbolic name to caller's. 676 */ 677 if (uio->uio_segflg != UIO_SYSSPACE) { 678 error = uiomove(symname, symlen, uio); 679 objcache_put(namei_oc, symname); 680 return (error); 681 } 682 uio->uio_resid -= symlen; 683 uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 684 uio->uio_iov->iov_len -= symlen; 685 return (0); 686 } 687 688 /* 689 * Calculate the logical to physical mapping if not done already, 690 * then call the device strategy routine. 691 * 692 * cd9660_strategy(struct buf *a_vp, struct buf *a_bio) 693 */ 694 static int 695 cd9660_strategy(struct vop_strategy_args *ap) 696 { 697 struct bio *bio = ap->a_bio; 698 struct bio *nbio; 699 struct buf *bp = bio->bio_buf; 700 struct vnode *vp = ap->a_vp; 701 struct iso_node *ip; 702 int error; 703 704 ip = VTOI(vp); 705 if (vp->v_type == VBLK || vp->v_type == VCHR) 706 panic("cd9660_strategy: spec"); 707 nbio = push_bio(bio); 708 if (nbio->bio_offset == NOOFFSET) { 709 error = VOP_BMAP(vp, bio->bio_offset, 710 &nbio->bio_offset, NULL, NULL, bp->b_cmd); 711 if (error) { 712 bp->b_error = error; 713 bp->b_flags |= B_ERROR; 714 /* I/O was never started on nbio, must biodone(bio) */ 715 biodone(bio); 716 return (error); 717 } 718 if (nbio->bio_offset == NOOFFSET) 719 clrbuf(bp); 720 } 721 if (nbio->bio_offset == NOOFFSET) { 722 /* I/O was never started on nbio, must biodone(bio) */ 723 biodone(bio); 724 return (0); 725 } 726 vp = ip->i_devvp; 727 vn_strategy(vp, nbio); 728 return (0); 729 } 730 731 /* 732 * Print out the contents of an inode. 733 * 734 * cd9660_print(struct vnode *a_vp) 735 */ 736 static int 737 cd9660_print(struct vop_print_args *ap) 738 { 739 kprintf("tag VT_ISOFS, isofs vnode\n"); 740 return (0); 741 } 742 743 /* 744 * Return POSIX pathconf information applicable to cd9660 filesystems. 745 * 746 * cd9660_pathconf(struct vnode *a_vp, int a_name, register_t *a_retval) 747 */ 748 static int 749 cd9660_pathconf(struct vop_pathconf_args *ap) 750 { 751 switch (ap->a_name) { 752 case _PC_LINK_MAX: 753 *ap->a_retval = 1; 754 return (0); 755 case _PC_NAME_MAX: 756 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 757 *ap->a_retval = NAME_MAX; 758 else 759 *ap->a_retval = 37; 760 return (0); 761 case _PC_PATH_MAX: 762 *ap->a_retval = PATH_MAX; 763 return (0); 764 case _PC_PIPE_BUF: 765 *ap->a_retval = PIPE_BUF; 766 return (0); 767 case _PC_CHOWN_RESTRICTED: 768 *ap->a_retval = 1; 769 return (0); 770 case _PC_NO_TRUNC: 771 *ap->a_retval = 1; 772 return (0); 773 default: 774 return (EINVAL); 775 } 776 /* NOTREACHED */ 777 } 778 779 /* 780 * Advisory lock support 781 */ 782 static int 783 cd9660_advlock(struct vop_advlock_args *ap) 784 { 785 struct iso_node *ip = VTOI(ap->a_vp); 786 return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); 787 } 788 789 /* 790 * Global vfs data structures for cd9660 791 */ 792 struct vop_ops cd9660_vnode_vops = { 793 .vop_default = vop_defaultop, 794 .vop_open = cd9660_open, 795 .vop_access = cd9660_access, 796 .vop_advlock = cd9660_advlock, 797 .vop_bmap = cd9660_bmap, 798 .vop_old_lookup = cd9660_lookup, 799 .vop_getattr = cd9660_getattr, 800 .vop_inactive = cd9660_inactive, 801 .vop_ioctl = cd9660_ioctl, 802 .vop_pathconf = cd9660_pathconf, 803 .vop_print = cd9660_print, 804 .vop_read = cd9660_read, 805 .vop_readdir = cd9660_readdir, 806 .vop_readlink = cd9660_readlink, 807 .vop_reclaim = cd9660_reclaim, 808 .vop_setattr = cd9660_setattr, 809 .vop_strategy = cd9660_strategy, 810 .vop_getpages = vop_stdgetpages, 811 .vop_putpages = vop_stdputpages 812 }; 813 814 /* 815 * Special device vnode ops 816 */ 817 struct vop_ops cd9660_spec_vops = { 818 .vop_default = vop_defaultop, 819 .vop_read = vop_stdnoread, 820 .vop_access = cd9660_access, 821 .vop_getattr = cd9660_getattr, 822 .vop_inactive = cd9660_inactive, 823 .vop_print = cd9660_print, 824 .vop_reclaim = cd9660_reclaim, 825 .vop_setattr = cd9660_setattr, 826 }; 827 828 struct vop_ops cd9660_fifo_vops = { 829 .vop_default = fifo_vnoperate, 830 .vop_access = cd9660_access, 831 .vop_getattr = cd9660_getattr, 832 .vop_inactive = cd9660_inactive, 833 .vop_print = cd9660_print, 834 .vop_reclaim = cd9660_reclaim, 835 .vop_setattr = cd9660_setattr, 836 }; 837