]> git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/fdesc/fdesc_vnops.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / miscfs / fdesc / fdesc_vnops.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26 /*
27 * Copyright (c) 1992, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * This code is derived from software donated to Berkeley by
31 * Jan-Simon Pendry.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
62 *
63 */
64
65 /*
66 * /dev/fd Filesystem
67 */
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/types.h>
72 #include <sys/time.h>
73 #include <sys/proc.h>
74 #include <sys/kernel.h> /* boottime */
75 #include <sys/resourcevar.h>
76 #include <sys/filedesc.h>
77 #include <sys/vnode.h>
78 #include <sys/malloc.h>
79 #include <sys/file.h>
80 #include <sys/stat.h>
81 #include <sys/mount.h>
82 #include <sys/namei.h>
83 #include <sys/buf.h>
84 #include <sys/dirent.h>
85 #include <sys/ubc.h>
86 #include <miscfs/fdesc/fdesc.h>
87 #include <vfs/vfs_support.h>
88
89 #define FDL_WANT 0x01
90 #define FDL_LOCKED 0x02
91 static int fdcache_lock;
92
93
94 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
95 FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
96 #endif
97
98 #define NFDCACHE 3
99
100 #define FD_NHASH(ix) \
101 (&fdhashtbl[(ix) & fdhash])
102 LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
103 u_long fdhash;
104
105 /*
106 * Initialise cache headers
107 */
108 fdesc_init(vfsp)
109 struct vfsconf *vfsp;
110 {
111
112 fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
113 }
114
115 int
116 fdesc_allocvp(ftype, ix, mp, vpp)
117 fdntype ftype;
118 int ix;
119 struct mount *mp;
120 struct vnode **vpp;
121 {
122 struct proc *p = current_proc(); /* XXX */
123 struct fdhashhead *fc;
124 struct fdescnode *fd;
125 int error = 0;
126
127 fc = FD_NHASH(ix);
128 loop:
129 for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
130 if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
131 if (vget(fd->fd_vnode, 0, p))
132 goto loop;
133 *vpp = fd->fd_vnode;
134 return (error);
135 }
136 }
137
138 /*
139 * otherwise lock the array while we call getnewvnode
140 * since that can block.
141 */
142 if (fdcache_lock & FDL_LOCKED) {
143 fdcache_lock |= FDL_WANT;
144 sleep((caddr_t) &fdcache_lock, PINOD);
145 goto loop;
146 }
147 fdcache_lock |= FDL_LOCKED;
148
149 MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
150 error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
151 if (error) {
152 FREE(fd, M_TEMP);
153 goto out;
154 }
155 (*vpp)->v_data = fd;
156 fd->fd_vnode = *vpp;
157 fd->fd_type = ftype;
158 fd->fd_fd = -1;
159 fd->fd_link = 0;
160 fd->fd_ix = ix;
161 LIST_INSERT_HEAD(fc, fd, fd_hash);
162
163 out:
164 fdcache_lock &= ~FDL_LOCKED;
165
166 if (fdcache_lock & FDL_WANT) {
167 fdcache_lock &= ~FDL_WANT;
168 wakeup((caddr_t) &fdcache_lock);
169 }
170
171 return (error);
172 }
173
174 /*
175 * vp is the current namei directory
176 * ndp is the name to locate in that directory...
177 */
178 int
179 fdesc_lookup(ap)
180 struct vop_lookup_args /* {
181 struct vnode * a_dvp;
182 struct vnode ** a_vpp;
183 struct componentname * a_cnp;
184 } */ *ap;
185 {
186 struct vnode **vpp = ap->a_vpp;
187 struct vnode *dvp = ap->a_dvp;
188 struct componentname *cnp = ap->a_cnp;
189 char *pname = cnp->cn_nameptr;
190 struct proc *p = cnp->cn_proc;
191 int nfiles = p->p_fd->fd_nfiles;
192 unsigned fd;
193 int error;
194 struct vnode *fvp;
195 char *ln;
196
197 VOP_UNLOCK(dvp, 0, p);
198 if (cnp->cn_namelen == 1 && *pname == '.') {
199 *vpp = dvp;
200 VREF(dvp);
201 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
202 return (0);
203 }
204
205 switch (VTOFDESC(dvp)->fd_type) {
206 default:
207 case Flink:
208 case Fdesc:
209 error = ENOTDIR;
210 goto bad;
211
212 case Froot:
213 if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
214 error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
215 if (error)
216 goto bad;
217 *vpp = fvp;
218 fvp->v_type = VDIR;
219 vn_lock(fvp, LK_SHARED | LK_RETRY, p);
220 return (0);
221 }
222
223 ln = 0;
224 switch (cnp->cn_namelen) {
225 case 5:
226 if (bcmp(pname, "stdin", 5) == 0) {
227 ln = "fd/0";
228 fd = FD_STDIN;
229 }
230 break;
231 case 6:
232 if (bcmp(pname, "stdout", 6) == 0) {
233 ln = "fd/1";
234 fd = FD_STDOUT;
235 } else
236 if (bcmp(pname, "stderr", 6) == 0) {
237 ln = "fd/2";
238 fd = FD_STDERR;
239 }
240 break;
241 }
242
243 if (ln) {
244 error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
245 if (error)
246 goto bad;
247 VTOFDESC(fvp)->fd_link = ln;
248 *vpp = fvp;
249 fvp->v_type = VLNK;
250 vn_lock(fvp, LK_SHARED | LK_RETRY, p);
251 return (0);
252 } else {
253 error = ENOENT;
254 goto bad;
255 }
256
257 /* FALL THROUGH */
258
259 case Fdevfd:
260 if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
261 if (error = fdesc_root(dvp->v_mount, vpp))
262 goto bad;
263 return (0);
264 }
265
266 fd = 0;
267 while (*pname >= '0' && *pname <= '9') {
268 fd = 10 * fd + *pname++ - '0';
269 if (fd >= nfiles)
270 break;
271 }
272
273 if (*pname != '\0') {
274 error = ENOENT;
275 goto bad;
276 }
277
278 if (fd >= nfiles ||
279 *fdfile(p, fd) == NULL ||
280 (*fdflags(p, fd) & UF_RESERVED)) {
281 error = EBADF;
282 goto bad;
283 }
284
285 error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
286 if (error)
287 goto bad;
288 VTOFDESC(fvp)->fd_fd = fd;
289 vn_lock(fvp, LK_SHARED | LK_RETRY, p);
290 *vpp = fvp;
291 return (0);
292 }
293
294 bad:;
295 vn_lock(dvp, LK_SHARED | LK_RETRY, p);
296 *vpp = NULL;
297 return (error);
298 }
299
300 int
301 fdesc_open(ap)
302 struct vop_open_args /* {
303 struct vnode *a_vp;
304 int a_mode;
305 struct ucred *a_cred;
306 struct proc *a_p;
307 } */ *ap;
308 {
309 struct vnode *vp = ap->a_vp;
310 int error = 0;
311
312 switch (VTOFDESC(vp)->fd_type) {
313 case Fdesc:
314 /*
315 * XXX Kludge: set p->p_dupfd to contain the value of the
316 * the file descriptor being sought for duplication. The error
317 * return ensures that the vnode for this device will be
318 * released by vn_open. Open will detect this special error and
319 * take the actions in dupfdopen. Other callers of vn_open or
320 * VOP_OPEN will simply report the error.
321 */
322 ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
323 error = ENODEV;
324 break;
325
326 }
327
328 return (error);
329 }
330
331 static int
332 fdesc_attr(fd, vap, cred, p)
333 int fd;
334 struct vattr *vap;
335 struct ucred *cred;
336 struct proc *p;
337 {
338 struct file *fp;
339 struct stat stb;
340 int error;
341
342 if (error = fdgetf(p, fd, &fp))
343 return (error);
344 switch (fp->f_type) {
345 case DTYPE_VNODE:
346 error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
347 if (error == 0 && vap->va_type == VDIR) {
348 /*
349 * directories can cause loops in the namespace,
350 * so turn off the 'x' bits to avoid trouble.
351 */
352 vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
353 }
354 break;
355
356 case DTYPE_SOCKET:
357 error = soo_stat((struct socket *)fp->f_data, &stb);
358 if (error == 0) {
359 vattr_null(vap);
360 vap->va_type = VSOCK;
361 vap->va_mode = stb.st_mode;
362 vap->va_nlink = stb.st_nlink;
363 vap->va_uid = stb.st_uid;
364 vap->va_gid = stb.st_gid;
365 vap->va_fsid = stb.st_dev;
366 vap->va_fileid = stb.st_ino;
367 vap->va_size = stb.st_size;
368 vap->va_blocksize = stb.st_blksize;
369 vap->va_atime = stb.st_atimespec;
370 vap->va_mtime = stb.st_mtimespec;
371 vap->va_ctime = stb.st_ctimespec;
372 vap->va_gen = stb.st_gen;
373 vap->va_flags = stb.st_flags;
374 vap->va_rdev = stb.st_rdev;
375 vap->va_bytes = stb.st_blocks * stb.st_blksize;
376 }
377 break;
378
379 default:
380 return (EBADF);
381 break;
382 }
383
384 return (error);
385 }
386
387 int
388 fdesc_getattr(ap)
389 struct vop_getattr_args /* {
390 struct vnode *a_vp;
391 struct vattr *a_vap;
392 struct ucred *a_cred;
393 struct proc *a_p;
394 } */ *ap;
395 {
396 struct vnode *vp = ap->a_vp;
397 struct vattr *vap = ap->a_vap;
398 unsigned fd;
399 int error = 0;
400
401 switch (VTOFDESC(vp)->fd_type) {
402 case Froot:
403 case Fdevfd:
404 case Flink:
405 bzero((caddr_t) vap, sizeof(*vap));
406 vattr_null(vap);
407 vap->va_fileid = VTOFDESC(vp)->fd_ix;
408
409 vap->va_uid = 0;
410 vap->va_gid = 0;
411 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
412 vap->va_blocksize = DEV_BSIZE;
413 vap->va_atime.tv_sec = boottime.tv_sec;
414 vap->va_atime.tv_nsec = 0;
415 vap->va_mtime = vap->va_atime;
416 vap->va_ctime = vap->va_mtime;
417 vap->va_gen = 0;
418 vap->va_flags = 0;
419 vap->va_rdev = 0;
420 vap->va_bytes = 0;
421
422 switch (VTOFDESC(vp)->fd_type) {
423 case Flink:
424 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
425 vap->va_type = VLNK;
426 vap->va_nlink = 1;
427 vap->va_size = strlen(VTOFDESC(vp)->fd_link);
428 break;
429
430 default:
431 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
432 vap->va_type = VDIR;
433 vap->va_nlink = 2;
434 vap->va_size = DEV_BSIZE;
435 break;
436 }
437 break;
438
439 case Fdesc:
440 fd = VTOFDESC(vp)->fd_fd;
441 error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
442 break;
443
444 default:
445 return (EBADF);
446 break;
447 }
448
449 if (error == 0) {
450 vp->v_type = vap->va_type;
451 }
452
453 return (error);
454 }
455
456 int
457 fdesc_setattr(ap)
458 struct vop_setattr_args /* {
459 struct vnode *a_vp;
460 struct vattr *a_vap;
461 struct ucred *a_cred;
462 struct proc *a_p;
463 } */ *ap;
464 {
465 struct file *fp;
466 unsigned fd;
467 int error;
468
469 /*
470 * Can't mess with the root vnode
471 */
472 switch (VTOFDESC(ap->a_vp)->fd_type) {
473 case Fdesc:
474 break;
475
476 default:
477 return (EACCES);
478 }
479
480 fd = VTOFDESC(ap->a_vp)->fd_fd;
481 if (error = fdgetf(ap->a_p, fd, &fp))
482 return (error);
483
484 /*
485 * Can setattr the underlying vnode, but not sockets!
486 */
487 switch (fp->f_type) {
488 case DTYPE_VNODE:
489 error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
490 break;
491
492 case DTYPE_SOCKET:
493 error = 0;
494 break;
495
496 default:
497 kprintf("fp->f_type = %d\n", fp->f_type);
498 error = EBADF;
499 break;
500 }
501
502 return (error);
503 }
504
505 #define UIO_MX 16
506
507 static struct dirtmp {
508 u_long d_fileno;
509 u_short d_reclen;
510 u_short d_namlen;
511 char d_name[8];
512 } rootent[] = {
513 { FD_DEVFD, UIO_MX, 2, "fd" },
514 { FD_STDIN, UIO_MX, 5, "stdin" },
515 { FD_STDOUT, UIO_MX, 6, "stdout" },
516 { FD_STDERR, UIO_MX, 6, "stderr" },
517 { 0 }
518 };
519
520 int
521 fdesc_readdir(ap)
522 struct vop_readdir_args /* {
523 struct vnode *a_vp;
524 struct uio *a_uio;
525 struct ucred *a_cred;
526 int *a_eofflag;
527 u_long *a_cookies;
528 int a_ncookies;
529 } */ *ap;
530 {
531 struct uio *uio = ap->a_uio;
532 struct proc *p = uio->uio_procp;
533 int i, error;
534
535 /*
536 * We don't allow exporting fdesc mounts, and currently local
537 * requests do not need cookies.
538 */
539 if (ap->a_ncookies)
540 return (EINVAL);
541
542 switch (VTOFDESC(ap->a_vp)->fd_type) {
543 case Fdesc:
544 return (ENOTDIR);
545
546 default:
547 break;
548 }
549
550 if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
551 struct dirent d;
552 struct dirent *dp = &d;
553 struct dirtmp *dt;
554 int fd;
555
556 i = uio->uio_offset / UIO_MX;
557 error = 0;
558
559 while (uio->uio_resid > 0) {
560 dt = &rootent[i];
561 if (dt->d_fileno == 0) {
562 /**eofflagp = 1;*/
563 break;
564 }
565 i++;
566
567 switch (dt->d_fileno) {
568 case FD_STDIN:
569 case FD_STDOUT:
570 case FD_STDERR:
571 fd = dt->d_fileno - FD_STDIN;
572 if (fd >= p->p_fd->fd_nfiles)
573 continue;
574 if (*fdfile(p, fd) == NULL &&
575 !(*fdflags(p, fd) &
576 UF_RESERVED))
577 continue;
578 break;
579 }
580 bzero((caddr_t) dp, UIO_MX);
581 dp->d_fileno = dt->d_fileno;
582 dp->d_namlen = dt->d_namlen;
583 dp->d_type = DT_UNKNOWN;
584 dp->d_reclen = dt->d_reclen;
585 bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
586 error = uiomove((caddr_t) dp, UIO_MX, uio);
587 if (error)
588 break;
589 }
590 uio->uio_offset = i * UIO_MX;
591 return (error);
592 }
593
594 i = uio->uio_offset / UIO_MX;
595 error = 0;
596 while (uio->uio_resid > 0) {
597 if (i >= p->p_fd->fd_nfiles)
598 break;
599
600 if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
601 struct dirent d;
602 struct dirent *dp = &d;
603
604 bzero((caddr_t) dp, UIO_MX);
605
606 dp->d_namlen = sprintf(dp->d_name, "%d", i);
607 dp->d_reclen = UIO_MX;
608 dp->d_type = DT_UNKNOWN;
609 dp->d_fileno = i + FD_STDIN;
610 /*
611 * And ship to userland
612 */
613 error = uiomove((caddr_t) dp, UIO_MX, uio);
614 if (error)
615 break;
616 }
617 i++;
618 }
619
620 uio->uio_offset = i * UIO_MX;
621 return (error);
622 }
623
624 int
625 fdesc_readlink(ap)
626 struct vop_readlink_args /* {
627 struct vnode *a_vp;
628 struct uio *a_uio;
629 struct ucred *a_cred;
630 } */ *ap;
631 {
632 struct vnode *vp = ap->a_vp;
633 int error;
634
635 if (vp->v_type != VLNK)
636 return (EPERM);
637
638 if (VTOFDESC(vp)->fd_type == Flink) {
639 char *ln = VTOFDESC(vp)->fd_link;
640 error = uiomove(ln, strlen(ln), ap->a_uio);
641 } else {
642 error = EOPNOTSUPP;
643 }
644
645 return (error);
646 }
647
648 int
649 fdesc_read(ap)
650 struct vop_read_args /* {
651 struct vnode *a_vp;
652 struct uio *a_uio;
653 int a_ioflag;
654 struct ucred *a_cred;
655 } */ *ap;
656 {
657
658 return (EOPNOTSUPP);
659 }
660
661 int
662 fdesc_write(ap)
663 struct vop_write_args /* {
664 struct vnode *a_vp;
665 struct uio *a_uio;
666 int a_ioflag;
667 struct ucred *a_cred;
668 } */ *ap;
669 {
670 return (EOPNOTSUPP);
671 }
672
673 int
674 fdesc_ioctl(ap)
675 struct vop_ioctl_args /* {
676 struct vnode *a_vp;
677 int a_command;
678 caddr_t a_data;
679 int a_fflag;
680 struct ucred *a_cred;
681 struct proc *a_p;
682 } */ *ap;
683 {
684 return (EOPNOTSUPP);
685 }
686
687 int
688 fdesc_select(ap)
689 struct vop_select_args /* {
690 struct vnode *a_vp;
691 int a_which;
692 int a_fflags;
693 struct ucred *a_cred;
694 void *a_wql;
695 struct proc *a_p;
696 } */ *ap;
697 {
698 return (EOPNOTSUPP);
699 }
700
701 int
702 fdesc_inactive(ap)
703 struct vop_inactive_args /* {
704 struct vnode *a_vp;
705 struct proc *a_p;
706 } */ *ap;
707 {
708 struct vnode *vp = ap->a_vp;
709
710 /*
711 * Clear out the v_type field to avoid
712 * nasty things happening in vgone().
713 */
714 VOP_UNLOCK(vp, 0, ap->a_p);
715 vp->v_type = VNON;
716 return (0);
717 }
718
719 int
720 fdesc_reclaim(ap)
721 struct vop_reclaim_args /* {
722 struct vnode *a_vp;
723 } */ *ap;
724 {
725 struct vnode *vp = ap->a_vp;
726 struct fdescnode *fd = VTOFDESC(vp);
727
728 LIST_REMOVE(fd, fd_hash);
729 FREE(vp->v_data, M_TEMP);
730 vp->v_data = 0;
731
732 return (0);
733 }
734
735 /*
736 * Return POSIX pathconf information applicable to special devices.
737 */
738 fdesc_pathconf(ap)
739 struct vop_pathconf_args /* {
740 struct vnode *a_vp;
741 int a_name;
742 int *a_retval;
743 } */ *ap;
744 {
745
746 switch (ap->a_name) {
747 case _PC_LINK_MAX:
748 *ap->a_retval = LINK_MAX;
749 return (0);
750 case _PC_MAX_CANON:
751 *ap->a_retval = MAX_CANON;
752 return (0);
753 case _PC_MAX_INPUT:
754 *ap->a_retval = MAX_INPUT;
755 return (0);
756 case _PC_PIPE_BUF:
757 *ap->a_retval = PIPE_BUF;
758 return (0);
759 case _PC_CHOWN_RESTRICTED:
760 *ap->a_retval = 1;
761 return (0);
762 case _PC_VDISABLE:
763 *ap->a_retval = _POSIX_VDISABLE;
764 return (0);
765 default:
766 return (EINVAL);
767 }
768 /* NOTREACHED */
769 }
770
771 /*
772 * Print out the contents of a /dev/fd vnode.
773 */
774 /* ARGSUSED */
775 int
776 fdesc_print(ap)
777 struct vop_print_args /* {
778 struct vnode *a_vp;
779 } */ *ap;
780 {
781
782 printf("tag VT_NON, fdesc vnode\n");
783 return (0);
784 }
785
786 /*void*/
787 int
788 fdesc_vfree(ap)
789 struct vop_vfree_args /* {
790 struct vnode *a_pvp;
791 ino_t a_ino;
792 int a_mode;
793 } */ *ap;
794 {
795
796 return (0);
797 }
798
799 /*
800 * /dev/fd "should never get here" operation
801 */
802 int
803 fdesc_badop()
804 {
805
806 return (ENOTSUP);
807 /* NOTREACHED */
808 }
809
810 #define VOPFUNC int (*)(void *)
811
812 #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
813 #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
814 #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
815 #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
816 #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
817 #define fdesc_revoke vop_revoke
818 #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
819 #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
820 #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
821 #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
822 #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
823 #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
824 #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
825 #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
826 #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
827 #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
828 #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
829 #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
830 #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
831 #define fdesc_islocked \
832 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
833 #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
834 #define fdesc_blkatoff \
835 ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
836 #define fdesc_valloc ((int(*) __P(( \
837 struct vnode *pvp, \
838 int mode, \
839 struct ucred *cred, \
840 struct vnode **vpp))) eopnotsupp)
841 #define fdesc_truncate \
842 ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
843 #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
844 #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
845 #define fdesc_blktooff ((int (*) __P((struct vop_blktooff_args *)))eopnotsupp)
846 #define fdesc_offtoblk ((int (*) __P((struct vop_offtoblk_args *)))eopnotsupp)
847 #define fdesc_cmap ((int (*) __P((struct vop_cmap_args *)))eopnotsupp)
848
849 int (**fdesc_vnodeop_p)(void *);
850 struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
851 { &vop_default_desc, (VOPFUNC)vn_default_error },
852 { &vop_lookup_desc, (VOPFUNC)fdesc_lookup }, /* lookup */
853 { &vop_create_desc, (VOPFUNC)fdesc_create }, /* create */
854 { &vop_mknod_desc, (VOPFUNC)fdesc_mknod }, /* mknod */
855 { &vop_open_desc, (VOPFUNC)fdesc_open }, /* open */
856 { &vop_close_desc, (VOPFUNC)fdesc_close }, /* close */
857 { &vop_access_desc, (VOPFUNC)fdesc_access }, /* access */
858 { &vop_getattr_desc, (VOPFUNC)fdesc_getattr }, /* getattr */
859 { &vop_setattr_desc, (VOPFUNC)fdesc_setattr }, /* setattr */
860 { &vop_read_desc, (VOPFUNC)fdesc_read }, /* read */
861 { &vop_write_desc, (VOPFUNC)fdesc_write }, /* write */
862 { &vop_ioctl_desc, (VOPFUNC)fdesc_ioctl }, /* ioctl */
863 { &vop_select_desc, (VOPFUNC)fdesc_select }, /* select */
864 { &vop_revoke_desc, (VOPFUNC)fdesc_revoke }, /* revoke */
865 { &vop_mmap_desc, (VOPFUNC)fdesc_mmap }, /* mmap */
866 { &vop_fsync_desc, (VOPFUNC)fdesc_fsync }, /* fsync */
867 { &vop_seek_desc, (VOPFUNC)fdesc_seek }, /* seek */
868 { &vop_remove_desc, (VOPFUNC)fdesc_remove }, /* remove */
869 { &vop_link_desc, (VOPFUNC)fdesc_link }, /* link */
870 { &vop_rename_desc, (VOPFUNC)fdesc_rename }, /* rename */
871 { &vop_mkdir_desc, (VOPFUNC)fdesc_mkdir }, /* mkdir */
872 { &vop_rmdir_desc, (VOPFUNC)fdesc_rmdir }, /* rmdir */
873 { &vop_symlink_desc, (VOPFUNC)fdesc_symlink }, /* symlink */
874 { &vop_readdir_desc, (VOPFUNC)fdesc_readdir }, /* readdir */
875 { &vop_readlink_desc, (VOPFUNC)fdesc_readlink },/* readlink */
876 { &vop_abortop_desc, (VOPFUNC)fdesc_abortop }, /* abortop */
877 { &vop_inactive_desc, (VOPFUNC)fdesc_inactive },/* inactive */
878 { &vop_reclaim_desc, (VOPFUNC)fdesc_reclaim }, /* reclaim */
879 { &vop_lock_desc, (VOPFUNC)fdesc_lock }, /* lock */
880 { &vop_unlock_desc, (VOPFUNC)fdesc_unlock }, /* unlock */
881 { &vop_bmap_desc, (VOPFUNC)fdesc_bmap }, /* bmap */
882 { &vop_strategy_desc, (VOPFUNC)fdesc_strategy }, /* strategy */
883 { &vop_print_desc, (VOPFUNC)fdesc_print }, /* print */
884 { &vop_islocked_desc, (VOPFUNC)fdesc_islocked }, /* islocked */
885 { &vop_pathconf_desc, (VOPFUNC)fdesc_pathconf }, /* pathconf */
886 { &vop_advlock_desc, (VOPFUNC)fdesc_advlock }, /* advlock */
887 { &vop_blkatoff_desc, (VOPFUNC)fdesc_blkatoff }, /* blkatoff */
888 { &vop_valloc_desc, (VOPFUNC)fdesc_valloc }, /* valloc */
889 { &vop_vfree_desc, (VOPFUNC)fdesc_vfree }, /* vfree */
890 { &vop_truncate_desc, (VOPFUNC)fdesc_truncate }, /* truncate */
891 { &vop_update_desc, (VOPFUNC)fdesc_update }, /* update */
892 { &vop_bwrite_desc, (VOPFUNC)fdesc_bwrite }, /* bwrite */
893 { &vop_pagein_desc, (VOPFUNC)err_pagein }, /* pagein */
894 { &vop_pageout_desc, (VOPFUNC)err_pageout }, /* pageout */
895 { &vop_copyfile_desc, (VOPFUNC)err_copyfile }, /* Copyfile */
896 { &vop_blktooff_desc, (VOPFUNC)fdesc_blktooff }, /* blktooff */
897 { &vop_blktooff_desc, (VOPFUNC)fdesc_offtoblk }, /* offtoblk */
898 { &vop_cmap_desc, (VOPFUNC)fdesc_cmap }, /* cmap */
899 { (struct vnodeop_desc*)NULL, (VOPFUNC)NULL }
900 };
901 struct vnodeopv_desc fdesc_vnodeop_opv_desc =
902 { &fdesc_vnodeop_p, fdesc_vnodeop_entries };