blob: dd82d9e654071343308816a9ffbe1c7cd1273a54 [file] [log] [blame]
/*
* Libkmod -- Python interface to kmod API.
*
* Copyright (C) 2012 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Andy Grover <agrover redhat com>
*
*/
#include <Python.h>
#include <libkmod.h>
typedef struct {
PyObject_HEAD
struct kmod_ctx *ctx;
} kmodobject;
static PyTypeObject KmodObjType;
static PyObject *KmodError;
/* ----------------------------------------------------------------------
* kmod toplevel module methods
*/
static PyObject *
kmod_library_get_version(PyObject *self, PyObject *unused_args)
{
return Py_BuildValue("s", "0.1");
}
/* ----------------------------------------------------------------------
* Kmod object initialization/deallocation
*/
static int
kmod_obj_init(PyObject *self, PyObject *args, PyObject *kwds)
{
kmodobject *kmod = (kmodobject *)self;
char *mod_dir = NULL;
if (!PyArg_ParseTuple(args, "|s", &mod_dir))
return -1;
/* init can be called multiple times */
if (kmod->ctx) {
kmod_unload_resources(kmod->ctx);
kmod_unref(kmod->ctx);
}
kmod->ctx = kmod_new(mod_dir, NULL);
if (!kmod->ctx) {
PyErr_SetString(KmodError, "Could not initialize");
return -1;
}
kmod_load_resources(kmod->ctx);
return 0;
}
static void
kmod_obj_dealloc(PyObject *self)
{
kmodobject *kmod = (kmodobject *)self;
kmod_unload_resources(kmod->ctx);
/* if already closed, don't reclose it */
if (kmod->ctx != NULL){
kmod_unref(kmod->ctx);
}
//self->ob_type->tp_free((PyObject*)self);
PyObject_Del(self);
}
/*
* list currently loaded modules and sizes
*/
static PyObject *
kmod_obj_loaded_modules(PyObject *self, PyObject *unused_args)
{
kmodobject *kmod = (kmodobject *)self;
struct kmod_list *list, *itr;
int err;
err = kmod_module_new_from_loaded(kmod->ctx, &list);
if (err < 0) {
PyErr_SetString(KmodError, "Could not get loaded modules");
return NULL;
}
PyObject *pylist = PyList_New(0);
if (!pylist) {
kmod_module_unref_list(list);
return PyErr_NoMemory();
}
/* refcountapallooza. */
kmod_list_foreach(itr, list) {
struct kmod_module *mod = kmod_module_get_module(itr);
const char *name = kmod_module_get_name(mod);
long size = kmod_module_get_size(mod);
PyObject *entry = Py_BuildValue("(sl)", name, size);
if (!entry) {
Py_DECREF(pylist);
kmod_module_unref(mod);
kmod_module_unref_list(list);
return NULL;
}
if (PyList_Append(pylist, entry) == -1) {
Py_DECREF(entry);
Py_DECREF(pylist);
kmod_module_unref(mod);
kmod_module_unref_list(list);
return NULL;
}
Py_DECREF(entry);
kmod_module_unref(mod);
}
kmod_module_unref_list(list);
return pylist;
}
static PyObject *
kmod_obj_modprobe(PyObject *self, PyObject *args)
{
kmodobject *kmod = (kmodobject *)self;
struct kmod_list *list = NULL, *itr;
struct kmod_module *mod;
char *alias_name;
unsigned int flags = KMOD_PROBE_APPLY_BLACKLIST;
int err;
if (!PyArg_ParseTuple(args, "s", &alias_name))
return NULL;
err = kmod_module_new_from_lookup(kmod->ctx, alias_name, &list);
if (err < 0) {
PyErr_SetString(KmodError, "Could not modprobe");
return NULL;
}
kmod_list_foreach(itr, list) {
mod = kmod_module_get_module(itr);
err = kmod_module_probe_insert_module(mod, flags,
NULL, NULL, NULL, NULL);
if (err < 0) {
if (err == -EEXIST) {
PyErr_SetString(KmodError, "Module already loaded");
goto err;
} else {
PyErr_SetString(KmodError, "Could not load module");
goto err;
}
}
kmod_module_unref(mod);
}
kmod_module_unref_list(list);
Py_INCREF(Py_None);
return Py_None;
err:
kmod_module_unref(mod);
kmod_module_unref_list(list);
return NULL;
}
static PyObject *
kmod_obj_rmmod(PyObject *self, PyObject *args)
{
kmodobject *kmod = (kmodobject *)self;
struct kmod_module *mod;
char *module_name;
int err;
if (!PyArg_ParseTuple(args, "s", &module_name))
return NULL;
err = kmod_module_new_from_name(kmod->ctx, module_name, &mod);
if (err < 0) {
PyErr_SetString(KmodError, "Could get module");
return NULL;
}
err = kmod_module_remove_module(mod, 0);
if (err < 0) {
PyErr_SetString(KmodError, "Could not remove module");
kmod_module_unref(mod);
return NULL;
}
kmod_module_unref(mod);
Py_INCREF(Py_None);
return Py_None;
}
/* ----------------------------------------------------------------------
* Method tables and other bureaucracy
*/
static PyMethodDef kmod_lib_methods[] = {
{"getVersion", kmod_library_get_version, METH_NOARGS },
{NULL, NULL} /* sentinel */
};
static PyMethodDef kmod_obj_methods[] = {
{"loaded_modules", kmod_obj_loaded_modules, METH_NOARGS,
"List loaded kernel modules, and their sizes"},
{"modprobe", kmod_obj_modprobe, METH_VARARGS,
"Load a kernel module"},
{"rmmod", kmod_obj_rmmod, METH_VARARGS,
"Unload a kernel module"},
{NULL, NULL} /* sentinel */
};
static PyTypeObject KmodObjType = {
PyObject_HEAD_INIT(NULL)
.tp_name = "kmod.Kmod",
.tp_basicsize = sizeof(kmodobject),
.tp_new = PyType_GenericNew,
.tp_init = kmod_obj_init,
.tp_dealloc = kmod_obj_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_doc = "kmod.Kmod object",
.tp_methods = kmod_obj_methods,
};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initkmod(void)
{
PyObject *m;
if (PyType_Ready(&KmodObjType) < 0)
return;
m = Py_InitModule3("kmod", kmod_lib_methods, "kmod module");
if (!m)
return;
Py_INCREF(&KmodObjType);
PyModule_AddObject(m, "Kmod", (PyObject *)&KmodObjType);
KmodError = PyErr_NewException("kmod.KmodError",
NULL, NULL);
if (KmodError) {
/* Each call to PyModule_AddObject decrefs it; compensate: */
Py_INCREF(KmodError);
PyModule_AddObject(m, "KmodError", KmodError);
}
}