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 + -
显示快捷键?