diff options
author | des <des@FreeBSD.org> | 2001-06-10 23:24:14 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2001-06-10 23:24:14 +0000 |
commit | 7183d49acf6d9c3725c3e96da424d7f470e671fb (patch) | |
tree | bb8366a13739907eafcd96e16836ef16e669d5ba /sys/compat/linprocfs | |
parent | 2a797ca9f1de2817083061efea0d7526d99129d6 (diff) | |
download | FreeBSD-src-7183d49acf6d9c3725c3e96da424d7f470e671fb.zip FreeBSD-src-7183d49acf6d9c3725c3e96da424d7f470e671fb.tar.gz |
These aren't needed any more.
Diffstat (limited to 'sys/compat/linprocfs')
-rw-r--r-- | sys/compat/linprocfs/linprocfs.h | 146 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_misc.c | 668 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_subr.c | 316 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_vfsops.c | 179 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_vnops.c | 854 |
5 files changed, 0 insertions, 2163 deletions
diff --git a/sys/compat/linprocfs/linprocfs.h b/sys/compat/linprocfs/linprocfs.h deleted file mode 100644 index 381ce21..0000000 --- a/sys/compat/linprocfs/linprocfs.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org> - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * Copyright (c) 1999 Pierre Beyssac - * 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.h 8.9 (Berkeley) 5/14/95 - * - * $FreeBSD$ - */ - -struct pfsnode; - -typedef int node_action_t __P((struct proc *curp, struct proc *p, - struct pfsnode *pfs, struct uio *uio)); - -struct node_data { - char *nd_name; - u_char nd_namlen; - u_char nd_type; - u_short nd_mode; - int nd_flags; - node_action_t *nd_action; -}; - -/* - * flag bits for nd_flags. - */ -#define PDEP 0x01 /* entry is process-dependent */ - -/* - * control data for the proc file system. - */ -struct pfsnode { - struct pfsnode *pfs_next; /* next on list */ - struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ - struct node_data *pfs_nd; /* static initializer */ - pid_t pfs_pid; /* associated process */ - u_long pfs_flags; /* open flags */ - u_long pfs_fileno; /* unique file id */ - pid_t pfs_lockowner; /* pfs lock owner */ -}; - -#define PROCFS_NAMELEN 8 /* max length of a filename component */ - -/* - * Kernel stuff follows - */ -#ifdef _KERNEL -#define KMEM_GROUP 2 - -#define PROCFS_FILENO(nd, pid) \ - ((nd)->nd_flags & PDEP) ? \ - (((pid) + 1) << 4) | ((((u_long)(nd)) >> 3) & 0x0f) : \ - (u_long)((nd)->nd_action) - -/* - * Convert between pfsnode vnode - */ -#define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data) -#define PFSTOV(pfs) ((pfs)->pfs_vnode) - -typedef struct vfs_namemap vfs_namemap_t; -struct vfs_namemap { - const char *nm_name; - int nm_val; -}; - -int vfs_getuserstr __P((struct uio *, char *, int *)); -vfs_namemap_t *vfs_findname __P((vfs_namemap_t *, char *, int)); - -/* <machine/reg.h> */ -struct reg; -struct fpreg; -struct dbreg; - -#define PFIND(pid) (pfind(pid)) - -void linprocfs_exit __P((struct proc *)); -int linprocfs_freevp __P((struct vnode *)); -int linprocfs_allocvp __P((struct mount *, struct vnode **, long, - struct node_data *)); - -node_action_t linprocfs_docmdline; -node_action_t linprocfs_docpuinfo; -node_action_t linprocfs_dodevices; -node_action_t linprocfs_doexelink; -node_action_t linprocfs_domeminfo; -node_action_t linprocfs_donetdev; -node_action_t linprocfs_doprocstat; -node_action_t linprocfs_doprocstatus; -node_action_t linprocfs_doselflink; -node_action_t linprocfs_dostat; -node_action_t linprocfs_douptime; -node_action_t linprocfs_doversion; -node_action_t linprocfs_doloadavg; - -extern node_action_t procfs_domem; -extern node_action_t procfs_docmdline; - -extern struct node_data root_dir[]; - -/* functions to check whether or not files should be displayed */ -int linprocfs_validfile __P((struct proc *)); - -#define PROCFS_LOCKED 0x01 -#define PROCFS_WANT 0x02 - -extern vop_t **linprocfs_vnodeop_p; - -int linprocfs_root __P((struct mount *, struct vnode **)); -int linprocfs_rw __P((struct vop_read_args *)); -#endif /* _KERNEL */ diff --git a/sys/compat/linprocfs/linprocfs_misc.c b/sys/compat/linprocfs/linprocfs_misc.c deleted file mode 100644 index 04858f7..0000000 --- a/sys/compat/linprocfs/linprocfs_misc.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * Copyright (c) 1999 Pierre Beyssac - * 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_status.c 8.4 (Berkeley) 6/15/94 - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/blist.h> -#include <sys/conf.h> -#include <sys/dkstat.h> -#include <sys/jail.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/resourcevar.h> -#include <sys/sbuf.h> -#include <sys/sysctl.h> -#include <sys/tty.h> -#include <sys/vnode.h> - -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> -#include <vm/vm_param.h> -#include <vm/vm_object.h> -#include <vm/vm_zone.h> -#include <vm/swap_pager.h> - -#include <sys/exec.h> -#include <sys/user.h> -#include <sys/vmmeter.h> - -#include <machine/clock.h> -#include <machine/cputypes.h> -#include <machine/md_var.h> - -#include <sys/socket.h> -#include <net/if.h> - -#include <compat/linux/linux_mib.h> -#include <compat/linprocfs/linprocfs.h> - -extern struct cdevsw *cdevsw[]; - -/* - * Various conversion macros - */ -#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ -#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ -#define B2K(x) ((x) >> 10) /* bytes to kbytes */ -#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ -#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ -#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ - -#define COMMON_START \ - struct sbuf sb; \ - char *ps; \ - int error, xlen - -#define COMMON_END \ - sbuf_finish(&sb); \ - ps = sbuf_data(&sb) + uio->uio_offset; \ - xlen = sbuf_len(&sb) - uio->uio_offset; \ - xlen = imin(xlen, uio->uio_resid); \ - error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); \ - sbuf_delete(&sb); \ - return (error) - -int -linprocfs_domeminfo(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - unsigned long memtotal; /* total memory in bytes */ - unsigned long memused; /* used memory in bytes */ - unsigned long memfree; /* free memory in bytes */ - unsigned long memshared; /* shared memory ??? */ - unsigned long buffers, cached; /* buffer / cache memory ??? */ - u_quad_t swaptotal; /* total swap space in bytes */ - u_quad_t swapused; /* used swap space in bytes */ - u_quad_t swapfree; /* free swap space in bytes */ - vm_object_t object; - - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - memtotal = physmem * PAGE_SIZE; - /* - * The correct thing here would be: - * - memfree = cnt.v_free_count * PAGE_SIZE; - memused = memtotal - memfree; - * - * but it might mislead linux binaries into thinking there - * is very little memory left, so we cheat and tell them that - * all memory that isn't wired down is free. - */ - memused = cnt.v_wire_count * PAGE_SIZE; - memfree = memtotal - memused; - if (swapblist == NULL) { - swaptotal = 0; - swapfree = 0; - } else { - swaptotal = (u_quad_t)swapblist->bl_blocks * 1024; /* XXX why 1024? */ - swapfree = (u_quad_t)swapblist->bl_root->u.bmu_avail * PAGE_SIZE; - } - swapused = swaptotal - swapfree; - memshared = 0; - TAILQ_FOREACH(object, &vm_object_list, object_list) - if (object->shadow_count > 1) - memshared += object->resident_page_count; - memshared *= PAGE_SIZE; - /* - * We'd love to be able to write: - * - buffers = bufspace; - * - * but bufspace is internal to vfs_bio.c and we don't feel - * like unstaticizing it just for linprocfs's sake. - */ - buffers = 0; - cached = cnt.v_cache_count * PAGE_SIZE; - - sbuf_new(&sb, NULL, 512, 0); - sbuf_printf(&sb, - " total: used: free: shared: buffers: cached:\n" - "Mem: %lu %lu %lu %lu %lu %lu\n" - "Swap: %llu %llu %llu\n" - "MemTotal: %9lu kB\n" - "MemFree: %9lu kB\n" - "MemShared:%9lu kB\n" - "Buffers: %9lu kB\n" - "Cached: %9lu kB\n" - "SwapTotal:%9llu kB\n" - "SwapFree: %9llu kB\n", - memtotal, memused, memfree, memshared, buffers, cached, - swaptotal, swapused, swapfree, - B2K(memtotal), B2K(memfree), - B2K(memshared), B2K(buffers), B2K(cached), - B2K(swaptotal), B2K(swapfree)); - - COMMON_END; -} - -int -linprocfs_docpuinfo(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - int class, i, fqmhz, fqkhz; - - /* - * We default the flags to include all non-conflicting flags, - * and the Intel versions of conflicting flags. - */ - static char *flags[] = { - "fpu", "vme", "de", "pse", "tsc", - "msr", "pae", "mce", "cx8", "apic", - "sep", "sep", "mtrr", "pge", "mca", - "cmov", "pat", "pse36", "pn", "b19", - "b20", "b21", "mmxext", "mmx", "fxsr", - "xmm", "b26", "b27", "b28", "b29", - "3dnowext", "3dnow" - }; - - if (uio->uio_rw != UIO_READ) - return (EOPNOTSUPP); - - switch (cpu_class) { - case CPUCLASS_286: - class = 2; - break; - case CPUCLASS_386: - class = 3; - break; - case CPUCLASS_486: - class = 4; - break; - case CPUCLASS_586: - class = 5; - break; - case CPUCLASS_686: - class = 6; - break; - default: - class = 0; - break; - } - - sbuf_new(&sb, NULL, 512, 0); - sbuf_printf(&sb, - "processor\t: %d\n" - "vendor_id\t: %.20s\n" - "cpu family\t: %d\n" - "model\t\t: %d\n" - "stepping\t: %d\n", - 0, cpu_vendor, class, cpu, cpu_id & 0xf); - - sbuf_cat(&sb, - "flags\t\t:"); - - if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { - flags[16] = "fcmov"; - } else if (!strcmp(cpu_vendor, "CyrixInstead")) { - flags[24] = "cxmmx"; - } - - for (i = 0; i < 32; i++) - if (cpu_feature & (1 << i)) - sbuf_printf(&sb, " %s", flags[i]); - sbuf_cat(&sb, "\n"); - if (class >= 5) { - fqmhz = (tsc_freq + 4999) / 1000000; - fqkhz = ((tsc_freq + 4999) / 10000) % 100; - sbuf_printf(&sb, - "cpu MHz\t\t: %d.%02d\n" - "bogomips\t: %d.%02d\n", - fqmhz, fqkhz, fqmhz, fqkhz); - } - - COMMON_END; -} - -int -linprocfs_dostat(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - - sbuf_new(&sb, NULL, 512, 0); - sbuf_printf(&sb, - "cpu %ld %ld %ld %ld\n" - "disk 0 0 0 0\n" - "page %u %u\n" - "swap %u %u\n" - "intr %u\n" - "ctxt %u\n" - "btime %ld\n", - T2J(cp_time[CP_USER]), - T2J(cp_time[CP_NICE]), - T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), - T2J(cp_time[CP_IDLE]), - cnt.v_vnodepgsin, - cnt.v_vnodepgsout, - cnt.v_swappgsin, - cnt.v_swappgsout, - cnt.v_intr, - cnt.v_swtch, - boottime.tv_sec); - - COMMON_END; -} - -int -linprocfs_douptime(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - struct timeval tv; - - getmicrouptime(&tv); - sbuf_new(&sb, NULL, 64, 0); - sbuf_printf(&sb, "%ld.%02ld %ld.%02ld\n", - tv.tv_sec, tv.tv_usec / 10000, - T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); - - COMMON_END; -} - -int -linprocfs_doversion(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - - sbuf_new(&sb, NULL, 128, 0); - sbuf_printf(&sb, - "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" - " #4 Sun Dec 18 04:30:00 CET 1977\n", - linux_get_osname(curp), - linux_get_osrelease(curp)); - - COMMON_END; -} - -int -linprocfs_doloadavg(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - int lastpid, ilen; - - ilen = sizeof(lastpid); - if (kernel_sysctlbyname(p, "kern.lastpid", - &lastpid, &ilen, NULL, 0, NULL) != 0) - lastpid = -1; /* fake it */ - - sbuf_new(&sb, NULL, 128, 0); - sbuf_printf(&sb, - "%d.%02d %d.%02d %d.%02d %d/%d %d\n", - (int)(averunnable.ldavg[0] / averunnable.fscale), - (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), - (int)(averunnable.ldavg[1] / averunnable.fscale), - (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), - (int)(averunnable.ldavg[2] / averunnable.fscale), - (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), - 1, /* number of running tasks */ - nprocs, /* number of tasks */ - lastpid /* the last pid */ - ); - - COMMON_END; -} - -int -linprocfs_doprocstat(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - struct kinfo_proc kp; - - fill_kinfo_proc(p, &kp); - sbuf_new(&sb, NULL, 1024, 0); - sbuf_printf(&sb, "%d", p->p_pid); -#define PS_ADD(name, fmt, arg) sbuf_printf(&sb, " " fmt, arg) - PS_ADD("comm", "(%s)", p->p_comm); - PS_ADD("statr", "%c", '0'); /* XXX */ - PROC_LOCK(p); - PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); - PROC_UNLOCK(p); - PS_ADD("pgrp", "%d", p->p_pgid); - PS_ADD("session", "%d", p->p_session->s_sid); - PS_ADD("tty", "%d", 0); /* XXX */ - PS_ADD("tpgid", "%d", 0); /* XXX */ - PS_ADD("flags", "%u", 0); /* XXX */ - PS_ADD("minflt", "%u", 0); /* XXX */ - PS_ADD("cminflt", "%u", 0); /* XXX */ - PS_ADD("majflt", "%u", 0); /* XXX */ - PS_ADD("cminflt", "%u", 0); /* XXX */ - PS_ADD("utime", "%d", 0); /* XXX */ - PS_ADD("stime", "%d", 0); /* XXX */ - PS_ADD("cutime", "%d", 0); /* XXX */ - PS_ADD("cstime", "%d", 0); /* XXX */ - PS_ADD("counter", "%d", 0); /* XXX */ - PS_ADD("priority", "%d", 0); /* XXX */ - PS_ADD("timeout", "%u", 0); /* XXX */ - PS_ADD("itrealvalue", "%u", 0); /* XXX */ - PS_ADD("starttime", "%d", 0); /* XXX */ - PS_ADD("vsize", "%u", kp.ki_size); - PS_ADD("rss", "%u", P2K(kp.ki_rssize)); - PS_ADD("rlim", "%u", 0); /* XXX */ - PS_ADD("startcode", "%u", (unsigned)0); - PS_ADD("endcode", "%u", 0); /* XXX */ - PS_ADD("startstack", "%u", 0); /* XXX */ - PS_ADD("esp", "%u", 0); /* XXX */ - PS_ADD("eip", "%u", 0); /* XXX */ - PS_ADD("signal", "%d", 0); /* XXX */ - PS_ADD("blocked", "%d", 0); /* XXX */ - PS_ADD("sigignore", "%d", 0); /* XXX */ - PS_ADD("sigcatch", "%d", 0); /* XXX */ - PS_ADD("wchan", "%u", 0); /* XXX */ - PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ - PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ - PS_ADD("exitsignal", "%d", 0); /* XXX */ - PS_ADD("processor", "%d", 0); /* XXX */ -#undef PS_ADD - sbuf_putc(&sb, '\n'); - - COMMON_END; -} - -/* - * Map process state to descriptive letter. Note that this does not - * quite correspond to what Linux outputs, but it's close enough. - */ -static char *state_str[] = { - "? (unknown)", - "I (idle)", - "R (running)", - "S (sleeping)", - "T (stopped)", - "Z (zombie)", - "W (waiting)", - "M (mutex)" -}; - -int -linprocfs_doprocstatus(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - struct kinfo_proc kp; - char *state; - segsz_t lsize; - int i; - - sbuf_new(&sb, NULL, 1024, 0); - - mtx_lock_spin(&sched_lock); - if (p->p_stat > sizeof state_str / sizeof *state_str) - state = state_str[0]; - else - state = state_str[(int)p->p_stat]; - mtx_unlock_spin(&sched_lock); - - fill_kinfo_proc(p, &kp); - sbuf_printf(&sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ - sbuf_printf(&sb, "State:\t%s\n", state); - - /* - * Credentials - */ - sbuf_printf(&sb, "Pid:\t%d\n", p->p_pid); - PROC_LOCK(p); - sbuf_printf(&sb, "PPid:\t%d\n", p->p_pptr ? - p->p_pptr->p_pid : 0); - sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, - p->p_ucred->cr_uid, - p->p_ucred->cr_svuid, - /* FreeBSD doesn't have fsuid */ - p->p_ucred->cr_uid); - sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, - p->p_ucred->cr_gid, - p->p_ucred->cr_svgid, - /* FreeBSD doesn't have fsgid */ - p->p_ucred->cr_gid); - sbuf_cat(&sb, "Groups:\t"); - for (i = 0; i < p->p_ucred->cr_ngroups; i++) - sbuf_printf(&sb, "%d ", p->p_ucred->cr_groups[i]); - PROC_UNLOCK(p); - sbuf_putc(&sb, '\n'); - - /* - * Memory - * - * While our approximation of VmLib may not be accurate (I - * don't know of a simple way to verify it, and I'm not sure - * it has much meaning anyway), I believe it's good enough. - * - * The same code that could (I think) accurately compute VmLib - * could also compute VmLck, but I don't really care enough to - * implement it. Submissions are welcome. - */ - sbuf_printf(&sb, "VmSize:\t%8u kB\n", B2K(kp.ki_size)); - sbuf_printf(&sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ - sbuf_printf(&sb, "VmRss:\t%8u kB\n", P2K(kp.ki_rssize)); - sbuf_printf(&sb, "VmData:\t%8u kB\n", P2K(kp.ki_dsize)); - sbuf_printf(&sb, "VmStk:\t%8u kB\n", P2K(kp.ki_ssize)); - sbuf_printf(&sb, "VmExe:\t%8u kB\n", P2K(kp.ki_tsize)); - lsize = B2P(kp.ki_size) - kp.ki_dsize - - kp.ki_ssize - kp.ki_tsize - 1; - sbuf_printf(&sb, "VmLib:\t%8u kB\n", P2K(lsize)); - - /* - * Signal masks - * - * We support up to 128 signals, while Linux supports 32, - * but we only define 32 (the same 32 as Linux, to boot), so - * just show the lower 32 bits of each mask. XXX hack. - * - * NB: on certain platforms (Sparc at least) Linux actually - * supports 64 signals, but this code is a long way from - * running on anything but i386, so ignore that for now. - */ - PROC_LOCK(p); - sbuf_printf(&sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); - /* - * I can't seem to find out where the signal mask is in - * relation to struct proc, so SigBlk is left unimplemented. - */ - sbuf_printf(&sb, "SigBlk:\t%08x\n", 0); /* XXX */ - sbuf_printf(&sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]); - sbuf_printf(&sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]); - PROC_UNLOCK(p); - - /* - * Linux also prints the capability masks, but we don't have - * capabilities yet, and when we do get them they're likely to - * be meaningless to Linux programs, so we lie. XXX - */ - sbuf_printf(&sb, "CapInh:\t%016x\n", 0); - sbuf_printf(&sb, "CapPrm:\t%016x\n", 0); - sbuf_printf(&sb, "CapEff:\t%016x\n", 0); - - COMMON_END; -} - -int -linprocfs_doselflink(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - char buf[16]; /* should be enough */ - int len; - - /* XXX shouldn't this be uio->uio_procp->p_pid? */ - len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - - return (uiomove(buf, len, uio)); -} - -int -linprocfs_doexelink(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - int error = 0; - char *fullpath = "unknown"; - char *freepath = NULL; - - p = PFIND(pfs->pfs_pid); - if (p == NULL || p->p_ucred == NULL) { - if (p != NULL) - PROC_UNLOCK(p); - printf("doexelink: pid %d disappeared\n", pfs->pfs_pid); - } else { - PROC_UNLOCK(p); - /* fullpath/freepath are unchanged if textvp_fullpath fails */ - error = textvp_fullpath(p, &fullpath, &freepath); - } - error = uiomove(fullpath, strlen(fullpath), uio); - if (freepath) - free(freepath, M_TEMP); - return (error); -} - -int -linprocfs_donetdev(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - struct ifnet *ifp; - int eth_index = 0; - - sbuf_new(&sb, NULL, 1024, 0); - sbuf_printf(&sb, - "Inter-| Receive " - " | Transmit\n" - " face |bytes packets errs drop fifo frame compressed " - "multicast|bytes packets errs drop fifo colls carrier " - "compressed\n"); - - TAILQ_FOREACH(ifp, &ifnet, if_link) { - if (strcmp(ifp->if_name, "lo") == 0) { - sbuf_printf(&sb, "%6.6s:", ifp->if_name); - } else { - sbuf_printf(&sb, "%5.5s%d:", "eth", eth_index); - eth_index++; - } - sbuf_printf(&sb, - "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " - "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0); - } - - COMMON_END; -} - -int -linprocfs_dodevices(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - int i; - - sbuf_new(&sb, NULL, 1024, 0); - sbuf_printf(&sb, "Character devices:\n"); - - for (i = 0; i < NUMCDEVSW; i++) { - if (cdevsw[i] != NULL) - sbuf_printf(&sb, "%3d %s\n", i, cdevsw[i]->d_name); - } - - sbuf_printf(&sb, "\nBlock devices:\n"); - - COMMON_END; -} - -int -linprocfs_docmdline(curp, p, pfs, uio) - struct proc *curp; - struct proc *p; - struct pfsnode *pfs; - struct uio *uio; -{ - COMMON_START; - - sbuf_new(&sb, NULL, 128, 0); - sbuf_printf(&sb, "BOOT_IMAGE=%s", kernelname); - sbuf_printf(&sb, " ro root=302\n"); - - COMMON_END; -} diff --git a/sys/compat/linprocfs/linprocfs_subr.c b/sys/compat/linprocfs/linprocfs_subr.c deleted file mode 100644 index 09b449e..0000000 --- a/sys/compat/linprocfs/linprocfs_subr.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * Copyright (c) 1999 Pierre Beyssac - * 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_subr.c 8.6 (Berkeley) 5/14/95 - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/proc.h> -#include <sys/vnode.h> - -#include <compat/linprocfs/linprocfs.h> - -static struct pfsnode *pfshead; -static int pfsvplock; - -/* - * allocate a pfsnode/vnode pair. the vnode is - * referenced, but not locked. - * - * the pid, node_data, and mount point uniquely - * identify a pfsnode. the mount point is needed - * because someone might mount this filesystem - * twice. - * - * all pfsnodes are maintained on a singly-linked - * list. new nodes are only allocated when they cannot - * be found on this list. entries on the list are - * removed when the vfs reclaim entry is called. - * - * a single lock is kept for the entire list. this is - * needed because the getnewvnode() function can block - * waiting for a vnode to become free, in which case there - * may be more than one process trying to get the same - * vnode. this lock is only taken if we are going to - * call getnewvnode, since the kernel itself is single-threaded. - * - * if an entry is found on the list, then call vget() to - * take a reference. this is done because there may be - * zero references to it and so it needs to removed from - * the vnode free list. - */ -int -linprocfs_allocvp(mp, vpp, pid, nd) - struct mount *mp; - struct vnode **vpp; - long pid; - struct node_data *nd; -{ - struct proc *p = curproc; /* XXX */ - struct pfsnode *pfs; - struct vnode *vp; - struct pfsnode **pp; - int error; - - if ((nd->nd_flags & PDEP) == 0) - pid = 0; - -loop: - for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) { - vp = PFSTOV(pfs); - if (pfs->pfs_pid == pid && - pfs->pfs_nd == nd && - vp->v_mount == mp) { - if (vget(vp, 0, p)) - goto loop; - *vpp = vp; - return (0); - } - } - - /* - * otherwise lock the vp list while we call getnewvnode - * since that can block. - */ - if (pfsvplock & PROCFS_LOCKED) { - pfsvplock |= PROCFS_WANT; - (void) tsleep((caddr_t) &pfsvplock, PINOD, "pfsavp", 0); - goto loop; - } - pfsvplock |= PROCFS_LOCKED; - - /* - * Do the MALLOC before the getnewvnode since doing so afterward - * might cause a bogus v_data pointer to get dereferenced - * elsewhere if MALLOC should block. - */ - MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); - - error = getnewvnode(VT_PROCFS, mp, linprocfs_vnodeop_p, vpp); - if (error) { - FREE(pfs, M_TEMP); - goto out; - } - vp = *vpp; - - vp->v_data = pfs; - - pfs->pfs_next = 0; - pfs->pfs_pid = (pid_t) pid; - pfs->pfs_nd = nd; - pfs->pfs_vnode = vp; - pfs->pfs_flags = 0; - pfs->pfs_lockowner = 0; - pfs->pfs_fileno = PROCFS_FILENO(nd, pid); - - vp->v_type = nd->nd_type; - if (nd == root_dir) - vp->v_flag = VROOT; - - /* add to procfs vnode list */ - for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) - continue; - *pp = pfs; - -out: - pfsvplock &= ~PROCFS_LOCKED; - - if (pfsvplock & PROCFS_WANT) { - pfsvplock &= ~PROCFS_WANT; - wakeup((caddr_t) &pfsvplock); - } - - return (error); -} - -int -linprocfs_freevp(vp) - struct vnode *vp; -{ - struct pfsnode **pfspp; - struct pfsnode *pfs = VTOPFS(vp); - - for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) { - if (*pfspp == pfs) { - *pfspp = pfs->pfs_next; - break; - } - } - - FREE(vp->v_data, M_TEMP); - vp->v_data = 0; - return (0); -} - -int -linprocfs_rw(ap) - struct vop_read_args *ap; -{ - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - struct proc *curp = uio->uio_procp; - struct pfsnode *pfs = VTOPFS(vp); - struct node_data *nd = pfs->pfs_nd; - struct proc *p = NULL; - int error; - - if (nd->nd_type == VDIR) - return (EOPNOTSUPP); - - if (nd->nd_flags & PDEP) { - p = PFIND(pfs->pfs_pid); - if (p == NULL) - return (EINVAL); - PROC_UNLOCK(p); - } - - mp_fixme("pfs_lockowner needs a lock"); - while (pfs->pfs_lockowner) { - tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0); - } - - pfs->pfs_lockowner = curproc->p_pid; - error = nd->nd_action(curp, p, pfs, uio); - pfs->pfs_lockowner = 0; - - wakeup(&pfs->pfs_lockowner); - return (error); -} - -#if 0 -/* - * Get a string from userland into (buf). Strip a trailing - * nl character (to allow easy access from the shell). - * The buffer should be *buflenp + 1 chars long. vfs_getuserstr - * will automatically add a nul char at the end. - * - * Returns 0 on success or the following errors - * - * EINVAL: file offset is non-zero. - * EMSGSIZE: message is longer than kernel buffer - * EFAULT: user i/o buffer is not addressable - */ -int -vfs_getuserstr(uio, buf, buflenp) - struct uio *uio; - char *buf; - int *buflenp; -{ - int xlen; - int error; - - if (uio->uio_offset != 0) - return (EINVAL); - - xlen = *buflenp; - - /* must be able to read the whole string in one go */ - if (xlen < uio->uio_resid) - return (EMSGSIZE); - xlen = uio->uio_resid; - - if ((error = uiomove(buf, xlen, uio)) != 0) - return (error); - - /* allow multiple writes without seeks */ - uio->uio_offset = 0; - - /* cleanup string and remove trailing newline */ - buf[xlen] = '\0'; - xlen = strlen(buf); - if (xlen > 0 && buf[xlen-1] == '\n') - buf[--xlen] = '\0'; - *buflenp = xlen; - - return (0); -} - -vfs_namemap_t * -vfs_findname(nm, buf, buflen) - vfs_namemap_t *nm; - char *buf; - int buflen; -{ - - for (; nm->nm_name; nm++) - if (bcmp(buf, nm->nm_name, buflen+1) == 0) - return (nm); - - return (0); -} -#endif - -void -linprocfs_exit(struct proc *p) -{ - struct pfsnode *pfs; - pid_t pid = p->p_pid; - - /* - * The reason for this loop is not obvious -- basicly, - * linprocfs_freevp(), which is called via vgone() (eventually), - * removes the specified procfs node from the pfshead list. - * It does this by *pfsp = pfs->pfs_next, meaning that it - * overwrites the node. So when we do pfs = pfs->next, we - * end up skipping the node that replaces the one that was - * vgone'd. Since it may have been the last one on the list, - * it may also have been set to null -- but *our* pfs pointer, - * here, doesn't see this. So the loop starts from the beginning - * again. - * - * This is not a for() loop because the final event - * would be "pfs = pfs->pfs_next"; in the case where - * pfs is set to pfshead again, that would mean that - * pfshead is skipped over. - * - */ - pfs = pfshead; - while (pfs) { - if (pfs->pfs_pid == pid) { - vgone(PFSTOV(pfs)); - pfs = pfshead; - } else - pfs = pfs->pfs_next; - } -} diff --git a/sys/compat/linprocfs/linprocfs_vfsops.c b/sys/compat/linprocfs/linprocfs_vfsops.c deleted file mode 100644 index d635522..0000000 --- a/sys/compat/linprocfs/linprocfs_vfsops.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * Copyright (c) 1999 Pierre Beyssac - * 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_vfsops.c 8.7 (Berkeley) 5/10/95 - * - * $FreeBSD$ - */ - -/* - * procfs VFS interface - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/proc.h> -#include <sys/syslog.h> -#include <sys/mount.h> -#include <sys/vnode.h> -#include <compat/linprocfs/linprocfs.h> - -static int linprocfs_mount __P((struct mount *mp, char *path, caddr_t data, - struct nameidata *ndp, struct proc *p)); -static int linprocfs_statfs __P((struct mount *mp, struct statfs *sbp, - struct proc *p)); -static int linprocfs_unmount __P((struct mount *mp, int mntflags, - struct proc *p)); - -/* - * VFS Operations. - * - * mount system call - */ -/* ARGSUSED */ -static int -linprocfs_mount(mp, path, data, ndp, p) - struct mount *mp; - char *path; - caddr_t data; - struct nameidata *ndp; - struct proc *p; -{ - size_t size; - int error; - - if (mp->mnt_flag & MNT_UPDATE) - return (EOPNOTSUPP); - - if (mp->mnt_vfc->vfc_refcount == 1 && (error = at_exit(linprocfs_exit))) { - printf("linprocfs: cannot register linprocfs_exit with at_exit\n"); - return(error); - } - - mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = 0; - vfs_getnewfsid(mp); - - size = sizeof("linprocfs") - 1; - bcopy("linprocfs", mp->mnt_stat.f_mntfromname, size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void)linprocfs_statfs(mp, &mp->mnt_stat, p); - - return (0); -} - -/* - * unmount system call - */ -static int -linprocfs_unmount(mp, mntflags, p) - struct mount *mp; - int mntflags; - struct proc *p; -{ - int error; - int flags = 0; - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - error = vflush(mp, 0, flags); - if (error) - return (error); - - if (mp->mnt_vfc->vfc_refcount == 1) - rm_at_exit(linprocfs_exit); - - return (0); -} - -int -linprocfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - - return (linprocfs_allocvp(mp, vpp, 0, root_dir)); -} - -/* - * Get file system statistics. - */ -static int -linprocfs_statfs(mp, sbp, p) - struct mount *mp; - struct statfs *sbp; - struct proc *p; -{ - sbp->f_bsize = PAGE_SIZE; - sbp->f_iosize = PAGE_SIZE; - sbp->f_blocks = 1; /* avoid divide by zero in some df's */ - sbp->f_bfree = 0; - sbp->f_bavail = 0; - sbp->f_files = maxproc; /* approx */ - sbp->f_ffree = maxproc - nprocs; /* approx */ - - if (sbp != &mp->mnt_stat) { - sbp->f_type = mp->mnt_vfc->vfc_typenum; - 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); - } - - return (0); -} - -static struct vfsops linprocfs_vfsops = { - linprocfs_mount, - vfs_stdstart, - linprocfs_unmount, - linprocfs_root, - vfs_stdquotactl, - linprocfs_statfs, - vfs_stdsync, - vfs_stdvget, - vfs_stdfhtovp, - vfs_stdcheckexp, - vfs_stdvptofh, - vfs_stdinit, -}; - -VFS_SET(linprocfs_vfsops, linprocfs, VFCF_SYNTHETIC); -MODULE_DEPEND(linprocfs, linux, 1, 1, 1); -MODULE_DEPEND(linprocfs, procfs, 1, 1, 1); diff --git a/sys/compat/linprocfs/linprocfs_vnops.c b/sys/compat/linprocfs/linprocfs_vnops.c deleted file mode 100644 index 08a5023..0000000 --- a/sys/compat/linprocfs/linprocfs_vnops.c +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org> - * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav - * Copyright (c) 1999 Pierre Beyssac - * Copyright (c) 1993, 1995 Jan-Simon Pendry - * Copyright (c) 1993, 1995 - * 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.18 (Berkeley) 5/21/95 - * - * $FreeBSD$ - */ - -/* - * procfs vnode interface - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/dirent.h> -#include <sys/fcntl.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mount.h> -#include <sys/mutex.h> -#include <sys/namei.h> -#include <sys/pioctl.h> -#include <sys/proc.h> -#include <sys/signalvar.h> -#include <sys/sx.h> -#include <sys/time.h> -#include <sys/vnode.h> - -#include <machine/reg.h> - -#include <vm/vm_zone.h> - -#include <compat/linprocfs/linprocfs.h> - -extern struct vnode *procfs_findtextvp __P((struct proc *)); -extern int procfs_kmemaccess __P((struct proc *)); - -static int linprocfs_access __P((struct vop_access_args *)); -static int linprocfs_badop __P((void)); -static int linprocfs_close __P((struct vop_close_args *)); -static int linprocfs_getattr __P((struct vop_getattr_args *)); -static int linprocfs_inactive __P((struct vop_inactive_args *)); -static int linprocfs_ioctl __P((struct vop_ioctl_args *)); -static int linprocfs_lookup __P((struct vop_lookup_args *)); -static int linprocfs_open __P((struct vop_open_args *)); -static int linprocfs_print __P((struct vop_print_args *)); -static int linprocfs_readdir __P((struct vop_readdir_args *)); -static int linprocfs_readlink __P((struct vop_readlink_args *)); -static int linprocfs_reclaim __P((struct vop_reclaim_args *)); -static int linprocfs_setattr __P((struct vop_setattr_args *)); -static pid_t atopid __P((const char *, u_int)); - -#define N(s) s, sizeof(s)-1 -#define A(s) linprocfs_ ## s -#define D(s) (node_action_t *)(s) - -struct node_data net_dir[] = { - { N("."), VDIR, 0555, 0, D(net_dir) }, - { N(".."), VDIR, 0555, 0, D(root_dir) }, - { N("dev"), VREG, 0444, 0, A(donetdev) }, - { N(""), VNON, 0000, 0, NULL }, -}; - -struct node_data proc_dir[] = { - { N("."), VDIR, 0555, PDEP, D(proc_dir) }, - { N(".."), VDIR, 0555, 0, D(root_dir) }, - { N("cmdline"), VREG, 0444, PDEP, procfs_docmdline }, - { N("exe"), VLNK, 0444, PDEP, A(doexelink) }, - { N("mem"), VREG, 0600, PDEP, procfs_domem }, - { N("stat"), VREG, 0444, PDEP, A(doprocstat) }, - { N("status"), VREG, 0444, PDEP, A(doprocstatus) }, - { N(""), VNON, 0000, 0, NULL }, -}; - -struct node_data root_dir[] = { - { N("."), VDIR, 0555, 0, D(root_dir) }, - { N(".."), VDIR, 0555, 0, NULL }, - { N("cmdline"), VREG, 0444, 0, A(docmdline) }, - { N("cpuinfo"), VREG, 0444, 0, A(docpuinfo) }, - { N("devices"), VREG, 0444, 0, A(dodevices) }, - { N("meminfo"), VREG, 0444, 0, A(domeminfo) }, - { N("net"), VDIR, 0555, 0, D(net_dir) }, - { N("self"), VLNK, 0444, 0, A(doselflink) }, - { N("stat"), VREG, 0444, 0, A(dostat) }, - { N("uptime"), VREG, 0444, 0, A(douptime) }, - { N("version"), VREG, 0444, 0, A(doversion) }, - { N("loadavg"), VREG, 0444, 0, A(doloadavg) }, - { N(""), VNON, 0000, 0, NULL }, -}; - -#undef N -#undef A - -static int vn2ft[] = { - DT_UNKNOWN, /* VNON */ - DT_REG, /* VREG */ - DT_DIR, /* VDIR */ - DT_BLK, /* VBLK */ - DT_CHR, /* VCHR */ - DT_LNK, /* VLNK */ - DT_SOCK, /* VSOCK */ - DT_FIFO, /* VFIFO */ - DT_UNKNOWN, /* VBAD */ -}; - -/* - * 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. - */ -static int -linprocfs_open(ap) - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct node_data *nd = pfs->pfs_nd; - struct proc *p1, *p2 = NULL; - - if (nd->nd_flags & PDEP) { - p2 = PFIND(pfs->pfs_pid); - if (p2 == NULL) - return (ENOENT); - if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL)) { - PROC_UNLOCK(p2); - return (ENOENT); - } - PROC_UNLOCK(p2); - } - - if (nd->nd_action == procfs_domem) { - if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || - ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) - return (EBUSY); - - p1 = ap->a_p; - if (p_can(p1, p2, P_CAN_DEBUG, NULL) && !procfs_kmemaccess(p1)) - return (EPERM); - - if (ap->a_mode & FWRITE) - pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); - } - - 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). - */ -static int -linprocfs_close(ap) - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *p; - - if (pfs->pfs_nd->nd_action == procfs_domem) { - if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) - pfs->pfs_flags &= ~(FWRITE|O_EXCL); - /* - * If this is the last close, then it checks to see if - * the target process has PF_LINGER set in p_pfsflags, - * if this is *not* the case, then the process' stop flags - * are cleared, and the process is woken up. This is - * to help prevent the case where a process has been - * told to stop on an event, but then the requesting process - * has gone away or forgotten about it. - */ - if ((ap->a_vp->v_usecount < 2) && (p = PFIND(pfs->pfs_pid))) { - if (!(p->p_pfsflags & PF_LINGER)) { - p->p_stops = 0; - p->p_step = 0; - wakeup(&p->p_step); - } - PROC_UNLOCK(p); - } - } - - return (0); -} - -/* - * do an ioctl operation on a pfsnode (vp). - * (vp) is not locked on entry or exit. - */ -static int -linprocfs_ioctl(ap) - struct vop_ioctl_args *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *procp, *p; - int error; - int signo; - struct procfs_status *psp; - unsigned char flags; - - p = ap->a_p; - procp = PFIND(pfs->pfs_pid); - if (procp == NULL) - return ENOTTY; - - if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) { - PROC_UNLOCK(procp); - return (error == ESRCH ? ENOENT : error); - } - - switch (ap->a_command) { - case PIOCBIS: - procp->p_stops |= *(unsigned int*)ap->a_data; - break; - case PIOCBIC: - procp->p_stops &= ~*(unsigned int*)ap->a_data; - break; - case PIOCSFL: - /* - * NFLAGS is "non-suser_xxx flags" -- currently, only - * PFS_ISUGID ("ignore set u/g id"); - */ -#define NFLAGS (PF_ISUGID) - flags = (unsigned char)*(unsigned int*)ap->a_data; - if (flags & NFLAGS && (error = suser(p))) { - PROC_UNLOCK(procp); - return error; - } - procp->p_pfsflags = flags; - break; - case PIOCGFL: - *(unsigned int*)ap->a_data = (unsigned int)procp->p_pfsflags; - /* FALLTHROUGH */ - case PIOCSTATUS: - psp = (struct procfs_status *)ap->a_data; - psp->state = (procp->p_step == 0); - psp->flags = procp->p_pfsflags; - psp->events = procp->p_stops; - if (procp->p_step) { - psp->why = procp->p_stype; - psp->val = procp->p_xstat; - } else { - psp->why = psp->val = 0; /* Not defined values */ - } - break; - case PIOCWAIT: - psp = (struct procfs_status *)ap->a_data; - if (procp->p_step == 0) { - error = msleep(&procp->p_stype, &procp->p_mtx, PWAIT | PCATCH, - "piocwait", 0); - if (error) { - PROC_UNLOCK(procp); - return error; - } - } - psp->state = 1; /* It stopped */ - psp->flags = procp->p_pfsflags; - psp->events = procp->p_stops; - psp->why = procp->p_stype; /* why it stopped */ - psp->val = procp->p_xstat; /* any extra info */ - break; - case PIOCCONT: /* Restart a proc */ - if (procp->p_step == 0) { - PROC_UNLOCK(procp); - return EINVAL; /* Can only start a stopped process */ - } - if ((signo = *(int*)ap->a_data) != 0) { - if (signo >= NSIG || signo <= 0) { - PROC_UNLOCK(procp); - return EINVAL; - } - psignal(procp, signo); - } - procp->p_step = 0; - wakeup(&procp->p_step); - break; - default: - PROC_UNLOCK(procp); - return (ENOTTY); - } - PROC_UNLOCK(procp); - return 0; -} - -/* - * linprocfs_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. - * - * (vp) is locked on entry, but must be unlocked on exit. - */ -static int -linprocfs_inactive(ap) - struct vop_inactive_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct vnode *vp = ap->a_vp; - - VOP_UNLOCK(vp, 0, ap->a_p); - - 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. - */ -static int -linprocfs_reclaim(ap) - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap; -{ - - return (linprocfs_freevp(ap->a_vp)); -} - -/* - * _print is used for debugging. - * just print a readable description - * of (vp). - */ -static int -linprocfs_print(ap) - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct node_data *nd = pfs->pfs_nd; - - printf("tag VT_PROCFS, name %s, pid %ld, mode %x, flags %lx\n", - nd->nd_name, (long)pfs->pfs_pid, nd->nd_mode, pfs->pfs_flags); - return (0); -} - -/* - * generic entry point for unsupported operations - */ -static int -linprocfs_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. - */ -static int -linprocfs_getattr(ap) - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct node_data *nd = pfs->pfs_nd; - struct vattr *vap = ap->a_vap; - struct proc *procp; - - /* - * First make sure that the process and its credentials - * still exist. - */ - if (nd->nd_flags & PDEP) { - procp = PFIND(pfs->pfs_pid); - if (procp == NULL) - return (ENOENT); - if (procp->p_ucred == NULL) { - PROC_UNLOCK(procp); - return (ENOENT); - } - if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) { - PROC_UNLOCK(procp); - return (ENOENT); - } - PROC_UNLOCK(procp); - } else { - procp = NULL; - } - - /* 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 = nd->nd_mode; - vap->va_fileid = pfs->pfs_fileno; - vap->va_flags = 0; - vap->va_blocksize = PAGE_SIZE; - vap->va_bytes = vap->va_size = 0; - vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; - vap->va_nlink = 1; - - /* - * 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. - */ - nanotime(&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. - */ - if (procp) { - PROC_LOCK(procp); - vap->va_uid = procp->p_ucred->cr_uid; - vap->va_gid = procp->p_ucred->cr_gid; - PROC_UNLOCK(procp); - } else { - vap->va_uid = 0; - vap->va_gid = 0; - } - - /* - * If the process has exercised some setuid or setgid - * privilege, then change the owner to root. - */ - if (nd->nd_action == procfs_domem) { - PROC_LOCK(procp); - if (procp->p_flag & P_SUGID) - vap->va_uid = 0; - PROC_UNLOCK(procp); - } - - return (0); -} - -static int -linprocfs_setattr(ap) - struct vop_setattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - - if (ap->a_vap->va_flags != VNOVAL) - return (EOPNOTSUPP); - - /* - * just fake out attribute setting - * it's not good to generate an error - * return, otherwise things like creat() - * will fail when they try to set the - * file length to 0. worse, this means - * that echo $note > /proc/$pid/note will fail. - */ - - return (0); -} - -/* - * implement access checking. - * - * actually, the check for super-user is slightly - * broken since it will allow read access to write-only - * objects. this doesn't cause any particular trouble - * but does mean that the i/o entry points need to check - * that the operation really does make sense. - */ -static int -linprocfs_access(ap) - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct vnode *vp = ap->a_vp; - struct proc *procp; - struct vattr *vap; - struct vattr vattr; - int error; - - if (pfs->pfs_nd->nd_flags & PDEP) { - procp = PFIND(pfs->pfs_pid); - if (procp == NULL) - return (ENOENT); - if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) { - PROC_UNLOCK(procp); - return (ENOENT); - } - PROC_UNLOCK(procp); - } - - vap = &vattr; - error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); - if (error) - return (error); - - return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, - ap->a_mode, ap->a_cred, NULL)); -} - -/* - * lookup. this is incredibly complicated in the - * general case, however for most pseudo-filesystems - * very little needs to be done. - * - * unless you want to get a migraine, just make sure your - * filesystem doesn't do any locking of its own. otherwise - * read and inwardly digest ufs_lookup(). - */ -static int -linprocfs_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 proc *curp = cnp->cn_proc; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - char *pname = cnp->cn_nameptr; - struct node_data *nd; - pid_t pid; - struct pfsnode *pfs; - struct proc *p; - int error; - - *vpp = NULL; - - if (cnp->cn_nameiop != LOOKUP) - return (EROFS); - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */ - return (0); - } - - pfs = VTOPFS(dvp); - nd = pfs->pfs_nd; - if (nd->nd_type != VDIR) - return (ENOTDIR); - - if (cnp->cn_flags & ISDOTDOT) { - if (nd == root_dir) - return (EIO); - nd = (struct node_data *)nd[1].nd_action; - return (linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, nd)); - } - - /* generic lookup */ - for (nd = pfs->pfs_nd; nd->nd_type != VNON; nd++) { - if (cnp->cn_namelen != nd->nd_namlen || - memcmp(pname, nd->nd_name, nd->nd_namlen)) - continue; - if (nd->nd_type == VDIR) - nd = (struct node_data *)nd->nd_action; - return (linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, nd)); - } - - error = ENOENT; - - /* directory specific lookups */ - if (pfs->pfs_nd == root_dir) { - pid = atopid(pname, cnp->cn_namelen); - if (pid == NO_PID) - goto done; - - p = PFIND(pid); - if (p == NULL) - goto done; - - if (p_can(curp, p, P_CAN_SEE, NULL)) { - PROC_UNLOCK(p); - goto done; - } - PROC_UNLOCK(p); - - error = linprocfs_allocvp(dvp->v_mount, vpp, pid, proc_dir); - } -done: - return (error); -} - -/* - * Does this process have a text file? - */ -int -linprocfs_validfile(p) - struct proc *p; -{ - - return (procfs_findtextvp(p) != NULLVP); -} - -/* - * readdir() returns directory entries from pfsnode (vp). - * - * We generate just one directory entry at a time, as it would probably - * not pay off to buffer several entries locally to save uiomove calls. - */ -static int -linprocfs_readdir(ap) - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - int *a_ncookies; - u_long **a_cookies; - } */ *ap; -{ - struct uio *uio = ap->a_uio; - struct dirent d; - struct dirent *dp = &d; - struct pfsnode *pfs; - struct node_data *nd; - struct proc *p; - int i, start, copied, error, off; - static u_int delen; - - if (!delen) { - d.d_namlen = PROCFS_NAMELEN; - delen = GENERIC_DIRSIZ(&d); - } - - pfs = VTOPFS(ap->a_vp); - nd = pfs->pfs_nd; - - if (nd->nd_type != VDIR) - return (ENOTDIR); - - off = (int)uio->uio_offset; - if (off != uio->uio_offset || off < 0 || - off % delen != 0 || uio->uio_resid < delen) - return (EINVAL); - - error = 0; - copied = 0; - start = off / delen; - - if (nd->nd_flags & PDEP) { - p = PFIND(pfs->pfs_pid); - if (p == NULL) - goto done; - if (p_can(curproc, p, P_CAN_SEE, NULL)) { - PROC_UNLOCK(p); - goto done; - } - PROC_UNLOCK(p); - } - - /* - * copy out static entries - */ - for (i = 0; i < start && nd->nd_type != VNON; nd++, i++); - for (; uio->uio_resid >= delen && nd->nd_type != VNON; nd++, copied++) { - - dp->d_reclen = delen; - dp->d_fileno = PROCFS_FILENO(nd, pfs->pfs_pid); - dp->d_namlen = nd->nd_namlen; - memcpy(dp->d_name, nd->nd_name, nd->nd_namlen + 1); - dp->d_type = vn2ft[nd->nd_type]; - - error = uiomove((caddr_t)dp, delen, uio); - if (error) - goto done; - } - - /* - * this is for the root of the procfs filesystem - */ - if (pfs->pfs_nd == root_dir) { - sx_slock(&allproc_lock); - p = LIST_FIRST(&allproc); - i = nd - pfs->pfs_nd; - - while (p && i < start) { - if (p_can(curproc, p, P_CAN_SEE, NULL) == 0) - i++; - p = LIST_NEXT(p, p_list); - } - for (; p && uio->uio_resid >= delen; p = LIST_NEXT(p, p_list)) { - if (p_can(curproc, p, P_CAN_SEE, NULL)) - continue; - dp->d_reclen = delen; - dp->d_fileno = PROCFS_FILENO(proc_dir, p->p_pid); - dp->d_namlen = sprintf(dp->d_name, "%ld", - (long)p->p_pid); - dp->d_type = DT_DIR; - - error = uiomove((caddr_t)dp, delen, uio); - if (error) - break; - copied++; - } - sx_sunlock(&allproc_lock); - } -done: - return (error); -} - -/* - * readlink reads the link of `self' or `exe' - */ -static int -linprocfs_readlink(ap) - struct vop_readlink_args *ap; -{ - struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct node_data *nd = pfs->pfs_nd; - - /* sanity check */ - if (nd->nd_type != VLNK) - return (EINVAL); - - return (nd->nd_action(NULL, NULL, pfs, ap->a_uio)); -} - -/* - * convert decimal ascii to pid_t - */ -static pid_t -atopid(b, len) - const char *b; - u_int len; -{ - pid_t p = 0; - - while (len--) { - char c = *b++; - if (c < '0' || c > '9') - return (NO_PID); - p = 10 * p + (c - '0'); - if (p > PID_MAX) - return (NO_PID); - } - - return (p); -} - -/* - * procfs vnode operations. - */ -vop_t **linprocfs_vnodeop_p; -static struct vnodeopv_entry_desc linprocfs_vnodeop_entries[] = { - { &vop_default_desc, (vop_t *) vop_defaultop }, - { &vop_access_desc, (vop_t *) linprocfs_access }, - { &vop_advlock_desc, (vop_t *) linprocfs_badop }, - { &vop_close_desc, (vop_t *) linprocfs_close }, - { &vop_create_desc, (vop_t *) linprocfs_badop }, - { &vop_getattr_desc, (vop_t *) linprocfs_getattr }, - { &vop_inactive_desc, (vop_t *) linprocfs_inactive }, - { &vop_link_desc, (vop_t *) linprocfs_badop }, - { &vop_lookup_desc, (vop_t *) linprocfs_lookup }, - { &vop_mkdir_desc, (vop_t *) linprocfs_badop }, - { &vop_mknod_desc, (vop_t *) linprocfs_badop }, - { &vop_open_desc, (vop_t *) linprocfs_open }, - { &vop_pathconf_desc, (vop_t *) vop_stdpathconf }, - { &vop_print_desc, (vop_t *) linprocfs_print }, - { &vop_read_desc, (vop_t *) linprocfs_rw }, - { &vop_readdir_desc, (vop_t *) linprocfs_readdir }, - { &vop_readlink_desc, (vop_t *) linprocfs_readlink }, - { &vop_reclaim_desc, (vop_t *) linprocfs_reclaim }, - { &vop_remove_desc, (vop_t *) linprocfs_badop }, - { &vop_rename_desc, (vop_t *) linprocfs_badop }, - { &vop_rmdir_desc, (vop_t *) linprocfs_badop }, - { &vop_setattr_desc, (vop_t *) linprocfs_setattr }, - { &vop_symlink_desc, (vop_t *) linprocfs_badop }, - { &vop_write_desc, (vop_t *) linprocfs_rw }, - { &vop_ioctl_desc, (vop_t *) linprocfs_ioctl }, - { NULL, NULL } -}; -static struct vnodeopv_desc linprocfs_vnodeop_opv_desc = - { &linprocfs_vnodeop_p, linprocfs_vnodeop_entries }; - -VNODEOP_SET(linprocfs_vnodeop_opv_desc); |