diff options
author | 1995-10-18 08:37:01 +0000 | |
---|---|---|
committer | 1995-10-18 08:37:01 +0000 | |
commit | df930be708d50e9715f173caa26ffe1b7599b157 (patch) | |
tree | aa317e49e28cb999c9cf3db7f00c20903fe6010a /sys/miscfs/kernfs | |
download | wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.tar.xz wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.zip |
initial import of NetBSD tree
Diffstat (limited to 'sys/miscfs/kernfs')
-rw-r--r-- | sys/miscfs/kernfs/kernfs.h | 58 | ||||
-rw-r--r-- | sys/miscfs/kernfs/kernfs_vfsops.c | 314 | ||||
-rw-r--r-- | sys/miscfs/kernfs/kernfs_vnops.c | 747 |
3 files changed, 1119 insertions, 0 deletions
diff --git a/sys/miscfs/kernfs/kernfs.h b/sys/miscfs/kernfs/kernfs.h new file mode 100644 index 00000000000..88434ff093f --- /dev/null +++ b/sys/miscfs/kernfs/kernfs.h @@ -0,0 +1,58 @@ +/* $NetBSD: kernfs.h,v 1.9 1995/03/29 22:08:22 briggs Exp $ */ + +/* + * 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.h 8.5 (Berkeley) 6/15/94 + */ + +#define _PATH_KERNFS "/kern" /* Default mountpoint */ + +#ifdef _KERNEL +struct kernfs_mount { + struct vnode *kf_root; /* Root node */ +}; + +struct kernfs_node { + struct kern_target *kf_kt; +}; + +#define VFSTOKERNFS(mp) ((struct kernfs_mount *)((mp)->mnt_data)) +#define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data) + +extern int (**kernfs_vnodeop_p)(); +extern struct vfsops kernfs_vfsops; +extern dev_t rrootdev; +#endif /* _KERNEL */ diff --git a/sys/miscfs/kernfs/kernfs_vfsops.c b/sys/miscfs/kernfs/kernfs_vfsops.c new file mode 100644 index 00000000000..e224cabed8c --- /dev/null +++ b/sys/miscfs/kernfs/kernfs_vfsops.c @@ -0,0 +1,314 @@ +/* $NetBSD: kernfs_vfsops.c,v 1.24 1995/06/18 14:47:27 cgd Exp $ */ + +/* + * 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_vfsops.c 8.5 (Berkeley) 6/15/94 + */ + +/* + * Kernel params Filesystem + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/types.h> +#include <sys/proc.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/namei.h> +#include <sys/malloc.h> + +#include <miscfs/specfs/specdev.h> +#include <miscfs/kernfs/kernfs.h> + +dev_t rrootdev = NODEV; + +kernfs_init() +{ + +} + +void +kernfs_get_rrootdev() +{ + static int tried = 0; + int cmaj; + + if (tried) { + /* Already did it once. */ + return; + } + tried = 1; + + if (rootdev == NODEV) + return; + for (cmaj = 0; cmaj < nchrdev; cmaj++) { + rrootdev = makedev(cmaj, minor(rootdev)); + if (chrtoblk(rrootdev) == rootdev) + return; + } + rrootdev = NODEV; + printf("kernfs_get_rrootdev: no raw root device\n"); +} + +/* + * Mount the Kernel params filesystem + */ +kernfs_mount(mp, path, data, ndp, p) + struct mount *mp; + char *path; + caddr_t data; + struct nameidata *ndp; + struct proc *p; +{ + int error = 0; + size_t size; + struct kernfs_mount *fmp; + struct vnode *rvp; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_mount(mp = %x)\n", mp); +#endif + + /* + * Update is a no-op + */ + if (mp->mnt_flag & MNT_UPDATE) + return (EOPNOTSUPP); + + if (error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp)) + return (error); + + MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), + M_MISCFSMNT, M_WAITOK); + rvp->v_type = VDIR; + rvp->v_flag |= VROOT; +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_mount: root vp = %x\n", rvp); +#endif + fmp->kf_root = rvp; + mp->mnt_flag |= MNT_LOCAL; + mp->mnt_data = (qaddr_t)fmp; + getnewfsid(mp, makefstype(MOUNT_KERNFS)); + + (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); + bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); + bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); + bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs")); +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname); +#endif + + kernfs_get_rrootdev(); + return (0); +} + +kernfs_start(mp, flags, p) + struct mount *mp; + int flags; + struct proc *p; +{ + + return (0); +} + +kernfs_unmount(mp, mntflags, p) + struct mount *mp; + int mntflags; + struct proc *p; +{ + int error; + int flags = 0; + extern int doforce; + struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_unmount(mp = %x)\n", mp); +#endif + + if (mntflags & MNT_FORCE) { + /* kernfs can never be rootfs so don't check for it */ + if (!doforce) + return (EINVAL); + flags |= FORCECLOSE; + } + + /* + * Clear out buffer cache. I don't think we + * ever get anything cached at this level at the + * moment, but who knows... + */ + if (rootvp->v_usecount > 1) + return (EBUSY); +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_unmount: calling vflush\n"); +#endif + if (error = vflush(mp, rootvp, flags)) + return (error); + +#ifdef KERNFS_DIAGNOSTIC + vprint("kernfs root", rootvp); +#endif + /* + * Clean out the old root vnode for reuse. + */ + vrele(rootvp); + vgone(rootvp); + /* + * Finally, throw away the kernfs_mount structure + */ + free(mp->mnt_data, M_MISCFSMNT); + mp->mnt_data = 0; + return (0); +} + +kernfs_root(mp, vpp) + struct mount *mp; + struct vnode **vpp; +{ + struct vnode *vp; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_root(mp = %x)\n", mp); +#endif + + /* + * Return locked reference to root. + */ + vp = VFSTOKERNFS(mp)->kf_root; + VREF(vp); + VOP_LOCK(vp); + *vpp = vp; + return (0); +} + +kernfs_quotactl(mp, cmd, uid, arg, p) + struct mount *mp; + int cmd; + uid_t uid; + caddr_t arg; + struct proc *p; +{ + + return (EOPNOTSUPP); +} + +kernfs_statfs(mp, sbp, p) + struct mount *mp; + struct statfs *sbp; + struct proc *p; +{ + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_statfs(mp = %x)\n", mp); +#endif + +#ifdef COMPAT_09 + sbp->f_type = 7; +#else + sbp->f_type = 0; +#endif + sbp->f_bsize = DEV_BSIZE; + sbp->f_iosize = DEV_BSIZE; + sbp->f_blocks = 2; /* 1K to keep df happy */ + sbp->f_bfree = 0; + sbp->f_bavail = 0; + sbp->f_files = 0; + sbp->f_ffree = 0; + if (sbp != &mp->mnt_stat) { + bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); + bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); + bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); + } + strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); + return (0); +} + +kernfs_sync(mp, waitfor) + struct mount *mp; + int waitfor; +{ + + return (0); +} + +/* + * Kernfs flat namespace lookup. + * Currently unsupported. + */ +kernfs_vget(mp, ino, vpp) + struct mount *mp; + ino_t ino; + struct vnode **vpp; +{ + + return (EOPNOTSUPP); +} + + +kernfs_fhtovp(mp, fhp, setgen, vpp) + struct mount *mp; + struct fid *fhp; + int setgen; + struct vnode **vpp; +{ + + return (EOPNOTSUPP); +} + +kernfs_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; +{ + + return (EOPNOTSUPP); +} + +struct vfsops kernfs_vfsops = { + MOUNT_KERNFS, + kernfs_mount, + kernfs_start, + kernfs_unmount, + kernfs_root, + kernfs_quotactl, + kernfs_statfs, + kernfs_sync, + kernfs_vget, + kernfs_fhtovp, + kernfs_vptofh, + kernfs_init, +}; diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c new file mode 100644 index 00000000000..e7e565bcd55 --- /dev/null +++ b/sys/miscfs/kernfs/kernfs_vnops.c @@ -0,0 +1,747 @@ +/* $NetBSD: kernfs_vnops.c,v 1.39 1995/10/09 14:25:02 mycroft Exp $ */ + +/* + * 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.9 (Berkeley) 6/15/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 <sys/msgbuf.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 { + u_char kt_type; + u_char kt_namlen; + 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 +#define KTT_DEVICE 71 +#define KTT_MSGBUF 89 + u_char kt_tag; + u_char kt_vtype; + mode_t kt_mode; +} kern_targets[] = { +/* NOTE: The name must be less than UIO_MX-16 chars in length */ +#define N(s) sizeof(s)-1, s + /* name data tag type ro/rw */ + { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE }, + { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE }, + { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE }, + { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE }, + { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE }, + { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE }, + { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, + { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, + { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE }, + { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, +#if 0 + { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, +#endif + { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE }, + { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE }, + { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE }, + { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE }, +#undef N +}; +static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); + +int +kernfs_xread(kt, off, bufp, len) + struct kern_target *kt; + int off; + char **bufp; + int len; +{ + + switch (kt->kt_tag) { + case KTT_TIME: { + struct timeval tv; + + microtime(&tv); + sprintf(*bufp, "%d %d\n", tv.tv_sec, tv.tv_usec); + break; + } + + case KTT_INT: { + int *ip = kt->kt_data; + + sprintf(*bufp, "%d\n", *ip); + break; + } + + case KTT_STRING: { + char *cp = kt->kt_data; + + *bufp = cp; + break; + } + + case KTT_MSGBUF: { + extern struct msgbuf *msgbufp; + long n; + + if (off >= MSG_BSIZE) + return (0); + n = msgbufp->msg_bufx + off; + if (n >= MSG_BSIZE) + n -= MSG_BSIZE; + len = min(MSG_BSIZE - n, MSG_BSIZE - off); + *bufp = msgbufp->msg_bufc + n; + return (len); + } + + case KTT_HOSTNAME: { + char *cp = hostname; + int xlen = hostnamelen; + + if (xlen >= (len-2)) + return (EINVAL); + + bcopy(cp, *bufp, xlen); + (*bufp)[xlen] = '\n'; + (*bufp)[xlen+1] = '\0'; + break; + } + + case KTT_AVENRUN: + averunnable.fscale = FSCALE; + sprintf(*bufp, "%ld %ld %ld %ld\n", + averunnable.ldavg[0], averunnable.ldavg[1], + averunnable.ldavg[2], averunnable.fscale); + break; + + default: + return (0); + } + + len = strlen(*bufp); + if (len <= off) + return (0); + *bufp += off; + return (len - off); +} + +int +kernfs_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 componentname *cnp = ap->a_cnp; + struct vnode **vpp = ap->a_vpp; + struct vnode *dvp = ap->a_dvp; + char *pname = cnp->cn_nameptr; + struct kern_target *kt; + struct vnode *fvp; + int error, i; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_lookup(%x)\n", ap); + printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp); + printf("kernfs_lookup(%s)\n", pname); +#endif + + *vpp = NULLVP; + + if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) + return (EROFS); + + 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 + + for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) { + if (cnp->cn_namelen == kt->kt_namlen && + bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) + goto found; + } + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_lookup: i = %d, failed", i); +#endif + + return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); + +found: + if (kt->kt_tag == KTT_DEVICE) { + dev_t *dp = kt->kt_data; + loop: + if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) + return (ENOENT); + *vpp = fvp; + if (vget(fvp, 1)) + goto loop; + return (0); + } + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_lookup: allocate new vnode\n"); +#endif + if (error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, + &fvp)) + return (error); + + MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, + M_WAITOK); + VTOKERN(fvp)->kf_kt = kt; + fvp->v_type = kt->kt_vtype; + *vpp = fvp; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_lookup: newvp = %x\n", fvp); +#endif + return (0); +} + +kernfs_open(ap) + struct vop_open_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + + /* Only need to check access permissions. */ + return (0); +} + +int +kernfs_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; + mode_t fmode = + (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode; + + return (vaccess(fmode, (uid_t)0, (gid_t)0, ap->a_mode, ap->a_cred)); +} + +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; + struct timeval tv; + int error = 0; + char strbuf[KSTRING], *buf; + + 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_size = 0; + vap->va_blocksize = DEV_BSIZE; + microtime(&tv); + TIMEVAL_TO_TIMESPEC(&tv, &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; + vap->va_bytes = 0; + + if (vp->v_flag & VROOT) { +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_getattr: stat rootdir\n"); +#endif + vap->va_type = VDIR; + vap->va_mode = DIR_MODE; + vap->va_nlink = 2; + vap->va_fileid = 2; + vap->va_size = DEV_BSIZE; + } else { + struct kern_target *kt = VTOKERN(vp)->kf_kt; + int nbytes, total; +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_getattr: stat target %s\n", kt->kt_name); +#endif + vap->va_type = kt->kt_vtype; + vap->va_mode = kt->kt_mode; + vap->va_nlink = 1; + vap->va_fileid = 3 + (kt - kern_targets); + total = 0; + while (buf = strbuf, + nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf))) + total += nbytes; + vap->va_size = total; + } + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_getattr: return error %d\n", error); +#endif + return (error); +} + +kernfs_setattr(ap) + struct vop_setattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct proc *a_p; + } */ *ap; +{ + + /* + * Silently ignore attribute changes. + * This allows for open with truncate to have no + * effect until some data is written. I want to + * do it this way because all writes are atomic. + */ + return (0); +} + +int +kernfs_read(ap) + struct vop_read_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + struct kern_target *kt; + char strbuf[KSTRING], *buf; + int off, len; + int error; + + if (vp->v_type == VDIR) + return (EOPNOTSUPP); + + kt = VTOKERN(vp)->kf_kt; + +#ifdef KERNFS_DIAGNOSTIC + printf("kern_read %s\n", kt->kt_name); +#endif + + off = uio->uio_offset; +#if 0 + while (buf = strbuf, +#else + if (buf = strbuf, +#endif + len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) { + if (error = uiomove(buf, len, uio)) + return (error); + off += len; + } + return (0); +} + +int +kernfs_write(ap) + struct vop_write_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + struct kern_target *kt; + int error, xlen; + char strbuf[KSTRING]; + + if (vp->v_type == VDIR) + return (EOPNOTSUPP); + + kt = VTOKERN(vp)->kf_kt; + + if (uio->uio_offset != 0) + return (EINVAL); + + xlen = min(uio->uio_resid, KSTRING-1); + if (error = uiomove(strbuf, xlen, uio)) + return (error); + + if (uio->uio_resid != 0) + return (EIO); + + strbuf[xlen] = '\0'; + xlen = strlen(strbuf); + return (kernfs_xwrite(kt, strbuf, xlen)); +} + +kernfs_readdir(ap) + struct vop_readdir_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + int *a_eofflag; + u_long *a_cookies; + int a_ncookies; + } */ *ap; +{ + struct uio *uio = ap->a_uio; + struct dirent d; + struct kern_target *kt; + int i; + int error; + u_long *cookies = ap->a_cookies; + int ncookies = ap->a_ncookies; + + if (ap->a_vp->v_type != VDIR) + return (ENOTDIR); + + if (uio->uio_resid < UIO_MX) + return (EINVAL); + if (uio->uio_offset < 0) + return (EINVAL); + + error = 0; + i = uio->uio_offset; + bzero((caddr_t)&d, UIO_MX); + d.d_reclen = UIO_MX; + + for (kt = &kern_targets[i]; + uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_readdir: i = %d\n", i); +#endif + + if (kt->kt_tag == KTT_DEVICE) { + dev_t *dp = kt->kt_data; + struct vnode *fvp; + + if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) + continue; + } + + d.d_fileno = i + 3; + d.d_namlen = kt->kt_namlen; + bcopy(kt->kt_name, d.d_name, kt->kt_namlen + 1); + d.d_type = kt->kt_type; + + if (error = uiomove((caddr_t)&d, UIO_MX, uio)) + break; + if (ncookies-- > 0) + *cookies++ = i + 1; + } + + uio->uio_offset = i; + return (error); +} + +kernfs_inactive(ap) + struct vop_inactive_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_inactive(%x)\n", vp); +#endif + /* + * Clear out the v_type field to avoid + * nasty things happening in vgone(). + */ + vp->v_type = VNON; + return (0); +} + +kernfs_reclaim(ap) + struct vop_reclaim_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_reclaim(%x)\n", vp); +#endif + if (vp->v_data) { + FREE(vp->v_data, M_TEMP); + vp->v_data = 0; + } + return (0); +} + +/* + * Return POSIX pathconf information applicable to special devices. + */ +kernfs_pathconf(ap) + struct vop_pathconf_args /* { + struct vnode *a_vp; + int a_name; + register_t *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 out the contents of a /dev/fd vnode. + */ +/* ARGSUSED */ +kernfs_print(ap) + struct vop_print_args /* { + struct vnode *a_vp; + } */ *ap; +{ + + printf("tag VT_KERNFS, kernfs vnode\n"); + return (0); +} + +/*void*/ +kernfs_vfree(ap) + struct vop_vfree_args /* { + struct vnode *a_pvp; + ino_t a_ino; + int a_mode; + } */ *ap; +{ + + return (0); +} + +/* + * /dev/fd vnode unsupported operation + */ +kernfs_enotsupp() +{ + + return (EOPNOTSUPP); +} + +/* + * /dev/fd "should never get here" operation + */ +kernfs_badop() +{ + + panic("kernfs: bad op"); + /* NOTREACHED */ +} + +/* + * kernfs vnode null operation + */ +kernfs_nullop() +{ + + return (0); +} + +#define kernfs_create ((int (*) __P((struct vop_create_args *)))kernfs_enotsupp) +#define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))kernfs_enotsupp) +#define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop) +#define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))kernfs_enotsupp) +#define kernfs_select ((int (*) __P((struct vop_select_args *)))kernfs_enotsupp) +#define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))kernfs_enotsupp) +#define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) +#define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop) +#define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp) +#define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp) +#define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp) +#define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp) +#define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp) +#define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp) +#define kernfs_readlink \ + ((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp) +#define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) +#define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop) +#define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) +#define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop) +#define kernfs_strategy ((int (*) __P((struct vop_strategy_args *)))kernfs_badop) +#define kernfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) +#define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp) +#define kernfs_blkatoff \ + ((int (*) __P((struct vop_blkatoff_args *)))kernfs_enotsupp) +#define kernfs_valloc ((int(*) __P(( \ + struct vnode *pvp, \ + int mode, \ + struct ucred *cred, \ + struct vnode **vpp))) kernfs_enotsupp) +#define kernfs_truncate \ + ((int (*) __P((struct vop_truncate_args *)))kernfs_enotsupp) +#define kernfs_update ((int (*) __P((struct vop_update_args *)))kernfs_enotsupp) +#define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))kernfs_enotsupp) + +int (**kernfs_vnodeop_p)(); +struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { + { &vop_default_desc, vn_default_error }, + { &vop_lookup_desc, kernfs_lookup }, /* lookup */ + { &vop_create_desc, kernfs_create }, /* create */ + { &vop_mknod_desc, kernfs_mknod }, /* mknod */ + { &vop_open_desc, kernfs_open }, /* open */ + { &vop_close_desc, kernfs_close }, /* close */ + { &vop_access_desc, kernfs_access }, /* access */ + { &vop_getattr_desc, kernfs_getattr }, /* getattr */ + { &vop_setattr_desc, kernfs_setattr }, /* setattr */ + { &vop_read_desc, kernfs_read }, /* read */ + { &vop_write_desc, kernfs_write }, /* write */ + { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ + { &vop_select_desc, kernfs_select }, /* select */ + { &vop_mmap_desc, kernfs_mmap }, /* mmap */ + { &vop_fsync_desc, kernfs_fsync }, /* fsync */ + { &vop_seek_desc, kernfs_seek }, /* seek */ + { &vop_remove_desc, kernfs_remove }, /* remove */ + { &vop_link_desc, kernfs_link }, /* link */ + { &vop_rename_desc, kernfs_rename }, /* rename */ + { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ + { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ + { &vop_symlink_desc, kernfs_symlink }, /* symlink */ + { &vop_readdir_desc, kernfs_readdir }, /* readdir */ + { &vop_readlink_desc, kernfs_readlink },/* readlink */ + { &vop_abortop_desc, kernfs_abortop }, /* abortop */ + { &vop_inactive_desc, kernfs_inactive },/* inactive */ + { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ + { &vop_lock_desc, kernfs_lock }, /* lock */ + { &vop_unlock_desc, kernfs_unlock }, /* unlock */ + { &vop_bmap_desc, kernfs_bmap }, /* bmap */ + { &vop_strategy_desc, kernfs_strategy },/* strategy */ + { &vop_print_desc, kernfs_print }, /* print */ + { &vop_islocked_desc, kernfs_islocked },/* islocked */ + { &vop_pathconf_desc, kernfs_pathconf },/* pathconf */ + { &vop_advlock_desc, kernfs_advlock }, /* advlock */ + { &vop_blkatoff_desc, kernfs_blkatoff },/* blkatoff */ + { &vop_valloc_desc, kernfs_valloc }, /* valloc */ + { &vop_vfree_desc, kernfs_vfree }, /* vfree */ + { &vop_truncate_desc, kernfs_truncate },/* truncate */ + { &vop_update_desc, kernfs_update }, /* update */ + { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ + { (struct vnodeop_desc*)NULL, (int(*)())NULL } +}; +struct vnodeopv_desc kernfs_vnodeop_opv_desc = + { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; |