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

📄 kern_descrip.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (uap->name != _PC_PIPE_BUF)			return (EINVAL);		*retval = PIPE_BUF;		return (0);	case DTYPE_VNODE:		vp = (struct vnode *)fp->f_data;		return (VOP_PATHCONF(vp, uap->name, retval));	default:		panic("fpathconf");	}	/*NOTREACHED*/}/* * 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;	int lim, last, nfiles;	struct file **newofile;	char *newofileflags;	/*	 * Search for a free descriptor starting at the higher	 * of want or fd_freefile.  If that fails, consider	 * expanding the ofile array.	 */	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);	for (;;) {		last = min(fdp->fd_nfiles, lim);		if ((i = want) < fdp->fd_freefile)			i = fdp->fd_freefile;		for (; i < last; i++) {			if (fdp->fd_ofiles[i] == NULL) {				fdp->fd_ofileflags[i] = 0;				if (i > fdp->fd_lastfile)					fdp->fd_lastfile = i;				if (want <= fdp->fd_freefile)					fdp->fd_freefile = i;				*result = i;				return (0);			}		}		/*		 * No space in current array.  Expand?		 */		if (fdp->fd_nfiles >= lim)			return (EMFILE);		if (fdp->fd_nfiles < NDEXTENT)			nfiles = NDEXTENT;		else			nfiles = 2 * fdp->fd_nfiles;		MALLOC(newofile, struct file **, nfiles * OFILESIZE,		    M_FILEDESC, M_WAITOK);		newofileflags = (char *) &newofile[nfiles];		/*		 * Copy the existing ofile and ofileflags arrays		 * and zero the new portion of each array.		 */		bcopy(fdp->fd_ofiles, newofile,			(i = sizeof(struct file *) * fdp->fd_nfiles));		bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);		bcopy(fdp->fd_ofileflags, newofileflags,			(i = sizeof(char) * fdp->fd_nfiles));		bzero(newofileflags + i, nfiles * sizeof(char) - i);		if (fdp->fd_nfiles > NDFILE)			FREE(fdp->fd_ofiles, M_FILEDESC);		fdp->fd_ofiles = newofile;		fdp->fd_ofileflags = newofileflags;		fdp->fd_nfiles = nfiles;		fdexpand++;	}}/* * Check to see whether n user file descriptors * are available to the process p. */fdavail(p, n)	struct proc *p;	register int n;{	register struct filedesc *fdp = p->p_fd;	register struct file **fpp;	register int i, lim;	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);	if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)		return (1);	fpp = &fdp->fd_ofiles[fdp->fd_freefile];	for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)		if (*fpp == NULL && --n <= 0)			return (1);	return (0);}/* * Create a new open file structure and allocate * a file decriptor for the process that refers to it. */falloc(p, resultfp, resultfd)	register struct proc *p;	struct file **resultfp;	int *resultfd;{	register struct file *fp, *fq, **fpp;	int error, i;	if (error = fdalloc(p, 0, &i))		return (error);	if (nfiles >= maxfiles) {		tablefull("file");		return (ENFILE);	}	/*	 * Allocate a new file descriptor.	 * If the process has file descriptor zero open, add to the list	 * of open files at that point, otherwise put it at the front of	 * the list of open files.	 */	nfiles++;	MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);	bzero(fp, sizeof(struct file));	if (fq = p->p_fd->fd_ofiles[0])		fpp = &fq->f_filef;	else		fpp = &filehead;	p->p_fd->fd_ofiles[i] = fp;	if (fq = *fpp)		fq->f_fileb = &fp->f_filef;	fp->f_filef = fq;	fp->f_fileb = fpp;	*fpp = fp;	fp->f_count = 1;	fp->f_cred = p->p_ucred;	crhold(fp->f_cred);	if (resultfp)		*resultfp = fp;	if (resultfd)		*resultfd = i;	return (0);}/* * Free a file descriptor. */ffree(fp)	register struct file *fp;{	register struct file *fq;	if (fq = fp->f_filef)		fq->f_fileb = fp->f_fileb;	*fp->f_fileb = fq;	crfree(fp->f_cred);#ifdef DIAGNOSTIC	fp->f_filef = NULL;	fp->f_fileb = NULL;	fp->f_count = 0;#endif	nfiles--;	FREE(fp, M_FILE);}/* * Copy a filedesc structure. */struct filedesc *fdcopy(p)	struct proc *p;{	register struct filedesc *newfdp, *fdp = p->p_fd;	register struct file **fpp;	register int i;	MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),	    M_FILEDESC, M_WAITOK);	bcopy(fdp, newfdp, sizeof(struct filedesc));	VREF(newfdp->fd_cdir);	if (newfdp->fd_rdir)		VREF(newfdp->fd_rdir);	newfdp->fd_refcnt = 1;	/*	 * If the number of open files fits in the internal arrays	 * of the open file structure, use them, otherwise allocate	 * additional memory for the number of descriptors currently	 * in use.	 */	if (newfdp->fd_lastfile < NDFILE) {		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;		newfdp->fd_ofileflags =		    ((struct filedesc0 *) newfdp)->fd_dfileflags;		i = NDFILE;	} else {		/*		 * Compute the smallest multiple of NDEXTENT needed		 * for the file descriptors currently in use,		 * allowing the table to shrink.		 */		i = newfdp->fd_nfiles;		while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)			i /= 2;		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,		    M_FILEDESC, M_WAITOK);		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];	}	newfdp->fd_nfiles = i;	bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));	bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));	fpp = newfdp->fd_ofiles;	for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)		if (*fpp != NULL)			(*fpp)->f_count++;	return (newfdp);}/* * Release a filedesc structure. */voidfdfree(p)	struct proc *p;{	register struct filedesc *fdp = p->p_fd;	struct file **fpp;	register int i;	if (--fdp->fd_refcnt > 0)		return;	fpp = fdp->fd_ofiles;	for (i = fdp->fd_lastfile; i-- >= 0; fpp++)		if (*fpp)			(void) closef(*fpp, p);	if (fdp->fd_nfiles > NDFILE)		FREE(fdp->fd_ofiles, M_FILEDESC);	vrele(fdp->fd_cdir);	if (fdp->fd_rdir)		vrele(fdp->fd_rdir);	FREE(fdp, M_FILEDESC);}/* * Internal form of close. * Decrement reference count on file structure. * Note: p may be NULL when closing a file * that was being passed in a message. */closef(fp, p)	register struct file *fp;	register struct proc *p;{	struct vnode *vp;	struct flock lf;	int error;	if (fp == NULL)		return (0);	/*	 * POSIX record locking dictates that any close releases ALL	 * locks owned by this process.  This is handled by setting	 * a flag in the unlock to free ONLY locks obeying POSIX	 * semantics, and not to free BSD-style file locks.	 * If the descriptor was in a message, POSIX-style locks	 * aren't passed with the descriptor.	 */	if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {		lf.l_whence = SEEK_SET;		lf.l_start = 0;		lf.l_len = 0;		lf.l_type = F_UNLCK;		vp = (struct vnode *)fp->f_data;		(void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);	}	if (--fp->f_count > 0)		return (0);	if (fp->f_count < 0)		panic("closef: count < 0");	if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {		lf.l_whence = SEEK_SET;		lf.l_start = 0;		lf.l_len = 0;		lf.l_type = F_UNLCK;		vp = (struct vnode *)fp->f_data;		(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);	}	if (fp->f_ops)		error = (*fp->f_ops->fo_close)(fp, p);	else		error = 0;	ffree(fp);	return (error);}/* * Apply an advisory lock on a file descriptor. * * Just attempt to get a record lock of the requested type on * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). */struct flock_args {	int	fd;	int	how;};/* ARGSUSED */flock(p, uap, retval)	struct proc *p;	register struct flock_args *uap;	int *retval;{	register struct filedesc *fdp = p->p_fd;	register struct file *fp;	struct vnode *vp;	struct flock lf;	if ((unsigned)uap->fd >= fdp->fd_nfiles ||	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)		return (EBADF);	if (fp->f_type != DTYPE_VNODE)		return (EOPNOTSUPP);	vp = (struct vnode *)fp->f_data;	lf.l_whence = SEEK_SET;	lf.l_start = 0;	lf.l_len = 0;	if (uap->how & LOCK_UN) {		lf.l_type = F_UNLCK;		fp->f_flag &= ~FHASLOCK;		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));	}	if (uap->how & LOCK_EX)		lf.l_type = F_WRLCK;	else if (uap->how & LOCK_SH)		lf.l_type = F_RDLCK;	else		return (EBADF);	fp->f_flag |= FHASLOCK;	if (uap->how & LOCK_NB)		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));	return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));}/* * File Descriptor pseudo-device driver (/dev/fd/). * * Opening minor device N dup()s the file (if any) connected to file * descriptor N belonging to the calling process.  Note that this driver * consists of only the ``open()'' routine, because all subsequent * references to this file will be direct to the other driver. *//* ARGSUSED */fdopen(dev, mode, type, p)	dev_t dev;	int mode, type;	struct proc *p;{	/*	 * XXX Kludge: set curproc->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 below. Other callers of vn_open or VOP_OPEN	 * will simply report the error.	 */	p->p_dupfd = minor(dev);	return (ENODEV);}/* * Duplicate the specified descriptor to a free descriptor. */dupfdopen(fdp, indx, dfd, mode, error)	register struct filedesc *fdp;	register int indx, dfd;	int mode;	int error;{	register struct file *wfp;	struct file *fp;		/*	 * If the to-be-dup'd fd number is greater than the allowed number	 * of file descriptors, or the fd to be dup'd has already been	 * closed, reject.  Note, check for new == old is necessary as	 * falloc could allocate an already closed to-be-dup'd descriptor	 * as the new descriptor.	 */	fp = fdp->fd_ofiles[indx];	if ((u_int)dfd >= fdp->fd_nfiles ||	    (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)		return (EBADF);	/*	 * There are two cases of interest here.	 *	 * For ENODEV simply dup (dfd) to file descriptor	 * (indx) and return.	 *	 * For ENXIO steal away the file structure from (dfd) and	 * store it in (indx).  (dfd) is effectively closed by	 * this operation.	 *	 * Any other error code is just returned.	 */	switch (error) {	case ENODEV:		/*		 * Check that the mode the file is being opened for is a		 * subset of the mode of the existing descriptor.		 */		if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)			return (EACCES);		fdp->fd_ofiles[indx] = wfp;		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];		wfp->f_count++;		if (indx > fdp->fd_lastfile)			fdp->fd_lastfile = indx;		return (0);	case ENXIO:		/*		 * Steal away the file pointer from dfd, and stuff it into indx.		 */		fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];		fdp->fd_ofiles[dfd] = NULL;		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];		fdp->fd_ofileflags[dfd] = 0;		/*		 * Complete the clean up of the filedesc structure by		 * recomputing the various hints.		 */		if (indx > fdp->fd_lastfile)			fdp->fd_lastfile = indx;		else			while (fdp->fd_lastfile > 0 &&			       fdp->fd_ofiles[fdp->fd_lastfile] == NULL)				fdp->fd_lastfile--;			if (dfd < fdp->fd_freefile)				fdp->fd_freefile = dfd;		return (0);	default:		return (error);	}	/* NOTREACHED */}

⌨️ 快捷键说明

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