- Commit work from libprocstat project. These patches add support for runtime
file and processes information retrieval from the running kernel via sysctl in the form of new library, libprocstat. The library also supports KVM backend for analyzing memory crash dumps. Both procstat(1) and fstat(1) utilities have been modified to take advantage of the library (as the bonus point the fstat(1) utility no longer need superuser privileges to operate), and the procstat(1) utility is now able to display information from memory dumps as well. The newly introduced fuser(1) utility also uses this library and able to operate via sysctl and kvm backends. The library is by no means complete (e.g. KVM backend is missing vnode name resolution routines, and there're no manpages for the library itself) so I plan to improve it further. I'm commiting it so it will get wider exposure and review. We won't be able to MFC this work as it relies on changes in HEAD, which was introduced some time ago, that break kernel ABI. OTOH we may be able to merge the library with KVM backend if we really need it there. Discussed with: rwatson
This commit is contained in:
parent
4b5404a9de
commit
0daf62d9f5
@ -92,6 +92,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
|
||||
${_libpkg} \
|
||||
${_libpmc} \
|
||||
${_libproc} \
|
||||
libprocstat \
|
||||
librt \
|
||||
${_librtld_db} \
|
||||
${_libsdp} \
|
||||
|
36
lib/libprocstat/Makefile
Normal file
36
lib/libprocstat/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
LIB= procstat
|
||||
|
||||
SRCS= cd9660.c \
|
||||
common_kvm.c \
|
||||
libprocstat.c \
|
||||
msdosfs.c \
|
||||
ntfs.c \
|
||||
nwfs.c \
|
||||
smbfs.c \
|
||||
udf.c
|
||||
|
||||
INCS= libprocstat.h
|
||||
CFLAGS+= -I. -I${.CURDIR} -D_KVM_VNODE
|
||||
SHLIB_MAJOR= 1
|
||||
WITHOUT_MAN= yes
|
||||
|
||||
# XXX This is a hack.
|
||||
.if ${MK_CDDL} != "no"
|
||||
CFLAGS+= -DZFS
|
||||
OBJS+= zfs/zfs.o
|
||||
SOBJS+= zfs/zfs.So
|
||||
POBJS+= zfs/zfs.po
|
||||
SUBDIR= zfs
|
||||
zfs/zfs.o: .PHONY
|
||||
@cd ${.CURDIR}/zfs && ${MAKE} zfs.o
|
||||
zfs/zfs.So: .PHONY
|
||||
@cd ${.CURDIR}/zfs && ${MAKE} zfs.So
|
||||
zfs/zfs.po: .PHONY
|
||||
@cd ${.CURDIR}/zfs && ${MAKE} zfs.po
|
||||
.endif
|
||||
|
||||
.include <bsd.lib.mk>
|
@ -49,31 +49,42 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <err.h>
|
||||
|
||||
#include <isofs/cd9660/cd9660_node.h>
|
||||
#define _KERNEL
|
||||
#include <isofs/cd9660/iso.h>
|
||||
#undef _KERNEL
|
||||
|
||||
#include <kvm.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "fstat.h"
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
int
|
||||
isofs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct iso_node isonode;
|
||||
struct iso_mnt mnt;
|
||||
|
||||
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 (!kvm_read_all(kd, (unsigned long)VTOI(vp), &isonode,
|
||||
sizeof(isonode))) {
|
||||
warnx("can't read iso_node at %p",
|
||||
(void *)VTOI(vp));
|
||||
return (1);
|
||||
}
|
||||
#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;
|
||||
if (!kvm_read_all(kd, (unsigned long)isonode.i_mnt, &mnt,
|
||||
sizeof(mnt))) {
|
||||
warnx("can't read iso_mnt at %p",
|
||||
(void *)VTOI(vp));
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fsid = dev2udev(kd, mnt.im_dev);
|
||||
vn->vn_mode = (mode_t)isonode.inode.iso_mode;
|
||||
vn->vn_fileid = (long)isonode.i_number;
|
||||
vn->vn_size = (u_long)isonode.i_size;
|
||||
return (0);
|
||||
}
|
||||
|
207
lib/libprocstat/common_kvm.c
Normal file
207
lib/libprocstat/common_kvm.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
|
||||
* 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/user.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vnode.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 <assert.h>
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libprocstat.h>
|
||||
#include "common_kvm.h"
|
||||
|
||||
int
|
||||
kvm_read_all(kvm_t *kd, unsigned long addr, void *buf, size_t nbytes)
|
||||
{
|
||||
ssize_t error;
|
||||
|
||||
if (nbytes >= SSIZE_MAX)
|
||||
return (0);
|
||||
error = kvm_read(kd, addr, buf, nbytes);
|
||||
return (error == (ssize_t)(nbytes));
|
||||
}
|
||||
|
||||
int
|
||||
kdevtoname(kvm_t *kd, struct cdev *dev, char *buf)
|
||||
{
|
||||
struct cdev si;
|
||||
|
||||
assert(buf);
|
||||
if (!kvm_read_all(kd, (unsigned long)dev, &si, sizeof(si)))
|
||||
return (1);
|
||||
strlcpy(buf, si.__si_namebuf, SPECNAMELEN + 1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct inode inode;
|
||||
|
||||
if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &inode, sizeof(inode))) {
|
||||
warnx("can't read inode at %p", (void *)VTOI(vp));
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
vn->vn_fsid = dev2udev(kd, inode.i_dev);
|
||||
vn->vn_fileid = (long)inode.i_number;
|
||||
vn->vn_mode = (mode_t)inode.i_mode;
|
||||
vn->vn_size = (u_long)inode.i_size;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct devfs_dirent devfs_dirent;
|
||||
struct mount mount;
|
||||
|
||||
if (!kvm_read_all(kd, (unsigned long)getvnodedata(vp), &devfs_dirent,
|
||||
sizeof(devfs_dirent))) {
|
||||
warnx("can't read devfs_dirent at %p",
|
||||
(void *)vp->v_data);
|
||||
return (1);
|
||||
}
|
||||
if (!kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mount,
|
||||
sizeof(mount))) {
|
||||
warnx("can't read mount at %p",
|
||||
(void *)getvnodemount(vp));
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
|
||||
vn->vn_fileid = devfs_dirent.de_inode;
|
||||
vn->vn_mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
|
||||
vn->vn_size = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct nfsnode nfsnode;
|
||||
mode_t mode;
|
||||
|
||||
if (!kvm_read_all(kd, (unsigned long)VTONFS(vp), &nfsnode,
|
||||
sizeof(nfsnode))) {
|
||||
warnx("can't read nfsnode at %p",
|
||||
(void *)VTONFS(vp));
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fsid = nfsnode.n_vattr.va_fsid;
|
||||
vn->vn_fileid = nfsnode.n_vattr.va_fileid;
|
||||
vn->vn_size = nfsnode.n_size;
|
||||
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;
|
||||
break;
|
||||
case VLNK:
|
||||
mode |= S_IFLNK;
|
||||
break;
|
||||
case VSOCK:
|
||||
mode |= S_IFSOCK;
|
||||
break;
|
||||
case VFIFO:
|
||||
mode |= S_IFIFO;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
vn->vn_mode = mode;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the cdev structure in the kernel in order to work out the
|
||||
* associated dev_t
|
||||
*/
|
||||
dev_t
|
||||
dev2udev(kvm_t *kd, struct cdev *dev)
|
||||
{
|
||||
struct cdev_priv priv;
|
||||
|
||||
assert(kd);
|
||||
if (kvm_read_all(kd, (unsigned long)cdev2priv(dev), &priv,
|
||||
sizeof(priv))) {
|
||||
return ((dev_t)priv.cdp_inode);
|
||||
} else {
|
||||
warnx("can't convert cdev *%p to a dev_t\n", dev);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
getvnodedata(struct vnode *vp)
|
||||
{
|
||||
return (vp->v_data);
|
||||
}
|
||||
|
||||
struct mount *
|
||||
getvnodemount(struct vnode *vp)
|
||||
{
|
||||
return (vp->v_mount);
|
||||
}
|
@ -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
|
||||
@ -29,48 +26,28 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef __FSTAT_H__
|
||||
#define __FSTAT_H__
|
||||
#ifndef _COMMON_KVM_H_
|
||||
#define _COMMON_KVM_H_
|
||||
|
||||
dev_t dev2udev(kvm_t *kd, struct cdev *dev);
|
||||
int kdevtoname(kvm_t *kd, struct cdev *dev, char *);
|
||||
int kvm_read_all(kvm_t *kd, unsigned long addr, void *buf,
|
||||
size_t nbytes);
|
||||
|
||||
/*
|
||||
* a kvm_read that returns true if everything is read
|
||||
* Filesystems specific access routines.
|
||||
*/
|
||||
#define KVM_READ(kaddr, paddr, len) \
|
||||
((len) < SSIZE_MAX && \
|
||||
kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (ssize_t)(len))
|
||||
int devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int nwfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int smbfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
int zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn);
|
||||
void *getvnodedata(struct vnode *vp);
|
||||
struct mount *getvnodemount(struct vnode *vp);
|
||||
|
||||
#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 /* _COMMON_KVM_H_ */
|
1306
lib/libprocstat/libprocstat.c
Normal file
1306
lib/libprocstat/libprocstat.c
Normal file
File diff suppressed because it is too large
Load Diff
160
lib/libprocstat/libprocstat.h
Normal file
160
lib/libprocstat/libprocstat.h
Normal file
@ -0,0 +1,160 @@
|
||||
/*-
|
||||
* 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 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$
|
||||
*/
|
||||
|
||||
#ifndef _LIBPROCSTAT_H_
|
||||
#define _LIBPROCSTAT_H_
|
||||
|
||||
/*
|
||||
* Vnode types.
|
||||
*/
|
||||
#define PS_FST_VTYPE_VNON 1
|
||||
#define PS_FST_VTYPE_VREG 2
|
||||
#define PS_FST_VTYPE_VDIR 3
|
||||
#define PS_FST_VTYPE_VBLK 4
|
||||
#define PS_FST_VTYPE_VCHR 5
|
||||
#define PS_FST_VTYPE_VLNK 6
|
||||
#define PS_FST_VTYPE_VSOCK 7
|
||||
#define PS_FST_VTYPE_VFIFO 8
|
||||
#define PS_FST_VTYPE_VBAD 9
|
||||
#define PS_FST_VTYPE_UNKNOWN 255
|
||||
|
||||
/*
|
||||
* Descriptor types.
|
||||
*/
|
||||
#define PS_FST_TYPE_VNODE 1
|
||||
#define PS_FST_TYPE_FIFO 2
|
||||
#define PS_FST_TYPE_SOCKET 3
|
||||
#define PS_FST_TYPE_PIPE 4
|
||||
#define PS_FST_TYPE_PTS 5
|
||||
#define PS_FST_TYPE_KQUEUE 6
|
||||
#define PS_FST_TYPE_CRYPTO 7
|
||||
#define PS_FST_TYPE_MQUEUE 8
|
||||
#define PS_FST_TYPE_SHM 9
|
||||
#define PS_FST_TYPE_SEM 10
|
||||
#define PS_FST_TYPE_UNKNOWN 11
|
||||
#define PS_FST_TYPE_NONE 12
|
||||
|
||||
/*
|
||||
* Special descriptor numbers.
|
||||
*/
|
||||
#define PS_FST_UFLAG_RDIR 0x0001
|
||||
#define PS_FST_UFLAG_CDIR 0x0002
|
||||
#define PS_FST_UFLAG_JAIL 0x0004
|
||||
#define PS_FST_UFLAG_TRACE 0x0008
|
||||
#define PS_FST_UFLAG_TEXT 0x0010
|
||||
#define PS_FST_UFLAG_MMAP 0x0020
|
||||
#define PS_FST_UFLAG_CTTY 0x0040
|
||||
|
||||
/*
|
||||
* Descriptor flags.
|
||||
*/
|
||||
#define PS_FST_FFLAG_READ 0x0001
|
||||
#define PS_FST_FFLAG_WRITE 0x0002
|
||||
#define PS_FST_FFLAG_NONBLOCK 0x0004
|
||||
#define PS_FST_FFLAG_APPEND 0x0008
|
||||
#define PS_FST_FFLAG_SHLOCK 0x0010
|
||||
#define PS_FST_FFLAG_EXLOCK 0x0020
|
||||
#define PS_FST_FFLAG_ASYNC 0x0040
|
||||
#define PS_FST_FFLAG_SYNC 0x0080
|
||||
#define PS_FST_FFLAG_NOFOLLOW 0x0100
|
||||
#define PS_FST_FFLAG_CREAT 0x0200
|
||||
#define PS_FST_FFLAG_TRUNC 0x0400
|
||||
#define PS_FST_FFLAG_EXCL 0x0800
|
||||
#define PS_FST_FFLAG_DIRECT 0x1000
|
||||
#define PS_FST_FFLAG_EXEC 0x2000
|
||||
#define PS_FST_FFLAG_HASLOCK 0x4000
|
||||
|
||||
struct procstat;
|
||||
struct filestat {
|
||||
int fs_type; /* Descriptor type. */
|
||||
int fs_flags; /* filestat specific flags. */
|
||||
int fs_fflags; /* Descriptor access flags. */
|
||||
int fs_uflags; /* How this file is used. */
|
||||
int fs_fd; /* File descriptor number. */
|
||||
int fs_ref_count; /* Reference count. */
|
||||
off_t fs_offset; /* Seek location. */
|
||||
void *fs_typedep; /* Type dependent data. */
|
||||
char *fs_path;
|
||||
STAILQ_ENTRY(filestat) next;
|
||||
};
|
||||
struct vnstat {
|
||||
uint64_t vn_fileid;
|
||||
uint64_t vn_size;
|
||||
char *vn_mntdir;
|
||||
uint32_t vn_dev;
|
||||
uint32_t vn_fsid;
|
||||
int vn_type;
|
||||
uint16_t vn_mode;
|
||||
char vn_devname[SPECNAMELEN + 1];
|
||||
};
|
||||
struct ptsstat {
|
||||
uint32_t dev;
|
||||
char devname[SPECNAMELEN + 1];
|
||||
};
|
||||
struct pipestat {
|
||||
size_t buffer_cnt;
|
||||
uint64_t addr;
|
||||
uint64_t peer;
|
||||
};
|
||||
struct sockstat {
|
||||
uint64_t inp_ppcb;
|
||||
uint64_t so_addr;
|
||||
uint64_t so_pcb;
|
||||
uint64_t unp_conn;
|
||||
int dom_family;
|
||||
int proto;
|
||||
int so_rcv_sb_state;
|
||||
int so_snd_sb_state;
|
||||
struct sockaddr_storage sa_local; /* Socket address. */
|
||||
struct sockaddr_storage sa_peer; /* Peer address. */
|
||||
int type;
|
||||
char dname[32];
|
||||
};
|
||||
|
||||
STAILQ_HEAD(filestat_list, filestat);
|
||||
|
||||
void procstat_close(struct procstat *procstat);
|
||||
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
|
||||
void procstat_freefiles(struct procstat *procstat,
|
||||
struct filestat_list *head);
|
||||
struct filestat_list *procstat_getfiles(struct procstat *procstat,
|
||||
struct kinfo_proc *kp, int mmapped);
|
||||
struct kinfo_proc *procstat_getprocs(struct procstat *procstat,
|
||||
int what, int arg, unsigned int *count);
|
||||
int procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct pipestat *pipe, char *errbuf);
|
||||
int procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct ptsstat *pts, char *errbuf);
|
||||
int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct sockstat *sock, char *errbuf);
|
||||
int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
|
||||
struct vnstat *vn, char *errbuf);
|
||||
struct procstat *procstat_open_sysctl(void);
|
||||
struct procstat *procstat_open_kvm(const char *nlistf, const char *memf);
|
||||
|
||||
#endif /* !_LIBPROCSTAT_H_ */
|
39
lib/libprocstat/libprocstat_internal.h
Normal file
39
lib/libprocstat/libprocstat_internal.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*-
|
||||
* 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 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$
|
||||
*/
|
||||
|
||||
#ifndef _LIBPROCSTAT_INTERNAL_H_
|
||||
#define _LIBPROCSTAT_INTERNAL_H_
|
||||
|
||||
struct procstat {
|
||||
int type;
|
||||
kvm_t *kd;
|
||||
void *vmentries;
|
||||
void *files;
|
||||
};
|
||||
|
||||
#endif /* !_LIBPROCSTAT_INTERNAL_H_ */
|
@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/stat.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define _KERNEL
|
||||
#include <sys/mount.h>
|
||||
#include <fs/msdosfs/bpb.h>
|
||||
@ -62,9 +64,10 @@ __FBSDID("$FreeBSD$");
|
||||
* 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)
|
||||
#define VTODE(vp) ((struct denode *)getvnodedata(vp))
|
||||
|
||||
#include "fstat.h"
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
struct dosmount {
|
||||
struct dosmount *next;
|
||||
@ -73,7 +76,7 @@ struct dosmount {
|
||||
};
|
||||
|
||||
int
|
||||
msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct denode denode;
|
||||
static struct dosmount *mounts;
|
||||
@ -81,10 +84,10 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
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;
|
||||
if (!kvm_read_all(kd, (unsigned long)VTODE(vp), &denode,
|
||||
sizeof(denode))) {
|
||||
warnx("can't read denode at %p", (void *)VTODE(vp));
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -96,30 +99,30 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
break;
|
||||
|
||||
if (!mnt) {
|
||||
if ((mnt = malloc(sizeof(struct dosmount))) == NULL)
|
||||
err(1, NULL);
|
||||
if (!KVM_READ(denode.de_pmp, &mnt->data, sizeof mnt->data)) {
|
||||
if ((mnt = malloc(sizeof(struct dosmount))) == NULL) {
|
||||
warn("malloc()");
|
||||
return (1);
|
||||
}
|
||||
if (!kvm_read_all(kd, (unsigned long)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;
|
||||
warnx("can't read mount info at %p",
|
||||
(void *)denode.de_pmp);
|
||||
return (1);
|
||||
}
|
||||
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;
|
||||
vn->vn_fsid = dev2udev(kd, mnt->data.pm_dev);
|
||||
vn->vn_mode = 0555;
|
||||
vn->vn_mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222;
|
||||
vn->vn_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;
|
||||
vn->vn_mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG;
|
||||
vn->vn_size = denode.de_FileSize;
|
||||
|
||||
/*
|
||||
* XXX -
|
||||
@ -145,6 +148,6 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
fileid += denode.de_diroffset / sizeof(struct direntry);
|
||||
}
|
||||
|
||||
fsp->fileid = fileid;
|
||||
return 1;
|
||||
vn->vn_fileid = fileid;
|
||||
return (0);
|
||||
}
|
71
lib/libprocstat/ntfs.c
Normal file
71
lib/libprocstat/ntfs.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* 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/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/ntfs/ntfs.h>
|
||||
#include <fs/ntfs/ntfs_inode.h>
|
||||
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
int
|
||||
ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct fnode fnod;
|
||||
struct ntnode node;
|
||||
int error;
|
||||
|
||||
assert(kd);
|
||||
assert(vn);
|
||||
error = kvm_read_all(kd, (unsigned long)VTOF(vp), &fnod, sizeof(fnod));
|
||||
if (error != 0) {
|
||||
warnx("can't read ntfs fnode at %p", (void *)VTOF(vp));
|
||||
return (1);
|
||||
}
|
||||
error = kvm_read_all(kd, (unsigned long)FTONT(&fnod), &node,
|
||||
sizeof(node));
|
||||
if (error != 0) {
|
||||
warnx("can't read ntfs node at %p", (void *)FTONT(&fnod));
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fileid = node.i_number;
|
||||
vn->vn_fsid = dev2udev(kd, node.i_dev);
|
||||
return (0);
|
||||
}
|
76
lib/libprocstat/nwfs.c
Normal file
76
lib/libprocstat/nwfs.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*-
|
||||
* 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/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/vnode.h>
|
||||
#define _KERNEL
|
||||
#include <sys/mount.h>
|
||||
#undef _KERNEL
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/nwfs/nwfs.h>
|
||||
#include <fs/nwfs/nwfs_node.h>
|
||||
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
int
|
||||
nwfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct mount mnt;
|
||||
struct nwnode node;
|
||||
int error;
|
||||
|
||||
assert(kd);
|
||||
assert(vn);
|
||||
error = kvm_read_all(kd, (unsigned long)VTONW(vp), &node, sizeof(node));
|
||||
if (error != 0) {
|
||||
warnx("can't read nwfs fnode at %p", (void *)VTONW(vp));
|
||||
return (1);
|
||||
}
|
||||
error = kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mnt,
|
||||
sizeof(mnt));
|
||||
if (error != 0) {
|
||||
warnx("can't read mount at %p for vnode %p",
|
||||
(void *)getvnodemount(vp), vp);
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fileid = node.n_fid.f_id;
|
||||
if (vn->vn_fileid == 0)
|
||||
vn->vn_fileid = NWFS_ROOT_INO;
|
||||
vn->vn_fsid = mnt.mnt_stat.f_fsid.val[0];
|
||||
return (0);
|
||||
}
|
77
lib/libprocstat/smbfs.c
Normal file
77
lib/libprocstat/smbfs.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* 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/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/vnode.h>
|
||||
#define _KERNEL
|
||||
#include <sys/mount.h>
|
||||
#undef _KERNEL
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/smbfs/smbfs.h>
|
||||
#include <fs/smbfs/smbfs_node.h>
|
||||
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
int
|
||||
smbfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct smbnode node;
|
||||
struct mount mnt;
|
||||
int error;
|
||||
|
||||
assert(kd);
|
||||
assert(vn);
|
||||
error = kvm_read_all(kd, (unsigned long)VTOSMB(vp), &node,
|
||||
sizeof(node));
|
||||
if (error != 0) {
|
||||
warnx("can't read smbfs fnode at %p", (void *)VTOSMB(vp));
|
||||
return (1);
|
||||
}
|
||||
error = kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mnt,
|
||||
sizeof(mnt));
|
||||
if (error != 0) {
|
||||
warnx("can't read mount at %p for vnode %p",
|
||||
(void *)getvnodemount(vp), vp);
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fileid = node.n_ino;
|
||||
if (vn->vn_fileid == 0)
|
||||
vn->vn_fileid = 2;
|
||||
vn->vn_fsid = mnt.mnt_stat.f_fsid.val[0];
|
||||
return (0);
|
||||
}
|
102
lib/libprocstat/udf.c
Normal file
102
lib/libprocstat/udf.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*-
|
||||
* 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/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/buf.h>
|
||||
#define _KERNEL
|
||||
#include <sys/mount.h>
|
||||
#undef _KERNEL
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <fs/udf/ecma167-udf.h>
|
||||
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
/* XXX */
|
||||
struct udf_mnt {
|
||||
int im_flags;
|
||||
struct mount *im_mountp;
|
||||
struct g_consumer *im_cp;
|
||||
struct bufobj *im_bo;
|
||||
struct cdev *im_dev;
|
||||
struct vnode *im_devvp;
|
||||
int bsize;
|
||||
int bshift;
|
||||
int bmask;
|
||||
uint32_t part_start;
|
||||
uint32_t part_len;
|
||||
uint64_t root_id;
|
||||
struct long_ad root_icb;
|
||||
int p_sectors;
|
||||
int s_table_entries;
|
||||
void *s_table;
|
||||
void *im_d2l;
|
||||
};
|
||||
struct udf_node {
|
||||
struct vnode *i_vnode;
|
||||
struct udf_mnt *udfmp;
|
||||
ino_t hash_id;
|
||||
long diroff;
|
||||
struct file_entry *fentry;
|
||||
};
|
||||
#define VTON(vp) ((struct udf_node *)((vp)->v_data))
|
||||
|
||||
int
|
||||
udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
struct udf_node node;
|
||||
struct udf_mnt mnt;
|
||||
int error;
|
||||
|
||||
assert(kd);
|
||||
assert(vn);
|
||||
error = kvm_read_all(kd, (unsigned long)VTON(vp), &node, sizeof(node));
|
||||
if (error != 0) {
|
||||
warnx("can't read udf fnode at %p", (void *)VTON(vp));
|
||||
return (1);
|
||||
}
|
||||
error = kvm_read_all(kd, (unsigned long)node.udfmp, &mnt, sizeof(mnt));
|
||||
if (error != 0) {
|
||||
warnx("can't read udf_mnt at %p for vnode %p",
|
||||
(void *)node.udfmp, vp);
|
||||
return (1);
|
||||
}
|
||||
vn->vn_fileid = node.hash_id;
|
||||
vn->vn_fsid = dev2udev(kd, mnt.im_dev);
|
||||
return (0);
|
||||
}
|
@ -45,14 +45,16 @@
|
||||
#include <sys/zfs_znode.h>
|
||||
#include <sys/zfs_sa.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ZFS
|
||||
#undef dprintf
|
||||
#include <fstat.h>
|
||||
#include "libprocstat.h"
|
||||
#include "common_kvm.h"
|
||||
|
||||
/*
|
||||
* Offset calculations that are used to get data from znode without having the
|
||||
@ -62,7 +64,7 @@
|
||||
#define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task)))
|
||||
|
||||
int
|
||||
zfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
|
||||
{
|
||||
|
||||
znode_phys_t zphys;
|
||||
@ -76,20 +78,19 @@ zfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
|
||||
len = sizeof(size);
|
||||
if (sysctlbyname("debug.sizeof.znode", &size, &len, NULL, 0) == -1) {
|
||||
dprintf(stderr, "error getting sysctl\n");
|
||||
return (0);
|
||||
warnx("error getting sysctl");
|
||||
return (1);
|
||||
}
|
||||
znodeptr = malloc(size);
|
||||
if (znodeptr == NULL) {
|
||||
dprintf(stderr, "error allocating memory for znode storage\n");
|
||||
return (0);
|
||||
warnx("error allocating memory for znode storage");
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (!kvm_read_all(kd, (unsigned long)vnodeptr, znodeptr,
|
||||
(size_t)size)) {
|
||||
warnx("can't read znode at %p", (void *)vnodeptr);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@ -104,33 +105,30 @@ zfs_filestat(struct vnode *vp, struct filestat *fsp)
|
||||
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);
|
||||
if (!kvm_read_all(kd, (unsigned long)zphys_addr, &zphys,
|
||||
sizeof(zphys))) {
|
||||
warnx("can't read znode_phys at %p", zphys_addr);
|
||||
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);
|
||||
if (!kvm_read_all(kd, (unsigned long)mountptr, &mount, sizeof(mount))) {
|
||||
warnx("can't read mount at %p", (void *)mountptr);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0];
|
||||
fsp->fileid = *zid;
|
||||
vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
|
||||
vn->vn_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:
|
||||
vn->vn_mode = (mode_t)zphys.zp_mode;
|
||||
vn->vn_size = (u_long)zphys.zp_size;
|
||||
free(znodeptr);
|
||||
return (0);
|
||||
bad:
|
||||
free(znodeptr);
|
||||
return (1);
|
||||
}
|
@ -9,7 +9,8 @@ LIB= util
|
||||
SHLIB_MAJOR= 9
|
||||
|
||||
SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c gr_util.c \
|
||||
hexdump.c humanize_number.c kinfo_getfile.c kinfo_getvmmap.c kld.c \
|
||||
hexdump.c humanize_number.c kinfo_getfile.c kinfo_getfile.c \
|
||||
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c kld.c \
|
||||
login_auth.c login_cap.c \
|
||||
login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \
|
||||
pidfile.c property.c pty.c pw_util.c quotafile.c realhostname.c \
|
||||
@ -29,7 +30,8 @@ MAN+= kld.3 login_auth.3 login_tty.3 pty.3 \
|
||||
_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
|
||||
realhostname_sa.3 trimdomain.3 fparseln.3 humanize_number.3 \
|
||||
pidfile.3 flopen.3 expand_number.3 hexdump.3 \
|
||||
kinfo_getfile.3 kinfo_getvmmap.3 quotafile.3
|
||||
kinfo_getfile.3 kinfo_getallproc.3 kinfo_getproc.3 \
|
||||
kinfo_getvmmap.3 quotafile.3
|
||||
MAN+= login.conf.5 auth.conf.5
|
||||
MLINKS+= kld.3 kld_isloaded.3 kld.3 kld_load.3
|
||||
MLINKS+= property.3 properties_read.3 property.3 properties_free.3
|
||||
|
74
lib/libutil/kinfo_getallproc.3
Normal file
74
lib/libutil/kinfo_getallproc.3
Normal file
@ -0,0 +1,74 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 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$
|
||||
.\"
|
||||
.Dd July 9, 2009
|
||||
.Os
|
||||
.Dt KINFO_GETALLPROC 3
|
||||
.Sh NAME
|
||||
.Nm kinfo_getallproc
|
||||
.Nd function for getting process information of all processes from kernel
|
||||
.Sh LIBRARY
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_proc *
|
||||
.Fn kinfo_getallproc "int *cntp"
|
||||
.Sh DESCRIPTION
|
||||
This function is used for obtaining process information of all processes from
|
||||
the kernel.
|
||||
.Pp
|
||||
The
|
||||
.Ar cntp
|
||||
field is a pointer containing the number of process structures returned.
|
||||
This function is a wrapper around
|
||||
.Xr sysctl 3
|
||||
with the
|
||||
.Dv KERN_PROC_PROC
|
||||
mib.
|
||||
While the kernel returns a packed structure, this function expands the
|
||||
data into a fixed record format.
|
||||
.Sh RETURN VALUES
|
||||
On success the
|
||||
.Fn kinfo_getallproc
|
||||
function returns a pointer to
|
||||
.Ar cntp
|
||||
.Vt struct kinfo_proc
|
||||
structures as defined by
|
||||
.In sys/user.h .
|
||||
The pointer was obtained by an internal call to
|
||||
.Xr malloc 3
|
||||
and must be freed by the caller with a call to
|
||||
.Xr free 3 .
|
||||
On failure the
|
||||
.Fn kinfo_getallproc
|
||||
function returns
|
||||
.Dv NULL .
|
||||
.Sh SEE ALSO
|
||||
.Xr free 3 ,
|
||||
.Xr malloc 3 ,
|
||||
.Xr sysctl 3
|
98
lib/libutil/kinfo_getallproc.c
Normal file
98
lib/libutil/kinfo_getallproc.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Robert N. M. Watson
|
||||
* Copyright (c) 2009 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/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libutil.h"
|
||||
|
||||
|
||||
/*
|
||||
* Sort processes first by pid and then tid.
|
||||
*/
|
||||
static int
|
||||
kinfo_proc_compare(const void *a, const void *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = ((const struct kinfo_proc *)a)->ki_pid -
|
||||
((const struct kinfo_proc *)b)->ki_pid;
|
||||
if (i != 0)
|
||||
return (i);
|
||||
i = ((const struct kinfo_proc *)a)->ki_tid -
|
||||
((const struct kinfo_proc *)b)->ki_tid;
|
||||
return (i);
|
||||
}
|
||||
|
||||
static void
|
||||
kinfo_proc_sort(struct kinfo_proc *kipp, int count)
|
||||
{
|
||||
|
||||
qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare);
|
||||
}
|
||||
|
||||
struct kinfo_proc *
|
||||
kinfo_getallproc(int *cntp)
|
||||
{
|
||||
struct kinfo_proc *kipp;
|
||||
size_t len;
|
||||
int mib[3];
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PROC;
|
||||
|
||||
len = 0;
|
||||
if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0)
|
||||
return (NULL);
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sysctl(mib, 3, kipp, &len, NULL, 0) < 0)
|
||||
goto bad;
|
||||
if (len % sizeof(*kipp) != 0)
|
||||
goto bad;
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
goto bad;
|
||||
*cntp = len / sizeof(*kipp);
|
||||
kinfo_proc_sort(kipp, len / sizeof(*kipp));
|
||||
return (kipp);
|
||||
bad:
|
||||
*cntp = 0;
|
||||
free(kipp);
|
||||
return (NULL);
|
||||
}
|
73
lib/libutil/kinfo_getproc.3
Normal file
73
lib/libutil/kinfo_getproc.3
Normal file
@ -0,0 +1,73 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2009 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$
|
||||
.\"
|
||||
.Dd July 9, 2009
|
||||
.Os
|
||||
.Dt KINFO_GETPROC 3
|
||||
.Sh NAME
|
||||
.Nm kinfo_getproc
|
||||
.Nd function for getting process information from kernel
|
||||
.Sh LIBRARY
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In libutil.h
|
||||
.Ft struct kinfo_proc *
|
||||
.Fn kinfo_getproc "pid_t pid" "int *cntp"
|
||||
.Sh DESCRIPTION
|
||||
This function is used for obtaining process information from the kernel.
|
||||
.Pp
|
||||
The
|
||||
.Ar pid
|
||||
field contains the process identifier.
|
||||
This should be the a process that you have privilige to access.
|
||||
This function is a wrapper around
|
||||
.Xr sysctl 3
|
||||
with the
|
||||
.Dv KERN_PROC_PID
|
||||
mib.
|
||||
While the kernel returns a packed structure, this function expands the
|
||||
data into a fixed record format.
|
||||
.Sh RETURN VALUES
|
||||
On success the
|
||||
.Fn kinfo_getproc
|
||||
function returns a pointer to a
|
||||
.Vt struct kinfo_proc
|
||||
structure as defined by
|
||||
.In sys/user.h .
|
||||
The pointer was obtained by an internal call to
|
||||
.Xr malloc 3
|
||||
and must be freed by the caller with a call to
|
||||
.Xr free 3 .
|
||||
On failure the
|
||||
.Fn kinfo_getproc
|
||||
function returns
|
||||
.Dv NULL .
|
||||
.Sh SEE ALSO
|
||||
.Xr free 3 ,
|
||||
.Xr malloc 3 ,
|
||||
.Xr sysctl 3
|
71
lib/libutil/kinfo_getproc.c
Normal file
71
lib/libutil/kinfo_getproc.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* Copyright (c) 2009 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/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libutil.h"
|
||||
|
||||
struct kinfo_proc *
|
||||
kinfo_getproc(pid_t pid)
|
||||
{
|
||||
struct kinfo_proc *kipp;
|
||||
int mib[4];
|
||||
size_t len;
|
||||
|
||||
len = 0;
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = pid;
|
||||
if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0)
|
||||
return (NULL);
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (sysctl(mib, 4, kipp, &len, NULL, 0) < 0)
|
||||
goto bad;
|
||||
if (len != sizeof(*kipp))
|
||||
goto bad;
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
goto bad;
|
||||
if (kipp->ki_pid != pid)
|
||||
goto bad;
|
||||
return (kipp);
|
||||
bad:
|
||||
free(kipp);
|
||||
return (NULL);
|
||||
}
|
@ -88,6 +88,7 @@ struct termios;
|
||||
struct winsize;
|
||||
struct in_addr;
|
||||
struct kinfo_file;
|
||||
struct kinfo_proc;
|
||||
struct kinfo_vmentry;
|
||||
|
||||
__BEGIN_DECLS
|
||||
@ -126,6 +127,10 @@ struct kinfo_file *
|
||||
kinfo_getfile(pid_t _pid, int *_cntp);
|
||||
struct kinfo_vmentry *
|
||||
kinfo_getvmmap(pid_t _pid, int *_cntp);
|
||||
struct kinfo_proc *
|
||||
kinfo_getallproc(int *_cntp);
|
||||
struct kinfo_proc *
|
||||
kinfo_getproc(pid_t _pid);
|
||||
|
||||
#ifdef _STDIO_H_ /* avoid adding new includes */
|
||||
char *fparseln(FILE *, size_t *, size_t *, const char[3], int);
|
||||
|
@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mqueue.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/pipe.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/protosw.h>
|
||||
@ -73,6 +75,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/unpcb.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/vnode.h>
|
||||
#ifdef KTRACE
|
||||
@ -81,6 +85,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <net/vnet.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
|
||||
#include <security/audit/audit.h>
|
||||
|
||||
#include <vm/uma.h>
|
||||
@ -106,6 +113,10 @@ static int fd_last_used(struct filedesc *, int, int);
|
||||
static void fdgrowtable(struct filedesc *, int);
|
||||
static void fdunused(struct filedesc *fdp, int fd);
|
||||
static void fdused(struct filedesc *fdp, int fd);
|
||||
static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
|
||||
static int fill_socket_info(struct socket *so, struct kinfo_file *kif);
|
||||
static int fill_pts_info(struct tty *tp, struct kinfo_file *kif);
|
||||
static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
|
||||
|
||||
/*
|
||||
* A process is initially started out with NDFILE descriptors stored within
|
||||
@ -2972,48 +2983,74 @@ CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
|
||||
#endif
|
||||
|
||||
static int
|
||||
export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req)
|
||||
export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
|
||||
int64_t offset, struct kinfo_file *kif, struct sysctl_req *req)
|
||||
{
|
||||
int error;
|
||||
char *fullpath, *freepath;
|
||||
int vfslocked;
|
||||
struct {
|
||||
int fflag;
|
||||
int kf_fflag;
|
||||
} fflags_table[] = {
|
||||
{ FAPPEND, KF_FLAG_APPEND },
|
||||
{ FASYNC, KF_FLAG_ASYNC },
|
||||
{ FFSYNC, KF_FLAG_FSYNC },
|
||||
{ FHASLOCK, KF_FLAG_HASLOCK },
|
||||
{ FNONBLOCK, KF_FLAG_NONBLOCK },
|
||||
{ FREAD, KF_FLAG_READ },
|
||||
{ FWRITE, KF_FLAG_WRITE },
|
||||
{ O_CREAT, KF_FLAG_CREAT },
|
||||
{ O_DIRECT, KF_FLAG_DIRECT },
|
||||
{ O_EXCL, KF_FLAG_EXCL },
|
||||
{ O_EXEC, KF_FLAG_EXEC },
|
||||
{ O_EXLOCK, KF_FLAG_EXLOCK },
|
||||
{ O_NOFOLLOW, KF_FLAG_NOFOLLOW },
|
||||
{ O_SHLOCK, KF_FLAG_SHLOCK },
|
||||
{ O_TRUNC, KF_FLAG_TRUNC }
|
||||
};
|
||||
#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table))
|
||||
struct vnode *vp;
|
||||
int error, vfslocked;
|
||||
unsigned int i;
|
||||
|
||||
bzero(kif, sizeof(*kif));
|
||||
|
||||
vref(vp);
|
||||
kif->kf_fd = type;
|
||||
kif->kf_type = KF_TYPE_VNODE;
|
||||
/* This function only handles directories. */
|
||||
if (vp->v_type != VDIR) {
|
||||
switch (type) {
|
||||
case KF_TYPE_FIFO:
|
||||
case KF_TYPE_VNODE:
|
||||
vp = (struct vnode *)data;
|
||||
error = fill_vnode_info(vp, kif);
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
return (ENOTDIR);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
break;
|
||||
case KF_TYPE_SOCKET:
|
||||
error = fill_socket_info((struct socket *)data, kif);
|
||||
break;
|
||||
case KF_TYPE_PIPE:
|
||||
error = fill_pipe_info((struct pipe *)data, kif);
|
||||
break;
|
||||
case KF_TYPE_PTS:
|
||||
error = fill_pts_info((struct tty *)data, kif);
|
||||
break;
|
||||
default:
|
||||
error = 0;
|
||||
}
|
||||
kif->kf_vnode_type = KF_VTYPE_VDIR;
|
||||
if (error == 0)
|
||||
kif->kf_status |= KF_ATTR_VALID;
|
||||
|
||||
/*
|
||||
* This is not a true file descriptor, so we set a bogus refcount
|
||||
* and offset to indicate these fields should be ignored.
|
||||
* Translate file access flags.
|
||||
*/
|
||||
kif->kf_ref_count = -1;
|
||||
kif->kf_offset = -1;
|
||||
|
||||
freepath = NULL;
|
||||
fullpath = "-";
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
vn_fullpath(curthread, vp, &fullpath, &freepath);
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
|
||||
if (freepath != NULL)
|
||||
free(freepath, M_TEMP);
|
||||
for (i = 0; i < NFFLAGS; i++)
|
||||
if (fflags & fflags_table[i].fflag)
|
||||
kif->kf_flags |= fflags_table[i].kf_fflag;
|
||||
kif->kf_fd = fd;
|
||||
kif->kf_type = type;
|
||||
kif->kf_ref_count = refcnt;
|
||||
kif->kf_offset = offset;
|
||||
/* Pack record size down */
|
||||
kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
|
||||
strlen(kif->kf_path) + 1;
|
||||
kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
|
||||
error = SYSCTL_OUT(req, kif, kif->kf_structsize);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -3023,17 +3060,16 @@ export_vnode_for_sysctl(struct vnode *vp, int type,
|
||||
static int
|
||||
sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char *fullpath, *freepath;
|
||||
struct kinfo_file *kif;
|
||||
struct filedesc *fdp;
|
||||
int error, i, *name;
|
||||
struct socket *so;
|
||||
struct vnode *vp;
|
||||
struct file *fp;
|
||||
struct filedesc *fdp;
|
||||
struct kinfo_file *kif;
|
||||
struct proc *p;
|
||||
struct tty *tp;
|
||||
int vfslocked;
|
||||
struct vnode *cttyvp, *textvp, *tracevp;
|
||||
size_t oldidx;
|
||||
int64_t offset;
|
||||
void *data;
|
||||
int error, i, *name;
|
||||
int type, refcnt, fflags;
|
||||
|
||||
name = (int *)arg1;
|
||||
if ((p = pfind((pid_t)name[0])) == NULL)
|
||||
@ -3042,177 +3078,136 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
PROC_UNLOCK(p);
|
||||
return (error);
|
||||
}
|
||||
/* ktrace vnode */
|
||||
tracevp = p->p_tracevp;
|
||||
if (tracevp != NULL)
|
||||
vref(tracevp);
|
||||
/* text vnode */
|
||||
textvp = p->p_textvp;
|
||||
if (textvp != NULL)
|
||||
vref(textvp);
|
||||
/* Controlling tty. */
|
||||
cttyvp = NULL;
|
||||
if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) {
|
||||
cttyvp = p->p_pgrp->pg_session->s_ttyvp;
|
||||
if (cttyvp != NULL)
|
||||
vref(cttyvp);
|
||||
}
|
||||
fdp = fdhold(p);
|
||||
PROC_UNLOCK(p);
|
||||
if (fdp == NULL)
|
||||
return (ENOENT);
|
||||
kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
|
||||
if (tracevp != NULL)
|
||||
export_fd_for_sysctl(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
|
||||
FREAD | FWRITE, -1, -1, kif, req);
|
||||
if (textvp != NULL)
|
||||
export_fd_for_sysctl(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
|
||||
FREAD, -1, -1, kif, req);
|
||||
if (cttyvp != NULL)
|
||||
export_fd_for_sysctl(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
|
||||
FREAD | FWRITE, -1, -1, kif, req);
|
||||
if (fdp == NULL)
|
||||
goto fail;
|
||||
FILEDESC_SLOCK(fdp);
|
||||
if (fdp->fd_cdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_rdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
|
||||
fdp, req);
|
||||
if (fdp->fd_jdir != NULL)
|
||||
export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
|
||||
fdp, req);
|
||||
/* working directory */
|
||||
if (fdp->fd_cdir != NULL) {
|
||||
vref(fdp->fd_cdir);
|
||||
data = fdp->fd_cdir;
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
|
||||
FREAD, -1, -1, kif, req);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
}
|
||||
/* root directory */
|
||||
if (fdp->fd_rdir != NULL) {
|
||||
vref(fdp->fd_rdir);
|
||||
data = fdp->fd_rdir;
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
|
||||
FREAD, -1, -1, kif, req);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
}
|
||||
/* jail directory */
|
||||
if (fdp->fd_jdir != NULL) {
|
||||
vref(fdp->fd_jdir);
|
||||
data = fdp->fd_jdir;
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
|
||||
FREAD, -1, -1, kif, req);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
}
|
||||
for (i = 0; i < fdp->fd_nfiles; i++) {
|
||||
if ((fp = fdp->fd_ofiles[i]) == NULL)
|
||||
continue;
|
||||
bzero(kif, sizeof(*kif));
|
||||
vp = NULL;
|
||||
so = NULL;
|
||||
tp = NULL;
|
||||
kif->kf_fd = i;
|
||||
data = NULL;
|
||||
switch (fp->f_type) {
|
||||
case DTYPE_VNODE:
|
||||
kif->kf_type = KF_TYPE_VNODE;
|
||||
vp = fp->f_vnode;
|
||||
type = KF_TYPE_VNODE;
|
||||
vref(fp->f_vnode);
|
||||
data = fp->f_vnode;
|
||||
break;
|
||||
|
||||
case DTYPE_SOCKET:
|
||||
kif->kf_type = KF_TYPE_SOCKET;
|
||||
so = fp->f_data;
|
||||
type = KF_TYPE_SOCKET;
|
||||
data = fp->f_data;
|
||||
break;
|
||||
|
||||
case DTYPE_PIPE:
|
||||
kif->kf_type = KF_TYPE_PIPE;
|
||||
type = KF_TYPE_PIPE;
|
||||
data = fp->f_data;
|
||||
break;
|
||||
|
||||
case DTYPE_FIFO:
|
||||
kif->kf_type = KF_TYPE_FIFO;
|
||||
vp = fp->f_vnode;
|
||||
type = KF_TYPE_FIFO;
|
||||
vref(fp->f_vnode);
|
||||
data = fp->f_vnode;
|
||||
break;
|
||||
|
||||
case DTYPE_KQUEUE:
|
||||
kif->kf_type = KF_TYPE_KQUEUE;
|
||||
type = KF_TYPE_KQUEUE;
|
||||
break;
|
||||
|
||||
case DTYPE_CRYPTO:
|
||||
kif->kf_type = KF_TYPE_CRYPTO;
|
||||
type = KF_TYPE_CRYPTO;
|
||||
break;
|
||||
|
||||
case DTYPE_MQUEUE:
|
||||
kif->kf_type = KF_TYPE_MQUEUE;
|
||||
type = KF_TYPE_MQUEUE;
|
||||
break;
|
||||
|
||||
case DTYPE_SHM:
|
||||
kif->kf_type = KF_TYPE_SHM;
|
||||
type = KF_TYPE_SHM;
|
||||
break;
|
||||
|
||||
case DTYPE_SEM:
|
||||
kif->kf_type = KF_TYPE_SEM;
|
||||
type = KF_TYPE_SEM;
|
||||
break;
|
||||
|
||||
case DTYPE_PTS:
|
||||
kif->kf_type = KF_TYPE_PTS;
|
||||
tp = fp->f_data;
|
||||
type = KF_TYPE_PTS;
|
||||
data = fp->f_data;
|
||||
break;
|
||||
|
||||
default:
|
||||
kif->kf_type = KF_TYPE_UNKNOWN;
|
||||
type = KF_TYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
kif->kf_ref_count = fp->f_count;
|
||||
if (fp->f_flag & FREAD)
|
||||
kif->kf_flags |= KF_FLAG_READ;
|
||||
if (fp->f_flag & FWRITE)
|
||||
kif->kf_flags |= KF_FLAG_WRITE;
|
||||
if (fp->f_flag & FAPPEND)
|
||||
kif->kf_flags |= KF_FLAG_APPEND;
|
||||
if (fp->f_flag & FASYNC)
|
||||
kif->kf_flags |= KF_FLAG_ASYNC;
|
||||
if (fp->f_flag & FFSYNC)
|
||||
kif->kf_flags |= KF_FLAG_FSYNC;
|
||||
if (fp->f_flag & FNONBLOCK)
|
||||
kif->kf_flags |= KF_FLAG_NONBLOCK;
|
||||
if (fp->f_flag & O_DIRECT)
|
||||
kif->kf_flags |= KF_FLAG_DIRECT;
|
||||
if (fp->f_flag & FHASLOCK)
|
||||
kif->kf_flags |= KF_FLAG_HASLOCK;
|
||||
kif->kf_offset = fp->f_offset;
|
||||
if (vp != NULL) {
|
||||
vref(vp);
|
||||
switch (vp->v_type) {
|
||||
case VNON:
|
||||
kif->kf_vnode_type = KF_VTYPE_VNON;
|
||||
break;
|
||||
case VREG:
|
||||
kif->kf_vnode_type = KF_VTYPE_VREG;
|
||||
break;
|
||||
case VDIR:
|
||||
kif->kf_vnode_type = KF_VTYPE_VDIR;
|
||||
break;
|
||||
case VBLK:
|
||||
kif->kf_vnode_type = KF_VTYPE_VBLK;
|
||||
break;
|
||||
case VCHR:
|
||||
kif->kf_vnode_type = KF_VTYPE_VCHR;
|
||||
break;
|
||||
case VLNK:
|
||||
kif->kf_vnode_type = KF_VTYPE_VLNK;
|
||||
break;
|
||||
case VSOCK:
|
||||
kif->kf_vnode_type = KF_VTYPE_VSOCK;
|
||||
break;
|
||||
case VFIFO:
|
||||
kif->kf_vnode_type = KF_VTYPE_VFIFO;
|
||||
break;
|
||||
case VBAD:
|
||||
kif->kf_vnode_type = KF_VTYPE_VBAD;
|
||||
break;
|
||||
default:
|
||||
kif->kf_vnode_type = KF_VTYPE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* It is OK to drop the filedesc lock here as we will
|
||||
* re-validate and re-evaluate its properties when
|
||||
* the loop continues.
|
||||
*/
|
||||
freepath = NULL;
|
||||
fullpath = "-";
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
vn_fullpath(curthread, vp, &fullpath, &freepath);
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vrele(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
strlcpy(kif->kf_path, fullpath,
|
||||
sizeof(kif->kf_path));
|
||||
if (freepath != NULL)
|
||||
free(freepath, M_TEMP);
|
||||
FILEDESC_SLOCK(fdp);
|
||||
}
|
||||
if (so != NULL) {
|
||||
struct sockaddr *sa;
|
||||
refcnt = fp->f_count;
|
||||
fflags = fp->f_flag;
|
||||
offset = fp->f_offset;
|
||||
|
||||
if (so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa)
|
||||
== 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
|
||||
bcopy(sa, &kif->kf_sa_local, sa->sa_len);
|
||||
free(sa, M_SONAME);
|
||||
}
|
||||
if (so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa)
|
||||
== 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
|
||||
bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
|
||||
free(sa, M_SONAME);
|
||||
}
|
||||
kif->kf_sock_domain =
|
||||
so->so_proto->pr_domain->dom_family;
|
||||
kif->kf_sock_type = so->so_type;
|
||||
kif->kf_sock_protocol = so->so_proto->pr_protocol;
|
||||
}
|
||||
if (tp != NULL) {
|
||||
strlcpy(kif->kf_path, tty_devname(tp),
|
||||
sizeof(kif->kf_path));
|
||||
}
|
||||
/* Pack record size down */
|
||||
kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
|
||||
strlen(kif->kf_path) + 1;
|
||||
kif->kf_structsize = roundup(kif->kf_structsize,
|
||||
sizeof(uint64_t));
|
||||
/*
|
||||
* Create sysctl entry.
|
||||
* It is OK to drop the filedesc lock here as we will
|
||||
* re-validate and re-evaluate its properties when
|
||||
* the loop continues.
|
||||
*/
|
||||
oldidx = req->oldidx;
|
||||
error = SYSCTL_OUT(req, kif, kif->kf_structsize);
|
||||
if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
error = export_fd_for_sysctl(data, type, i,
|
||||
fflags, refcnt, offset, kif, req);
|
||||
if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
|
||||
FILEDESC_SLOCK(fdp);
|
||||
if (error) {
|
||||
if (error == ENOMEM) {
|
||||
/*
|
||||
@ -3228,11 +3223,164 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
|
||||
}
|
||||
}
|
||||
FILEDESC_SUNLOCK(fdp);
|
||||
fail:
|
||||
fddrop(fdp);
|
||||
free(kif, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vntype_to_kinfo(int vtype)
|
||||
{
|
||||
struct {
|
||||
int vtype;
|
||||
int kf_vtype;
|
||||
} vtypes_table[] = {
|
||||
{ VBAD, KF_VTYPE_VBAD },
|
||||
{ VBLK, KF_VTYPE_VBLK },
|
||||
{ VCHR, KF_VTYPE_VCHR },
|
||||
{ VDIR, KF_VTYPE_VDIR },
|
||||
{ VFIFO, KF_VTYPE_VFIFO },
|
||||
{ VLNK, KF_VTYPE_VLNK },
|
||||
{ VNON, KF_VTYPE_VNON },
|
||||
{ VREG, KF_VTYPE_VREG },
|
||||
{ VSOCK, KF_VTYPE_VSOCK }
|
||||
};
|
||||
#define NVTYPES (sizeof(vtypes_table) / sizeof(*vtypes_table))
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Perform vtype translation.
|
||||
*/
|
||||
for (i = 0; i < NVTYPES; i++)
|
||||
if (vtypes_table[i].vtype == vtype)
|
||||
break;
|
||||
if (i < NVTYPES)
|
||||
return (vtypes_table[i].kf_vtype);
|
||||
|
||||
return (KF_VTYPE_UNKNOWN);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
|
||||
{
|
||||
struct vattr va;
|
||||
char *fullpath, *freepath;
|
||||
int error, vfslocked;
|
||||
|
||||
if (vp == NULL)
|
||||
return (1);
|
||||
kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
|
||||
freepath = NULL;
|
||||
fullpath = "-";
|
||||
error = vn_fullpath(curthread, vp, &fullpath, &freepath);
|
||||
if (error == 0) {
|
||||
strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
|
||||
}
|
||||
if (freepath != NULL)
|
||||
free(freepath, M_TEMP);
|
||||
|
||||
/*
|
||||
* Retrieve vnode attributes.
|
||||
*/
|
||||
va.va_fsid = VNOVAL;
|
||||
va.va_rdev = NODEV;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
error = VOP_GETATTR(vp, &va, curthread->td_ucred);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (va.va_fsid != VNOVAL)
|
||||
kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
|
||||
else
|
||||
kif->kf_un.kf_file.kf_file_fsid =
|
||||
vp->v_mount->mnt_stat.f_fsid.val[0];
|
||||
kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
|
||||
kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
|
||||
kif->kf_un.kf_file.kf_file_size = va.va_size;
|
||||
kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_socket_info(struct socket *so, struct kinfo_file *kif)
|
||||
{
|
||||
struct sockaddr *sa;
|
||||
struct inpcb *inpcb;
|
||||
struct unpcb *unpcb;
|
||||
int error;
|
||||
|
||||
if (so == NULL)
|
||||
return (1);
|
||||
kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
|
||||
kif->kf_sock_type = so->so_type;
|
||||
kif->kf_sock_protocol = so->so_proto->pr_protocol;
|
||||
kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
|
||||
switch(kif->kf_sock_domain) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
if (kif->kf_sock_protocol == IPPROTO_TCP) {
|
||||
if (so->so_pcb != NULL) {
|
||||
inpcb = (struct inpcb *)(so->so_pcb);
|
||||
kif->kf_un.kf_sock.kf_sock_inpcb =
|
||||
(uintptr_t)inpcb->inp_ppcb;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AF_UNIX:
|
||||
if (so->so_pcb != NULL) {
|
||||
unpcb = (struct unpcb *)(so->so_pcb);
|
||||
if (unpcb->unp_conn) {
|
||||
kif->kf_un.kf_sock.kf_sock_unpconn =
|
||||
(uintptr_t)unpcb->unp_conn;
|
||||
kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
|
||||
so->so_rcv.sb_state;
|
||||
kif->kf_un.kf_sock.kf_sock_snd_sb_state =
|
||||
so->so_snd.sb_state;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
|
||||
if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
|
||||
bcopy(sa, &kif->kf_sa_local, sa->sa_len);
|
||||
free(sa, M_SONAME);
|
||||
}
|
||||
error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
|
||||
if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
|
||||
bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
|
||||
free(sa, M_SONAME);
|
||||
}
|
||||
strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
|
||||
sizeof(kif->kf_path));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_pts_info(struct tty *tp, struct kinfo_file *kif)
|
||||
{
|
||||
|
||||
if (tp == NULL)
|
||||
return (1);
|
||||
kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
|
||||
strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_pipe_info(struct pipe *pi, struct kinfo_file *kif)
|
||||
{
|
||||
|
||||
if (pi == NULL)
|
||||
return (1);
|
||||
kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
|
||||
kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
|
||||
kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD,
|
||||
sysctl_kern_proc_filedesc, "Process filedesc entries");
|
||||
|
||||
|
@ -1757,8 +1757,6 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
|
||||
last_timestamp = map->timestamp;
|
||||
vm_map_unlock_read(map);
|
||||
|
||||
kve->kve_fileid = 0;
|
||||
kve->kve_fsid = 0;
|
||||
freepath = NULL;
|
||||
fullpath = "";
|
||||
if (lobj) {
|
||||
@ -1800,12 +1798,18 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
|
||||
if (vp != NULL) {
|
||||
vn_fullpath(curthread, vp, &fullpath,
|
||||
&freepath);
|
||||
kve->kve_vn_type = vntype_to_kinfo(vp->v_type);
|
||||
cred = curthread->td_ucred;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
vn_lock(vp, LK_SHARED | LK_RETRY);
|
||||
if (VOP_GETATTR(vp, &va, cred) == 0) {
|
||||
kve->kve_fileid = va.va_fileid;
|
||||
kve->kve_fsid = va.va_fsid;
|
||||
kve->kve_vn_fileid = va.va_fileid;
|
||||
kve->kve_vn_fsid = va.va_fsid;
|
||||
kve->kve_vn_mode =
|
||||
MAKEIMODE(va.va_type, va.va_mode);
|
||||
kve->kve_vn_size = va.va_size;
|
||||
kve->kve_vn_rdev = va.va_rdev;
|
||||
kve->kve_status = KF_ATTR_VALID;
|
||||
}
|
||||
vput(vp);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
|
@ -233,6 +233,8 @@ struct user {
|
||||
* The KERN_PROC_FILE sysctl allows a process to dump the file descriptor
|
||||
* array of another process.
|
||||
*/
|
||||
#define KF_ATTR_VALID 0x0001
|
||||
|
||||
#define KF_TYPE_NONE 0
|
||||
#define KF_TYPE_VNODE 1
|
||||
#define KF_TYPE_SOCKET 2
|
||||
@ -260,6 +262,9 @@ struct user {
|
||||
#define KF_FD_TYPE_CWD -1 /* Current working directory */
|
||||
#define KF_FD_TYPE_ROOT -2 /* Root directory */
|
||||
#define KF_FD_TYPE_JAIL -3 /* Jail directory */
|
||||
#define KF_FD_TYPE_TRACE -4 /* ptrace vnode */
|
||||
#define KF_FD_TYPE_TEXT -5 /* Text vnode */
|
||||
#define KF_FD_TYPE_CTTY -6 /* Controlling terminal */
|
||||
|
||||
#define KF_FLAG_READ 0x00000001
|
||||
#define KF_FLAG_WRITE 0x00000002
|
||||
@ -269,6 +274,13 @@ struct user {
|
||||
#define KF_FLAG_NONBLOCK 0x00000020
|
||||
#define KF_FLAG_DIRECT 0x00000040
|
||||
#define KF_FLAG_HASLOCK 0x00000080
|
||||
#define KF_FLAG_SHLOCK 0x00000100
|
||||
#define KF_FLAG_EXLOCK 0x00000200
|
||||
#define KF_FLAG_NOFOLLOW 0x00000400
|
||||
#define KF_FLAG_CREAT 0x00000800
|
||||
#define KF_FLAG_TRUNC 0x00001000
|
||||
#define KF_FLAG_EXCL 0x00002000
|
||||
#define KF_FLAG_EXEC 0x00004000
|
||||
|
||||
/*
|
||||
* Old format. Has variable hidden padding due to alignment.
|
||||
@ -303,22 +315,67 @@ struct kinfo_ofile {
|
||||
#endif
|
||||
|
||||
struct kinfo_file {
|
||||
int kf_structsize; /* Variable size of record. */
|
||||
int kf_type; /* Descriptor type. */
|
||||
int kf_fd; /* Array index. */
|
||||
int kf_ref_count; /* Reference count. */
|
||||
int kf_flags; /* Flags. */
|
||||
int _kf_pad0; /* Round to 64 bit alignment */
|
||||
int64_t kf_offset; /* Seek location. */
|
||||
int kf_vnode_type; /* Vnode type. */
|
||||
int kf_sock_domain; /* Socket domain. */
|
||||
int kf_sock_type; /* Socket type. */
|
||||
int kf_sock_protocol; /* Socket protocol. */
|
||||
int kf_structsize; /* Variable size of record. */
|
||||
int kf_type; /* Descriptor type. */
|
||||
int kf_fd; /* Array index. */
|
||||
int kf_ref_count; /* Reference count. */
|
||||
int kf_flags; /* Flags. */
|
||||
int kf_pad0; /* Round to 64 bit alignment. */
|
||||
int64_t kf_offset; /* Seek location. */
|
||||
int kf_vnode_type; /* Vnode type. */
|
||||
int kf_sock_domain; /* Socket domain. */
|
||||
int kf_sock_type; /* Socket type. */
|
||||
int kf_sock_protocol; /* Socket protocol. */
|
||||
struct sockaddr_storage kf_sa_local; /* Socket address. */
|
||||
struct sockaddr_storage kf_sa_peer; /* Peer address. */
|
||||
int _kf_ispare[16]; /* Space for more stuff. */
|
||||
union {
|
||||
struct {
|
||||
/* Address of so_pcb. */
|
||||
uint64_t kf_sock_pcb;
|
||||
/* Address of inp_ppcb. */
|
||||
uint64_t kf_sock_inpcb;
|
||||
/* Address of unp_conn. */
|
||||
uint64_t kf_sock_unpconn;
|
||||
/* Send buffer state. */
|
||||
uint16_t kf_sock_snd_sb_state;
|
||||
/* Receive buffer state. */
|
||||
uint16_t kf_sock_rcv_sb_state;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint32_t kf_sock_pad0;
|
||||
} kf_sock;
|
||||
struct {
|
||||
/* Global file id. */
|
||||
uint64_t kf_file_fileid;
|
||||
/* File size. */
|
||||
uint64_t kf_file_size;
|
||||
/* Vnode filesystem id. */
|
||||
uint32_t kf_file_fsid;
|
||||
/* File device. */
|
||||
uint32_t kf_file_rdev;
|
||||
/* File mode. */
|
||||
uint16_t kf_file_mode;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint16_t kf_file_pad0;
|
||||
uint32_t kf_file_pad1;
|
||||
} kf_file;
|
||||
struct {
|
||||
uint64_t kf_pipe_addr;
|
||||
uint64_t kf_pipe_peer;
|
||||
uint32_t kf_pipe_buffer_cnt;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint32_t kf_pipe_pad0[3];
|
||||
} kf_pipe;
|
||||
struct {
|
||||
uint32_t kf_pts_dev;
|
||||
/* Round to 64 bit alignment. */
|
||||
uint32_t kf_pts_pad0[7];
|
||||
} kf_pts;
|
||||
} kf_un;
|
||||
uint16_t kf_status; /* Status flags. */
|
||||
uint16_t kf_pad1; /* Round to 32 bit alignment. */
|
||||
int _kf_ispare[7]; /* Space for more stuff. */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kf_path[PATH_MAX]; /* Path to file, if any. */
|
||||
char kf_path[PATH_MAX]; /* Path to file, if any. */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -379,16 +436,20 @@ struct kinfo_vmentry {
|
||||
uint64_t kve_start; /* Starting address. */
|
||||
uint64_t kve_end; /* Finishing address. */
|
||||
uint64_t kve_offset; /* Mapping offset in object */
|
||||
uint64_t kve_fileid; /* inode number if vnode */
|
||||
uint32_t kve_fsid; /* dev_t of vnode location */
|
||||
uint64_t kve_vn_fileid; /* inode number if vnode */
|
||||
uint32_t kve_vn_fsid; /* dev_t of vnode location */
|
||||
int kve_flags; /* Flags on map entry. */
|
||||
int kve_resident; /* Number of resident pages. */
|
||||
int kve_private_resident; /* Number of private pages. */
|
||||
int kve_protection; /* Protection bitmask. */
|
||||
int kve_ref_count; /* VM obj ref count. */
|
||||
int kve_shadow_count; /* VM obj shadow count. */
|
||||
int _kve_pad0; /* 64bit align next field */
|
||||
int _kve_ispare[16]; /* Space for more stuff. */
|
||||
int kve_vn_type; /* Vnode type. */
|
||||
uint64_t kve_vn_size; /* File size. */
|
||||
uint32_t kve_vn_rdev; /* Device id if device. */
|
||||
uint16_t kve_vn_mode; /* File mode. */
|
||||
uint16_t kve_status; /* Status flags. */
|
||||
int _kve_ispare[12]; /* Space for more stuff. */
|
||||
/* Truncated before copyout in sysctl */
|
||||
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
|
||||
};
|
||||
@ -415,4 +476,8 @@ struct kinfo_kstack {
|
||||
int _kkst_ispare[16]; /* Space for more stuff. */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
int vntype_to_kinfo(int vtype);
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
LDADD= -lkvm -lutil -lprocstat
|
||||
|
||||
CFLAGS+=-D_KVM_VNODE
|
||||
|
||||
# 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>
|
||||
|
File diff suppressed because it is too large
Load Diff
34
usr.bin/fstat/functions.h
Normal file
34
usr.bin/fstat/functions.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*-
|
||||
* 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 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$
|
||||
*/
|
||||
#ifndef __FUNCTIONS_H__
|
||||
#define __FUNCTIONS_H__
|
||||
|
||||
int do_fstat(int argc, char *argv[]);
|
||||
int do_fuser(int argc, char *argv[]);
|
||||
|
||||
#endif /* !__FUNCTIONS_H__ */
|
148
usr.bin/fstat/fuser.1
Normal file
148
usr.bin/fstat/fuser.1
Normal file
@ -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 .
|
369
usr.bin/fstat/fuser.c
Normal file
369
usr.bin/fstat/fuser.c
Normal file
@ -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);
|
||||
}
|
49
usr.bin/fstat/main.c
Normal file
49
usr.bin/fstat/main.c
Normal file
@ -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));
|
||||
}
|
@ -13,7 +13,7 @@ SRCS= procstat.c \
|
||||
procstat_threads.c \
|
||||
procstat_vm.c
|
||||
|
||||
LDADD+= -lutil
|
||||
LDADD+= -lutil -lprocstat -lkvm
|
||||
DPADD+= ${LIBUTIL}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysexits.h>
|
||||
@ -45,36 +46,36 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: procstat [-h] [-n] [-w interval] [-b | -c | -f | "
|
||||
"-i | -j | -k | -s | -t | -v]\n");
|
||||
fprintf(stderr, "usage: procstat [-h] [-M core] [-N system] "
|
||||
"[-w interval] [-b | -c | -f | -i | -j | -k | -s | -t | -v]\n");
|
||||
fprintf(stderr, " [-a | pid ...]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
procstat(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat(struct procstat *prstat, struct kinfo_proc *kipp)
|
||||
{
|
||||
|
||||
if (bflag)
|
||||
procstat_bin(pid, kipp);
|
||||
procstat_bin(kipp);
|
||||
else if (cflag)
|
||||
procstat_args(pid, kipp);
|
||||
procstat_args(kipp);
|
||||
else if (fflag)
|
||||
procstat_files(pid, kipp);
|
||||
procstat_files(prstat, kipp);
|
||||
else if (iflag)
|
||||
procstat_sigs(pid, kipp);
|
||||
procstat_sigs(prstat, kipp);
|
||||
else if (jflag)
|
||||
procstat_threads_sigs(pid, kipp);
|
||||
procstat_threads_sigs(prstat, kipp);
|
||||
else if (kflag)
|
||||
procstat_kstack(pid, kipp, kflag);
|
||||
procstat_kstack(kipp, kflag);
|
||||
else if (sflag)
|
||||
procstat_cred(pid, kipp);
|
||||
procstat_cred(kipp);
|
||||
else if (tflag)
|
||||
procstat_threads(pid, kipp);
|
||||
procstat_threads(kipp);
|
||||
else if (vflag)
|
||||
procstat_vm(pid, kipp);
|
||||
procstat_vm(kipp);
|
||||
else
|
||||
procstat_basic(pid, kipp);
|
||||
procstat_basic(kipp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -104,17 +105,26 @@ kinfo_proc_sort(struct kinfo_proc *kipp, int count)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, interval, name[4], tmp;
|
||||
unsigned int i;
|
||||
struct kinfo_proc *kipp;
|
||||
size_t len;
|
||||
int ch, interval, tmp;
|
||||
int i;
|
||||
struct kinfo_proc *p;
|
||||
struct procstat *prstat;
|
||||
long l;
|
||||
pid_t pid;
|
||||
char *dummy;
|
||||
char *nlistf, *memf;
|
||||
int cnt;
|
||||
|
||||
interval = 0;
|
||||
while ((ch = getopt(argc, argv, "abcfijknhstvw:")) != -1) {
|
||||
memf = nlistf = NULL;
|
||||
while ((ch = getopt(argc, argv, "N:M:abcfijkhstvw:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
aflag++;
|
||||
break;
|
||||
@ -194,38 +204,27 @@ main(int argc, char *argv[])
|
||||
if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
|
||||
usage();
|
||||
|
||||
if (memf != NULL)
|
||||
prstat = procstat_open_kvm(nlistf, memf);
|
||||
else
|
||||
prstat = procstat_open_sysctl();
|
||||
if (prstat == NULL)
|
||||
errx(1, "procstat_open()");
|
||||
do {
|
||||
if (aflag) {
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PROC;
|
||||
|
||||
len = 0;
|
||||
if (sysctl(name, 3, NULL, &len, NULL, 0) < 0)
|
||||
err(-1, "sysctl: kern.proc.all");
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 3, kipp, &len, NULL, 0) < 0) {
|
||||
free(kipp);
|
||||
err(-1, "sysctl: kern.proc.all");
|
||||
}
|
||||
if (len % sizeof(*kipp) != 0)
|
||||
err(-1, "kinfo_proc mismatch");
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
err(-1, "kinfo_proc structure mismatch");
|
||||
kinfo_proc_sort(kipp, len / sizeof(*kipp));
|
||||
for (i = 0; i < len / sizeof(*kipp); i++) {
|
||||
procstat(kipp[i].ki_pid, &kipp[i]);
|
||||
p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt);
|
||||
if (p == NULL)
|
||||
errx(1, "procstat_getprocs()");
|
||||
kinfo_proc_sort(p, cnt);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
procstat(prstat, &p[i]);
|
||||
|
||||
/* Suppress header after first process. */
|
||||
hflag = 1;
|
||||
}
|
||||
free(kipp);
|
||||
procstat_freeprocs(prstat, p);
|
||||
}
|
||||
for (i = 0; i < (unsigned int)argc; i++) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
l = strtol(argv[i], &dummy, 10);
|
||||
if (*dummy != '\0')
|
||||
usage();
|
||||
@ -233,31 +232,12 @@ main(int argc, char *argv[])
|
||||
usage();
|
||||
pid = l;
|
||||
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PID;
|
||||
name[3] = pid;
|
||||
|
||||
len = 0;
|
||||
if (sysctl(name, 4, NULL, &len, NULL, 0) < 0)
|
||||
err(-1, "sysctl: kern.proc.pid: %d", pid);
|
||||
|
||||
kipp = malloc(len);
|
||||
if (kipp == NULL)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kipp, &len, NULL, 0) < 0) {
|
||||
free(kipp);
|
||||
err(-1, "sysctl: kern.proc.pid: %d", pid);
|
||||
}
|
||||
if (len != sizeof(*kipp))
|
||||
err(-1, "kinfo_proc mismatch");
|
||||
if (kipp->ki_structsize != sizeof(*kipp))
|
||||
errx(-1, "kinfo_proc structure mismatch");
|
||||
if (kipp->ki_pid != pid)
|
||||
errx(-1, "kinfo_proc pid mismatch");
|
||||
procstat(pid, kipp);
|
||||
free(kipp);
|
||||
p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt);
|
||||
if (p == NULL)
|
||||
errx(1, "procstat_getprocs()");
|
||||
if (cnt != 0)
|
||||
procstat(prstat, p);
|
||||
procstat_freeprocs(prstat, p);
|
||||
|
||||
/* Suppress header after first process. */
|
||||
hflag = 1;
|
||||
@ -265,5 +245,6 @@ main(int argc, char *argv[])
|
||||
if (interval)
|
||||
sleep(interval);
|
||||
} while (interval);
|
||||
procstat_close(prstat);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -34,15 +34,15 @@ extern int hflag, nflag;
|
||||
struct kinfo_proc;
|
||||
void kinfo_proc_sort(struct kinfo_proc *kipp, int count);
|
||||
|
||||
void procstat_args(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_basic(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_bin(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_cred(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_files(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag);
|
||||
void procstat_sigs(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_threads(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_threads_sigs(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_vm(pid_t pid, struct kinfo_proc *kipp);
|
||||
void procstat_args(struct kinfo_proc *kipp);
|
||||
void procstat_basic(struct kinfo_proc *kipp);
|
||||
void procstat_bin(struct kinfo_proc *kipp);
|
||||
void procstat_cred(struct kinfo_proc *kipp);
|
||||
void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
|
||||
void procstat_kstack(struct kinfo_proc *kipp, int kflag);
|
||||
void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
|
||||
void procstat_threads(struct kinfo_proc *kipp);
|
||||
void procstat_threads_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
|
||||
void procstat_vm(struct kinfo_proc *kipp);
|
||||
|
||||
#endif /* !PROCSTAT_H */
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libprocstat.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -42,7 +43,7 @@
|
||||
static char args[ARG_MAX];
|
||||
|
||||
void
|
||||
procstat_args(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_args(struct kinfo_proc *kipp)
|
||||
{
|
||||
int error, name[4];
|
||||
size_t len;
|
||||
@ -54,11 +55,11 @@ procstat_args(pid_t pid, struct kinfo_proc *kipp)
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_ARGS;
|
||||
name[3] = pid;
|
||||
name[3] = kipp->ki_pid;
|
||||
len = sizeof(args);
|
||||
error = sysctl(name, 4, args, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.args: %d", pid);
|
||||
warn("sysctl: kern.proc.args: %d", kipp->ki_pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
@ -68,7 +69,7 @@ procstat_args(pid_t pid, struct kinfo_proc *kipp)
|
||||
len = strlen(args) + 1;
|
||||
}
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%-16s ", kipp->ki_comm);
|
||||
for (cp = args; cp < args + len; cp += strlen(cp) + 1)
|
||||
printf("%s%s", cp != args ? " " : "", cp);
|
||||
|
@ -31,13 +31,14 @@
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_basic(pid_t pid __unused, struct kinfo_proc *kipp)
|
||||
procstat_basic(struct kinfo_proc *kipp)
|
||||
{
|
||||
|
||||
if (!hflag)
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libprocstat.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -39,7 +40,7 @@
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_bin(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_bin(struct kinfo_proc *kipp)
|
||||
{
|
||||
char pathname[PATH_MAX];
|
||||
int error, name[4];
|
||||
@ -51,12 +52,12 @@ procstat_bin(pid_t pid, struct kinfo_proc *kipp)
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PATHNAME;
|
||||
name[3] = pid;
|
||||
name[3] = kipp->ki_pid;
|
||||
|
||||
len = sizeof(pathname);
|
||||
error = sysctl(name, 4, pathname, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.pathname: %d", pid);
|
||||
warn("sysctl: kern.proc.pathname: %d", kipp->ki_pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
@ -64,7 +65,7 @@ procstat_bin(pid_t pid, struct kinfo_proc *kipp)
|
||||
if (len == 0 || strlen(pathname) == 0)
|
||||
strcpy(pathname, "-");
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%-16s ", kipp->ki_comm);
|
||||
printf("%s\n", pathname);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@ -38,7 +39,7 @@
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_cred(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_cred(struct kinfo_proc *kipp)
|
||||
{
|
||||
int i;
|
||||
int mib[4];
|
||||
@ -51,7 +52,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp)
|
||||
"COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "SVGID",
|
||||
"GROUPS");
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%-16s ", kipp->ki_comm);
|
||||
printf("%5d ", kipp->ki_uid);
|
||||
printf("%5d ", kipp->ki_ruid);
|
||||
@ -69,7 +70,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp)
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_GROUPS;
|
||||
mib[3] = pid;
|
||||
mib[3] = kipp->ki_pid;
|
||||
|
||||
ngroups = sysconf(_SC_NGROUPS_MAX) + 1;
|
||||
len = ngroups * sizeof(gid_t);
|
||||
@ -78,7 +79,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp)
|
||||
|
||||
if (sysctl(mib, 4, groups, &len, NULL, 0) == -1) {
|
||||
warn("sysctl: kern.proc.groups: %d "
|
||||
"group list truncated", pid);
|
||||
"group list truncated", kipp->ki_pid);
|
||||
free(groups);
|
||||
groups = NULL;
|
||||
}
|
||||
|
@ -37,11 +37,11 @@
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <libprocstat.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libutil.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
@ -132,162 +132,165 @@ print_address(struct sockaddr_storage *ss)
|
||||
}
|
||||
|
||||
void
|
||||
procstat_files(pid_t pid, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_file *freep, *kif;
|
||||
int i, cnt;
|
||||
procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct sockstat sock;
|
||||
struct filestat_list *head;
|
||||
struct filestat *fst;
|
||||
const char *str;
|
||||
struct vnstat vn;
|
||||
int error;
|
||||
|
||||
if (!hflag)
|
||||
printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
|
||||
"PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
|
||||
"PRO", "NAME");
|
||||
|
||||
freep = kinfo_getfile(pid, &cnt);
|
||||
if (freep == NULL)
|
||||
head = procstat_getfiles(procstat, kipp, 0);
|
||||
if (head == NULL)
|
||||
return;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
kif = &freep[i];
|
||||
|
||||
printf("%5d ", pid);
|
||||
STAILQ_FOREACH(fst, head, next) {
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%-16s ", kipp->ki_comm);
|
||||
switch (kif->kf_fd) {
|
||||
case KF_FD_TYPE_CWD:
|
||||
if (fst->fs_uflags & PS_FST_UFLAG_CTTY)
|
||||
printf("ctty ");
|
||||
else if (fst->fs_uflags & PS_FST_UFLAG_CDIR)
|
||||
printf(" cwd ");
|
||||
break;
|
||||
|
||||
case KF_FD_TYPE_ROOT:
|
||||
printf("root ");
|
||||
break;
|
||||
|
||||
case KF_FD_TYPE_JAIL:
|
||||
else if (fst->fs_uflags & PS_FST_UFLAG_JAIL)
|
||||
printf("jail ");
|
||||
break;
|
||||
else if (fst->fs_uflags & PS_FST_UFLAG_RDIR)
|
||||
printf("root ");
|
||||
else if (fst->fs_uflags & PS_FST_UFLAG_TEXT)
|
||||
printf("text ");
|
||||
else if (fst->fs_uflags & PS_FST_UFLAG_TRACE)
|
||||
printf("trace ");
|
||||
else
|
||||
printf("%4d ", fst->fs_fd);
|
||||
|
||||
default:
|
||||
printf("%4d ", kif->kf_fd);
|
||||
break;
|
||||
}
|
||||
switch (kif->kf_type) {
|
||||
case KF_TYPE_VNODE:
|
||||
switch (fst->fs_type) {
|
||||
case PS_FST_TYPE_VNODE:
|
||||
str = "v";
|
||||
break;
|
||||
|
||||
case KF_TYPE_SOCKET:
|
||||
case PS_FST_TYPE_SOCKET:
|
||||
str = "s";
|
||||
break;
|
||||
|
||||
case KF_TYPE_PIPE:
|
||||
case PS_FST_TYPE_PIPE:
|
||||
str = "p";
|
||||
break;
|
||||
|
||||
case KF_TYPE_FIFO:
|
||||
case PS_FST_TYPE_FIFO:
|
||||
str = "f";
|
||||
break;
|
||||
|
||||
case KF_TYPE_KQUEUE:
|
||||
case PS_FST_TYPE_KQUEUE:
|
||||
str = "k";
|
||||
break;
|
||||
|
||||
case KF_TYPE_CRYPTO:
|
||||
case PS_FST_TYPE_CRYPTO:
|
||||
str = "c";
|
||||
break;
|
||||
|
||||
case KF_TYPE_MQUEUE:
|
||||
case PS_FST_TYPE_MQUEUE:
|
||||
str = "m";
|
||||
break;
|
||||
|
||||
case KF_TYPE_SHM:
|
||||
case PS_FST_TYPE_SHM:
|
||||
str = "h";
|
||||
break;
|
||||
|
||||
case KF_TYPE_PTS:
|
||||
case PS_FST_TYPE_PTS:
|
||||
str = "t";
|
||||
break;
|
||||
|
||||
case KF_TYPE_SEM:
|
||||
case PS_FST_TYPE_SEM:
|
||||
str = "e";
|
||||
break;
|
||||
|
||||
case KF_TYPE_NONE:
|
||||
case KF_TYPE_UNKNOWN:
|
||||
case PS_FST_TYPE_NONE:
|
||||
case PS_FST_TYPE_UNKNOWN:
|
||||
default:
|
||||
str = "?";
|
||||
break;
|
||||
}
|
||||
printf("%1s ", str);
|
||||
str = "-";
|
||||
if (kif->kf_type == KF_TYPE_VNODE) {
|
||||
switch (kif->kf_vnode_type) {
|
||||
case KF_VTYPE_VREG:
|
||||
if (fst->fs_type == PS_FST_TYPE_VNODE) {
|
||||
error = procstat_get_vnode_info(procstat, fst, &vn, NULL);
|
||||
switch (vn.vn_type) {
|
||||
case PS_FST_VTYPE_VREG:
|
||||
str = "r";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VDIR:
|
||||
case PS_FST_VTYPE_VDIR:
|
||||
str = "d";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VBLK:
|
||||
case PS_FST_VTYPE_VBLK:
|
||||
str = "b";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VCHR:
|
||||
case PS_FST_VTYPE_VCHR:
|
||||
str = "c";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VLNK:
|
||||
case PS_FST_VTYPE_VLNK:
|
||||
str = "l";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VSOCK:
|
||||
case PS_FST_VTYPE_VSOCK:
|
||||
str = "s";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VFIFO:
|
||||
case PS_FST_VTYPE_VFIFO:
|
||||
str = "f";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VBAD:
|
||||
case PS_FST_VTYPE_VBAD:
|
||||
str = "x";
|
||||
break;
|
||||
|
||||
case KF_VTYPE_VNON:
|
||||
case KF_VTYPE_UNKNOWN:
|
||||
case PS_FST_VTYPE_VNON:
|
||||
case PS_FST_VTYPE_UNKNOWN:
|
||||
default:
|
||||
str = "?";
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%1s ", str);
|
||||
printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-");
|
||||
printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
|
||||
printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
|
||||
if (kif->kf_ref_count > -1)
|
||||
printf("%3d ", kif->kf_ref_count);
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-");
|
||||
printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
|
||||
printf("%s ", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
|
||||
if (fst->fs_ref_count > -1)
|
||||
printf("%3d ", fst->fs_ref_count);
|
||||
else
|
||||
printf("%3c ", '-');
|
||||
if (kif->kf_offset > -1)
|
||||
printf("%7jd ", (intmax_t)kif->kf_offset);
|
||||
if (fst->fs_offset > -1)
|
||||
printf("%7jd ", (intmax_t)fst->fs_offset);
|
||||
else
|
||||
printf("%7c ", '-');
|
||||
|
||||
switch (kif->kf_type) {
|
||||
case KF_TYPE_VNODE:
|
||||
case KF_TYPE_FIFO:
|
||||
case KF_TYPE_PTS:
|
||||
switch (fst->fs_type) {
|
||||
case PS_FST_TYPE_VNODE:
|
||||
case PS_FST_TYPE_FIFO:
|
||||
case PS_FST_TYPE_PTS:
|
||||
printf("%-3s ", "-");
|
||||
printf("%-18s", kif->kf_path);
|
||||
printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-");
|
||||
break;
|
||||
|
||||
case KF_TYPE_SOCKET:
|
||||
case PS_FST_TYPE_SOCKET:
|
||||
error = procstat_get_socket_info(procstat, fst, &sock, NULL);
|
||||
if (error != 0)
|
||||
break;
|
||||
printf("%-3s ",
|
||||
protocol_to_string(kif->kf_sock_domain,
|
||||
kif->kf_sock_type, kif->kf_sock_protocol));
|
||||
protocol_to_string(sock.dom_family,
|
||||
sock.type, sock.proto));
|
||||
/*
|
||||
* While generally we like to print two addresses,
|
||||
* local and peer, for sockets, it turns out to be
|
||||
@ -295,18 +298,18 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
|
||||
* local sockets, as typically they aren't bound and
|
||||
* connected, and the path strings can get long.
|
||||
*/
|
||||
if (kif->kf_sock_domain == AF_LOCAL) {
|
||||
if (sock.dom_family == AF_LOCAL) {
|
||||
struct sockaddr_un *sun =
|
||||
(struct sockaddr_un *)&kif->kf_sa_local;
|
||||
(struct sockaddr_un *)&sock.sa_local;
|
||||
|
||||
if (sun->sun_path[0] != 0)
|
||||
print_address(&kif->kf_sa_local);
|
||||
print_address(&sock.sa_local);
|
||||
else
|
||||
print_address(&kif->kf_sa_peer);
|
||||
print_address(&sock.sa_peer);
|
||||
} else {
|
||||
print_address(&kif->kf_sa_local);
|
||||
print_address(&sock.sa_local);
|
||||
printf(" ");
|
||||
print_address(&kif->kf_sa_peer);
|
||||
print_address(&sock.sa_peer);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -317,5 +320,4 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
free(freep);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -124,7 +125,7 @@ kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count)
|
||||
|
||||
|
||||
void
|
||||
procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
procstat_kstack(struct kinfo_proc *kipp, int kflag)
|
||||
{
|
||||
struct kinfo_kstack *kkstp, *kkstp_free;
|
||||
struct kinfo_proc *kip, *kip_free;
|
||||
@ -140,12 +141,12 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_KSTACK;
|
||||
name[3] = pid;
|
||||
name[3] = kipp->ki_pid;
|
||||
|
||||
kstk_len = 0;
|
||||
error = sysctl(name, 4, NULL, &kstk_len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
|
||||
warn("sysctl: kern.proc.kstack: %d", pid);
|
||||
warn("sysctl: kern.proc.kstack: %d", kipp->ki_pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0 && errno == ENOENT) {
|
||||
@ -160,7 +161,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kkstp, &kstk_len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
warn("sysctl: kern.proc.pid: %d", kipp->ki_pid);
|
||||
free(kkstp);
|
||||
return;
|
||||
}
|
||||
@ -171,12 +172,12 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD;
|
||||
name[3] = pid;
|
||||
name[3] = kipp->ki_pid;
|
||||
|
||||
kip_len = 0;
|
||||
error = sysctl(name, 4, NULL, &kip_len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
warn("sysctl: kern.proc.pid: %d", kipp->ki_pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
@ -187,7 +188,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kip, &kip_len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
warn("sysctl: kern.proc.pid: %d", kipp->ki_pid);
|
||||
free(kip);
|
||||
return;
|
||||
}
|
||||
@ -209,7 +210,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag)
|
||||
if (kipp == NULL)
|
||||
continue;
|
||||
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%6d ", kkstp->kkst_tid);
|
||||
printf("%-16s ", kipp->ki_comm);
|
||||
printf("%-16s ", (strlen(kipp->ki_ocomm) &&
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libprocstat.h>
|
||||
|
||||
#include "procstat.h"
|
||||
|
||||
@ -63,10 +64,12 @@ procstat_print_sig(const sigset_t *set, int sig, char flag)
|
||||
}
|
||||
|
||||
void
|
||||
procstat_sigs(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
|
||||
{
|
||||
int j;
|
||||
pid_t pid;
|
||||
|
||||
pid = kipp->ki_pid;
|
||||
if (!hflag)
|
||||
printf("%5s %-16s %-7s %4s\n", "PID", "COMM", "SIG", "FLAGS");
|
||||
|
||||
@ -83,13 +86,15 @@ procstat_sigs(pid_t pid, struct kinfo_proc *kipp)
|
||||
}
|
||||
|
||||
void
|
||||
procstat_threads_sigs(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_threads_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_proc *kip;
|
||||
pid_t pid;
|
||||
int error, name[4], j;
|
||||
unsigned int i;
|
||||
size_t len;
|
||||
|
||||
pid = kipp->ki_pid;
|
||||
if (!hflag)
|
||||
printf("%5s %6s %-16s %-7s %4s\n", "PID", "TID", "COMM",
|
||||
"SIG", "FLAGS");
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -39,7 +40,7 @@
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_threads(pid_t pid, struct kinfo_proc *kipp)
|
||||
procstat_threads(struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_proc *kip;
|
||||
int error, name[4];
|
||||
@ -57,12 +58,12 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp)
|
||||
name[0] = CTL_KERN;
|
||||
name[1] = KERN_PROC;
|
||||
name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD;
|
||||
name[3] = pid;
|
||||
name[3] = kipp->ki_pid;
|
||||
|
||||
len = 0;
|
||||
error = sysctl(name, 4, NULL, &len, NULL, 0);
|
||||
if (error < 0 && errno != ESRCH) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
warn("sysctl: kern.proc.pid: %d", kipp->ki_pid);
|
||||
return;
|
||||
}
|
||||
if (error < 0)
|
||||
@ -73,7 +74,7 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp)
|
||||
err(-1, "malloc");
|
||||
|
||||
if (sysctl(name, 4, kip, &len, NULL, 0) < 0) {
|
||||
warn("sysctl: kern.proc.pid: %d", pid);
|
||||
warn("sysctl: kern.proc.pid: %d", kipp->ki_pid);
|
||||
free(kip);
|
||||
return;
|
||||
}
|
||||
@ -81,7 +82,7 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp)
|
||||
kinfo_proc_sort(kip, len / sizeof(*kipp));
|
||||
for (i = 0; i < len / sizeof(*kipp); i++) {
|
||||
kipp = &kip[i];
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%6d ", kipp->ki_tid);
|
||||
printf("%-16s ", strlen(kipp->ki_comm) ?
|
||||
kipp->ki_comm : "-");
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libprocstat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@ -40,7 +41,7 @@
|
||||
#include "procstat.h"
|
||||
|
||||
void
|
||||
procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused)
|
||||
procstat_vm(struct kinfo_proc *kipp)
|
||||
{
|
||||
struct kinfo_vmentry *freep, *kve;
|
||||
int ptrwidth;
|
||||
@ -53,12 +54,12 @@ procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused)
|
||||
"PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
|
||||
"PRES", "REF", "SHD", "FL", "TP", "PATH");
|
||||
|
||||
freep = kinfo_getvmmap(pid, &cnt);
|
||||
freep = kinfo_getvmmap(kipp->ki_pid, &cnt);
|
||||
if (freep == NULL)
|
||||
return;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
kve = &freep[i];
|
||||
printf("%5d ", pid);
|
||||
printf("%5d ", kipp->ki_pid);
|
||||
printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
|
||||
printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
|
||||
printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
|
||||
|
Loading…
Reference in New Issue
Block a user