svn commit: r195711 - projects/libprocstat/usr.bin/fstat

Stanislav Sedov stas at FreeBSD.org
Wed Jul 15 17:24:05 UTC 2009


Author: stas
Date: Wed Jul 15 17:24:03 2009
New Revision: 195711
URL: http://svn.freebsd.org/changeset/base/195711

Log:
  - A second (hopefully more successfull attempt) to get a clean separation
  of fstat code to data retrieval and representation parts.  I added a number
  of independent structural parts (filestat, vnstat, pipestat, ptsstat) which
  is used to return information about appropiate file descriptors and is
  supposed to be independent of the access method that was used.  Method-specific
  that can be used to obtain further information later is stored in opaque field
  of filestat structure.

Modified:
  projects/libprocstat/usr.bin/fstat/Makefile
  projects/libprocstat/usr.bin/fstat/cd9660.c
  projects/libprocstat/usr.bin/fstat/common.c
  projects/libprocstat/usr.bin/fstat/common.h
  projects/libprocstat/usr.bin/fstat/fstat.c
  projects/libprocstat/usr.bin/fstat/libprocstat.c
  projects/libprocstat/usr.bin/fstat/libprocstat.h
  projects/libprocstat/usr.bin/fstat/main.c
  projects/libprocstat/usr.bin/fstat/msdosfs.c
  projects/libprocstat/usr.bin/fstat/zfs.c

Modified: projects/libprocstat/usr.bin/fstat/Makefile
==============================================================================
--- projects/libprocstat/usr.bin/fstat/Makefile	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/Makefile	Wed Jul 15 17:24:03 2009	(r195711)
@@ -4,11 +4,11 @@
 .include <bsd.own.mk>
 
 PROG=	fstat
-SRCS=	cd9660.c common.c fstat.c main.c msdosfs.c fuser.c libprocstat.c
+SRCS=	common.c fstat.c main.c libprocstat.c cd9660.c msdosfs.c
 LINKS=	${BINDIR}/fstat ${BINDIR}/fuser
 DPADD=	${LIBKVM}
 LDADD=	-lkvm -lutil
-WARNS?=	6
+WARNS?=	3
 
 MAN1=	fuser.1 fstat.1
 

Modified: projects/libprocstat/usr.bin/fstat/cd9660.c
==============================================================================
--- projects/libprocstat/usr.bin/fstat/cd9660.c	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/cd9660.c	Wed Jul 15 17:24:03 2009	(r195711)
@@ -49,6 +49,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/vnode.h>
 #include <sys/mount.h>
 
+#include <err.h>
+
 #include <isofs/cd9660/cd9660_node.h>
 #define _KERNEL
 #include <isofs/cd9660/iso.h>
@@ -60,28 +62,26 @@ __FBSDID("$FreeBSD$");
 #include "common.h"
 
 int
-isofs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp)
+isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 	struct iso_node isonode;
 	struct iso_mnt mnt;
 
 	if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &isonode,
 	    sizeof(isonode))) {
-		dprintf(stderr, "can't read iso_node at %p\n",
+		warnx("can't read iso_node at %p",
 		    (void *)VTOI(vp));
-		return (0);
+		return (1);
 	}
 	if (!kvm_read_all(kd, (unsigned long)isonode.i_mnt, &mnt,
 	    sizeof(mnt))) {
-		dprintf(stderr, "can't read iso_mnt at %p\n",
+		warnx("can't read iso_mnt at %p",
 		    (void *)VTOI(vp));
-		return (0);
+		return (1);
 	}
-	fsp->fsid = dev2udev(kd, mnt.im_dev);
-	fsp->mode = (mode_t)isonode.inode.iso_mode;
-	fsp->rdev = isonode.inode.iso_rdev;
-
-	fsp->fileid = (long)isonode.i_number;
-	fsp->size = (u_long)isonode.i_size;
-	return (1);
+	vn->vn_fsid = dev2udev(kd, mnt.im_dev);
+	vn->vn_mode = (mode_t)isonode.inode.iso_mode;
+	vn->vn_fileid = (long)isonode.i_number;
+	vn->vn_size = (u_long)isonode.i_size;
+	return (0);
 }

Modified: projects/libprocstat/usr.bin/fstat/common.c
==============================================================================
--- projects/libprocstat/usr.bin/fstat/common.c	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/common.c	Wed Jul 15 17:24:03 2009	(r195711)
@@ -129,86 +129,66 @@ kdevtoname(kvm_t *kd, struct cdev *dev)
 }
 
 int
