| Index: third_party/psutil/psutil/_psutil_osx.c
|
| diff --git a/third_party/psutil/psutil/_psutil_osx.c b/third_party/psutil/psutil/_psutil_osx.c
|
| index 64947a708922ecc306d5a1aeec42bd9d26200517..29162f20b6f757eef9e692a2b8dfa83cc4c3a7a7 100644
|
| --- a/third_party/psutil/psutil/_psutil_osx.c
|
| +++ b/third_party/psutil/psutil/_psutil_osx.c
|
| @@ -1,5 +1,9 @@
|
| /*
|
| - * $Id: _psutil_osx.c 780 2010-11-10 18:42:47Z jloden $
|
| + * $Id: _psutil_osx.c 1142 2011-10-05 18:45:49Z g.rodola $
|
| + *
|
| + * 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.
|
| *
|
| * OS X platform-specific module methods for _psutil_osx
|
| */
|
| @@ -10,9 +14,13 @@
|
| #include <stdbool.h>
|
| #include <stdlib.h>
|
| #include <stdio.h>
|
| -#include <signal.h>
|
| #include <sys/sysctl.h>
|
| #include <sys/vmmeter.h>
|
| +#include <libproc.h>
|
| +#include <sys/proc_info.h>
|
| +#include <netinet/tcp_fsm.h>
|
| +#include <arpa/inet.h>
|
| +#include <net/if_dl.h>
|
|
|
| #include <mach/mach.h>
|
| #include <mach/task.h>
|
| @@ -22,152 +30,18 @@
|
| #include <mach/mach_traps.h>
|
| #include <mach/shared_memory_server.h>
|
|
|
| +#include <CoreFoundation/CoreFoundation.h>
|
| +#include <IOKit/IOKitLib.h>
|
| +#include <IOKit/storage/IOBlockStorageDriver.h>
|
| +#include <IOKit/storage/IOMedia.h>
|
| +#include <IOKit/IOBSD.h>
|
| +
|
| #include "_psutil_osx.h"
|
| +#include "_psutil_common.h"
|
| #include "arch/osx/process_info.h"
|
|
|
|
|
| /*
|
| - * define the psutil C module methods and initialize the module.
|
| - */
|
| -static PyMethodDef
|
| -PsutilMethods[] =
|
| -{
|
| - // --- per-process functions
|
| -
|
| - {"get_process_name", get_process_name, METH_VARARGS,
|
| - "Return process name"},
|
| - {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
|
| - "Return process cmdline as a list of cmdline arguments"},
|
| - {"get_process_ppid", get_process_ppid, METH_VARARGS,
|
| - "Return process ppid as an integer"},
|
| - {"get_process_uid", get_process_uid, METH_VARARGS,
|
| - "Return process real user id as an integer"},
|
| - {"get_process_gid", get_process_gid, METH_VARARGS,
|
| - "Return process real group id as an integer"},
|
| - {"get_cpu_times", get_cpu_times, METH_VARARGS,
|
| - "Return tuple of user/kern time for the given PID"},
|
| - {"get_process_create_time", get_process_create_time, METH_VARARGS,
|
| - "Return a float indicating the process create time expressed in "
|
| - "seconds since the epoch"},
|
| - {"get_memory_info", get_memory_info, METH_VARARGS,
|
| - "Return a tuple of RSS/VMS memory information"},
|
| - {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
|
| - "Return number of threads used by process"},
|
| -
|
| - // --- system-related functions
|
| -
|
| - {"get_pid_list", get_pid_list, METH_VARARGS,
|
| - "Returns a list of PIDs currently running on the system"},
|
| - {"get_num_cpus", get_num_cpus, METH_VARARGS,
|
| - "Return number of CPUs on the system"},
|
| - {"get_total_phymem", get_total_phymem, METH_VARARGS,
|
| - "Return the total amount of physical memory, in bytes"},
|
| - {"get_avail_phymem", get_avail_phymem, METH_VARARGS,
|
| - "Return the amount of available physical memory, in bytes"},
|
| - {"get_total_virtmem", get_total_virtmem, METH_VARARGS,
|
| - "Return the total amount of virtual memory, in bytes"},
|
| - {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS,
|
| - "Return the amount of available virtual memory, in bytes"},
|
| - {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
|
| - "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
|
| -
|
| - {NULL, NULL, 0, NULL}
|
| -};
|
| -
|
| -
|
| -/*
|
| - * Raises an OSError(errno=ESRCH, strerror="No such process") exception
|
| - * in Python.
|
| - */
|
| -static PyObject*
|
| -NoSuchProcess(void) {
|
| - errno = ESRCH;
|
| - return PyErr_SetFromErrno(PyExc_OSError);
|
| -}
|
| -
|
| -/*
|
| - * Raises an OSError(errno=EPERM, strerror="Operation not permitted") exception
|
| - * in Python.
|
| - */
|
| -static PyObject*
|
| -AccessDenied(void) {
|
| - errno = EPERM;
|
| - return PyErr_SetFromErrno(PyExc_OSError);
|
| -}
|
| -
|
| -struct module_state {
|
| - PyObject *error;
|
| -};
|
| -
|
| -#if PY_MAJOR_VERSION >= 3
|
| -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
| -#else
|
| -#define GETSTATE(m) (&_state)
|
| -static struct module_state _state;
|
| -#endif
|
| -
|
| -#if PY_MAJOR_VERSION >= 3
|
| -
|
| -static int
|
| -psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) {
|
| - Py_VISIT(GETSTATE(m)->error);
|
| - return 0;
|
| -}
|
| -
|
| -static int
|
| -psutil_osx_clear(PyObject *m) {
|
| - Py_CLEAR(GETSTATE(m)->error);
|
| - return 0;
|
| -}
|
| -
|
| -
|
| -static struct PyModuleDef
|
| -moduledef = {
|
| - PyModuleDef_HEAD_INIT,
|
| - "psutil_osx",
|
| - NULL,
|
| - sizeof(struct module_state),
|
| - PsutilMethods,
|
| - NULL,
|
| - psutil_osx_traverse,
|
| - psutil_osx_clear,
|
| - NULL
|
| -};
|
| -
|
| -#define INITERROR return NULL
|
| -
|
| -PyObject *
|
| -PyInit__psutil_osx(void)
|
| -
|
| -#else
|
| -#define INITERROR return
|
| -
|
| -void
|
| -init_psutil_osx(void)
|
| -#endif
|
| -{
|
| -#if PY_MAJOR_VERSION >= 3
|
| - PyObject *module = PyModule_Create(&moduledef);
|
| -#else
|
| - PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
|
| -#endif
|
| - if (module == NULL) {
|
| - INITERROR;
|
| - }
|
| - struct module_state *st = GETSTATE(module);
|
| -
|
| - st->error = PyErr_NewException("_psutil_osx.Error", NULL, NULL);
|
| - if (st->error == NULL) {
|
| - Py_DECREF(module);
|
| - INITERROR;
|
| - }
|
| -#if PY_MAJOR_VERSION >= 3
|
| - return module;
|
| -#endif
|
| -}
|
| -
|
| -
|
| -/*
|
| * Return a Python list of all the PIDs running on the system.
|
| */
|
| static PyObject*
|
| @@ -234,13 +108,7 @@ get_process_cmdline(PyObject* self, PyObject* args)
|
|
|
| // get the commandline, defined in arch/osx/process_info.c
|
| arglist = get_arg_list(pid);
|
| -
|
| - // get_arg_list() returns NULL only if getcmdargs failed with ESRCH
|
| - // (no process with that PID)
|
| - if (NULL == arglist) {
|
| - return PyErr_SetFromErrno(PyExc_OSError);
|
| - }
|
| - return Py_BuildValue("N", arglist);
|
| + return arglist;
|
| }
|
|
|
|
|
| @@ -266,7 +134,7 @@ get_process_ppid(PyObject* self, PyObject* args)
|
| * Return process real uid from kinfo_proc as a Python integer.
|
| */
|
| static PyObject*
|
| -get_process_uid(PyObject* self, PyObject* args)
|
| +get_process_uids(PyObject* self, PyObject* args)
|
| {
|
| long pid;
|
| struct kinfo_proc kp;
|
| @@ -276,7 +144,9 @@ get_process_uid(PyObject* self, PyObject* args)
|
| if (get_kinfo_proc(pid, &kp) == -1) {
|
| return NULL;
|
| }
|
| - return Py_BuildValue("l", (long)kp.kp_eproc.e_pcred.p_ruid);
|
| + return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_ruid,
|
| + (long)kp.kp_eproc.e_ucred.cr_uid,
|
| + (long)kp.kp_eproc.e_pcred.p_svuid);
|
| }
|
|
|
|
|
| @@ -284,7 +154,7 @@ get_process_uid(PyObject* self, PyObject* args)
|
| * Return process real group id from ki_comm as a Python integer.
|
| */
|
| static PyObject*
|
| -get_process_gid(PyObject* self, PyObject* args)
|
| +get_process_gids(PyObject* self, PyObject* args)
|
| {
|
| long pid;
|
| struct kinfo_proc kp;
|
| @@ -294,30 +164,27 @@ get_process_gid(PyObject* self, PyObject* args)
|
| if (get_kinfo_proc(pid, &kp) == -1) {
|
| return NULL;
|
| }
|
| - return Py_BuildValue("l", (long)kp.kp_eproc.e_pcred.p_rgid);
|
| + return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_rgid,
|
| + (long)kp.kp_eproc.e_ucred.cr_groups[0],
|
| + (long)kp.kp_eproc.e_pcred.p_svgid);
|
| }
|
|
|
|
|
| /*
|
| - * Return 1 if PID exists in the current process list, else 0.
|
| + * Return process controlling terminal number as an integer.
|
| */
|
| -static int
|
| -pid_exists(long pid) {
|
| - int kill_ret;
|
| -
|
| - // save some time if it's an invalid PID
|
| - if (pid < 0) {
|
| - return 0;
|
| +static PyObject*
|
| +get_process_tty_nr(PyObject* self, PyObject* args)
|
| +{
|
| + long pid;
|
| + struct kinfo_proc kp;
|
| + if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| + return NULL;
|
| }
|
| -
|
| - // if kill returns success of permission denied we know it's a valid PID
|
| - kill_ret = kill(pid , 0);
|
| - if ( (0 == kill_ret) || (EPERM == errno) ) {
|
| - return 1;
|
| + if (get_kinfo_proc(pid, &kp) == -1) {
|
| + return NULL;
|
| }
|
| -
|
| - // otherwise return 0 for PID not found
|
| - return 0;
|
| + return Py_BuildValue("i", kp.kp_eproc.e_tdev);
|
| }
|
|
|
|
|
| @@ -356,45 +223,44 @@ get_cpu_times(PyObject* self, PyObject* args)
|
| long pid;
|
| int err;
|
| unsigned int info_count = TASK_BASIC_INFO_COUNT;
|
| - task_port_t task;// = (task_port_t)NULL;
|
| + task_port_t task; // = (task_port_t)NULL;
|
| time_value_t user_time, system_time;
|
| struct task_basic_info tasks_info;
|
| struct task_thread_times_info task_times;
|
|
|
| - // the argument passed should be a process id
|
| if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| return NULL;
|
| }
|
|
|
| - /* task_for_pid() requires special privileges
|
| + /* task_for_pid() requires special privileges
|
| * "This function can be called only if the process is owned by the
|
| * procmod group or if the caller is root."
|
| - * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html
|
| - */
|
| + * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html */
|
| err = task_for_pid(mach_task_self(), pid, &task);
|
| if ( err == KERN_SUCCESS) {
|
| info_count = TASK_BASIC_INFO_COUNT;
|
| err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
|
| if (err != KERN_SUCCESS) {
|
| - if (err == 4) { // errcode 4 is "invalid argument" (access denied)
|
| + // errcode 4 is "invalid argument" (access denied)
|
| + if (err == 4) {
|
| return AccessDenied();
|
| }
|
|
|
| - //otherwise throw a runtime error with appropriate error code
|
| - return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
|
| - pid, mach_error_string(err), err);
|
| -
|
| + // otherwise throw a runtime error with appropriate error code
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "task_info(TASK_BASIC_INFO) failed");
|
| }
|
|
|
| info_count = TASK_THREAD_TIMES_INFO_COUNT;
|
| - err = task_info(task, TASK_THREAD_TIMES_INFO, (task_info_t)&task_times, &info_count);
|
| + err = task_info(task, TASK_THREAD_TIMES_INFO,
|
| + (task_info_t)&task_times, &info_count);
|
| if (err != KERN_SUCCESS) {
|
| - if (err == 4) { // errcode 4 is "invalid argument" (access denied)
|
| + // errcode 4 is "invalid argument" (access denied)
|
| + if (err == 4) {
|
| return AccessDenied();
|
| }
|
| -
|
| - return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_THREAD_TIMES_INFO) failed for pid %lu - %s (%i)",
|
| - pid, mach_error_string(err), err);
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "task_info(TASK_BASIC_INFO) failed");
|
| }
|
| }
|
|
|
| @@ -402,7 +268,6 @@ get_cpu_times(PyObject* self, PyObject* args)
|
| if (! pid_exists(pid) ) {
|
| return NoSuchProcess();
|
| }
|
| -
|
| // pid exists, so return AccessDenied error since task_for_pid() failed
|
| return AccessDenied();
|
| }
|
| @@ -464,20 +329,19 @@ get_memory_info(PyObject* self, PyObject* args)
|
| /* task_for_pid() requires special privileges
|
| * "This function can be called only if the process is owned by the
|
| * procmod group or if the caller is root."
|
| - * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html
|
| - */
|
| + * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html */
|
| err = task_for_pid(mach_task_self(), pid, &task);
|
| if ( err == KERN_SUCCESS) {
|
| info_count = TASK_BASIC_INFO_COUNT;
|
| err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
|
| if (err != KERN_SUCCESS) {
|
| - if (err == 4) { // errcode 4 is "invalid argument" (access denied)
|
| + if (err == 4) {
|
| + // errcode 4 is "invalid argument" (access denied)
|
| return AccessDenied();
|
| }
|
| -
|
| - //otherwise throw a runtime error with appropriate error code
|
| - return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
|
| - pid, mach_error_string(err), err);
|
| + // otherwise throw a runtime error with appropriate error code
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "task_info(TASK_BASIC_INFO) failed");
|
| }
|
|
|
| /* Issue #73 http://code.google.com/p/psutil/issues/detail?id=73
|
| @@ -489,8 +353,9 @@ get_memory_info(PyObject* self, PyObject* args)
|
| (vm_region_info_t)&b_info, &info_count, &object_name);
|
| if (err == KERN_SUCCESS) {
|
| if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
|
| - tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) {
|
| - tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
|
| + tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE))
|
| + {
|
| + tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
|
| }
|
| }
|
| }
|
| @@ -515,7 +380,7 @@ static PyObject*
|
| get_process_num_threads(PyObject* self, PyObject* args)
|
| {
|
| long pid;
|
| - int err;
|
| + int err, ret;
|
| unsigned int info_count = TASK_BASIC_INFO_COUNT;
|
| mach_port_t task;
|
| struct task_basic_info tasks_info;
|
| @@ -537,22 +402,28 @@ get_process_num_threads(PyObject* self, PyObject* args)
|
| info_count = TASK_BASIC_INFO_COUNT;
|
| err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
|
| if (err != KERN_SUCCESS) {
|
| - if (err == 4) { // errcode 4 is "invalid argument" (access denied)
|
| + // errcode 4 is "invalid argument" (access denied)
|
| + if (err == 4) {
|
| return AccessDenied();
|
| }
|
|
|
| - //otherwise throw a runtime error with appropriate error code
|
| - return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
|
| - pid, mach_error_string(err), err);
|
| + // otherwise throw a runtime error with appropriate error code
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "task_info(TASK_BASIC_INFO) failed");
|
| }
|
| -
|
| err = task_threads(task, &thread_list, &thread_count);
|
| if (err == KERN_SUCCESS) {
|
| + ret = vm_deallocate(task, (vm_address_t)thread_list,
|
| + thread_count * sizeof(int));
|
| + if (ret != KERN_SUCCESS) {
|
| + printf("vm_deallocate() failed\n");
|
| + }
|
| return Py_BuildValue("l", (long)thread_count);
|
| }
|
| + else {
|
| + return PyErr_Format(PyExc_RuntimeError, "task_thread() failed");
|
| + }
|
| }
|
| -
|
| -
|
| else {
|
| if (! pid_exists(pid) ) {
|
| return NoSuchProcess();
|
| @@ -584,7 +455,6 @@ get_total_phymem(PyObject* self, PyObject* args)
|
| PyErr_SetFromErrno(0);
|
| return NULL;
|
| }
|
| -
|
| return Py_BuildValue("L", total_phymem);
|
| }
|
|
|
| @@ -678,12 +548,883 @@ get_system_cpu_times(PyObject* self, PyObject* args)
|
| "Error in host_statistics(): %s", mach_error_string(error));
|
| }
|
|
|
| - //user, nice, system, idle, iowait, irqm, softirq
|
| return Py_BuildValue("(dddd)",
|
| - (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
|
| - (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
|
| - (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
|
| - (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
|
| - );
|
| + (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
|
| + (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
|
| + (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
|
| + (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
|
| + );
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return a Python list of tuple representing per-cpu times
|
| + */
|
| +static PyObject*
|
| +get_system_per_cpu_times(PyObject* self, PyObject* args)
|
| +{
|
| + natural_t cpu_count;
|
| + processor_info_array_t info_array;
|
| + mach_msg_type_number_t info_count;
|
| + kern_return_t error;
|
| + processor_cpu_load_info_data_t* cpu_load_info;
|
| + PyObject* py_retlist = PyList_New(0);
|
| + PyObject* py_cputime;
|
| + int i, ret;
|
| +
|
| + error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO,
|
| + &cpu_count, &info_array, &info_count);
|
| + if (error != KERN_SUCCESS) {
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "Error in host_processor_info(): %s", mach_error_string(error));
|
| + }
|
| +
|
| + cpu_load_info = (processor_cpu_load_info_data_t*) info_array;
|
| +
|
| + for (i = 0; i < cpu_count; i++) {
|
| + py_cputime = Py_BuildValue("(dddd)",
|
| + (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK,
|
| + (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
|
| + (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
|
| + (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
|
| + );
|
| + PyList_Append(py_retlist, py_cputime);
|
| + Py_XDECREF(py_cputime);
|
| + }
|
| +
|
| + ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
|
| + info_count * sizeof(int));
|
| + if (ret != KERN_SUCCESS) {
|
| + printf("vm_deallocate() failed\n");
|
| + }
|
| + return py_retlist;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return a Python float indicating the system boot time expressed in
|
| + * seconds since the epoch.
|
| + */
|
| +static PyObject*
|
| +get_system_boot_time(PyObject* self, PyObject* args)
|
| +{
|
| + /* fetch sysctl "kern.boottime" */
|
| + static int request[2] = { CTL_KERN, KERN_BOOTTIME };
|
| + struct timeval result;
|
| + size_t result_len = sizeof result;
|
| + time_t boot_time = 0;
|
| +
|
| + if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) {
|
| + PyErr_SetFromErrno(0);
|
| + return NULL;
|
| + }
|
| + boot_time = result.tv_sec;
|
| + return Py_BuildValue("f", (float)boot_time);
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return a list of tuples including device, mount point and fs type
|
| + * for all partitions mounted on the system.
|
| + */
|
| +static PyObject*
|
| +get_disk_partitions(PyObject* self, PyObject* args)
|
| +{
|
| + int num;
|
| + int i;
|
| + long len;
|
| + struct statfs *fs;
|
| + PyObject* py_retlist = PyList_New(0);
|
| + PyObject* py_tuple;
|
| +
|
| + // get the number of mount points
|
| + Py_BEGIN_ALLOW_THREADS
|
| + num = getfsstat(NULL, 0, MNT_NOWAIT);
|
| + Py_END_ALLOW_THREADS
|
| + if (num == -1) {
|
| + PyErr_SetFromErrno(0);
|
| + return NULL;
|
| + }
|
| +
|
| + len = sizeof(*fs) * num;
|
| + fs = malloc(len);
|
| +
|
| + Py_BEGIN_ALLOW_THREADS
|
| + num = getfsstat(fs, len, MNT_NOWAIT);
|
| + Py_END_ALLOW_THREADS
|
| + if (num == -1) {
|
| + free(fs);
|
| + PyErr_SetFromErrno(0);
|
| + return NULL;
|
| + }
|
| +
|
| + for (i = 0; i < num; i++) {
|
| + py_tuple = Py_BuildValue("(sss)", fs[i].f_mntfromname, // device
|
| + fs[i].f_mntonname, // mount point
|
| + fs[i].f_fstypename); // fs type
|
| + PyList_Append(py_retlist, py_tuple);
|
| + Py_XDECREF(py_tuple);
|
| + }
|
| +
|
| + free(fs);
|
| + return py_retlist;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return process status as a Python integer.
|
| + */
|
| +static PyObject*
|
| +get_process_status(PyObject* self, PyObject* args)
|
| +{
|
| + long pid;
|
| + struct kinfo_proc kp;
|
| + if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| + return NULL;
|
| + }
|
| + if (get_kinfo_proc(pid, &kp) == -1) {
|
| + return NULL;
|
| + }
|
| + return Py_BuildValue("i", (int)kp.kp_proc.p_stat);
|
| }
|
|
|
| +
|
| +/*
|
| + * Return process threads
|
| + */
|
| +static PyObject*
|
| +get_process_threads(PyObject* self, PyObject* args)
|
| +{
|
| + long pid;
|
| + int err, j, ret;
|
| + kern_return_t kr;
|
| + unsigned int info_count = TASK_BASIC_INFO_COUNT;
|
| + mach_port_t task;
|
| + struct task_basic_info tasks_info;
|
| + thread_act_port_array_t thread_list;
|
| + thread_info_data_t thinfo;
|
| + thread_basic_info_t basic_info_th;
|
| + mach_msg_type_number_t thread_count, thread_info_count;
|
| +
|
| + PyObject* retList = PyList_New(0);
|
| + PyObject* pyTuple = NULL;
|
| +
|
| + // the argument passed should be a process id
|
| + if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| + return NULL;
|
| + }
|
| +
|
| + // task_for_pid() requires special privileges
|
| + err = task_for_pid(mach_task_self(), pid, &task);
|
| + if (err != KERN_SUCCESS) {
|
| + if (! pid_exists(pid) ) {
|
| + return NoSuchProcess();
|
| + }
|
| + return AccessDenied();
|
| + }
|
| +
|
| + info_count = TASK_BASIC_INFO_COUNT;
|
| + err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
|
| + if (err != KERN_SUCCESS) {
|
| + // errcode 4 is "invalid argument" (access denied)
|
| + if (err == 4) {
|
| + return AccessDenied();
|
| + }
|
| + // otherwise throw a runtime error with appropriate error code
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "task_info(TASK_BASIC_INFO) failed");
|
| + }
|
| +
|
| + err = task_threads(task, &thread_list, &thread_count);
|
| + if (err != KERN_SUCCESS) {
|
| + return PyErr_Format(PyExc_RuntimeError, "task_threads() failed");
|
| + }
|
| +
|
| + for (j = 0; j < thread_count; j++) {
|
| + thread_info_count = THREAD_INFO_MAX;
|
| + kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
|
| + (thread_info_t)thinfo, &thread_info_count);
|
| + if (kr != KERN_SUCCESS) {
|
| + return PyErr_Format(PyExc_RuntimeError, "thread_info() failed");
|
| + }
|
| + basic_info_th = (thread_basic_info_t)thinfo;
|
| + // XXX - thread_info structure does not provide any process id;
|
| + // the best we can do is assigning an incremental bogus value
|
| + pyTuple = Py_BuildValue("Iff", j + 1,
|
| + (float)basic_info_th->user_time.microseconds / 1000000.0,
|
| + (float)basic_info_th->system_time.microseconds / 1000000.0
|
| + );
|
| + PyList_Append(retList, pyTuple);
|
| + Py_XDECREF(pyTuple);
|
| + }
|
| +
|
| + ret = vm_deallocate(task, (vm_address_t)thread_list,
|
| + thread_count * sizeof(int));
|
| + if (ret != KERN_SUCCESS) {
|
| + printf("vm_deallocate() failed\n");
|
| + }
|
| +
|
| + return retList;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return process open files as a Python tuple.
|
| + * References:
|
| + * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd
|
| + * - /usr/include/sys/proc_info.h
|
| + */
|
| +static PyObject*
|
| +get_process_open_files(PyObject* self, PyObject* args)
|
| +{
|
| + long pid;
|
| + int pidinfo_result;
|
| + int iterations;
|
| + int i;
|
| + int nb;
|
| +
|
| + struct proc_fdinfo *fds_pointer;
|
| + struct proc_fdinfo *fdp_pointer;
|
| + struct vnode_fdinfowithpath vi;
|
| +
|
| + PyObject *retList = PyList_New(0);
|
| + PyObject *tuple = NULL;
|
| +
|
| + if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| + return NULL;
|
| + }
|
| +
|
| + pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
|
| + if (pidinfo_result <= 0) {
|
| + goto error;
|
| + }
|
| +
|
| + fds_pointer = malloc(pidinfo_result);
|
| + pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
|
| + pidinfo_result);
|
| + free(fds_pointer);
|
| +
|
| + if (pidinfo_result <= 0) {
|
| + goto error;
|
| + }
|
| +
|
| + iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
|
| +
|
| + for (i = 0; i < iterations; i++) {
|
| + fdp_pointer = &fds_pointer[i];
|
| +
|
| + //
|
| + if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE)
|
| + {
|
| + nb = proc_pidfdinfo(pid,
|
| + fdp_pointer->proc_fd,
|
| + PROC_PIDFDVNODEPATHINFO,
|
| + &vi,
|
| + sizeof(vi));
|
| +
|
| + // --- errors checking
|
| + if (nb <= 0) {
|
| + if ((errno == ENOENT) || (errno == EBADF)) {
|
| + // no such file or directory or bad file descriptor;
|
| + // let's assume the file has been closed or removed
|
| + continue;
|
| + }
|
| + if (errno != 0) {
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + }
|
| + else
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
|
| + }
|
| + if (nb < sizeof(vi)) {
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
|
| + }
|
| + // --- /errors checking
|
| +
|
| + // --- construct python list
|
| + tuple = Py_BuildValue("(si)", vi.pvip.vip_path,
|
| + (int)fdp_pointer->proc_fd);
|
| + PyList_Append(retList, tuple);
|
| + Py_DECREF(tuple);
|
| + // --- /construct python list
|
| + }
|
| + }
|
| +
|
| + return retList;
|
| +
|
| +error:
|
| + if (errno != 0)
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + else if (! pid_exists(pid) )
|
| + return NoSuchProcess();
|
| + else
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDLISTFDS) failed");
|
| +}
|
| +
|
| +
|
| +/*
|
| + * mathes Linux net/tcp_states.h:
|
| + * http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
|
| + */
|
| +static char *
|
| +get_connection_status(int st) {
|
| + switch (st) {
|
| + case TCPS_CLOSED:
|
| + return "CLOSE";
|
| + case TCPS_CLOSING:
|
| + return "CLOSING";
|
| + case TCPS_CLOSE_WAIT:
|
| + return "CLOSE_WAIT";
|
| + case TCPS_LISTEN:
|
| + return "LISTEN";
|
| + case TCPS_ESTABLISHED:
|
| + return "ESTABLISHED";
|
| + case TCPS_SYN_SENT:
|
| + return "SYN_SENT";
|
| + case TCPS_SYN_RECEIVED:
|
| + return "SYN_RECV";
|
| + case TCPS_FIN_WAIT_1:
|
| + return "FIN_WAIT_1";
|
| + case TCPS_FIN_WAIT_2:
|
| + return "FIN_WAIT_2";
|
| + case TCPS_LAST_ACK:
|
| + return "LAST_ACK";
|
| + case TCPS_TIME_WAIT:
|
| + return "TIME_WAIT";
|
| + default:
|
| + return "";
|
| + }
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return process TCP and UDP connections as a list of tuples.
|
| + * References:
|
| + * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0
|
| + * - /usr/include/sys/proc_info.h
|
| + */
|
| +static PyObject*
|
| +get_process_connections(PyObject* self, PyObject* args)
|
| +{
|
| + long pid;
|
| + int pidinfo_result;
|
| + int iterations;
|
| + int i;
|
| + int nb;
|
| +
|
| + struct proc_fdinfo *fds_pointer;
|
| + struct proc_fdinfo *fdp_pointer;
|
| + struct socket_fdinfo si;
|
| +
|
| +
|
| + PyObject *retList = PyList_New(0);
|
| + PyObject *tuple = NULL;
|
| + PyObject *laddr = NULL;
|
| + PyObject *raddr = NULL;
|
| +
|
| + if (! PyArg_ParseTuple(args, "l", &pid)) {
|
| + return NULL;
|
| + }
|
| +
|
| + if (pid == 0) {
|
| + return retList;
|
| + }
|
| +
|
| + pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
|
| + if (pidinfo_result <= 0) {
|
| + goto error;
|
| + }
|
| +
|
| + fds_pointer = malloc(pidinfo_result);
|
| + pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
|
| + pidinfo_result);
|
| + free(fds_pointer);
|
| +
|
| + if (pidinfo_result <= 0) {
|
| + goto error;
|
| + }
|
| +
|
| + iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
|
| +
|
| + for (i = 0; i < iterations; i++) {
|
| + errno = 0;
|
| + fdp_pointer = &fds_pointer[i];
|
| +
|
| + //
|
| + if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET)
|
| + {
|
| + nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, PROC_PIDFDSOCKETINFO,
|
| + &si, sizeof(si));
|
| +
|
| + // --- errors checking
|
| + if (nb <= 0) {
|
| + if (errno == EBADF) {
|
| + // let's assume socket has been closed
|
| + continue;
|
| + }
|
| + if (errno != 0) {
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + }
|
| + else {
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
|
| + }
|
| + }
|
| + if (nb < sizeof(si)) {
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
|
| + }
|
| + // --- /errors checking
|
| +
|
| + //
|
| + int fd, family, type, lport, rport;
|
| + char lip[200], rip[200];
|
| + char *state;
|
| +
|
| + fd = (int)fdp_pointer->proc_fd;
|
| + family = si.psi.soi_family;
|
| + type = si.psi.soi_kind;
|
| +
|
| + if ((family != AF_INET) && (family != AF_INET6)) {
|
| + continue;
|
| + }
|
| +
|
| + if (type == 2)
|
| + type = SOCK_STREAM;
|
| + else if (type == 1)
|
| + type = SOCK_DGRAM;
|
| + else
|
| + continue;
|
| +
|
| + if (errno != 0) {
|
| + printf("errno 1 = %i\n", errno);
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + }
|
| +
|
| +
|
| + if (family == AF_INET) {
|
| + inet_ntop(AF_INET,
|
| + &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4,
|
| + lip,
|
| + sizeof(lip));
|
| + inet_ntop(AF_INET,
|
| + &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4,
|
| + rip,
|
| + sizeof(lip));
|
| + }
|
| + else {
|
| + inet_ntop(AF_INET6,
|
| + &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6,
|
| + lip, sizeof(lip));
|
| + inet_ntop(AF_INET6,
|
| + &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6,
|
| + lip, sizeof(rip));
|
| + }
|
| +
|
| + // check for inet_ntop failures
|
| + if (errno != 0) {
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + }
|
| +
|
| + lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
|
| + rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
|
| + if (type == SOCK_STREAM)
|
| + state = get_connection_status((int)si.psi.soi_proto.pri_tcp.tcpsi_state);
|
| + else
|
| + state = "";
|
| +
|
| + laddr = Py_BuildValue("(si)", lip, lport);
|
| + if (rport != 0)
|
| + raddr = Py_BuildValue("(si)", rip, rport);
|
| + else
|
| + raddr = PyTuple_New(0);
|
| +
|
| + // --- construct python list
|
| + tuple = Py_BuildValue("(iiiNNs)", fd, family, type, laddr, raddr,
|
| + state);
|
| + PyList_Append(retList, tuple);
|
| + Py_DECREF(tuple);
|
| + // --- /construct python list
|
| + }
|
| + }
|
| +
|
| + return retList;
|
| +
|
| +error:
|
| + if (errno != 0)
|
| + return PyErr_SetFromErrno(PyExc_OSError);
|
| + else if (! pid_exists(pid) )
|
| + return NoSuchProcess();
|
| + else
|
| + return PyErr_Format(PyExc_RuntimeError,
|
| + "proc_pidinfo(PROC_PIDLISTFDS) failed");
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return a Python list of named tuples with overall network I/O information
|
| + */
|
| +static PyObject*
|
| +get_network_io_counters(PyObject* self, PyObject* args)
|
| +{
|
| + PyObject* py_retdict = PyDict_New();
|
| + PyObject* py_ifc_info;
|
| +
|
| + char *buf = NULL, *lim, *next;
|
| + struct if_msghdr *ifm;
|
| + int mib[6];
|
| + size_t len;
|
| +
|
| + 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_IFLIST2; // operation
|
| + mib[5] = 0;
|
| +
|
| + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
|
| + Py_DECREF(py_retdict);
|
| + PyErr_SetFromErrno(0);
|
| + return NULL;
|
| + }
|
| +
|
| + buf = malloc(len);
|
| +
|
| + if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
|
| + if (buf) {
|
| + free(buf);
|
| + }
|
| + Py_DECREF(py_retdict);
|
| + PyErr_SetFromErrno(0);
|
| + return NULL;
|
| + }
|
| +
|
| + lim = buf + len;
|
| +
|
| + for (next = buf; next < lim; ) {
|
| + ifm = (struct if_msghdr *)next;
|
| + next += ifm->ifm_msglen;
|
| +
|
| + if (ifm->ifm_type == RTM_IFINFO2) {
|
| + struct if_msghdr2 *if2m = (struct if_msghdr2 *)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;
|
| +
|
| + py_ifc_info = Py_BuildValue("(KKKK)",
|
| + if2m->ifm_data.ifi_obytes,
|
| + if2m->ifm_data.ifi_ibytes,
|
| + if2m->ifm_data.ifi_opackets,
|
| + if2m->ifm_data.ifi_ipackets);
|
| + PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info);
|
| + Py_XDECREF(py_ifc_info);
|
| + }
|
| + else {
|
| + continue;
|
| + }
|
| + }
|
| +
|
| + free(buf);
|
| +
|
| + return py_retdict;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * Return a Python dict of tuples for disk I/O information
|
| + */
|
| +static PyObject*
|
| +get_disk_io_counters(PyObject* self, PyObject* args)
|
| +{
|
| + PyObject* py_retdict = PyDict_New();
|
| + PyObject* py_disk_info;
|
| +
|
| + CFDictionaryRef parent_dict;
|
| + CFDictionaryRef props_dict;
|
| + CFDictionaryRef stats_dict;
|
| + io_registry_entry_t parent;
|
| + io_registry_entry_t disk;
|
| + io_iterator_t disk_list;
|
| +
|
| + /* Get list of disks */
|
| + if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
| + IOServiceMatching(kIOMediaClass),
|
| + &disk_list) != kIOReturnSuccess) {
|
| + Py_DECREF(py_retdict);
|
| + PyErr_SetString(PyExc_RuntimeError, "Unable to get the list of disks.");
|
| + return NULL;
|
| + }
|
| +
|
| + /* Iterate over disks */
|
| + while ((disk = IOIteratorNext(disk_list)) != 0) {
|
| + parent_dict = NULL;
|
| + props_dict = NULL;
|
| + stats_dict = NULL;
|
| +
|
| + if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) != kIOReturnSuccess) {
|
| + PyErr_SetString(PyExc_RuntimeError, "Unable to get the disk's parent.");
|
| + Py_DECREF(py_retdict);
|
| + IOObjectRelease(disk);
|
| + return NULL;
|
| + }
|
| +
|
| + if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
|
| + if(IORegistryEntryCreateCFProperties(
|
| + disk,
|
| + (CFMutableDictionaryRef *) &parent_dict,
|
| + kCFAllocatorDefault,
|
| + kNilOptions) != kIOReturnSuccess)
|
| + {
|
| + PyErr_SetString(PyExc_RuntimeError,
|
| + "Unable to get the parent's properties.");
|
| + Py_DECREF(py_retdict);
|
| + IOObjectRelease(disk);
|
| + IOObjectRelease(parent);
|
| + return NULL;
|
| + }
|
| +
|
| + if (IORegistryEntryCreateCFProperties(parent,
|
| + (CFMutableDictionaryRef *) &props_dict,
|
| + kCFAllocatorDefault,
|
| + kNilOptions) != kIOReturnSuccess)
|
| + {
|
| + PyErr_SetString(PyExc_RuntimeError,
|
| + "Unable to get the disk properties.");
|
| + Py_DECREF(py_retdict);
|
| + IOObjectRelease(disk);
|
| + return NULL;
|
| + }
|
| +
|
| + const int kMaxDiskNameSize = 64;
|
| + CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue(
|
| + parent_dict,
|
| + CFSTR(kIOBSDNameKey));
|
| + char disk_name[kMaxDiskNameSize];
|
| +
|
| + CFStringGetCString(disk_name_ref,
|
| + disk_name,
|
| + kMaxDiskNameSize,
|
| + CFStringGetSystemEncoding());
|
| +
|
| + stats_dict = (CFDictionaryRef)CFDictionaryGetValue(
|
| + props_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsKey));
|
| +
|
| + if (stats_dict == NULL) {
|
| + PyErr_SetString(PyExc_RuntimeError, "Unable to get disk stats.");
|
| + Py_DECREF(py_retdict);
|
| + CFRelease(props_dict);
|
| + IOObjectRelease(disk);
|
| + IOObjectRelease(parent);
|
| + return NULL;
|
| + }
|
| +
|
| + CFNumberRef number;
|
| + int64_t reads, writes, read_bytes, write_bytes, read_time, write_time = 0;
|
| +
|
| + /* Get disk reads/writes */
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsReadsKey))))
|
| + {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &reads);
|
| + }
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsWritesKey))))
|
| + {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &writes);
|
| + }
|
| +
|
| + /* Get disk bytes read/written */
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey))))
|
| + {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes);
|
| + }
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey))))
|
| + {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes);
|
| + }
|
| +
|
| + /* Get disk time spent reading/writing (nanoseconds) */
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey))))
|
| + {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &read_time);
|
| + }
|
| + if ((number = (CFNumberRef)CFDictionaryGetValue(
|
| + stats_dict,
|
| + CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
|
| + CFNumberGetValue(number, kCFNumberSInt64Type, &write_time);
|
| + }
|
| +
|
| + py_disk_info = Py_BuildValue("(KKKKKK)",
|
| + reads, writes,
|
| + read_bytes, write_bytes,
|
| + read_time, write_time);
|
| + PyDict_SetItemString(py_retdict, disk_name, py_disk_info);
|
| + Py_XDECREF(py_disk_info);
|
| +
|
| + CFRelease(parent_dict);
|
| + IOObjectRelease(parent);
|
| + CFRelease(props_dict);
|
| + IOObjectRelease(disk);
|
| + }
|
| + }
|
| +
|
| + IOObjectRelease (disk_list);
|
| +
|
| + return py_retdict;
|
| +}
|
| +
|
| +
|
| +/*
|
| + * define the psutil C module methods and initialize the module.
|
| + */
|
| +static PyMethodDef
|
| +PsutilMethods[] =
|
| +{
|
| + // --- per-process functions
|
| +
|
| + {"get_process_name", get_process_name, METH_VARARGS,
|
| + "Return process name"},
|
| + {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
|
| + "Return process cmdline as a list of cmdline arguments"},
|
| + {"get_process_ppid", get_process_ppid, METH_VARARGS,
|
| + "Return process ppid as an integer"},
|
| + {"get_process_uids", get_process_uids, METH_VARARGS,
|
| + "Return process real user id as an integer"},
|
| + {"get_process_gids", get_process_gids, METH_VARARGS,
|
| + "Return process real group id as an integer"},
|
| + {"get_cpu_times", get_cpu_times, METH_VARARGS,
|
| + "Return tuple of user/kern time for the given PID"},
|
| + {"get_process_create_time", get_process_create_time, METH_VARARGS,
|
| + "Return a float indicating the process create time expressed in "
|
| + "seconds since the epoch"},
|
| + {"get_memory_info", get_memory_info, METH_VARARGS,
|
| + "Return a tuple of RSS/VMS memory information"},
|
| + {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
|
| + "Return number of threads used by process"},
|
| + {"get_process_status", get_process_status, METH_VARARGS,
|
| + "Return process status as an integer"},
|
| + {"get_process_threads", get_process_threads, METH_VARARGS,
|
| + "Return process threads as a list of tuples"},
|
| + {"get_process_open_files", get_process_open_files, METH_VARARGS,
|
| + "Return files opened by process as a list of tuples"},
|
| + {"get_process_connections", get_process_connections, METH_VARARGS,
|
| + "Get process TCP and UDP connections as a list of tuples"},
|
| + {"get_process_tty_nr", get_process_tty_nr, METH_VARARGS,
|
| + "Return process tty number as an integer"},
|
| +
|
| + // --- system-related functions
|
| +
|
| + {"get_pid_list", get_pid_list, METH_VARARGS,
|
| + "Returns a list of PIDs currently running on the system"},
|
| + {"get_num_cpus", get_num_cpus, METH_VARARGS,
|
| + "Return number of CPUs on the system"},
|
| + {"get_total_phymem", get_total_phymem, METH_VARARGS,
|
| + "Return the total amount of physical memory, in bytes"},
|
| + {"get_avail_phymem", get_avail_phymem, METH_VARARGS,
|
| + "Return the amount of available physical memory, in bytes"},
|
| + {"get_total_virtmem", get_total_virtmem, METH_VARARGS,
|
| + "Return the total amount of virtual memory, in bytes"},
|
| + {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS,
|
| + "Return the amount of available virtual memory, in bytes"},
|
| + {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
|
| + "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
|
| + {"get_system_per_cpu_times", get_system_per_cpu_times, METH_VARARGS,
|
| + "Return system per-cpu times as a list of tuples"},
|
| + {"get_system_boot_time", get_system_boot_time, METH_VARARGS,
|
| + "Return a float indicating the system boot time expressed in "
|
| + "seconds since the epoch"},
|
| + {"get_disk_partitions", get_disk_partitions, METH_VARARGS,
|
| + "Return a list of tuples including device, mount point and "
|
| + "fs type for all partitions mounted on the system."},
|
| + {"get_network_io_counters", get_network_io_counters, METH_VARARGS,
|
| + "Return dict of tuples of networks I/O information."},
|
| + {"get_disk_io_counters", get_disk_io_counters, METH_VARARGS,
|
| + "Return dict of tuples of disks I/O information."},
|
| +
|
| + {NULL, NULL, 0, NULL}
|
| +};
|
| +
|
| +
|
| +struct module_state {
|
| + PyObject *error;
|
| +};
|
| +
|
| +#if PY_MAJOR_VERSION >= 3
|
| +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
|
| +#else
|
| +#define GETSTATE(m) (&_state)
|
| +#endif
|
| +
|
| +#if PY_MAJOR_VERSION >= 3
|
| +
|
| +static int
|
| +psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) {
|
| + Py_VISIT(GETSTATE(m)->error);
|
| + return 0;
|
| +}
|
| +
|
| +static int
|
| +psutil_osx_clear(PyObject *m) {
|
| + Py_CLEAR(GETSTATE(m)->error);
|
| + return 0;
|
| +}
|
| +
|
| +
|
| +static struct PyModuleDef
|
| +moduledef = {
|
| + PyModuleDef_HEAD_INIT,
|
| + "psutil_osx",
|
| + NULL,
|
| + sizeof(struct module_state),
|
| + PsutilMethods,
|
| + NULL,
|
| + psutil_osx_traverse,
|
| + psutil_osx_clear,
|
| + NULL
|
| +};
|
| +
|
| +#define INITERROR return NULL
|
| +
|
| +PyObject *
|
| +PyInit__psutil_osx(void)
|
| +
|
| +#else
|
| +#define INITERROR return
|
| +
|
| +void
|
| +init_psutil_osx(void)
|
| +#endif
|
| +{
|
| +#if PY_MAJOR_VERSION >= 3
|
| + PyObject *module = PyModule_Create(&moduledef);
|
| +#else
|
| + PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
|
| +#endif
|
| + // process status constants, defined in:
|
| + // http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149
|
| + PyModule_AddIntConstant(module, "SIDL", SIDL);
|
| + PyModule_AddIntConstant(module, "SRUN", SRUN);
|
| + PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
|
| + PyModule_AddIntConstant(module, "SSTOP", SSTOP);
|
| + PyModule_AddIntConstant(module, "SZOMB", SZOMB);
|
| +
|
| + if (module == NULL) {
|
| + INITERROR;
|
| + }
|
| +#if PY_MAJOR_VERSION >= 3
|
| + return module;
|
| +#endif
|
| +}
|
|
|