kernfs_vnops.c

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

C
760
字号
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software donated 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. * *	@(#)kernfs_vnops.c	8.6 (Berkeley) 2/10/94 *//* * Kernel parameter filesystem (/kern) */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/vmmeter.h>#include <sys/types.h>#include <sys/time.h>#include <sys/proc.h>#include <sys/vnode.h>#include <sys/malloc.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/namei.h>#include <sys/buf.h>#include <sys/dirent.h>#include <miscfs/kernfs/kernfs.h>#define KSTRING	256		/* Largest I/O available via this filesystem */#define	UIO_MX 32#define	READ_MODE	(S_IRUSR|S_IRGRP|S_IROTH)#define	WRITE_MODE	(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)#define DIR_MODE	(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)struct kern_target {	char *kt_name;	void *kt_data;#define	KTT_NULL 1#define	KTT_TIME 5#define KTT_INT	17#define	KTT_STRING 31#define KTT_HOSTNAME 47#define KTT_AVENRUN 53	int kt_tag;	int kt_rw;	int kt_vtype;} kern_targets[] = {/* NOTE: The name must be less than UIO_MX-16 chars in length */	/* name		data		tag		ro/rw */	{ ".",		0,		KTT_NULL,	VREAD,		VDIR },	{ "..",		0,		KTT_NULL,	VREAD,		VDIR },	{ "boottime",	&boottime.tv_sec, KTT_INT,	VREAD,		VREG },	{ "copyright",	copyright,	KTT_STRING,	VREAD,		VREG },	{ "hostname",	0,		KTT_HOSTNAME,	VREAD|VWRITE,	VREG },	{ "hz",		&hz,		KTT_INT,	VREAD,		VREG },	{ "loadavg",	0,		KTT_AVENRUN,	VREAD,		VREG },	{ "pagesize",	&cnt.v_page_size, KTT_INT,	VREAD,		VREG },	{ "physmem",	&physmem,	KTT_INT,	VREAD,		VREG },#if 0	{ "root",	0,		KTT_NULL,	VREAD,		VDIR },#endif	{ "rootdev",	0,		KTT_NULL,	VREAD,		VBLK },	{ "rrootdev",	0,		KTT_NULL,	VREAD,		VCHR },	{ "time",	0,		KTT_TIME,	VREAD,		VREG },	{ "version",	version,	KTT_STRING,	VREAD,		VREG },};static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);static intkernfs_xread(kt, buf, len, lenp)	struct kern_target *kt;	char *buf;	int len;	int *lenp;{	switch (kt->kt_tag) {	case KTT_TIME: {		struct timeval tv;		microtime(&tv);		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);		break;	}	case KTT_INT: {		int *ip = kt->kt_data;		sprintf(buf, "%d\n", *ip);		break;	}	case KTT_STRING: {		char *cp = kt->kt_data;		int xlen = strlen(cp) + 1;		if (xlen >= len)			return (EINVAL);		bcopy(cp, buf, xlen);		break;	}	case KTT_HOSTNAME: {		char *cp = hostname;		int xlen = hostnamelen;		if (xlen >= (len-2))			return (EINVAL);		bcopy(cp, buf, xlen);		buf[xlen] = '\n';		buf[xlen+1] = '\0';		break;	}	case KTT_AVENRUN:		sprintf(buf, "%ld %ld %ld %ld\n",				averunnable.ldavg[0],				averunnable.ldavg[1],				averunnable.ldavg[2],				averunnable.fscale);		break;	default:		return (EINVAL);	}	*lenp = strlen(buf);	return (0);}static intkernfs_xwrite(kt, buf, len)	struct kern_target *kt;	char *buf;	int len;{	switch (kt->kt_tag) {	case KTT_HOSTNAME: {		if (buf[len-1] == '\n')			--len;		bcopy(buf, hostname, len);		hostname[len] = '\0';		hostnamelen = len;		return (0);	}	default:		return (EIO);	}}/* * vp is the current namei directory * ndp is the name to locate in that directory... */kernfs_lookup(ap)	struct vop_lookup_args /* {		struct vnode * a_dvp;		struct vnode ** a_vpp;		struct componentname * a_cnp;	} */ *ap;{	struct vnode **vpp = ap->a_vpp;	struct vnode *dvp = ap->a_dvp;	struct componentname *cnp = ap->a_cnp;	struct vnode *fvp;	int error, i;	char *pname;#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup(%x)\n", ap);	printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp);#endif	pname = cnp->cn_nameptr;#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup(%s)\n", pname);#endif	if (cnp->cn_namelen == 1 && *pname == '.') {		*vpp = dvp;		VREF(dvp);		/*VOP_LOCK(dvp);*/		return (0);	}#if 0	if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {		*vpp = rootdir;		VREF(rootdir);		VOP_LOCK(rootdir);		return (0);	}#endif	/*	 * /kern/rootdev is the root device	 */	if (cnp->cn_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {		*vpp = rootvp;		VREF(rootvp);		VOP_LOCK(rootvp);		return (0);	}	/*	 * /kern/rrootdev is the raw root device	 */	if (cnp->cn_namelen == 8 && bcmp(pname, "rrootdev", 8) == 0) {		if (rrootvp) {			*vpp = rrootvp;			VREF(rrootvp);			VOP_LOCK(rrootvp);			return (0);		}		error = ENXIO;		goto bad;	}	error = ENOENT;	for (i = 0; i < nkern_targets; i++) {		struct kern_target *kt = &kern_targets[i];		if (cnp->cn_namelen == strlen(kt->kt_name) &&		    bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {			error = 0;			break;		}	}#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup: i = %d, error = %d\n", i, error);#endif	if (error)		goto bad;#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup: allocate new vnode\n");#endif	error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);	if (error)		goto bad;	MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);	VTOKERN(fvp)->kf_kt = &kern_targets[i];	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;	*vpp = fvp;#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup: newvp = %x\n", fvp);#endif	return (0);bad:;	*vpp = NULL;#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_lookup: error = %d\n", error);#endif	return (error);}kernfs_open(ap)	struct vop_open_args /* {		struct vnode *a_vp;		int  a_mode;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	struct vnode *vp = ap->a_vp;	/*	 * Can always open the root (modulo perms)	 */	if (vp->v_flag & VROOT)		return (0);#ifdef KERNFS_DIAGNOSTIC	printf("kernfs_open, mode = %x, file = %s\n",			ap->a_mode, VTOKERN(vp)->kf_kt->kt_name);#endif	if ((ap->a_mode & FWRITE) && !(VTOKERN(vp)->kf_kt->kt_rw & VWRITE))		return (EOPNOTSUPP);	return (0);}static intkernfs_access(ap)	struct vop_access_args /* {		struct vnode *a_vp;		int  a_mode;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	struct vnode *vp = ap->a_vp;	struct ucred *cred = ap->a_cred;	mode_t mode = ap->a_mode;	if (mode & VEXEC) {		if (vp->v_flag & VROOT)			return (0);		return (EACCES);	}	if (cred->cr_uid == 0) {		if ((vp->v_flag & VROOT) == 0) {			struct kern_target *kt = VTOKERN(vp)->kf_kt;			if ((mode & VWRITE) && !(kt->kt_rw & VWRITE))				return (EROFS);		}		return (0);	}	if (mode & VWRITE)		return (EACCES);	return (0);}kernfs_getattr(ap)	struct vop_getattr_args /* {		struct vnode *a_vp;		struct vattr *a_vap;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap;{	struct vnode *vp = ap->a_vp;	struct vattr *vap = ap->a_vap;	int error = 0;	char strbuf[KSTRING];	bzero((caddr_t) vap, sizeof(*vap));	vattr_null(vap);	vap->va_uid = 0;	vap->va_gid = 0;	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];	/* vap->va_qsize = 0; */	vap->va_blocksize = DEV_BSIZE;	microtime(&vap->va_atime);	vap->va_mtime = vap->va_atime;	vap->va_ctime = vap->va_ctime;	vap->va_gen = 0;	vap->va_flags = 0;	vap->va_rdev = 0;

⌨️ 快捷键说明

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