|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
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 <miscfs/fdesc/fdesc.h>
86:
87: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
88:
89: #define FDL_WANT 0x01
90: #define FDL_LOCKED 0x02
91: static int fdcache_lock;
92:
93: dev_t devctty;
94:
95: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
96: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
97: #endif
98:
99: #define NFDCACHE 4
100:
101: #define FD_NHASH(ix) \
102: (&fdhashtbl[(ix) & fdhash])
103: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
104: u_long fdhash;
105:
106: /*
107: * Initialise cache headers
108: */
109: fdesc_init(vfsp)
110: struct vfsconf *vfsp;
111: {
112:
113: devctty = makedev(nchrdev, 0);
114: fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
115: }
116:
117: int
118: fdesc_allocvp(ftype, ix, mp, vpp)
119: fdntype ftype;
120: int ix;
121: struct mount *mp;
122: struct vnode **vpp;
123: {
124: struct proc *p = current_proc(); /* XXX */
125: struct fdhashhead *fc;
126: struct fdescnode *fd;
127: int error = 0;
128:
129: fc = FD_NHASH(ix);
130: loop:
131: for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
132: if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
133: if (vget(fd->fd_vnode, 0, p))
134: goto loop;
135: *vpp = fd->fd_vnode;
136: return (error);
137: }
138: }
139:
140: /*
141: * otherwise lock the array while we call getnewvnode
142: * since that can block.
143: */
144: if (fdcache_lock & FDL_LOCKED) {
145: fdcache_lock |= FDL_WANT;
146: sleep((caddr_t) &fdcache_lock, PINOD);
147: goto loop;
148: }
149: fdcache_lock |= FDL_LOCKED;
150:
151: error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
152: if (error)
153: goto out;
154: MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
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: case Fctty:
210: error = ENOTDIR;
211: goto bad;
212:
213: case Froot:
214: if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
215: error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
216: if (error)
217: goto bad;
218: *vpp = fvp;
219: fvp->v_type = VDIR;
220: vn_lock(fvp, LK_SHARED | LK_RETRY, p);
221: return (0);
222: }
223:
224: if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
225: struct vnode *ttyvp = cttyvp(p);
226: if (ttyvp == NULL) {
227: error = ENXIO;
228: goto bad;
229: }
230: error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp);
231: if (error)
232: goto bad;
233: *vpp = fvp;
234: fvp->v_type = VFIFO;
235: vn_lock(fvp, LK_SHARED | LK_RETRY, p);
236: return (0);
237: }
238:
239: ln = 0;
240: switch (cnp->cn_namelen) {
241: case 5:
242: if (bcmp(pname, "stdin", 5) == 0) {
243: ln = "fd/0";
244: fd = FD_STDIN;
245: }
246: break;
247: case 6:
248: if (bcmp(pname, "stdout", 6) == 0) {
249: ln = "fd/1";
250: fd = FD_STDOUT;
251: } else
252: if (bcmp(pname, "stderr", 6) == 0) {
253: ln = "fd/2";
254: fd = FD_STDERR;
255: }
256: break;
257: }
258:
259: if (ln) {
260: error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
261: if (error)
262: goto bad;
263: VTOFDESC(fvp)->fd_link = ln;
264: *vpp = fvp;
265: fvp->v_type = VLNK;
266: vn_lock(fvp, LK_SHARED | LK_RETRY, p);
267: return (0);
268: } else {
269: error = ENOENT;
270: goto bad;
271: }
272:
273: /* FALL THROUGH */
274:
275: case Fdevfd:
276: if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
277: if (error = fdesc_root(dvp->v_mount, vpp))
278: goto bad;
279: return (0);
280: }
281:
282: fd = 0;
283: while (*pname >= '0' && *pname <= '9') {
284: fd = 10 * fd + *pname++ - '0';
285: if (fd >= nfiles)
286: break;
287: }
288:
289: if (*pname != '\0') {
290: error = ENOENT;
291: goto bad;
292: }
293:
294: if (fd >= nfiles ||
295: *fdfile(p, fd) == NULL ||
296: (*fdflags(p, fd) & UF_RESERVED)) {
297: error = EBADF;
298: goto bad;
299: }
300:
301: error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
302: if (error)
303: goto bad;
304: VTOFDESC(fvp)->fd_fd = fd;
305: vn_lock(fvp, LK_SHARED | LK_RETRY, p);
306: *vpp = fvp;
307: return (0);
308: }
309:
310: bad:;
311: vn_lock(dvp, LK_SHARED | LK_RETRY, p);
312: *vpp = NULL;
313: return (error);
314: }
315:
316: int
317: fdesc_open(ap)
318: struct vop_open_args /* {
319: struct vnode *a_vp;
320: int a_mode;
321: struct ucred *a_cred;
322: struct proc *a_p;
323: } */ *ap;
324: {
325: struct vnode *vp = ap->a_vp;
326: int error = 0;
327:
328: switch (VTOFDESC(vp)->fd_type) {
329: case Fdesc:
330: /*
331: * XXX Kludge: set p->p_dupfd to contain the value of the
332: * the file descriptor being sought for duplication. The error
333: * return ensures that the vnode for this device will be
334: * released by vn_open. Open will detect this special error and
335: * take the actions in dupfdopen. Other callers of vn_open or
336: * VOP_OPEN will simply report the error.
337: */
338: ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
339: error = ENODEV;
340: break;
341:
342: case Fctty:
343: error = cttyopen(devctty, ap->a_mode, 0, ap->a_p);
344: break;
345: }
346:
347: return (error);
348: }
349:
350: static int
351: fdesc_attr(fd, vap, cred, p)
352: int fd;
353: struct vattr *vap;
354: struct ucred *cred;
355: struct proc *p;
356: {
357: struct file *fp;
358: struct stat stb;
359: int error;
360:
361: if (error = fdgetf(p, fd, &fp))
362: return (error);
363: switch (fp->f_type) {
364: case DTYPE_VNODE:
365: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
366: if (error == 0 && vap->va_type == VDIR) {
367: /*
368: * directories can cause loops in the namespace,
369: * so turn off the 'x' bits to avoid trouble.
370: */
371: vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
372: }
373: break;
374:
375: case DTYPE_SOCKET:
376: error = soo_stat((struct socket *)fp->f_data, &stb);
377: if (error == 0) {
378: vattr_null(vap);
379: vap->va_type = VSOCK;
380: vap->va_mode = stb.st_mode;
381: vap->va_nlink = stb.st_nlink;
382: vap->va_uid = stb.st_uid;
383: vap->va_gid = stb.st_gid;
384: vap->va_fsid = stb.st_dev;
385: vap->va_fileid = stb.st_ino;
386: vap->va_size = stb.st_size;
387: vap->va_blocksize = stb.st_blksize;
388: vap->va_atime = stb.st_atimespec;
389: vap->va_mtime = stb.st_mtimespec;
390: vap->va_ctime = stb.st_ctimespec;
391: vap->va_gen = stb.st_gen;
392: vap->va_flags = stb.st_flags;
393: vap->va_rdev = stb.st_rdev;
394: vap->va_bytes = stb.st_blocks * stb.st_blksize;
395: }
396: break;
397:
398: default:
399: panic("fdesc attr");
400: break;
401: }
402:
403: return (error);
404: }
405:
406: int
407: fdesc_getattr(ap)
408: struct vop_getattr_args /* {
409: struct vnode *a_vp;
410: struct vattr *a_vap;
411: struct ucred *a_cred;
412: struct proc *a_p;
413: } */ *ap;
414: {
415: struct vnode *vp = ap->a_vp;
416: struct vattr *vap = ap->a_vap;
417: unsigned fd;
418: int error = 0;
419:
420: switch (VTOFDESC(vp)->fd_type) {
421: case Froot:
422: case Fdevfd:
423: case Flink:
424: case Fctty:
425: bzero((caddr_t) vap, sizeof(*vap));
426: vattr_null(vap);
427: vap->va_fileid = VTOFDESC(vp)->fd_ix;
428:
429: switch (VTOFDESC(vp)->fd_type) {
430: case Flink:
431: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
432: vap->va_type = VLNK;
433: vap->va_nlink = 1;
434: vap->va_size = strlen(VTOFDESC(vp)->fd_link);
435: break;
436:
437: case Fctty:
438: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
439: vap->va_type = VFIFO;
440: vap->va_nlink = 1;
441: vap->va_size = 0;
442: break;
443:
444: default:
445: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
446: vap->va_type = VDIR;
447: vap->va_nlink = 2;
448: vap->va_size = DEV_BSIZE;
449: break;
450: }
451: vap->va_uid = 0;
452: vap->va_gid = 0;
453: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
454: vap->va_blocksize = DEV_BSIZE;
455: vap->va_atime.tv_sec = boottime.tv_sec;
456: vap->va_atime.tv_nsec = 0;
457: vap->va_mtime = vap->va_atime;
458: vap->va_ctime = vap->va_mtime;
459: vap->va_gen = 0;
460: vap->va_flags = 0;
461: vap->va_rdev = 0;
462: vap->va_bytes = 0;
463: break;
464:
465: case Fdesc:
466: fd = VTOFDESC(vp)->fd_fd;
467: error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
468: break;
469:
470: default:
471: panic("fdesc_getattr");
472: break;
473: }
474:
475: if (error == 0)
476: vp->v_type = vap->va_type;
477:
478: return (error);
479: }
480:
481: int
482: fdesc_setattr(ap)
483: struct vop_setattr_args /* {
484: struct vnode *a_vp;
485: struct vattr *a_vap;
486: struct ucred *a_cred;
487: struct proc *a_p;
488: } */ *ap;
489: {
490: struct file *fp;
491: unsigned fd;
492: int error;
493:
494: /*
495: * Can't mess with the root vnode
496: */
497: switch (VTOFDESC(ap->a_vp)->fd_type) {
498: case Fdesc:
499: break;
500:
501: case Fctty:
502: return (0);
503:
504: default:
505: return (EACCES);
506: }
507:
508: fd = VTOFDESC(ap->a_vp)->fd_fd;
509: if (error = fdgetf(ap->a_p, fd, &fp))
510: return (error);
511:
512: /*
513: * Can setattr the underlying vnode, but not sockets!
514: */
515: switch (fp->f_type) {
516: case DTYPE_VNODE:
517: error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
518: break;
519:
520: case DTYPE_SOCKET:
521: error = 0;
522: break;
523:
524: default:
525: kprintf("fp->f_type = %d\n", fp->f_type);
526: error = EBADF;
527: break;
528: }
529:
530: return (error);
531: }
532:
533: #define UIO_MX 16
534:
535: static struct dirtmp {
536: u_long d_fileno;
537: u_short d_reclen;
538: u_short d_namlen;
539: char d_name[8];
540: } rootent[] = {
541: { FD_DEVFD, UIO_MX, 2, "fd" },
542: { FD_STDIN, UIO_MX, 5, "stdin" },
543: { FD_STDOUT, UIO_MX, 6, "stdout" },
544: { FD_STDERR, UIO_MX, 6, "stderr" },
545: { FD_CTTY, UIO_MX, 3, "tty" },
546: { 0 }
547: };
548:
549: int
550: fdesc_readdir(ap)
551: struct vop_readdir_args /* {
552: struct vnode *a_vp;
553: struct uio *a_uio;
554: struct ucred *a_cred;
555: int *a_eofflag;
556: u_long *a_cookies;
557: int a_ncookies;
558: } */ *ap;
559: {
560: struct uio *uio = ap->a_uio;
561: struct proc *p = uio->uio_procp;
562: int i, error;
563:
564: /*
565: * We don't allow exporting fdesc mounts, and currently local
566: * requests do not need cookies.
567: */
568: if (ap->a_ncookies)
569: panic("fdesc_readdir: not hungry");
570:
571: switch (VTOFDESC(ap->a_vp)->fd_type) {
572: case Fctty:
573: return (0);
574:
575: case Fdesc:
576: return (ENOTDIR);
577:
578: default:
579: break;
580: }
581:
582: if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
583: struct dirent d;
584: struct dirent *dp = &d;
585: struct dirtmp *dt;
586: int fd;
587:
588: i = uio->uio_offset / UIO_MX;
589: error = 0;
590:
591: while (uio->uio_resid > 0) {
592: dt = &rootent[i];
593: if (dt->d_fileno == 0) {
594: /**eofflagp = 1;*/
595: break;
596: }
597: i++;
598:
599: switch (dt->d_fileno) {
600: case FD_CTTY:
601: if (cttyvp(uio->uio_procp) == NULL)
602: continue;
603: break;
604:
605: case FD_STDIN:
606: case FD_STDOUT:
607: case FD_STDERR:
608: fd = dt->d_fileno - FD_STDIN;
609: if (fd >= p->p_fd->fd_nfiles)
610: continue;
611: if (*fdfile(p, fd) == NULL &&
612: !(*fdflags(p, fd) &
613: UF_RESERVED))
614: continue;
615: break;
616: }
617: bzero((caddr_t) dp, UIO_MX);
618: dp->d_fileno = dt->d_fileno;
619: dp->d_namlen = dt->d_namlen;
620: dp->d_type = DT_UNKNOWN;
621: dp->d_reclen = dt->d_reclen;
622: bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
623: error = uiomove((caddr_t) dp, UIO_MX, uio);
624: if (error)
625: break;
626: }
627: uio->uio_offset = i * UIO_MX;
628: return (error);
629: }
630:
631: i = uio->uio_offset / UIO_MX;
632: error = 0;
633: while (uio->uio_resid > 0) {
634: if (i >= p->p_fd->fd_nfiles)
635: break;
636:
637: if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
638: struct dirent d;
639: struct dirent *dp = &d;
640:
641: bzero((caddr_t) dp, UIO_MX);
642:
643: dp->d_namlen = sprintf(dp->d_name, "%d", i);
644: dp->d_reclen = UIO_MX;
645: dp->d_type = DT_UNKNOWN;
646: dp->d_fileno = i + FD_STDIN;
647: /*
648: * And ship to userland
649: */
650: error = uiomove((caddr_t) dp, UIO_MX, uio);
651: if (error)
652: break;
653: }
654: i++;
655: }
656:
657: uio->uio_offset = i * UIO_MX;
658: return (error);
659: }
660:
661: int
662: fdesc_readlink(ap)
663: struct vop_readlink_args /* {
664: struct vnode *a_vp;
665: struct uio *a_uio;
666: struct ucred *a_cred;
667: } */ *ap;
668: {
669: struct vnode *vp = ap->a_vp;
670: int error;
671:
672: if (vp->v_type != VLNK)
673: return (EPERM);
674:
675: if (VTOFDESC(vp)->fd_type == Flink) {
676: char *ln = VTOFDESC(vp)->fd_link;
677: error = uiomove(ln, strlen(ln), ap->a_uio);
678: } else {
679: error = EOPNOTSUPP;
680: }
681:
682: return (error);
683: }
684:
685: int
686: fdesc_read(ap)
687: struct vop_read_args /* {
688: struct vnode *a_vp;
689: struct uio *a_uio;
690: int a_ioflag;
691: struct ucred *a_cred;
692: } */ *ap;
693: {
694: int error = EOPNOTSUPP;
695:
696: switch (VTOFDESC(ap->a_vp)->fd_type) {
697: case Fctty:
698: error = cttyread(devctty, ap->a_uio, ap->a_ioflag);
699: break;
700:
701: default:
702: error = EOPNOTSUPP;
703: break;
704: }
705:
706: return (error);
707: }
708:
709: int
710: fdesc_write(ap)
711: struct vop_write_args /* {
712: struct vnode *a_vp;
713: struct uio *a_uio;
714: int a_ioflag;
715: struct ucred *a_cred;
716: } */ *ap;
717: {
718: int error = EOPNOTSUPP;
719:
720: switch (VTOFDESC(ap->a_vp)->fd_type) {
721: case Fctty:
722: error = cttywrite(devctty, ap->a_uio, ap->a_ioflag);
723: break;
724:
725: default:
726: error = EOPNOTSUPP;
727: break;
728: }
729:
730: return (error);
731: }
732:
733: int
734: fdesc_ioctl(ap)
735: struct vop_ioctl_args /* {
736: struct vnode *a_vp;
737: int a_command;
738: caddr_t a_data;
739: int a_fflag;
740: struct ucred *a_cred;
741: struct proc *a_p;
742: } */ *ap;
743: {
744: int error = EOPNOTSUPP;
745:
746: switch (VTOFDESC(ap->a_vp)->fd_type) {
747: case Fctty:
748: error = cttyioctl(devctty, ap->a_command, ap->a_data,
749: ap->a_fflag, ap->a_p);
750: break;
751:
752: default:
753: error = EOPNOTSUPP;
754: break;
755: }
756:
757: return (error);
758: }
759:
760: int
761: fdesc_select(ap)
762: struct vop_select_args /* {
763: struct vnode *a_vp;
764: int a_which;
765: int a_fflags;
766: struct ucred *a_cred;
767: struct proc *a_p;
768: } */ *ap;
769: {
770: int error = EOPNOTSUPP;
771:
772: switch (VTOFDESC(ap->a_vp)->fd_type) {
773: case Fctty:
774: error = cttyselect(devctty, ap->a_fflags, ap->a_p);
775: break;
776:
777: default:
778: error = EOPNOTSUPP;
779: break;
780: }
781:
782: return (error);
783: }
784:
785: int
786: fdesc_inactive(ap)
787: struct vop_inactive_args /* {
788: struct vnode *a_vp;
789: struct proc *a_p;
790: } */ *ap;
791: {
792: struct vnode *vp = ap->a_vp;
793:
794: /*
795: * Clear out the v_type field to avoid
796: * nasty things happening in vgone().
797: */
798: VOP_UNLOCK(vp, 0, ap->a_p);
799: vp->v_type = VNON;
800: return (0);
801: }
802:
803: int
804: fdesc_reclaim(ap)
805: struct vop_reclaim_args /* {
806: struct vnode *a_vp;
807: } */ *ap;
808: {
809: struct vnode *vp = ap->a_vp;
810: struct fdescnode *fd = VTOFDESC(vp);
811:
812: LIST_REMOVE(fd, fd_hash);
813: FREE(vp->v_data, M_TEMP);
814: vp->v_data = 0;
815:
816: return (0);
817: }
818:
819: /*
820: * Return POSIX pathconf information applicable to special devices.
821: */
822: fdesc_pathconf(ap)
823: struct vop_pathconf_args /* {
824: struct vnode *a_vp;
825: int a_name;
826: int *a_retval;
827: } */ *ap;
828: {
829:
830: switch (ap->a_name) {
831: case _PC_LINK_MAX:
832: *ap->a_retval = LINK_MAX;
833: return (0);
834: case _PC_MAX_CANON:
835: *ap->a_retval = MAX_CANON;
836: return (0);
837: case _PC_MAX_INPUT:
838: *ap->a_retval = MAX_INPUT;
839: return (0);
840: case _PC_PIPE_BUF:
841: *ap->a_retval = PIPE_BUF;
842: return (0);
843: case _PC_CHOWN_RESTRICTED:
844: *ap->a_retval = 1;
845: return (0);
846: case _PC_VDISABLE:
847: *ap->a_retval = _POSIX_VDISABLE;
848: return (0);
849: default:
850: return (EINVAL);
851: }
852: /* NOTREACHED */
853: }
854:
855: /*
856: * Print out the contents of a /dev/fd vnode.
857: */
858: /* ARGSUSED */
859: int
860: fdesc_print(ap)
861: struct vop_print_args /* {
862: struct vnode *a_vp;
863: } */ *ap;
864: {
865:
866: printf("tag VT_NON, fdesc vnode\n");
867: return (0);
868: }
869:
870: /*void*/
871: int
872: fdesc_vfree(ap)
873: struct vop_vfree_args /* {
874: struct vnode *a_pvp;
875: ino_t a_ino;
876: int a_mode;
877: } */ *ap;
878: {
879:
880: return (0);
881: }
882:
883: /*
884: * /dev/fd "should never get here" operation
885: */
886: int
887: fdesc_badop()
888: {
889:
890: panic("fdesc: bad op");
891: /* NOTREACHED */
892: }
893:
894: /* Pagein */
895: fdesc_pagein(ap)
896: struct vop_pagein_args /* {
897: struct vnode *a_vp;
898: struct uio *a_uio;
899: int a_ioflag;
900: struct ucred *a_cred;
901: } */ *ap;
902: {
903: /* pass thru to read */
904: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
905: }
906:
907: /* Pageout */
908: fdesc_pageout(ap)
909: struct vop_pageout_args /* {
910: struct vnode *a_vp;
911: struct uio *a_uio;
912: int a_ioflag;
913: struct ucred *a_cred;
914: } */ *ap;
915: {
916: /* pass thru to write */
917: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
918: }
919:
920: #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
921: #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
922: #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
923: #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
924: #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
925: #define fdesc_revoke vop_revoke
926: #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
927: #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
928: #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
929: #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
930: #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
931: #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
932: #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
933: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
934: #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
935: #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
936: #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
937: #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
938: #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
939: #define fdesc_islocked \
940: ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
941: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
942: #define fdesc_blkatoff \
943: ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
944: #define fdesc_valloc ((int(*) __P(( \
945: struct vnode *pvp, \
946: int mode, \
947: struct ucred *cred, \
948: struct vnode **vpp))) eopnotsupp)
949: #define fdesc_truncate \
950: ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
951: #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
952: #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
953:
954: int (**fdesc_vnodeop_p)();
955: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
956: { &vop_default_desc, vn_default_error },
957: { &vop_lookup_desc, fdesc_lookup }, /* lookup */
958: { &vop_create_desc, fdesc_create }, /* create */
959: { &vop_mknod_desc, fdesc_mknod }, /* mknod */
960: { &vop_open_desc, fdesc_open }, /* open */
961: { &vop_close_desc, fdesc_close }, /* close */
962: { &vop_access_desc, fdesc_access }, /* access */
963: { &vop_getattr_desc, fdesc_getattr }, /* getattr */
964: { &vop_setattr_desc, fdesc_setattr }, /* setattr */
965: { &vop_read_desc, fdesc_read }, /* read */
966: { &vop_write_desc, fdesc_write }, /* write */
967: { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */
968: { &vop_select_desc, fdesc_select }, /* select */
969: { &vop_revoke_desc, fdesc_revoke }, /* revoke */
970: { &vop_mmap_desc, fdesc_mmap }, /* mmap */
971: { &vop_fsync_desc, fdesc_fsync }, /* fsync */
972: { &vop_seek_desc, fdesc_seek }, /* seek */
973: { &vop_remove_desc, fdesc_remove }, /* remove */
974: { &vop_link_desc, fdesc_link }, /* link */
975: { &vop_rename_desc, fdesc_rename }, /* rename */
976: { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */
977: { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */
978: { &vop_symlink_desc, fdesc_symlink }, /* symlink */
979: { &vop_readdir_desc, fdesc_readdir }, /* readdir */
980: { &vop_readlink_desc, fdesc_readlink }, /* readlink */
981: { &vop_abortop_desc, fdesc_abortop }, /* abortop */
982: { &vop_inactive_desc, fdesc_inactive }, /* inactive */
983: { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */
984: { &vop_lock_desc, fdesc_lock }, /* lock */
985: { &vop_unlock_desc, fdesc_unlock }, /* unlock */
986: { &vop_bmap_desc, fdesc_bmap }, /* bmap */
987: { &vop_strategy_desc, fdesc_strategy }, /* strategy */
988: { &vop_print_desc, fdesc_print }, /* print */
989: { &vop_islocked_desc, fdesc_islocked }, /* islocked */
990: { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */
991: { &vop_advlock_desc, fdesc_advlock }, /* advlock */
992: { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */
993: { &vop_valloc_desc, fdesc_valloc }, /* valloc */
994: { &vop_vfree_desc, fdesc_vfree }, /* vfree */
995: { &vop_truncate_desc, fdesc_truncate }, /* truncate */
996: { &vop_update_desc, fdesc_update }, /* update */
997: { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */
998: { &vop_bwrite_desc, fdesc_pagein }, /* pagein */
999: { &vop_bwrite_desc, fdesc_pageout }, /* pageout */
1000: { (struct vnodeop_desc*)NULL, (int(*)())NULL }
1001: };
1002: struct vnodeopv_desc fdesc_vnodeop_opv_desc =
1003: { &fdesc_vnodeop_p, fdesc_vnodeop_entries };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.