summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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