use std::ffi::CString;
use std::mem::MaybeUninit;
use std::path::Path;
use std::path::PathBuf;
use crate::core::device::Tag;
use crate::core::device::TagName;
use crate::ffi_utils;
pub fn find_device_name_from_tag(tag: &Tag) -> Option<PathBuf> {
if !matches!(tag.name(), TagName::Label) && !matches!(tag.name(), TagName::Uuid) {
return None;
}
let key_cstr = tag.name().to_c_string();
let value_cstr = tag.value_to_c_string().ok()?;
log::debug!(
"core::utils::evaluation::find_device_name_from_tag getting device name from tag: {:?}",
tag
);
let mut device_name_ptr = MaybeUninit::<*mut libc::c_char>::zeroed();
unsafe {
device_name_ptr.write(libblkid::blkid_evaluate_tag(
key_cstr.as_ptr(),
value_cstr.as_ptr(),
std::ptr::null_mut(),
));
}
match unsafe { device_name_ptr.assume_init() } {
ptr if ptr.is_null() => {
let err_msg = format!("failed to get device name from matching tag: {:?}", tag);
log::debug!("core::utils::evaluation::find_device_name_from_tag {}. libblkid::blkid_evaluate_tag returned a NULL pointer", err_msg);
None
}
ptr => {
let name = ffi_utils::const_c_char_array_to_path_buf(ptr);
log::debug!(
"core::utils::evaluation::find_device_name_from_tag found device named {:?}",
name
);
unsafe {
libc::free(ptr as *mut _);
}
Some(name)
}
}
}
#[doc(hidden)]
fn device_name_from_spec(spec: CString) -> Option<PathBuf> {
log::debug!(
"core::utils::evaluation::device_name_from_spec getting device name from spec {:?}",
spec
);
let mut device_name_ptr = MaybeUninit::<*mut libc::c_char>::zeroed();
unsafe {
device_name_ptr.write(libblkid::blkid_evaluate_spec(
spec.as_ptr(),
std::ptr::null_mut(),
));
};
match unsafe { device_name_ptr.assume_init() } {
ptr if ptr.is_null() => {
let err_msg = format!("failed to get device name from spec {:?}", spec);
log::debug!("core::utils::evaluation::device_name_from_spec {}. libblkid::blkid_evaluate_spec returned a NULL pointer", err_msg);
None
}
ptr => {
let name = ffi_utils::const_c_char_array_to_path_buf(ptr);
unsafe {
libc::free(ptr as *mut _);
}
log::debug!(
"core::utils::evaluation::device_name_from_spec found device named {:?}",
name
);
Some(name)
}
}
}
pub fn find_canonical_device_name_from_tag(tag: &Tag) -> Option<PathBuf> {
log::debug!(
"Cache::find_canonical_device_name_from_tag getting device name matching tag {:?}",
tag
);
if !matches!(tag.name(), TagName::Label) && !matches!(tag.name(), TagName::Uuid) {
return None;
}
let tag_cstr = tag.to_c_string().ok()?;
device_name_from_spec(tag_cstr)
}
pub fn find_canonical_device_name_from_path<T>(path: T) -> Option<PathBuf>
where
T: AsRef<Path>,
{
let path = path.as_ref();
log::debug!(
"core::utils::evaluation::find_canonical_device_name_from_path getting device name from path {:?}",
path
);
let path_cstr = ffi_utils::as_ref_path_to_c_string(path).ok()?;
device_name_from_spec(path_cstr)
}