diff options
Diffstat (limited to 'sys/fs/portalfs')
-rw-r--r-- | sys/fs/portalfs/portal.h | 72 | ||||
-rw-r--r-- | sys/fs/portalfs/portal_vfsops.c | 313 | ||||
-rw-r--r-- | sys/fs/portalfs/portal_vnops.c | 707 |
3 files changed, 1092 insertions, 0 deletions
diff --git a/sys/fs/portalfs/portal.h b/sys/fs/portalfs/portal.h new file mode 100644 index 0000000..38d7ee0 --- /dev/null +++ b/sys/fs/portalfs/portal.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)portal.h 8.4 (Berkeley) 1/21/94 + * + * $Id: portal.h,v 1.3 1992/05/30 10:05:24 jsp Exp jsp $ + */ + +struct portal_args { + char *pa_config; /* Config file */ + int pa_socket; /* Socket to server */ +}; + +struct portal_cred { + int pcr_flag; /* File open mode */ + uid_t pcr_uid; /* From ucred */ + short pcr_ngroups; /* From ucred */ + gid_t pcr_groups[NGROUPS]; /* From ucred */ +}; + +#ifdef KERNEL +struct portalmount { + struct vnode *pm_root; /* Root node */ + struct file *pm_server; /* Held reference to server socket */ +}; + +struct portalnode { + int pt_size; /* Length of Arg */ + char *pt_arg; /* Arg to send to server */ + int pt_fileid; /* cookie */ +}; + +#define VFSTOPORTAL(mp) ((struct portalmount *)((mp)->mnt_data)) +#define VTOPORTAL(vp) ((struct portalnode *)(vp)->v_data) + +#define PORTAL_ROOTFILEID 2 + +extern int (**portal_vnodeop_p)(); +extern struct vfsops portal_vfsops; +#endif /* KERNEL */ diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c new file mode 100644 index 0000000..39e8563 --- /dev/null +++ b/sys/fs/portalfs/portal_vfsops.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)portal_vfsops.c 8.6 (Berkeley) 1/21/94 + * + * $Id: portal_vfsops.c,v 1.5 1992/05/30 10:25:27 jsp Exp jsp $ + */ + +/* + * Portal Filesystem + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/proc.h> +#include <sys/filedesc.h> +#include <sys/file.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/namei.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/un.h> +#include <miscfs/portal/portal.h> + +int +portal_init() +{ + + return (0); +} + +/* + * Mount the per-process file descriptors (/dev/fd) + */ +int +portal_mount(mp, path, data, ndp, p) + struct mount *mp; + char *path; + caddr_t data; + struct nameidata *ndp; + struct proc *p; +{ + struct file *fp; + struct portal_args args; + struct portalmount *fmp; + struct socket *so; + struct vnode *rvp; + u_int size; + int error; + + /* + * Update is a no-op + */ + if (mp->mnt_flag & MNT_UPDATE) + return (EOPNOTSUPP); + + if (error = copyin(data, (caddr_t) &args, sizeof(struct portal_args))) + return (error); + + if (error = getsock(p->p_fd, args.pa_socket, &fp)) + return (error); + so = (struct socket *) fp->f_data; + if (so->so_proto->pr_domain->dom_family != AF_UNIX) + return (ESOCKTNOSUPPORT); + + error = getnewvnode(VT_PORTAL, mp, portal_vnodeop_p, &rvp); /* XXX */ + if (error) + return (error); + MALLOC(rvp->v_data, void *, sizeof(struct portalnode), + M_TEMP, M_WAITOK); + + fmp = (struct portalmount *) malloc(sizeof(struct portalmount), + M_UFSMNT, M_WAITOK); /* XXX */ + rvp->v_type = VDIR; + rvp->v_flag |= VROOT; + VTOPORTAL(rvp)->pt_arg = 0; + VTOPORTAL(rvp)->pt_size = 0; + VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID; + fmp->pm_root = rvp; + fmp->pm_server = fp; fp->f_count++; + + mp->mnt_flag |= MNT_LOCAL; + mp->mnt_data = (qaddr_t) fmp; + getnewfsid(mp, MOUNT_PORTAL); + + (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); + bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); + (void)copyinstr(args.pa_config, + mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); + bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + +#ifdef notdef + bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); + bcopy("portal", mp->mnt_stat.f_mntfromname, sizeof("portal")); +#endif + + return (0); +} + +int +portal_start(mp, flags, p) + struct mount *mp; + int flags; + struct proc *p; +{ + + return (0); +} + +int +portal_unmount(mp, mntflags, p) + struct mount *mp; + int mntflags; + struct proc *p; +{ + extern int doforce; + struct vnode *rootvp = VFSTOPORTAL(mp)->pm_root; + int error, flags = 0; + + + if (mntflags & MNT_FORCE) { + /* portal can never be rootfs so don't check for it */ + if (!doforce) + return (EINVAL); + flags |= FORCECLOSE; + } + + /* + * Clear out buffer cache. I don't think we + * ever get anything cached at this level at the + * moment, but who knows... + */ +#ifdef notyet + mntflushbuf(mp, 0); + if (mntinvalbuf(mp, 1)) + return (EBUSY); +#endif + if (rootvp->v_usecount > 1) + return (EBUSY); + if (error = vflush(mp, rootvp, flags)) + return (error); + + /* + * Release reference on underlying root vnode + */ + vrele(rootvp); + /* + * And blow it away for future re-use + */ + vgone(rootvp); + /* + * Shutdown the socket. This will cause the select in the + * daemon to wake up, and then the accept will get ECONNABORTED + * which it interprets as a request to go and bury itself. + */ + soshutdown((struct socket *) VFSTOPORTAL(mp)->pm_server->f_data, 2); + /* + * Discard reference to underlying file. Must call closef because + * this may be the last reference. + */ + closef(VFSTOPORTAL(mp)->pm_server, (struct proc *) 0); + /* + * Finally, throw away the portalmount structure + */ + free(mp->mnt_data, M_UFSMNT); /* XXX */ + mp->mnt_data = 0; + return (0); +} + +int +portal_root(mp, vpp) + struct mount *mp; + struct vnode **vpp; +{ + struct vnode *vp; + + + /* + * Return locked reference to root. + */ + vp = VFSTOPORTAL(mp)->pm_root; + VREF(vp); + VOP_LOCK(vp); + *vpp = vp; + return (0); +} + +int +portal_quotactl(mp, cmd, uid, arg, p) + struct mount *mp; + int cmd; + uid_t uid; + caddr_t arg; + struct proc *p; +{ + + return (EOPNOTSUPP); +} + +int +portal_statfs(mp, sbp, p) + struct mount *mp; + struct statfs *sbp; + struct proc *p; +{ + + sbp->f_type = MOUNT_PORTAL; + sbp->f_flags = 0; + sbp->f_bsize = DEV_BSIZE; + sbp->f_iosize = DEV_BSIZE; + sbp->f_blocks = 2; /* 1K to keep df happy */ + sbp->f_bfree = 0; + sbp->f_bavail = 0; + sbp->f_files = 1; /* Allow for "." */ + sbp->f_ffree = 0; /* See comments above */ + if (sbp != &mp->mnt_stat) { + bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); + bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); + bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); + } + return (0); +} + +int +portal_sync(mp, waitfor) + struct mount *mp; + int waitfor; +{ + + return (0); +} + +int +portal_vget(mp, ino, vpp) + struct mount *mp; + ino_t ino; + struct vnode **vpp; +{ + + return (EOPNOTSUPP); +} + +int +portal_fhtovp(mp, fhp, vpp) + struct mount *mp; + struct fid *fhp; + struct vnode **vpp; +{ + + return (EOPNOTSUPP); +} + +int +portal_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; +{ + + return (EOPNOTSUPP); +} + +struct vfsops portal_vfsops = { + portal_mount, + portal_start, + portal_unmount, + portal_root, + portal_quotactl, + portal_statfs, + portal_sync, + portal_vget, + portal_fhtovp, + portal_vptofh, + portal_init, +}; diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c new file mode 100644 index 0000000..5e17026 --- /dev/null +++ b/sys/fs/portalfs/portal_vnops.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)portal_vnops.c 8.8 (Berkeley) 1/21/94 + * + * $Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp jsp $ + */ + +/* + * Portal Filesystem + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/filedesc.h> +#include <sys/vnode.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/mount.h> +#include <sys/malloc.h> +#include <sys/namei.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/un.h> +#include <sys/unpcb.h> +#include <miscfs/portal/portal.h> + +static int portal_fileid = PORTAL_ROOTFILEID+1; + +static void +portal_closefd(p, fd) + struct proc *p; + int fd; +{ + int error; + struct { + int fd; + } ua; + int rc; + + ua.fd = fd; + error = close(p, &ua, &rc); + /* + * We should never get an error, and there isn't anything + * we could do if we got one, so just print a message. + */ + if (error) + printf("portal_closefd: error = %d\n", error); +} + +/* + * vp is the current namei directory + * cnp is the name to locate in that directory... + */ +int +portal_lookup(ap) + struct vop_lookup_args /* { + struct vnode * a_dvp; + struct vnode ** a_vpp; + struct componentname * a_cnp; + } */ *ap; +{ + char *pname = ap->a_cnp->cn_nameptr; + struct portalnode *pt; + int error; + struct vnode *fvp = 0; + char *path; + int size; + + if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { + *ap->a_vpp = ap->a_dvp; + VREF(ap->a_dvp); + /*VOP_LOCK(ap->a_dvp);*/ + return (0); + } + + + error = getnewvnode(VT_PORTAL, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp); + if (error) + goto bad; + fvp->v_type = VREG; + MALLOC(fvp->v_data, void *, sizeof(struct portalnode), + M_TEMP, M_WAITOK); + + pt = VTOPORTAL(fvp); + /* + * Save all of the remaining pathname and + * advance the namei next pointer to the end + * of the string. + */ + for (size = 0, path = pname; *path; path++) + size++; + ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen; + + pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK); + pt->pt_size = size+1; + bcopy(pname, pt->pt_arg, pt->pt_size); + pt->pt_fileid = portal_fileid++; + + *ap->a_vpp = fvp; + /*VOP_LOCK(fvp);*/ + return (0); + +bad:; + if (fvp) { + vrele(fvp); + } + *ap->a_vpp = NULL; + return (error); +} + +static int +portal_connect(so, so2) + struct socket *so; + struct socket *so2; +{ + /* from unp_connect, bypassing the namei stuff... */ + struct socket *so3; + struct unpcb *unp2; + struct unpcb *unp3; + + if (so2 == 0) + return (ECONNREFUSED); + + if (so->so_type != so2->so_type) + return (EPROTOTYPE); + + if ((so2->so_options & SO_ACCEPTCONN) == 0) + return (ECONNREFUSED); + + if ((so3 = sonewconn(so2, 0)) == 0) + return (ECONNREFUSED); + + unp2 = sotounpcb(so2); + unp3 = sotounpcb(so3); + if (unp2->unp_addr) + unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL); + + so2 = so3; + + + return (unp_connect2(so, so2)); +} + +int +portal_open(ap) + struct vop_open_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct socket *so = 0; + struct portalnode *pt; + struct proc *p = ap->a_p; + struct vnode *vp = ap->a_vp; + int s; + struct uio auio; + struct iovec aiov[2]; + int res; + struct mbuf *cm = 0; + struct cmsghdr *cmsg; + int newfds; + int *ip; + int fd; + int error; + int len; + struct portalmount *fmp; + struct file *fp; + struct portal_cred pcred; + + /* + * Nothing to do when opening the root node. + */ + if (vp->v_flag & VROOT) + return (0); + + /* + * Can't be opened unless the caller is set up + * to deal with the side effects. Check for this + * by testing whether the p_dupfd has been set. + */ + if (p->p_dupfd >= 0) + return (ENODEV); + + pt = VTOPORTAL(vp); + fmp = VFSTOPORTAL(vp->v_mount); + + /* + * Create a new socket. + */ + error = socreate(AF_UNIX, &so, SOCK_STREAM, 0); + if (error) + goto bad; + + /* + * Reserve some buffer space + */ + res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ + error = soreserve(so, res, res); + if (error) + goto bad; + + /* + * Kick off connection + */ + error = portal_connect(so, (struct socket *)fmp->pm_server->f_data); + if (error) + goto bad; + + /* + * Wait for connection to complete + */ + /* + * XXX: Since the mount point is holding a reference on the + * underlying server socket, it is not easy to find out whether + * the server process is still running. To handle this problem + * we loop waiting for the new socket to be connected (something + * which will only happen if the server is still running) or for + * the reference count on the server socket to drop to 1, which + * will happen if the server dies. Sleep for 5 second intervals + * and keep polling the reference count. XXX. + */ + s = splnet(); + while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { + if (fmp->pm_server->f_count == 1) { + error = ECONNREFUSED; + splx(s); + goto bad; + } + (void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz); + } + splx(s); + + if (so->so_error) { + error = so->so_error; + goto bad; + } + + /* + * Set miscellaneous flags + */ + so->so_rcv.sb_timeo = 0; + so->so_snd.sb_timeo = 0; + so->so_rcv.sb_flags |= SB_NOINTR; + so->so_snd.sb_flags |= SB_NOINTR; + + + pcred.pcr_flag = ap->a_mode; + pcred.pcr_uid = ap->a_cred->cr_uid; + pcred.pcr_ngroups = ap->a_cred->cr_ngroups; + bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); + aiov[0].iov_base = (caddr_t) &pcred; + aiov[0].iov_len = sizeof(pcred); + aiov[1].iov_base = pt->pt_arg; + aiov[1].iov_len = pt->pt_size; + auio.uio_iov = aiov; + auio.uio_iovcnt = 2; + auio.uio_rw = UIO_WRITE; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_procp = p; + auio.uio_offset = 0; + auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; + + error = sosend(so, (struct mbuf *) 0, &auio, + (struct mbuf *) 0, (struct mbuf *) 0, 0); + if (error) + goto bad; + + len = auio.uio_resid = sizeof(int); + do { + struct mbuf *m = 0; + int flags = MSG_WAITALL; + error = soreceive(so, (struct mbuf **) 0, &auio, + &m, &cm, &flags); + if (error) + goto bad; + + /* + * Grab an error code from the mbuf. + */ + if (m) { + m = m_pullup(m, sizeof(int)); /* Needed? */ + if (m) { + error = *(mtod(m, int *)); + m_freem(m); + } else { + error = EINVAL; + } + } else { + if (cm == 0) { + error = ECONNRESET; /* XXX */ +#ifdef notdef + break; +#endif + } + } + } while (cm == 0 && auio.uio_resid == len && !error); + + if (cm == 0) + goto bad; + + if (auio.uio_resid) { + error = 0; +#ifdef notdef + error = EMSGSIZE; + goto bad; +#endif + } + + /* + * XXX: Break apart the control message, and retrieve the + * received file descriptor. Note that more than one descriptor + * may have been received, or that the rights chain may have more + * than a single mbuf in it. What to do? + */ + cmsg = mtod(cm, struct cmsghdr *); + newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int); + if (newfds == 0) { + error = ECONNREFUSED; + goto bad; + } + /* + * At this point the rights message consists of a control message + * header, followed by a data region containing a vector of + * integer file descriptors. The fds were allocated by the action + * of receiving the control message. + */ + ip = (int *) (cmsg + 1); + fd = *ip++; + if (newfds > 1) { + /* + * Close extra fds. + */ + int i; + printf("portal_open: %d extra fds\n", newfds - 1); + for (i = 1; i < newfds; i++) { + portal_closefd(p, *ip); + ip++; + } + } + + /* + * Check that the mode the file is being opened for is a subset + * of the mode of the existing descriptor. + */ + fp = p->p_fd->fd_ofiles[fd]; + if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) { + portal_closefd(p, fd); + error = EACCES; + goto bad; + } + + /* + * Save the dup fd in the proc structure then return the + * special error code (ENXIO) which causes magic things to + * happen in vn_open. The whole concept is, well, hmmm. + */ + p->p_dupfd = fd; + error = ENXIO; + +bad:; + /* + * And discard the control message. + */ + if (cm) { + m_freem(cm); + } + + if (so) { + soshutdown(so, 2); + soclose(so); + } + return (error); +} + +int +portal_getattr(ap) + struct vop_getattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct vattr *vap = ap->a_vap; + + bzero(vap, sizeof(*vap)); + vattr_null(vap); + vap->va_uid = 0; + vap->va_gid = 0; + vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; + vap->va_size = DEV_BSIZE; + vap->va_blocksize = DEV_BSIZE; + microtime(&vap->va_atime); + vap->va_mtime = vap->va_atime; + vap->va_ctime = vap->va_ctime; + vap->va_gen = 0; + vap->va_flags = 0; + vap->va_rdev = 0; + /* vap->va_qbytes = 0; */ + vap->va_bytes = 0; + /* vap->va_qsize = 0; */ + if (vp->v_flag & VROOT) { + vap->va_type = VDIR; + vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR| + S_IRGRP|S_IWGRP|S_IXGRP| + S_IROTH|S_IWOTH|S_IXOTH; + vap->va_nlink = 2; + vap->va_fileid = 2; + } else { + vap->va_type = VREG; + vap->va_mode = S_IRUSR|S_IWUSR| + S_IRGRP|S_IWGRP| + S_IROTH|S_IWOTH; + vap->va_nlink = 1; + vap->va_fileid = VTOPORTAL(vp)->pt_fileid; + } + return (0); +} + +int +portal_setattr(ap) + struct vop_setattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + + /* + * Can't mess with the root vnode + */ + if (ap->a_vp->v_flag & VROOT) + return (EACCES); + + return (0); +} + +/* + * Fake readdir, just return empty directory. + * It is hard to deal with '.' and '..' so don't bother. + */ +int +portal_readdir(ap) + struct vop_readdir_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + } */ *ap; +{ + + return (0); +} + +int +portal_inactive(ap) + struct vop_inactive_args /* { + struct vnode *a_vp; + } */ *ap; +{ + + return (0); +} + +int +portal_reclaim(ap) + struct vop_reclaim_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct portalnode *pt = VTOPORTAL(ap->a_vp); + + if (pt->pt_arg) { + free((caddr_t) pt->pt_arg, M_TEMP); + pt->pt_arg = 0; + } + FREE(ap->a_vp->v_data, M_TEMP); + ap->a_vp->v_data = 0; + + return (0); +} + +/* + * Return POSIX pathconf information applicable to special devices. + */ +portal_pathconf(ap) + struct vop_pathconf_args /* { + struct vnode *a_vp; + int a_name; + int *a_retval; + } */ *ap; +{ + + switch (ap->a_name) { + case _PC_LINK_MAX: + *ap->a_retval = LINK_MAX; + return (0); + case _PC_MAX_CANON: + *ap->a_retval = MAX_CANON; + return (0); + case _PC_MAX_INPUT: + *ap->a_retval = MAX_INPUT; + return (0); + case _PC_PIPE_BUF: + *ap->a_retval = PIPE_BUF; + return (0); + case _PC_CHOWN_RESTRICTED: + *ap->a_retval = 1; + return (0); + case _PC_VDISABLE: + *ap->a_retval = _POSIX_VDISABLE; + return (0); + default: + return (EINVAL); + } + /* NOTREACHED */ +} + +/* + * Print out the contents of a Portal vnode. + */ +/* ARGSUSED */ +int +portal_print(ap) + struct vop_print_args /* { + struct vnode *a_vp; + } */ *ap; +{ + + printf("tag VT_PORTAL, portal vnode\n"); + return (0); +} + +/*void*/ +int +portal_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; +{ + + return (0); +} + + +/* + * Portal vnode unsupported operation + */ +int +portal_enotsupp() +{ + + return (EOPNOTSUPP); +} + +/* + * Portal "should never get here" operation + */ +int +portal_badop() +{ + + panic("portal: bad op"); + /* NOTREACHED */ +} + +/* + * Portal vnode null operation + */ +int +portal_nullop() +{ + + return (0); +} + +#define portal_create ((int (*) __P((struct vop_create_args *)))portal_enotsupp) +#define portal_mknod ((int (*) __P((struct vop_mknod_args *)))portal_enotsupp) +#define portal_close ((int (*) __P((struct vop_close_args *)))nullop) +#define portal_access ((int (*) __P((struct vop_access_args *)))nullop) +#define portal_read ((int (*) __P((struct vop_read_args *)))portal_enotsupp) +#define portal_write ((int (*) __P((struct vop_write_args *)))portal_enotsupp) +#define portal_ioctl ((int (*) __P((struct vop_ioctl_args *)))portal_enotsupp) +#define portal_select ((int (*) __P((struct vop_select_args *)))portal_enotsupp) +#define portal_mmap ((int (*) __P((struct vop_mmap_args *)))portal_enotsupp) +#define portal_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) +#define portal_seek ((int (*) __P((struct vop_seek_args *)))nullop) +#define portal_remove ((int (*) __P((struct vop_remove_args *)))portal_enotsupp) +#define portal_link ((int (*) __P((struct vop_link_args *)))portal_enotsupp) +#define portal_rename ((int (*) __P((struct vop_rename_args *)))portal_enotsupp) +#define portal_mkdir ((int (*) __P((struct vop_mkdir_args *)))portal_enotsupp) +#define portal_rmdir ((int (*) __P((struct vop_rmdir_args *)))portal_enotsupp) +#define portal_symlink \ + ((int (*) __P((struct vop_symlink_args *)))portal_enotsupp) +#define portal_readlink \ + ((int (*) __P((struct vop_readlink_args *)))portal_enotsupp) +#define portal_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) +#define portal_lock ((int (*) __P((struct vop_lock_args *)))nullop) +#define portal_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) +#define portal_bmap ((int (*) __P((struct vop_bmap_args *)))portal_badop) +#define portal_strategy \ + ((int (*) __P((struct vop_strategy_args *)))portal_badop) +#define portal_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) +#define portal_advlock \ + ((int (*) __P((struct vop_advlock_args *)))portal_enotsupp) +#define portal_blkatoff \ + ((int (*) __P((struct vop_blkatoff_args *)))portal_enotsupp) +#define portal_valloc ((int(*) __P(( \ + struct vnode *pvp, \ + int mode, \ + struct ucred *cred, \ + struct vnode **vpp))) portal_enotsupp) +#define portal_truncate \ + ((int (*) __P((struct vop_truncate_args *)))portal_enotsupp) +#define portal_update ((int (*) __P((struct vop_update_args *)))portal_enotsupp) +#define portal_bwrite ((int (*) __P((struct vop_bwrite_args *)))portal_enotsupp) + +int (**portal_vnodeop_p)(); +struct vnodeopv_entry_desc portal_vnodeop_entries[] = { + { &vop_default_desc, vn_default_error }, + { &vop_lookup_desc, portal_lookup }, /* lookup */ + { &vop_create_desc, portal_create }, /* create */ + { &vop_mknod_desc, portal_mknod }, /* mknod */ + { &vop_open_desc, portal_open }, /* open */ + { &vop_close_desc, portal_close }, /* close */ + { &vop_access_desc, portal_access }, /* access */ + { &vop_getattr_desc, portal_getattr }, /* getattr */ + { &vop_setattr_desc, portal_setattr }, /* setattr */ + { &vop_read_desc, portal_read }, /* read */ + { &vop_write_desc, portal_write }, /* write */ + { &vop_ioctl_desc, portal_ioctl }, /* ioctl */ + { &vop_select_desc, portal_select }, /* select */ + { &vop_mmap_desc, portal_mmap }, /* mmap */ + { &vop_fsync_desc, portal_fsync }, /* fsync */ + { &vop_seek_desc, portal_seek }, /* seek */ + { &vop_remove_desc, portal_remove }, /* remove */ + { &vop_link_desc, portal_link }, /* link */ + { &vop_rename_desc, portal_rename }, /* rename */ + { &vop_mkdir_desc, portal_mkdir }, /* mkdir */ + { &vop_rmdir_desc, portal_rmdir }, /* rmdir */ + { &vop_symlink_desc, portal_symlink }, /* symlink */ + { &vop_readdir_desc, portal_readdir }, /* readdir */ + { &vop_readlink_desc, portal_readlink }, /* readlink */ + { &vop_abortop_desc, portal_abortop }, /* abortop */ + { &vop_inactive_desc, portal_inactive }, /* inactive */ + { &vop_reclaim_desc, portal_reclaim }, /* reclaim */ + { &vop_lock_desc, portal_lock }, /* lock */ + { &vop_unlock_desc, portal_unlock }, /* unlock */ + { &vop_bmap_desc, portal_bmap }, /* bmap */ + { &vop_strategy_desc, portal_strategy }, /* strategy */ + { &vop_print_desc, portal_print }, /* print */ + { &vop_islocked_desc, portal_islocked }, /* islocked */ + { &vop_pathconf_desc, portal_pathconf }, /* pathconf */ + { &vop_advlock_desc, portal_advlock }, /* advlock */ + { &vop_blkatoff_desc, portal_blkatoff }, /* blkatoff */ + { &vop_valloc_desc, portal_valloc }, /* valloc */ + { &vop_vfree_desc, portal_vfree }, /* vfree */ + { &vop_truncate_desc, portal_truncate }, /* truncate */ + { &vop_update_desc, portal_update }, /* update */ + { &vop_bwrite_desc, portal_bwrite }, /* bwrite */ + { (struct vnodeop_desc*)NULL, (int(*)())NULL } +}; +struct vnodeopv_desc portal_vnodeop_opv_desc = + { &portal_vnodeop_p, portal_vnodeop_entries }; |