summaryrefslogtreecommitdiff
path: root/psutil/_psutil_osx.c
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2018-06-26 16:57:36 -0700
committerGitHub <noreply@github.com>2018-06-26 16:57:36 -0700
commit2f60e997fc1c500e0c245979bbecf2761f36e820 (patch)
tree5459ce3b71fad107ec41c8b720811a8110a3380d /psutil/_psutil_osx.c
parent7a3ed446447ec845a7d03b32233b4ed7b48f3c26 (diff)
downloadpsutil-2f60e997fc1c500e0c245979bbecf2761f36e820.tar.gz
Rename OSX to macOS (#1298)
rename OSX to macOS
Diffstat (limited to 'psutil/_psutil_osx.c')
-rw-r--r--psutil/_psutil_osx.c2144
1 files changed, 0 insertions, 2144 deletions
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c
deleted file mode 100644
index 15f4d4f6..00000000
--- a/psutil/_psutil_osx.c
+++ /dev/null
@@ -1,2144 +0,0 @@
-/*
- * Copyright (c) 2009, 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
- */
-
-#include <Python.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <utmpx.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 <pwd.h>
-
-#include <mach/mach.h>
-#include <mach/task.h>
-#include <mach/mach_init.h>
-#include <mach/host_info.h>
-#include <mach/mach_host.h>
-#include <mach/mach_traps.h>
-#include <mach/mach_vm.h>
-#include <mach/shared_region.h>
-
-#include <mach-o/loader.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/storage/IOBlockStorageDriver.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/IOBSD.h>
-#include <IOKit/ps/IOPowerSources.h>
-#include <IOKit/ps/IOPSKeys.h>
-
-#include "_psutil_common.h"
-#include "_psutil_posix.h"
-#include "arch/osx/process_info.h"
-#include "arch/osx/smc.h"
-
-
-#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
-
-static PyObject *ZombieProcessError;
-
-
-/*
- * A wrapper around host_statistics() invoked with HOST_VM_INFO.
- */
-int
-psutil_sys_vminfo(vm_statistics_data_t *vmstat) {
- kern_return_t ret;
- mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t);
- mach_port_t mport = mach_host_self();
-
- ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)vmstat, &count);
- if (ret != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_VM_INFO) syscall failed: %s",
- mach_error_string(ret));
- return 0;
- }
- mach_port_deallocate(mach_task_self(), mport);
- return 1;
-}
-
-
-/*
- * Return 1 if pid refers to a zombie process else 0.
- */
-int
-psutil_is_zombie(long pid)
-{
- struct kinfo_proc kp;
-
- if (psutil_get_kinfo_proc(pid, &kp) == -1)
- return 0;
- return (kp.kp_proc.p_stat == SZOMB) ? 1 : 0;
-}
-
-
-/*
- * A wrapper around task_for_pid() which sucks big time:
- * - it's not documented
- * - errno is set only sometimes
- * - sometimes errno is ENOENT (?!?)
- * - for PIDs != getpid() or PIDs which are not members of the procmod
- * it requires root
- * As such we can only guess what the heck went wrong and fail either
- * with NoSuchProcess, ZombieProcessError or giveup with AccessDenied.
- * Here's some history:
- * https://github.com/giampaolo/psutil/issues/1181
- * https://github.com/giampaolo/psutil/issues/1209
- * https://github.com/giampaolo/psutil/issues/1291#issuecomment-396062519
- */
-int
-psutil_task_for_pid(long pid, mach_port_t *task)
-{
- // See: https://github.com/giampaolo/psutil/issues/1181
- kern_return_t err = KERN_SUCCESS;
-
- err = task_for_pid(mach_task_self(), (pid_t)pid, task);
- if (err != KERN_SUCCESS) {
- if (psutil_pid_exists(pid) == 0)
- NoSuchProcess("task_for_pid() failed");
- else if (psutil_is_zombie(pid) == 1)
- PyErr_SetString(ZombieProcessError, "task_for_pid() failed");
- else {
- psutil_debug(
- "task_for_pid() failed (pid=%ld, err=%i, errno=%i, msg='%s'); "
- "setting AccessDenied()",
- pid, err, errno, mach_error_string(err));
- AccessDenied("task_for_pid() failed");
- }
- return 1;
- }
- return 0;
-}
-
-
-/*
- * Return a Python list of all the PIDs running on the system.
- */
-static PyObject *
-psutil_pids(PyObject *self, PyObject *args) {
- kinfo_proc *proclist = NULL;
- kinfo_proc *orig_address = NULL;
- size_t num_processes;
- size_t idx;
- PyObject *py_pid = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
-
- if (psutil_get_proc_list(&proclist, &num_processes) != 0) {
- if (errno != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- }
- else {
- PyErr_SetString(PyExc_RuntimeError,
- "failed to retrieve process list");
- }
- goto error;
- }
-
- if (num_processes > 0) {
- // save the address of proclist so we can free it later
- orig_address = proclist;
- for (idx = 0; idx < num_processes; idx++) {
- py_pid = Py_BuildValue("i", proclist->kp_proc.p_pid);
- if (! py_pid)
- goto error;
- if (PyList_Append(py_retlist, py_pid))
- goto error;
- Py_DECREF(py_pid);
- proclist++;
- }
- free(orig_address);
- }
- return py_retlist;
-
-error:
- Py_XDECREF(py_pid);
- Py_DECREF(py_retlist);
- if (orig_address != NULL)
- free(orig_address);
- return NULL;
-}
-
-
-/*
- * Return multiple process info as a Python tuple in one shot by
- * using sysctl() and filling up a kinfo_proc struct.
- * It should be possible to do this for all processes without
- * incurring into permission (EPERM) errors.
- * This will also succeed for zombie processes returning correct
- * information.
- */
-static PyObject *
-psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
- long pid;
- struct kinfo_proc kp;
- PyObject *py_name;
- PyObject *py_retlist;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
- if (psutil_get_kinfo_proc(pid, &kp) == -1)
- return NULL;
-
- py_name = PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm);
- if (! py_name) {
- // Likely a decoding error. We don't want to fail the whole
- // operation. The python module may retry with proc_name().
- PyErr_Clear();
- py_name = Py_None;
- }
-
- py_retlist = Py_BuildValue(
- "lllllllidiO",
- (long)kp.kp_eproc.e_ppid, // (long) ppid
- (long)kp.kp_eproc.e_pcred.p_ruid, // (long) real uid
- (long)kp.kp_eproc.e_ucred.cr_uid, // (long) effective uid
- (long)kp.kp_eproc.e_pcred.p_svuid, // (long) saved uid
- (long)kp.kp_eproc.e_pcred.p_rgid, // (long) real gid
- (long)kp.kp_eproc.e_ucred.cr_groups[0], // (long) effective gid
- (long)kp.kp_eproc.e_pcred.p_svgid, // (long) saved gid
- kp.kp_eproc.e_tdev, // (int) tty nr
- PSUTIL_TV2DOUBLE(kp.kp_proc.p_starttime), // (double) create time
- (int)kp.kp_proc.p_stat, // (int) status
- py_name // (pystr) name
- );
-
- if (py_retlist != NULL) {
- // XXX shall we decref() also in case of Py_BuildValue() error?
- Py_DECREF(py_name);
- }
- return py_retlist;
-}
-
-
-/*
- * Return multiple process info as a Python tuple in one shot by
- * using proc_pidinfo(PROC_PIDTASKINFO) and filling a proc_taskinfo
- * struct.
- * Contrarily from proc_kinfo above this function will fail with
- * EACCES for PIDs owned by another user and with ESRCH for zombie
- * processes.
- */
-static PyObject *
-psutil_proc_pidtaskinfo_oneshot(PyObject *self, PyObject *args) {
- long pid;
- struct proc_taskinfo pti;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
- if (psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)) <= 0)
- return NULL;
-
- return Py_BuildValue(
- "(ddKKkkkk)",
- (float)pti.pti_total_user / 1000000000.0, // (float) cpu user time
- (float)pti.pti_total_system / 1000000000.0, // (float) cpu sys time
- // Note about memory: determining other mem stats on OSX is a mess:
- // http://www.opensource.apple.com/source/top/top-67/libtop.c?txt
- // I just give up.
- // struct proc_regioninfo pri;
- // psutil_proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, &pri, sizeof(pri))
- pti.pti_resident_size, // (uns long long) rss
- pti.pti_virtual_size, // (uns long long) vms
- pti.pti_faults, // (uns long) number of page faults (pages)
- pti.pti_pageins, // (uns long) number of actual pageins (pages)
- pti.pti_threadnum, // (uns long) num threads
- // Unvoluntary value seems not to be available;
- // pti.pti_csw probably refers to the sum of the two;
- // getrusage() numbers seems to confirm this theory.
- pti.pti_csw // (uns long) voluntary ctx switches
- );
-}
-
-
-/*
- * Return process name from kinfo_proc as a Python string.
- */
-static PyObject *
-psutil_proc_name(PyObject *self, PyObject *args) {
- long pid;
- struct kinfo_proc kp;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
- if (psutil_get_kinfo_proc(pid, &kp) == -1)
- return NULL;
- return PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm);
-}
-
-
-/*
- * Return process current working directory.
- * Raises NSP in case of zombie process.
- */
-static PyObject *
-psutil_proc_cwd(PyObject *self, PyObject *args) {
- long pid;
- struct proc_vnodepathinfo pathinfo;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
- if (psutil_proc_pidinfo(
- pid, PROC_PIDVNODEPATHINFO, 0, &pathinfo, sizeof(pathinfo)) <= 0)
- {
- return NULL;
- }
-
- return PyUnicode_DecodeFSDefault(pathinfo.pvi_cdir.vip_path);
-}
-
-
-/*
- * Return path of the process executable.
- */
-static PyObject *
-psutil_proc_exe(PyObject *self, PyObject *args) {
- long pid;
- char buf[PATH_MAX];
- int ret;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
- errno = 0;
- ret = proc_pidpath((pid_t)pid, &buf, sizeof(buf));
- if (ret == 0) {
- if (pid == 0)
- AccessDenied("");
- else
- psutil_raise_for_pid(pid, "proc_pidpath()");
- return NULL;
- }
- return PyUnicode_DecodeFSDefault(buf);
-}
-
-
-/*
- * Return process cmdline as a Python list of cmdline arguments.
- */
-static PyObject *
-psutil_proc_cmdline(PyObject *self, PyObject *args) {
- long pid;
- PyObject *py_retlist = NULL;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
- // get the commandline, defined in arch/osx/process_info.c
- py_retlist = psutil_get_cmdline(pid);
- return py_retlist;
-}
-
-
-/*
- * Return process environment as a Python string.
- */
-static PyObject *
-psutil_proc_environ(PyObject *self, PyObject *args) {
- long pid;
- PyObject *py_retdict = NULL;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
- // get the environment block, defined in arch/osx/process_info.c
- py_retdict = psutil_get_environ(pid);
- return py_retdict;
-}
-
-
-/*
- * Return a list of tuples for every process memory maps.
- * 'procstat' cmdline utility has been used as an example.
- */
-static PyObject *
-psutil_proc_memory_maps(PyObject *self, PyObject *args) {
- char buf[PATH_MAX];
- char addr_str[34];
- char perms[8];
- int pagesize = getpagesize();
- long pid;
- kern_return_t err = KERN_SUCCESS;
- mach_port_t task = MACH_PORT_NULL;
- uint32_t depth = 1;
- vm_address_t address = 0;
- vm_size_t size = 0;
-
- PyObject *py_tuple = NULL;
- PyObject *py_path = NULL;
- PyObject *py_list = PyList_New(0);
-
- if (py_list == NULL)
- return NULL;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- goto error;
-
- if (psutil_task_for_pid(pid, &task) != 0)
- goto error;
-
- while (1) {
- py_tuple = NULL;
- struct vm_region_submap_info_64 info;
- mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
-
- err = vm_region_recurse_64(task, &address, &size, &depth,
- (vm_region_info_64_t)&info, &count);
- if (err == KERN_INVALID_ADDRESS) {
- // TODO temporary
- psutil_debug("vm_region_recurse_64 returned KERN_INVALID_ADDRESS");
- break;
- }
- if (err != KERN_SUCCESS) {
- psutil_debug("vm_region_recurse_64 returned != KERN_SUCCESS");
- }
-
- if (info.is_submap) {
- depth++;
- }
- else {
- // Free/Reset the char[]s to avoid weird paths
- memset(buf, 0, sizeof(buf));
- memset(addr_str, 0, sizeof(addr_str));
- memset(perms, 0, sizeof(perms));
-
- sprintf(addr_str,
- "%016lx-%016lx",
- (long unsigned int)address,
- (long unsigned int)address + size);
- sprintf(perms, "%c%c%c/%c%c%c",
- (info.protection & VM_PROT_READ) ? 'r' : '-',
- (info.protection & VM_PROT_WRITE) ? 'w' : '-',
- (info.protection & VM_PROT_EXECUTE) ? 'x' : '-',
- (info.max_protection & VM_PROT_READ) ? 'r' : '-',
- (info.max_protection & VM_PROT_WRITE) ? 'w' : '-',
- (info.max_protection & VM_PROT_EXECUTE) ? 'x' : '-');
-
- // proc_regionfilename() return value seems meaningless
- // so we do what we can in order to not continue in case
- // of error.
- errno = 0;
- proc_regionfilename((pid_t)pid, address, buf, sizeof(buf));
- if ((errno != 0) || ((sizeof(buf)) <= 0)) {
- // TODO temporary
- psutil_debug("proc_regionfilename() failed");
- psutil_raise_for_pid(pid, "proc_regionfilename()");
- goto error;
- }
-
- if (info.share_mode == SM_COW && info.ref_count == 1) {
- // Treat single reference SM_COW as SM_PRIVATE
- info.share_mode = SM_PRIVATE;
- }
-
- if (strlen(buf) == 0) {
- switch (info.share_mode) {
-// #ifdef SM_LARGE_PAGE
- // case SM_LARGE_PAGE:
- // Treat SM_LARGE_PAGE the same as SM_PRIVATE
- // since they are not shareable and are wired.
-// #endif
- case SM_COW:
- strcpy(buf, "[cow]");
- break;
- case SM_PRIVATE:
- strcpy(buf, "[prv]");
- break;
- case SM_EMPTY:
- strcpy(buf, "[nul]");
- break;
- case SM_SHARED:
- case SM_TRUESHARED:
- strcpy(buf, "[shm]");
- break;
- case SM_PRIVATE_ALIASED:
- strcpy(buf, "[ali]");
- break;
- case SM_SHARED_ALIASED:
- strcpy(buf, "[s/a]");
- break;
- default:
- strcpy(buf, "[???]");
- }
- }
-
- py_path = PyUnicode_DecodeFSDefault(buf);
- if (! py_path)
- goto error;
- py_tuple = Py_BuildValue(
- "ssOIIIIIH",
- addr_str, // "start-end"address
- perms, // "rwx" permissions
- py_path, // path
- info.pages_resident * pagesize, // rss
- info.pages_shared_now_private * pagesize, // private
- info.pages_swapped_out * pagesize, // swapped
- info.pages_dirtied * pagesize, // dirtied
- info.ref_count, // ref count
- info.shadow_depth // shadow depth
- );
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_list, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- Py_DECREF(py_path);
- }
-
- // increment address for the next map/file
- address += size;
- }
-
- if (task != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), task);
-
- return py_list;
-
-error:
- if (task != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), task);
- Py_XDECREF(py_tuple);
- Py_XDECREF(py_path);
- Py_DECREF(py_list);
- return NULL;
-}
-
-
-/*
- * Return the number of logical CPUs in the system.
- * XXX this could be shared with BSD.
- */
-static PyObject *
-psutil_cpu_count_logical(PyObject *self, PyObject *args) {
- /*
- int mib[2];
- int ncpu;
- size_t len;
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
-
- if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", ncpu);
- */
- int num;
- size_t size = sizeof(int);
-
- if (sysctlbyname("hw.logicalcpu", &num, &size, NULL, 2))
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", num);
-}
-
-
-/*
- * Return the number of physical CPUs in the system.
- */
-static PyObject *
-psutil_cpu_count_phys(PyObject *self, PyObject *args) {
- int num;
- size_t size = sizeof(int);
-
- if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0))
- Py_RETURN_NONE; // mimic os.cpu_count()
- else
- return Py_BuildValue("i", num);
-}
-
-
-/*
- * Indicates if the given virtual address on the given architecture is in the
- * shared VM region.
- */
-bool
-psutil_in_shared_region(mach_vm_address_t addr, cpu_type_t type) {
- mach_vm_address_t base;
- mach_vm_address_t size;
-
- switch (type) {
- case CPU_TYPE_ARM:
- base = SHARED_REGION_BASE_ARM;
- size = SHARED_REGION_SIZE_ARM;
- break;
- case CPU_TYPE_I386:
- base = SHARED_REGION_BASE_I386;
- size = SHARED_REGION_SIZE_I386;
- break;
- case CPU_TYPE_X86_64:
- base = SHARED_REGION_BASE_X86_64;
- size = SHARED_REGION_SIZE_X86_64;
- break;
- default:
- return false;
- }
-
- return base <= addr && addr < (base + size);
-}
-
-
-/*
- * Returns the USS (unique set size) of the process. Reference:
- * https://dxr.mozilla.org/mozilla-central/source/xpcom/base/
- * nsMemoryReporterManager.cpp
- */
-static PyObject *
-psutil_proc_memory_uss(PyObject *self, PyObject *args) {
- long pid;
- size_t len;
- cpu_type_t cpu_type;
- size_t private_pages = 0;
- mach_vm_size_t size = 0;
- mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT;
- kern_return_t kr;
- vm_size_t page_size;
- mach_vm_address_t addr = MACH_VM_MIN_ADDRESS;
- mach_port_t task = MACH_PORT_NULL;
- vm_region_top_info_data_t info;
- mach_port_t object_name;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
- if (psutil_task_for_pid(pid, &task) != 0)
- return NULL;
-
- len = sizeof(cpu_type);
- if (sysctlbyname("sysctl.proc_cputype", &cpu_type, &len, NULL, 0) != 0)
- return PyErr_SetFromErrno(PyExc_OSError);
-
- // Roughly based on libtop_update_vm_regions in
- // http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c
- for (addr = 0; ; addr += size) {
- kr = mach_vm_region(
- task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info,
- &info_count, &object_name);
- if (kr == KERN_INVALID_ADDRESS) {
- // Done iterating VM regions.
- break;
- }
- else if (kr != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "mach_vm_region(VM_REGION_TOP_INFO) syscall failed");
- return NULL;
- }
-
- if (psutil_in_shared_region(addr, cpu_type) &&
- info.share_mode != SM_PRIVATE) {
- continue;
- }
-
- switch (info.share_mode) {
-#ifdef SM_LARGE_PAGE
- case SM_LARGE_PAGE:
- // NB: Large pages are not shareable and always resident.
-#endif
- case SM_PRIVATE:
- private_pages += info.private_pages_resident;
- private_pages += info.shared_pages_resident;
- break;
- case SM_COW:
- private_pages += info.private_pages_resident;
- if (info.ref_count == 1) {
- // Treat copy-on-write pages as private if they only
- // have one reference.
- private_pages += info.shared_pages_resident;
- }
- break;
- case SM_SHARED:
- default:
- break;
- }
- }
-
- mach_port_deallocate(mach_task_self(), task);
-
- if (host_page_size(mach_host_self(), &page_size) != KERN_SUCCESS)
- page_size = PAGE_SIZE;
-
- return Py_BuildValue("K", private_pages * page_size);
-}
-
-
-/*
- * Return system virtual memory stats.
- * See:
- * http://opensource.apple.com/source/system_cmds/system_cmds-498.2/
- * vm_stat.tproj/vm_stat.c
- */
-static PyObject *
-psutil_virtual_mem(PyObject *self, PyObject *args) {
- int mib[2];
- uint64_t total;
- size_t len = sizeof(total);
- vm_statistics_data_t vm;
- int pagesize = getpagesize();
- // physical mem
- mib[0] = CTL_HW;
- mib[1] = HW_MEMSIZE;
-
- // This is also available as sysctlbyname("hw.memsize").
- if (sysctl(mib, 2, &total, &len, NULL, 0)) {
- if (errno != 0)
- PyErr_SetFromErrno(PyExc_OSError);
- else
- PyErr_Format(
- PyExc_RuntimeError, "sysctl(HW_MEMSIZE) syscall failed");
- return NULL;
- }
-
- // vm
- if (!psutil_sys_vminfo(&vm))
- return NULL;
-
- return Py_BuildValue(
- "KKKKK",
- total,
- (unsigned long long) vm.active_count * pagesize,
- (unsigned long long) vm.inactive_count * pagesize,
- (unsigned long long) vm.wire_count * pagesize,
- // this is how vm_stat cmd does it
- (unsigned long long) (vm.free_count - vm.speculative_count) * pagesize
- );
-}
-
-
-/*
- * Return stats about swap memory.
- */
-static PyObject *
-psutil_swap_mem(PyObject *self, PyObject *args) {
- int mib[2];
- size_t size;
- struct xsw_usage totals;
- vm_statistics_data_t vmstat;
- int pagesize = getpagesize();
-
- mib[0] = CTL_VM;
- mib[1] = VM_SWAPUSAGE;
- size = sizeof(totals);
- if (sysctl(mib, 2, &totals, &size, NULL, 0) == -1) {
- if (errno != 0)
- PyErr_SetFromErrno(PyExc_OSError);
- else
- PyErr_Format(
- PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) syscall failed");
- return NULL;
- }
- if (!psutil_sys_vminfo(&vmstat))
- return NULL;
-
- return Py_BuildValue(
- "LLLKK",
- totals.xsu_total,
- totals.xsu_used,
- totals.xsu_avail,
- (unsigned long long)vmstat.pageins * pagesize,
- (unsigned long long)vmstat.pageouts * pagesize);
-}
-
-
-/*
- * Return a Python tuple representing user, kernel and idle CPU times
- */
-static PyObject *
-psutil_cpu_times(PyObject *self, PyObject *args) {
- mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
- kern_return_t error;
- host_cpu_load_info_data_t r_load;
-
- mach_port_t host_port = mach_host_self();
- error = host_statistics(host_port, HOST_CPU_LOAD_INFO,
- (host_info_t)&r_load, &count);
- if (error != KERN_SUCCESS) {
- return PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_CPU_LOAD_INFO) syscall failed: %s",
- mach_error_string(error));
- }
- mach_port_deallocate(mach_task_self(), host_port);
-
- 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
- );
-}
-
-
-/*
- * Return a Python list of tuple representing per-cpu times
- */
-static PyObject *
-psutil_per_cpu_times(PyObject *self, PyObject *args) {
- natural_t cpu_count;
- natural_t i;
- 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 = NULL;
- int ret;
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_cputime = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- mach_port_t host_port = mach_host_self();
- error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO,
- &cpu_count, &info_array, &info_count);
- if (error != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_processor_info(PROCESSOR_CPU_LOAD_INFO) syscall failed: %s",
- mach_error_string(error));
- goto error;
- }
- mach_port_deallocate(mach_task_self(), host_port);
-
- 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
- );
- if (!py_cputime)
- goto error;
- if (PyList_Append(py_retlist, py_cputime))
- goto error;
- Py_DECREF(py_cputime);
- }
-
- ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
- info_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
- return py_retlist;
-
-error:
- Py_XDECREF(py_cputime);
- Py_DECREF(py_retlist);
- if (cpu_load_info != NULL) {
- ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
- info_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
- }
- return NULL;
-}
-
-
-/*
- * Retrieve CPU frequency.
- */
-static PyObject *
-psutil_cpu_freq(PyObject *self, PyObject *args) {
- int64_t curr;
- int64_t min;
- int64_t max;
- size_t size = sizeof(int64_t);
-
- if (sysctlbyname("hw.cpufrequency", &curr, &size, NULL, 0))
- return PyErr_SetFromErrno(PyExc_OSError);
- if (sysctlbyname("hw.cpufrequency_min", &min, &size, NULL, 0))
- return PyErr_SetFromErrno(PyExc_OSError);
- if (sysctlbyname("hw.cpufrequency_max", &max, &size, NULL, 0))
- return PyErr_SetFromErrno(PyExc_OSError);
-
- return Py_BuildValue(
- "KKK",
- curr / 1000 / 1000,
- min / 1000 / 1000,
- max / 1000 / 1000);
-}
-
-
-/*
- * Return a Python float indicating the system boot time expressed in
- * seconds since the epoch.
- */
-static PyObject *
-psutil_boot_time(PyObject *self, PyObject *args) {
- // fetch sysctl "kern.boottime"
- static int request[2] = { CTL_KERN, KERN_BOOTTIME };
- struct timeval result;
- size_t result_len = sizeof result;
- time_t boot_time = 0;
-
- if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1)
- return PyErr_SetFromErrno(PyExc_OSError);
- boot_time = result.tv_sec;
- return Py_BuildValue("f", (float)boot_time);
-}
-
-/*
- * Return a Python float indicating the value of the temperature
- * measured by an SMC key
- */
-static PyObject *
-psutil_smc_get_temperature(PyObject *self, PyObject *args) {
- char* key;
- float temp;
-
- if (! PyArg_ParseTuple(args, "s", &key)) {
- return NULL;
- }
- temp = SMCGetTemperature(key);
- return Py_BuildValue("d", temp);
-}
-
-
-/*
- * Return a Python list of tuples of fan label and speed
- */
-static PyObject *
-psutil_sensors_fans(PyObject *self, PyObject *args) {
- int key;
- int speed;
- char fan[7];
- int fan_count;
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
-
- fan_count = SMCGetFanNumber(SMC_KEY_FAN_NUM);
- if (fan_count < 0)
- fan_count = 0;
-
- for (key = 0; key < fan_count; key++) {
- sprintf(fan, "Fan %d", key);
- speed = SMCGetFanSpeed(key);
- if (speed < 0)
- continue;
- py_tuple = Py_BuildValue("(si)", fan, speed);
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_XDECREF(py_tuple);
- }
-
- return py_retlist;
-
-error:
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- return NULL;
-}
-
-/*
- * Return a list of tuples including device, mount point and fs type
- * for all partitions mounted on the system.
- */
-static PyObject *
-psutil_disk_partitions(PyObject *self, PyObject *args) {
- int num;
- int i;
- int len;
- uint64_t flags;
- char opts[400];
- struct statfs *fs = NULL;
- PyObject *py_dev = NULL;
- PyObject *py_mountp = NULL;
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
-
- // 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(PyExc_OSError);
- goto error;
- }
-
- len = sizeof(*fs) * num;
- fs = malloc(len);
- if (fs == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- Py_BEGIN_ALLOW_THREADS
- num = getfsstat(fs, len, MNT_NOWAIT);
- Py_END_ALLOW_THREADS
- if (num == -1) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- for (i = 0; i < num; i++) {
- opts[0] = 0;
- flags = fs[i].f_flags;
-
- // see sys/mount.h
- if (flags & MNT_RDONLY)
- strlcat(opts, "ro", sizeof(opts));
- else
- strlcat(opts, "rw", sizeof(opts));
- if (flags & MNT_SYNCHRONOUS)
- strlcat(opts, ",sync", sizeof(opts));
- if (flags & MNT_NOEXEC)
- strlcat(opts, ",noexec", sizeof(opts));
- if (flags & MNT_NOSUID)
- strlcat(opts, ",nosuid", sizeof(opts));
- if (flags & MNT_UNION)
- strlcat(opts, ",union", sizeof(opts));
- if (flags & MNT_ASYNC)
- strlcat(opts, ",async", sizeof(opts));
- if (flags & MNT_EXPORTED)
- strlcat(opts, ",exported", sizeof(opts));
- if (flags & MNT_QUARANTINE)
- strlcat(opts, ",quarantine", sizeof(opts));
- if (flags & MNT_LOCAL)
- strlcat(opts, ",local", sizeof(opts));
- if (flags & MNT_QUOTA)
- strlcat(opts, ",quota", sizeof(opts));
- if (flags & MNT_ROOTFS)
- strlcat(opts, ",rootfs", sizeof(opts));
- if (flags & MNT_DOVOLFS)
- strlcat(opts, ",dovolfs", sizeof(opts));
- if (flags & MNT_DONTBROWSE)
- strlcat(opts, ",dontbrowse", sizeof(opts));
- if (flags & MNT_IGNORE_OWNERSHIP)
- strlcat(opts, ",ignore-ownership", sizeof(opts));
- if (flags & MNT_AUTOMOUNTED)
- strlcat(opts, ",automounted", sizeof(opts));
- if (flags & MNT_JOURNALED)
- strlcat(opts, ",journaled", sizeof(opts));
- if (flags & MNT_NOUSERXATTR)
- strlcat(opts, ",nouserxattr", sizeof(opts));
- if (flags & MNT_DEFWRITE)
- strlcat(opts, ",defwrite", sizeof(opts));
- if (flags & MNT_MULTILABEL)
- strlcat(opts, ",multilabel", sizeof(opts));
- if (flags & MNT_NOATIME)
- strlcat(opts, ",noatime", sizeof(opts));
- if (flags & MNT_UPDATE)
- strlcat(opts, ",update", sizeof(opts));
- if (flags & MNT_RELOAD)
- strlcat(opts, ",reload", sizeof(opts));
- if (flags & MNT_FORCE)
- strlcat(opts, ",force", sizeof(opts));
- if (flags & MNT_CMDFLAGS)
- strlcat(opts, ",cmdflags", sizeof(opts));
-
- py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname);
- if (! py_dev)
- goto error;
- py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname);
- if (! py_mountp)
- goto error;
- py_tuple = Py_BuildValue(
- "(OOss)",
- py_dev, // device
- py_mountp, // mount point
- fs[i].f_fstypename, // fs type
- opts); // options
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_DECREF(py_dev);
- Py_DECREF(py_mountp);
- Py_DECREF(py_tuple);
- }
-
- free(fs);
- return py_retlist;
-
-error:
- Py_XDECREF(py_dev);
- Py_XDECREF(py_mountp);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- if (fs != NULL)
- free(fs);
- return NULL;
-}
-
-
-/*
- * Return process threads
- */
-static PyObject *
-psutil_proc_threads(PyObject *self, PyObject *args) {
- long pid;
- int err, ret;
- kern_return_t kr;
- unsigned int info_count = TASK_BASIC_INFO_COUNT;
- mach_port_t task = MACH_PORT_NULL;
- struct task_basic_info tasks_info;
- thread_act_port_array_t thread_list = NULL;
- thread_info_data_t thinfo_basic;
- thread_basic_info_t basic_info_th;
- mach_msg_type_number_t thread_count, thread_info_count, j;
-
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- goto error;
-
- if (psutil_task_for_pid(pid, &task) != 0)
- goto error;
-
- 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) {
- AccessDenied("");
- }
- else {
- // otherwise throw a runtime error with appropriate error code
- PyErr_Format(PyExc_RuntimeError,
- "task_info(TASK_BASIC_INFO) syscall failed");
- }
- goto error;
- }
-
- err = task_threads(task, &thread_list, &thread_count);
- if (err != KERN_SUCCESS) {
- PyErr_Format(PyExc_RuntimeError, "task_threads() syscall failed");
- goto error;
- }
-
- for (j = 0; j < thread_count; j++) {
- py_tuple = NULL;
- thread_info_count = THREAD_INFO_MAX;
- kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
- (thread_info_t)thinfo_basic, &thread_info_count);
- if (kr != KERN_SUCCESS) {
- PyErr_Format(PyExc_RuntimeError,
- "thread_info(THREAD_BASIC_INFO) syscall failed");
- goto error;
- }
-
- basic_info_th = (thread_basic_info_t)thinfo_basic;
- py_tuple = Py_BuildValue(
- "Iff",
- j + 1,
- basic_info_th->user_time.seconds + \
- (float)basic_info_th->user_time.microseconds / 1000000.0,
- basic_info_th->system_time.seconds + \
- (float)basic_info_th->system_time.microseconds / 1000000.0
- );
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- }
-
- ret = vm_deallocate(task, (vm_address_t)thread_list,
- thread_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
-
- mach_port_deallocate(mach_task_self(), task);
-
- return py_retlist;
-
-error:
- if (task != MACH_PORT_NULL)
- mach_port_deallocate(mach_task_self(), task);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- if (thread_list != NULL) {
- ret = vm_deallocate(task, (vm_address_t)thread_list,
- thread_count * sizeof(int));
- if (ret != KERN_SUCCESS)
- PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
- }
- return NULL;
-}
-
-
-/*
- * 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 *
-psutil_proc_open_files(PyObject *self, PyObject *args) {
- long pid;
- int pidinfo_result;
- int iterations;
- int i;
- unsigned long nb;
-
- struct proc_fdinfo *fds_pointer = NULL;
- struct proc_fdinfo *fdp_pointer;
- struct vnode_fdinfowithpath vi;
-
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_tuple = NULL;
- PyObject *py_path = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- goto error;
-
- pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
- if (pidinfo_result <= 0)
- goto error;
-
- fds_pointer = malloc(pidinfo_result);
- if (fds_pointer == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- pidinfo_result = psutil_proc_pidinfo(
- pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result);
- 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) {
- errno = 0;
- nb = proc_pidfdinfo((pid_t)pid,
- fdp_pointer->proc_fd,
- PROC_PIDFDVNODEPATHINFO,
- &vi,
- sizeof(vi));
-
- // --- errors checking
- if ((nb <= 0) || nb < sizeof(vi)) {
- 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;
- }
- else {
- psutil_raise_for_pid(
- pid, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO)");
- goto error;
- }
- }
- // --- /errors checking
-
- // --- construct python list
- py_path = PyUnicode_DecodeFSDefault(vi.pvip.vip_path);
- if (! py_path)
- goto error;
- py_tuple = Py_BuildValue(
- "(Oi)",
- py_path,
- (int)fdp_pointer->proc_fd);
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- py_tuple = NULL;
- Py_DECREF(py_path);
- py_path = NULL;
- // --- /construct python list
- }
- }
-
- free(fds_pointer);
- return py_retlist;
-
-error:
- Py_XDECREF(py_tuple);
- Py_XDECREF(py_path);
- Py_DECREF(py_retlist);
- if (fds_pointer != NULL)
- free(fds_pointer);
- return NULL; // exception has already been set earlier
-}
-
-
-/*
- * Return process TCP and UDP connections as a list of tuples.
- * Raises NSP in case of zombie process.
- * References:
- * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0
- * - /usr/include/sys/proc_info.h
- */
-static PyObject *
-psutil_proc_connections(PyObject *self, PyObject *args) {
- long pid;
- int pidinfo_result;
- int iterations;
- int i;
- unsigned long nb;
-
- struct proc_fdinfo *fds_pointer = NULL;
- struct proc_fdinfo *fdp_pointer;
- struct socket_fdinfo si;
-
- PyObject *py_retlist = PyList_New(0);
- PyObject *py_tuple = NULL;
- PyObject *py_laddr = NULL;
- PyObject *py_raddr = NULL;
- PyObject *py_af_filter = NULL;
- PyObject *py_type_filter = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
- goto error;
-
- if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
- PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
- goto error;
- }
-
- if (pid == 0)
- return py_retlist;
- pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
- if (pidinfo_result <= 0)
- goto error;
-
- fds_pointer = malloc(pidinfo_result);
- if (fds_pointer == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- pidinfo_result = psutil_proc_pidinfo(
- pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result);
- if (pidinfo_result <= 0)
- goto error;
-
- iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
- for (i = 0; i < iterations; i++) {
- py_tuple = NULL;
- py_laddr = NULL;
- py_raddr = NULL;
- fdp_pointer = &fds_pointer[i];
-
- if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) {
- errno = 0;
- nb = proc_pidfdinfo((pid_t)pid, fdp_pointer->proc_fd,
- PROC_PIDFDSOCKETINFO, &si, sizeof(si));
-
- // --- errors checking
- if ((nb <= 0) || (nb < sizeof(si))) {
- if (errno == EBADF) {
- // let's assume socket has been closed
- continue;
- }
- else {
- psutil_raise_for_pid(
- pid, "proc_pidinfo(PROC_PIDFDSOCKETINFO)");
- goto error;
- }
- }
- // --- /errors checking
-
- //
- int fd, family, type, lport, rport, state;
- char lip[200], rip[200];
- int inseq;
- PyObject *py_family;
- PyObject *py_type;
-
- fd = (int)fdp_pointer->proc_fd;
- family = si.psi.soi_family;
- type = si.psi.soi_type;
-
- // apply filters
- py_family = PyLong_FromLong((long)family);
- inseq = PySequence_Contains(py_af_filter, py_family);
- Py_DECREF(py_family);
- if (inseq == 0)
- continue;
- py_type = PyLong_FromLong((long)type);
- inseq = PySequence_Contains(py_type_filter, py_type);
- Py_DECREF(py_type);
- if (inseq == 0)
- continue;
-
- if (errno != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- if ((family == AF_INET) || (family == AF_INET6)) {
- 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(rip));
- }
- 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,
- rip, sizeof(rip));
- }
-
- // check for inet_ntop failures
- if (errno != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- 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 = (int)si.psi.soi_proto.pri_tcp.tcpsi_state;
- else
- state = PSUTIL_CONN_NONE;
-
- py_laddr = Py_BuildValue("(si)", lip, lport);
- if (!py_laddr)
- goto error;
- if (rport != 0)
- py_raddr = Py_BuildValue("(si)", rip, rport);
- else
- py_raddr = Py_BuildValue("()");
- if (!py_raddr)
- goto error;
-
- // construct the python list
- py_tuple = Py_BuildValue(
- "(iiiNNi)", fd, family, type, py_laddr, py_raddr, state);
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- }
- else if (family == AF_UNIX) {
- py_laddr = PyUnicode_DecodeFSDefault(
- si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path);
- if (!py_laddr)
- goto error;
- py_raddr = PyUnicode_DecodeFSDefault(
- si.psi.soi_proto.pri_un.unsi_caddr.ua_sun.sun_path);
- if (!py_raddr)
- goto error;
- // construct the python list
- py_tuple = Py_BuildValue(
- "(iiiOOi)",
- fd, family, type,
- py_laddr,
- py_raddr,
- PSUTIL_CONN_NONE);
- if (!py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_DECREF(py_tuple);
- Py_DECREF(py_laddr);
- Py_DECREF(py_raddr);
- }
- }
- }
-
- free(fds_pointer);
- return py_retlist;
-
-error:
- Py_XDECREF(py_tuple);
- Py_XDECREF(py_laddr);
- Py_XDECREF(py_raddr);
- Py_DECREF(py_retlist);
- if (fds_pointer != NULL)
- free(fds_pointer);
- return NULL;
-}
-
-
-/*
- * Return number of file descriptors opened by process.
- * Raises NSP in case of zombie process.
- */
-static PyObject *
-psutil_proc_num_fds(PyObject *self, PyObject *args) {
- long pid;
- int pidinfo_result;
- int num;
- struct proc_fdinfo *fds_pointer;
-
- if (! PyArg_ParseTuple(args, "l", &pid))
- return NULL;
-
- pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, NULL, 0);
- if (pidinfo_result <= 0)
- return PyErr_SetFromErrno(PyExc_OSError);
-
- fds_pointer = malloc(pidinfo_result);
- if (fds_pointer == NULL)
- return PyErr_NoMemory();
- pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, fds_pointer,
- pidinfo_result);
- if (pidinfo_result <= 0) {
- free(fds_pointer);
- return PyErr_SetFromErrno(PyExc_OSError);
- }
-
- num = (pidinfo_result / PROC_PIDLISTFD_SIZE);
- free(fds_pointer);
- return Py_BuildValue("i", num);
-}
-
-
-/*
- * Return a Python list of named tuples with overall network I/O information
- */
-static PyObject *
-psutil_net_io_counters(PyObject *self, PyObject *args) {
- char *buf = NULL, *lim, *next;
- struct if_msghdr *ifm;
- int mib[6];
- size_t len;
- PyObject *py_retdict = PyDict_New();
- PyObject *py_ifc_info = NULL;
-
- if (py_retdict == NULL)
- return NULL;
-
- mib[0] = CTL_NET; // networking subsystem
- mib[1] = PF_ROUTE; // type of information
- mib[2] = 0; // protocol (IPPROTO_xxx)
- mib[3] = 0; // address family
- mib[4] = NET_RT_IFLIST2; // operation
- mib[5] = 0;
-
- if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- buf = malloc(len);
- if (buf == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
- PyErr_SetFromErrno(PyExc_OSError);
- goto error;
- }
-
- lim = buf + len;
-
- for (next = buf; next < lim; ) {
- ifm = (struct if_msghdr *)next;
- next += ifm->ifm_msglen;
-
- if (ifm->ifm_type == RTM_IFINFO2) {
- py_ifc_info = NULL;
- 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(
- "(KKKKKKKi)",
- if2m->ifm_data.ifi_obytes,
- if2m->ifm_data.ifi_ibytes,
- if2m->ifm_data.ifi_opackets,
- if2m->ifm_data.ifi_ipackets,
- if2m->ifm_data.ifi_ierrors,
- if2m->ifm_data.ifi_oerrors,
- if2m->ifm_data.ifi_iqdrops,
- 0); // dropout not supported
-
- if (!py_ifc_info)
- goto error;
- if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
- goto error;
- Py_DECREF(py_ifc_info);
- }
- else {
- continue;
- }
- }
-
- free(buf);
- return py_retdict;
-
-error:
- Py_XDECREF(py_ifc_info);
- Py_DECREF(py_retdict);
- if (buf != NULL)
- free(buf);
- return NULL;
-}
-
-
-/*
- * Return a Python dict of tuples for disk I/O information
- */
-static PyObject *
-psutil_disk_io_counters(PyObject *self, PyObject *args) {
- CFDictionaryRef parent_dict;
- CFDictionaryRef props_dict;
- CFDictionaryRef stats_dict;
- io_registry_entry_t parent;
- io_registry_entry_t disk;
- io_iterator_t disk_list;
- PyObject *py_retdict = PyDict_New();
- PyObject *py_disk_info = NULL;
-
- if (py_retdict == NULL)
- return NULL;
-
- // Get list of disks
- if (IOServiceGetMatchingServices(kIOMasterPortDefault,
- IOServiceMatching(kIOMediaClass),
- &disk_list) != kIOReturnSuccess) {
- PyErr_SetString(
- PyExc_RuntimeError, "unable to get the list of disks.");
- goto error;
- }
-
- // Iterate over disks
- while ((disk = IOIteratorNext(disk_list)) != 0) {
- py_disk_info = NULL;
- 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.");
- IOObjectRelease(disk);
- goto error;
- }
-
- if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
- if (IORegistryEntryCreateCFProperties(
- disk,
- (CFMutableDictionaryRef *) &parent_dict,
- kCFAllocatorDefault,
- kNilOptions
- ) != kIOReturnSuccess)
- {
- PyErr_SetString(PyExc_RuntimeError,
- "unable to get the parent's properties.");
- IOObjectRelease(disk);
- IOObjectRelease(parent);
- goto error;
- }
-
- if (IORegistryEntryCreateCFProperties(
- parent,
- (CFMutableDictionaryRef *) &props_dict,
- kCFAllocatorDefault,
- kNilOptions
- ) != kIOReturnSuccess)
- {
- PyErr_SetString(PyExc_RuntimeError,
- "unable to get the disk properties.");
- CFRelease(props_dict);
- IOObjectRelease(disk);
- IOObjectRelease(parent);
- goto error;
- }
-
- 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.");
- goto error;
- }
-
- CFNumberRef number;
- int64_t reads = 0;
- int64_t writes = 0;
- int64_t read_bytes = 0;
- int64_t write_bytes = 0;
- int64_t read_time = 0;
- int64_t 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);
- }
-
- // Read/Write time on OS X comes back in nanoseconds and in psutil
- // we've standardized on milliseconds so do the conversion.
- py_disk_info = Py_BuildValue(
- "(KKKKKK)",
- reads,
- writes,
- read_bytes,
- write_bytes,
- read_time / 1000 / 1000,
- write_time / 1000 / 1000);
- if (!py_disk_info)
- goto error;
- if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info))
- goto error;
- Py_DECREF(py_disk_info);
-
- CFRelease(parent_dict);
- IOObjectRelease(parent);
- CFRelease(props_dict);
- IOObjectRelease(disk);
- }
- }
-
- IOObjectRelease (disk_list);
-
- return py_retdict;
-
-error:
- Py_XDECREF(py_disk_info);
- Py_DECREF(py_retdict);
- return NULL;
-}
-
-
-/*
- * Return currently connected users as a list of tuples.
- */
-static PyObject *
-psutil_users(PyObject *self, PyObject *args) {
- struct utmpx *utx;
- PyObject *py_username = NULL;
- PyObject *py_tty = NULL;
- PyObject *py_hostname = NULL;
- PyObject *py_tuple = NULL;
- PyObject *py_retlist = PyList_New(0);
-
- if (py_retlist == NULL)
- return NULL;
- while ((utx = getutxent()) != NULL) {
- if (utx->ut_type != USER_PROCESS)
- continue;
- py_username = PyUnicode_DecodeFSDefault(utx->ut_user);
- if (! py_username)
- goto error;
- py_tty = PyUnicode_DecodeFSDefault(utx->ut_line);
- if (! py_tty)
- goto error;
- py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host);
- if (! py_hostname)
- goto error;
- py_tuple = Py_BuildValue(
- "(OOOfi)",
- py_username, // username
- py_tty, // tty
- py_hostname, // hostname
- (float)utx->ut_tv.tv_sec, // start time
- utx->ut_pid // process id
- );
- if (!py_tuple) {
- endutxent();
- goto error;
- }
- if (PyList_Append(py_retlist, py_tuple)) {
- endutxent();
- goto error;
- }
- Py_DECREF(py_username);
- Py_DECREF(py_tty);
- Py_DECREF(py_hostname);
- Py_DECREF(py_tuple);
- }
-
- endutxent();
- return py_retlist;
-
-error:
- Py_XDECREF(py_username);
- Py_XDECREF(py_tty);
- Py_XDECREF(py_hostname);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- return NULL;
-}
-
-
-/*
- * Return CPU statistics.
- */
-static PyObject *
-psutil_cpu_stats(PyObject *self, PyObject *args) {
- struct vmmeter vmstat;
- kern_return_t ret;
- mach_msg_type_number_t count = sizeof(vmstat) / sizeof(integer_t);
- mach_port_t mport = mach_host_self();
-
- ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)&vmstat, &count);
- if (ret != KERN_SUCCESS) {
- PyErr_Format(
- PyExc_RuntimeError,
- "host_statistics(HOST_VM_INFO) failed: %s",
- mach_error_string(ret));
- return NULL;
- }
- mach_port_deallocate(mach_task_self(), mport);
-
- return Py_BuildValue(
- "IIIII",
- vmstat.v_swtch, // ctx switches
- vmstat.v_intr, // interrupts
- vmstat.v_soft, // software interrupts
- vmstat.v_syscall, // syscalls
- vmstat.v_trap // traps
- );
-}
-
-
-
-/*
- * Return battery information.
- */
-static PyObject *
-psutil_sensors_battery(PyObject *self, PyObject *args) {
- PyObject *py_tuple = NULL;
- CFTypeRef power_info = NULL;
- CFArrayRef power_sources_list = NULL;
- CFDictionaryRef power_sources_information = NULL;
- CFNumberRef capacity_ref = NULL;
- CFNumberRef time_to_empty_ref = NULL;
- CFStringRef ps_state_ref = NULL;
- uint32_t capacity; /* units are percent */
- int time_to_empty; /* units are minutes */
- int is_power_plugged;
-
- power_info = IOPSCopyPowerSourcesInfo();
-
- if (!power_info) {
- PyErr_SetString(PyExc_RuntimeError,
- "IOPSCopyPowerSourcesInfo() syscall failed");
- goto error;
- }
-
- power_sources_list = IOPSCopyPowerSourcesList(power_info);
- if (!power_sources_list) {
- PyErr_SetString(PyExc_RuntimeError,
- "IOPSCopyPowerSourcesList() syscall failed");
- goto error;
- }
-
- /* Should only get one source. But in practice, check for > 0 sources */
- if (!CFArrayGetCount(power_sources_list)) {
- PyErr_SetString(PyExc_NotImplementedError, "no battery");
- goto error;
- }
-
- power_sources_information = IOPSGetPowerSourceDescription(
- power_info, CFArrayGetValueAtIndex(power_sources_list, 0));
-
- capacity_ref = (CFNumberRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSCurrentCapacityKey));
- if (!CFNumberGetValue(capacity_ref, kCFNumberSInt32Type, &capacity)) {
- PyErr_SetString(PyExc_RuntimeError,
- "No battery capacity infomration in power sources info");
- goto error;
- }
-
- ps_state_ref = (CFStringRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSPowerSourceStateKey));
- is_power_plugged = CFStringCompare(
- ps_state_ref, CFSTR(kIOPSACPowerValue), 0)
- == kCFCompareEqualTo;
-
- time_to_empty_ref = (CFNumberRef) CFDictionaryGetValue(
- power_sources_information, CFSTR(kIOPSTimeToEmptyKey));
- if (!CFNumberGetValue(time_to_empty_ref,
- kCFNumberIntType, &time_to_empty)) {
- /* This value is recommended for non-Apple power sources, so it's not
- * an error if it doesn't exist. We'll return -1 for "unknown" */
- /* A value of -1 indicates "Still Calculating the Time" also for
- * apple power source */
- time_to_empty = -1;
- }
-
- py_tuple = Py_BuildValue("Iii",
- capacity, time_to_empty, is_power_plugged);
- if (!py_tuple) {
- goto error;
- }
-
- CFRelease(power_info);
- CFRelease(power_sources_list);
- /* Caller should NOT release power_sources_information */
-
- return py_tuple;
-
-error:
- if (power_info)
- CFRelease(power_info);
- if (power_sources_list)
- CFRelease(power_sources_list);
- Py_XDECREF(py_tuple);
- return NULL;
-}
-
-
-/*
- * define the psutil C module methods and initialize the module.
- */
-static PyMethodDef
-PsutilMethods[] = {
- // --- per-process functions
-
- {"proc_kinfo_oneshot", psutil_proc_kinfo_oneshot, METH_VARARGS,
- "Return multiple process info."},
- {"proc_pidtaskinfo_oneshot", psutil_proc_pidtaskinfo_oneshot, METH_VARARGS,
- "Return multiple process info."},
- {"proc_name", psutil_proc_name, METH_VARARGS,
- "Return process name"},
- {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS,
- "Return process cmdline as a list of cmdline arguments"},
- {"proc_environ", psutil_proc_environ, METH_VARARGS,
- "Return process environment data"},
- {"proc_exe", psutil_proc_exe, METH_VARARGS,
- "Return path of the process executable"},
- {"proc_cwd", psutil_proc_cwd, METH_VARARGS,
- "Return process current working directory."},
- {"proc_memory_uss", psutil_proc_memory_uss, METH_VARARGS,
- "Return process USS memory"},
- {"proc_threads", psutil_proc_threads, METH_VARARGS,
- "Return process threads as a list of tuples"},
- {"proc_open_files", psutil_proc_open_files, METH_VARARGS,
- "Return files opened by process as a list of tuples"},
- {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS,
- "Return the number of fds opened by process."},
- {"proc_connections", psutil_proc_connections, METH_VARARGS,
- "Get process TCP and UDP connections as a list of tuples"},
- {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS,
- "Return a list of tuples for every process's memory map"},
-
- // --- system-related functions
-
- {"pids", psutil_pids, METH_VARARGS,
- "Returns a list of PIDs currently running on the system"},
- {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS,
- "Return number of logical CPUs on the system"},
- {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS,
- "Return number of physical CPUs on the system"},
- {"virtual_mem", psutil_virtual_mem, METH_VARARGS,
- "Return system virtual memory stats"},
- {"swap_mem", psutil_swap_mem, METH_VARARGS,
- "Return stats about swap memory, in bytes"},
- {"cpu_times", psutil_cpu_times, METH_VARARGS,
- "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
- {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS,
- "Return system per-cpu times as a list of tuples"},
- {"cpu_freq", psutil_cpu_freq, METH_VARARGS,
- "Return cpu current frequency"},
- {"boot_time", psutil_boot_time, METH_VARARGS,
- "Return the system boot time expressed in seconds since the epoch."},
- {"disk_partitions", psutil_disk_partitions, METH_VARARGS,
- "Return a list of tuples including device, mount point and "
- "fs type for all partitions mounted on the system."},
- {"net_io_counters", psutil_net_io_counters, METH_VARARGS,
- "Return dict of tuples of networks I/O information."},
- {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS,
- "Return dict of tuples of disks I/O information."},
- {"users", psutil_users, METH_VARARGS,
- "Return currently connected users as a list of tuples"},
- {"cpu_stats", psutil_cpu_stats, METH_VARARGS,
- "Return CPU statistics"},
- {"smc_get_temperature", psutil_smc_get_temperature, METH_VARARGS,
- "Temperature of SMC key as float"},
- {"sensors_fans", psutil_sensors_fans, METH_VARARGS,
- "Return the RPM of the fan with SMC key"},
- {"sensors_battery", psutil_sensors_battery, METH_VARARGS,
- "Return battery information."},
-
- // --- others
- {"set_testing", psutil_set_testing, METH_NOARGS,
- "Set psutil in testing mode"},
-
- {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
-
-PyMODINIT_FUNC 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
- PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
- // 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);
- // connection status constants
- PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED);
- PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING);
- PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT);
- PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN);
- PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED);
- PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT);
- PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED);
- PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1);
- PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2);
- PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK);
- PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
- PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
-
- // Exception.
- ZombieProcessError = PyErr_NewException(
- "_psutil_osx.ZombieProcessError", NULL, NULL);
- Py_INCREF(ZombieProcessError);
- PyModule_AddObject(module, "ZombieProcessError", ZombieProcessError);
-
- psutil_setup();
-
- if (module == NULL)
- INITERROR;
-#if PY_MAJOR_VERSION >= 3
- return module;
-#endif
-}