-ufs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp)
+ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 	struct inode inode;
 
 	if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &inode, sizeof(inode))) {
-		dprintf(stderr, "can't read inode at %p\n", (void *)VTOI(vp));
-		return 0;
+		warnx("can't read inode at %p", (void *)VTOI(vp));
+		return (1);
 	}
 	/*
 	 * The st_dev from stat(2) is a dev_t. These kernel structures
 	 * contain cdev pointers. We need to convert to dev_t to make
 	 * comparisons
 	 */
-	fsp->fsid = dev2udev(kd, inode.i_dev);
-	fsp->fileid = (long)inode.i_number;
-	fsp->mode = (mode_t)inode.i_mode;
-	fsp->size = (u_long)inode.i_size;
-#if should_be_but_is_hard
-	/* XXX - need to load i_ump and i_din[12] from kernel memory */
-	if (inode.i_ump->um_fstype == UFS1)
-		fsp->rdev = inode.i_din1->di_rdev;
-	else
-		fsp->rdev = inode.i_din2->di_rdev;
-#else
-	fsp->rdev = 0;
-#endif
-
-	return 1;
+	vn->vn_fsid = dev2udev(kd, inode.i_dev);
+	vn->vn_fileid = (long)inode.i_number;
+	vn->vn_mode = (mode_t)inode.i_mode;
+	vn->vn_size = (u_long)inode.i_size;
+	return (0);
 }
 
 int
-devfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp)
+devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 	struct devfs_dirent devfs_dirent;
 	struct mount mount;
