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