|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1992, 1993
25: * The Regents of the University of California. All rights reserved.
26: *
27: * This code is derived from software donated to Berkeley by
28: * Jan-Simon Pendry.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
59: *
60: */
61:
62: /*
63: * /dev/fd Filesystem
64: */
65:
66: #include <sys/param.h>
67: #include <sys/systm.h>
68: #include <sys/types.h>
69: #include <sys/time.h>
70: #include <sys/proc.h>
71: #include <sys/kernel.h> /* boottime */
72: #include <sys/resourcevar.h>
73: #include <sys/filedesc.h>
74: #include <sys/vnode.h>
75: #include <sys/malloc.h>
76: #include <sys/file.h>
77: #include <sys/stat.h>
78: #include <sys/mount.h>
79: #include <sys/namei.h>
80: #include <sys/buf.h>
81: #include <sys/dirent.h>
82: #include <vfs/vfs_support.h>
83: #include <miscfs/fdesc/fdesc.h>
84:
85: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
86:
87: #define FDL_WANT 0x01
88: #define FDL_LOCKED 0x02
89: static int fdcache_lock;
90:
91: dev_t devctty;
92:
93: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
94: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
95: #endif
96:
97: #define NFDCACHE 4
98:
99: #define FD_NHASH(ix) \
100: (&fdhashtbl[(ix) & fdhash])
101: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
102: u_long fdhash;
103:
104: /*
105: * Initialise cache headers
106: */
107: fdesc_init(vfsp)
108: struct vfsconf *vfsp;
109: {
110:
111: devctty = makedev(nchrdev, 0);
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: 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 = VCHR;
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: vap->va_uid = 0;
430: vap->va_gid = 0;
431: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
432: vap->va_blocksize = DEV_BSIZE;
433: vap->va_atime.tv_sec = boottime.tv_sec;
434: vap->va_atime.tv_nsec = 0;
435: vap->va_mtime = vap->va_atime;
436: vap->va_ctime = vap->va_mtime;
437: vap->va_gen = 0;
438: vap->va_flags = 0;
439: vap->va_rdev = 0;
440: vap->va_bytes = 0;
441:
442: switch (VTOFDESC(vp)->fd_type) {
443: case Flink:
444: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
445: vap->va_type = VLNK;
446: vap->va_nlink = 1;
447: vap->va_size = strlen(VTOFDESC(vp)->fd_link);
448: break;
449:
450: case Fctty:
451: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
452: vap->va_type = VCHR;
453: vap->va_nlink = 1;
454: vap->va_size = 0;
455: vap->va_rdev = devctty;
456: break;
457:
458: default:
459: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
460: vap->va_type = VDIR;
461: vap->va_nlink = 2;
462: vap->va_size = DEV_BSIZE;
463: break;
464: }
465: break;
466:
467: case Fdesc:
468: fd = VTOFDESC(vp)->fd_fd;
469: error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
470: break;
471:
472: default:
473: panic("fdesc_getattr");
474: break;
475: }
476:
477: if (error == 0)
478: vp->v_type = vap->va_type;
479:
480: return (error);
481: }
482:
483: int
484: fdesc_setattr(ap)
485: struct vop_setattr_args /* {
486: struct vnode *a_vp;
487: struct vattr *a_vap;
488: struct ucred *a_cred;
489: struct proc *a_p;
490: } */ *ap;
491: {
492: struct file *fp;
493: unsigned fd;
494: int error;
495:
496: /*
497: * Can't mess with the root vnode
498: */
499: switch (VTOFDESC(ap->a_vp)->fd_type) {
500: case Fdesc:
501: break;
502:
503: case Fctty:
504: return (0);
505:
506: default:
507: return (EACCES);
508: }
509:
510: fd = VTOFDESC(ap->a_vp)->fd_fd;
511: if (error = fdgetf(ap->a_p, fd, &fp))
512: return (error);
513:
514: /*
515: * Can setattr the underlying vnode, but not sockets!
516: */
517: switch (fp->f_type) {
518: case DTYPE_VNODE:
519: error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
520: break;
521:
522: case DTYPE_SOCKET:
523: error = 0;
524: break;
525:
526: default:
527: kprintf("fp->f_type = %d\n", fp->f_type);
528: error = EBADF;
529: break;
530: }
531:
532: return (error);
533: }
534:
535: #define UIO_MX 16
536:
537: static struct dirtmp {
538: u_long d_fileno;
539: u_short d_reclen;
540: u_short d_namlen;
541: char d_name[8];
542: } rootent[] = {
543: { FD_DEVFD, UIO_MX, 2, "fd" },
544: { FD_STDIN, UIO_MX, 5, "stdin" },
545: { FD_STDOUT, UIO_MX, 6, "stdout" },
546: { FD_STDERR, UIO_MX, 6, "stderr" },
547: { FD_CTTY, UIO_MX, 3, "tty" },
548: { 0 }
549: };
550:
551: int
552: fdesc_readdir(ap)
553: struct vop_readdir_args /* {
554: struct vnode *a_vp;
555: struct uio *a_uio;
556: struct ucred *a_cred;
557: int *a_eofflag;
558: u_long *a_cookies;
559: int a_ncookies;
560: } */ *ap;
561: {
562: struct uio *uio = ap->a_uio;
563: struct proc *p = uio->uio_procp;
564: int i, error;
565:
566: /*
567: * We don't allow exporting fdesc mounts, and currently local
568: * requests do not need cookies.
569: */
570: if (ap->a_ncookies)
571: panic("fdesc_readdir: not hungry");
572:
573: switch (VTOFDESC(ap->a_vp)->fd_type) {
574: case Fctty:
575: return (0);
576:
577: case Fdesc:
578: return (ENOTDIR);
579:
580: default:
581: break;
582: }
583:
584: if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
585: struct dirent d;
586: struct dirent *dp = &d;
587: struct dirtmp *dt;
588: int fd;
589:
590: i = uio->uio_offset / UIO_MX;
591: error = 0;
592:
593: while (uio->uio_resid > 0) {
594: dt = &rootent[i];
595: if (dt->d_fileno == 0) {
596: /**eofflagp = 1;*/
597: break;
598: }
599: i++;
600:
601: switch (dt->d_fileno) {
602: case FD_CTTY:
603: if (cttyvp(uio->uio_procp) == NULL)
604: continue;
605: break;
606:
607: case FD_STDIN:
608: case FD_STDOUT:
609: case FD_STDERR:
610: fd = dt->d_fileno - FD_STDIN;
611: if (fd >= p->p_fd->fd_nfiles)
612: continue;
613: if (*fdfile(p, fd) == NULL &&
614: !(*fdflags(p, fd) &
615: UF_RESERVED))
616: continue;
617: break;
618: }
619: bzero((caddr_t) dp, UIO_MX);
620: dp->d_fileno = dt->d_fileno;
621: dp->d_namlen = dt->d_namlen;
622: dp->d_type = DT_UNKNOWN;
623: dp->d_reclen = dt->d_reclen;
624: bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
625: error = uiomove((caddr_t) dp, UIO_MX, uio);
626: if (error)
627: break;
628: }
629: uio->uio_offset = i * UIO_MX;
630: return (error);
631: }
632:
633: i = uio->uio_offset / UIO_MX;
634: error = 0;
635: while (uio->uio_resid > 0) {
636: if (i >= p->p_fd->fd_nfiles)
637: break;
638:
639: if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
640: struct dirent d;
641: struct dirent *dp = &d;
642:
643: bzero((caddr_t) dp, UIO_MX);
644:
645: dp->d_namlen = sprintf(dp->d_name, "%d", i);
646: dp->d_reclen = UIO_MX;
647: dp->d_type = DT_UNKNOWN;
648: dp->d_fileno = i + FD_STDIN;
649: /*
650: * And ship to userland
651: */
652: error = uiomove((caddr_t) dp, UIO_MX, uio);
653: if (error)
654: break;
655: }
656: i++;
657: }
658:
659: uio->uio_offset = i * UIO_MX;
660: return (error);
661: }
662:
663: int
664: fdesc_readlink(ap)
665: struct vop_readlink_args /* {
666: struct vnode *a_vp;
667: struct uio *a_uio;
668: struct ucred *a_cred;
669: } */ *ap;
670: {
671: struct vnode *vp = ap->a_vp;
672: int error;
673:
674: if (vp->v_type != VLNK)
675: return (EPERM);
676:
677: if (VTOFDESC(vp)->fd_type == Flink) {
678: char *ln = VTOFDESC(vp)->fd_link;
679: error = uiomove(ln, strlen(ln), ap->a_uio);
680: } else {
681: error = EOPNOTSUPP;
682: }
683:
684: return (error);
685: }
686:
687: int
688: fdesc_read(ap)
689: struct vop_read_args /* {
690: struct vnode *a_vp;
691: struct uio *a_uio;
692: int a_ioflag;
693: struct ucred *a_cred;
694: } */ *ap;
695: {
696: int error = EOPNOTSUPP;
697:
698: switch (VTOFDESC(ap->a_vp)->fd_type) {
699: case Fctty:
700: error = cttyread(devctty, ap->a_uio, ap->a_ioflag);
701: break;
702:
703: default:
704: error = EOPNOTSUPP;
705: break;
706: }
707:
708: return (error);
709: }
710:
711: int
712: fdesc_write(ap)
713: struct vop_write_args /* {
714: struct vnode *a_vp;
715: struct uio *a_uio;
716: int a_ioflag;
717: struct ucred *a_cred;
718: } */ *ap;
719: {
720: int error = EOPNOTSUPP;
721:
722: switch (VTOFDESC(ap->a_vp)->fd_type) {
723: case Fctty:
724: error = cttywrite(devctty, ap->a_uio, ap->a_ioflag);
725: break;
726:
727: default:
728: error = EOPNOTSUPP;
729: break;
730: }
731:
732: return (error);
733: }
734:
735: int
736: fdesc_ioctl(ap)
737: struct vop_ioctl_args /* {
738: struct vnode *a_vp;
739: int a_command;
740: caddr_t a_data;
741: int a_fflag;
742: struct ucred *a_cred;
743: struct proc *a_p;
744: } */ *ap;
745: {
746: int error = EOPNOTSUPP;
747:
748: switch (VTOFDESC(ap->a_vp)->fd_type) {
749: case Fctty:
750: error = cttyioctl(devctty, ap->a_command, ap->a_data,
751: ap->a_fflag, ap->a_p);
752: break;
753:
754: default:
755: error = EOPNOTSUPP;
756: break;
757: }
758:
759: return (error);
760: }
761:
762: int
763: fdesc_select(ap)
764: struct vop_select_args /* {
765: struct vnode *a_vp;
766: int a_which;
767: int a_fflags;
768: struct ucred *a_cred;
769: struct proc *a_p;
770: } */ *ap;
771: {
772: int error = EOPNOTSUPP;
773:
774: switch (VTOFDESC(ap->a_vp)->fd_type) {
775: case Fctty:
776: error = cttyselect(devctty, ap->a_fflags, ap->a_p);
777: break;
778:
779: default:
780: error = EOPNOTSUPP;
781: break;
782: }
783:
784: return (error);
785: }
786:
787: int
788: fdesc_inactive(ap)
789: struct vop_inactive_args /* {
790: struct vnode *a_vp;
791: struct proc *a_p;
792: } */ *ap;
793: {
794: struct vnode *vp = ap->a_vp;
795:
796: /*
797: * Clear out the v_type field to avoid
798: * nasty things happening in vgone().
799: */
800: VOP_UNLOCK(vp, 0, ap->a_p);
801: vp->v_type = VNON;
802: return (0);
803: }
804:
805: int
806: fdesc_reclaim(ap)
807: struct vop_reclaim_args /* {
808: struct vnode *a_vp;
809: } */ *ap;
810: {
811: struct vnode *vp = ap->a_vp;
812: struct fdescnode *fd = VTOFDESC(vp);
813:
814: LIST_REMOVE(fd, fd_hash);
815: FREE(vp->v_data, M_TEMP);
816: vp->v_data = 0;
817:
818: return (0);
819: }
820:
821: /*
822: * Return POSIX pathconf information applicable to special devices.
823: */
824: fdesc_pathconf(ap)
825: struct vop_pathconf_args /* {
826: struct vnode *a_vp;
827: int a_name;
828: int *a_retval;
829: } */ *ap;
830: {
831:
832: switch (ap->a_name) {
833: case _PC_LINK_MAX:
834: *ap->a_retval = LINK_MAX;
835: return (0);
836: case _PC_MAX_CANON:
837: *ap->a_retval = MAX_CANON;
838: return (0);
839: case _PC_MAX_INPUT:
840: *ap->a_retval = MAX_INPUT;
841: return (0);
842: case _PC_PIPE_BUF:
843: *ap->a_retval = PIPE_BUF;
844: return (0);
845: case _PC_CHOWN_RESTRICTED:
846: *ap->a_retval = 1;
847: return (0);
848: case _PC_VDISABLE:
849: *ap->a_retval = _POSIX_VDISABLE;
850: return (0);
851: default:
852: return (EINVAL);
853: }
854: /* NOTREACHED */
855: }
856:
857: /*
858: * Print out the contents of a /dev/fd vnode.
859: */
860: /* ARGSUSED */
861: int
862: fdesc_print(ap)
863: struct vop_print_args /* {
864: struct vnode *a_vp;
865: } */ *ap;
866: {
867:
868: printf("tag VT_NON, fdesc vnode\n");
869: return (0);
870: }
871:
872: /*void*/
873: int
874: fdesc_vfree(ap)
875: struct vop_vfree_args /* {
876: struct vnode *a_pvp;
877: ino_t a_ino;
878: int a_mode;
879: } */ *ap;
880: {
881:
882: return (0);
883: }
884:
885: /*
886: * /dev/fd "should never get here" operation
887: */
888: int
889: fdesc_badop()
890: {
891:
892: panic("fdesc: bad op");
893: /* NOTREACHED */
894: }
895:
896: /* Pagein */
897: fdesc_pagein(ap)
898: struct vop_pagein_args /* {
899: struct vnode *a_vp;
900: struct uio *a_uio;
901: int a_ioflag;
902: struct ucred *a_cred;
903: } */ *ap;
904: {
905: /* pass thru to read */
906: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
907: }
908:
909: /* Pageout */
910: fdesc_pageout(ap)
911: struct vop_pageout_args /* {
912: struct vnode *a_vp;
913: struct uio *a_uio;
914: int a_ioflag;
915: struct ucred *a_cred;
916: } */ *ap;
917: {
918: /* pass thru to write */
919: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
920: }
921:
922: #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
923: #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
924: #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
925: #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
926: #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
927: #define fdesc_revoke vop_revoke
928: #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
929: #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
930: #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
931: #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
932: #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
933: #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
934: #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
935: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
936: #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
937: #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
938: #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
939: #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
940: #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
941: #define fdesc_islocked \
942: ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
943: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
944: #define fdesc_blkatoff \
945: ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
946: #define fdesc_valloc ((int(*) __P(( \
947: struct vnode *pvp, \
948: int mode, \
949: struct ucred *cred, \
950: struct vnode **vpp))) eopnotsupp)
951: #define fdesc_truncate \
952: ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
953: #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
954: #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
955:
956: int (**fdesc_vnodeop_p)();
957: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
958: { &vop_default_desc, vn_default_error },
959: { &vop_lookup_desc, fdesc_lookup }, /* lookup */
960: { &vop_create_desc, fdesc_create }, /* create */
961: { &vop_mknod_desc, fdesc_mknod }, /* mknod */
962: { &vop_open_desc, fdesc_open }, /* open */
963: { &vop_close_desc, fdesc_close }, /* close */
964: { &vop_access_desc, fdesc_access }, /* access */
965: { &vop_getattr_desc, fdesc_getattr }, /* getattr */
966: { &vop_setattr_desc, fdesc_setattr }, /* setattr */
967: { &vop_read_desc, fdesc_read }, /* read */
968: { &vop_write_desc, fdesc_write }, /* write */
969: { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */
970: { &vop_select_desc, fdesc_select }, /* select */
971: { &vop_revoke_desc, fdesc_revoke }, /* revoke */
972: { &vop_mmap_desc, fdesc_mmap }, /* mmap */
973: { &vop_fsync_desc, fdesc_fsync }, /* fsync */
974: { &vop_seek_desc, fdesc_seek }, /* seek */
975: { &vop_remove_desc, fdesc_remove }, /* remove */
976: { &vop_link_desc, fdesc_link }, /* link */
977: { &vop_rename_desc, fdesc_rename }, /* rename */
978: { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */
979: { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */
980: { &vop_symlink_desc, fdesc_symlink }, /* symlink */
981: { &vop_readdir_desc, fdesc_readdir }, /* readdir */
982: { &vop_readlink_desc, fdesc_readlink }, /* readlink */
983: { &vop_abortop_desc, fdesc_abortop }, /* abortop */
984: { &vop_inactive_desc, fdesc_inactive }, /* inactive */
985: { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */
986: { &vop_lock_desc, fdesc_lock }, /* lock */
987: { &vop_unlock_desc, fdesc_unlock }, /* unlock */
988: { &vop_bmap_desc, fdesc_bmap }, /* bmap */
989: { &vop_strategy_desc, fdesc_strategy }, /* strategy */
990: { &vop_print_desc, fdesc_print }, /* print */
991: { &vop_islocked_desc, fdesc_islocked }, /* islocked */
992: { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */
993: { &vop_advlock_desc, fdesc_advlock }, /* advlock */
994: { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */
995: { &vop_valloc_desc, fdesc_valloc }, /* valloc */
996: { &vop_vfree_desc, fdesc_vfree }, /* vfree */
997: { &vop_truncate_desc, fdesc_truncate }, /* truncate */
998: { &vop_update_desc, fdesc_update }, /* update */
999: { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */
1000: { &vop_bwrite_desc, fdesc_pagein }, /* pagein */
1001: { &vop_bwrite_desc, fdesc_pageout }, /* pageout */
1002: { &vop_copyfile_desc, err_copyfile }, /* Copyfile */
1003: { (struct vnodeop_desc*)NULL, (int(*)())NULL }
1004: };
1005: struct vnodeopv_desc fdesc_vnodeop_opv_desc =
1006: { &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.