Fix several issues related to process information on OpenBSD and drop lsof usage.

This commit is contained in:
Robert Nagy
2014-01-23 10:39:39 +01:00
committed by Jasper Lievisse Adriaanse
parent ff07ba102f
commit df1db43032
3 changed files with 125 additions and 150 deletions

View File

@@ -55,6 +55,7 @@ glibtop_open_p (glibtop *server, const char *program_name,
const unsigned long features, const unsigned long features,
const unsigned flags) const unsigned flags)
{ {
char errbuf[_POSIX2_LINE_MAX];
#ifdef DEBUG #ifdef DEBUG
fprintf (stderr, "DEBUG (%d): glibtop_open_p ()\n", getpid ()); fprintf (stderr, "DEBUG (%d): glibtop_open_p ()\n", getpid ());
#endif #endif
@@ -69,7 +70,7 @@ glibtop_open_p (glibtop *server, const char *program_name,
server->os_version_code = OpenBSD; server->os_version_code = OpenBSD;
/* Setup machine-specific data */ /* Setup machine-specific data */
server->machine.kd = kvm_open (NULL, NULL, NULL, O_RDONLY, "kvm_open"); server->machine.kd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, errbuf);
if (server->machine.kd == NULL) if (server->machine.kd == NULL)
glibtop_error_io_r (server, "kvm_open"); glibtop_error_io_r (server, "kvm_open");

View File

@@ -78,8 +78,8 @@ glibtop_get_proc_kernel_p (glibtop *server,
return; return;
} }
if (pinfo->p_wmesg[0]) if (pinfo->p_wmesg)
g_strlcpy(buf->wchan, pinfo->p_wmesg[0], sizeof(buf->wchan)); g_strlcpy(buf->wchan, pinfo->p_wmesg, sizeof(buf->wchan));
buf->min_flt = pinfo[0].p_uru_minflt; buf->min_flt = pinfo[0].p_uru_minflt;
buf->maj_flt = pinfo[0].p_uru_majflt; buf->maj_flt = pinfo[0].p_uru_majflt;

View File

@@ -1,8 +1,9 @@
/* $OpenBSD: procopenfiles.c,v 1.2 2011/05/23 19:35:55 jasper Exp $ */ /* $OpenBSD: patch-sysdeps_openbsd_procopenfiles_c,v 1.1 2013/12/09 14:26:56 robert Exp $ */
/* Copyright (C) 1998-99 Martin Baulig /* Copyright (C) 1998-99 Martin Baulig
Copyright (C) 2004 Nicol\ufffds Lichtmaier Copyright (C) 2004 Nicol\ufffds Lichtmaier
Copyright (C) 2007 Joe Marcus Clarke Copyright (C) 2007 Joe Marcus Clarke
Copyright (C) 2013 Robert Nagy
This file is part of LibGTop 1.0. This file is part of LibGTop 1.0.
Modified by Nicol\ufffds Lichtmaier to give a process open files. Modified by Nicol\ufffds Lichtmaier to give a process open files.
@@ -33,7 +34,12 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#define _KERNEL
#include <sys/file.h>
#undef _KERNEL
#include <sys/mount.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/vnode.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <string.h> #include <string.h>
@@ -46,6 +52,20 @@ static const unsigned long _glibtop_sysdeps_proc_open_files =
(1L << GLIBTOP_PROC_OPEN_FILES_TOTAL)| (1L << GLIBTOP_PROC_OPEN_FILES_TOTAL)|
(1L << GLIBTOP_PROC_OPEN_FILES_SIZE); (1L << GLIBTOP_PROC_OPEN_FILES_SIZE);
kvm_t *kd;
struct filearg {
SLIST_ENTRY(filearg) next;
dev_t dev;
ino_t ino;
char *name;
TAILQ_HEAD(fuserhead, fuser) fusers;
};
SLIST_HEAD(fileargs, filearg);
struct fileargs fileargs = SLIST_HEAD_INITIALIZER(fileargs);
/* Init function. */ /* Init function. */
void void
@@ -54,167 +74,121 @@ _glibtop_init_proc_open_files_s (glibtop *server)
server->sysdeps.proc_open_files = _glibtop_sysdeps_proc_open_files; server->sysdeps.proc_open_files = _glibtop_sysdeps_proc_open_files;
} }
static GArray * static char *
parse_output(const char *output) { addr_to_string(struct kinfo_file *kf)
GArray *entries; {
char **lines; char *buffer = NULL;
char *ftype = NULL; struct in_addr faddr;
char *fname = NULL;
guint i;
guint len;
int fd = -1;
entries = g_array_new(FALSE, FALSE, sizeof(glibtop_open_files_entry)); memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
lines = g_strsplit(output, "\n", 0); if ((kf->so_protocol == IPPROTO_TCP) ||
len = g_strv_length(lines); (kf->so_protocol == IPPROTO_UDP)) {
if (kf->inp_fport) {
for (i = 0; i < len && lines[i]; i++) { buffer = g_strdup(faddr.s_addr == INADDR_ANY ? "*" :
glibtop_open_files_entry entry = {0}; inet_ntoa(faddr));
if (strlen(lines[i]) < 2)
continue;
if (!g_str_has_prefix(lines[i], "f") &&
!g_str_has_prefix(lines[i], "t") &&
!g_str_has_prefix(lines[i], "n"))
continue;
if (g_str_has_prefix(lines[i], "f")) {
if (!g_ascii_isdigit(*(lines[i] + 1)))
i += 2;
else
fd = atoi(lines[i] + 1);
continue;
} }
if (g_str_has_prefix(lines[i], "t")) {
ftype = lines[i];
ftype++;
continue;
} else {
fname = lines[i];
fname++;
}
if (ftype == NULL || fname == NULL)
continue;
if (!strcmp(ftype, "unix")) {
entry.type = GLIBTOP_FILE_TYPE_LOCALSOCKET;
g_strlcpy(entry.info.localsock.name, fname,
sizeof(entry.info.localsock.name));
} else if (!strcmp(ftype, "PIPE")) {
entry.type = GLIBTOP_FILE_TYPE_PIPE;
} else if (!strcmp(ftype, "VREG") ||
!strcmp(ftype, "GDIR") ||
!strcmp(ftype, "GREG") ||
!strcmp(ftype, "VCHR") ||
!strcmp(ftype, "VBLK") ||
!strcmp(ftype, "DIR") ||
!strcmp(ftype, "LINK") ||
!strcmp(ftype, "REG") ||
!strcmp(ftype, "VDIR")) {
entry.type = GLIBTOP_FILE_TYPE_FILE;
g_strlcpy(entry.info.file.name, fname,
sizeof(entry.info.file.name));
} else if (!strcmp(ftype, "IPv4")) {
char **hosts;
char **remote_host;
if (!strstr(fname, "->")) {
remote_host = g_strsplit(fname, ":", 0);
} else {
hosts = g_strsplit(fname, "->", 0);
if (g_strv_length(hosts) < 2) {
g_strfreev(hosts);
continue;
}
remote_host = g_strsplit(hosts[1], ":", 0);
g_strfreev(hosts);
}
if (g_strv_length(remote_host) < 2) {
g_strfreev(remote_host);
continue;
}
entry.type = GLIBTOP_FILE_TYPE_INETSOCKET;
if (!strcmp(remote_host[0], "*"))
g_strlcpy(entry.info.sock.dest_host, "0.0.0.0",
sizeof(entry.info.sock.dest_host));
else
g_strlcpy(entry.info.sock.dest_host,
remote_host[0],
sizeof(entry.info.sock.dest_host));
entry.info.sock.dest_port = atoi(remote_host[1]);
g_strfreev(remote_host);
} else if (!strcmp(ftype, "IPv6")) {
char **hosts;
char **remote_host;
if (!strstr(fname, "->")) {
remote_host = g_strsplit(fname, ":", 0);
} else {
hosts = g_strsplit(fname, "->", 0);
if (g_strv_length(hosts) < 2) {
g_strfreev(hosts);
continue;
}
remote_host = g_strsplit(hosts[1], "]", 0);
g_strfreev(hosts);
}
if (g_strv_length(remote_host) < 2) {
g_strfreev(remote_host);
continue;
}
entry.type = GLIBTOP_FILE_TYPE_INET6SOCKET;
if (!strcmp(remote_host[0], "*"))
g_strlcpy(entry.info.sock.dest_host, "0.0.0.0",
sizeof(entry.info.sock.dest_host));
else
g_strlcpy(entry.info.sock.dest_host,
remote_host[0] + 1,
sizeof(entry.info.sock.dest_host));
entry.info.sock.dest_port = atoi(remote_host[1] + 1);
g_strfreev(remote_host);
} else
continue;
entry.fd = fd;
fd = -1;
ftype = NULL;
fname = NULL;
g_array_append_val(entries, entry);
} }
g_strfreev(lines); return buffer;
return entries;
} }
glibtop_open_files_entry * glibtop_open_files_entry *
glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf, pid_t pid) glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf, pid_t pid)
{ {
char *output; struct kinfo_file *kf, *kflast;
int cnt;
char kbuf[_POSIX2_LINE_MAX];
GArray *entries; GArray *entries;
memset(buf, 0, sizeof (glibtop_proc_open_files)); memset(buf, 0, sizeof (glibtop_proc_open_files));
output = execute_lsof(pid); if ((kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, kbuf)) == NULL)
if (output == NULL) return NULL; g_warning("%s", kbuf);
entries = parse_output(output); if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof(*kf), &cnt)) == NULL)
g_warning("%s", kvm_geterr(kd));
g_free(output); entries = g_array_new(FALSE, FALSE, sizeof(glibtop_open_files_entry));
for (kflast = &kf[cnt]; kf < kflast; ++kf) {
glibtop_open_files_entry entry = {0};
if (kf->fd_fd < 0)
continue;
if (kf->f_type == DTYPE_SOCKET) {
if (kf->so_family == AF_LOCAL) {
entry.type = GLIBTOP_FILE_TYPE_LOCALSOCKET;
static char *stypename[] = {
"unused", /* 0 */
"stream",
"dgram",
"raw",
"rdm",
"seqpak"
};
#define STYPEMAX 5
char *stype, stypebuf[24];
if (kf->so_type > STYPEMAX) {
snprintf(stypebuf, sizeof(stypebuf), "?%d", kf->so_type);
stype = stypebuf;
} else {
stype = stypename[kf->so_type];
}
g_strlcpy(entry.info.localsock.name, stype,
sizeof(entry.info.localsock.name));
} else if (kf->so_family == AF_INET ||
kf->so_family == AF_INET6) {
char *addrstr;
if (kf->so_family == AF_INET)
entry.type = GLIBTOP_FILE_TYPE_INETSOCKET;
else
entry.type = GLIBTOP_FILE_TYPE_INET6SOCKET;
addrstr = addr_to_string(kf);
g_strlcpy(entry.info.sock.dest_host,
addrstr,
sizeof(entry.info.sock.dest_host));
g_free(addrstr);
entry.info.sock.dest_port = kf->inp_fport ? ntohs(kf->inp_fport) : 0;
}
} else if (kf->f_type == DTYPE_PIPE) {
entry.type = GLIBTOP_FILE_TYPE_PIPE;
} else if (kf->f_type == DTYPE_VNODE) {
int badtype = 0;
char nbuf[MAXPATHLEN];
entry.type = GLIBTOP_FILE_TYPE_FILE;
if ((kf->v_type == VNON) ||
(kf->v_type == VBAD) ||
(kf->v_tag == VT_NON && !(kf->v_flag & VCLONE))) {
badtype = 1;
}
if (badtype)
continue;
if ((kf->v_type == VBLK) ||
(kf->v_type == VCHR)) {
snprintf(nbuf, sizeof(nbuf), "/dev/%s",
devname(kf->va_rdev, kf->v_type == VCHR ? S_IFCHR : S_IFBLK));
} else {
snprintf(nbuf, sizeof(nbuf), "inode %llu on %s", kf->va_fileid,
kf->f_mntonname);
}
g_strlcpy(entry.info.file.name, nbuf,
sizeof(entry.info.file.name));
} else
continue;
entry.fd = kf->fd_fd;
g_array_append_val(entries, entry);
}
buf->flags = _glibtop_sysdeps_proc_open_files; buf->flags = _glibtop_sysdeps_proc_open_files;
buf->number = entries->len; buf->number = entries->len;