summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2023-04-19 20:15:29 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2023-04-19 20:15:29 +0200
commitf6c003293249fab17e33d48c76d8527bdd91a0f7 (patch)
tree509cf0e0467c39c7f134082c0543c8471420d8f4
parent968e4bba7dd015d5a469c77ec65956f211d3a5bd (diff)
parentcaa184349c934958b3673c8d3532c607caa2052a (diff)
downloadpsutil-f6c003293249fab17e33d48c76d8527bdd91a0f7.tar.gz
Merge branch 'c-refact'
-rw-r--r--MANIFEST.in14
-rw-r--r--Makefile1
-rw-r--r--psutil/_psutil_bsd.c1012
-rw-r--r--psutil/arch/bsd/cpu.c55
-rw-r--r--psutil/arch/bsd/cpu.h10
-rw-r--r--psutil/arch/bsd/disk.c183
-rw-r--r--psutil/arch/bsd/disk.h9
-rw-r--r--psutil/arch/bsd/net.c105
-rw-r--r--psutil/arch/bsd/net.h9
-rw-r--r--psutil/arch/bsd/proc.c494
-rw-r--r--psutil/arch/bsd/proc.h13
-rw-r--r--psutil/arch/bsd/sys.c161
-rw-r--r--psutil/arch/bsd/sys.h10
-rwxr-xr-xsetup.py21
14 files changed, 1093 insertions, 1004 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index a594328d..db707935 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -47,6 +47,16 @@ include psutil/arch/aix/ifaddrs.h
include psutil/arch/aix/net_connections.c
include psutil/arch/aix/net_connections.h
include psutil/arch/aix/net_kernel_structs.h
+include psutil/arch/bsd/cpu.c
+include psutil/arch/bsd/cpu.h
+include psutil/arch/bsd/disk.c
+include psutil/arch/bsd/disk.h
+include psutil/arch/bsd/net.c
+include psutil/arch/bsd/net.h
+include psutil/arch/bsd/proc.c
+include psutil/arch/bsd/proc.h
+include psutil/arch/bsd/sys.c
+include psutil/arch/bsd/sys.h
include psutil/arch/freebsd/cpu.c
include psutil/arch/freebsd/cpu.h
include psutil/arch/freebsd/disk.c
@@ -106,10 +116,14 @@ include psutil/arch/windows/process_utils.c
include psutil/arch/windows/process_utils.h
include psutil/arch/windows/security.c
include psutil/arch/windows/security.h
+include psutil/arch/windows/sensors.c
+include psutil/arch/windows/sensors.h
include psutil/arch/windows/services.c
include psutil/arch/windows/services.h
include psutil/arch/windows/socks.c
include psutil/arch/windows/socks.h
+include psutil/arch/windows/sys.c
+include psutil/arch/windows/sys.h
include psutil/arch/windows/wmi.c
include psutil/arch/windows/wmi.h
include psutil/tests/README.rst
diff --git a/Makefile b/Makefile
index 27bba266..ba62aa98 100644
--- a/Makefile
+++ b/Makefile
@@ -87,6 +87,7 @@ build: ## Compile (in parallel) without installing.
@# to allow "import psutil" when using the interactive interpreter from
@# within this directory.
PYTHONWARNINGS=all $(PYTHON) setup.py build_ext -i $(BUILD_OPTS)
+ $(PYTHON) -c "import psutil" # make sure it actually worked
install: ## Install this package as current user in "edit" mode.
${MAKE} build
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[] = {
diff --git a/psutil/arch/bsd/cpu.c b/psutil/arch/bsd/cpu.c
new file mode 100644
index 00000000..69325c63
--- /dev/null
+++ b/psutil/arch/bsd/cpu.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+#include <sys/sched.h>
+
+
+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);
+}
+
+
+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
+ );
+}
diff --git a/psutil/arch/bsd/cpu.h b/psutil/arch/bsd/cpu.h
new file mode 100644
index 00000000..9c5d297f
--- /dev/null
+++ b/psutil/arch/bsd/cpu.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_cpu_count_logical(PyObject *self, PyObject *args);
+PyObject *psutil_cpu_times(PyObject *self, PyObject *args);
diff --git a/psutil/arch/bsd/disk.c b/psutil/arch/bsd/disk.c
new file mode 100644
index 00000000..bc1cf863
--- /dev/null
+++ b/psutil/arch/bsd/disk.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+#include <sys/mount.h>
+#if PSUTIL_NETBSD
+ // getvfsstat()
+ #include <sys/types.h>
+ #include <sys/statvfs.h>
+#else
+ // getfsstat()
+ #include <sys/param.h>
+ #include <sys/ucred.h>
+ #include <sys/mount.h>
+#endif
+
+
+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;
+}
diff --git a/psutil/arch/bsd/disk.h b/psutil/arch/bsd/disk.h
new file mode 100644
index 00000000..628907a9
--- /dev/null
+++ b/psutil/arch/bsd/disk.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_disk_partitions(PyObject *self, PyObject *args);
diff --git a/psutil/arch/bsd/net.c b/psutil/arch/bsd/net.c
new file mode 100644
index 00000000..c2fcc066
--- /dev/null
+++ b/psutil/arch/bsd/net.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+#include <sys/sysctl.h>
+#include <string.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+
+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;
+}
diff --git a/psutil/arch/bsd/net.h b/psutil/arch/bsd/net.h
new file mode 100644
index 00000000..99079523
--- /dev/null
+++ b/psutil/arch/bsd/net.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_net_io_counters(PyObject *self, PyObject *args);
diff --git a/psutil/arch/bsd/proc.c b/psutil/arch/bsd/proc.c
new file mode 100644
index 00000000..e64cf80d
--- /dev/null
+++ b/psutil/arch/bsd/proc.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+#include <kvm.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/vnode.h> // VREG
+#ifdef PSUTIL_FREEBSD
+ #include <sys/user.h> // kinfo_proc, kinfo_file, KF_*
+ #include <libutil.h> // kinfo_getfile()
+#endif
+
+#include "../../_psutil_common.h"
+#include "../../_psutil_posix.h"
+#ifdef PSUTIL_FREEBSD
+ #include "../../arch/freebsd/proc.h"
+#elif PSUTIL_OPENBSD
+ #include "../../arch/openbsd/proc.h"
+#elif PSUTIL_NETBSD
+ #include "../../arch/netbsd/proc.h"
+#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.
+ */
+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;
+}
+
+
+/*
+ * Collect different info about a process in one shot and return
+ * them as a big Python tuple.
+ */
+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;
+}
+
+
+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);
+}
+
+
+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 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)
+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
diff --git a/psutil/arch/bsd/proc.h b/psutil/arch/bsd/proc.h
new file mode 100644
index 00000000..2ed8e42d
--- /dev/null
+++ b/psutil/arch/bsd/proc.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_pids(PyObject *self, PyObject *args);
+PyObject *psutil_proc_environ(PyObject *self, PyObject *args);
+PyObject *psutil_proc_name(PyObject *self, PyObject *args);
+PyObject *psutil_proc_oneshot_info(PyObject *self, PyObject *args);
+PyObject *psutil_proc_open_files(PyObject *self, PyObject *args);
diff --git a/psutil/arch/bsd/sys.c b/psutil/arch/bsd/sys.c
new file mode 100644
index 00000000..5911f7a5
--- /dev/null
+++ b/psutil/arch/bsd/sys.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+#include <sys/sysctl.h>
+#include <stdio.h>
+#include <sys/param.h> // OS version
+#ifdef PSUTIL_FREEBSD
+ #if __FreeBSD_version < 900000
+ #include <utmp.h>
+ #else
+ #include <utmpx.h>
+ #endif
+#elif PSUTIL_NETBSD
+ #include <utmpx.h>
+#elif PSUTIL_OPENBSD
+ #include <utmp.h>
+#endif
+
+
+// Return a Python float indicating the system boot time expressed in
+// seconds since the epoch.
+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);
+}
+
+
+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;
+}
diff --git a/psutil/arch/bsd/sys.h b/psutil/arch/bsd/sys.h
new file mode 100644
index 00000000..344ca21d
--- /dev/null
+++ b/psutil/arch/bsd/sys.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_boot_time(PyObject *self, PyObject *args);
+PyObject *psutil_users(PyObject *self, PyObject *args);
diff --git a/setup.py b/setup.py
index 4923600a..4682a4dd 100755
--- a/setup.py
+++ b/setup.py
@@ -255,13 +255,18 @@ elif FREEBSD:
'psutil._psutil_bsd',
sources=sources + [
'psutil/_psutil_bsd.c',
+ 'psutil/arch/bsd/cpu.c',
+ 'psutil/arch/bsd/disk.c',
+ 'psutil/arch/bsd/net.c',
+ 'psutil/arch/bsd/proc.c',
+ 'psutil/arch/bsd/sys.c',
'psutil/arch/freebsd/cpu.c',
- 'psutil/arch/freebsd/mem.c',
'psutil/arch/freebsd/disk.c',
- 'psutil/arch/freebsd/sensors.c',
+ 'psutil/arch/freebsd/mem.c',
'psutil/arch/freebsd/proc.c',
- 'psutil/arch/freebsd/sys_socks.c',
'psutil/arch/freebsd/proc_socks.c',
+ 'psutil/arch/freebsd/sensors.c',
+ 'psutil/arch/freebsd/sys_socks.c',
],
define_macros=macros,
libraries=["devstat"],
@@ -273,6 +278,11 @@ elif OPENBSD:
'psutil._psutil_bsd',
sources=sources + [
'psutil/_psutil_bsd.c',
+ 'psutil/arch/bsd/cpu.c',
+ 'psutil/arch/bsd/disk.c',
+ 'psutil/arch/bsd/net.c',
+ 'psutil/arch/bsd/proc.c',
+ 'psutil/arch/bsd/sys.c',
'psutil/arch/openbsd/cpu.c',
'psutil/arch/openbsd/disk.c',
'psutil/arch/openbsd/mem.c',
@@ -289,6 +299,11 @@ elif NETBSD:
'psutil._psutil_bsd',
sources=sources + [
'psutil/_psutil_bsd.c',
+ 'psutil/arch/bsd/cpu.c',
+ 'psutil/arch/bsd/disk.c',
+ 'psutil/arch/bsd/net.c',
+ 'psutil/arch/bsd/proc.c',
+ 'psutil/arch/bsd/sys.c',
'psutil/arch/netbsd/cpu.c',
'psutil/arch/netbsd/disk.c',
'psutil/arch/netbsd/mem.c',