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