#include <Python.h>
#include <stdbool.h>
-#include <sys/utsname.h>
/*
Big parts of this were taken from
*/
/* /sys paths */
-#define _PATH_SYS_SYSTEM "/sys/devices/system"
-#define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu"
#define _PATH_PROC_XEN "/proc/xen"
#define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
-#define _PATH_PROC_CPUINFO "/proc/cpuinfo"
#define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
/* virtualization types */
[HYPER_VMWARE] = "VMWare"
};
-/* CPU modes (bits) */
-enum {
- MODE_REAL = (1 << 1),
- MODE_TRANSPARENT = (1 << 2),
- MODE_LONG = (1 << 3)
-};
-
-/* global description */
-struct lscpu_desc {
- char *arch;
- char *vendor;
- char *family;
- char *model;
- char *virtflag; /* virtualization flag (vmx, svm) */
- int hyper; /* hypervisor vendor ID */
- int virtype; /* VIRT_PARA|FULL|NONE ? */
- char *mhz;
- char *stepping;
- char *bogomips;
- char *flags;
- int mode; /* rm, lm or/and tm */
-
- int ncpus; /* number of CPUs */
-};
-
struct hypervisor_desc {
int hyper; /* hypervisor vendor ID */
int virtype; /* VIRT_PARA|FULL|NONE ? */
static size_t sysrootlen;
static char pathbuf[PATH_MAX];
-static int maxcpus; /* size in bits of kernel cpu mask */
-static FILE *path_fopen(const char *mode, int exit_on_err, const char *path, ...)
- __attribute__ ((__format__ (__printf__, 3, 4)));
+static FILE *path_fopen(const char *mode, const char *path, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
static int path_exist(const char *path, ...)
__attribute__ ((__format__ (__printf__, 1, 2)));
}
static FILE *
-path_vfopen(const char *mode, int exit_on_error, const char *path, va_list ap)
+path_vfopen(const char *mode, const char *path, va_list ap)
{
- FILE *f;
const char *p = path_vcreate(path, ap);
- f = fopen(p, mode);
- if (!f && exit_on_error)
- PyErr_SetString(PyExc_Exception,
- (const char *)sprintf("error: cannot open %s", p));
- return f;
+ return fopen(p, mode);
}
static FILE *
-path_fopen(const char *mode, int exit_on_error, const char *path, ...)
+path_fopen(const char *mode, const char *path, ...)
{
FILE *fd;
va_list ap;
va_start(ap, path);
- fd = path_vfopen(mode, exit_on_error, path, ap);
+ fd = path_vfopen(mode, path, ap);
va_end(ap);
return fd;
}
-static int
-path_getnum(const char *path, ...)
-{
- FILE *fd;
- va_list ap;
- int result;
-
- va_start(ap, path);
- fd = path_vfopen("r", 1, path, ap);
- va_end(ap);
-
- if (fscanf(fd, "%d", &result) != 1) {
- if (ferror(fd))
- PyErr_SetString(PyExc_Exception, (const char *)sprintf("failed to read: %s", pathbuf));
- else
- PyErr_SetString(PyExc_Exception, (const char *)sprintf("parse error: %s", pathbuf));
- }
- fclose(fd);
- return result;
-}
-
static int
path_exist(const char *path, ...)
{
return access(p, F_OK) == 0;
}
-static char *
-xstrdup(const char *str)
-{
- char *s = strdup(str);
- if (!s)
- PyErr_SetString(PyExc_Exception, "error: strdup failed");
- return s;
-}
-
-/* Lookup a pattern and get the value from cpuinfo.
- * Format is:
- *
- * "<pattern> : <key>"
- */
-int lookup(char *line, char *pattern, char **value)
-{
- char *p, *v;
- int len = strlen(pattern);
-
- if (!*line)
- return 0;
-
- /* pattern */
- if (strncmp(line, pattern, len))
- return 0;
-
- /* white spaces */
- for (p = line + len; isspace(*p); p++);
-
- /* separator */
- if (*p != ':')
- return 0;
-
- /* white spaces */
- for (++p; isspace(*p); p++);
-
- /* value */
- if (!*p)
- return 0;
- v = p;
-
- /* end of value */
- len = strlen(line) - 1;
- for (p = line + len; isspace(*(p-1)); p--);
- *p = '\0';
-
- *value = xstrdup(v);
- return 1;
-}
-
-static void
-read_basicinfo(struct lscpu_desc *desc)
-{
- FILE *fp = path_fopen("r", 1, _PATH_PROC_CPUINFO);
- char buf[BUFSIZ];
- struct utsname utsbuf;
-
- /* architecture */
- if (uname(&utsbuf) == -1)
- PyErr_SetString(PyExc_Exception, "error: uname failed");
- desc->arch = xstrdup(utsbuf.machine);
-
- /* count CPU(s) */
- while(path_exist(_PATH_SYS_SYSTEM "/cpu/cpu%d", desc->ncpus))
- desc->ncpus++;
-
- /* details */
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- /* IA64 */
- if (lookup(buf, "vendor", &desc->vendor)) ;
- else if (lookup(buf, "vendor_id", &desc->vendor)) ;
- /* IA64 */
- else if (lookup(buf, "family", &desc->family)) ;
- else if (lookup(buf, "cpu family", &desc->family)) ;
- else if (lookup(buf, "model", &desc->model)) ;
- else if (lookup(buf, "stepping", &desc->stepping)) ;
- else if (lookup(buf, "cpu MHz", &desc->mhz)) ;
- else if (lookup(buf, "flags", &desc->flags)) ;
- else if (lookup(buf, "bogomips", &desc->bogomips)) ;
- else
- continue;
- }
-
- if (desc->flags) {
- snprintf(buf, sizeof(buf), " %s ", desc->flags);
- if (strstr(buf, " svm "))
- desc->virtflag = strdup("svm");
- else if (strstr(buf, " vmx "))
- desc->virtflag = strdup("vmx");
-
- if (strstr(buf, " rm "))
- desc->mode |= MODE_REAL;
- if (strstr(buf, " tm "))
- desc->mode |= MODE_TRANSPARENT;
- if (strstr(buf, " lm "))
- desc->mode |= MODE_LONG;
- }
-
- fclose(fp);
-
- if (path_exist(_PATH_SYS_SYSTEM "/cpu/kernel_max"))
- maxcpus = path_getnum(_PATH_SYS_SYSTEM "/cpu/kernel_max");
-
- else
- /* we are reading some /sys snapshot instead of the real /sys,
- * let's use any crazy number... */
- maxcpus = desc->ncpus > 2048 ? desc->ncpus : 2048;
-}
-
static int
has_pci_device(int vendor, int device)
{
int num, fn, ven, dev;
int res = 1;
- f = path_fopen("r", 0, _PATH_PROC_PCIDEVS);
+ f = path_fopen("r", _PATH_PROC_PCIDEVS);
if (!f)
return 0;
: "1" (op), "c"(0));
}
-static int
+static void
read_hypervisor_cpuid(struct hypervisor_desc *desc)
{
unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
#else /* ! __x86_64__ */
static void
-read_hypervisor_cpuid(struct lscpu_desc *desc)
+read_hypervisor_cpuid(struct hypervisor_desc *desc)
{
}
#endif
else if (path_exist(_PATH_PROC_XEN)) {
/* Xen para-virt or dom0 */
- FILE *fd = path_fopen("r", 0, _PATH_PROC_XENCAP);
+ FILE *fd = path_fopen("r", _PATH_PROC_XENCAP);
int dom0 = 0;
if (fd) {
return false;
}
-static PyObject *
-do_cpuinfo() {
- /*
- This function collects information about the CPU.
- */
- struct lscpu_desc _desc, *desc = &_desc;
- memset(desc, 0, sizeof(*desc));
-
- read_basicinfo(desc);
- read_hypervisor(desc);
-
- PyObject *o = NULL;
- PyObject *d = PyDict_New();
-
- /* Arch */
- PyDict_SetItemString(d, "arch", PyString_FromString(desc->arch));
-
- /* Vendor */
- PyDict_SetItemString(d, "vendor", PyString_FromString(desc->vendor));
-
- /* Family */
- PyDict_SetItemString(d, "family", PyString_FromString(desc->family));
-
- /* Model */
- PyDict_SetItemString(d, "model", PyString_FromString(desc->model));
-
- /* Virtualization flag */
- if (desc->virtflag) {
- o = PyString_FromString(desc->virtflag);
- } else {
- o = Py_None;
- }
- PyDict_SetItemString(d, "virtflag", o);
-
- /* Stepping */
- PyDict_SetItemString(d, "stepping", PyString_FromString(desc->stepping));
-
- /* MHz */
- PyDict_SetItemString(d, "mhz", PyString_FromString(desc->mhz));
-
- /* Bogomips */
- PyDict_SetItemString(d, "bogomips", PyString_FromString(desc->bogomips));
-
- /* Flags */
- PyDict_SetItemString(d, "flags", PyString_FromString(desc->flags));
-
- /* Mode */
- if (desc->mode & (MODE_REAL | MODE_TRANSPARENT | MODE_LONG)) {
- o = PyList_New(0);
-
- if (desc->mode & MODE_REAL) {
- PyList_Append(o, (PyObject *)PyInt_FromLong(16));
- }
- if (desc->mode & MODE_TRANSPARENT) {
- PyList_Append(o, (PyObject *)PyInt_FromLong(32));
- }
- if (desc->mode & MODE_LONG) {
- PyList_Append(o, (PyObject *)PyInt_FromLong(64));
- }
- PyDict_SetItemString(d, "mode", o);
- }
-
- /* Hypervisor */
- if (desc->hyper == HYPER_NONE) {
- o = Py_None;
- } else {
- o = PyString_FromString((const char *)hv_vendors[desc->hyper]);
- }
- PyDict_SetItemString(d, "hypervisor", o);
-
- /* Virtualization type */
- if (desc->virtype == VIRT_NONE) {
- o = Py_None;
- } else {
- o = PyString_FromString((const char *)virt_types[desc->virtype]);
- }
- PyDict_SetItemString(d, "virtype", o);
-
- /* Number of CPUs */
- PyDict_SetItemString(d, "ncpus", PyInt_FromLong(desc->ncpus));
-
- return d;
-}
-
static PyObject *
do_get_hypervisor() {
/*
}
static PyMethodDef fireinfoModuleMethods[] = {
- { "cpuinfo", (PyCFunction) do_cpuinfo, METH_NOARGS, NULL },
{ "get_hypervisor", (PyCFunction) do_get_hypervisor, METH_NOARGS, NULL },
{ "is_virtualized", (PyCFunction) do_is_virtualized, METH_NOARGS, NULL },
{ NULL, NULL, 0, NULL }