Annotation of src/sys/miscfs/fdesc/fdesc_vnops.c, Revision 1.9
1.1 cgd 1: /*
1.8 cgd 2: * Copyright (c) 1992 The Regents of the University of California
3: * Copyright (c) 1990, 1992, 1993 Jan-Simon Pendry
1.1 cgd 4: * All rights reserved.
5: *
1.8 cgd 6: * This code is derived from software donated to Berkeley by
1.1 cgd 7: * Jan-Simon Pendry.
8: *
1.2 cgd 9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
1.8 cgd 19: * This product includes software developed by the University of
20: * California, Berkeley and its contributors.
1.2 cgd 21: * 4. Neither the name of the University nor the names of its contributors
22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
1.1 cgd 24: *
1.2 cgd 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
1.1 cgd 36: *
1.8 cgd 37: * From:
38: * Id: fdesc_vnops.c,v 4.1 1993/12/17 10:47:45 jsp Rel
39: *
1.9 ! cgd 40: * $Id: fdesc_vnops.c,v 1.8 1994/01/05 09:01:02 cgd Exp $
1.1 cgd 41: */
42:
43: /*
44: * /dev/fd Filesystem
45: */
46:
1.8 cgd 47: #include <sys/param.h>
48: #include <sys/systm.h>
49: #include <sys/types.h>
50: #include <sys/time.h>
51: #include <sys/proc.h>
52: #include <sys/kernel.h> /* boottime */
53: #include <sys/resourcevar.h>
54: #include <sys/filedesc.h>
55: #include <sys/vnode.h>
56: #include <sys/file.h>
57: #include <sys/stat.h>
58: #include <sys/mount.h>
59: #include <sys/namei.h>
60: #include <sys/buf.h>
61: #include <miscfs/fdesc/fdesc.h>
62:
63: #include <ufs/dir.h> /* For readdir() XXX */
64:
65: #define cttyvp(p) ((p)->p_flag&SCTTY ? (p)->p_session->s_ttyvp : NULL)
66:
67: #define FDL_WANT 0x01
68: #define FDL_LOCKED 0x02
69: static int fdescvplock;
70: static struct vnode *fdescvp[FD_MAX];
71:
72: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
73: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
74: #endif
75:
76: fdesc_allocvp(ftype, ix, mp, vpp)
77: fdntype ftype;
78: int ix;
79: struct mount *mp;
80: struct vnode **vpp;
81: {
82: struct vnode **nvpp = 0;
83: int error = 0;
84:
85: loop:
86: /* get stashed copy of the vnode */
87: if (ix >= 0 && ix < FD_MAX) {
88: nvpp = &fdescvp[ix];
89: if (*nvpp) {
90: if (vget(*nvpp))
91: goto loop;
92: VOP_UNLOCK(*nvpp);
93: *vpp = *nvpp;
94: return (error);
95: }
96: }
97:
98: /*
99: * otherwise lock the array while we call getnewvnode
100: * since that can block.
101: */
102: if (fdescvplock & FDL_LOCKED) {
103: fdescvplock |= FDL_WANT;
104: sleep((caddr_t) &fdescvplock, PINOD);
105: goto loop;
106: }
107: fdescvplock |= FDL_LOCKED;
1.1 cgd 108:
1.9 ! cgd 109: error = getnewvnode(VT_FDESC, mp, &fdesc_vnodeops, vpp);
1.8 cgd 110: if (error)
111: goto out;
112: if (nvpp)
113: *nvpp = *vpp;
114: VTOFDESC(*vpp)->fd_type = ftype;
115: VTOFDESC(*vpp)->fd_fd = -1;
116: VTOFDESC(*vpp)->fd_link = 0;
117: VTOFDESC(*vpp)->fd_ix = ix;
118:
119: out:;
120: fdescvplock &= ~FDL_LOCKED;
121:
122: if (fdescvplock & FDL_WANT) {
123: fdescvplock &= ~FDL_WANT;
124: wakeup((caddr_t) &fdescvplock);
125: }
126:
127: return (error);
128: }
1.1 cgd 129:
130: /*
131: * vp is the current namei directory
132: * ndp is the name to locate in that directory...
133: */
134: fdesc_lookup(dvp, ndp, p)
135: struct vnode *dvp;
136: struct nameidata *ndp;
137: struct proc *p;
138: {
139: char *pname = ndp->ni_ptr;
140: int nfiles = p->p_fd->fd_nfiles;
141: unsigned fd;
142: int error;
143: struct vnode *fvp;
1.8 cgd 144: char *ln;
1.1 cgd 145:
146: #ifdef FDESC_DIAGNOSTIC
147: printf("fdesc_lookup(%s)\n", pname);
148: #endif
149: if (ndp->ni_namelen == 1 && *pname == '.') {
150: ndp->ni_dvp = dvp;
151: ndp->ni_vp = dvp;
152: VREF(dvp);
1.8 cgd 153: VOP_LOCK(dvp);
1.1 cgd 154: return (0);
155: }
156:
1.8 cgd 157: switch (VTOFDESC(dvp)->fd_type) {
158: default:
159: case Flink:
160: case Fdesc:
161: case Fctty:
162: error = ENOTDIR;
163: goto bad;
164:
165: case Froot:
166: if (ndp->ni_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
167: error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
168: if (error)
169: goto bad;
170: ndp->ni_dvp = dvp;
171: ndp->ni_vp = fvp;
172: fvp->v_type = VDIR;
173: VOP_LOCK(fvp);
174: #ifdef FDESC_DIAGNOSTIC
175: printf("fdesc_lookup: newvp = %x\n", fvp);
176: #endif
177: return (0);
178: }
179:
180: if (ndp->ni_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
181: struct vnode *ttyvp = cttyvp(p);
182: if (ttyvp == NULL) {
183: error = ENXIO;
184: goto bad;
185: }
186: error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp);
187: if (error)
188: goto bad;
189: ndp->ni_dvp = dvp;
190: ndp->ni_vp = fvp;
191: fvp->v_type = VFIFO;
192: VOP_LOCK(fvp);
193: #ifdef FDESC_DIAGNOSTIC
194: printf("fdesc_lookup: ttyvp = %x\n", fvp);
195: #endif
196: return (0);
197: }
198:
199: ln = 0;
200: switch (ndp->ni_namelen) {
201: case 5:
202: if (bcmp(pname, "stdin", 5) == 0) {
203: ln = "fd/0";
204: fd = FD_STDIN;
205: }
1.1 cgd 206: break;
1.8 cgd 207: case 6:
208: if (bcmp(pname, "stdout", 6) == 0) {
209: ln = "fd/1";
210: fd = FD_STDOUT;
211: } else
212: if (bcmp(pname, "stderr", 6) == 0) {
213: ln = "fd/2";
214: fd = FD_STDERR;
215: }
216: break;
217: }
218:
219: if (ln) {
220: #ifdef FDESC_DIAGNOSTIC
221: printf("fdesc_lookup: link -> %s\n", ln);
222: #endif
223: error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
224: if (error)
225: goto bad;
226: VTOFDESC(fvp)->fd_link = ln;
227: ndp->ni_dvp = dvp;
228: ndp->ni_vp = fvp;
229: fvp->v_type = VLNK;
230: VOP_LOCK(fvp);
231: #ifdef FDESC_DIAGNOSTIC
232: printf("fdesc_lookup: newvp = %x\n", fvp);
233: #endif
234: return (0);
235: } else {
236: error = ENOENT;
237: goto bad;
238: }
239:
240: /* fall through */
241:
242: case Fdevfd:
243: if (ndp->ni_namelen == 2 && bcmp(pname, "..", 2) == 0) {
244: ndp->ni_dvp = dvp;
245: error = fdesc_root(dvp->v_mount, &ndp->ni_vp);
246: return (error);
247: }
248:
249: fd = 0;
250: while (*pname >= '0' && *pname <= '9') {
251: fd = 10 * fd + *pname++ - '0';
252: if (fd >= nfiles)
253: break;
254: }
1.1 cgd 255:
256: #ifdef FDESC_DIAGNOSTIC
1.8 cgd 257: printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname);
1.1 cgd 258: #endif
1.8 cgd 259: if (*pname == '/') {
260: error = ENOTDIR;
261: goto bad;
262: }
1.1 cgd 263:
1.8 cgd 264: if (*pname != '\0') {
265: error = ENOENT;
266: goto bad;
267: }
1.1 cgd 268:
1.8 cgd 269: devfd:
270: if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) {
271: error = EBADF;
272: goto bad;
273: }
1.1 cgd 274:
275: #ifdef FDESC_DIAGNOSTIC
1.8 cgd 276: printf("fdesc_lookup: allocate new vnode\n");
1.1 cgd 277: #endif
1.8 cgd 278: error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
279: if (error)
280: goto bad;
281: VTOFDESC(fvp)->fd_fd = fd;
282: ndp->ni_dvp = dvp;
283: ndp->ni_vp = fvp;
1.1 cgd 284: #ifdef FDESC_DIAGNOSTIC
1.8 cgd 285: printf("fdesc_lookup: newvp = %x\n", fvp);
1.1 cgd 286: #endif
1.8 cgd 287: return (0);
288: }
1.1 cgd 289:
290: bad:;
291: ndp->ni_dvp = dvp;
292: ndp->ni_vp = NULL;
293: #ifdef FDESC_DIAGNOSTIC
294: printf("fdesc_lookup: error = %d\n", error);
295: #endif
296: return (error);
297: }
298:
299: fdesc_open(vp, mode, cred, p)
300: struct vnode *vp;
301: int mode;
302: struct ucred *cred;
303: struct proc *p;
304: {
1.8 cgd 305: int error = 0;
306:
307: switch (VTOFDESC(vp)->fd_type) {
308: case Fdesc:
309: /*
310: * XXX Kludge: set p->p_dupfd to contain the value of the
311: * the file descriptor being sought for duplication. The error
312: * return ensures that the vnode for this device will be
313: * released by vn_open. Open will detect this special error and
314: * take the actions in dupfdopen. Other callers of vn_open or
315: * VOP_OPEN will simply report the error.
316: */
317: p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
318: error = ENODEV;
319: break;
1.1 cgd 320:
1.8 cgd 321: case Fctty:
322: error = cttyopen(devctty, mode, 0, p);
323: break;
324: }
1.1 cgd 325:
1.8 cgd 326: return (error);
1.1 cgd 327: }
328:
329: static int
330: fdesc_attr(fd, vap, cred, p)
331: int fd;
332: struct vattr *vap;
333: struct ucred *cred;
334: struct proc *p;
335: {
336: struct filedesc *fdp = p->p_fd;
337: struct file *fp;
1.8 cgd 338: struct stat stb;
1.1 cgd 339: int error;
340:
341: #ifdef FDESC_DIAGNOSTIC
342: printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
343: #endif
344: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
345: #ifdef FDESC_DIAGNOSTIC
346: printf("fdesc_attr: fp = %x (EBADF)\n", fp);
347: #endif
348: return (EBADF);
349: }
350:
351: /*
352: * Can stat the underlying vnode, but not sockets because
353: * they don't use struct vattrs. Well, we could convert from
354: * a struct stat back to a struct vattr, later...
355: */
356: switch (fp->f_type) {
357: case DTYPE_VNODE:
358: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
1.8 cgd 359: if (error == 0 && vap->va_type == VDIR) {
360: /*
361: * don't allow directories to show up because
362: * that causes loops in the namespace.
363: */
364: vap->va_type = VFIFO;
365: }
1.1 cgd 366: break;
367:
368: case DTYPE_SOCKET:
1.8 cgd 369: error = soo_stat((struct socket *)fp->f_data, &stb);
370: if (error == 0) {
371: vattr_null(vap);
372: vap->va_type = VSOCK;
373: vap->va_mode = stb.st_mode;
374: vap->va_nlink = stb.st_nlink;
375: vap->va_uid = stb.st_uid;
376: vap->va_gid = stb.st_gid;
377: vap->va_fsid = stb.st_dev;
378: vap->va_fileid = stb.st_ino;
379: vap->va_size = stb.st_size;
380: vap->va_blocksize = stb.st_blksize;
381: vap->va_atime.tv_sec = stb.st_atime;
382: vap->va_atime.tv_usec = 0;
383: vap->va_mtime.tv_sec = stb.st_mtime;
384: vap->va_mtime.tv_usec = 0;
385: vap->va_ctime.tv_sec = stb.st_ctime;
386: vap->va_ctime.tv_usec = 0;
387: vap->va_gen = stb.st_gen;
388: vap->va_flags = stb.st_flags;
389: vap->va_rdev = stb.st_rdev;
390: vap->va_bytes = stb.st_blocks * stb.st_blksize;
391: }
1.1 cgd 392: break;
393:
394: default:
395: panic("fdesc attr");
396: break;
397: }
398:
399: #ifdef FDESC_DIAGNOSTIC
400: printf("fdesc_attr: returns error %d\n", error);
401: #endif
402: return (error);
403: }
404:
405: fdesc_getattr(vp, vap, cred, p)
406: struct vnode *vp;
407: struct vattr *vap;
408: struct ucred *cred;
409: struct proc *p;
410: {
411: unsigned fd;
1.8 cgd 412: int error = 0;
1.1 cgd 413:
414: #ifdef FDESC_DIAGNOSTIC
1.8 cgd 415: printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type);
1.1 cgd 416: #endif
1.8 cgd 417:
418: switch (VTOFDESC(vp)->fd_type) {
419: case Froot:
420: case Fdevfd:
421: case Flink:
422: case Fctty:
1.1 cgd 423: bzero((caddr_t) vap, sizeof(*vap));
424: vattr_null(vap);
1.8 cgd 425: vap->va_fileid = VTOFDESC(vp)->fd_ix;
426:
427: switch (VTOFDESC(vp)->fd_type) {
428: case Flink:
429: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
430: vap->va_type = VLNK;
431: vap->va_nlink = 1;
432: /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */
433: vap->va_size = strlen(VTOFDESC(vp)->fd_link);
434: break;
435:
436: case Fctty:
437: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
438: vap->va_type = VFIFO;
439: vap->va_nlink = 1;
440: /* vap->va_qsize = 0; */
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_qsize = 0; */
449: vap->va_size = DEV_BSIZE;
450: break;
451: }
1.1 cgd 452: vap->va_uid = 0;
453: vap->va_gid = 0;
454: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
455: vap->va_blocksize = DEV_BSIZE;
1.8 cgd 456: vap->va_atime.tv_sec = boottime.tv_sec;
457: vap->va_atime.tv_usec = 0;
1.1 cgd 458: vap->va_mtime = vap->va_atime;
459: vap->va_ctime = vap->va_ctime;
460: vap->va_gen = 0;
461: vap->va_flags = 0;
462: vap->va_rdev = 0;
463: /* vap->va_qbytes = 0; */
464: vap->va_bytes = 0;
1.8 cgd 465: break;
466:
467: case Fdesc:
468: #ifdef FDESC_DIAGNOSTIC
469: printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd);
470: #endif
471: fd = VTOFDESC(vp)->fd_fd;
472: error = fdesc_attr(fd, vap, cred, p);
473: break;
474:
475: default:
476: panic("fdesc_getattr");
477: break;
1.1 cgd 478: }
479:
480: if (error == 0)
481: vp->v_type = vap->va_type;
1.8 cgd 482:
483: #ifdef FDESC_DIAGNOSTIC
484: printf("fdesc_getattr: stat returns 0\n");
485: #endif
1.1 cgd 486: return (error);
487: }
488:
489: fdesc_setattr(vp, vap, cred, p)
490: struct vnode *vp;
491: struct vattr *vap;
492: struct ucred *cred;
493: struct proc *p;
494: {
495: struct filedesc *fdp = p->p_fd;
496: struct file *fp;
497: unsigned fd;
498: int error;
499:
500: /*
501: * Can't mess with the root vnode
502: */
1.8 cgd 503: switch (VTOFDESC(vp)->fd_type) {
504: case Fdesc:
505: break;
506:
507: case Fctty:
508: return (0);
509:
510: default:
1.1 cgd 511: return (EACCES);
1.8 cgd 512: }
1.1 cgd 513:
1.8 cgd 514: fd = VTOFDESC(vp)->fd_fd;
1.1 cgd 515: #ifdef FDESC_DIAGNOSTIC
516: printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
517: #endif
518: if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
519: #ifdef FDESC_DIAGNOSTIC
520: printf("fdesc_setattr: fp = %x (EBADF)\n", fp);
521: #endif
522: return (EBADF);
523: }
524:
525: /*
526: * Can setattr the underlying vnode, but not sockets!
527: */
528: switch (fp->f_type) {
529: case DTYPE_VNODE:
530: error = VOP_SETATTR((struct vnode *) fp->f_data, vap, cred, p);
531: break;
532:
533: case DTYPE_SOCKET:
1.8 cgd 534: error = 0; /* EOPNOTSUPP? */
1.1 cgd 535: break;
536:
537: default:
538: panic("fdesc setattr");
539: break;
540: }
541:
542: #ifdef FDESC_DIAGNOSTIC
543: printf("fdesc_setattr: returns error %d\n", error);
544: #endif
545: return (error);
546: }
547:
1.8 cgd 548: #define UIO_MX 16
549:
550: static struct dirtmp {
551: u_long d_ino;
552: u_short d_reclen;
553: u_short d_namlen;
554: char d_name[8];
555: } rootent[] = {
556: { FD_DEVFD, UIO_MX, 2, "fd" },
557: { FD_STDIN, UIO_MX, 5, "stdin" },
558: { FD_STDOUT, UIO_MX, 6, "stdout" },
559: { FD_STDERR, UIO_MX, 6, "stderr" },
560: { FD_CTTY, UIO_MX, 3, "tty" },
561: { 0 }
562: };
563:
1.6 ws 564: fdesc_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
1.1 cgd 565: struct vnode *vp;
566: struct uio *uio;
567: struct ucred *cred;
568: int *eofflagp;
1.6 ws 569: u_int *cookies;
570: int ncookies;
1.1 cgd 571: {
572: struct filedesc *fdp;
1.8 cgd 573: int i;
1.1 cgd 574: int error;
575:
1.8 cgd 576: switch (VTOFDESC(vp)->fd_type) {
577: case Fctty:
578: return (0);
579:
580: case Fdesc:
581: return (ENOTDIR);
582:
583: default:
584: break;
585: }
1.1 cgd 586:
587: fdp = uio->uio_procp->p_fd;
1.8 cgd 588:
589: if (VTOFDESC(vp)->fd_type == Froot) {
1.3 cgd 590: struct direct d;
591: struct direct *dp = &d;
1.8 cgd 592: struct dirtmp *dt;
593:
594: i = uio->uio_offset / UIO_MX;
595: error = 0;
1.3 cgd 596:
1.8 cgd 597: while (uio->uio_resid > 0) {
598: dt = &rootent[i];
599: if (dt->d_ino == 0) {
600: *eofflagp = 1;
601: break;
602: }
603: i++;
604:
605: switch (dt->d_ino) {
606: case FD_CTTY:
607: if (cttyvp(uio->uio_procp) == NULL)
608: continue;
609: break;
610:
611: case FD_STDIN:
612: case FD_STDOUT:
613: case FD_STDERR:
614: if ((dt->d_ino-FD_STDIN) >= fdp->fd_nfiles)
615: continue;
616: if (fdp->fd_ofiles[dt->d_ino-FD_STDIN] == NULL)
617: continue;
618: break;
619: }
620: bzero(dp, UIO_MX);
621: dp->d_ino = dt->d_ino;
622: dp->d_namlen = dt->d_namlen;
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;
1.3 cgd 628: }
1.8 cgd 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) {
1.1 cgd 636: if (i >= fdp->fd_nfiles) {
637: *eofflagp = 1;
638: break;
639: }
640: if (fdp->fd_ofiles[i] != NULL) {
641: struct direct d;
642: struct direct *dp = &d;
643: #ifdef FDESC_FILEID
644: struct vattr va;
645: #endif
646: bzero((caddr_t) dp, UIO_MX);
647:
1.8 cgd 648: dp->d_namlen = sprintf(dp->d_name, "%d", i);
1.1 cgd 649: /*
650: * Fill in the remaining fields
651: */
652: dp->d_reclen = UIO_MX;
1.8 cgd 653: dp->d_ino = i + FD_STDIN;
1.1 cgd 654: #ifdef FDESC_FILEID
655: /*
656: * If we want the file ids to match the
657: * we must call getattr on the underlying file.
658: * fdesc_attr may return an error, in which case
659: * we ignore the returned file id.
660: */
661: error = fdesc_attr(i, &va, cred, p);
662: if (error == 0)
663: dp->d_ino = va.va_fileid;
664: #endif
665: /*
666: * And ship to userland
667: */
668: error = uiomove((caddr_t) dp, UIO_MX, uio);
669: if (error)
670: break;
671: }
1.8 cgd 672: i++;
673: }
674:
675: uio->uio_offset = i * UIO_MX;
676: return (error);
677: }
678:
679: fdesc_readlink(vp, uio, cred)
680: struct vnode *vp;
681: struct uio *uio;
682: struct ucred *cred;
683: {
684: int error;
685:
686: if (VTOFDESC(vp)->fd_type == Flink) {
687: char *ln = VTOFDESC(vp)->fd_link;
688: error = uiomove(ln, strlen(ln), uio);
689: } else {
690: error = EOPNOTSUPP;
691: }
692:
693: return (error);
694: }
695:
696: fdesc_read(vp, uio, ioflag, cred)
697: struct vnode *vp;
698: struct uio *uio;
699: int ioflag;
700: struct ucred *cred;
701: {
702: int error = EOPNOTSUPP;
703:
704: switch (VTOFDESC(vp)->fd_type) {
705: case Fctty:
706: error = cttyread(devctty, uio, ioflag);
707: break;
708:
709: default:
710: error = EOPNOTSUPP;
711: break;
712: }
713:
714: return (error);
715: }
716:
717: fdesc_write(vp, uio, ioflag, cred)
718: struct vnode *vp;
719: struct uio *uio;
720: int ioflag;
721: struct ucred *cred;
722: {
723: int error = EOPNOTSUPP;
724:
725: switch (VTOFDESC(vp)->fd_type) {
726: case Fctty:
727: error = cttywrite(devctty, uio, ioflag);
728: break;
729:
730: default:
731: error = EOPNOTSUPP;
732: break;
733: }
734:
735: return (error);
736: }
737:
738: fdesc_ioctl(vp, command, data, fflag, cred, p)
739: struct vnode *vp;
740: int command;
741: caddr_t data;
742: int fflag;
743: struct ucred *cred;
744: struct proc *p;
745: {
746: int error = EOPNOTSUPP;
747:
748: #ifdef FDESC_DIAGNOSTIC
749: printf("fdesc_ioctl: type = %d, command = %x\n",
750: VTOFDESC(vp)->fd_type, command);
751: #endif
752: switch (VTOFDESC(vp)->fd_type) {
753: case Fctty:
754: error = cttyioctl(devctty, command, data, fflag, p);
755: break;
756:
757: default:
758: error = EOPNOTSUPP;
759: break;
1.1 cgd 760: }
1.8 cgd 761:
762: return (error);
763: }
764:
765: fdesc_select(vp, which, fflags, cred, p)
766: struct vnode *vp;
767: int which;
768: int fflags;
769: struct ucred *cred;
770: struct proc *p;
771: {
772: int error = EOPNOTSUPP;
773:
774: switch (VTOFDESC(vp)->fd_type) {
775: case Fctty:
776: error = cttyselect(devctty, fflags, p);
777: break;
1.1 cgd 778:
1.8 cgd 779: default:
780: error = EOPNOTSUPP;
781: break;
782: }
783:
1.1 cgd 784: return (error);
1.8 cgd 785:
1.1 cgd 786: }
787:
788: fdesc_inactive(vp, p)
789: struct vnode *vp;
790: struct proc *p;
791: {
792: /*
793: * Clear out the v_type field to avoid
794: * nasty things happening in vgone().
795: */
796: vp->v_type = VNON;
797: #ifdef FDESC_DIAGNOSTIC
798: printf("fdesc_inactive(%x)\n", vp);
799: #endif
800: return (0);
801: }
802:
1.8 cgd 803: int fdesc_reclaim(vp)
804: struct vnode *vp;
805: {
806: int ix;
807:
808: #ifdef FDESC_DIAGNOSTIC
809: printf("fdesc_reclaim(%x)\n", vp);
810: #endif
811:
812: ix = VTOFDESC(vp)->fd_ix;
813: if (ix >= 0 && ix < FD_MAX) {
814: if (fdescvp[ix] != vp)
815: panic("fdesc_reclaim");
816: fdescvp[ix] = 0;
817: }
818: return (0);
819: }
820:
1.1 cgd 821: /*
822: * Print out the contents of a /dev/fd vnode.
823: */
824: /* ARGSUSED */
825: fdesc_print(vp)
826: struct vnode *vp;
827: {
1.8 cgd 828: printf("tag VT_NON, fdesc vnode\n");
1.1 cgd 829: }
830:
831: /*
832: * /dev/fd vnode unsupported operation
833: */
834: fdesc_enotsupp()
835: {
836: return (EOPNOTSUPP);
837: }
838:
839: /*
840: * /dev/fd "should never get here" operation
841: */
842: fdesc_badop()
843: {
844: panic("fdesc: bad op");
845: /* NOTREACHED */
846: }
847:
848: /*
849: * /dev/fd vnode null operation
850: */
851: fdesc_nullop()
852: {
853: return (0);
854: }
855:
856: #define fdesc_create ((int (*) __P(( \
857: struct nameidata *ndp, \
858: struct vattr *vap, \
859: struct proc *p))) fdesc_enotsupp)
860: #define fdesc_mknod ((int (*) __P(( \
861: struct nameidata *ndp, \
862: struct vattr *vap, \
863: struct ucred *cred, \
864: struct proc *p))) fdesc_enotsupp)
865: #define fdesc_close ((int (*) __P(( \
866: struct vnode *vp, \
867: int fflag, \
868: struct ucred *cred, \
869: struct proc *p))) nullop)
870: #define fdesc_access ((int (*) __P(( \
871: struct vnode *vp, \
872: int mode, \
873: struct ucred *cred, \
874: struct proc *p))) nullop)
875: #define fdesc_mmap ((int (*) __P(( \
876: struct vnode *vp, \
877: int fflags, \
878: struct ucred *cred, \
879: struct proc *p))) fdesc_enotsupp)
880: #define fdesc_fsync ((int (*) __P(( \
881: struct vnode *vp, \
882: int fflags, \
883: struct ucred *cred, \
884: int waitfor, \
885: struct proc *p))) nullop)
886: #define fdesc_seek ((int (*) __P(( \
887: struct vnode *vp, \
888: off_t oldoff, \
889: off_t newoff, \
890: struct ucred *cred))) nullop)
891: #define fdesc_remove ((int (*) __P(( \
892: struct nameidata *ndp, \
893: struct proc *p))) fdesc_enotsupp)
894: #define fdesc_link ((int (*) __P(( \
895: struct vnode *vp, \
896: struct nameidata *ndp, \
897: struct proc *p))) fdesc_enotsupp)
898: #define fdesc_rename ((int (*) __P(( \
899: struct nameidata *fndp, \
900: struct nameidata *tdnp, \
901: struct proc *p))) fdesc_enotsupp)
902: #define fdesc_mkdir ((int (*) __P(( \
903: struct nameidata *ndp, \
904: struct vattr *vap, \
905: struct proc *p))) fdesc_enotsupp)
906: #define fdesc_rmdir ((int (*) __P(( \
907: struct nameidata *ndp, \
908: struct proc *p))) fdesc_enotsupp)
909: #define fdesc_symlink ((int (*) __P(( \
910: struct nameidata *ndp, \
911: struct vattr *vap, \
912: char *target, \
913: struct proc *p))) fdesc_enotsupp)
914: #define fdesc_abortop ((int (*) __P(( \
915: struct nameidata *ndp))) nullop)
916: #define fdesc_lock ((int (*) __P(( \
917: struct vnode *vp))) nullop)
918: #define fdesc_unlock ((int (*) __P(( \
919: struct vnode *vp))) nullop)
920: #define fdesc_bmap ((int (*) __P(( \
921: struct vnode *vp, \
922: daddr_t bn, \
923: struct vnode **vpp, \
924: daddr_t *bnp))) fdesc_badop)
925: #define fdesc_strategy ((int (*) __P(( \
926: struct buf *bp))) fdesc_badop)
927: #define fdesc_islocked ((int (*) __P(( \
928: struct vnode *vp))) nullop)
929: #define fdesc_advlock ((int (*) __P(( \
930: struct vnode *vp, \
931: caddr_t id, \
932: int op, \
933: struct flock *fl, \
934: int flags))) fdesc_enotsupp)
935:
936: struct vnodeops fdesc_vnodeops = {
937: fdesc_lookup, /* lookup */
938: fdesc_create, /* create */
939: fdesc_mknod, /* mknod */
940: fdesc_open, /* open */
941: fdesc_close, /* close */
942: fdesc_access, /* access */
943: fdesc_getattr, /* getattr */
944: fdesc_setattr, /* setattr */
945: fdesc_read, /* read */
946: fdesc_write, /* write */
947: fdesc_ioctl, /* ioctl */
948: fdesc_select, /* select */
949: fdesc_mmap, /* mmap */
950: fdesc_fsync, /* fsync */
951: fdesc_seek, /* seek */
952: fdesc_remove, /* remove */
953: fdesc_link, /* link */
954: fdesc_rename, /* rename */
955: fdesc_mkdir, /* mkdir */
956: fdesc_rmdir, /* rmdir */
957: fdesc_symlink, /* symlink */
958: fdesc_readdir, /* readdir */
959: fdesc_readlink, /* readlink */
960: fdesc_abortop, /* abortop */
961: fdesc_inactive, /* inactive */
962: fdesc_reclaim, /* reclaim */
963: fdesc_lock, /* lock */
964: fdesc_unlock, /* unlock */
965: fdesc_bmap, /* bmap */
966: fdesc_strategy, /* strategy */
967: fdesc_print, /* print */
968: fdesc_islocked, /* islocked */
969: fdesc_advlock, /* advlock */
970: };
CVSweb <webmaster@jp.NetBSD.org>