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



commit df1db430320c8646f809ef0224c2a620f7cadd1b
Author: Robert Nagy <robert openbsd org>
Date:   Thu Jan 23 10:39:39 2014 +0100

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

 sysdeps/openbsd/open.c          |    3 +-
 sysdeps/openbsd/prockernel.c    |    6 +-
 sysdeps/openbsd/procopenfiles.c |  248 +++++++++++++++++---------------------
 3 files changed, 116 insertions(+), 141 deletions(-)
---
diff --git a/sysdeps/openbsd/open.c b/sysdeps/openbsd/open.c
index d24bdd1..290c9ed 100644
--- a/sysdeps/openbsd/open.c
+++ b/sysdeps/openbsd/open.c
@@ -55,6 +55,7 @@ glibtop_open_p (glibtop *server, const char *program_name,
                const unsigned long features,
                const unsigned flags)
 {
+       char errbuf[_POSIX2_LINE_MAX];
 #ifdef DEBUG
        fprintf (stderr, "DEBUG (%d): glibtop_open_p ()\n", getpid ());
 #endif
@@ -69,7 +70,7 @@ glibtop_open_p (glibtop *server, const char *program_name,
        server->os_version_code = OpenBSD;
 
        /* 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)
                glibtop_error_io_r (server, "kvm_open");
diff --git a/sysdeps/openbsd/prockernel.c b/sysdeps/openbsd/prockernel.c
index 44ed6d8..85ad7f5 100644
--- a/sysdeps/openbsd/prockernel.c
+++ b/sysdeps/openbsd/prockernel.c
@@ -78,9 +78,9 @@ glibtop_get_proc_kernel_p (glibtop *server,
                return;
        }
 
-       if (pinfo->p_wmesg[0])
-               g_strlcpy(buf->wchan, pinfo->p_wmesg[0], sizeof(buf->wchan));
-       
+       if (pinfo->p_wmesg)
+               g_strlcpy(buf->wchan, pinfo->p_wmesg, sizeof(buf->wchan));
+
        buf->min_flt = pinfo[0].p_uru_minflt;
        buf->maj_flt = pinfo[0].p_uru_majflt;
 
diff --git a/sysdeps/openbsd/procopenfiles.c b/sysdeps/openbsd/procopenfiles.c
index 25f9157..ed987a2 100644
--- a/sysdeps/openbsd/procopenfiles.c
+++ b/sysdeps/openbsd/procopenfiles.c
@@ -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) 2004 Nicol\ufffds Lichtmaier
    Copyright (C) 2007 Joe Marcus Clarke
+   Copyright (C) 2013 Robert Nagy
    This file is part of LibGTop 1.0.
 
    Modified by Nicol\ufffds Lichtmaier to give a process open files.
@@ -33,7 +34,12 @@
 #include <sys/socket.h>
 #include <sys/param.h>
 #include <sys/sysctl.h>
+#define _KERNEL
+#include <sys/file.h>
+#undef _KERNEL
+#include <sys/mount.h>
 #include <sys/un.h>
+#include <sys/vnode.h>
 #include <netinet/in.h>
 #include <arpa/inet.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_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. */
 
 void
@@ -54,168 +74,122 @@ _glibtop_init_proc_open_files_s (glibtop *server)
        server->sysdeps.proc_open_files = _glibtop_sysdeps_proc_open_files;
 }
 
-static GArray *
-parse_output(const char *output) {
-       GArray *entries;
-       char **lines;
-       char  *ftype = NULL;
-       char  *fname = NULL;
-       guint  i;
-       guint  len;
-       int    fd = -1;
-
-       entries = g_array_new(FALSE, FALSE, sizeof(glibtop_open_files_entry));
+static char *
+addr_to_string(struct kinfo_file *kf)
+{
+       char *buffer = NULL;
+       struct in_addr faddr;
 
-       lines = g_strsplit(output, "\n", 0);
-       len = g_strv_length(lines);
+       memcpy(&faddr, kf->inp_faddru, sizeof(faddr));
 
-       for (i = 0; i < len && lines[i]; i++) {
-               glibtop_open_files_entry entry = {0};
+       if ((kf->so_protocol == IPPROTO_TCP) ||
+           (kf->so_protocol == IPPROTO_UDP)) {
+               if (kf->inp_fport) {
+                       buffer = g_strdup(faddr.s_addr == INADDR_ANY ? "*" :
+                           inet_ntoa(faddr));
+               }
+       }
 
-               if (strlen(lines[i]) < 2)
-                       continue;
+       return buffer;
+}
 
-               if (!g_str_has_prefix(lines[i], "f") &&
-                   !g_str_has_prefix(lines[i], "t") &&
-                   !g_str_has_prefix(lines[i], "n"))
-                       continue;
+glibtop_open_files_entry *
+glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf,  pid_t pid)
+{
+       struct kinfo_file *kf, *kflast;
+       int cnt;
+       char kbuf[_POSIX2_LINE_MAX];
+       GArray *entries;
 
-               if (g_str_has_prefix(lines[i], "f")) {
-                       if (!g_ascii_isdigit(*(lines[i] + 1)))
-                               i += 2;
-                       else
-                               fd = atoi(lines[i] + 1);
-                       continue;
-               }
+       memset(buf, 0, sizeof (glibtop_proc_open_files));
 
-               if (g_str_has_prefix(lines[i], "t")) {
-                       ftype = lines[i];
-                       ftype++;
-                       continue;
-               } else {
-                       fname = lines[i];
-                       fname++;
-               }
+       if ((kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, kbuf)) == NULL)
+               g_warning("%s", kbuf);
 
-               if (ftype == NULL || fname == NULL)
-                       continue;
+       if ((kf = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof(*kf), &cnt)) == NULL)
+               g_warning("%s", kvm_geterr(kd));
 
-               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;
-                               }
+       entries = g_array_new(FALSE, FALSE, sizeof(glibtop_open_files_entry));
 
