| 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 | 
| +} | 
|  |