Files
lxdeviced/libcompat/udev/src/lib.rs
T
2026-09-07 03:49:15 +00:00

955 lines
25 KiB
Rust

use ipc::client::Client;
use rule::parser::{Str, When};
use rustc_hash::FxHashMap;
use std::{
ffi::{CStr, CString},
str::FromStr,
sync::atomic::{self, AtomicUsize},
};
#[derive(Debug)]
pub struct Udev {
client: Client,
userdata: *mut u8,
refcount: AtomicUsize,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_new() -> *mut Udev {
let Ok(client) = Client::connect() else {
return std::ptr::null_mut();
};
Box::into_raw(Box::new(Udev {
client,
userdata: std::ptr::null_mut(),
refcount: AtomicUsize::new(1),
}))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_ref(udev: *mut Udev) -> *mut Udev {
unsafe {
(*udev).refcount.fetch_add(1, atomic::Ordering::SeqCst);
}
udev
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_unref(udev: *mut Udev) -> *mut Udev {
unsafe {
let oldval = (*udev).refcount.fetch_sub(1, atomic::Ordering::SeqCst);
if oldval == 1 {
drop(Box::from_raw(udev));
std::ptr::null_mut()
} else {
udev
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_get_userdata(udev: *const Udev) -> *mut u8 {
unsafe { (*udev).userdata }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_set_userdata(udev: *mut Udev, userdata: *mut u8) {
unsafe {
(*udev).userdata = userdata;
}
}
#[derive(Debug)]
pub struct UdevListEntry {
key: CString,
value: CString,
next: Option<Box<UdevListEntry>>,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_list_entry_get_next(
entry: *const UdevListEntry,
) -> *const UdevListEntry {
unsafe {
(*entry)
.next
.as_ref()
.map(|x| &raw const **x)
.unwrap_or_default()
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_list_entry_get_by_name(
mut entry: *const UdevListEntry,
name: *const libc::c_char,
) -> *const UdevListEntry {
unsafe {
let name = CStr::from_ptr(name);
while !entry.is_null() {
if (*entry).key == name {
return entry;
}
entry = udev_list_entry_get_next(entry);
}
std::ptr::null()
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_list_entry_get_name(
entry: *const UdevListEntry,
) -> *const libc::c_char {
unsafe { (*entry).key.as_ptr() }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_list_entry_get_value(
entry: *const UdevListEntry,
) -> *const libc::c_char {
unsafe { (*entry).value.as_ptr() }
}
#[derive(Debug)]
pub struct UdevDevice {
refcount: AtomicUsize,
udev: *mut Udev,
properties: UdevListEntry,
syspath: Option<CString>,
devlinks: UdevListEntry,
tags: UdevListEntry,
sysattr: UdevListEntry,
action: Option<CString>,
seqnum: libc::c_ulonglong,
sysattr_cache: FxHashMap<CString, CString>,
}
impl UdevDevice {
fn new(udev: *mut Udev, properties: FxHashMap<String, String>) -> Self {
let syspath_str = properties.get("DEVPATH").map(|x| format!("/sys/{x}"));
let syspath = syspath_str
.as_deref()
.map(|x| CString::from_str(x).unwrap_or_default());
let devlinks = properties
.get("SYMLINKS")
.map(|x| x.as_str())
.unwrap_or_default()
.split('\0')
.filter(|x| !x.is_empty())
.map(|x| x.to_string())
.collect();
let devlinks = vec_to_list(&devlinks);
let tags = properties
.get("TAGS")
.map(|x| x.as_str())
.unwrap_or_default()
.split('\0')
.filter(|x| !x.is_empty())
.map(|x| x.to_string())
.collect();
let tags = vec_to_list(&tags);
let mut sysattr = Vec::new();
if let Some(syspath_str) = &syspath_str
&& let Ok(read_dir) = std::fs::read_dir(syspath_str)
{
for i in read_dir {
let Ok(i) = i else {
break;
};
sysattr.push(i.file_name().to_string_lossy().to_string());
}
}
let sysattr = vec_to_list(&sysattr);
Self {
refcount: AtomicUsize::new(1),
udev,
properties: *hashmap_to_list(&properties),
syspath,
devlinks: *devlinks,
tags: *tags,
sysattr: *sysattr,
action: None,
seqnum: 0,
sysattr_cache: Default::default(),
}
}
}
impl Drop for UdevDevice {
fn drop(&mut self) {
unsafe {
udev_unref(self.udev);
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_new_from_syspath(
_udev: *mut Udev,
_syspath: *const libc::c_char,
) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_new_from_devnum(
_udev: *mut Udev,
_type: libc::c_char,
_devnum: libc::dev_t,
) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_new_from_subsystem_sysname(
_udev: *mut Udev,
_subsystem: *const libc::c_char,
_sysname: *const libc::c_char,
) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_new_from_device_id(
_udev: *mut Udev,
_id: *const libc::c_char,
) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_new_from_environment(_udev: *mut Udev) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_parent(_dev: *mut UdevDevice) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_parent_with_subsystem_devtype(
_dev: *mut UdevDevice,
_subsystem: *const libc::c_char,
_devtype: *const libc::c_char,
) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_ref(dev: *mut UdevDevice) -> *mut UdevDevice {
unsafe {
(*dev).refcount.fetch_add(1, atomic::Ordering::SeqCst);
}
dev
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_unref(dev: *mut UdevDevice) -> *mut UdevDevice {
unsafe {
let oldval = (*dev).refcount.fetch_sub(1, atomic::Ordering::SeqCst);
if oldval == 1 {
drop(Box::from_raw(dev));
std::ptr::null_mut()
} else {
dev
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_udev(dev: *const UdevDevice) -> *mut Udev {
unsafe { (*dev).udev }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_devpath(dev: *const UdevDevice) -> *const libc::c_char {
unsafe { udev_device_get_property_value(dev, c"DEVPATH".as_ptr()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_subsystem(dev: *const UdevDevice) -> *const libc::c_char {
unsafe { udev_device_get_property_value(dev, c"SUBSYSTEM".as_ptr()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_devtype(dev: *const UdevDevice) -> *const libc::c_char {
unsafe { udev_device_get_property_value(dev, c"DEVTYPE".as_ptr()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_syspath(dev: *const UdevDevice) -> *const libc::c_char {
unsafe {
(*dev)
.syspath
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or_default()
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_sysname(dev: *const UdevDevice) -> *const libc::c_char {
unsafe {
if dev.is_null() {
return std::ptr::null();
}
let Some(syspath) = (*dev).syspath.as_ref() else {
return std::ptr::null();
};
let split_pos = syspath.as_bytes().iter().rposition(|x| *x == b'/');
let offset = split_pos.map(|x| x + 1).unwrap_or_default();
syspath.as_ptr().add(offset)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_sysnum(dev: *const UdevDevice) -> *const libc::c_char {
unsafe {
let mut sysname = udev_device_get_sysname(dev);
let mut found: *const libc::c_char = std::ptr::null();
if sysname.is_null() {
return std::ptr::null();
}
while *sysname != 0 {
if found.is_null() && (*sysname as char).is_ascii_digit() {
found = sysname;
}
if !found.is_null() && (*sysname as char).is_ascii_alphabetic() {
found = std::ptr::null();
}
sysname = sysname.add(1);
}
found
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_devnode(dev: *const UdevDevice) -> *const libc::c_char {
unsafe { udev_device_get_property_value(dev, c"DEVNODE".as_ptr()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_is_initialized(_: *const UdevDevice) -> libc::c_int {
1
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_devlinks_list_entry(
dev: *const UdevDevice,
) -> *const UdevListEntry {
unsafe { &raw const (*dev).devlinks }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_properties_list_entry(
dev: *const UdevDevice,
) -> *const UdevListEntry {
unsafe { &raw const (*dev).properties }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_tags_list_entry(
dev: *const UdevDevice,
) -> *const UdevListEntry {
unsafe { &raw const (*dev).tags }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_current_tags_list_entry(
dev: *const UdevDevice,
) -> *const UdevListEntry {
unsafe { &raw const (*dev).tags }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_sysattr_list_entry(
dev: *const UdevDevice,
) -> *const UdevListEntry {
unsafe { &raw const (*dev).sysattr }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_property_value(
dev: *const UdevDevice,
key: *const libc::c_char,
) -> *const libc::c_char {
unsafe { udev_list_entry_get_value(udev_list_entry_get_by_name(&(*dev).properties, key)) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_driver(dev: *mut UdevDevice) -> *const libc::c_char {
unsafe { udev_device_get_sysattr_value(dev, c"driver".as_ptr()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_devnum(dev: *const UdevDevice) -> libc::dev_t {
unsafe {
let devnode = udev_device_get_devnode(dev);
if devnode.is_null() {
return 0;
}
let mut statbuf = std::mem::zeroed();
let status = libc::lstat(devnode, &mut statbuf);
if status != 0 {
return 0;
}
statbuf.st_rdev
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_action(dev: *const UdevDevice) -> *const libc::c_char {
unsafe {
(*dev)
.action
.as_ref()
.map(|x| x.as_ptr())
.unwrap_or_default()
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_seqnum(dev: *const UdevDevice) -> libc::c_ulonglong {
unsafe { (*dev).seqnum }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_usec_since_initialized(
_: *const UdevDevice,
) -> libc::c_ulonglong {
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_get_sysattr_value(
dev: *mut UdevDevice,
sysattr: *const libc::c_char,
) -> *const libc::c_char {
unsafe {
let sysattr = CStr::from_ptr(sysattr);
let Ok(sysattr_str) = sysattr.to_str() else {
return std::ptr::null();
};
if let Some(val) = (*dev).sysattr_cache.get(sysattr) {
return val.as_ptr();
}
let Some(syspath) = (*dev).syspath.as_ref() else {
return std::ptr::null();
};
let Ok(mut path) = String::from_utf8(syspath.as_bytes().to_vec()) else {
return std::ptr::null();
};
path.push('/');
path.push_str(sysattr_str);
let Ok(data) = std::fs::read_to_string(path) else {
return std::ptr::null();
};
let Ok(data) = CString::from_str(&data) else {
return std::ptr::null();
};
let ptr = data.as_ptr();
(*dev).sysattr_cache.insert(CString::from(sysattr), data);
ptr
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_set_sysattr_value(
dev: *mut UdevDevice,
sysattr: *const libc::c_char,
value: *const libc::c_char,
) -> libc::c_int {
unsafe {
let dev = &mut *dev;
let sysattr = match CStr::from_ptr(sysattr).to_str() {
Ok(s) => s,
Err(_) => return -libc::EINVAL,
};
let value = match CStr::from_ptr(value).to_str() {
Ok(s) => s,
Err(_) => return -libc::EINVAL,
};
let syspath = match dev.syspath.as_ref() {
Some(p) => p,
None => return -libc::ENOENT,
};
let path = match syspath.to_str() {
Ok(p) => format!("{}/{}", p, sysattr),
Err(_) => return -libc::ENOENT,
};
match std::fs::write(&path, value) {
Ok(_) => {
if let Ok(cstr) = CString::new(value) {
let key = match CString::new(sysattr) {
Ok(k) => k,
Err(_) => return 0,
};
dev.sysattr_cache.insert(key, cstr);
}
0
}
Err(e) => match e.raw_os_error() {
Some(code) => -code,
None => -libc::EIO,
},
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_has_tag(
dev: *const UdevDevice,
tag: *const libc::c_char,
) -> libc::c_int {
unsafe {
(!udev_list_entry_get_by_name(udev_device_get_tags_list_entry(dev), tag).is_null()) as _
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_device_has_current_tag(
dev: *const UdevDevice,
tag: *const libc::c_char,
) -> libc::c_int {
unsafe {
(!udev_list_entry_get_by_name(udev_device_get_tags_list_entry(dev), tag).is_null()) as _
}
}
#[derive(Debug)]
pub struct UdevMonitor {
udev: *mut Udev,
refcount: AtomicUsize,
}
impl Drop for UdevMonitor {
fn drop(&mut self) {
unsafe {
udev_unref(self.udev);
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_ref(mon: *mut UdevMonitor) -> *mut UdevMonitor {
unsafe {
(*mon).refcount.fetch_add(1, atomic::Ordering::SeqCst);
}
mon
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_unref(mon: *mut UdevMonitor) -> *mut UdevMonitor {
unsafe {
let oldval = (*mon).refcount.fetch_sub(1, atomic::Ordering::SeqCst);
if oldval == 1 {
drop(Box::from_raw(mon));
std::ptr::null_mut()
} else {
mon
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_get_udev(mon: *const UdevMonitor) -> *mut Udev {
unsafe { (*mon).udev }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_new_from_netlink(
udev: *mut Udev,
name: *const libc::c_char,
) -> *mut UdevMonitor {
unsafe {
let name = CStr::from_ptr(name);
if name != c"udev" {
return std::ptr::null_mut();
}
Box::into_raw(Box::new(UdevMonitor {
udev,
refcount: AtomicUsize::new(1),
}))
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_enable_receiving(_: *const UdevMonitor) -> libc::c_int {
-libc::EPERM
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_set_receive_buffer_size(
_: *const UdevMonitor,
_: libc::c_int,
) -> libc::c_int {
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_get_fd(_: *const UdevMonitor) -> libc::c_int {
-1
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_receive_device(_: *const UdevMonitor) -> *mut UdevDevice {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_filter_add_match_subsystem_devtype(
_mon: *mut UdevMonitor,
_subsystem: *const libc::c_char,
_devtype: *const libc::c_char,
) -> libc::c_int {
-libc::EPERM
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_filter_add_match_tag(
_mon: *mut UdevMonitor,
_tag: *const libc::c_char,
) -> libc::c_int {
-libc::EPERM
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_filter_update(_mon: *mut UdevMonitor) -> libc::c_int {
-libc::EPERM
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_monitor_filter_remove(_mon: *mut UdevMonitor) -> libc::c_int {
-libc::EPERM
}
#[derive(Debug)]
pub struct UdevEnumerate {
udev: *mut Udev,
refcount: AtomicUsize,
filters: Vec<When>,
result: Option<UdevListEntry>,
}
impl Drop for UdevEnumerate {
fn drop(&mut self) {
unsafe {
udev_unref(self.udev);
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_ref(p: *mut UdevEnumerate) -> *mut UdevEnumerate {
unsafe {
(*p).refcount.fetch_add(1, atomic::Ordering::SeqCst);
}
p
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_unref(p: *mut UdevEnumerate) -> *mut UdevEnumerate {
unsafe {
let oldval = (*p).refcount.fetch_sub(1, atomic::Ordering::SeqCst);
if oldval == 1 {
drop(Box::from_raw(p));
std::ptr::null_mut()
} else {
p
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_get_udev(p: *mut UdevEnumerate) -> *mut Udev {
unsafe { (*p).udev }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_new(udev: *mut Udev) -> *mut UdevEnumerate {
Box::into_raw(Box::new(UdevEnumerate {
udev,
refcount: AtomicUsize::new(1),
filters: Vec::with_capacity(16),
result: None,
}))
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_subsystem(
udev_enumerate: *mut UdevEnumerate,
subsystem: *const libc::c_char,
) -> libc::c_int {
unsafe { udev_enumerate_match(udev_enumerate, "SUBSYSTEM", subsystem, false) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_nomatch_subsystem(
udev_enumerate: *mut UdevEnumerate,
subsystem: *const libc::c_char,
) -> libc::c_int {
unsafe { udev_enumerate_match(udev_enumerate, "SUBSYSTEM", subsystem, true) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_sysattr(
udev_enumerate: *mut UdevEnumerate,
sysattr: *const libc::c_char,
value: *const libc::c_char,
) -> libc::c_int {
unsafe {
let Ok(sysattr) = CStr::from_ptr(sysattr).to_str() else {
return -libc::EINVAL;
};
udev_enumerate_match(udev_enumerate, sysattr, value, false)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_nomatch_sysattr(
udev_enumerate: *mut UdevEnumerate,
sysattr: *const libc::c_char,
value: *const libc::c_char,
) -> libc::c_int {
unsafe {
let Ok(sysattr) = CStr::from_ptr(sysattr).to_str() else {
return -libc::EINVAL;
};
udev_enumerate_match(udev_enumerate, sysattr, value, true)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_property(
udev_enumerate: *mut UdevEnumerate,
property: *const libc::c_char,
value: *const libc::c_char,
) -> libc::c_int {
unsafe {
let Ok(property) = CStr::from_ptr(property).to_str() else {
return -libc::EINVAL;
};
udev_enumerate_match(udev_enumerate, property, value, false)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_sysname(
udev_enumerate: *mut UdevEnumerate,
sysname: *const libc::c_char,
) -> libc::c_int {
unsafe { udev_enumerate_match(udev_enumerate, "SYSNAME", sysname, false) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_tag(
udev_enumerate: *mut UdevEnumerate,
tag: *const libc::c_char,
) -> libc::c_int {
unsafe { udev_enumerate_match(udev_enumerate, "TAGS", tag, false) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_parent(
_: *mut UdevEnumerate,
_: *mut libc::c_void,
) -> libc::c_int {
-libc::EOPNOTSUPP
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_match_is_initialized(
_: *mut UdevEnumerate,
) -> libc::c_int {
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_add_syspath(
udev_enumerate: *mut UdevEnumerate,
syspath: *const libc::c_char,
) -> libc::c_int {
unsafe { udev_enumerate_match(udev_enumerate, "SYSPATH", syspath, false) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_scan_devices(
udev_enumerate: *mut UdevEnumerate,
) -> libc::c_int {
unsafe {
let udev = (*udev_enumerate).udev;
let when = When::All((*udev_enumerate).filters.clone());
let result = match (*udev).client.list_devices(when) {
Ok(x) => x,
Err(_) => return -libc::EPERM,
};
(*udev_enumerate).result = Some(*vec_to_list(&result));
0
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_scan_subsystems(
udev_enumerate: *mut UdevEnumerate,
) -> libc::c_int {
unsafe { udev_enumerate_scan_devices(udev_enumerate) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_enumerate_get_list_entry(
udev_enumerate: *mut UdevEnumerate,
) -> *mut UdevListEntry {
unsafe {
(*udev_enumerate)
.result
.as_mut()
.map(|x| &raw mut *x)
.unwrap_or_default()
}
}
unsafe fn udev_enumerate_match(
this: *mut UdevEnumerate,
key: &str,
data: *const libc::c_char,
not: bool,
) -> libc::c_int {
unsafe {
let Ok(data) = CStr::from_ptr(data).to_str() else {
return -libc::EINVAL;
};
let mut when = When::Match(Str::Direct(key.into()), Str::Direct(data.into()));
if not {
when = When::Not(Box::new(when));
}
(*this).filters.push(when);
0
}
}
#[derive(Debug)]
pub struct UdevQueue;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_ref(_p: *mut UdevQueue) -> *mut UdevQueue {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_unref(_p: *mut UdevQueue) -> *mut UdevQueue {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_get_udev(_udev_queue: *mut UdevQueue) -> *mut Udev {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_new(_udev: *mut Udev) -> *mut UdevQueue {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_get_udev_is_active(_udev_queue: *mut UdevQueue) -> libc::c_int {
-1
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_get_queue_is_empty(_udev_queue: *mut UdevQueue) -> libc::c_int {
-1
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_get_fd(_udev_queue: *mut UdevQueue) -> libc::c_int {
-1
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_queue_flush(_udev_queue: *mut UdevQueue) -> libc::c_int {
-1
}
#[derive(Debug)]
pub struct UdevHwdb;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_hwdb_new(_udev: *mut Udev) -> *mut UdevHwdb {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_hwdb_ref(_p: *mut UdevHwdb) -> *mut UdevHwdb {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_hwdb_unref(_p: *mut UdevHwdb) -> *mut UdevHwdb {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_hwdb_get_properties_list_entry(
_hwdb: *mut UdevHwdb,
_modalias: *const libc::c_char,
_flags: libc::c_uint,
) -> *mut UdevListEntry {
std::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn udev_util_encode_string(
s: *const std::ffi::c_char,
str_enc: *mut std::ffi::c_char,
len: usize,
) -> std::ffi::c_int {
unsafe {
libc::memcpy(str_enc.cast(), s.cast(), len);
}
len as _
}
fn hashmap_to_list(hashmap: &FxHashMap<String, String>) -> Box<UdevListEntry> {
let mut head = None;
let mut tail = &mut head;
for (key, value) in hashmap {
let key_cstr = CString::new(key.as_str()).unwrap();
let value_cstr = CString::new(value.as_str()).unwrap();
let entry = Box::new(UdevListEntry {
key: key_cstr,
value: value_cstr,
next: None,
});
*tail = Some(entry);
tail = &mut tail.as_mut().unwrap().next;
}
head.unwrap_or(Box::new(UdevListEntry {
key: CString::new("").unwrap(),
value: CString::new("").unwrap(),
next: None,
}))
}
fn vec_to_list(vec: &Vec<String>) -> Box<UdevListEntry> {
let mut head = None;
let mut tail = &mut head;
for s in vec {
let cstr = CString::new(s.as_str()).unwrap();
let entry = Box::new(UdevListEntry {
key: cstr,
value: CString::new("").unwrap(),
next: None,
});
*tail = Some(entry);
tail = &mut tail.as_mut().unwrap().next;
}
head.unwrap_or_else(|| {
Box::new(UdevListEntry {
key: CString::new("").unwrap(),
value: CString::new("").unwrap(),
next: None,
})
})
}