bin/53682: [PATCH] add fuser(1) utitity
Lukas Ertl
l.ertl at univie.ac.at
Tue Jun 24 07:20:11 PDT 2003
>Number: 53682
>Category: bin
>Synopsis: [PATCH] add fuser(1) utitity
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Jun 24 07:20:07 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator: Lukas Ertl
>Release: FreeBSD 5.1-CURRENT i386
>Organization:
Vienna University Computer Center
>Environment:
System: FreeBSD leelou 5.1-CURRENT FreeBSD 5.1-CURRENT #1: Sun Jun 22 12:56:44 CEST 2003 le at leelou:/usr/obj/usr/src/sys/LEELOU i386
>Description:
Although our fstat(1) provides the same functionality, POSIX requires an
fuser(1) utility, which is still missing on FreeBSD.
>How-To-Repeat:
>Fix:
This patch was sent to me from tjr@ who has received it from Peter Werner
<peterw at ifost.org.au>.
I had to hack a bit to make it compile and run on FreeBSD.
--- fuser.diff begins here ---
diff -ruN /usr/src/usr.bin/fuser/Makefile usr.bin/fuser/Makefile
--- /usr/src/usr.bin/fuser/Makefile Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/Makefile Tue Jun 24 15:52:01 2003
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG= fuser
+SRCS= isofs.c filestat.c fuser.c
+LDADD= -lkvm
+DPADD= ${LIBKVM}
+BINGRP= kmem
+BINMODE=2555
+
+.include <bsd.prog.mk>
diff -ruN /usr/src/usr.bin/fuser/filestat.c usr.bin/fuser/filestat.c
--- /usr/src/usr.bin/fuser/filestat.c Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/filestat.c Tue Jun 24 16:01:49 2003
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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.
+ * 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/vnode.h>
+#define _KERNEL
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/mount.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#include <fs/nullfs/null.h>
+#undef _KERNEL
+#include <nfs/nfsproto.h>
+#include <nfs/rpcv2.h>
+#include <nfsclient/nfs.h>
+#include <nfsclient/nfsnode.h>
+
+#include <kvm.h>
+#include <string.h>
+
+#include "fuser.h"
+
+udev_t dev2udev(struct cdev *dev);
+
+extern kvm_t *kd;
+
+int
+ufs_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+ struct inode inode;
+
+ if (!KVM_READ(VTOI(vp), &inode, sizeof (inode)))
+ return 0;
+
+ fi->fi_dev = dev2udev(inode.i_dev) & 0xffff;
+ fi->fi_inode = (long)inode.i_number;
+
+ return 1;
+}
+
+int
+ext2fs_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+ struct inode inode;
+
+ if (!KVM_READ(VTOI(vp), &inode, sizeof (inode)))
+ return 0;
+
+ fi->fi_dev = dev2udev(inode.i_dev) & 0xffff;
+ fi->fi_inode = (long)inode.i_number;
+
+ return 1;
+}
+
+int
+msdos_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+#if 0
+ struct inode inode;
+
+ if (!KVM_READ(VTOI(vp), &inode, sizeof (inode)))
+ return 0;
+
+ fi->fi_dev = inode.i_dev & 0xffff;
+ fi->fi_inode = (long)inode.i_number;
+#endif
+
+ return 1;
+}
+
+int
+nfs_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+ struct nfsnode nfsnode;
+ mode_t mode;
+
+ if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode)))
+ return 0;
+
+
+ fi->fi_dev = nfsnode.n_vattr.va_fsid;
+ fi->fi_inode = nfsnode.n_vattr.va_fileid;
+
+ return 1;
+}
+
+int
+null_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+ struct null_node node;
+ struct fileinfo fis;
+ struct vnode vn;
+ char tagstr[12], *tagptr;
+ int fail = 1;
+
+ memset(&fis, 0, sizeof fis);
+
+ if (!KVM_READ(VTONULL(vp), &node, sizeof (node)))
+ return 0;
+
+
+ /*
+ * Attempt to find information that might be useful.
+ */
+ if (node.null_lowervp) {
+ if (!KVM_READ(node.null_lowervp, &vn, sizeof (vn)))
+ return 0;
+ if (!KVM_READ(&node.null_lowervp->v_tag, &tagptr, sizeof tagptr))
+ return 0;
+ if (!KVM_READ(tagptr, tagstr, sizeof tagstr))
+ return 0;
+
+ tagstr[sizeof(tagstr) - 1] = '\0';
+
+ fail = 0;
+ if (vn.v_type == VNON || vn.v_type == VBAD)
+ fail = 1;
+ else {
+ if (!strcmp("ufs", tagstr) || !strcmp("mfs", tagstr)) {
+ if (!ufs_filestat(&vn, &fis))
+ fail = 1;
+ } else if (!strcmp("nfs", tagstr)) {
+ if (!nfs_filestat(&vn, &fis))
+ fail = 1;
+ } else if (!strcmp("ext2fs", tagstr)) {
+ if (!ext2fs_filestat(&vn, &fis))
+ fail = 1;
+ } else if (!strcmp("isofs", tagstr)) {
+ if (!isofs_filestat(&vn, &fis))
+ fail = 1;
+ } else if (!strcmp("msdosfs", tagstr)) {
+ if (!msdos_filestat(&vn, &fis))
+ fail = 1;
+ }
+ }
+ }
+
+ fi->fi_dev = (long)node.null_vnode;
+ if (fail)
+ fi->fi_inode = (long)node.null_lowervp;
+ else
+ fi->fi_inode = fis.fi_inode;
+
+ return 1;
+}
+
+/*
+ * Read the cdev structure in the kernel
+ * in order to work out the associated udev_t
+ */
+udev_t
+dev2udev(struct cdev *dev)
+{
+ struct cdev si;
+
+ if (KVM_READ(dev, &si, sizeof si)) {
+ return si.si_udev;
+ } else {
+ errx("can't convert dev_t %x to a udev_t\n", dev);
+ return -1;
+ }
+}
diff -ruN /usr/src/usr.bin/fuser/fuser.1 usr.bin/fuser/fuser.1
--- /usr/src/usr.bin/fuser/fuser.1 Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/fuser.1 Wed Jun 4 19:24:41 2003
@@ -0,0 +1,124 @@
+.\" Copyright (c) 2002 Peter Werner <peterw at ifost.org.au>
+.\" 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. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED ``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.
+.Dd June 4, 2003
+.Dt FUSER 1
+.Os
+.Sh NAME
+.Nm fuser
+.Nd list process IDs holding specific files open
+.Sh SYNOPSIS
+.Nm
+.Op Fl cfu
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Ar
+.Sh DESCRIPTION
+.Nm
+will write to standard output the process IDs of processes running on the
+local system that have one or more of the named files open.
+If
+.Ar file
+is a block device, and it has an equivalent
+.Xr fstab 5
+entry, the output will show all processes having files opened on that file
+system.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl c
+The file is treated as a mount point and
+.Nm
+will report on any files open in the file system.
+.It Fl f
+The report shall be only for the named file(s).
+.It Fl u
+The username associated with each process ID using the file will be printed
+in parentheses to standard error.
+If the username is unable to be determined, the real user id will be printed
+instead.
+.It Fl M Ar core
+Extract values associated with the name list from the specified core
+instead of the running kernel.
+.It Fl N Ar system
+Extract the name list from the specified system instead of the running kernel.
+.El
+.Pp
+The
+.Fl c
+and
+.Fl f
+options are mutually exclusive.
+.Pp
+The name of the file followed by a colon
+.Pq Sq \&:
+will be printed to standard error.
+The following characters may be printed to standard error after the process id
+if the described conditions are true:
+.Bl -tag -width Ds
+.It r
+The file is the processes root directory.
+.It c
+The file is the processes current working directory.
+.El
+.Pp
+.Sh EXAMPLES
+.Cm $ fuser -c /mnt
+.Pp
+This will print the process id's of any processes holding files open under the
+.Ar /mnt
+filesystem.
+.Pp
+.Cm # fuser -c /mnt 2> /dev/null \&| xargs kill
+.Sy -TERM
+.Pp
+This will result in any process holding a file open under the
+.Ar /mnt
+filesystem being sent SIGTERM (unless a process releases the file in the time
+it takes
+.Nm
+to exit and
+.Xr kill 1
+to run).
+.Pp
+.Cm $ fuser /dev/ad0s1a
+.Pp
+.Nm
+will report on all files opened under the filesystem on which
+.Ar /dev/ad0s1a
+is mounted on.
+.Pp
+.Cm $ fuser -f /dev/ad0s1a
+.Pp
+.Nm
+will report on all processes currently holding
+.Ar /dev/ad0s1a
+open.
+.Sh DIAGNOSTICS
+The
+.Nm
+utility exits 0 on success or >0 if an error occured.
+.Sh SEE ALSO
+.Xr fstat 1 ,
+.Xr kill 1 ,
+.Xr signal 3 ,
+.Xr fstab 5
diff -ruN /usr/src/usr.bin/fuser/fuser.c usr.bin/fuser/fuser.c
--- /usr/src/usr.bin/fuser/fuser.c Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/fuser.c Tue Jun 24 16:01:35 2003
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2002 Peter Werner <peterw at ifost.org.au>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/vnode.h>
+#include <sys/filedesc.h>
+#define _KERNEL
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/mount.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/inode.h>
+#undef _KERNEL
+#include <err.h>
+#include <fcntl.h>
+#include <fstab.h>
+#include <kvm.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fuser.h"
+
+struct f_file {
+ SLIST_ENTRY(f_file) f_next;
+ dev_t f_dev;
+ ino_t f_file;
+ char *f_name;
+ uid_t *f_uids;
+ pid_t *f_pids;
+ int *f_flags;
+#define F_ROOT 0x01 /* is procs root directory */
+#define F_CWD 0x02 /* is procs cwd */
+#define F_OPEN 0x04 /* just has it open */
+ int f_nuids;
+};
+
+struct fproc {
+ uid_t fp_uid;
+ pid_t fp_pid;
+ struct file **fp_fvec;
+ int fp_nfiles;
+ struct vnode *fp_cdir;
+ struct vnode *fp_rdir;
+};
+
+int getprocfdtable(struct kinfo_proc *kp, struct fproc *);
+int filecwd(struct f_file *ff, struct fproc *);
+int fileroot(struct f_file *ff, struct fproc *);
+int fileopened(struct f_file *ff, struct fproc *);
+int match(struct f_file *ff, struct fileinfo *fi);
+struct f_file *alloc_file(char *);
+void check(struct kinfo_proc *);
+struct fileinfo *getfileinfo(struct vnode *);
+void print(void);
+void printff(struct f_file *, int);
+void usage(void);
+
+kvm_t *kd;
+SLIST_HEAD(, f_file) filelist;
+int nprocs = 0; /* # of processes given to us by kvm_getprocs() */
+int uflag = 0; /* print usernames to stderr */
+int cflag = 0; /* find all files open under this device */
+int fflag = 0; /* mainly for show */
+int error = 0; /* exit > 0 on error */
+extern char *__progname;
+
+/*
+ * list process IDs of all processes that have one or more files open
+ */
+int
+main(int argc, char **argv)
+{
+ char errbuf[_POSIX2_LINE_MAX];
+ char *memf, *nlistf;
+ struct kinfo_proc *kp;
+ int i, ch;
+ struct f_file *ff;
+
+ memf = nlistf = NULL;
+ SLIST_INIT(&filelist);
+
+ while ((ch = getopt(argc, argv, "cufN:M:")) != -1)
+ switch(ch) {
+ case 'c':
+ cflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ default:
+ usage();
+ }
+
+ if (fflag && cflag) {
+ fprintf(stderr, "%s: 'f' and 'c' cannot be used together\n",
+ __progname);
+ usage();
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc == 0)
+ usage();
+
+ if (nlistf != NULL || memf != NULL) {
+ setegid(getgid());
+ setgid(getgid());
+ }
+
+ kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ if (kd == NULL)
+ errx(1, "%s", errbuf);
+
+ setgid(getgid());
+
+ kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs);
+ if (kp == NULL)
+ errx(1, "%s", kvm_geterr(kd));
+
+ for (i = 0; argv[i] != NULL && i < argc; i++) {
+ ff = alloc_file(argv[i]);
+ if (ff == NULL) {
+ error++;
+ warn("%s", argv[i]);
+ continue;
+ }
+ SLIST_INSERT_HEAD(&filelist, ff, f_next);
+ }
+
+ for (i = 0; i < nprocs; ++kp, i++) {
+ if (kp->ki_stat == SZOMB)
+ continue;
+
+ check(kp);
+ }
+
+ kvm_close(kd);
+
+ print();
+
+ return(error);
+}
+
+/*
+ * print out all the information we have gathered
+ */
+void
+print(void)
+{
+ struct f_file *ff;
+ int i;
+
+ SLIST_FOREACH(ff, &filelist, f_next) {
+ fprintf(stderr, "%s: ", ff->f_name);
+ for (i = 0; i < ff->f_nuids; i++)
+ if (ff->f_flags[i] != 0)
+ printff(ff, i);
+
+ fflush(stdout);
+ fprintf(stderr, "\n");
+ }
+
+ return;
+}
+
+/*
+ * print out the specfics for a given file/filesystem
+ */
+void
+printff(struct f_file *ff, int i)
+{
+ struct passwd *pwd;
+
+ printf("%d", ff->f_pids[i]);
+ fflush(stdout);
+
+ if (ff->f_flags[i] & F_CWD)
+ fprintf(stderr, "c");
+
+ if (ff->f_flags[i] & F_ROOT)
+ fprintf(stderr, "r");
+
+ if (uflag) {
+ pwd = getpwuid(ff->f_uids[i]);
+ if (pwd != NULL)
+ fprintf(stderr, "(%s)", pwd->pw_name);
+ else
+ fprintf(stderr, "(%d)", ff->f_uids[i]);
+ }
+
+ putchar(' ');
+}
+
+struct fproc *
+alloc_fproc(struct kinfo_proc *kp)
+{
+ struct fproc *fp;
+
+ fp = malloc(sizeof(struct fproc));
+ if (fp == NULL)
+ return(NULL);
+
+ memset(fp, 0, sizeof(struct fproc));
+ fp->fp_pid = kp->ki_pid;
+ fp->fp_uid = kp->ki_ruid;
+
+ return(fp);
+}
+
+/*
+ * return 1 if the file watched (ff) is
+ * equivalent to a file held by a process (fi)
+ */
+int
+match(struct f_file *ff, struct fileinfo *fi)
+{
+ if (fi->fi_dev == ff->f_dev) {
+ if (cflag)
+ return(1);
+ if (fi->fi_inode == ff->f_file)
+ return(1);
+ }
+
+ return(0);
+}
+
+/*
+ * examine all files held open by a process and record the details if they
+ * are of interest to us.
+ */
+void
+check(struct kinfo_proc *kp)
+{
+ struct f_file *ff;
+ struct fproc *fp;
+
+ fp = alloc_fproc(kp);
+ if (fp == NULL) {
+ error++;
+ warn("alloc fp");
+ return;
+ }
+
+ if (!getprocfdtable(kp, fp))
+ return;
+
+ SLIST_FOREACH(ff, &filelist, f_next) {
+
+ ff->f_uids[ff->f_nuids] = fp->fp_uid;
+ ff->f_pids[ff->f_nuids] = fp->fp_pid;
+
+ if (fileopened(ff, fp))
+ ff->f_flags[ff->f_nuids] |= F_OPEN;
+
+ if (fileroot(ff, fp))
+ ff->f_flags[ff->f_nuids] |= F_ROOT;
+
+ if (filecwd(ff, fp))
+ ff->f_flags[ff->f_nuids] |= F_CWD;
+
+ ff->f_nuids++;
+ }
+
+}
+
+/*
+ * see if the process (fp) has a specific file (ff) opened
+ */
+int
+fileopened(struct f_file *ff, struct fproc *fp)
+{
+ struct file f;
+ struct fileinfo *fi;
+ int i;
+
+ for (i = 0; i < fp->fp_nfiles; i++) {
+
+ if (fp->fp_fvec[i] == NULL)
+ continue;
+
+ if (!KVM_READ(fp->fp_fvec[i], &f, sizeof(f)))
+ continue;
+
+ if (f.f_type != DTYPE_VNODE)
+ continue;
+
+ fi = getfileinfo((struct vnode *)f.f_data);
+ if (fi == NULL)
+ continue;
+
+ if (match(ff, fi))
+ return(1);
+
+ }
+
+ return(0);
+}
+
+/*
+ * see if a processes (fp) root directory is a file we're interested in (ff)
+ */
+int
+fileroot(struct f_file *ff, struct fproc *fp)
+{
+ struct fileinfo *fi;
+
+ if (fp->fp_rdir == NULL)
+ return(0);
+
+ fi = getfileinfo(fp->fp_rdir);
+ if (fi == NULL)
+ return(0);
+
+ return(match(ff, fi));
+}
+
+/*
+ * see if a processes current working directory is a file we're interested in
+ */
+int
+filecwd(struct f_file *ff, struct fproc *fp)
+{
+ struct fileinfo *fi;
+
+ if (fp->fp_cdir == NULL)
+ return(0);
+
+ fi = getfileinfo(fp->fp_cdir);
+ if (fi == NULL)
+ return(0);
+
+ return(match(ff, fi));
+}
+
+/*
+ * read in a processes filedesc table
+ */
+int
+getprocfdtable(struct kinfo_proc *kp, struct fproc *fp)
+{
+ struct filedesc0 filed0;
+ int nfiles;
+ struct file **fvec;
+#define filed filed0.fd_fd
+
+ if (kp->ki_fd == NULL)
+ return;
+
+ if (!KVM_READ(kp->ki_fd, &filed0, sizeof(filed0)))
+ return(0);
+
+ nfiles = filed.fd_lastfile + 1;
+ fvec = calloc(nfiles, sizeof(struct file *));
+ if (fvec == NULL)
+ return(0);
+
+ memset(fvec, 0, nfiles * sizeof(struct file *));
+
+ if (filed.fd_nfiles < 0 || filed.fd_lastfile >= filed.fd_nfiles ||
+ filed.fd_freefile > filed.fd_lastfile + 1) {
+ fprintf(stderr, "filedesc corrupted for pid %d", kp->ki_pid);
+ return(0);
+ }
+
+ /*
+ * since we dont bother with filedesc0, just read from kvm
+ */
+ if (!KVM_READ(filed.fd_ofiles, fvec, nfiles * sizeof(struct file *)))
+ return(0);
+
+ fp->fp_rdir = filed.fd_rdir;
+ fp->fp_cdir = filed.fd_cdir;
+ fp->fp_fvec = fvec;
+ fp->fp_nfiles = nfiles;
+
+ return(1);
+}
+
+/*
+ * return pertinent information for the vnode located in kmem at address v
+ */
+struct fileinfo *
+getfileinfo(struct vnode *vp)
+{
+ struct fileinfo *fi;
+ struct vnode vn;
+ char tagstr[12], *tagptr;
+
+ fi = malloc(sizeof(struct fileinfo));
+ if (fi == NULL) {
+ error++;
+ warn("malloc failed");
+ return(NULL);
+ }
+
+ if (!KVM_READ(vp, &vn, sizeof(struct vnode))) {
+ error++;
+ warnx("rd vnode %s", kvm_geterr(kd));
+ return(NULL);
+ }
+ if (!KVM_READ(&vp->v_tag, &tagptr, sizeof tagptr)) {
+ error++;
+ warnx("rd vtag %s", kvm_geterr(kd));
+ return(NULL);
+ }
+ if (!KVM_READ(tagptr, tagstr, sizeof tagstr)) {
+ error++;
+ warnx("rd tagptr %s", kvm_geterr(kd));
+ return(NULL);
+ }
+
+ tagstr[sizeof(tagstr) - 1] = '\0';
+
+ if (vn.v_type == VBAD || vn.v_type == VNON)
+ return(NULL);
+
+ if (!strcmp("ufs", tagstr) || !strcmp("mfs", tagstr)) {
+ if (!ufs_filestat(&vn, fi))
+ return (NULL);
+ } else if (!strcmp("nfs", tagstr)) {
+ if (!nfs_filestat(&vn, fi))
+ return (NULL);
+ } else if (!strcmp("ext2fs", tagstr)) {
+ if (!ext2fs_filestat(&vn, fi))
+ return (NULL);
+ } else if (!strcmp("isofs", tagstr)) {
+ if (!isofs_filestat(&vn, fi))
+ return (NULL);
+ } else if (!strcmp("msdosfs", tagstr)) {
+ if (!msdos_filestat(&vn, fi))
+ return (NULL);
+ } else if (!strcmp("nullfs", tagstr)) {
+ if (!null_filestat(&vn, fi))
+ return(NULL);
+ }
+
+ return(fi);
+}
+
+struct f_file *
+alloc_file(char *fname)
+{
+ int i;
+ struct f_file *ff;
+ struct stat sb;
+ struct fstab *fstp;
+
+ ff = malloc(sizeof(struct f_file));
+ if (ff == NULL)
+ return(NULL);
+
+ memset(ff, 0, sizeof(struct f_file));
+
+ i = stat(fname, &sb);
+ if (i == -1) {
+ free(ff);
+ return(NULL);
+ }
+
+ /*
+ * not too sure what to do here, the spec states 'For block special
+ * devices, all processes using any file on that device are listed' and
+ * then on the -f option 'The report shall be only for the named
+ * files.' so what happens if you do 'fuser -f <blk dev>'? currently -f
+ * will be only for the block device, while 'fuser <blk dev>' will show
+ * all processes under that filesystem (if its in /etc/fstab).
+ */
+ if (sb.st_mode & S_IFBLK && fflag == 0) {
+ fstp = getfsspec(fname);
+ if (fstp != NULL) {
+ i = stat(fstp->fs_file, &sb);
+ if (i == -1) {
+ free(ff);
+ return(NULL);
+ }
+ cflag = 1;
+ }
+ }
+
+ ff->f_file = sb.st_ino;
+ ff->f_dev = sb.st_dev & 0xffff;
+
+ /*
+ * calloc will memset for us regardless of /etc/malloc.conf
+ */
+ ff->f_uids = calloc(nprocs + 1, sizeof(uid_t));
+ if (ff->f_uids == NULL) {
+ free(ff);
+ return(NULL);
+ }
+
+ ff->f_pids = calloc(nprocs + 1, sizeof(pid_t));
+ if (ff->f_pids == NULL) {
+ free(ff->f_uids);
+ free(ff);
+ return(NULL);
+ }
+
+ ff->f_flags = calloc(nprocs + 1, sizeof(int));
+ if (ff->f_flags == NULL) {
+ free(ff->f_pids);
+ free(ff->f_uids);
+ free(ff);
+ return(NULL);
+ }
+
+ ff->f_name = strdup(fname);
+ if (ff->f_name == NULL) {
+ free(ff->f_flags);
+ free(ff->f_pids);
+ free(ff->f_uids);
+ free(ff);
+ return(NULL);
+ }
+
+ ff->f_nuids = 0;
+
+ return(ff);
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "%s: [ -cfu ] [ -M core ] [ -N system ] file ...\n",
+ __progname);
+ exit(1);
+}
diff -ruN /usr/src/usr.bin/fuser/fuser.h usr.bin/fuser/fuser.h
--- /usr/src/usr.bin/fuser/fuser.h Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/fuser.h Wed Jun 4 18:50:39 2003
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002 Peter Werner <peterw at ifost.org.au>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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.
+ */
+#ifndef __fuser_h
+#define __fuser_h
+
+#include <sys/types.h>
+
+struct fileinfo {
+ dev_t fi_dev;
+ ino_t fi_inode;
+};
+
+/*
+ * functions from fstat
+ */
+int ufs_filestat(struct vnode *, struct fileinfo *);
+int ext2fs_filestat(struct vnode *, struct fileinfo *);
+int isofs_filestat(struct vnode *, struct fileinfo *);
+int msdos_filestat(struct vnode *, struct fileinfo *);
+int nfs_filestat(struct vnode *, struct fileinfo *);
+int null_filestat(struct vnode *, struct fileinfo *);
+
+/*
+ * a kvm_read that returns true if everything is read
+ */
+#define KVM_READ(kaddr, paddr, len) \
+ (kvm_read(kd, (u_long)(kaddr), (void *)(paddr), (len)) == (len))
+
+#endif /* ! __fuser_h */
diff -ruN /usr/src/usr.bin/fuser/isofs.c usr.bin/fuser/isofs.c
--- /usr/src/usr.bin/fuser/isofs.c Thu Jan 1 01:00:00 1970
+++ usr.bin/fuser/isofs.c Tue Jun 24 16:02:23 2003
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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.
+ * 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/vnode.h>
+#include <sys/sysctl.h>
+#define _KERNEL
+#include <sys/mount.h>
+#undef _KERNEL
+
+#include <isofs/cd9660/iso.h>
+#include <isofs/cd9660/cd9660_node.h>
+
+#include <kvm.h>
+
+#include "fuser.h"
+
+extern kvm_t *kd;
+
+int
+isofs_filestat(struct vnode *vp, struct fileinfo *fi)
+{
+ struct iso_node inode;
+
+ if (!KVM_READ(VTOI(vp), &inode, sizeof (inode)))
+ return 0;
+
+ fi->fi_dev = inode.i_dev & 0xffff;
+ fi->fi_inode = (long)inode.i_number;
+ return 1;
+}
--- fuser.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list