diff --git a/Cargo.lock b/Cargo.lock index a0a10a9..82cc000 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,11 +366,11 @@ dependencies = [ "humantime", "log", "rustix", + "thiserror", "tokio", "tokio-stream", "tokio-util", "udev", - "unescape", "walkdir", ] @@ -1370,12 +1370,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "unescape" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" - [[package]] name = "unicode-bidi" version = "0.3.15" diff --git a/Cargo.toml b/Cargo.toml index f7d2f1d..a3c755f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,11 @@ clap = { version = "4", features = ["default", "derive"] } clap-verbosity-flag = "2" humantime = "2" bytes = "1" +thiserror = "1" tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" tokio-util = { version = "0.7", features = ["full"] } async-stream = "0.3" -unescape = "0.1" udev = "0.8" bollard = "0.16" futures = "0.3" diff --git a/src/dev/device.rs b/src/dev/device.rs index 3f2c55c..256d533 100644 --- a/src/dev/device.rs +++ b/src/dev/device.rs @@ -42,7 +42,7 @@ impl Device { }) .or_else(|| { let vendor = self.device.property_value("ID_VENDOR_ENC")?.to_str()?; - let vendor = unescape::unescape(vendor)?; + let vendor = crate::util::escape::unescape_devnode(vendor).ok()?; Some(vendor) })?; @@ -57,7 +57,7 @@ impl Device { }) .or_else(|| { let model = self.device.property_value("ID_MODEL_ENC")?.to_str()?; - let model = unescape::unescape(model)?; + let model = crate::util::escape::unescape_devnode(model).ok()?; Some(model) })?; diff --git a/src/util/escape.rs b/src/util/escape.rs new file mode 100644 index 0000000..6da4ec9 --- /dev/null +++ b/src/util/escape.rs @@ -0,0 +1,32 @@ +#[derive(thiserror::Error, Debug)] +#[error("Invalid escape sequence")] +pub struct InvalidEscapeError; + +/// Unescape a udev-escaped devnode name. +pub fn unescape_devnode(escaped: &str) -> Result { + let mut result = String::with_capacity(escaped.len()); + let mut iter = escaped.chars(); + + while let Some(c) = iter.next() { + if c != '\\' { + result.push(c); + continue; + } + + // Udev escaped devnode names only use hexadecimal escapes, so we only need to handle those. + if iter.next() != Some('x') { + return Err(InvalidEscapeError); + } + + let hex = iter.as_str().get(..2).ok_or(InvalidEscapeError)?; + result.push( + u8::from_str_radix(hex, 16) + .map_err(|_| InvalidEscapeError)? + .into(), + ); + iter.next(); + iter.next(); + } + + Ok(result) +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 56c9fb4..53a58f8 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1 +1,2 @@ +pub mod escape; pub mod tty_mode_guard;