summaryrefslogtreecommitdiff
path: root/psutil/_psutil_bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'psutil/_psutil_bsd.c')
-rw-r--r--psutil/_psutil_bsd.c1012
1 files changed, 11 insertions, 1001 deletions
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index dfebf9ff..a1b4a3e5 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil (OpenBSD).
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola', Landry Breuil
+ * (OpenBSD implementation), Ryo Onodera (NetBSD implementation).
* All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
@@ -15,1034 +16,43 @@
* - psutil.Process.memory_maps()
*/
-#if defined(PSUTIL_NETBSD)
- #define _KMEMUSER
-#endif
-
#include <Python.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#if !defined(__NetBSD__)
- #include <sys/user.h>
-#endif
#include <sys/proc.h>
-#include <sys/file.h>
-#include <sys/socket.h>
-#include <net/route.h>
-#include <sys/socketvar.h> // for struct xsocket
-#include <sys/un.h>
-#include <sys/unpcb.h>
-// for xinpcb struct
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/in_pcb.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp_var.h> // for struct xtcpcb
+#include <sys/param.h> // BSD version
#include <netinet/tcp_fsm.h> // for TCP connection states
-#include <arpa/inet.h> // for inet_ntop()
-#include <sys/mount.h>
-#include <net/if.h> // net io counters
-#include <net/if_dl.h>
-#include <net/route.h>
-#include <netinet/in.h> // process open files/connections
-#include <sys/un.h>
-#include <kvm.h>
#include "_psutil_common.h"
#include "_psutil_posix.h"
+#include "arch/bsd/cpu.h"
+#include "arch/bsd/disk.h"
+#include "arch/bsd/net.h"
+#include "arch/bsd/proc.h"
+#include "arch/bsd/sys.h"
#ifdef PSUTIL_FREEBSD
#include "arch/freebsd/cpu.h"
- #include "arch/freebsd/mem.h"
#include "arch/freebsd/disk.h"
- #include "arch/freebsd/sensors.h"
+ #include "arch/freebsd/mem.h"
#include "arch/freebsd/proc.h"
- #include "arch/freebsd/sys_socks.h"
#include "arch/freebsd/proc_socks.h"
-
- #include <net/if_media.h>
- #include <devstat.h> // get io counters
- #include <libutil.h> // process open files, shared libs (kinfo_getvmmap)
- #if __FreeBSD_version < 900000
- #include <utmp.h> // system users
- #else
- #include <utmpx.h>
- #endif
+ #include "arch/freebsd/sensors.h"
+ #include "arch/freebsd/sys_socks.h"
#elif PSUTIL_OPENBSD
#include "arch/openbsd/cpu.h"
#include "arch/openbsd/disk.h"
#include "arch/openbsd/mem.h"
#include "arch/openbsd/proc.h"
#include "arch/openbsd/socks.h"
-
- #include <utmp.h>
- #include <sys/vnode.h> // for VREG
- #define _KERNEL // for DTYPE_VNODE
- #include <sys/file.h>
- #undef _KERNEL
- #include <sys/sched.h> // for CPUSTATES & CP_*
#elif PSUTIL_NETBSD
#include "arch/netbsd/cpu.h"
#include "arch/netbsd/disk.h"
#include "arch/netbsd/mem.h"
#include "arch/netbsd/proc.h"
#include "arch/netbsd/socks.h"
-
- #include <utmpx.h>
- #include <sys/vnode.h> // for VREG
- #include <sys/sched.h> // for CPUSTATES & CP_*
- #ifndef DTYPE_VNODE
- #define DTYPE_VNODE 1
- #endif
-#endif
-
-
-// convert a timeval struct to a double
-#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
-
-#if defined(PSUTIL_OPENBSD) || defined (PSUTIL_NETBSD)
- #define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
#endif
/*
- * Return a Python list of all the PIDs running on the system.
- */
-static PyObject *
-psutil_pids(PyObject *self, PyObject *args) {
- kinfo_proc *proclist = NULL;
- kinfo_proc *orig_address = NULL;
- size_t num_processes;
- size_t idx;
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_pid = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- if (psutil_get_proc_list(&proclist, &num_processes) != 0)
- goto error;
-
- if (num_processes > 0) {
- orig_address = proclist; // save so we can free it after we're done
- for (idx = 0; idx < num_processes; idx++) {
-#ifdef PSUTIL_FREEBSD
- py_pid = PyLong_FromPid(proclist->ki_pid);
-#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
- py_pid = PyLong_FromPid(proclist->p_pid);
-#endif
- if (!py_pid)
- goto error;
- if (PyList_Append(py_retlist, py_pid))
- goto error;
- Py_CLEAR(py_pid);
- proclist++;
- }
- free(orig_address);
- }
-
- return py_retlist;
-
-error:
- Py_XDECREF(py_pid);
- Py_DECREF(py_retlist);
- if (orig_address != NULL)
- free(orig_address);
- return NULL;
-}
-
-
-/*
- * Return a Python float indicating the system boot time expressed in
- * seconds since the epoch.
- */
-static PyObject *
-psutil_boot_time(PyObject *self, PyObject *args) {
- // fetch sysctl "kern.boottime"
- static int request[2] = { CTL_KERN, KERN_BOOTTIME };
- struct timeval boottime;
- size_t len = sizeof(boottime);
-
- if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1)
- return PyErr_SetFromErrno(PyExc_OSError);
- return Py_BuildValue("d", (double)boottime.tv_sec);
-}
-
-
-/*
- * Collect different info about a process in one shot and return
- * them as a big Python tuple.
- */
-static PyObject *
-psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
- pid_t pid;
- long rss;
- long vms;
- long memtext;
- long memdata;
- long memstack;
- int oncpu;
- kinfo_proc kp;
- long pagesize = psutil_getpagesize();
- char str[1000];
- PyObject *py_name;
- PyObject *py_ppid;
- PyObject *py_retlist;
-
- if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
- return NULL;
- if (psutil_kinfo_proc(pid, &kp) == -1)
- return NULL;
-
- // Process
-#ifdef PSUTIL_FREEBSD
- sprintf(str, "%s", kp.ki_comm);
-#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
- sprintf(str, "%s", kp.p_comm);
-#endif
- py_name = PyUnicode_DecodeFSDefault(str);
- if (! py_name) {
- // Likely a decoding error. We don't want to fail the whole
- // operation. The python module may retry with proc_name().
- PyErr_Clear();
- py_name = Py_None;
- }
- // Py_INCREF(py_name);
-
- // Calculate memory.
-#ifdef PSUTIL_FREEBSD
- rss = (long)kp.ki_rssize * pagesize;
- vms = (long)kp.ki_size;
- memtext = (long)kp.ki_tsize * pagesize;
- memdata = (long)kp.ki_dsize * pagesize;
- memstack = (long)kp.ki_ssize * pagesize;
-#else
- rss = (long)kp.p_vm_rssize * pagesize;
- #ifdef PSUTIL_OPENBSD
- // VMS, this is how ps determines it on OpenBSD:
- // https://github.com/openbsd/src/blob/
- // 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L505
- vms = (long)(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize) * pagesize;
- #elif PSUTIL_NETBSD
- // VMS, this is how top determines it on NetBSD:
- // https://github.com/IIJ-NetBSD/netbsd-src/blob/master/external/
- // bsd/top/dist/machine/m_netbsd.c
- vms = (long)kp.p_vm_msize * pagesize;
- #endif
- memtext = (long)kp.p_vm_tsize * pagesize;
- memdata = (long)kp.p_vm_dsize * pagesize;
- memstack = (long)kp.p_vm_ssize * pagesize;
-#endif
-
-#ifdef PSUTIL_FREEBSD
- // what CPU we're on; top was used as an example:
- // https://svnweb.freebsd.org/base/head/usr.bin/top/machine.c?
- // view=markup&pathrev=273835
- // XXX - note: for "intr" PID this is -1.
- if (kp.ki_stat == SRUN && kp.ki_oncpu != NOCPU)
- oncpu = kp.ki_oncpu;
- else
- oncpu = kp.ki_lastcpu;
-#else
- // On Net/OpenBSD we have kp.p_cpuid but it appears it's always
- // set to KI_NOCPU. Even if it's not, ki_lastcpu does not exist
- // so there's no way to determine where "sleeping" processes
- // were. Not supported.
- oncpu = -1;
-#endif
-
-#ifdef PSUTIL_FREEBSD
- py_ppid = PyLong_FromPid(kp.ki_ppid);
-#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
- py_ppid = PyLong_FromPid(kp.p_ppid);
-#else
- py_ppid = Py_BuildfValue(-1);
-#endif
- if (! py_ppid)
- return NULL;
-
- // Return a single big tuple with all process info.
- py_retlist = Py_BuildValue(
-#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
- "(OillllllLdllllddddlllllbO)",
-#else
- "(OillllllidllllddddlllllbO)",
-#endif
-#ifdef PSUTIL_FREEBSD
- py_ppid, // (pid_t) ppid
- (int)kp.ki_stat, // (int) status
- // UIDs
- (long)kp.ki_ruid, // (long) real uid
- (long)kp.ki_uid, // (long) effective uid
- (long)kp.ki_svuid, // (long) saved uid
- // GIDs
- (long)kp.ki_rgid, // (long) real gid
- (long)kp.ki_groups[0], // (long) effective gid
- (long)kp.ki_svuid, // (long) saved gid
- //
- kp.ki_tdev, // (int or long long) tty nr
- PSUTIL_TV2DOUBLE(kp.ki_start), // (double) create time
- // ctx switches
- kp.ki_rusage.ru_nvcsw, // (long) ctx switches (voluntary)
- kp.ki_rusage.ru_nivcsw, // (long) ctx switches (unvoluntary)
- // IO count
- kp.ki_rusage.ru_inblock, // (long) read io count
- kp.ki_rusage.ru_oublock, // (long) write io count
- // CPU times: convert from micro seconds to seconds.
- PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime), // (double) user time
- PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime), // (double) sys time
- PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_utime), // (double) children utime
- PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_stime), // (double) children stime
- // memory
- rss, // (long) rss
- vms, // (long) vms
- memtext, // (long) mem text
- memdata, // (long) mem data
- memstack, // (long) mem stack
- // others
- oncpu, // (int) the CPU we are on
-#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
- py_ppid, // (pid_t) ppid
- (int)kp.p_stat, // (int) status
- // UIDs
- (long)kp.p_ruid, // (long) real uid
- (long)kp.p_uid, // (long) effective uid
- (long)kp.p_svuid, // (long) saved uid
- // GIDs
- (long)kp.p_rgid, // (long) real gid
- (long)kp.p_groups[0], // (long) effective gid
- (long)kp.p_svuid, // (long) saved gid
- //
- kp.p_tdev, // (int) tty nr
- PSUTIL_KPT2DOUBLE(kp.p_ustart), // (double) create time
- // ctx switches
- kp.p_uru_nvcsw, // (long) ctx switches (voluntary)
- kp.p_uru_nivcsw, // (long) ctx switches (unvoluntary)
- // IO count
- kp.p_uru_inblock, // (long) read io count
- kp.p_uru_oublock, // (long) write io count
- // CPU times: convert from micro seconds to seconds.
- PSUTIL_KPT2DOUBLE(kp.p_uutime), // (double) user time
- PSUTIL_KPT2DOUBLE(kp.p_ustime), // (double) sys time
- // OpenBSD and NetBSD provide children user + system times summed
- // together (no distinction).
- kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch utime
- kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch stime
- // memory
- rss, // (long) rss
- vms, // (long) vms
- memtext, // (long) mem text
- memdata, // (long) mem data
- memstack, // (long) mem stack
- // others
- oncpu, // (int) the CPU we are on
-#endif
- py_name // (pystr) name
- );
-
- Py_DECREF(py_name);
- Py_DECREF(py_ppid);
- return py_retlist;
-}
-
-
-/*
- * Return process name from kinfo_proc as a Python string.
- */
-static PyObject *
-psutil_proc_name(PyObject *self, PyObject *args) {
- pid_t pid;
- kinfo_proc kp;
- char str[1000];
-
- if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
- return NULL;
- if (psutil_kinfo_proc(pid, &kp) == -1)
- return NULL;
-
-#ifdef PSUTIL_FREEBSD
- sprintf(str, "%s", kp.ki_comm);
-#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
- sprintf(str, "%s", kp.p_comm);
-#endif
- return PyUnicode_DecodeFSDefault(str);
-}
-
-
-
-/*
- * Return process environment as a Python dictionary
- */
-PyObject *
-psutil_proc_environ(PyObject *self, PyObject *args) {
- int i, cnt = -1;
- long pid;
- char *s, **envs, errbuf[_POSIX2_LINE_MAX];
- PyObject *py_value=NULL, *py_retdict=NULL;
- kvm_t *kd;
-#ifdef PSUTIL_NETBSD
- struct kinfo_proc2 *p;
-#else
- struct kinfo_proc *p;
-#endif
-
- if (!PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
-#if defined(PSUTIL_FREEBSD)
- kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
-#else
- kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
-#endif
- if (!kd) {
- convert_kvm_err("kvm_openfiles", errbuf);
- return NULL;
- }
-
- py_retdict = PyDict_New();
- if (!py_retdict)
- goto error;
-
-#if defined(PSUTIL_FREEBSD)
- p = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt);
-#elif defined(PSUTIL_OPENBSD)
- p = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(*p), &cnt);
-#elif defined(PSUTIL_NETBSD)
- p = kvm_getproc2(kd, KERN_PROC_PID, pid, sizeof(*p), &cnt);
-#endif
- if (!p) {
- NoSuchProcess("kvm_getprocs");
- goto error;
- }
- if (cnt <= 0) {
- NoSuchProcess(cnt < 0 ? kvm_geterr(kd) : "kvm_getprocs: cnt==0");
- goto error;
- }
-
- // On *BSD kernels there are a few kernel-only system processes without an
- // environment (See e.g. "procstat -e 0 | 1 | 2 ..." on FreeBSD.)
- // Some system process have no stats attached at all
- // (they are marked with P_SYSTEM.)
- // On FreeBSD, it's possible that the process is swapped or paged out,
- // then there no access to the environ stored in the process' user area.
- // On NetBSD, we cannot call kvm_getenvv2() for a zombie process.
- // To make unittest suite happy, return an empty environment.
-#if defined(PSUTIL_FREEBSD)
-#if (defined(__FreeBSD_version) && __FreeBSD_version >= 700000)
- if (!((p)->ki_flag & P_INMEM) || ((p)->ki_flag & P_SYSTEM)) {
-#else
- if ((p)->ki_flag & P_SYSTEM) {
-#endif
-#elif defined(PSUTIL_NETBSD)
- if ((p)->p_stat == SZOMB) {
-#elif defined(PSUTIL_OPENBSD)
- if ((p)->p_flag & P_SYSTEM) {
-#endif
- kvm_close(kd);
- return py_retdict;
- }
-
-#if defined(PSUTIL_NETBSD)
- envs = kvm_getenvv2(kd, p, 0);
-#else
- envs = kvm_getenvv(kd, p, 0);
-#endif
- if (!envs) {
- // Map to "psutil" general high-level exceptions
- switch (errno) {
- case 0:
- // Process has cleared it's environment, return empty one
- kvm_close(kd);
- return py_retdict;
- case EPERM:
- AccessDenied("kvm_getenvv -> EPERM");
- break;
- case ESRCH:
- NoSuchProcess("kvm_getenvv -> ESRCH");
- break;
-#if defined(PSUTIL_FREEBSD)
- case ENOMEM:
- // Unfortunately, under FreeBSD kvm_getenvv() returns
- // failure for certain processes ( e.g. try
- // "sudo procstat -e <pid of your XOrg server>".)
- // Map the error condition to 'AccessDenied'.
- sprintf(errbuf,
- "kvm_getenvv(pid=%ld, ki_uid=%d) -> ENOMEM",
- pid, p->ki_uid);
- AccessDenied(errbuf);
- break;
-#endif
- default:
- sprintf(errbuf, "kvm_getenvv(pid=%ld)", pid);
- PyErr_SetFromOSErrnoWithSyscall(errbuf);
- break;
- }
- goto error;
- }
-
- for (i = 0; envs[i] != NULL; i++) {
- s = strchr(envs[i], '=');
- if (!s)
- continue;
- *s++ = 0;
- py_value = PyUnicode_DecodeFSDefault(s);
- if (!py_value)
- goto error;
- if (PyDict_SetItemString(py_retdict, envs[i], py_value)) {
- goto error;
- }
- Py_DECREF(py_value);
- }
-
- kvm_close(kd);
- return py_retdict;
-
-error:
- Py_XDECREF(py_value);
- Py_XDECREF(py_retdict);
- kvm_close(kd);
- return NULL;
-}
-
-/*
- * Return the number of logical CPUs in the system.
- * XXX this could be shared with macOS
- */
-static PyObject *
-psutil_cpu_count_logical(PyObject *self, PyObject *args) {
- int mib[2];
- int ncpu;
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
-
- if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", ncpu);
-}
-
-
-/*
- * Return a Python tuple representing user, kernel and idle CPU times
- */
-static PyObject *
-psutil_cpu_times(PyObject *self, PyObject *args) {
-#ifdef PSUTIL_NETBSD
- u_int64_t cpu_time[CPUSTATES];
-#else
- long cpu_time[CPUSTATES];
-#endif
- size_t size = sizeof(cpu_time);
- int ret;
-
-#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD)
- ret = sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0);
-#elif PSUTIL_OPENBSD
- int mib[] = {CTL_KERN, KERN_CPTIME};
- ret = sysctl(mib, 2, &cpu_time, &size, NULL, 0);
-#endif
- if (ret == -1)
- return PyErr_SetFromErrno(PyExc_OSError);
- return Py_BuildValue("(ddddd)",
- (double)cpu_time[CP_USER] / CLOCKS_PER_SEC,
- (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC,
- (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC,
- (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC,
- (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC
- );
-}
-
-
- /*
- * Return files opened by process as a list of (path, fd) tuples.
- * TODO: this is broken as it may report empty paths. 'procstat'
- * utility has the same problem see:
- * https://github.com/giampaolo/psutil/issues/595
- */
-#if (defined(__FreeBSD_version) && __FreeBSD_version >= 800000) || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD)
-static PyObject *
-psutil_proc_open_files(PyObject *self, PyObject *args) {
- pid_t pid;
- int i;
- int cnt;
- int regular;
- int fd;
- char *path;
- struct kinfo_file *freep = NULL;
- struct kinfo_file *kif;
- kinfo_proc kipp;
- PyObject *py_tuple = NULL;
- PyObject *py_path = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
- if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
- goto error;
- if (psutil_kinfo_proc(pid, &kipp) == -1)
- goto error;
-
- errno = 0;
- freep = kinfo_getfile(pid, &cnt);
- if (freep == NULL) {
-#if !defined(PSUTIL_OPENBSD)
- psutil_raise_for_pid(pid, "kinfo_getfile()");
-#endif
- goto error;
- }
-
- for (i = 0; i < cnt; i++) {
- kif = &freep[i];
-
-#ifdef PSUTIL_FREEBSD
- regular = (kif->kf_type == KF_TYPE_VNODE) && \
- (kif->kf_vnode_type == KF_VTYPE_VREG);
- fd = kif->kf_fd;
- path = kif->kf_path;
-#elif PSUTIL_OPENBSD
- regular = (kif->f_type == DTYPE_VNODE) && (kif->v_type == VREG);
- fd = kif->fd_fd;
- // XXX - it appears path is not exposed in the kinfo_file struct.
- path = "";
-#elif PSUTIL_NETBSD
- regular = (kif->ki_ftype == DTYPE_VNODE) && (kif->ki_vtype == VREG);
- fd = kif->ki_fd;
- // XXX - it appears path is not exposed in the kinfo_file struct.
- path = "";
-#endif
- if (regular == 1) {
- py_path = PyUnicode_DecodeFSDefault(path);
- if (! py_path)
- goto error;
- py_tuple = Py_BuildValue("(Oi)", py_path, fd);
- if (py_tuple == NULL)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_CLEAR(py_path);
- Py_CLEAR(py_tuple);
- }
- }
- free(freep);
- return py_retlist;
-
-error:
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- if (freep != NULL)
- free(freep);
- return NULL;
-}
-#endif
-
-
-/*
- * Return a list of tuples including device, mount point and fs type
- * for all partitions mounted on the system.
- */
-static PyObject *
-psutil_disk_partitions(PyObject *self, PyObject *args) {
- int num;
- int i;
- long len;
- uint64_t flags;
- char opts[200];
-#ifdef PSUTIL_NETBSD
- struct statvfs *fs = NULL;
-#else
- struct statfs *fs = NULL;
-#endif
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_dev = NULL;
- PyObject *py_mountp = NULL;
- PyObject *py_tuple = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- // get the number of mount points
- Py_BEGIN_ALLOW_THREADS
-#ifdef PSUTIL_NETBSD
- num = getvfsstat(NULL, 0, MNT_NOWAIT);
-#else
- num = getfsstat(NULL, 0, MNT_NOWAIT);
-#endif
- Py_END_ALLOW_THREADS
- if (num == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- len = sizeof(*fs) * num;
- fs = malloc(len);
- if (fs == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- Py_BEGIN_ALLOW_THREADS
-#ifdef PSUTIL_NETBSD
- num = getvfsstat(fs, len, MNT_NOWAIT);
-#else
- num = getfsstat(fs, len, MNT_NOWAIT);
-#endif
- Py_END_ALLOW_THREADS
- if (num == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- for (i = 0; i < num; i++) {
- py_tuple = NULL;
- opts[0] = 0;
-#ifdef PSUTIL_NETBSD
- flags = fs[i].f_flag;
-#else
- flags = fs[i].f_flags;
-#endif
-
- // see sys/mount.h
- if (flags & MNT_RDONLY)
- strlcat(opts, "ro", sizeof(opts));
- else
- strlcat(opts, "rw", sizeof(opts));
- if (flags & MNT_SYNCHRONOUS)
- strlcat(opts, ",sync", sizeof(opts));
- if (flags & MNT_NOEXEC)
- strlcat(opts, ",noexec", sizeof(opts));
- if (flags & MNT_NOSUID)
- strlcat(opts, ",nosuid", sizeof(opts));
- if (flags & MNT_ASYNC)
- strlcat(opts, ",async", sizeof(opts));
- if (flags & MNT_NOATIME)
- strlcat(opts, ",noatime", sizeof(opts));
- if (flags & MNT_SOFTDEP)
- strlcat(opts, ",softdep", sizeof(opts));
-#ifdef PSUTIL_FREEBSD
- if (flags & MNT_UNION)
- strlcat(opts, ",union", sizeof(opts));
- if (flags & MNT_SUIDDIR)
- strlcat(opts, ",suiddir", sizeof(opts));
- if (flags & MNT_SOFTDEP)
- strlcat(opts, ",softdep", sizeof(opts));
- if (flags & MNT_NOSYMFOLLOW)
- strlcat(opts, ",nosymfollow", sizeof(opts));
-#ifdef MNT_GJOURNAL
- if (flags & MNT_GJOURNAL)
- strlcat(opts, ",gjournal", sizeof(opts));
-#endif
- if (flags & MNT_MULTILABEL)
- strlcat(opts, ",multilabel", sizeof(opts));
- if (flags & MNT_ACLS)
- strlcat(opts, ",acls", sizeof(opts));
- if (flags & MNT_NOCLUSTERR)
- strlcat(opts, ",noclusterr", sizeof(opts));
- if (flags & MNT_NOCLUSTERW)
- strlcat(opts, ",noclusterw", sizeof(opts));
-#ifdef MNT_NFS4ACLS
- if (flags & MNT_NFS4ACLS)
- strlcat(opts, ",nfs4acls", sizeof(opts));
-#endif
-#elif PSUTIL_NETBSD
- if (flags & MNT_NODEV)
- strlcat(opts, ",nodev", sizeof(opts));
- if (flags & MNT_UNION)
- strlcat(opts, ",union", sizeof(opts));
- if (flags & MNT_NOCOREDUMP)
- strlcat(opts, ",nocoredump", sizeof(opts));
-#ifdef MNT_RELATIME
- if (flags & MNT_RELATIME)
- strlcat(opts, ",relatime", sizeof(opts));
-#endif
- if (flags & MNT_IGNORE)
- strlcat(opts, ",ignore", sizeof(opts));
-#ifdef MNT_DISCARD
- if (flags & MNT_DISCARD)
- strlcat(opts, ",discard", sizeof(opts));
-#endif
-#ifdef MNT_EXTATTR
- if (flags & MNT_EXTATTR)
- strlcat(opts, ",extattr", sizeof(opts));
-#endif
- if (flags & MNT_LOG)
- strlcat(opts, ",log", sizeof(opts));
- if (flags & MNT_SYMPERM)
- strlcat(opts, ",symperm", sizeof(opts));
- if (flags & MNT_NODEVMTIME)
- strlcat(opts, ",nodevmtime", sizeof(opts));
-#endif
- py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname);
- if (! py_dev)
- goto error;
- py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname);
- if (! py_mountp)
- goto error;
- py_tuple = Py_BuildValue("(OOss)",
- py_dev, // device
- py_mountp, // mount point
- fs[i].f_fstypename, // fs type
- opts); // options
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_CLEAR(py_dev);
- Py_CLEAR(py_mountp);
- Py_CLEAR(py_tuple);
- }
-
- free(fs);
- return py_retlist;
-
-error:
- Py_XDECREF(py_dev);
- Py_XDECREF(py_mountp);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- if (fs != NULL)
- free(fs);
- return NULL;
-}
-
-
-/*
- * Return a Python list of named tuples with overall network I/O information
- */
-static PyObject *
-psutil_net_io_counters(PyObject *self, PyObject *args) {
- char *buf = NULL, *lim, *next;
- struct if_msghdr *ifm;
- int mib[6];
- size_t len;
- PyObject *py_retdict = PyDict_New();
- PyObject *py_ifc_info = NULL;
- if (py_retdict == NULL)
- return NULL;
-
- mib[0] = CTL_NET; // networking subsystem
- mib[1] = PF_ROUTE; // type of information
- mib[2] = 0; // protocol (IPPROTO_xxx)
- mib[3] = 0; // address family
- mib[4] = NET_RT_IFLIST; // operation
- mib[5] = 0;
-
- if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- buf = malloc(len);
- if (buf == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- lim = buf + len;
-
- for (next = buf; next < lim; ) {
- py_ifc_info = NULL;
- ifm = (struct if_msghdr *)next;
- next += ifm->ifm_msglen;
-
- if (ifm->ifm_type == RTM_IFINFO) {
- struct if_msghdr *if2m = (struct if_msghdr *)ifm;
- struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
- char ifc_name[32];
-
- strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen);
- ifc_name[sdl->sdl_nlen] = 0;
- // XXX: ignore usbus interfaces:
- // http://lists.freebsd.org/pipermail/freebsd-current/
- // 2011-October/028752.html
- // 'ifconfig -a' doesn't show them, nor do we.
- if (strncmp(ifc_name, "usbus", 5) == 0)
- continue;
-
- py_ifc_info = Py_BuildValue("(kkkkkkki)",
- if2m->ifm_data.ifi_obytes,
- if2m->ifm_data.ifi_ibytes,
- if2m->ifm_data.ifi_opackets,
- if2m->ifm_data.ifi_ipackets,
- if2m->ifm_data.ifi_ierrors,
- if2m->ifm_data.ifi_oerrors,
- if2m->ifm_data.ifi_iqdrops,
-#ifdef _IFI_OQDROPS
- if2m->ifm_data.ifi_oqdrops
-#else
- 0
-#endif
- );
- if (!py_ifc_info)
- goto error;
- if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
- goto error;
- Py_CLEAR(py_ifc_info);
- }
- else {
- continue;
- }
- }
-
- free(buf);
- return py_retdict;
-
-error:
- Py_XDECREF(py_ifc_info);
- Py_DECREF(py_retdict);
- if (buf != NULL)
- free(buf);
- return NULL;
-}
-
-
-/*
- * Return currently connected users as a list of tuples.
- */
-static PyObject *
-psutil_users(PyObject *self, PyObject *args) {
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_username = NULL;
- PyObject *py_tty = NULL;
- PyObject *py_hostname = NULL;
- PyObject *py_tuple = NULL;
- PyObject *py_pid = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
-#if (defined(__FreeBSD_version) && (__FreeBSD_version < 900000)) || PSUTIL_OPENBSD
- struct utmp ut;
- FILE *fp;
-
- Py_BEGIN_ALLOW_THREADS
- fp = fopen(_PATH_UTMP, "r");
- Py_END_ALLOW_THREADS
- if (fp == NULL) {
- PyErr_SetFromErrnoWithFilename(PyExc_OSError, _PATH_UTMP);
- goto error;
- }
-
- while (fread(&ut, sizeof(ut), 1, fp) == 1) {
- if (*ut.ut_name == '\0')
- continue;
- py_username = PyUnicode_DecodeFSDefault(ut.ut_name);
- if (! py_username)
- goto error;
- py_tty = PyUnicode_DecodeFSDefault(ut.ut_line);
- if (! py_tty)
- goto error;
- py_hostname = PyUnicode_DecodeFSDefault(ut.ut_host);
- if (! py_hostname)
- goto error;
- py_tuple = Py_BuildValue(
- "(OOOdi)",
- py_username, // username
- py_tty, // tty
- py_hostname, // hostname
- (double)ut.ut_time, // start time
-#if defined(PSUTIL_OPENBSD) || (defined(__FreeBSD_version) && __FreeBSD_version < 900000)
- -1 // process id (set to None later)
-#else
- ut.ut_pid // TODO: use PyLong_FromPid
-#endif
- );
- if (!py_tuple) {
- fclose(fp);
- goto error;
- }
- if (PyList_Append(py_retlist, py_tuple)) {
- fclose(fp);
- goto error;
- }
- Py_CLEAR(py_username);
- Py_CLEAR(py_tty);
- Py_CLEAR(py_hostname);
- Py_CLEAR(py_tuple);
- }
-
- fclose(fp);
-#else
- struct utmpx *utx;
- setutxent();
- while ((utx = getutxent()) != NULL) {
- if (utx->ut_type != USER_PROCESS)
- continue;
- py_username = PyUnicode_DecodeFSDefault(utx->ut_user);
- if (! py_username)
- goto error;
- py_tty = PyUnicode_DecodeFSDefault(utx->ut_line);
- if (! py_tty)
- goto error;
- py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host);
- if (! py_hostname)
- goto error;
-#ifdef PSUTIL_OPENBSD
- py_pid = Py_BuildValue("i", -1); // set to None later
-#else
- py_pid = PyLong_FromPid(utx->ut_pid);
-#endif
- if (! py_pid)
- goto error;
-
- py_tuple = Py_BuildValue(
- "(OOOdO)",
- py_username, // username
- py_tty, // tty
- py_hostname, // hostname
- (double)utx->ut_tv.tv_sec, // start time
- py_pid // process id
- );
-
- if (!py_tuple) {
- endutxent();
- goto error;
- }
- if (PyList_Append(py_retlist, py_tuple)) {
- endutxent();
- goto error;
- }
- Py_CLEAR(py_username);
- Py_CLEAR(py_tty);
- Py_CLEAR(py_hostname);
- Py_CLEAR(py_tuple);
- Py_CLEAR(py_pid);
- }
-
- endutxent();
-#endif
- return py_retlist;
-
-error:
- Py_XDECREF(py_username);
- Py_XDECREF(py_tty);
- Py_XDECREF(py_hostname);
- Py_XDECREF(py_tuple);
- Py_XDECREF(py_pid);
- Py_DECREF(py_retlist);
- return NULL;
-}
-
-
-/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef mod_methods[] = {