|
Packit |
d37888 |
/* Copyright (C) 1998-99 Martin Baulig
|
|
Packit |
d37888 |
Copyright (C) 2004 Nicol\ufffds Lichtmaier
|
|
Packit |
d37888 |
Copyright (C) 2007 Joe Marcus Clarke
|
|
Packit |
d37888 |
Copyright (C) 2013 Robert Nagy
|
|
Packit |
d37888 |
This file is part of LibGTop 1.0.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
Modified by Nicol\ufffds Lichtmaier to give a process open files.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
Contributed by Martin Baulig <martin@home-of-linux.org>, April 1998.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
LibGTop is free software; you can redistribute it and/or modify it
|
|
Packit |
d37888 |
under the terms of the GNU General Public License as published by
|
|
Packit |
d37888 |
the Free Software Foundation; either version 2 of the License,
|
|
Packit |
d37888 |
or (at your option) any later version.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
LibGTop is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit |
d37888 |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
d37888 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
Packit |
d37888 |
for more details.
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
You should have received a copy of the GNU General Public License
|
|
Packit |
d37888 |
along with LibGTop; see the file COPYING. If not, write to the
|
|
Packit |
d37888 |
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Packit |
d37888 |
Boston, MA 02110-1301, USA.
|
|
Packit |
d37888 |
*/
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#include <config.h>
|
|
Packit |
d37888 |
#include <glibtop.h>
|
|
Packit |
d37888 |
#include <glibtop/error.h>
|
|
Packit |
d37888 |
#include <glibtop/procopenfiles.h>
|
|
Packit |
d37888 |
#include <sys/types.h>
|
|
Packit |
d37888 |
#include <sys/socket.h>
|
|
Packit |
d37888 |
#include <sys/param.h>
|
|
Packit |
d37888 |
#include <sys/sysctl.h>
|
|
Packit |
d37888 |
#define _KERNEL
|
|
Packit |
d37888 |
#include <sys/file.h>
|
|
Packit |
d37888 |
#undef _KERNEL
|
|
Packit |
d37888 |
#include <sys/mount.h>
|
|
Packit |
d37888 |
#include <sys/un.h>
|
|
Packit |
d37888 |
#include <sys/vnode.h>
|
|
Packit |
d37888 |
#include <netinet/in.h>
|
|
Packit |
d37888 |
#include <arpa/inet.h>
|
|
Packit |
d37888 |
#include <string.h>
|
|
Packit |
d37888 |
#include <stdlib.h>
|
|
Packit |
d37888 |
#include <kvm.h>
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
#include "glibtop_private.h"
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
static const unsigned long _glibtop_sysdeps_proc_open_files =
|
|
Packit |
d37888 |
(1L << GLIBTOP_PROC_OPEN_FILES_NUMBER)|
|
|
Packit |
d37888 |
(1L << GLIBTOP_PROC_OPEN_FILES_TOTAL)|
|
|
Packit |
d37888 |
(1L << GLIBTOP_PROC_OPEN_FILES_SIZE);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
kvm_t *kd;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
struct filearg {
|
|
Packit |
d37888 |
SLIST_ENTRY(filearg) next;
|
|
Packit |
d37888 |
dev_t dev;
|
|
Packit |
d37888 |
ino_t ino;
|
|
Packit |
d37888 |
char *name;
|
|
Packit |
d37888 |
TAILQ_HEAD(fuserhead, fuser) fusers;
|
|
Packit |
d37888 |
};
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
SLIST_HEAD(fileargs, filearg);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
/* Init function. */
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
void
|
|
Packit |
d37888 |
_glibtop_init_proc_open_files_s (glibtop *server)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
server->sysdeps.proc_open_files = _glibtop_sysdeps_proc_open_files;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
static char *
|
|
Packit |
d37888 |
addr_to_string(struct kinfo_file *kf)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
char *buffer = NULL;
|
|
Packit |
d37888 |
struct in_addr faddr;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((kf->so_protocol == IPPROTO_TCP) ||
|
|
Packit |
d37888 |
(kf->so_protocol == IPPROTO_UDP)) {
|
|
Packit |
d37888 |
if (kf->inp_fport) {
|
|
Packit |
d37888 |
buffer = g_strdup(faddr.s_addr == INADDR_ANY ? "*" :
|
|
Packit |
d37888 |
inet_ntoa(faddr));
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
return buffer;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
glibtop_open_files_entry *
|
|
Packit |
d37888 |
glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf, pid_t pid)
|
|
Packit |
d37888 |
{
|
|
Packit |
d37888 |
struct kinfo_file *kf, *kflast;
|
|
Packit |
d37888 |
int cnt;
|
|
Packit |
d37888 |
char kbuf[_POSIX2_LINE_MAX];
|
|
Packit |
d37888 |
GArray *entries;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
memset(buf, 0, sizeof (glibtop_proc_open_files));
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, kbuf)) == NULL)
|
|
Packit |
d37888 |
g_warning("%s", kbuf);
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof(*kf), &cnt)) == NULL)
|
|
Packit |
d37888 |
g_warning("%s", kvm_geterr(kd));
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
entries = g_array_new(FALSE, FALSE, sizeof(glibtop_open_files_entry));
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
for (kflast = &kf[cnt]; kf < kflast; ++kf) {
|
|
Packit |
d37888 |
glibtop_open_files_entry entry = {0};
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (kf->fd_fd < 0)
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (kf->f_type == DTYPE_SOCKET) {
|
|
Packit |
d37888 |
if (kf->so_family == AF_LOCAL) {
|
|
Packit |
d37888 |
entry.type = GLIBTOP_FILE_TYPE_LOCALSOCKET;
|
|
Packit |
d37888 |
static char *stypename[] = {
|
|
Packit |
d37888 |
"unused", /* 0 */
|
|
Packit |
d37888 |
"stream",
|
|
Packit |
d37888 |
"dgram",
|
|
Packit |
d37888 |
"raw",
|
|
Packit |
d37888 |
"rdm",
|
|
Packit |
d37888 |
"seqpak"
|
|
Packit |
d37888 |
};
|
|
Packit |
d37888 |
#define STYPEMAX 5
|
|
Packit |
d37888 |
char *stype, stypebuf[24];
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (kf->so_type > STYPEMAX) {
|
|
Packit |
d37888 |
snprintf(stypebuf, sizeof(stypebuf), "?%d", kf->so_type);
|
|
Packit |
d37888 |
stype = stypebuf;
|
|
Packit |
d37888 |
} else {
|
|
Packit |
d37888 |
stype = stypename[kf->so_type];
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
g_strlcpy(entry.info.localsock.name, stype,
|
|
Packit |
d37888 |
sizeof(entry.info.localsock.name));
|
|
Packit |
d37888 |
} else if (kf->so_family == AF_INET ||
|
|
Packit |
d37888 |
kf->so_family == AF_INET6) {
|
|
Packit |
d37888 |
char *addrstr;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (kf->so_family == AF_INET)
|
|
Packit |
d37888 |
entry.type = GLIBTOP_FILE_TYPE_INETSOCKET;
|
|
Packit |
d37888 |
else
|
|
Packit |
d37888 |
entry.type = GLIBTOP_FILE_TYPE_INET6SOCKET;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
addrstr = addr_to_string(kf);
|
|
Packit |
d37888 |
g_strlcpy(entry.info.sock.dest_host,
|
|
Packit |
d37888 |
addrstr,
|
|
Packit |
d37888 |
sizeof(entry.info.sock.dest_host));
|
|
Packit |
d37888 |
g_free(addrstr);
|
|
Packit |
d37888 |
entry.info.sock.dest_port = kf->inp_fport ? ntohs(kf->inp_fport) : 0;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
} else if (kf->f_type == DTYPE_PIPE) {
|
|
Packit |
d37888 |
entry.type = GLIBTOP_FILE_TYPE_PIPE;
|
|
Packit |
d37888 |
} else if (kf->f_type == DTYPE_VNODE) {
|
|
Packit |
d37888 |
int badtype = 0;
|
|
Packit |
d37888 |
char nbuf[MAXPATHLEN];
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
entry.type = GLIBTOP_FILE_TYPE_FILE;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((kf->v_type == VNON) ||
|
|
Packit |
d37888 |
(kf->v_type == VBAD) ||
|
|
Packit |
d37888 |
(kf->v_tag == VT_NON && !(kf->v_flag & VCLONE))) {
|
|
Packit |
d37888 |
badtype = 1;
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if (badtype)
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
if ((kf->v_type == VBLK) ||
|
|
Packit |
d37888 |
(kf->v_type == VCHR)) {
|
|
Packit |
d37888 |
snprintf(nbuf, sizeof(nbuf), "/dev/%s",
|
|
Packit |
d37888 |
devname(kf->va_rdev, kf->v_type == VCHR ? S_IFCHR : S_IFBLK));
|
|
Packit |
d37888 |
} else {
|
|
Packit |
d37888 |
snprintf(nbuf, sizeof(nbuf), "inode %llu on %s", kf->va_fileid,
|
|
Packit |
d37888 |
kf->f_mntonname);
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
g_strlcpy(entry.info.file.name, nbuf,
|
|
Packit |
d37888 |
sizeof(entry.info.file.name));
|
|
Packit |
d37888 |
} else
|
|
Packit |
d37888 |
continue;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
entry.fd = kf->fd_fd;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
g_array_append_val(entries, entry);
|
|
Packit |
d37888 |
}
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
buf->flags = _glibtop_sysdeps_proc_open_files;
|
|
Packit |
d37888 |
buf->number = entries->len;
|
|
Packit |
d37888 |
buf->size = sizeof(glibtop_open_files_entry);
|
|
Packit |
d37888 |
buf->total = buf->number * buf->size;
|
|
Packit |
d37888 |
|
|
Packit |
d37888 |
return (glibtop_open_files_entry*)g_array_free(entries, FALSE);
|
|
Packit |
d37888 |
}
|