1 /* $NetBSD: fdesc_vnops.c,v 1.108 2009/07/31 18:50:58 pooka Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software donated to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
36 * #Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp #
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.108 2009/07/31 18:50:58 pooka Exp $");
46 #include <sys/param.h>
47 #include <sys/systm.h>
50 #include <sys/kernel.h> /* boottime */
51 #include <sys/resourcevar.h>
52 #include <sys/socketvar.h>
53 #include <sys/filedesc.h>
54 #include <sys/vnode.h>
55 #include <sys/malloc.h>
59 #include <sys/mount.h>
60 #include <sys/namei.h>
62 #include <sys/dirent.h>
64 #include <sys/kauth.h>
65 #include <sys/atomic.h>
67 #include <miscfs/fdesc/fdesc.h>
68 #include <miscfs/genfs/genfs.h>
70 #define cttyvp(p) ((p)->p_lflag & PL_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
73 #define FDL_LOCKED 0x02
74 static int fdcache_lock
;
78 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
79 FD_STDIN
, FD_STDOUT
, FD_STDERR must be a sequence n
, n
+1, n
+2
84 #define FD_NHASH(ix) \
85 (&fdhashtbl[(ix) & fdhash])
86 LIST_HEAD(fdhashhead
, fdescnode
) *fdhashtbl
;
89 int fdesc_lookup(void *);
90 #define fdesc_create genfs_eopnotsupp
91 #define fdesc_mknod genfs_eopnotsupp
92 int fdesc_open(void *);
93 #define fdesc_close genfs_nullop
94 #define fdesc_access genfs_nullop
95 int fdesc_getattr(void *);
96 int fdesc_setattr(void *);
97 int fdesc_read(void *);
98 int fdesc_write(void *);
99 int fdesc_ioctl(void *);
100 int fdesc_poll(void *);
101 int fdesc_kqfilter(void *);
102 #define fdesc_mmap genfs_eopnotsupp
103 #define fdesc_fcntl genfs_fcntl
104 #define fdesc_fsync genfs_nullop
105 #define fdesc_seek genfs_seek
106 #define fdesc_remove genfs_eopnotsupp
107 int fdesc_link(void *);
108 #define fdesc_rename genfs_eopnotsupp
109 #define fdesc_mkdir genfs_eopnotsupp
110 #define fdesc_rmdir genfs_eopnotsupp
111 int fdesc_symlink(void *);
112 int fdesc_readdir(void *);
113 int fdesc_readlink(void *);
114 #define fdesc_abortop genfs_abortop
115 int fdesc_inactive(void *);
116 int fdesc_reclaim(void *);
117 #define fdesc_lock genfs_lock
118 #define fdesc_unlock genfs_unlock
119 #define fdesc_bmap genfs_badop
120 #define fdesc_strategy genfs_badop
121 int fdesc_print(void *);
122 int fdesc_pathconf(void *);
123 #define fdesc_islocked genfs_islocked
124 #define fdesc_advlock genfs_einval
125 #define fdesc_bwrite genfs_eopnotsupp
126 #define fdesc_revoke genfs_revoke
127 #define fdesc_putpages genfs_null_putpages
129 static int fdesc_attr(int, struct vattr
*, kauth_cred_t
);
131 int (**fdesc_vnodeop_p
)(void *);
132 const struct vnodeopv_entry_desc fdesc_vnodeop_entries
[] = {
133 { &vop_default_desc
, vn_default_error
},
134 { &vop_lookup_desc
, fdesc_lookup
}, /* lookup */
135 { &vop_create_desc
, fdesc_create
}, /* create */
136 { &vop_mknod_desc
, fdesc_mknod
}, /* mknod */
137 { &vop_open_desc
, fdesc_open
}, /* open */
138 { &vop_close_desc
, fdesc_close
}, /* close */
139 { &vop_access_desc
, fdesc_access
}, /* access */
140 { &vop_getattr_desc
, fdesc_getattr
}, /* getattr */
141 { &vop_setattr_desc
, fdesc_setattr
}, /* setattr */
142 { &vop_read_desc
, fdesc_read
}, /* read */
143 { &vop_write_desc
, fdesc_write
}, /* write */
144 { &vop_ioctl_desc
, fdesc_ioctl
}, /* ioctl */
145 { &vop_fcntl_desc
, fdesc_fcntl
}, /* fcntl */
146 { &vop_poll_desc
, fdesc_poll
}, /* poll */
147 { &vop_kqfilter_desc
, fdesc_kqfilter
}, /* kqfilter */
148 { &vop_revoke_desc
, fdesc_revoke
}, /* revoke */
149 { &vop_mmap_desc
, fdesc_mmap
}, /* mmap */
150 { &vop_fsync_desc
, fdesc_fsync
}, /* fsync */
151 { &vop_seek_desc
, fdesc_seek
}, /* seek */
152 { &vop_remove_desc
, fdesc_remove
}, /* remove */
153 { &vop_link_desc
, fdesc_link
}, /* link */
154 { &vop_rename_desc
, fdesc_rename
}, /* rename */
155 { &vop_mkdir_desc
, fdesc_mkdir
}, /* mkdir */
156 { &vop_rmdir_desc
, fdesc_rmdir
}, /* rmdir */
157 { &vop_symlink_desc
, fdesc_symlink
}, /* symlink */
158 { &vop_readdir_desc
, fdesc_readdir
}, /* readdir */
159 { &vop_readlink_desc
, fdesc_readlink
}, /* readlink */
160 { &vop_abortop_desc
, fdesc_abortop
}, /* abortop */
161 { &vop_inactive_desc
, fdesc_inactive
}, /* inactive */
162 { &vop_reclaim_desc
, fdesc_reclaim
}, /* reclaim */
163 { &vop_lock_desc
, fdesc_lock
}, /* lock */
164 { &vop_unlock_desc
, fdesc_unlock
}, /* unlock */
165 { &vop_bmap_desc
, fdesc_bmap
}, /* bmap */
166 { &vop_strategy_desc
, fdesc_strategy
}, /* strategy */
167 { &vop_print_desc
, fdesc_print
}, /* print */
168 { &vop_islocked_desc
, fdesc_islocked
}, /* islocked */
169 { &vop_pathconf_desc
, fdesc_pathconf
}, /* pathconf */
170 { &vop_advlock_desc
, fdesc_advlock
}, /* advlock */
171 { &vop_bwrite_desc
, fdesc_bwrite
}, /* bwrite */
172 { &vop_putpages_desc
, fdesc_putpages
}, /* putpages */
176 const struct vnodeopv_desc fdesc_vnodeop_opv_desc
=
177 { &fdesc_vnodeop_p
, fdesc_vnodeop_entries
};
180 * Initialise cache headers
187 /* locate the major number */
188 cttymajor
= devsw_name2chr("ctty", NULL
, 0);
189 devctty
= makedev(cttymajor
, 0);
190 fdhashtbl
= hashinit(NFDCACHE
, HASH_LIST
, true, &fdhash
);
199 hashdone(fdhashtbl
, HASH_LIST
, fdhash
);
203 * Return a locked vnode of the correct type.
206 fdesc_allocvp(fdntype ftype
, int ix
, struct mount
*mp
, struct vnode
**vpp
)
208 struct fdhashhead
*fc
;
209 struct fdescnode
*fd
;
214 for (fd
= fc
->lh_first
; fd
!= 0; fd
= fd
->fd_hash
.le_next
) {
215 if (fd
->fd_ix
== ix
&& fd
->fd_vnode
->v_mount
== mp
) {
216 if (vget(fd
->fd_vnode
, LK_EXCLUSIVE
))
224 * otherwise lock the array while we call getnewvnode
225 * since that can block.
227 if (fdcache_lock
& FDL_LOCKED
) {
228 fdcache_lock
|= FDL_WANT
;
229 (void) tsleep(&fdcache_lock
, PINOD
, "fdcache", 0);
232 fdcache_lock
|= FDL_LOCKED
;
234 error
= getnewvnode(VT_FDESC
, mp
, fdesc_vnodeop_p
, vpp
);
237 fd
= malloc(sizeof(struct fdescnode
), M_TEMP
, M_WAITOK
);
244 uvm_vnp_setsize(*vpp
, 0);
245 VOP_LOCK(*vpp
, LK_EXCLUSIVE
);
246 LIST_INSERT_HEAD(fc
, fd
, fd_hash
);
249 fdcache_lock
&= ~FDL_LOCKED
;
251 if (fdcache_lock
& FDL_WANT
) {
252 fdcache_lock
&= ~FDL_WANT
;
253 wakeup(&fdcache_lock
);
260 * vp is the current namei directory
261 * ndp is the name to locate in that directory...
264 fdesc_lookup(void *v
)
266 struct vop_lookup_args
/* {
267 struct vnode * a_dvp;
268 struct vnode ** a_vpp;
269 struct componentname * a_cnp;
271 struct vnode
**vpp
= ap
->a_vpp
;
272 struct vnode
*dvp
= ap
->a_dvp
;
273 struct componentname
*cnp
= ap
->a_cnp
;
274 struct lwp
*l
= curlwp
;
275 const char *pname
= cnp
->cn_nameptr
;
276 struct proc
*p
= l
->l_proc
;
283 dt
= curlwp
->l_fd
->fd_dt
;
285 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
291 switch (VTOFDESC(dvp
)->fd_type
) {
300 if (cnp
->cn_namelen
== 2 && memcmp(pname
, "fd", 2) == 0) {
301 error
= fdesc_allocvp(Fdevfd
, FD_DEVFD
, dvp
->v_mount
, &fvp
);
309 if (cnp
->cn_namelen
== 3 && memcmp(pname
, "tty", 3) == 0) {
310 struct vnode
*ttyvp
= cttyvp(p
);
315 error
= fdesc_allocvp(Fctty
, FD_CTTY
, dvp
->v_mount
, &fvp
);
324 switch (cnp
->cn_namelen
) {
326 if (memcmp(pname
, "stdin", 5) == 0) {
332 if (memcmp(pname
, "stdout", 6) == 0) {
336 if (memcmp(pname
, "stderr", 6) == 0) {
344 error
= fdesc_allocvp(Flink
, fd
, dvp
->v_mount
, &fvp
);
348 VTOFDESC(fvp
)->fd_link
= __UNCONST(ln
);
360 if (cnp
->cn_namelen
== 2 && memcmp(pname
, "..", 2) == 0) {
362 error
= fdesc_root(dvp
->v_mount
, vpp
);
363 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
370 while (*pname
>= '0' && *pname
<= '9') {
371 fd
= 10 * fd
+ *pname
++ - '0';
372 if (fd
>= dt
->dt_nfiles
)
376 if (*pname
!= '\0') {
381 if (fd
>= dt
->dt_nfiles
|| dt
->dt_ff
[fd
] == NULL
||
382 dt
->dt_ff
[fd
]->ff_file
== NULL
) {
387 error
= fdesc_allocvp(Fdesc
, FD_DESC
+fd
, dvp
->v_mount
, &fvp
);
390 VTOFDESC(fvp
)->fd_fd
= fd
;
406 struct vop_open_args
/* {
411 struct vnode
*vp
= ap
->a_vp
;
413 switch (VTOFDESC(vp
)->fd_type
) {
416 * XXX Kludge: set dupfd to contain the value of the
417 * the file descriptor being sought for duplication. The error
418 * return ensures that the vnode for this device will be
419 * released by vn_open. Open will detect this special error and
420 * take the actions in dupfdopen. Other callers of vn_open or
421 * VOP_OPEN will simply report the error.
423 curlwp
->l_dupfd
= VTOFDESC(vp
)->fd_fd
; /* XXX */
427 return cdev_open(devctty
, ap
->a_mode
, 0, curlwp
);
438 fdesc_attr(int fd
, struct vattr
*vap
, kauth_cred_t cred
)
444 if ((fp
= fd_getfile(fd
)) == NULL
)
447 switch (fp
->f_type
) {
449 error
= VOP_GETATTR((struct vnode
*) fp
->f_data
, vap
, cred
);
450 if (error
== 0 && vap
->va_type
== VDIR
) {
452 * directories can cause loops in the namespace,
453 * so turn off the 'x' bits to avoid trouble.
455 vap
->va_mode
&= ~(S_IXUSR
|S_IXGRP
|S_IXOTH
);
460 memset(&stb
, 0, sizeof(stb
));
461 error
= (*fp
->f_ops
->fo_stat
)(fp
, &stb
);
468 vap
->va_type
= VSOCK
;
471 vap
->va_type
= VFIFO
;
474 /* use VNON perhaps? */
478 vap
->va_mode
= stb
.st_mode
;
479 vap
->va_nlink
= stb
.st_nlink
;
480 vap
->va_uid
= stb
.st_uid
;
481 vap
->va_gid
= stb
.st_gid
;
482 vap
->va_fsid
= stb
.st_dev
;
483 vap
->va_fileid
= stb
.st_ino
;
484 vap
->va_size
= stb
.st_size
;
485 vap
->va_blocksize
= stb
.st_blksize
;
486 vap
->va_atime
= stb
.st_atimespec
;
487 vap
->va_mtime
= stb
.st_mtimespec
;
488 vap
->va_ctime
= stb
.st_ctimespec
;
489 vap
->va_gen
= stb
.st_gen
;
490 vap
->va_flags
= stb
.st_flags
;
491 vap
->va_rdev
= stb
.st_rdev
;
492 vap
->va_bytes
= stb
.st_blocks
* stb
.st_blksize
;
501 fdesc_getattr(void *v
)
503 struct vop_getattr_args
/* {
509 struct vnode
*vp
= ap
->a_vp
;
510 struct vattr
*vap
= ap
->a_vap
;
514 switch (VTOFDESC(vp
)->fd_type
) {
520 vap
->va_fileid
= VTOFDESC(vp
)->fd_ix
;
522 #define R_ALL (S_IRUSR|S_IRGRP|S_IROTH)
523 #define W_ALL (S_IWUSR|S_IWGRP|S_IWOTH)
524 #define X_ALL (S_IXUSR|S_IXGRP|S_IXOTH)
526 switch (VTOFDESC(vp
)->fd_type
) {
528 vap
->va_mode
= R_ALL
|X_ALL
;
532 vap
->va_size
= strlen(VTOFDESC(vp
)->fd_link
);
536 vap
->va_mode
= R_ALL
|W_ALL
;
538 vap
->va_rdev
= devctty
;
544 vap
->va_mode
= R_ALL
|X_ALL
;
548 vap
->va_size
= DEV_BSIZE
;
553 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsidx
.__fsid_val
[0];
554 vap
->va_blocksize
= DEV_BSIZE
;
555 vap
->va_atime
.tv_sec
= boottime
.tv_sec
;
556 vap
->va_atime
.tv_nsec
= 0;
557 vap
->va_mtime
= vap
->va_atime
;
558 vap
->va_ctime
= vap
->va_mtime
;
565 fd
= VTOFDESC(vp
)->fd_fd
;
566 error
= fdesc_attr(fd
, vap
, ap
->a_cred
);
570 panic("fdesc_getattr");
575 vp
->v_type
= vap
->va_type
;
581 fdesc_setattr(void *v
)
583 struct vop_setattr_args
/* {
592 * Can't mess with the root vnode
594 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
605 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
606 if ((fp
= fd_getfile(fd
)) == NULL
)
610 * XXX: Can't reasonably set the attr's on any types currently.
611 * On vnode's this will cause truncation and socket/pipes make
619 struct fdesc_target
{
624 } fdesc_targets
[] = {
625 #define N(s) sizeof(s)-1, s
626 { FD_DEVFD
, DT_DIR
, N("fd") },
627 { FD_STDIN
, DT_LNK
, N("stdin") },
628 { FD_STDOUT
, DT_LNK
, N("stdout") },
629 { FD_STDERR
, DT_LNK
, N("stderr") },
630 { FD_CTTY
, DT_UNKNOWN
, N("tty") },
632 #define UIO_MX _DIRENT_RECLEN((struct dirent *)NULL, sizeof("stderr") - 1)
634 static int nfdesc_targets
= sizeof(fdesc_targets
) / sizeof(fdesc_targets
[0]);
637 fdesc_readdir(void *v
)
639 struct vop_readdir_args
/* {
647 struct uio
*uio
= ap
->a_uio
;
652 off_t
*cookies
= NULL
;
656 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
667 dt
= curlwp
->l_fd
->fd_dt
;
669 if (uio
->uio_resid
< UIO_MX
)
671 if (uio
->uio_offset
< 0)
676 (void)memset(&d
, 0, UIO_MX
);
679 ncookies
= uio
->uio_resid
/ UIO_MX
;
683 if (VTOFDESC(ap
->a_vp
)->fd_type
== Froot
) {
684 struct fdesc_target
*ft
;
686 if (i
>= nfdesc_targets
)
689 if (ap
->a_ncookies
) {
690 ncookies
= min(ncookies
, (nfdesc_targets
- i
));
691 cookies
= malloc(ncookies
* sizeof(off_t
),
693 *ap
->a_cookies
= cookies
;
694 *ap
->a_ncookies
= ncookies
;
697 for (ft
= &fdesc_targets
[i
]; uio
->uio_resid
>= UIO_MX
&&
698 i
< nfdesc_targets
; ft
++, i
++) {
699 switch (ft
->ft_fileno
) {
701 if (cttyvp(curproc
) == NULL
)
708 if ((ft
->ft_fileno
- FD_STDIN
) >=
711 if (dt
->dt_ff
[ft
->ft_fileno
- FD_STDIN
]
712 == NULL
|| dt
->dt_ff
[ft
->ft_fileno
-
713 FD_STDIN
]->ff_file
== NULL
)
718 d
.d_fileno
= ft
->ft_fileno
;
719 d
.d_namlen
= ft
->ft_namlen
;
720 (void)memcpy(d
.d_name
, ft
->ft_name
, ft
->ft_namlen
+ 1);
721 d
.d_type
= ft
->ft_type
;
723 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
730 if (ap
->a_ncookies
) {
731 ncookies
= min(ncookies
, dt
->dt_nfiles
+ 2);
732 cookies
= malloc(ncookies
* sizeof(off_t
),
734 *ap
->a_cookies
= cookies
;
735 *ap
->a_ncookies
= ncookies
;
737 for (; i
- 2 < dt
->dt_nfiles
&& uio
->uio_resid
>= UIO_MX
; i
++) {
741 d
.d_fileno
= FD_ROOT
; /* XXX */
743 (void)memcpy(d
.d_name
, "..", d
.d_namlen
);
744 d
.d_name
[i
+ 1] = '\0';
750 if (dt
->dt_ff
[j
] == NULL
||
751 dt
->dt_ff
[j
]->ff_file
== NULL
)
753 d
.d_fileno
= j
+ FD_STDIN
;
754 d
.d_namlen
= sprintf(d
.d_name
, "%d", j
);
755 d
.d_type
= DT_UNKNOWN
;
759 if ((error
= uiomove(&d
, UIO_MX
, uio
)) != 0)
766 if (ap
->a_ncookies
&& error
) {
767 free(*ap
->a_cookies
, M_TEMP
);
769 *ap
->a_cookies
= NULL
;
777 fdesc_readlink(void *v
)
779 struct vop_readlink_args
/* {
784 struct vnode
*vp
= ap
->a_vp
;
787 if (vp
->v_type
!= VLNK
)
790 if (VTOFDESC(vp
)->fd_type
== Flink
) {
791 char *ln
= VTOFDESC(vp
)->fd_link
;
792 error
= uiomove(ln
, strlen(ln
), ap
->a_uio
);
803 struct vop_read_args
/* {
809 int error
= EOPNOTSUPP
;
810 struct vnode
*vp
= ap
->a_vp
;
812 switch (VTOFDESC(vp
)->fd_type
) {
815 error
= cdev_read(devctty
, ap
->a_uio
, ap
->a_ioflag
);
816 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
830 struct vop_write_args
/* {
836 int error
= EOPNOTSUPP
;
837 struct vnode
*vp
= ap
->a_vp
;
839 switch (VTOFDESC(vp
)->fd_type
) {
842 error
= cdev_write(devctty
, ap
->a_uio
, ap
->a_ioflag
);
843 vn_lock(vp
, LK_EXCLUSIVE
| LK_RETRY
);
857 struct vop_ioctl_args
/* {
864 int error
= EOPNOTSUPP
;
866 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
868 error
= cdev_ioctl(devctty
, ap
->a_command
, ap
->a_data
,
869 ap
->a_fflag
, curlwp
);
883 struct vop_poll_args
/* {
889 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
891 revents
= cdev_poll(devctty
, ap
->a_events
, curlwp
);
895 revents
= genfs_poll(v
);
903 fdesc_kqfilter(void *v
)
905 struct vop_kqfilter_args
/* {
912 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
914 error
= cdev_kqfilter(devctty
, ap
->a_kn
);
918 /* just invoke kqfilter for the underlying descriptor */
919 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
920 if ((fp
= fd_getfile(fd
)) == NULL
)
922 error
= (*fp
->f_ops
->fo_kqfilter
)(fp
, ap
->a_kn
);
927 return (genfs_kqfilter(v
));
934 fdesc_inactive(void *v
)
936 struct vop_inactive_args
/* {
939 struct vnode
*vp
= ap
->a_vp
;
942 * Clear out the v_type field to avoid
943 * nasty things happening in vgone().
951 fdesc_reclaim(void *v
)
953 struct vop_reclaim_args
/* {
956 struct vnode
*vp
= ap
->a_vp
;
957 struct fdescnode
*fd
= VTOFDESC(vp
);
959 LIST_REMOVE(fd
, fd_hash
);
960 free(vp
->v_data
, M_TEMP
);
967 * Return POSIX pathconf information applicable to special devices.
970 fdesc_pathconf(void *v
)
972 struct vop_pathconf_args
/* {
975 register_t *a_retval;
978 switch (ap
->a_name
) {
980 *ap
->a_retval
= LINK_MAX
;
983 *ap
->a_retval
= MAX_CANON
;
986 *ap
->a_retval
= MAX_INPUT
;
989 *ap
->a_retval
= PIPE_BUF
;
991 case _PC_CHOWN_RESTRICTED
:
995 *ap
->a_retval
= _POSIX_VDISABLE
;
1007 * Print out the contents of a /dev/fd vnode.
1011 fdesc_print(void *v
)
1013 printf("tag VT_NON, fdesc vnode\n");
1020 struct vop_link_args
/* {
1021 struct vnode *a_dvp;
1023 struct componentname *a_cnp;
1026 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);
1032 fdesc_symlink(void *v
)
1034 struct vop_symlink_args
/* {
1035 struct vnode *a_dvp;
1036 struct vnode **a_vpp;
1037 struct componentname *a_cnp;
1038 struct vattr *a_vap;
1042 VOP_ABORTOP(ap
->a_dvp
, ap
->a_cnp
);