⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kern_descrip.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -