* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software donated to Berkeley by
* %sccs.include.redist.c%
* @(#)portal_vnops.c 8.5 (Berkeley) %G%
* $Id: portal_vnops.c,v 1.4 1992/05/30 10:05:24 jsp Exp jsp $
#include <sys/filedesc.h>
#include <sys/socketvar.h>
#include <miscfs/portal/portal.h>
static int portal_fileid
= PORTAL_ROOTFILEID
+1;
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.
printf("portal_closefd: error = %d\n", error
);
* vp is the current namei directory
* cnp is the name to locate in that directory...
struct vop_lookup_args
/* {
struct componentname * a_cnp;
char *pname
= ap
->a_cnp
->cn_nameptr
;
printf("portal_lookup(%s)\n", pname
);
if (ap
->a_cnp
->cn_namelen
== 1 && *pname
== '.') {
printf("portal_lookup: allocate new vnode\n");
error
= getnewvnode(VT_PORTAL
, ap
->a_dvp
->v_mount
, portal_vnodeop_p
, &fvp
);
MALLOC(fvp
->v_data
, void *, sizeof(struct portalnode
),
* Save all of the remaining pathname and
* advance the namei next pointer to the end
for (size
= 0, path
= pname
; *path
; path
++)
ap
->a_cnp
->cn_consume
= size
- ap
->a_cnp
->cn_namelen
;
pt
->pt_arg
= malloc(size
+1, M_TEMP
, M_WAITOK
);
bcopy(pname
, pt
->pt_arg
, pt
->pt_size
);
pt
->pt_fileid
= portal_fileid
++;
printf("portal_lookup: newvp = %x\n", fvp
);
printf("portal_lookup: vrele(%x)\n", fvp
);
printf("portal_lookup: error = %d\n", error
);
/* from unp_connect, bypassing the namei stuff... */
printf("portal_connect\n");
if (so
->so_type
!= so2
->so_type
)
if ((so2
->so_options
& SO_ACCEPTCONN
) == 0)
printf("portal_connect: calling sonewconn\n");
if ((so3
= sonewconn(so2
, 0)) == 0)
unp3
->unp_addr
= m_copy(unp2
->unp_addr
, 0, (int)M_COPYALL
);
printf("portal_connect: calling unp_connect2\n");
return (unp_connect2(so
, so2
));
struct vop_open_args
/* {
struct proc
*p
= ap
->a_p
;
struct vnode
*vp
= ap
->a_vp
;
struct portal_cred pcred
;
* Nothing to do when opening the root node.
printf("portal_open(%x)\n", vp
);
* 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.
fmp
= VFSTOPORTAL(vp
->v_mount
);
error
= socreate(AF_UNIX
, &so
, SOCK_STREAM
, 0);
* Reserve some buffer space
printf("portal_open: calling soreserve\n");
res
= pt
->pt_size
+ sizeof(pcred
) + 512; /* XXX */
error
= soreserve(so
, res
, res
);
printf("portal_open: calling portal_connect\n");
error
= portal_connect(so
, (struct socket
*)fmp
->pm_server
->f_data
);
* Wait for connection to complete
printf("portal_open: waiting for connect\n");
* 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.
while ((so
->so_state
& SS_ISCONNECTING
) && so
->so_error
== 0) {
if (fmp
->pm_server
->f_count
== 1) {
printf("portal_open: server process has gone away\n");
(void) tsleep((caddr_t
) &so
->so_timeo
, PSOCK
, "portalcon", 5 * hz
);
* Set miscellaneous flags
so
->so_rcv
.sb_flags
|= SB_NOINTR
;
so
->so_snd
.sb_flags
|= SB_NOINTR
;
printf("portal_open: constructing data uio\n");
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_segflg
= UIO_SYSSPACE
;
auio
.uio_resid
= aiov
[0].iov_len
+ aiov
[1].iov_len
;
printf("portal_open: sending data to server\n");
error
= sosend(so
, (struct mbuf
*) 0, &auio
,
(struct mbuf
*) 0, (struct mbuf
*) 0, 0);
len
= auio
.uio_resid
= sizeof(int);
printf("portal_open: receiving data from server\n");
printf("portal_open: so = %x, cm = %x, resid = %d\n",
printf("portal_open, uio=%x, mp0=%x, controlp=%x\n", &auio
, &cm
);
error
= soreceive(so
, (struct mbuf
**) 0, &auio
,
printf("portal_open: after receiving data\n");
printf("portal_open: so = %x, cm = %x, resid = %d\n",
* Grab an error code from the mbuf.
m
= m_pullup(m
, sizeof(int)); /* Needed? */
error
= *(mtod(m
, int *));
printf("portal_open: error returned is %d\n", error
);
printf("portal_open: no rights received\n");
error
= ECONNRESET
; /* XXX */
} while (cm
== 0 && auio
.uio_resid
== len
&& !error
);
printf("portal_open: still need another %d bytes\n", auio
.uio_resid
);
* 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?
printf("portal_open: about to break apart control message\n");
cmsg
= mtod(cm
, struct cmsghdr
*);
newfds
= (cmsg
->cmsg_len
- sizeof(*cmsg
)) / sizeof (int);
printf("portal_open: received no fds\n");
* 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.
printf("portal_open: %d extra fds\n", newfds
- 1);
for (i
= 1; i
< newfds
; i
++) {
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
printf("portal_open: checking file flags, fd = %d\n", fd
);
fp
= p
->p_fd
->fd_ofiles
[fd
];
if (((ap
->a_mode
& (FREAD
|FWRITE
)) | fp
->f_flag
) != fp
->f_flag
) {
printf("portal_open: got fd = %d\n", fd
);
* 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.
* And discard the control message.
printf("portal_open: free'ing control message\n");
printf("portal_open: calling soshutdown\n");
printf("portal_open: calling soclose\n");
printf("portal_open: error = %d\n", error
);
struct vop_getattr_args
/* {
struct vnode
*vp
= ap
->a_vp
;
struct vattr
*vap
= ap
->a_vap
;
bzero(vap
, sizeof(*vap
));
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_qbytes = 0; */
if (vp
->v_flag
& VROOT
) {
printf("portal_getattr: stat rootdir\n");
vap
->va_mode
= S_IRUSR
|S_IWUSR
|S_IXUSR
|
printf("portal_getattr: stat portal\n");
vap
->va_mode
= S_IRUSR
|S_IWUSR
|
vap
->va_fileid
= VTOPORTAL(vp
)->pt_fileid
;
struct vop_setattr_args
/* {
* Can't mess with the root vnode
if (ap
->a_vp
->v_flag
& VROOT
)
* Fake readdir, just return empty directory.
* It is hard to deal with '.' and '..' so don't bother.
struct vop_readdir_args
/* {
/* *ap->a_eofflagp = 1; */
struct vop_inactive_args
/* {
if (VTOPORTAL(ap
->a_vp
)->pt_arg
)
printf("portal_inactive(%x, %s)\n", ap
->a_vp
, VTOPORTAL(ap
->a_vp
)->pt_arg
);
printf("portal_inactive(%x)\n", ap
->a_vp
);
struct vop_reclaim_args
/* {
struct portalnode
*pt
= VTOPORTAL(ap
->a_vp
);
printf("portal_reclaim(%x)\n", ap
->a_vp
);
free((caddr_t
) pt
->pt_arg
, M_TEMP
);
FREE(ap
->a_vp
->v_data
, M_TEMP
);
* Print out the contents of a Portal vnode.
struct vop_print_args
/* {
printf("tag VT_PORTAL, portal vnode\n");
struct vop_vfree_args
/* {
* Portal vnode unsupported operation
* Portal "should never get here" operation
* Portal vnode null operation
#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)
((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)
((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 **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_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
};