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