summaryrefslogtreecommitdiffstats
path: root/sys/miscfs/procfs/procfs_subr.c
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2000-04-22 03:44:41 +0000
committergreen <green@FreeBSD.org>2000-04-22 03:44:41 +0000
commitd6606f6ffa25f25dd1b21027e947eda396dae2e8 (patch)
tree1180daeccbf00c233b5f29459132ff6d9dc97ccc /sys/miscfs/procfs/procfs_subr.c
parentceecd18663bf96e4035f579bb44400dfa4b3f99f (diff)
downloadFreeBSD-src-d6606f6ffa25f25dd1b21027e947eda396dae2e8.zip
FreeBSD-src-d6606f6ffa25f25dd1b21027e947eda396dae2e8.tar.gz
Welcome back our old friend from procfs, "file"!
Diffstat (limited to 'sys/miscfs/procfs/procfs_subr.c')
-rw-r--r--sys/miscfs/procfs/procfs_subr.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c
index 01e8ae9..a7bbfd7 100644
--- a/sys/miscfs/procfs/procfs_subr.c
+++ b/sys/miscfs/procfs/procfs_subr.c
@@ -41,9 +41,13 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <sys/proc.h>
+#include <sys/mount.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
+
#include <miscfs/procfs/procfs.h>
static struct pfsnode *pfshead;
@@ -159,6 +163,10 @@ loop:
break;
case Pfile:
+ pfs->pfs_mode = (VREAD|VEXEC);
+ vp->v_type = VLNK;
+ break;
+
case Pmem:
pfs->pfs_mode = (VREAD|VWRITE) |
(VREAD) >> 3;;
@@ -400,3 +408,99 @@ procfs_exit(struct proc *p)
pfs = pfs->pfs_next;
}
}
+
+/*
+ * Thus begins the fullpath magic.
+ */
+
+SYSCTL_DECL(_vfs_cache);
+
+#define STATNODE(name) \
+ static u_int name; \
+ SYSCTL_INT(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, "")
+
+static int disablefullpath;
+SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW,
+ &disablefullpath, 0, "");
+
+STATNODE(numfullpathcalls);
+STATNODE(numfullpathfail1);
+STATNODE(numfullpathfail2);
+STATNODE(numfullpathfail3);
+STATNODE(numfullpathfail4);
+STATNODE(numfullpathfound);
+
+int
+procfs_fullpath(struct proc *p, char **retbuf, char **retfreebuf) {
+ char *bp, *buf;
+ int i, slash_prefixed;
+ struct filedesc *fdp;
+ struct namecache *ncp;
+ struct vnode *vp, *textvp;
+
+ numfullpathcalls++;
+ if (disablefullpath)
+ return (ENODEV);
+ textvp = p->p_textvp;
+ if (textvp == NULL)
+ return (EINVAL);
+ buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ bp = buf + MAXPATHLEN - 1;
+ *bp = '\0';
+ fdp = p->p_fd;
+ slash_prefixed = 0;
+ for (vp = textvp; vp != fdp->fd_rdir && vp != rootvnode;) {
+ if (vp->v_flag & VROOT) {
+ if (vp->v_mount == NULL) { /* forced unmount */
+ free(buf, M_TEMP);
+ return (EBADF);
+ }
+ vp = vp->v_mount->mnt_vnodecovered;
+ continue;
+ }
+ if (vp != textvp && vp->v_dd->v_id != vp->v_ddid) {
+ numfullpathfail1++;
+ free(buf, M_TEMP);
+ return (ENOTDIR);
+ }
+ ncp = TAILQ_FIRST(&vp->v_cache_dst);
+ if (!ncp) {
+ numfullpathfail2++;
+ free(buf, M_TEMP);
+ return (ENOENT);
+ }
+ if (vp != textvp && ncp->nc_dvp != vp->v_dd) {
+ numfullpathfail3++;
+ free(buf, M_TEMP);
+ return (EBADF);
+ }
+ for (i = ncp->nc_nlen - 1; i >= 0; i--) {
+ if (bp == buf) {
+ numfullpathfail4++;
+ free(buf, M_TEMP);
+ return (ENOMEM);
+ }
+ *--bp = ncp->nc_name[i];
+ }
+ if (bp == buf) {
+ numfullpathfail4++;
+ free(buf, M_TEMP);
+ return (ENOMEM);
+ }
+ *--bp = '/';
+ slash_prefixed = 1;
+ vp = ncp->nc_dvp;
+ }
+ if (!slash_prefixed) {
+ if (bp == buf) {
+ numfullpathfail4++;
+ free(buf, M_TEMP);
+ return (ENOMEM);
+ }
+ *--bp = '/';
+ }
+ numfullpathfound++;
+ *retbuf = bp;
+ *retfreebuf = buf;
+ return (0);
+}
OpenPOWER on IntegriCloud