1use crate::errors::*;
2use crate::modules::{Module, ModuleIterator};
3use std::ffi::{CStr, CString, OsStr, OsString};
4use std::os::unix::ffi::OsStrExt;
5use std::path::Path;
6use std::{fmt, ptr};
7
8pub struct Context {
14 ctx: *mut kmod_sys::kmod_ctx,
15}
16
17impl Drop for Context {
18 fn drop(&mut self) {
19 trace!("dropping kmod: {:?}", self.ctx);
20 let _ = unsafe { kmod_sys::kmod_unref(self.ctx) };
21 }
22}
23
24impl Context {
25 #[inline]
31 pub fn new() -> Result<Context> {
32 let ctx = unsafe { kmod_sys::kmod_new(ptr::null(), ptr::null()) };
33 if ctx.is_null() {
34 Err(Error::NewCtx)
35 } else {
36 trace!("creating kmod: {:?}", ctx);
37 Ok(Context { ctx })
38 }
39 }
40
41 pub fn new_with_dirname(dirname: &Path) -> Result<Context> {
48 let dirname = CString::new(dirname.as_os_str().as_bytes())?;
49
50 let ctx = unsafe { kmod_sys::kmod_new(dirname.as_ptr(), ptr::null()) };
51
52 if ctx.is_null() {
53 Err(Error::NewCtx)
54 } else {
55 trace!("creating kmod: {:?}", ctx);
56 Ok(Context { ctx })
57 }
58 }
59
60 #[inline]
69 pub fn modules_loaded(&self) -> Result<ModuleIterator> {
70 let mut list = ptr::null::<kmod_sys::kmod_list>() as *mut kmod_sys::kmod_list;
71 let ret = unsafe { kmod_sys::kmod_module_new_from_loaded(self.ctx, &mut list) };
72
73 if ret < 0 {
74 Err(Error::LoadedModules)
75 } else {
76 trace!("kmod_module_new_from_loaded: {:?}", list);
77 Ok(ModuleIterator::new(list))
78 }
79 }
80
81 pub fn module_new_from_lookup<S: AsRef<OsStr>>(&self, alias: S) -> Result<ModuleIterator> {
93 let mut list = ptr::null::<kmod_sys::kmod_list>() as *mut kmod_sys::kmod_list;
94 let alias = CString::new(alias.as_ref().as_bytes())?;
95 let ret =
96 unsafe { kmod_sys::kmod_module_new_from_lookup(self.ctx, alias.as_ptr(), &mut list) };
97
98 if ret < 0 {
99 Err(Error::ModuleFromLookup)
100 } else {
101 trace!("kmod_module_new_from_lookup: {:?}", list);
102 Ok(ModuleIterator::new(list))
103 }
104 }
105
106 pub fn module_new_from_path<S: AsRef<OsStr>>(&self, filename: S) -> Result<Module> {
113 let mut module = ptr::null::<kmod_sys::kmod_module>() as *mut kmod_sys::kmod_module;
114
115 let filename = CString::new(filename.as_ref().as_bytes())?;
116 let ret = unsafe {
117 kmod_sys::kmod_module_new_from_path(self.ctx, filename.as_ptr(), &mut module)
118 };
119
120 if ret < 0 {
121 Err(Error::ModuleFromPath(errno::errno()))
122 } else {
123 trace!("kmod_module_new_from_path: {:?}", module);
124 Ok(Module::new(module))
125 }
126 }
127
128 pub fn module_new_from_name(&self, name: &str) -> Result<Module> {
135 let mut module = ptr::null::<kmod_sys::kmod_module>() as *mut kmod_sys::kmod_module;
136
137 let name = CString::new(name)?;
138 let ret =
139 unsafe { kmod_sys::kmod_module_new_from_name(self.ctx, name.as_ptr(), &mut module) };
140
141 if ret < 0 {
142 Err(Error::ModuleFromName)
143 } else {
144 trace!("kmod_module_new_from_name: {:?}", module);
145 Ok(Module::new(module))
146 }
147 }
148
149 pub fn dirname(&self) -> OsString {
156 use std::os::unix::ffi::OsStringExt;
157
158 let dirname = unsafe { kmod_sys::kmod_get_dirname(self.ctx) };
159 let dirname = unsafe { CStr::from_ptr(dirname) };
160 OsString::from_vec(dirname.to_bytes().to_vec())
161 }
162}
163
164impl fmt::Debug for Context {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 f.pad("Context { .. }")
167 }
168}