-	struct vnode vnode;
 
 	if (!kvm_read_all(kd, (unsigned long)vp->v_data, &devfs_dirent,
 	    sizeof(devfs_dirent))) {
-		dprintf(stderr, "can't read devfs_dirent at %p\n",
+		warnx("can't read devfs_dirent at %p",
 		    (void *)vp->v_data);
-		return 0;
+		return (1);
 	}
 	if (!kvm_read_all(kd, (unsigned long)vp->v_mount, &mount,
 	    sizeof(mount))) {
-		dprintf(stderr, "can't read mount at %p\n",
+		warnx("can't read mount at %p",
 		    (void *)vp->v_mount);
-		return 0;
-	}
-	if (!kvm_read_all(kd, (unsigned long)devfs_dirent.de_vnode, &vnode,
-	    sizeof(vnode))) {
-		dprintf(stderr, "can't read vnode at %p\n",
-		    (void *)devfs_dirent.de_vnode);
-		return 0;
+		return (1);
 	}
-	fsp->fsid = (long)mount.mnt_stat.f_fsid.val[0];
-	fsp->fileid = devfs_dirent.de_inode;
-	fsp->mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
-	fsp->size = 0;
-	fsp->rdev = dev2udev(kd, vnode.v_rdev);
-
-	return 1;
+	vn->vn_fsid = (long)mount.mnt_stat.f_fsid.val[0];
+	vn->vn_fileid = devfs_dirent.de_inode;
+	vn->vn_mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
+	vn->vn_size = 0;
+	return (0);
 }
 
 int
-nfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp)
+nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
 {
 	struct nfsnode nfsnode;
 	mode_t mode;
 
 	if (!kvm_read_all(kd, (unsigned long)VTONFS(vp), &nfsnode,
 	    sizeof(nfsnode))) {
-		dprintf(stderr, "can't read nfsnode at %p\n",
+		warnx("can't read nfsnode at %p",
 		    (void *)VTONFS(vp));
-		return 0;
+		return (1);
 	}
-	fsp->fsid = nfsnode.n_vattr.va_fsid;
-	fsp->fileid = nfsnode.n_vattr.va_fileid;
-	fsp->size = nfsnode.n_size;
-	fsp->rdev = nfsnode.n_vattr.va_rdev;
+	vn->vn_fsid = nfsnode.n_vattr.va_fsid;
+	vn->vn_fileid = nfsnode.n_vattr.va_fileid;
+	vn->vn_size = nfsnode.n_size;
 	mode = (mode_t)nfsnode.n_vattr.va_mode;
 	switch (vp->v_type) {
 	case VREG:
@@ -232,14 +212,11 @@ nfs_filestat(kvm_t *kd, struct vnode *vp
 	case VFIFO:
 		mode |= S_IFIFO;
 		break;
-	case VNON:
-	case VBAD:
-	case VMARKER:
-		return 0;
+	default:
+		break;
 	};
-	fsp->mode = mode;
-
-	return 1;
+	vn->vn_mode = mode;
+	return (0);
 }
 
 /*

Modified: projects/libprocstat/usr.bin/fstat/common.h
==============================================================================
--- projects/libprocstat/usr.bin/fstat/common.h	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/common.h	Wed Jul 15 17:24:03 2009	(r195711)
@@ -36,19 +36,70 @@
 #ifndef	__COMMON_H__
 #define	__COMMON_H__
 
+#if 0
 struct  filestat {
-	long	fsid;
-	long	fileid;
-	mode_t	mode;
-	u_long	size;
-	dev_t	rdev;
-	int	vtype;
+	union {
+		struct {
+			long	fsid;
+			long	fileid;
+			mode_t	mode;
+			u_long	size;
+			dev_t rdev;
+			dev_t dev;
+			int	vtype;
+			char	*mntdir;
+		} vnode;
+//		struct pipe pipe;
+		dev_t ttydev;
+		struct {
+			int type;
+			char *domain_name;
+			int dom_family;
+			int proto;
+			caddr_t so_pcb;
+			caddr_t tcpcb;
+			caddr_t conntcb;
+			caddr_t sockaddr;
+//			struct socket sock;
+		} socket;
+	};
 	int	type;
-	char	*mntdir;
 	int	flags;
 	int	fflags;
 	int	fd;
 };
+#endif
+
+struct filestat {
+	int	fs_type;	/* Descriptor type. */
+	int	fs_flags;	/* filestat specific flags. */
+	int	fs_fflags;	/* Descriptor access flags. */
+	int	fs_fd;		/* File descriptor number. */
+	void	*fs_typedep;	/* Type dependent data. */
+	STAILQ_ENTRY(filestat)	next;
+};
+
+struct vnstat {
+	dev_t	vn_dev;
+	int	vn_type;
+	long	vn_fsid;
+	long	vn_fileid;
+	mode_t	vn_mode;
+	u_long	vn_size;
+	char	*mntdir;
+};
+
+struct ptsstat {
+	dev_t	dev;
+};
+
+struct pipestat {
+	caddr_t	addr;
+	caddr_t	peer;
+	size_t	buffer_cnt;
+};
+
+STAILQ_HEAD(filestat_list, filestat);
 
 extern int vflg;
 
@@ -61,13 +112,13 @@ int	kvm_read_all(kvm_t *kd, unsigned lon
 /*
  * Filesystems specific access routines.
  */
-int	devfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
-int	isofs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
-int	msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
-int	nfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
-int	ufs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
+int	devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
+int	isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
+int	msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
+int	nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
+int	ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
 #ifdef ZFS
-int	zfs_filestat(kvm_t *kd, struct vnode *vp, struct filestat *fsp);
+int	zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
 void	*getvnodedata(struct vnode *vp);
 struct mount	*getvnodemount(struct vnode *vp);
 #endif

Modified: projects/libprocstat/usr.bin/fstat/fstat.c
==============================================================================
--- projects/libprocstat/usr.bin/fstat/fstat.c	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/fstat.c	Wed Jul 15 17:24:03 2009	(r195711)
@@ -147,6 +147,8 @@ static void
 print_pts_info(struct procstat *procstat, struct filestat *fst);
 static void
 print_vnode_info(struct procstat *procstat, struct filestat *fst);
+static void
+print_access_flags(int flags);
 
 int
 do_fstat(int argc, char **argv)
@@ -268,22 +270,22 @@ fstat1(int what, int arg)
 static void
 dofiles(struct procstat *procstat, struct kinfo_proc *kp)
 {
-	struct filestat *fst;
-	unsigned int count;
-	const char *cmd, *uname;
+	struct filestat_list *head;
+	const char *cmd;
+	const char *uname;
 	int pid;
-	unsigned int i;
+	struct filestat *fst;
 
 	uname = user_from_uid(kp->ki_uid, 0);
 	pid = kp->ki_pid;
 	cmd = kp->ki_comm;
 
-	fst = procstat_getfiles(procstat, kp, &count);
-	if (fst == NULL)
+	head = procstat_getfiles(procstat, kp);
+	if (head == NULL)
 		return;
 
-	for (i = 0; i < count; i++)
-		print_file_info(procstat, &fst[i], uname, cmd, pid);
+	STAILQ_FOREACH(fst, head, next)
+		print_file_info(procstat, fst, uname, cmd, pid);
 }
 
 
@@ -291,45 +293,38 @@ static void
 print_file_info(struct procstat *procstat, struct filestat *fst,
     const char *uname, const char *cmd, int pid)
 {
-	const char *badtype, *filename;
+	const char *filename;
+	struct vnstat vn;
+	int error;
+	int fsmatch = 0;
+	DEVS *d;
 
-	badtype = NULL;
 	filename = NULL;
-	if (fst->type == PS_FST_TYPE_VNODE || fst->type == PS_FST_TYPE_FIFO) {
-		if (fst->flags & PS_FST_FLAG_ERROR)
-			badtype = "error";
-		else if (fst->flags == PS_FST_FLAG_UNKNOWNFS)
-			badtype = "unknown";
-		else if (fst->vtype == PS_FST_VTYPE_VNON)
-			badtype = "none";
-		else if (fst->vtype == PS_FST_VTYPE_VBAD)
-			badtype = "bad";
-
-		if (checkfile) {
-			int fsmatch = 0;
-			DEVS *d;
-
-			if (badtype)
-				return;
-			for (d = devs; d != NULL; d = d->next)
-				if (d->fsid == fst->fsid) {
-					fsmatch = 1;
-					if (d->ino == fst->fileid) {
-						filename = d->name;
-						break;
-					}
+	if (checkfile != 0) {
+		if (fst->fs_type != PS_FST_TYPE_VNODE &&
+		    fst->fs_type == PS_FST_TYPE_FIFO)
+			return;
+		error = procstat_get_vnode_info(procstat, fst, &vn, NULL);
+		if (error != 0)
+			return;
+
+		for (d = devs; d != NULL; d = d->next)
+			if (d->fsid == vn.vn_fsid) {
+				fsmatch = 1;
+				if (d->ino == vn.vn_fileid) {
+					filename = d->name;
+					break;
 				}
-			if (fsmatch == 0 || (filename == NULL && fsflg == 0))
-				return;
-		}
-	} else if (checkfile != 0)
-		return;
+			}
+		if (fsmatch == 0 || (filename == NULL && fsflg == 0))
+			return;
+	}
 
 	/*
 	 * Print entry prefix.
 	 */
 	printf("%-8.8s %-10s %5d", uname, cmd, pid);
-	switch(fst->fd) {
+	switch(fst->fs_fd) {
 	case PS_FST_FD_TEXT:
 		printf(" text");
 		break;
@@ -349,18 +344,14 @@ print_file_info(struct procstat *procsta
 		printf(" jail");
 		break;
 	default:
-		printf(" %4d", fst->fd);
+		printf(" %4d", fst->fs_fd);
 		break;
 	}
-	if (badtype) {
-		(void)printf(" -         -  %10s    -\n", badtype);
-		return;
-	}
 
 	/*
 	 * Print type-specific data.
 	 */
-	switch (fst->type) {
+	switch (fst->fs_type) {
 	case PS_FST_TYPE_FIFO:
 	case PS_FST_TYPE_VNODE:
 		print_vnode_info(procstat, fst);
@@ -377,7 +368,7 @@ print_file_info(struct procstat *procsta
 	default:	
 		dprintf(stderr,
 		    "unknown file type %d for file %d of pid %d\n",
-		    fst->type, fst->fd, pid);
+		    fst->fs_type, fst->fs_fd, pid);
 	}
 	if (filename && !fsflg)
 		printf("  %s", filename);
@@ -392,60 +383,101 @@ print_socket_info(struct procstat *procs
 }
 
 static void
-print_pipe_info(struct procstat *procstat __unused, struct filestat *fst __unused)
+print_pipe_info(struct procstat *procstat, struct filestat *fst)
 {
-
-	printf(" not implemented\n");
+	struct pipestat pipe;
+	char errbuf[_POSIX2_LINE_MAX];
+	int error;
+
+	error = procstat_get_pipe_info(procstat, fst, &pipe, errbuf);
+	if (error != 0) {
+		printf("* error");
+		return;
+	}
+	printf("* pipe %8lx <-> %8lx", (u_long)pipe.addr, (u_long)pipe.peer);
+	printf(" %6zd", pipe.buffer_cnt);
+	print_access_flags(fst->fs_fflags);
 }
 
 static void
-print_pts_info(struct procstat *procstat __unused, struct filestat *fst __unused)
+print_pts_info(struct procstat *procstat, struct filestat *fst)
 {
-
-	printf(" not implemented\n");
+	struct ptsstat pts;
+	char errbuf[_POSIX2_LINE_MAX];
+	int error;
+
+	error = procstat_get_pts_info(procstat, fst, &pts, errbuf);
+	if (error != 0) {
+		printf("* error");
+		return;
+	}
+	printf("* pseudo-terminal master ");
+	if (nflg) {
+		printf("%10d,%-2d", major(pts.dev), minor(pts.dev));
+	} /* else {
+		printf("%10s", pts.name);
+	} */
+	print_access_flags(fst->fs_fflags);
 }
 
 static void
-print_vnode_info(struct procstat *procstat __unused, struct filestat *fst)
+print_vnode_info(struct procstat *procstat, struct filestat *fst)
 {
+	struct vnstat vn;
+	char *name;
+	const char *badtype;
+	char errbuf[_POSIX2_LINE_MAX];
 	char mode[15];
-	char rw[3];
+	int error;
+
+	badtype = NULL;
+	error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+	if (error != 0)
+		badtype = errbuf;
+	else if (vn.vn_type == PS_FST_VTYPE_VBAD)
+		badtype = "bad";
+	else if (vn.vn_type == PS_FST_VTYPE_VNON)
+		badtype = "none";
+	if (badtype != NULL)
+		printf(" -         -  %10s    -", badtype);
 
 	if (nflg)
-		(void)printf(" %2d,%-2d", major(fst->fsid), minor(fst->fsid));
-	else if (fst->mntdir != NULL)
-		(void)printf(" %-8s", fst->mntdir);
+		printf(" %2d,%-2d", major(vn.vn_fsid), minor(vn.vn_fsid));
+	else if (vn.mntdir != NULL)
+		(void)printf(" %-8s", vn.mntdir);
+
+	/*
+	 * Print access mode.
+	 */
 	if (nflg)
-		(void)sprintf(mode, "%o", fst->mode);
+		(void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode);
 	else {
-		strmode(fst->mode, mode);
+		strmode(vn.vn_mode, mode);
 	}
-	(void)printf(" %6ld %10s", fst->fileid, mode);
-	switch (fst->vtype) {
-	case PS_FST_VTYPE_VBLK:
-	case PS_FST_VTYPE_VCHR: {
-		char *name;
-
-#if 0
-		name = procstat_devname(procstat, fst->rdev,
-		    fst->vtype = PS_FST_VTYPE_VBLK ? S_IFBLK : S_IFCHR);
-#else
+	(void)printf(" %6ld %10s", vn.vn_fileid, mode);
+
+	if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
 		name = NULL;
-#endif
+//		name = fst->vnode.dev.name;
 		if (nflg || !name)
-			printf("  %2d,%-2d", major(fst->rdev), minor(fst->rdev));
+			printf("  %2d,%-2d", major(vn.vn_dev), minor(vn.vn_dev));
 		else {
 			printf(" %6s", name);
 		}
-		break;
-	}
-	default:
-		printf(" %6lu", fst->size);
-	}
+	} else
+		printf(" %6lu", vn.vn_size);
+	print_access_flags(fst->fs_fflags);
+}
+
+static void
+print_access_flags(int flags)
+{
+	char rw[3];
+
 	rw[0] = '\0';
-	if (fst->fflags & PS_FST_FFLAG_READ)
+	if (flags & PS_FST_FFLAG_READ)
 		strcat(rw, "r");
-	if (fst->fflags & PS_FST_FFLAG_WRITE)
+	if (flags & PS_FST_FFLAG_WRITE)
 		strcat(rw, "w");
 	printf(" %2s", rw);
 }

Modified: projects/libprocstat/usr.bin/fstat/libprocstat.c
==============================================================================
--- projects/libprocstat/usr.bin/fstat/libprocstat.c	Wed Jul 15 17:07:39 2009	(r195710)
+++ projects/libprocstat/usr.bin/fstat/libprocstat.c	Wed Jul 15 17:24:03 2009	(r195711)
@@ -79,6 +79,26 @@ static struct {
 #define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst))
 
 char *getmnton(kvm_t *kd, struct mount *m);
+void
+socktrans(kvm_t *kd, struct socket *sock, int fd, int flags, struct filestat *fst);
+int	procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
+    struct vnstat *vn, char *errbuf);
+int
+procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
+    char *errbuf);
+int
+procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *pipe,
+    char *errbuf);
+int
+procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
+    struct pipestat *pipe, char *errbuf);
+int
+procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
+    char *errbuf);
+int
+procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
+    struct ptsstat *pts, char *errbuf);
+
 
 /*
  * Filesystem specific handlers.
@@ -87,7 +107,7 @@ char *getmnton(kvm_t *kd, struct mount *
 struct {
         const char      *tag;
         int             (*handler)(kvm_t *kd, struct vnode *vp,
-            struct filestat *fsp);
+            struct vnstat *vn);
 } fstypes[] = {
         FSTYPE(ufs),
         FSTYPE(devfs),
@@ -211,31 +231,50 @@ fail:
 	return (NULL);
 }
 
-struct filestat *
-procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp,
-    unsigned int *cnt)
+struct filestat_list *
+procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp)
 {
 	
 	if (procstat->type == PROCSTAT_SYSCTL)
-		return (procstat_getfiles_sysctl(kp, cnt));
+		return (procstat_getfiles_sysctl(kp));
 	else if (procstat->type == PROCSTAT_KVM)
-		 return (procstat_getfiles_kvm(procstat->kd, kp, cnt));
+		 return (procstat_getfiles_kvm(procstat->kd, kp));
 	else
 		return (NULL);
 }
 
-struct filestat *
-procstat_getfiles_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cnt)
+static struct filestat *
+filestat_new_entry(struct vnode *vp, int type, int fd, int fflags)
+{
+	struct filestat *entry;
+
+	entry = calloc(1, sizeof(*entry));
+	if (entry == NULL) {
+		warn("malloc()");
+		return (NULL);
+	}
+	entry->fs_typedep = vp;
+	entry->fs_fflags = fflags;
+	entry->fs_fd = fd;
+	entry->fs_type = type;
+	return (entry);
+}
+
+struct filestat_list *
+procstat_getfiles_kvm(kvm_t *kd, struct kinfo_proc *kp)
 {
 	int i;
 	struct file file;
 	struct filedesc filed;
-	unsigned int nfiles, count, f;
+	unsigned int nfiles;
 	struct file **ofiles;
-	struct filestat *fst;
+	struct filestat *entry;
+	struct filestat_list *head;
+	int type;
+	void *data;
 
 	assert(kd);
-	assert(cnt);
+
 	if (kp->ki_fd == NULL)
 		return (NULL);
 	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
@@ -243,31 +282,50 @@ procstat_getfiles_kvm(kvm_t *kd, struct 
 		warnx("can't read filedesc at %p\n", (void *)kp->ki_fd);
 		return (NULL);
 	}
-	count = 5;	/* Allocate additional space for special files. */
-	if (filed.fd_lastfile >= 0)
-		count += filed.fd_lastfile + 1;
-	fst = malloc(count * sizeof(*fst));
-	if (fst == NULL) {
-		warn("malloc(%zd)", count * sizeof(*fst));
+
+	/*
+	 * Allocate list head.
+	 */
+	head = malloc(sizeof(*head));
+	if (head == NULL)
 		return (NULL);
-	}
+	STAILQ_INIT(head);
 
 	/* root directory vnode, if one. */
-	f = 0;
-	if (filed.fd_rdir)
-		vtrans_kvm(kd, filed.fd_rdir, PS_FST_FD_RDIR, PS_FST_FFLAG_READ, &fst[f++]);
+	if (filed.fd_rdir) {
+		entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, PS_FST_FD_RDIR,
+		    PS_FST_FFLAG_READ);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
+	}
 	/* current working directory vnode. */
