From owner-svn-src-projects@FreeBSD.ORG Wed Jul 15 17:24:04 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B46C21065674; Wed, 15 Jul 2009 17:24:04 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 643798FC22; Wed, 15 Jul 2009 17:24:04 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6FHO4WC099302; Wed, 15 Jul 2009 17:24:04 GMT (envelope-from stas@svn.freebsd.org) Received: (from stas@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6FHO3Mc099294; Wed, 15 Jul 2009 17:24:03 GMT (envelope-from stas@svn.freebsd.org) Message-Id: <200907151724.n6FHO3Mc099294@svn.freebsd.org> From: Stanislav Sedov Date: Wed, 15 Jul 2009 17:24:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195711 - projects/libprocstat/usr.bin/fstat X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 15 Jul 2009 17:24:05 -0000 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 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 #include +#include + #include #define _KERNEL #include @@ -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 ***