summaryrefslogtreecommitdiffstats
path: root/sys/compat/linprocfs/linprocfs_vnops.c
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/linprocfs_vnops.c
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/linprocfs_vnops.c')
-rw-r--r--sys/compat/linprocfs/linprocfs_vnops.c556
1 files changed, 168 insertions, 388 deletions
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