-	if (filed.fd_cdir)
-		vtrans_kvm(kd, filed.fd_cdir, PS_FST_FD_CDIR, PS_FST_FFLAG_READ, &fst[f++]);
+	if (filed.fd_cdir) {
+		entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, PS_FST_FD_CDIR,
+		    PS_FST_FFLAG_READ);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
+	}
 	/* jail root, if any. */
-	if (filed.fd_jdir)
-		vtrans_kvm(kd, filed.fd_jdir, PS_FST_FD_JAIL, PS_FST_FFLAG_READ, &fst[f++]);
+	if (filed.fd_jdir) {
+		entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, PS_FST_FD_JAIL,
+		    PS_FST_FFLAG_READ);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
+	}
 	/* ktrace vnode, if one */
-	if (kp->ki_tracep)
-		vtrans_kvm(kd, kp->ki_tracep, PS_FST_FD_TRACE, PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, &fst[f++]);
+	if (kp->ki_tracep) {
+		entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, PS_FST_FD_TRACE,
+		    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
+	}
 	/* text vnode, if one */
-	if (kp->ki_textvp)
-		vtrans_kvm(kd, kp->ki_textvp, PS_FST_FD_TEXT, PS_FST_FFLAG_READ, &fst[f++]);
+	if (kp->ki_textvp) {
+		entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, PS_FST_FD_TEXT,
+		    PS_FST_FFLAG_READ);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
+	}
 
 	nfiles = filed.fd_lastfile + 1;
 	ofiles = malloc(nfiles * sizeof(struct file *));
