From 9d4bbb6e9ecc66b589c8d473e10d16c54782a46b Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 19 Aug 2026 17:27:50 -0300 Subject: [PATCH 1/6] fix: cloud-sdk: compute the download progress with integer arithmetic The progress counter accumulated a `f32` percentage, one addition per chunk, and then cast the result back to `usize`. The rounding error grew with the number of chunks, so a complete download reported 99% instead of 100%. The cast also triggered `cast_possible_truncation`, `cast_sign_loss`, and `cast_precision_loss` under `clippy::pedantic`. Track the number of written bytes as a `u64` and derive the percentage from the total on each chunk. The result is exact and no cast remains. The log normalization in the tests accepted two digits only, which was enough while the counter never reached 100. Widen it to three digits and normalize the snapshot lines that recorded the literal `100%`. --- updatehub-cloud-sdk/src/client.rs | 13 +++++++------ updatehub/tests/common.rs | 2 +- updatehub/tests/successful_integration_test.rs | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/updatehub-cloud-sdk/src/client.rs b/updatehub-cloud-sdk/src/client.rs index 48c5aa18..b2544766 100644 --- a/updatehub-cloud-sdk/src/client.rs +++ b/updatehub-cloud-sdk/src/client.rs @@ -35,21 +35,22 @@ where return Err(Error::InvalidStatusResponse(resp.status())); } - let mut written: f32 = 0.; + let mut written: u64 = 0; let mut threshold = 10; let length = match resp.headers().get(header::CONTENT_LENGTH) { - Some(v) => usize::from_str(v.to_str()?)?, + Some(v) => u64::from_str(v.to_str()?)?, None => 0, }; while let Some(chunk) = resp.chunk().await? { - let read = chunk.len(); + let read = chunk.len() as u64; handle.write_all(&chunk).await?; if length > 0 { - written += read as f32 / (length as f32 / 100.); - if written as usize >= threshold { + written += read; + let percent = written * 100 / length; + if percent >= threshold { threshold += 20; - debug!("{}% of the file has been downloaded", std::cmp::min(written as usize, 100)); + debug!("{}% of the file has been downloaded", std::cmp::min(percent, 100)); } } } diff --git a/updatehub/tests/common.rs b/updatehub/tests/common.rs index 3fb835bf..d704ff14 100644 --- a/updatehub/tests/common.rs +++ b/updatehub/tests/common.rs @@ -383,7 +383,7 @@ pub fn rewrite_log_output(s: String) -> (String, String) { let time_re = Regex::new(r#"(\d{5}) seconds"#).unwrap(); let trce_re = Regex::new(r" TRCE.*").unwrap(); let debg_re = Regex::new(r" DEBG.*").unwrap(); - let download_re = Regex::new(r"DEBG (\d{2})%").unwrap(); + let download_re = Regex::new(r"DEBG (\d{1,3})%").unwrap(); let s = server_address_re.replace_all(&s, "http://127.0.0.1:[port]"); let s = version_re.replace_all(&s, "Agent "); diff --git a/updatehub/tests/successful_integration_test.rs b/updatehub/tests/successful_integration_test.rs index 77185beb..68788a75 100644 --- a/updatehub/tests/successful_integration_test.rs +++ b/updatehub/tests/successful_integration_test.rs @@ -268,7 +268,7 @@ fn correct_config_update_polling() { DEBG starting download of: testfile (23c3c412177bd37b9b61bf4738b18dc1fe003811c2583a14d2d9952d8b6a75b4) DEBG % of the file has been downloaded DEBG % of the file has been downloaded - DEBG 100% of the file has been downloaded + DEBG % of the file has been downloaded TRCE starting to handle 'validation' state INFO no signature key available on device, ignoring signature validation TRCE starting to handle 'install' state @@ -297,7 +297,7 @@ fn correct_config_update_polling() { DEBG starting download of: testfile (23c3c412177bd37b9b61bf4738b18dc1fe003811c2583a14d2d9952d8b6a75b4) DEBG % of the file has been downloaded DEBG % of the file has been downloaded - DEBG 100% of the file has been downloaded + DEBG % of the file has been downloaded TRCE starting to handle 'validation' state INFO no signature key available on device, ignoring signature validation TRCE starting to handle 'install' state From e17ef7d873a4cc4326eb6063c3cbd290c8ccde30 Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 19 Aug 2026 17:27:57 -0300 Subject: [PATCH 2/6] refactor: remove the lossy casts and the implicit clones `clippy::pedantic` reports every `as` cast that can truncate or lose the sign. The remaining cases convert a block count or a buffer size, which a 32-bit target can truncate without any sign of failure. Replace each cast with `try_from`: - `Count::Limited` holds an `isize` that the deserializer keeps at zero or above, so a negative value can only come from code. Map it to zero, which copies nothing, instead of a very large block count. - `Pattern::buffer_size` is a `u64` read buffer capacity. Clamp it to `usize::MAX`. - The test helpers panic on a value that does not fit, because the test itself supplies it. Also replace `to_owned` and an assignment of a clone with `clone` and `clone_from`, and drop a `to_vec` call on a value that is already a `Vec`. --- updatehub-cloud-sdk/src/api.rs | 2 +- updatehub/src/object/installer/mod.rs | 3 ++- updatehub/src/object/installer/raw.rs | 13 ++++++++----- updatehub/src/states/download.rs | 2 +- updatehub/src/tests.rs | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/updatehub-cloud-sdk/src/api.rs b/updatehub-cloud-sdk/src/api.rs index 8424a4a2..cfba9f05 100644 --- a/updatehub-cloud-sdk/src/api.rs +++ b/updatehub-cloud-sdk/src/api.rs @@ -73,7 +73,7 @@ impl UpdatePackage { impl Signature { pub fn from_base64_str(bytes: &str) -> crate::Result { - Ok(Signature(openssl::base64::decode_block(bytes)?.to_vec())) + Ok(Signature(openssl::base64::decode_block(bytes)?)) } pub fn validate(&self, key: &Path, package: &UpdatePackage) -> crate::Result<()> { diff --git a/updatehub/src/object/installer/mod.rs b/updatehub/src/object/installer/mod.rs index 517fdafd..efdf6b37 100644 --- a/updatehub/src/object/installer/mod.rs +++ b/updatehub/src/object/installer/mod.rs @@ -76,7 +76,8 @@ async fn check_if_different( } definitions::InstallIfDifferent::CustomPattern { version, pattern } => { handle.seek(io::SeekFrom::Start(pattern.seek)).await?; - let mut src = BufReader::with_capacity(pattern.buffer_size as usize, handle); + let buffer_size = usize::try_from(pattern.buffer_size).unwrap_or(usize::MAX); + let mut src = BufReader::with_capacity(buffer_size, handle); if let Some(ref cur_version) = fbv::version_with_pattern(&mut src, &pattern.regexp).await { diff --git a/updatehub/src/object/installer/raw.rs b/updatehub/src/object/installer/raw.rs index bd8c6946..a0e2a169 100644 --- a/updatehub/src/object/installer/raw.rs +++ b/updatehub/src/object/installer/raw.rs @@ -60,7 +60,8 @@ impl Installer for objects::Raw { let h: Box = match &count { definitions::Count::All => Box::new(h), definitions::Count::Limited(n) => { - Box::new(h.take_with_seek((*n as usize * chunk_size) as u64)) + let count = u64::try_from(*n).unwrap_or(0); + Box::new(h.take_with_seek(count * chunk_size as u64)) } }; Ok(h) @@ -79,7 +80,8 @@ impl Installer for objects::Raw { match count { definitions::Count::All => Box::new(input), definitions::Count::Limited(n) => { - Box::new(input.take((n as usize * chunk_size) as u64)) + let count = u64::try_from(n).unwrap_or(0); + Box::new(input.take(count * chunk_size as u64)) } } }; @@ -135,7 +137,8 @@ mod tests { let download_dir = tempdir()?; let mut source = NamedTempFile::new_in(download_dir.path())?; - let original_data = std::iter::repeat_n(ORIGINAL_BYTE, size as usize).collect::>(); + let data_len = usize::try_from(size).unwrap(); + let original_data = std::iter::repeat_n(ORIGINAL_BYTE, data_len).collect::>(); let data = if compressed { let mut e = GzEncoder::new(Vec::new(), Compression::default()); e.write_all(&original_data).unwrap(); @@ -147,7 +150,7 @@ mod tests { source.seek(SeekFrom::Start(0))?; let mut dest = NamedTempFile::new_in(download_dir.path())?; - dest.write_all(&std::iter::repeat_n(DEFAULT_BYTE, size as usize).collect::>())?; + dest.write_all(&std::iter::repeat_n(DEFAULT_BYTE, data_len).collect::>())?; dest.seek(SeekFrom::Start(0))?; Ok(( @@ -200,7 +203,7 @@ mod tests { seek: u64, count: definitions::Count, ) -> io::Result<()> { - let skip = skip as usize * chunk_size; + let skip = usize::try_from(skip).unwrap() * chunk_size; let file = fs::File::open(file).await?; let mut f1 = io::BufReader::with_capacity(chunk_size, &data[skip..]); let mut f2 = io::BufReader::with_capacity(chunk_size, file); diff --git a/updatehub/src/states/download.rs b/updatehub/src/states/download.rs index 555fd135..ebb08d66 100644 --- a/updatehub/src/states/download.rs +++ b/updatehub/src/states/download.rs @@ -28,7 +28,7 @@ impl Download { ) -> Result<()> { let installation_set = installation_set::inactive().log_error_msg("unable to get current installation set")?; - let download_dir = context.lock().await.settings.update.download_dir.to_owned(); + let download_dir = context.lock().await.settings.update.download_dir.clone(); update_package .clear_unrelated_files(&download_dir, installation_set, &context.lock().await.settings) diff --git a/updatehub/src/tests.rs b/updatehub/src/tests.rs index a80319e1..6cc941b6 100644 --- a/updatehub/src/tests.rs +++ b/updatehub/src/tests.rs @@ -192,7 +192,7 @@ impl TestEnvironmentBuilder { fs::remove_file(&file_path).unwrap(); let mut runtime_settings = RuntimeSettings::default(); - runtime_settings.path = file_path.clone(); + runtime_settings.path.clone_from(&file_path); if self.booting_from_update { runtime_settings.enable_persistency(); runtime_settings.set_upgrading_to(Set(InstallationSet::A)).unwrap(); From 4890bfd9a025a0cdd332790d20f382116d4d725e Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 19 Aug 2026 17:29:57 -0300 Subject: [PATCH 3/6] refactor: replace lazy_static with std::sync::LazyLock The standard library gained `LazyLock` in Rust 1.80, so the `lazy_static` macro no longer earns its place. `clippy::non_std_lazy_statics` reports each of the four remaining uses. Declare each static directly. The types stay the same, so every call site keeps working through `Deref`. Drop the `lazy_static` dependency from the updatehub crate. --- Cargo.lock | 1 - updatehub/Cargo.toml | 1 - updatehub/src/logger.rs | 8 +++----- updatehub/src/object/installer/mod.rs | 7 ++----- updatehub/src/utils/mtd.rs | 7 ++----- updatehub/src/utils/test_env.rs | 7 ++----- 6 files changed, 9 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d826332d..cedf6696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3392,7 +3392,6 @@ dependencies = [ "futures-util", "git-version", "insta", - "lazy_static", "logging_content", "loopdev-3", "mockito", diff --git a/updatehub/Cargo.toml b/updatehub/Cargo.toml index 8548d9a3..06083535 100644 --- a/updatehub/Cargo.toml +++ b/updatehub/Cargo.toml @@ -71,7 +71,6 @@ derive_more = { version = "2", default-features = false, features = [ easy_process = "0.2" find-binary-version = "0.5" futures-util = { version = "0.3", default-features = false } -lazy_static = "1" logging_content = "0.1" mockito = { version = "1", optional = true } ms-converter = "1" diff --git a/updatehub/src/logger.rs b/updatehub/src/logger.rs index 7de5d282..35d6eaa3 100644 --- a/updatehub/src/logger.rs +++ b/updatehub/src/logger.rs @@ -3,13 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::mem_drain::MemDrain; -use lazy_static::lazy_static; use slog::{Drain, Logger, o}; -use std::sync::{Arc, Mutex, MutexGuard}; +use std::sync::{Arc, LazyLock, Mutex, MutexGuard}; -lazy_static! { - static ref BUFFER: Arc> = Arc::new(Mutex::new(MemDrain::default())); -} +static BUFFER: LazyLock>> = + LazyLock::new(|| Arc::new(Mutex::new(MemDrain::default()))); pub fn init(level: slog::Level) -> slog_scope::GlobalLoggerGuard { let buffer_drain = buffer().filter_level(level).fuse(); diff --git a/updatehub/src/object/installer/mod.rs b/updatehub/src/object/installer/mod.rs index efdf6b37..014dd86e 100644 --- a/updatehub/src/object/installer/mod.rs +++ b/updatehub/src/object/installer/mod.rs @@ -130,20 +130,17 @@ where #[cfg(test)] pub(crate) mod tests { use super::*; - use lazy_static::lazy_static; use std::{ fs, io::Write, os::unix::fs::PermissionsExt, path::{Path, PathBuf}, - sync::{Arc, Mutex}, + sync::{Arc, LazyLock, Mutex}, }; use tempfile::TempDir; // Used to serialize access to Loop devices across tests - lazy_static! { - pub static ref SERIALIZE: Arc> = Arc::new(Mutex::default()); - } + pub static SERIALIZE: LazyLock>> = LazyLock::new(|| Arc::new(Mutex::default())); fn create_echo_bin(bin: &Path, output: &Path) -> std::io::Result<()> { let mut file = std::fs::File::create(bin)?; diff --git a/updatehub/src/utils/mtd.rs b/updatehub/src/utils/mtd.rs index 54533c80..9cc93a6e 100644 --- a/updatehub/src/utils/mtd.rs +++ b/updatehub/src/utils/mtd.rs @@ -173,9 +173,8 @@ mod ffi { #[cfg(test)] pub(crate) mod tests { use super::*; - use lazy_static::lazy_static; use pretty_assertions::assert_eq; - use std::sync::{Arc, Mutex}; + use std::sync::{Arc, LazyLock, Mutex}; pub(crate) struct FakeUbi { #[allow(dead_code)] @@ -265,9 +264,7 @@ pub(crate) mod tests { } // Used to serialize access to MTD devices - lazy_static! { - pub static ref SERIALIZE: Arc> = Arc::new(Mutex::default()); - } + pub static SERIALIZE: LazyLock>> = LazyLock::new(|| Arc::new(Mutex::default())); #[test] #[ignore] diff --git a/updatehub/src/utils/test_env.rs b/updatehub/src/utils/test_env.rs index fc3d80c6..23e05186 100644 --- a/updatehub/src/utils/test_env.rs +++ b/updatehub/src/utils/test_env.rs @@ -6,17 +6,14 @@ //! only needs `is_executable_in_path` to see other directories. It changes no //! process state at all. -use lazy_static::lazy_static; use std::{ env, ffi::OsString, path::Path, - sync::{Mutex, MutexGuard}, + sync::{LazyLock, Mutex, MutexGuard}, }; -lazy_static! { - static ref ENV_LOCK: Mutex<()> = Mutex::default(); -} +static ENV_LOCK: LazyLock> = LazyLock::new(Mutex::default); /// Holds `PATH` at a test-defined value, and restores it on drop. /// From b0e6c8aafb7de2919e3d581e090f8b1f967ddb2f Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Wed, 19 Aug 2026 17:34:36 -0300 Subject: [PATCH 4/6] style: apply the mechanical clippy::pedantic code fixes This is a code style pass with no change in behavior. It closes every `clippy::pedantic` warning that names a concrete rewrite: - add the missing semicolon on a statement that returns the unit type, and drop the ones that add nothing; - replace a closure that only calls one method with the method itself, and call `to_string` on the value instead of on a double reference; - write `String::new` instead of an empty literal, and drop the raw string hashes that no string needs; - prefer `if let` and `let ... else` over a match with one meaningful arm, join the arms that share a body, and name the last variant instead of a wildcard; - move an item declaration above the statements of its function; - take `Option<&T>` instead of `&Option` in `fs::format`, `fs::chown`, and `should_skip_install`, which removes one level of indirection at every call site. Some warnings stay open on purpose: - `unnecessary_debug_formatting` marks paths written with `{:?}`. The quotes it adds are what makes a path with a space safe inside the shell commands the flash and raw-delta handlers build. - `used_underscore_binding` marks the `_mount` field of `MountGuard`, whose name states that the guard only holds the mount alive. - `wildcard_imports` marks `use super::*` in a test module, which is the usual pattern. - `unused_async` marks trait methods with a default body, the mock cloud client that must match the real signature, a warp handler, and a public SDK function. The `async` is part of the contract in each case. - `too_many_lines` needs the functions to be split, which does not belong in a style pass. --- updatehub-cloud-sdk/src/client.rs | 36 +++++++++---------- .../src/definitions/chunk_size.rs | 2 +- .../src/definitions/install_if_different.rs | 2 +- updatehub-sdk/src/listener.rs | 2 +- updatehub-sdk/tests/openapi_integration.rs | 15 +++----- updatehub/src/cloud_mock.rs | 2 +- updatehub/src/firmware/hook.rs | 4 +-- updatehub/src/http_api.rs | 2 +- updatehub/src/logger.rs | 6 ++-- updatehub/src/main.rs | 6 ++-- updatehub/src/mem_drain.rs | 4 +-- updatehub/src/object/installer/copy.rs | 24 ++++++------- updatehub/src/object/installer/flash.rs | 6 ++-- updatehub/src/object/installer/imxkobs.rs | 15 ++++---- updatehub/src/object/installer/mod.rs | 2 +- updatehub/src/object/installer/raw.rs | 18 +++++----- updatehub/src/object/installer/tarball.rs | 6 ++-- updatehub/src/settings.rs | 9 +++-- updatehub/src/states/direct_download.rs | 7 ++-- updatehub/src/states/download.rs | 24 +++++++------ updatehub/src/states/mod.rs | 2 +- updatehub/src/states/probe.rs | 4 +-- updatehub/src/states/tests.rs | 4 +-- updatehub/src/states/validation.rs | 26 ++++++-------- updatehub/src/tests.rs | 7 ++-- updatehub/src/update_package/mod.rs | 4 +-- updatehub/src/utils/fs.rs | 23 ++++++------ updatehub/src/utils/mtd.rs | 5 +-- updatehub/src/utils/test_env.rs | 2 +- updatehub/tests/common.rs | 16 ++++----- updatehub/tests/failed_integration_test.rs | 8 ++--- .../tests/successful_integration_test.rs | 34 +++++++++--------- 32 files changed, 160 insertions(+), 167 deletions(-) diff --git a/updatehub-cloud-sdk/src/client.rs b/updatehub-cloud-sdk/src/client.rs index b2544766..c7a558a4 100644 --- a/updatehub-cloud-sdk/src/client.rs +++ b/updatehub-cloud-sdk/src/client.rs @@ -75,7 +75,7 @@ impl<'a> Client<'a> { .build() .unwrap(); - Self { server, client } + Self { client, server } } pub async fn probe( @@ -96,24 +96,24 @@ impl<'a> Client<'a> { match response.status() { StatusCode::NOT_FOUND => Ok(api::ProbeResponse::NoUpdate), StatusCode::OK => { - match response + let extra_poll = response .headers() .get("add-extra-poll") .and_then(|extra_poll| extra_poll.to_str().ok()) - .and_then(|extra_poll| extra_poll.parse().ok()) - { - Some(extra_poll) => Ok(api::ProbeResponse::ExtraPoll(extra_poll)), - None => { - let signature = response - .headers() - .get("UH-Signature") - .map(TryInto::try_into) - .transpose()?; - Ok(api::ProbeResponse::Update( - api::UpdatePackage::parse(&response.bytes().await?)?, - signature, - )) - } + .and_then(|extra_poll| extra_poll.parse().ok()); + + if let Some(extra_poll) = extra_poll { + Ok(api::ProbeResponse::ExtraPoll(extra_poll)) + } else { + let signature = response + .headers() + .get("UH-Signature") + .map(TryInto::try_into) + .transpose()?; + Ok(api::ProbeResponse::Update( + api::UpdatePackage::parse(&response.bytes().await?)?, + signature, + )) } } s => Err(Error::InvalidStatusResponse(s)), @@ -162,8 +162,6 @@ impl<'a> Client<'a> { error_message: Option, current_log: Option, ) -> Result<()> { - validate_url(self.server)?; - #[derive(serde::Serialize)] #[serde(rename_all = "kebab-case")] struct Payload<'a> { @@ -180,6 +178,8 @@ impl<'a> Client<'a> { current_log: Option, } + validate_url(self.server)?; + let payload = Payload { state, firmware, package_uid, previous_state, error_message, current_log }; diff --git a/updatehub-package-schema/src/definitions/chunk_size.rs b/updatehub-package-schema/src/definitions/chunk_size.rs index 016a7a08..c590cb7d 100644 --- a/updatehub-package-schema/src/definitions/chunk_size.rs +++ b/updatehub-package-schema/src/definitions/chunk_size.rs @@ -46,7 +46,7 @@ mod test { serde_json::from_value::(json!({ "chunk_size": 313 })).ok(), Some(Payload { chunk_size: ChunkSize(313) }) ); - assert!(serde_json::from_value::(json!({ "chunk_size": 0 })).is_err()) + assert!(serde_json::from_value::(json!({ "chunk_size": 0 })).is_err()); } #[test] diff --git a/updatehub-package-schema/src/definitions/install_if_different.rs b/updatehub-package-schema/src/definitions/install_if_different.rs index da4b49c0..fe402115 100644 --- a/updatehub-package-schema/src/definitions/install_if_different.rs +++ b/updatehub-package-schema/src/definitions/install_if_different.rs @@ -91,6 +91,6 @@ mod test { "pattern": "linux-kernel" })) .unwrap() - ) + ); } } diff --git a/updatehub-sdk/src/listener.rs b/updatehub-sdk/src/listener.rs index 66c26206..0e3a86d1 100644 --- a/updatehub-sdk/src/listener.rs +++ b/updatehub-sdk/src/listener.rs @@ -103,7 +103,7 @@ impl StateChange { F: Fn(Handler) -> Fut + 'static, Fut: Future> + 'static, { - self.callbacks.entry(state).or_default().push(Box::new(move |d| Box::pin(f(d)))) + self.callbacks.entry(state).or_default().push(Box::new(move |d| Box::pin(f(d)))); } /// Start the agent to listen for messages on the socket. diff --git a/updatehub-sdk/tests/openapi_integration.rs b/updatehub-sdk/tests/openapi_integration.rs index 365d2a68..da7bfe8e 100644 --- a/updatehub-sdk/tests/openapi_integration.rs +++ b/updatehub-sdk/tests/openapi_integration.rs @@ -43,8 +43,7 @@ async fn probe_default() { let client = sdk::Client::new(&addr); let response = client.probe(None).await; match dbg!(response) { - Ok(_) => {} - Err(sdk::Error::AgentIsBusy(_)) => {} + Ok(_) | Err(sdk::Error::AgentIsBusy(_)) => {} Err(e) => panic!("Unexpected Error response: {e}"), } } @@ -55,8 +54,7 @@ async fn probe_custom() { let client = sdk::Client::new(&addr); let response = client.probe(Some(String::from("http://foo.bar"))).await; match dbg!(response) { - Ok(_) => {} - Err(sdk::Error::AgentIsBusy(_)) => {} + Ok(_) | Err(sdk::Error::AgentIsBusy(_)) => {} Err(e) => panic!("Unexpected Error response: {e}"), } } @@ -69,8 +67,7 @@ async fn local_install() { let response = client.local_install(file.path()).await; match dbg!(response) { - Ok(_) => {} - Err(sdk::Error::AgentIsBusy(_)) => {} + Ok(_) | Err(sdk::Error::AgentIsBusy(_)) => {} Err(e) => panic!("Unexpected Error response: {e}"), } } @@ -81,8 +78,7 @@ async fn remote_install() { let client = sdk::Client::new(&addr); let response = client.remote_install("http://foo.bar").await; match dbg!(response) { - Ok(_) => {} - Err(sdk::Error::AgentIsBusy(_)) => {} + Ok(_) | Err(sdk::Error::AgentIsBusy(_)) => {} Err(e) => panic!("Unexpected Error response: {e}"), } } @@ -93,8 +89,7 @@ async fn abort_download() { let client = sdk::Client::new(&addr); let response = client.abort_download().await; match dbg!(response) { - Ok(_) => {} - Err(sdk::Error::AbortDownloadRefused(_)) => {} + Ok(_) | Err(sdk::Error::AbortDownloadRefused(_)) => {} Err(e) => panic!("Unexpected Error response: {e}"), } } diff --git a/updatehub/src/cloud_mock.rs b/updatehub/src/cloud_mock.rs index 8f738f2f..9787b723 100644 --- a/updatehub/src/cloud_mock.rs +++ b/updatehub/src/cloud_mock.rs @@ -64,7 +64,7 @@ impl<'a> Client<'a> { object: &str, ) -> Result<()> { if let Some(data) = OBJECT_DATA.with(|conf| conf.borrow_mut().take()) { - tokio::fs::write(download_dir.join(object), data).await? + tokio::fs::write(download_dir.join(object), data).await?; } Ok(()) diff --git a/updatehub/src/firmware/hook.rs b/updatehub/src/firmware/hook.rs index 82de6648..d4388dbc 100644 --- a/updatehub/src/firmware/hook.rs +++ b/updatehub/src/firmware/hook.rs @@ -10,7 +10,7 @@ use walkdir::WalkDir; pub(crate) fn run_hook(path: &Path) -> Result { if !path.exists() { - return Ok("".into()); + return Ok(String::new()); } run_script(path.to_str().expect("invalid path for hook")) @@ -35,7 +35,7 @@ pub(crate) fn run_script(cmd: &str) -> Result { Err(easy_process::Error::Failure(status, output)) => { error!("Script {} failed to run: {}", cmd, status); if !output.stderr.is_empty() { - output.stderr.lines().for_each(|err| error!("{} (stderr): {}", cmd, err)) + output.stderr.lines().for_each(|err| error!("{} (stderr): {}", cmd, err)); } Err(easy_process::Error::Failure(status, output).into()) } diff --git a/updatehub/src/http_api.rs b/updatehub/src/http_api.rs index 349c4065..0d334be6 100644 --- a/updatehub/src/http_api.rs +++ b/updatehub/src/http_api.rs @@ -13,7 +13,7 @@ pub(crate) struct Api(); impl Api { pub(crate) async fn serve(addr: machine::Addr, socket: std::net::SocketAddr) { - warp::serve(Api::filter(addr)).run(socket).await + warp::serve(Api::filter(addr)).run(socket).await; } fn filter(addr: machine::Addr) -> warp::filters::BoxedFilter<(impl warp::Reply,)> { diff --git a/updatehub/src/logger.rs b/updatehub/src/logger.rs index 35d6eaa3..87ee757d 100644 --- a/updatehub/src/logger.rs +++ b/updatehub/src/logger.rs @@ -31,15 +31,15 @@ pub fn buffer() -> Arc> { /// The buffered drain, recovering the lock if a thread panicked while holding /// it: being unable to log must not bring the agent down. fn buffer_lock() -> MutexGuard<'static, MemDrain> { - BUFFER.lock().unwrap_or_else(|poisoned| poisoned.into_inner()) + BUFFER.lock().unwrap_or_else(std::sync::PoisonError::into_inner) } pub fn start_memory_logging() { - buffer_lock().start_logging() + buffer_lock().start_logging(); } pub fn stop_memory_logging() { - buffer_lock().stop_logging() + buffer_lock().stop_logging(); } /// Record what `f` logs even while memory logging is stopped. diff --git a/updatehub/src/main.rs b/updatehub/src/main.rs index ef836533..2ad433f2 100644 --- a/updatehub/src/main.rs +++ b/updatehub/src/main.rs @@ -97,7 +97,7 @@ struct DaemonOptions { fn verbosity_level(value: &str) -> Result { use std::str::FromStr; - slog::Level::from_str(value).map_err(|_| format!("failed to parse verbosity level: {value}")) + slog::Level::from_str(value).map_err(|()| format!("failed to parse verbosity level: {value}")) } async fn daemon_main(cmd: DaemonOptions) -> updatehub::Result<()> { @@ -157,10 +157,10 @@ async fn client_main(client_options: ClientOptions) -> updatehub::Result<()> { } else { match response { sdk::api::probe::Response::Updating => { - println!("Update available. The update is running in background.") + println!("Update available. The update is running in background."); } sdk::api::probe::Response::NoUpdate => { - println!("There are no updates available.") + println!("There are no updates available."); } sdk::api::probe::Response::TryAgain(t) => { println!("Server replied asking us to try again in {t} seconds"); diff --git a/updatehub/src/mem_drain.rs b/updatehub/src/mem_drain.rs index 04c001b8..0761b74b 100644 --- a/updatehub/src/mem_drain.rs +++ b/updatehub/src/mem_drain.rs @@ -128,11 +128,11 @@ impl MemDrain { /// The recorded entries, recovering the lock if a thread panicked while /// holding it: being unable to log must not bring the agent down. fn records(&self) -> RwLockReadGuard<'_, Records> { - self.records.read().unwrap_or_else(|poisoned| poisoned.into_inner()) + self.records.read().unwrap_or_else(std::sync::PoisonError::into_inner) } fn records_mut(&self) -> RwLockWriteGuard<'_, Records> { - self.records.write().unwrap_or_else(|poisoned| poisoned.into_inner()) + self.records.write().unwrap_or_else(std::sync::PoisonError::into_inner) } /// Start recording a new operation, discarding what the previous one left. diff --git a/updatehub/src/object/installer/copy.rs b/updatehub/src/object/installer/copy.rs index d4ea6690..402d45e9 100644 --- a/updatehub/src/object/installer/copy.rs +++ b/updatehub/src/object/installer/copy.rs @@ -45,7 +45,7 @@ impl Installer for objects::Copy { let device = self.target_type.get_target().log_error_msg("failed to get target device")?; let filesystem = self.filesystem; let mount_options = &self.mount_options; - let format_options = &self.target_format.format_options; + let format_options = self.target_format.format_options.as_deref(); let chunk_size = definitions::ChunkSize::default().0; let sha256sum = self.sha256sum(); let target_path = self.target_path.strip_prefix("/").unwrap_or(&self.target_path); @@ -56,7 +56,7 @@ impl Installer for objects::Copy { let file_path = mount_guard.mount_point().join(target_path); let should_skip_install = file_path.exists() && super::should_skip_install( - &self.install_if_different, + self.install_if_different.as_ref(), &self.sha256sum, async move { Ok(fs::File::open(file_path).await?) }, ) @@ -113,8 +113,8 @@ impl Installer for objects::Copy { utils::fs::chown( &dest, - &self.target_permissions.target_uid, - &self.target_permissions.target_gid, + self.target_permissions.target_uid.as_ref(), + self.target_permissions.target_gid.as_ref(), ) .log_error_msg("failed to update ownership")?; @@ -164,7 +164,7 @@ mod tests { }; // Format the faked device - utils::fs::format(&device, definitions::Filesystem::Ext4, &None)?; + utils::fs::format(&device, definitions::Filesystem::Ext4, None)?; // Generate the source file let download_dir = tempfile::tempdir()?; @@ -193,12 +193,12 @@ mod tests { utils::fs::chmod(&file, mode)?; } - utils::fs::chown(&file, &perm.target_uid, &perm.target_gid)?; + utils::fs::chown(&file, perm.target_uid.as_ref(), perm.target_gid.as_ref())?; } // Generate base copy object let mut obj = objects::Copy { - filename: "".to_string(), + filename: String::new(), filesystem: definitions::Filesystem::Ext4, size: FILE_SIZE as u64, sha256sum: source.path().to_string_lossy().to_string(), @@ -245,17 +245,17 @@ mod tests { let metadata = dest.metadata()?; if let Some(mode) = obj.target_permissions.target_mode { assert_eq!(mode, metadata.mode() % 0o1000); - }; + } if let Some(uid) = obj.target_permissions.target_uid { let uid = uid.as_u32(); assert_eq!(uid, metadata.uid()); - }; + } if let Some(gid) = obj.target_permissions.target_gid { let gid = gid.as_u32(); assert_eq!(gid, metadata.gid()); - }; + } } loopdev.detach()?; @@ -299,7 +299,7 @@ mod tests { exec_test_with_copy( |obj| { obj.target_permissions.target_uid = - Some(definitions::target_permissions::Uid::Number(0)) + Some(definitions::target_permissions::Uid::Number(0)); }, None, false, @@ -314,7 +314,7 @@ mod tests { exec_test_with_copy( |obj| { obj.target_permissions.target_gid = - Some(definitions::target_permissions::Gid::Number(0)) + Some(definitions::target_permissions::Gid::Number(0)); }, Some(definitions::TargetPermissions { target_mode: Some(0o666), diff --git a/updatehub/src/object/installer/flash.rs b/updatehub/src/object/installer/flash.rs index 6a141c49..5e4628cc 100644 --- a/updatehub/src/object/installer/flash.rs +++ b/updatehub/src/object/installer/flash.rs @@ -30,7 +30,9 @@ impl Installer for objects::Flash { )?; Ok(()) } - _ => Err(Error::InvalidTargetType(self.target.clone())), + definitions::TargetType::UBIVolume(_) => { + Err(Error::InvalidTargetType(self.target.clone())) + } } } @@ -40,7 +42,7 @@ impl Installer for objects::Flash { let target = self.target.get_target()?; let source = context.download_dir.join(self.sha256sum()); - if super::should_skip_install(&self.install_if_different, &self.sha256sum, async { + if super::should_skip_install(self.install_if_different.as_ref(), &self.sha256sum, async { tokio::fs::File::open(&target).await.map_err(Error::from) }) .await? diff --git a/updatehub/src/object/installer/imxkobs.rs b/updatehub/src/object/installer/imxkobs.rs index 15b47cce..fc853280 100644 --- a/updatehub/src/object/installer/imxkobs.rs +++ b/updatehub/src/object/installer/imxkobs.rs @@ -36,15 +36,18 @@ impl Installer for objects::Imxkobs { async fn install(&self, context: &Context) -> Result<()> { info!("'imxkobs' handler Install {} ({})", self.filename, self.sha256sum); - let should_skip_install = - super::should_skip_install(&self.install_if_different, &self.sha256sum, async { + let should_skip_install = super::should_skip_install( + self.install_if_different.as_ref(), + &self.sha256sum, + async { let path = chip_0_path(self); let f = path.file_name().ok_or(Error::InvalidPath)?; let mut file_name = f.to_os_string(); file_name.push("ro"); tokio::fs::File::open(path.with_file_name(file_name)).await.map_err(Error::from) - }) - .await?; + }, + ) + .await?; if should_skip_install { return Ok(()); } @@ -52,8 +55,8 @@ impl Installer for objects::Imxkobs { let mut cmd = String::from("kobs-ng init "); if self.padding_1k { - cmd += "-x " - }; + cmd += "-x "; + } cmd += context .download_dir diff --git a/updatehub/src/object/installer/mod.rs b/updatehub/src/object/installer/mod.rs index 014dd86e..ee8bfa87 100644 --- a/updatehub/src/object/installer/mod.rs +++ b/updatehub/src/object/installer/mod.rs @@ -91,7 +91,7 @@ async fn check_if_different( } async fn should_skip_install( - rule: &Option, + rule: Option<&definitions::InstallIfDifferent>, sha256sum: &str, handler: F, ) -> Result diff --git a/updatehub/src/object/installer/raw.rs b/updatehub/src/object/installer/raw.rs index a0e2a169..af5c5ffb 100644 --- a/updatehub/src/object/installer/raw.rs +++ b/updatehub/src/object/installer/raw.rs @@ -38,9 +38,8 @@ impl Installer for objects::Raw { async fn install(&self, context: &Context) -> Result<()> { info!("'raw' handler Install {} ({})", self.filename, self.sha256sum); - let device = match self.target_type { - definitions::TargetType::Device(ref p) => p, - _ => unreachable!("device should be secured by check_requirements"), + let definitions::TargetType::Device(ref device) = self.target_type else { + unreachable!("device should be secured by check_requirements") }; let source = context.download_dir.join(self.sha256sum()); let chunk_size = self.chunk_size.0; @@ -49,8 +48,10 @@ impl Installer for objects::Raw { let truncate = self.truncate.0; let count = self.count.clone(); - let should_skip_install = - super::should_skip_install(&self.install_if_different, &self.sha256sum, async { + let should_skip_install = super::should_skip_install( + self.install_if_different.as_ref(), + &self.sha256sum, + async { trait AsyncReadSeek: AsyncRead + AsyncSeek + Unpin {} impl AsyncReadSeek for R {} @@ -65,8 +66,9 @@ impl Installer for objects::Raw { } }; Ok(h) - }) - .await?; + }, + ) + .await?; if should_skip_install { return Ok(()); } @@ -155,7 +157,7 @@ mod tests { Ok(( objects::Raw { - filename: "".to_string(), + filename: String::new(), size, sha256sum: source.path().to_string_lossy().to_string(), target_type: definitions::TargetType::Device(dest.path().into()), diff --git a/updatehub/src/object/installer/tarball.rs b/updatehub/src/object/installer/tarball.rs index 5a3cb4a1..19b603f5 100644 --- a/updatehub/src/object/installer/tarball.rs +++ b/updatehub/src/object/installer/tarball.rs @@ -41,7 +41,7 @@ impl Installer for objects::Tarball { let device = self.target.get_target().log_error_msg("failed to get target device")?; let filesystem = self.filesystem; let mount_options = &self.mount_options; - let format_options = &self.target_format.format_options; + let format_options = self.target_format.format_options.as_deref(); let sha256sum = self.sha256sum(); let target_path = self.target_path.strip_prefix("/").unwrap_or(&self.target_path); let source = context.download_dir.join(sha256sum); @@ -100,11 +100,11 @@ mod tests { }; // Format the faked device - utils::fs::format(&device, definitions::Filesystem::Ext4, &None)?; + utils::fs::format(&device, definitions::Filesystem::Ext4, None)?; // Generate base copy object let mut obj = objects::Tarball { - filename: "".to_string(), + filename: String::new(), filesystem: definitions::Filesystem::Ext4, size: CONTENT_SIZE as u64, sha256sum: "tree.tar".to_string(), diff --git a/updatehub/src/settings.rs b/updatehub/src/settings.rs index 6ec2a34e..fb9abb03 100644 --- a/updatehub/src/settings.rs +++ b/updatehub/src/settings.rs @@ -172,7 +172,7 @@ fn v1_parse(content: &str, toml_err: toml::de::Error) -> Result { "dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs", ] .iter() - .map(|i| i.to_string()) + .map(|i| (*i).to_string()) .collect(), } } @@ -340,7 +340,7 @@ metadata="/usr/share/updatehub" "dry-run", "copy", "flash", "imxkobs", "raw", "tarball", "ubifs", ] .iter() - .map(|i| i.to_string()) + .map(|i| (*i).to_string()) .collect(), }, network: api::Network { @@ -381,7 +381,10 @@ ListenSocket=localhost:8313 }, update: api::Update { download_dir: "/tmp/download".into(), - supported_install_modes: ["mode1", "mode2"].iter().map(|i| i.to_string()).collect(), + supported_install_modes: ["mode1", "mode2"] + .iter() + .map(|i| (*i).to_string()) + .collect(), }, network: api::Network { server_address: "http://localhost".to_string(), diff --git a/updatehub/src/states/direct_download.rs b/updatehub/src/states/direct_download.rs index 8fff1bc1..61dbac82 100644 --- a/updatehub/src/states/direct_download.rs +++ b/updatehub/src/states/direct_download.rs @@ -28,7 +28,7 @@ impl StateChangeImpl for DirectDownload { async fn handle(self, context: &mut Context) -> Result<(State, machine::StepTransition)> { info!("fetching update package directly from url: {:?}", self.url); - use std::ops::DerefMut; + let communication_receiver = &context.communication.receiver.clone(); let context = Mutex::new(context); @@ -48,9 +48,8 @@ impl StateChangeImpl for DirectDownload { let message_handle_future = async { while let Ok((msg, responder)) = communication_receiver.recv().await { - if let Some(new_state) = self - .handle_communication(msg, responder, context.lock().await.deref_mut()) - .await + if let Some(new_state) = + self.handle_communication(msg, responder, *context.lock().await).await { return Ok(new_state); } diff --git a/updatehub/src/states/download.rs b/updatehub/src/states/download.rs index ebb08d66..0b29968e 100644 --- a/updatehub/src/states/download.rs +++ b/updatehub/src/states/download.rs @@ -58,11 +58,15 @@ impl Download { Some((filename, sha256sum)) } - (filename, sha256sum, Ok(object::info::Status::Missing)) - | (filename, sha256sum, Ok(object::info::Status::Incomplete)) - | (filename, sha256sum, Ok(object::info::Status::Corrupted)) => { - Some((filename, sha256sum)) - } + ( + filename, + sha256sum, + Ok( + object::info::Status::Missing + | object::info::Status::Incomplete + | object::info::Status::Corrupted, + ), + ) => Some((filename, sha256sum)), (_, _, Ok(object::info::Status::Ready)) => None, } @@ -125,7 +129,6 @@ impl StateChangeImpl for Download { } async fn handle(self, context: &mut Context) -> Result<(State, machine::StepTransition)> { - use std::ops::DerefMut; let communication_receiver = &context.communication.receiver.clone(); let context = Mutex::new(context); @@ -137,9 +140,8 @@ impl StateChangeImpl for Download { let message_handle_future = async { while let Ok((msg, responder)) = communication_receiver.recv().await { - if let Some(new_state) = self - .handle_communication(msg, responder, context.lock().await.deref_mut()) - .await + if let Some(new_state) = + self.handle_communication(msg, responder, *context.lock().await).await { return Ok(Some(new_state)); } @@ -231,12 +233,12 @@ mod test { #[tokio::test] #[ignore] async fn download_small_object() { - test_object_download(16).await + test_object_download(16).await; } #[tokio::test] #[ignore] async fn download_large_object() { - test_object_download(100_000_000).await + test_object_download(100_000_000).await; } } diff --git a/updatehub/src/states/mod.rs b/updatehub/src/states/mod.rs index 3340275c..16c013c4 100644 --- a/updatehub/src/states/mod.rs +++ b/updatehub/src/states/mod.rs @@ -165,7 +165,7 @@ trait ProgressReporter: CallbackReporter { Ok((state, trans)) => { if let Err(e) = report(leave_state, None, None, None).await { warn!("report failed: {}", e); - }; + } Ok((state, trans)) } Err(e) => { diff --git a/updatehub/src/states/probe.rs b/updatehub/src/states/probe.rs index a45f3ad7..b3f2827a 100644 --- a/updatehub/src/states/probe.rs +++ b/updatehub/src/states/probe.rs @@ -94,7 +94,7 @@ impl StateChangeImpl for Probe { match probe { ProbeResponse::NoUpdate => { crate::logger::record_out_of_scope(|| { - info!("no update is current available for this device") + info!("no update is current available for this device"); }); // Store timestamp of last polling @@ -107,7 +107,7 @@ impl StateChangeImpl for Probe { ProbeResponse::ExtraPoll(s) => { crate::logger::record_out_of_scope(|| { - info!("delaying the probing for {} seconds as requested by the server", s) + info!("delaying the probing for {} seconds as requested by the server", s); }); Ok((State::Probe(self), machine::StepTransition::Delayed(Duration::seconds(s)))) } diff --git a/updatehub/src/states/tests.rs b/updatehub/src/states/tests.rs index b43ce99a..ba111e94 100644 --- a/updatehub/src/states/tests.rs +++ b/updatehub/src/states/tests.rs @@ -92,7 +92,7 @@ fn validate_v1_restored_runtime_settings() { ) .unwrap(); // Overwrite runtimesettings with a v1 model - let original_runtime_settings = r#" + let original_runtime_settings = r" [Polling] LastPoll=2021-06-01T14:38:57-03:00 FirstPoll=2021-05-01T13:33:33-03:00 @@ -102,7 +102,7 @@ ProbeASAP=false [Update] UpgradeToInstallation=0 -"#; +"; std::fs::write(&setup.runtime_settings.stored_path, original_runtime_settings).unwrap(); let mut loaded_runtime_settings = RuntimeSettings::load(&setup.runtime_settings.stored_path).unwrap(); diff --git a/updatehub/src/states/validation.rs b/updatehub/src/states/validation.rs index 37a2235f..924dd61a 100644 --- a/updatehub/src/states/validation.rs +++ b/updatehub/src/states/validation.rs @@ -33,16 +33,13 @@ impl StateChangeImpl for Validation { async fn handle(self, context: &mut Context) -> Result<(State, machine::StepTransition)> { if let Some(key) = context.firmware.pub_key.as_ref() { - match self.sign.as_ref() { - Some(sign) => { - debug!("validating signature"); - sign.validate(key, &self.package) - .log_error_msg("uhupkg failed signature validation")?; - } - None => { - error!("missing signature key"); - return Err(super::TransitionError::SignatureNotFound); - } + if let Some(sign) = self.sign.as_ref() { + debug!("validating signature"); + sign.validate(key, &self.package) + .log_error_msg("uhupkg failed signature validation")?; + } else { + error!("missing signature key"); + return Err(super::TransitionError::SignatureNotFound); } } else { info!("no signature key available on device, ignoring signature validation"); @@ -70,7 +67,7 @@ impl StateChangeImpl for Validation { self.package .validate_install_modes(&context.settings, inactive_installation_set) .log_error_msg("install mode failed validation")?; - for obj in self.package.objects(inactive_installation_set).iter() { + for obj in self.package.objects(inactive_installation_set) { if let Err(e) = obj.check_requirements(&object_context).await { error!( "update package: {} ({}) has failed to meet the install requirements", @@ -87,8 +84,7 @@ impl StateChangeImpl for Validation { if context .runtime_settings .applied_package_uid() - .map(|u| *u == update_package.package_uid()) - .unwrap_or_default() + .is_some_and(|u| *u == update_package.package_uid()) { info!("not downloading update package, the same package has already been installed"); Ok((State::EntryPoint(EntryPoint {}), machine::StepTransition::Immediate)) @@ -115,10 +111,10 @@ impl StateChangeImpl for Validation { for object in not_ready { match object { (filename, Ok(status)) => { - error!(" file '{}' is {:?}", filename, status) + error!(" file '{}' is {:?}", filename, status); } (filename, Err(err)) => { - error!(" file '{}' has failed with error: {:?}", filename, err) + error!(" file '{}' has failed with error: {:?}", filename, err); } } } diff --git a/updatehub/src/tests.rs b/updatehub/src/tests.rs index 6cc941b6..6fcd286e 100644 --- a/updatehub/src/tests.rs +++ b/updatehub/src/tests.rs @@ -126,10 +126,7 @@ impl TestEnvironmentBuilder { hardware_hook(dir_path), &format!( "#!/bin/sh\necho {}", - match self.invalid_hardware { - false => "board", - true => "invalid", - } + if self.invalid_hardware { "invalid" } else { "board" } ), ); create_hook( @@ -166,7 +163,7 @@ impl TestEnvironmentBuilder { create_hook(validate_hook(&firmware.stored_path), &script); } - for bin in self.extra_binaries.into_iter() { + for bin in self.extra_binaries { let mut file = fs::File::create(bin_dir_path.join(&bin)).unwrap(); writeln!(file, "#!/bin/sh\necho {} $@ >> {}", bin, output_file.to_string_lossy()) .unwrap(); diff --git a/updatehub/src/update_package/mod.rs b/updatehub/src/update_package/mod.rs index fa2fdb0a..d568ff26 100644 --- a/updatehub/src/update_package/mod.rs +++ b/updatehub/src/update_package/mod.rs @@ -70,7 +70,7 @@ impl UpdatePackageExt for UpdatePackage { if let Some(mode) = self .objects(installation_set) .iter() - .map(|o| o.mode()) + .map(super::object::info::Info::mode) .find(|mode| !install_modes.contains(mode)) { return Err(Error::IncompatibleInstallMode(mode)); @@ -104,7 +104,7 @@ impl UpdatePackageExt for UpdatePackage { .filter(|o| { o.status(&settings.update.download_dir) .map_err(|e| { - error!("fail accessing the object: {} (err: {})", o.sha256sum(), e) + error!("fail accessing the object: {} (err: {})", o.sha256sum(), e); }) .unwrap_or(object::info::Status::Missing) .eq(&filter) diff --git a/updatehub/src/utils/fs.rs b/updatehub/src/utils/fs.rs index 529bacf3..2caf14d7 100644 --- a/updatehub/src/utils/fs.rs +++ b/updatehub/src/utils/fs.rs @@ -140,7 +140,7 @@ fn parse_mount_entry(line: &str) -> Option { Some(MountEntry { device: (major.parse().ok()?, minor.parse().ok()?), - source: fields.get(separator + 2)?.to_string(), + source: (*fields.get(separator + 2)?).to_string(), mount_point: PathBuf::from(fields.get(4)?), }) } @@ -206,9 +206,10 @@ pub(crate) fn is_executable_in_path(cmd: &str) -> Result<()> { #[cfg(test)] if let Some(dirs) = search_path::current() { - return match dirs.iter().any(|dir| is_executable_file(&dir.join(cmd))) { - true => Ok(()), - false => Err(Error::ExecutableNotInPath(cmd.to_owned())), + return if dirs.iter().any(|dir| is_executable_file(&dir.join(cmd))) { + Ok(()) + } else { + Err(Error::ExecutableNotInPath(cmd.to_owned())) }; } @@ -273,18 +274,18 @@ pub(crate) mod search_path { } pub(super) fn current() -> Option> { - OVERRIDE.with_borrow(|o| o.clone()) + OVERRIDE.with_borrow(std::clone::Clone::clone) } } -pub(crate) fn format(target: &Path, fs: Filesystem, options: &Option) -> Result<()> { +pub(crate) fn format(target: &Path, fs: Filesystem, options: Option<&str>) -> Result<()> { // The commands below are forced so they run unattended, which also means // they will not refuse to wipe a mounted filesystem on their own. ensure_not_mounted(target)?; trace!("formating {:?} as {}", target, fs); let target = target.display(); - let options = options.clone().unwrap_or_default(); + let options = options.unwrap_or_default(); let cmd = match fs { Filesystem::Jffs2 => format!("flash_erase -j {options} {target} 0 0"), @@ -330,12 +331,12 @@ pub(crate) fn chmod(path: &Path, mode: u32) -> Result<()> { Ok(()) } -pub(crate) fn chown(path: &Path, uid: &Option, gid: &Option) -> Result<()> { +pub(crate) fn chown(path: &Path, uid: Option<&Uid>, gid: Option<&Gid>) -> Result<()> { trace!("applying ownership of uid:{:?} and gid:{:?} to {:?}", uid, gid, path); Ok(nix::unistd::chown( path, - uid.as_ref().map(|id| nix::unistd::Uid::from_raw(id.as_u32())), - gid.as_ref().map(|id| nix::unistd::Gid::from_raw(id.as_u32())), + uid.map(|id| nix::unistd::Uid::from_raw(id.as_u32())), + gid.map(|id| nix::unistd::Gid::from_raw(id.as_u32())), )?) } @@ -537,7 +538,7 @@ mod tests { "an unmounted loop device should be free to install onto" ); - format(&loop_device.device, Filesystem::Ext4, &None).unwrap(); + format(&loop_device.device, Filesystem::Ext4, None).unwrap(); let guard = mount(&loop_device.device, Filesystem::Ext4, "").unwrap(); let in_use = ensure_not_mounted(&loop_device.device); diff --git a/updatehub/src/utils/mtd.rs b/updatehub/src/utils/mtd.rs index 9cc93a6e..8063b439 100644 --- a/updatehub/src/utils/mtd.rs +++ b/updatehub/src/utils/mtd.rs @@ -16,10 +16,7 @@ pub(crate) fn target_device_from_ubi_volume_name(volume: &str) -> Result (MutexGuard<'static, ()>, Option) { // A panicking test poisons the lock, but `Drop` still restored `PATH` // during the unwind, so the poison carries no information. - let lock = ENV_LOCK.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); + let lock = ENV_LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner); let previous = env::var_os("PATH"); (lock, previous) diff --git a/updatehub/tests/common.rs b/updatehub/tests/common.rs index d704ff14..2cb5f31f 100644 --- a/updatehub/tests/common.rs +++ b/updatehub/tests/common.rs @@ -79,10 +79,10 @@ impl Settings { setup = setup.validate_callback(s.to_owned()); } if let Some(l) = self.install_modes { - setup = setup.supported_install_modes(l) + setup = setup.supported_install_modes(l); } if !self.polling { - setup = setup.disable_polling() + setup = setup.disable_polling(); } let mut setup = setup.finish(); @@ -380,7 +380,7 @@ pub fn rewrite_log_output(s: String) -> (String, String) { let version_re = Regex::new(r"Agent .*").unwrap(); let tmpfile_re = Regex::new(r#""/.*/.tmp.*""#).unwrap(); let date_re = Regex::new(r"\b(?:Jan|...|Dec) (\d{2}) (\d{2}):(\d{2}):(\d{2}).(\d{3})").unwrap(); - let time_re = Regex::new(r#"(\d{5}) seconds"#).unwrap(); + let time_re = Regex::new(r"(\d{5}) seconds").unwrap(); let trce_re = Regex::new(r" TRCE.*").unwrap(); let debg_re = Regex::new(r" DEBG.*").unwrap(); let download_re = Regex::new(r"DEBG (\d{1,3})%").unwrap(); @@ -390,17 +390,13 @@ pub fn rewrite_log_output(s: String) -> (String, String) { let s = tmpfile_re.replace_all(&s, r#""""#); let s = date_re.replace_all(&s, ""); let s = download_re.replace_all(&s, "DEBG %"); - let s = time_re.replace_all(&s, r#"