Home | History | Annotate | Line # | Download | only in fdesc
fdesc_vnops.c revision 1.114.12.1
      1  1.114.12.1       tls /*	$NetBSD: fdesc_vnops.c,v 1.114.12.1 2014/08/20 00:04:30 tls Exp $	*/
      2        1.15       cgd 
      3         1.1       cgd /*
      4        1.14   mycroft  * Copyright (c) 1992, 1993
      5        1.14   mycroft  *	The Regents of the University of California.  All rights reserved.
      6         1.1       cgd  *
      7         1.8       cgd  * This code is derived from software donated to Berkeley by
      8         1.1       cgd  * Jan-Simon Pendry.
      9         1.1       cgd  *
     10         1.2       cgd  * Redistribution and use in source and binary forms, with or without
     11         1.2       cgd  * modification, are permitted provided that the following conditions
     12         1.2       cgd  * are met:
     13         1.2       cgd  * 1. Redistributions of source code must retain the above copyright
     14         1.2       cgd  *    notice, this list of conditions and the following disclaimer.
     15         1.2       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16         1.2       cgd  *    notice, this list of conditions and the following disclaimer in the
     17         1.2       cgd  *    documentation and/or other materials provided with the distribution.
     18        1.78       agc  * 3. Neither the name of the University nor the names of its contributors
     19         1.2       cgd  *    may be used to endorse or promote products derived from this software
     20         1.2       cgd  *    without specific prior written permission.
     21         1.1       cgd  *
     22         1.2       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23         1.2       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24         1.2       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25         1.2       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26         1.2       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27         1.2       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28         1.2       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29         1.2       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30         1.2       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31         1.2       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32         1.2       cgd  * SUCH DAMAGE.
     33         1.1       cgd  *
     34        1.44      fvdl  *	@(#)fdesc_vnops.c	8.17 (Berkeley) 5/22/95
     35        1.22   mycroft  *
     36        1.22   mycroft  * #Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp #
     37         1.1       cgd  */
     38         1.1       cgd 
     39         1.1       cgd /*
     40         1.1       cgd  * /dev/fd Filesystem
     41         1.1       cgd  */
     42        1.65     lukem 
     43        1.65     lukem #include <sys/cdefs.h>
     44  1.114.12.1       tls __KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.114.12.1 2014/08/20 00:04:30 tls Exp $");
     45         1.1       cgd 
     46         1.8       cgd #include <sys/param.h>
     47         1.8       cgd #include <sys/systm.h>
     48         1.8       cgd #include <sys/time.h>
     49         1.8       cgd #include <sys/proc.h>
     50         1.8       cgd #include <sys/kernel.h>	/* boottime */
     51         1.8       cgd #include <sys/resourcevar.h>
     52        1.30  christos #include <sys/socketvar.h>
     53         1.8       cgd #include <sys/filedesc.h>
     54         1.8       cgd #include <sys/vnode.h>
     55        1.14   mycroft #include <sys/malloc.h>
     56        1.32       mrg #include <sys/conf.h>
     57         1.8       cgd #include <sys/file.h>
     58         1.8       cgd #include <sys/stat.h>
     59         1.8       cgd #include <sys/mount.h>
     60         1.8       cgd #include <sys/namei.h>
     61         1.8       cgd #include <sys/buf.h>
     62        1.14   mycroft #include <sys/dirent.h>
     63        1.30  christos #include <sys/tty.h>
     64        1.92      elad #include <sys/kauth.h>
     65       1.102        ad #include <sys/atomic.h>
     66        1.34   mycroft 
     67         1.8       cgd #include <miscfs/fdesc/fdesc.h>
     68        1.34   mycroft #include <miscfs/genfs/genfs.h>
     69         1.8       cgd 
     70        1.96        ad #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
     71         1.8       cgd 
     72        1.14   mycroft dev_t devctty;
     73         1.8       cgd 
     74         1.8       cgd #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
     75         1.8       cgd FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
     76         1.8       cgd #endif
     77         1.8       cgd 
     78        1.86   xtraeme int	fdesc_lookup(void *);
     79        1.74  jdolecek #define	fdesc_create	genfs_eopnotsupp
     80        1.74  jdolecek #define	fdesc_mknod	genfs_eopnotsupp
     81        1.86   xtraeme int	fdesc_open(void *);
     82        1.34   mycroft #define	fdesc_close	genfs_nullop
     83        1.34   mycroft #define	fdesc_access	genfs_nullop
     84        1.86   xtraeme int	fdesc_getattr(void *);
     85        1.86   xtraeme int	fdesc_setattr(void *);
     86        1.86   xtraeme int	fdesc_read(void *);
     87        1.86   xtraeme int	fdesc_write(void *);
     88        1.86   xtraeme int	fdesc_ioctl(void *);
     89        1.86   xtraeme int	fdesc_poll(void *);
     90        1.86   xtraeme int	fdesc_kqfilter(void *);
     91        1.34   mycroft #define	fdesc_mmap	genfs_eopnotsupp
     92        1.50  wrstuden #define	fdesc_fcntl	genfs_fcntl
     93        1.34   mycroft #define	fdesc_fsync	genfs_nullop
     94        1.40      fvdl #define	fdesc_seek	genfs_seek
     95        1.74  jdolecek #define	fdesc_remove	genfs_eopnotsupp
     96        1.86   xtraeme int	fdesc_link(void *);
     97        1.74  jdolecek #define	fdesc_rename	genfs_eopnotsupp
     98        1.74  jdolecek #define	fdesc_mkdir	genfs_eopnotsupp
     99        1.74  jdolecek #define	fdesc_rmdir	genfs_eopnotsupp
    100        1.86   xtraeme int	fdesc_symlink(void *);
    101        1.86   xtraeme int	fdesc_readdir(void *);
    102        1.86   xtraeme int	fdesc_readlink(void *);
    103        1.34   mycroft #define	fdesc_abortop	genfs_abortop
    104        1.86   xtraeme int	fdesc_inactive(void *);
    105        1.86   xtraeme int	fdesc_reclaim(void *);
    106        1.48  wrstuden #define	fdesc_lock	genfs_lock
    107        1.48  wrstuden #define	fdesc_unlock	genfs_unlock
    108        1.34   mycroft #define	fdesc_bmap	genfs_badop
    109        1.34   mycroft #define	fdesc_strategy	genfs_badop
    110        1.86   xtraeme int	fdesc_print(void *);
    111        1.86   xtraeme int	fdesc_pathconf(void *);
    112        1.48  wrstuden #define	fdesc_islocked	genfs_islocked
    113        1.47    kleink #define	fdesc_advlock	genfs_einval
    114        1.34   mycroft #define	fdesc_bwrite	genfs_eopnotsupp
    115        1.44      fvdl #define fdesc_revoke	genfs_revoke
    116        1.67       chs #define fdesc_putpages	genfs_null_putpages
    117        1.30  christos 
    118       1.102        ad static int fdesc_attr(int, struct vattr *, kauth_cred_t);
    119        1.30  christos 
    120        1.86   xtraeme int (**fdesc_vnodeop_p)(void *);
    121        1.58  jdolecek const struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
    122        1.30  christos 	{ &vop_default_desc, vn_default_error },
    123        1.34   mycroft 	{ &vop_lookup_desc, fdesc_lookup },		/* lookup */
    124        1.34   mycroft 	{ &vop_create_desc, fdesc_create },		/* create */
    125        1.34   mycroft 	{ &vop_mknod_desc, fdesc_mknod },		/* mknod */
    126        1.34   mycroft 	{ &vop_open_desc, fdesc_open },			/* open */
    127        1.34   mycroft 	{ &vop_close_desc, fdesc_close },		/* close */
    128        1.34   mycroft 	{ &vop_access_desc, fdesc_access },		/* access */
    129        1.34   mycroft 	{ &vop_getattr_desc, fdesc_getattr },		/* getattr */
    130        1.34   mycroft 	{ &vop_setattr_desc, fdesc_setattr },		/* setattr */
    131        1.34   mycroft 	{ &vop_read_desc, fdesc_read },			/* read */
    132        1.34   mycroft 	{ &vop_write_desc, fdesc_write },		/* write */
    133  1.114.12.1       tls 	{ &vop_fallocate_desc, genfs_eopnotsupp },	/* fallocate */
    134  1.114.12.1       tls 	{ &vop_fdiscard_desc, genfs_eopnotsupp },	/* fdiscard */
    135        1.34   mycroft 	{ &vop_ioctl_desc, fdesc_ioctl },		/* ioctl */
    136        1.50  wrstuden 	{ &vop_fcntl_desc, fdesc_fcntl },		/* fcntl */
    137        1.35   mycroft 	{ &vop_poll_desc, fdesc_poll },			/* poll */
    138        1.71  jdolecek 	{ &vop_kqfilter_desc, fdesc_kqfilter },		/* kqfilter */
    139        1.44      fvdl 	{ &vop_revoke_desc, fdesc_revoke },		/* revoke */
    140        1.34   mycroft 	{ &vop_mmap_desc, fdesc_mmap },			/* mmap */
    141        1.34   mycroft 	{ &vop_fsync_desc, fdesc_fsync },		/* fsync */
    142        1.34   mycroft 	{ &vop_seek_desc, fdesc_seek },			/* seek */
    143        1.34   mycroft 	{ &vop_remove_desc, fdesc_remove },		/* remove */
    144        1.34   mycroft 	{ &vop_link_desc, fdesc_link },			/* link */
    145        1.34   mycroft 	{ &vop_rename_desc, fdesc_rename },		/* rename */
    146        1.34   mycroft 	{ &vop_mkdir_desc, fdesc_mkdir },		/* mkdir */
    147        1.34   mycroft 	{ &vop_rmdir_desc, fdesc_rmdir },		/* rmdir */
    148        1.34   mycroft 	{ &vop_symlink_desc, fdesc_symlink },		/* symlink */
    149        1.34   mycroft 	{ &vop_readdir_desc, fdesc_readdir },		/* readdir */
    150        1.34   mycroft 	{ &vop_readlink_desc, fdesc_readlink },		/* readlink */
    151        1.34   mycroft 	{ &vop_abortop_desc, fdesc_abortop },		/* abortop */
    152        1.34   mycroft 	{ &vop_inactive_desc, fdesc_inactive },		/* inactive */
    153        1.34   mycroft 	{ &vop_reclaim_desc, fdesc_reclaim },		/* reclaim */
    154        1.34   mycroft 	{ &vop_lock_desc, fdesc_lock },			/* lock */
    155        1.34   mycroft 	{ &vop_unlock_desc, fdesc_unlock },		/* unlock */
    156        1.34   mycroft 	{ &vop_bmap_desc, fdesc_bmap },			/* bmap */
    157        1.34   mycroft 	{ &vop_strategy_desc, fdesc_strategy },		/* strategy */
    158        1.34   mycroft 	{ &vop_print_desc, fdesc_print },		/* print */
    159        1.34   mycroft 	{ &vop_islocked_desc, fdesc_islocked },		/* islocked */
    160        1.34   mycroft 	{ &vop_pathconf_desc, fdesc_pathconf },		/* pathconf */
    161        1.34   mycroft 	{ &vop_advlock_desc, fdesc_advlock },		/* advlock */
    162        1.34   mycroft 	{ &vop_bwrite_desc, fdesc_bwrite },		/* bwrite */
    163        1.67       chs 	{ &vop_putpages_desc, fdesc_putpages },		/* putpages */
    164        1.67       chs 	{ NULL, NULL }
    165        1.30  christos };
    166        1.30  christos 
    167        1.58  jdolecek const struct vnodeopv_desc fdesc_vnodeop_opv_desc =
    168        1.30  christos 	{ &fdesc_vnodeop_p, fdesc_vnodeop_entries };
    169        1.30  christos 
    170        1.14   mycroft /*
    171        1.14   mycroft  * Initialise cache headers
    172        1.14   mycroft  */
    173        1.30  christos void
    174       1.106    cegger fdesc_init(void)
    175        1.14   mycroft {
    176        1.32       mrg 	int cttymajor;
    177        1.14   mycroft 
    178        1.32       mrg 	/* locate the major number */
    179       1.108     pooka 	cttymajor = devsw_name2chr("ctty", NULL, 0);
    180        1.32       mrg 	devctty = makedev(cttymajor, 0);
    181        1.54  jdolecek }
    182        1.54  jdolecek 
    183        1.54  jdolecek void
    184       1.106    cegger fdesc_done(void)
    185        1.54  jdolecek {
    186         1.8       cgd }
    187         1.1       cgd 
    188         1.1       cgd /*
    189         1.1       cgd  * vp is the current namei directory
    190         1.1       cgd  * ndp is the name to locate in that directory...
    191         1.1       cgd  */
    192        1.14   mycroft int
    193       1.105       dsl fdesc_lookup(void *v)
    194        1.30  christos {
    195  1.114.12.1       tls 	struct vop_lookup_v2_args /* {
    196        1.14   mycroft 		struct vnode * a_dvp;
    197        1.14   mycroft 		struct vnode ** a_vpp;
    198        1.14   mycroft 		struct componentname * a_cnp;
    199        1.30  christos 	} */ *ap = v;
    200        1.14   mycroft 	struct vnode **vpp = ap->a_vpp;
    201        1.14   mycroft 	struct vnode *dvp = ap->a_dvp;
    202        1.44      fvdl 	struct componentname *cnp = ap->a_cnp;
    203       1.101     pooka 	struct lwp *l = curlwp;
    204        1.44      fvdl 	const char *pname = cnp->cn_nameptr;
    205        1.89  christos 	struct proc *p = l->l_proc;
    206        1.30  christos 	unsigned fd = 0;
    207  1.114.12.1       tls 	int error, ix = -1;
    208       1.107        ad 	fdtab_t *dt;
    209       1.107        ad 
    210       1.107        ad 	dt = curlwp->l_fd->fd_dt;
    211         1.1       cgd 
    212        1.44      fvdl 	if (cnp->cn_namelen == 1 && *pname == '.') {
    213        1.14   mycroft 		*vpp = dvp;
    214       1.109     pooka 		vref(dvp);
    215         1.1       cgd 		return (0);
    216         1.1       cgd 	}
    217         1.1       cgd 
    218         1.8       cgd 	switch (VTOFDESC(dvp)->fd_type) {
    219         1.8       cgd 	default:
    220         1.8       cgd 	case Flink:
    221         1.8       cgd 	case Fdesc:
    222         1.8       cgd 	case Fctty:
    223         1.8       cgd 		error = ENOTDIR;
    224         1.8       cgd 		goto bad;
    225         1.8       cgd 
    226         1.8       cgd 	case Froot:
    227        1.46     perry 		if (cnp->cn_namelen == 2 && memcmp(pname, "fd", 2) == 0) {
    228  1.114.12.1       tls 			ix = FD_DEVFD;
    229        1.48  wrstuden 			goto good;
    230         1.8       cgd 		}
    231         1.8       cgd 
    232        1.46     perry 		if (cnp->cn_namelen == 3 && memcmp(pname, "tty", 3) == 0) {
    233         1.8       cgd 			struct vnode *ttyvp = cttyvp(p);
    234         1.8       cgd 			if (ttyvp == NULL) {
    235         1.8       cgd 				error = ENXIO;
    236         1.8       cgd 				goto bad;
    237         1.8       cgd 			}
    238  1.114.12.1       tls 			ix = FD_CTTY;
    239        1.48  wrstuden 			goto good;
    240         1.8       cgd 		}
    241         1.8       cgd 
    242        1.44      fvdl 		switch (cnp->cn_namelen) {
    243         1.8       cgd 		case 5:
    244        1.46     perry 			if (memcmp(pname, "stdin", 5) == 0) {
    245  1.114.12.1       tls 				ix = FD_STDIN;
    246  1.114.12.1       tls 				goto good;
    247         1.8       cgd 			}
    248         1.1       cgd 			break;
    249         1.8       cgd 		case 6:
    250        1.46     perry 			if (memcmp(pname, "stdout", 6) == 0) {
    251  1.114.12.1       tls 				ix = FD_STDOUT;
    252  1.114.12.1       tls 				goto good;
    253  1.114.12.1       tls 			} else if (memcmp(pname, "stderr", 6) == 0) {
    254  1.114.12.1       tls 				ix = FD_STDERR;
    255  1.114.12.1       tls 				goto good;
    256         1.8       cgd 			}
    257         1.8       cgd 			break;
    258         1.8       cgd 		}
    259         1.8       cgd 
    260  1.114.12.1       tls 		error = ENOENT;
    261  1.114.12.1       tls 		goto bad;
    262         1.8       cgd 
    263         1.8       cgd 	case Fdevfd:
    264        1.46     perry 		if (cnp->cn_namelen == 2 && memcmp(pname, "..", 2) == 0) {
    265  1.114.12.1       tls 			ix = FD_ROOT;
    266  1.114.12.1       tls 			goto good;
    267         1.8       cgd 		}
    268         1.8       cgd 
    269         1.8       cgd 		fd = 0;
    270         1.8       cgd 		while (*pname >= '0' && *pname <= '9') {
    271         1.8       cgd 			fd = 10 * fd + *pname++ - '0';
    272       1.107        ad 			if (fd >= dt->dt_nfiles)
    273         1.8       cgd 				break;
    274         1.8       cgd 		}
    275         1.1       cgd 
    276         1.8       cgd 		if (*pname != '\0') {
    277         1.8       cgd 			error = ENOENT;
    278         1.8       cgd 			goto bad;
    279         1.8       cgd 		}
    280         1.1       cgd 
    281       1.107        ad 		if (fd >= dt->dt_nfiles || dt->dt_ff[fd] == NULL ||
    282       1.107        ad 		    dt->dt_ff[fd]->ff_file == NULL) {
    283         1.8       cgd 			error = EBADF;
    284         1.8       cgd 			goto bad;
    285         1.8       cgd 		}
    286         1.1       cgd 
    287  1.114.12.1       tls 		ix = FD_DESC + fd;
    288        1.48  wrstuden 		goto good;
    289         1.8       cgd 	}
    290         1.1       cgd 
    291        1.95       chs bad:
    292        1.14   mycroft 	*vpp = NULL;
    293  1.114.12.1       tls 	return error;
    294        1.48  wrstuden 
    295        1.95       chs good:
    296  1.114.12.1       tls 	KASSERT(ix != -1);
    297  1.114.12.1       tls 	error = vcache_get(dvp->v_mount, &ix, sizeof(ix), vpp);
    298  1.114.12.1       tls 	return error;
    299         1.1       cgd }
    300         1.1       cgd 
    301        1.14   mycroft int
    302       1.105       dsl fdesc_open(void *v)
    303        1.30  christos {
    304        1.14   mycroft 	struct vop_open_args /* {
    305        1.14   mycroft 		struct vnode *a_vp;
    306        1.14   mycroft 		int  a_mode;
    307        1.92      elad 		kauth_cred_t a_cred;
    308        1.30  christos 	} */ *ap = v;
    309        1.14   mycroft 	struct vnode *vp = ap->a_vp;
    310         1.8       cgd 
    311         1.8       cgd 	switch (VTOFDESC(vp)->fd_type) {
    312         1.8       cgd 	case Fdesc:
    313        1.23   mycroft 		/*
    314        1.79  jdolecek 		 * XXX Kludge: set dupfd to contain the value of the
    315        1.83     perry 		 * the file descriptor being sought for duplication. The error
    316        1.23   mycroft 		 * return ensures that the vnode for this device will be
    317        1.23   mycroft 		 * released by vn_open. Open will detect this special error and
    318        1.23   mycroft 		 * take the actions in dupfdopen.  Other callers of vn_open or
    319        1.23   mycroft 		 * VOP_OPEN will simply report the error.
    320        1.23   mycroft 		 */
    321        1.79  jdolecek 		curlwp->l_dupfd = VTOFDESC(vp)->fd_fd;	/* XXX */
    322        1.82  christos 		return EDUPFD;
    323         1.1       cgd 
    324         1.8       cgd 	case Fctty:
    325       1.100     pooka 		return cdev_open(devctty, ap->a_mode, 0, curlwp);
    326        1.30  christos 	case Froot:
    327        1.30  christos 	case Fdevfd:
    328        1.30  christos 	case Flink:
    329        1.30  christos 		break;
    330         1.8       cgd 	}
    331         1.1       cgd 
    332        1.21   mycroft 	return (0);
    333         1.1       cgd }
    334         1.1       cgd 
    335         1.1       cgd static int
    336       1.105       dsl fdesc_attr(int fd, struct vattr *vap, kauth_cred_t cred)
    337         1.1       cgd {
    338       1.102        ad 	file_t *fp;
    339         1.8       cgd 	struct stat stb;
    340         1.1       cgd 	int error;
    341         1.1       cgd 
    342       1.102        ad 	if ((fp = fd_getfile(fd)) == NULL)
    343         1.1       cgd 		return (EBADF);
    344         1.1       cgd 
    345         1.1       cgd 	switch (fp->f_type) {
    346         1.1       cgd 	case DTYPE_VNODE:
    347       1.114   hannken 		vn_lock((struct vnode *) fp->f_data, LK_SHARED | LK_RETRY);
    348       1.100     pooka 		error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred);
    349       1.114   hannken 		VOP_UNLOCK((struct vnode *) fp->f_data);
    350         1.8       cgd 		if (error == 0 && vap->va_type == VDIR) {
    351         1.8       cgd 			/*
    352        1.22   mycroft 			 * directories can cause loops in the namespace,
    353        1.22   mycroft 			 * so turn off the 'x' bits to avoid trouble.
    354         1.8       cgd 			 */
    355        1.41   mycroft 			vap->va_mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
    356         1.8       cgd 		}
    357         1.1       cgd 		break;
    358         1.1       cgd 
    359        1.69  jdolecek 	default:
    360        1.69  jdolecek 		memset(&stb, 0, sizeof(stb));
    361       1.102        ad 		error = (*fp->f_ops->fo_stat)(fp, &stb);
    362        1.69  jdolecek 		if (error)
    363        1.69  jdolecek 			break;
    364        1.69  jdolecek 
    365        1.69  jdolecek 		vattr_null(vap);
    366        1.69  jdolecek 		switch(fp->f_type) {
    367        1.69  jdolecek 		case DTYPE_SOCKET:
    368        1.69  jdolecek 			vap->va_type = VSOCK;
    369        1.69  jdolecek 			break;
    370        1.69  jdolecek 		case DTYPE_PIPE:
    371        1.69  jdolecek 			vap->va_type = VFIFO;
    372        1.69  jdolecek 			break;
    373        1.69  jdolecek 		default:
    374        1.69  jdolecek 			/* use VNON perhaps? */
    375        1.69  jdolecek 			vap->va_type = VBAD;
    376        1.69  jdolecek 			break;
    377         1.8       cgd 		}
    378        1.69  jdolecek 		vap->va_mode = stb.st_mode;
    379        1.69  jdolecek 		vap->va_nlink = stb.st_nlink;
    380        1.69  jdolecek 		vap->va_uid = stb.st_uid;
    381        1.69  jdolecek 		vap->va_gid = stb.st_gid;
    382        1.69  jdolecek 		vap->va_fsid = stb.st_dev;
    383        1.69  jdolecek 		vap->va_fileid = stb.st_ino;
    384        1.69  jdolecek 		vap->va_size = stb.st_size;
    385        1.69  jdolecek 		vap->va_blocksize = stb.st_blksize;
    386        1.69  jdolecek 		vap->va_atime = stb.st_atimespec;
    387        1.69  jdolecek 		vap->va_mtime = stb.st_mtimespec;
    388        1.69  jdolecek 		vap->va_ctime = stb.st_ctimespec;
    389        1.69  jdolecek 		vap->va_gen = stb.st_gen;
    390        1.69  jdolecek 		vap->va_flags = stb.st_flags;
    391        1.69  jdolecek 		vap->va_rdev = stb.st_rdev;
    392        1.69  jdolecek 		vap->va_bytes = stb.st_blocks * stb.st_blksize;
    393         1.1       cgd 		break;
    394         1.1       cgd 	}
    395         1.1       cgd 
    396       1.102        ad 	fd_putfile(fd);
    397         1.1       cgd 	return (error);
    398         1.1       cgd }
    399         1.1       cgd 
    400        1.14   mycroft int
    401       1.105       dsl fdesc_getattr(void *v)
    402        1.30  christos {
    403        1.14   mycroft 	struct vop_getattr_args /* {
    404        1.14   mycroft 		struct vnode *a_vp;
    405        1.14   mycroft 		struct vattr *a_vap;
    406        1.92      elad 		kauth_cred_t a_cred;
    407        1.89  christos 		struct lwp *a_l;
    408        1.30  christos 	} */ *ap = v;
    409        1.14   mycroft 	struct vnode *vp = ap->a_vp;
    410        1.14   mycroft 	struct vattr *vap = ap->a_vap;
    411         1.1       cgd 	unsigned fd;
    412         1.8       cgd 	int error = 0;
    413         1.1       cgd 
    414         1.8       cgd 	switch (VTOFDESC(vp)->fd_type) {
    415         1.8       cgd 	case Froot:
    416         1.8       cgd 	case Fdevfd:
    417         1.8       cgd 	case Flink:
    418         1.8       cgd 	case Fctty:
    419       1.109     pooka 		vattr_null(vap);
    420         1.8       cgd 		vap->va_fileid = VTOFDESC(vp)->fd_ix;
    421         1.8       cgd 
    422        1.30  christos #define R_ALL (S_IRUSR|S_IRGRP|S_IROTH)
    423        1.30  christos #define W_ALL (S_IWUSR|S_IWGRP|S_IWOTH)
    424        1.30  christos #define X_ALL (S_IXUSR|S_IXGRP|S_IXOTH)
    425        1.30  christos 
    426         1.8       cgd 		switch (VTOFDESC(vp)->fd_type) {
    427         1.8       cgd 		case Flink:
    428        1.30  christos 			vap->va_mode = R_ALL|X_ALL;
    429         1.8       cgd 			vap->va_type = VLNK;
    430        1.32       mrg 			vap->va_rdev = 0;
    431         1.8       cgd 			vap->va_nlink = 1;
    432         1.8       cgd 			vap->va_size = strlen(VTOFDESC(vp)->fd_link);
    433         1.8       cgd 			break;
    434         1.8       cgd 
    435         1.8       cgd 		case Fctty:
    436        1.30  christos 			vap->va_mode = R_ALL|W_ALL;
    437        1.32       mrg 			vap->va_type = VCHR;
    438        1.32       mrg 			vap->va_rdev = devctty;
    439         1.8       cgd 			vap->va_nlink = 1;
    440         1.8       cgd 			vap->va_size = 0;
    441         1.8       cgd 			break;
    442         1.8       cgd 
    443         1.8       cgd 		default:
    444        1.30  christos 			vap->va_mode = R_ALL|X_ALL;
    445         1.8       cgd 			vap->va_type = VDIR;
    446        1.32       mrg 			vap->va_rdev = 0;
    447         1.8       cgd 			vap->va_nlink = 2;
    448         1.8       cgd 			vap->va_size = DEV_BSIZE;
    449         1.8       cgd 			break;
    450         1.8       cgd 		}
    451         1.1       cgd 		vap->va_uid = 0;
    452         1.1       cgd 		vap->va_gid = 0;
    453        1.80  christos 		vap->va_fsid = vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
    454         1.1       cgd 		vap->va_blocksize = DEV_BSIZE;
    455        1.28       jtc 		vap->va_atime.tv_sec = boottime.tv_sec;
    456        1.28       jtc 		vap->va_atime.tv_nsec = 0;
    457         1.1       cgd 		vap->va_mtime = vap->va_atime;
    458        1.14   mycroft 		vap->va_ctime = vap->va_mtime;
    459         1.1       cgd 		vap->va_gen = 0;
    460         1.1       cgd 		vap->va_flags = 0;
    461         1.1       cgd 		vap->va_bytes = 0;
    462         1.8       cgd 		break;
    463         1.8       cgd 
    464         1.8       cgd 	case Fdesc:
    465         1.8       cgd 		fd = VTOFDESC(vp)->fd_fd;
    466       1.102        ad 		error = fdesc_attr(fd, vap, ap->a_cred);
    467         1.8       cgd 		break;
    468         1.8       cgd 
    469         1.8       cgd 	default:
    470         1.8       cgd 		panic("fdesc_getattr");
    471        1.83     perry 		break;
    472         1.1       cgd 	}
    473         1.1       cgd 
    474         1.1       cgd 	if (error == 0)
    475         1.1       cgd 		vp->v_type = vap->va_type;
    476         1.8       cgd 
    477         1.1       cgd 	return (error);
    478         1.1       cgd }
    479         1.1       cgd 
    480        1.14   mycroft int
    481       1.105       dsl fdesc_setattr(void *v)
    482        1.30  christos {
    483        1.14   mycroft 	struct vop_setattr_args /* {
    484        1.14   mycroft 		struct vnode *a_vp;
    485        1.14   mycroft 		struct vattr *a_vap;
    486        1.92      elad 		kauth_cred_t a_cred;
    487        1.30  christos 	} */ *ap = v;
    488       1.102        ad 	file_t *fp;
    489         1.1       cgd 	unsigned fd;
    490         1.1       cgd 
    491         1.1       cgd 	/*
    492         1.1       cgd 	 * Can't mess with the root vnode
    493         1.1       cgd 	 */
    494        1.14   mycroft 	switch (VTOFDESC(ap->a_vp)->fd_type) {
    495         1.8       cgd 	case Fdesc:
    496         1.8       cgd 		break;
    497         1.8       cgd 
    498         1.8       cgd 	case Fctty:
    499         1.8       cgd 		return (0);
    500         1.8       cgd 
    501         1.8       cgd 	default:
    502         1.1       cgd 		return (EACCES);
    503         1.8       cgd 	}
    504         1.1       cgd 
    505        1.14   mycroft 	fd = VTOFDESC(ap->a_vp)->fd_fd;
    506       1.102        ad 	if ((fp = fd_getfile(fd)) == NULL)
    507         1.1       cgd 		return (EBADF);
    508         1.1       cgd 
    509         1.1       cgd 	/*
    510        1.68       jmc 	 * XXX: Can't reasonably set the attr's on any types currently.
    511        1.68       jmc 	 *      On vnode's this will cause truncation and socket/pipes make
    512        1.68       jmc 	 *      no sense.
    513         1.1       cgd 	 */
    514       1.102        ad 	fd_putfile(fd);
    515        1.69  jdolecek 	return (0);
    516         1.1       cgd }
    517         1.1       cgd 
    518         1.8       cgd 
    519        1.25   mycroft struct fdesc_target {
    520        1.25   mycroft 	ino_t ft_fileno;
    521        1.25   mycroft 	u_char ft_type;
    522        1.25   mycroft 	u_char ft_namlen;
    523        1.84  christos 	const char *ft_name;
    524        1.25   mycroft } fdesc_targets[] = {
    525        1.25   mycroft #define N(s) sizeof(s)-1, s
    526        1.25   mycroft 	{ FD_DEVFD,  DT_DIR,     N("fd")     },
    527        1.27   mycroft 	{ FD_STDIN,  DT_LNK,     N("stdin")  },
    528        1.27   mycroft 	{ FD_STDOUT, DT_LNK,     N("stdout") },
    529        1.27   mycroft 	{ FD_STDERR, DT_LNK,     N("stderr") },
    530        1.25   mycroft 	{ FD_CTTY,   DT_UNKNOWN, N("tty")    },
    531        1.25   mycroft #undef N
    532        1.85  christos #define UIO_MX _DIRENT_RECLEN((struct dirent *)NULL, sizeof("stderr") - 1)
    533         1.8       cgd };
    534        1.25   mycroft static int nfdesc_targets = sizeof(fdesc_targets) / sizeof(fdesc_targets[0]);
    535         1.8       cgd 
    536        1.14   mycroft int
    537       1.105       dsl fdesc_readdir(void *v)
    538        1.30  christos {
    539        1.14   mycroft 	struct vop_readdir_args /* {
    540        1.14   mycroft 		struct vnode *a_vp;
    541        1.14   mycroft 		struct uio *a_uio;
    542        1.92      elad 		kauth_cred_t a_cred;
    543        1.22   mycroft 		int *a_eofflag;
    544        1.44      fvdl 		off_t **a_cookies;
    545        1.44      fvdl 		int *a_ncookies;
    546        1.30  christos 	} */ *ap = v;
    547        1.14   mycroft 	struct uio *uio = ap->a_uio;
    548        1.25   mycroft 	struct dirent d;
    549        1.53  sommerfe 	off_t i;
    550        1.87  christos 	int j;
    551         1.1       cgd 	int error;
    552        1.44      fvdl 	off_t *cookies = NULL;
    553        1.87  christos 	int ncookies;
    554       1.107        ad 	fdtab_t *dt;
    555        1.11        ws 
    556        1.14   mycroft 	switch (VTOFDESC(ap->a_vp)->fd_type) {
    557         1.8       cgd 	case Fctty:
    558        1.87  christos 		return 0;
    559         1.8       cgd 
    560         1.8       cgd 	case Fdesc:
    561        1.87  christos 		return ENOTDIR;
    562        1.30  christos 
    563        1.30  christos 	default:
    564        1.30  christos 		break;
    565         1.8       cgd 	}
    566         1.1       cgd 
    567       1.107        ad 	dt = curlwp->l_fd->fd_dt;
    568         1.8       cgd 
    569        1.25   mycroft 	if (uio->uio_resid < UIO_MX)
    570        1.87  christos 		return EINVAL;
    571        1.26   mycroft 	if (uio->uio_offset < 0)
    572        1.87  christos 		return EINVAL;
    573        1.25   mycroft 
    574        1.25   mycroft 	error = 0;
    575        1.26   mycroft 	i = uio->uio_offset;
    576        1.87  christos 	(void)memset(&d, 0, UIO_MX);
    577        1.25   mycroft 	d.d_reclen = UIO_MX;
    578        1.44      fvdl 	if (ap->a_ncookies)
    579        1.87  christos 		ncookies = uio->uio_resid / UIO_MX;
    580        1.87  christos 	else
    581        1.87  christos 		ncookies = 0;
    582        1.25   mycroft 
    583        1.14   mycroft 	if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
    584        1.25   mycroft 		struct fdesc_target *ft;
    585        1.51  christos 
    586        1.51  christos 		if (i >= nfdesc_targets)
    587        1.52  sommerfe 			return 0;
    588         1.3       cgd 
    589        1.44      fvdl 		if (ap->a_ncookies) {
    590        1.44      fvdl 			ncookies = min(ncookies, (nfdesc_targets - i));
    591        1.56   thorpej 			cookies = malloc(ncookies * sizeof(off_t),
    592        1.44      fvdl 			    M_TEMP, M_WAITOK);
    593        1.44      fvdl 			*ap->a_cookies = cookies;
    594        1.44      fvdl 			*ap->a_ncookies = ncookies;
    595        1.44      fvdl 		}
    596        1.44      fvdl 
    597        1.87  christos 		for (ft = &fdesc_targets[i]; uio->uio_resid >= UIO_MX &&
    598        1.87  christos 		    i < nfdesc_targets; ft++, i++) {
    599        1.25   mycroft 			switch (ft->ft_fileno) {
    600         1.8       cgd 			case FD_CTTY:
    601        1.90      yamt 				if (cttyvp(curproc) == NULL)
    602         1.8       cgd 					continue;
    603         1.8       cgd 				break;
    604         1.8       cgd 
    605         1.8       cgd 			case FD_STDIN:
    606         1.8       cgd 			case FD_STDOUT:
    607         1.8       cgd 			case FD_STDERR:
    608        1.87  christos 				if ((ft->ft_fileno - FD_STDIN) >=
    609       1.107        ad 				    dt->dt_nfiles)
    610        1.87  christos 					continue;
    611       1.107        ad 				if (dt->dt_ff[ft->ft_fileno - FD_STDIN]
    612       1.107        ad 				    == NULL || dt->dt_ff[ft->ft_fileno -
    613       1.102        ad 				    FD_STDIN]->ff_file == NULL)
    614         1.8       cgd 					continue;
    615         1.8       cgd 				break;
    616         1.8       cgd 			}
    617        1.25   mycroft 
    618        1.25   mycroft 			d.d_fileno = ft->ft_fileno;
    619        1.25   mycroft 			d.d_namlen = ft->ft_namlen;
    620        1.87  christos 			(void)memcpy(d.d_name, ft->ft_name, ft->ft_namlen + 1);
    621        1.25   mycroft 			d.d_type = ft->ft_type;
    622        1.25   mycroft 
    623        1.81       jrf 			if ((error = uiomove(&d, UIO_MX, uio)) != 0)
    624         1.8       cgd 				break;
    625        1.44      fvdl 			if (cookies)
    626        1.26   mycroft 				*cookies++ = i + 1;
    627         1.3       cgd 		}
    628        1.25   mycroft 	} else {
    629       1.102        ad 		membar_consumer();
    630        1.44      fvdl 		if (ap->a_ncookies) {
    631       1.107        ad 			ncookies = min(ncookies, dt->dt_nfiles + 2);
    632        1.56   thorpej 			cookies = malloc(ncookies * sizeof(off_t),
    633        1.56   thorpej 			    M_TEMP, M_WAITOK);
    634        1.44      fvdl 			*ap->a_cookies = cookies;
    635        1.44      fvdl 			*ap->a_ncookies = ncookies;
    636        1.44      fvdl 		}
    637       1.107        ad 		for (; i - 2 < dt->dt_nfiles && uio->uio_resid >= UIO_MX; i++) {
    638        1.25   mycroft 			switch (i) {
    639        1.25   mycroft 			case 0:
    640        1.25   mycroft 			case 1:
    641        1.25   mycroft 				d.d_fileno = FD_ROOT;		/* XXX */
    642        1.25   mycroft 				d.d_namlen = i + 1;
    643        1.87  christos 				(void)memcpy(d.d_name, "..", d.d_namlen);
    644        1.25   mycroft 				d.d_name[i + 1] = '\0';
    645        1.25   mycroft 				d.d_type = DT_DIR;
    646        1.25   mycroft 				break;
    647        1.83     perry 
    648        1.25   mycroft 			default:
    649        1.87  christos 				j = (int)i - 2;
    650       1.107        ad 				if (dt->dt_ff[j] == NULL ||
    651       1.107        ad 				    dt->dt_ff[j]->ff_file == NULL)
    652        1.25   mycroft 					continue;
    653        1.87  christos 				d.d_fileno = j + FD_STDIN;
    654  1.114.12.1       tls 				d.d_namlen = snprintf(d.d_name,
    655  1.114.12.1       tls 				    sizeof(d.d_name), "%d", j);
    656        1.25   mycroft 				d.d_type = DT_UNKNOWN;
    657        1.25   mycroft 				break;
    658        1.25   mycroft 			}
    659         1.8       cgd 
    660        1.81       jrf 			if ((error = uiomove(&d, UIO_MX, uio)) != 0)
    661         1.1       cgd 				break;
    662        1.44      fvdl 			if (cookies)
    663        1.26   mycroft 				*cookies++ = i + 1;
    664         1.1       cgd 		}
    665         1.8       cgd 	}
    666         1.8       cgd 
    667        1.44      fvdl 	if (ap->a_ncookies && error) {
    668        1.56   thorpej 		free(*ap->a_cookies, M_TEMP);
    669        1.44      fvdl 		*ap->a_ncookies = 0;
    670        1.44      fvdl 		*ap->a_cookies = NULL;
    671        1.44      fvdl 	}
    672        1.44      fvdl 
    673        1.26   mycroft 	uio->uio_offset = i;
    674        1.87  christos 	return error;
    675         1.8       cgd }
    676         1.8       cgd 
    677        1.14   mycroft int
    678       1.105       dsl fdesc_readlink(void *v)
    679        1.30  christos {
    680        1.14   mycroft 	struct vop_readlink_args /* {
    681        1.14   mycroft 		struct vnode *a_vp;
    682        1.14   mycroft 		struct uio *a_uio;
    683        1.92      elad 		kauth_cred_t a_cred;
    684        1.30  christos 	} */ *ap = v;
    685        1.14   mycroft 	struct vnode *vp = ap->a_vp;
    686         1.8       cgd 	int error;
    687         1.8       cgd 
    688        1.14   mycroft 	if (vp->v_type != VLNK)
    689        1.14   mycroft 		return (EPERM);
    690        1.14   mycroft 
    691         1.8       cgd 	if (VTOFDESC(vp)->fd_type == Flink) {
    692  1.114.12.1       tls 		const char *ln = VTOFDESC(vp)->fd_link;
    693  1.114.12.1       tls 		error = uiomove(__UNCONST(ln), strlen(ln), ap->a_uio);
    694         1.8       cgd 	} else {
    695         1.8       cgd 		error = EOPNOTSUPP;
    696         1.8       cgd 	}
    697         1.8       cgd 
    698         1.8       cgd 	return (error);
    699         1.8       cgd }
    700         1.8       cgd 
    701        1.14   mycroft int
    702       1.105       dsl fdesc_read(void *v)
    703        1.30  christos {
    704        1.14   mycroft 	struct vop_read_args /* {
    705        1.14   mycroft 		struct vnode *a_vp;
    706        1.14   mycroft 		struct uio *a_uio;
    707        1.14   mycroft 		int  a_ioflag;
    708        1.92      elad 		kauth_cred_t a_cred;
    709        1.30  christos 	} */ *ap = v;
    710         1.8       cgd 	int error = EOPNOTSUPP;
    711        1.49   thorpej 	struct vnode *vp = ap->a_vp;
    712         1.8       cgd 
    713        1.49   thorpej 	switch (VTOFDESC(vp)->fd_type) {
    714         1.8       cgd 	case Fctty:
    715       1.110   hannken 		VOP_UNLOCK(vp);
    716        1.97        ad 		error = cdev_read(devctty, ap->a_uio, ap->a_ioflag);
    717        1.49   thorpej 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    718         1.8       cgd 		break;
    719         1.8       cgd 
    720         1.8       cgd 	default:
    721         1.8       cgd 		error = EOPNOTSUPP;
    722         1.8       cgd 		break;
    723         1.8       cgd 	}
    724        1.83     perry 
    725         1.8       cgd 	return (error);
    726         1.8       cgd }
    727         1.8       cgd 
    728        1.14   mycroft int
    729       1.105       dsl fdesc_write(void *v)
    730        1.30  christos {
    731        1.14   mycroft 	struct vop_write_args /* {
    732        1.14   mycroft 		struct vnode *a_vp;
    733        1.14   mycroft 		struct uio *a_uio;
    734        1.14   mycroft 		int  a_ioflag;
    735        1.92      elad 		kauth_cred_t a_cred;
    736        1.30  christos 	} */ *ap = v;
    737         1.8       cgd 	int error = EOPNOTSUPP;
    738        1.49   thorpej 	struct vnode *vp = ap->a_vp;
    739         1.8       cgd 
    740        1.49   thorpej 	switch (VTOFDESC(vp)->fd_type) {
    741         1.8       cgd 	case Fctty:
    742       1.110   hannken 		VOP_UNLOCK(vp);
    743        1.97        ad 		error = cdev_write(devctty, ap->a_uio, ap->a_ioflag);
    744        1.49   thorpej 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    745         1.8       cgd 		break;
    746         1.8       cgd 
    747         1.8       cgd 	default:
    748         1.8       cgd 		error = EOPNOTSUPP;
    749         1.8       cgd 		break;
    750         1.8       cgd 	}
    751        1.83     perry 
    752         1.8       cgd 	return (error);
    753         1.8       cgd }
    754         1.8       cgd 
    755        1.14   mycroft int
    756       1.105       dsl fdesc_ioctl(void *v)
    757        1.30  christos {
    758        1.14   mycroft 	struct vop_ioctl_args /* {
    759        1.14   mycroft 		struct vnode *a_vp;
    760        1.19       cgd 		u_long a_command;
    761        1.81       jrf 		void *a_data;
    762        1.14   mycroft 		int  a_fflag;
    763        1.92      elad 		kauth_cred_t a_cred;
    764        1.30  christos 	} */ *ap = v;
    765         1.8       cgd 	int error = EOPNOTSUPP;
    766         1.8       cgd 
    767        1.14   mycroft 	switch (VTOFDESC(ap->a_vp)->fd_type) {
    768         1.8       cgd 	case Fctty:
    769        1.97        ad 		error = cdev_ioctl(devctty, ap->a_command, ap->a_data,
    770       1.100     pooka 		    ap->a_fflag, curlwp);
    771         1.8       cgd 		break;
    772         1.8       cgd 
    773         1.8       cgd 	default:
    774         1.8       cgd 		error = EOPNOTSUPP;
    775         1.8       cgd 		break;
    776         1.1       cgd 	}
    777        1.83     perry 
    778         1.8       cgd 	return (error);
    779         1.8       cgd }
    780         1.8       cgd 
    781        1.14   mycroft int
    782       1.105       dsl fdesc_poll(void *v)
    783        1.30  christos {
    784        1.35   mycroft 	struct vop_poll_args /* {
    785        1.14   mycroft 		struct vnode *a_vp;
    786        1.35   mycroft 		int a_events;
    787        1.30  christos 	} */ *ap = v;
    788        1.35   mycroft 	int revents;
    789         1.8       cgd 
    790        1.14   mycroft 	switch (VTOFDESC(ap->a_vp)->fd_type) {
    791         1.8       cgd 	case Fctty:
    792       1.100     pooka 		revents = cdev_poll(devctty, ap->a_events, curlwp);
    793         1.8       cgd 		break;
    794         1.1       cgd 
    795         1.8       cgd 	default:
    796        1.35   mycroft 		revents = genfs_poll(v);
    797         1.8       cgd 		break;
    798         1.8       cgd 	}
    799        1.34   mycroft 
    800        1.35   mycroft 	return (revents);
    801        1.71  jdolecek }
    802        1.71  jdolecek 
    803        1.71  jdolecek int
    804       1.105       dsl fdesc_kqfilter(void *v)
    805        1.71  jdolecek {
    806        1.71  jdolecek 	struct vop_kqfilter_args /* {
    807        1.71  jdolecek 		struct vnode *a_vp;
    808        1.71  jdolecek 		struct knote *a_kn;
    809        1.71  jdolecek 	} */ *ap = v;
    810       1.102        ad 	int error, fd;
    811       1.102        ad 	file_t *fp;
    812        1.71  jdolecek 
    813        1.71  jdolecek 	switch (VTOFDESC(ap->a_vp)->fd_type) {
    814        1.71  jdolecek 	case Fctty:
    815        1.97        ad 		error = cdev_kqfilter(devctty, ap->a_kn);
    816        1.71  jdolecek 		break;
    817        1.71  jdolecek 
    818        1.71  jdolecek 	case Fdesc:
    819        1.71  jdolecek 		/* just invoke kqfilter for the underlying descriptor */
    820       1.102        ad 		fd = VTOFDESC(ap->a_vp)->fd_fd;
    821       1.102        ad 		if ((fp = fd_getfile(fd)) == NULL)
    822        1.71  jdolecek 			return (1);
    823        1.71  jdolecek 		error = (*fp->f_ops->fo_kqfilter)(fp, ap->a_kn);
    824       1.102        ad 		fd_putfile(fd);
    825        1.71  jdolecek 		break;
    826        1.71  jdolecek 
    827        1.71  jdolecek 	default:
    828        1.71  jdolecek 		return (genfs_kqfilter(v));
    829        1.71  jdolecek 	}
    830        1.71  jdolecek 
    831        1.71  jdolecek 	return (error);
    832         1.1       cgd }
    833         1.1       cgd 
    834        1.14   mycroft int
    835       1.105       dsl fdesc_inactive(void *v)
    836        1.30  christos {
    837        1.14   mycroft 	struct vop_inactive_args /* {
    838        1.14   mycroft 		struct vnode *a_vp;
    839        1.30  christos 	} */ *ap = v;
    840        1.14   mycroft 	struct vnode *vp = ap->a_vp;
    841  1.114.12.1       tls 	struct fdescnode *fd = VTOFDESC(vp);
    842        1.14   mycroft 
    843         1.1       cgd 	/*
    844         1.1       cgd 	 * Clear out the v_type field to avoid
    845  1.114.12.1       tls 	 * nasty things happening on reclaim.
    846         1.1       cgd 	 */
    847  1.114.12.1       tls 	if (fd->fd_type == Fctty || fd->fd_type == Fdesc)
    848  1.114.12.1       tls 		vp->v_type = VNON;
    849       1.110   hannken 	VOP_UNLOCK(vp);
    850         1.1       cgd 	return (0);
    851         1.1       cgd }
    852         1.1       cgd 
    853        1.14   mycroft int
    854       1.105       dsl fdesc_reclaim(void *v)
    855        1.30  christos {
    856        1.14   mycroft 	struct vop_reclaim_args /* {
    857        1.14   mycroft 		struct vnode *a_vp;
    858        1.30  christos 	} */ *ap = v;
    859        1.14   mycroft 	struct vnode *vp = ap->a_vp;
    860        1.17   mycroft 	struct fdescnode *fd = VTOFDESC(vp);
    861        1.14   mycroft 
    862  1.114.12.1       tls 	vp->v_data = NULL;
    863  1.114.12.1       tls 	vcache_remove(vp->v_mount, &fd->fd_ix, sizeof(fd->fd_ix));
    864  1.114.12.1       tls 	kmem_free(fd, sizeof(struct fdescnode));
    865        1.14   mycroft 
    866        1.14   mycroft 	return (0);
    867        1.14   mycroft }
    868        1.14   mycroft 
    869        1.14   mycroft /*
    870        1.14   mycroft  * Return POSIX pathconf information applicable to special devices.
    871        1.14   mycroft  */
    872        1.30  christos int
    873       1.105       dsl fdesc_pathconf(void *v)
    874        1.30  christos {
    875        1.14   mycroft 	struct vop_pathconf_args /* {
    876        1.14   mycroft 		struct vnode *a_vp;
    877        1.14   mycroft 		int a_name;
    878        1.18       cgd 		register_t *a_retval;
    879        1.30  christos 	} */ *ap = v;
    880         1.8       cgd 
    881        1.14   mycroft 	switch (ap->a_name) {
    882        1.14   mycroft 	case _PC_LINK_MAX:
    883        1.14   mycroft 		*ap->a_retval = LINK_MAX;
    884        1.14   mycroft 		return (0);
    885        1.14   mycroft 	case _PC_MAX_CANON:
    886        1.14   mycroft 		*ap->a_retval = MAX_CANON;
    887        1.14   mycroft 		return (0);
    888        1.14   mycroft 	case _PC_MAX_INPUT:
    889        1.14   mycroft 		*ap->a_retval = MAX_INPUT;
    890        1.14   mycroft 		return (0);
    891        1.14   mycroft 	case _PC_PIPE_BUF:
    892        1.14   mycroft 		*ap->a_retval = PIPE_BUF;
    893        1.14   mycroft 		return (0);
    894        1.14   mycroft 	case _PC_CHOWN_RESTRICTED:
    895        1.14   mycroft 		*ap->a_retval = 1;
    896        1.14   mycroft 		return (0);
    897        1.14   mycroft 	case _PC_VDISABLE:
    898        1.14   mycroft 		*ap->a_retval = _POSIX_VDISABLE;
    899        1.45    kleink 		return (0);
    900        1.45    kleink 	case _PC_SYNC_IO:
    901        1.45    kleink 		*ap->a_retval = 1;
    902        1.14   mycroft 		return (0);
    903        1.14   mycroft 	default:
    904        1.14   mycroft 		return (EINVAL);
    905         1.8       cgd 	}
    906        1.14   mycroft 	/* NOTREACHED */
    907         1.8       cgd }
    908         1.8       cgd 
    909         1.1       cgd /*
    910         1.1       cgd  * Print out the contents of a /dev/fd vnode.
    911         1.1       cgd  */
    912         1.1       cgd /* ARGSUSED */
    913        1.14   mycroft int
    914        1.94  christos fdesc_print(void *v)
    915         1.1       cgd {
    916        1.37  christos 	printf("tag VT_NON, fdesc vnode\n");
    917        1.14   mycroft 	return (0);
    918        1.14   mycroft }
    919        1.14   mycroft 
    920        1.14   mycroft int
    921       1.105       dsl fdesc_link(void *v)
    922        1.30  christos {
    923        1.29   mycroft 	struct vop_link_args /* {
    924        1.29   mycroft 		struct vnode *a_dvp;
    925        1.83     perry 		struct vnode *a_vp;
    926        1.29   mycroft 		struct componentname *a_cnp;
    927        1.30  christos 	} */ *ap = v;
    928        1.83     perry 
    929        1.29   mycroft 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
    930        1.29   mycroft 	vput(ap->a_dvp);
    931        1.29   mycroft 	return (EROFS);
    932        1.29   mycroft }
    933        1.29   mycroft 
    934        1.29   mycroft int
    935       1.105       dsl fdesc_symlink(void *v)
    936        1.30  christos {
    937  1.114.12.1       tls 	struct vop_symlink_v3_args /* {
    938        1.29   mycroft 		struct vnode *a_dvp;
    939        1.29   mycroft 		struct vnode **a_vpp;
    940        1.29   mycroft 		struct componentname *a_cnp;
    941        1.29   mycroft 		struct vattr *a_vap;
    942        1.29   mycroft 		char *a_target;
    943        1.30  christos 	} */ *ap = v;
    944        1.83     perry 
    945        1.29   mycroft 	VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
    946        1.29   mycroft 	return (EROFS);
    947         1.1       cgd }
    948