-                               remote_host = g_strsplit(hosts[1], ":", 0);
-                               g_strfreev(hosts);
-                       }
+       for (kflast = &kf[cnt]; kf < kflast; ++kf) {
+               glibtop_open_files_entry entry = {0};
 
-                       if (g_strv_length(remote_host) < 2) {
-                               g_strfreev(remote_host);
-                               continue;
-                       }
+               if (kf->fd_fd < 0)
+                       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
+               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,
-                                         remote_host[0],
+                                         addrstr,
                                          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;
+                               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];
 
-                       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;
-                               }
+                       entry.type = GLIBTOP_FILE_TYPE_FILE;
 
-                               remote_host = g_strsplit(hosts[1], "]", 0);
-                               g_strfreev(hosts);
+                       if ((kf->v_type == VNON) ||
+                           (kf->v_type == VBAD) ||
+                           (kf->v_tag == VT_NON && !(kf->v_flag & VCLONE))) {
+                               badtype = 1;
                        }
 
-                       if (g_strv_length(remote_host) < 2) {
-                               g_strfreev(remote_host);
+                       if (badtype)
                                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);
+                       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 = fd;
-
-               fd = -1;
-               ftype = NULL;
-               fname = NULL;
+               entry.fd = kf->fd_fd;
 
                g_array_append_val(entries, entry);
        }
 
-       g_strfreev(lines);
-
-       return entries;
-}
-
-glibtop_open_files_entry *
-glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf,  pid_t pid)
-{
-       char *output;
-       GArray *entries;
-
-       memset(buf, 0, sizeof (glibtop_proc_open_files));
-
-       output = execute_lsof(pid);
-       if (output == NULL) return NULL;
-
-       entries = parse_output(output);
-
-       g_free(output);
-
        buf->flags = _glibtop_sysdeps_proc_open_files;
        buf->number = entries->len;
        buf->size = sizeof(glibtop_open_files_entry);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]