summaryrefslogtreecommitdiffstats
path: root/usr.bin/fstat
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/fstat')
-rw-r--r--usr.bin/fstat/Makefile20
-rw-r--r--usr.bin/fstat/cd9660.c79
-rw-r--r--usr.bin/fstat/fstat.c986
-rw-r--r--usr.bin/fstat/functions.h (renamed from usr.bin/fstat/fstat.h)56
-rw-r--r--usr.bin/fstat/fuser.1148
-rw-r--r--usr.bin/fstat/fuser.c369
-rw-r--r--usr.bin/fstat/main.c49
-rw-r--r--usr.bin/fstat/msdosfs.c150
-rw-r--r--usr.bin/fstat/zfs.c136
-rw-r--r--usr.bin/fstat/zfs/Makefile23
10 files changed, 817 insertions, 1199 deletions
diff --git a/usr.bin/fstat/Makefile b/usr.bin/fstat/Makefile
index 23e907b..c59e123 100644
--- a/usr.bin/fstat/Makefile
+++ b/usr.bin/fstat/Makefile
@@ -1,24 +1,12 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
-.include <bsd.own.mk>
-
PROG= fstat
-SRCS= cd9660.c fstat.c msdosfs.c
+SRCS= fstat.c fuser.c main.c
+LINKS= ${BINDIR}/fstat ${BINDIR}/fuser
DPADD= ${LIBKVM}
-LDADD= -lkvm
-BINGRP= kmem
-BINMODE=2555
-
-CFLAGS+=-D_KVM_VNODE
+LDADD= -lkvm -lutil -lprocstat
-# XXX This is a hack.
-.if ${MK_CDDL} != "no"
-CFLAGS+= -DZFS
-OBJS+= zfs/zfs.o
-SUBDIR= zfs
-zfs/zfs.o: .PHONY
- @cd ${.CURDIR}/zfs && ${MAKE} zfs.o
-.endif
+MAN1= fuser.1 fstat.1
.include <bsd.prog.mk>
diff --git a/usr.bin/fstat/cd9660.c b/usr.bin/fstat/cd9660.c
deleted file mode 100644
index 1c26e8d..0000000
--- a/usr.bin/fstat/cd9660.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2000 Peter Edwards
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by Peter Edwards
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXX -
- * This had to be separated from fstat.c because cd9660s has namespace
- * conflicts with UFS.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/vnode.h>
-#include <sys/mount.h>
-
-#include <isofs/cd9660/cd9660_node.h>
-
-#include <kvm.h>
-#include <stdio.h>
-
-#include "fstat.h"
-
-int
-isofs_filestat(struct vnode *vp, struct filestat *fsp)
-{
- struct iso_node isonode;
-
- if (!KVM_READ(VTOI(vp), &isonode, sizeof (isonode))) {
- dprintf(stderr, "can't read iso_node at %p for pid %d\n",
- (void *)VTOI(vp), Pid);
- return 0;
- }
-#if 0
- fsp->fsid = dev2udev(isonode.i_dev);
-#endif
- 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;
-}
-
diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c
index 7725c88..9d057e5 100644
--- a/usr.bin/fstat/fstat.c
+++ b/usr.bin/fstat/fstat.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -27,69 +28,24 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95";
-#endif
-#endif /* not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/proc.h>
#include <sys/user.h>
#include <sys/stat.h>
-#include <sys/vnode.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/un.h>
-#include <sys/unpcb.h>
#include <sys/sysctl.h>
-#include <sys/tty.h>
-#include <sys/filedesc.h>
#include <sys/queue.h>
-#define _WANT_FILE
-#include <sys/file.h>
-#include <sys/conf.h>
-#define _KERNEL
-#include <sys/pipe.h>
-#include <sys/mount.h>
-#include <ufs/ufs/quota.h>
-#include <ufs/ufs/inode.h>
-#include <fs/devfs/devfs.h>
-#include <fs/devfs/devfs_int.h>
-#undef _KERNEL
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfsclient/nfsnode.h>
-
-
-#include <vm/vm.h>
-#include <vm/vm_map.h>
-#include <vm/vm_object.h>
-
-#include <net/route.h>
+
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
-#include <fcntl.h>
-#include <kvm.h>
+#include <libprocstat.h>
#include <limits.h>
-#include <nlist.h>
-#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@@ -98,69 +54,49 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <netdb.h>
-#include "fstat.h"
-
-#define TEXT -1
-#define CDIR -2
-#define RDIR -3
-#define TRACE -4
-#define MMAP -5
-#define JDIR -6
-
-DEVS *devs;
-
-#ifdef notdef
-struct nlist nl[] = {
- { "" },
-};
-#endif
+#include "functions.h"
int fsflg, /* show files on same filesystem as file(s) argument */
pflg, /* show files open by a particular pid */
uflg; /* show files open by a particular (effective) user */
int checkfile; /* true if restricting to particular files or filesystems */
int nflg; /* (numerical) display f.s. and rdev as dev_t */
-int vflg; /* display errors in locating kernel data objects etc... */
int mflg; /* include memory-mapped files */
+int vflg; /* be verbose */
+typedef struct devs {
+ struct devs *next;
+ uint32_t fsid;
+ uint64_t ino;
+ const char *name;
+} DEVS;
-struct file **ofiles; /* buffer of pointers to file structures */
-int maxfiles;
-#define ALLOC_OFILES(d) \
- if ((d) > maxfiles) { \
- free(ofiles); \
- ofiles = malloc((d) * sizeof(struct file *)); \
- if (ofiles == NULL) { \
- err(1, NULL); \
- } \
- maxfiles = (d); \
- }
-
+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);
-void dommap(struct kinfo_proc *kp);
-void vtrans(struct vnode *vp, int i, int flag);
-int ufs_filestat(struct vnode *vp, struct filestat *fsp);
-int nfs_filestat(struct vnode *vp, struct filestat *fsp);
-int devfs_filestat(struct vnode *vp, struct filestat *fsp);
-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 getinetproto(int number);
-int getfname(const char *filename);
-void usage(void);
-char *kdevtoname(struct cdev *dev);
+
+static int getfname(const char *filename);
+static void dofiles(struct procstat *procstat, struct kinfo_proc *p);
+static void print_access_flags(int flags);
+static void print_file_info(struct procstat *procstat,
+ struct filestat *fst, const char *uname, const char *cmd, int pid);
+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_socket_info(struct procstat *procstat,
+ struct filestat *fst);
+static void print_vnode_info(struct procstat *procstat,
+ struct filestat *fst);
+static void usage(void) __dead2;
int
-main(int argc, char **argv)
+do_fstat(int argc, char **argv)
{
+ struct kinfo_proc *p;
struct passwd *passwd;
+ struct procstat *procstat;
int arg, ch, what;
+ int cnt, i;
arg = 0;
what = KERN_PROC_PROC;
@@ -225,16 +161,18 @@ main(int argc, char **argv)
}
if (memf != NULL)
- fstat_kvm(what, arg);
+ procstat = procstat_open_kvm(nlistf, memf);
else
- fstat_sysctl(what, arg);
- exit(0);
-}
-
-static void
-print_header(void)
-{
+ procstat = procstat_open_sysctl();
+ 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");
@@ -245,312 +183,65 @@ 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;
-
- ALLOC_OFILES(256); /* reserve space for file pointers */
/*
- * 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());
-#ifdef notdef
- if (kvm_nlist(kd, nl) != 0)
- errx(1, "no namelist: %s", kvm_geterr(kd));
-#endif
- 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);
- if (mflg)
- dommap(p);
+ dofiles(procstat, &p[i]);
}
+ procstat_freeprocs(procstat, p);
+ procstat_close(procstat);
+ return (0);
}
static void
-fstat_sysctl(int what, int arg)
-{
-
- /* not yet implemented */
- fstat_kvm(what, arg);
-}
-
-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)
+dofiles(struct procstat *procstat, struct kinfo_proc *kp)
{
- int i;
- struct file file;
- struct filedesc filed;
-
- Uname = user_from_uid(kp->ki_uid, 0);
- Pid = kp->ki_pid;
- Comm = kp->ki_comm;
-
- if (kp->ki_fd == NULL)
+ const char *cmd;
+ const char *uname;
+ struct filestat *fst;
+ struct filestat_list *head;
+ int pid;
+
+ uname = user_from_uid(kp->ki_uid, 0);
+ pid = kp->ki_pid;
+ cmd = kp->ki_comm;
+
+ head = procstat_getfiles(procstat, kp, mflg);
+ if (head == NULL)
return;
- if (!KVM_READ(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)
-
- /* Sanity check on filed.fd_lastfile */
- if (filed.fd_lastfile <= -1 || filed.fd_lastfile > MAX_LASTFILE)
- return;
-
- ALLOC_OFILES(filed.fd_lastfile+1);
- if (!KVM_READ(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);
- return;
- }
- for (i = 0; i <= filed.fd_lastfile; i++) {
- if (ofiles[i] == NULL)
- continue;
- if (!KVM_READ(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);
- }
- }
-}
-
-void
-dommap(struct kinfo_proc *kp)
-{
- 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(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(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;
-
- if ((objp = entry.object.vm_object) == NULL)
- continue;
-
- for (; objp; objp = object.backing_object) {
- if (!KVM_READ(objp, &object, sizeof(object))) {
- dprintf(stderr,
- "can't read vm_object at %p for pid %d\n",
- (void *)objp, Pid);
- 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;
- }
- }
+ STAILQ_FOREACH(fst, head, next)
+ print_file_info(procstat, fst, uname, cmd, pid);
+ procstat_freefiles(procstat, head);
}
-char *
-kdevtoname(struct cdev *dev)
-{
- struct cdev si;
- if (!KVM_READ(dev, &si, sizeof si))
- return (NULL);
- return (strdup(si.__si_namebuf));
-}
-
-void
-vtrans(struct vnode *vp, int i, int flag)
+static void
+print_file_info(struct procstat *procstat, struct filestat *fst,
+ const char *uname, const char *cmd, int pid)
{
- struct vnode vn;
- struct filestat fst;
- char rw[3], mode[15], tagstr[12], *tagptr;
- const char *badtype, *filename;
-
- filename = badtype = NULL;
- if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
- dprintf(stderr, "can't read vnode at %p for pid %d\n",
- (void *)vp, Pid);
- return;
- }
- if (!KVM_READ(&vp->v_tag, &tagptr, sizeof tagptr) ||
- !KVM_READ(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(&vn, &fst))
- badtype = "error";
- } else if (!strcmp("devfs", tagstr)) {
- if (!devfs_filestat(&vn, &fst))
- badtype = "error";
- } else if (!strcmp("nfs", tagstr)) {
- if (!nfs_filestat(&vn, &fst))
- badtype = "error";
- } else if (!strcmp("msdosfs", tagstr)) {
- if (!msdosfs_filestat(&vn, &fst))
- badtype = "error";
- } else if (!strcmp("isofs", tagstr)) {
- if (!isofs_filestat(&vn, &fst))
- badtype = "error";
-#ifdef ZFS
- } else if (!strcmp("zfs", tagstr)) {
- if (!zfs_filestat(&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)
+ struct vnstat vn;
+ DEVS *d;
+ const char *filename;
+ int error, fsmatch = 0;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ filename = NULL;
+ 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, errbuf);
+ if (error != 0)
+ return;
+
for (d = devs; d != NULL; d = d->next)
- if (d->fsid == fst.fsid) {
+ if (d->fsid == vn.vn_fsid) {
fsmatch = 1;
- if (d->ino == fst.fileid) {
+ if ((unsigned)d->ino == vn.vn_fileid) {
filename = d->name;
break;
}
@@ -558,271 +249,83 @@ vtrans(struct vnode *vp, int i, int flag)
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
- (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(vn.v_rdev);
- if (nflg || !name)
- printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev));
- else {
- printf(" %6s", name);
- free(name);
- }
- 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');
-}
-
-int
-ufs_filestat(struct vnode *vp, struct filestat *fsp)
-{
- struct inode inode;
- if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
- dprintf(stderr, "can't read inode at %p for pid %d\n",
- (void *)VTOI(vp), Pid);
- return 0;
- }
/*
- * 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
+ * Print entry prefix.
*/
- fsp->fsid = dev2udev(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;
+ printf("%-8.8s %-10s %5d", uname, cmd, pid);
+ if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
+ printf(" text");
+ else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
+ printf(" wd");
+ else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
+ printf(" root");
+ else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
+ printf(" tr");
+ else if (fst->fs_uflags & PS_FST_UFLAG_MMAP)
+ printf(" mmap");
+ else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
+ printf(" jail");
+ else if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
+ printf(" ctty");
else
- fsp->rdev = inode.i_din2->di_rdev;
-#else
- fsp->rdev = 0;
-#endif
-
- return 1;
-}
-
-int
-devfs_filestat(struct vnode *vp, struct filestat *fsp)
-{
- struct devfs_dirent devfs_dirent;
- struct mount mount;
- struct vnode vnode;
-
- if (!KVM_READ(vp->v_data, &devfs_dirent, sizeof (devfs_dirent))) {
- dprintf(stderr, "can't read devfs_dirent at %p for pid %d\n",
- (void *)vp->v_data, Pid);
- return 0;
- }
- if (!KVM_READ(vp->v_mount, &mount, sizeof (mount))) {
- dprintf(stderr, "can't read mount at %p for pid %d\n",
- (void *)vp->v_mount, Pid);
- return 0;
- }
- if (!KVM_READ(devfs_dirent.de_vnode, &vnode, sizeof (vnode))) {
- dprintf(stderr, "can't read vnode at %p for pid %d\n",
- (void *)devfs_dirent.de_vnode, Pid);
- return 0;
- }
- fsp->fsid = (long)(uint32_t)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(vnode.v_rdev);
+ printf(" %4d", fst->fs_fd);
- return 1;
-}
-
-int
-nfs_filestat(struct vnode *vp, struct filestat *fsp)
-{
- struct nfsnode nfsnode;
- mode_t mode;
-
- if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
- dprintf(stderr, "can't read nfsnode at %p for pid %d\n",
- (void *)VTONFS(vp), Pid);
- return 0;
- }
- 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;
- mode = (mode_t)nfsnode.n_vattr.va_mode;
- switch (vp->v_type) {
- case VREG:
- mode |= S_IFREG;
- break;
- case VDIR:
- mode |= S_IFDIR;
- break;
- case VBLK:
- mode |= S_IFBLK;
- break;
- case VCHR:
- mode |= S_IFCHR;
+ /*
+ * Print type-specific data.
+ */
+ switch (fst->fs_type) {
+ case PS_FST_TYPE_FIFO:
+ case PS_FST_TYPE_VNODE:
+ print_vnode_info(procstat, fst);
break;
- case VLNK:
- mode |= S_IFLNK;
+ case PS_FST_TYPE_SOCKET:
+ print_socket_info(procstat, fst);
break;
- case VSOCK:
- mode |= S_IFSOCK;
+ case PS_FST_TYPE_PIPE:
+ print_pipe_info(procstat, fst);
break;
- case VFIFO:
- mode |= S_IFIFO;
+ case PS_FST_TYPE_PTS:
+ print_pts_info(procstat, fst);
break;
- case VNON:
- case VBAD:
- case VMARKER:
- return 0;
- };
- fsp->mode = mode;
-
- return 1;
-}
-
-
-char *
-getmnton(struct mount *m)
-{
- static struct mount mount;
- 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(m, &mount, 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(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
- mt->next = mhead;
- mhead = mt;
- return (mt->mntonname);
-}
-
-void
-pipetrans(struct pipe *pi, int i, int flag)
-{
- struct pipe pip;
- char rw[3];
-
- PREFIX(i);
-
- /* fill in socket */
- if (!KVM_READ(pi, &pip, sizeof(struct pipe))) {
- dprintf(stderr, "can't read pipe at %p\n", (void *)pi);
- goto bad;
+ default:
+ if (vflg)
+ fprintf(stderr,
+ "unknown file type %d for file %d of pid %d\n",
+ fst->fs_type, fst->fs_fd, pid);
}
-
- 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);
+ if (filename && !fsflg)
+ printf(" %s", filename);
putchar('\n');
- return;
-
-bad:
- printf("* error\n");
}
-void
-socktrans(struct socket *sock, int i)
+static void
+print_socket_info(struct procstat *procstat, struct filestat *fst)
{
static const char *stypename[] = {
"unused", /* 0 */
- "stream", /* 1 */
+ "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(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(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(proto.pr_domain, &dom, sizeof(struct domain))) {
- dprintf(stderr, "can't read domain at %p\n",
- (void *)proto.pr_domain);
- goto bad;
- }
+#define STYPEMAX 5
+ struct sockstat sock;
+ struct protoent *pe;
+ char errbuf[_POSIX2_LINE_MAX];
+ int error;
+ static int isopen;
- if ((len = kvm_read(kd, (u_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';
+ error = procstat_get_socket_info(procstat, fst, &sock, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
}
+ if (sock.type > STYPEMAX)
+ printf("* %s ?%d", sock.dname, sock.type);
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]);
+ printf("* %s %s", sock.dname, stypename[sock.type]);
/*
* protocol specific formatting
@@ -835,139 +338,144 @@ socktrans(struct socket *sock, int i)
* The idea is not to duplicate netstat, but to make available enough
* information for further analysis.
*/
- switch(dom.dom_family) {
+ switch (sock.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);
- }
+ if (!isopen)
+ setprotoent(++isopen);
+ if ((pe = getprotobynumber(sock.proto)) != NULL)
+ printf(" %s", pe->p_name);
+ else
+ printf(" %d", sock.proto);
+ if (sock.proto == IPPROTO_TCP ) {
+ if (sock.inp_ppcb != 0)
+ printf(" %lx", (u_long)sock.inp_ppcb);
}
- else if (so.so_pcb)
- printf(" %lx", (u_long)so.so_pcb);
+ else if (sock.so_pcb != 0)
+ printf(" %lx", (u_long)sock.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);
- goto bad;
- }
- if (unpcb.unp_conn) {
+ if (sock.so_pcb != 0) {
+ printf(" %lx", (u_long)sock.so_pcb);
+ if (sock.unp_conn) {
char shoconn[4], *cp;
cp = shoconn;
- if (!(so.so_rcv.sb_state & SBS_CANTRCVMORE))
+ if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE))
*cp++ = '<';
*cp++ = '-';
- if (!(so.so_snd.sb_state & SBS_CANTSENDMORE))
+ if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE))
*cp++ = '>';
*cp = '\0';
printf(" %s %lx", shoconn,
- (u_long)unpcb.unp_conn);
- }
+ (u_long)sock.unp_conn);
+ }
}
break;
default:
/* print protocol number and socket address */
- printf(" %d %lx", proto.pr_protocol, (u_long)sock);
+ printf(" %d %lx", sock.proto, (u_long)sock.so_addr);
}
- printf("\n");
- return;
-bad:
- printf("* error\n");
}
-void
-ptstrans(struct tty *tp, int i, int flag)
+static void
+print_pipe_info(struct procstat *procstat, struct filestat *fst)
{
- struct tty tty;
- char *name;
- char rw[3];
- dev_t rdev;
+ struct pipestat ps;
+ char errbuf[_POSIX2_LINE_MAX];
+ int error;
- PREFIX(i);
-
- /* Obtain struct tty. */
- if (!KVM_READ(tp, &tty, sizeof(struct tty))) {
- dprintf(stderr, "can't read tty at %p\n", (void *)tp);
- goto bad;
- }
-
- /* Figure out the device name. */
- name = kdevtoname(tty.t_dev);
- if (name == NULL) {
- dprintf(stderr, "can't determine tty name at %p\n", (void *)tp);
- goto bad;
+ error = procstat_get_pipe_info(procstat, fst, &ps, errbuf);
+ if (error != 0) {
+ printf("* error");
+ return;
}
+ printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer);
+ printf(" %6zd", ps.buffer_cnt);
+ print_access_flags(fst->fs_fflags);
+}
- rw[0] = '\0';
- if (flag & FREAD)
- strcat(rw, "r");
- if (flag & FWRITE)
- strcat(rw, "w");
+static void
+print_pts_info(struct procstat *procstat, struct filestat *fst)
+{
+ 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 || !name) {
- rdev = dev2udev(tty.t_dev);
- printf("%10d,%-2d", major(rdev), minor(rdev));
+ if (nflg || !*pts.devname) {
+ printf("%10d,%-2d", major(pts.dev), minor(pts.dev));
} else {
- printf("%10s", name);
+ printf("%10s", pts.devname);
}
- printf(" %2s\n", rw);
-
- free(name);
-
- return;
-bad:
- printf("* error\n");
+ print_access_flags(fst->fs_fflags);
}
-/*
- * Read the cdev structure in the kernel in order to work out the
- * associated dev_t
- */
-dev_t
-dev2udev(struct cdev *dev)
+static void
+print_vnode_info(struct procstat *procstat, struct filestat *fst)
{
- struct cdev_priv priv;
+ struct vnstat vn;
+ char errbuf[_POSIX2_LINE_MAX];
+ char mode[15];
+ const char *badtype;
+ 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);
+ return;
+ }
- if (KVM_READ(cdev2priv(dev), &priv, sizeof priv)) {
- return ((dev_t)priv.cdp_inode);
- } else {
- dprintf(stderr, "can't convert cdev *%p to a dev_t\n", dev);
- return -1;
+ if (nflg)
+ printf(" %2d,%-2d", major(vn.vn_fsid), minor(vn.vn_fsid));
+ else if (vn.vn_mntdir != NULL)
+ (void)printf(" %-8s", vn.vn_mntdir);
+
+ /*
+ * Print access mode.
+ */
+ if (nflg)
+ (void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode);
+ else {
+ strmode(vn.vn_mode, mode);
}
+ (void)printf(" %6ld %10s", vn.vn_fileid, mode);
+
+ if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) {
+ if (nflg || !*vn.vn_devname)
+ printf(" %2d,%-2d", major(vn.vn_dev), minor(vn.vn_dev));
+ else {
+ printf(" %6s", vn.vn_devname);
+ }
+ } else
+ printf(" %6lu", vn.vn_size);
+ print_access_flags(fst->fs_fflags);
}
-/*
- * getinetproto --
- * print name of protocol number
- */
-void
-getinetproto(int number)
+static void
+print_access_flags(int flags)
{
- static int isopen;
- struct protoent *pe;
+ char rw[3];
- if (!isopen)
- setprotoent(++isopen);
- if ((pe = getprotobynumber(number)) != NULL)
- printf(" %s", pe->p_name);
- else
- printf(" %d", number);
+ rw[0] = '\0';
+ if (flags & PS_FST_FFLAG_READ)
+ strcat(rw, "r");
+ if (flags & PS_FST_FFLAG_WRITE)
+ strcat(rw, "w");
+ printf(" %2s", rw);
}
int
@@ -978,7 +486,7 @@ getfname(const char *filename)
if (stat(filename, &statbuf)) {
warn("%s", filename);
- return(0);
+ return (0);
}
if ((cur = malloc(sizeof(DEVS))) == NULL)
err(1, NULL);
@@ -988,24 +496,10 @@ getfname(const char *filename)
cur->ino = statbuf.st_ino;
cur->fsid = statbuf.st_dev;
cur->name = filename;
- return(1);
+ return (1);
}
-#ifdef ZFS
-void *
-getvnodedata(struct vnode *vp)
-{
- return (vp->v_data);
-}
-
-struct mount *
-getvnodemount(struct vnode *vp)
-{
- return (vp->v_mount);
-}
-#endif
-
-void
+static void
usage(void)
{
(void)fprintf(stderr,
diff --git a/usr.bin/fstat/fstat.h b/usr.bin/fstat/functions.h
index 3533a60..a23d27e 100644
--- a/usr.bin/fstat/fstat.h
+++ b/usr.bin/fstat/functions.h
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,9 +10,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -28,49 +25,10 @@
*
* $FreeBSD$
*/
+#ifndef __FUNCTIONS_H__
+#define __FUNCTIONS_H__
-#ifndef __FSTAT_H__
-#define __FSTAT_H__
+int do_fstat(int argc, char *argv[]);
+int do_fuser(int argc, char *argv[]);
-/*
- * a kvm_read that returns true if everything is read
- */
-#define KVM_READ(kaddr, paddr, len) \
- ((len) < SSIZE_MAX && \
- kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (ssize_t)(len))
-
-#define dprintf if (vflg) fprintf
-
-typedef struct devs {
- struct devs *next;
- long fsid;
- long ino;
- const char *name;
-} DEVS;
-
-struct filestat {
- long fsid;
- long fileid;
- mode_t mode;
- u_long size;
- dev_t rdev;
-};
-
-/* Ugh */
-extern kvm_t *kd;
-extern int vflg;
-extern int Pid;
-
-dev_t dev2udev(struct cdev *dev);
-
-/* Additional filesystem types */
-int isofs_filestat(struct vnode *vp, struct filestat *fsp);
-int msdosfs_filestat(struct vnode *vp, struct filestat *fsp);
-
-#ifdef ZFS
-int zfs_filestat(struct vnode *vp, struct filestat *fsp);
-void *getvnodedata(struct vnode *vp);
-struct mount *getvnodemount(struct vnode *vp);
-#endif
-
-#endif /* __FSTAT_H__ */
+#endif /* !__FUNCTIONS_H__ */
diff --git a/usr.bin/fstat/fuser.1 b/usr.bin/fstat/fuser.1
new file mode 100644
index 0000000..999a72d
--- /dev/null
+++ b/usr.bin/fstat/fuser.1
@@ -0,0 +1,148 @@
+.\" Copyright (c) 2005-2009 Stanislav Sedov <stas@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 31, 2009
+.Dt FUSER 1
+.Os
+.Sh NAME
+.Nm fuser
+.Nd list IDs of all processes that have one or more files open
+.Sh SYNOPSIS
+.Nm
+.Op Fl cfkmu
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl s Ar signal
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes to stdout the PIDs of processes that have one or
+more named files open.
+For block and character special devices, all processes using files
+on that device are listed.
+A file is considered open by a process if it was explicitly opened,
+is the working directory, root directory, jail root directory,
+active executable text, kernel trace file or the controlling terminal
+of the process.
+If
+.Fl m
+option is specified, the
+.Nm
+utility will also look through mmapped files.
+.Pp
+The following options are available:
+.Bl -tag -width indent
+.It Fl c
+Treat files as mount point and report on any files open in the file system.
+.It Fl f
+The report must be only for named files.
+.It Fl k
+Send signal to reported processes
+.Pq SIGKILL by default .
+.It Fl m
+Search through mmapped files too.
+.It Fl u
+Write the user name associated with each process to stdout.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default
+.Pa /dev/kmem .
+.It Fl N
+Extract the name list from the specified system instead of the default,
+which is the kernel image the system has booted from.
+.It Fl s
+Use given signal name instead of default SIGKILL.
+.El
+.Pp
+The following symbols, written to stderr will indicate how files is used:
+.Bl -tag -width MOUNT
+.It Cm r
+The file is the root directory of the process.
+.It Cm c
+The file is the current workdir directory of the process.
+.It Cm j
+The file is the jail-root of the process.
+.It Cm t
+The file is the kernel tracing file for the process.
+.It Cm x
+The file is executable text of the process.
+.It Cm y
+The process use this file as its controlling tty.
+.It Cm m
+The file is mmapped.
+.It Cm w
+The file is open for writing.
+.It Cm a
+The file is open as append only
+.Pq O_APPEND was specified .
+.It Cm d
+The process bypasses fs cache while writing to this file
+.Pq O_DIRECT was specified .
+.It Cm s
+Shared lock is hold.
+.It Cm e
+Exclusive lock is hold.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility returns 0 on successful completion and >0 otherwise.
+.Sh EXAMPLES
+The command:
+.Dq Li "fuser -fu ."
+writes to standart output the process IDs of processes that are using the
+current directory and writes to stderr an indication of how those processes are
+using the direcory and user names associated with the processes that are using
+this directory.
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr ps 1 ,
+.Xr systat 1 ,
+.Xr iostat 8 ,
+.Xr pstat 8 ,
+.Xr vmstat 8
+.Sh STANDARTS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.1-2004 .
+.Sh BUGS
+Since
+.Nm
+takes a snapshot of the system, it is only correct for a very short period
+of time.
+When working via
+.Xr kvm 3
+interface the report will be limited to filesystems the
+.Nm
+utility knows about (currently only cd9660, devfs, nfs, ntfs, nwfs, udf,
+ufs and zfs).
+.Sh AUTHORS
+The
+.Nm
+utility and this manual page was written by
+.An Stanislav Sedov Aq stas@FreeBSD.org .
diff --git a/usr.bin/fstat/fuser.c b/usr.bin/fstat/fuser.c
new file mode 100644
index 0000000..02975b3
--- /dev/null
+++ b/usr.bin/fstat/fuser.c
@@ -0,0 +1,369 @@
+/*-
+ * Copyright (c) 2005-2009 Stanislav Sedov <stas@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <libprocstat.h>
+#include <limits.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "functions.h"
+
+/*
+ * File access mode flags table.
+ */
+struct {
+ int flag;
+ char ch;
+} fflags[] = {
+ {PS_FST_FFLAG_WRITE, 'w'},
+ {PS_FST_FFLAG_APPEND, 'a'},
+ {PS_FST_FFLAG_DIRECT, 'd'},
+ {PS_FST_FFLAG_SHLOCK, 's'},
+ {PS_FST_FFLAG_EXLOCK, 'e'}
+};
+#define NFFLAGS (sizeof(fflags) / sizeof(*fflags))
+
+/*
+ * Usage flags translation table.
+ */
+struct {
+ int flag;
+ char ch;
+} uflags[] = {
+ {PS_FST_UFLAG_RDIR, 'r'},
+ {PS_FST_UFLAG_CDIR, 'c'},
+ {PS_FST_UFLAG_JAIL, 'j'},
+ {PS_FST_UFLAG_TRACE, 't'},
+ {PS_FST_UFLAG_TEXT, 'x'},
+ {PS_FST_UFLAG_MMAP, 'm'},
+ {PS_FST_UFLAG_CTTY, 'y'}
+};
+#define NUFLAGS (sizeof(uflags) / sizeof(*uflags))
+
+struct consumer {
+ pid_t pid;
+ uid_t uid;
+ int fd;
+ int flags;
+ int uflags;
+ STAILQ_ENTRY(consumer) next;
+};
+struct reqfile {
+ uint32_t fsid;
+ uint64_t fileid;
+ const char *name;
+ STAILQ_HEAD(, consumer) consumers;
+};
+
+/*
+ * Option flags.
+ */
+#define UFLAG 0x01 /* -u flag: show users */
+#define FFLAG 0x02 /* -f flag: specified files only */
+#define CFLAG 0x04 /* -c flag: treat as mpoints */
+#define MFLAG 0x10 /* -m flag: mmapped files too */
+#define KFLAG 0x20 /* -k flag: send signal (SIGKILL by default) */
+
+static int flags = 0; /* Option flags. */
+
+static void printflags(struct consumer *consumer);
+static int str2sig(const char *str);
+static void usage(void) __dead2;
+static int addfile(const char *path, struct reqfile *reqfile);
+static void dofiles(struct procstat *procstat, struct kinfo_proc *kp,
+ struct reqfile *reqfiles, size_t nfiles);
+
+static void
+usage(void)
+{
+
+ fprintf(stderr,
+"usage: fuser [-cfhkmu] [-M core] [-N system] [-s signal] file ...\n");
+ exit(EX_USAGE);
+}
+
+static void
+printflags(struct consumer *cons)
+{
+ unsigned int i;
+
+ assert(cons);
+ for (i = 0; i < NUFLAGS; i++)
+ if ((cons->uflags & uflags[i].flag) != 0)
+ fputc(uflags[i].ch, stderr);
+ for (i = 0; i < NFFLAGS; i++)
+ if ((cons->flags & fflags[i].flag) != 0)
+ fputc(fflags[i].ch, stderr);
+}
+
+/*
+ * Add file to the list.
+ */
+static int
+addfile(const char *path, struct reqfile *reqfile)
+{
+ struct stat sb;
+
+ assert(path);
+ if (stat(path, &sb) != 0) {
+ warn("%s", path);
+ return (1);
+ }
+ reqfile->fileid = sb.st_ino;
+ reqfile->fsid = sb.st_dev;
+ reqfile->name = path;
+ STAILQ_INIT(&reqfile->consumers);
+ return (0);
+}
+
+int
+do_fuser(int argc, char *argv[])
+{
+ struct consumer *consumer;
+ struct kinfo_proc *p, *procs;
+ struct procstat *procstat;
+ struct reqfile *reqfiles;
+ char *ep, *nlistf, *memf;
+ int ch, cnt, sig;
+ unsigned int i, nfiles;
+
+ sig = SIGKILL; /* Default to kill. */
+ nlistf = NULL;
+ memf = NULL;
+ while ((ch = getopt(argc, argv, "M:N:cfhkms:u")) != -1)
+ switch(ch) {
+ case 'f':
+ if ((flags & CFLAG) != 0)
+ usage();
+ flags |= FFLAG;
+ break;
+ case 'c':
+ if ((flags & FFLAG) != 0)
+ usage();
+ flags |= CFLAG;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'u':
+ flags |= UFLAG;
+ break;
+ case 'm':
+ flags |= MFLAG;
+ break;
+ case 'k':
+ flags |= KFLAG;
+ break;
+ case 's':
+ if (isdigit(*optarg)) {
+ sig = strtol(optarg, &ep, 10);
+ if (*ep != '\0' || sig < 0 || sig >= sys_nsig)
+ errx(EX_USAGE, "illegal signal number" ": %s",
+ optarg);
+ } else {
+ sig = str2sig(optarg);
+ if (sig < 0)
+ errx(EX_USAGE, "illegal signal name: "
+ "%s", optarg);
+ }
+ break;
+ case 'h':
+ /* PASSTHROUGH */
+ default:
+ usage();
+ /* NORETURN */
+ }
+ argv += optind;
+ argc -= optind;
+
+ assert(argc >= 0);
+ if (argc == 0)
+ usage();
+ /* NORETURN */
+
+ /*
+ * Process named files.
+ */
+ reqfiles = malloc(argc * sizeof(struct reqfile));
+ if (reqfiles == NULL)
+ err(EX_OSERR, "malloc()");
+ nfiles = 0;
+ while (argc--)
+ if (!addfile(*(argv++), &reqfiles[nfiles]))
+ nfiles++;
+ if (nfiles == 0)
+ errx(EX_IOERR, "files not accessible");
+
+ if (memf != NULL)
+ procstat = procstat_open_kvm(nlistf, memf);
+ else
+ procstat = procstat_open_sysctl();
+ if (procstat == NULL)
+ errx(1, "procstat_open()");
+ procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &cnt);
+ if (procs == NULL)
+ errx(1, "procstat_getprocs()");
+
+ /*
+ * Walk through process table and look for matching files.
+ */
+ p = procs;
+ while(cnt--)
+ if (p->ki_stat != SZOMB)
+ dofiles(procstat, p++, reqfiles, nfiles);
+
+ for (i = 0; i < nfiles; i++) {
+ fprintf(stderr, "%s:", reqfiles[i].name);
+ fflush(stderr);
+ STAILQ_FOREACH(consumer, &reqfiles[i].consumers, next) {
+ if (consumer->flags != 0) {
+ fprintf(stdout, "%6d", consumer->pid);
+ fflush(stdout);
+ printflags(consumer);
+ if ((flags & UFLAG) != 0)
+ fprintf(stderr, "(%s)",
+ user_from_uid(consumer->uid, 0));
+ if ((flags & KFLAG) != 0)
+ kill(consumer->pid, sig);
+ fflush(stderr);
+ }
+ }
+ (void)fprintf(stderr, "\n");
+ }
+ procstat_freeprocs(procstat, procs);
+ procstat_close(procstat);
+ free(reqfiles);
+ return (0);
+}
+
+static void
+dofiles(struct procstat *procstat, struct kinfo_proc *kp,
+ struct reqfile *reqfiles, size_t nfiles)
+{
+ struct vnstat vn;
+ struct consumer *cons;
+ struct filestat *fst;
+ struct filestat_list *head;
+ int error, match;
+ unsigned int i;
+ char errbuf[_POSIX2_LINE_MAX];
+
+ head = procstat_getfiles(procstat, kp, flags & MFLAG);
+ if (head == NULL)
+ return;
+ STAILQ_FOREACH(fst, head, next) {
+ if (fst->fs_type != PS_FST_TYPE_VNODE)
+ continue;
+ error = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+ if (error != 0)
+ continue;
+ for (i = 0; i < nfiles; i++) {
+ if (flags & CFLAG && reqfiles[i].fsid == vn.vn_fsid) {
+ break;
+ }
+ else if (reqfiles[i].fsid == vn.vn_fsid &&
+ reqfiles[i].fileid == vn.vn_fileid) {
+ break;
+ }
+ else if (!(flags & FFLAG) &&
+ (vn.vn_type == PS_FST_VTYPE_VCHR ||
+ vn.vn_type == PS_FST_VTYPE_VBLK) &&
+ vn.vn_fsid == reqfiles[i].fileid) {
+ break;
+ }
+ }
+ if (i == nfiles)
+ continue; /* No match. */
+
+ /*
+ * Look for existing entries.
+ */
+ match = 0;
+ STAILQ_FOREACH(cons, &reqfiles[i].consumers, next)
+ if (cons->pid == kp->ki_pid) {
+ match = 1;
+ break;
+ }
+ if (match == 1) { /* Use old entry. */
+ cons->flags |= fst->fs_fflags;
+ cons->uflags |= fst->fs_uflags;
+ } else {
+ /*
+ * Create new entry in the consumer chain.
+ */
+ cons = calloc(1, sizeof(struct consumer));
+ if (cons == NULL) {
+ warn("malloc()");
+ continue;
+ }
+ cons->uid = kp->ki_uid;
+ cons->pid = kp->ki_pid;
+ cons->uflags = fst->fs_uflags;
+ cons->flags = fst->fs_fflags;
+ STAILQ_INSERT_TAIL(&reqfiles[i].consumers, cons, next);
+ }
+ }
+ procstat_freefiles(procstat, head);
+}
+
+/*
+ * Returns signal number for it's string representation.
+ */
+static int
+str2sig(const char *str)
+{
+ int i;
+
+#define SIGPREFIX "sig"
+ if (!strncasecmp(str, SIGPREFIX, sizeof(SIGPREFIX)))
+ str += sizeof(SIGPREFIX);
+ for (i = 1; i < sys_nsig; i++) {
+ if (!strcasecmp(sys_signame[i], str))
+ return (i);
+ }
+ return (-1);
+}
diff --git a/usr.bin/fstat/main.c b/usr.bin/fstat/main.c
new file mode 100644
index 0000000..4123e64
--- /dev/null
+++ b/usr.bin/fstat/main.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "functions.h"
+
+int
+main(int argc, char *argv[])
+{
+ char *p;
+
+ p = basename(argv[0]);
+ if (p == NULL)
+ err(1, "basename(%s)", argv[0]);
+ if (!strcmp(p, "fuser"))
+ return (do_fuser(argc, argv));
+ else
+ return (do_fstat(argc, argv));
+}
diff --git a/usr.bin/fstat/msdosfs.c b/usr.bin/fstat/msdosfs.c
deleted file mode 100644
index 7f80499..0000000
--- a/usr.bin/fstat/msdosfs.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2000 Peter Edwards
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by Peter Edwards
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/vnode.h>
-
-#define _KERNEL
-#include <sys/mount.h>
-#include <fs/msdosfs/bpb.h>
-#include <fs/msdosfs/msdosfsmount.h>
-#undef _KERNEL
-
-#include <fs/msdosfs/denode.h>
-#include <fs/msdosfs/direntry.h>
-#include <fs/msdosfs/fat.h>
-
-#include <err.h>
-#include <kvm.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
- * XXX -
- * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to
- * header explosion
- */
-#define VTODE(vp) ((struct denode *)(vp)->v_data)
-
-#include "fstat.h"
-
-struct dosmount {
- struct dosmount *next;
- struct msdosfsmount *kptr; /* Pointer in kernel space */
- struct msdosfsmount data; /* User space copy of structure */
-};
-
-int
-msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
-{
- struct denode denode;
- static struct dosmount *mounts;
- struct dosmount *mnt;
- u_long dirsperblk;
- int fileid;
-
- if (!KVM_READ(VTODE(vp), &denode, sizeof (denode))) {
- dprintf(stderr, "can't read denode at %p for pid %d\n",
- (void *)VTODE(vp), Pid);
- return 0;
- }
-
- /*
- * Find msdosfsmount structure for the vnode's filesystem. Needed
- * for some filesystem parameters
- */
- for (mnt = mounts; mnt; mnt = mnt->next)
- if (mnt->kptr == denode.de_pmp)
- break;
-
- if (!mnt) {
- if ((mnt = malloc(sizeof(struct dosmount))) == NULL)
- err(1, NULL);
- if (!KVM_READ(denode.de_pmp, &mnt->data, sizeof mnt->data)) {
- free(mnt);
- dprintf(stderr,
- "can't read mount info at %p for pid %d\n",
- (void *)denode.de_pmp, Pid);
- return 0;
- }
- mnt->next = mounts;
- mounts = mnt;
- mnt->kptr = denode.de_pmp;
- }
-
- fsp->fsid = dev2udev(mnt->data.pm_dev);
- fsp->mode = 0555;
- fsp->mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222;
- fsp->mode &= mnt->data.pm_mask;
-
- /* Distinguish directories and files. No "special" files in FAT. */
- fsp->mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG;
-
- fsp->size = denode.de_FileSize;
- fsp->rdev = 0;
-
- /*
- * XXX -
- * Culled from msdosfs_vnops.c. There appears to be a problem
- * here, in that a directory has the same inode number as the first
- * file in the directory. stat(2) suffers from this problem also, so
- * I won't try to fix it here.
- *
- * The following computation of the fileid must be the same as that
- * used in msdosfs_readdir() to compute d_fileno. If not, pwd
- * doesn't work.
- */
- dirsperblk = mnt->data.pm_BytesPerSec / sizeof(struct direntry);
- if (denode.de_Attributes & ATTR_DIRECTORY) {
- fileid = cntobn(&mnt->data, denode.de_StartCluster)
- * dirsperblk;
- if (denode.de_StartCluster == MSDOSFSROOT)
- fileid = 1;
- } else {
- fileid = cntobn(&mnt->data, denode.de_dirclust) * dirsperblk;
- if (denode.de_dirclust == MSDOSFSROOT)
- fileid = roottobn(&mnt->data, 0) * dirsperblk;
- fileid += denode.de_diroffset / sizeof(struct direntry);
- }
-
- fsp->fileid = fileid;
- return 1;
-}
diff --git a/usr.bin/fstat/zfs.c b/usr.bin/fstat/zfs.c
deleted file mode 100644
index cdca41f..0000000
--- a/usr.bin/fstat/zfs.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*-
- * Copyright (c) 2007 Ulf Lilleengen
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#define _KERNEL
-#include <sys/mount.h>
-#include <sys/taskqueue.h>
-#undef _KERNEL
-#include <sys/sysctl.h>
-
-#undef lbolt
-#undef lbolt64
-#undef gethrestime_sec
-#include <sys/zfs_context.h>
-#include <sys/spa.h>
-#include <sys/spa_impl.h>
-#include <sys/dmu.h>
-#include <sys/zap.h>
-#include <sys/fs/zfs.h>
-#include <sys/zfs_znode.h>
-#include <sys/zfs_sa.h>
-
-#include <err.h>
-#include <kvm.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define ZFS
-#undef dprintf
-#include <fstat.h>
-
-/*
- * Offset calculations that are used to get data from znode without having the
- * definition.
- */
-#define LOCATION_ZID (2 * sizeof(void *))
-#define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task)))
-
-int
-zfs_filestat(struct vnode *vp, struct filestat *fsp)
-{
-
- znode_phys_t zphys;
- struct mount mount, *mountptr;
- uint64_t *zid;
- void *znodeptr, *vnodeptr;
- char *dataptr;
- void *zphys_addr;
- size_t len;
- int size;
-
- len = sizeof(size);
- if (sysctlbyname("debug.sizeof.znode", &size, &len, NULL, 0) == -1) {
- dprintf(stderr, "error getting sysctl\n");
- return (0);
- }
- znodeptr = malloc(size);
- if (znodeptr == NULL) {
- dprintf(stderr, "error allocating memory for znode storage\n");
- return (0);
- }
-
- /* Since we have problems including vnode.h, we'll use the wrappers. */
- vnodeptr = getvnodedata(vp);
- if (!KVM_READ(vnodeptr, znodeptr, (size_t)size)) {
- dprintf(stderr, "can't read znode at %p for pid %d\n",
- (void *)vnodeptr, Pid);
- goto bad;
- }
-
- /*
- * z_id field is stored in the third pointer. We therefore skip the two
- * first bytes.
- *
- * Pointer to the z_phys structure is the next last pointer. Therefore
- * go back two bytes from the end.
- */
- dataptr = znodeptr;
- zid = (uint64_t *)(dataptr + LOCATION_ZID);
- zphys_addr = *(void **)(dataptr + LOCATION_ZPHYS(size));
-
- if (!KVM_READ(zphys_addr, &zphys, sizeof(zphys))) {
- dprintf(stderr, "can't read znode_phys at %p for pid %d\n",
- zphys_addr, Pid);
- goto bad;
- }
-
- /* Get the mount pointer, and read from the address. */
- mountptr = getvnodemount(vp);
- if (!KVM_READ(mountptr, &mount, sizeof(mount))) {
- dprintf(stderr, "can't read mount at %p for pid %d\n",
- (void *)mountptr, Pid);
- goto bad;
- }
-
- fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0];
- fsp->fileid = *zid;
- /*
- * XXX: Shows up wrong in output, but UFS has this error too. Could
- * be that we're casting mode-variables from 64-bit to 8-bit or simply
- * error in the mode-to-string function.
- */
- fsp->mode = (mode_t)zphys.zp_mode;
- fsp->size = (u_long)zphys.zp_size;
- fsp->rdev = (dev_t)zphys.zp_rdev;
- free(znodeptr);
- return (1);
-bad:
- free(znodeptr);
- return (0);
-}
diff --git a/usr.bin/fstat/zfs/Makefile b/usr.bin/fstat/zfs/Makefile
deleted file mode 100644
index 7ecfc85..0000000
--- a/usr.bin/fstat/zfs/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/..
-
-SRCS= zfs.c
-OBJS= zfs.o
-WARNS?= 1
-
-CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
-CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
-CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
-CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common
-CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs
-CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common
-CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys
-CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head
-CFLAGS+= -I${.CURDIR}/..
-CFLAGS+= -DNEED_SOLARIS_BOOLEAN
-
-all: ${OBJS}
-CLEANFILES= ${OBJS}
-
-.include <bsd.lib.mk>
OpenPOWER on IntegriCloud