From 21349c40b94fa5c8fa37b2046054ab165997c196 Mon Sep 17 00:00:00 2001 From: Johannes Leupolz Date: Wed, 17 Dec 2025 22:40:08 +0000 Subject: [PATCH] Improved action handlers; now also use anyhow --- vuinputd/src/actions/action.rs | 18 ++++++++--- vuinputd/src/actions/handle_action.rs | 30 ++++++++++++++++--- ...{mknod_input_device.rs => input_device.rs} | 14 +++++---- vuinputd/src/actions/mod.rs | 2 +- vuinputd/src/jobs/inject_in_container_job.rs | 2 +- .../src/jobs/remove_from_container_job.rs | 2 +- 6 files changed, 51 insertions(+), 17 deletions(-) rename vuinputd/src/actions/{mknod_input_device.rs => input_device.rs} (88%) diff --git a/vuinputd/src/actions/action.rs b/vuinputd/src/actions/action.rs index 6939e82..ba2a6f7 100644 --- a/vuinputd/src/actions/action.rs +++ b/vuinputd/src/actions/action.rs @@ -2,6 +2,8 @@ // // Author: Johannes Leupolz +use std::collections::HashMap; + use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -12,12 +14,20 @@ pub enum Action { path: String, major: u32, minor: u32, - mode: u32, }, - #[serde(rename = "announce-via-netlink")] - AnnounceViaNetlink { message: String }, + #[serde(rename = "emit-udev-event")] + EmitUdevEvent { + netlink_message: HashMap, + runtime_data: Option, + major: u32, + minor: u32, + }, #[serde(rename = "remove-device")] - RemoveDevice { path: String }, + RemoveDevice { + path: String, + major: u32, + minor: u32, + }, } diff --git a/vuinputd/src/actions/handle_action.rs b/vuinputd/src/actions/handle_action.rs index 10f12e2..61d6947 100644 --- a/vuinputd/src/actions/handle_action.rs +++ b/vuinputd/src/actions/handle_action.rs @@ -3,6 +3,9 @@ // Author: Johannes Leupolz use super::action::Action; +use super::input_device; +use super::netlink_message; +use super::runtime_data; pub fn handle_cli_action(json: String) -> i32 { let action: Action = serde_json::from_str(&json).expect("invalid action JSON"); @@ -12,10 +15,29 @@ pub fn handle_cli_action(json: String) -> i32 { 0 } -fn handle_action(action: Action) -> Result<(), String> { +fn handle_action(action: Action) -> anyhow::Result<()> { match action { - Action::MknodDevice { .. } => Ok(()), - Action::AnnounceViaNetlink { .. } => Ok(()), - Action::RemoveDevice { .. } => Ok(()), + Action::MknodDevice { path, major, minor } => { + input_device::ensure_input_device(path, major.into(), minor.into())?; + Ok(()) + } + Action::EmitUdevEvent { + netlink_message, + runtime_data, + major, + minor, + } => { + netlink_message::send_udev_monitor_message_with_properties(netlink_message); + runtime_data::ensure_udev_structure()?; + match runtime_data { + Some(data) => runtime_data::write_udev_data(&data, major.into(), minor.into())?, + None => runtime_data::delete_udev_data(major.into(), minor.into())?, + } + Ok(()) + } + Action::RemoveDevice { path, major, minor } => { + input_device::remove_input_device(path, major.into(), minor.into())?; + Ok(()) + } } } diff --git a/vuinputd/src/actions/mknod_input_device.rs b/vuinputd/src/actions/input_device.rs similarity index 88% rename from vuinputd/src/actions/mknod_input_device.rs rename to vuinputd/src/actions/input_device.rs index 02fc4bd..a01efa0 100644 --- a/vuinputd/src/actions/mknod_input_device.rs +++ b/vuinputd/src/actions/input_device.rs @@ -2,13 +2,13 @@ // // Author: Johannes Leupolz +use anyhow::anyhow; use nix::sys::stat::{makedev, mknod, stat, Mode, SFlag}; -use std::error::Error; use std::fs; use std::os::unix::fs::PermissionsExt; use std::path::Path; -pub fn ensure_input_device(dev_path: String, major: u64, minor: u64) -> Result<(), Box> { +pub fn ensure_input_device(dev_path: String, major: u64, minor: u64) -> anyhow::Result<()> { let input_dir = Path::new("/dev/input"); // Create directory like `mkdir -p` if !input_dir.exists() { @@ -70,23 +70,25 @@ pub fn ensure_input_device(dev_path: String, major: u64, minor: u64) -> Result<( Ok(()) } -pub fn remove_input_device(dev_path: String, major: u64, minor: u64) -> Result<(), Box> { +pub fn remove_input_device(dev_path: String, major: u64, minor: u64) -> anyhow::Result<()> { let path = Path::new(&dev_path); let expected_dev = makedev(major, minor); // --- Step 1: Ensure it is the correct device --- if !path.exists() { - return Err("Device does not exist".into()); + return Err(anyhow!("Device does not exist")); } match stat(path) { Ok(st) => { let is_char = (st.st_mode & libc::S_IFMT as u32) == libc::S_IFCHR as u32; let dev_ok = st.st_rdev == expected_dev; if !(is_char && dev_ok) { - return Err("Device that should be deleted has wrong major and minor".into()); + return Err(anyhow!( + "Device that should be deleted has wrong major and minor" + )); } } - Err(_x) => return Err("Could not execute stat on device file".into()), + Err(_x) => return Err(anyhow!("Could not execute stat on device file")), } let _ = fs::remove_file(path); diff --git a/vuinputd/src/actions/mod.rs b/vuinputd/src/actions/mod.rs index af3b886..a5e98d7 100644 --- a/vuinputd/src/actions/mod.rs +++ b/vuinputd/src/actions/mod.rs @@ -4,6 +4,6 @@ pub mod action; pub mod handle_action; -pub mod mknod_input_device; +pub mod input_device; pub mod netlink_message; pub mod runtime_data; diff --git a/vuinputd/src/jobs/inject_in_container_job.rs b/vuinputd/src/jobs/inject_in_container_job.rs index ae3067b..0d9f83c 100644 --- a/vuinputd/src/jobs/inject_in_container_job.rs +++ b/vuinputd/src/jobs/inject_in_container_job.rs @@ -15,7 +15,7 @@ use log::debug; use crate::{ actions::{ - mknod_input_device::ensure_input_device, + input_device::ensure_input_device, netlink_message::send_udev_monitor_message_with_properties, runtime_data::{ensure_udev_structure, read_udev_data, write_udev_data}, }, diff --git a/vuinputd/src/jobs/remove_from_container_job.rs b/vuinputd/src/jobs/remove_from_container_job.rs index 48d23d2..990f9c9 100644 --- a/vuinputd/src/jobs/remove_from_container_job.rs +++ b/vuinputd/src/jobs/remove_from_container_job.rs @@ -12,7 +12,7 @@ use log::debug; use crate::{ actions::{ - mknod_input_device::remove_input_device, + input_device::remove_input_device, netlink_message::send_udev_monitor_message_with_properties, runtime_data::delete_udev_data, }, job_engine::job::{Job, JobTarget},