fstat.c revision 181905
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1988, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3527272Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1988, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4127272Scharnier#if 0
4223693Speterstatic char sccsid[] = "@(#)fstat.c	8.3 (Berkeley) 5/2/95";
4327272Scharnier#endif
441590Srgrimes#endif /* not lint */
4599112Sobrien#include <sys/cdefs.h>
4699112Sobrien__FBSDID("$FreeBSD: head/usr.bin/fstat/fstat.c 181905 2008-08-20 08:31:58Z ed $");
471590Srgrimes
481590Srgrimes#include <sys/param.h>
491590Srgrimes#include <sys/time.h>
501590Srgrimes#include <sys/proc.h>
511590Srgrimes#include <sys/user.h>
521590Srgrimes#include <sys/stat.h>
531590Srgrimes#include <sys/vnode.h>
541590Srgrimes#include <sys/socket.h>
551590Srgrimes#include <sys/socketvar.h>
561590Srgrimes#include <sys/domain.h>
571590Srgrimes#include <sys/protosw.h>
5836110Smarkm#include <sys/un.h>
591590Srgrimes#include <sys/unpcb.h>
601590Srgrimes#include <sys/sysctl.h>
61181905Sed#include <sys/tty.h>
621590Srgrimes#include <sys/filedesc.h>
637726Sdg#include <sys/queue.h>
64179320Spjd#define	_WANT_FILE
65179320Spjd#include <sys/file.h>
66179759Sed#include <sys/conf.h>
67132477Ssilby#define	_KERNEL
6817808Speter#include <sys/pipe.h>
69101872Sbmilekic#include <sys/mount.h>
701590Srgrimes#include <ufs/ufs/quota.h>
711590Srgrimes#include <ufs/ufs/inode.h>
7288051Sgreen#include <fs/devfs/devfs.h>
73152105Scsjp#include <fs/devfs/devfs_int.h>
7455206Speter#undef _KERNEL
759336Sdfr#include <nfs/nfsproto.h>
761590Srgrimes#include <nfs/rpcv2.h>
7783653Speter#include <nfsclient/nfs.h>
7883653Speter#include <nfsclient/nfsnode.h>
791590Srgrimes
8058125Sgreen
8159029Sgreen#include <vm/vm.h>
8259029Sgreen#include <vm/vm_map.h>
8359029Sgreen#include <vm/vm_object.h>
8459029Sgreen
851590Srgrimes#include <net/route.h>
861590Srgrimes#include <netinet/in.h>
871590Srgrimes#include <netinet/in_systm.h>
881590Srgrimes#include <netinet/ip.h>
891590Srgrimes#include <netinet/in_pcb.h>
901590Srgrimes
911590Srgrimes#include <ctype.h>
9227272Scharnier#include <err.h>
9318570Sbde#include <fcntl.h>
941590Srgrimes#include <kvm.h>
9523693Speter#include <limits.h>
961590Srgrimes#include <nlist.h>
971590Srgrimes#include <paths.h>
981590Srgrimes#include <pwd.h>
991590Srgrimes#include <stdio.h>
1001590Srgrimes#include <stdlib.h>
101179828Skib#include <stddef.h>
1021590Srgrimes#include <string.h>
10323693Speter#include <unistd.h>
10448463Sru#include <netdb.h>
1051590Srgrimes
10658125Sgreen#include "fstat.h"
10758125Sgreen
1081590Srgrimes#define	TEXT	-1
1091590Srgrimes#define	CDIR	-2
1101590Srgrimes#define	RDIR	-3
1111590Srgrimes#define	TRACE	-4
11259029Sgreen#define	MMAP	-5
113140958Sphk#define	JDIR	-6
1141590Srgrimes
1151590SrgrimesDEVS *devs;
1161590Srgrimes
1171590Srgrimes#ifdef notdef
1181590Srgrimesstruct nlist nl[] = {
1191590Srgrimes	{ "" },
1201590Srgrimes};
1211590Srgrimes#endif
1221590Srgrimes
1231590Srgrimesint 	fsflg,	/* show files on same filesystem as file(s) argument */
1241590Srgrimes	pflg,	/* show files open by a particular pid */
1251590Srgrimes	uflg;	/* show files open by a particular (effective) user */
1261590Srgrimesint 	checkfile; /* true if restricting to particular files or filesystems */
1271590Srgrimesint	nflg;	/* (numerical) display f.s. and rdev as dev_t */
1281590Srgrimesint	vflg;	/* display errors in locating kernel data objects etc... */
12959029Sgreenint	mflg;	/* include memory-mapped files */
1301590Srgrimes
1311590Srgrimes
1321590Srgrimesstruct file **ofiles;	/* buffer of pointers to file structures */
1331590Srgrimesint maxfiles;
1341590Srgrimes#define ALLOC_OFILES(d)	\
1351590Srgrimes	if ((d) > maxfiles) { \
1361590Srgrimes		free(ofiles); \
1371590Srgrimes		ofiles = malloc((d) * sizeof(struct file *)); \
1381590Srgrimes		if (ofiles == NULL) { \
13927272Scharnier			err(1, NULL); \
1401590Srgrimes		} \
1411590Srgrimes		maxfiles = (d); \
1421590Srgrimes	}
1431590Srgrimes
14497946Sdeschar *memf, *nlistf;
1451590Srgrimeskvm_t *kd;
1461590Srgrimes
14797946Sdesstatic void fstat_kvm(int, int);
14897946Sdesstatic void fstat_sysctl(int, int);
14992920Simpvoid dofiles(struct kinfo_proc *kp);
15092920Simpvoid dommap(struct kinfo_proc *kp);
15192920Simpvoid vtrans(struct vnode *vp, int i, int flag);
15292920Simpint  ufs_filestat(struct vnode *vp, struct filestat *fsp);
15392920Simpint  nfs_filestat(struct vnode *vp, struct filestat *fsp);
15492920Simpint  devfs_filestat(struct vnode *vp, struct filestat *fsp);
15592920Simpchar *getmnton(struct mount *m);
15692920Simpvoid pipetrans(struct pipe *pi, int i, int flag);
15792920Simpvoid socktrans(struct socket *sock, int i);
158181905Sedvoid ptstrans(struct tty *tp, int i, int flag);
15992920Simpvoid getinetproto(int number);
16093427Sdwmaloneint  getfname(const char *filename);
16192920Simpvoid usage(void);
162148573Scsjpchar *kdevtoname(struct cdev *dev);
1631590Srgrimes
16417808Speterint
165131293Sdwmalonemain(int argc, char **argv)
1661590Srgrimes{
16793427Sdwmalone	struct passwd *passwd;
1681590Srgrimes	int arg, ch, what;
1691590Srgrimes
1701590Srgrimes	arg = 0;
171167367Semaste	what = KERN_PROC_PROC;
1721590Srgrimes	nlistf = memf = NULL;
17359029Sgreen	while ((ch = getopt(argc, argv, "fmnp:u:vN:M:")) != -1)
1741590Srgrimes		switch((char)ch) {
1751590Srgrimes		case 'f':
1761590Srgrimes			fsflg = 1;
1771590Srgrimes			break;
1781590Srgrimes		case 'M':
1791590Srgrimes			memf = optarg;
1801590Srgrimes			break;
1811590Srgrimes		case 'N':
1821590Srgrimes			nlistf = optarg;
1831590Srgrimes			break;
18459029Sgreen		case 'm':
18559029Sgreen			mflg = 1;
18659029Sgreen			break;
1871590Srgrimes		case 'n':
1881590Srgrimes			nflg = 1;
1891590Srgrimes			break;
1901590Srgrimes		case 'p':
1911590Srgrimes			if (pflg++)
1921590Srgrimes				usage();
1931590Srgrimes			if (!isdigit(*optarg)) {
19427311Scharnier				warnx("-p requires a process id");
1951590Srgrimes				usage();
1961590Srgrimes			}
1971590Srgrimes			what = KERN_PROC_PID;
1981590Srgrimes			arg = atoi(optarg);
1991590Srgrimes			break;
2001590Srgrimes		case 'u':
2011590Srgrimes			if (uflg++)
2021590Srgrimes				usage();
20327272Scharnier			if (!(passwd = getpwnam(optarg)))
20427272Scharnier				errx(1, "%s: unknown uid", optarg);
2051590Srgrimes			what = KERN_PROC_UID;
2061590Srgrimes			arg = passwd->pw_uid;
2071590Srgrimes			break;
2081590Srgrimes		case 'v':
2091590Srgrimes			vflg = 1;
2101590Srgrimes			break;
2111590Srgrimes		case '?':
2121590Srgrimes		default:
2131590Srgrimes			usage();
2141590Srgrimes		}
2151590Srgrimes
2161590Srgrimes	if (*(argv += optind)) {
2171590Srgrimes		for (; *argv; ++argv) {
2181590Srgrimes			if (getfname(*argv))
2191590Srgrimes				checkfile = 1;
2201590Srgrimes		}
2211590Srgrimes		if (!checkfile)	/* file(s) specified, but none accessable */
2221590Srgrimes			exit(1);
2231590Srgrimes	}
2241590Srgrimes
2258874Srgrimes	if (fsflg && !checkfile) {
2261590Srgrimes		/* -f with no files means use wd */
2271590Srgrimes		if (getfname(".") == 0)
2281590Srgrimes			exit(1);
2291590Srgrimes		checkfile = 1;
2301590Srgrimes	}
2311590Srgrimes
23297946Sdes	if (memf != NULL)
23397946Sdes		fstat_kvm(what, arg);
23497946Sdes	else
23597946Sdes		fstat_sysctl(what, arg);
23697946Sdes	exit(0);
23797946Sdes}
23897946Sdes
23997946Sdesstatic void
24097946Sdesprint_header(void)
24197946Sdes{
24297946Sdes
24397946Sdes	if (nflg)
24497946Sdes		printf("%s",
24597946Sdes"USER     CMD          PID   FD  DEV    INUM       MODE SZ|DV R/W");
24697946Sdes	else
24797946Sdes		printf("%s",
24897946Sdes"USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W");
24997946Sdes	if (checkfile && fsflg == 0)
25097946Sdes		printf(" NAME\n");
25197946Sdes	else
25297946Sdes		putchar('\n');
25397946Sdes}
25497946Sdes
25597946Sdesstatic void
25697946Sdesfstat_kvm(int what, int arg)
25797946Sdes{
25897946Sdes	struct kinfo_proc *p, *plast;
25997946Sdes	char buf[_POSIX2_LINE_MAX];
26097946Sdes	int cnt;
26197946Sdes
26297946Sdes	ALLOC_OFILES(256);	/* reserve space for file pointers */
26397946Sdes
2641590Srgrimes	/*
2651590Srgrimes	 * Discard setgid privileges if not the running kernel so that bad
2661590Srgrimes	 * guys can't print interesting stuff from kernel memory.
2671590Srgrimes	 */
2681590Srgrimes	if (nlistf != NULL || memf != NULL)
2691590Srgrimes		setgid(getgid());
2701590Srgrimes
27127272Scharnier	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL)
27227272Scharnier		errx(1, "%s", buf);
27382664Sru	setgid(getgid());
2741590Srgrimes#ifdef notdef
27527272Scharnier	if (kvm_nlist(kd, nl) != 0)
27627272Scharnier		errx(1, "no namelist: %s", kvm_geterr(kd));
2771590Srgrimes#endif
27827272Scharnier	if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL)
27927272Scharnier		errx(1, "%s", kvm_geterr(kd));
280116717Smaxim	print_header();
2811590Srgrimes	for (plast = &p[cnt]; p < plast; ++p) {
28269896Smckusick		if (p->ki_stat == SZOMB)
2831590Srgrimes			continue;
2841590Srgrimes		dofiles(p);
28559029Sgreen		if (mflg)
28659029Sgreen			dommap(p);
2871590Srgrimes	}
2881590Srgrimes}
2891590Srgrimes
29097946Sdesstatic void
29197946Sdesfstat_sysctl(int what, int arg)
29297946Sdes{
29397946Sdes
29497946Sdes	/* not yet implemented */
29597946Sdes	fstat_kvm(what, arg);
29697946Sdes}
29797946Sdes
29893427Sdwmaloneconst char	*Uname, *Comm;
2991590Srgrimesint	Pid;
3001590Srgrimes
3011590Srgrimes#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
3021590Srgrimes	switch(i) { \
3031590Srgrimes	case TEXT: \
3041590Srgrimes		printf(" text"); \
3051590Srgrimes		break; \
3061590Srgrimes	case CDIR: \
3071590Srgrimes		printf("   wd"); \
3081590Srgrimes		break; \
3091590Srgrimes	case RDIR: \
3101590Srgrimes		printf(" root"); \
3111590Srgrimes		break; \
3121590Srgrimes	case TRACE: \
3131590Srgrimes		printf("   tr"); \
3141590Srgrimes		break; \
31559029Sgreen	case MMAP: \
31659029Sgreen		printf(" mmap"); \
31759029Sgreen		break; \
318140958Sphk	case JDIR: \
319140958Sphk		printf(" jail"); \
320140958Sphk		break; \
3211590Srgrimes	default: \
3221590Srgrimes		printf(" %4d", i); \
3231590Srgrimes		break; \
3241590Srgrimes	}
3251590Srgrimes
3261590Srgrimes/*
3271590Srgrimes * print open files attributed to this process
3281590Srgrimes */
3291590Srgrimesvoid
330131293Sdwmalonedofiles(struct kinfo_proc *kp)
3311590Srgrimes{
33227272Scharnier	int i;
3331590Srgrimes	struct file file;
334137352Sphk	struct filedesc filed;
3351590Srgrimes
33669896Smckusick	Uname = user_from_uid(kp->ki_uid, 0);
33769896Smckusick	Pid = kp->ki_pid;
33869896Smckusick	Comm = kp->ki_comm;
3391590Srgrimes
34069896Smckusick	if (kp->ki_fd == NULL)
3411590Srgrimes		return;
342137352Sphk	if (!KVM_READ(kp->ki_fd, &filed, sizeof (filed))) {
34337453Sbde		dprintf(stderr, "can't read filedesc at %p for pid %d\n",
34469896Smckusick		    (void *)kp->ki_fd, Pid);
3451590Srgrimes		return;
3461590Srgrimes	}
3471590Srgrimes	/*
3481590Srgrimes	 * root directory vnode, if one
3491590Srgrimes	 */
3501590Srgrimes	if (filed.fd_rdir)
3511590Srgrimes		vtrans(filed.fd_rdir, RDIR, FREAD);
3521590Srgrimes	/*
3531590Srgrimes	 * current working directory vnode
3541590Srgrimes	 */
355178831Sjhb	if (filed.fd_cdir)
356178831Sjhb		vtrans(filed.fd_cdir, CDIR, FREAD);
3571590Srgrimes	/*
358140958Sphk	 * jail root, if any.
359140958Sphk	 */
360140958Sphk	if (filed.fd_jdir)
361140958Sphk		vtrans(filed.fd_jdir, JDIR, FREAD);
362140958Sphk	/*
3631590Srgrimes	 * ktrace vnode, if one
3641590Srgrimes	 */
36569896Smckusick	if (kp->ki_tracep)
36669896Smckusick		vtrans(kp->ki_tracep, TRACE, FREAD|FWRITE);
3671590Srgrimes	/*
36817813Speter	 * text vnode, if one
36917813Speter	 */
37069896Smckusick	if (kp->ki_textvp)
37169896Smckusick		vtrans(kp->ki_textvp, TEXT, FREAD);
37217813Speter	/*
3731590Srgrimes	 * open files
3741590Srgrimes	 */
3751590Srgrimes#define FPSIZE	(sizeof (struct file *))
376140958Sphk#define MAX_LASTFILE	(0x1000000)
377140958Sphk
378140958Sphk	/* Sanity check on filed.fd_lastfile */
379140958Sphk	if (filed.fd_lastfile <= -1 || filed.fd_lastfile > MAX_LASTFILE)
380140958Sphk		return;
381140958Sphk
3821590Srgrimes	ALLOC_OFILES(filed.fd_lastfile+1);
383137352Sphk	if (!KVM_READ(filed.fd_ofiles, ofiles,
384137352Sphk	    (filed.fd_lastfile+1) * FPSIZE)) {
385137352Sphk		dprintf(stderr,
386137352Sphk		    "can't read file structures at %p for pid %d\n",
387137352Sphk		    (void *)filed.fd_ofiles, Pid);
388137352Sphk		return;
389137352Sphk	}
3901590Srgrimes	for (i = 0; i <= filed.fd_lastfile; i++) {
3911590Srgrimes		if (ofiles[i] == NULL)
3921590Srgrimes			continue;
3931590Srgrimes		if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
39437453Sbde			dprintf(stderr, "can't read file %d at %p for pid %d\n",
39537453Sbde			    i, (void *)ofiles[i], Pid);
3961590Srgrimes			continue;
3971590Srgrimes		}
3981590Srgrimes		if (file.f_type == DTYPE_VNODE)
399140078Sssouhlal			vtrans(file.f_vnode, i, file.f_flag);
4001590Srgrimes		else if (file.f_type == DTYPE_SOCKET) {
4011590Srgrimes			if (checkfile == 0)
402109153Sdillon				socktrans(file.f_data, i);
4031590Srgrimes		}
40417808Speter#ifdef DTYPE_PIPE
40517808Speter		else if (file.f_type == DTYPE_PIPE) {
40617808Speter			if (checkfile == 0)
407109153Sdillon				pipetrans(file.f_data, i, file.f_flag);
40817808Speter		}
40917808Speter#endif
41078401Sroam#ifdef DTYPE_FIFO
41178401Sroam		else if (file.f_type == DTYPE_FIFO) {
41278401Sroam			if (checkfile == 0)
413140078Sssouhlal				vtrans(file.f_vnode, i, file.f_flag);
41478401Sroam		}
41578401Sroam#endif
416181905Sed#ifdef DTYPE_PTS
417181905Sed		else if (file.f_type == DTYPE_PTS) {
418181905Sed			if (checkfile == 0)
419181905Sed				ptstrans(file.f_data, i, file.f_flag);
420181905Sed		}
421181905Sed#endif
4221590Srgrimes		else {
4238874Srgrimes			dprintf(stderr,
42478401Sroam			    "unknown file type %d for file %d of pid %d\n",
42578401Sroam			    file.f_type, i, Pid);
4261590Srgrimes		}
4271590Srgrimes	}
4281590Srgrimes}
4291590Srgrimes
4301590Srgrimesvoid
431131293Sdwmalonedommap(struct kinfo_proc *kp)
43259029Sgreen{
43369896Smckusick	vm_map_t map;
43459029Sgreen	struct vmspace vmspace;
43559029Sgreen	struct vm_map_entry entry;
43659029Sgreen	vm_map_entry_t entryp;
43759029Sgreen	struct vm_object object;
43859029Sgreen	vm_object_t objp;
43959029Sgreen	int prot, fflags;
44059029Sgreen
44169896Smckusick	if (!KVM_READ(kp->ki_vmspace, &vmspace, sizeof(vmspace))) {
44269896Smckusick		dprintf(stderr,
44369896Smckusick		    "can't read vmspace at %p for pid %d\n",
44469896Smckusick		    (void *)kp->ki_vmspace, Pid);
44559029Sgreen		return;
44659029Sgreen	}
44759029Sgreen	map = &vmspace.vm_map;
44859029Sgreen
44972527Siedowse	for (entryp = map->header.next;
45072527Siedowse	    entryp != &kp->ki_vmspace->vm_map.header; entryp = entry.next) {
45159029Sgreen		if (!KVM_READ(entryp, &entry, sizeof(entry))) {
45259029Sgreen			dprintf(stderr,
45359029Sgreen			    "can't read vm_map_entry at %p for pid %d\n",
45459029Sgreen			    (void *)entryp, Pid);
45559029Sgreen			return;
45659029Sgreen		}
45759029Sgreen
45859029Sgreen		if (entry.eflags & MAP_ENTRY_IS_SUB_MAP)
45959029Sgreen			continue;
46059029Sgreen
46159029Sgreen		if ((objp = entry.object.vm_object) == NULL)
46259029Sgreen			continue;
46359029Sgreen
46459029Sgreen		for (; objp; objp = object.backing_object) {
46559029Sgreen			if (!KVM_READ(objp, &object, sizeof(object))) {
46659029Sgreen				dprintf(stderr,
46759029Sgreen				    "can't read vm_object at %p for pid %d\n",
46859029Sgreen				    (void *)objp, Pid);
46959029Sgreen				return;
47059029Sgreen			}
47159029Sgreen		}
47259029Sgreen
47359029Sgreen		prot = entry.protection;
47459029Sgreen		fflags = (prot & VM_PROT_READ ? FREAD : 0) |
47559029Sgreen		    (prot & VM_PROT_WRITE ? FWRITE : 0);
47659029Sgreen
47759029Sgreen		switch (object.type) {
47859029Sgreen		case OBJT_VNODE:
47959029Sgreen			vtrans((struct vnode *)object.handle, MMAP, fflags);
48059029Sgreen			break;
48159029Sgreen		default:
48259029Sgreen			break;
48359029Sgreen		}
48459029Sgreen	}
48559029Sgreen}
48659029Sgreen
487148573Scsjpchar *
488148573Scsjpkdevtoname(struct cdev *dev)
489148573Scsjp{
490148573Scsjp	struct cdev si;
491148573Scsjp
492148573Scsjp	if (!KVM_READ(dev, &si, sizeof si))
493148573Scsjp		return (NULL);
494148573Scsjp	return (strdup(si.__si_namebuf));
495148573Scsjp}
496148573Scsjp
49759029Sgreenvoid
498131293Sdwmalonevtrans(struct vnode *vp, int i, int flag)
4991590Srgrimes{
5001590Srgrimes	struct vnode vn;
5011590Srgrimes	struct filestat fst;
502103325Snjl	char rw[3], mode[15], tagstr[12], *tagptr;
50393427Sdwmalone	const char *badtype, *filename;
5041590Srgrimes
5051590Srgrimes	filename = badtype = NULL;
5061590Srgrimes	if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
50737453Sbde		dprintf(stderr, "can't read vnode at %p for pid %d\n",
50837453Sbde		    (void *)vp, Pid);
5091590Srgrimes		return;
5101590Srgrimes	}
511103325Snjl	if (!KVM_READ(&vp->v_tag, &tagptr, sizeof tagptr) ||
512103325Snjl	    !KVM_READ(tagptr, tagstr, sizeof tagstr)) {
513103325Snjl		dprintf(stderr, "can't read v_tag at %p for pid %d\n",
514103325Snjl		    (void *)vp, Pid);
515103325Snjl		return;
516103325Snjl	}
517103325Snjl	tagstr[sizeof(tagstr) - 1] = '\0';
518103325Snjl	if (vn.v_type == VNON)
5191590Srgrimes		badtype = "none";
5201590Srgrimes	else if (vn.v_type == VBAD)
5211590Srgrimes		badtype = "bad";
522103325Snjl	else {
523103325Snjl		if (!strcmp("ufs", tagstr)) {
5241590Srgrimes			if (!ufs_filestat(&vn, &fst))
5251590Srgrimes				badtype = "error";
526103325Snjl		} else if (!strcmp("devfs", tagstr)) {
52788051Sgreen			if (!devfs_filestat(&vn, &fst))
52888051Sgreen				badtype = "error";
529103325Snjl		} else if (!strcmp("nfs", tagstr)) {
5301590Srgrimes			if (!nfs_filestat(&vn, &fst))
5311590Srgrimes				badtype = "error";
532103325Snjl		} else if (!strcmp("msdosfs", tagstr)) {
53358125Sgreen			if (!msdosfs_filestat(&vn, &fst))
53458125Sgreen				badtype = "error";
535103325Snjl		} else if (!strcmp("isofs", tagstr)) {
53658125Sgreen			if (!isofs_filestat(&vn, &fst))
53758125Sgreen				badtype = "error";
538173376Slulf#ifdef ZFS
539173376Slulf		} else if (!strcmp("zfs", tagstr)) {
540173376Slulf			if (!zfs_filestat(&vn, &fst))
541173376Slulf				badtype = "error";
542173376Slulf#endif
543103325Snjl		} else {
544103325Snjl			static char unknown[32];
545103325Snjl			snprintf(unknown, sizeof unknown, "?(%s)", tagstr);
54693427Sdwmalone			badtype = unknown;
5471590Srgrimes		}
5481590Srgrimes	}
5491590Srgrimes	if (checkfile) {
5501590Srgrimes		int fsmatch = 0;
55193427Sdwmalone		DEVS *d;
5521590Srgrimes
5531590Srgrimes		if (badtype)
5541590Srgrimes			return;
5551590Srgrimes		for (d = devs; d != NULL; d = d->next)
5561590Srgrimes			if (d->fsid == fst.fsid) {
5571590Srgrimes				fsmatch = 1;
5581590Srgrimes				if (d->ino == fst.fileid) {
5591590Srgrimes					filename = d->name;
5601590Srgrimes					break;
5611590Srgrimes				}
5621590Srgrimes			}
5631590Srgrimes		if (fsmatch == 0 || (filename == NULL && fsflg == 0))
5641590Srgrimes			return;
5651590Srgrimes	}
5661590Srgrimes	PREFIX(i);
5671590Srgrimes	if (badtype) {
5681590Srgrimes		(void)printf(" -         -  %10s    -\n", badtype);
5691590Srgrimes		return;
5701590Srgrimes	}
5711590Srgrimes	if (nflg)
5721590Srgrimes		(void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
5731590Srgrimes	else
5741590Srgrimes		(void)printf(" %-8s", getmnton(vn.v_mount));
5751590Srgrimes	if (nflg)
5761590Srgrimes		(void)sprintf(mode, "%o", fst.mode);
5771590Srgrimes	else
5781590Srgrimes		strmode(fst.mode, mode);
57937453Sbde	(void)printf(" %6ld %10s", fst.fileid, mode);
5801590Srgrimes	switch (vn.v_type) {
5811590Srgrimes	case VBLK:
5821590Srgrimes	case VCHR: {
5831590Srgrimes		char *name;
5841590Srgrimes
585148573Scsjp		name = kdevtoname(vn.v_rdev);
586148573Scsjp		if (nflg || !name)
5871590Srgrimes			printf("  %2d,%-2d", major(fst.rdev), minor(fst.rdev));
588148573Scsjp		else {
5891590Srgrimes			printf(" %6s", name);
590148573Scsjp			free(name);
591148573Scsjp		}
5921590Srgrimes		break;
5931590Srgrimes	}
5941590Srgrimes	default:
59528948Salex		printf(" %6lu", fst.size);
5961590Srgrimes	}
5971590Srgrimes	rw[0] = '\0';
5981590Srgrimes	if (flag & FREAD)
5991590Srgrimes		strcat(rw, "r");
6001590Srgrimes	if (flag & FWRITE)
6011590Srgrimes		strcat(rw, "w");
6021590Srgrimes	printf(" %2s", rw);
6031590Srgrimes	if (filename && !fsflg)
6041590Srgrimes		printf("  %s", filename);
6051590Srgrimes	putchar('\n');
6061590Srgrimes}
6071590Srgrimes
6081590Srgrimesint
609131293Sdwmaloneufs_filestat(struct vnode *vp, struct filestat *fsp)
6101590Srgrimes{
6111590Srgrimes	struct inode inode;
6121590Srgrimes
6131590Srgrimes	if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
61437453Sbde		dprintf(stderr, "can't read inode at %p for pid %d\n",
61537453Sbde		    (void *)VTOI(vp), Pid);
6161590Srgrimes		return 0;
6171590Srgrimes	}
61853133Sgreen	/*
619130640Sphk	 * The st_dev from stat(2) is a dev_t. These kernel structures
620130640Sphk	 * contain cdev pointers. We need to convert to dev_t to make
62153133Sgreen	 * comparisons
62253133Sgreen	 */
62386100Sdwmalone	fsp->fsid = dev2udev(inode.i_dev);
6241590Srgrimes	fsp->fileid = (long)inode.i_number;
6251590Srgrimes	fsp->mode = (mode_t)inode.i_mode;
6261590Srgrimes	fsp->size = (u_long)inode.i_size;
62798542Smckusick#if should_be_but_is_hard
628116780Sjmg	/* XXX - need to load i_ump and i_din[12] from kernel memory */
629116780Sjmg	if (inode.i_ump->um_fstype == UFS1)
630116780Sjmg		fsp->rdev = inode.i_din1->di_rdev;
631116780Sjmg	else
632116780Sjmg		fsp->rdev = inode.i_din2->di_rdev;
63398542Smckusick#else
63498542Smckusick	fsp->rdev = 0;
63598542Smckusick#endif
6361590Srgrimes
6371590Srgrimes	return 1;
6381590Srgrimes}
6391590Srgrimes
6401590Srgrimesint
641131293Sdwmalonedevfs_filestat(struct vnode *vp, struct filestat *fsp)
64288051Sgreen{
64388051Sgreen	struct devfs_dirent devfs_dirent;
64488051Sgreen	struct mount mount;
64588051Sgreen	struct vnode vnode;
64688051Sgreen
64788051Sgreen	if (!KVM_READ(vp->v_data, &devfs_dirent, sizeof (devfs_dirent))) {
64888051Sgreen		dprintf(stderr, "can't read devfs_dirent at %p for pid %d\n",
64988051Sgreen		    (void *)vp->v_data, Pid);
65088051Sgreen		return 0;
65188051Sgreen	}
65288051Sgreen	if (!KVM_READ(vp->v_mount, &mount, sizeof (mount))) {
65388051Sgreen		dprintf(stderr, "can't read mount at %p for pid %d\n",
65488051Sgreen		    (void *)vp->v_mount, Pid);
65588051Sgreen		return 0;
65688051Sgreen	}
65788051Sgreen	if (!KVM_READ(devfs_dirent.de_vnode, &vnode, sizeof (vnode))) {
65888051Sgreen		dprintf(stderr, "can't read vnode at %p for pid %d\n",
65988051Sgreen		    (void *)devfs_dirent.de_vnode, Pid);
66088051Sgreen		return 0;
66188051Sgreen	}
66288051Sgreen	fsp->fsid = (long)mount.mnt_stat.f_fsid.val[0];
66388051Sgreen	fsp->fileid = devfs_dirent.de_inode;
66488051Sgreen	fsp->mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
66588051Sgreen	fsp->size = 0;
666116556Sjmg	fsp->rdev = dev2udev(vnode.v_rdev);
66788051Sgreen
66888051Sgreen	return 1;
66988051Sgreen}
67088051Sgreen
67188051Sgreenint
672131293Sdwmalonenfs_filestat(struct vnode *vp, struct filestat *fsp)
6731590Srgrimes{
6741590Srgrimes	struct nfsnode nfsnode;
67593427Sdwmalone	mode_t mode;
6761590Srgrimes
6771590Srgrimes	if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
67837453Sbde		dprintf(stderr, "can't read nfsnode at %p for pid %d\n",
67937453Sbde		    (void *)VTONFS(vp), Pid);
6801590Srgrimes		return 0;
6811590Srgrimes	}
6821590Srgrimes	fsp->fsid = nfsnode.n_vattr.va_fsid;
6831590Srgrimes	fsp->fileid = nfsnode.n_vattr.va_fileid;
6841590Srgrimes	fsp->size = nfsnode.n_size;
6851590Srgrimes	fsp->rdev = nfsnode.n_vattr.va_rdev;
6861590Srgrimes	mode = (mode_t)nfsnode.n_vattr.va_mode;
6871590Srgrimes	switch (vp->v_type) {
6881590Srgrimes	case VREG:
6891590Srgrimes		mode |= S_IFREG;
6901590Srgrimes		break;
6911590Srgrimes	case VDIR:
6921590Srgrimes		mode |= S_IFDIR;
6931590Srgrimes		break;
6941590Srgrimes	case VBLK:
6951590Srgrimes		mode |= S_IFBLK;
6961590Srgrimes		break;
6971590Srgrimes	case VCHR:
6981590Srgrimes		mode |= S_IFCHR;
6991590Srgrimes		break;
7001590Srgrimes	case VLNK:
7011590Srgrimes		mode |= S_IFLNK;
7021590Srgrimes		break;
7031590Srgrimes	case VSOCK:
7041590Srgrimes		mode |= S_IFSOCK;
7051590Srgrimes		break;
7061590Srgrimes	case VFIFO:
7071590Srgrimes		mode |= S_IFIFO;
7081590Srgrimes		break;
70948463Sru	case VNON:
71048463Sru	case VBAD:
711154152Stegge	case VMARKER:
71248463Sru		return 0;
7131590Srgrimes	};
7141590Srgrimes	fsp->mode = mode;
7151590Srgrimes
7161590Srgrimes	return 1;
7171590Srgrimes}
7181590Srgrimes
7191590Srgrimes
7201590Srgrimeschar *
721131293Sdwmalonegetmnton(struct mount *m)
7221590Srgrimes{
7231590Srgrimes	static struct mount mount;
7241590Srgrimes	static struct mtab {
7251590Srgrimes		struct mtab *next;
7261590Srgrimes		struct mount *m;
7271590Srgrimes		char mntonname[MNAMELEN];
7281590Srgrimes	} *mhead = NULL;
72993427Sdwmalone	struct mtab *mt;
7301590Srgrimes
7311590Srgrimes	for (mt = mhead; mt != NULL; mt = mt->next)
7321590Srgrimes		if (m == mt->m)
7331590Srgrimes			return (mt->mntonname);
7341590Srgrimes	if (!KVM_READ(m, &mount, sizeof(struct mount))) {
73537453Sbde		warnx("can't read mount table at %p", (void *)m);
7361590Srgrimes		return (NULL);
7371590Srgrimes	}
73827272Scharnier	if ((mt = malloc(sizeof (struct mtab))) == NULL)
73927272Scharnier		err(1, NULL);
7401590Srgrimes	mt->m = m;
7411590Srgrimes	bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
7421590Srgrimes	mt->next = mhead;
7431590Srgrimes	mhead = mt;
7441590Srgrimes	return (mt->mntonname);
7451590Srgrimes}
7461590Srgrimes
7471590Srgrimesvoid
748131293Sdwmalonepipetrans(struct pipe *pi, int i, int flag)
74917808Speter{
75017808Speter	struct pipe pip;
75117808Speter	char rw[3];
75217808Speter
75317808Speter	PREFIX(i);
75417808Speter
75517808Speter	/* fill in socket */
75617808Speter	if (!KVM_READ(pi, &pip, sizeof(struct pipe))) {
75737453Sbde		dprintf(stderr, "can't read pipe at %p\n", (void *)pi);
75817808Speter		goto bad;
75917808Speter	}
76017808Speter
76180355Smjacob	printf("* pipe %8lx <-> %8lx", (u_long)pi, (u_long)pip.pipe_peer);
76217808Speter	printf(" %6d", (int)pip.pipe_buffer.cnt);
76317808Speter	rw[0] = '\0';
76417808Speter	if (flag & FREAD)
76517808Speter		strcat(rw, "r");
76617808Speter	if (flag & FWRITE)
76717808Speter		strcat(rw, "w");
76817808Speter	printf(" %2s", rw);
76917808Speter	putchar('\n');
77017808Speter	return;
77117808Speter
77217808Speterbad:
77317808Speter	printf("* error\n");
77417808Speter}
77517808Speter
77617808Spetervoid
777131293Sdwmalonesocktrans(struct socket *sock, int i)
7781590Srgrimes{
77993427Sdwmalone	static const char *stypename[] = {
7801590Srgrimes		"unused",	/* 0 */
7811590Srgrimes		"stream", 	/* 1 */
7821590Srgrimes		"dgram",	/* 2 */
7831590Srgrimes		"raw",		/* 3 */
7841590Srgrimes		"rdm",		/* 4 */
7851590Srgrimes		"seqpak"	/* 5 */
7861590Srgrimes	};
7871590Srgrimes#define	STYPEMAX 5
7881590Srgrimes	struct socket	so;
7891590Srgrimes	struct protosw	proto;
7901590Srgrimes	struct domain	dom;
7911590Srgrimes	struct inpcb	inpcb;
7921590Srgrimes	struct unpcb	unpcb;
7931590Srgrimes	int len;
79493427Sdwmalone	char dname[32];
7951590Srgrimes
7961590Srgrimes	PREFIX(i);
7971590Srgrimes
7981590Srgrimes	/* fill in socket */
7991590Srgrimes	if (!KVM_READ(sock, &so, sizeof(struct socket))) {
80037453Sbde		dprintf(stderr, "can't read sock at %p\n", (void *)sock);
8011590Srgrimes		goto bad;
8021590Srgrimes	}
8031590Srgrimes
8041590Srgrimes	/* fill in protosw entry */
8051590Srgrimes	if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
80637453Sbde		dprintf(stderr, "can't read protosw at %p",
80737453Sbde		    (void *)so.so_proto);
8081590Srgrimes		goto bad;
8091590Srgrimes	}
8101590Srgrimes
8111590Srgrimes	/* fill in domain */
8121590Srgrimes	if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
81337453Sbde		dprintf(stderr, "can't read domain at %p\n",
81437453Sbde		    (void *)proto.pr_domain);
8151590Srgrimes		goto bad;
8161590Srgrimes	}
8171590Srgrimes
8181590Srgrimes	if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
8191590Srgrimes	    sizeof(dname) - 1)) < 0) {
82037453Sbde		dprintf(stderr, "can't read domain name at %p\n",
82137453Sbde		    (void *)dom.dom_name);
8221590Srgrimes		dname[0] = '\0';
8231590Srgrimes	}
8241590Srgrimes	else
8251590Srgrimes		dname[len] = '\0';
8261590Srgrimes
8271590Srgrimes	if ((u_short)so.so_type > STYPEMAX)
8281590Srgrimes		printf("* %s ?%d", dname, so.so_type);
8291590Srgrimes	else
8301590Srgrimes		printf("* %s %s", dname, stypename[so.so_type]);
8311590Srgrimes
8328874Srgrimes	/*
8331590Srgrimes	 * protocol specific formatting
8341590Srgrimes	 *
8351590Srgrimes	 * Try to find interesting things to print.  For tcp, the interesting
8361590Srgrimes	 * thing is the address of the tcpcb, for udp and others, just the
8371590Srgrimes	 * inpcb (socket pcb).  For unix domain, its the address of the socket
8381590Srgrimes	 * pcb and the address of the connected pcb (if connected).  Otherwise
8391590Srgrimes	 * just print the protocol number and address of the socket itself.
8401590Srgrimes	 * The idea is not to duplicate netstat, but to make available enough
8411590Srgrimes	 * information for further analysis.
8421590Srgrimes	 */
8431590Srgrimes	switch(dom.dom_family) {
8441590Srgrimes	case AF_INET:
84557345Sshin	case AF_INET6:
8461590Srgrimes		getinetproto(proto.pr_protocol);
8471590Srgrimes		if (proto.pr_protocol == IPPROTO_TCP ) {
8481590Srgrimes			if (so.so_pcb) {
8491590Srgrimes				if (kvm_read(kd, (u_long)so.so_pcb,
8501590Srgrimes				    (char *)&inpcb, sizeof(struct inpcb))
8511590Srgrimes				    != sizeof(struct inpcb)) {
8528874Srgrimes					dprintf(stderr,
85337453Sbde					    "can't read inpcb at %p\n",
85437453Sbde					    (void *)so.so_pcb);
8551590Srgrimes					goto bad;
8561590Srgrimes				}
85780355Smjacob				printf(" %lx", (u_long)inpcb.inp_ppcb);
8581590Srgrimes			}
8591590Srgrimes		}
8601590Srgrimes		else if (so.so_pcb)
86180355Smjacob			printf(" %lx", (u_long)so.so_pcb);
8621590Srgrimes		break;
8631590Srgrimes	case AF_UNIX:
8641590Srgrimes		/* print address of pcb and connected pcb */
8651590Srgrimes		if (so.so_pcb) {
86680355Smjacob			printf(" %lx", (u_long)so.so_pcb);
8671590Srgrimes			if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
8681590Srgrimes			    sizeof(struct unpcb)) != sizeof(struct unpcb)){
86937453Sbde				dprintf(stderr, "can't read unpcb at %p\n",
87037453Sbde				    (void *)so.so_pcb);
8711590Srgrimes				goto bad;
8721590Srgrimes			}
8731590Srgrimes			if (unpcb.unp_conn) {
8741590Srgrimes				char shoconn[4], *cp;
8751590Srgrimes
8761590Srgrimes				cp = shoconn;
877130489Srwatson				if (!(so.so_rcv.sb_state & SBS_CANTRCVMORE))
8781590Srgrimes					*cp++ = '<';
8791590Srgrimes				*cp++ = '-';
880130489Srwatson				if (!(so.so_snd.sb_state & SBS_CANTSENDMORE))
8811590Srgrimes					*cp++ = '>';
8821590Srgrimes				*cp = '\0';
88380355Smjacob				printf(" %s %lx", shoconn,
88480355Smjacob				    (u_long)unpcb.unp_conn);
8851590Srgrimes			}
8861590Srgrimes		}
8871590Srgrimes		break;
8881590Srgrimes	default:
8891590Srgrimes		/* print protocol number and socket address */
89080355Smjacob		printf(" %d %lx", proto.pr_protocol, (u_long)sock);
8911590Srgrimes	}
8921590Srgrimes	printf("\n");
8931590Srgrimes	return;
8941590Srgrimesbad:
8951590Srgrimes	printf("* error\n");
8961590Srgrimes}
8971590Srgrimes
898181905Sedvoid
899181905Sedptstrans(struct tty *tp, int i, int flag)
900181905Sed{
901181905Sed	struct tty tty;
902181905Sed	char *name;
903181905Sed	char rw[3];
904181905Sed	dev_t rdev;
90553133Sgreen
906181905Sed	PREFIX(i);
907181905Sed
908181905Sed	/* Obtain struct tty. */
909181905Sed	if (!KVM_READ(tp, &tty, sizeof(struct tty))) {
910181905Sed		dprintf(stderr, "can't read tty at %p\n", (void *)tp);
911181905Sed		goto bad;
912181905Sed	}
913181905Sed
914181905Sed	/* Figure out the device name. */
915181905Sed	name = kdevtoname(tty.t_dev);
916181905Sed	if (name == NULL) {
917181905Sed		dprintf(stderr, "can't determine tty name at %p\n", (void *)tp);
918181905Sed		goto bad;
919181905Sed	}
920181905Sed
921181905Sed	rw[0] = '\0';
922181905Sed	if (flag & FREAD)
923181905Sed		strcat(rw, "r");
924181905Sed	if (flag & FWRITE)
925181905Sed		strcat(rw, "w");
926181905Sed
927181905Sed	printf("* pseudo-terminal master ");
928181905Sed	if (nflg || !name) {
929181905Sed		rdev = dev2udev(tty.t_dev);
930181905Sed		printf("%10d,%-2d", major(rdev), minor(rdev));
931181905Sed	} else {
932181905Sed		printf("%10s", name);
933181905Sed	}
934181905Sed	printf(" %2s\n", rw);
935181905Sed
936181905Sed	free(name);
937181905Sed
938181905Sed	return;
939181905Sedbad:
940181905Sed	printf("* error\n");
941181905Sed}
942181905Sed
9431590Srgrimes/*
944130640Sphk * Read the cdev structure in the kernel in order to work out the
945130640Sphk * associated dev_t
94653133Sgreen */
947130640Sphkdev_t
948131293Sdwmalonedev2udev(struct cdev *dev)
94953133Sgreen{
950152105Scsjp	struct cdev_priv priv;
95153133Sgreen
952179828Skib	if (KVM_READ(cdev2priv(dev), &priv, sizeof priv)) {
953152105Scsjp		return ((dev_t)priv.cdp_inode);
95453133Sgreen	} else {
955131293Sdwmalone		dprintf(stderr, "can't convert cdev *%p to a dev_t\n", dev);
95653133Sgreen		return -1;
95753133Sgreen	}
95853133Sgreen}
95953133Sgreen
96053133Sgreen/*
9611590Srgrimes * getinetproto --
9621590Srgrimes *	print name of protocol number
9631590Srgrimes */
9641590Srgrimesvoid
965131293Sdwmalonegetinetproto(int number)
9661590Srgrimes{
96748463Sru	static int isopen;
96893427Sdwmalone	struct protoent *pe;
9691590Srgrimes
97048463Sru	if (!isopen)
97148463Sru		setprotoent(++isopen);
97248463Sru	if ((pe = getprotobynumber(number)) != NULL)
97348463Sru		printf(" %s", pe->p_name);
97448463Sru	else
9751590Srgrimes		printf(" %d", number);
9761590Srgrimes}
9771590Srgrimes
97817808Speterint
979131293Sdwmalonegetfname(const char *filename)
9801590Srgrimes{
9811590Srgrimes	struct stat statbuf;
9821590Srgrimes	DEVS *cur;
9831590Srgrimes
9841590Srgrimes	if (stat(filename, &statbuf)) {
98527272Scharnier		warn("%s", filename);
9861590Srgrimes		return(0);
9871590Srgrimes	}
98827272Scharnier	if ((cur = malloc(sizeof(DEVS))) == NULL)
98927272Scharnier		err(1, NULL);
9901590Srgrimes	cur->next = devs;
9911590Srgrimes	devs = cur;
9921590Srgrimes
9931590Srgrimes	cur->ino = statbuf.st_ino;
99486100Sdwmalone	cur->fsid = statbuf.st_dev;
9951590Srgrimes	cur->name = filename;
9961590Srgrimes	return(1);
9971590Srgrimes}
9981590Srgrimes
999173376Slulf#ifdef ZFS
1000173376Slulfvoid *
1001173376Slulfgetvnodedata(struct vnode *vp)
1002173376Slulf{
1003173376Slulf	return (vp->v_data);
1004173376Slulf}
1005173376Slulf
1006173376Slulfstruct mount *
1007173376Slulfgetvnodemount(struct vnode *vp)
1008173376Slulf{
1009173376Slulf	return (vp->v_mount);
1010173376Slulf}
1011173376Slulf#endif
1012173376Slulf
10131590Srgrimesvoid
1014131293Sdwmaloneusage(void)
10151590Srgrimes{
10161590Srgrimes	(void)fprintf(stderr,
1017146466Sru "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [file ...]\n");
10181590Srgrimes	exit(1);
10191590Srgrimes}
1020