use crate::{
debugfs::file_ops::FileOps,
prelude::*,
str::{
CStr,
CStrExt as _, },
sync::Arc,
};
use core::marker::PhantomData;
pub(crate) struct Entry<'a> {
entry: *mut bindings::dentry,
_parent: Option<Arc<Entry<'static>>>,
_phantom: PhantomData<&'a ()>,
}
unsafe impl Send for Entry<'_> {}
unsafe impl Sync for Entry<'_> {}
impl Entry<'static> {
pub(crate) fn dynamic_dir(name: &CStr, parent: Option<Arc<Self>>) -> Self {
let parent_ptr = match &parent {
Some(entry) => entry.as_ptr(),
None => core::ptr::null_mut(),
};
let entry = unsafe { bindings::debugfs_create_dir(name.as_char_ptr(), parent_ptr) };
Entry {
entry,
_parent: parent,
_phantom: PhantomData,
}
}
pub(crate) unsafe fn dynamic_file<T>(
name: &CStr,
parent: Arc<Self>,
data: &T,
file_ops: &'static FileOps<T>,
) -> Self {
let entry = unsafe {
bindings::debugfs_create_file_full(
name.as_char_ptr(),
file_ops.mode(),
parent.as_ptr(),
core::ptr::from_ref(data) as *mut c_void,
core::ptr::null(),
&**file_ops,
)
};
Entry {
entry,
_parent: Some(parent),
_phantom: PhantomData,
}
}
}
impl<'a> Entry<'a> {
pub(crate) fn dir(name: &CStr, parent: Option<&'a Entry<'_>>) -> Self {
let parent_ptr = match &parent {
Some(entry) => entry.as_ptr(),
None => core::ptr::null_mut(),
};
let entry = unsafe { bindings::debugfs_create_dir(name.as_char_ptr(), parent_ptr) };
Entry {
entry,
_parent: None,
_phantom: PhantomData,
}
}
pub(crate) fn file<T>(
name: &CStr,
parent: &'a Entry<'_>,
data: &'a T,
file_ops: &FileOps<T>,
) -> Self {
let entry = unsafe {
bindings::debugfs_create_file_full(
name.as_char_ptr(),
file_ops.mode(),
parent.as_ptr(),
core::ptr::from_ref(data) as *mut c_void,
core::ptr::null(),
&**file_ops,
)
};
Entry {
entry,
_parent: None,
_phantom: PhantomData,
}
}
}
impl Entry<'_> {
pub(crate) fn empty() -> Self {
Self {
entry: core::ptr::null_mut(),
_parent: None,
_phantom: PhantomData,
}
}
pub(crate) fn as_ptr(&self) -> *mut bindings::dentry {
self.entry
}
}
impl Drop for Entry<'_> {
fn drop(&mut self) {
unsafe { bindings::debugfs_remove(self.as_ptr()) }
}
}