procfs_vnops.c

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

C
815
字号
	case Pfpregs:	case Pctl:	case Pstatus:	case Pnote:	case Pnotepg:		vap->va_nlink = 1;		vap->va_uid = procp->p_ucred->cr_uid;		vap->va_gid = procp->p_ucred->cr_gid;		break;	default:		panic("procfs_getattr");	}	return (error);}procfs_setattr(ap)	struct vop_setattr_args *ap;{	/*	 * just fake out attribute setting	 * it's not good to generate an error	 * return, otherwise things like creat()	 * will fail when they try to set the	 * file length to 0.  worse, this means	 * that echo $note > /proc/$pid/note will fail.	 */	return (0);}/* * implement access checking. * * something very similar to this code is duplicated * throughout the 4bsd kernel and should be moved * into kern/vfs_subr.c sometime. * * actually, the check for super-user is slightly * broken since it will allow read access to write-only * objects.  this doesn't cause any particular trouble * but does mean that the i/o entry points need to check * that the operation really does make sense. */procfs_access(ap)	struct vop_access_args *ap;{	struct vattr *vap;	struct vattr vattr;	int error;	/*	 * If you're the super-user,	 * you always get access.	 */	if (ap->a_cred->cr_uid == (uid_t) 0)		return (0);	vap = &vattr;	if (error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p))		return (error);	/*	 * Access check is based on only one of owner, group, public.	 * If not owner, then check group. If not a member of the	 * group, then check public access.	 */	if (ap->a_cred->cr_uid != vap->va_uid) {		gid_t *gp;		int i;		(ap->a_mode) >>= 3;		gp = ap->a_cred->cr_groups;		for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)			if (vap->va_gid == *gp)				goto found;		ap->a_mode >>= 3;found:		;	}	if ((vap->va_mode & ap->a_mode) == ap->a_mode)		return (0);	return (EACCES);}/* * lookup.  this is incredibly complicated in the * general case, however for most pseudo-filesystems * very little needs to be done. * * unless you want to get a migraine, just make sure your * filesystem doesn't do any locking of its own.  otherwise * read and inwardly digest ufs_lookup(). */procfs_lookup(ap)	struct vop_lookup_args *ap;{	struct componentname *cnp = ap->a_cnp;	struct vnode **vpp = ap->a_vpp;	struct vnode *dvp = ap->a_dvp;	char *pname = cnp->cn_nameptr;	int error = 0;	pid_t pid;	struct vnode *nvp;	struct pfsnode *pfs;	struct proc *procp;	pfstype pfs_type;	int i;	if (cnp->cn_namelen == 1 && *pname == '.') {		*vpp = dvp;		VREF(dvp);		/*VOP_LOCK(dvp);*/		return (0);	}	*vpp = NULL;	pfs = VTOPFS(dvp);	switch (pfs->pfs_type) {	case Proot:		if (cnp->cn_flags & ISDOTDOT)			return (EIO);		if (CNEQ(cnp, "curproc", 7))			pid = cnp->cn_proc->p_pid;		else			pid = atopid(pname, cnp->cn_namelen);		if (pid == NO_PID)			return (ENOENT);		procp = PFIND(pid);		if (procp == 0)			return (ENOENT);		error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);		if (error)			return (error);		nvp->v_type = VDIR;		pfs = VTOPFS(nvp);		*vpp = nvp;		return (0);	case Pproc:		if (cnp->cn_flags & ISDOTDOT) {			error = procfs_root(dvp->v_mount, vpp);			return (error);		}		procp = PFIND(pfs->pfs_pid);		if (procp == 0)			return (ENOENT);		for (i = 0; i < Nprocent; i++) {			struct pfsnames *dp = &procent[i];			if (cnp->cn_namelen == dp->d_namlen &&			    bcmp(pname, dp->d_name, dp->d_namlen) == 0) {			    	pfs_type = dp->d_pfstype;				goto found;			}		}		return (ENOENT);	found:		if (pfs_type == Pfile) {			nvp = procfs_findtextvp(procp);			if (nvp) {				VREF(nvp);				VOP_LOCK(nvp);			} else {				error = ENXIO;			}		} else {			error = procfs_allocvp(dvp->v_mount, &nvp,					pfs->pfs_pid, pfs_type);			if (error)				return (error);			nvp->v_type = VREG;			pfs = VTOPFS(nvp);		}		*vpp = nvp;		return (error);	default:		return (ENOTDIR);	}}/* * readdir returns directory entries from pfsnode (vp). * * the strategy here with procfs is to generate a single * directory entry at a time (struct pfsdent) and then * copy that out to userland using uiomove.  a more efficent * though more complex implementation, would try to minimize * the number of calls to uiomove().  for procfs, this is * hardly worth the added code complexity. * * this should just be done through read() */procfs_readdir(ap)	struct vop_readdir_args *ap;{	struct uio *uio = ap->a_uio;	struct pfsdent d;	struct pfsdent *dp = &d;	struct pfsnode *pfs;	int error;	int count;	int i;	pfs = VTOPFS(ap->a_vp);	if (uio->uio_resid < UIO_MX)		return (EINVAL);	if (uio->uio_offset & (UIO_MX-1))		return (EINVAL);	if (uio->uio_offset < 0)		return (EINVAL);	error = 0;	count = 0;	i = uio->uio_offset / UIO_MX;	switch (pfs->pfs_type) {	/*	 * this is for the process-specific sub-directories.	 * all that is needed to is copy out all the entries	 * from the procent[] table (top of this file).	 */	case Pproc: {		while (uio->uio_resid >= UIO_MX) {			struct pfsnames *dt;			if (i >= Nprocent)				break;			dt = &procent[i];						dp->d_reclen = UIO_MX;			dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, dt->d_pfstype);			dp->d_type = DT_REG;			dp->d_namlen = dt->d_namlen;			bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);			error = uiomove((caddr_t) dp, UIO_MX, uio);			if (error)				break;			count += UIO_MX;			i++;		}	    	break;	    }	/*	 * this is for the root of the procfs filesystem	 * what is needed is a special entry for "curproc"	 * followed by an entry for each process on allproc#ifdef PROCFS_ZOMBIE	 * and zombproc.#endif	 */	case Proot: {		int pcnt;#ifdef PROCFS_ZOMBIE		int doingzomb = 0;#endif		volatile struct proc *p;		p = allproc;#define PROCFS_XFILES	1	/* number of other entries, like "curproc" */		pcnt = PROCFS_XFILES;		while (p && uio->uio_resid >= UIO_MX) {			bzero((char *) dp, UIO_MX);			dp->d_type = DT_DIR;			dp->d_reclen = UIO_MX;			switch (i) {			case 0:				/* ship out entry for "curproc" */				dp->d_fileno = PROCFS_FILENO(PID_MAX+1, Pproc);				dp->d_namlen = sprintf(dp->d_name, "curproc");				break;			default:				if (pcnt >= i) {					dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);					dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);				}				p = p->p_next;#ifdef PROCFS_ZOMBIE				if (p == 0 && doingzomb == 0) {					doingzomb = 1;					p = zombproc;				}#endif				if (pcnt++ < i)					continue;				break;			}			error = uiomove((caddr_t) dp, UIO_MX, uio);			if (error)				break;			count += UIO_MX;			i++;		}		break;	    }	default:		error = ENOTDIR;		break;	}	uio->uio_offset = i * UIO_MX;	return (error);}/* * convert decimal ascii to pid_t */static pid_tatopid(b, len)	const char *b;	u_int len;{	pid_t p = 0;	while (len--) {		char c = *b++;		if (c < '0' || c > '9')			return (NO_PID);		p = 10 * p + (c - '0');		if (p > PID_MAX)			return (NO_PID);	}	return (p);}/* * procfs vnode operations. */int (**procfs_vnodeop_p)();struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {	{ &vop_default_desc, vn_default_error },	{ &vop_lookup_desc, procfs_lookup },		/* lookup */	{ &vop_create_desc, procfs_create },		/* create */	{ &vop_mknod_desc, procfs_mknod },		/* mknod */	{ &vop_open_desc, procfs_open },		/* open */	{ &vop_close_desc, procfs_close },		/* close */	{ &vop_access_desc, procfs_access },		/* access */	{ &vop_getattr_desc, procfs_getattr },		/* getattr */	{ &vop_setattr_desc, procfs_setattr },		/* setattr */	{ &vop_read_desc, procfs_read },		/* read */	{ &vop_write_desc, procfs_write },		/* write */	{ &vop_ioctl_desc, procfs_ioctl },		/* ioctl */	{ &vop_select_desc, procfs_select },		/* select */	{ &vop_mmap_desc, procfs_mmap },		/* mmap */	{ &vop_fsync_desc, procfs_fsync },		/* fsync */	{ &vop_seek_desc, procfs_seek },		/* seek */	{ &vop_remove_desc, procfs_remove },		/* remove */	{ &vop_link_desc, procfs_link },		/* link */	{ &vop_rename_desc, procfs_rename },		/* rename */	{ &vop_mkdir_desc, procfs_mkdir },		/* mkdir */	{ &vop_rmdir_desc, procfs_rmdir },		/* rmdir */	{ &vop_symlink_desc, procfs_symlink },		/* symlink */	{ &vop_readdir_desc, procfs_readdir },		/* readdir */	{ &vop_readlink_desc, procfs_readlink },	/* readlink */	{ &vop_abortop_desc, procfs_abortop },		/* abortop */	{ &vop_inactive_desc, procfs_inactive },	/* inactive */	{ &vop_reclaim_desc, procfs_reclaim },		/* reclaim */	{ &vop_lock_desc, procfs_lock },		/* lock */	{ &vop_unlock_desc, procfs_unlock },		/* unlock */	{ &vop_bmap_desc, procfs_bmap },		/* bmap */	{ &vop_strategy_desc, procfs_strategy },	/* strategy */	{ &vop_print_desc, procfs_print },		/* print */	{ &vop_islocked_desc, procfs_islocked },	/* islocked */	{ &vop_pathconf_desc, procfs_pathconf },	/* pathconf */	{ &vop_advlock_desc, procfs_advlock },		/* advlock */	{ &vop_blkatoff_desc, procfs_blkatoff },	/* blkatoff */	{ &vop_valloc_desc, procfs_valloc },		/* valloc */	{ &vop_vfree_desc, procfs_vfree },		/* vfree */	{ &vop_truncate_desc, procfs_truncate },	/* truncate */	{ &vop_update_desc, procfs_update },		/* update */	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }};struct vnodeopv_desc procfs_vnodeop_opv_desc =	{ &procfs_vnodeop_p, procfs_vnodeop_entries };

⌨️ 快捷键说明

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