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*65513Spendry * @(#)fdesc_vnops.c 8.7 (Berkeley) 01/05/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 42*65513Spendry static int fdcache_lock; 4359255Spendry 44*65513Spendry dev_t devctty; 45*65513Spendry 4659255Spendry #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 4759255Spendry FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 4859255Spendry #endif 4959255Spendry 50*65513Spendry #define NFDCACHE 3 51*65513Spendry #define FD_NHASH(ix) ((ix) & NFDCACHE) 52*65513Spendry 53*65513Spendry /* 54*65513Spendry * Cache head 55*65513Spendry */ 56*65513Spendry struct fdcache { 57*65513Spendry struct fdescnode *fc_forw; 58*65513Spendry struct fdescnode *fc_back; 59*65513Spendry }; 60*65513Spendry 61*65513Spendry static struct fdcache fdcache[NFDCACHE]; 62*65513Spendry 63*65513Spendry /* 64*65513Spendry * Initialise cache headers 65*65513Spendry */ 66*65513Spendry fdesc_init() 67*65513Spendry { 68*65513Spendry struct fdcache *fc; 69*65513Spendry 70*65513Spendry devctty = makedev(nchrdev, 0); 71*65513Spendry 72*65513Spendry for (fc = fdcache; fc < fdcache + NFDCACHE; fc++) 73*65513Spendry fc->fc_forw = fc->fc_back = (struct fdescnode *) fc; 74*65513Spendry } 75*65513Spendry 76*65513Spendry /* 77*65513Spendry * Compute hash list for given target vnode 78*65513Spendry */ 79*65513Spendry static struct fdcache * 80*65513Spendry fdesc_hash(ix) 81*65513Spendry int ix; 82*65513Spendry { 83*65513Spendry 84*65513Spendry return (&fdcache[FD_NHASH(ix)]); 85*65513Spendry } 86*65513Spendry 87*65513Spendry int 8859255Spendry fdesc_allocvp(ftype, ix, mp, vpp) 8959255Spendry fdntype ftype; 9059255Spendry int ix; 9159255Spendry struct mount *mp; 9259255Spendry struct vnode **vpp; 9359255Spendry { 94*65513Spendry struct fdcache *fc; 95*65513Spendry struct fdescnode *fd; 9659255Spendry int error = 0; 9759255Spendry 9859457Spendry loop: 99*65513Spendry fc = fdesc_hash(ix); 100*65513Spendry for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) { 101*65513Spendry if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { 102*65513Spendry if (vget(fd->fd_vnode, 0)) 10359457Spendry goto loop; 104*65513Spendry *vpp = fd->fd_vnode; 10559255Spendry return (error); 10659255Spendry } 10759255Spendry } 10859255Spendry 10959255Spendry /* 11059255Spendry * otherwise lock the array while we call getnewvnode 11159255Spendry * since that can block. 11259255Spendry */ 113*65513Spendry if (fdcache_lock & FDL_LOCKED) { 114*65513Spendry fdcache_lock |= FDL_WANT; 115*65513Spendry sleep((caddr_t) &fdcache_lock, PINOD); 11659457Spendry goto loop; 11759255Spendry } 118*65513Spendry fdcache_lock |= FDL_LOCKED; 11959255Spendry 12065380Spendry error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); 12159255Spendry if (error) 12259255Spendry goto out; 123*65513Spendry MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 124*65513Spendry (*vpp)->v_data = fd; 125*65513Spendry fd->fd_vnode = *vpp; 126*65513Spendry fd->fd_type = ftype; 127*65513Spendry fd->fd_fd = -1; 128*65513Spendry fd->fd_link = 0; 129*65513Spendry fd->fd_ix = ix; 130*65513Spendry fc = fdesc_hash(ix); 131*65513Spendry insque(fd, fc); 13259255Spendry 13359255Spendry out:; 134*65513Spendry fdcache_lock &= ~FDL_LOCKED; 13559255Spendry 136*65513Spendry if (fdcache_lock & FDL_WANT) { 137*65513Spendry fdcache_lock &= ~FDL_WANT; 138*65513Spendry wakeup((caddr_t) &fdcache_lock); 13959255Spendry } 14059255Spendry 14159255Spendry return (error); 14259255Spendry } 14359255Spendry 14453838Spendry /* 14553838Spendry * vp is the current namei directory 14653838Spendry * ndp is the name to locate in that directory... 14753838Spendry */ 148*65513Spendry int 14955017Smckusick fdesc_lookup(ap) 15055017Smckusick struct vop_lookup_args /* { 15155017Smckusick struct vnode * a_dvp; 15255017Smckusick struct vnode ** a_vpp; 15355017Smckusick struct componentname * a_cnp; 15455017Smckusick } */ *ap; 15553838Spendry { 15654049Spendry struct vnode **vpp = ap->a_vpp; 15754049Spendry struct vnode *dvp = ap->a_dvp; 15853838Spendry char *pname; 15953838Spendry struct proc *p; 16053838Spendry int nfiles; 16153838Spendry unsigned fd; 16253838Spendry int error; 16353838Spendry struct vnode *fvp; 16459255Spendry char *ln; 16553838Spendry 16653838Spendry pname = ap->a_cnp->cn_nameptr; 16753838Spendry if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 16854049Spendry *vpp = dvp; 16954049Spendry VREF(dvp); 17059255Spendry VOP_LOCK(dvp); 17153838Spendry return (0); 17253838Spendry } 17353838Spendry 17453838Spendry p = ap->a_cnp->cn_proc; 17553838Spendry nfiles = p->p_fd->fd_nfiles; 17653838Spendry 17759255Spendry switch (VTOFDESC(dvp)->fd_type) { 17859255Spendry default: 17959255Spendry case Flink: 18059255Spendry case Fdesc: 18159255Spendry case Fctty: 18259255Spendry error = ENOTDIR; 18359255Spendry goto bad; 18459255Spendry 18559255Spendry case Froot: 18659255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { 18759255Spendry error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); 18859255Spendry if (error) 18959255Spendry goto bad; 19059255Spendry *vpp = fvp; 19159255Spendry fvp->v_type = VDIR; 19259255Spendry VOP_LOCK(fvp); 19359255Spendry return (0); 19459255Spendry } 19559255Spendry 19659255Spendry if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 19759255Spendry struct vnode *ttyvp = cttyvp(p); 19859255Spendry if (ttyvp == NULL) { 19959255Spendry error = ENXIO; 20059255Spendry goto bad; 20159255Spendry } 20259255Spendry error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 20359255Spendry if (error) 20459255Spendry goto bad; 20559255Spendry *vpp = fvp; 20659255Spendry fvp->v_type = VFIFO; 20759255Spendry VOP_LOCK(fvp); 20859255Spendry return (0); 20959255Spendry } 21059255Spendry 21159255Spendry ln = 0; 21259255Spendry switch (ap->a_cnp->cn_namelen) { 21359255Spendry case 5: 21459255Spendry if (bcmp(pname, "stdin", 5) == 0) { 21559255Spendry ln = "fd/0"; 21659255Spendry fd = FD_STDIN; 21759255Spendry } 21853838Spendry break; 21959255Spendry case 6: 22059255Spendry if (bcmp(pname, "stdout", 6) == 0) { 22159255Spendry ln = "fd/1"; 22259255Spendry fd = FD_STDOUT; 22359255Spendry } else 22459255Spendry if (bcmp(pname, "stderr", 6) == 0) { 22559255Spendry ln = "fd/2"; 22659255Spendry fd = FD_STDERR; 22759255Spendry } 22859255Spendry break; 22959255Spendry } 23053838Spendry 23159255Spendry if (ln) { 23259255Spendry error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 23359255Spendry if (error) 23459255Spendry goto bad; 23559255Spendry VTOFDESC(fvp)->fd_link = ln; 23659255Spendry *vpp = fvp; 23759255Spendry fvp->v_type = VLNK; 23859255Spendry VOP_LOCK(fvp); 23959255Spendry return (0); 24059255Spendry } else { 24159255Spendry error = ENOENT; 24259255Spendry goto bad; 24359255Spendry } 24453838Spendry 245*65513Spendry /* FALL THROUGH */ 24653838Spendry 24759255Spendry case Fdevfd: 24859255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { 24959255Spendry error = fdesc_root(dvp->v_mount, vpp); 25059255Spendry return (error); 25159255Spendry } 25259255Spendry 25359255Spendry fd = 0; 25459255Spendry while (*pname >= '0' && *pname <= '9') { 25559255Spendry fd = 10 * fd + *pname++ - '0'; 25659255Spendry if (fd >= nfiles) 25759255Spendry break; 25859255Spendry } 25959255Spendry 26059255Spendry if (*pname != '\0') { 26159255Spendry error = ENOENT; 26259255Spendry goto bad; 26359255Spendry } 26459255Spendry 26559255Spendry if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 26659255Spendry error = EBADF; 26759255Spendry goto bad; 26859255Spendry } 26959255Spendry 27059255Spendry error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 27159255Spendry if (error) 27259255Spendry goto bad; 27359255Spendry VTOFDESC(fvp)->fd_fd = fd; 27459255Spendry *vpp = fvp; 27559255Spendry return (0); 27659255Spendry } 27753838Spendry 27853838Spendry bad:; 27954049Spendry *vpp = NULL; 28053838Spendry return (error); 28153838Spendry } 28253838Spendry 283*65513Spendry int 28455017Smckusick fdesc_open(ap) 28555017Smckusick struct vop_open_args /* { 28655017Smckusick struct vnode *a_vp; 28755017Smckusick int a_mode; 28855017Smckusick struct ucred *a_cred; 28955017Smckusick struct proc *a_p; 29055017Smckusick } */ *ap; 29153838Spendry { 29254049Spendry struct vnode *vp = ap->a_vp; 29359255Spendry int error = 0; 29454049Spendry 29559255Spendry switch (VTOFDESC(vp)->fd_type) { 29659255Spendry case Fdesc: 29759255Spendry /* 29859255Spendry * XXX Kludge: set p->p_dupfd to contain the value of the 29959255Spendry * the file descriptor being sought for duplication. The error 30059255Spendry * return ensures that the vnode for this device will be 30159255Spendry * released by vn_open. Open will detect this special error and 30259255Spendry * take the actions in dupfdopen. Other callers of vn_open or 30359255Spendry * VOP_OPEN will simply report the error. 30459255Spendry */ 30559255Spendry ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 30659255Spendry error = ENODEV; 30759255Spendry break; 30853838Spendry 30959255Spendry case Fctty: 31059255Spendry error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); 31159255Spendry break; 31259255Spendry } 31359255Spendry 31459255Spendry return (error); 31553838Spendry } 31653838Spendry 31753838Spendry static int 31853838Spendry fdesc_attr(fd, vap, cred, p) 31953838Spendry int fd; 32053838Spendry struct vattr *vap; 32153838Spendry struct ucred *cred; 32253838Spendry struct proc *p; 32353838Spendry { 32453838Spendry struct filedesc *fdp = p->p_fd; 32553838Spendry struct file *fp; 32659562Spendry struct stat stb; 32753838Spendry int error; 32853838Spendry 329*65513Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) 33053838Spendry return (EBADF); 33153838Spendry 33253838Spendry switch (fp->f_type) { 33353838Spendry case DTYPE_VNODE: 33453838Spendry error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 33559561Spendry if (error == 0 && vap->va_type == VDIR) { 33659561Spendry /* 33759561Spendry * don't allow directories to show up because 33859561Spendry * that causes loops in the namespace. 33959561Spendry */ 34059561Spendry vap->va_type = VFIFO; 34159561Spendry } 34253838Spendry break; 34353838Spendry 34453838Spendry case DTYPE_SOCKET: 34559562Spendry error = soo_stat((struct socket *)fp->f_data, &stb); 34659562Spendry if (error == 0) { 34759562Spendry vattr_null(vap); 34859562Spendry vap->va_type = VSOCK; 34959562Spendry vap->va_mode = stb.st_mode; 35059562Spendry vap->va_nlink = stb.st_nlink; 35159562Spendry vap->va_uid = stb.st_uid; 35259562Spendry vap->va_gid = stb.st_gid; 35359562Spendry vap->va_fsid = stb.st_dev; 35459562Spendry vap->va_fileid = stb.st_ino; 35559562Spendry vap->va_size = stb.st_size; 35659562Spendry vap->va_blocksize = stb.st_blksize; 35759562Spendry vap->va_atime = stb.st_atimespec; 35859562Spendry vap->va_mtime = stb.st_mtimespec; 35959562Spendry vap->va_ctime = stb.st_ctimespec; 36059562Spendry vap->va_gen = stb.st_gen; 36159562Spendry vap->va_flags = stb.st_flags; 36259562Spendry vap->va_rdev = stb.st_rdev; 36359562Spendry vap->va_bytes = stb.st_blocks * stb.st_blksize; 36459562Spendry } 36553838Spendry break; 36653838Spendry 36753838Spendry default: 36853838Spendry panic("fdesc attr"); 36953838Spendry break; 37053838Spendry } 37153838Spendry 37253838Spendry return (error); 37353838Spendry } 37453838Spendry 375*65513Spendry int 37655017Smckusick fdesc_getattr(ap) 37755017Smckusick struct vop_getattr_args /* { 37855017Smckusick struct vnode *a_vp; 37955017Smckusick struct vattr *a_vap; 38055017Smckusick struct ucred *a_cred; 38155017Smckusick struct proc *a_p; 38255017Smckusick } */ *ap; 38353838Spendry { 38454049Spendry struct vnode *vp = ap->a_vp; 38554049Spendry struct vattr *vap = ap->a_vap; 38653838Spendry unsigned fd; 38763556Smckusick int error = 0; 38853838Spendry 38959255Spendry switch (VTOFDESC(vp)->fd_type) { 39059255Spendry case Froot: 39159255Spendry case Fdevfd: 39259255Spendry case Flink: 39359255Spendry case Fctty: 39454049Spendry bzero((caddr_t) vap, sizeof(*vap)); 39554049Spendry vattr_null(vap); 39659255Spendry vap->va_fileid = VTOFDESC(vp)->fd_ix; 39759255Spendry 39859255Spendry switch (VTOFDESC(vp)->fd_type) { 39959255Spendry case Flink: 40059255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 40159255Spendry vap->va_type = VLNK; 40259255Spendry vap->va_nlink = 1; 40359255Spendry vap->va_size = strlen(VTOFDESC(vp)->fd_link); 40459255Spendry break; 40559255Spendry 40659255Spendry case Fctty: 40759255Spendry vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 40859255Spendry vap->va_type = VFIFO; 40959255Spendry vap->va_nlink = 1; 41059255Spendry vap->va_size = 0; 41159255Spendry break; 41259255Spendry 41359255Spendry default: 41459255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 41559255Spendry vap->va_type = VDIR; 41659255Spendry vap->va_nlink = 2; 41759255Spendry vap->va_size = DEV_BSIZE; 41859255Spendry break; 41959255Spendry } 42054049Spendry vap->va_uid = 0; 42154049Spendry vap->va_gid = 0; 42254049Spendry vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 42354049Spendry vap->va_blocksize = DEV_BSIZE; 42459255Spendry vap->va_atime.ts_sec = boottime.tv_sec; 42559255Spendry vap->va_atime.ts_nsec = 0; 42654049Spendry vap->va_mtime = vap->va_atime; 42764276Smckusick vap->va_ctime = vap->va_mtime; 42854049Spendry vap->va_gen = 0; 42954049Spendry vap->va_flags = 0; 43054049Spendry vap->va_rdev = 0; 43154049Spendry vap->va_bytes = 0; 43259255Spendry break; 43359255Spendry 43459255Spendry case Fdesc: 43559255Spendry fd = VTOFDESC(vp)->fd_fd; 43659255Spendry error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); 43759255Spendry break; 43859255Spendry 43959255Spendry default: 44059255Spendry panic("fdesc_getattr"); 44159255Spendry break; 44253838Spendry } 44353838Spendry 44453838Spendry if (error == 0) 44554049Spendry vp->v_type = vap->va_type; 44659255Spendry 44753838Spendry return (error); 44853838Spendry } 44953838Spendry 450*65513Spendry int 45155017Smckusick fdesc_setattr(ap) 45255017Smckusick struct vop_setattr_args /* { 45355017Smckusick struct vnode *a_vp; 45455017Smckusick struct vattr *a_vap; 45555017Smckusick struct ucred *a_cred; 45655017Smckusick struct proc *a_p; 45755017Smckusick } */ *ap; 45853838Spendry { 45953838Spendry struct filedesc *fdp = ap->a_p->p_fd; 46053838Spendry struct file *fp; 46153838Spendry unsigned fd; 46253838Spendry int error; 46353838Spendry 46453838Spendry /* 46553838Spendry * Can't mess with the root vnode 46653838Spendry */ 46759255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 46859255Spendry case Fdesc: 46959255Spendry break; 47059255Spendry 47159255Spendry case Fctty: 47259255Spendry return (0); 47359255Spendry 47459255Spendry default: 47553838Spendry return (EACCES); 47659255Spendry } 47753838Spendry 47859255Spendry fd = VTOFDESC(ap->a_vp)->fd_fd; 47953838Spendry if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 48053838Spendry return (EBADF); 48153838Spendry } 48253838Spendry 48353838Spendry /* 48453838Spendry * Can setattr the underlying vnode, but not sockets! 48553838Spendry */ 48653838Spendry switch (fp->f_type) { 48753838Spendry case DTYPE_VNODE: 48853838Spendry error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); 48953838Spendry break; 49053838Spendry 49153838Spendry case DTYPE_SOCKET: 49258646Spendry error = 0; 49353838Spendry break; 49453838Spendry 49553838Spendry default: 49653838Spendry panic("fdesc setattr"); 49753838Spendry break; 49853838Spendry } 49953838Spendry 50053838Spendry return (error); 50153838Spendry } 50253838Spendry 50359255Spendry #define UIO_MX 16 50459255Spendry 50559255Spendry static struct dirtmp { 50659255Spendry u_long d_fileno; 50759255Spendry u_short d_reclen; 50859255Spendry u_short d_namlen; 50959255Spendry char d_name[8]; 51059255Spendry } rootent[] = { 51159255Spendry { FD_DEVFD, UIO_MX, 2, "fd" }, 51259255Spendry { FD_STDIN, UIO_MX, 5, "stdin" }, 51359255Spendry { FD_STDOUT, UIO_MX, 6, "stdout" }, 51459255Spendry { FD_STDERR, UIO_MX, 6, "stderr" }, 51559255Spendry { FD_CTTY, UIO_MX, 3, "tty" }, 51659255Spendry { 0 } 51759255Spendry }; 51859255Spendry 519*65513Spendry int 52055017Smckusick fdesc_readdir(ap) 52155017Smckusick struct vop_readdir_args /* { 52255017Smckusick struct vnode *a_vp; 52355017Smckusick struct uio *a_uio; 52455017Smckusick struct ucred *a_cred; 52555017Smckusick } */ *ap; 52653838Spendry { 52754049Spendry struct uio *uio = ap->a_uio; 52853838Spendry struct filedesc *fdp; 52953838Spendry int i; 53053838Spendry int error; 53153838Spendry 53259255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 53359255Spendry case Fctty: 53459255Spendry return (0); 53553838Spendry 53659255Spendry case Fdesc: 53759255Spendry return (ENOTDIR); 53859255Spendry 53959255Spendry default: 54059255Spendry break; 54159255Spendry } 54259255Spendry 54354049Spendry fdp = uio->uio_procp->p_fd; 54459255Spendry 54559255Spendry if (VTOFDESC(ap->a_vp)->fd_type == Froot) { 54659255Spendry struct dirent d; 54759255Spendry struct dirent *dp = &d; 54859255Spendry struct dirtmp *dt; 54959255Spendry 55059255Spendry i = uio->uio_offset / UIO_MX; 55159255Spendry error = 0; 55259255Spendry 55359255Spendry while (uio->uio_resid > 0) { 55459255Spendry dt = &rootent[i]; 55559255Spendry if (dt->d_fileno == 0) { 55659255Spendry /**eofflagp = 1;*/ 55759255Spendry break; 55859255Spendry } 55959255Spendry i++; 56059255Spendry 56159255Spendry switch (dt->d_fileno) { 56259255Spendry case FD_CTTY: 56359255Spendry if (cttyvp(uio->uio_procp) == NULL) 56459255Spendry continue; 56559255Spendry break; 56659255Spendry 56759255Spendry case FD_STDIN: 56859255Spendry case FD_STDOUT: 56959255Spendry case FD_STDERR: 57064276Smckusick if ((dt->d_fileno-FD_STDIN) >= fdp->fd_nfiles) 57159255Spendry continue; 57264276Smckusick if (fdp->fd_ofiles[dt->d_fileno-FD_STDIN] == NULL) 57359255Spendry continue; 57459255Spendry break; 57559255Spendry } 57664276Smckusick bzero((caddr_t) dp, UIO_MX); 57759255Spendry dp->d_fileno = dt->d_fileno; 57859255Spendry dp->d_namlen = dt->d_namlen; 57959255Spendry dp->d_type = DT_UNKNOWN; 58059255Spendry dp->d_reclen = dt->d_reclen; 58159255Spendry bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 58259255Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 58359255Spendry if (error) 58459255Spendry break; 58559255Spendry } 58659255Spendry uio->uio_offset = i * UIO_MX; 58759255Spendry return (error); 58859255Spendry } 58959255Spendry 59054049Spendry i = uio->uio_offset / UIO_MX; 59153838Spendry error = 0; 59254049Spendry while (uio->uio_resid > 0) { 593*65513Spendry if (i >= fdp->fd_nfiles) 59453838Spendry break; 595*65513Spendry 59653838Spendry if (fdp->fd_ofiles[i] != NULL) { 59754981Spendry struct dirent d; 59854981Spendry struct dirent *dp = &d; 599*65513Spendry 60053838Spendry bzero((caddr_t) dp, UIO_MX); 60153838Spendry 60253838Spendry dp->d_namlen = sprintf(dp->d_name, "%d", i); 60353838Spendry dp->d_reclen = UIO_MX; 60454981Spendry dp->d_type = DT_UNKNOWN; 60559255Spendry dp->d_fileno = i + FD_STDIN; 60653838Spendry /* 60753838Spendry * And ship to userland 60853838Spendry */ 60954049Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 61053838Spendry if (error) 61153838Spendry break; 61253838Spendry } 61353838Spendry i++; 61453838Spendry } 61553838Spendry 61654049Spendry uio->uio_offset = i * UIO_MX; 61753838Spendry return (error); 61853838Spendry } 61953838Spendry 62059255Spendry int 62159255Spendry fdesc_readlink(ap) 62259255Spendry struct vop_readlink_args /* { 62359255Spendry struct vnode *a_vp; 62459255Spendry struct uio *a_uio; 62559255Spendry struct ucred *a_cred; 62659255Spendry } */ *ap; 62759255Spendry { 628*65513Spendry struct vnode *vp = ap->a_vp; 62959255Spendry int error; 63059255Spendry 63159255Spendry if (vp->v_type != VLNK) 63259255Spendry return (EPERM); 63359255Spendry 63459255Spendry if (VTOFDESC(vp)->fd_type == Flink) { 63559255Spendry char *ln = VTOFDESC(vp)->fd_link; 63659255Spendry error = uiomove(ln, strlen(ln), ap->a_uio); 63759255Spendry } else { 63859255Spendry error = EOPNOTSUPP; 63959255Spendry } 64059255Spendry 64159255Spendry return (error); 64259255Spendry } 64359255Spendry 644*65513Spendry int 64559255Spendry fdesc_read(ap) 64659255Spendry struct vop_read_args /* { 64759255Spendry struct vnode *a_vp; 64859255Spendry struct uio *a_uio; 64959255Spendry int a_ioflag; 65059255Spendry struct ucred *a_cred; 65159255Spendry } */ *ap; 65259255Spendry { 65359255Spendry int error = EOPNOTSUPP; 65459255Spendry 65559255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 65659255Spendry case Fctty: 65759255Spendry error = cttyread(devctty, ap->a_uio, ap->a_ioflag); 65859255Spendry break; 65959255Spendry 66059255Spendry default: 66159255Spendry error = EOPNOTSUPP; 66259255Spendry break; 66359255Spendry } 66459255Spendry 66559255Spendry return (error); 66659255Spendry } 66759255Spendry 668*65513Spendry int 66959255Spendry fdesc_write(ap) 67059255Spendry struct vop_write_args /* { 67159255Spendry struct vnode *a_vp; 67259255Spendry struct uio *a_uio; 67359255Spendry int a_ioflag; 67459255Spendry struct ucred *a_cred; 67559255Spendry } */ *ap; 67659255Spendry { 67759255Spendry int error = EOPNOTSUPP; 67859255Spendry 67959255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 68059255Spendry case Fctty: 68159255Spendry error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); 68259255Spendry break; 68359255Spendry 68459255Spendry default: 68559255Spendry error = EOPNOTSUPP; 68659255Spendry break; 68759255Spendry } 68859255Spendry 68959255Spendry return (error); 69059255Spendry } 69159255Spendry 692*65513Spendry int 69359255Spendry fdesc_ioctl(ap) 69459255Spendry struct vop_ioctl_args /* { 69559255Spendry struct vnode *a_vp; 69659255Spendry int a_command; 69759255Spendry caddr_t a_data; 69859255Spendry int a_fflag; 69959255Spendry struct ucred *a_cred; 70059255Spendry struct proc *a_p; 70159255Spendry } */ *ap; 70259255Spendry { 70359255Spendry int error = EOPNOTSUPP; 70459255Spendry 70559255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 70659255Spendry case Fctty: 70759255Spendry error = cttyioctl(devctty, ap->a_command, ap->a_data, 70859255Spendry ap->a_fflag, ap->a_p); 70959255Spendry break; 71059255Spendry 71159255Spendry default: 71259255Spendry error = EOPNOTSUPP; 71359255Spendry break; 71459255Spendry } 71559255Spendry 71659255Spendry return (error); 71759255Spendry } 71859255Spendry 719*65513Spendry int 72059255Spendry fdesc_select(ap) 72159255Spendry struct vop_select_args /* { 72259255Spendry struct vnode *a_vp; 72359255Spendry int a_which; 72459255Spendry int a_fflags; 72559255Spendry struct ucred *a_cred; 72659255Spendry struct proc *a_p; 72759255Spendry } */ *ap; 72859255Spendry { 72959255Spendry int error = EOPNOTSUPP; 73059255Spendry 73159255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 73259255Spendry case Fctty: 73359255Spendry error = cttyselect(devctty, ap->a_fflags, ap->a_p); 73459255Spendry break; 73559255Spendry 73659255Spendry default: 73759255Spendry error = EOPNOTSUPP; 73859255Spendry break; 73959255Spendry } 74059255Spendry 74159255Spendry return (error); 74259255Spendry } 74359255Spendry 744*65513Spendry int 74555017Smckusick fdesc_inactive(ap) 74655017Smckusick struct vop_inactive_args /* { 74755017Smckusick struct vnode *a_vp; 74855017Smckusick } */ *ap; 74953838Spendry { 75054049Spendry struct vnode *vp = ap->a_vp; 75154049Spendry 75253838Spendry /* 75353838Spendry * Clear out the v_type field to avoid 75453838Spendry * nasty things happening in vgone(). 75553838Spendry */ 75654049Spendry vp->v_type = VNON; 75753838Spendry return (0); 75853838Spendry } 75953838Spendry 760*65513Spendry int 76155017Smckusick fdesc_reclaim(ap) 76255017Smckusick struct vop_reclaim_args /* { 76355017Smckusick struct vnode *a_vp; 76455017Smckusick } */ *ap; 76553838Spendry { 76653838Spendry struct vnode *vp = ap->a_vp; 76759255Spendry 768*65513Spendry remque(VTOFDESC(vp)); 769*65513Spendry FREE(vp->v_data, M_TEMP); 770*65513Spendry vp->v_data = 0; 771*65513Spendry 77253838Spendry return (0); 77353838Spendry } 77453838Spendry 77553838Spendry /* 77653838Spendry * Print out the contents of a /dev/fd vnode. 77753838Spendry */ 77853838Spendry /* ARGSUSED */ 779*65513Spendry int 78055017Smckusick fdesc_print(ap) 78155017Smckusick struct vop_print_args /* { 78255017Smckusick struct vnode *a_vp; 78355017Smckusick } */ *ap; 78453838Spendry { 78555017Smckusick 78653838Spendry printf("tag VT_NON, fdesc vnode\n"); 78755017Smckusick return (0); 78853838Spendry } 78953838Spendry 79053838Spendry /*void*/ 791*65513Spendry int 79255017Smckusick fdesc_vfree(ap) 79355017Smckusick struct vop_vfree_args /* { 79455017Smckusick struct vnode *a_pvp; 79555017Smckusick ino_t a_ino; 79655017Smckusick int a_mode; 79755017Smckusick } */ *ap; 79853838Spendry { 79953838Spendry 80055017Smckusick return (0); 80153838Spendry } 80253838Spendry 80353838Spendry /* 80453838Spendry * /dev/fd vnode unsupported operation 80553838Spendry */ 806*65513Spendry int 80753838Spendry fdesc_enotsupp() 80853838Spendry { 80955017Smckusick 81053838Spendry return (EOPNOTSUPP); 81153838Spendry } 81253838Spendry 81353838Spendry /* 81453838Spendry * /dev/fd "should never get here" operation 81553838Spendry */ 816*65513Spendry int 81753838Spendry fdesc_badop() 81853838Spendry { 81955017Smckusick 82053838Spendry panic("fdesc: bad op"); 82153838Spendry /* NOTREACHED */ 82253838Spendry } 82353838Spendry 82453838Spendry /* 82553838Spendry * /dev/fd vnode null operation 82653838Spendry */ 827*65513Spendry int 82853838Spendry fdesc_nullop() 82953838Spendry { 83055017Smckusick 83153838Spendry return (0); 83253838Spendry } 83353838Spendry 83453838Spendry #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) 83553838Spendry #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) 83653838Spendry #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) 83753838Spendry #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) 83853838Spendry #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) 83953838Spendry #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 84053838Spendry #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) 84153838Spendry #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) 84253838Spendry #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) 84353838Spendry #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) 84453838Spendry #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) 84553838Spendry #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) 84655017Smckusick #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) 84753838Spendry #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 84853838Spendry #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) 84953838Spendry #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 85053838Spendry #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) 85153838Spendry #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) 85253838Spendry #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 85355017Smckusick #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) 85455170Spendry #define fdesc_blkatoff \ 85555017Smckusick ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) 85653838Spendry #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) 85753838Spendry #define fdesc_valloc ((int(*) __P(( \ 85853838Spendry struct vnode *pvp, \ 85953838Spendry int mode, \ 86053838Spendry struct ucred *cred, \ 86153838Spendry struct vnode **vpp))) fdesc_enotsupp) 86255170Spendry #define fdesc_truncate \ 86355017Smckusick ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) 86453838Spendry #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) 86553838Spendry #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) 86653838Spendry 86753838Spendry int (**fdesc_vnodeop_p)(); 86853838Spendry struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { 86953838Spendry { &vop_default_desc, vn_default_error }, 87053838Spendry { &vop_lookup_desc, fdesc_lookup }, /* lookup */ 87153838Spendry { &vop_create_desc, fdesc_create }, /* create */ 87253838Spendry { &vop_mknod_desc, fdesc_mknod }, /* mknod */ 87355017Smckusick { &vop_open_desc, fdesc_open }, /* open */ 87453838Spendry { &vop_close_desc, fdesc_close }, /* close */ 87553838Spendry { &vop_access_desc, fdesc_access }, /* access */ 87653838Spendry { &vop_getattr_desc, fdesc_getattr }, /* getattr */ 87753838Spendry { &vop_setattr_desc, fdesc_setattr }, /* setattr */ 87855017Smckusick { &vop_read_desc, fdesc_read }, /* read */ 87953838Spendry { &vop_write_desc, fdesc_write }, /* write */ 88053838Spendry { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ 88153838Spendry { &vop_select_desc, fdesc_select }, /* select */ 88255017Smckusick { &vop_mmap_desc, fdesc_mmap }, /* mmap */ 88353838Spendry { &vop_fsync_desc, fdesc_fsync }, /* fsync */ 88455017Smckusick { &vop_seek_desc, fdesc_seek }, /* seek */ 88553838Spendry { &vop_remove_desc, fdesc_remove }, /* remove */ 88655017Smckusick { &vop_link_desc, fdesc_link }, /* link */ 88753838Spendry { &vop_rename_desc, fdesc_rename }, /* rename */ 88853838Spendry { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ 88953838Spendry { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ 89053838Spendry { &vop_symlink_desc, fdesc_symlink }, /* symlink */ 89153838Spendry { &vop_readdir_desc, fdesc_readdir }, /* readdir */ 89253838Spendry { &vop_readlink_desc, fdesc_readlink }, /* readlink */ 89353838Spendry { &vop_abortop_desc, fdesc_abortop }, /* abortop */ 89453838Spendry { &vop_inactive_desc, fdesc_inactive }, /* inactive */ 89553838Spendry { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ 89655017Smckusick { &vop_lock_desc, fdesc_lock }, /* lock */ 89753838Spendry { &vop_unlock_desc, fdesc_unlock }, /* unlock */ 89855017Smckusick { &vop_bmap_desc, fdesc_bmap }, /* bmap */ 89953838Spendry { &vop_strategy_desc, fdesc_strategy }, /* strategy */ 90053838Spendry { &vop_print_desc, fdesc_print }, /* print */ 90153838Spendry { &vop_islocked_desc, fdesc_islocked }, /* islocked */ 90253838Spendry { &vop_advlock_desc, fdesc_advlock }, /* advlock */ 90353838Spendry { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ 90453838Spendry { &vop_valloc_desc, fdesc_valloc }, /* valloc */ 90553838Spendry { &vop_vfree_desc, fdesc_vfree }, /* vfree */ 90653838Spendry { &vop_truncate_desc, fdesc_truncate }, /* truncate */ 90753838Spendry { &vop_update_desc, fdesc_update }, /* update */ 90853838Spendry { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ 90953838Spendry { (struct vnodeop_desc*)NULL, (int(*)())NULL } 91053838Spendry }; 91153838Spendry struct vnodeopv_desc fdesc_vnodeop_opv_desc = 91253838Spendry { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; 913