http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_psutil_windows.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_psutil_windows.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_psutil_windows.h new file mode 100644 index 0000000..546704e --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_psutil_windows.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> +#include <windows.h> + +// --- per-process functions + +static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args); +static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); +static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); +static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args); +static PyObject* psutil_proc_cpu_times_2(PyObject* self, PyObject* args); +static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args); +static PyObject* psutil_proc_create_time_2(PyObject* self, PyObject* args); +static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); +static PyObject* psutil_proc_exe(PyObject* self, PyObject* args); +static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args); +static PyObject* psutil_proc_io_counters_2(PyObject* self, PyObject* args); +static PyObject* psutil_proc_is_suspended(PyObject* self, PyObject* args); +static PyObject* psutil_proc_kill(PyObject* self, PyObject* args); +static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args); +static PyObject* psutil_proc_memory_info_2(PyObject* self, PyObject* args); +static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); +static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args); +static PyObject* psutil_proc_num_handles(PyObject* self, PyObject* args); +static PyObject* psutil_proc_num_handles_2(PyObject* self, PyObject* args); +static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); +static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args); +static PyObject* psutil_proc_priority_get(PyObject* self, PyObject* args); +static PyObject* psutil_proc_priority_set(PyObject* self, PyObject* args); +static PyObject* psutil_proc_resume(PyObject* self, PyObject* args); +static PyObject* psutil_proc_suspend(PyObject* self, PyObject* args); +static PyObject* psutil_proc_threads(PyObject* self, PyObject* args); +static PyObject* psutil_proc_username(PyObject* self, PyObject* args); +static PyObject* psutil_proc_wait(PyObject* self, PyObject* args); + +#if (PSUTIL_WINVER >= 0x0600) // Windows Vista +static PyObject* psutil_proc_io_priority_get(PyObject* self, PyObject* args); +static PyObject* psutil_proc_io_priority_set(PyObject* self, PyObject* args); +#endif + +// --- system-related functions + +static PyObject* psutil_boot_time(PyObject* self, PyObject* args); +static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args); +static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); +static PyObject* psutil_cpu_times(PyObject* self, PyObject* args); +static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); +static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); +static PyObject* psutil_disk_usage(PyObject* self, PyObject* args); +static PyObject* psutil_net_connections(PyObject* self, PyObject* args); +static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args); +static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); +static PyObject* psutil_pid_exists(PyObject* self, PyObject* args); +static PyObject* psutil_pids(PyObject* self, PyObject* args); +static PyObject* psutil_ppid_map(PyObject* self, PyObject* args); +static PyObject* psutil_users(PyObject* self, PyObject* args); +static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); + +// --- windows API bindings + +static PyObject* psutil_win32_QueryDosDevice(PyObject* self, PyObject* args); + +// --- internal + +int psutil_proc_suspend_or_resume(DWORD pid, int suspend);
http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_pswindows.py ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_pswindows.py b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_pswindows.py new file mode 100644 index 0000000..1a786f1 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/_pswindows.py @@ -0,0 +1,485 @@ +#!/usr/bin/env python + +# 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. + +"""Windows platform implementation.""" + +import errno +import os +import sys + +from psutil import _common +from psutil._common import conn_tmap, usage_percent, isfile_strict +from psutil._compat import PY3, xrange, wraps, lru_cache, namedtuple +import _psutil_windows as cext + +# process priority constants, import from __init__.py: +# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx +__extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", + "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", + "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS", + # + "CONN_DELETE_TCB", + ] + +# --- module level constants (gets pushed up to psutil module) + +CONN_DELETE_TCB = "DELETE_TCB" +WAIT_TIMEOUT = 0x00000102 # 258 in decimal +ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES, + cext.ERROR_ACCESS_DENIED]) + +TCP_STATUSES = { + cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, + cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, + cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, + cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, + cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, + cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, + cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, + cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, + cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, + cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, +} + + +scputimes = namedtuple('scputimes', ['user', 'system', 'idle']) +svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) +pextmem = namedtuple( + 'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', + 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', + 'pagefile', 'peak_pagefile', 'private']) +pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) +pmmap_ext = namedtuple( + 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) + +# set later from __init__.py +NoSuchProcess = None +AccessDenied = None +TimeoutExpired = None + + +@lru_cache(maxsize=512) +def _win32_QueryDosDevice(s): + return cext.win32_QueryDosDevice(s) + + +def _convert_raw_path(s): + # convert paths using native DOS format like: + # "\Device\HarddiskVolume1\Windows\systemew\file.txt" + # into: "C:\Windows\systemew\file.txt" + if PY3 and not isinstance(s, str): + s = s.decode('utf8') + rawdrive = '\\'.join(s.split('\\')[:3]) + driveletter = _win32_QueryDosDevice(rawdrive) + return os.path.join(driveletter, s[len(rawdrive):]) + + +# --- public functions + + +def virtual_memory(): + """System virtual memory as a namedtuple.""" + mem = cext.virtual_mem() + totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem + # + total = totphys + avail = availphys + free = availphys + used = total - avail + percent = usage_percent((total - avail), total, _round=1) + return svmem(total, avail, percent, used, free) + + +def swap_memory(): + """Swap system memory as a (total, used, free, sin, sout) tuple.""" + mem = cext.virtual_mem() + total = mem[2] + free = mem[3] + used = total - free + percent = usage_percent(used, total, _round=1) + return _common.sswap(total, used, free, percent, 0, 0) + + +def disk_usage(path): + """Return disk usage associated with path.""" + try: + total, free = cext.disk_usage(path) + except WindowsError: + if not os.path.exists(path): + msg = "No such file or directory: '%s'" % path + raise OSError(errno.ENOENT, msg) + raise + used = total - free + percent = usage_percent(used, total, _round=1) + return _common.sdiskusage(total, used, free, percent) + + +def disk_partitions(all): + """Return disk partitions.""" + rawlist = cext.disk_partitions(all) + return [_common.sdiskpart(*x) for x in rawlist] + + +def cpu_times(): + """Return system CPU times as a named tuple.""" + user, system, idle = cext.cpu_times() + return scputimes(user, system, idle) + + +def per_cpu_times(): + """Return system per-CPU times as a list of named tuples.""" + ret = [] + for cpu_t in cext.per_cpu_times(): + user, system, idle = cpu_t + item = scputimes(user, system, idle) + ret.append(item) + return ret + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + return cext.cpu_count_logical() + + +def cpu_count_physical(): + """Return the number of physical CPUs in the system.""" + return cext.cpu_count_phys() + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + return cext.boot_time() + + +def net_connections(kind, _pid=-1): + """Return socket connections. If pid == -1 return system-wide + connections (as opposed to connections opened by one process only). + """ + if kind not in conn_tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in conn_tmap]))) + families, types = conn_tmap[kind] + rawlist = cext.net_connections(_pid, families, types) + ret = [] + for item in rawlist: + fd, fam, type, laddr, raddr, status, pid = item + status = TCP_STATUSES[status] + if _pid == -1: + nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid) + else: + nt = _common.pconn(fd, fam, type, laddr, raddr, status) + ret.append(nt) + return ret + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + for item in rawlist: + user, hostname, tstamp = item + nt = _common.suser(user, None, hostname, tstamp) + retlist.append(nt) + return retlist + + +pids = cext.pids +pid_exists = cext.pid_exists +net_io_counters = cext.net_io_counters +disk_io_counters = cext.disk_io_counters +ppid_map = cext.ppid_map # not meant to be public + + +def wrap_exceptions(fun): + """Decorator which translates bare OSError and WindowsError + exceptions into NoSuchProcess and AccessDenied. + """ + @wraps(fun) + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except OSError: + # support for private module import + if NoSuchProcess is None or AccessDenied is None: + raise + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + raise AccessDenied(self.pid, self._name) + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + raise + return wrapper + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name"] + + def __init__(self, pid): + self.pid = pid + self._name = None + + @wrap_exceptions + def name(self): + """Return process name, which on Windows is always the final + part of the executable. + """ + # This is how PIDs 0 and 4 are always represented in taskmgr + # and process-hacker. + if self.pid == 0: + return "System Idle Process" + elif self.pid == 4: + return "System" + else: + return os.path.basename(self.exe()) + + @wrap_exceptions + def exe(self): + # Note: os.path.exists(path) may return False even if the file + # is there, see: + # http://stackoverflow.com/questions/3112546/os-path-exists-lies + return _convert_raw_path(cext.proc_exe(self.pid)) + + @wrap_exceptions + def cmdline(self): + return cext.proc_cmdline(self.pid) + + def ppid(self): + try: + return ppid_map()[self.pid] + except KeyError: + raise NoSuchProcess(self.pid, self._name) + + def _get_raw_meminfo(self): + try: + return cext.proc_memory_info(self.pid) + except OSError: + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + return cext.proc_memory_info_2(self.pid) + raise + + @wrap_exceptions + def memory_info(self): + # on Windows RSS == WorkingSetSize and VSM == PagefileUsage + # fields of PROCESS_MEMORY_COUNTERS struct: + # http://msdn.microsoft.com/en-us/library/windows/desktop/ + # ms684877(v=vs.85).aspx + t = self._get_raw_meminfo() + return _common.pmem(t[2], t[7]) + + @wrap_exceptions + def memory_info_ex(self): + return pextmem(*self._get_raw_meminfo()) + + def memory_maps(self): + try: + raw = cext.proc_memory_maps(self.pid) + except OSError: + # XXX - can't use wrap_exceptions decorator as we're + # returning a generator; probably needs refactoring. + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + raise AccessDenied(self.pid, self._name) + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + raise + else: + for addr, perm, path, rss in raw: + path = _convert_raw_path(path) + addr = hex(addr) + yield (addr, perm, path, rss) + + @wrap_exceptions + def kill(self): + return cext.proc_kill(self.pid) + + @wrap_exceptions + def wait(self, timeout=None): + if timeout is None: + timeout = cext.INFINITE + else: + # WaitForSingleObject() expects time in milliseconds + timeout = int(timeout * 1000) + ret = cext.proc_wait(self.pid, timeout) + if ret == WAIT_TIMEOUT: + # support for private module import + if TimeoutExpired is None: + raise RuntimeError("timeout expired") + raise TimeoutExpired(timeout, self.pid, self._name) + return ret + + @wrap_exceptions + def username(self): + if self.pid in (0, 4): + return 'NT AUTHORITY\\SYSTEM' + return cext.proc_username(self.pid) + + @wrap_exceptions + def create_time(self): + # special case for kernel process PIDs; return system boot time + if self.pid in (0, 4): + return boot_time() + try: + return cext.proc_create_time(self.pid) + except OSError: + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + return cext.proc_create_time_2(self.pid) + raise + + @wrap_exceptions + def num_threads(self): + return cext.proc_num_threads(self.pid) + + @wrap_exceptions + def threads(self): + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + return retlist + + @wrap_exceptions + def cpu_times(self): + try: + ret = cext.proc_cpu_times(self.pid) + except OSError: + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + ret = cext.proc_cpu_times_2(self.pid) + else: + raise + return _common.pcputimes(*ret) + + @wrap_exceptions + def suspend(self): + return cext.proc_suspend(self.pid) + + @wrap_exceptions + def resume(self): + return cext.proc_resume(self.pid) + + @wrap_exceptions + def cwd(self): + if self.pid in (0, 4): + raise AccessDenied(self.pid, self._name) + # return a normalized pathname since the native C function appends + # "\\" at the and of the path + path = cext.proc_cwd(self.pid) + return os.path.normpath(path) + + @wrap_exceptions + def open_files(self): + if self.pid in (0, 4): + return [] + retlist = [] + # Filenames come in in native format like: + # "\Device\HarddiskVolume1\Windows\systemew\file.txt" + # Convert the first part in the corresponding drive letter + # (e.g. "C:\") by using Windows's QueryDosDevice() + raw_file_names = cext.proc_open_files(self.pid) + for file in raw_file_names: + file = _convert_raw_path(file) + if isfile_strict(file) and file not in retlist: + ntuple = _common.popenfile(file, -1) + retlist.append(ntuple) + return retlist + + @wrap_exceptions + def connections(self, kind='inet'): + return net_connections(kind, _pid=self.pid) + + @wrap_exceptions + def nice_get(self): + return cext.proc_priority_get(self.pid) + + @wrap_exceptions + def nice_set(self, value): + return cext.proc_priority_set(self.pid, value) + + # available on Windows >= Vista + if hasattr(cext, "proc_io_priority_get"): + @wrap_exceptions + def ionice_get(self): + return cext.proc_io_priority_get(self.pid) + + @wrap_exceptions + def ionice_set(self, value, _): + if _: + raise TypeError("set_proc_ionice() on Windows takes only " + "1 argument (2 given)") + if value not in (2, 1, 0): + raise ValueError("value must be 2 (normal), 1 (low) or 0 " + "(very low); got %r" % value) + return cext.proc_io_priority_set(self.pid, value) + + @wrap_exceptions + def io_counters(self): + try: + ret = cext.proc_io_counters(self.pid) + except OSError: + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + ret = cext.proc_io_counters_2(self.pid) + else: + raise + return _common.pio(*ret) + + @wrap_exceptions + def status(self): + suspended = cext.proc_is_suspended(self.pid) + if suspended: + return _common.STATUS_STOPPED + else: + return _common.STATUS_RUNNING + + @wrap_exceptions + def cpu_affinity_get(self): + from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x] + bitmask = cext.proc_cpu_affinity_get(self.pid) + return from_bitmask(bitmask) + + @wrap_exceptions + def cpu_affinity_set(self, value): + def to_bitmask(l): + if not l: + raise ValueError("invalid argument %r" % l) + out = 0 + for b in l: + out |= 2 ** b + return out + + # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER + # is returned for an invalid CPU but this seems not to be true, + # therefore we check CPUs validy beforehand. + allcpus = list(range(len(per_cpu_times()))) + for cpu in value: + if cpu not in allcpus: + raise ValueError("invalid CPU %r" % cpu) + + bitmask = to_bitmask(value) + cext.proc_cpu_affinity_set(self.pid, bitmask) + + @wrap_exceptions + def num_handles(self): + try: + return cext.proc_num_handles(self.pid) + except OSError: + err = sys.exc_info()[1] + if err.errno in ACCESS_DENIED_SET: + return cext.proc_num_handles_2(self.pid) + raise + + @wrap_exceptions + def num_ctx_switches(self): + tupl = cext.proc_num_ctx_switches(self.pid) + return _common.pctxsw(*tupl) http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.c ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.c b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.c new file mode 100644 index 0000000..1c19556 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.c @@ -0,0 +1,285 @@ +/* + * 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. + * + * Helper functions related to fetching process information. + * Used by _psutil_bsd module methods. + */ + + +#include <Python.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#include <sys/param.h> +#include <sys/user.h> +#include <sys/proc.h> +#include <signal.h> + +#include "process_info.h" + + +/* + * Returns a list of all BSD processes on the system. This routine + * allocates the list and puts it in *procList and a count of the + * number of entries in *procCount. You are responsible for freeing + * this list (use "free" from System framework). + * On success, the function returns 0. + * On error, the function returns a BSD errno value. + */ +int +psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) +{ + int err; + struct kinfo_proc *result; + int done; + static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 }; + // Declaring name as const requires us to cast it when passing it to + // sysctl because the prototype doesn't include the const modifier. + size_t length; + + assert( procList != NULL); + assert(*procList == NULL); + assert(procCount != NULL); + + *procCount = 0; + + /* + * We start by calling sysctl with result == NULL and length == 0. + * That will succeed, and set length to the appropriate length. + * We then allocate a buffer of that size and call sysctl again + * with that buffer. If that succeeds, we're done. If that fails + * with ENOMEM, we have to throw away our buffer and loop. Note + * that the loop causes use to call sysctl with NULL again; this + * is necessary because the ENOMEM failure case sets length to + * the amount of data returned, not the amount of data that + * could have been returned. + */ + result = NULL; + done = 0; + do { + assert(result == NULL); + // Call sysctl with a NULL buffer. + length = 0; + err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, + NULL, &length, NULL, 0); + if (err == -1) + err = errno; + + // Allocate an appropriately sized buffer based on the results + // from the previous call. + if (err == 0) { + result = malloc(length); + if (result == NULL) + err = ENOMEM; + } + + // Call sysctl again with the new buffer. If we get an ENOMEM + // error, toss away our buffer and start again. + if (err == 0) { + err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1, + result, &length, NULL, 0); + if (err == -1) + err = errno; + if (err == 0) { + done = 1; + } + else if (err == ENOMEM) { + assert(result != NULL); + free(result); + result = NULL; + err = 0; + } + } + } while (err == 0 && ! done); + + // Clean up and establish post conditions. + if (err != 0 && result != NULL) { + free(result); + result = NULL; + } + + *procList = result; + *procCount = length / sizeof(struct kinfo_proc); + + assert((err == 0) == (*procList != NULL)); + return err; +} + + +char +*psutil_get_cmd_path(long pid, size_t *pathsize) +{ + int mib[4]; + char *path; + size_t size = 0; + + /* + * Make a sysctl() call to get the raw argument space of the process. + */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = pid; + + // call with a null buffer first to determine if we need a buffer + if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1) { + return NULL; + } + + path = malloc(size); + if (path == NULL) { + PyErr_NoMemory(); + return NULL; + } + + *pathsize = size; + if (sysctl(mib, 4, path, &size, NULL, 0) == -1) { + free(path); + return NULL; // Insufficient privileges + } + + return path; +} + + +/* + * XXX no longer used; it probably makese sense to remove it. + * Borrowed from psi Python System Information project + * + * Get command arguments and environment variables. + * + * Based on code from ps. + * + * Returns: + * 0 for success; + * -1 for failure (Exception raised); + * 1 for insufficient privileges. + */ +char +*psutil_get_cmd_args(long pid, size_t *argsize) +{ + int mib[4], argmax; + size_t size = sizeof(argmax); + char *procargs = NULL; + + // Get the maximum process arguments size. + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + + size = sizeof(argmax); + if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) + return NULL; + + // Allocate space for the arguments. + procargs = (char *)malloc(argmax); + if (procargs == NULL) { + PyErr_NoMemory(); + return NULL; + } + + /* + * Make a sysctl() call to get the raw argument space of the process. + */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ARGS; + mib[3] = pid; + + size = argmax; + if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) { + free(procargs); + return NULL; // Insufficient privileges + } + + // return string and set the length of arguments + *argsize = size; + return procargs; +} + + +// returns the command line as a python list object +PyObject * +psutil_get_arg_list(long pid) +{ + char *argstr = NULL; + int pos = 0; + size_t argsize = 0; + PyObject *retlist = Py_BuildValue("[]"); + PyObject *item = NULL; + + if (pid < 0) { + return retlist; + } + + argstr = psutil_get_cmd_args(pid, &argsize); + if (argstr == NULL) { + goto error; + } + + // args are returned as a flattened string with \0 separators between + // arguments add each string to the list then step forward to the next + // separator + if (argsize > 0) { + while (pos < argsize) { + item = Py_BuildValue("s", &argstr[pos]); + if (!item) + goto error; + if (PyList_Append(retlist, item)) + goto error; + Py_DECREF(item); + pos = pos + strlen(&argstr[pos]) + 1; + } + } + + free(argstr); + return retlist; + +error: + Py_XDECREF(item); + Py_DECREF(retlist); + if (argstr != NULL) + free(argstr); + return NULL; +} + + +/* + * Return 1 if PID exists in the current process list, else 0. + */ +int +psutil_pid_exists(long pid) +{ + int kill_ret; + if (pid < 0) { + return 0; + } + + // 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; + } + + // otherwise return 0 for PID not found + return 0; +} + + +/* + * Set exception to AccessDenied if pid exists else NoSuchProcess. + */ +int +psutil_raise_ad_or_nsp(pid) { + if (psutil_pid_exists(pid) == 0) { + NoSuchProcess(); + } + else { + AccessDenied(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.h new file mode 100644 index 0000000..858bd88 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/bsd/process_info.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> + +typedef struct kinfo_proc kinfo_proc; + +char *psutil_get_cmd_args(long pid, size_t *argsize); +char *psutil_get_cmd_path(long pid, size_t *pathsize); +int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); +int psutil_pid_exists(long pid); +PyObject* psutil_get_arg_list(long pid); http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.c ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.c b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.c new file mode 100644 index 0000000..be8092e --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.c @@ -0,0 +1,293 @@ +/* + * 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. + * + * Helper functions related to fetching process information. + * Used by _psutil_osx module methods. + */ + + +#include <Python.h> +#include <assert.h> +#include <errno.h> +#include <limits.h> // for INT_MAX +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <sys/sysctl.h> +#include <libproc.h> + +#include "process_info.h" +#include "../../_psutil_common.h" + + +/* + * Return 1 if PID exists in the current process list, else 0. + */ +int +psutil_pid_exists(long pid) +{ + int kill_ret; + + // save some time if it's an invalid PID + if (pid < 0) { + return 0; + } + + // 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; + } + + // otherwise return 0 for PID not found + return 0; +} + + +/* + * Returns a list of all BSD processes on the system. This routine + * allocates the list and puts it in *procList and a count of the + * number of entries in *procCount. You are responsible for freeing + * this list (use "free" from System framework). + * On success, the function returns 0. + * On error, the function returns a BSD errno value. + */ +int +psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) +{ + // Declaring mib as const requires use of a cast since the + // sysctl prototype doesn't include the const modifier. + static const int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; + size_t size, size2; + void *ptr; + int err, lim = 8; // some limit + + assert( procList != NULL); + assert(*procList == NULL); + assert(procCount != NULL); + + *procCount = 0; + + /* + * We start by calling sysctl with ptr == NULL and size == 0. + * That will succeed, and set size to the appropriate length. + * We then allocate a buffer of at least that size and call + * sysctl with that buffer. If that succeeds, we're done. + * If that call fails with ENOMEM, we throw the buffer away + * and try again. + * Note that the loop calls sysctl with NULL again. This is + * is necessary because the ENOMEM failure case sets size to + * the amount of data returned, not the amount of data that + * could have been returned. + */ + while (lim-- > 0) { + size = 0; + if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) { + return errno; + } + + size2 = size + (size >> 3); // add some + if (size2 > size) { + ptr = malloc(size2); + if (ptr == NULL) { + ptr = malloc(size); + } else { + size = size2; + } + } + else { + ptr = malloc(size); + } + if (ptr == NULL) { + return ENOMEM; + } + + if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) { + err = errno; + free(ptr); + if (err != ENOMEM) { + return err; + } + + } else { + *procList = (kinfo_proc *)ptr; + *procCount = size / sizeof(kinfo_proc); + return 0; + } + } + return ENOMEM; +} + + +// Read the maximum argument size for processes +int +psutil_get_argmax() +{ + int argmax; + int mib[] = { CTL_KERN, KERN_ARGMAX }; + size_t size = sizeof(argmax); + + if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) { + return argmax; + } + return 0; +} + + +// return process args as a python list +PyObject * +psutil_get_arg_list(long pid) +{ + int mib[3]; + int nargs; + int len; + char *procargs = NULL; + char *arg_ptr; + char *arg_end; + char *curr_arg; + size_t argmax; + PyObject *arg = NULL; + PyObject *arglist = NULL; + + // special case for PID 0 (kernel_task) where cmdline cannot be fetched + if (pid == 0) { + return Py_BuildValue("[]"); + } + + // read argmax and allocate memory for argument space. + argmax = psutil_get_argmax(); + if (! argmax) { + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + + procargs = (char *)malloc(argmax); + if (NULL == procargs) { + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + + // read argument space + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = pid; + if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { + if (EINVAL == errno) { + // EINVAL == access denied OR nonexistent PID + if ( psutil_pid_exists(pid) ) { + AccessDenied(); + } else { + NoSuchProcess(); + } + } + goto error; + } + + arg_end = &procargs[argmax]; + // copy the number of arguments to nargs + memcpy(&nargs, procargs, sizeof(nargs)); + + arg_ptr = procargs + sizeof(nargs); + len = strlen(arg_ptr); + arg_ptr += len + 1; + + if (arg_ptr == arg_end) { + free(procargs); + return Py_BuildValue("[]"); + } + + // skip ahead to the first argument + for (; arg_ptr < arg_end; arg_ptr++) { + if (*arg_ptr != '\0') { + break; + } + } + + // iterate through arguments + curr_arg = arg_ptr; + arglist = Py_BuildValue("[]"); + if (!arglist) + goto error; + while (arg_ptr < arg_end && nargs > 0) { + if (*arg_ptr++ == '\0') { + arg = Py_BuildValue("s", curr_arg); + if (!arg) + goto error; + if (PyList_Append(arglist, arg)) + goto error; + Py_DECREF(arg); + // iterate to next arg and decrement # of args + curr_arg = arg_ptr; + nargs--; + } + } + + free(procargs); + return arglist; + +error: + Py_XDECREF(arg); + Py_XDECREF(arglist); + if (procargs != NULL) + free(procargs); + return NULL; +} + + +int +psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) +{ + int mib[4]; + size_t len; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = pid; + + // fetch the info with sysctl() + len = sizeof(struct kinfo_proc); + + // now read the data from sysctl + if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) { + // raise an exception and throw errno as the error + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + // sysctl succeeds but len is zero, happens when process has gone away + if (len == 0) { + NoSuchProcess(); + return -1; + } + return 0; +} + + +/* + * A thin wrapper around proc_pidinfo() + */ +int +psutil_proc_pidinfo(long pid, int flavor, void *pti, int size) +{ + int ret = proc_pidinfo((int)pid, flavor, 0, pti, size); + if (ret == 0) { + if (! psutil_pid_exists(pid)) { + NoSuchProcess(); + return 0; + } + else { + AccessDenied(); + return 0; + } + } + else if (ret != size) { + AccessDenied(); + return 0; + } + else { + return 1; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.h new file mode 100644 index 0000000..c89c857 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/osx/process_info.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> + +typedef struct kinfo_proc kinfo_proc; + +int psutil_get_argmax(void); +int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp); +int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); +int psutil_pid_exists(long pid); +int psutil_proc_pidinfo(long pid, int flavor, void *pti, int size); +PyObject* psutil_get_arg_list(long pid); http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/glpi.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/glpi.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/glpi.h new file mode 100644 index 0000000..6f98483 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/glpi.h @@ -0,0 +1,41 @@ +// mingw headers are missing this + +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage, + RelationGroup, + RelationAll=0xffff +} LOGICAL_PROCESSOR_RELATIONSHIP; + +typedef enum _PROCESSOR_CACHE_TYPE { + CacheUnified,CacheInstruction,CacheData,CacheTrace +} PROCESSOR_CACHE_TYPE; + +typedef struct _CACHE_DESCRIPTOR { + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD Size; + PROCESSOR_CACHE_TYPE Type; +} CACHE_DESCRIPTOR,*PCACHE_DESCRIPTOR; + +typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { + ULONG_PTR ProcessorMask; + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + union { + struct { + BYTE Flags; + } ProcessorCore; + struct { + DWORD NodeNumber; + } NumaNode; + CACHE_DESCRIPTOR Cache; + ULONGLONG Reserved[2]; + }; +} SYSTEM_LOGICAL_PROCESSOR_INFORMATION,*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; + +WINBASEAPI WINBOOL WINAPI +GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, + PDWORD ReturnedLength); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/ntextapi.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/ntextapi.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/ntextapi.h new file mode 100644 index 0000000..298c078 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/ntextapi.h @@ -0,0 +1,287 @@ +/* + * 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. + */ + +typedef enum _KTHREAD_STATE { + Initialized, + Ready, + Running, + Standby, + Terminated, + Waiting, + Transition, + DeferredReady, + GateWait, + MaximumThreadState +} KTHREAD_STATE, *PKTHREAD_STATE; + +typedef enum _KWAIT_REASON { + Executive = 0, + FreePage = 1, + PageIn = 2, + PoolAllocation = 3, + DelayExecution = 4, + Suspended = 5, + UserRequest = 6, + WrExecutive = 7, + WrFreePage = 8, + WrPageIn = 9, + WrPoolAllocation = 10, + WrDelayExecution = 11, + WrSuspended = 12, + WrUserRequest = 13, + WrEventPair = 14, + WrQueue = 15, + WrLpcReceive = 16, + WrLpcReply = 17, + WrVirtualMemory = 18, + WrPageOut = 19, + WrRendezvous = 20, + Spare2 = 21, + Spare3 = 22, + Spare4 = 23, + Spare5 = 24, + WrCalloutStack = 25, + WrKernel = 26, + WrResource = 27, + WrPushLock = 28, + WrMutex = 29, + WrQuantumEnd = 30, + WrDispatchInt = 31, + WrPreempted = 32, + WrYieldExecution = 33, + WrFastMutex = 34, + WrGuardedMutex = 35, + WrRundown = 36, + MaximumWaitReason = 37 +} KWAIT_REASON, *PKWAIT_REASON; + +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; + + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _SYSTEM_TIMEOFDAY_INFORMATION { + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG TimeZoneId; + ULONG Reserved; + ULONGLONG BootTimeBias; + ULONGLONG SleepTimeBias; +} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION; + +typedef struct _SYSTEM_THREAD_INFORMATION { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + LONG Priority; + LONG BasePriority; + ULONG ContextSwitches; + ULONG ThreadState; + KWAIT_REASON WaitReason; +} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; + +typedef struct _TEB *PTEB; + +// private +typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION { + SYSTEM_THREAD_INFORMATION ThreadInfo; + PVOID StackBase; + PVOID StackLimit; + PVOID Win32StartAddress; + PTEB TebBase; + ULONG_PTR Reserved2; + ULONG_PTR Reserved3; + ULONG_PTR Reserved4; +} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; + +typedef struct _SYSTEM_PROCESS_INFORMATION { + ULONG NextEntryOffset; + ULONG NumberOfThreads; + LARGE_INTEGER SpareLi1; + LARGE_INTEGER SpareLi2; + LARGE_INTEGER SpareLi3; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ImageName; + LONG BasePriority; + HANDLE UniqueProcessId; + HANDLE InheritedFromUniqueProcessId; + ULONG HandleCount; + ULONG SessionId; + ULONG_PTR PageDirectoryBase; + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + DWORD PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; + SIZE_T PrivatePageCount; + LARGE_INTEGER ReadOperationCount; + LARGE_INTEGER WriteOperationCount; + LARGE_INTEGER OtherOperationCount; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + SYSTEM_THREAD_INFORMATION Threads[1]; +} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; + + +// structures and enums from winternl.h (not available under mingw) +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER Reserved1[2]; + ULONG Reserved2; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, + *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + + +typedef enum _SYSTEM_INFORMATION_CLASS { + SystemBasicInformation = 0, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, + SystemProcessInformation = 5, + SystemProcessorPerformanceInformation = 8, + SystemInterruptInformation = 23, + SystemExceptionInformation = 33, + SystemRegistryQuotaInformation = 37, + SystemLookasideInformation = 45 +} SYSTEM_INFORMATION_CLASS; + + +// ================================================ +// psutil.users() support +// ================================================ + +typedef struct _WINSTATION_INFO { + BYTE Reserved1[72]; + ULONG SessionId; + BYTE Reserved2[4]; + FILETIME ConnectTime; + FILETIME DisconnectTime; + FILETIME LastInputTime; + FILETIME LoginTime; + BYTE Reserved3[1096]; + FILETIME CurrentTime; +} WINSTATION_INFO, *PWINSTATION_INFO; + +typedef enum _WINSTATIONINFOCLASS { + WinStationInformation = 8 +} WINSTATIONINFOCLASS; + +typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW) + (HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG); + +typedef struct _WINSTATIONINFORMATIONW { + BYTE Reserved2[70]; + ULONG LogonId; + BYTE Reserved3[1140]; +} WINSTATIONINFORMATIONW, *PWINSTATIONINFORMATIONW; + +// mingw support: +// http://www.koders.com/c/fid7C02CAE627C526914CDEB427405B51DF393A5EFA.aspx +#ifndef _INC_WTSAPI +typedef struct _WTS_CLIENT_ADDRESS { + DWORD AddressFamily; // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC + BYTE Address[20]; // client network address +} WTS_CLIENT_ADDRESS, * PWTS_CLIENT_ADDRESS; + +HANDLE WINAPI WTSOpenServerA(IN LPSTR pServerName); + +VOID WINAPI WTSCloseServer(IN HANDLE hServer); +#endif + + +/* + * NtQueryInformationProcess code taken from + * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/ + * typedefs needed to compile against ntdll functions not exposted in the API + */ +typedef LONG NTSTATUS; + +typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)( + HANDLE ProcessHandle, + DWORD ProcessInformationClass, + PVOID ProcessInformation, + DWORD ProcessInformationLength, + PDWORD ReturnLength +); + +typedef NTSTATUS (NTAPI *_NtSetInformationProcess)( + HANDLE ProcessHandle, + DWORD ProcessInformationClass, + PVOID ProcessInformation, + DWORD ProcessInformationLength +); + +typedef struct _PROCESS_BASIC_INFORMATION { + PVOID Reserved1; + PVOID PebBaseAddress; + PVOID Reserved2[2]; + ULONG_PTR UniqueProcessId; + PVOID Reserved3; +} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; + +typedef enum _PROCESSINFOCLASS { + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + /* added after XP+ */ + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + ProcessIoPriority, + ProcessExecuteFlags, + ProcessResourceManagement, + ProcessCookie, + ProcessImageInformation, + MaxProcessInfoClass +} PROCESSINFOCLASS; http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.c ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.c b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.c new file mode 100644 index 0000000..a8a9de1 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.c @@ -0,0 +1,336 @@ +/* + * 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. + * + */ + +#ifndef UNICODE +#define UNICODE +#endif + +#include <Python.h> +#include <windows.h> +#include <stdio.h> +#include "process_handles.h" + +#ifndef NT_SUCCESS +#define NT_SUCCESS(x) ((x) >= 0) +#endif +#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 + +#define SystemHandleInformation 16 +#define ObjectBasicInformation 0 +#define ObjectNameInformation 1 +#define ObjectTypeInformation 2 + + +typedef LONG NTSTATUS; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)( + ULONG SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength +); + +typedef NTSTATUS (NTAPI *_NtDuplicateObject)( + HANDLE SourceProcessHandle, + HANDLE SourceHandle, + HANDLE TargetProcessHandle, + PHANDLE TargetHandle, + ACCESS_MASK DesiredAccess, + ULONG Attributes, + ULONG Options +); + +typedef NTSTATUS (NTAPI *_NtQueryObject)( + HANDLE ObjectHandle, + ULONG ObjectInformationClass, + PVOID ObjectInformation, + ULONG ObjectInformationLength, + PULONG ReturnLength +); + +typedef struct _SYSTEM_HANDLE { + ULONG ProcessId; + BYTE ObjectTypeNumber; + BYTE Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE, *PSYSTEM_HANDLE; + +typedef struct _SYSTEM_HANDLE_INFORMATION { + ULONG HandleCount; + SYSTEM_HANDLE Handles[1]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +typedef enum _POOL_TYPE { + NonPagedPool, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS +} POOL_TYPE, *PPOOL_TYPE; + +typedef struct _OBJECT_TYPE_INFORMATION { + UNICODE_STRING Name; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccess; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + USHORT MaintainTypeList; + POOL_TYPE PoolType; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + + +PVOID +GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName) +{ + return GetProcAddress(GetModuleHandleA(LibraryName), ProcName); +} + + +PyObject * +psutil_get_open_files(long pid, HANDLE processHandle) +{ + _NtQuerySystemInformation NtQuerySystemInformation = + GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); + _NtQueryObject NtQueryObject = + GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); + + NTSTATUS status; + PSYSTEM_HANDLE_INFORMATION handleInfo; + ULONG handleInfoSize = 0x10000; + ULONG i; + ULONG fileNameLength; + PyObject *filesList = Py_BuildValue("[]"); + PyObject *arg = NULL; + PyObject *fileFromWchar = NULL; + + if (filesList == NULL) + return NULL; + + handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); + if (handleInfo == NULL) { + Py_DECREF(filesList); + PyErr_NoMemory(); + return NULL; + } + + // NtQuerySystemInformation won't give us the correct buffer size, + // so we guess by doubling the buffer size. + while ((status = NtQuerySystemInformation( + SystemHandleInformation, + handleInfo, + handleInfoSize, + NULL + )) == STATUS_INFO_LENGTH_MISMATCH) + { + handleInfo = (PSYSTEM_HANDLE_INFORMATION) \ + realloc(handleInfo, handleInfoSize *= 2); + } + + // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH + if (!NT_SUCCESS(status)) { + Py_DECREF(filesList); + free(handleInfo); + return NULL; + } + + for (i = 0; i < handleInfo->HandleCount; i++) { + SYSTEM_HANDLE handle = handleInfo->Handles[i]; + HANDLE dupHandle = NULL; + HANDLE mapHandle = NULL; + POBJECT_TYPE_INFORMATION objectTypeInfo = NULL; + PVOID objectNameInfo; + UNICODE_STRING objectName; + ULONG returnLength; + DWORD error = 0; + fileFromWchar = NULL; + arg = NULL; + + // Check if this handle belongs to the PID the user specified. + if (handle.ProcessId != pid) + continue; + + // Skip handles with the following access codes as the next call + // to NtDuplicateObject() or NtQueryObject() might hang forever. + if ((handle.GrantedAccess == 0x0012019f) + || (handle.GrantedAccess == 0x001a019f) + || (handle.GrantedAccess == 0x00120189) + || (handle.GrantedAccess == 0x00100000)) { + continue; + } + + if (!DuplicateHandle(processHandle, + handle.Handle, + GetCurrentProcess(), + &dupHandle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS)) + { + //printf("[%#x] Error: %d \n", handle.Handle, GetLastError()); + continue; + } + + + mapHandle = CreateFileMapping(dupHandle, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + if (mapHandle == NULL && + (error == ERROR_INVALID_HANDLE || + error == ERROR_BAD_EXE_FORMAT)) { + CloseHandle(dupHandle); + //printf("CreateFileMapping Error: %d\n", error); + continue; + } + CloseHandle(mapHandle); + + // Query the object type. + objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectTypeInformation, + objectTypeInfo, + 0x1000, + NULL + ))) + { + free(objectTypeInfo); + CloseHandle(dupHandle); + continue; + } + + objectNameInfo = malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + 0x1000, + &returnLength + ))) + { + // Reallocate the buffer and try again. + objectNameInfo = realloc(objectNameInfo, returnLength); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + returnLength, + NULL + ))) + { + // We have the type name, so just display that. + /* + printf( + "[%#x] %.*S: (could not get name)\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer + ); + */ + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + continue; + + } + } + + // Cast our buffer into an UNICODE_STRING. + objectName = *(PUNICODE_STRING)objectNameInfo; + + // Print the information! + if (objectName.Length) + { + // The object has a name. Make sure it is a file otherwise + // ignore it + fileNameLength = objectName.Length / 2; + if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) { + // printf("%.*S\n", objectName.Length / 2, objectName.Buffer); + fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer, + fileNameLength); + if (fileFromWchar == NULL) + goto error_py_fun; +#if PY_MAJOR_VERSION >= 3 + arg = Py_BuildValue("N", + PyUnicode_AsUTF8String(fileFromWchar)); +#else + arg = Py_BuildValue("N", + PyUnicode_FromObject(fileFromWchar)); +#endif + if (!arg) + goto error_py_fun; + Py_XDECREF(fileFromWchar); + fileFromWchar = NULL; + if (PyList_Append(filesList, arg)) + goto error_py_fun; + Py_XDECREF(arg); + } + /* + printf( + "[%#x] %.*S: %.*S\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer, + objectName.Length / 2, + objectName.Buffer + ); + */ + } + else + { + // Print something else. + /* + printf( + "[%#x] %.*S: (unnamed)\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer + ); + */ + ;; + } + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + } + free(handleInfo); + CloseHandle(processHandle); + return filesList; + +error_py_fun: + Py_XDECREF(arg); + Py_XDECREF(fileFromWchar); + Py_DECREF(filesList); + return NULL; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.h new file mode 100644 index 0000000..342ce8f --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_handles.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> +#include <windows.h> + +PyObject* psutil_get_open_files(long pid, HANDLE processHandle); http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.c ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.c b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.c new file mode 100644 index 0000000..8298b16 --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.c @@ -0,0 +1,443 @@ +/* + * 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. + * + * Helper functions related to fetching process information. Used by + * _psutil_windows module methods. + */ + +#include <Python.h> +#include <windows.h> +#include <Psapi.h> +#include <tlhelp32.h> + +#include "security.h" +#include "process_info.h" +#include "ntextapi.h" +#include "../../_psutil_common.h" + + +/* + * A wrapper around OpenProcess setting NSP exception if process + * no longer exists. + * "pid" is the process pid, "dwDesiredAccess" is the first argument + * exptected by OpenProcess. + * Return a process handle or NULL. + */ +HANDLE +psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess) +{ + HANDLE hProcess; + DWORD processExitCode = 0; + + if (pid == 0) { + // otherwise we'd get NoSuchProcess + return AccessDenied(); + } + + hProcess = OpenProcess(dwDesiredAccess, FALSE, pid); + if (hProcess == NULL) { + if (GetLastError() == ERROR_INVALID_PARAMETER) { + NoSuchProcess(); + } + else { + PyErr_SetFromWindowsErr(0); + } + return NULL; + } + + // make sure the process is running + GetExitCodeProcess(hProcess, &processExitCode); + if (processExitCode == 0) { + NoSuchProcess(); + CloseHandle(hProcess); + return NULL; + } + return hProcess; +} + + +/* + * Same as psutil_handle_from_pid_waccess but implicitly uses + * PROCESS_QUERY_INFORMATION | PROCESS_VM_READ as dwDesiredAccess + * parameter for OpenProcess. + */ +HANDLE +psutil_handle_from_pid(DWORD pid) { + DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; + return psutil_handle_from_pid_waccess(pid, dwDesiredAccess); +} + + +// fetch the PEB base address from NtQueryInformationProcess() +PVOID +psutil_get_peb_address(HANDLE ProcessHandle) +{ + _NtQueryInformationProcess NtQueryInformationProcess = + (_NtQueryInformationProcess)GetProcAddress( + GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); + PROCESS_BASIC_INFORMATION pbi; + + NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL); + return pbi.PebBaseAddress; +} + + +DWORD * +psutil_get_pids(DWORD *numberOfReturnedPIDs) { + // Win32 SDK says the only way to know if our process array + // wasn't large enough is to check the returned size and make + // sure that it doesn't match the size of the array. + // If it does we allocate a larger array and try again + + // Stores the actual array + DWORD *procArray = NULL; + DWORD procArrayByteSz; + int procArraySz = 0; + + // Stores the byte size of the returned array from enumprocesses + DWORD enumReturnSz = 0; + + do { + procArraySz += 1024; + free(procArray); + procArrayByteSz = procArraySz * sizeof(DWORD); + procArray = malloc(procArrayByteSz); + if (procArray == NULL) { + PyErr_NoMemory(); + return NULL; + } + if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) { + free(procArray); + PyErr_SetFromWindowsErr(0); + return NULL; + } + } while (enumReturnSz == procArraySz * sizeof(DWORD)); + + // The number of elements is the returned size / size of each element + *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD); + + return procArray; +} + + +int +psutil_pid_is_running(DWORD pid) +{ + HANDLE hProcess; + DWORD exitCode; + + // Special case for PID 0 System Idle Process + if (pid == 0) { + return 1; + } + + if (pid < 0) { + return 0; + } + + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, pid); + if (NULL == hProcess) { + // invalid parameter is no such process + if (GetLastError() == ERROR_INVALID_PARAMETER) { + CloseHandle(hProcess); + return 0; + } + + // access denied obviously means there's a process to deny access to... + if (GetLastError() == ERROR_ACCESS_DENIED) { + CloseHandle(hProcess); + return 1; + } + + CloseHandle(hProcess); + PyErr_SetFromWindowsErr(0); + return -1; + } + + if (GetExitCodeProcess(hProcess, &exitCode)) { + CloseHandle(hProcess); + return (exitCode == STILL_ACTIVE); + } + + // access denied means there's a process there so we'll assume + // it's running + if (GetLastError() == ERROR_ACCESS_DENIED) { + CloseHandle(hProcess); + return 1; + } + + PyErr_SetFromWindowsErr(0); + CloseHandle(hProcess); + return -1; +} + + +int +psutil_pid_in_proclist(DWORD pid) +{ + DWORD *proclist = NULL; + DWORD numberOfReturnedPIDs; + DWORD i; + + proclist = psutil_get_pids(&numberOfReturnedPIDs); + if (NULL == proclist) { + return -1; + } + + for (i = 0; i < numberOfReturnedPIDs; i++) { + if (pid == proclist[i]) { + free(proclist); + return 1; + } + } + + free(proclist); + return 0; +} + + +// Check exit code from a process handle. Return FALSE on an error also +// XXX - not used anymore +int +handlep_is_running(HANDLE hProcess) +{ + DWORD dwCode; + if (NULL == hProcess) { + return 0; + } + if (GetExitCodeProcess(hProcess, &dwCode)) { + if (dwCode == STILL_ACTIVE) { + return 1; + } + } + return 0; +} + + +/* + * returns a Python list representing the arguments for the process + * with given pid or NULL on error. + */ +PyObject * +psutil_get_arg_list(long pid) +{ + int nArgs, i; + LPWSTR *szArglist = NULL; + HANDLE hProcess = NULL; + PVOID pebAddress; + PVOID rtlUserProcParamsAddress; + UNICODE_STRING commandLine; + WCHAR *commandLineContents = NULL; + PyObject *arg = NULL; + PyObject *arg_from_wchar = NULL; + PyObject *argList = NULL; + + hProcess = psutil_handle_from_pid(pid); + if (hProcess == NULL) { + return NULL; + } + + pebAddress = psutil_get_peb_address(hProcess); + + // get the address of ProcessParameters +#ifdef _WIN64 + if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32, + &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) +#else + if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10, + &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) +#endif + { + ////printf("Could not read the address of ProcessParameters!\n"); + PyErr_SetFromWindowsErr(0); + goto error; + } + + // read the CommandLine UNICODE_STRING structure +#ifdef _WIN64 + if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112, + &commandLine, sizeof(commandLine), NULL)) +#else + if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40, + &commandLine, sizeof(commandLine), NULL)) +#endif + { + PyErr_SetFromWindowsErr(0); + goto error; + } + + + // allocate memory to hold the command line + commandLineContents = (WCHAR *)malloc(commandLine.Length + 1); + if (commandLineContents == NULL) { + PyErr_NoMemory(); + goto error; + } + + // read the command line + if (!ReadProcessMemory(hProcess, commandLine.Buffer, + commandLineContents, commandLine.Length, NULL)) + { + PyErr_SetFromWindowsErr(0); + goto error; + } + + // Null-terminate the string to prevent wcslen from returning + // incorrect length the length specifier is in characters, but + // commandLine.Length is in bytes. + commandLineContents[(commandLine.Length / sizeof(WCHAR))] = '\0'; + + // attempt tp parse the command line using Win32 API, fall back + // on string cmdline version otherwise + szArglist = CommandLineToArgvW(commandLineContents, &nArgs); + if (NULL == szArglist) { + // failed to parse arglist + // encode as a UTF8 Python string object from WCHAR string + arg_from_wchar = PyUnicode_FromWideChar(commandLineContents, + commandLine.Length / 2); + if (arg_from_wchar == NULL) + goto error; +#if PY_MAJOR_VERSION >= 3 + argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar)); +#else + argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar)); +#endif + if (!argList) + goto error; + } + else { + // arglist parsed as array of UNICODE_STRING, so convert each to + // Python string object and add to arg list + argList = Py_BuildValue("[]"); + if (argList == NULL) + goto error; + for (i = 0; i < nArgs; i++) { + arg_from_wchar = NULL; + arg = NULL; + arg_from_wchar = PyUnicode_FromWideChar(szArglist[i], + wcslen(szArglist[i])); + if (arg_from_wchar == NULL) + goto error; +#if PY_MAJOR_VERSION >= 3 + arg = PyUnicode_FromObject(arg_from_wchar); +#else + arg = PyUnicode_AsUTF8String(arg_from_wchar); +#endif + if (arg == NULL) + goto error; + Py_XDECREF(arg_from_wchar); + if (PyList_Append(argList, arg)) + goto error; + Py_XDECREF(arg); + } + } + + if (szArglist != NULL) + LocalFree(szArglist); + free(commandLineContents); + CloseHandle(hProcess); + return argList; + +error: + Py_XDECREF(arg); + Py_XDECREF(arg_from_wchar); + Py_XDECREF(argList); + if (hProcess != NULL) + CloseHandle(hProcess); + if (commandLineContents != NULL) + free(commandLineContents); + if (szArglist != NULL) + LocalFree(szArglist); + return NULL; +} + + +#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes)) +#define PH_NEXT_PROCESS(Process) ( \ + ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \ + (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \ + ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \ + NULL) + +const int STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; +const int STATUS_BUFFER_TOO_SMALL = 0xC0000023L; + +/* + * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure + * fills the structure with process information. + * On success return 1, else 0 with Python exception already set. + */ +int +psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, + PVOID *retBuffer) +{ + static ULONG initialBufferSize = 0x4000; + NTSTATUS status; + PVOID buffer; + ULONG bufferSize; + PSYSTEM_PROCESS_INFORMATION process; + + // get NtQuerySystemInformation + typedef DWORD (_stdcall * NTQSI_PROC) (int, PVOID, ULONG, PULONG); + NTQSI_PROC NtQuerySystemInformation; + HINSTANCE hNtDll; + hNtDll = LoadLibrary(TEXT("ntdll.dll")); + NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress( + hNtDll, "NtQuerySystemInformation"); + + bufferSize = initialBufferSize; + buffer = malloc(bufferSize); + if (buffer == NULL) { + PyErr_NoMemory(); + goto error; + } + + while (TRUE) { + status = NtQuerySystemInformation(SystemProcessInformation, buffer, + bufferSize, &bufferSize); + + if (status == STATUS_BUFFER_TOO_SMALL || + status == STATUS_INFO_LENGTH_MISMATCH) + { + free(buffer); + buffer = malloc(bufferSize); + if (buffer == NULL) { + PyErr_NoMemory(); + goto error; + } + } + else { + break; + } + } + + if (status != 0) { + PyErr_Format(PyExc_RuntimeError, "NtQuerySystemInformation() failed"); + goto error; + } + + if (bufferSize <= 0x20000) { + initialBufferSize = bufferSize; + } + + process = PH_FIRST_PROCESS(buffer); + do { + if (process->UniqueProcessId == (HANDLE)pid) { + *retProcess = process; + *retBuffer = buffer; + return 1; + } + } while ( (process = PH_NEXT_PROCESS(process)) ); + + NoSuchProcess(); + goto error; + +error: + FreeLibrary(hNtDll); + if (buffer != NULL) + free(buffer); + return 0; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.h new file mode 100644 index 0000000..9544f5d --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/process_info.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <Python.h> +#include <windows.h> + +DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs); +HANDLE psutil_handle_from_pid(DWORD pid); +HANDLE psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess); +int psutil_handlep_is_running(HANDLE hProcess); +int psutil_pid_in_proclist(DWORD pid); +int psutil_pid_is_running(DWORD pid); +PVOID psutil_get_peb_address(HANDLE ProcessHandle); +PyObject* psutil_get_arg_list(long pid); http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.c ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.c b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.c new file mode 100644 index 0000000..a837dfe --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.c @@ -0,0 +1,238 @@ +/* + * 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. + * + * Security related functions for Windows platform (Set privileges such as + * SeDebug), as well as security helper functions. + */ + +#include <windows.h> +#include <Python.h> + + +/* + * Convert a process handle to a process token handle. + */ +HANDLE +psutil_token_from_handle(HANDLE hProcess) { + HANDLE hToken = NULL; + + if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) { + return PyErr_SetFromWindowsErr(0); + } + return hToken; +} + + +/* + * http://www.ddj.com/windows/184405986 + * + * There's a way to determine whether we're running under the Local System + * account. However (you guessed it), we have to call more Win32 functions to + * determine this. Backing up through the code listing, we need to make another + * call to GetTokenInformation, but instead of passing through the TOKEN_USER + * constant, we pass through the TOKEN_PRIVILEGES constant. This value returns + * an array of privileges that the account has in the environment. Iterating + * through the array, we call the function LookupPrivilegeName looking for the + * string �SeTcbPrivilege. If the function returns this string, then this + * account has Local System privileges + */ +int +psutil_has_system_privilege(HANDLE hProcess) { + DWORD i; + DWORD dwSize = 0; + DWORD dwRetval = 0; + TCHAR privName[256]; + DWORD dwNameSize = 256; + // PTOKEN_PRIVILEGES tp = NULL; + BYTE *pBuffer = NULL; + TOKEN_PRIVILEGES *tp = NULL; + HANDLE hToken = psutil_token_from_handle(hProcess); + + if (NULL == hToken) { + return -1; + } + + // call GetTokenInformation first to get the buffer size + if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) { + dwRetval = GetLastError(); + // if it failed for a reason other than the buffer, bail out + if (dwRetval != ERROR_INSUFFICIENT_BUFFER ) { + PyErr_SetFromWindowsErr(dwRetval); + return 0; + } + } + + // allocate buffer and call GetTokenInformation again + // tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize); + pBuffer = (BYTE *) malloc(dwSize); + if (pBuffer == NULL) { + PyErr_NoMemory(); + return -1; + } + + if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer, + dwSize, &dwSize)) + { + PyErr_SetFromWindowsErr(0); + free(pBuffer); + return -1; + } + + // convert the BYTE buffer to a TOKEN_PRIVILEGES struct pointer + tp = (TOKEN_PRIVILEGES *)pBuffer; + + // check all the privileges looking for SeTcbPrivilege + for (i = 0; i < tp->PrivilegeCount; i++) { + // reset the buffer contents and the buffer size + strcpy(privName, ""); + dwNameSize = sizeof(privName) / sizeof(TCHAR); + if (! LookupPrivilegeName(NULL, + &tp->Privileges[i].Luid, + (LPTSTR)privName, + &dwNameSize)) + { + PyErr_SetFromWindowsErr(0); + free(pBuffer); + return -1; + } + + // if we find the SeTcbPrivilege then it's a LocalSystem process + if (! lstrcmpi(privName, TEXT("SeTcbPrivilege"))) { + free(pBuffer); + return 1; + } + } + + free(pBuffer); + return 0; +} + + +BOOL +psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) +{ + TOKEN_PRIVILEGES tp; + LUID luid; + TOKEN_PRIVILEGES tpPrevious; + DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); + + if (!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; + + // first pass. get current privilege setting + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = 0; + + AdjustTokenPrivileges( + hToken, + FALSE, + &tp, + sizeof(TOKEN_PRIVILEGES), + &tpPrevious, + &cbPrevious + ); + + if (GetLastError() != ERROR_SUCCESS) return FALSE; + + // second pass. set privilege based on previous setting + tpPrevious.PrivilegeCount = 1; + tpPrevious.Privileges[0].Luid = luid; + + if (bEnablePrivilege) { + tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); + } + + else { + tpPrevious.Privileges[0].Attributes ^= + (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); + } + + AdjustTokenPrivileges( + hToken, + FALSE, + &tpPrevious, + cbPrevious, + NULL, + NULL + ); + + if (GetLastError() != ERROR_SUCCESS) return FALSE; + + return TRUE; +} + + +int +psutil_set_se_debug() +{ + HANDLE hToken; + if (! OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + FALSE, + &hToken) + ) { + if (GetLastError() == ERROR_NO_TOKEN) { + if (!ImpersonateSelf(SecurityImpersonation)) { + CloseHandle(hToken); + return 0; + } + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + FALSE, + &hToken) + ) { + RevertToSelf(); + CloseHandle(hToken); + return 0; + } + } + } + + // enable SeDebugPrivilege (open any process) + if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE)) { + RevertToSelf(); + CloseHandle(hToken); + return 0; + } + + RevertToSelf(); + CloseHandle(hToken); + return 1; +} + + +int +psutil_unset_se_debug() +{ + HANDLE hToken; + if (! OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + FALSE, + &hToken) + ) { + if (GetLastError() == ERROR_NO_TOKEN) { + if (! ImpersonateSelf(SecurityImpersonation)) { + return 0; + } + + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + FALSE, + &hToken) + ) + { + return 0; + } + } + } + + // now disable SeDebug + if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) { + return 0; + } + + CloseHandle(hToken); + return 1; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/a52f8a55/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.h ---------------------------------------------------------------------- diff --git a/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.h b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.h new file mode 100644 index 0000000..aa8a22a --- /dev/null +++ b/ambari-metrics/ambari-metrics-host-monitoring/src/main/python/psutil/psutil/arch/windows/security.h @@ -0,0 +1,17 @@ +/* + * 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. + * + * Security related functions for Windows platform (Set privileges such as + * SeDebug), as well as security helper functions. + */ + +#include <windows.h> + +BOOL psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege); +HANDLE psutil_token_from_handle(HANDLE hProcess); +int psutil_has_system_privilege(HANDLE hProcess); +int psutil_set_se_debug(); +int psutil_unset_se_debug(); +