procfs_vnops.c
来自「早期freebsd实现」· C语言 代码 · 共 815 行 · 第 1/2 页
C
815 行
/* * Copyright (c) 1993 Jan-Simon Pendry * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed 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. * * @(#)procfs_vnops.c 8.6 (Berkeley) 2/7/94 * * From: * $Id: procfs_vnops.c,v 3.2 1993/12/15 09:40:17 jsp Exp $ *//* * procfs vnode interface */#include <sys/param.h>#include <sys/systm.h>#include <sys/time.h>#include <sys/kernel.h>#include <sys/file.h>#include <sys/proc.h>#include <sys/vnode.h>#include <sys/namei.h>#include <sys/malloc.h>#include <sys/dirent.h>#include <sys/resourcevar.h>#include <miscfs/procfs/procfs.h>#include <vm/vm.h> /* for PAGE_SIZE *//* * Vnode Operations. * *//* * This is a list of the valid names in the * process-specific sub-directories. It is * used in procfs_lookup and procfs_readdir */static struct pfsnames { u_short d_namlen; char d_name[PROCFS_NAMELEN]; pfstype d_pfstype;} procent[] = {#define N(s) sizeof(s)-1, s /* namlen, nam, type */ { N("file"), Pfile }, { N("mem"), Pmem }, { N("regs"), Pregs }, { N("fpregs"), Pfpregs }, { N("ctl"), Pctl }, { N("status"), Pstatus }, { N("note"), Pnote }, { N("notepg"), Pnotepg },#undef N};#define Nprocent (sizeof(procent)/sizeof(procent[0]))static pid_t atopid __P((const char *, u_int));/* * set things up for doing i/o on * the pfsnode (vp). (vp) is locked * on entry, and should be left locked * on exit. * * for procfs we don't need to do anything * in particular for i/o. all that is done * is to support exclusive open on process * memory images. */procfs_open(ap) struct vop_open_args *ap;{ struct pfsnode *pfs = VTOPFS(ap->a_vp); switch (pfs->pfs_type) { case Pmem: if (PFIND(pfs->pfs_pid) == 0) return (ENOENT); /* was ESRCH, jsp */ if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) || (pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE)) return (EBUSY); if (ap->a_mode & FWRITE) pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); return (0); default: break; } return (0);}/* * close the pfsnode (vp) after doing i/o. * (vp) is not locked on entry or exit. * * nothing to do for procfs other than undo * any exclusive open flag (see _open above). */procfs_close(ap) struct vop_close_args *ap;{ struct pfsnode *pfs = VTOPFS(ap->a_vp); switch (pfs->pfs_type) { case Pmem: if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) pfs->pfs_flags &= ~(FWRITE|O_EXCL); break; } return (0);}/* * do an ioctl operation on pfsnode (vp). * (vp) is not locked on entry or exit. */procfs_ioctl(ap) struct vop_ioctl_args *ap;{ return (ENOTTY);}/* * do block mapping for pfsnode (vp). * since we don't use the buffer cache * for procfs this function should never * be called. in any case, it's not clear * what part of the kernel ever makes use * of this function. for sanity, this is the * usual no-op bmap, although returning * (EIO) would be a reasonable alternative. */procfs_bmap(ap) struct vop_bmap_args *ap;{ if (ap->a_vpp != NULL) *ap->a_vpp = ap->a_vp; if (ap->a_bnp != NULL) *ap->a_bnp = ap->a_bn; return (0);}/* * _inactive is called when the pfsnode * is vrele'd and the reference count goes * to zero. (vp) will be on the vnode free * list, so to get it back vget() must be * used. * * for procfs, check if the process is still * alive and if it isn't then just throw away * the vnode by calling vgone(). this may * be overkill and a waste of time since the * chances are that the process will still be * there and PFIND is not free. * * (vp) is not locked on entry or exit. */procfs_inactive(ap) struct vop_inactive_args *ap;{ struct pfsnode *pfs = VTOPFS(ap->a_vp); if (PFIND(pfs->pfs_pid) == 0) vgone(ap->a_vp); return (0);}/* * _reclaim is called when getnewvnode() * wants to make use of an entry on the vnode * free list. at this time the filesystem needs * to free any private data and remove the node * from any private lists. */procfs_reclaim(ap) struct vop_reclaim_args *ap;{ int error; error = procfs_freevp(ap->a_vp); return (error);}/* * Return POSIX pathconf information applicable to special devices. */procfs_pathconf(ap) struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; int *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 is used for debugging. * just print a readable description * of (vp). */procfs_print(ap) struct vop_print_args *ap;{ struct pfsnode *pfs = VTOPFS(ap->a_vp); printf("tag VT_PROCFS, pid %d, mode %x, flags %x\n", pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);}/* * _abortop is called when operations such as * rename and create fail. this entry is responsible * for undoing any side-effects caused by the lookup. * this will always include freeing the pathname buffer. */procfs_abortop(ap) struct vop_abortop_args *ap;{ if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); return (0);}/* * generic entry point for unsupported operations */procfs_badop(){ return (EIO);}/* * Invent attributes for pfsnode (vp) and store * them in (vap). * Directories lengths are returned as zero since * any real length would require the genuine size * to be computed, and nothing cares anyway. * * this is relatively minimal for procfs. */procfs_getattr(ap) struct vop_getattr_args *ap;{ struct pfsnode *pfs = VTOPFS(ap->a_vp); struct vattr *vap = ap->a_vap; struct proc *procp; int error; /* first check the process still exists */ switch (pfs->pfs_type) { case Proot: procp = 0; break; default: procp = PFIND(pfs->pfs_pid); if (procp == 0) return (ENOENT); } error = 0; /* start by zeroing out the attributes */ VATTR_NULL(vap); /* next do all the common fields */ vap->va_type = ap->a_vp->v_type; vap->va_mode = pfs->pfs_mode; vap->va_fileid = pfs->pfs_fileno; vap->va_flags = 0; vap->va_blocksize = PAGE_SIZE; vap->va_bytes = vap->va_size = 0; /* * If the process has exercised some setuid or setgid * privilege, then rip away read/write permission so * that only root can gain access. */ switch (pfs->pfs_type) { case Pregs: case Pfpregs: case Pmem: if (procp->p_flag & P_SUGID) vap->va_mode &= ~((VREAD|VWRITE)| ((VREAD|VWRITE)>>3)| ((VREAD|VWRITE)>>6)); break; } /* * Make all times be current TOD. * It would be possible to get the process start * time from the p_stat structure, but there's * no "file creation" time stamp anyway, and the * p_stat structure is not addressible if u. gets * swapped out for that process. */ microtime(&vap->va_ctime); vap->va_atime = vap->va_mtime = vap->va_ctime; /* * now do the object specific fields * * The size could be set from struct reg, but it's hardly * worth the trouble, and it puts some (potentially) machine * dependent data into this machine-independent code. If it * becomes important then this function should break out into * a per-file stat function in the corresponding .c file. */ switch (pfs->pfs_type) { case Proot: vap->va_nlink = 2; vap->va_uid = 0; vap->va_gid = 0; break; case Pproc: vap->va_nlink = 2; vap->va_uid = procp->p_ucred->cr_uid; vap->va_gid = procp->p_ucred->cr_gid; break; case Pfile: error = EOPNOTSUPP; break; case Pmem: vap->va_nlink = 1; vap->va_bytes = vap->va_size = ctob(procp->p_vmspace->vm_tsize + procp->p_vmspace->vm_dsize + procp->p_vmspace->vm_ssize); vap->va_uid = procp->p_ucred->cr_uid; vap->va_gid = procp->p_ucred->cr_gid; break; case Pregs:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?