|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* $NetBSD: cd9660_vnops.c,v 1.22 1994/12/27 19:05:12 mycroft Exp $ */ ! 23: ! 24: /*- ! 25: * Copyright (c) 1994 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * This code is derived from software contributed to Berkeley ! 29: * by Pace Willisson ([email protected]). The Rock Ridge Extension ! 30: * Support code is derived from software contributed to Berkeley ! 31: * by Atsushi Murai ([email protected]). ! 32: * ! 33: * Redistribution and use in source and binary forms, with or without ! 34: * modification, are permitted provided that the following conditions ! 35: * are met: ! 36: * 1. Redistributions of source code must retain the above copyright ! 37: * notice, this list of conditions and the following disclaimer. ! 38: * 2. Redistributions in binary form must reproduce the above copyright ! 39: * notice, this list of conditions and the following disclaimer in the ! 40: * documentation and/or other materials provided with the distribution. ! 41: * 3. All advertising materials mentioning features or use of this software ! 42: * must display the following acknowledgement: ! 43: * This product includes software developed by the University of ! 44: * California, Berkeley and its contributors. ! 45: * 4. Neither the name of the University nor the names of its contributors ! 46: * may be used to endorse or promote products derived from this software ! 47: * without specific prior written permission. ! 48: * ! 49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 59: * SUCH DAMAGE. ! 60: * ! 61: * @(#)cd9660_vnops.c 8.15 (Berkeley) 12/5/94 ! 62: * ! 63: * HISTORY ! 64: * 02-Feb-00 chw Add cd9660_copyfile to return error ! 65: * 29-Sep-98 djb Add cd9660_getattrlist VOP for VDI support. ! 66: * 15-sep-98 added cd9660_rmdir to do proper unlocking - chw ! 67: * 12-aug-98 added cd9660_remove which will do proper unlocking - chw ! 68: * 17-Feb-98 radar 1669467 - changed lock protocols to use the lock manager - chw ! 69: * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc ! 70: */ ! 71: ! 72: #include <sys/param.h> ! 73: #include <sys/systm.h> ! 74: #include <sys/namei.h> ! 75: #include <sys/resourcevar.h> ! 76: #include <sys/kernel.h> ! 77: #include <sys/file.h> ! 78: #include <sys/stat.h> ! 79: #include <sys/buf.h> ! 80: #include <sys/proc.h> ! 81: #include <sys/conf.h> ! 82: #include <sys/mount.h> ! 83: #include <sys/vnode.h> ! 84: #include <miscfs/specfs/specdev.h> ! 85: #include <miscfs/fifofs/fifo.h> ! 86: #include <sys/malloc.h> ! 87: #include <sys/dir.h> ! 88: #include <sys/attr.h> ! 89: #include <vfs/vfs_support.h> ! 90: ! 91: // radar 1669467 Using the lock manager now so include lock.h ! 92: #include <sys/lock.h> ! 93: ! 94: #include <isofs/cd9660/iso.h> ! 95: #include <isofs/cd9660/cd9660_node.h> ! 96: #include <isofs/cd9660/iso_rrip.h> ! 97: ! 98: ! 99: #if 0 ! 100: /* ! 101: * Mknod vnode call ! 102: * Actually remap the device number ! 103: */ ! 104: cd9660_mknod(ndp, vap, cred, p) ! 105: struct nameidata *ndp; ! 106: struct ucred *cred; ! 107: struct vattr *vap; ! 108: struct proc *p; ! 109: { ! 110: #ifndef ISODEVMAP ! 111: FREE_ZONE(ndp->ni_pnbuf, ndp->ni_pnlen, M_NAMEI); ! 112: vput(ndp->ni_dvp); ! 113: vput(ndp->ni_vp); ! 114: return (EINVAL); ! 115: #else ! 116: register struct vnode *vp; ! 117: struct iso_node *ip; ! 118: struct iso_dnode *dp; ! 119: int error; ! 120: ! 121: vp = ndp->ni_vp; ! 122: ip = VTOI(vp); ! 123: ! 124: if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP ! 125: || vap->va_type != vp->v_type ! 126: || (vap->va_type != VCHR && vap->va_type != VBLK)) { ! 127: FREE_ZONE(ndp->ni_pnbuf, ndp->ni_pnlen, M_NAMEI); ! 128: vput(ndp->ni_dvp); ! 129: vput(ndp->ni_vp); ! 130: return (EINVAL); ! 131: } ! 132: ! 133: dp = iso_dmap(ip->i_dev,ip->i_number,1); ! 134: if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) { ! 135: /* same as the unmapped one, delete the mapping */ ! 136: remque(dp); ! 137: FREE(dp,M_CACHE); ! 138: } else ! 139: /* enter new mapping */ ! 140: dp->d_dev = vap->va_rdev; ! 141: ! 142: /* ! 143: * Remove inode so that it will be reloaded by iget and ! 144: * checked to see if it is an alias of an existing entry ! 145: * in the inode cache. ! 146: */ ! 147: vput(vp); ! 148: vp->v_type = VNON; ! 149: vgone(vp); ! 150: return (0); ! 151: #endif ! 152: } ! 153: #endif ! 154: ! 155: /* ! 156: * Open called. ! 157: * ! 158: * Nothing to do. ! 159: */ ! 160: /* ARGSUSED */ ! 161: int ! 162: cd9660_open(ap) ! 163: struct vop_open_args /* { ! 164: struct vnode *a_vp; ! 165: int a_mode; ! 166: struct ucred *a_cred; ! 167: struct proc *a_p; ! 168: } */ *ap; ! 169: { ! 170: return (0); ! 171: } ! 172: ! 173: /* ! 174: * Close called ! 175: * ! 176: * Update the times on the inode on writeable file systems. ! 177: */ ! 178: /* ARGSUSED */ ! 179: int ! 180: cd9660_close(ap) ! 181: struct vop_close_args /* { ! 182: struct vnode *a_vp; ! 183: int a_fflag; ! 184: struct ucred *a_cred; ! 185: struct proc *a_p; ! 186: } */ *ap; ! 187: { ! 188: return (0); ! 189: } ! 190: ! 191: /* ! 192: * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. ! 193: * The mode is shifted to select the owner/group/other fields. The ! 194: * super user is granted all permissions. ! 195: */ ! 196: /* ARGSUSED */ ! 197: int ! 198: cd9660_access(ap) ! 199: struct vop_access_args /* { ! 200: struct vnode *a_vp; ! 201: int a_mode; ! 202: struct ucred *a_cred; ! 203: struct proc *a_p; ! 204: } */ *ap; ! 205: { ! 206: struct vnode *vp = ap->a_vp; ! 207: struct iso_node *ip = VTOI(vp); ! 208: struct ucred *cred = ap->a_cred; ! 209: mode_t mask, mode = ap->a_mode; ! 210: register gid_t *gp; ! 211: int i, error; ! 212: ! 213: /* ! 214: * Disallow write attempts on read-only file systems; ! 215: * unless the file is a socket, fifo, or a block or ! 216: * character device resident on the file system. ! 217: */ ! 218: if (mode & VWRITE) { ! 219: switch (vp->v_type) { ! 220: case VDIR: ! 221: case VLNK: ! 222: case VREG: ! 223: if (vp->v_mount->mnt_flag & MNT_RDONLY) ! 224: return (EROFS); ! 225: #if QUOTA ! 226: if ( (error = getinoquota(ip)) ) ! 227: return (error); ! 228: #endif ! 229: break; ! 230: default: // radar 1669467 - fix compiler warning ! 231: break; ! 232: } ! 233: } ! 234: ! 235: /* If immutable bit set, nobody gets to write it. */ ! 236: if ((mode & VWRITE) && (ip->i_flag & IMMUTABLE)) ! 237: return (EPERM); ! 238: ! 239: /* Otherwise, user id 0 always gets access. */ ! 240: if (cred->cr_uid == 0) ! 241: return (0); ! 242: ! 243: mask = 0; ! 244: ! 245: /* Otherwise, check the owner. */ ! 246: if (cred->cr_uid == ip->inode.iso_uid) { ! 247: if (mode & VEXEC) ! 248: mask |= S_IXUSR; ! 249: if (mode & VREAD) ! 250: mask |= S_IRUSR; ! 251: if (mode & VWRITE) ! 252: mask |= S_IWUSR; ! 253: return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); ! 254: } ! 255: ! 256: /* Otherwise, check the groups. */ ! 257: for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) ! 258: if (ip->inode.iso_gid == *gp) { ! 259: if (mode & VEXEC) ! 260: mask |= S_IXGRP; ! 261: if (mode & VREAD) ! 262: mask |= S_IRGRP; ! 263: if (mode & VWRITE) ! 264: mask |= S_IWGRP; ! 265: return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); ! 266: } ! 267: ! 268: /* Otherwise, check everyone else. */ ! 269: if (mode & VEXEC) ! 270: mask |= S_IXOTH; ! 271: if (mode & VREAD) ! 272: mask |= S_IROTH; ! 273: if (mode & VWRITE) ! 274: mask |= S_IWOTH; ! 275: return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); ! 276: } ! 277: ! 278: int ! 279: cd9660_getattr(ap) ! 280: struct vop_getattr_args /* { ! 281: struct vnode *a_vp; ! 282: struct vattr *a_vap; ! 283: struct ucred *a_cred; ! 284: struct proc *a_p; ! 285: } */ *ap; ! 286: ! 287: { ! 288: struct vnode *vp = ap->a_vp; ! 289: register struct vattr *vap = ap->a_vap; ! 290: register struct iso_node *ip = VTOI(vp); ! 291: ! 292: vap->va_fsid = ip->i_dev; ! 293: vap->va_fileid = ip->i_number; ! 294: ! 295: vap->va_mode = ip->inode.iso_mode; ! 296: vap->va_nlink = ip->inode.iso_links; ! 297: vap->va_uid = ip->inode.iso_uid; ! 298: vap->va_gid = ip->inode.iso_gid; ! 299: vap->va_atime = ip->inode.iso_atime; ! 300: vap->va_mtime = ip->inode.iso_mtime; ! 301: vap->va_ctime = ip->inode.iso_ctime; ! 302: vap->va_rdev = ip->inode.iso_rdev; ! 303: ! 304: vap->va_size = (u_quad_t) ip->i_size; ! 305: if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { ! 306: struct vop_readlink_args rdlnk; ! 307: struct iovec aiov; ! 308: struct uio auio; ! 309: char *cp; ! 310: ! 311: MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); ! 312: aiov.iov_base = cp; ! 313: aiov.iov_len = MAXPATHLEN; ! 314: auio.uio_iov = &aiov; ! 315: auio.uio_iovcnt = 1; ! 316: auio.uio_offset = 0; ! 317: auio.uio_rw = UIO_READ; ! 318: auio.uio_segflg = UIO_SYSSPACE; ! 319: auio.uio_procp = ap->a_p; ! 320: auio.uio_resid = MAXPATHLEN; ! 321: rdlnk.a_uio = &auio; ! 322: rdlnk.a_vp = ap->a_vp; ! 323: rdlnk.a_cred = ap->a_cred; ! 324: if (cd9660_readlink(&rdlnk) == 0) ! 325: vap->va_size = MAXPATHLEN - auio.uio_resid; ! 326: FREE(cp, M_TEMP); ! 327: } ! 328: vap->va_flags = 0; ! 329: vap->va_gen = 1; ! 330: vap->va_blocksize = ip->i_mnt->logical_block_size; ! 331: vap->va_bytes = (u_quad_t) ip->i_size; ! 332: vap->va_type = vp->v_type; ! 333: ! 334: return (0); ! 335: } ! 336: ! 337: #if ISO_DEFAULT_BLOCK_SIZE >= NBPG ! 338: #ifdef DEBUG ! 339: extern int doclusterread; ! 340: #else ! 341: #define doclusterread 1 ! 342: #endif ! 343: #else ! 344: /* XXX until cluster routines can handle block sizes less than one page */ ! 345: #define doclusterread 0 ! 346: #endif ! 347: ! 348: /* ! 349: * Vnode op for reading. ! 350: */ ! 351: int ! 352: cd9660_read(ap) ! 353: struct vop_read_args /* { ! 354: struct vnode *a_vp; ! 355: struct uio *a_uio; ! 356: int a_ioflag; ! 357: struct ucred *a_cred; ! 358: } */ *ap; ! 359: { ! 360: struct vnode *vp = ap->a_vp; ! 361: register struct uio *uio = ap->a_uio; ! 362: register struct iso_node *ip = VTOI(vp); ! 363: register struct iso_mnt *imp; ! 364: struct buf *bp; ! 365: daddr_t lbn, rablock; ! 366: off_t diff; ! 367: int rasize, error = 0; ! 368: long size, n, on; ! 369: #ifdef NeXT ! 370: int firstpass; ! 371: int seq; ! 372: int devBlockSize; ! 373: #endif /* NeXT */ ! 374: ! 375: if (uio->uio_resid == 0) ! 376: return (0); ! 377: if (uio->uio_offset < 0) ! 378: return (EINVAL); ! 379: ip->i_flag |= IN_ACCESS; ! 380: imp = ip->i_mnt; ! 381: #ifdef NeXT ! 382: firstpass=TRUE; ! 383: VOP_DEVBLOCKSIZE(ip->i_devvp, &devBlockSize); ! 384: #endif /* NeXT */ ! 385: do { ! 386: lbn = lblkno(imp, uio->uio_offset); ! 387: on = blkoff(imp, uio->uio_offset); ! 388: n = min((u_int)(imp->logical_block_size - on), ! 389: uio->uio_resid); ! 390: diff = (off_t)ip->i_size - uio->uio_offset; ! 391: if (diff <= 0) ! 392: return (0); ! 393: if (diff < n) ! 394: n = diff; ! 395: size = blksize(imp, ip, lbn); ! 396: rablock = lbn + 1; ! 397: if (doclusterread) { ! 398: if (lblktosize(imp, rablock) <= ip->i_size) ! 399: #ifdef NeXT ! 400: error = cluster_read(vp, (off_t)ip->i_size, ! 401: lbn, size, NOCRED, &bp, devBlockSize, ! 402: firstpass, (uio->uio_resid + on), &seq); ! 403: #else ! 404: error = cluster_read(vp, (off_t)ip->i_size, ! 405: lbn, size, NOCRED, &bp); ! 406: #endif /* NeXT */ ! 407: else ! 408: error = bread(vp, lbn, size, NOCRED, &bp); ! 409: } else { ! 410: if (vp->v_lastr + 1 == lbn && ! 411: lblktosize(imp, rablock) < ip->i_size) { ! 412: rasize = blksize(imp, ip, rablock); ! 413: error = breadn(vp, lbn, size, &rablock, ! 414: &rasize, 1, NOCRED, &bp); ! 415: } else ! 416: error = bread(vp, lbn, size, NOCRED, &bp); ! 417: } ! 418: vp->v_lastr = lbn; ! 419: n = min(n, size - bp->b_resid); ! 420: if (error) { ! 421: brelse(bp); ! 422: return (error); ! 423: } ! 424: ! 425: error = uiomove(bp->b_data + on, (int)n, uio); ! 426: if (n + on == imp->logical_block_size || ! 427: uio->uio_offset == (off_t)ip->i_size) ! 428: bp->b_flags |= B_AGE; ! 429: brelse(bp); ! 430: firstpass = FALSE; ! 431: } while (error == 0 && uio->uio_resid > 0 && n != 0); ! 432: return (error); ! 433: } ! 434: ! 435: /* ARGSUSED */ ! 436: int ! 437: cd9660_ioctl(ap) ! 438: struct vop_ioctl_args /* { ! 439: struct vnode *a_vp; ! 440: u_long a_command; ! 441: caddr_t a_data; ! 442: int a_fflag; ! 443: struct ucred *a_cred; ! 444: struct proc *a_p; ! 445: } */ *ap; ! 446: { ! 447: printf("You did ioctl for isofs !!\n"); ! 448: return (ENOTTY); ! 449: } ! 450: ! 451: /* ARGSUSED */ ! 452: int ! 453: cd9660_select(ap) ! 454: struct vop_select_args /* { ! 455: struct vnode *a_vp; ! 456: int a_which; ! 457: int a_fflags; ! 458: struct ucred *a_cred; ! 459: struct proc *a_p; ! 460: } */ *ap; ! 461: { ! 462: /* ! 463: * We should really check to see if I/O is possible. ! 464: */ ! 465: return (1); ! 466: } ! 467: ! 468: /* ! 469: * Mmap a file ! 470: * ! 471: * NB Currently unsupported. ! 472: */ ! 473: /* ARGSUSED */ ! 474: int ! 475: cd9660_mmap(ap) ! 476: struct vop_mmap_args /* { ! 477: struct vnode *a_vp; ! 478: int a_fflags; ! 479: struct ucred *a_cred; ! 480: struct proc *a_p; ! 481: } */ *ap; ! 482: { ! 483: ! 484: return (EINVAL); ! 485: } ! 486: ! 487: /* ! 488: * Seek on a file ! 489: * ! 490: * Nothing to do, so just return. ! 491: */ ! 492: /* ARGSUSED */ ! 493: int ! 494: cd9660_seek(ap) ! 495: struct vop_seek_args /* { ! 496: struct vnode *a_vp; ! 497: off_t a_oldoff; ! 498: off_t a_newoff; ! 499: struct ucred *a_cred; ! 500: } */ *ap; ! 501: { ! 502: ! 503: return (0); ! 504: } ! 505: ! 506: /* ! 507: * Structure for reading directories ! 508: */ ! 509: struct isoreaddir { ! 510: struct dirent saveent; ! 511: struct dirent assocent; ! 512: struct dirent current; ! 513: off_t saveoff; ! 514: off_t assocoff; ! 515: off_t curroff; ! 516: struct uio *uio; ! 517: off_t uio_off; ! 518: int eofflag; ! 519: // u_long **cookies; ! 520: // int *ncookies; ! 521: }; ! 522: ! 523: int ! 524: iso_uiodir(idp,dp,off) ! 525: struct isoreaddir *idp; ! 526: struct dirent *dp; ! 527: off_t off; ! 528: { ! 529: int error; ! 530: ! 531: dp->d_name[dp->d_namlen] = 0; ! 532: dp->d_reclen = DIRSIZ(dp); ! 533: ! 534: if (idp->uio->uio_resid < dp->d_reclen) { ! 535: idp->eofflag = 0; ! 536: return (-1); ! 537: } ! 538: ! 539: #if 0 ! 540: if (idp->cookies) { ! 541: if (*idp->ncookies <= 0) { ! 542: idp->eofflag = 0; ! 543: return (-1); ! 544: } ! 545: ! 546: **idp->cookies++ = off; ! 547: --*idp->ncookies; ! 548: } ! 549: #endif ! 550: ! 551: if ( (error = uiomove( (caddr_t)dp, dp->d_reclen, idp->uio )) ) ! 552: return (error); ! 553: idp->uio_off = off; ! 554: return (0); ! 555: } ! 556: ! 557: int ! 558: iso_shipdir(idp) ! 559: struct isoreaddir *idp; ! 560: { ! 561: struct dirent *dp; ! 562: int cl, sl, assoc; ! 563: int error; ! 564: char *cname, *sname; ! 565: ! 566: cl = idp->current.d_namlen; ! 567: cname = idp->current.d_name; ! 568: assoc = (cl > 1) && (*cname == ASSOCCHAR ); ! 569: if (assoc) { ! 570: cl--; ! 571: cname++; ! 572: } ! 573: ! 574: dp = &idp->saveent; ! 575: sname = dp->d_name; ! 576: if (!(sl = dp->d_namlen)) { ! 577: dp = &idp->assocent; ! 578: sname = dp->d_name + 1; ! 579: sl = dp->d_namlen - 1; ! 580: } ! 581: if (sl > 0) { ! 582: if (sl != cl ! 583: || bcmp(sname,cname,sl)) { ! 584: if (idp->assocent.d_namlen) { ! 585: if ( (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) ) ! 586: return (error); ! 587: idp->assocent.d_namlen = 0; ! 588: } ! 589: if (idp->saveent.d_namlen) { ! 590: if ( (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) ) ! 591: return (error); ! 592: idp->saveent.d_namlen = 0; ! 593: } ! 594: } ! 595: } ! 596: idp->current.d_reclen = DIRSIZ(&idp->current); ! 597: if (assoc) { ! 598: idp->assocoff = idp->curroff; ! 599: bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); ! 600: } else { ! 601: idp->saveoff = idp->curroff; ! 602: bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); ! 603: } ! 604: return (0); ! 605: } ! 606: ! 607: /* ! 608: * Vnode op for readdir ! 609: */ ! 610: int ! 611: cd9660_readdir(ap) ! 612: struct vop_readdir_args /* { ! 613: struct vnodeop_desc *a_desc; ! 614: struct vnode *a_vp; ! 615: struct uio *a_uio; ! 616: struct ucred *a_cred; ! 617: int *a_eofflag; ! 618: int *a_ncookies; ! 619: u_long **a_cookies; ! 620: } */ *ap; ! 621: { ! 622: register struct uio *uio = ap->a_uio; ! 623: off_t startingOffset = uio->uio_offset; ! 624: size_t lost = 0; ! 625: struct isoreaddir *idp; ! 626: struct vnode *vdp = ap->a_vp; ! 627: struct iso_node *dp; ! 628: struct iso_mnt *imp; ! 629: struct buf *bp = NULL; ! 630: struct iso_directory_record *ep; ! 631: int entryoffsetinblock; ! 632: doff_t endsearch; ! 633: u_long bmask; ! 634: int error = 0; ! 635: int reclen; ! 636: u_short namelen; ! 637: ! 638: dp = VTOI(vdp); ! 639: imp = dp->i_mnt; ! 640: bmask = imp->im_bmask; ! 641: ! 642: MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); ! 643: idp->saveent.d_namlen = idp->assocent.d_namlen = 0; ! 644: /* ! 645: * XXX ! 646: * Is it worth trying to figure out the type? ! 647: */ ! 648: idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = ! 649: DT_UNKNOWN; ! 650: idp->uio = uio; ! 651: idp->eofflag = 1; ! 652: idp->curroff = uio->uio_offset; ! 653: ! 654: if ((entryoffsetinblock = idp->curroff & bmask) && ! 655: (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) { ! 656: FREE(idp, M_TEMP); ! 657: return (error); ! 658: } ! 659: endsearch = dp->i_size; ! 660: ! 661: while (idp->curroff < endsearch) { ! 662: /* ! 663: * If offset is on a block boundary, ! 664: * read the next directory block. ! 665: * Release previous if it exists. ! 666: */ ! 667: if ((idp->curroff & bmask) == 0) { ! 668: if (bp != NULL) ! 669: brelse(bp); ! 670: if ( (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp)) ) ! 671: break; ! 672: entryoffsetinblock = 0; ! 673: } ! 674: /* ! 675: * Get pointer to next entry. ! 676: */ ! 677: ep = (struct iso_directory_record *) ! 678: ((char *)bp->b_data + entryoffsetinblock); ! 679: ! 680: reclen = isonum_711(ep->length); ! 681: if (reclen == 0) { ! 682: /* skip to next block, if any */ ! 683: idp->curroff = ! 684: (idp->curroff & ~bmask) + imp->logical_block_size; ! 685: continue; ! 686: } ! 687: ! 688: if (reclen < ISO_DIRECTORY_RECORD_SIZE) { ! 689: error = EINVAL; ! 690: /* illegal entry, stop */ ! 691: break; ! 692: } ! 693: ! 694: if (entryoffsetinblock + reclen > imp->logical_block_size) { ! 695: error = EINVAL; ! 696: /* illegal directory, so stop looking */ ! 697: break; ! 698: } ! 699: ! 700: idp->current.d_namlen = isonum_711(ep->name_len); ! 701: ! 702: if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { ! 703: error = EINVAL; ! 704: /* illegal entry, stop */ ! 705: break; ! 706: } ! 707: ! 708: #if 1 // radar 1669467 - make it pretty ! 709: if ( isonum_711(ep->flags) & directoryBit ) ! 710: #else ! 711: if (isonum_711(ep->flags)&2) ! 712: #endif // radar 1669467 ! 713: idp->current.d_fileno = isodirino(ep, imp); ! 714: else ! 715: { ! 716: ! 717: #if 1 // radar 1669467 ! 718: idp->current.d_fileno = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock; ! 719: #else ! 720: idp->current.d_fileno = dbtob(bp->b_blkno) + entryoffsetinblock; ! 721: #endif // radar 1669467 ! 722: ! 723: } ! 724: ! 725: idp->curroff += reclen; ! 726: ! 727: switch (imp->iso_ftype) { ! 728: case ISO_FTYPE_RRIP: ! 729: cd9660_rrip_getname(ep,idp->current.d_name, &namelen, ! 730: &idp->current.d_fileno,imp); ! 731: idp->current.d_namlen = (u_char)namelen; ! 732: if (idp->current.d_namlen) ! 733: error = iso_uiodir(idp,&idp->current,idp->curroff); ! 734: break; ! 735: default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ ! 736: strcpy(idp->current.d_name,".."); ! 737: switch (ep->name[0]) { ! 738: case 0: ! 739: idp->current.d_namlen = 1; ! 740: error = iso_uiodir(idp,&idp->current,idp->curroff); ! 741: break; ! 742: case 1: ! 743: idp->current.d_namlen = 2; ! 744: error = iso_uiodir(idp,&idp->current,idp->curroff); ! 745: break; ! 746: default: ! 747: isofntrans(ep->name,idp->current.d_namlen, ! 748: idp->current.d_name, &namelen, ! 749: imp->iso_ftype == ISO_FTYPE_9660, ! 750: isonum_711(ep->flags) & associatedBit); ! 751: idp->current.d_namlen = (u_char)namelen; ! 752: if (imp->iso_ftype == ISO_FTYPE_DEFAULT) ! 753: error = iso_shipdir(idp); ! 754: else ! 755: error = iso_uiodir(idp,&idp->current,idp->curroff); ! 756: break; ! 757: } ! 758: } ! 759: if (error) ! 760: break; ! 761: ! 762: entryoffsetinblock += reclen; ! 763: } ! 764: ! 765: if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { ! 766: idp->current.d_namlen = 0; ! 767: error = iso_shipdir(idp); ! 768: } ! 769: ! 770: if (!error && ap->a_ncookies) { ! 771: struct dirent *dp, *dpstart; ! 772: off_t bufferOffset; ! 773: u_long *cookies; ! 774: int ncookies; ! 775: ! 776: /* ! 777: * Only the NFS server uses cookies, and it loads the ! 778: * directory block into system space, so we can just look at ! 779: * it directly. ! 780: * ! 781: * We assume the entire transfer is done to a single contiguous buffer. ! 782: */ ! 783: if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) ! 784: panic("ufs_readdir: lost in space"); ! 785: ! 786: /* ! 787: * Make a first pass over the buffer just generated, ! 788: * counting the number of entries: ! 789: */ ! 790: dpstart = (struct dirent *) (uio->uio_iov->iov_base - (uio->uio_offset - startingOffset)); ! 791: for (dp = dpstart, bufferOffset = startingOffset, ncookies = 0; ! 792: bufferOffset < uio->uio_offset; ) { ! 793: if (dp->d_reclen == 0) ! 794: break; ! 795: bufferOffset += dp->d_reclen; ! 796: ncookies++; ! 797: dp = (struct dirent *)((caddr_t)dp + dp->d_reclen); ! 798: } ! 799: lost += uio->uio_offset - bufferOffset; ! 800: uio->uio_offset = bufferOffset; ! 801: ! 802: /* ! 803: * Allocate a buffer to hold the cookies requested: ! 804: */ ! 805: MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK); ! 806: *ap->a_ncookies = ncookies; ! 807: *ap->a_cookies = cookies; ! 808: ! 809: /* ! 810: * Fill in the offsets for each entry in the buffer just allocated: ! 811: */ ! 812: for (bufferOffset = startingOffset, dp = dpstart; bufferOffset < uio->uio_offset; ) { ! 813: *(cookies++) = bufferOffset; ! 814: bufferOffset += dp->d_reclen; ! 815: dp = (struct dirent *)((caddr_t)dp + dp->d_reclen); ! 816: } ! 817: } ! 818: ! 819: if (error < 0) ! 820: error = 0; ! 821: ! 822: if (bp) ! 823: brelse (bp); ! 824: ! 825: uio->uio_offset = idp->uio_off; ! 826: *ap->a_eofflag = idp->eofflag; ! 827: ! 828: FREE(idp, M_TEMP); ! 829: ! 830: return (error); ! 831: } ! 832: ! 833: /* ! 834: * Return target name of a symbolic link ! 835: * Shouldn't we get the parent vnode and read the data from there? ! 836: * This could eventually result in deadlocks in cd9660_lookup. ! 837: * But otherwise the block read here is in the block buffer two times. ! 838: */ ! 839: typedef struct iso_directory_record ISODIR; ! 840: typedef struct iso_node ISONODE; ! 841: typedef struct iso_mnt ISOMNT; ! 842: int ! 843: cd9660_readlink(ap) ! 844: struct vop_readlink_args /* { ! 845: struct vnode *a_vp; ! 846: struct uio *a_uio; ! 847: struct ucred *a_cred; ! 848: } */ *ap; ! 849: { ! 850: ISONODE *ip; ! 851: ISODIR *dirp; ! 852: ISOMNT *imp; ! 853: struct buf *bp; ! 854: struct uio *uio; ! 855: u_short symlen; ! 856: int error; ! 857: char *symname; ! 858: ! 859: ip = VTOI(ap->a_vp); ! 860: imp = ip->i_mnt; ! 861: uio = ap->a_uio; ! 862: ! 863: if (imp->iso_ftype != ISO_FTYPE_RRIP) ! 864: return (EINVAL); ! 865: ! 866: /* ! 867: * Get parents directory record block that this inode included. ! 868: */ ! 869: error = bread(imp->im_devvp, ! 870: #if 1 // radar 1669467 ! 871: (ip->i_number >> imp->im_bshift), ! 872: #else ! 873: (ip->i_number >> imp->im_bshift) << (imp->im_bshift - DEV_BSHIFT), ! 874: #endif // radar 1669467 ! 875: imp->logical_block_size, NOCRED, &bp); ! 876: if (error) { ! 877: brelse(bp); ! 878: return (EINVAL); ! 879: } ! 880: ! 881: /* ! 882: * Setup the directory pointer for this inode ! 883: */ ! 884: dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); ! 885: ! 886: /* ! 887: * Just make sure, we have a right one.... ! 888: * 1: Check not cross boundary on block ! 889: */ ! 890: if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) ! 891: > imp->logical_block_size) { ! 892: brelse(bp); ! 893: return (EINVAL); ! 894: } ! 895: ! 896: /* ! 897: * Now get a buffer ! 898: * Abuse a namei buffer for now. ! 899: */ ! 900: if (uio->uio_segflg == UIO_SYSSPACE) ! 901: symname = uio->uio_iov->iov_base; ! 902: else ! 903: MALLOC_ZONE(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); ! 904: ! 905: /* ! 906: * Ok, we just gathering a symbolic name in SL record. ! 907: */ ! 908: if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { ! 909: if (uio->uio_segflg != UIO_SYSSPACE) ! 910: FREE_ZONE(symname, MAXPATHLEN, M_NAMEI); ! 911: brelse(bp); ! 912: return (EINVAL); ! 913: } ! 914: /* ! 915: * Don't forget before you leave from home ;-) ! 916: */ ! 917: brelse(bp); ! 918: ! 919: /* ! 920: * return with the symbolic name to caller's. ! 921: */ ! 922: if (uio->uio_segflg != UIO_SYSSPACE) { ! 923: error = uiomove(symname, symlen, uio); ! 924: FREE_ZONE(symname, MAXPATHLEN, M_NAMEI); ! 925: return (error); ! 926: } ! 927: uio->uio_resid -= symlen; ! 928: uio->uio_iov->iov_base += symlen; ! 929: uio->uio_iov->iov_len -= symlen; ! 930: return (0); ! 931: } ! 932: ! 933: /* ! 934: * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually ! 935: * done. If a buffer has been saved in anticipation of a CREATE, delete it. ! 936: */ ! 937: int ! 938: cd9660_abortop(ap) ! 939: struct vop_abortop_args /* { ! 940: struct vnode *a_dvp; ! 941: struct componentname *a_cnp; ! 942: } */ *ap; ! 943: { ! 944: if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) ! 945: FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI); ! 946: return (0); ! 947: } ! 948: ! 949: /* ! 950: * Lock an inode. ! 951: */ ! 952: ! 953: // radar 1669467 - changed ap struct too!!! ! 954: // radar 1669467 - chw changed implementation to use the lock manager. This is a delta from ! 955: // what we first did with the radar. This is now basically identical to ufs_lock. ! 956: int ! 957: cd9660_lock(ap) ! 958: struct vop_lock_args /* { ! 959: struct vnode *a_vp; ! 960: int a_flags; ! 961: struct proc *a_p; ! 962: } */ *ap; ! 963: { ! 964: struct vnode *vp = ap->a_vp; ! 965: ! 966: if (VTOI(vp) == (struct inode *) NULL) ! 967: panic ("cd9660 inode in vnode is null\n"); ! 968: return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,ap->a_p)); ! 969: } ! 970: ! 971: /* ! 972: * Unlock an inode. ! 973: */ ! 974: ! 975: // radar 1669467 - chw changed implementation to use the lock manager. As with lock, this is a ! 976: // delta from what we first did with the radar. ! 977: ! 978: int ! 979: cd9660_unlock(ap) ! 980: struct vop_unlock_args /* { ! 981: struct vnode *a_vp; ! 982: int a_flags; ! 983: struct proc *a_p; ! 984: } */ *ap; ! 985: { ! 986: struct vnode *vp = ap->a_vp; ! 987: ! 988: return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock,ap->a_p)); ! 989: ! 990: } ! 991: ! 992: /* ! 993: * Calculate the logical to physical mapping if not done already, ! 994: * then call the device strategy routine. ! 995: */ ! 996: int ! 997: cd9660_strategy(ap) ! 998: struct vop_strategy_args /* { ! 999: struct buf *a_bp; ! 1000: } */ *ap; ! 1001: { ! 1002: register struct buf *bp = ap->a_bp; ! 1003: register struct vnode *vp = bp->b_vp; ! 1004: register struct iso_node *ip; ! 1005: int error; ! 1006: ! 1007: ip = VTOI(vp); ! 1008: if (vp->v_type == VBLK || vp->v_type == VCHR) ! 1009: panic("cd9660_strategy: spec"); ! 1010: if (bp->b_blkno == bp->b_lblkno) { ! 1011: if ( (error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) ) { ! 1012: bp->b_error = error; ! 1013: bp->b_flags |= B_ERROR; ! 1014: biodone(bp); ! 1015: return (error); ! 1016: } ! 1017: if ((long)bp->b_blkno == -1) ! 1018: clrbuf(bp); ! 1019: } ! 1020: if ((long)bp->b_blkno == -1) { ! 1021: biodone(bp); ! 1022: return (0); ! 1023: } ! 1024: vp = ip->i_devvp; ! 1025: bp->b_dev = vp->v_rdev; ! 1026: VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); ! 1027: return (0); ! 1028: } ! 1029: ! 1030: /* ! 1031: * Print out the contents of an inode. ! 1032: */ ! 1033: int ! 1034: cd9660_print(ap) ! 1035: struct vop_print_args /* { ! 1036: struct vnode *a_vp; ! 1037: } */ *ap; ! 1038: { ! 1039: ! 1040: printf("tag VT_ISOFS, isofs vnode\n"); ! 1041: return (0); ! 1042: } ! 1043: ! 1044: /* ! 1045: * Check for a locked inode. ! 1046: */ ! 1047: // radar 1669467 changed this to use the lock manager - chw ! 1048: ! 1049: int ! 1050: cd9660_islocked(ap) ! 1051: struct vop_islocked_args /* { ! 1052: struct vnode *a_vp; ! 1053: } */ *ap; ! 1054: { ! 1055: ! 1056: return (lockstatus(&VTOI(ap->a_vp)->i_lock)); ! 1057: } ! 1058: ! 1059: /* ! 1060: * Return POSIX pathconf information applicable to cd9660 filesystems. ! 1061: */ ! 1062: int ! 1063: cd9660_pathconf(ap) ! 1064: struct vop_pathconf_args /* { ! 1065: struct vnode *a_vp; ! 1066: int a_name; ! 1067: register_t *a_retval; ! 1068: } */ *ap; ! 1069: { ! 1070: ! 1071: switch (ap->a_name) { ! 1072: case _PC_LINK_MAX: ! 1073: *ap->a_retval = 1; ! 1074: return (0); ! 1075: case _PC_NAME_MAX: ! 1076: if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) ! 1077: *ap->a_retval = NAME_MAX; ! 1078: else ! 1079: *ap->a_retval = 37; ! 1080: return (0); ! 1081: case _PC_PATH_MAX: ! 1082: *ap->a_retval = PATH_MAX; ! 1083: return (0); ! 1084: case _PC_PIPE_BUF: ! 1085: *ap->a_retval = PIPE_BUF; ! 1086: return (0); ! 1087: case _PC_CHOWN_RESTRICTED: ! 1088: *ap->a_retval = 1; ! 1089: return (0); ! 1090: case _PC_NO_TRUNC: ! 1091: *ap->a_retval = 1; ! 1092: return (0); ! 1093: default: ! 1094: return (EINVAL); ! 1095: } ! 1096: /* NOTREACHED */ ! 1097: } ! 1098: ! 1099: /* ! 1100: * Unsupported operation ! 1101: */ ! 1102: int ! 1103: cd9660_enotsupp() ! 1104: { ! 1105: ! 1106: return (EOPNOTSUPP); ! 1107: } ! 1108: /* Pagein */ ! 1109: int ! 1110: cd9660_pagein(ap) ! 1111: struct vop_pagein_args /* { ! 1112: struct vnode *a_vp; ! 1113: struct uio *a_uio; ! 1114: int a_ioflag; ! 1115: struct ucred *a_cred; ! 1116: } */ *ap; ! 1117: { ! 1118: /* pass thru to read */ ! 1119: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 1120: } ! 1121: ! 1122: /* Pageout */ ! 1123: int ! 1124: cd9660_pageout(ap) ! 1125: struct vop_pageout_args /* { ! 1126: struct vnode *a_vp; ! 1127: struct uio *a_uio; ! 1128: int a_ioflag; ! 1129: struct ucred *a_cred; ! 1130: } */ *ap; ! 1131: { ! 1132: /* pass thru to write */ ! 1133: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 1134: } ! 1135: ! 1136: /* ! 1137: * cd9660_remove - not possible to remove a file from iso cds ! 1138: * ! 1139: * Locking policy: a_dvp and vp locked on entry, unlocked on exit ! 1140: */ ! 1141: int ! 1142: cd9660_remove(ap) ! 1143: struct vop_remove_args /* { struct vnode *a_dvp; struct vnode *a_vp; ! 1144: struct componentname *a_cnp; } */ *ap; ! 1145: { ! 1146: if (ap->a_dvp == ap->a_vp) ! 1147: vrele(ap->a_vp); ! 1148: else ! 1149: vput(ap->a_vp); ! 1150: vput(ap->a_dvp); ! 1151: ! 1152: return (EROFS); ! 1153: } ! 1154: ! 1155: ! 1156: /* ! 1157: * cd9660_rmdir - not possible to remove a directory from iso cds ! 1158: * ! 1159: * Locking policy: a_dvp and vp locked on entry, unlocked on exit ! 1160: */ ! 1161: int ! 1162: cd9660_rmdir(ap) ! 1163: struct vop_rmdir_args /* { struct vnode *a_dvp; struct vnode *a_vp; ! 1164: struct componentname *a_cnp; } */ *ap; ! 1165: { ! 1166: (void) nop_rmdir(ap); ! 1167: return (EROFS); ! 1168: } ! 1169: ! 1170: /* ! 1171: ! 1172: # ! 1173: #% getattrlist vp = = = ! 1174: # ! 1175: vop_getattrlist { ! 1176: IN struct vnode *vp; ! 1177: IN struct attrlist *alist; ! 1178: INOUT struct uio *uio; ! 1179: IN struct ucred *cred; ! 1180: IN struct proc *p; ! 1181: }; ! 1182: ! 1183: */ ! 1184: int ! 1185: cd9660_getattrlist(ap) ! 1186: struct vop_getattrlist_args /* { ! 1187: struct vnode *a_vp; ! 1188: struct attrlist *a_alist ! 1189: struct uio *a_uio; ! 1190: struct ucred *a_cred; ! 1191: struct proc *a_p; ! 1192: } */ *ap; ! 1193: { ! 1194: struct attrlist *alist = ap->a_alist; ! 1195: int fixedblocksize; ! 1196: int attrblocksize; ! 1197: int attrbufsize; ! 1198: void *attrbufptr; ! 1199: void *attrptr; ! 1200: void *varptr; ! 1201: int error = 0; ! 1202: ! 1203: if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) || ! 1204: ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) || ! 1205: ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) || ! 1206: ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) || ! 1207: ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0) || ! 1208: ((alist->forkattr & ~ATTR_FORK_VALIDMASK) != 0)) { ! 1209: return EINVAL; ! 1210: }; ! 1211: ! 1212: /* ! 1213: * Requesting volume information requires setting the ATTR_VOL_INFO bit and ! 1214: * volume info requests are mutually exclusive with all other info requests: ! 1215: */ ! 1216: if ((alist->volattr != 0) && ! 1217: (((alist->volattr & ATTR_VOL_INFO) == 0) || ! 1218: (alist->dirattr != 0) || ! 1219: (alist->fileattr != 0) || ! 1220: (alist->forkattr != 0) )) { ! 1221: return EINVAL; ! 1222: }; ! 1223: ! 1224: /* ! 1225: * Reject requests for unsupported options for now: ! 1226: */ ! 1227: if (alist->volattr & ATTR_VOL_MOUNTPOINT) return EINVAL; ! 1228: if (alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) return EINVAL; ! 1229: if (alist->fileattr & ! 1230: (ATTR_FILE_FILETYPE | ! 1231: ATTR_FILE_FORKCOUNT | ! 1232: ATTR_FILE_FORKLIST | ! 1233: ATTR_FILE_DATAEXTENTS | ! 1234: ATTR_FILE_RSRCEXTENTS)) { ! 1235: return EINVAL; ! 1236: }; ! 1237: ! 1238: ! 1239: fixedblocksize = attrcalcsize(alist); ! 1240: attrblocksize = fixedblocksize + (sizeof(u_long)); /* u_long for length longword */ ! 1241: if (alist->commonattr & ATTR_CMN_NAME) attrblocksize += NAME_MAX; ! 1242: if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST) attrblocksize += 0; /* XXX PPD */ ! 1243: if (alist->volattr & ATTR_VOL_MOUNTPOINT) attrblocksize += PATH_MAX; ! 1244: if (alist->volattr & ATTR_VOL_NAME) attrblocksize += NAME_MAX; ! 1245: if (alist->fileattr & ATTR_FILE_FORKLIST) attrblocksize += 0; /* XXX PPD */ ! 1246: ! 1247: attrbufsize = MIN(ap->a_uio->uio_resid, attrblocksize); ! 1248: MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK); ! 1249: attrptr = attrbufptr; ! 1250: *((u_long *)attrptr) = 0; /* Set buffer length in case of errors */ ! 1251: ++((u_long *)attrptr); /* Reserve space for length field */ ! 1252: varptr = ((char *)attrptr) + fixedblocksize; /* Point to variable-length storage */ ! 1253: ! 1254: packattrblk(alist, ap->a_vp, &attrptr, &varptr); ! 1255: ! 1256: *((u_long *)attrbufptr) = (varptr - attrbufptr); /* Store length of fixed + var block */ ! 1257: attrbufsize = MIN(attrbufsize, varptr - attrbufptr); /* Don't copy out more data than was generated */ ! 1258: ! 1259: error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio); ! 1260: ! 1261: FREE(attrbufptr, M_TEMP); ! 1262: ! 1263: return error; ! 1264: } ! 1265: ! 1266: /* ! 1267: * Global vfs data structures for isofs ! 1268: */ ! 1269: #define cd9660_create \ ! 1270: ((int (*) __P((struct vop_create_args *)))err_create) ! 1271: #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))err_mknod) ! 1272: #define cd9660_setattr \ ! 1273: ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp) ! 1274: #define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp) ! 1275: #if NFSSERVER ! 1276: int lease_check __P((struct vop_lease_args *)); ! 1277: #define cd9660_lease_check lease_check ! 1278: #else ! 1279: #define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) ! 1280: #endif ! 1281: #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) ! 1282: #define cd9660_rename \ ! 1283: ((int (*) __P((struct vop_rename_args *)))err_rename) ! 1284: #define cd9660_copyfile \ ! 1285: ((int (*) __P((struct vop_copyfile *)))err_copyfile) ! 1286: #define cd9660_link ((int (*) __P((struct vop_link_args *)))err_link) ! 1287: #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))err_mkdir) ! 1288: #define cd9660_symlink \ ! 1289: ((int (*) __P((struct vop_symlink_args *)))err_symlink) ! 1290: #define cd9660_advlock \ ! 1291: ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp) ! 1292: #define cd9660_valloc ((int(*) __P(( \ ! 1293: struct vnode *pvp, \ ! 1294: int mode, \ ! 1295: struct ucred *cred, \ ! 1296: struct vnode **vpp))) cd9660_enotsupp) ! 1297: #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp) ! 1298: #define cd9660_truncate \ ! 1299: ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp) ! 1300: #define cd9660_update \ ! 1301: ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp) ! 1302: #define cd9660_bwrite \ ! 1303: ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp) ! 1304: ! 1305: /* ! 1306: * Global vfs data structures for cd9660 ! 1307: */ ! 1308: int (**cd9660_vnodeop_p)(); ! 1309: struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { ! 1310: { &vop_default_desc, vn_default_error }, ! 1311: { &vop_lookup_desc, cd9660_lookup }, /* lookup */ ! 1312: { &vop_create_desc, cd9660_create }, /* create */ ! 1313: { &vop_mknod_desc, cd9660_mknod }, /* mknod */ ! 1314: { &vop_open_desc, cd9660_open }, /* open */ ! 1315: { &vop_close_desc, cd9660_close }, /* close */ ! 1316: { &vop_access_desc, cd9660_access }, /* access */ ! 1317: { &vop_getattr_desc, cd9660_getattr }, /* getattr */ ! 1318: { &vop_setattr_desc, cd9660_setattr }, /* setattr */ ! 1319: { &vop_read_desc, cd9660_read }, /* read */ ! 1320: { &vop_write_desc, cd9660_write }, /* write */ ! 1321: { &vop_lease_desc, cd9660_lease_check },/* lease */ ! 1322: { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ ! 1323: { &vop_select_desc, cd9660_select }, /* select */ ! 1324: { &vop_mmap_desc, cd9660_mmap }, /* mmap */ ! 1325: { &vop_fsync_desc, cd9660_fsync }, /* fsync */ ! 1326: { &vop_seek_desc, cd9660_seek }, /* seek */ ! 1327: { &vop_remove_desc, cd9660_remove }, /* remove */ ! 1328: { &vop_link_desc, cd9660_link }, /* link */ ! 1329: { &vop_rename_desc, cd9660_rename }, /* rename */ ! 1330: { &vop_copyfile_desc, cd9660_copyfile },/* copyfile */ ! 1331: { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ ! 1332: { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ ! 1333: { &vop_symlink_desc, cd9660_symlink }, /* symlink */ ! 1334: { &vop_readdir_desc, cd9660_readdir }, /* readdir */ ! 1335: { &vop_readlink_desc, cd9660_readlink },/* readlink */ ! 1336: { &vop_abortop_desc, cd9660_abortop }, /* abortop */ ! 1337: { &vop_inactive_desc, cd9660_inactive },/* inactive */ ! 1338: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ ! 1339: { &vop_lock_desc, cd9660_lock }, /* lock */ ! 1340: { &vop_unlock_desc, cd9660_unlock }, /* unlock */ ! 1341: { &vop_bmap_desc, cd9660_bmap }, /* bmap */ ! 1342: { &vop_strategy_desc, cd9660_strategy },/* strategy */ ! 1343: { &vop_print_desc, cd9660_print }, /* print */ ! 1344: { &vop_islocked_desc, cd9660_islocked },/* islocked */ ! 1345: { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ ! 1346: { &vop_advlock_desc, cd9660_advlock }, /* advlock */ ! 1347: { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */ ! 1348: { &vop_valloc_desc, cd9660_valloc }, /* valloc */ ! 1349: { &vop_vfree_desc, cd9660_vfree }, /* vfree */ ! 1350: { &vop_truncate_desc, cd9660_truncate },/* truncate */ ! 1351: { &vop_update_desc, cd9660_update }, /* update */ ! 1352: { &vop_bwrite_desc, vn_bwrite }, ! 1353: { &vop_pagein_desc, cd9660_pagein }, /* Pagein */ ! 1354: { &vop_pageout_desc, cd9660_pageout }, /* Pageout */ ! 1355: { &vop_getattrlist_desc, cd9660_getattrlist }, /* getattrlist */ ! 1356: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 1357: }; ! 1358: struct vnodeopv_desc cd9660_vnodeop_opv_desc = ! 1359: { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; ! 1360: ! 1361: /* ! 1362: * Special device vnode ops ! 1363: */ ! 1364: int (**cd9660_specop_p)(); ! 1365: struct vnodeopv_entry_desc cd9660_specop_entries[] = { ! 1366: { &vop_default_desc, vn_default_error }, ! 1367: { &vop_lookup_desc, spec_lookup }, /* lookup */ ! 1368: { &vop_create_desc, spec_create }, /* create */ ! 1369: { &vop_mknod_desc, spec_mknod }, /* mknod */ ! 1370: { &vop_open_desc, spec_open }, /* open */ ! 1371: { &vop_close_desc, spec_close }, /* close */ ! 1372: { &vop_access_desc, cd9660_access }, /* access */ ! 1373: { &vop_getattr_desc, cd9660_getattr }, /* getattr */ ! 1374: { &vop_setattr_desc, cd9660_setattr }, /* setattr */ ! 1375: { &vop_read_desc, spec_read }, /* read */ ! 1376: { &vop_write_desc, spec_write }, /* write */ ! 1377: { &vop_lease_desc, spec_lease_check }, /* lease */ ! 1378: { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ ! 1379: { &vop_select_desc, spec_select }, /* select */ ! 1380: { &vop_mmap_desc, spec_mmap }, /* mmap */ ! 1381: { &vop_fsync_desc, spec_fsync }, /* fsync */ ! 1382: { &vop_seek_desc, spec_seek }, /* seek */ ! 1383: { &vop_remove_desc, spec_remove }, /* remove */ ! 1384: { &vop_link_desc, spec_link }, /* link */ ! 1385: { &vop_rename_desc, spec_rename }, /* rename */ ! 1386: { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ ! 1387: { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ ! 1388: { &vop_symlink_desc, spec_symlink }, /* symlink */ ! 1389: { &vop_readdir_desc, spec_readdir }, /* readdir */ ! 1390: { &vop_readlink_desc, spec_readlink }, /* readlink */ ! 1391: { &vop_abortop_desc, spec_abortop }, /* abortop */ ! 1392: { &vop_inactive_desc, cd9660_inactive },/* inactive */ ! 1393: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ ! 1394: { &vop_lock_desc, cd9660_lock }, /* lock */ ! 1395: { &vop_unlock_desc, cd9660_unlock }, /* unlock */ ! 1396: { &vop_bmap_desc, spec_bmap }, /* bmap */ ! 1397: { &vop_strategy_desc, spec_strategy }, /* strategy */ ! 1398: { &vop_print_desc, cd9660_print }, /* print */ ! 1399: { &vop_islocked_desc, cd9660_islocked },/* islocked */ ! 1400: { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ ! 1401: { &vop_advlock_desc, spec_advlock }, /* advlock */ ! 1402: { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ ! 1403: { &vop_valloc_desc, spec_valloc }, /* valloc */ ! 1404: { &vop_vfree_desc, spec_vfree }, /* vfree */ ! 1405: { &vop_truncate_desc, spec_truncate }, /* truncate */ ! 1406: { &vop_update_desc, cd9660_update }, /* update */ ! 1407: { &vop_bwrite_desc, vn_bwrite }, ! 1408: #ifdef NeXT ! 1409: { &vop_devblocksize_desc, spec_devblocksize }, /* devblocksize */ ! 1410: #endif /* NeXT */ ! 1411: { &vop_pagein_desc, cd9660_pagein }, /* Pagein */ ! 1412: { &vop_pageout_desc, cd9660_pageout }, /* Pageout */ ! 1413: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 1414: }; ! 1415: struct vnodeopv_desc cd9660_specop_opv_desc = ! 1416: { &cd9660_specop_p, cd9660_specop_entries }; ! 1417: ! 1418: #if FIFO ! 1419: int (**cd9660_fifoop_p)(); ! 1420: struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { ! 1421: { &vop_default_desc, vn_default_error }, ! 1422: { &vop_lookup_desc, fifo_lookup }, /* lookup */ ! 1423: { &vop_create_desc, fifo_create }, /* create */ ! 1424: { &vop_mknod_desc, fifo_mknod }, /* mknod */ ! 1425: { &vop_open_desc, fifo_open }, /* open */ ! 1426: { &vop_close_desc, fifo_close }, /* close */ ! 1427: { &vop_access_desc, cd9660_access }, /* access */ ! 1428: { &vop_getattr_desc, cd9660_getattr }, /* getattr */ ! 1429: { &vop_setattr_desc, cd9660_setattr }, /* setattr */ ! 1430: { &vop_read_desc, fifo_read }, /* read */ ! 1431: { &vop_write_desc, fifo_write }, /* write */ ! 1432: { &vop_lease_desc, fifo_lease_check }, /* lease */ ! 1433: { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ ! 1434: { &vop_select_desc, fifo_select }, /* select */ ! 1435: { &vop_mmap_desc, fifo_mmap }, /* mmap */ ! 1436: { &vop_fsync_desc, fifo_fsync }, /* fsync */ ! 1437: { &vop_seek_desc, fifo_seek }, /* seek */ ! 1438: { &vop_remove_desc, fifo_remove }, /* remove */ ! 1439: { &vop_link_desc, fifo_link } , /* link */ ! 1440: { &vop_rename_desc, fifo_rename }, /* rename */ ! 1441: { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ ! 1442: { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ ! 1443: { &vop_symlink_desc, fifo_symlink }, /* symlink */ ! 1444: { &vop_readdir_desc, fifo_readdir }, /* readdir */ ! 1445: { &vop_readlink_desc, fifo_readlink }, /* readlink */ ! 1446: { &vop_abortop_desc, fifo_abortop }, /* abortop */ ! 1447: { &vop_inactive_desc, cd9660_inactive },/* inactive */ ! 1448: { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ ! 1449: { &vop_lock_desc, cd9660_lock }, /* lock */ ! 1450: { &vop_unlock_desc, cd9660_unlock }, /* unlock */ ! 1451: { &vop_bmap_desc, fifo_bmap }, /* bmap */ ! 1452: { &vop_strategy_desc, fifo_strategy }, /* strategy */ ! 1453: { &vop_print_desc, cd9660_print }, /* print */ ! 1454: { &vop_islocked_desc, cd9660_islocked },/* islocked */ ! 1455: { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ ! 1456: { &vop_advlock_desc, fifo_advlock }, /* advlock */ ! 1457: { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ ! 1458: { &vop_valloc_desc, fifo_valloc }, /* valloc */ ! 1459: { &vop_vfree_desc, fifo_vfree }, /* vfree */ ! 1460: { &vop_truncate_desc, fifo_truncate }, /* truncate */ ! 1461: { &vop_update_desc, cd9660_update }, /* update */ ! 1462: { &vop_bwrite_desc, vn_bwrite }, ! 1463: { &vop_pagein_desc, cd9660_pagein }, /* Pagein */ ! 1464: { &vop_pageout_desc, cd9660_pageout }, /* Pageout */ ! 1465: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 1466: }; ! 1467: struct vnodeopv_desc cd9660_fifoop_opv_desc = ! 1468: { &cd9660_fifoop_p, cd9660_fifoop_entries }; ! 1469: #endif /* FIFO */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.