From owner-freebsd-bugs@FreeBSD.ORG Tue Jun 24 07:20:10 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 22F1737B401 for ; Tue, 24 Jun 2003 07:20:09 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id EA83043FBF for ; Tue, 24 Jun 2003 07:20:07 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h5OEK7Up085772 for ; Tue, 24 Jun 2003 07:20:07 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h5OEK7Pr085771; Tue, 24 Jun 2003 07:20:07 -0700 (PDT) Resent-Date: Tue, 24 Jun 2003 07:20:07 -0700 (PDT) Resent-Message-Id: <200306241420.h5OEK7Pr085771@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Lukas Ertl Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 2F4A537B401 for ; Tue, 24 Jun 2003 07:14:48 -0700 (PDT) Received: from mailbox.univie.ac.at (mail.univie.ac.at [131.130.1.27]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1DBB543FE0 for ; Tue, 24 Jun 2003 07:14:46 -0700 (PDT) (envelope-from le@univie.ac.at) Received: from leelou.in.tern (adslle.cc.univie.ac.at [131.130.102.11]) by mailbox.univie.ac.at (8.12.2/8.12.2) with ESMTP id h5OEESZs278090 for ; Tue, 24 Jun 2003 16:14:31 +0200 Received: from leelou.in.tern (leelou [127.0.0.1]) by leelou.in.tern (8.12.9/8.12.9) with ESMTP id h5OEESqs016292 for ; Tue, 24 Jun 2003 16:14:28 +0200 (CEST) (envelope-from le@leelou.in.tern) Received: (from le@localhost) by leelou.in.tern (8.12.9/8.12.9/Submit) id h5OEER3v016291; Tue, 24 Jun 2003 16:14:27 +0200 (CEST) (envelope-from le) Message-Id: <200306241414.h5OEER3v016291@leelou.in.tern> Date: Tue, 24 Jun 2003 16:14:27 +0200 (CEST) From: Lukas Ertl To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/53682: [PATCH] add fuser(1) utitity X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Lukas Ertl List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Jun 2003 14:20:11 -0000 >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@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 . 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#define _KERNEL +#include +#include +#include +#include +#include +#include +#undef _KERNEL +#include +#include +#include +#include + +#include +#include + +#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 +.\" 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 + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#define _KERNEL +#include +#include +#include +#include +#include +#undef _KERNEL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 '? currently -f + * will be only for the block device, while 'fuser ' 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 + * 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 + +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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#define _KERNEL +#include +#undef _KERNEL + +#include +#include + +#include + +#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: