153846Spendry /*
253846Spendry  * Copyright (c) 1992 The Regents of the University of California
353846Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
453846Spendry  * All rights reserved.
553846Spendry  *
653846Spendry  * This code is derived from software donated to Berkeley by
753846Spendry  * Jan-Simon Pendry.
853846Spendry  *
953846Spendry  * %sccs.include.redist.c%
1053846Spendry  *
11*54978Spendry  *	@(#)portal_vnops.c	1.2 (Berkeley) 07/12/92
1253846Spendry  *
1353846Spendry  * $Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp jsp $
1453846Spendry  */
1553846Spendry 
1653846Spendry /*
1753846Spendry  * Portal Filesystem
1853846Spendry  */
1953846Spendry 
2053846Spendry #include <sys/param.h>
2153846Spendry #include <sys/systm.h>
2253846Spendry #include <sys/kernel.h>
2353846Spendry #include <sys/types.h>
2453846Spendry #include <sys/time.h>
2553846Spendry #include <sys/proc.h>
2653846Spendry /*#include <sys/resourcevar.h>*/
2753846Spendry #include <sys/filedesc.h>
2853846Spendry #include <sys/vnode.h>
2953846Spendry #include <sys/file.h>
3053846Spendry #include <sys/stat.h>
3153846Spendry #include <sys/mount.h>
3253846Spendry #include <sys/malloc.h>
3353846Spendry #include <sys/namei.h>
3453846Spendry /*#include <sys/buf.h>*/
3553846Spendry #include <sys/mbuf.h>
3653846Spendry #include <sys/socket.h>
3753846Spendry #include <sys/socketvar.h>
3853846Spendry #include <sys/un.h>
3953846Spendry #include <sys/unpcb.h>
4053846Spendry #include <portal/portal.h>
4153846Spendry 
4253846Spendry static int portal_fileid = PORTAL_ROOTFILEID+1;
4353846Spendry 
4453846Spendry static void
4553846Spendry portal_closefd(p, fd)
4653846Spendry 	struct proc *p;
4753846Spendry 	int fd;
4853846Spendry {
4953846Spendry 	int error;
5053846Spendry 	struct {
5153846Spendry 		int fd;
5253846Spendry 	} ua;
5353846Spendry 	int rc;
5453846Spendry 
5553846Spendry 	ua.fd = fd;
5653846Spendry 	error = close(p, &ua, &rc);
5753846Spendry 	/*
5853846Spendry 	 * We should never get an error, and there isn't anything
5953846Spendry 	 * we could do if we got one, so just print a message.
6053846Spendry 	 */
6153846Spendry 	if (error)
6253846Spendry 		printf("portal_closefd: error = %d\n", error);
6353846Spendry }
6453846Spendry 
6553846Spendry /*
6653846Spendry  * vp is the current namei directory
6753846Spendry  * cnp is the name to locate in that directory...
6853846Spendry  */
6953846Spendry portal_lookup (ap)
7053846Spendry 	struct vop_lookup_args *ap;
7153846Spendry {
7253846Spendry 	char *pname = ap->a_cnp->cn_nameptr;
7353846Spendry 	struct portalnode *pt;
7453846Spendry 	int error;
7553846Spendry 	struct vnode *fvp = 0;
7653846Spendry 	char *path;
7753846Spendry 	int size;
7853846Spendry 
7953846Spendry #ifdef PORTAL_DIAGNOSTIC
8053846Spendry 	printf("portal_lookup(%s)\n", pname);
8153846Spendry #endif
8253846Spendry 	if (ap->a_cnp->cn_namelen == 1 && *pname == '.') {
8353846Spendry 		*ap->a_vpp = ap->a_dvp;
8453846Spendry 		VREF(ap->a_dvp);
8553846Spendry 		/*VOP_LOCK(ap->a_dvp);*/
8653846Spendry 		return (0);
8753846Spendry 	}
8853846Spendry 
8953846Spendry 
9053846Spendry #ifdef PORTAL_DIAGNOSTIC
9153846Spendry 	printf("portal_lookup: allocate new vnode\n");
9253846Spendry #endif
9353846Spendry 	error = getnewvnode(VT_UFS, ap->a_dvp->v_mount, portal_vnodeop_p, &fvp);
9453846Spendry 	if (error)
9553846Spendry 		goto bad;
9653846Spendry 	fvp->v_type = VREG;
9753846Spendry 	MALLOC(fvp->v_data, void *, sizeof(struct portalnode),
9853846Spendry 		M_TEMP, M_WAITOK);
9953846Spendry 
10053846Spendry 	pt = VTOPORTAL(fvp);
10153846Spendry 	/*
10253846Spendry 	 * Save all of the remaining pathname and
10353846Spendry 	 * advance the namei next pointer to the end
10453846Spendry 	 * of the string.
10553846Spendry 	 */
10653846Spendry 	for (size = 0, path = pname; *path; path++)
10753846Spendry 		size++;
108*54978Spendry 	ap->a_cnp->cn_consume = size - ap->a_cnp->cn_namelen;
109*54978Spendry 
11053846Spendry 	pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
11153846Spendry 	pt->pt_size = size+1;
11253846Spendry 	bcopy(pname, pt->pt_arg, pt->pt_size);
11353846Spendry 	pt->pt_fileid = portal_fileid++;
11453846Spendry 
11553846Spendry 	*ap->a_vpp = fvp;
11653846Spendry 	/*VOP_LOCK(fvp);*/
11753846Spendry #ifdef PORTAL_DIAGNOSTIC
11853846Spendry 	printf("portal_lookup: newvp = %x\n", fvp);
11953846Spendry #endif
12053846Spendry 	return (0);
12153846Spendry 
12253846Spendry bad:;
12353846Spendry 	if (fvp) {
12453846Spendry #ifdef PORTAL_DIAGNOSTIC
12553846Spendry 		printf("portal_lookup: vrele(%x)\n", fvp);
12653846Spendry #endif
12753846Spendry 		vrele(fvp);
12853846Spendry 	}
12953846Spendry 	*ap->a_vpp = NULL;
13053846Spendry #ifdef PORTAL_DIAGNOSTIC
13153846Spendry 	printf("portal_lookup: error = %d\n", error);
13253846Spendry #endif
13353846Spendry 	return (error);
13453846Spendry }
13553846Spendry 
13653846Spendry static int
13753846Spendry portal_connect(so, so2)
13853846Spendry 	struct socket *so;
13953846Spendry 	struct socket *so2;
14053846Spendry {
14153846Spendry 	/* from unp_connect, bypassing the namei stuff... */
14253846Spendry 
14353846Spendry 	struct socket *so3;
14453846Spendry 	struct unpcb *unp2;
14553846Spendry 	struct unpcb *unp3;
14653846Spendry 
14753846Spendry #ifdef PORTAL_DIAGNOSTIC
14853846Spendry 	printf("portal_connect\n");
14953846Spendry #endif
15053846Spendry 
15153846Spendry 	if (so2 == 0)
15253846Spendry 		return (ECONNREFUSED);
15353846Spendry 
15453846Spendry 	if (so->so_type != so2->so_type)
15553846Spendry 		return (EPROTOTYPE);
15653846Spendry 
15753846Spendry 	if ((so2->so_options & SO_ACCEPTCONN) == 0)
15853846Spendry 		return (ECONNREFUSED);
15953846Spendry 
16053846Spendry #ifdef PORTAL_DIAGNOSTIC
16153846Spendry 	printf("portal_connect: calling sonewconn\n");
16253846Spendry #endif
16353846Spendry 
16453846Spendry 	if ((so3 = sonewconn(so2, 0)) == 0)
16553846Spendry 		return (ECONNREFUSED);
16653846Spendry 
16753846Spendry 	unp2 = sotounpcb(so2);
16853846Spendry 	unp3 = sotounpcb(so3);
16953846Spendry 	if (unp2->unp_addr)
17053846Spendry 		unp3->unp_addr = m_copy(unp2->unp_addr, 0, (int)M_COPYALL);
17153846Spendry 
17253846Spendry 	so2 = so3;
17353846Spendry 
17453846Spendry #ifdef PORTAL_DIAGNOSTIC
17553846Spendry 	printf("portal_connect: calling unp_connect2\n");
17653846Spendry #endif
17753846Spendry 
17853846Spendry 	return (unp_connect2(so, so2));
17953846Spendry }
18053846Spendry 
18153846Spendry portal_open (ap)
18253846Spendry 	struct vop_open_args *ap;
18353846Spendry {
18453846Spendry 	struct socket *so = 0;
18553846Spendry 	struct portalnode *pt;
18653846Spendry 	int s;
18753846Spendry 	struct uio auio;
18853846Spendry 	struct iovec aiov[2];
18953846Spendry 	int res;
19053846Spendry 	struct mbuf *cm = 0;
19153846Spendry 	struct cmsghdr *cmsg;
19253846Spendry 	int newfds;
19353846Spendry 	int *ip;
19453846Spendry 	int fd;
19553846Spendry 	int error;
19653846Spendry 	int len;
19753846Spendry 	struct portalmount *fmp;
19853846Spendry 	struct file *fp;
19953846Spendry 	struct portal_cred pcred;
20053846Spendry 
20153846Spendry 	/*
20253846Spendry 	 * Nothing to do when opening the root node.
20353846Spendry 	 */
20453846Spendry 	if (ap->a_vp->v_flag & VROOT)
20553846Spendry 		return (0);
20653846Spendry 
20753846Spendry #ifdef PORTAL_DIAGNOSTIC
20853846Spendry 	printf("portal_open(%x)\n", ap->a_vp);
20953846Spendry #endif
21053846Spendry 
21153846Spendry 	/*
21253846Spendry 	 * Can't be opened unless the caller is set up
21353846Spendry 	 * to deal with the side effects.  Check for this
21453846Spendry 	 * by testing whether the p_dupfd has been set.
21553846Spendry 	 */
21653846Spendry 	if (ap->a_p->p_dupfd >= 0)
21753846Spendry 		return (ENODEV);
21853846Spendry 
21953846Spendry 	pt = VTOPORTAL(ap->a_vp);
22053846Spendry 	fmp = VFSTOPORTAL(ap->a_vp->v_mount);
22153846Spendry 
22253846Spendry 	/*
22353846Spendry 	 * Create a new socket.
22453846Spendry 	 */
22553846Spendry 	error = socreate(AF_UNIX, &so, SOCK_STREAM, 0);
22653846Spendry 	if (error)
22753846Spendry 		goto bad;
22853846Spendry 
22953846Spendry 	/*
23053846Spendry 	 * Reserve some buffer space
23153846Spendry 	 */
23253846Spendry #ifdef PORTAL_DIAGNOSTIC
23353846Spendry 	printf("portal_open: calling soreserve\n");
23453846Spendry #endif
235*54978Spendry 	res = pt->pt_size + sizeof(pcred) + 512;	/* XXX */
23653846Spendry 	error = soreserve(so, res, res);
23753846Spendry 	if (error)
23853846Spendry 		goto bad;
23953846Spendry 
24053846Spendry 	/*
24153846Spendry 	 * Kick off connection
24253846Spendry 	 */
24353846Spendry #ifdef PORTAL_DIAGNOSTIC
24453846Spendry 	printf("portal_open: calling portal_connect\n");
24553846Spendry #endif
24653846Spendry 	error = portal_connect(so, (struct socket *)fmp->pm_server->f_data);
24753846Spendry 	if (error)
24853846Spendry 		goto bad;
24953846Spendry 
25053846Spendry 	/*
25153846Spendry 	 * Wait for connection to complete
25253846Spendry 	 */
25353846Spendry #ifdef PORTAL_DIAGNOSTIC
25453846Spendry 	printf("portal_open: waiting for connect\n");
25553846Spendry #endif
25653846Spendry 	/*
25753846Spendry 	 * XXX: Since the mount point is holding a reference on the
25853846Spendry 	 * underlying server socket, it is not easy to find out whether
25953846Spendry 	 * the server process is still running.  To handle this problem
26053846Spendry 	 * we loop waiting for the new socket to be connected (something
26153846Spendry 	 * which will only happen if the server is still running) or for
26253846Spendry 	 * the reference count on the server socket to drop to 1, which
26353846Spendry 	 * will happen if the server dies.  Sleep for 5 second intervals
26453846Spendry 	 * and keep polling the reference count.   XXX.
26553846Spendry 	 */
26653846Spendry 	s = splnet();
26753846Spendry 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
26853846Spendry 		if (fmp->pm_server->f_count == 1) {
26953846Spendry 			error = ECONNREFUSED;
27053846Spendry 			splx(s);
27153846Spendry #ifdef PORTAL_DIAGNOSTIC
27253846Spendry 			printf("portal_open: server process has gone away\n");
27353846Spendry #endif
27453846Spendry 			goto bad;
27553846Spendry 		}
27653846Spendry 		(void) tsleep((caddr_t) &so->so_timeo, PSOCK, "portalcon", 5 * hz);
27753846Spendry 	}
27853846Spendry 	splx(s);
27953846Spendry 
28053846Spendry 	if (so->so_error) {
28153846Spendry 		error = so->so_error;
28253846Spendry 		goto bad;
28353846Spendry 	}
28453846Spendry 
28553846Spendry 	/*
28653846Spendry 	 * Set miscellaneous flags
28753846Spendry 	 */
28853846Spendry 	so->so_rcv.sb_timeo = 0;
28953846Spendry 	so->so_snd.sb_timeo = 0;
29053846Spendry 	so->so_rcv.sb_flags |= SB_NOINTR;
29153846Spendry 	so->so_snd.sb_flags |= SB_NOINTR;
29253846Spendry 
29353846Spendry #ifdef PORTAL_DIAGNOSTIC
29453846Spendry 	printf("portal_open: constructing data uio\n");
29553846Spendry #endif
29653846Spendry 
297*54978Spendry 	pcred.pcr_flag = ap->a_mode;
29853846Spendry 	pcred.pcr_uid = ap->a_cred->cr_uid;
299*54978Spendry 	pcred.pcr_ngroups = ap->a_cred->cr_ngroups;
300*54978Spendry 	bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t));
30153846Spendry 	aiov[0].iov_base = (caddr_t) &pcred;
30253846Spendry 	aiov[0].iov_len = sizeof(pcred);
30353846Spendry 	aiov[1].iov_base = pt->pt_arg;
30453846Spendry 	aiov[1].iov_len = pt->pt_size;
30553846Spendry 	auio.uio_iov = aiov;
30653846Spendry 	auio.uio_iovcnt = 2;
30753846Spendry 	auio.uio_rw = UIO_WRITE;
30853846Spendry 	auio.uio_segflg = UIO_SYSSPACE;
30953846Spendry 	auio.uio_procp = ap->a_p;
31053846Spendry 	auio.uio_offset = 0;
31153846Spendry 	auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;
31253846Spendry 
31353846Spendry #ifdef PORTAL_DIAGNOSTIC
31453846Spendry 	printf("portal_open: sending data to server\n");
31553846Spendry #endif
31653846Spendry 	error = sosend(so, (struct sockaddr *) 0, &auio,
31753846Spendry 			(struct mbuf *) 0, (struct mbuf *) 0, 0);
31853846Spendry 	if (error)
31953846Spendry 		goto bad;
32053846Spendry 
32153846Spendry 	len = auio.uio_resid = sizeof(int);
32253846Spendry 	do {
32353846Spendry 		struct mbuf *m = 0;
32453846Spendry 		int flags = MSG_WAITALL;
32553846Spendry #ifdef PORTAL_DIAGNOSTIC
32653846Spendry 		printf("portal_open: receiving data from server\n");
32753846Spendry 		printf("portal_open: so = %x, cm = %x, resid = %d\n",
32853846Spendry 				so, cm, auio.uio_resid);
32953846Spendry 		printf("portal_open, uio=%x, mp0=%x, controlp=%x\n", &auio, &cm);
33053846Spendry #endif
33153846Spendry 		error = soreceive(so, (struct mbuf **) 0, &auio,
33253846Spendry 					&m, &cm, &flags);
33353846Spendry #ifdef PORTAL_DIAGNOSTIC
33453846Spendry 		printf("portal_open: after receiving data\n");
33553846Spendry 		printf("portal_open: so = %x, cm = %x, resid = %d\n",
33653846Spendry 				so, cm, auio.uio_resid);
33753846Spendry #endif
33853846Spendry 		if (error)
33953846Spendry 			goto bad;
34053846Spendry 
34153846Spendry 		/*
34253846Spendry 		 * Grab an error code from the mbuf.
34353846Spendry 		 */
34453846Spendry 		if (m) {
34553846Spendry 			m = m_pullup(m, sizeof(int));	/* Needed? */
34653846Spendry 			if (m) {
34753846Spendry 				error = *(mtod(m, int *));
34853846Spendry 				m_freem(m);
34953846Spendry 			} else {
35053846Spendry 				error = EINVAL;
35153846Spendry 			}
35253846Spendry #ifdef PORTAL_DIAGNOSTIC
35353846Spendry 			printf("portal_open: error returned is %d\n", error);
35453846Spendry #endif
35553846Spendry 		} else {
35653846Spendry 			if (cm == 0) {
35753846Spendry #ifdef PORTAL_DIAGNOSTIC
35853846Spendry 				printf("portal_open: no rights received\n");
35953846Spendry #endif
36053846Spendry 				error = ECONNRESET;	 /* XXX */
36153846Spendry #ifdef notdef
36253846Spendry 				break;
36353846Spendry #endif
36453846Spendry 			}
36553846Spendry 		}
36653846Spendry 	} while (cm == 0 && auio.uio_resid == len && !error);
36753846Spendry 
36853846Spendry 	if (cm == 0)
36953846Spendry 		goto bad;
37053846Spendry 
37153846Spendry 	if (auio.uio_resid) {
37253846Spendry #ifdef PORTAL_DIAGNOSTIC
37353846Spendry 		printf("portal_open: still need another %d bytes\n", auio.uio_resid);
37453846Spendry #endif
37553846Spendry 		error = 0;
37653846Spendry #ifdef notdef
37753846Spendry 		error = EMSGSIZE;
37853846Spendry 		goto bad;
37953846Spendry #endif
38053846Spendry 	}
38153846Spendry 
38253846Spendry 	/*
38353846Spendry 	 * XXX: Break apart the control message, and retrieve the
38453846Spendry 	 * received file descriptor.  Note that more than one descriptor
38553846Spendry 	 * may have been received, or that the rights chain may have more
38653846Spendry 	 * than a single mbuf in it.  What to do?
38753846Spendry 	 */
38853846Spendry #ifdef PORTAL_DIAGNOSTIC
38953846Spendry 	printf("portal_open: about to break apart control message\n");
39053846Spendry #endif
39153846Spendry 	cmsg = mtod(cm, struct cmsghdr *);
39253846Spendry 	newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
39353846Spendry 	if (newfds == 0) {
39453846Spendry #ifdef PORTAL_DIAGNOSTIC
39553846Spendry 		printf("portal_open: received no fds\n");
39653846Spendry #endif
39753846Spendry 		error = ECONNREFUSED;
39853846Spendry 		goto bad;
39953846Spendry 	}
40053846Spendry 	/*
40153846Spendry 	 * At this point the rights message consists of a control message
40253846Spendry 	 * header, followed by a data region containing a vector of
40353846Spendry 	 * integer file descriptors.  The fds were allocated by the action
40453846Spendry 	 * of receiving the control message.
40553846Spendry 	 */
40653846Spendry 	ip = (int *) (cmsg + 1);
40753846Spendry 	fd = *ip++;
40853846Spendry 	if (newfds > 1) {
40953846Spendry 		/*
41053846Spendry 		 * Close extra fds.
41153846Spendry 		 */
41253846Spendry 		int i;
41353846Spendry 		printf("portal_open: %d extra fds\n", newfds - 1);
41453846Spendry 		for (i = 1; i < newfds; i++) {
41553846Spendry 			portal_closefd(ap->a_p, *ip);
41653846Spendry 			ip++;
41753846Spendry 		}
41853846Spendry 	}
41953846Spendry 
42053846Spendry 	/*
42153846Spendry 	 * Check that the ap->a_mode the file is being opened for is a subset
42253846Spendry 	 * of the ap->a_mode of the existing descriptor.
42353846Spendry 	 */
42453846Spendry #ifdef PORTAL_DIAGNOSTIC
42553846Spendry 	printf("portal_open: checking file flags, fd = %d\n", fd);
42653846Spendry #endif
42753846Spendry  	fp = ap->a_p->p_fd->fd_ofiles[fd];
42853846Spendry 	if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
42953846Spendry 		portal_closefd(ap->a_p, fd);
43053846Spendry 		error = EACCES;
43153846Spendry 		goto bad;
43253846Spendry 	}
43353846Spendry 
43453846Spendry #ifdef PORTAL_DIAGNOSTIC
43553846Spendry 	printf("portal_open: got fd = %d\n", fd);
43653846Spendry #endif
43753846Spendry 	/*
43853846Spendry 	 * Save the dup fd in the proc structure then return the
43953846Spendry 	 * special error code (ENXIO) which causes magic things to
44053846Spendry 	 * happen in vn_open.  The whole concept is, well, hmmm.
44153846Spendry 	 */
44253846Spendry 	ap->a_p->p_dupfd = fd;
44353846Spendry 	error = ENXIO;
44453846Spendry 
44553846Spendry bad:;
44653846Spendry 	/*
44753846Spendry 	 * And discard the control message.
44853846Spendry 	 */
44953846Spendry 	if (cm) {
45053846Spendry #ifdef PORTAL_DIAGNOSTIC
45153846Spendry 		printf("portal_open: free'ing control message\n");
45253846Spendry #endif
45353846Spendry 		m_freem(cm);
45453846Spendry 	}
45553846Spendry 
45653846Spendry 	if (so) {
45753846Spendry #ifdef PORTAL_DIAGNOSTIC
45853846Spendry 		printf("portal_open: calling soshutdown\n");
45953846Spendry #endif
46053846Spendry 		soshutdown(so, 2);
46153846Spendry #ifdef PORTAL_DIAGNOSTIC
46253846Spendry 		printf("portal_open: calling soclose\n");
46353846Spendry #endif
46453846Spendry 		soclose(so);
46553846Spendry 	}
46653846Spendry #ifdef PORTAL_DIAGNOSTIC
46753846Spendry 	if (error != ENODEV)
46853846Spendry 		printf("portal_open: error = %d\n", error);
46953846Spendry #endif
47053846Spendry 	return (error);
47153846Spendry }
47253846Spendry 
47353846Spendry portal_getattr (ap)
47453846Spendry 	struct vop_getattr_args *ap;
47553846Spendry {
47653846Spendry 	unsigned fd;
47753846Spendry 	int error;
47853846Spendry 
47953846Spendry 	bzero((caddr_t) ap->a_vap, sizeof(*ap->a_vap));
48053846Spendry 	vattr_null(ap->a_vap);
48153846Spendry 	ap->a_vap->va_uid = 0;
48253846Spendry 	ap->a_vap->va_gid = 0;
48353846Spendry 	ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
48453846Spendry 	ap->a_vap->va_size = DEV_BSIZE;
48553846Spendry 	ap->a_vap->va_blocksize = DEV_BSIZE;
48653846Spendry 	microtime(&ap->a_vap->va_atime);
48753846Spendry 	ap->a_vap->va_mtime = ap->a_vap->va_atime;
48853846Spendry 	ap->a_vap->va_ctime = ap->a_vap->va_ctime;
48953846Spendry 	ap->a_vap->va_gen = 0;
49053846Spendry 	ap->a_vap->va_flags = 0;
49153846Spendry 	ap->a_vap->va_rdev = 0;
49253846Spendry 	/* ap->a_vap->va_qbytes = 0; */
49353846Spendry 	ap->a_vap->va_bytes = 0;
49453846Spendry 	/* ap->a_vap->va_qsize = 0; */
49553846Spendry 	if (ap->a_vp->v_flag & VROOT) {
49653846Spendry #ifdef PORTAL_DIAGNOSTIC
49753846Spendry 		printf("portal_getattr: stat rootdir\n");
49853846Spendry #endif
49953846Spendry 		ap->a_vap->va_type = VDIR;
50053846Spendry 		ap->a_vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR|
50153846Spendry 				S_IRGRP|S_IWGRP|S_IXGRP|
50253846Spendry 				S_IROTH|S_IWOTH|S_IXOTH;
50353846Spendry 		ap->a_vap->va_nlink = 2;
50453846Spendry 		ap->a_vap->va_fileid = 2;
50553846Spendry 	} else {
50653846Spendry #ifdef PORTAL_DIAGNOSTIC
50753846Spendry 		printf("portal_getattr: stat portal\n");
50853846Spendry #endif
50953846Spendry 		ap->a_vap->va_type = VREG;
51053846Spendry 		ap->a_vap->va_mode = S_IRUSR|S_IWUSR|
51153846Spendry 				S_IRGRP|S_IWGRP|
51253846Spendry 				S_IROTH|S_IWOTH;
51353846Spendry 		ap->a_vap->va_nlink = 1;
51453846Spendry 		ap->a_vap->va_fileid = VTOPORTAL(ap->a_vp)->pt_fileid;
51553846Spendry 	}
51653846Spendry 	return (0);
51753846Spendry }
51853846Spendry 
51953846Spendry portal_setattr (ap)
52053846Spendry 	struct vop_setattr_args *ap;
52153846Spendry {
52253846Spendry 	/*
52353846Spendry 	 * Can't mess with the root vnode
52453846Spendry 	 */
52553846Spendry 	if (ap->a_vp->v_flag & VROOT)
52653846Spendry 		return (EACCES);
52753846Spendry 
52853846Spendry 	return (0);
52953846Spendry }
53053846Spendry 
53153846Spendry /*
53253846Spendry  * Fake readdir, just return empty directory.
53353846Spendry  * It is hard to deal with '.' and '..' so don't bother.
53453846Spendry  */
53553846Spendry portal_readdir (ap)
53653846Spendry 	struct vop_readdir_args *ap;
53753846Spendry {
538*54978Spendry 	/* *ap->a_eofflagp = 1; */
53953846Spendry 	return (0);
54053846Spendry }
54153846Spendry 
54253846Spendry portal_inactive (ap)
54353846Spendry 	struct vop_inactive_args *ap;
54453846Spendry {
54553846Spendry #ifdef PORTAL_DIAGNOSTIC
54653846Spendry 	if (VTOPORTAL(ap->a_vp)->pt_arg)
54753846Spendry 		printf("portal_inactive(%x, %s)\n", ap->a_vp, VTOPORTAL(ap->a_vp)->pt_arg);
54853846Spendry 	else
54953846Spendry 		printf("portal_inactive(%x)\n", ap->a_vp);
55053846Spendry #endif
55153846Spendry 	/*vgone(ap->a_vp);*/
55253846Spendry 	return (0);
55353846Spendry }
55453846Spendry 
55553846Spendry portal_reclaim (ap)
55653846Spendry 	struct vop_reclaim_args *ap;
55753846Spendry {
55853846Spendry 	struct portalnode *pt = VTOPORTAL(ap->a_vp);
55953846Spendry #ifdef PORTAL_DIAGOISTIC
56053846Spendry 	printf("portal_reclaim(%x)\n", ap->a_vp);
56153846Spendry #endif
56253846Spendry 	if (pt->pt_arg) {
56353846Spendry 		free((caddr_t) pt->pt_arg, M_TEMP);
56453846Spendry 		pt->pt_arg = 0;
56553846Spendry 	}
56653846Spendry 	FREE(pt, M_TEMP);
56753846Spendry 	return (0);
56853846Spendry }
56953846Spendry 
57053846Spendry /*
57153846Spendry  * Print out the contents of a Portal vnode.
57253846Spendry  */
57353846Spendry /* ARGSUSED */
57453846Spendry portal_print (ap)
57553846Spendry 	struct vop_print_args *ap;
57653846Spendry {
57753846Spendry 	printf("tag VT_PORTAL, portal vnode\n");
57853846Spendry }
57953846Spendry 
58053846Spendry /*void*/
58153846Spendry portal_vfree (ap)
58253846Spendry 	struct vop_vfree_args *ap;
58353846Spendry {
58453846Spendry 	return;
58553846Spendry }
58653846Spendry 
58753846Spendry 
58853846Spendry /*
58953846Spendry  * Portal vnode unsupported operation
59053846Spendry  */
59153846Spendry portal_enotsupp()
59253846Spendry {
59353846Spendry 	return (EOPNOTSUPP);
59453846Spendry }
59553846Spendry 
59653846Spendry /*
59753846Spendry  * Portal "should never get here" operation
59853846Spendry  */
59953846Spendry portal_badop()
60053846Spendry {
60153846Spendry 	panic("portal: bad op");
60253846Spendry 	/* NOTREACHED */
60353846Spendry }
60453846Spendry 
60553846Spendry /*
60653846Spendry  * Portal vnode null operation
60753846Spendry  */
60853846Spendry portal_nullop()
60953846Spendry {
61053846Spendry 	return (0);
61153846Spendry }
61253846Spendry 
61353846Spendry #define portal_create ((int (*) __P((struct  vop_create_args *)))portal_enotsupp)
61453846Spendry #define portal_mknod ((int (*) __P((struct  vop_mknod_args *)))portal_enotsupp)
61553846Spendry #define portal_close ((int (*) __P((struct  vop_close_args *)))nullop)
61653846Spendry #define portal_access ((int (*) __P((struct  vop_access_args *)))nullop)
61753846Spendry #define portal_read ((int (*) __P((struct  vop_read_args *)))portal_enotsupp)
61853846Spendry #define portal_write ((int (*) __P((struct  vop_write_args *)))portal_enotsupp)
61953846Spendry #define portal_ioctl ((int (*) __P((struct  vop_ioctl_args *)))portal_enotsupp)
62053846Spendry #define portal_select ((int (*) __P((struct  vop_select_args *)))portal_enotsupp)
62153846Spendry #define portal_mmap ((int (*) __P((struct  vop_mmap_args *)))portal_enotsupp)
62253846Spendry #define portal_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
62353846Spendry #define portal_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
62453846Spendry #define portal_remove ((int (*) __P((struct  vop_remove_args *)))portal_enotsupp)
62553846Spendry #define portal_link ((int (*) __P((struct  vop_link_args *)))portal_enotsupp)
62653846Spendry #define portal_rename ((int (*) __P((struct  vop_rename_args *)))portal_enotsupp)
62753846Spendry #define portal_mkdir ((int (*) __P((struct  vop_mkdir_args *)))portal_enotsupp)
62853846Spendry #define portal_rmdir ((int (*) __P((struct  vop_rmdir_args *)))portal_enotsupp)
62953846Spendry #define portal_symlink ((int (*) __P((struct  vop_symlink_args *)))portal_enotsupp)
63053846Spendry #define portal_readlink ((int (*) __P((struct  vop_readlink_args *)))portal_enotsupp)
63153846Spendry #define portal_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
63253846Spendry #define portal_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
63353846Spendry #define portal_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
63453846Spendry #define portal_bmap ((int (*) __P((struct  vop_bmap_args *)))portal_badop)
63553846Spendry #define portal_strategy ((int (*) __P((struct  vop_strategy_args *)))portal_badop)
63653846Spendry #define portal_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
63753846Spendry #define portal_advlock ((int (*) __P((struct  vop_advlock_args *)))portal_enotsupp)
63853846Spendry #define portal_blkatoff ((int (*) __P((struct  vop_blkatoff_args *)))portal_enotsupp)
63953846Spendry #define portal_valloc ((int(*) __P(( \
64053846Spendry 		struct vnode *pvp, \
64153846Spendry 		int mode, \
64253846Spendry 		struct ucred *cred, \
64353846Spendry 		struct vnode **vpp))) portal_enotsupp)
64453846Spendry #define portal_truncate ((int (*) __P((struct  vop_truncate_args *)))portal_enotsupp)
64553846Spendry #define portal_update ((int (*) __P((struct  vop_update_args *)))portal_enotsupp)
64653846Spendry #define portal_bwrite ((int (*) __P((struct  vop_bwrite_args *)))portal_enotsupp)
64753846Spendry 
64853846Spendry int (**portal_vnodeop_p)();
64953846Spendry struct vnodeopv_entry_desc portal_vnodeop_entries[] = {
65053846Spendry 	{ &vop_default_desc, vn_default_error },
65153846Spendry 	{ &vop_lookup_desc, portal_lookup },		/* lookup */
65253846Spendry 	{ &vop_create_desc, portal_create },		/* create */
65353846Spendry 	{ &vop_mknod_desc, portal_mknod },		/* mknod */
65453846Spendry 	{ &vop_open_desc, portal_open },		/* open */
65553846Spendry 	{ &vop_close_desc, portal_close },		/* close */
65653846Spendry 	{ &vop_access_desc, portal_access },		/* access */
65753846Spendry 	{ &vop_getattr_desc, portal_getattr },		/* getattr */
65853846Spendry 	{ &vop_setattr_desc, portal_setattr },		/* setattr */
65953846Spendry 	{ &vop_read_desc, portal_read },		/* read */
66053846Spendry 	{ &vop_write_desc, portal_write },		/* write */
66153846Spendry 	{ &vop_ioctl_desc, portal_ioctl },		/* ioctl */
66253846Spendry 	{ &vop_select_desc, portal_select },		/* select */
66353846Spendry 	{ &vop_mmap_desc, portal_mmap },		/* mmap */
66453846Spendry 	{ &vop_fsync_desc, portal_fsync },		/* fsync */
66553846Spendry 	{ &vop_seek_desc, portal_seek },		/* seek */
66653846Spendry 	{ &vop_remove_desc, portal_remove },		/* remove */
66753846Spendry 	{ &vop_link_desc, portal_link },		/* link */
66853846Spendry 	{ &vop_rename_desc, portal_rename },		/* rename */
66953846Spendry 	{ &vop_mkdir_desc, portal_mkdir },		/* mkdir */
67053846Spendry 	{ &vop_rmdir_desc, portal_rmdir },		/* rmdir */
67153846Spendry 	{ &vop_symlink_desc, portal_symlink },		/* symlink */
67253846Spendry 	{ &vop_readdir_desc, portal_readdir },		/* readdir */
67353846Spendry 	{ &vop_readlink_desc, portal_readlink },	/* readlink */
67453846Spendry 	{ &vop_abortop_desc, portal_abortop },		/* abortop */
67553846Spendry 	{ &vop_inactive_desc, portal_inactive },	/* inactive */
67653846Spendry 	{ &vop_reclaim_desc, portal_reclaim },		/* reclaim */
67753846Spendry 	{ &vop_lock_desc, portal_lock },		/* lock */
67853846Spendry 	{ &vop_unlock_desc, portal_unlock },		/* unlock */
67953846Spendry 	{ &vop_bmap_desc, portal_bmap },		/* bmap */
68053846Spendry 	{ &vop_strategy_desc, portal_strategy },	/* strategy */
68153846Spendry 	{ &vop_print_desc, portal_print },		/* print */
68253846Spendry 	{ &vop_islocked_desc, portal_islocked },	/* islocked */
68353846Spendry 	{ &vop_advlock_desc, portal_advlock },		/* advlock */
68453846Spendry 	{ &vop_blkatoff_desc, portal_blkatoff },	/* blkatoff */
68553846Spendry 	{ &vop_valloc_desc, portal_valloc },		/* valloc */
68653846Spendry 	{ &vop_vfree_desc, portal_vfree },		/* vfree */
68753846Spendry 	{ &vop_truncate_desc, portal_truncate },	/* truncate */
68853846Spendry 	{ &vop_update_desc, portal_update },		/* update */
68953846Spendry 	{ &vop_bwrite_desc, portal_bwrite },		/* bwrite */
69053846Spendry 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
69153846Spendry };
69253846Spendry struct vnodeopv_desc portal_vnodeop_opv_desc =
69353846Spendry 	{ &portal_vnodeop_p, portal_vnodeop_entries };
694