procfs_vnops.c

来自「早期freebsd实现」· C语言 代码 · 共 815 行 · 第 1/2 页

C
815
字号
/* * Copyright (c) 1993 Jan-Simon Pendry * Copyright (c) 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Jan-Simon Pendry. * * 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. * *	@(#)procfs_vnops.c	8.6 (Berkeley) 2/7/94 * * From: *	$Id: procfs_vnops.c,v 3.2 1993/12/15 09:40:17 jsp Exp $ *//* * procfs vnode interface */#include <sys/param.h>#include <sys/systm.h>#include <sys/time.h>#include <sys/kernel.h>#include <sys/file.h>#include <sys/proc.h>#include <sys/vnode.h>#include <sys/namei.h>#include <sys/malloc.h>#include <sys/dirent.h>#include <sys/resourcevar.h>#include <miscfs/procfs/procfs.h>#include <vm/vm.h>	/* for PAGE_SIZE *//* * Vnode Operations. * *//* * This is a list of the valid names in the * process-specific sub-directories.  It is * used in procfs_lookup and procfs_readdir */static struct pfsnames {	u_short	d_namlen;	char	d_name[PROCFS_NAMELEN];	pfstype	d_pfstype;} procent[] = {#define N(s) sizeof(s)-1, s	/* namlen, nam, type */	{  N("file"),	Pfile },	{  N("mem"),	Pmem },	{  N("regs"),	Pregs },	{  N("fpregs"),	Pfpregs },	{  N("ctl"),	Pctl },	{  N("status"),	Pstatus },	{  N("note"),	Pnote },	{  N("notepg"),	Pnotepg },#undef N};#define Nprocent (sizeof(procent)/sizeof(procent[0]))static pid_t atopid __P((const char *, u_int));/* * set things up for doing i/o on * the pfsnode (vp).  (vp) is locked * on entry, and should be left locked * on exit. * * for procfs we don't need to do anything * in particular for i/o.  all that is done * is to support exclusive open on process * memory images. */procfs_open(ap)	struct vop_open_args *ap;{	struct pfsnode *pfs = VTOPFS(ap->a_vp);	switch (pfs->pfs_type) {	case Pmem:		if (PFIND(pfs->pfs_pid) == 0)			return (ENOENT);	/* was ESRCH, jsp */		if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||				(pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))			return (EBUSY);		if (ap->a_mode & FWRITE)			pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);		return (0);	default:		break;	}	return (0);}/* * close the pfsnode (vp) after doing i/o. * (vp) is not locked on entry or exit. * * nothing to do for procfs other than undo * any exclusive open flag (see _open above). */procfs_close(ap)	struct vop_close_args *ap;{	struct pfsnode *pfs = VTOPFS(ap->a_vp);	switch (pfs->pfs_type) {	case Pmem:		if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))			pfs->pfs_flags &= ~(FWRITE|O_EXCL);		break;	}	return (0);}/* * do an ioctl operation on pfsnode (vp). * (vp) is not locked on entry or exit. */procfs_ioctl(ap)	struct vop_ioctl_args *ap;{	return (ENOTTY);}/* * do block mapping for pfsnode (vp). * since we don't use the buffer cache * for procfs this function should never * be called.  in any case, it's not clear * what part of the kernel ever makes use * of this function.  for sanity, this is the * usual no-op bmap, although returning * (EIO) would be a reasonable alternative. */procfs_bmap(ap)	struct vop_bmap_args *ap;{	if (ap->a_vpp != NULL)		*ap->a_vpp = ap->a_vp;	if (ap->a_bnp != NULL)		*ap->a_bnp = ap->a_bn;	return (0);}/* * _inactive is called when the pfsnode * is vrele'd and the reference count goes * to zero.  (vp) will be on the vnode free * list, so to get it back vget() must be * used. * * for procfs, check if the process is still * alive and if it isn't then just throw away * the vnode by calling vgone().  this may * be overkill and a waste of time since the * chances are that the process will still be * there and PFIND is not free. * * (vp) is not locked on entry or exit. */procfs_inactive(ap)	struct vop_inactive_args *ap;{	struct pfsnode *pfs = VTOPFS(ap->a_vp);	if (PFIND(pfs->pfs_pid) == 0)		vgone(ap->a_vp);	return (0);}/* * _reclaim is called when getnewvnode() * wants to make use of an entry on the vnode * free list.  at this time the filesystem needs * to free any private data and remove the node * from any private lists. */procfs_reclaim(ap)	struct vop_reclaim_args *ap;{	int error;	error = procfs_freevp(ap->a_vp);	return (error);}/* * Return POSIX pathconf information applicable to special devices. */procfs_pathconf(ap)	struct vop_pathconf_args /* {		struct vnode *a_vp;		int a_name;		int *a_retval;	} */ *ap;{	switch (ap->a_name) {	case _PC_LINK_MAX:		*ap->a_retval = LINK_MAX;		return (0);	case _PC_MAX_CANON:		*ap->a_retval = MAX_CANON;		return (0);	case _PC_MAX_INPUT:		*ap->a_retval = MAX_INPUT;		return (0);	case _PC_PIPE_BUF:		*ap->a_retval = PIPE_BUF;		return (0);	case _PC_CHOWN_RESTRICTED:		*ap->a_retval = 1;		return (0);	case _PC_VDISABLE:		*ap->a_retval = _POSIX_VDISABLE;		return (0);	default:		return (EINVAL);	}	/* NOTREACHED */}/* * _print is used for debugging. * just print a readable description * of (vp). */procfs_print(ap)	struct vop_print_args *ap;{	struct pfsnode *pfs = VTOPFS(ap->a_vp);	printf("tag VT_PROCFS, pid %d, mode %x, flags %x\n",		pfs->pfs_pid,		pfs->pfs_mode, pfs->pfs_flags);}/* * _abortop is called when operations such as * rename and create fail.  this entry is responsible * for undoing any side-effects caused by the lookup. * this will always include freeing the pathname buffer. */procfs_abortop(ap)	struct vop_abortop_args *ap;{	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);	return (0);}/* * generic entry point for unsupported operations */procfs_badop(){	return (EIO);}/* * Invent attributes for pfsnode (vp) and store * them in (vap). * Directories lengths are returned as zero since * any real length would require the genuine size * to be computed, and nothing cares anyway. * * this is relatively minimal for procfs. */procfs_getattr(ap)	struct vop_getattr_args *ap;{	struct pfsnode *pfs = VTOPFS(ap->a_vp);	struct vattr *vap = ap->a_vap;	struct proc *procp;	int error;	/* first check the process still exists */	switch (pfs->pfs_type) {	case Proot:		procp = 0;		break;	default:		procp = PFIND(pfs->pfs_pid);		if (procp == 0)			return (ENOENT);	}	error = 0;	/* start by zeroing out the attributes */	VATTR_NULL(vap);	/* next do all the common fields */	vap->va_type = ap->a_vp->v_type;	vap->va_mode = pfs->pfs_mode;	vap->va_fileid = pfs->pfs_fileno;	vap->va_flags = 0;	vap->va_blocksize = PAGE_SIZE;	vap->va_bytes = vap->va_size = 0;	/*	 * If the process has exercised some setuid or setgid	 * privilege, then rip away read/write permission so	 * that only root can gain access.	 */	switch (pfs->pfs_type) {	case Pregs:	case Pfpregs:	case Pmem:		if (procp->p_flag & P_SUGID)			vap->va_mode &= ~((VREAD|VWRITE)|					  ((VREAD|VWRITE)>>3)|					  ((VREAD|VWRITE)>>6));		break;	}	/*	 * Make all times be current TOD.	 * It would be possible to get the process start	 * time from the p_stat structure, but there's	 * no "file creation" time stamp anyway, and the	 * p_stat structure is not addressible if u. gets	 * swapped out for that process.	 */	microtime(&vap->va_ctime);	vap->va_atime = vap->va_mtime = vap->va_ctime;	/*	 * now do the object specific fields	 *	 * The size could be set from struct reg, but it's hardly	 * worth the trouble, and it puts some (potentially) machine	 * dependent data into this machine-independent code.  If it	 * becomes important then this function should break out into	 * a per-file stat function in the corresponding .c file.	 */	switch (pfs->pfs_type) {	case Proot:		vap->va_nlink = 2;		vap->va_uid = 0;		vap->va_gid = 0;		break;	case Pproc:		vap->va_nlink = 2;		vap->va_uid = procp->p_ucred->cr_uid;		vap->va_gid = procp->p_ucred->cr_gid;		break;	case Pfile:		error = EOPNOTSUPP;		break;	case Pmem:		vap->va_nlink = 1;		vap->va_bytes = vap->va_size =			ctob(procp->p_vmspace->vm_tsize +				    procp->p_vmspace->vm_dsize +				    procp->p_vmspace->vm_ssize);		vap->va_uid = procp->p_ucred->cr_uid;		vap->va_gid = procp->p_ucred->cr_gid;		break;	case Pregs:

⌨️ 快捷键说明

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