📄 kern_descrip.c
字号:
/* $Id: kern_descrip.c,v 1.3 1998/06/17 00:49:47 chris Exp $ *//* * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. * All rights reserved. * * 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 7.28 (Berkeley) 6/25/91 */#include "param.h"#include "systm.h"#include "filedesc.h"#include "kernel.h"#include "vnode.h"#include "proc.h"#include "file.h"#include "socket.h"#include "socketvar.h"#include "stat.h"#include "ioctl.h"#include "fcntl.h"#include "malloc.h"#include "syslog.h"#include "resourcevar.h"/* * Descriptor management. */struct file *filehead; /* head of list of open files */int nfiles; /* actual number of open files *//* * System calls on descriptors. *//* ARGSUSED */SYSCALL(getdtablesize)(p, uap, retval) struct proc *p; struct args *uap; int *retval;{#ifdef PROM *retval = NDFILE;#else *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;#endif return (0);}/* * Duplicate a file descriptor. *//* ARGSUSED */SYSCALL(dup)(p, v, retval) struct proc *p; void *v; int *retval;{ register struct args { int i; } *uap = v; register struct filedesc *fdp = p->p_fd; struct file *fp; int fd, error; /* * XXX Compatibility */ if (uap->i &~ 077) { uap->i &= 077; return (SYSCALL(dup2)(p, uap, retval)); } if ((unsigned)uap->i >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[uap->i]) == NULL) return (EBADF); if (error = fdalloc(p, 0, &fd)) return (error); fdp->fd_ofiles[fd] = fp; fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; fp->f_count++; if (fd > fdp->fd_lastfile) fdp->fd_lastfile = fd; *retval = fd; return (0);}/* * Duplicate a file descriptor to a particular value. *//* ARGSUSED */SYSCALL(dup2)(p, v, retval) struct proc *p; void *v; int *retval;{ register struct args { u_int from; u_int to; } *uap = v; register struct filedesc *fdp = p->p_fd; register struct file *fp; register u_int old = uap->from, new = uap->to; int i, error; if (old >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[old]) == NULL ||#ifdef PROM new >= NDFILE#else new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur#endif ) return (EBADF); *retval = new; if (old == 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]) {#ifndef PROM if (fdp->fd_ofileflags[new] & UF_MAPPED) (void) munmapfd(p, new);#endif /* * dup2() must succeed even if the close has an error. */ (void) closef(fdp->fd_ofiles[new], p); } 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; return (0);}/* * The file control system call. *//* ARGSUSED */SYSCALL(fcntl)(p, v, retval) struct proc *p; void *v; int *retval;{ register struct args { int fd; int cmd; int arg; } *uap = v; 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; 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:#ifdef PROM if ((unsigned)uap->arg >= NDFILE) return (EINVAL);#else if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur) return (EINVAL);#endif if (error = fdalloc(p, uap->arg, &i)) return (error); fdp->fd_ofiles[i] = fp; fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE; fp->f_count++; if (i > fdp->fd_lastfile) fdp->fd_lastfile = i; *retval = i; return (0); 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);#ifdef PROM uap->arg = p1->p_pid;#else uap->arg = p1->p_pgrp->pg_id;#endif } return ((*fp->f_ops->fo_ioctl) (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));#ifndef PROM 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 |= SADVLCK; 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 |= SADVLCK; 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)));#endif default: return (EINVAL); } /* NOTREACHED */}/* * Close a file descriptor. *//* ARGSUSED */SYSCALL(close)(p, v, retval) struct proc *p; void *v; int *retval;{ register struct args { int fd; } *uap = v; 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];#ifndef PROM if (*pf & UF_MAPPED) (void) munmapfd(p, fd);#endif 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));}/* * Return status information about a file descriptor. *//* ARGSUSED */SYSCALL(fstat)(p, v, retval) struct proc *p; void *v; int *retval;{ register struct args { int fd; struct stat *sb; } *uap = v; 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) {#ifndef PROM case DTYPE_VNODE: error = vn_stat((struct vnode *)fp->f_data, &ub, p); break;#endif 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);}/* * Allocate a file descriptor for the process. */int fdexpand;fdalloc(p, want, result) struct proc *p; int want; int *result;{ register struct filedesc *fdp = p->p_fd; register int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -