153838Spendry /* 253838Spendry * Copyright (c) 1992 The Regents of the University of California 359255Spendry * Copyright (c) 1990, 1992, 1993 Jan-Simon Pendry 453838Spendry * All rights reserved. 553838Spendry * 653838Spendry * This code is derived from software donated to Berkeley by 753838Spendry * Jan-Simon Pendry. 853838Spendry * 953838Spendry * %sccs.include.redist.c% 1053838Spendry * 11*59452Smckusick * @(#)fdesc_vnops.c 7.5 (Berkeley) 04/28/93 1253838Spendry * 1359255Spendry * $Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp $ 1453838Spendry */ 1553838Spendry 1653838Spendry /* 1753838Spendry * /dev/fd Filesystem 1853838Spendry */ 1953838Spendry 2053838Spendry #include <sys/param.h> 2153838Spendry #include <sys/systm.h> 2253838Spendry #include <sys/types.h> 2353838Spendry #include <sys/time.h> 2453838Spendry #include <sys/proc.h> 2559255Spendry #include <sys/kernel.h> /* boottime */ 2653838Spendry #include <sys/resourcevar.h> 2753838Spendry #include <sys/filedesc.h> 2853838Spendry #include <sys/vnode.h> 2953838Spendry #include <sys/malloc.h> 3053838Spendry #include <sys/file.h> 3153838Spendry #include <sys/stat.h> 3253838Spendry #include <sys/mount.h> 3353838Spendry #include <sys/namei.h> 3453838Spendry #include <sys/buf.h> 3554981Spendry #include <sys/dirent.h> 3655017Smckusick #include <miscfs/fdesc/fdesc.h> 3753838Spendry 3859255Spendry #define cttyvp(p) ((p)->p_flag&SCTTY ? (p)->p_session->s_ttyvp : NULL) 3959255Spendry 4059255Spendry #define FDL_WANT 0x01 4159255Spendry #define FDL_LOCKED 0x02 4259255Spendry static int fdescvplock; 4359255Spendry static struct vnode *fdescvp[FD_MAX]; 4459255Spendry 4559255Spendry #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 4659255Spendry FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 4759255Spendry #endif 4859255Spendry 4959255Spendry fdesc_allocvp(ftype, ix, mp, vpp) 5059255Spendry fdntype ftype; 5159255Spendry int ix; 5259255Spendry struct mount *mp; 5359255Spendry struct vnode **vpp; 5459255Spendry { 5559255Spendry struct vnode **nvpp = 0; 5659255Spendry int error = 0; 5759255Spendry 5859255Spendry /* get stashed copy of the vnode */ 5959255Spendry if (ix >= 0 && ix < FD_MAX) { 6059255Spendry nvpp = &fdescvp[ix]; 61*59452Smckusick if (*nvpp && vget(*nvpp) == 0) { 62*59452Smckusick VOP_UNLOCK(*nvpp); 6359255Spendry *vpp = *nvpp; 6459255Spendry return (error); 6559255Spendry } 6659255Spendry } 6759255Spendry 6859255Spendry /* 6959255Spendry * otherwise lock the array while we call getnewvnode 7059255Spendry * since that can block. 7159255Spendry */ 7259255Spendry while (fdescvplock & FDL_LOCKED) { 7359255Spendry fdescvplock |= FDL_WANT; 7459255Spendry sleep((caddr_t) &fdescvplock, PINOD); 7559255Spendry } 7659255Spendry fdescvplock |= FDL_LOCKED; 7759255Spendry 7859255Spendry error = getnewvnode(VT_UFS, mp, fdesc_vnodeop_p, vpp); 7959255Spendry if (error) 8059255Spendry goto out; 8159255Spendry MALLOC((*vpp)->v_data, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 8259255Spendry if (nvpp) 8359255Spendry *nvpp = *vpp; 8459255Spendry VTOFDESC(*vpp)->fd_type = ftype; 8559255Spendry VTOFDESC(*vpp)->fd_fd = -1; 8659255Spendry VTOFDESC(*vpp)->fd_link = 0; 8759255Spendry VTOFDESC(*vpp)->fd_ix = ix; 8859255Spendry 8959255Spendry out:; 9059255Spendry fdescvplock &= ~FDL_LOCKED; 9159255Spendry 9259255Spendry if (fdescvplock & FDL_WANT) { 9359255Spendry fdescvplock &= ~FDL_WANT; 9459255Spendry wakeup((caddr_t) &fdescvplock); 9559255Spendry } 9659255Spendry 9759255Spendry return (error); 9859255Spendry } 9959255Spendry 10053838Spendry /* 10153838Spendry * vp is the current namei directory 10253838Spendry * ndp is the name to locate in that directory... 10353838Spendry */ 10455017Smckusick fdesc_lookup(ap) 10555017Smckusick struct vop_lookup_args /* { 10655017Smckusick struct vnode * a_dvp; 10755017Smckusick struct vnode ** a_vpp; 10855017Smckusick struct componentname * a_cnp; 10955017Smckusick } */ *ap; 11053838Spendry { 11154049Spendry struct vnode **vpp = ap->a_vpp; 11254049Spendry struct vnode *dvp = ap->a_dvp; 11353838Spendry char *pname; 11453838Spendry struct proc *p; 11553838Spendry int nfiles; 11653838Spendry unsigned fd; 11753838Spendry int error; 11853838Spendry struct vnode *fvp; 11959255Spendry char *ln; 12053838Spendry 12153838Spendry #ifdef FDESC_DIAGNOSTIC 12253838Spendry printf("fdesc_lookup(%x)\n", ap); 12354049Spendry printf("fdesc_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp); 12453838Spendry #endif 12553838Spendry pname = ap->a_cnp->cn_nameptr; 12653838Spendry #ifdef FDESC_DIAGNOSTIC 12753838Spendry printf("fdesc_lookup(%s)\n", pname); 12853838Spendry #endif 12953838Spendry if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 13054049Spendry *vpp = dvp; 13154049Spendry VREF(dvp); 13259255Spendry VOP_LOCK(dvp); 13353838Spendry return (0); 13453838Spendry } 13553838Spendry 13653838Spendry p = ap->a_cnp->cn_proc; 13753838Spendry nfiles = p->p_fd->fd_nfiles; 13853838Spendry 13959255Spendry switch (VTOFDESC(dvp)->fd_type) { 14059255Spendry default: 14159255Spendry case Flink: 14259255Spendry case Fdesc: 14359255Spendry case Fctty: 14459255Spendry error = ENOTDIR; 14559255Spendry goto bad; 14659255Spendry 14759255Spendry case Froot: 14859255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { 14959255Spendry error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); 15059255Spendry if (error) 15159255Spendry goto bad; 15259255Spendry *vpp = fvp; 15359255Spendry fvp->v_type = VDIR; 15459255Spendry VOP_LOCK(fvp); 15559255Spendry #ifdef FDESC_DIAGNOSTIC 15659255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 15759255Spendry #endif 15859255Spendry return (0); 15959255Spendry } 16059255Spendry 16159255Spendry if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 16259255Spendry struct vnode *ttyvp = cttyvp(p); 16359255Spendry if (ttyvp == NULL) { 16459255Spendry error = ENXIO; 16559255Spendry goto bad; 16659255Spendry } 16759255Spendry error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 16859255Spendry if (error) 16959255Spendry goto bad; 17059255Spendry *vpp = fvp; 17159255Spendry fvp->v_type = VFIFO; 17259255Spendry VOP_LOCK(fvp); 17359255Spendry #ifdef FDESC_DIAGNOSTIC 17459255Spendry printf("fdesc_lookup: ttyvp = %x\n", fvp); 17559255Spendry #endif 17659255Spendry return (0); 17759255Spendry } 17859255Spendry 17959255Spendry ln = 0; 18059255Spendry switch (ap->a_cnp->cn_namelen) { 18159255Spendry case 5: 18259255Spendry if (bcmp(pname, "stdin", 5) == 0) { 18359255Spendry ln = "fd/0"; 18459255Spendry fd = FD_STDIN; 18559255Spendry } 18653838Spendry break; 18759255Spendry case 6: 18859255Spendry if (bcmp(pname, "stdout", 6) == 0) { 18959255Spendry ln = "fd/1"; 19059255Spendry fd = FD_STDOUT; 19159255Spendry } else 19259255Spendry if (bcmp(pname, "stderr", 6) == 0) { 19359255Spendry ln = "fd/2"; 19459255Spendry fd = FD_STDERR; 19559255Spendry } 19659255Spendry break; 19759255Spendry } 19853838Spendry 19959255Spendry if (ln) { 20053838Spendry #ifdef FDESC_DIAGNOSTIC 20159255Spendry printf("fdesc_lookup: link -> %s\n", ln); 20253838Spendry #endif 20359255Spendry error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 20459255Spendry if (error) 20559255Spendry goto bad; 20659255Spendry VTOFDESC(fvp)->fd_link = ln; 20759255Spendry *vpp = fvp; 20859255Spendry fvp->v_type = VLNK; 20959255Spendry VOP_LOCK(fvp); 21059255Spendry #ifdef FDESC_DIAGNOSTIC 21159255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 21259255Spendry #endif 21359255Spendry return (0); 21459255Spendry } else { 21559255Spendry error = ENOENT; 21659255Spendry goto bad; 21759255Spendry } 21853838Spendry 21959255Spendry /* fall through */ 22053838Spendry 22159255Spendry case Fdevfd: 22259255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { 22359255Spendry error = fdesc_root(dvp->v_mount, vpp); 22459255Spendry return (error); 22559255Spendry } 22659255Spendry 22759255Spendry fd = 0; 22859255Spendry while (*pname >= '0' && *pname <= '9') { 22959255Spendry fd = 10 * fd + *pname++ - '0'; 23059255Spendry if (fd >= nfiles) 23159255Spendry break; 23259255Spendry } 23359255Spendry 23453838Spendry #ifdef FDESC_DIAGNOSTIC 23559255Spendry printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); 23653838Spendry #endif 23759255Spendry if (*pname != '\0') { 23859255Spendry error = ENOENT; 23959255Spendry goto bad; 24059255Spendry } 24159255Spendry 24259255Spendry if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 24359255Spendry error = EBADF; 24459255Spendry goto bad; 24559255Spendry } 24659255Spendry 24753838Spendry #ifdef FDESC_DIAGNOSTIC 24859255Spendry printf("fdesc_lookup: allocate new vnode\n"); 24953838Spendry #endif 25059255Spendry error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 25159255Spendry if (error) 25259255Spendry goto bad; 25359255Spendry VTOFDESC(fvp)->fd_fd = fd; 25459255Spendry *vpp = fvp; 25559255Spendry #ifdef FDESC_DIAGNOSTIC 25659255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 25759255Spendry #endif 25859255Spendry return (0); 25959255Spendry } 26053838Spendry 26153838Spendry bad:; 26254049Spendry *vpp = NULL; 26353838Spendry #ifdef FDESC_DIAGNOSTIC 26453838Spendry printf("fdesc_lookup: error = %d\n", error); 26553838Spendry #endif 26653838Spendry return (error); 26753838Spendry } 26853838Spendry 26955017Smckusick fdesc_open(ap) 27055017Smckusick struct vop_open_args /* { 27155017Smckusick struct vnode *a_vp; 27255017Smckusick int a_mode; 27355017Smckusick struct ucred *a_cred; 27455017Smckusick struct proc *a_p; 27555017Smckusick } */ *ap; 27653838Spendry { 27754049Spendry struct vnode *vp = ap->a_vp; 27859255Spendry int error = 0; 27954049Spendry 28059255Spendry switch (VTOFDESC(vp)->fd_type) { 28159255Spendry case Fdesc: 28259255Spendry /* 28359255Spendry * XXX Kludge: set p->p_dupfd to contain the value of the 28459255Spendry * the file descriptor being sought for duplication. The error 28559255Spendry * return ensures that the vnode for this device will be 28659255Spendry * released by vn_open. Open will detect this special error and 28759255Spendry * take the actions in dupfdopen. Other callers of vn_open or 28859255Spendry * VOP_OPEN will simply report the error. 28959255Spendry */ 29059255Spendry ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 29159255Spendry error = ENODEV; 29259255Spendry break; 29353838Spendry 29459255Spendry case Fctty: 29559255Spendry error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); 29659255Spendry break; 29759255Spendry } 29859255Spendry 29959255Spendry return (error); 30053838Spendry } 30153838Spendry 30253838Spendry static int 30353838Spendry fdesc_attr(fd, vap, cred, p) 30453838Spendry int fd; 30553838Spendry struct vattr *vap; 30653838Spendry struct ucred *cred; 30753838Spendry struct proc *p; 30853838Spendry { 30953838Spendry struct filedesc *fdp = p->p_fd; 31053838Spendry struct file *fp; 31153838Spendry int error; 31253838Spendry 31353838Spendry #ifdef FDESC_DIAGNOSTIC 31453838Spendry printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 31553838Spendry #endif 31653838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 31753838Spendry #ifdef FDESC_DIAGNOSTIC 31853838Spendry printf("fdesc_attr: fp = %x (EBADF)\n", fp); 31953838Spendry #endif 32053838Spendry return (EBADF); 32153838Spendry } 32253838Spendry 32353838Spendry /* 32453838Spendry * Can stat the underlying vnode, but not sockets because 32553838Spendry * they don't use struct vattrs. Well, we could convert from 32653838Spendry * a struct stat back to a struct vattr, later... 32753838Spendry */ 32853838Spendry switch (fp->f_type) { 32953838Spendry case DTYPE_VNODE: 33053838Spendry error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 33153838Spendry break; 33253838Spendry 33353838Spendry case DTYPE_SOCKET: 33453838Spendry error = EOPNOTSUPP; 33553838Spendry break; 33653838Spendry 33753838Spendry default: 33853838Spendry panic("fdesc attr"); 33953838Spendry break; 34053838Spendry } 34153838Spendry 34253838Spendry #ifdef FDESC_DIAGNOSTIC 34353838Spendry printf("fdesc_attr: returns error %d\n", error); 34453838Spendry #endif 34553838Spendry return (error); 34653838Spendry } 34753838Spendry 34855017Smckusick fdesc_getattr(ap) 34955017Smckusick struct vop_getattr_args /* { 35055017Smckusick struct vnode *a_vp; 35155017Smckusick struct vattr *a_vap; 35255017Smckusick struct ucred *a_cred; 35355017Smckusick struct proc *a_p; 35455017Smckusick } */ *ap; 35553838Spendry { 35654049Spendry struct vnode *vp = ap->a_vp; 35754049Spendry struct vattr *vap = ap->a_vap; 35853838Spendry unsigned fd; 35953838Spendry int error; 36053838Spendry 36153838Spendry #ifdef FDESC_DIAGNOSTIC 36259255Spendry printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type); 36353838Spendry #endif 36459255Spendry 36559255Spendry switch (VTOFDESC(vp)->fd_type) { 36659255Spendry case Froot: 36759255Spendry case Fdevfd: 36859255Spendry case Flink: 36959255Spendry case Fctty: 37054049Spendry bzero((caddr_t) vap, sizeof(*vap)); 37154049Spendry vattr_null(vap); 37259255Spendry vap->va_fileid = VTOFDESC(vp)->fd_ix; 37359255Spendry 37459255Spendry switch (VTOFDESC(vp)->fd_type) { 37559255Spendry case Flink: 37659255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 37759255Spendry vap->va_type = VLNK; 37859255Spendry vap->va_nlink = 1; 37959255Spendry /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */ 38059255Spendry vap->va_size = strlen(VTOFDESC(vp)->fd_link); 38159255Spendry break; 38259255Spendry 38359255Spendry case Fctty: 38459255Spendry vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 38559255Spendry vap->va_type = VFIFO; 38659255Spendry vap->va_nlink = 1; 38759255Spendry /* vap->va_qsize = 0; */ 38859255Spendry vap->va_size = 0; 38959255Spendry break; 39059255Spendry 39159255Spendry default: 39259255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 39359255Spendry vap->va_type = VDIR; 39459255Spendry vap->va_nlink = 2; 39559255Spendry /* vap->va_qsize = 0; */ 39659255Spendry vap->va_size = DEV_BSIZE; 39759255Spendry break; 39859255Spendry } 39954049Spendry vap->va_uid = 0; 40054049Spendry vap->va_gid = 0; 40154049Spendry vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 40254049Spendry vap->va_blocksize = DEV_BSIZE; 40359255Spendry vap->va_atime.ts_sec = boottime.tv_sec; 40459255Spendry vap->va_atime.ts_nsec = 0; 40554049Spendry vap->va_mtime = vap->va_atime; 40654049Spendry vap->va_ctime = vap->va_ctime; 40754049Spendry vap->va_gen = 0; 40854049Spendry vap->va_flags = 0; 40954049Spendry vap->va_rdev = 0; 41054049Spendry /* vap->va_qbytes = 0; */ 41154049Spendry vap->va_bytes = 0; 41259255Spendry break; 41359255Spendry 41459255Spendry case Fdesc: 41559255Spendry #ifdef FDESC_DIAGNOSTIC 41659255Spendry printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd); 41759255Spendry #endif 41859255Spendry fd = VTOFDESC(vp)->fd_fd; 41959255Spendry error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); 42059255Spendry break; 42159255Spendry 42259255Spendry default: 42359255Spendry panic("fdesc_getattr"); 42459255Spendry break; 42553838Spendry } 42653838Spendry 42753838Spendry if (error == 0) 42854049Spendry vp->v_type = vap->va_type; 42959255Spendry 43059255Spendry #ifdef FDESC_DIAGNOSTIC 43159255Spendry printf("fdesc_getattr: stat returns 0\n"); 43259255Spendry #endif 43353838Spendry return (error); 43453838Spendry } 43553838Spendry 43655017Smckusick fdesc_setattr(ap) 43755017Smckusick struct vop_setattr_args /* { 43855017Smckusick struct vnode *a_vp; 43955017Smckusick struct vattr *a_vap; 44055017Smckusick struct ucred *a_cred; 44155017Smckusick struct proc *a_p; 44255017Smckusick } */ *ap; 44353838Spendry { 44453838Spendry struct filedesc *fdp = ap->a_p->p_fd; 44553838Spendry struct file *fp; 44653838Spendry unsigned fd; 44753838Spendry int error; 44853838Spendry 44953838Spendry /* 45053838Spendry * Can't mess with the root vnode 45153838Spendry */ 45259255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 45359255Spendry case Fdesc: 45459255Spendry break; 45559255Spendry 45659255Spendry case Fctty: 45759255Spendry return (0); 45859255Spendry 45959255Spendry default: 46053838Spendry return (EACCES); 46159255Spendry } 46253838Spendry 46359255Spendry fd = VTOFDESC(ap->a_vp)->fd_fd; 46453838Spendry #ifdef FDESC_DIAGNOSTIC 46553838Spendry printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 46653838Spendry #endif 46753838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 46853838Spendry #ifdef FDESC_DIAGNOSTIC 46953838Spendry printf("fdesc_setattr: fp = %x (EBADF)\n", fp); 47053838Spendry #endif 47153838Spendry return (EBADF); 47253838Spendry } 47353838Spendry 47453838Spendry /* 47553838Spendry * Can setattr the underlying vnode, but not sockets! 47653838Spendry */ 47753838Spendry switch (fp->f_type) { 47853838Spendry case DTYPE_VNODE: 47953838Spendry error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); 48053838Spendry break; 48153838Spendry 48253838Spendry case DTYPE_SOCKET: 48358646Spendry error = 0; 48453838Spendry break; 48553838Spendry 48653838Spendry default: 48753838Spendry panic("fdesc setattr"); 48853838Spendry break; 48953838Spendry } 49053838Spendry 49153838Spendry #ifdef FDESC_DIAGNOSTIC 49253838Spendry printf("fdesc_setattr: returns error %d\n", error); 49353838Spendry #endif 49453838Spendry return (error); 49553838Spendry } 49653838Spendry 49759255Spendry #define UIO_MX 16 49859255Spendry 49959255Spendry static struct dirtmp { 50059255Spendry u_long d_fileno; 50159255Spendry u_short d_reclen; 50259255Spendry u_short d_namlen; 50359255Spendry char d_name[8]; 50459255Spendry } rootent[] = { 50559255Spendry { FD_DEVFD, UIO_MX, 2, "fd" }, 50659255Spendry { FD_STDIN, UIO_MX, 5, "stdin" }, 50759255Spendry { FD_STDOUT, UIO_MX, 6, "stdout" }, 50859255Spendry { FD_STDERR, UIO_MX, 6, "stderr" }, 50959255Spendry { FD_CTTY, UIO_MX, 3, "tty" }, 51059255Spendry { 0 } 51159255Spendry }; 51259255Spendry 51355017Smckusick fdesc_readdir(ap) 51455017Smckusick struct vop_readdir_args /* { 51555017Smckusick struct vnode *a_vp; 51655017Smckusick struct uio *a_uio; 51755017Smckusick struct ucred *a_cred; 51855017Smckusick } */ *ap; 51953838Spendry { 52054049Spendry struct uio *uio = ap->a_uio; 52153838Spendry struct filedesc *fdp; 52253838Spendry int i; 52353838Spendry int error; 52453838Spendry 52559255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 52659255Spendry case Fctty: 52759255Spendry return (0); 52853838Spendry 52959255Spendry case Fdesc: 53059255Spendry return (ENOTDIR); 53159255Spendry 53259255Spendry default: 53359255Spendry break; 53459255Spendry } 53559255Spendry 53654049Spendry fdp = uio->uio_procp->p_fd; 53759255Spendry 53859255Spendry if (VTOFDESC(ap->a_vp)->fd_type == Froot) { 53959255Spendry struct dirent d; 54059255Spendry struct dirent *dp = &d; 54159255Spendry struct dirtmp *dt; 54259255Spendry 54359255Spendry i = uio->uio_offset / UIO_MX; 54459255Spendry error = 0; 54559255Spendry 54659255Spendry while (uio->uio_resid > 0) { 54759255Spendry dt = &rootent[i]; 54859255Spendry if (dt->d_fileno == 0) { 54959255Spendry /**eofflagp = 1;*/ 55059255Spendry break; 55159255Spendry } 55259255Spendry i++; 55359255Spendry 55459255Spendry switch (dt->d_fileno) { 55559255Spendry case FD_CTTY: 55659255Spendry if (cttyvp(uio->uio_procp) == NULL) 55759255Spendry continue; 55859255Spendry break; 55959255Spendry 56059255Spendry case FD_STDIN: 56159255Spendry case FD_STDOUT: 56259255Spendry case FD_STDERR: 56359255Spendry if ((i-FD_STDIN) >= fdp->fd_nfiles) 56459255Spendry continue; 56559255Spendry if (fdp->fd_ofiles[i-FD_STDIN] == NULL) 56659255Spendry continue; 56759255Spendry break; 56859255Spendry } 56959255Spendry bzero(dp, UIO_MX); 57059255Spendry dp->d_fileno = dt->d_fileno; 57159255Spendry dp->d_namlen = dt->d_namlen; 57259255Spendry dp->d_type = DT_UNKNOWN; 57359255Spendry dp->d_reclen = dt->d_reclen; 57459255Spendry bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 57559255Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 57659255Spendry if (error) 57759255Spendry break; 57859255Spendry } 57959255Spendry uio->uio_offset = i * UIO_MX; 58059255Spendry return (error); 58159255Spendry } 58259255Spendry 58354049Spendry i = uio->uio_offset / UIO_MX; 58453838Spendry error = 0; 58554049Spendry while (uio->uio_resid > 0) { 58653838Spendry if (i >= fdp->fd_nfiles) { 58754980Spendry /* *ap->a_eofflagp = 1; */ 58853838Spendry break; 58953838Spendry } 59053838Spendry if (fdp->fd_ofiles[i] != NULL) { 59154981Spendry struct dirent d; 59254981Spendry struct dirent *dp = &d; 59353838Spendry char *cp = dp->d_name; 59453838Spendry bzero((caddr_t) dp, UIO_MX); 59553838Spendry 59653838Spendry dp->d_namlen = sprintf(dp->d_name, "%d", i); 59753838Spendry /* 59853838Spendry * Fill in the remaining fields 59953838Spendry */ 60053838Spendry dp->d_reclen = UIO_MX; 60154981Spendry dp->d_type = DT_UNKNOWN; 60259255Spendry dp->d_fileno = i + FD_STDIN; 60353838Spendry /* 60453838Spendry * And ship to userland 60553838Spendry */ 60654049Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 60753838Spendry if (error) 60853838Spendry break; 60953838Spendry } 61053838Spendry i++; 61153838Spendry } 61253838Spendry 61354049Spendry uio->uio_offset = i * UIO_MX; 61453838Spendry return (error); 61553838Spendry } 61653838Spendry 61759255Spendry int 61859255Spendry fdesc_readlink(ap) 61959255Spendry struct vop_readlink_args /* { 62059255Spendry struct vnode *a_vp; 62159255Spendry struct uio *a_uio; 62259255Spendry struct ucred *a_cred; 62359255Spendry } */ *ap; 62459255Spendry { 62559255Spendry register struct vnode *vp = ap->a_vp; 62659255Spendry int error; 62759255Spendry 62859255Spendry if (vp->v_type != VLNK) 62959255Spendry return (EPERM); 63059255Spendry 63159255Spendry if (VTOFDESC(vp)->fd_type == Flink) { 63259255Spendry char *ln = VTOFDESC(vp)->fd_link; 63359255Spendry error = uiomove(ln, strlen(ln), ap->a_uio); 63459255Spendry } else { 63559255Spendry error = EOPNOTSUPP; 63659255Spendry } 63759255Spendry 63859255Spendry return (error); 63959255Spendry } 64059255Spendry 64159255Spendry fdesc_read(ap) 64259255Spendry struct vop_read_args /* { 64359255Spendry struct vnode *a_vp; 64459255Spendry struct uio *a_uio; 64559255Spendry int a_ioflag; 64659255Spendry struct ucred *a_cred; 64759255Spendry } */ *ap; 64859255Spendry { 64959255Spendry int error = EOPNOTSUPP; 65059255Spendry 65159255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 65259255Spendry case Fctty: 65359255Spendry error = cttyread(devctty, ap->a_uio, ap->a_ioflag); 65459255Spendry break; 65559255Spendry 65659255Spendry default: 65759255Spendry error = EOPNOTSUPP; 65859255Spendry break; 65959255Spendry } 66059255Spendry 66159255Spendry return (error); 66259255Spendry } 66359255Spendry 66459255Spendry fdesc_write(ap) 66559255Spendry struct vop_write_args /* { 66659255Spendry struct vnode *a_vp; 66759255Spendry struct uio *a_uio; 66859255Spendry int a_ioflag; 66959255Spendry struct ucred *a_cred; 67059255Spendry } */ *ap; 67159255Spendry { 67259255Spendry int error = EOPNOTSUPP; 67359255Spendry 67459255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 67559255Spendry case Fctty: 67659255Spendry error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); 67759255Spendry break; 67859255Spendry 67959255Spendry default: 68059255Spendry error = EOPNOTSUPP; 68159255Spendry break; 68259255Spendry } 68359255Spendry 68459255Spendry return (error); 68559255Spendry } 68659255Spendry 68759255Spendry fdesc_ioctl(ap) 68859255Spendry struct vop_ioctl_args /* { 68959255Spendry struct vnode *a_vp; 69059255Spendry int a_command; 69159255Spendry caddr_t a_data; 69259255Spendry int a_fflag; 69359255Spendry struct ucred *a_cred; 69459255Spendry struct proc *a_p; 69559255Spendry } */ *ap; 69659255Spendry { 69759255Spendry int error = EOPNOTSUPP; 69859255Spendry 69959255Spendry #ifdef FDESC_DIAGNOSTIC 70059255Spendry printf("fdesc_ioctl: type = %d, command = %x\n", 70159255Spendry VTOFDESC(ap->a_vp)->fd_type, ap->a_command); 70259255Spendry #endif 70359255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 70459255Spendry case Fctty: 70559255Spendry error = cttyioctl(devctty, ap->a_command, ap->a_data, 70659255Spendry ap->a_fflag, ap->a_p); 70759255Spendry break; 70859255Spendry 70959255Spendry default: 71059255Spendry error = EOPNOTSUPP; 71159255Spendry break; 71259255Spendry } 71359255Spendry 71459255Spendry return (error); 71559255Spendry } 71659255Spendry 71759255Spendry fdesc_select(ap) 71859255Spendry struct vop_select_args /* { 71959255Spendry struct vnode *a_vp; 72059255Spendry int a_which; 72159255Spendry int a_fflags; 72259255Spendry struct ucred *a_cred; 72359255Spendry struct proc *a_p; 72459255Spendry } */ *ap; 72559255Spendry { 72659255Spendry int error = EOPNOTSUPP; 72759255Spendry 72859255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 72959255Spendry case Fctty: 73059255Spendry error = cttyselect(devctty, ap->a_fflags, ap->a_p); 73159255Spendry break; 73259255Spendry 73359255Spendry default: 73459255Spendry error = EOPNOTSUPP; 73559255Spendry break; 73659255Spendry } 73759255Spendry 73859255Spendry return (error); 73959255Spendry } 74059255Spendry 74155017Smckusick fdesc_inactive(ap) 74255017Smckusick struct vop_inactive_args /* { 74355017Smckusick struct vnode *a_vp; 74455017Smckusick } */ *ap; 74553838Spendry { 74654049Spendry struct vnode *vp = ap->a_vp; 74754049Spendry 74853838Spendry /* 74953838Spendry * Clear out the v_type field to avoid 75053838Spendry * nasty things happening in vgone(). 75153838Spendry */ 75254049Spendry vp->v_type = VNON; 75353838Spendry #ifdef FDESC_DIAGNOSTIC 75454049Spendry printf("fdesc_inactive(%x)\n", vp); 75553838Spendry #endif 75653838Spendry return (0); 75753838Spendry } 75853838Spendry 75955017Smckusick fdesc_reclaim(ap) 76055017Smckusick struct vop_reclaim_args /* { 76155017Smckusick struct vnode *a_vp; 76255017Smckusick } */ *ap; 76353838Spendry { 76453838Spendry struct vnode *vp = ap->a_vp; 76559255Spendry int ix; 76659255Spendry 76759255Spendry #ifdef FDESC_DIAGNOSTIC 76853838Spendry printf("fdesc_reclaim(%x)\n", vp); 76959255Spendry #endif 77059255Spendry ix = VTOFDESC(vp)->fd_ix; 77159255Spendry if (ix >= 0 && ix < FD_MAX) { 77259255Spendry if (fdescvp[ix] != vp) 77359255Spendry panic("fdesc_reclaim"); 77459255Spendry fdescvp[ix] = 0; 77559255Spendry } 77653838Spendry if (vp->v_data) { 77753838Spendry FREE(vp->v_data, M_TEMP); 77853838Spendry vp->v_data = 0; 77953838Spendry } 78053838Spendry return (0); 78153838Spendry } 78253838Spendry 78353838Spendry /* 78453838Spendry * Print out the contents of a /dev/fd vnode. 78553838Spendry */ 78653838Spendry /* ARGSUSED */ 78755017Smckusick fdesc_print(ap) 78855017Smckusick struct vop_print_args /* { 78955017Smckusick struct vnode *a_vp; 79055017Smckusick } */ *ap; 79153838Spendry { 79255017Smckusick 79353838Spendry printf("tag VT_NON, fdesc vnode\n"); 79455017Smckusick return (0); 79553838Spendry } 79653838Spendry 79753838Spendry /*void*/ 79855017Smckusick fdesc_vfree(ap) 79955017Smckusick struct vop_vfree_args /* { 80055017Smckusick struct vnode *a_pvp; 80155017Smckusick ino_t a_ino; 80255017Smckusick int a_mode; 80355017Smckusick } */ *ap; 80453838Spendry { 80553838Spendry 80655017Smckusick return (0); 80753838Spendry } 80853838Spendry 80953838Spendry /* 81053838Spendry * /dev/fd vnode unsupported operation 81153838Spendry */ 81253838Spendry fdesc_enotsupp() 81353838Spendry { 81455017Smckusick 81553838Spendry return (EOPNOTSUPP); 81653838Spendry } 81753838Spendry 81853838Spendry /* 81953838Spendry * /dev/fd "should never get here" operation 82053838Spendry */ 82153838Spendry fdesc_badop() 82253838Spendry { 82355017Smckusick 82453838Spendry panic("fdesc: bad op"); 82553838Spendry /* NOTREACHED */ 82653838Spendry } 82753838Spendry 82853838Spendry /* 82953838Spendry * /dev/fd vnode null operation 83053838Spendry */ 83153838Spendry fdesc_nullop() 83253838Spendry { 83355017Smckusick 83453838Spendry return (0); 83553838Spendry } 83653838Spendry 83753838Spendry #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) 83853838Spendry #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) 83953838Spendry #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) 84053838Spendry #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) 84153838Spendry #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) 84253838Spendry #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 84353838Spendry #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) 84453838Spendry #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) 84553838Spendry #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) 84653838Spendry #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) 84753838Spendry #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) 84853838Spendry #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) 84955017Smckusick #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) 85053838Spendry #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 85153838Spendry #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) 85253838Spendry #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 85353838Spendry #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) 85453838Spendry #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) 85553838Spendry #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 85655017Smckusick #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) 85755170Spendry #define fdesc_blkatoff \ 85855017Smckusick ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) 85953838Spendry #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) 86053838Spendry #define fdesc_valloc ((int(*) __P(( \ 86153838Spendry struct vnode *pvp, \ 86253838Spendry int mode, \ 86353838Spendry struct ucred *cred, \ 86453838Spendry struct vnode **vpp))) fdesc_enotsupp) 86555170Spendry #define fdesc_truncate \ 86655017Smckusick ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) 86753838Spendry #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) 86853838Spendry #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) 86953838Spendry 87053838Spendry int (**fdesc_vnodeop_p)(); 87153838Spendry struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { 87253838Spendry { &vop_default_desc, vn_default_error }, 87353838Spendry { &vop_lookup_desc, fdesc_lookup }, /* lookup */ 87453838Spendry { &vop_create_desc, fdesc_create }, /* create */ 87553838Spendry { &vop_mknod_desc, fdesc_mknod }, /* mknod */ 87655017Smckusick { &vop_open_desc, fdesc_open }, /* open */ 87753838Spendry { &vop_close_desc, fdesc_close }, /* close */ 87853838Spendry { &vop_access_desc, fdesc_access }, /* access */ 87953838Spendry { &vop_getattr_desc, fdesc_getattr }, /* getattr */ 88053838Spendry { &vop_setattr_desc, fdesc_setattr }, /* setattr */ 88155017Smckusick { &vop_read_desc, fdesc_read }, /* read */ 88253838Spendry { &vop_write_desc, fdesc_write }, /* write */ 88353838Spendry { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ 88453838Spendry { &vop_select_desc, fdesc_select }, /* select */ 88555017Smckusick { &vop_mmap_desc, fdesc_mmap }, /* mmap */ 88653838Spendry { &vop_fsync_desc, fdesc_fsync }, /* fsync */ 88755017Smckusick { &vop_seek_desc, fdesc_seek }, /* seek */ 88853838Spendry { &vop_remove_desc, fdesc_remove }, /* remove */ 88955017Smckusick { &vop_link_desc, fdesc_link }, /* link */ 89053838Spendry { &vop_rename_desc, fdesc_rename }, /* rename */ 89153838Spendry { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ 89253838Spendry { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ 89353838Spendry { &vop_symlink_desc, fdesc_symlink }, /* symlink */ 89453838Spendry { &vop_readdir_desc, fdesc_readdir }, /* readdir */ 89553838Spendry { &vop_readlink_desc, fdesc_readlink }, /* readlink */ 89653838Spendry { &vop_abortop_desc, fdesc_abortop }, /* abortop */ 89753838Spendry { &vop_inactive_desc, fdesc_inactive }, /* inactive */ 89853838Spendry { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ 89955017Smckusick { &vop_lock_desc, fdesc_lock }, /* lock */ 90053838Spendry { &vop_unlock_desc, fdesc_unlock }, /* unlock */ 90155017Smckusick { &vop_bmap_desc, fdesc_bmap }, /* bmap */ 90253838Spendry { &vop_strategy_desc, fdesc_strategy }, /* strategy */ 90353838Spendry { &vop_print_desc, fdesc_print }, /* print */ 90453838Spendry { &vop_islocked_desc, fdesc_islocked }, /* islocked */ 90553838Spendry { &vop_advlock_desc, fdesc_advlock }, /* advlock */ 90653838Spendry { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ 90753838Spendry { &vop_valloc_desc, fdesc_valloc }, /* valloc */ 90853838Spendry { &vop_vfree_desc, fdesc_vfree }, /* vfree */ 90953838Spendry { &vop_truncate_desc, fdesc_truncate }, /* truncate */ 91053838Spendry { &vop_update_desc, fdesc_update }, /* update */ 91153838Spendry { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ 91253838Spendry { (struct vnodeop_desc*)NULL, (int(*)())NULL } 91353838Spendry }; 91453838Spendry struct vnodeopv_desc fdesc_vnodeop_opv_desc = 91553838Spendry { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; 916