spec_vnops.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 737 行 · 第 1/2 页

C
737
字号
/*	$NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $	*//* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * 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. * *	@(#)spec_vnops.c	8.8 (Berkeley) 11/21/94 */#include <sys/param.h>#include <sys/proc.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/buf.h>#include <sys/mount.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/stat.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/disklabel.h>#include <miscfs/specfs/specdev.h>/* symbolic sleep message strings for devices */char	devopn[] = "devopn";char	devio[] = "devio";char	devwait[] = "devwait";char	devin[] = "devin";char	devout[] = "devout";char	devioc[] = "devioc";char	devcls[] = "devcls";int (**spec_vnodeop_p) __P((void *));struct vnodeopv_entry_desc spec_vnodeop_entries[] = {	{ &vop_default_desc, vn_default_error },	{ &vop_lookup_desc, spec_lookup },		/* lookup */	{ &vop_create_desc, spec_create },		/* create */	{ &vop_mknod_desc, spec_mknod },		/* mknod */	{ &vop_open_desc, spec_open },			/* open */	{ &vop_close_desc, spec_close },		/* close */	{ &vop_access_desc, spec_access },		/* access */	{ &vop_getattr_desc, spec_getattr },		/* getattr */	{ &vop_setattr_desc, spec_setattr },		/* setattr */	{ &vop_read_desc, spec_read },			/* read */	{ &vop_write_desc, spec_write },		/* write */	{ &vop_lease_desc, spec_lease_check },		/* lease */	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */	{ &vop_select_desc, spec_select },		/* select */	{ &vop_mmap_desc, spec_mmap },			/* mmap */	{ &vop_fsync_desc, spec_fsync },		/* fsync */	{ &vop_seek_desc, spec_seek },			/* seek */	{ &vop_remove_desc, spec_remove },		/* remove */	{ &vop_link_desc, spec_link },			/* link */	{ &vop_rename_desc, spec_rename },		/* rename */	{ &vop_mkdir_desc, spec_mkdir },		/* mkdir */	{ &vop_rmdir_desc, spec_rmdir },		/* rmdir */	{ &vop_symlink_desc, spec_symlink },		/* symlink */	{ &vop_readdir_desc, spec_readdir },		/* readdir */	{ &vop_readlink_desc, spec_readlink },		/* readlink */	{ &vop_abortop_desc, spec_abortop },		/* abortop */	{ &vop_inactive_desc, spec_inactive },		/* inactive */	{ &vop_reclaim_desc, spec_reclaim },		/* reclaim */	{ &vop_lock_desc, spec_lock },			/* lock */	{ &vop_unlock_desc, spec_unlock },		/* unlock */	{ &vop_bmap_desc, spec_bmap },			/* bmap */	{ &vop_strategy_desc, spec_strategy },		/* strategy */	{ &vop_print_desc, spec_print },		/* print */	{ &vop_islocked_desc, spec_islocked },		/* islocked */	{ &vop_pathconf_desc, spec_pathconf },		/* pathconf */	{ &vop_advlock_desc, spec_advlock },		/* advlock */	{ &vop_blkatoff_desc, spec_blkatoff },		/* blkatoff */	{ &vop_valloc_desc, spec_valloc },		/* valloc */	{ &vop_vfree_desc, spec_vfree },		/* vfree */	{ &vop_truncate_desc, spec_truncate },		/* truncate */	{ &vop_update_desc, spec_update },		/* update */	{ &vop_bwrite_desc, spec_bwrite },		/* bwrite */	{ (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL }};struct vnodeopv_desc spec_vnodeop_opv_desc =	{ &spec_vnodeop_p, spec_vnodeop_entries };/* * Trivial lookup routine that always fails. */intspec_lookup(v)	void *v;{	struct vop_lookup_args /* {		struct vnode *a_dvp;		struct vnode **a_vpp;		struct componentname *a_cnp;	} */ *ap = v;	*ap->a_vpp = NULL;	return (ENOTDIR);}/* * Open a special file. *//* ARGSUSED */intspec_open(v)	void *v;{	struct vop_open_args /* {		struct vnode *a_vp;		int  a_mode;		struct ucred *a_cred;		struct proc *a_p;	} */ *ap = v;	struct vnode *bvp, *vp = ap->a_vp;	dev_t bdev, dev = (dev_t)vp->v_rdev;	register int maj = major(dev);	int error;	/*	 * Don't allow open if fs is mounted -nodev.	 */	if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))		return (ENXIO);	switch (vp->v_type) {	case VCHR:		if ((u_int)maj >= nchrdev)			return (ENXIO);		if (ap->a_cred != FSCRED && (ap->a_mode & FWRITE)) {			/*			 * When running in very secure mode, do not allow			 * opens for writing of any disk character devices.			 */			if (securelevel >= 2 && cdevsw[maj].d_type == D_DISK)				return (EPERM);			/*			 * When running in secure mode, do not allow opens			 * for writing of /dev/mem, /dev/kmem, or character			 * devices whose corresponding block devices are			 * currently mounted.			 */			if (securelevel >= 1) {				if ((bdev = chrtoblk(dev)) != NODEV &&				    vfinddev(bdev, VBLK, &bvp) &&				    bvp->v_usecount > 0 &&				    (error = vfs_mountedon(bvp)))					return (error);				if (iskmemdev(dev))					return (EPERM);			}		}		if (cdevsw[maj].d_type == D_TTY)			vp->v_flag |= VISTTY;		VOP_UNLOCK(vp);		error = (*cdevsw[maj].d_open)(dev, ap->a_mode, S_IFCHR, ap->a_p);		VOP_LOCK(vp);		return (error);	case VBLK:		if ((u_int)maj >= nblkdev)			return (ENXIO);		/*		 * When running in very secure mode, do not allow		 * opens for writing of any disk block devices.		 */		if (securelevel >= 2 && ap->a_cred != FSCRED &&		    (ap->a_mode & FWRITE) && bdevsw[maj].d_type == D_DISK)			return (EPERM);		/*		 * Do not allow opens of block devices that are		 * currently mounted.		 */		if ((error = vfs_mountedon(vp)) != 0)			return (error);		return ((*bdevsw[maj].d_open)(dev, ap->a_mode, S_IFBLK, ap->a_p));	case VNON:	case VLNK:	case VDIR:	case VREG:	case VBAD:	case VFIFO:	case VSOCK:		break;	}	return (0);}/* * Vnode op for read *//* ARGSUSED */intspec_read(v)	void *v;{	struct vop_read_args /* {		struct vnode *a_vp;		struct uio *a_uio;		int  a_ioflag;		struct ucred *a_cred;	} */ *ap = v;	register struct vnode *vp = ap->a_vp;	register struct uio *uio = ap->a_uio; 	struct proc *p = uio->uio_procp;	struct buf *bp;	daddr_t bn, nextbn;	long bsize, bscale, ssize;	struct partinfo dpart;	int n, on, majordev;	int (*ioctl) __P((dev_t, u_long, caddr_t, int, struct proc *));	int error = 0;#ifdef DIAGNOSTIC	if (uio->uio_rw != UIO_READ)		panic("spec_read mode");	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)		panic("spec_read proc");#endif	if (uio->uio_resid == 0)		return (0);	switch (vp->v_type) {	case VCHR:		VOP_UNLOCK(vp);		error = (*cdevsw[major(vp->v_rdev)].d_read)			(vp->v_rdev, uio, ap->a_ioflag);		VOP_LOCK(vp);		return (error);	case VBLK:		if (uio->uio_resid == 0)			return (0);		if (uio->uio_offset < 0)			return (EINVAL);		bsize = BLKDEV_IOSIZE;		ssize = DEV_BSIZE;		if ((majordev = major(vp->v_rdev)) < nblkdev &&		    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&		    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {			if (dpart.part->p_fstype == FS_BSDFFS &&			    dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)				bsize = dpart.part->p_frag *				    dpart.part->p_fsize;			if (dpart.disklab->d_secsize != 0)				ssize = dpart.disklab->d_secsize;		}		bscale = bsize / ssize;		do {			bn = (uio->uio_offset / ssize) &~ (bscale - 1);			on = uio->uio_offset % bsize;			n = min((unsigned)(bsize - on), uio->uio_resid);			if (vp->v_lastr + bscale == bn) {				nextbn = bn + bscale;				error = breadn(vp, bn, (int)bsize, &nextbn,					(int *)&bsize, 1, NOCRED, &bp);			} else				error = bread(vp, bn, (int)bsize, NOCRED, &bp);			vp->v_lastr = bn;			n = min(n, bsize - bp->b_resid);			if (error) {				brelse(bp);				return (error);			}			error = uiomove((char *)bp->b_data + on, n, uio);			brelse(bp);		} while (error == 0 && uio->uio_resid > 0 && n != 0);		return (error);	default:		panic("spec_read type");	}	/* NOTREACHED */}/* * Vnode op for write *//* ARGSUSED */intspec_write(v)	void *v;{	struct vop_write_args /* {		struct vnode *a_vp;		struct uio *a_uio;		int  a_ioflag;		struct ucred *a_cred;	} */ *ap = v;	register struct vnode *vp = ap->a_vp;	register struct uio *uio = ap->a_uio;	struct proc *p = uio->uio_procp;	struct buf *bp;	daddr_t bn;	long bsize, bscale, ssize;	struct partinfo dpart;	int n, on, majordev;	int (*ioctl) __P((dev_t, u_long, caddr_t, int, struct proc *));	int error = 0;#ifdef DIAGNOSTIC	if (uio->uio_rw != UIO_WRITE)		panic("spec_write mode");	if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)		panic("spec_write proc");#endif	switch (vp->v_type) {	case VCHR:		VOP_UNLOCK(vp);		error = (*cdevsw[major(vp->v_rdev)].d_write)			(vp->v_rdev, uio, ap->a_ioflag);		VOP_LOCK(vp);		return (error);	case VBLK:		if (uio->uio_resid == 0)			return (0);		if (uio->uio_offset < 0)			return (EINVAL);		bsize = BLKDEV_IOSIZE;		ssize = DEV_BSIZE;		if ((majordev = major(vp->v_rdev)) < nblkdev &&		    (ioctl = bdevsw[majordev].d_ioctl) != NULL &&		    (*ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) {			if (dpart.part->p_fstype == FS_BSDFFS &&			    dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)				bsize = dpart.part->p_frag *				    dpart.part->p_fsize;			if (dpart.disklab->d_secsize != 0)				ssize = dpart.disklab->d_secsize;		}		bscale = bsize / ssize;		do {			bn = (uio->uio_offset / ssize) &~ (bscale - 1);			on = uio->uio_offset % bsize;			n = min((unsigned)(bsize - on), uio->uio_resid);

⌨️ 快捷键说明

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