summaryrefslogtreecommitdiffstats
path: root/sys/compat/linprocfs
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-03-12 03:16:56 +0000
committerjlemon <jlemon@FreeBSD.org>2001-03-12 03:16:56 +0000
commit9060ef19e9519428bb13225828f90a85571542df (patch)
treee336cee327fa5c64c3713ae052fa321fde6c5464 /sys/compat/linprocfs
parent9b532c7054cf3ae570bbf4f36637b7a80564cee5 (diff)
downloadFreeBSD-src-9060ef19e9519428bb13225828f90a85571542df.zip
FreeBSD-src-9060ef19e9519428bb13225828f90a85571542df.tar.gz
Eliminate global node types and instead use an operations vector for
each node in order to make it easier to add new entries. Rewrite the internal directory structure so that it is possible to have independent subdirectories. Utilize this to add /proc/net/dev. Reviewed by: DES
Diffstat (limited to 'sys/compat/linprocfs')
-rw-r--r--sys/compat/linprocfs/linprocfs.c228
-rw-r--r--sys/compat/linprocfs/linprocfs.h102
-rw-r--r--sys/compat/linprocfs/linprocfs_misc.c228
-rw-r--r--sys/compat/linprocfs/linprocfs_subr.c135
-rw-r--r--sys/compat/linprocfs/linprocfs_vfsops.c2
-rw-r--r--sys/compat/linprocfs/linprocfs_vnops.c556
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));
}
/*
OpenPOWER on IntegriCloud