@@ -293,122 +351,45 @@ procstat_getfiles_kvm(kvm_t *kd, struct 
 		}
 		switch (file.f_type) {
 		case DTYPE_VNODE:
-			vtrans_kvm(kd, file.f_vnode, i, file.f_flag, &fst[f++]);
+			type = PS_FST_TYPE_VNODE;
+			data = file.f_vnode;
 			break;
-/*
 		case DTYPE_SOCKET:
-			socktrans(file.f_data, i, &fst[f++]);
+			type = PS_FST_TYPE_SOCKET;
+			data = file.f_data;
 			break;
 		case DTYPE_PIPE:
-			pipetrans(file.f_data, i, file.f_flag, &fst[f++]);
+			type = PS_FST_TYPE_PIPE;
+			data = file.f_data;
 			break;
 		case DTYPE_FIFO:
-			vtrans(file.f_vnode, i, file.f_flag, &fst[f++]);
+			type = PS_FST_TYPE_FIFO;
+			data = file.f_vnode;
 			break;
+#ifdef DTYPE_PTS
 		case DTYPE_PTS:
-			ptstrans(file.f_data, i, file.f_flag, &fst[f++]);
+			type = PS_FST_TYPE_PTS;
+			data = file.f_data;
 			break;
-*/
+#endif
 		default:
-			dprintf(stderr,
-			    "unknown file type %d for file %d\n",
+			warnx("unknown file type %d for file %d\n",
 			    file.f_type, i);
+			continue;
 		}
+		entry = filestat_new_entry(data, type, i,
+		    PS_FST_FFLAG_READ);
+		if (entry != NULL)
+			STAILQ_INSERT_TAIL(head, entry, next);
 	}
 	free(ofiles);
 exit:
