Initial commit

Signed-off-by: sisungo <[email protected]>
This commit is contained in:
2026-09-01 13:01:13 +00:00
commit 5163bdc367
34 changed files with 2625 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
[package]
name = "udev"
version = "0.1.0"
edition = "2024"
[dependencies]
ipc = { path = "../../libs/ipc" }
libc = "0.2"
rustc-hash = "2"
rule = { path = "../../libs/rule" }
+124
View File
@@ -0,0 +1,124 @@
#ifndef _LIBUDEV_H_
#define _LIBUDEV_H_
#include <stddef.h>
#include <sys/stat.h>
#ifdef __cplusplus
extern "C" {
#endif
struct udev;
struct udev* udev_ref(struct udev *p);
struct udev* udev_unref(struct udev *udev);
struct udev* udev_new(void);
void* udev_get_userdata(struct udev *udev);
void udev_set_userdata(struct udev *udev, void *userdata);
struct udev_list_entry;
struct udev_list_entry* udev_list_entry_get_next(struct udev_list_entry *list_entry);
struct udev_list_entry* udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *name);
const char* udev_list_entry_get_name(struct udev_list_entry *list_entry);
const char* udev_list_entry_get_value(struct udev_list_entry *list_entry);
#define udev_list_entry_foreach(list_entry, first_entry) \
for (list_entry = first_entry; \
list_entry; \
list_entry = udev_list_entry_get_next(list_entry))
struct udev_device;
struct udev_device* udev_device_ref(struct udev_device *p);
struct udev_device* udev_device_unref(struct udev_device *p);
struct udev* udev_device_get_udev(struct udev_device *udev_device);
struct udev_device* udev_device_new_from_syspath(struct udev *udev, const char *syspath);
struct udev_device* udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum);
struct udev_device* udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname);
struct udev_device* udev_device_new_from_device_id(struct udev *udev, const char *id);
struct udev_device* udev_device_new_from_environment(struct udev *udev);
struct udev_device* udev_device_get_parent(struct udev_device *udev_device);
struct udev_device* udev_device_get_parent_with_subsystem_devtype(
struct udev_device *udev_device,
const char *subsystem,
const char *devtype);
const char* udev_device_get_devpath(struct udev_device *udev_device);
const char* udev_device_get_subsystem(struct udev_device *udev_device);
const char* udev_device_get_devtype(struct udev_device *udev_device);
const char* udev_device_get_syspath(struct udev_device *udev_device);
const char* udev_device_get_sysname(struct udev_device *udev_device);
const char* udev_device_get_sysnum(struct udev_device *udev_device);
const char* udev_device_get_devnode(struct udev_device *udev_device);
int udev_device_get_is_initialized(struct udev_device *udev_device);
struct udev_list_entry* udev_device_get_devlinks_list_entry(struct udev_device *udev_device);
struct udev_list_entry* udev_device_get_properties_list_entry(struct udev_device *udev_device);
struct udev_list_entry* udev_device_get_tags_list_entry(struct udev_device *udev_device);
struct udev_list_entry* udev_device_get_current_tags_list_entry(struct udev_device *udev_device);
struct udev_list_entry* udev_device_get_sysattr_list_entry(struct udev_device *udev_device);
const char* udev_device_get_property_value(struct udev_device *udev_device, const char *key);
const char* udev_device_get_driver(struct udev_device *udev_device);
dev_t udev_device_get_devnum(struct udev_device *udev_device);
const char* udev_device_get_action(struct udev_device *udev_device);
unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
const char* udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, const char *value);
int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
int udev_device_has_current_tag(struct udev_device *udev_device, const char *tag);
struct udev_monitor;
struct udev_monitor* udev_monitor_ref(struct udev_monitor *p);
struct udev_monitor* udev_monitor_unref(struct udev_monitor *p);
struct udev* udev_monitor_get_udev(struct udev_monitor *udev_monitor);
struct udev_monitor* udev_monitor_new_from_netlink(struct udev *udev, const char *name);
int udev_monitor_enable_receiving(struct udev_monitor *udev_monitor);
int udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, int size);
int udev_monitor_get_fd(struct udev_monitor *udev_monitor);
struct udev_device* udev_monitor_receive_device(struct udev_monitor *udev_monitor);
int udev_monitor_filter_add_match_subsystem_devtype(
struct udev_monitor *udev_monitor,
const char *subsystem,
const char *devtype);
int udev_monitor_filter_add_match_tag(struct udev_monitor *udev_monitor, const char *tag);
int udev_monitor_filter_update(struct udev_monitor *udev_monitor);
int udev_monitor_filter_remove(struct udev_monitor *udev_monitor);
struct udev_enumerate;
struct udev_enumerate* udev_enumerate_ref(struct udev_enumerate *p);
struct udev_enumerate* udev_enumerate_unref(struct udev_enumerate *p);
struct udev* udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate);
struct udev_enumerate* udev_enumerate_new(struct udev *udev);
int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem);
int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value);
int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value);
int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname);
int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag);
int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent);
int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate);
int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath);
int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate);
int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate);
struct udev_list_entry* udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate);
struct udev_queue;
struct udev_queue* udev_queue_ref(struct udev_queue *p);
struct udev_queue* udev_queue_unref(struct udev_queue *p);
struct udev* udev_queue_get_udev(struct udev_queue *udev_queue);
struct udev_queue* udev_queue_new(struct udev *udev);
int udev_queue_get_udev_is_active(struct udev_queue *udev_queue);
int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue);
int udev_queue_get_fd(struct udev_queue *udev_queue);
int udev_queue_flush(struct udev_queue *udev_queue);
struct udev_hwdb;
struct udev_hwdb* udev_hwdb_new(struct udev *udev);
struct udev_hwdb* udev_hwdb_ref(struct udev_hwdb *p);
struct udev_hwdb* udev_hwdb_unref(struct udev_hwdb *p);
struct udev_list_entry* udev_hwdb_get_properties_list_entry(struct udev_hwdb *hwdb, const char *modalias, unsigned flags);
int udev_util_encode_string(const char *str, char *str_enc, size_t len);
#ifdef __cplusplus
}
#endif
#endif
+901
View File
@@ -0,0 +1,901 @@
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_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,
})
})
}