|
|
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) 1992, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * This code is derived from software donated to Berkeley by ! 28: * Jan-Simon Pendry. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95 ! 59: * ! 60: * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94 ! 61: */ ! 62: ! 63: /* ! 64: * Portal Filesystem ! 65: */ ! 66: ! 67: #include <sys/param.h> ! 68: #include <sys/systm.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/types.h> ! 71: #include <sys/time.h> ! 72: #include <sys/proc.h> ! 73: #include <sys/filedesc.h> ! 74: #include <sys/vnode.h> ! 75: #include <sys/file.h> ! 76: #include <sys/stat.h> ! 77: #include <sys/mount.h> ! 78: #include <sys/malloc.h> ! 79: #include <sys/namei.h> ! 80: #include <sys/mbuf.h> ! 81: #include <sys/socket.h> ! 82: #include <sys/socketvar.h> ! 83: #include <sys/un.h> ! 84: #include <sys/unpcb.h> ! 85: #include <vfs/vfs_support.h> ! 86: #include <miscfs/portal/portal.h> ! 87: ! 88: static int portal_fileid = PORTAL_ROOTFILEID+1; ! 89: ! 90: static void ! 91: portal_closefd(p, fd) ! 92: struct proc *p; ! 93: int fd; ! 94: { ! 95: int error; ! 96: struct { ! 97: int fd; ! 98: } ua; ! 99: int rc; ! 100: ! 101: ua.fd = fd; ! 102: error = close(p, &ua, &rc); ! 103: /* ! 104: * We should never get an error, and there isn't anything ! 105: * we could do if we got one, so just print a message. ! 106: */ ! 107: if (error) ! 108: printf("portal_closefd: error = %d\n", error); ! 109: } ! 110: ! 111: /* ! 112: * vp is the current namei directory ! 113: * cnp is the name to locate in that directory... ! 114: */ ! 115: int ! 116: portal_lookup(ap) ! 117: struct vop_lookup_args /* { ! 118: struct vnode * a_dvp; ! 119: struct vnode ** a_vpp; ! 120: struct componentname * a_cnp; ! 121: } */ *ap; ! 122: { ! 123: struct componentname *cnp = ap->a_cnp; ! 124: struct vnode **vpp = ap->a_vpp; ! 125: struct vnode *dvp = ap->a_dvp; ! 126: char *pname = cnp->cn_nameptr; ! 127: struct portalnode *pt; ! 128: int error; ! 129: struct vnode *fvp = 0; ! 130: char *path; ! 131: int size; ! 132: ! 133: *vpp = NULLVP; ! 134: ! 135: if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) ! 136: return (EROFS); ! 137: ! 138: if (cnp->cn_namelen == 1 && *pname == '.') { ! 139: *vpp = dvp; ! 140: VREF(dvp); ! 141: /*VOP_LOCK(dvp);*/ ! 142: return (0); ! 143: } ! 144: ! 145: MALLOC(pt, void *, sizeof(struct portalnode), M_TEMP, M_WAITOK); ! 146: error = getnewvnode(VT_PORTAL, dvp->v_mount, portal_vnodeop_p, &fvp); ! 147: if (error) { ! 148: FREE(pt, M_TEMP); ! 149: goto bad; ! 150: } ! 151: fvp->v_type = VREG; ! 152: fvp->v_data = pt; ! 153: ! 154: /* ! 155: * Save all of the remaining pathname and ! 156: * advance the namei next pointer to the end ! 157: * of the string. ! 158: */ ! 159: for (size = 0, path = pname; *path; path++) ! 160: size++; ! 161: cnp->cn_consume = size - cnp->cn_namelen; ! 162: ! 163: MALLOC(pt->pt_arg, caddr_t, size+1, M_TEMP, M_WAITOK); ! 164: pt->pt_size = size+1; ! 165: bcopy(pname, pt->pt_arg, pt->pt_size); ! 166: pt->pt_fileid = portal_fileid++; ! 167: ! 168: *vpp = fvp; ! 169: /*VOP_LOCK(fvp);*/ ! 170: return (0); ! 171: ! 172: bad: ! 173: if (fvp) ! 174: vrele(fvp); ! 175: return (error); ! 176: } ! 177: ! 178: static int ! 179: portal_connect(so, so2) ! 180: struct socket *so; ! 181: struct socket *so2; ! 182: { ! 183: /* from unp_connect, bypassing the namei stuff... */ ! 184: struct socket *so3; ! 185: struct unpcb *unp2; ! 186: struct unpcb *unp3; ! 187: ! 188: if (so2 == 0) ! 189: return (ECONNREFUSED); ! 190: ! 191: if (so->so_type != so2->so_type) ! 192: return (EPROTOTYPE); ! 193: ! 194: if ((so2->so_options & SO_ACCEPTCONN) == 0) ! 195: return (ECONNREFUSED); ! 196: ! 197: if ((so3 = sonewconn(so2, 0)) == 0) ! 198: return (ECONNREFUSED); ! 199: ! 200: unp2 = sotounpcb(so2); ! 201: unp3 = sotounpcb(so3); ! 202: if (unp2->unp_addr) ! 203: unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL); ! 204: ! 205: so2 = so3; ! 206: ! 207: ! 208: return (unp_connect2(so, so2)); ! 209: } ! 210: ! 211: int ! 212: portal_open(ap) ! 213: struct vop_open_args /* { ! 214: struct vnode *a_vp; ! 215: int a_mode; ! 216: struct ucred *a_cred; ! 217: struct proc *a_p; ! 218: } */ *ap; ! 219: { ! 220: struct socket *so = 0; ! 221: struct portalnode *pt; ! 222: struct proc *p = ap->a_p; ! 223: struct vnode *vp = ap->a_vp; ! 224: int s; ! 225: struct uio auio; ! 226: struct iovec aiov[2]; ! 227: int res; ! 228: struct mbuf *cm = 0; ! 229: struct cmsghdr *cmsg; ! 230: int newfds; ! 231: int *ip; ! 232: int fd; ! 233: int error; ! 234: int len; ! 235: struct portalmount *fmp; ! 236: struct file *fp; ! 237: struct portal_cred pcred; ! 238: ! 239: /* ! 240: * Nothing to do when opening the root node. ! 241: */ ! 242: if (vp->v_flag & VROOT) ! 243: return (0); ! 244: ! 245: /* ! 246: * Can't be opened unless the caller is set up ! 247: * to deal with the side effects. Check for this ! 248: * by testing whether the p_dupfd has been set. ! 249: */ ! 250: if (p->p_dupfd >= 0) ! 251: return (ENODEV); ! 252: ! 253: pt = VTOPORTAL(vp); ! 254: fmp = VFSTOPORTAL(vp->v_mount); ! 255: ! 256: /* ! 257: * Create a new socket. ! 258: */ ! 259: error = socreate(AF_UNIX, &so, SOCK_STREAM, 0); ! 260: if (error) ! 261: goto bad; ! 262: ! 263: /* ! 264: * Reserve some buffer space ! 265: */ ! 266: res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ ! 267: error = soreserve(so, res, res); ! 268: if (error) ! 269: goto bad; ! 270: ! 271: /* ! 272: * Kick off connection ! 273: */ ! 274: error = portal_connect(so, (struct socket *)fmp->pm_server->f_data); ! 275: if (error) ! 276: goto bad; ! 277: ! 278: /* ! 279: * Wait for connection to complete ! 280: */ ! 281: /* ! 282: * XXX: Since the mount point is holding a reference on the ! 283: * underlying server socket, it is not easy to find out whether ! 284: * the server process is still running. To handle this problem ! 285: * we loop waiting for the new socket to be connected (something ! 286: * which will only happen if the server is still running) or for ! 287: * the reference count on the server socket to drop to 1, which ! 288: * will happen if the server dies. Sleep for 5 second intervals ! 289: * and keep polling the reference count. XXX. ! 290: */ ! 291: s = splnet(); ! 292: while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { ! 293: if (fmp->pm_server->f_count == 1) { ! 294: error = ECONNREFUSED; ! 295: splx(s); ! 296: goto bad; ! 297: } ! 298: (void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz); ! 299: } ! 300: splx(s); ! 301: ! 302: if (so->so_error) { ! 303: error = so->so_error; ! 304: goto bad; ! 305: } ! 306: ! 307: /* ! 308: * Set miscellaneous flags ! 309: */ ! 310: so->so_rcv.sb_timeo = 0; ! 311: so->so_snd.sb_timeo = 0; ! 312: so->so_rcv.sb_flags |= SB_NOINTR; ! 313: so->so_snd.sb_flags |= SB_NOINTR; ! 314: ! 315: ! 316: pcred.pcr_flag = ap->a_mode; ! 317: pcred.pcr_uid = ap->a_cred->cr_uid; ! 318: pcred.pcr_ngroups = ap->a_cred->cr_ngroups; ! 319: bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); ! 320: aiov[0].iov_base = (caddr_t) &pcred; ! 321: aiov[0].iov_len = sizeof(pcred); ! 322: aiov[1].iov_base = pt->pt_arg; ! 323: aiov[1].iov_len = pt->pt_size; ! 324: auio.uio_iov = aiov; ! 325: auio.uio_iovcnt = 2; ! 326: auio.uio_rw = UIO_WRITE; ! 327: auio.uio_segflg = UIO_SYSSPACE; ! 328: auio.uio_procp = p; ! 329: auio.uio_offset = 0; ! 330: auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; ! 331: ! 332: error = sosend(so, (struct sockaddr *) 0, &auio, ! 333: (struct mbuf *) 0, (struct mbuf *) 0, 0); ! 334: if (error) ! 335: goto bad; ! 336: ! 337: len = auio.uio_resid = sizeof(int); ! 338: do { ! 339: struct mbuf *m = 0; ! 340: int flags = MSG_WAITALL; ! 341: error = soreceive(so, (struct sockaddr **) 0, &auio, ! 342: &m, &cm, &flags); ! 343: if (error) ! 344: goto bad; ! 345: ! 346: /* ! 347: * Grab an error code from the mbuf. ! 348: */ ! 349: if (m) { ! 350: m = m_pullup(m, sizeof(int)); /* Needed? */ ! 351: if (m) { ! 352: error = *(mtod(m, int *)); ! 353: m_freem(m); ! 354: } else { ! 355: error = EINVAL; ! 356: } ! 357: } else { ! 358: if (cm == 0) { ! 359: error = ECONNRESET; /* XXX */ ! 360: #ifdef notdef ! 361: break; ! 362: #endif ! 363: } ! 364: } ! 365: } while (cm == 0 && auio.uio_resid == len && !error); ! 366: ! 367: if (cm == 0) ! 368: goto bad; ! 369: ! 370: if (auio.uio_resid) { ! 371: error = 0; ! 372: #ifdef notdef ! 373: error = EMSGSIZE; ! 374: goto bad; ! 375: #endif ! 376: } ! 377: ! 378: /* ! 379: * XXX: Break apart the control message, and retrieve the ! 380: * received file descriptor. Note that more than one descriptor ! 381: * may have been received, or that the rights chain may have more ! 382: * than a single mbuf in it. What to do? ! 383: */ ! 384: cmsg = mtod(cm, struct cmsghdr *); ! 385: newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int); ! 386: if (newfds == 0) { ! 387: error = ECONNREFUSED; ! 388: goto bad; ! 389: } ! 390: /* ! 391: * At this point the rights message consists of a control message ! 392: * header, followed by a data region containing a vector of ! 393: * integer file descriptors. The fds were allocated by the action ! 394: * of receiving the control message. ! 395: */ ! 396: ip = (int *) (cmsg + 1); ! 397: fd = *ip++; ! 398: if (newfds > 1) { ! 399: /* ! 400: * Close extra fds. ! 401: */ ! 402: int i; ! 403: printf("portal_open: %d extra fds\n", newfds - 1); ! 404: for (i = 1; i < newfds; i++) { ! 405: portal_closefd(p, *ip); ! 406: ip++; ! 407: } ! 408: } ! 409: ! 410: /* ! 411: * Check that the mode the file is being opened for is a subset ! 412: * of the mode of the existing descriptor. ! 413: */ ! 414: fp = *fdfile(p, fd); ! 415: if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) { ! 416: portal_closefd(p, fd); ! 417: error = EACCES; ! 418: goto bad; ! 419: } ! 420: ! 421: /* ! 422: * Save the dup fd in the proc structure then return the ! 423: * special error code (ENXIO) which causes magic things to ! 424: * happen in vn_open. The whole concept is, well, hmmm. ! 425: */ ! 426: p->p_dupfd = fd; ! 427: error = ENXIO; ! 428: ! 429: bad:; ! 430: /* ! 431: * And discard the control message. ! 432: */ ! 433: if (cm) { ! 434: m_freem(cm); ! 435: } ! 436: ! 437: if (so) { ! 438: soshutdown(so, 2); ! 439: soclose(so); ! 440: } ! 441: return (error); ! 442: } ! 443: ! 444: int ! 445: portal_getattr(ap) ! 446: struct vop_getattr_args /* { ! 447: struct vnode *a_vp; ! 448: struct vattr *a_vap; ! 449: struct ucred *a_cred; ! 450: struct proc *a_p; ! 451: } */ *ap; ! 452: { ! 453: struct vnode *vp = ap->a_vp; ! 454: struct vattr *vap = ap->a_vap; ! 455: struct timeval tv; ! 456: ! 457: bzero(vap, sizeof(*vap)); ! 458: vattr_null(vap); ! 459: vap->va_uid = 0; ! 460: vap->va_gid = 0; ! 461: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; ! 462: vap->va_size = DEV_BSIZE; ! 463: vap->va_blocksize = DEV_BSIZE; ! 464: microtime(&tv); ! 465: TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime); ! 466: vap->va_mtime = vap->va_atime; ! 467: vap->va_ctime = vap->va_ctime; ! 468: vap->va_gen = 0; ! 469: vap->va_flags = 0; ! 470: vap->va_rdev = 0; ! 471: /* vap->va_qbytes = 0; */ ! 472: vap->va_bytes = 0; ! 473: /* vap->va_qsize = 0; */ ! 474: if (vp->v_flag & VROOT) { ! 475: vap->va_type = VDIR; ! 476: vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR| ! 477: S_IRGRP|S_IWGRP|S_IXGRP| ! 478: S_IROTH|S_IWOTH|S_IXOTH; ! 479: vap->va_nlink = 2; ! 480: vap->va_fileid = 2; ! 481: } else { ! 482: vap->va_type = VREG; ! 483: vap->va_mode = S_IRUSR|S_IWUSR| ! 484: S_IRGRP|S_IWGRP| ! 485: S_IROTH|S_IWOTH; ! 486: vap->va_nlink = 1; ! 487: vap->va_fileid = VTOPORTAL(vp)->pt_fileid; ! 488: } ! 489: return (0); ! 490: } ! 491: ! 492: int ! 493: portal_setattr(ap) ! 494: struct vop_setattr_args /* { ! 495: struct vnode *a_vp; ! 496: struct vattr *a_vap; ! 497: struct ucred *a_cred; ! 498: struct proc *a_p; ! 499: } */ *ap; ! 500: { ! 501: ! 502: /* ! 503: * Can't mess with the root vnode ! 504: */ ! 505: if (ap->a_vp->v_flag & VROOT) ! 506: return (EACCES); ! 507: ! 508: return (0); ! 509: } ! 510: ! 511: /* ! 512: * Fake readdir, just return empty directory. ! 513: * It is hard to deal with '.' and '..' so don't bother. ! 514: */ ! 515: int ! 516: portal_readdir(ap) ! 517: struct vop_readdir_args /* { ! 518: struct vnode *a_vp; ! 519: struct uio *a_uio; ! 520: struct ucred *a_cred; ! 521: int *a_eofflag; ! 522: u_long *a_cookies; ! 523: int a_ncookies; ! 524: } */ *ap; ! 525: { ! 526: ! 527: /* ! 528: * We don't allow exporting portal mounts, and currently local ! 529: * requests do not need cookies. ! 530: */ ! 531: if (ap->a_ncookies) ! 532: panic("portal_readdir: not hungry"); ! 533: ! 534: return (0); ! 535: } ! 536: ! 537: int ! 538: portal_inactive(ap) ! 539: struct vop_inactive_args /* { ! 540: struct vnode *a_vp; ! 541: struct proc *a_p; ! 542: } */ *ap; ! 543: { ! 544: ! 545: VOP_UNLOCK(ap->a_vp, 0, ap->a_p); ! 546: return (0); ! 547: } ! 548: ! 549: int ! 550: portal_reclaim(ap) ! 551: struct vop_reclaim_args /* { ! 552: struct vnode *a_vp; ! 553: } */ *ap; ! 554: { ! 555: struct portalnode *pt = VTOPORTAL(ap->a_vp); ! 556: ! 557: if (pt->pt_arg) { ! 558: _FREE((caddr_t) pt->pt_arg, M_TEMP); ! 559: pt->pt_arg = 0; ! 560: } ! 561: FREE(ap->a_vp->v_data, M_TEMP); ! 562: ap->a_vp->v_data = 0; ! 563: ! 564: return (0); ! 565: } ! 566: ! 567: /* ! 568: * Return POSIX pathconf information applicable to special devices. ! 569: */ ! 570: portal_pathconf(ap) ! 571: struct vop_pathconf_args /* { ! 572: struct vnode *a_vp; ! 573: int a_name; ! 574: int *a_retval; ! 575: } */ *ap; ! 576: { ! 577: ! 578: switch (ap->a_name) { ! 579: case _PC_LINK_MAX: ! 580: *ap->a_retval = LINK_MAX; ! 581: return (0); ! 582: case _PC_MAX_CANON: ! 583: *ap->a_retval = MAX_CANON; ! 584: return (0); ! 585: case _PC_MAX_INPUT: ! 586: *ap->a_retval = MAX_INPUT; ! 587: return (0); ! 588: case _PC_PIPE_BUF: ! 589: *ap->a_retval = PIPE_BUF; ! 590: return (0); ! 591: case _PC_CHOWN_RESTRICTED: ! 592: *ap->a_retval = 1; ! 593: return (0); ! 594: case _PC_VDISABLE: ! 595: *ap->a_retval = _POSIX_VDISABLE; ! 596: return (0); ! 597: default: ! 598: return (EINVAL); ! 599: } ! 600: /* NOTREACHED */ ! 601: } ! 602: ! 603: /* ! 604: * Print out the contents of a Portal vnode. ! 605: */ ! 606: /* ARGSUSED */ ! 607: int ! 608: portal_print(ap) ! 609: struct vop_print_args /* { ! 610: struct vnode *a_vp; ! 611: } */ *ap; ! 612: { ! 613: ! 614: printf("tag VT_PORTAL, portal vnode\n"); ! 615: return (0); ! 616: } ! 617: ! 618: /*void*/ ! 619: int ! 620: portal_vfree(ap) ! 621: struct vop_vfree_args /* { ! 622: struct vnode *a_pvp; ! 623: ino_t a_ino; ! 624: int a_mode; ! 625: } */ *ap; ! 626: { ! 627: ! 628: return (0); ! 629: } ! 630: ! 631: ! 632: /* ! 633: * Portal vnode unsupported operation ! 634: */ ! 635: int ! 636: portal_enotsupp() ! 637: { ! 638: ! 639: return (EOPNOTSUPP); ! 640: } ! 641: ! 642: /* ! 643: * Portal "should never get here" operation ! 644: */ ! 645: int ! 646: portal_badop() ! 647: { ! 648: ! 649: panic("portal: bad op"); ! 650: /* NOTREACHED */ ! 651: } ! 652: ! 653: /* ! 654: * Portal vnode null operation ! 655: */ ! 656: int ! 657: portal_nullop() ! 658: { ! 659: ! 660: return (0); ! 661: } ! 662: ! 663: #define portal_create ((int (*) __P((struct vop_create_args *)))portal_enotsupp) ! 664: #define portal_mknod ((int (*) __P((struct vop_mknod_args *)))portal_enotsupp) ! 665: #define portal_close ((int (*) __P((struct vop_close_args *)))nullop) ! 666: #define portal_access ((int (*) __P((struct vop_access_args *)))nullop) ! 667: #define portal_read ((int (*) __P((struct vop_read_args *)))portal_enotsupp) ! 668: #define portal_write ((int (*) __P((struct vop_write_args *)))portal_enotsupp) ! 669: #define portal_pagein ((int (*) __P((struct vop_pagein_args *)))portal_enotsupp) ! 670: #define portal_pageout ((int (*) __P((struct vop_pageout_args *)))portal_enotsupp) ! 671: #define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp) ! 672: #define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp) ! 673: #define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp) ! 674: #define portal_revoke vop_revoke ! 675: #define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) ! 676: #define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop) ! 677: #define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp) ! 678: #define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp) ! 679: #define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp) ! 680: #define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp) ! 681: #define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp) ! 682: #define portal_symlink \ ! 683: ((int (*) __P((struct vop_symlink_args *)))portal_enotsupp) ! 684: #define portal_readlink \ ! 685: ((int (*) __P((struct vop_readlink_args *)))portal_enotsupp) ! 686: #define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) ! 687: #define portal_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock) ! 688: #define portal_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock) ! 689: #define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop) ! 690: #define portal_strategy \ ! 691: ((int (*) __P((struct vop_strategy_args *)))portal_badop) ! 692: #define portal_islocked \ ! 693: ((int (*) __P((struct vop_islocked_args *)))vop_noislocked) ! 694: #define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked) ! 695: #define portal_advlock \ ! 696: ((int (*) __P((struct vop_advlock_args *)))portal_enotsupp) ! 697: #define portal_blkatoff \ ! 698: ((int (*) __P((struct vop_blkatoff_args *)))portal_enotsupp) ! 699: #define portal_valloc ((int(*) __P(( \ ! 700: struct vnode *pvp, \ ! 701: int mode, \ ! 702: struct ucred *cred, \ ! 703: struct vnode **vpp))) portal_enotsupp) ! 704: #define portal_truncate \ ! 705: ((int (*) __P((struct vop_truncate_args *)))portal_enotsupp) ! 706: #define portal_update ((int (*) __P((struct vop_update_args *)))portal_enotsupp) ! 707: #define portal_copyfile ((int (*) __P((struct vop_copyfile *)))err_copyfile) ! 708: #define portal_bwrite ((int (*) __P((struct vop_bwrite_args *)))portal_enotsupp) ! 709: ! 710: int (**portal_vnodeop_p)(); ! 711: struct vnodeopv_entry_desc portal_vnodeop_entries[] = { ! 712: { &vop_default_desc, vn_default_error }, ! 713: { &vop_lookup_desc, portal_lookup }, /* lookup */ ! 714: { &vop_create_desc, portal_create }, /* create */ ! 715: { &vop_mknod_desc, portal_mknod }, /* mknod */ ! 716: { &vop_open_desc, portal_open }, /* open */ ! 717: { &vop_close_desc, portal_close }, /* close */ ! 718: { &vop_access_desc, portal_access }, /* access */ ! 719: { &vop_getattr_desc, portal_getattr }, /* getattr */ ! 720: { &vop_setattr_desc, portal_setattr }, /* setattr */ ! 721: { &vop_read_desc, portal_read }, /* read */ ! 722: { &vop_write_desc, portal_write }, /* write */ ! 723: { &vop_ioctl_desc, portal_ioctl }, /* ioctl */ ! 724: { &vop_select_desc, portal_select }, /* select */ ! 725: { &vop_mmap_desc, portal_mmap }, /* mmap */ ! 726: { &vop_revoke_desc, portal_revoke }, /* revoke */ ! 727: { &vop_fsync_desc, portal_fsync }, /* fsync */ ! 728: { &vop_seek_desc, portal_seek }, /* seek */ ! 729: { &vop_remove_desc, portal_remove }, /* remove */ ! 730: { &vop_link_desc, portal_link }, /* link */ ! 731: { &vop_rename_desc, portal_rename }, /* rename */ ! 732: { &vop_mkdir_desc, portal_mkdir }, /* mkdir */ ! 733: { &vop_rmdir_desc, portal_rmdir }, /* rmdir */ ! 734: { &vop_symlink_desc, portal_symlink }, /* symlink */ ! 735: { &vop_readdir_desc, portal_readdir }, /* readdir */ ! 736: { &vop_readlink_desc, portal_readlink }, /* readlink */ ! 737: { &vop_abortop_desc, portal_abortop }, /* abortop */ ! 738: { &vop_inactive_desc, portal_inactive }, /* inactive */ ! 739: { &vop_reclaim_desc, portal_reclaim }, /* reclaim */ ! 740: { &vop_lock_desc, portal_lock }, /* lock */ ! 741: { &vop_unlock_desc, portal_unlock }, /* unlock */ ! 742: { &vop_bmap_desc, portal_bmap }, /* bmap */ ! 743: { &vop_strategy_desc, portal_strategy }, /* strategy */ ! 744: { &vop_print_desc, portal_print }, /* print */ ! 745: { &vop_islocked_desc, portal_islocked }, /* islocked */ ! 746: { &vop_pathconf_desc, portal_pathconf }, /* pathconf */ ! 747: { &vop_advlock_desc, portal_advlock }, /* advlock */ ! 748: { &vop_blkatoff_desc, portal_blkatoff }, /* blkatoff */ ! 749: { &vop_valloc_desc, portal_valloc }, /* valloc */ ! 750: { &vop_vfree_desc, portal_vfree }, /* vfree */ ! 751: { &vop_truncate_desc, portal_truncate }, /* truncate */ ! 752: { &vop_update_desc, portal_update }, /* update */ ! 753: { &vop_bwrite_desc, portal_bwrite }, /* bwrite */ ! 754: { &vop_pagein_desc, portal_pagein }, /* Pagein */ ! 755: { &vop_pageout_desc, portal_pageout }, /* Pageout */ ! 756: { &vop_copyfile_desc, portal_copyfile }, /* Copyfile */ ! 757: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 758: }; ! 759: struct vnodeopv_desc portal_vnodeop_opv_desc = ! 760: { &portal_vnodeop_p, portal_vnodeop_entries };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.