update FSF address in COPYING and COPYING.LESSER
[python-kmod.git] / libkmod.c
index 0d16c76dc38004be74f35afa001db5789b6987bb..82f0de8b65fcda0925221df78404f74355a91276 100644 (file)
--- a/libkmod.c
+++ b/libkmod.c
@@ -23,130 +23,247 @@ typedef struct {
     struct kmod_ctx *ctx;
 } kmodobject;
 
-static PyTypeObject LibKmodType;
-
-static PyObject *LibKmodError;
+static PyTypeObject KmodObjType;
 
+static PyObject *KmodError;
 
 /* ----------------------------------------------------------------------
- * kmod object initialization/deallocation
+ * 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
-libkmod_init(kmodobject *self, PyObject *arg)
+kmod_obj_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
+    kmodobject *kmod = (kmodobject *)self;
     char *mod_dir = NULL;
 
-    if (!PyArg_ParseTuple(arg, "|s", &mod_dir))
+    if (!PyArg_ParseTuple(args, "|s", &mod_dir))
        return -1;
 
-    self->ctx = kmod_new(mod_dir, NULL);
-    if (!self->ctx) {
-        PyErr_SetFromErrno(PyExc_OSError);
+    /* 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
-libkmod_dealloc(kmodobject *self)
+kmod_obj_dealloc(PyObject *self)
 {
+    kmodobject *kmod = (kmodobject *)self;
+
+    kmod_unload_resources(kmod->ctx);
+
     /* if already closed, don't reclose it */
-    if (self->ctx != NULL){
-           kmod_unref(self->ctx);
+    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 *
-libkmod_library_get_version(kmodobject *self)
+kmod_obj_rmmod(PyObject *self, PyObject *args)
 {
-    return Py_BuildValue("s", "whatup dude v1.234");
+    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 Libkmod_methods[] = {
-    /* LVM methods */
-    { "getVersion",          (PyCFunction)libkmod_library_get_version, METH_NOARGS },
-    { NULL,             NULL}           /* sentinel */
+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 LibKmodType = {
+
+static PyTypeObject KmodObjType = {
     PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "kmod.kmod",             /*tp_name*/
-    sizeof(kmodobject),             /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)libkmod_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    0,                         /*tp_as_number*/
-    0,                         /*tp_as_sequence*/
-    0,                         /*tp_as_mapping*/
-    0,                         /*tp_hash */
-    0,                         /*tp_call*/
-    0,                         /*tp_str*/
-    0,                         /*tp_getattro*/
-    0,                         /*tp_setattro*/
-    0,                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
-    "Libkmod objects",           /* tp_doc */
-    0,                       /* tp_traverse */
-    0,                       /* tp_clear */
-    0,                       /* tp_richcompare */
-    0,                       /* tp_weaklistoffset */
-    0,                       /* tp_iter */
-    0,                       /* tp_iternext */
-    Libkmod_methods,             /* tp_methods */
-    0,             /* tp_members */
-    0,                         /* tp_getset */
-    0,                         /* tp_base */
-    0,                         /* tp_dict */
-    0,                         /* tp_descr_get */
-    0,                         /* tp_descr_set */
-    0,                         /* tp_dictoffset */
-    (initproc)libkmod_init,      /* tp_init */
-    0,                         /* tp_alloc */
-    0,
-    //(newfunc)Libkmod_new,                 /* tp_new */
+    .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
-initlibkmod(void)
+initkmod(void)
 {
     PyObject *m;
 
-    LibKmodType.tp_new = PyType_GenericNew;
-    if (PyType_Ready(&LibKmodType) < 0)
+    if (PyType_Ready(&KmodObjType) < 0)
         return;
 
-    m = Py_InitModule3("libkmod", Libkmod_methods, "Libkmod module");
-    if (m == NULL)
+    m = Py_InitModule3("kmod", kmod_lib_methods, "kmod module");
+    if (!m)
         return;
 
-    Py_INCREF(&LibKmodType);
-    PyModule_AddObject(m, "LibKmod", (PyObject *)&LibKmodType);
+    Py_INCREF(&KmodObjType);
+    PyModule_AddObject(m, "Kmod", (PyObject *)&KmodObjType);
 
-    LibKmodError = PyErr_NewException("Libkmod.LibKmodError",
-                                      NULL, NULL);
-    if (LibKmodError) {
+    KmodError = PyErr_NewException("kmod.KmodError",
+                                   NULL, NULL);
+    if (KmodError) {
         /* Each call to PyModule_AddObject decrefs it; compensate: */
-        Py_INCREF(LibKmodError);
-        Py_INCREF(LibKmodError);
-        PyModule_AddObject(m, "error", LibKmodError);
-        PyModule_AddObject(m, "LibKmodError", LibKmodError);
+        Py_INCREF(KmodError);
+        PyModule_AddObject(m, "KmodError", KmodError);
     }
-
 }
-