|
|
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: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1990, 1993, 1995 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * Redistribution and use in source and binary forms, with or without ! 28: * modification, are permitted provided that the following conditions ! 29: * are met: ! 30: * 1. Redistributions of source code must retain the above copyright ! 31: * notice, this list of conditions and the following disclaimer. ! 32: * 2. Redistributions in binary form must reproduce the above copyright ! 33: * notice, this list of conditions and the following disclaimer in the ! 34: * documentation and/or other materials provided with the distribution. ! 35: * 3. All advertising materials mentioning features or use of this software ! 36: * must display the following acknowledgement: ! 37: * This product includes software developed by the University of ! 38: * California, Berkeley and its contributors. ! 39: * 4. Neither the name of the University nor the names of its contributors ! 40: * may be used to endorse or promote products derived from this software ! 41: * without specific prior written permission. ! 42: * ! 43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 53: * SUCH DAMAGE. ! 54: * ! 55: * @(#)fifo_vnops.c 8.4 (Berkeley) 8/10/94 ! 56: */ ! 57: ! 58: #include <sys/param.h> ! 59: #include <sys/proc.h> ! 60: #include <sys/time.h> ! 61: #include <sys/namei.h> ! 62: #include <sys/vnode.h> ! 63: #include <sys/socket.h> ! 64: #include <sys/socketvar.h> ! 65: #include <sys/stat.h> ! 66: #include <sys/systm.h> ! 67: #include <sys/ioctl.h> ! 68: #include <sys/file.h> ! 69: #include <sys/errno.h> ! 70: #include <sys/malloc.h> ! 71: #include <vfs/vfs_support.h> ! 72: #include <miscfs/fifofs/fifo.h> ! 73: ! 74: /* ! 75: * This structure is associated with the FIFO vnode and stores ! 76: * the state associated with the FIFO. ! 77: */ ! 78: struct fifoinfo { ! 79: struct socket *fi_readsock; ! 80: struct socket *fi_writesock; ! 81: long fi_readers; ! 82: long fi_writers; ! 83: }; ! 84: ! 85: int (**fifo_vnodeop_p)(); ! 86: struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { ! 87: { &vop_default_desc, vn_default_error }, ! 88: { &vop_lookup_desc, fifo_lookup }, /* lookup */ ! 89: { &vop_create_desc, fifo_create }, /* create */ ! 90: { &vop_mknod_desc, fifo_mknod }, /* mknod */ ! 91: { &vop_open_desc, fifo_open }, /* open */ ! 92: { &vop_close_desc, fifo_close }, /* close */ ! 93: { &vop_access_desc, fifo_access }, /* access */ ! 94: { &vop_getattr_desc, fifo_getattr }, /* getattr */ ! 95: { &vop_setattr_desc, fifo_setattr }, /* setattr */ ! 96: { &vop_read_desc, fifo_read }, /* read */ ! 97: { &vop_write_desc, fifo_write }, /* write */ ! 98: { &vop_lease_desc, fifo_lease_check }, /* lease */ ! 99: { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ ! 100: { &vop_select_desc, fifo_select }, /* select */ ! 101: { &vop_revoke_desc, fifo_revoke }, /* revoke */ ! 102: { &vop_mmap_desc, fifo_mmap }, /* mmap */ ! 103: { &vop_fsync_desc, fifo_fsync }, /* fsync */ ! 104: { &vop_seek_desc, fifo_seek }, /* seek */ ! 105: { &vop_remove_desc, fifo_remove }, /* remove */ ! 106: { &vop_link_desc, fifo_link }, /* link */ ! 107: { &vop_rename_desc, fifo_rename }, /* rename */ ! 108: { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ ! 109: { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ ! 110: { &vop_symlink_desc, fifo_symlink }, /* symlink */ ! 111: { &vop_readdir_desc, fifo_readdir }, /* readdir */ ! 112: { &vop_readlink_desc, fifo_readlink }, /* readlink */ ! 113: { &vop_abortop_desc, fifo_abortop }, /* abortop */ ! 114: { &vop_inactive_desc, fifo_inactive }, /* inactive */ ! 115: { &vop_reclaim_desc, fifo_reclaim }, /* reclaim */ ! 116: { &vop_lock_desc, fifo_lock }, /* lock */ ! 117: { &vop_unlock_desc, fifo_unlock }, /* unlock */ ! 118: { &vop_bmap_desc, fifo_bmap }, /* bmap */ ! 119: { &vop_strategy_desc, fifo_strategy }, /* strategy */ ! 120: { &vop_print_desc, fifo_print }, /* print */ ! 121: { &vop_islocked_desc, fifo_islocked }, /* islocked */ ! 122: { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ ! 123: { &vop_advlock_desc, fifo_advlock }, /* advlock */ ! 124: { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ ! 125: { &vop_valloc_desc, fifo_valloc }, /* valloc */ ! 126: { &vop_vfree_desc, fifo_vfree }, /* vfree */ ! 127: { &vop_truncate_desc, fifo_truncate }, /* truncate */ ! 128: { &vop_update_desc, fifo_update }, /* update */ ! 129: { &vop_bwrite_desc, fifo_bwrite }, /* bwrite */ ! 130: { &vop_pagein_desc, fifo_pagein }, /* Pagein */ ! 131: { &vop_copyfile_desc, err_copyfile }, /* Copyfile */ ! 132: { &vop_pageout_desc, fifo_pageout }, /* Pageout */ ! 133: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 134: }; ! 135: struct vnodeopv_desc fifo_vnodeop_opv_desc = ! 136: { &fifo_vnodeop_p, fifo_vnodeop_entries }; ! 137: ! 138: /* ! 139: * Trivial lookup routine that always fails. ! 140: */ ! 141: /* ARGSUSED */ ! 142: fifo_lookup(ap) ! 143: struct vop_lookup_args /* { ! 144: struct vnode * a_dvp; ! 145: struct vnode ** a_vpp; ! 146: struct componentname * a_cnp; ! 147: } */ *ap; ! 148: { ! 149: ! 150: *ap->a_vpp = NULL; ! 151: return (ENOTDIR); ! 152: } ! 153: ! 154: /* ! 155: * Open called to set up a new instance of a fifo or ! 156: * to find an active instance of a fifo. ! 157: */ ! 158: /* ARGSUSED */ ! 159: fifo_open(ap) ! 160: struct vop_open_args /* { ! 161: struct vnode *a_vp; ! 162: int a_mode; ! 163: struct ucred *a_cred; ! 164: struct proc *a_p; ! 165: } */ *ap; ! 166: { ! 167: struct vnode *vp = ap->a_vp; ! 168: struct fifoinfo *fip; ! 169: struct proc *p = ap->a_p; ! 170: struct socket *rso, *wso; ! 171: int error; ! 172: ! 173: if ((fip = vp->v_fifoinfo) == NULL) { ! 174: MALLOC_ZONE(fip, struct fifoinfo *, ! 175: sizeof(*fip), M_VNODE, M_WAITOK); ! 176: vp->v_fifoinfo = fip; ! 177: if (error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) { ! 178: _FREE_ZONE(fip, sizeof *fip, M_VNODE); ! 179: vp->v_fifoinfo = NULL; ! 180: return (error); ! 181: } ! 182: fip->fi_readsock = rso; ! 183: if (error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) { ! 184: (void)soclose(rso); ! 185: _FREE_ZONE(fip, sizeof *fip, M_VNODE); ! 186: vp->v_fifoinfo = NULL; ! 187: return (error); ! 188: } ! 189: fip->fi_writesock = wso; ! 190: if (error = unp_connect2(wso, rso)) { ! 191: (void)soclose(wso); ! 192: (void)soclose(rso); ! 193: _FREE_ZONE(fip, sizeof *fip, M_VNODE); ! 194: vp->v_fifoinfo = NULL; ! 195: return (error); ! 196: } ! 197: fip->fi_readers = fip->fi_writers = 0; ! 198: wso->so_state |= SS_CANTRCVMORE; ! 199: wso->so_snd.sb_lowat = PIPE_BUF; ! 200: rso->so_state |= SS_CANTSENDMORE; ! 201: } ! 202: if (ap->a_mode & FREAD) { ! 203: fip->fi_readers++; ! 204: if (fip->fi_readers == 1) { ! 205: fip->fi_writesock->so_state &= ~SS_CANTSENDMORE; ! 206: if (fip->fi_writers > 0) ! 207: wakeup((caddr_t)&fip->fi_writers); ! 208: } ! 209: } ! 210: if (ap->a_mode & FWRITE) { ! 211: fip->fi_writers++; ! 212: if (fip->fi_writers == 1) { ! 213: fip->fi_readsock->so_state &= ~SS_CANTRCVMORE; ! 214: if (fip->fi_readers > 0) ! 215: wakeup((caddr_t)&fip->fi_readers); ! 216: } ! 217: } ! 218: if ((ap->a_mode & FREAD) && (ap->a_mode & O_NONBLOCK) == 0) { ! 219: if (fip->fi_writers == 0) { ! 220: VOP_UNLOCK(vp, 0, p); ! 221: error = tsleep((caddr_t)&fip->fi_readers, ! 222: PCATCH | PSOCK, "fifoor", 0); ! 223: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); ! 224: if (error) ! 225: goto bad; ! 226: if (fip->fi_readers == 1) { ! 227: if (fip->fi_writers > 0) ! 228: wakeup((caddr_t)&fip->fi_writers); ! 229: } ! 230: } ! 231: } ! 232: if (ap->a_mode & FWRITE) { ! 233: if (ap->a_mode & O_NONBLOCK) { ! 234: if (fip->fi_readers == 0) { ! 235: error = ENXIO; ! 236: goto bad; ! 237: } ! 238: } else { ! 239: if (fip->fi_readers == 0) { ! 240: VOP_UNLOCK(vp, 0, p); ! 241: error = tsleep((caddr_t)&fip->fi_writers, ! 242: PCATCH | PSOCK, "fifoow", 0); ! 243: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); ! 244: if (error) ! 245: goto bad; ! 246: if (fip->fi_writers == 1) { ! 247: if (fip->fi_readers > 0) ! 248: wakeup((caddr_t)&fip->fi_readers); ! 249: } ! 250: } ! 251: } ! 252: } ! 253: return (0); ! 254: bad: ! 255: if (error) ! 256: VOP_CLOSE(vp, ap->a_mode, ap->a_cred, p); ! 257: return (error); ! 258: } ! 259: ! 260: /* ! 261: * Vnode op for read ! 262: */ ! 263: /* ARGSUSED */ ! 264: fifo_read(ap) ! 265: struct vop_read_args /* { ! 266: struct vnode *a_vp; ! 267: struct uio *a_uio; ! 268: int a_ioflag; ! 269: struct ucred *a_cred; ! 270: } */ *ap; ! 271: { ! 272: struct uio *uio = ap->a_uio; ! 273: struct socket *rso = ap->a_vp->v_fifoinfo->fi_readsock; ! 274: struct proc *p = uio->uio_procp; ! 275: int error, startresid; ! 276: ! 277: #if DIAGNOSTIC ! 278: if (uio->uio_rw != UIO_READ) ! 279: panic("fifo_read mode"); ! 280: #endif ! 281: if (uio->uio_resid == 0) ! 282: return (0); ! 283: if (ap->a_ioflag & IO_NDELAY) ! 284: rso->so_state |= SS_NBIO; ! 285: startresid = uio->uio_resid; ! 286: VOP_UNLOCK(ap->a_vp, 0, p); ! 287: error = soreceive(rso, (struct sockaddr **)0, uio, (struct mbuf **)0, ! 288: (struct mbuf **)0, (int *)0); ! 289: vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); ! 290: /* ! 291: * Clear EOF indication after first such return. ! 292: */ ! 293: if (uio->uio_resid == startresid) ! 294: rso->so_state &= ~SS_CANTRCVMORE; ! 295: if (ap->a_ioflag & IO_NDELAY) ! 296: rso->so_state &= ~SS_NBIO; ! 297: return (error); ! 298: } ! 299: ! 300: /* ! 301: * Vnode op for write ! 302: */ ! 303: /* ARGSUSED */ ! 304: fifo_write(ap) ! 305: struct vop_write_args /* { ! 306: struct vnode *a_vp; ! 307: struct uio *a_uio; ! 308: int a_ioflag; ! 309: struct ucred *a_cred; ! 310: } */ *ap; ! 311: { ! 312: struct socket *wso = ap->a_vp->v_fifoinfo->fi_writesock; ! 313: struct proc *p = ap->a_uio->uio_procp; ! 314: int error; ! 315: ! 316: #if DIAGNOSTIC ! 317: if (ap->a_uio->uio_rw != UIO_WRITE) ! 318: panic("fifo_write mode"); ! 319: #endif ! 320: if (ap->a_ioflag & IO_NDELAY) ! 321: wso->so_state |= SS_NBIO; ! 322: VOP_UNLOCK(ap->a_vp, 0, p); ! 323: error = sosend(wso, (struct sockaddr *)0, ap->a_uio, 0, (struct mbuf *)0, 0); ! 324: vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, p); ! 325: if (ap->a_ioflag & IO_NDELAY) ! 326: wso->so_state &= ~SS_NBIO; ! 327: return (error); ! 328: } ! 329: ! 330: /* ! 331: * Device ioctl operation. ! 332: */ ! 333: /* ARGSUSED */ ! 334: fifo_ioctl(ap) ! 335: struct vop_ioctl_args /* { ! 336: struct vnode *a_vp; ! 337: int a_command; ! 338: caddr_t a_data; ! 339: int a_fflag; ! 340: struct ucred *a_cred; ! 341: struct proc *a_p; ! 342: } */ *ap; ! 343: { ! 344: struct file filetmp; ! 345: int error; ! 346: ! 347: if (ap->a_command == FIONBIO) ! 348: return (0); ! 349: if (ap->a_fflag & FREAD) { ! 350: filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; ! 351: error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); ! 352: if (error) ! 353: return (error); ! 354: } ! 355: if (ap->a_fflag & FWRITE) { ! 356: filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; ! 357: error = soo_ioctl(&filetmp, ap->a_command, ap->a_data, ap->a_p); ! 358: if (error) ! 359: return (error); ! 360: } ! 361: return (0); ! 362: } ! 363: ! 364: /* ARGSUSED */ ! 365: fifo_select(ap) ! 366: struct vop_select_args /* { ! 367: struct vnode *a_vp; ! 368: int a_which; ! 369: int a_fflags; ! 370: struct ucred *a_cred; ! 371: struct proc *a_p; ! 372: } */ *ap; ! 373: { ! 374: struct file filetmp; ! 375: int ready; ! 376: ! 377: if (ap->a_fflags & FREAD) { ! 378: filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; ! 379: ready = soo_select(&filetmp, ap->a_which, ap->a_p); ! 380: if (ready) ! 381: return (ready); ! 382: } ! 383: if (ap->a_fflags & FWRITE) { ! 384: filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; ! 385: ready = soo_select(&filetmp, ap->a_which, ap->a_p); ! 386: if (ready) ! 387: return (ready); ! 388: } ! 389: return (0); ! 390: } ! 391: ! 392: int ! 393: fifo_inactive(ap) ! 394: struct vop_inactive_args /* { ! 395: struct vnode *a_vp; ! 396: struct proc *a_p; ! 397: } */ *ap; ! 398: { ! 399: ! 400: VOP_UNLOCK(ap->a_vp, 0, ap->a_p); ! 401: return (0); ! 402: } ! 403: ! 404: /* ! 405: * This is a noop, simply returning what one has been given. ! 406: */ ! 407: fifo_bmap(ap) ! 408: struct vop_bmap_args /* { ! 409: struct vnode *a_vp; ! 410: daddr_t a_bn; ! 411: struct vnode **a_vpp; ! 412: daddr_t *a_bnp; ! 413: int *a_runp; ! 414: } */ *ap; ! 415: { ! 416: ! 417: if (ap->a_vpp != NULL) ! 418: *ap->a_vpp = ap->a_vp; ! 419: if (ap->a_bnp != NULL) ! 420: *ap->a_bnp = ap->a_bn; ! 421: if (ap->a_runp != NULL) ! 422: *ap->a_runp = 0; ! 423: return (0); ! 424: } ! 425: ! 426: /* ! 427: * Device close routine ! 428: */ ! 429: /* ARGSUSED */ ! 430: fifo_close(ap) ! 431: struct vop_close_args /* { ! 432: struct vnode *a_vp; ! 433: int a_fflag; ! 434: struct ucred *a_cred; ! 435: struct proc *a_p; ! 436: } */ *ap; ! 437: { ! 438: register struct vnode *vp = ap->a_vp; ! 439: register struct fifoinfo *fip = vp->v_fifoinfo; ! 440: int error1, error2; ! 441: ! 442: if (ap->a_fflag & FREAD) { ! 443: fip->fi_readers--; ! 444: if (fip->fi_readers == 0) ! 445: socantsendmore(fip->fi_writesock); ! 446: } ! 447: if (ap->a_fflag & FWRITE) { ! 448: fip->fi_writers--; ! 449: if (fip->fi_writers == 0) ! 450: socantrcvmore(fip->fi_readsock); ! 451: } ! 452: if (vp->v_usecount > 1) ! 453: return (0); ! 454: error1 = soclose(fip->fi_readsock); ! 455: error2 = soclose(fip->fi_writesock); ! 456: FREE_ZONE(fip, sizeof *fip, M_VNODE); ! 457: vp->v_fifoinfo = NULL; ! 458: if (error1) ! 459: return (error1); ! 460: return (error2); ! 461: } ! 462: ! 463: /* ! 464: * Print out the contents of a fifo vnode. ! 465: */ ! 466: fifo_print(ap) ! 467: struct vop_print_args /* { ! 468: struct vnode *a_vp; ! 469: } */ *ap; ! 470: { ! 471: ! 472: printf("tag VT_NON"); ! 473: fifo_printinfo(ap->a_vp); ! 474: printf("\n"); ! 475: } ! 476: ! 477: /* ! 478: * Print out internal contents of a fifo vnode. ! 479: */ ! 480: fifo_printinfo(vp) ! 481: struct vnode *vp; ! 482: { ! 483: register struct fifoinfo *fip = vp->v_fifoinfo; ! 484: ! 485: printf(", fifo with %d readers and %d writers", ! 486: fip->fi_readers, fip->fi_writers); ! 487: } ! 488: ! 489: /* ! 490: * Return POSIX pathconf information applicable to fifo's. ! 491: */ ! 492: fifo_pathconf(ap) ! 493: struct vop_pathconf_args /* { ! 494: struct vnode *a_vp; ! 495: int a_name; ! 496: int *a_retval; ! 497: } */ *ap; ! 498: { ! 499: ! 500: switch (ap->a_name) { ! 501: case _PC_LINK_MAX: ! 502: *ap->a_retval = LINK_MAX; ! 503: return (0); ! 504: case _PC_PIPE_BUF: ! 505: *ap->a_retval = PIPE_BUF; ! 506: return (0); ! 507: case _PC_CHOWN_RESTRICTED: ! 508: *ap->a_retval = 1; ! 509: return (0); ! 510: default: ! 511: return (EINVAL); ! 512: } ! 513: /* NOTREACHED */ ! 514: } ! 515: ! 516: /* ! 517: * Fifo failed operation ! 518: */ ! 519: fifo_ebadf() ! 520: { ! 521: ! 522: return (EBADF); ! 523: } ! 524: ! 525: /* ! 526: * Fifo advisory byte-level locks. ! 527: */ ! 528: /* ARGSUSED */ ! 529: fifo_advlock(ap) ! 530: struct vop_advlock_args /* { ! 531: struct vnode *a_vp; ! 532: caddr_t a_id; ! 533: int a_op; ! 534: struct flock *a_fl; ! 535: int a_flags; ! 536: } */ *ap; ! 537: { ! 538: ! 539: return (EOPNOTSUPP); ! 540: } ! 541: ! 542: /* ! 543: * Fifo bad operation ! 544: */ ! 545: fifo_badop() ! 546: { ! 547: ! 548: panic("fifo_badop called"); ! 549: /* NOTREACHED */ ! 550: } ! 551: /* Pagein */ ! 552: fifo_pagein(ap) ! 553: struct vop_pagein_args /* { ! 554: struct vnode *a_vp; ! 555: struct uio *a_uio; ! 556: int a_ioflag; ! 557: struct ucred *a_cred; ! 558: } */ *ap; ! 559: { ! 560: /* pass thru to read */ ! 561: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 562: } ! 563: ! 564: /* Pageout */ ! 565: fifo_pageout(ap) ! 566: struct vop_pageout_args /* { ! 567: struct vnode *a_vp; ! 568: struct uio *a_uio; ! 569: int a_ioflag; ! 570: struct ucred *a_cred; ! 571: } */ *ap; ! 572: { ! 573: /* pass thru to write */ ! 574: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 575: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.