-	*cnt = f;
-	return (fst);
+	return (head);
 }
 
-struct filestat *
-procstat_getfiles_sysctl(struct kinfo_proc *kp __unused, unsigned int *cnt __unused)
+struct filestat_list *
+procstat_getfiles_sysctl(struct kinfo_proc *kp __unused)
 {
-#if 0
-	int i;
-	struct file file;
-	struct filedesc filed;
-	unsigned int nfiles, count, f;
-	struct file **ofiles;
-	struct filestat *fst;
-
-	assert(kp);
-	assert(cnt);
-
-	/*
-	 * XXX: special files (TEXTVP, KTRACEVP...)
-	 */
-
-	/*
-	 * Open files.
-	 */
-	freep = kinfo_getfile(kp->ki_pid, &count);
-	if (freep == NULL) {
-		warn("kinfo_getfile()");
-		return (NULL);
-	}
-	if (count == 0)
-		return (NULL);
-
-	fst = malloc(count * sizeof(*fst));
-	if (fst == NULL) {
-		warn("malloc(%zd)", count * sizeof(*fst));
-		return (NULL);
-	}
-	f = 0;
-	for (i = 0; i < count; i++) {
-		kif = &freep[i];
-		switch (kif->kf_type) {
-		case KF_TYPE_VNODE:
-			if (kif->kf_fd == KF_FD_TYPE_CWD) {
-				fd_type = CDIR;
-				flags = FST_READ;
-			} else if (kif->kf_fd == KF_FD_TYPE_ROOT) {
-				fd_type = RDIR;
-				flags = FST_READ;
-			} else if (kif->kf_fd == KF_FD_TYPE_JAIL) {
-				fd_type = JDIR;
-				flags = FST_READ;
-			} else {
-				fd_type = i;
-				flags = kif->kf_flags;
-			}
-			/* Only do this if the attributes are valid. */
-			if (kif->kf_status & KF_ATTR_VALID)
-				vtrans_sysctl(kif, fd_type, flags, &fst[f++]);
-			break;
-#if 0
-		case KF_TYPE_PIPE:
-			if (checkfile == 0)
-				pipetrans_sysctl(kif, i, kif->kf_flags, &fst[f++]);
-			break;
-		case KF_TYPE_SOCKET:
-			if (checkfile == 0)
-				socktrans_sysctl(file.f_data, i);
-			break;
-		case KF_TYPE_PIPE:
-			if (checkfile == 0)
-				pipetrans_sysctl(file.f_data, i, file.f_flag, &fst[f++]);
-			break;
-		case KF_TYPE_FIFO:
-			if (checkfile == 0)
-				vtrans_sysctl(file.f_vnode, i, file.f_flag, &fst[f++]);
-			break;
-		case KF_TYPE_PTS:
-			if (checkfile == 0)
-				ptstrans_sysctl(file.f_data, i, file.f_flag, &fst[f++]);
-			break;
-#endif
-		default:
-			dprintf(stderr,
-			    "unknown file type %d for file %d\n",
-			    file.f_type, i);
-		}
-	}
-	free(freep);
-	*cnt = f;
-	return (fst);
-#endif
 	return (NULL);
 }
 
