fdesc_vnops.c
来自「早期freebsd实现」· C语言 代码 · 共 975 行 · 第 1/2 页
C
975 行
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software donated to Berkeley by * Jan-Simon Pendry. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fdesc_vnops.c 8.9 (Berkeley) 1/21/94 * * $Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp $ *//* * /dev/fd Filesystem */#include <sys/param.h>#include <sys/systm.h>#include <sys/types.h>#include <sys/time.h>#include <sys/proc.h>#include <sys/kernel.h> /* boottime */#include <sys/resourcevar.h>#include <sys/filedesc.h>#include <sys/vnode.h>#include <sys/malloc.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/namei.h>#include <sys/buf.h>#include <sys/dirent.h>#include <miscfs/fdesc/fdesc.h>#define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)#define FDL_WANT 0x01#define FDL_LOCKED 0x02static int fdcache_lock;dev_t devctty;#if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2#endif#define NFDCACHE 3#define FD_NHASH(ix) ((ix) & NFDCACHE)/* * Cache head */struct fdcache { struct fdescnode *fc_forw; struct fdescnode *fc_back;};static struct fdcache fdcache[NFDCACHE];/* * Initialise cache headers */fdesc_init(){ struct fdcache *fc; devctty = makedev(nchrdev, 0); for (fc = fdcache; fc < fdcache + NFDCACHE; fc++) fc->fc_forw = fc->fc_back = (struct fdescnode *) fc;}/* * Compute hash list for given target vnode */static struct fdcache *fdesc_hash(ix) int ix;{ return (&fdcache[FD_NHASH(ix)]);}intfdesc_allocvp(ftype, ix, mp, vpp) fdntype ftype; int ix; struct mount *mp; struct vnode **vpp;{ struct fdcache *fc; struct fdescnode *fd; int error = 0;loop: fc = fdesc_hash(ix); for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) { if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { if (vget(fd->fd_vnode, 0)) goto loop; *vpp = fd->fd_vnode; return (error); } } /* * otherwise lock the array while we call getnewvnode * since that can block. */ if (fdcache_lock & FDL_LOCKED) { fdcache_lock |= FDL_WANT; sleep((caddr_t) &fdcache_lock, PINOD); goto loop; } fdcache_lock |= FDL_LOCKED; error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); if (error) goto out; MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); (*vpp)->v_data = fd; fd->fd_vnode = *vpp; fd->fd_type = ftype; fd->fd_fd = -1; fd->fd_link = 0; fd->fd_ix = ix; fc = fdesc_hash(ix); insque(fd, fc);out:; fdcache_lock &= ~FDL_LOCKED; if (fdcache_lock & FDL_WANT) { fdcache_lock &= ~FDL_WANT; wakeup((caddr_t) &fdcache_lock); } return (error);}/* * vp is the current namei directory * ndp is the name to locate in that directory... */intfdesc_lookup(ap) struct vop_lookup_args /* { struct vnode * a_dvp; struct vnode ** a_vpp; struct componentname * a_cnp; } */ *ap;{ struct vnode **vpp = ap->a_vpp; struct vnode *dvp = ap->a_dvp; char *pname; struct proc *p; int nfiles; unsigned fd; int error; struct vnode *fvp; char *ln; pname = ap->a_cnp->cn_nameptr; if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; VREF(dvp); VOP_LOCK(dvp); return (0); } p = ap->a_cnp->cn_proc; nfiles = p->p_fd->fd_nfiles; switch (VTOFDESC(dvp)->fd_type) { default: case Flink: case Fdesc: case Fctty: error = ENOTDIR; goto bad; case Froot: if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); if (error) goto bad; *vpp = fvp; fvp->v_type = VDIR; VOP_LOCK(fvp); return (0); } if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { struct vnode *ttyvp = cttyvp(p); if (ttyvp == NULL) { error = ENXIO; goto bad; } error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); if (error) goto bad; *vpp = fvp; fvp->v_type = VFIFO; VOP_LOCK(fvp); return (0); } ln = 0; switch (ap->a_cnp->cn_namelen) { case 5: if (bcmp(pname, "stdin", 5) == 0) { ln = "fd/0"; fd = FD_STDIN; } break; case 6: if (bcmp(pname, "stdout", 6) == 0) { ln = "fd/1"; fd = FD_STDOUT; } else if (bcmp(pname, "stderr", 6) == 0) { ln = "fd/2"; fd = FD_STDERR; } break; } if (ln) { error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); if (error) goto bad; VTOFDESC(fvp)->fd_link = ln; *vpp = fvp; fvp->v_type = VLNK; VOP_LOCK(fvp); return (0); } else { error = ENOENT; goto bad; } /* FALL THROUGH */ case Fdevfd: if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { error = fdesc_root(dvp->v_mount, vpp); return (error); } fd = 0; while (*pname >= '0' && *pname <= '9') { fd = 10 * fd + *pname++ - '0'; if (fd >= nfiles) break; } if (*pname != '\0') { error = ENOENT; goto bad; } if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { error = EBADF; goto bad; } error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); if (error) goto bad; VTOFDESC(fvp)->fd_fd = fd; *vpp = fvp; return (0); }bad:; *vpp = NULL; return (error);}intfdesc_open(ap) struct vop_open_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct vnode *vp = ap->a_vp; int error = 0; switch (VTOFDESC(vp)->fd_type) { case Fdesc: /* * XXX Kludge: set p->p_dupfd to contain the value of the * the file descriptor being sought for duplication. The error * return ensures that the vnode for this device will be * released by vn_open. Open will detect this special error and * take the actions in dupfdopen. Other callers of vn_open or * VOP_OPEN will simply report the error. */ ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ error = ENODEV; break; case Fctty: error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); break; } return (error);}static intfdesc_attr(fd, vap, cred, p) int fd; struct vattr *vap; struct ucred *cred; struct proc *p;{ struct filedesc *fdp = p->p_fd; struct file *fp; struct stat stb; int error; if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_VNODE: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); if (error == 0 && vap->va_type == VDIR) { /* * don't allow directories to show up because * that causes loops in the namespace. */ vap->va_type = VFIFO; } break; case DTYPE_SOCKET: error = soo_stat((struct socket *)fp->f_data, &stb); if (error == 0) { vattr_null(vap); vap->va_type = VSOCK; vap->va_mode = stb.st_mode; vap->va_nlink = stb.st_nlink; vap->va_uid = stb.st_uid; vap->va_gid = stb.st_gid; vap->va_fsid = stb.st_dev; vap->va_fileid = stb.st_ino; vap->va_size = stb.st_size; vap->va_blocksize = stb.st_blksize; vap->va_atime = stb.st_atimespec; vap->va_mtime = stb.st_mtimespec; vap->va_ctime = stb.st_ctimespec; vap->va_gen = stb.st_gen; vap->va_flags = stb.st_flags; vap->va_rdev = stb.st_rdev; vap->va_bytes = stb.st_blocks * stb.st_blksize; } break; default: panic("fdesc attr"); break; } return (error);}intfdesc_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct vnode *vp = ap->a_vp; struct vattr *vap = ap->a_vap; unsigned fd; int error = 0; switch (VTOFDESC(vp)->fd_type) { case Froot: case Fdevfd: case Flink: case Fctty: bzero((caddr_t) vap, sizeof(*vap)); vattr_null(vap); vap->va_fileid = VTOFDESC(vp)->fd_ix; switch (VTOFDESC(vp)->fd_type) { case Flink: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; vap->va_type = VLNK; vap->va_nlink = 1; vap->va_size = strlen(VTOFDESC(vp)->fd_link); break; case Fctty: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; vap->va_type = VFIFO; vap->va_nlink = 1; vap->va_size = 0; break; default: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; vap->va_type = VDIR; vap->va_nlink = 2; vap->va_size = DEV_BSIZE; break; } vap->va_uid = 0; vap->va_gid = 0; vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; vap->va_blocksize = DEV_BSIZE; vap->va_atime.ts_sec = boottime.tv_sec; vap->va_atime.ts_nsec = 0; vap->va_mtime = vap->va_atime; vap->va_ctime = vap->va_mtime; vap->va_gen = 0; vap->va_flags = 0; vap->va_rdev = 0; vap->va_bytes = 0; break; case Fdesc: fd = VTOFDESC(vp)->fd_fd; error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); break; default: panic("fdesc_getattr"); break; } if (error == 0) vp->v_type = vap->va_type; return (error);}intfdesc_setattr(ap) struct vop_setattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct filedesc *fdp = ap->a_p->p_fd; struct file *fp; unsigned fd; int error;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?