diff options
Diffstat (limited to 'psutil/_psutil_osx.c')
-rw-r--r-- | psutil/_psutil_osx.c | 792 |
1 files changed, 6 insertions, 786 deletions
diff --git a/psutil/_psutil_osx.c b/psutil/_psutil_osx.c index 713f3d6c..30a5312e 100644 --- a/psutil/_psutil_osx.c +++ b/psutil/_psutil_osx.c @@ -12,33 +12,27 @@ #include <stdbool.h> #include <stdlib.h> #include <stdio.h> -#include <utmpx.h> #include <sys/sysctl.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 <unistd.h> #include <mach/mach.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/cpu.h" +#include "arch/osx/disk.h" +#include "arch/osx/mem.h" +#include "arch/osx/net.h" +#include "arch/osx/process_info.h" +#include "arch/osx/sensors.h" +#include "arch/osx/sys.h" #define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) @@ -47,28 +41,6 @@ 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; -} - - -/* * A wrapper around task_for_pid() which sucks big time: * - it's not documented * - errno is set only sometimes @@ -499,350 +471,6 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) { /* - * Return system virtual memory stats. - * See: - * https://opensource.apple.com/source/system_cmds/system_cmds-790/ - * vm_stat.tproj/vm_stat.c.auto.html - */ -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; - long pagesize = psutil_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( - "KKKKKK", - total, - (unsigned long long) vm.active_count * pagesize, // active - (unsigned long long) vm.inactive_count * pagesize, // inactive - (unsigned long long) vm.wire_count * pagesize, // wired - (unsigned long long) vm.free_count * pagesize, // free - (unsigned long long) vm.speculative_count * pagesize // speculative - ); -} - - -/* - * 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; - long pagesize = psutil_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 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_CLEAR(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; -} - - -/* - * 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 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_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -static PyObject * -psutil_disk_usage_used(PyObject *self, PyObject *args) { - PyObject *py_default_value; - PyObject *py_mount_point_bytes = NULL; - char* mount_point; - -#if PY_MAJOR_VERSION >= 3 - if (!PyArg_ParseTuple(args, "O&O", PyUnicode_FSConverter, &py_mount_point_bytes, &py_default_value)) { - return NULL; - } - mount_point = PyBytes_AsString(py_mount_point_bytes); - if (NULL == mount_point) { - Py_XDECREF(py_mount_point_bytes); - return NULL; - } -#else - if (!PyArg_ParseTuple(args, "sO", &mount_point, &py_default_value)) { - return NULL; - } -#endif - -#ifdef ATTR_VOL_SPACEUSED - /* Call getattrlist(ATTR_VOL_SPACEUSED) to get used space info. */ - int ret; - struct { - uint32_t size; - uint64_t spaceused; - } __attribute__((aligned(4), packed)) attrbuf = {0}; - struct attrlist attrs = {0}; - - attrs.bitmapcount = ATTR_BIT_MAP_COUNT; - attrs.volattr = ATTR_VOL_INFO | ATTR_VOL_SPACEUSED; - Py_BEGIN_ALLOW_THREADS - ret = getattrlist(mount_point, &attrs, &attrbuf, sizeof(attrbuf), 0); - Py_END_ALLOW_THREADS - if (ret == 0) { - Py_XDECREF(py_mount_point_bytes); - return PyLong_FromUnsignedLongLong(attrbuf.spaceused); - } - psutil_debug("getattrlist(ATTR_VOL_SPACEUSED) failed, fall-back to default value"); -#endif - Py_XDECREF(py_mount_point_bytes); - Py_INCREF(py_default_value); - return py_default_value; -} - -/* * Return process threads */ static PyObject * @@ -1254,414 +882,6 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) { /* - * 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]; - 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; - size_t len; - PyObject *py_ifc_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - - 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_CLEAR(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return 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_disk_info = NULL; - PyObject *py_retdict = PyDict_New(); - - 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 macOS 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_CLEAR(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( - "(OOOdi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (double)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_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(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 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 mod_methods[] = { |