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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
| 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. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95
|
39 * $Id: cd9660_vnops.c,v 1.51 1997/12/27 02:56:20 bde Exp $
| 39 * $Id: cd9660_vnops.c,v 1.52 1998/03/06 09:46:14 msmith Exp $
|
40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/namei.h> 45#include <sys/kernel.h> 46#include <sys/stat.h> 47#include <sys/buf.h> 48#include <sys/mount.h> 49#include <sys/vnode.h> 50#include <miscfs/specfs/specdev.h> 51#include <miscfs/fifofs/fifo.h> 52#include <sys/malloc.h> 53#include <sys/dirent.h> 54#include <sys/unistd.h> 55 56#include <vm/vm.h> 57#include <vm/vm_zone.h> 58#include <vm/vnode_pager.h> 59 60#include <isofs/cd9660/iso.h> 61#include <isofs/cd9660/cd9660_node.h> 62#include <isofs/cd9660/iso_rrip.h> 63 64static int cd9660_setattr __P((struct vop_setattr_args *)); 65static int cd9660_access __P((struct vop_access_args *)); 66static int cd9660_getattr __P((struct vop_getattr_args *)); 67static int cd9660_pathconf __P((struct vop_pathconf_args *)); 68static int cd9660_read __P((struct vop_read_args *)); 69struct isoreaddir; 70static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp, 71 off_t off)); 72static int iso_shipdir __P((struct isoreaddir *idp)); 73static int cd9660_readdir __P((struct vop_readdir_args *)); 74static int cd9660_readlink __P((struct vop_readlink_args *ap)); 75static int cd9660_abortop __P((struct vop_abortop_args *)); 76static int cd9660_strategy __P((struct vop_strategy_args *)); 77static int cd9660_print __P((struct vop_print_args *)); 78static int cd9660_getpages __P((struct vop_getpages_args *)); 79static int cd9660_putpages __P((struct vop_putpages_args *)); 80 81/* 82 * Setattr call. Only allowed for block and character special devices. 83 */ 84int 85cd9660_setattr(ap) 86 struct vop_setattr_args /* { 87 struct vnodeop_desc *a_desc; 88 struct vnode *a_vp; 89 struct vattr *a_vap; 90 struct ucred *a_cred; 91 struct proc *a_p; 92 } */ *ap; 93{ 94 struct vnode *vp = ap->a_vp; 95 struct vattr *vap = ap->a_vap; 96 97 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 98 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 99 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 100 return (EROFS); 101 if (vap->va_size != (u_quad_t)VNOVAL) { 102 switch (vp->v_type) { 103 case VDIR: 104 return (EISDIR); 105 case VLNK: 106 case VREG: 107 return (EROFS); 108 case VCHR: 109 case VBLK: 110 case VSOCK: 111 case VFIFO: 112 return (0); 113 } 114 } 115 return (0); 116} 117 118/* 119 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 120 * The mode is shifted to select the owner/group/other fields. The 121 * super user is granted all permissions. 122 */ 123/* ARGSUSED */ 124static int 125cd9660_access(ap) 126 struct vop_access_args /* { 127 struct vnode *a_vp; 128 int a_mode; 129 struct ucred *a_cred; 130 struct proc *a_p; 131 } */ *ap; 132{ 133 struct vnode *vp = ap->a_vp; 134 struct iso_node *ip = VTOI(vp); 135 struct ucred *cred = ap->a_cred; 136 mode_t mask, mode = ap->a_mode; 137 gid_t *gp; 138 int i; 139 140 /* 141 * Disallow write attempts unless the file is a socket, 142 * fifo, or a block or character device resident on the 143 * file system. 144 */ 145 if (mode & VWRITE) { 146 switch (vp->v_type) { 147 case VDIR: 148 case VLNK: 149 case VREG: 150 return (EROFS); 151 } 152 } 153 154 /* User id 0 always gets access. */ 155 if (cred->cr_uid == 0) 156 return (0); 157 158 mask = 0; 159 160 /* Otherwise, check the owner. */ 161 if (cred->cr_uid == ip->inode.iso_uid) { 162 if (mode & VEXEC) 163 mask |= S_IXUSR; 164 if (mode & VREAD) 165 mask |= S_IRUSR; 166 if (mode & VWRITE) 167 mask |= S_IWUSR; 168 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 169 } 170 171 /* Otherwise, check the groups. */ 172 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 173 if (ip->inode.iso_gid == *gp) { 174 if (mode & VEXEC) 175 mask |= S_IXGRP; 176 if (mode & VREAD) 177 mask |= S_IRGRP; 178 if (mode & VWRITE) 179 mask |= S_IWGRP; 180 return ((ip->inode.iso_mode & mask) == mask ? 181 0 : EACCES); 182 } 183 184 /* Otherwise, check everyone else. */ 185 if (mode & VEXEC) 186 mask |= S_IXOTH; 187 if (mode & VREAD) 188 mask |= S_IROTH; 189 if (mode & VWRITE) 190 mask |= S_IWOTH; 191 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 192} 193 194static int 195cd9660_getattr(ap) 196 struct vop_getattr_args /* { 197 struct vnode *a_vp; 198 struct vattr *a_vap; 199 struct ucred *a_cred; 200 struct proc *a_p; 201 } */ *ap; 202 203{ 204 struct vnode *vp = ap->a_vp; 205 register struct vattr *vap = ap->a_vap; 206 register struct iso_node *ip = VTOI(vp); 207 208 vap->va_fsid = ip->i_dev; 209 vap->va_fileid = ip->i_number; 210 211 vap->va_mode = ip->inode.iso_mode; 212 vap->va_nlink = ip->inode.iso_links; 213 vap->va_uid = ip->inode.iso_uid; 214 vap->va_gid = ip->inode.iso_gid; 215 vap->va_atime = ip->inode.iso_atime; 216 vap->va_mtime = ip->inode.iso_mtime; 217 vap->va_ctime = ip->inode.iso_ctime; 218 vap->va_rdev = ip->inode.iso_rdev; 219 220 vap->va_size = (u_quad_t) ip->i_size; 221 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 222 struct vop_readlink_args rdlnk; 223 struct iovec aiov; 224 struct uio auio; 225 char *cp; 226 227 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 228 aiov.iov_base = cp; 229 aiov.iov_len = MAXPATHLEN; 230 auio.uio_iov = &aiov; 231 auio.uio_iovcnt = 1; 232 auio.uio_offset = 0; 233 auio.uio_rw = UIO_READ; 234 auio.uio_segflg = UIO_SYSSPACE; 235 auio.uio_procp = ap->a_p; 236 auio.uio_resid = MAXPATHLEN; 237 rdlnk.a_uio = &auio; 238 rdlnk.a_vp = ap->a_vp; 239 rdlnk.a_cred = ap->a_cred; 240 if (cd9660_readlink(&rdlnk) == 0) 241 vap->va_size = MAXPATHLEN - auio.uio_resid; 242 FREE(cp, M_TEMP); 243 } 244 vap->va_flags = 0; 245 vap->va_gen = 1; 246 vap->va_blocksize = ip->i_mnt->logical_block_size; 247 vap->va_bytes = (u_quad_t) ip->i_size; 248 vap->va_type = vp->v_type; 249 vap->va_filerev = 0; 250 return (0); 251} 252 253/* 254 * Vnode op for reading. 255 */ 256static int 257cd9660_read(ap) 258 struct vop_read_args /* { 259 struct vnode *a_vp; 260 struct uio *a_uio; 261 int a_ioflag; 262 struct ucred *a_cred; 263 } */ *ap; 264{ 265 struct vnode *vp = ap->a_vp; 266 register struct uio *uio = ap->a_uio; 267 register struct iso_node *ip = VTOI(vp); 268 register struct iso_mnt *imp; 269 struct buf *bp; 270 daddr_t lbn, rablock; 271 off_t diff; 272 int rasize, error = 0; 273 long size, n, on; 274 275 if (uio->uio_resid == 0) 276 return (0); 277 if (uio->uio_offset < 0) 278 return (EINVAL); 279 ip->i_flag |= IN_ACCESS; 280 imp = ip->i_mnt; 281 do { 282 lbn = lblkno(imp, uio->uio_offset); 283 on = blkoff(imp, uio->uio_offset); 284 n = min((u_int)(imp->logical_block_size - on), 285 uio->uio_resid); 286 diff = (off_t)ip->i_size - uio->uio_offset; 287 if (diff <= 0) 288 return (0); 289 if (diff < n) 290 n = diff; 291 size = blksize(imp, ip, lbn); 292 rablock = lbn + 1; 293 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 294 if (lblktosize(imp, rablock) < ip->i_size) 295 error = cluster_read(vp, (off_t)ip->i_size, 296 lbn, size, NOCRED, uio->uio_resid, 297 (ap->a_ioflag >> 16), &bp); 298 else 299 error = bread(vp, lbn, size, NOCRED, &bp); 300 } else { 301 if (vp->v_lastr + 1 == lbn && 302 lblktosize(imp, rablock) < ip->i_size) { 303 rasize = blksize(imp, ip, rablock); 304 error = breadn(vp, lbn, size, &rablock, 305 &rasize, 1, NOCRED, &bp); 306 } else 307 error = bread(vp, lbn, size, NOCRED, &bp); 308 } 309 vp->v_lastr = lbn; 310 n = min(n, size - bp->b_resid); 311 if (error) { 312 brelse(bp); 313 return (error); 314 } 315 316 error = uiomove(bp->b_data + on, (int)n, uio); 317 brelse(bp); 318 } while (error == 0 && uio->uio_resid > 0 && n != 0); 319 return (error); 320} 321 322/* 323 * Structure for reading directories 324 */ 325struct isoreaddir { 326 struct dirent saveent; 327 struct dirent assocent; 328 struct dirent current; 329 off_t saveoff; 330 off_t assocoff; 331 off_t curroff; 332 struct uio *uio; 333 off_t uio_off; 334 int eofflag; 335 u_long *cookies; 336 int ncookies; 337}; 338 339int 340iso_uiodir(idp,dp,off) 341 struct isoreaddir *idp; 342 struct dirent *dp; 343 off_t off; 344{ 345 int error; 346 347 dp->d_name[dp->d_namlen] = 0; 348 dp->d_reclen = GENERIC_DIRSIZ(dp); 349 350 if (idp->uio->uio_resid < dp->d_reclen) { 351 idp->eofflag = 0; 352 return (-1); 353 } 354 355 if (idp->cookies) { 356 if (idp->ncookies <= 0) { 357 idp->eofflag = 0; 358 return (-1); 359 } 360 361 *idp->cookies++ = off; 362 --idp->ncookies; 363 } 364 365 if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) 366 return (error); 367 idp->uio_off = off; 368 return (0); 369} 370 371int 372iso_shipdir(idp) 373 struct isoreaddir *idp; 374{ 375 struct dirent *dp; 376 int cl, sl, assoc; 377 int error; 378 char *cname, *sname; 379 380 cl = idp->current.d_namlen; 381 cname = idp->current.d_name; 382assoc = (cl > 1) && (*cname == ASSOCCHAR); 383 if (assoc) { 384 cl--; 385 cname++; 386 } 387 388 dp = &idp->saveent; 389 sname = dp->d_name; 390 if (!(sl = dp->d_namlen)) { 391 dp = &idp->assocent; 392 sname = dp->d_name + 1; 393 sl = dp->d_namlen - 1; 394 } 395 if (sl > 0) { 396 if (sl != cl 397 || bcmp(sname,cname,sl)) { 398 if (idp->assocent.d_namlen) { 399 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) 400 return (error); 401 idp->assocent.d_namlen = 0; 402 } 403 if (idp->saveent.d_namlen) { 404 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) 405 return (error); 406 idp->saveent.d_namlen = 0; 407 } 408 } 409 } 410 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 411 if (assoc) { 412 idp->assocoff = idp->curroff; 413 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 414 } else { 415 idp->saveoff = idp->curroff; 416 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 417 } 418 return (0); 419} 420 421/* 422 * Vnode op for readdir 423 */ 424static int 425cd9660_readdir(ap) 426 struct vop_readdir_args /* { 427 struct vnode *a_vp; 428 struct uio *a_uio; 429 struct ucred *a_cred; 430 int *a_eofflag; 431 int *a_ncookies; 432 u_long *a_cookies; 433 } */ *ap; 434{ 435 register struct uio *uio = ap->a_uio; 436 struct isoreaddir *idp; 437 struct vnode *vdp = ap->a_vp; 438 struct iso_node *dp; 439 struct iso_mnt *imp; 440 struct buf *bp = NULL; 441 struct iso_directory_record *ep; 442 int entryoffsetinblock; 443 doff_t endsearch; 444 u_long bmask; 445 int error = 0; 446 int reclen; 447 u_short namelen; 448 int ncookies = 0; 449 u_long *cookies = NULL; 450 451 dp = VTOI(vdp); 452 imp = dp->i_mnt; 453 bmask = imp->im_bmask; 454 455 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 456 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 457 /* 458 * XXX 459 * Is it worth trying to figure out the type? 460 */ 461 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 462 DT_UNKNOWN; 463 idp->uio = uio; 464 if (ap->a_ncookies == NULL) { 465 idp->cookies = NULL; 466 } else { 467 /* 468 * Guess the number of cookies needed. 469 */ 470 ncookies = uio->uio_resid / 16; 471 MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 472 M_WAITOK); 473 idp->cookies = cookies; 474 idp->ncookies = ncookies; 475 } 476 idp->eofflag = 1; 477 idp->curroff = uio->uio_offset; 478 479 if ((entryoffsetinblock = idp->curroff & bmask) && 480 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 481 FREE(idp, M_TEMP); 482 return (error); 483 } 484 endsearch = dp->i_size; 485 486 while (idp->curroff < endsearch) { 487 /* 488 * If offset is on a block boundary, 489 * read the next directory block. 490 * Release previous if it exists. 491 */ 492 if ((idp->curroff & bmask) == 0) { 493 if (bp != NULL) 494 brelse(bp); 495 if (error = 496 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) 497 break; 498 entryoffsetinblock = 0; 499 } 500 /* 501 * Get pointer to next entry. 502 */ 503 ep = (struct iso_directory_record *) 504 ((char *)bp->b_data + entryoffsetinblock); 505 506 reclen = isonum_711(ep->length); 507 if (reclen == 0) { 508 /* skip to next block, if any */ 509 idp->curroff = 510 (idp->curroff & ~bmask) + imp->logical_block_size; 511 continue; 512 } 513 514 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 515 error = EINVAL; 516 /* illegal entry, stop */ 517 break; 518 } 519 520 if (entryoffsetinblock + reclen > imp->logical_block_size) { 521 error = EINVAL; 522 /* illegal directory, so stop looking */ 523 break; 524 } 525 526 idp->current.d_namlen = isonum_711(ep->name_len); 527 528 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 529 error = EINVAL; 530 /* illegal entry, stop */ 531 break; 532 } 533 534 if (isonum_711(ep->flags)&2) 535 idp->current.d_fileno = isodirino(ep, imp); 536 else 537 idp->current.d_fileno = dbtob(bp->b_blkno) + 538 entryoffsetinblock; 539 540 idp->curroff += reclen; 541 542 switch (imp->iso_ftype) { 543 case ISO_FTYPE_RRIP: 544 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 545 &idp->current.d_fileno,imp); 546 idp->current.d_namlen = (u_char)namelen; 547 if (idp->current.d_namlen) 548 error = iso_uiodir(idp,&idp->current,idp->curroff); 549 break; 550 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 551 strcpy(idp->current.d_name,".."); 552 switch (ep->name[0]) { 553 case 0: 554 idp->current.d_namlen = 1; 555 error = iso_uiodir(idp,&idp->current,idp->curroff); 556 break; 557 case 1: 558 idp->current.d_namlen = 2; 559 error = iso_uiodir(idp,&idp->current,idp->curroff); 560 break; 561 default: 562 isofntrans(ep->name,idp->current.d_namlen, 563 idp->current.d_name, &namelen, 564 imp->iso_ftype == ISO_FTYPE_9660, 565 isonum_711(ep->flags)&4); 566 idp->current.d_namlen = (u_char)namelen; 567 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 568 error = iso_shipdir(idp); 569 else 570 error = iso_uiodir(idp,&idp->current,idp->curroff); 571 break; 572 } 573 } 574 if (error) 575 break; 576 577 entryoffsetinblock += reclen; 578 } 579 580 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 581 idp->current.d_namlen = 0; 582 error = iso_shipdir(idp); 583 } 584 if (error < 0) 585 error = 0; 586 587 if (ap->a_ncookies != NULL) { 588 if (error) 589 free(cookies, M_TEMP); 590 else { 591 /* 592 * Work out the number of cookies actually used. 593 */ 594 *ap->a_ncookies = ncookies - idp->ncookies; 595 *ap->a_cookies = cookies; 596 } 597 } 598 599 if (bp) 600 brelse (bp); 601 602 uio->uio_offset = idp->uio_off; 603 *ap->a_eofflag = idp->eofflag; 604 605 FREE(idp, M_TEMP); 606 607 return (error); 608} 609 610/* 611 * Return target name of a symbolic link 612 * Shouldn't we get the parent vnode and read the data from there? 613 * This could eventually result in deadlocks in cd9660_lookup. 614 * But otherwise the block read here is in the block buffer two times. 615 */ 616typedef struct iso_directory_record ISODIR; 617typedef struct iso_node ISONODE; 618typedef struct iso_mnt ISOMNT; 619static int 620cd9660_readlink(ap) 621 struct vop_readlink_args /* { 622 struct vnode *a_vp; 623 struct uio *a_uio; 624 struct ucred *a_cred; 625 } */ *ap; 626{ 627 ISONODE *ip; 628 ISODIR *dirp; 629 ISOMNT *imp; 630 struct buf *bp; 631 struct uio *uio; 632 u_short symlen; 633 int error; 634 char *symname; 635 636 ip = VTOI(ap->a_vp); 637 imp = ip->i_mnt; 638 uio = ap->a_uio; 639 640 if (imp->iso_ftype != ISO_FTYPE_RRIP) 641 return (EINVAL); 642 643 /* 644 * Get parents directory record block that this inode included. 645 */ 646 error = bread(imp->im_devvp, 647 (ip->i_number >> imp->im_bshift) << 648 (imp->im_bshift - DEV_BSHIFT), 649 imp->logical_block_size, NOCRED, &bp); 650 if (error) { 651 brelse(bp); 652 return (EINVAL); 653 } 654 655 /* 656 * Setup the directory pointer for this inode 657 */ 658 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 659 660 /* 661 * Just make sure, we have a right one.... 662 * 1: Check not cross boundary on block 663 */ 664 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 665 > (unsigned)imp->logical_block_size) { 666 brelse(bp); 667 return (EINVAL); 668 } 669 670 /* 671 * Now get a buffer 672 * Abuse a namei buffer for now. 673 */ 674 if (uio->uio_segflg == UIO_SYSSPACE) 675 symname = uio->uio_iov->iov_base; 676 else 677 symname = zalloc(namei_zone); 678 679 /* 680 * Ok, we just gathering a symbolic name in SL record. 681 */ 682 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 683 if (uio->uio_segflg != UIO_SYSSPACE) 684 zfree(namei_zone, symname); 685 brelse(bp); 686 return (EINVAL); 687 } 688 /* 689 * Don't forget before you leave from home ;-) 690 */ 691 brelse(bp); 692 693 /* 694 * return with the symbolic name to caller's. 695 */ 696 if (uio->uio_segflg != UIO_SYSSPACE) { 697 error = uiomove(symname, symlen, uio); 698 zfree(namei_zone, symname); 699 return (error); 700 } 701 uio->uio_resid -= symlen; 702 uio->uio_iov->iov_base += symlen; 703 uio->uio_iov->iov_len -= symlen; 704 return (0); 705} 706 707/* 708 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 709 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 710 */ 711static int 712cd9660_abortop(ap) 713 struct vop_abortop_args /* { 714 struct vnode *a_dvp; 715 struct componentname *a_cnp; 716 } */ *ap; 717{ 718 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 719 zfree(namei_zone, ap->a_cnp->cn_pnbuf); 720 return (0); 721} 722 723/* 724 * Calculate the logical to physical mapping if not done already, 725 * then call the device strategy routine. 726 */ 727static int 728cd9660_strategy(ap) 729 struct vop_strategy_args /* {
| 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/namei.h> 45#include <sys/kernel.h> 46#include <sys/stat.h> 47#include <sys/buf.h> 48#include <sys/mount.h> 49#include <sys/vnode.h> 50#include <miscfs/specfs/specdev.h> 51#include <miscfs/fifofs/fifo.h> 52#include <sys/malloc.h> 53#include <sys/dirent.h> 54#include <sys/unistd.h> 55 56#include <vm/vm.h> 57#include <vm/vm_zone.h> 58#include <vm/vnode_pager.h> 59 60#include <isofs/cd9660/iso.h> 61#include <isofs/cd9660/cd9660_node.h> 62#include <isofs/cd9660/iso_rrip.h> 63 64static int cd9660_setattr __P((struct vop_setattr_args *)); 65static int cd9660_access __P((struct vop_access_args *)); 66static int cd9660_getattr __P((struct vop_getattr_args *)); 67static int cd9660_pathconf __P((struct vop_pathconf_args *)); 68static int cd9660_read __P((struct vop_read_args *)); 69struct isoreaddir; 70static int iso_uiodir __P((struct isoreaddir *idp, struct dirent *dp, 71 off_t off)); 72static int iso_shipdir __P((struct isoreaddir *idp)); 73static int cd9660_readdir __P((struct vop_readdir_args *)); 74static int cd9660_readlink __P((struct vop_readlink_args *ap)); 75static int cd9660_abortop __P((struct vop_abortop_args *)); 76static int cd9660_strategy __P((struct vop_strategy_args *)); 77static int cd9660_print __P((struct vop_print_args *)); 78static int cd9660_getpages __P((struct vop_getpages_args *)); 79static int cd9660_putpages __P((struct vop_putpages_args *)); 80 81/* 82 * Setattr call. Only allowed for block and character special devices. 83 */ 84int 85cd9660_setattr(ap) 86 struct vop_setattr_args /* { 87 struct vnodeop_desc *a_desc; 88 struct vnode *a_vp; 89 struct vattr *a_vap; 90 struct ucred *a_cred; 91 struct proc *a_p; 92 } */ *ap; 93{ 94 struct vnode *vp = ap->a_vp; 95 struct vattr *vap = ap->a_vap; 96 97 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 98 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 99 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 100 return (EROFS); 101 if (vap->va_size != (u_quad_t)VNOVAL) { 102 switch (vp->v_type) { 103 case VDIR: 104 return (EISDIR); 105 case VLNK: 106 case VREG: 107 return (EROFS); 108 case VCHR: 109 case VBLK: 110 case VSOCK: 111 case VFIFO: 112 return (0); 113 } 114 } 115 return (0); 116} 117 118/* 119 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 120 * The mode is shifted to select the owner/group/other fields. The 121 * super user is granted all permissions. 122 */ 123/* ARGSUSED */ 124static int 125cd9660_access(ap) 126 struct vop_access_args /* { 127 struct vnode *a_vp; 128 int a_mode; 129 struct ucred *a_cred; 130 struct proc *a_p; 131 } */ *ap; 132{ 133 struct vnode *vp = ap->a_vp; 134 struct iso_node *ip = VTOI(vp); 135 struct ucred *cred = ap->a_cred; 136 mode_t mask, mode = ap->a_mode; 137 gid_t *gp; 138 int i; 139 140 /* 141 * Disallow write attempts unless the file is a socket, 142 * fifo, or a block or character device resident on the 143 * file system. 144 */ 145 if (mode & VWRITE) { 146 switch (vp->v_type) { 147 case VDIR: 148 case VLNK: 149 case VREG: 150 return (EROFS); 151 } 152 } 153 154 /* User id 0 always gets access. */ 155 if (cred->cr_uid == 0) 156 return (0); 157 158 mask = 0; 159 160 /* Otherwise, check the owner. */ 161 if (cred->cr_uid == ip->inode.iso_uid) { 162 if (mode & VEXEC) 163 mask |= S_IXUSR; 164 if (mode & VREAD) 165 mask |= S_IRUSR; 166 if (mode & VWRITE) 167 mask |= S_IWUSR; 168 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 169 } 170 171 /* Otherwise, check the groups. */ 172 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 173 if (ip->inode.iso_gid == *gp) { 174 if (mode & VEXEC) 175 mask |= S_IXGRP; 176 if (mode & VREAD) 177 mask |= S_IRGRP; 178 if (mode & VWRITE) 179 mask |= S_IWGRP; 180 return ((ip->inode.iso_mode & mask) == mask ? 181 0 : EACCES); 182 } 183 184 /* Otherwise, check everyone else. */ 185 if (mode & VEXEC) 186 mask |= S_IXOTH; 187 if (mode & VREAD) 188 mask |= S_IROTH; 189 if (mode & VWRITE) 190 mask |= S_IWOTH; 191 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 192} 193 194static int 195cd9660_getattr(ap) 196 struct vop_getattr_args /* { 197 struct vnode *a_vp; 198 struct vattr *a_vap; 199 struct ucred *a_cred; 200 struct proc *a_p; 201 } */ *ap; 202 203{ 204 struct vnode *vp = ap->a_vp; 205 register struct vattr *vap = ap->a_vap; 206 register struct iso_node *ip = VTOI(vp); 207 208 vap->va_fsid = ip->i_dev; 209 vap->va_fileid = ip->i_number; 210 211 vap->va_mode = ip->inode.iso_mode; 212 vap->va_nlink = ip->inode.iso_links; 213 vap->va_uid = ip->inode.iso_uid; 214 vap->va_gid = ip->inode.iso_gid; 215 vap->va_atime = ip->inode.iso_atime; 216 vap->va_mtime = ip->inode.iso_mtime; 217 vap->va_ctime = ip->inode.iso_ctime; 218 vap->va_rdev = ip->inode.iso_rdev; 219 220 vap->va_size = (u_quad_t) ip->i_size; 221 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 222 struct vop_readlink_args rdlnk; 223 struct iovec aiov; 224 struct uio auio; 225 char *cp; 226 227 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 228 aiov.iov_base = cp; 229 aiov.iov_len = MAXPATHLEN; 230 auio.uio_iov = &aiov; 231 auio.uio_iovcnt = 1; 232 auio.uio_offset = 0; 233 auio.uio_rw = UIO_READ; 234 auio.uio_segflg = UIO_SYSSPACE; 235 auio.uio_procp = ap->a_p; 236 auio.uio_resid = MAXPATHLEN; 237 rdlnk.a_uio = &auio; 238 rdlnk.a_vp = ap->a_vp; 239 rdlnk.a_cred = ap->a_cred; 240 if (cd9660_readlink(&rdlnk) == 0) 241 vap->va_size = MAXPATHLEN - auio.uio_resid; 242 FREE(cp, M_TEMP); 243 } 244 vap->va_flags = 0; 245 vap->va_gen = 1; 246 vap->va_blocksize = ip->i_mnt->logical_block_size; 247 vap->va_bytes = (u_quad_t) ip->i_size; 248 vap->va_type = vp->v_type; 249 vap->va_filerev = 0; 250 return (0); 251} 252 253/* 254 * Vnode op for reading. 255 */ 256static int 257cd9660_read(ap) 258 struct vop_read_args /* { 259 struct vnode *a_vp; 260 struct uio *a_uio; 261 int a_ioflag; 262 struct ucred *a_cred; 263 } */ *ap; 264{ 265 struct vnode *vp = ap->a_vp; 266 register struct uio *uio = ap->a_uio; 267 register struct iso_node *ip = VTOI(vp); 268 register struct iso_mnt *imp; 269 struct buf *bp; 270 daddr_t lbn, rablock; 271 off_t diff; 272 int rasize, error = 0; 273 long size, n, on; 274 275 if (uio->uio_resid == 0) 276 return (0); 277 if (uio->uio_offset < 0) 278 return (EINVAL); 279 ip->i_flag |= IN_ACCESS; 280 imp = ip->i_mnt; 281 do { 282 lbn = lblkno(imp, uio->uio_offset); 283 on = blkoff(imp, uio->uio_offset); 284 n = min((u_int)(imp->logical_block_size - on), 285 uio->uio_resid); 286 diff = (off_t)ip->i_size - uio->uio_offset; 287 if (diff <= 0) 288 return (0); 289 if (diff < n) 290 n = diff; 291 size = blksize(imp, ip, lbn); 292 rablock = lbn + 1; 293 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 294 if (lblktosize(imp, rablock) < ip->i_size) 295 error = cluster_read(vp, (off_t)ip->i_size, 296 lbn, size, NOCRED, uio->uio_resid, 297 (ap->a_ioflag >> 16), &bp); 298 else 299 error = bread(vp, lbn, size, NOCRED, &bp); 300 } else { 301 if (vp->v_lastr + 1 == lbn && 302 lblktosize(imp, rablock) < ip->i_size) { 303 rasize = blksize(imp, ip, rablock); 304 error = breadn(vp, lbn, size, &rablock, 305 &rasize, 1, NOCRED, &bp); 306 } else 307 error = bread(vp, lbn, size, NOCRED, &bp); 308 } 309 vp->v_lastr = lbn; 310 n = min(n, size - bp->b_resid); 311 if (error) { 312 brelse(bp); 313 return (error); 314 } 315 316 error = uiomove(bp->b_data + on, (int)n, uio); 317 brelse(bp); 318 } while (error == 0 && uio->uio_resid > 0 && n != 0); 319 return (error); 320} 321 322/* 323 * Structure for reading directories 324 */ 325struct isoreaddir { 326 struct dirent saveent; 327 struct dirent assocent; 328 struct dirent current; 329 off_t saveoff; 330 off_t assocoff; 331 off_t curroff; 332 struct uio *uio; 333 off_t uio_off; 334 int eofflag; 335 u_long *cookies; 336 int ncookies; 337}; 338 339int 340iso_uiodir(idp,dp,off) 341 struct isoreaddir *idp; 342 struct dirent *dp; 343 off_t off; 344{ 345 int error; 346 347 dp->d_name[dp->d_namlen] = 0; 348 dp->d_reclen = GENERIC_DIRSIZ(dp); 349 350 if (idp->uio->uio_resid < dp->d_reclen) { 351 idp->eofflag = 0; 352 return (-1); 353 } 354 355 if (idp->cookies) { 356 if (idp->ncookies <= 0) { 357 idp->eofflag = 0; 358 return (-1); 359 } 360 361 *idp->cookies++ = off; 362 --idp->ncookies; 363 } 364 365 if (error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) 366 return (error); 367 idp->uio_off = off; 368 return (0); 369} 370 371int 372iso_shipdir(idp) 373 struct isoreaddir *idp; 374{ 375 struct dirent *dp; 376 int cl, sl, assoc; 377 int error; 378 char *cname, *sname; 379 380 cl = idp->current.d_namlen; 381 cname = idp->current.d_name; 382assoc = (cl > 1) && (*cname == ASSOCCHAR); 383 if (assoc) { 384 cl--; 385 cname++; 386 } 387 388 dp = &idp->saveent; 389 sname = dp->d_name; 390 if (!(sl = dp->d_namlen)) { 391 dp = &idp->assocent; 392 sname = dp->d_name + 1; 393 sl = dp->d_namlen - 1; 394 } 395 if (sl > 0) { 396 if (sl != cl 397 || bcmp(sname,cname,sl)) { 398 if (idp->assocent.d_namlen) { 399 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) 400 return (error); 401 idp->assocent.d_namlen = 0; 402 } 403 if (idp->saveent.d_namlen) { 404 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) 405 return (error); 406 idp->saveent.d_namlen = 0; 407 } 408 } 409 } 410 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 411 if (assoc) { 412 idp->assocoff = idp->curroff; 413 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 414 } else { 415 idp->saveoff = idp->curroff; 416 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 417 } 418 return (0); 419} 420 421/* 422 * Vnode op for readdir 423 */ 424static int 425cd9660_readdir(ap) 426 struct vop_readdir_args /* { 427 struct vnode *a_vp; 428 struct uio *a_uio; 429 struct ucred *a_cred; 430 int *a_eofflag; 431 int *a_ncookies; 432 u_long *a_cookies; 433 } */ *ap; 434{ 435 register struct uio *uio = ap->a_uio; 436 struct isoreaddir *idp; 437 struct vnode *vdp = ap->a_vp; 438 struct iso_node *dp; 439 struct iso_mnt *imp; 440 struct buf *bp = NULL; 441 struct iso_directory_record *ep; 442 int entryoffsetinblock; 443 doff_t endsearch; 444 u_long bmask; 445 int error = 0; 446 int reclen; 447 u_short namelen; 448 int ncookies = 0; 449 u_long *cookies = NULL; 450 451 dp = VTOI(vdp); 452 imp = dp->i_mnt; 453 bmask = imp->im_bmask; 454 455 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 456 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 457 /* 458 * XXX 459 * Is it worth trying to figure out the type? 460 */ 461 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 462 DT_UNKNOWN; 463 idp->uio = uio; 464 if (ap->a_ncookies == NULL) { 465 idp->cookies = NULL; 466 } else { 467 /* 468 * Guess the number of cookies needed. 469 */ 470 ncookies = uio->uio_resid / 16; 471 MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 472 M_WAITOK); 473 idp->cookies = cookies; 474 idp->ncookies = ncookies; 475 } 476 idp->eofflag = 1; 477 idp->curroff = uio->uio_offset; 478 479 if ((entryoffsetinblock = idp->curroff & bmask) && 480 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 481 FREE(idp, M_TEMP); 482 return (error); 483 } 484 endsearch = dp->i_size; 485 486 while (idp->curroff < endsearch) { 487 /* 488 * If offset is on a block boundary, 489 * read the next directory block. 490 * Release previous if it exists. 491 */ 492 if ((idp->curroff & bmask) == 0) { 493 if (bp != NULL) 494 brelse(bp); 495 if (error = 496 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) 497 break; 498 entryoffsetinblock = 0; 499 } 500 /* 501 * Get pointer to next entry. 502 */ 503 ep = (struct iso_directory_record *) 504 ((char *)bp->b_data + entryoffsetinblock); 505 506 reclen = isonum_711(ep->length); 507 if (reclen == 0) { 508 /* skip to next block, if any */ 509 idp->curroff = 510 (idp->curroff & ~bmask) + imp->logical_block_size; 511 continue; 512 } 513 514 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 515 error = EINVAL; 516 /* illegal entry, stop */ 517 break; 518 } 519 520 if (entryoffsetinblock + reclen > imp->logical_block_size) { 521 error = EINVAL; 522 /* illegal directory, so stop looking */ 523 break; 524 } 525 526 idp->current.d_namlen = isonum_711(ep->name_len); 527 528 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 529 error = EINVAL; 530 /* illegal entry, stop */ 531 break; 532 } 533 534 if (isonum_711(ep->flags)&2) 535 idp->current.d_fileno = isodirino(ep, imp); 536 else 537 idp->current.d_fileno = dbtob(bp->b_blkno) + 538 entryoffsetinblock; 539 540 idp->curroff += reclen; 541 542 switch (imp->iso_ftype) { 543 case ISO_FTYPE_RRIP: 544 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 545 &idp->current.d_fileno,imp); 546 idp->current.d_namlen = (u_char)namelen; 547 if (idp->current.d_namlen) 548 error = iso_uiodir(idp,&idp->current,idp->curroff); 549 break; 550 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 551 strcpy(idp->current.d_name,".."); 552 switch (ep->name[0]) { 553 case 0: 554 idp->current.d_namlen = 1; 555 error = iso_uiodir(idp,&idp->current,idp->curroff); 556 break; 557 case 1: 558 idp->current.d_namlen = 2; 559 error = iso_uiodir(idp,&idp->current,idp->curroff); 560 break; 561 default: 562 isofntrans(ep->name,idp->current.d_namlen, 563 idp->current.d_name, &namelen, 564 imp->iso_ftype == ISO_FTYPE_9660, 565 isonum_711(ep->flags)&4); 566 idp->current.d_namlen = (u_char)namelen; 567 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 568 error = iso_shipdir(idp); 569 else 570 error = iso_uiodir(idp,&idp->current,idp->curroff); 571 break; 572 } 573 } 574 if (error) 575 break; 576 577 entryoffsetinblock += reclen; 578 } 579 580 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 581 idp->current.d_namlen = 0; 582 error = iso_shipdir(idp); 583 } 584 if (error < 0) 585 error = 0; 586 587 if (ap->a_ncookies != NULL) { 588 if (error) 589 free(cookies, M_TEMP); 590 else { 591 /* 592 * Work out the number of cookies actually used. 593 */ 594 *ap->a_ncookies = ncookies - idp->ncookies; 595 *ap->a_cookies = cookies; 596 } 597 } 598 599 if (bp) 600 brelse (bp); 601 602 uio->uio_offset = idp->uio_off; 603 *ap->a_eofflag = idp->eofflag; 604 605 FREE(idp, M_TEMP); 606 607 return (error); 608} 609 610/* 611 * Return target name of a symbolic link 612 * Shouldn't we get the parent vnode and read the data from there? 613 * This could eventually result in deadlocks in cd9660_lookup. 614 * But otherwise the block read here is in the block buffer two times. 615 */ 616typedef struct iso_directory_record ISODIR; 617typedef struct iso_node ISONODE; 618typedef struct iso_mnt ISOMNT; 619static int 620cd9660_readlink(ap) 621 struct vop_readlink_args /* { 622 struct vnode *a_vp; 623 struct uio *a_uio; 624 struct ucred *a_cred; 625 } */ *ap; 626{ 627 ISONODE *ip; 628 ISODIR *dirp; 629 ISOMNT *imp; 630 struct buf *bp; 631 struct uio *uio; 632 u_short symlen; 633 int error; 634 char *symname; 635 636 ip = VTOI(ap->a_vp); 637 imp = ip->i_mnt; 638 uio = ap->a_uio; 639 640 if (imp->iso_ftype != ISO_FTYPE_RRIP) 641 return (EINVAL); 642 643 /* 644 * Get parents directory record block that this inode included. 645 */ 646 error = bread(imp->im_devvp, 647 (ip->i_number >> imp->im_bshift) << 648 (imp->im_bshift - DEV_BSHIFT), 649 imp->logical_block_size, NOCRED, &bp); 650 if (error) { 651 brelse(bp); 652 return (EINVAL); 653 } 654 655 /* 656 * Setup the directory pointer for this inode 657 */ 658 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 659 660 /* 661 * Just make sure, we have a right one.... 662 * 1: Check not cross boundary on block 663 */ 664 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 665 > (unsigned)imp->logical_block_size) { 666 brelse(bp); 667 return (EINVAL); 668 } 669 670 /* 671 * Now get a buffer 672 * Abuse a namei buffer for now. 673 */ 674 if (uio->uio_segflg == UIO_SYSSPACE) 675 symname = uio->uio_iov->iov_base; 676 else 677 symname = zalloc(namei_zone); 678 679 /* 680 * Ok, we just gathering a symbolic name in SL record. 681 */ 682 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 683 if (uio->uio_segflg != UIO_SYSSPACE) 684 zfree(namei_zone, symname); 685 brelse(bp); 686 return (EINVAL); 687 } 688 /* 689 * Don't forget before you leave from home ;-) 690 */ 691 brelse(bp); 692 693 /* 694 * return with the symbolic name to caller's. 695 */ 696 if (uio->uio_segflg != UIO_SYSSPACE) { 697 error = uiomove(symname, symlen, uio); 698 zfree(namei_zone, symname); 699 return (error); 700 } 701 uio->uio_resid -= symlen; 702 uio->uio_iov->iov_base += symlen; 703 uio->uio_iov->iov_len -= symlen; 704 return (0); 705} 706 707/* 708 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 709 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 710 */ 711static int 712cd9660_abortop(ap) 713 struct vop_abortop_args /* { 714 struct vnode *a_dvp; 715 struct componentname *a_cnp; 716 } */ *ap; 717{ 718 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 719 zfree(namei_zone, ap->a_cnp->cn_pnbuf); 720 return (0); 721} 722 723/* 724 * Calculate the logical to physical mapping if not done already, 725 * then call the device strategy routine. 726 */ 727static int 728cd9660_strategy(ap) 729 struct vop_strategy_args /* {
|
| 730 struct buf *a_vp;
|
730 struct buf *a_bp; 731 } */ *ap; 732{ 733 register struct buf *bp = ap->a_bp; 734 register struct vnode *vp = bp->b_vp; 735 register struct iso_node *ip; 736 int error; 737 738 ip = VTOI(vp); 739 if (vp->v_type == VBLK || vp->v_type == VCHR) 740 panic("cd9660_strategy: spec"); 741 if (bp->b_blkno == bp->b_lblkno) { 742 if ((error = 743 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) { 744 bp->b_error = error; 745 bp->b_flags |= B_ERROR; 746 biodone(bp); 747 return (error); 748 } 749 if ((long)bp->b_blkno == -1) 750 clrbuf(bp); 751 } 752 if ((long)bp->b_blkno == -1) { 753 biodone(bp); 754 return (0); 755 } 756 vp = ip->i_devvp; 757 bp->b_dev = vp->v_rdev;
| 731 struct buf *a_bp; 732 } */ *ap; 733{ 734 register struct buf *bp = ap->a_bp; 735 register struct vnode *vp = bp->b_vp; 736 register struct iso_node *ip; 737 int error; 738 739 ip = VTOI(vp); 740 if (vp->v_type == VBLK || vp->v_type == VCHR) 741 panic("cd9660_strategy: spec"); 742 if (bp->b_blkno == bp->b_lblkno) { 743 if ((error = 744 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL))) { 745 bp->b_error = error; 746 bp->b_flags |= B_ERROR; 747 biodone(bp); 748 return (error); 749 } 750 if ((long)bp->b_blkno == -1) 751 clrbuf(bp); 752 } 753 if ((long)bp->b_blkno == -1) { 754 biodone(bp); 755 return (0); 756 } 757 vp = ip->i_devvp; 758 bp->b_dev = vp->v_rdev;
|
758 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
| 759 VOP_STRATEGY(vp, bp);
|
759 return (0); 760} 761 762/* 763 * Print out the contents of an inode. 764 */ 765static int 766cd9660_print(ap) 767 struct vop_print_args /* { 768 struct vnode *a_vp; 769 } */ *ap; 770{ 771 772 printf("tag VT_ISOFS, isofs vnode\n"); 773 return (0); 774} 775 776/* 777 * Return POSIX pathconf information applicable to cd9660 filesystems. 778 */ 779static int 780cd9660_pathconf(ap) 781 struct vop_pathconf_args /* { 782 struct vnode *a_vp; 783 int a_name; 784 register_t *a_retval; 785 } */ *ap; 786{ 787 788 switch (ap->a_name) { 789 case _PC_LINK_MAX: 790 *ap->a_retval = 1; 791 return (0); 792 case _PC_NAME_MAX: 793 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 794 *ap->a_retval = NAME_MAX; 795 else 796 *ap->a_retval = 37; 797 return (0); 798 case _PC_PATH_MAX: 799 *ap->a_retval = PATH_MAX; 800 return (0); 801 case _PC_PIPE_BUF: 802 *ap->a_retval = PIPE_BUF; 803 return (0); 804 case _PC_CHOWN_RESTRICTED: 805 *ap->a_retval = 1; 806 return (0); 807 case _PC_NO_TRUNC: 808 *ap->a_retval = 1; 809 return (0); 810 default: 811 return (EINVAL); 812 } 813 /* NOTREACHED */ 814} 815 816/* 817 * get page routine 818 * 819 * XXX By default, wimp out... note that a_offset is ignored (and always 820 * XXX has been). 821 */ 822int 823cd9660_getpages(ap) 824 struct vop_getpages_args *ap; 825{ 826 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, 827 ap->a_reqpage); 828} 829 830/* 831 * put page routine 832 * 833 * XXX By default, wimp out... note that a_offset is ignored (and always 834 * XXX has been). 835 */ 836int 837cd9660_putpages(ap) 838 struct vop_putpages_args *ap; 839{ 840 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, 841 ap->a_sync, ap->a_rtvals); 842} 843 844/* 845 * Global vfs data structures for cd9660 846 */ 847vop_t **cd9660_vnodeop_p; 848static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 849 { &vop_default_desc, (vop_t *) vop_defaultop }, 850 { &vop_abortop_desc, (vop_t *) cd9660_abortop }, 851 { &vop_access_desc, (vop_t *) cd9660_access }, 852 { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 853 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 854 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 855 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 856 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 857 { &vop_lock_desc, (vop_t *) vop_stdlock }, 858 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 859 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 860 { &vop_print_desc, (vop_t *) cd9660_print }, 861 { &vop_read_desc, (vop_t *) cd9660_read }, 862 { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 863 { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 864 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 865 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 866 { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 867 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 868 { &vop_getpages_desc, (vop_t *) cd9660_getpages }, 869 { &vop_putpages_desc, (vop_t *) cd9660_putpages }, 870 { NULL, NULL } 871}; 872static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 873 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 874VNODEOP_SET(cd9660_vnodeop_opv_desc); 875 876/* 877 * Special device vnode ops 878 */ 879vop_t **cd9660_specop_p; 880static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 881 { &vop_default_desc, (vop_t *) spec_vnoperate }, 882 { &vop_access_desc, (vop_t *) cd9660_access }, 883 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 884 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 885 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 886 { &vop_lock_desc, (vop_t *) vop_stdlock }, 887 { &vop_print_desc, (vop_t *) cd9660_print }, 888 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 889 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 890 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 891 { NULL, NULL } 892}; 893static struct vnodeopv_desc cd9660_specop_opv_desc = 894 { &cd9660_specop_p, cd9660_specop_entries }; 895VNODEOP_SET(cd9660_specop_opv_desc); 896 897vop_t **cd9660_fifoop_p; 898static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 899 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 900 { &vop_access_desc, (vop_t *) cd9660_access }, 901 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 902 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 903 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 904 { &vop_lock_desc, (vop_t *) vop_stdlock }, 905 { &vop_print_desc, (vop_t *) cd9660_print }, 906 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 907 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 908 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 909 { NULL, NULL } 910}; 911static struct vnodeopv_desc cd9660_fifoop_opv_desc = 912 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 913 914VNODEOP_SET(cd9660_fifoop_opv_desc);
| 760 return (0); 761} 762 763/* 764 * Print out the contents of an inode. 765 */ 766static int 767cd9660_print(ap) 768 struct vop_print_args /* { 769 struct vnode *a_vp; 770 } */ *ap; 771{ 772 773 printf("tag VT_ISOFS, isofs vnode\n"); 774 return (0); 775} 776 777/* 778 * Return POSIX pathconf information applicable to cd9660 filesystems. 779 */ 780static int 781cd9660_pathconf(ap) 782 struct vop_pathconf_args /* { 783 struct vnode *a_vp; 784 int a_name; 785 register_t *a_retval; 786 } */ *ap; 787{ 788 789 switch (ap->a_name) { 790 case _PC_LINK_MAX: 791 *ap->a_retval = 1; 792 return (0); 793 case _PC_NAME_MAX: 794 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 795 *ap->a_retval = NAME_MAX; 796 else 797 *ap->a_retval = 37; 798 return (0); 799 case _PC_PATH_MAX: 800 *ap->a_retval = PATH_MAX; 801 return (0); 802 case _PC_PIPE_BUF: 803 *ap->a_retval = PIPE_BUF; 804 return (0); 805 case _PC_CHOWN_RESTRICTED: 806 *ap->a_retval = 1; 807 return (0); 808 case _PC_NO_TRUNC: 809 *ap->a_retval = 1; 810 return (0); 811 default: 812 return (EINVAL); 813 } 814 /* NOTREACHED */ 815} 816 817/* 818 * get page routine 819 * 820 * XXX By default, wimp out... note that a_offset is ignored (and always 821 * XXX has been). 822 */ 823int 824cd9660_getpages(ap) 825 struct vop_getpages_args *ap; 826{ 827 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, 828 ap->a_reqpage); 829} 830 831/* 832 * put page routine 833 * 834 * XXX By default, wimp out... note that a_offset is ignored (and always 835 * XXX has been). 836 */ 837int 838cd9660_putpages(ap) 839 struct vop_putpages_args *ap; 840{ 841 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, 842 ap->a_sync, ap->a_rtvals); 843} 844 845/* 846 * Global vfs data structures for cd9660 847 */ 848vop_t **cd9660_vnodeop_p; 849static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 850 { &vop_default_desc, (vop_t *) vop_defaultop }, 851 { &vop_abortop_desc, (vop_t *) cd9660_abortop }, 852 { &vop_access_desc, (vop_t *) cd9660_access }, 853 { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 854 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 855 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 856 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 857 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 858 { &vop_lock_desc, (vop_t *) vop_stdlock }, 859 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 860 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 861 { &vop_print_desc, (vop_t *) cd9660_print }, 862 { &vop_read_desc, (vop_t *) cd9660_read }, 863 { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 864 { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 865 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 866 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 867 { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 868 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 869 { &vop_getpages_desc, (vop_t *) cd9660_getpages }, 870 { &vop_putpages_desc, (vop_t *) cd9660_putpages }, 871 { NULL, NULL } 872}; 873static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 874 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 875VNODEOP_SET(cd9660_vnodeop_opv_desc); 876 877/* 878 * Special device vnode ops 879 */ 880vop_t **cd9660_specop_p; 881static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 882 { &vop_default_desc, (vop_t *) spec_vnoperate }, 883 { &vop_access_desc, (vop_t *) cd9660_access }, 884 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 885 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 886 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 887 { &vop_lock_desc, (vop_t *) vop_stdlock }, 888 { &vop_print_desc, (vop_t *) cd9660_print }, 889 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 890 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 891 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 892 { NULL, NULL } 893}; 894static struct vnodeopv_desc cd9660_specop_opv_desc = 895 { &cd9660_specop_p, cd9660_specop_entries }; 896VNODEOP_SET(cd9660_specop_opv_desc); 897 898vop_t **cd9660_fifoop_p; 899static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 900 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 901 { &vop_access_desc, (vop_t *) cd9660_access }, 902 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 903 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 904 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 905 { &vop_lock_desc, (vop_t *) vop_stdlock }, 906 { &vop_print_desc, (vop_t *) cd9660_print }, 907 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 908 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 909 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 910 { NULL, NULL } 911}; 912static struct vnodeopv_desc cd9660_fifoop_opv_desc = 913 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 914 915VNODEOP_SET(cd9660_fifoop_opv_desc);
|