From owner-svn-src-projects@FreeBSD.ORG Mon Jul 13 21:18:54 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 E4F0A1065670; Mon, 13 Jul 2009 21:18:54 +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 D36F58FC13; Mon, 13 Jul 2009 21:18:54 +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 n6DLIscH035962; Mon, 13 Jul 2009 21:18:54 GMT (envelope-from stas@svn.freebsd.org) Received: (from stas@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6DLIsDD035957; Mon, 13 Jul 2009 21:18:54 GMT (envelope-from stas@svn.freebsd.org) Message-Id: <200907132118.n6DLIsDD035957@svn.freebsd.org> From: Stanislav Sedov Date: Mon, 13 Jul 2009 21:18:54 +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: r195664 - 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: Mon, 13 Jul 2009 21:18:55 -0000 Author: stas Date: Mon Jul 13 21:18:54 2009 New Revision: 195664 URL: http://svn.freebsd.org/changeset/base/195664 Log: - Work-in-progress work on separating access-independent fstat code from data access routines and attempt to create a generic transparent interface to kernel structures supporting both KVM and sysctl interfaces. This is still very dirty and current fstat is broken in a number of ways (and only ordinary vnodes are supported now). Added: projects/libprocstat/usr.bin/fstat/libprocstat.c projects/libprocstat/usr.bin/fstat/libprocstat.h Modified: projects/libprocstat/usr.bin/fstat/Makefile projects/libprocstat/usr.bin/fstat/common.h projects/libprocstat/usr.bin/fstat/fstat.c projects/libprocstat/usr.bin/fstat/fuser.c Modified: projects/libprocstat/usr.bin/fstat/Makefile ============================================================================== --- projects/libprocstat/usr.bin/fstat/Makefile Mon Jul 13 20:19:29 2009 (r195663) +++ projects/libprocstat/usr.bin/fstat/Makefile Mon Jul 13 21:18:54 2009 (r195664) @@ -4,12 +4,10 @@ .include PROG= fstat -SRCS= cd9660.c common.c fstat.c main.c msdosfs.c fuser.c +SRCS= cd9660.c common.c fstat.c main.c msdosfs.c fuser.c libprocstat.c LINKS= ${BINDIR}/fstat ${BINDIR}/fuser DPADD= ${LIBKVM} LDADD= -lkvm -lutil -BINGRP= kmem -BINMODE=2555 WARNS?= 6 MAN1= fuser.1 fstat.1 Modified: projects/libprocstat/usr.bin/fstat/common.h ============================================================================== --- projects/libprocstat/usr.bin/fstat/common.h Mon Jul 13 20:19:29 2009 (r195663) +++ projects/libprocstat/usr.bin/fstat/common.h Mon Jul 13 21:18:54 2009 (r195664) @@ -42,6 +42,12 @@ struct filestat { mode_t mode; u_long size; dev_t rdev; + int vtype; + int type; + char *mntdir; + int flags; + int fflags; + int fd; }; extern int vflg; Modified: projects/libprocstat/usr.bin/fstat/fstat.c ============================================================================== --- projects/libprocstat/usr.bin/fstat/fstat.c Mon Jul 13 20:19:29 2009 (r195663) +++ projects/libprocstat/usr.bin/fstat/fstat.c Mon Jul 13 21:18:54 2009 (r195664) @@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -104,13 +105,7 @@ __FBSDID("$FreeBSD$"); #include "common.h" #include "functions.h" - -#define TEXT -1 -#define CDIR -2 -#define RDIR -3 -#define TRACE -4 -#define MMAP -5 -#define JDIR -6 +#include "libprocstat.h" int fsflg, /* show files on same filesystem as file(s) argument */ pflg, /* show files open by a particular pid */ @@ -128,27 +123,30 @@ typedef struct devs { DEVS *devs; char *memf, *nlistf; -kvm_t *kd; -static void fstat_kvm(int, int); -static void fstat_sysctl(int, int); -void dofiles(struct kinfo_proc *kp); +static void fstat1(int what, int arg); +static void dofiles(struct procstat *procstat, struct kinfo_proc *p); void dofiles_kinfo(struct kinfo_proc *kp); void dommap(struct kinfo_proc *kp); -void vtrans(struct vnode *vp, int i, int flag); +void vtrans(struct vnode *vp, int i, int flag, const char *uname, const char *cmd, int pid); char *getmnton(struct mount *m); -void pipetrans(struct pipe *pi, int i, int flag); -void socktrans(struct socket *sock, int i); -void ptstrans(struct tty *tp, int i, int flag); +void pipetrans(struct pipe *pi, int i, int flag, const char *uname, const char *cmd, int pid); +void socktrans(struct socket *sock, int i, const char *uname, const char *cmd, int pid); +void ptstrans(struct tty *tp, int i, int flag, const char *uname, const char *cmd, int pid); void getinetproto(int number); int getfname(const char *filename); void usage(void); -static int kinfo_proc_compare(const void *, const void *); -static void kinfo_proc_sort(struct kinfo_proc *, int); -void vtrans_kinfo(struct kinfo_file *, int i, int flag); +void vtrans_kinfo(struct kinfo_file *, int i, int flag, const char *uname, const char *cmd, int pid); +static void print_file_info(struct procstat *procstat, struct filestat *fst, const char *uname, const char *cmd, int pid); -/* XXX: sys/mount.h */ -int statfs(const char *, struct statfs *); +static void +print_socket_info(struct procstat *procstat, struct filestat *fst); +static void +print_pipe_info(struct procstat *procstat, struct filestat *fst); +static void +print_pts_info(struct procstat *procstat, struct filestat *fst); +static void +print_vnode_info(struct procstat *procstat, struct filestat *fst); int do_fstat(int argc, char **argv) @@ -218,17 +216,28 @@ do_fstat(int argc, char **argv) checkfile = 1; } - if (memf != NULL) - fstat_kvm(what, arg); - else - fstat_sysctl(what, arg); + fstat1(what, arg); exit(0); } static void -print_header(void) +fstat1(int what, int arg) { + struct kinfo_proc *p; + struct procstat *procstat; + int cnt; + int i; + + procstat = procstat_open(nlistf, memf); + if (procstat == NULL) + errx(1, "procstat_open()"); + p = procstat_getprocs(procstat, what, arg, &cnt); + if (p == NULL) + errx(1, "procstat_getprocs()"); + /* + * Print header. + */ if (nflg) printf("%s", "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); @@ -239,854 +248,206 @@ print_header(void) printf(" NAME\n"); else putchar('\n'); -} - -static void -fstat_kvm(int what, int arg) -{ - struct kinfo_proc *p, *plast; - char buf[_POSIX2_LINE_MAX]; - int cnt; /* - * Discard setgid privileges if not the running kernel so that bad - * guys can't print interesting stuff from kernel memory. + * Go through the process list. */ - if (nlistf != NULL || memf != NULL) - setgid(getgid()); - - if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) - errx(1, "%s", buf); - setgid(getgid()); - if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) - errx(1, "%s", kvm_geterr(kd)); - print_header(); - for (plast = &p[cnt]; p < plast; ++p) { - if (p->ki_stat == SZOMB) + for (i = 0; i < cnt; i++) { + if (p[i].ki_stat == SZOMB) continue; - dofiles(p); + dofiles(procstat, &p[i]); +/* if (mflg) - dommap(p); + dommap(procstat, &p[i]); +*/ } -} - -/* - * Sort processes first by pid and then tid. - */ -static int -kinfo_proc_compare(const void *a, const void *b) -{ - int i; - - i = ((const struct kinfo_proc *)b)->ki_pid - - ((const struct kinfo_proc *)a)->ki_pid; - if (i != 0) - return (i); - i = ((const struct kinfo_proc *)b)->ki_tid - - ((const struct kinfo_proc *)a)->ki_tid; - return (i); -} - -static void -kinfo_proc_sort(struct kinfo_proc *kipp, int count) -{ - - qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); + free(p); + procstat_close(procstat); } static void -fstat_sysctl(int what, int arg) +dofiles(struct procstat *procstat, struct kinfo_proc *kp) { - struct kinfo_proc *kipp; - int name[4]; - size_t len; + struct filestat *fst; + unsigned int count; + const char *cmd, *uname; + int pid; unsigned int i; - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = what; - name[3] = arg; - - len = 0; - if (sysctl(name, 4, NULL, &len, NULL, 0) < 0) - err(-1, "sysctl: kern.proc"); - kipp = malloc(len); - if (kipp == NULL) - err(-1, "malloc"); - - if (sysctl(name, 4, kipp, &len, NULL, 0) < 0) { - free(kipp); - err(-1, "sysctl: kern.proc"); - } - if (len % sizeof(*kipp) != 0) - err(-1, "kinfo_proc mismatch"); - if (kipp->ki_structsize != sizeof(*kipp)) - err(-1, "kinfo_proc structure mismatch"); - kinfo_proc_sort(kipp, len / sizeof(*kipp)); - print_header(); - for (i = 0; i < len / sizeof(*kipp); i++) { - dofiles_kinfo(&kipp[i]); - if (mflg) - dommap(&kipp[i]); - } - free(kipp); -} - -const char *Uname, *Comm; -int Pid; - -#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ - switch(i) { \ - case TEXT: \ - printf(" text"); \ - break; \ - case CDIR: \ - printf(" wd"); \ - break; \ - case RDIR: \ - printf(" root"); \ - break; \ - case TRACE: \ - printf(" tr"); \ - break; \ - case MMAP: \ - printf(" mmap"); \ - break; \ - case JDIR: \ - printf(" jail"); \ - break; \ - default: \ - printf(" %4d", i); \ - break; \ - } - -/* - * print open files attributed to this process - */ -void -dofiles(struct kinfo_proc *kp) -{ - int i; - struct file file; - struct filedesc filed; - unsigned int nfiles; - struct file **ofiles; - - Uname = user_from_uid(kp->ki_uid, 0); - Pid = kp->ki_pid; - Comm = kp->ki_comm; - - if (kp->ki_fd == NULL) - return; - if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed, - sizeof(filed))) { - dprintf(stderr, "can't read filedesc at %p for pid %d\n", - (void *)kp->ki_fd, Pid); - return; - } - /* - * root directory vnode, if one - */ - if (filed.fd_rdir) - vtrans(filed.fd_rdir, RDIR, FREAD); - /* - * current working directory vnode - */ - if (filed.fd_cdir) - vtrans(filed.fd_cdir, CDIR, FREAD); - /* - * jail root, if any. - */ - if (filed.fd_jdir) - vtrans(filed.fd_jdir, JDIR, FREAD); - /* - * ktrace vnode, if one - */ - if (kp->ki_tracep) - vtrans(kp->ki_tracep, TRACE, FREAD|FWRITE); - /* - * text vnode, if one - */ - if (kp->ki_textvp) - vtrans(kp->ki_textvp, TEXT, FREAD); - /* - * open files - */ -#define FPSIZE (sizeof (struct file *)) -#define MAX_LASTFILE (0x1000000) + uname = user_from_uid(kp->ki_uid, 0); + pid = kp->ki_pid; + cmd = kp->ki_comm; - /* Sanity check on filed.fd_lastfile */ - if (filed.fd_lastfile <= -1 || filed.fd_lastfile > MAX_LASTFILE) + fst = procstat_getfiles(procstat, kp, &count); + if (fst == NULL) return; - nfiles = filed.fd_lastfile + 1; - ofiles = malloc(nfiles * sizeof(struct file *)); - if (ofiles == NULL) { - warn("malloc(%zd)", nfiles * sizeof(struct file *)); - return; - } - if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles, - (filed.fd_lastfile+1) * FPSIZE)) { - dprintf(stderr, - "can't read file structures at %p for pid %d\n", - (void *)filed.fd_ofiles, Pid); - free(ofiles); - return; - } - for (i = 0; i <= filed.fd_lastfile; i++) { - if (ofiles[i] == NULL) - continue; - if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file, - sizeof(struct file))) { - dprintf(stderr, "can't read file %d at %p for pid %d\n", - i, (void *)ofiles[i], Pid); - continue; - } - if (file.f_type == DTYPE_VNODE) - vtrans(file.f_vnode, i, file.f_flag); - else if (file.f_type == DTYPE_SOCKET) { - if (checkfile == 0) - socktrans(file.f_data, i); - } -#ifdef DTYPE_PIPE - else if (file.f_type == DTYPE_PIPE) { - if (checkfile == 0) - pipetrans(file.f_data, i, file.f_flag); - } -#endif -#ifdef DTYPE_FIFO - else if (file.f_type == DTYPE_FIFO) { - if (checkfile == 0) - vtrans(file.f_vnode, i, file.f_flag); - } -#endif -#ifdef DTYPE_PTS - else if (file.f_type == DTYPE_PTS) { - if (checkfile == 0) - ptstrans(file.f_data, i, file.f_flag); - } -#endif - else { - dprintf(stderr, - "unknown file type %d for file %d of pid %d\n", - file.f_type, i, Pid); - } - } - free(ofiles); + for (i = 0; i < count; i++) + print_file_info(procstat, &fst[i], uname, cmd, pid); } -/* - * print open files attributed to this process using kinfo - */ -void -dofiles_kinfo(struct kinfo_proc *kp) -{ - struct kinfo_file *kif, *freep; -#if 0 - struct kinfo_file kifb; -#endif - int i, cnt, fd_type, flags; - - Uname = user_from_uid(kp->ki_uid, 0); - Pid = kp->ki_pid; - Comm = kp->ki_comm; - - if (kp->ki_fd == NULL) - return; - -#if 0 - /* - * ktrace vnode, if one - */ - if (kp->ki_tracep) - vtrans_kin(kp->ki_tracep, TRACE, FREAD|FWRITE); - /* - * text vnode, if one - */ - vtrans(kp->ki_textvp, TEXT, FREAD); - /* Text vnode. */ - if (kp->ki_textvp) { - if (gettextvp(kp, &kifb) == 0) - vtrans_kinfo(&kifb, TEXT, FREAD); - } -#endif - - /* - * open files - */ - freep = kinfo_getfile(kp->ki_pid, &cnt); - if (freep == NULL) - err(1, "kinfo_getfile"); - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - switch (kif->kf_type) { - case KF_TYPE_VNODE: - if (kif->kf_fd == KF_FD_TYPE_CWD) { - fd_type = CDIR; - flags = FREAD; - } else if (kif->kf_fd == KF_FD_TYPE_ROOT) { - fd_type = RDIR; - flags = FREAD; - } else if (kif->kf_fd == KF_FD_TYPE_JAIL) { - fd_type = JDIR; - flags = FREAD; - } else { - fd_type = i; - flags = kif->kf_flags; - } - /* Only do this if the attributes are valid. */ - if (kif->kf_status & KF_ATTR_VALID) - vtrans_kinfo(kif, fd_type, flags); - break; -#if 0 - case KF_TYPE_PIPE: - if (checkfile == 0) - pipetrans_kinfo(kif, i, kif->kf_flags); - break; - else if (file.f_type == DTYPE_SOCKET) { - if (checkfile == 0) - socktrans(file.f_data, i); - } -#ifdef DTYPE_PIPE - else if (file.f_type == DTYPE_PIPE) { - if (checkfile == 0) - pipetrans(file.f_data, i, file.f_flag); - } -#endif -#ifdef DTYPE_FIFO - else if (file.f_type == DTYPE_FIFO) { - if (checkfile == 0) - vtrans(file.f_vnode, i, file.f_flag); - } -#endif -#ifdef DTYPE_PTS - else if (file.f_type == DTYPE_PTS) { - if (checkfile == 0) - ptstrans(file.f_data, i, file.f_flag); - } -#endif - else { - dprintf(stderr, - "unknown file type %d for file %d of pid %d\n", - file.f_type, i, Pid); - } -#endif - } - } - free(freep); -} -void -dommap(struct kinfo_proc *kp) +static void +print_file_info(struct procstat *procstat, struct filestat *fst, + const char *uname, const char *cmd, int pid) { - vm_map_t map; - struct vmspace vmspace; - struct vm_map_entry entry; - vm_map_entry_t entryp; - struct vm_object object; - vm_object_t objp; - int prot, fflags; - - if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace, - sizeof(vmspace))) { - dprintf(stderr, - "can't read vmspace at %p for pid %d\n", - (void *)kp->ki_vmspace, Pid); - return; - } - map = &vmspace.vm_map; - - for (entryp = map->header.next; - entryp != &kp->ki_vmspace->vm_map.header; entryp = entry.next) { - if (!kvm_read_all(kd, (unsigned long)entryp, &entry, - sizeof(entry))) { - dprintf(stderr, - "can't read vm_map_entry at %p for pid %d\n", - (void *)entryp, Pid); - return; - } - - if (entry.eflags & MAP_ENTRY_IS_SUB_MAP) - continue; + const char *badtype, *filename; - if ((objp = entry.object.vm_object) == NULL) - continue; + 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; - for (; objp; objp = object.backing_object) { - if (!kvm_read_all(kd, (unsigned long)objp, &object, - sizeof(object))) { - dprintf(stderr, - "can't read vm_object at %p for pid %d\n", - (void *)objp, Pid); + if (badtype) return; - } - } - - prot = entry.protection; - fflags = (prot & VM_PROT_READ ? FREAD : 0) | - (prot & VM_PROT_WRITE ? FWRITE : 0); - - switch (object.type) { - case OBJT_VNODE: - vtrans((struct vnode *)object.handle, MMAP, fflags); - break; - default: - break; - } - } -} - -void -vtrans(struct vnode *vp, int i, int flag) -{ - struct vnode vn; - struct filestat fst; - char rw[3], mode[15], tagstr[12], *tagptr; - const char *badtype, *filename; - - filename = badtype = NULL; - if (!kvm_read_all(kd, (unsigned long)vp, &vn, sizeof(struct vnode))) { - dprintf(stderr, "can't read vnode at %p for pid %d\n", - (void *)vp, Pid); - return; - } - if (!kvm_read_all(kd, (unsigned long)&vp->v_tag, &tagptr, - sizeof(tagptr)) || !kvm_read_all(kd, (unsigned long)tagptr, tagstr, - sizeof(tagstr))) { - dprintf(stderr, "can't read v_tag at %p for pid %d\n", - (void *)vp, Pid); - return; - } - tagstr[sizeof(tagstr) - 1] = '\0'; - if (vn.v_type == VNON) - badtype = "none"; - else if (vn.v_type == VBAD) - badtype = "bad"; - else { - if (!strcmp("ufs", tagstr)) { - if (!ufs_filestat(kd, &vn, &fst)) - badtype = "error"; - } else if (!strcmp("devfs", tagstr)) { - if (!devfs_filestat(kd, &vn, &fst)) - badtype = "error"; - } else if (!strcmp("nfs", tagstr)) { - if (!nfs_filestat(kd, &vn, &fst)) - badtype = "error"; - } else if (!strcmp("msdosfs", tagstr)) { - if (!msdosfs_filestat(kd, &vn, &fst)) - badtype = "error"; - } else if (!strcmp("isofs", tagstr)) { - if (!isofs_filestat(kd, &vn, &fst)) - badtype = "error"; -#ifdef ZFS - } else if (!strcmp("zfs", tagstr)) { - if (!zfs_filestat(kd, &vn, &fst)) - badtype = "error"; -#endif - } else { - static char unknown[32]; - snprintf(unknown, sizeof unknown, "?(%s)", tagstr); - badtype = unknown; - } - } - 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; + 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 (fsmatch == 0 || (filename == NULL && fsflg == 0)) - return; - } - PREFIX(i); - if (badtype) { - (void)printf(" - - %10s -\n", badtype); + if (fsmatch == 0 || (filename == NULL && fsflg == 0)) + return; + } + } else if (checkfile != 0) return; - } - if (nflg) - (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid)); - else - (void)printf(" %-8s", getmnton(vn.v_mount)); - if (nflg) - (void)sprintf(mode, "%o", fst.mode); - else - strmode(fst.mode, mode); - (void)printf(" %6ld %10s", fst.fileid, mode); - switch (vn.v_type) { - case VBLK: - case VCHR: { - char *name; - name = kdevtoname(kd, vn.v_rdev); - if (nflg || !name) - printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev)); - else { - printf(" %6s", name); - free(name); - } + /* + * Print entry prefix. + */ + printf("%-8.8s %-10s %5d", uname, cmd, pid); + switch(fst->fd) { + case PS_FST_FD_TEXT: + printf(" text"); break; - } - default: - printf(" %6lu", fst.size); - } - rw[0] = '\0'; - if (flag & FREAD) - strcat(rw, "r"); - if (flag & FWRITE) - strcat(rw, "w"); - printf(" %2s", rw); - if (filename && !fsflg) - printf(" %s", filename); - putchar('\n'); -} - -void -vtrans_kinfo(struct kinfo_file *kif, int i, int flag) -{ - struct filestat fst; - char rw[3], mode[15]; - const char *badtype, *filename; - struct statfs stbuf; - - filename = badtype = NULL; - fst.fsid = fst.fileid = fst.mode = fst.size = fst.rdev = 0; - bzero(&stbuf, sizeof(struct statfs)); - switch (kif->kf_vnode_type) { - case VNON: - badtype = "none"; + case PS_FST_FD_CDIR: + printf(" wd"); + break; + case PS_FST_FD_RDIR: + printf(" root"); + break; + case PS_FST_FD_TRACE: + printf(" tr"); + break; + case PS_FST_FD_MMAP: + printf(" mmap"); break; - case VBAD: - badtype = "bad"; + case PS_FST_FD_JAIL: + printf(" jail"); break; default: - fst.fsid = kif->kf_file_fsid; - fst.fileid = kif->kf_file_fileid; - fst.mode = kif->kf_file_mode; - fst.size = kif->kf_file_size; - fst.rdev = kif->kf_file_rdev; + printf(" %4d", fst->fd); break; } - 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 (fsmatch == 0 || (filename == NULL && fsflg == 0)) - return; - } - PREFIX(i); if (badtype) { (void)printf(" - - %10s -\n", badtype); return; } - if (nflg) - (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid)); - else { - if (strlen(kif->kf_path) > 0) - statfs(kif->kf_path, &stbuf); - (void)printf(" %-8s", stbuf.f_mntonname); - } - if (nflg) - (void)sprintf(mode, "%o", fst.mode); - else { - strmode(fst.mode, mode); - } - (void)printf(" %6ld %10s", fst.fileid, mode); - switch (kif->kf_vnode_type) { - case KF_VTYPE_VBLK: { - char *name; - name = devname(fst.rdev, S_IFBLK); - if (nflg || !name) - printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev)); - else { - printf(" %6s", name); - } + + /* + * Print type-specific data. + */ + switch (fst->type) { + case PS_FST_TYPE_FIFO: + case PS_FST_TYPE_VNODE: + print_vnode_info(procstat, fst); break; - } - case KF_VTYPE_VCHR: { - char *name; - name = devname(fst.rdev, S_IFCHR); - if (nflg || !name) - printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev)); - else { - printf(" %6s", name); - } + case PS_FST_TYPE_SOCKET: + print_socket_info(procstat, fst); break; + case PS_FST_TYPE_PIPE: + print_pipe_info(procstat, fst); + break; + case PS_FST_TYPE_PTS: + print_pts_info(procstat, fst); + break; + default: + dprintf(stderr, + "unknown file type %d for file %d of pid %d\n", + fst->type, fst->fd, pid); } - default: - printf(" %6lu", fst.size); - } - rw[0] = '\0'; - if (flag & FREAD) - strcat(rw, "r"); - if (flag & FWRITE) - strcat(rw, "w"); - printf(" %2s", rw); if (filename && !fsflg) printf(" %s", filename); putchar('\n'); } -char * -getmnton(struct mount *m) +static void +print_socket_info(struct procstat *procstat __unused, struct filestat *fst __unused) { - static struct mount mnt; - static struct mtab { - struct mtab *next; - struct mount *m; - char mntonname[MNAMELEN]; - } *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); - mt->next = mhead; - mhead = mt; - return (mt->mntonname); + + printf(" not implemented\n"); } -void -pipetrans(struct pipe *pi, int i, int flag) +static void +print_pipe_info(struct procstat *procstat __unused, struct filestat *fst __unused) { - struct pipe pip; - char rw[3]; - - PREFIX(i); - /* fill in socket */ - if (!kvm_read_all(kd, (unsigned long)pi, &pip, sizeof(struct pipe))) { - dprintf(stderr, "can't read pipe at %p\n", (void *)pi); - goto bad; - } - - printf("* pipe %8lx <-> %8lx", (u_long)pi, (u_long)pip.pipe_peer); - printf(" %6d", (int)pip.pipe_buffer.cnt); - rw[0] = '\0'; - if (flag & FREAD) - strcat(rw, "r"); - if (flag & FWRITE) - strcat(rw, "w"); - printf(" %2s", rw); - putchar('\n'); - return; - -bad: - printf("* error\n"); + printf(" not implemented\n"); } -void -socktrans(struct socket *sock, int i) +static void +print_pts_info(struct procstat *procstat __unused, struct filestat *fst __unused) { - 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]; - - PREFIX(i); - - /* fill in socket */ - if (!kvm_read_all(kd, (unsigned long)sock, &so, - sizeof(struct socket))) { - dprintf(stderr, "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'; - if ((u_short)so.so_type > STYPEMAX) - printf("* %s ?%d", dname, so.so_type); - else - printf("* %s %s", dname, stypename[so.so_type]); - - /* - * 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); - goto bad; - } - printf(" %lx", (u_long)inpcb.inp_ppcb); - } - } - else if (so.so_pcb) - printf(" %lx", (u_long)so.so_pcb); - break; - case AF_UNIX: - /* print address of pcb and connected pcb */ - if (so.so_pcb) { - printf(" %lx", (u_long)so.so_pcb); - if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, - sizeof(struct unpcb)) != sizeof(struct unpcb)){ - dprintf(stderr, "can't read unpcb at %p\n", - (void *)so.so_pcb); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***