1# Copyright (C) 2012 Red Hat, Inc.
2#                    W. Trevor King <wking@tremily.us>
3#
4# This file is part of python-kmod.
5#
6# python-kmod is free software: you can redistribute it and/or modify it under
7# the terms of the GNU Lesser General Public License version 2.1 as published
8# by the Free Software Foundation.
9#
10# python-kmod is distributed in the hope that it will be useful, but WITHOUT
11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
13# details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with python-kmod.  If not, see <http://www.gnu.org/licenses/>.
17
18"Define the Kmod class"
19
20cimport cython as _cython
21cimport _libkmod_h
22from error import KmodError as _KmodError
23cimport module as _module
24import module as _module
25cimport list as _list
26import list as _list
27
28
29cdef class Kmod (object):
30    "Wrap a struct kmod_ctx* item"
31    def __cinit__(self):
32        self._kmod_ctx = NULL
33        self.mod_dir = None
34
35    def __dealloc__(self):
36        self._cleanup()
37
38    def __init__(self, mod_dir=None):
39        self.set_mod_dir(mod_dir=mod_dir)
40
41    def set_mod_dir(self, mod_dir=None):
42        self.mod_dir = mod_dir
43        self._setup()
44
45    def _setup(self):
46        cdef char *mod_dir = NULL
47        self._cleanup()
48        if self.mod_dir:
49            mod_dir = self.mod_dir
50        self._kmod_ctx = _libkmod_h.kmod_new(mod_dir, NULL);
51        if self._kmod_ctx is NULL:
52            raise _KmodError('Could not initialize')
53        _libkmod_h.kmod_load_resources(self._kmod_ctx)
54
55    def _cleanup(self):
56        if self._kmod_ctx is not NULL:
57            _libkmod_h.kmod_unload_resources(self._kmod_ctx);
58            self._kmod_ctx = NULL
59
60    def loaded(self):
61        "iterate through currently loaded modules"
62        cdef _list.ModList ml = _list.ModList()
63        cdef _list.ModListItem mli
64        err = _libkmod_h.kmod_module_new_from_loaded(self._kmod_ctx, &ml.list)
65        if err < 0:
66            raise _KmodError('Could not get loaded modules')
67        for item in ml:
68            mli = <_list.ModListItem> item
69            mod = _module.Module()
70            mod.from_mod_list_item(item)
71            yield mod
72
73    def lookup(self, alias_name, flags=_libkmod_h.KMOD_PROBE_APPLY_BLACKLIST):
74        "iterate through modules matching `alias_name`"
75        cdef _list.ModList ml = _list.ModList()
76        cdef _list.ModListItem mli
77        if hasattr(alias_name, 'encode'):
78            alias_name = alias_name.encode('ascii')
79        err = _libkmod_h.kmod_module_new_from_lookup(
80            self._kmod_ctx, alias_name, &ml.list)
81        if err < 0:
82            raise _KmodError('Could not modprobe')
83        for item in ml:
84            mli = <_list.ModListItem> item
85            mod = _module.Module()
86            mod.from_mod_list_item(item)
87            yield mod
88
89    @_cython.always_allow_keywords(True)
90    def module_from_name(self, name):
91        cdef _module.Module mod = _module.Module()
92        if hasattr(name, 'encode'):
93            name = name.encode('ascii')
94        err = _libkmod_h.kmod_module_new_from_name(
95            self._kmod_ctx, name, &mod.module)
96        if err < 0:
97            raise _KmodError('Could not get module')
98        return mod
99
100    def list(self):
101        "iterate through currently loaded modules and sizes"
102        for mod in self.loaded():
103            yield (mod.name, mod.size)
104
105    def modprobe(self, name, quiet=False, *args, **kwargs):
106        """
107        Load a module (or alias) and all modules on which it depends.
108        The 'quiet' option defaults to False; set to True to mimic the behavior
109        of the '--quiet' commandline option.
110        """
111        mods = list(self.lookup(alias_name=name))
112
113        if not mods and not quiet:
114            raise _KmodError('Could not modprobe %s' % name)
115
116        for mod in mods:
117            mod.insert(*args, **kwargs)
118
119    def rmmod(self, module_name, *args, **kwargs):
120       """
121       remove module from current tree
122       e.g. km.rmmod("thinkpad_acpi")
123       """
124       mod = self.module_from_name(name=module_name)
125       mod.remove(*args, **kwargs)
126