153838Spendry /* 253838Spendry * Copyright (c) 1992 The Regents of the University of California 3*59255Spendry * 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*59255Spendry * @(#)fdesc_vnops.c 7.4 (Berkeley) 04/22/93 1253838Spendry * 13*59255Spendry * $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> 25*59255Spendry #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 38*59255Spendry #define cttyvp(p) ((p)->p_flag&SCTTY ? (p)->p_session->s_ttyvp : NULL) 39*59255Spendry 40*59255Spendry #define FDL_WANT 0x01 41*59255Spendry #define FDL_LOCKED 0x02 42*59255Spendry static int fdescvplock; 43*59255Spendry static struct vnode *fdescvp[FD_MAX]; 44*59255Spendry 45*59255Spendry #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 46*59255Spendry FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 47*59255Spendry #endif 48*59255Spendry 49*59255Spendry fdesc_allocvp(ftype, ix, mp, vpp) 50*59255Spendry fdntype ftype; 51*59255Spendry int ix; 52*59255Spendry struct mount *mp; 53*59255Spendry struct vnode **vpp; 54*59255Spendry { 55*59255Spendry struct vnode **nvpp = 0; 56*59255Spendry int error = 0; 57*59255Spendry 58*59255Spendry /* get stashed copy of the vnode */ 59*59255Spendry if (ix >= 0 && ix < FD_MAX) { 60*59255Spendry nvpp = &fdescvp[ix]; 61*59255Spendry if (*nvpp) { 62*59255Spendry *vpp = *nvpp; 63*59255Spendry VREF(*nvpp); 64*59255Spendry return (error); 65*59255Spendry } 66*59255Spendry } 67*59255Spendry 68*59255Spendry /* 69*59255Spendry * otherwise lock the array while we call getnewvnode 70*59255Spendry * since that can block. 71*59255Spendry */ 72*59255Spendry while (fdescvplock & FDL_LOCKED) { 73*59255Spendry fdescvplock |= FDL_WANT; 74*59255Spendry sleep((caddr_t) &fdescvplock, PINOD); 75*59255Spendry } 76*59255Spendry fdescvplock |= FDL_LOCKED; 77*59255Spendry 78*59255Spendry error = getnewvnode(VT_UFS, mp, fdesc_vnodeop_p, vpp); 79*59255Spendry if (error) 80*59255Spendry goto out; 81*59255Spendry MALLOC((*vpp)->v_data, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 82*59255Spendry if (nvpp) 83*59255Spendry *nvpp = *vpp; 84*59255Spendry VTOFDESC(*vpp)->fd_type = ftype; 85*59255Spendry VTOFDESC(*vpp)->fd_fd = -1; 86*59255Spendry VTOFDESC(*vpp)->fd_link = 0; 87*59255Spendry VTOFDESC(*vpp)->fd_ix = ix; 88*59255Spendry 89*59255Spendry out:; 90*59255Spendry fdescvplock &= ~FDL_LOCKED; 91*59255Spendry 92*59255Spendry if (fdescvplock & FDL_WANT) { 93*59255Spendry fdescvplock &= ~FDL_WANT; 94*59255Spendry wakeup((caddr_t) &fdescvplock); 95*59255Spendry } 96*59255Spendry 97*59255Spendry return (error); 98*59255Spendry } 99*59255Spendry 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; 119*59255Spendry 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); 132*59255Spendry VOP_LOCK(dvp); 13353838Spendry return (0); 13453838Spendry } 13553838Spendry 13653838Spendry p = ap->a_cnp->cn_proc; 13753838Spendry nfiles = p->p_fd->fd_nfiles; 13853838Spendry 139*59255Spendry switch (VTOFDESC(dvp)->fd_type) { 140*59255Spendry default: 141*59255Spendry case Flink: 142*59255Spendry case Fdesc: 143*59255Spendry case Fctty: 144*59255Spendry error = ENOTDIR; 145*59255Spendry goto bad; 146*59255Spendry 147*59255Spendry case Froot: 148*59255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { 149*59255Spendry error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); 150*59255Spendry if (error) 151*59255Spendry goto bad; 152*59255Spendry *vpp = fvp; 153*59255Spendry fvp->v_type = VDIR; 154*59255Spendry VOP_LOCK(fvp); 155*59255Spendry #ifdef FDESC_DIAGNOSTIC 156*59255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 157*59255Spendry #endif 158*59255Spendry return (0); 159*59255Spendry } 160*59255Spendry 161*59255Spendry if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 162*59255Spendry struct vnode *ttyvp = cttyvp(p); 163*59255Spendry if (ttyvp == NULL) { 164*59255Spendry error = ENXIO; 165*59255Spendry goto bad; 166*59255Spendry } 167*59255Spendry error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 168*59255Spendry if (error) 169*59255Spendry goto bad; 170*59255Spendry *vpp = fvp; 171*59255Spendry fvp->v_type = VFIFO; 172*59255Spendry VOP_LOCK(fvp); 173*59255Spendry #ifdef FDESC_DIAGNOSTIC 174*59255Spendry printf("fdesc_lookup: ttyvp = %x\n", fvp); 175*59255Spendry #endif 176*59255Spendry return (0); 177*59255Spendry } 178*59255Spendry 179*59255Spendry ln = 0; 180*59255Spendry switch (ap->a_cnp->cn_namelen) { 181*59255Spendry case 5: 182*59255Spendry if (bcmp(pname, "stdin", 5) == 0) { 183*59255Spendry ln = "fd/0"; 184*59255Spendry fd = FD_STDIN; 185*59255Spendry } 18653838Spendry break; 187*59255Spendry case 6: 188*59255Spendry if (bcmp(pname, "stdout", 6) == 0) { 189*59255Spendry ln = "fd/1"; 190*59255Spendry fd = FD_STDOUT; 191*59255Spendry } else 192*59255Spendry if (bcmp(pname, "stderr", 6) == 0) { 193*59255Spendry ln = "fd/2"; 194*59255Spendry fd = FD_STDERR; 195*59255Spendry } 196*59255Spendry break; 197*59255Spendry } 19853838Spendry 199*59255Spendry if (ln) { 20053838Spendry #ifdef FDESC_DIAGNOSTIC 201*59255Spendry printf("fdesc_lookup: link -> %s\n", ln); 20253838Spendry #endif 203*59255Spendry error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 204*59255Spendry if (error) 205*59255Spendry goto bad; 206*59255Spendry VTOFDESC(fvp)->fd_link = ln; 207*59255Spendry *vpp = fvp; 208*59255Spendry fvp->v_type = VLNK; 209*59255Spendry VOP_LOCK(fvp); 210*59255Spendry #ifdef FDESC_DIAGNOSTIC 211*59255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 212*59255Spendry #endif 213*59255Spendry return (0); 214*59255Spendry } else { 215*59255Spendry error = ENOENT; 216*59255Spendry goto bad; 217*59255Spendry } 21853838Spendry 219*59255Spendry /* fall through */ 22053838Spendry 221*59255Spendry case Fdevfd: 222*59255Spendry if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { 223*59255Spendry error = fdesc_root(dvp->v_mount, vpp); 224*59255Spendry return (error); 225*59255Spendry } 226*59255Spendry 227*59255Spendry fd = 0; 228*59255Spendry while (*pname >= '0' && *pname <= '9') { 229*59255Spendry fd = 10 * fd + *pname++ - '0'; 230*59255Spendry if (fd >= nfiles) 231*59255Spendry break; 232*59255Spendry } 233*59255Spendry 23453838Spendry #ifdef FDESC_DIAGNOSTIC 235*59255Spendry printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); 23653838Spendry #endif 237*59255Spendry if (*pname != '\0') { 238*59255Spendry error = ENOENT; 239*59255Spendry goto bad; 240*59255Spendry } 241*59255Spendry 242*59255Spendry if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 243*59255Spendry error = EBADF; 244*59255Spendry goto bad; 245*59255Spendry } 246*59255Spendry 24753838Spendry #ifdef FDESC_DIAGNOSTIC 248*59255Spendry printf("fdesc_lookup: allocate new vnode\n"); 24953838Spendry #endif 250*59255Spendry error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 251*59255Spendry if (error) 252*59255Spendry goto bad; 253*59255Spendry VTOFDESC(fvp)->fd_fd = fd; 254*59255Spendry *vpp = fvp; 255*59255Spendry #ifdef FDESC_DIAGNOSTIC 256*59255Spendry printf("fdesc_lookup: newvp = %x\n", fvp); 257*59255Spendry #endif 258*59255Spendry return (0); 259*59255Spendry } 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; 278*59255Spendry int error = 0; 27954049Spendry 280*59255Spendry switch (VTOFDESC(vp)->fd_type) { 281*59255Spendry case Fdesc: 282*59255Spendry /* 283*59255Spendry * XXX Kludge: set p->p_dupfd to contain the value of the 284*59255Spendry * the file descriptor being sought for duplication. The error 285*59255Spendry * return ensures that the vnode for this device will be 286*59255Spendry * released by vn_open. Open will detect this special error and 287*59255Spendry * take the actions in dupfdopen. Other callers of vn_open or 288*59255Spendry * VOP_OPEN will simply report the error. 289*59255Spendry */ 290*59255Spendry ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 291*59255Spendry error = ENODEV; 292*59255Spendry break; 29353838Spendry 294*59255Spendry case Fctty: 295*59255Spendry error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); 296*59255Spendry break; 297*59255Spendry } 298*59255Spendry 299*59255Spendry 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 362*59255Spendry printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type); 36353838Spendry #endif 364*59255Spendry 365*59255Spendry switch (VTOFDESC(vp)->fd_type) { 366*59255Spendry case Froot: 367*59255Spendry case Fdevfd: 368*59255Spendry case Flink: 369*59255Spendry case Fctty: 37054049Spendry bzero((caddr_t) vap, sizeof(*vap)); 37154049Spendry vattr_null(vap); 372*59255Spendry vap->va_fileid = VTOFDESC(vp)->fd_ix; 373*59255Spendry 374*59255Spendry switch (VTOFDESC(vp)->fd_type) { 375*59255Spendry case Flink: 376*59255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 377*59255Spendry vap->va_type = VLNK; 378*59255Spendry vap->va_nlink = 1; 379*59255Spendry /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */ 380*59255Spendry vap->va_size = strlen(VTOFDESC(vp)->fd_link); 381*59255Spendry break; 382*59255Spendry 383*59255Spendry case Fctty: 384*59255Spendry vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 385*59255Spendry vap->va_type = VFIFO; 386*59255Spendry vap->va_nlink = 1; 387*59255Spendry /* vap->va_qsize = 0; */ 388*59255Spendry vap->va_size = 0; 389*59255Spendry break; 390*59255Spendry 391*59255Spendry default: 392*59255Spendry vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 393*59255Spendry vap->va_type = VDIR; 394*59255Spendry vap->va_nlink = 2; 395*59255Spendry /* vap->va_qsize = 0; */ 396*59255Spendry vap->va_size = DEV_BSIZE; 397*59255Spendry break; 398*59255Spendry } 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; 403*59255Spendry vap->va_atime.ts_sec = boottime.tv_sec; 404*59255Spendry 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; 412*59255Spendry break; 413*59255Spendry 414*59255Spendry case Fdesc: 415*59255Spendry #ifdef FDESC_DIAGNOSTIC 416*59255Spendry printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd); 417*59255Spendry #endif 418*59255Spendry fd = VTOFDESC(vp)->fd_fd; 419*59255Spendry error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); 420*59255Spendry break; 421*59255Spendry 422*59255Spendry default: 423*59255Spendry panic("fdesc_getattr"); 424*59255Spendry break; 42553838Spendry } 42653838Spendry 42753838Spendry if (error == 0) 42854049Spendry vp->v_type = vap->va_type; 429*59255Spendry 430*59255Spendry #ifdef FDESC_DIAGNOSTIC 431*59255Spendry printf("fdesc_getattr: stat returns 0\n"); 432*59255Spendry #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 */ 452*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 453*59255Spendry case Fdesc: 454*59255Spendry break; 455*59255Spendry 456*59255Spendry case Fctty: 457*59255Spendry return (0); 458*59255Spendry 459*59255Spendry default: 46053838Spendry return (EACCES); 461*59255Spendry } 46253838Spendry 463*59255Spendry 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 497*59255Spendry #define UIO_MX 16 498*59255Spendry 499*59255Spendry static struct dirtmp { 500*59255Spendry u_long d_fileno; 501*59255Spendry u_short d_reclen; 502*59255Spendry u_short d_namlen; 503*59255Spendry char d_name[8]; 504*59255Spendry } rootent[] = { 505*59255Spendry { FD_DEVFD, UIO_MX, 2, "fd" }, 506*59255Spendry { FD_STDIN, UIO_MX, 5, "stdin" }, 507*59255Spendry { FD_STDOUT, UIO_MX, 6, "stdout" }, 508*59255Spendry { FD_STDERR, UIO_MX, 6, "stderr" }, 509*59255Spendry { FD_CTTY, UIO_MX, 3, "tty" }, 510*59255Spendry { 0 } 511*59255Spendry }; 512*59255Spendry 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 525*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 526*59255Spendry case Fctty: 527*59255Spendry return (0); 52853838Spendry 529*59255Spendry case Fdesc: 530*59255Spendry return (ENOTDIR); 531*59255Spendry 532*59255Spendry default: 533*59255Spendry break; 534*59255Spendry } 535*59255Spendry 53654049Spendry fdp = uio->uio_procp->p_fd; 537*59255Spendry 538*59255Spendry if (VTOFDESC(ap->a_vp)->fd_type == Froot) { 539*59255Spendry struct dirent d; 540*59255Spendry struct dirent *dp = &d; 541*59255Spendry struct dirtmp *dt; 542*59255Spendry 543*59255Spendry i = uio->uio_offset / UIO_MX; 544*59255Spendry error = 0; 545*59255Spendry 546*59255Spendry while (uio->uio_resid > 0) { 547*59255Spendry dt = &rootent[i]; 548*59255Spendry if (dt->d_fileno == 0) { 549*59255Spendry /**eofflagp = 1;*/ 550*59255Spendry break; 551*59255Spendry } 552*59255Spendry i++; 553*59255Spendry 554*59255Spendry switch (dt->d_fileno) { 555*59255Spendry case FD_CTTY: 556*59255Spendry if (cttyvp(uio->uio_procp) == NULL) 557*59255Spendry continue; 558*59255Spendry break; 559*59255Spendry 560*59255Spendry case FD_STDIN: 561*59255Spendry case FD_STDOUT: 562*59255Spendry case FD_STDERR: 563*59255Spendry if ((i-FD_STDIN) >= fdp->fd_nfiles) 564*59255Spendry continue; 565*59255Spendry if (fdp->fd_ofiles[i-FD_STDIN] == NULL) 566*59255Spendry continue; 567*59255Spendry break; 568*59255Spendry } 569*59255Spendry bzero(dp, UIO_MX); 570*59255Spendry dp->d_fileno = dt->d_fileno; 571*59255Spendry dp->d_namlen = dt->d_namlen; 572*59255Spendry dp->d_type = DT_UNKNOWN; 573*59255Spendry dp->d_reclen = dt->d_reclen; 574*59255Spendry bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 575*59255Spendry error = uiomove((caddr_t) dp, UIO_MX, uio); 576*59255Spendry if (error) 577*59255Spendry break; 578*59255Spendry } 579*59255Spendry uio->uio_offset = i * UIO_MX; 580*59255Spendry return (error); 581*59255Spendry } 582*59255Spendry 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; 602*59255Spendry 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 617*59255Spendry int 618*59255Spendry fdesc_readlink(ap) 619*59255Spendry struct vop_readlink_args /* { 620*59255Spendry struct vnode *a_vp; 621*59255Spendry struct uio *a_uio; 622*59255Spendry struct ucred *a_cred; 623*59255Spendry } */ *ap; 624*59255Spendry { 625*59255Spendry register struct vnode *vp = ap->a_vp; 626*59255Spendry int error; 627*59255Spendry 628*59255Spendry if (vp->v_type != VLNK) 629*59255Spendry return (EPERM); 630*59255Spendry 631*59255Spendry if (VTOFDESC(vp)->fd_type == Flink) { 632*59255Spendry char *ln = VTOFDESC(vp)->fd_link; 633*59255Spendry error = uiomove(ln, strlen(ln), ap->a_uio); 634*59255Spendry } else { 635*59255Spendry error = EOPNOTSUPP; 636*59255Spendry } 637*59255Spendry 638*59255Spendry return (error); 639*59255Spendry } 640*59255Spendry 641*59255Spendry fdesc_read(ap) 642*59255Spendry struct vop_read_args /* { 643*59255Spendry struct vnode *a_vp; 644*59255Spendry struct uio *a_uio; 645*59255Spendry int a_ioflag; 646*59255Spendry struct ucred *a_cred; 647*59255Spendry } */ *ap; 648*59255Spendry { 649*59255Spendry int error = EOPNOTSUPP; 650*59255Spendry 651*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 652*59255Spendry case Fctty: 653*59255Spendry error = cttyread(devctty, ap->a_uio, ap->a_ioflag); 654*59255Spendry break; 655*59255Spendry 656*59255Spendry default: 657*59255Spendry error = EOPNOTSUPP; 658*59255Spendry break; 659*59255Spendry } 660*59255Spendry 661*59255Spendry return (error); 662*59255Spendry } 663*59255Spendry 664*59255Spendry fdesc_write(ap) 665*59255Spendry struct vop_write_args /* { 666*59255Spendry struct vnode *a_vp; 667*59255Spendry struct uio *a_uio; 668*59255Spendry int a_ioflag; 669*59255Spendry struct ucred *a_cred; 670*59255Spendry } */ *ap; 671*59255Spendry { 672*59255Spendry int error = EOPNOTSUPP; 673*59255Spendry 674*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 675*59255Spendry case Fctty: 676*59255Spendry error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); 677*59255Spendry break; 678*59255Spendry 679*59255Spendry default: 680*59255Spendry error = EOPNOTSUPP; 681*59255Spendry break; 682*59255Spendry } 683*59255Spendry 684*59255Spendry return (error); 685*59255Spendry } 686*59255Spendry 687*59255Spendry fdesc_ioctl(ap) 688*59255Spendry struct vop_ioctl_args /* { 689*59255Spendry struct vnode *a_vp; 690*59255Spendry int a_command; 691*59255Spendry caddr_t a_data; 692*59255Spendry int a_fflag; 693*59255Spendry struct ucred *a_cred; 694*59255Spendry struct proc *a_p; 695*59255Spendry } */ *ap; 696*59255Spendry { 697*59255Spendry int error = EOPNOTSUPP; 698*59255Spendry 699*59255Spendry #ifdef FDESC_DIAGNOSTIC 700*59255Spendry printf("fdesc_ioctl: type = %d, command = %x\n", 701*59255Spendry VTOFDESC(ap->a_vp)->fd_type, ap->a_command); 702*59255Spendry #endif 703*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 704*59255Spendry case Fctty: 705*59255Spendry error = cttyioctl(devctty, ap->a_command, ap->a_data, 706*59255Spendry ap->a_fflag, ap->a_p); 707*59255Spendry break; 708*59255Spendry 709*59255Spendry default: 710*59255Spendry error = EOPNOTSUPP; 711*59255Spendry break; 712*59255Spendry } 713*59255Spendry 714*59255Spendry return (error); 715*59255Spendry } 716*59255Spendry 717*59255Spendry fdesc_select(ap) 718*59255Spendry struct vop_select_args /* { 719*59255Spendry struct vnode *a_vp; 720*59255Spendry int a_which; 721*59255Spendry int a_fflags; 722*59255Spendry struct ucred *a_cred; 723*59255Spendry struct proc *a_p; 724*59255Spendry } */ *ap; 725*59255Spendry { 726*59255Spendry int error = EOPNOTSUPP; 727*59255Spendry 728*59255Spendry switch (VTOFDESC(ap->a_vp)->fd_type) { 729*59255Spendry case Fctty: 730*59255Spendry error = cttyselect(devctty, ap->a_fflags, ap->a_p); 731*59255Spendry break; 732*59255Spendry 733*59255Spendry default: 734*59255Spendry error = EOPNOTSUPP; 735*59255Spendry break; 736*59255Spendry } 737*59255Spendry 738*59255Spendry return (error); 739*59255Spendry } 740*59255Spendry 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; 765*59255Spendry int ix; 766*59255Spendry 767*59255Spendry #ifdef FDESC_DIAGNOSTIC 76853838Spendry printf("fdesc_reclaim(%x)\n", vp); 769*59255Spendry #endif 770*59255Spendry ix = VTOFDESC(vp)->fd_ix; 771*59255Spendry if (ix >= 0 && ix < FD_MAX) { 772*59255Spendry if (fdescvp[ix] != vp) 773*59255Spendry panic("fdesc_reclaim"); 774*59255Spendry fdescvp[ix] = 0; 775*59255Spendry } 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