📄 kern_descrip.c
字号:
/* * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * * @(#)kern_descrip.c 8.6 (Berkeley) 4/19/94 */#include <sys/param.h>#include <sys/systm.h>#include <sys/filedesc.h>#include <sys/kernel.h>#include <sys/vnode.h>#include <sys/proc.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/fcntl.h>#include <sys/malloc.h>#include <sys/syslog.h>#include <sys/unistd.h>#include <sys/resourcevar.h>/* * Descriptor management. */struct file *filehead; /* head of list of open files */int nfiles; /* actual number of open files *//* * System calls on descriptors. */struct getdtablesize_args { int dummy;};/* ARGSUSED */getdtablesize(p, uap, retval) struct proc *p; struct getdtablesize_args *uap; int *retval;{ *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); return (0);}/* * Duplicate a file descriptor. */struct dup_args { u_int fd;};/* ARGSUSED */dup(p, uap, retval) struct proc *p; struct dup_args *uap; int *retval;{ register struct filedesc *fdp; u_int old; int new, error; old = uap->fd; /* * XXX Compatibility */ if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); } fdp = p->p_fd; if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL) return (EBADF); if (error = fdalloc(p, 0, &new)) return (error); return (finishdup(fdp, (int)old, new, retval));}/* * Duplicate a file descriptor to a particular value. */struct dup2_args { u_int from; u_int to;};/* ARGSUSED */dup2(p, uap, retval) struct proc *p; struct dup2_args *uap; int *retval;{ register struct filedesc *fdp = p->p_fd; register u_int old = uap->from, new = uap->to; int i, error; if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL || new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || new >= maxfiles) return (EBADF); if (old == new) { *retval = new; return (0); } if (new >= fdp->fd_nfiles) { if (error = fdalloc(p, new, &i)) return (error); if (new != i) panic("dup2: fdalloc"); } else if (fdp->fd_ofiles[new]) { if (fdp->fd_ofileflags[new] & UF_MAPPED) (void) munmapfd(p, new); /* * dup2() must succeed even if the close has an error. */ (void) closef(fdp->fd_ofiles[new], p); } return (finishdup(fdp, (int)old, (int)new, retval));}/* * The file control system call. */struct fcntl_args { int fd; int cmd; int arg;};/* ARGSUSED */fcntl(p, uap, retval) struct proc *p; register struct fcntl_args *uap; int *retval;{ register struct filedesc *fdp = p->p_fd; register struct file *fp; register char *pop; struct vnode *vp; int i, tmp, error, flg = F_POSIX; struct flock fl; u_int newmin; if ((unsigned)uap->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->fd]) == NULL) return (EBADF); pop = &fdp->fd_ofileflags[uap->fd]; switch (uap->cmd) { case F_DUPFD: newmin = uap->arg; if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur || newmin >= maxfiles) return (EINVAL); if (error = fdalloc(p, newmin, &i)) return (error); return (finishdup(fdp, uap->fd, i, retval)); case F_GETFD: *retval = *pop & 1; return (0); case F_SETFD: *pop = (*pop &~ 1) | (uap->arg & 1); return (0); case F_GETFL: *retval = OFLAGS(fp->f_flag); return (0); case F_SETFL: fp->f_flag &= ~FCNTLFLAGS; fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; tmp = fp->f_flag & FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); if (error) return (error); tmp = fp->f_flag & FASYNC; error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); if (!error) return (0); fp->f_flag &= ~FNONBLOCK; tmp = 0; (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); return (error); case F_GETOWN: if (fp->f_type == DTYPE_SOCKET) { *retval = ((struct socket *)fp->f_data)->so_pgid; return (0); } error = (*fp->f_ops->fo_ioctl) (fp, (int)TIOCGPGRP, (caddr_t)retval, p); *retval = -*retval; return (error); case F_SETOWN: if (fp->f_type == DTYPE_SOCKET) { ((struct socket *)fp->f_data)->so_pgid = uap->arg; return (0); } if (uap->arg <= 0) { uap->arg = -uap->arg; } else { struct proc *p1 = pfind(uap->arg); if (p1 == 0) return (ESRCH); uap->arg = p1->p_pgrp->pg_id; } return ((*fp->f_ops->fo_ioctl) (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p)); case F_SETLKW: flg |= F_WAIT; /* Fall into F_SETLK */ case F_SETLK: if (fp->f_type != DTYPE_VNODE) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); if (error) return (error); if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; switch (fl.l_type) { case F_RDLCK: if ((fp->f_flag & FREAD) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_WRLCK: if ((fp->f_flag & FWRITE) == 0) return (EBADF); p->p_flag |= P_ADVLOCK; return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); case F_UNLCK: return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, F_POSIX)); default: return (EINVAL); } case F_GETLK: if (fp->f_type != DTYPE_VNODE) return (EBADF); vp = (struct vnode *)fp->f_data; /* Copy in the lock structure */ error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); if (error) return (error); if (fl.l_whence == SEEK_CUR) fl.l_start += fp->f_offset; if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) return (error); return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); default: return (EINVAL); } /* NOTREACHED */}/* * Common code for dup, dup2, and fcntl(F_DUPFD). */intfinishdup(fdp, old, new, retval) register struct filedesc *fdp; register int old, new, *retval;{ register struct file *fp; fp = fdp->fd_ofiles[old]; fdp->fd_ofiles[new] = fp; fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; fp->f_count++; if (new > fdp->fd_lastfile) fdp->fd_lastfile = new; *retval = new; return (0);}/* * Close a file descriptor. */struct close_args { int fd;};/* ARGSUSED */close(p, uap, retval) struct proc *p; struct close_args *uap; int *retval;{ register struct filedesc *fdp = p->p_fd; register struct file *fp; register int fd = uap->fd; register u_char *pf; if ((unsigned)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); pf = (u_char *)&fdp->fd_ofileflags[fd]; if (*pf & UF_MAPPED) (void) munmapfd(p, fd); fdp->fd_ofiles[fd] = NULL; while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) fdp->fd_lastfile--; if (fd < fdp->fd_freefile) fdp->fd_freefile = fd; *pf = 0; return (closef(fp, p));}#if defined(COMPAT_43) || defined(COMPAT_SUNOS)/* * Return status information about a file descriptor. */struct ofstat_args { int fd; struct ostat *sb;};/* ARGSUSED */ofstat(p, uap, retval) struct proc *p; register struct ofstat_args *uap; int *retval;{ register struct filedesc *fdp = p->p_fd; register struct file *fp; struct stat ub; struct ostat oub; int error; if ((unsigned)uap->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->fd]) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_VNODE: error = vn_stat((struct vnode *)fp->f_data, &ub, p); break; case DTYPE_SOCKET: error = soo_stat((struct socket *)fp->f_data, &ub); break; default: panic("ofstat"); /*NOTREACHED*/ } cvtstat(&ub, &oub); if (error == 0) error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub)); return (error);}#endif /* COMPAT_43 || COMPAT_SUNOS *//* * Return status information about a file descriptor. */struct fstat_args { int fd; struct stat *sb;};/* ARGSUSED */fstat(p, uap, retval) struct proc *p; register struct fstat_args *uap; int *retval;{ register struct filedesc *fdp = p->p_fd; register struct file *fp; struct stat ub; int error; if ((unsigned)uap->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->fd]) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_VNODE: error = vn_stat((struct vnode *)fp->f_data, &ub, p); break; case DTYPE_SOCKET: error = soo_stat((struct socket *)fp->f_data, &ub); break; default: panic("fstat"); /*NOTREACHED*/ } if (error == 0) error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); return (error);}/* * Return pathconf information about a file descriptor. */struct fpathconf_args { int fd; int name;};/* ARGSUSED */fpathconf(p, uap, retval) struct proc *p; register struct fpathconf_args *uap; int *retval;{ struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; if ((unsigned)uap->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->fd]) == NULL) return (EBADF); switch (fp->f_type) { case DTYPE_SOCKET:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -