153838Spendry /* 263557Sbostic * Copyright (c) 1992, 1993 363557Sbostic * The Regents of the University of California. All rights reserved. 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*65380Spendry * @(#)fdesc_vnops.c 8.5 (Berkeley) 01/04/94 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 3864629Sbostic #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (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 5859457Spendry loop: 5959255Spendry /* get stashed copy of the vnode */ 6059255Spendry if (ix >= 0 && ix < FD_MAX) { 6159255Spendry nvpp = &fdescvp[ix]; 6259457Spendry if (*nvpp) { 6365244Smckusick if (vget(*nvpp, 1)) 6459457Spendry goto loop; 6559452Smckusick VOP_UNLOCK(*nvpp); 6659255Spendry *vpp = *nvpp; 6759255Spendry return (error); 6859255Spendry } 6959255Spendry } 7059255Spendry 7159255Spendry /* 7259255Spendry * otherwise lock the array while we call getnewvnode 7359255Spendry * since that can block. 7459255Spendry */ 7559457Spendry if (fdescvplock & FDL_LOCKED) { 7659255Spendry fdescvplock |= FDL_WANT; 7759255Spendry sleep((caddr_t) &fdescvplock, PINOD); 7859457Spendry goto loop; 7959255Spendry } 8059255Spendry fdescvplock |= FDL_LOCKED; 8159255Spendry 82*65380Spendry error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); 8359255Spendry if (error) 8459255Spendry goto out; 8559255Spendry MALLOC((*vpp)->v_data, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 8659255Spendry if (nvpp) 8759255Spendry *nvpp = *vpp; 8859255Spendry VTOFDESC(*vpp)->fd_type = ftype; 8959255Spendry VTOFDESC(*vpp)->fd_fd = -1; 9059255Spendry VTOFDESC(*vpp)->fd_link = 0; 9159255Spendry VTOFDESC(*vpp)->fd_ix = ix; 9259255Spendry 9359255Spendry out:; 9459255Spendry fdescvplock &= ~FDL_LOCKED; 9559255Spendry 9659255Spendry if (fdescvplock & FDL_WANT) { 9759255Spendry fdescvplock &= ~FDL_WANT; 9859255Spendry wakeup((caddr_t) &fdescvplock); 9959255Spendry } 10059255Spendry 10159255Spendry return (error); 10259255Spendry } 10359255Spendry 10453838Spendry /* 10553838Spendry * vp is the current namei directory 10653838Spendry * ndp is the name to locate in that directory... 10753838Spendry */ 10855017Smckusick fdesc_lookup(ap) 10955017Smckusick struct vop_lookup_args /* { 11055017Smckusick struct vnode * a_dvp; 11155017Smckusick struct vnode ** a_vpp; 11255017Smckusick struct componentname * a_cnp; 11355017Smckusick } */ *ap; 11453838Spendry { 11554049Spendry struct vnode **vpp = ap->a_vpp; 11654049Spendry struct vnode *dvp = ap->a_dvp; 11753838Spendry char *pname; 11853838Spendry struct proc *p; 11953838Spendry int nfiles; 12053838Spendry unsigned fd; 12153838Spendry int error; 12253838Spendry struct vnode *fvp; 12359255Spendry char *ln; 12453838Spendry 12553838Spendry #ifdef FDESC_DIAGNOSTIC 12653838Spendry printf("fdesc_lookup(%x)\n", ap); 12754049Spendry printf("fdesc_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp); 12853838Spendry #endif 12953838Spendry pname = ap->a_cnp->cn_nameptr; 13053838Spendry #ifdef FDESC_DIAGNOSTIC 13153838Spendry printf("fdesc_lookup(%s)\n", pname); 13253838Spendry #endif 13353838Spendry if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 13454049Spendry *vpp = dvp; 13554049Spendry VREF(dvp); 13659255Spendry VOP_LOCK(dvp); 13753838Spendry return (0); 13853838Spendry } 13953838Spendry 14053838Spendry p = ap->a_cnp->cn_proc; 14153838Spendry nfiles = p->p_fd->fd_nfiles; 14253838Spendry 14359255Spendry switch (VTOFDESC(dvp)->fd_type) { 14459255Spendry default: 14559255Spendry case Flink: 14659255Spendry case Fdesc: 14759255Spendry case Fctty: 14859255Spendry error = ENOTDIR; 14959255Spendry goto bad; 15059255Spendry 15159255Spendry case Froot: 15259255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { 15359255Spendry error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); 15459255Spendry if (error) 15559255Spendry goto bad; 15659255Spendry *vpp = fvp; 15759255Spendry fvp->v_type = VDIR; 15859255Spendry VOP_LOCK(fvp); 15959255Spendry #ifdef FDESC_DIAGNOSTIC 16059255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 16159255Spendry #endif 16259255Spendry return (0); 16359255Spendry } 16459255Spendry 16559255Spendry if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 16659255Spendry struct vnode *ttyvp = cttyvp(p); 16759255Spendry if (ttyvp == NULL) { 16859255Spendry error = ENXIO; 16959255Spendry goto bad; 17059255Spendry } 17159255Spendry error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 17259255Spendry if (error) 17359255Spendry goto bad; 17459255Spendry *vpp = fvp; 17559255Spendry fvp->v_type = VFIFO; 17659255Spendry VOP_LOCK(fvp); 17759255Spendry #ifdef FDESC_DIAGNOSTIC 17859255Spendry printf("fdesc_lookup: ttyvp = %x\n", fvp); 17959255Spendry #endif 18059255Spendry return (0); 18159255Spendry } 18259255Spendry 18359255Spendry ln = 0; 18459255Spendry switch (ap->a_cnp->cn_namelen) { 18559255Spendry case 5: 18659255Spendry if (bcmp(pname, "stdin", 5) == 0) { 18759255Spendry ln = "fd/0"; 18859255Spendry fd = FD_STDIN; 18959255Spendry } 19053838Spendry break; 19159255Spendry case 6: 19259255Spendry if (bcmp(pname, "stdout", 6) == 0) { 19359255Spendry ln = "fd/1"; 19459255Spendry fd = FD_STDOUT; 19559255Spendry } else 19659255Spendry if (bcmp(pname, "stderr", 6) == 0) { 19759255Spendry ln = "fd/2"; 19859255Spendry fd = FD_STDERR; 19959255Spendry } 20059255Spendry break; 20159255Spendry } 20253838Spendry 20359255Spendry if (ln) { 20453838Spendry #ifdef FDESC_DIAGNOSTIC 20559255Spendry printf("fdesc_lookup: link -> %s\n", ln); 20653838Spendry #endif 20759255Spendry error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 20859255Spendry if (error) 20959255Spendry goto bad; 21059255Spendry VTOFDESC(fvp)->fd_link = ln; 21159255Spendry *vpp = fvp; 21259255Spendry fvp->v_type = VLNK; 21359255Spendry VOP_LOCK(fvp); 21459255Spendry #ifdef FDESC_DIAGNOSTIC 21559255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 21659255Spendry #endif 21759255Spendry return (0); 21859255Spendry } else { 21959255Spendry error = ENOENT; 22059255Spendry goto bad; 22159255Spendry } 22253838Spendry 22359255Spendry /* fall through */ 22453838Spendry 22559255Spendry case Fdevfd: 22659255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { 22759255Spendry error = fdesc_root(dvp->v_mount, vpp); 22859255Spendry return (error); 22959255Spendry } 23059255Spendry 23159255Spendry fd = 0; 23259255Spendry while (*pname >= '0' && *pname <= '9') { 23359255Spendry fd = 10 * fd + *pname++ - '0'; 23459255Spendry if (fd >= nfiles) 23559255Spendry break; 23659255Spendry } 23759255Spendry 23853838Spendry #ifdef FDESC_DIAGNOSTIC 23959255Spendry printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); 24053838Spendry #endif 24159255Spendry if (*pname != '\0') { 24259255Spendry error = ENOENT; 24359255Spendry goto bad; 24459255Spendry } 24559255Spendry 24659255Spendry if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 24759255Spendry error = EBADF; 24859255Spendry goto bad; 24959255Spendry } 25059255Spendry 25153838Spendry #ifdef FDESC_DIAGNOSTIC 25259255Spendry printf("fdesc_lookup: allocate new vnode\n"); 25353838Spendry #endif 25459255Spendry error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 25559255Spendry if (error) 25659255Spendry goto bad; 25759255Spendry VTOFDESC(fvp)->fd_fd = fd; 25859255Spendry *vpp = fvp; 25959255Spendry #ifdef FDESC_DIAGNOSTIC 26059255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 26159255Spendry #endif 26259255Spendry return (0); 26359255Spendry } 26453838Spendry 26553838Spendry bad:; 26654049Spendry *vpp = NULL; 26753838Spendry #ifdef FDESC_DIAGNOSTIC 26853838Spendry printf("fdesc_lookup: error = %d\n", error); 26953838Spendry #endif 27053838Spendry return (error); 27153838Spendry } 27253838Spendry 27355017Smckusick fdesc_open(ap) 27455017Smckusick struct vop_open_args /* { 27555017Smckusick struct vnode *a_vp; 27655017Smckusick int a_mode; 27755017Smckusick struct ucred *a_cred; 27855017Smckusick struct proc *a_p; 27955017Smckusick } */ *ap; 28053838Spendry { 28154049Spendry struct vnode *vp = ap->a_vp; 28259255Spendry int error = 0; 28354049Spendry 28459255Spendry switch (VTOFDESC(vp)->fd_type) { 28559255Spendry case Fdesc: 28659255Spendry /* 28759255Spendry * XXX Kludge: set p->p_dupfd to contain the value of the 28859255Spendry * the file descriptor being sought for duplication. The error 28959255Spendry * return ensures that the vnode for this device will be 29059255Spendry * released by vn_open. Open will detect this special error and 29159255Spendry * take the actions in dupfdopen. Other callers of vn_open or 29259255Spendry * VOP_OPEN will simply report the error. 29359255Spendry */ 29459255Spendry ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 29559255Spendry error = ENODEV; 29659255Spendry break; 29753838Spendry 29859255Spendry case Fctty: 29959255Spendry error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); 30059255Spendry break; 30159255Spendry } 30259255Spendry 30359255Spendry return (error); 30453838Spendry } 30553838Spendry 30653838Spendry static int 30753838Spendry fdesc_attr(fd, vap, cred, p) 30853838Spendry int fd; 30953838Spendry struct vattr *vap; 31053838Spendry struct ucred *cred; 31153838Spendry struct proc *p; 31253838Spendry { 31353838Spendry struct filedesc *fdp = p->p_fd; 31453838Spendry struct file *fp; 31559562Spendry struct stat stb; 31653838Spendry int error; 31753838Spendry 31853838Spendry #ifdef FDESC_DIAGNOSTIC 31953838Spendry printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 32053838Spendry #endif 32153838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 32253838Spendry #ifdef FDESC_DIAGNOSTIC 32353838Spendry printf("fdesc_attr: fp = %x (EBADF)\n", fp); 32453838Spendry #endif 32553838Spendry return (EBADF); 32653838Spendry } 32753838Spendry 32853838Spendry switch (fp->f_type) { 32953838Spendry case DTYPE_VNODE: 33053838Spendry error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 33159561Spendry if (error == 0 && vap->va_type == VDIR) { 33259561Spendry /* 33359561Spendry * don't allow directories to show up because 33459561Spendry * that causes loops in the namespace. 33559561Spendry */ 33659561Spendry vap->va_type = VFIFO; 33759561Spendry } 33853838Spendry break; 33953838Spendry 34053838Spendry case DTYPE_SOCKET: 34159562Spendry error = soo_stat((struct socket *)fp->f_data, &stb); 34259562Spendry if (error == 0) { 34359562Spendry vattr_null(vap); 34459562Spendry vap->va_type = VSOCK; 34559562Spendry vap->va_mode = stb.st_mode; 34659562Spendry vap->va_nlink = stb.st_nlink; 34759562Spendry vap->va_uid = stb.st_uid; 34859562Spendry vap->va_gid = stb.st_gid; 34959562Spendry vap->va_fsid = stb.st_dev; 35059562Spendry vap->va_fileid = stb.st_ino; 35159562Spendry vap->va_size = stb.st_size; 35259562Spendry vap->va_blocksize = stb.st_blksize; 35359562Spendry vap->va_atime = stb.st_atimespec; 35459562Spendry vap->va_mtime = stb.st_mtimespec; 35559562Spendry vap->va_ctime = stb.st_ctimespec; 35659562Spendry vap->va_gen = stb.st_gen; 35759562Spendry vap->va_flags = stb.st_flags; 35859562Spendry vap->va_rdev = stb.st_rdev; 35959562Spendry vap->va_bytes = stb.st_blocks * stb.st_blksize; 36059562Spendry } 36153838Spendry break; 36253838Spendry 36353838Spendry default: 36453838Spendry panic("fdesc attr"); 36553838Spendry break; 36653838Spendry } 36753838Spendry 36853838Spendry #ifdef FDESC_DIAGNOSTIC 36953838Spendry printf("fdesc_attr: returns error %d\n", error); 37053838Spendry #endif 37153838Spendry return (error); 37253838Spendry } 37353838Spendry 37455017Smckusick fdesc_getattr(ap) 37555017Smckusick struct vop_getattr_args /* { 37655017Smckusick struct vnode *a_vp; 37755017Smckusick struct vattr *a_vap; 37855017Smckusick struct ucred *a_cred; 37955017Smckusick struct proc *a_p; 38055017Smckusick } */ *ap; 38153838Spendry { 38254049Spendry struct vnode *vp = ap->a_vp; 38354049Spendry struct vattr *vap = ap->a_vap; 38453838Spendry unsigned fd; 38563556Smckusick int error = 0; 38653838Spendry 38753838Spendry #ifdef FDESC_DIAGNOSTIC 38859255Spendry printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type); 38953838Spendry #endif 39059255Spendry 39159255Spendry switch (VTOFDESC(vp)->fd_type) { 39259255Spendry case Froot: 39359255Spendry case Fdevfd: 39459255Spendry case Flink: 39559255Spendry case Fctty: 39654049Spendry bzero((caddr_t) vap, sizeof(*vap)); 39754049Spendry vattr_null(vap); 39859255Spendry vap->va_fileid = VTOFDESC(vp)->fd_ix; 39959255Spendry 40059255Spendry switch (VTOFDESC(vp)->fd_type) { 40159255Spendry case Flink: 40259255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 40359255Spendry vap->va_type = VLNK; 40459255Spendry vap->va_nlink = 1; 40559255Spendry /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */ 40659255Spendry vap->va_size = strlen(VTOFDESC(vp)->fd_link); 40759255Spendry break; 40859255Spendry 40959255Spendry case Fctty: 41059255Spendry vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 41159255Spendry vap->va_type = VFIFO; 41259255Spendry vap->va_nlink = 1; 41359255Spendry /* vap->va_qsize = 0; */ 41459255Spendry vap->va_size = 0; 41559255Spendry break; 41659255Spendry 41759255Spendry default: 41859255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 41959255Spendry vap->va_type = VDIR; 42059255Spendry vap->va_nlink = 2; 42159255Spendry /* vap->va_qsize = 0; */ 42259255Spendry vap->va_size = DEV_BSIZE; 42359255Spendry break; 42459255Spendry } 42554049Spendry vap->va_uid = 0; 42654049Spendry vap->va_gid = 0; 42754049Spendry vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 42854049Spendry vap->va_blocksize = DEV_BSIZE; 42959255Spendry vap->va_atime.ts_sec = boottime.tv_sec; 43059255Spendry vap->va_atime.ts_nsec = 0; 43154049Spendry vap->va_mtime = vap->va_atime; 43264276Smckusick vap->va_ctime = vap->va_mtime; 43354049Spendry vap->va_gen = 0; 43454049Spendry vap->va_flags = 0; 43554049Spendry vap->va_rdev = 0; 43654049Spendry /* vap->va_qbytes = 0; */ 43754049Spendry vap->va_bytes = 0; 43859255Spendry break; 43959255Spendry 44059255Spendry case Fdesc: 44159255Spendry #ifdef FDESC_DIAGNOSTIC 44259255Spendry printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd); 44359255Spendry #endif 44459255Spendry fd = VTOFDESC(vp)->fd_fd; 44559255Spendry error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); 44659255Spendry break; 44759255Spendry 44859255Spendry default: 44959255Spendry panic("fdesc_getattr"); 45059255Spendry break; 45153838Spendry } 45253838Spendry 45353838Spendry if (error == 0) 45454049Spendry vp->v_type = vap->va_type; 45559255Spendry 45659255Spendry #ifdef FDESC_DIAGNOSTIC 45759255Spendry printf("fdesc_getattr: stat returns 0\n"); 45859255Spendry #endif 45953838Spendry return (error); 46053838Spendry } 46153838Spendry 46255017Smckusick fdesc_setattr(ap) 46355017Smckusick struct vop_setattr_args /* { 46455017Smckusick struct vnode *a_vp; 46555017Smckusick struct vattr *a_vap; 46655017Smckusick struct ucred *a_cred; 46755017Smckusick struct proc *a_p; 46855017Smckusick } */ *ap; 46953838Spendry { 47053838Spendry struct filedesc *fdp = ap->a_p->p_fd; 47153838Spendry struct file *fp; 47253838Spendry unsigned fd; 47353838Spendry int error; 47453838Spendry 47553838Spendry /* 47653838Spendry * Can't mess with the root vnode 47753838Spendry */ 47859255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 47959255Spendry case Fdesc: 48059255Spendry break; 48159255Spendry 48259255Spendry case Fctty: 48359255Spendry return (0); 48459255Spendry 48559255Spendry default: 48653838Spendry return (EACCES); 48759255Spendry } 48853838Spendry 48959255Spendry fd = VTOFDESC(ap->a_vp)->fd_fd; 49053838Spendry #ifdef FDESC_DIAGNOSTIC 49153838Spendry printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 49253838Spendry #endif 49353838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 49453838Spendry #ifdef FDESC_DIAGNOSTIC 49553838Spendry printf("fdesc_setattr: fp = %x (EBADF)\n", fp); 49653838Spendry #endif 49753838Spendry return (EBADF); 49853838Spendry } 49953838Spendry 50053838Spendry /* 50153838Spendry * Can setattr the underlying vnode, but not sockets! 50253838Spendry */ 50353838Spendry switch (fp->f_type) { 50453838Spendry case DTYPE_VNODE: 50553838Spendry error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); 50653838Spendry break; 50753838Spendry 50853838Spendry case DTYPE_SOCKET: 50958646Spendry error = 0; 51053838Spendry break; 51153838Spendry 51253838Spendry default: 51353838Spendry panic("fdesc setattr"); 51453838Spendry break; 51553838Spendry } 51653838Spendry 51753838Spendry #ifdef FDESC_DIAGNOSTIC 51853838Spendry printf("fdesc_setattr: returns error %d\n", error); 51953838Spendry #endif 52053838Spendry return (error); 52153838Spendry } 52253838Spendry 52359255Spendry #define UIO_MX 16 52459255Spendry 52559255Spendry static struct dirtmp { 52659255Spendry u_long d_fileno; 52759255Spendry u_short d_reclen; 52859255Spendry u_short d_namlen; 52959255Spendry char d_name[8]; 53059255Spendry } rootent[] = { 53159255Spendry { FD_DEVFD, UIO_MX, 2, "fd" }, 53259255Spendry { FD_STDIN, UIO_MX, 5, "stdin" }, 53359255Spendry { FD_STDOUT, UIO_MX, 6, "stdout" }, 53459255Spendry { FD_STDERR, UIO_MX, 6, "stderr" }, 53559255Spendry { FD_CTTY, UIO_MX, 3, "tty" }, 53659255Spendry { 0 } 53759255Spendry }; 53859255Spendry 53955017Smckusick fdesc_readdir(ap) 54055017Smckusick struct vop_readdir_args /* { 54155017Smckusick struct vnode *a_vp; 54255017Smckusick struct uio *a_uio; 54355017Smckusick struct ucred *a_cred; 54455017Smckusick } */ *ap; 54553838Spendry { 54654049Spendry struct uio *uio = ap->a_uio; 54753838Spendry struct filedesc *fdp; 54853838Spendry int i; 54953838Spendry int error; 55053838Spendry 55159255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 55259255Spendry case Fctty: 55359255Spendry return (0); 55453838Spendry 55559255Spendry case Fdesc: 55659255Spendry return (ENOTDIR); 55759255Spendry 55859255Spendry default: 55959255Spendry break; 56059255Spendry } 56159255Spendry 56254049Spendry fdp = uio->uio_procp->p_fd; 56359255Spendry 56459255Spendry if (VTOFDESC(ap->a_vp)->fd_type == Froot) { 56559255Spendry struct dirent d; 56659255Spendry struct dirent *dp = &d; 56759255Spendry struct dirtmp *dt; 56859255Spendry 56959255Spendry i = uio->uio_offset / UIO_MX; 57059255Spendry error = 0; 57159255Spendry 57259255Spendry while (uio->uio_resid > 0) { 57359255Spendry dt = &rootent[i]; 57459255Spendry if (dt->d_fileno == 0) { 57559255Spendry /**eofflagp = 1;*/ 57659255Spendry break; 57759255Spendry } 57859255Spendry i++; 57959255Spendry 58059255Spendry switch (dt->d_fileno) { 58159255Spendry case FD_CTTY: 58259255Spendry if (cttyvp(uio->uio_procp) == NULL) 58359255Spendry continue; 58459255Spendry break; 58559255Spendry 58659255Spendry case FD_STDIN: 58759255Spendry case FD_STDOUT: 58859255Spendry case FD_STDERR: 58964276Smckusick if ((dt->d_fileno-FD_STDIN) >= fdp->fd_nfiles) 59059255Spendry continue; 59164276Smckusick if (fdp->fd_ofiles[dt->d_fileno-FD_STDIN] == NULL) 59259255Spendry continue; 59359255Spendry break; 59459255Spendry } 59564276Smckusick bzero((caddr_t) dp, UIO_MX); 59659255Spendry dp->d_fileno = dt->d_fileno; 59759255Spendry dp->d_namlen = dt->d_namlen; 59859255Spendry dp->d_type = DT_UNKNOWN; 59959255Spendry dp->d_reclen = dt->d_reclen; 60059255Spendry bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 60159255Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 60259255Spendry if (error) 60359255Spendry break; 60459255Spendry } 60559255Spendry uio->uio_offset = i * UIO_MX; 60659255Spendry return (error); 60759255Spendry } 60859255Spendry 60954049Spendry i = uio->uio_offset / UIO_MX; 61053838Spendry error = 0; 61154049Spendry while (uio->uio_resid > 0) { 61253838Spendry if (i >= fdp->fd_nfiles) { 61354980Spendry /* *ap->a_eofflagp = 1; */ 61453838Spendry break; 61553838Spendry } 61653838Spendry if (fdp->fd_ofiles[i] != NULL) { 61754981Spendry struct dirent d; 61854981Spendry struct dirent *dp = &d; 61953838Spendry char *cp = dp->d_name; 62053838Spendry bzero((caddr_t) dp, UIO_MX); 62153838Spendry 62253838Spendry dp->d_namlen = sprintf(dp->d_name, "%d", i); 62353838Spendry /* 62453838Spendry * Fill in the remaining fields 62553838Spendry */ 62653838Spendry dp->d_reclen = UIO_MX; 62754981Spendry dp->d_type = DT_UNKNOWN; 62859255Spendry dp->d_fileno = i + FD_STDIN; 62953838Spendry /* 63053838Spendry * And ship to userland 63153838Spendry */ 63254049Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 63353838Spendry if (error) 63453838Spendry break; 63553838Spendry } 63653838Spendry i++; 63753838Spendry } 63853838Spendry 63954049Spendry uio->uio_offset = i * UIO_MX; 64053838Spendry return (error); 64153838Spendry } 64253838Spendry 64359255Spendry int 64459255Spendry fdesc_readlink(ap) 64559255Spendry struct vop_readlink_args /* { 64659255Spendry struct vnode *a_vp; 64759255Spendry struct uio *a_uio; 64859255Spendry struct ucred *a_cred; 64959255Spendry } */ *ap; 65059255Spendry { 65159255Spendry register struct vnode *vp = ap->a_vp; 65259255Spendry int error; 65359255Spendry 65459255Spendry if (vp->v_type != VLNK) 65559255Spendry return (EPERM); 65659255Spendry 65759255Spendry if (VTOFDESC(vp)->fd_type == Flink) { 65859255Spendry char *ln = VTOFDESC(vp)->fd_link; 65959255Spendry error = uiomove(ln, strlen(ln), ap->a_uio); 66059255Spendry } else { 66159255Spendry error = EOPNOTSUPP; 66259255Spendry } 66359255Spendry 66459255Spendry return (error); 66559255Spendry } 66659255Spendry 66759255Spendry fdesc_read(ap) 66859255Spendry struct vop_read_args /* { 66959255Spendry struct vnode *a_vp; 67059255Spendry struct uio *a_uio; 67159255Spendry int a_ioflag; 67259255Spendry struct ucred *a_cred; 67359255Spendry } */ *ap; 67459255Spendry { 67559255Spendry int error = EOPNOTSUPP; 67659255Spendry 67759255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 67859255Spendry case Fctty: 67959255Spendry error = cttyread(devctty, ap->a_uio, ap->a_ioflag); 68059255Spendry break; 68159255Spendry 68259255Spendry default: 68359255Spendry error = EOPNOTSUPP; 68459255Spendry break; 68559255Spendry } 68659255Spendry 68759255Spendry return (error); 68859255Spendry } 68959255Spendry 69059255Spendry fdesc_write(ap) 69159255Spendry struct vop_write_args /* { 69259255Spendry struct vnode *a_vp; 69359255Spendry struct uio *a_uio; 69459255Spendry int a_ioflag; 69559255Spendry struct ucred *a_cred; 69659255Spendry } */ *ap; 69759255Spendry { 69859255Spendry int error = EOPNOTSUPP; 69959255Spendry 70059255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 70159255Spendry case Fctty: 70259255Spendry error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); 70359255Spendry break; 70459255Spendry 70559255Spendry default: 70659255Spendry error = EOPNOTSUPP; 70759255Spendry break; 70859255Spendry } 70959255Spendry 71059255Spendry return (error); 71159255Spendry } 71259255Spendry 71359255Spendry fdesc_ioctl(ap) 71459255Spendry struct vop_ioctl_args /* { 71559255Spendry struct vnode *a_vp; 71659255Spendry int a_command; 71759255Spendry caddr_t a_data; 71859255Spendry int a_fflag; 71959255Spendry struct ucred *a_cred; 72059255Spendry struct proc *a_p; 72159255Spendry } */ *ap; 72259255Spendry { 72359255Spendry int error = EOPNOTSUPP; 72459255Spendry 72559255Spendry #ifdef FDESC_DIAGNOSTIC 72659255Spendry printf("fdesc_ioctl: type = %d, command = %x\n", 72759255Spendry VTOFDESC(ap->a_vp)->fd_type, ap->a_command); 72859255Spendry #endif 72959255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 73059255Spendry case Fctty: 73159255Spendry error = cttyioctl(devctty, ap->a_command, ap->a_data, 73259255Spendry ap->a_fflag, ap->a_p); 73359255Spendry break; 73459255Spendry 73559255Spendry default: 73659255Spendry error = EOPNOTSUPP; 73759255Spendry break; 73859255Spendry } 73959255Spendry 74059255Spendry return (error); 74159255Spendry } 74259255Spendry 74359255Spendry fdesc_select(ap) 74459255Spendry struct vop_select_args /* { 74559255Spendry struct vnode *a_vp; 74659255Spendry int a_which; 74759255Spendry int a_fflags; 74859255Spendry struct ucred *a_cred; 74959255Spendry struct proc *a_p; 75059255Spendry } */ *ap; 75159255Spendry { 75259255Spendry int error = EOPNOTSUPP; 75359255Spendry 75459255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 75559255Spendry case Fctty: 75659255Spendry error = cttyselect(devctty, ap->a_fflags, ap->a_p); 75759255Spendry break; 75859255Spendry 75959255Spendry default: 76059255Spendry error = EOPNOTSUPP; 76159255Spendry break; 76259255Spendry } 76359255Spendry 76459255Spendry return (error); 76559255Spendry } 76659255Spendry 76755017Smckusick fdesc_inactive(ap) 76855017Smckusick struct vop_inactive_args /* { 76955017Smckusick struct vnode *a_vp; 77055017Smckusick } */ *ap; 77153838Spendry { 77254049Spendry struct vnode *vp = ap->a_vp; 77354049Spendry 77453838Spendry /* 77553838Spendry * Clear out the v_type field to avoid 77653838Spendry * nasty things happening in vgone(). 77753838Spendry */ 77854049Spendry vp->v_type = VNON; 77953838Spendry #ifdef FDESC_DIAGNOSTIC 78054049Spendry printf("fdesc_inactive(%x)\n", vp); 78153838Spendry #endif 78253838Spendry return (0); 78353838Spendry } 78453838Spendry 78555017Smckusick fdesc_reclaim(ap) 78655017Smckusick struct vop_reclaim_args /* { 78755017Smckusick struct vnode *a_vp; 78855017Smckusick } */ *ap; 78953838Spendry { 79053838Spendry struct vnode *vp = ap->a_vp; 79159255Spendry int ix; 79259255Spendry 79359255Spendry #ifdef FDESC_DIAGNOSTIC 79453838Spendry printf("fdesc_reclaim(%x)\n", vp); 79559255Spendry #endif 79659255Spendry ix = VTOFDESC(vp)->fd_ix; 79759255Spendry if (ix >= 0 && ix < FD_MAX) { 79859255Spendry if (fdescvp[ix] != vp) 79959255Spendry panic("fdesc_reclaim"); 80059255Spendry fdescvp[ix] = 0; 80159255Spendry } 80253838Spendry if (vp->v_data) { 80353838Spendry FREE(vp->v_data, M_TEMP); 80453838Spendry vp->v_data = 0; 80553838Spendry } 80653838Spendry return (0); 80753838Spendry } 80853838Spendry 80953838Spendry /* 81053838Spendry * Print out the contents of a /dev/fd vnode. 81153838Spendry */ 81253838Spendry /* ARGSUSED */ 81355017Smckusick fdesc_print(ap) 81455017Smckusick struct vop_print_args /* { 81555017Smckusick struct vnode *a_vp; 81655017Smckusick } */ *ap; 81753838Spendry { 81855017Smckusick 81953838Spendry printf("tag VT_NON, fdesc vnode\n"); 82055017Smckusick return (0); 82153838Spendry } 82253838Spendry 82353838Spendry /*void*/ 82455017Smckusick fdesc_vfree(ap) 82555017Smckusick struct vop_vfree_args /* { 82655017Smckusick struct vnode *a_pvp; 82755017Smckusick ino_t a_ino; 82855017Smckusick int a_mode; 82955017Smckusick } */ *ap; 83053838Spendry { 83153838Spendry 83255017Smckusick return (0); 83353838Spendry } 83453838Spendry 83553838Spendry /* 83653838Spendry * /dev/fd vnode unsupported operation 83753838Spendry */ 83853838Spendry fdesc_enotsupp() 83953838Spendry { 84055017Smckusick 84153838Spendry return (EOPNOTSUPP); 84253838Spendry } 84353838Spendry 84453838Spendry /* 84553838Spendry * /dev/fd "should never get here" operation 84653838Spendry */ 84753838Spendry fdesc_badop() 84853838Spendry { 84955017Smckusick 85053838Spendry panic("fdesc: bad op"); 85153838Spendry /* NOTREACHED */ 85253838Spendry } 85353838Spendry 85453838Spendry /* 85553838Spendry * /dev/fd vnode null operation 85653838Spendry */ 85753838Spendry fdesc_nullop() 85853838Spendry { 85955017Smckusick 86053838Spendry return (0); 86153838Spendry } 86253838Spendry 86353838Spendry #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) 86453838Spendry #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) 86553838Spendry #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) 86653838Spendry #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) 86753838Spendry #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) 86853838Spendry #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 86953838Spendry #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) 87053838Spendry #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) 87153838Spendry #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) 87253838Spendry #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) 87353838Spendry #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) 87453838Spendry #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) 87555017Smckusick #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) 87653838Spendry #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 87753838Spendry #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) 87853838Spendry #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 87953838Spendry #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) 88053838Spendry #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) 88153838Spendry #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 88255017Smckusick #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) 88355170Spendry #define fdesc_blkatoff \ 88455017Smckusick ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) 88553838Spendry #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) 88653838Spendry #define fdesc_valloc ((int(*) __P(( \ 88753838Spendry struct vnode *pvp, \ 88853838Spendry int mode, \ 88953838Spendry struct ucred *cred, \ 89053838Spendry struct vnode **vpp))) fdesc_enotsupp) 89155170Spendry #define fdesc_truncate \ 89255017Smckusick ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) 89353838Spendry #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) 89453838Spendry #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) 89553838Spendry 89653838Spendry int (**fdesc_vnodeop_p)(); 89753838Spendry struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { 89853838Spendry { &vop_default_desc, vn_default_error }, 89953838Spendry { &vop_lookup_desc, fdesc_lookup }, /* lookup */ 90053838Spendry { &vop_create_desc, fdesc_create }, /* create */ 90153838Spendry { &vop_mknod_desc, fdesc_mknod }, /* mknod */ 90255017Smckusick { &vop_open_desc, fdesc_open }, /* open */ 90353838Spendry { &vop_close_desc, fdesc_close }, /* close */ 90453838Spendry { &vop_access_desc, fdesc_access }, /* access */ 90553838Spendry { &vop_getattr_desc, fdesc_getattr }, /* getattr */ 90653838Spendry { &vop_setattr_desc, fdesc_setattr }, /* setattr */ 90755017Smckusick { &vop_read_desc, fdesc_read }, /* read */ 90853838Spendry { &vop_write_desc, fdesc_write }, /* write */ 90953838Spendry { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ 91053838Spendry { &vop_select_desc, fdesc_select }, /* select */ 91155017Smckusick { &vop_mmap_desc, fdesc_mmap }, /* mmap */ 91253838Spendry { &vop_fsync_desc, fdesc_fsync }, /* fsync */ 91355017Smckusick { &vop_seek_desc, fdesc_seek }, /* seek */ 91453838Spendry { &vop_remove_desc, fdesc_remove }, /* remove */ 91555017Smckusick { &vop_link_desc, fdesc_link }, /* link */ 91653838Spendry { &vop_rename_desc, fdesc_rename }, /* rename */ 91753838Spendry { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ 91853838Spendry { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ 91953838Spendry { &vop_symlink_desc, fdesc_symlink }, /* symlink */ 92053838Spendry { &vop_readdir_desc, fdesc_readdir }, /* readdir */ 92153838Spendry { &vop_readlink_desc, fdesc_readlink }, /* readlink */ 92253838Spendry { &vop_abortop_desc, fdesc_abortop }, /* abortop */ 92353838Spendry { &vop_inactive_desc, fdesc_inactive }, /* inactive */ 92453838Spendry { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ 92555017Smckusick { &vop_lock_desc, fdesc_lock }, /* lock */ 92653838Spendry { &vop_unlock_desc, fdesc_unlock }, /* unlock */ 92755017Smckusick { &vop_bmap_desc, fdesc_bmap }, /* bmap */ 92853838Spendry { &vop_strategy_desc, fdesc_strategy }, /* strategy */ 92953838Spendry { &vop_print_desc, fdesc_print }, /* print */ 93053838Spendry { &vop_islocked_desc, fdesc_islocked }, /* islocked */ 93153838Spendry { &vop_advlock_desc, fdesc_advlock }, /* advlock */ 93253838Spendry { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ 93353838Spendry { &vop_valloc_desc, fdesc_valloc }, /* valloc */ 93453838Spendry { &vop_vfree_desc, fdesc_vfree }, /* vfree */ 93553838Spendry { &vop_truncate_desc, fdesc_truncate }, /* truncate */ 93653838Spendry { &vop_update_desc, fdesc_update }, /* update */ 93753838Spendry { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ 93853838Spendry { (struct vnodeop_desc*)NULL, (int(*)())NULL } 93953838Spendry }; 94053838Spendry struct vnodeopv_desc fdesc_vnodeop_opv_desc = 94153838Spendry { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; 942