diff options
-rw-r--r-- | sys/compat/linprocfs/linprocfs.c | 228 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs.h | 102 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_misc.c | 228 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_subr.c | 135 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_vfsops.c | 2 | ||||
-rw-r--r-- | sys/compat/linprocfs/linprocfs_vnops.c | 556 |
6 files changed, 564 insertions, 687 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 26b1aca..6f22200 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -42,9 +42,11 @@ */ #include <sys/param.h> +#include <sys/conf.h> #include <sys/blist.h> #include <sys/dkstat.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/sbuf.h> @@ -69,9 +71,14 @@ #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 */ @@ -81,6 +88,20 @@ #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) @@ -89,9 +110,7 @@ linprocfs_domeminfo(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; unsigned long memtotal; /* total memory in bytes */ unsigned long memused; /* used memory in bytes */ unsigned long memfree; /* free memory in bytes */ @@ -160,13 +179,7 @@ linprocfs_domeminfo(curp, p, pfs, uio) B2K(memshared), B2K(buffers), B2K(cached), B2K(swaptotal), B2K(swapfree)); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -176,9 +189,7 @@ linprocfs_docpuinfo(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; int class, i, fqmhz, fqkhz; /* @@ -250,13 +261,7 @@ linprocfs_docpuinfo(curp, p, pfs, uio) fqmhz, fqkhz, fqmhz, fqkhz); } - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -266,9 +271,7 @@ linprocfs_dostat(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; sbuf_new(&sb, NULL, 512, 0); sbuf_printf(&sb, @@ -291,13 +294,7 @@ linprocfs_dostat(curp, p, pfs, uio) cnt.v_swtch, boottime.tv_sec); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -307,9 +304,7 @@ linprocfs_douptime(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; struct timeval tv; getmicrouptime(&tv); @@ -317,13 +312,8 @@ linprocfs_douptime(curp, p, pfs, uio) 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); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + + COMMON_END; } int @@ -333,9 +323,7 @@ linprocfs_doversion(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; sbuf_new(&sb, NULL, 128, 0); sbuf_printf(&sb, @@ -343,13 +331,8 @@ linprocfs_doversion(curp, p, pfs, uio) " #4 Sun Dec 18 04:30:00 CET 1977\n", linux_get_osname(curp), linux_get_osrelease(curp)); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + + COMMON_END; } int @@ -359,10 +342,8 @@ linprocfs_doprocstat(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { + COMMON_START; struct kinfo_proc kp; - struct sbuf sb; - char *ps; - int r, xlen; fill_kinfo_proc(p, &kp); sbuf_new(&sb, NULL, 1024, 0); @@ -411,13 +392,7 @@ linprocfs_doprocstat(curp, p, pfs, uio) #undef PS_ADD sbuf_putc(&sb, '\n'); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } /* @@ -442,12 +417,11 @@ linprocfs_doprocstatus(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { + COMMON_START; struct kinfo_proc kp; - struct sbuf sb; - char *ps; char *state; - int i, r, xlen; segsz_t lsize; + int i; sbuf_new(&sb, NULL, 1024, 0); @@ -537,11 +511,125 @@ linprocfs_doprocstatus(curp, p, pfs, uio) sbuf_printf(&sb, "CapPrm:\t%016x\n", 0); sbuf_printf(&sb, "CapEff:\t%016x\n", 0); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + 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) + PROC_LOCK(p); + if (p == NULL || p->p_cred == 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.h b/sys/compat/linprocfs/linprocfs.h index fb085fe..5cea78a 100644 --- a/sys/compat/linprocfs/linprocfs.h +++ b/sys/compat/linprocfs/linprocfs.h @@ -1,4 +1,5 @@ /* + * 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 @@ -41,37 +42,36 @@ * $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; +}; + /* - * The different types of node in a procfs filesystem + * flag bits for nd_flags. */ -typedef enum { - Proot, /* the filesystem root */ - Pself, /* symbolic link for curproc */ - Pproc, /* a process-specific sub-directory */ - Pexe, /* the executable file */ - Pmem, /* the process's memory image */ - Pcmdline, /* command line */ - Pprocstat, /* the process's status */ - Pprocstatus, /* the process's status (again) */ - Pmeminfo, /* memory system statistics */ - Pcpuinfo, /* CPU model, speed and features */ - Pstat, /* kernel/system statistics */ - Puptime, /* system uptime */ - Pversion, /* system version */ -} pfstype; +#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 */ - pfstype pfs_type; /* type of procfs node */ - pid_t pfs_pid; /* associated process */ - u_short pfs_mode; /* mode bits for stat() */ - u_long pfs_flags; /* open flags */ - u_long pfs_fileno; /* unique file id */ - pid_t pfs_lockowner; /* pfs lock owner */ + 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 */ @@ -80,16 +80,12 @@ struct pfsnode { * Kernel stuff follows */ #ifdef _KERNEL -#define CNEQ(cnp, s, len) \ - ((cnp)->cn_namelen == (len) && \ - (bcmp((s), (cnp)->cn_nameptr, (len)) == 0)) - #define KMEM_GROUP 2 -#define PROCFS_FILENO(pid, type) \ - (((type) < Pproc) ? \ - ((type) + 2) : \ - ((((pid)+1) << 4) + ((int) (type)))) +#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 @@ -113,26 +109,28 @@ struct dbreg; #define PFIND(pid) ((pid) ? pfind(pid) : &proc0) -void linprocfs_exit __P((struct proc *)); -int linprocfs_freevp __P((struct vnode *)); -int linprocfs_allocvp __P((struct mount *, struct vnode **, long, pfstype)); -int linprocfs_sstep __P((struct proc *)); -void linprocfs_fix_sstep __P((struct proc *)); -#if 0 -int linprocfs_read_regs __P((struct proc *, struct reg *)); -int linprocfs_write_regs __P((struct proc *, struct reg *)); -int linprocfs_read_fpregs __P((struct proc *, struct fpreg *)); -int linprocfs_write_fpregs __P((struct proc *, struct fpreg *)); -int linprocfs_read_dbregs __P((struct proc *, struct dbreg *)); -int linprocfs_write_dbregs __P((struct proc *, struct dbreg *)); -#endif -int linprocfs_domeminfo __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_docpuinfo __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_dostat __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_douptime __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_doversion __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_doprocstat __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -int linprocfs_doprocstatus __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); +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; + +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 *)); diff --git a/sys/compat/linprocfs/linprocfs_misc.c b/sys/compat/linprocfs/linprocfs_misc.c index 26b1aca..6f22200 100644 --- a/sys/compat/linprocfs/linprocfs_misc.c +++ b/sys/compat/linprocfs/linprocfs_misc.c @@ -42,9 +42,11 @@ */ #include <sys/param.h> +#include <sys/conf.h> #include <sys/blist.h> #include <sys/dkstat.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/sbuf.h> @@ -69,9 +71,14 @@ #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 */ @@ -81,6 +88,20 @@ #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) @@ -89,9 +110,7 @@ linprocfs_domeminfo(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; unsigned long memtotal; /* total memory in bytes */ unsigned long memused; /* used memory in bytes */ unsigned long memfree; /* free memory in bytes */ @@ -160,13 +179,7 @@ linprocfs_domeminfo(curp, p, pfs, uio) B2K(memshared), B2K(buffers), B2K(cached), B2K(swaptotal), B2K(swapfree)); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -176,9 +189,7 @@ linprocfs_docpuinfo(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; int class, i, fqmhz, fqkhz; /* @@ -250,13 +261,7 @@ linprocfs_docpuinfo(curp, p, pfs, uio) fqmhz, fqkhz, fqmhz, fqkhz); } - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -266,9 +271,7 @@ linprocfs_dostat(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; sbuf_new(&sb, NULL, 512, 0); sbuf_printf(&sb, @@ -291,13 +294,7 @@ linprocfs_dostat(curp, p, pfs, uio) cnt.v_swtch, boottime.tv_sec); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } int @@ -307,9 +304,7 @@ linprocfs_douptime(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; struct timeval tv; getmicrouptime(&tv); @@ -317,13 +312,8 @@ linprocfs_douptime(curp, p, pfs, uio) 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); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + + COMMON_END; } int @@ -333,9 +323,7 @@ linprocfs_doversion(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - struct sbuf sb; - char *ps; - int r, xlen; + COMMON_START; sbuf_new(&sb, NULL, 128, 0); sbuf_printf(&sb, @@ -343,13 +331,8 @@ linprocfs_doversion(curp, p, pfs, uio) " #4 Sun Dec 18 04:30:00 CET 1977\n", linux_get_osname(curp), linux_get_osrelease(curp)); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + + COMMON_END; } int @@ -359,10 +342,8 @@ linprocfs_doprocstat(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { + COMMON_START; struct kinfo_proc kp; - struct sbuf sb; - char *ps; - int r, xlen; fill_kinfo_proc(p, &kp); sbuf_new(&sb, NULL, 1024, 0); @@ -411,13 +392,7 @@ linprocfs_doprocstat(curp, p, pfs, uio) #undef PS_ADD sbuf_putc(&sb, '\n'); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + COMMON_END; } /* @@ -442,12 +417,11 @@ linprocfs_doprocstatus(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { + COMMON_START; struct kinfo_proc kp; - struct sbuf sb; - char *ps; char *state; - int i, r, xlen; segsz_t lsize; + int i; sbuf_new(&sb, NULL, 1024, 0); @@ -537,11 +511,125 @@ linprocfs_doprocstatus(curp, p, pfs, uio) sbuf_printf(&sb, "CapPrm:\t%016x\n", 0); sbuf_printf(&sb, "CapEff:\t%016x\n", 0); - sbuf_finish(&sb); - ps = sbuf_data(&sb) + uio->uio_offset; - xlen = sbuf_len(&sb) - uio->uio_offset; - xlen = imin(xlen, uio->uio_resid); - r = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); - sbuf_delete(&sb); - return r; + 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) + PROC_LOCK(p); + if (p == NULL || p->p_cred == 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 index b008443..809db3c 100644 --- a/sys/compat/linprocfs/linprocfs_subr.c +++ b/sys/compat/linprocfs/linprocfs_subr.c @@ -51,14 +51,11 @@ static struct pfsnode *pfshead; static int pfsvplock; -extern int procfs_domem __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); -extern int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *pfsp, struct uio *uio)); - /* * allocate a pfsnode/vnode pair. the vnode is * referenced, but not locked. * - * the pid, pfs_type, and mount point uniquely + * the pid, node_data, and mount point uniquely * identify a pfsnode. the mount point is needed * because someone might mount this filesystem * twice. @@ -81,11 +78,11 @@ extern int procfs_docmdline __P((struct proc *, struct proc *, struct pfsnode *p * the vnode free list. */ int -linprocfs_allocvp(mp, vpp, pid, pfs_type) +linprocfs_allocvp(mp, vpp, pid, nd) struct mount *mp; struct vnode **vpp; long pid; - pfstype pfs_type; + struct node_data *nd; { struct proc *p = curproc; /* XXX */ struct pfsnode *pfs; @@ -93,11 +90,14 @@ linprocfs_allocvp(mp, vpp, pid, pfs_type) 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_type == pfs_type && + pfs->pfs_nd == nd && vp->v_mount == mp) { if (vget(vp, 0, p)) goto loop; @@ -124,7 +124,8 @@ loop: */ MALLOC(pfs, struct pfsnode *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); - if ((error = getnewvnode(VT_PROCFS, mp, linprocfs_vnodeop_p, vpp)) != 0) { + error = getnewvnode(VT_PROCFS, mp, linprocfs_vnodeop_p, vpp); + if (error) { FREE(pfs, M_TEMP); goto out; } @@ -134,67 +135,15 @@ loop: pfs->pfs_next = 0; pfs->pfs_pid = (pid_t) pid; - pfs->pfs_type = pfs_type; + pfs->pfs_nd = nd; pfs->pfs_vnode = vp; pfs->pfs_flags = 0; pfs->pfs_lockowner = 0; - pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type); - - switch (pfs_type) { - case Proot: /* /proc = dr-xr-xr-x */ - pfs->pfs_mode = (VREAD|VEXEC) | - (VREAD|VEXEC) >> 3 | - (VREAD|VEXEC) >> 6; - vp->v_type = VDIR; + pfs->pfs_fileno = PROCFS_FILENO(nd, pid); + + vp->v_type = nd->nd_type; + if (nd == root_dir) vp->v_flag = VROOT; - break; - - case Pself: /* /proc/self = lr--r--r-- */ - pfs->pfs_mode = (VREAD) | - (VREAD >> 3) | - (VREAD >> 6); - vp->v_type = VLNK; - break; - - case Pproc: - pfs->pfs_mode = (VREAD|VEXEC) | - (VREAD|VEXEC) >> 3 | - (VREAD|VEXEC) >> 6; - vp->v_type = VDIR; - break; - - case Pexe: - pfs->pfs_mode = (VREAD|VEXEC) | - (VREAD|VEXEC) >> 3 | - (VREAD|VEXEC) >> 6; - vp->v_type = VLNK; - break; - - case Pmem: - pfs->pfs_mode = (VREAD|VWRITE) | - (VREAD) >> 3;; - vp->v_type = VREG; - break; - - case Pprocstat: - case Pprocstatus: - case Pcmdline: - /* fallthrough */ - - case Pmeminfo: - case Pcpuinfo: - case Pstat: - case Puptime: - case Pversion: - pfs->pfs_mode = (VREAD) | - (VREAD >> 3) | - (VREAD >> 6); - vp->v_type = VREG; - break; - - default: - panic("linprocfs_allocvp"); - } /* add to procfs vnode list */ for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) @@ -239,55 +188,29 @@ linprocfs_rw(ap) struct uio *uio = ap->a_uio; struct proc *curp = uio->uio_procp; struct pfsnode *pfs = VTOPFS(vp); - struct proc *p; - int rtval; + struct node_data *nd = pfs->pfs_nd; + struct proc *p = NULL; + int error; - p = PFIND(pfs->pfs_pid); - if (p == 0) - return (EINVAL); - if (p->p_pid == 1 && securelevel > 0 && uio->uio_rw == UIO_WRITE) - return (EACCES); + if (nd->nd_type == VDIR) + return (EOPNOTSUPP); + + if (nd->nd_flags & PDEP) { + p = PFIND(pfs->pfs_pid); + if (p == NULL) + return (EINVAL); + } while (pfs->pfs_lockowner) { tsleep(&pfs->pfs_lockowner, PRIBIO, "pfslck", 0); } - pfs->pfs_lockowner = curproc->p_pid; - switch (pfs->pfs_type) { - case Pcmdline: - rtval = procfs_docmdline(curp, p, pfs, uio); - break; - case Pmem: - rtval = procfs_domem(curp, p, pfs, uio); - break; - case Pprocstat: - rtval = linprocfs_doprocstat(curp, p, pfs, uio); - break; - case Pprocstatus: - rtval = linprocfs_doprocstatus(curp, p, pfs, uio); - break; - case Pmeminfo: - rtval = linprocfs_domeminfo(curp, p, pfs, uio); - break; - case Pcpuinfo: - rtval = linprocfs_docpuinfo(curp, p, pfs, uio); - break; - case Pstat: - rtval = linprocfs_dostat(curp, p, pfs, uio); - break; - case Puptime: - rtval = linprocfs_douptime(curp, p, pfs, uio); - break; - case Pversion: - rtval = linprocfs_doversion(curp, p, pfs, uio); - break; - default: - rtval = EOPNOTSUPP; - break; - } + pfs->pfs_lockowner = curproc->p_pid; + error = nd->nd_action(curp, p, pfs, uio); pfs->pfs_lockowner = 0; + wakeup(&pfs->pfs_lockowner); - return rtval; + return (error); } #if 0 diff --git a/sys/compat/linprocfs/linprocfs_vfsops.c b/sys/compat/linprocfs/linprocfs_vfsops.c index 1e4bc87..d635522 100644 --- a/sys/compat/linprocfs/linprocfs_vfsops.c +++ b/sys/compat/linprocfs/linprocfs_vfsops.c @@ -129,7 +129,7 @@ linprocfs_root(mp, vpp) struct vnode **vpp; { - return (linprocfs_allocvp(mp, vpp, 0, Proot)); + return (linprocfs_allocvp(mp, vpp, 0, root_dir)); } /* diff --git a/sys/compat/linprocfs/linprocfs_vnops.c b/sys/compat/linprocfs/linprocfs_vnops.c index 722544a..506a6f6 100644 --- a/sys/compat/linprocfs/linprocfs_vnops.c +++ b/sys/compat/linprocfs/linprocfs_vnops.c @@ -1,4 +1,5 @@ /* + * 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 @@ -80,33 +81,59 @@ 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)); -/* - * This is a list of the valid names in the - * process-specific sub-directories. It is - * used in linprocfs_lookup and linprocfs_readdir - */ -static struct proc_target { - u_char pt_type; - u_char pt_namlen; - char *pt_name; - pfstype pt_pfstype; - int (*pt_valid) __P((struct proc *p)); -} proc_targets[] = { -#define N(s) sizeof(s)-1, s - /* name type validp */ - { DT_DIR, N("."), Pproc, NULL }, - { DT_DIR, N(".."), Proot, NULL }, - { DT_REG, N("cmdline"), Pcmdline, NULL }, - { DT_LNK, N("exe"), Pexe, NULL }, - { DT_REG, N("mem"), Pmem, NULL }, - { DT_REG, N("stat"), Pprocstat, NULL }, - { DT_REG, N("status"), Pprocstatus, NULL }, -#undef N +#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 }, }; -static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); -static pid_t atopid __P((const char *, u_int)); +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(""), 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 @@ -129,32 +156,28 @@ linprocfs_open(ap) } */ *ap; { struct pfsnode *pfs = VTOPFS(ap->a_vp); - struct proc *p1, *p2; + struct node_data *nd = pfs->pfs_nd; + struct proc *p1, *p2 = NULL; - p2 = PFIND(pfs->pfs_pid); - if (p2 == NULL) - return (ENOENT); - if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL)) - return (ENOENT); + 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)) + return (ENOENT); + } - switch (pfs->pfs_type) { - case Pmem: + 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)) + 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); - - default: - break; } return (0); @@ -179,8 +202,7 @@ linprocfs_close(ap) struct pfsnode *pfs = VTOPFS(ap->a_vp); struct proc *p; - switch (pfs->pfs_type) { - case Pmem: + if (pfs->pfs_nd->nd_action == procfs_domem) { if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) pfs->pfs_flags &= ~(FWRITE|O_EXCL); /* @@ -192,7 +214,7 @@ linprocfs_close(ap) * 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 ((ap->a_vp->v_usecount < 2) && (p = PFIND(pfs->pfs_pid))) { PROC_LOCK(p); if (!(p->p_pfsflags & PF_LINGER)) { p->p_stops = 0; @@ -202,9 +224,6 @@ linprocfs_close(ap) } else PROC_UNLOCK(p); } - break; - default: - break; } return (0); @@ -226,7 +245,7 @@ linprocfs_ioctl(ap) unsigned char flags; p = ap->a_p; - procp = pfind(pfs->pfs_pid); + procp = PFIND(pfs->pfs_pid); if (procp == NULL) return ENOTTY; @@ -398,9 +417,10 @@ linprocfs_print(ap) } */ *ap; { struct pfsnode *pfs = VTOPFS(ap->a_vp); + struct node_data *nd = pfs->pfs_nd; - printf("tag VT_PROCFS, type %d, pid %ld, mode %x, flags %lx\n", - pfs->pfs_type, (long)pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); + 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); } @@ -433,21 +453,15 @@ linprocfs_getattr(ap) } */ *ap; { struct pfsnode *pfs = VTOPFS(ap->a_vp); + struct node_data *nd = pfs->pfs_nd; struct vattr *vap = ap->a_vap; struct proc *procp; - int error; /* * First make sure that the process and its credentials * still exist. */ - switch (pfs->pfs_type) { - case Proot: - case Pself: - procp = NULL; - break; - - default: + if (nd->nd_flags & PDEP) { procp = PFIND(pfs->pfs_pid); if (procp == NULL) return (ENOENT); @@ -459,21 +473,22 @@ linprocfs_getattr(ap) PROC_UNLOCK(procp); if (p_can(ap->a_p, procp, P_CAN_SEE, NULL)) return (ENOENT); + } else { + procp = NULL; } - 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_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. @@ -487,23 +502,6 @@ linprocfs_getattr(ap) vap->va_atime = vap->va_mtime = vap->va_ctime; /* - * 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 Pmem: - /* Retain group kmem readablity. */ - PROC_LOCK(procp); - if (procp->p_flag & P_SUGID) - vap->va_mode &= ~(VREAD|VWRITE); - PROC_UNLOCK(procp); - break; - default: - break; - } - - /* * now do the object specific fields * * The size could be set from struct reg, but it's hardly @@ -512,91 +510,28 @@ linprocfs_getattr(ap) * becomes important then this function should break out into * a per-file stat function in the corresponding .c file. */ - - vap->va_nlink = 1; if (procp) { PROC_LOCK(procp); vap->va_uid = procp->p_ucred->cr_uid; vap->va_gid = procp->p_ucred->cr_gid; PROC_UNLOCK(procp); - } - - switch (pfs->pfs_type) { - case Proot: - /* - * Set nlink to 1 to tell fts(3) we don't actually know. - */ - vap->va_nlink = 1; - vap->va_uid = 0; - vap->va_gid = 0; - vap->va_size = vap->va_bytes = DEV_BSIZE; - break; - - case Pself: { - char buf[16]; /* should be enough */ + } else { vap->va_uid = 0; vap->va_gid = 0; - vap->va_size = vap->va_bytes = - snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); - break; } - case Pproc: - vap->va_nlink = nproc_targets; - vap->va_size = vap->va_bytes = DEV_BSIZE; - break; - - case Pexe: { - char *fullpath, *freepath; - error = textvp_fullpath(procp, &fullpath, &freepath); - if (error == 0) { - vap->va_size = strlen(fullpath); - free(freepath, M_TEMP); - } else { - vap->va_size = sizeof("unknown") - 1; - error = 0; - } - vap->va_bytes = vap->va_size; - break; - } - - case Pmeminfo: - case Pcpuinfo: - case Pstat: - case Puptime: - case Pversion: - vap->va_bytes = vap->va_size = 0; - vap->va_uid = 0; - vap->va_gid = 0; - break; - - case Pmem: - /* - * If we denied owner access earlier, then we have to - * change the owner to root - otherwise 'ps' and friends - * will break even though they are setgid kmem. *SIGH* - */ + /* + * 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; - else - vap->va_uid = procp->p_ucred->cr_uid; PROC_UNLOCK(procp); - vap->va_gid = KMEM_GROUP; - break; - - case Pcmdline: - case Pprocstat: - case Pprocstatus: - vap->va_bytes = vap->va_size = 0; - /* uid, gid are already set */ - break; - - default: - panic("linprocfs_getattr"); } - return (error); + return (0); } static int @@ -649,16 +584,7 @@ linprocfs_access(ap) struct vattr vattr; int error; - switch (pfs->pfs_type) { - case Proot: - case Pself: - case Pmeminfo: - case Pcpuinfo: - case Pstat: - case Puptime: - case Pversion: - break; - default: + if (pfs->pfs_nd->nd_flags & PDEP) { procp = PFIND(pfs->pfs_pid); if (procp == NULL) return (ENOENT); @@ -697,16 +623,15 @@ linprocfs_lookup(ap) struct vnode **vpp = ap->a_vpp; struct vnode *dvp = ap->a_dvp; char *pname = cnp->cn_nameptr; - struct proc_target *pt; + struct node_data *nd; pid_t pid; struct pfsnode *pfs; struct proc *p; - int i; + int error; *vpp = NULL; - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME || - cnp->cn_nameiop == CREATE) + if (cnp->cn_nameiop != LOOKUP) return (EROFS); if (cnp->cn_namelen == 1 && *pname == '.') { @@ -717,62 +642,46 @@ linprocfs_lookup(ap) } pfs = VTOPFS(dvp); - switch (pfs->pfs_type) { - case Proot: - if (cnp->cn_flags & ISDOTDOT) + 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)); + } - if (CNEQ(cnp, "self", 4)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pself)); - if (CNEQ(cnp, "meminfo", 7)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pmeminfo)); - if (CNEQ(cnp, "cpuinfo", 7)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pcpuinfo)); - if (CNEQ(cnp, "stat", 4)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pstat)); - if (CNEQ(cnp, "uptime", 6)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Puptime)); - if (CNEQ(cnp, "version", 7)) - return (linprocfs_allocvp(dvp->v_mount, vpp, 0, Pversion)); + error = ENOENT; + /* directory specific lookups */ + if (pfs->pfs_nd == root_dir) { pid = atopid(pname, cnp->cn_namelen); if (pid == NO_PID) - break; + goto done; p = PFIND(pid); if (p == NULL) - break; + goto done; if (p_can(curp, p, P_CAN_SEE, NULL)) - break; - - return (linprocfs_allocvp(dvp->v_mount, vpp, pid, Pproc)); - - case Pproc: - if (cnp->cn_flags & ISDOTDOT) - return (linprocfs_root(dvp->v_mount, vpp)); - - p = PFIND(pfs->pfs_pid); - if (p == NULL) - break; - - for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { - if (cnp->cn_namelen == pt->pt_namlen && - bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && - (pt->pt_valid == NULL || (*pt->pt_valid)(p))) - goto found; - } - break; + goto done; - found: - return (linprocfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, - pt->pt_pfstype)); - - default: - return (ENOTDIR); + error = linprocfs_allocvp(dvp->v_mount, vpp, pid, proc_dir); } - - return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); +done: + return (error); } /* @@ -807,16 +716,21 @@ linprocfs_readdir(ap) struct dirent d; struct dirent *dp = &d; struct pfsnode *pfs; - int count, error, i, off; + 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 || @@ -824,164 +738,65 @@ linprocfs_readdir(ap) return (EINVAL); error = 0; - count = 0; - i = off / delen; - - switch (pfs->pfs_type) { - /* - * this is for the process-specific sub-directories. - * all that is needed to is copy out all the entries - * from the procent[] table (top of this file). - */ - case Pproc: { - struct proc *p; - struct proc_target *pt; + copied = 0; + start = off / delen; + if (nd->nd_flags & PDEP) { p = PFIND(pfs->pfs_pid); if (p == NULL) - break; + goto done; if (p_can(curproc, p, P_CAN_SEE, NULL)) - break; - - for (pt = &proc_targets[i]; - uio->uio_resid >= delen && i < nproc_targets; pt++, i++) { - if (pt->pt_valid && (*pt->pt_valid)(p) == 0) - continue; - - dp->d_reclen = delen; - dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype); - dp->d_namlen = pt->pt_namlen; - bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1); - dp->d_type = pt->pt_type; - - if ((error = uiomove((caddr_t)dp, delen, uio)) != 0) - break; - } + goto done; + } - break; - } + /* + * 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 - * what is needed is a special entry for "self" - * followed by an entry for each process on allproc -#ifdef PROCFS_ZOMBIE - * and zombproc. -#endif */ - - case Proot: { -#ifdef PROCFS_ZOMBIE - int doingzomb = 0; -#endif - int pcnt = 0; - struct proc *p; - + if (pfs->pfs_nd == root_dir) { ALLPROC_LOCK(AP_SHARED); p = LIST_FIRST(&allproc); - for (; p && uio->uio_resid >= delen; i++, pcnt++) { - bzero((char *) dp, delen); - dp->d_reclen = delen; - - switch (i) { - case 0: /* `.' */ - case 1: /* `..' */ - dp->d_fileno = PROCFS_FILENO(0, Proot); - dp->d_namlen = i + 1; - bcopy("..", dp->d_name, dp->d_namlen); - dp->d_name[i + 1] = '\0'; - dp->d_type = DT_DIR; - break; - - case 2: - dp->d_fileno = PROCFS_FILENO(0, Pself); - dp->d_namlen = 4; - bcopy("self", dp->d_name, 5); - dp->d_type = DT_LNK; - break; - - case 3: - dp->d_fileno = PROCFS_FILENO(0, Pmeminfo); - dp->d_namlen = 7; - bcopy("meminfo", dp->d_name, 8); - dp->d_type = DT_REG; - break; - - case 4: - dp->d_fileno = PROCFS_FILENO(0, Pcpuinfo); - dp->d_namlen = 7; - bcopy("cpuinfo", dp->d_name, 8); - dp->d_type = DT_REG; - break; - - case 5: - dp->d_fileno = PROCFS_FILENO(0, Pstat); - dp->d_namlen = 4; - bcopy("stat", dp->d_name, 5); - dp->d_type = DT_REG; - break; - - case 6: - dp->d_fileno = PROCFS_FILENO(0, Puptime); - dp->d_namlen = 6; - bcopy("uptime", dp->d_name, 7); - dp->d_type = DT_REG; - break; - - case 7: - dp->d_fileno = PROCFS_FILENO(0, Pversion); - dp->d_namlen = 7; - bcopy("version", dp->d_name, 8); - dp->d_type = DT_REG; - break; - - default: - while (pcnt < i) { - p = LIST_NEXT(p, p_list); - if (p == NULL) - goto done; - if (p_can(curproc, p, P_CAN_SEE, NULL)) - continue; - pcnt++; - } - while (p_can(curproc, p, P_CAN_SEE, NULL)) { - p = LIST_NEXT(p, p_list); - if (p == NULL) - goto done; - } - dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc); - dp->d_namlen = sprintf(dp->d_name, "%ld", - (long)p->p_pid); - dp->d_type = DT_DIR; - p = LIST_NEXT(p, p_list); - break; - } + i = (nd - pfs->pfs_nd) / sizeof(*nd); - if ((error = uiomove((caddr_t)dp, delen, uio)) != 0) - break; + while (p && i < start) { + if (p_can(curproc, p, P_CAN_SEE, NULL) == 0) + i++; + p = LIST_NEXT(p, p_list); } - done: + 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; -#ifdef PROCFS_ZOMBIE - if (p == NULL && doingzomb == 0) { - doingzomb = 1; - p = LIST_FIRST(&zombproc); - goto again; + error = uiomove((caddr_t)dp, delen, uio); + if (error) + break; + copied++; } -#endif - ALLPROC_LOCK(AP_RELEASE); - break; - - } - - default: - error = ENOTDIR; - break; } - - uio->uio_offset = i * delen; - +done: + uio->uio_offset += copied * delen; return (error); } @@ -992,49 +807,14 @@ static int linprocfs_readlink(ap) struct vop_readlink_args *ap; { - char buf[16]; /* should be enough */ - struct proc *procp; - struct vnode *vp = ap->a_vp; - struct pfsnode *pfs = VTOPFS(vp); - char *fullpath, *freepath; - int error, len; - - switch (pfs->pfs_type) { - case Pself: - if (pfs->pfs_fileno != PROCFS_FILENO(0, Pself)) - return (EINVAL); - - len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); + struct pfsnode *pfs = VTOPFS(ap->a_vp); + struct node_data *nd = pfs->pfs_nd; - return (uiomove(buf, len, ap->a_uio)); - /* - * There _should_ be no way for an entire process to disappear - * from under us... - */ - case Pexe: - procp = PFIND(pfs->pfs_pid); - if (procp != NULL) - PROC_LOCK(procp); - if (procp == NULL || procp->p_cred == NULL || - procp->p_ucred == NULL) { - if (procp != NULL) - PROC_UNLOCK(procp); - printf("linprocfs_readlink: pid %d disappeared\n", - pfs->pfs_pid); - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); - } - PROC_UNLOCK(procp); - error = textvp_fullpath(procp, &fullpath, &freepath); - if (error != 0) - return (uiomove("unknown", sizeof("unknown") - 1, - ap->a_uio)); - error = uiomove(fullpath, strlen(fullpath), ap->a_uio); - free(freepath, M_TEMP); - return (error); - default: + /* sanity check */ + if (nd->nd_type != VLNK) return (EINVAL); - } + + return (nd->nd_action(NULL, NULL, pfs, ap->a_uio)); } /* |