@@ -427,34 +408,316 @@ vntype2psfsttype(int type)
 	return (fst_type);
 }
 
+char *
+getmnton(kvm_t *kd, struct mount *m)
+{
+	static struct mount mnt;
+	static struct mtab {
+		struct mtab *next;
+		struct mount *m;
+		char mntonname[MNAMELEN + 1];
+	} *mhead = NULL;
+	struct mtab *mt;
+
+	for (mt = mhead; mt != NULL; mt = mt->next)
+		if (m == mt->m)
+			return (mt->mntonname);
+	if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) {
+		warnx("can't read mount table at %p", (void *)m);
+		return (NULL);
+	}
+	if ((mt = malloc(sizeof (struct mtab))) == NULL)
+		err(1, NULL);
+	mt->m = m;
+	bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
+	mnt.mnt_stat.f_mntonname[MNAMELEN] = '\0';
+	mt->next = mhead;
+	mhead = mt;
+	return (mt->mntonname);
+}
+
+void
+socktrans(kvm_t *kd __unused, struct socket *sock __unused, int fd __unused, int flags __unused, struct filestat *fst __unused)
+{
+
+#if 0
+	static const char *stypename[] = {
+		"unused",	/* 0 */
+		"stream", 	/* 1 */
+		"dgram",	/* 2 */
+		"raw",		/* 3 */
+		"rdm",		/* 4 */
+		"seqpak"	/* 5 */
+	};
+#define	STYPEMAX 5
+	struct socket	so;
+	struct protosw	proto;
+	struct domain	dom;
+	struct inpcb	inpcb;
+	struct unpcb	unpcb;
+	int len;
+	char dname[32];
+
+	bzero(fst, sizeof(*fst));
+
+	/* fill in socket */
+	if (!kvm_read_all(kd, (unsigned long)sock, &so,
+	    sizeof(struct socket))) {
+		warnx("can't read sock at %p\n", (void *)sock);
+		goto bad;
+	}
+	/* fill in protosw entry */
+	if (!kvm_read_all(kd, (unsigned long)so.so_proto, &proto,
+	    sizeof(struct protosw))) {
+		dprintf(stderr, "can't read protosw at %p",
+		    (void *)so.so_proto);
+		goto bad;
+	}
+	/* fill in domain */
+	if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom,
+	    sizeof(struct domain))) {
+		dprintf(stderr, "can't read domain at %p\n",
+		    (void *)proto.pr_domain);
+		goto bad;
+	}
+	if ((len = kvm_read(kd, (unsigned long)dom.dom_name, dname,
+	    sizeof(dname) - 1)) < 0) {
+		dprintf(stderr, "can't read domain name at %p\n",
+		    (void *)dom.dom_name);
+		dname[0] = '\0';
+	}
+	else
+		dname[len] = '\0';
+
+	fst->sock_type = so.so_type;
+	fst->sock_dname = strdup(dname)
+	fst->sock_protocol = proto.pr_protocol;
+	fst->sock = sock;
+	fst->fflags = flags;
+
+	/*
+	 * protocol specific formatting
+	 *
+	 * Try to find interesting things to print.  For tcp, the interesting
+	 * thing is the address of the tcpcb, for udp and others, just the
+	 * inpcb (socket pcb).  For unix domain, its the address of the socket
+	 * pcb and the address of the connected pcb (if connected).  Otherwise
+	 * just print the protocol number and address of the socket itself.
+	 * The idea is not to duplicate netstat, but to make available enough
+	 * information for further analysis.
+	 */
+	switch(dom.dom_family) {
+	case AF_INET:
+	case AF_INET6:
+		getinetproto(proto.pr_protocol);
+		if (proto.pr_protocol == IPPROTO_TCP ) {
+			if (so.so_pcb) {
+				if (kvm_read(kd, (u_long)so.so_pcb,
+				    (char *)&inpcb, sizeof(struct inpcb))
+				    != sizeof(struct inpcb)) {
+					dprintf(stderr,
+					    "can't read inpcb at %p\n",
+					    (void *)so.so_pcb);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list