kern_descrip.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 925 行 · 第 1/2 页

C
925
字号
/*	$NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $	*//* * 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>#include <sys/conf.h>#include <sys/mount.h>#include <sys/syscallargs.h>#include <vm/vm.h>/* * Descriptor management. */struct filelist filehead;	/* head of list of open files */int nfiles;			/* actual number of open files */static __inline void fd_used __P((struct filedesc *, int));static __inline void fd_unused __P((struct filedesc *, int));int finishdup __P((struct filedesc *, int, int, register_t *));static __inline voidfd_used(fdp, fd)	register struct filedesc *fdp;	register int fd;{	if (fd > fdp->fd_lastfile)		fdp->fd_lastfile = fd;}static __inline voidfd_unused(fdp, fd)	register struct filedesc *fdp;	register int fd;{	if (fd < fdp->fd_freefile)		fdp->fd_freefile = fd;#ifdef DIAGNOSTIC	if (fd > fdp->fd_lastfile)		panic("fd_unused: fd_lastfile inconsistent");#endif	if (fd == fdp->fd_lastfile) {		do {			fd--;		} while (fd >= 0 && fdp->fd_ofiles[fd] == NULL);		fdp->fd_lastfile = fd;	}}/* * System calls on descriptors. *//* * Duplicate a file descriptor. *//* ARGSUSED */intsys_dup(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_dup_args /* {		syscallarg(u_int) fd;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	register int old = SCARG(uap, fd);	int new;	int error;	if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)		return (EBADF);	if ((error = fdalloc(p, 0, &new)) != 0)		return (error);	return (finishdup(fdp, old, new, retval));}/* * Duplicate a file descriptor to a particular value. *//* ARGSUSED */intsys_dup2(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_dup2_args /* {		syscallarg(u_int) from;		syscallarg(u_int) to;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	register int old = SCARG(uap, from), new = SCARG(uap, to);	int i, error;	if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL ||	    (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||	    (u_int)new >= maxfiles)		return (EBADF);	if (old == new) {		*retval = new;		return (0);	}	if (new >= fdp->fd_nfiles) {		if ((error = fdalloc(p, new, &i)) != 0)			return (error);		if (new != i)			panic("dup2: fdalloc");	} else {		(void) fdrelease(p, new);	}	return (finishdup(fdp, old, new, retval));}/* * The file control system call. *//* ARGSUSED */intsys_fcntl(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_fcntl_args /* {		syscallarg(int) fd;		syscallarg(int) cmd;		syscallarg(void *) arg;	} */ *uap = v;	int fd = SCARG(uap, fd);	register struct filedesc *fdp = p->p_fd;	register struct file *fp;	struct vnode *vp;	int i, tmp, error, flg = F_POSIX;	struct flock fl;	int newmin;	if ((u_int)fd >= fdp->fd_nfiles ||	    (fp = fdp->fd_ofiles[fd]) == NULL)		return (EBADF);	switch (SCARG(uap, cmd)) {	case F_DUPFD:		newmin = (long)SCARG(uap, arg);		if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||		    (u_int)newmin >= maxfiles)			return (EINVAL);		if ((error = fdalloc(p, newmin, &i)) != 0)			return (error);		return (finishdup(fdp, fd, i, retval));	case F_GETFD:		*retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;		return (0);	case F_SETFD:		if ((long)SCARG(uap, arg) & 1)			fdp->fd_ofileflags[fd] |= UF_EXCLOSE;		else			fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;		return (0);	case F_GETFL:		*retval = OFLAGS(fp->f_flag);		return (0);	case F_SETFL:		fp->f_flag &= ~FCNTLFLAGS;		fp->f_flag |= FFLAGS((long)SCARG(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, 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 =			    (long)SCARG(uap, arg);			return (0);		}		if ((long)SCARG(uap, arg) <= 0) {			SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg));		} else {			struct proc *p1 = pfind((long)SCARG(uap, arg));			if (p1 == 0)				return (ESRCH);			SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id;		}		return ((*fp->f_ops->fo_ioctl)			(fp, TIOCSPGRP, (caddr_t)&SCARG(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)SCARG(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)SCARG(uap, arg), (caddr_t)&fl,		    sizeof (fl));		if (error)			return (error);		if (fl.l_whence == SEEK_CUR)			fl.l_start += fp->f_offset;		error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);		if (error)			return (error);		return (copyout((caddr_t)&fl, (caddr_t)SCARG(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;	register_t *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++;	fd_used(fdp, new);	*retval = new;	return (0);}intfdrelease(p, fd)	struct proc *p;	int fd;{	register struct filedesc *fdp = p->p_fd;	register struct file **fpp, *fp;	register char *pf;	fpp = &fdp->fd_ofiles[fd];	fp = *fpp;	if (fp == NULL)		return (EBADF);	pf = &fdp->fd_ofileflags[fd];	if (*pf & UF_MAPPED)		(void) munmapfd(p, fd);	*fpp = NULL;	*pf = 0;	fd_unused(fdp, fd);	return (closef(fp, p));}/* * Close a file descriptor. *//* ARGSUSED */intsys_close(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_close_args /* {		syscallarg(int) fd;	} */ *uap = v;	int fd = SCARG(uap, fd);	register struct filedesc *fdp = p->p_fd;	if ((u_int)fd >= fdp->fd_nfiles)		return (EBADF);	return (fdrelease(p, fd));}/* * Return status information about a file descriptor. *//* ARGSUSED */intsys_fstat(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_fstat_args /* {		syscallarg(int) fd;		syscallarg(struct stat *) sb;	} */ *uap = v;	int fd = SCARG(uap, fd);	register struct filedesc *fdp = p->p_fd;	register struct file *fp;	struct stat ub;	int error;	if ((u_int)fd >= fdp->fd_nfiles ||	    (fp = fdp->fd_ofiles[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)SCARG(uap, sb),		    sizeof (ub));	return (error);}/* * Return pathconf information about a file descriptor. *//* ARGSUSED */intsys_fpathconf(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_fpathconf_args /* {		syscallarg(int) fd;		syscallarg(int) name;	} */ *uap = v;	int fd = SCARG(uap, fd);	struct filedesc *fdp = p->p_fd;	struct file *fp;	struct vnode *vp;	if ((u_int)fd >= fdp->fd_nfiles ||	    (fp = fdp->fd_ofiles[fd]) == NULL)		return (EBADF);	switch (fp->f_type) {	case DTYPE_SOCKET:		if (SCARG(uap, name) != _PC_PIPE_BUF)			return (EINVAL);		*retval = PIPE_BUF;		return (0);	case DTYPE_VNODE:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?