modules.rs (2154B)
1 use std::os::unix::ffi::OsStrExt; 2 3 use async_process::Command; 4 use async_trait::async_trait; 5 use blocking::unblock; 6 use futures_lite::StreamExt; 7 use futures_lite::stream::iter; 8 use log::{info, warn}; 9 use walkdir::WalkDir; 10 11 use kanit_common::error::{Context, Result}; 12 use kanit_unit::Unit; 13 14 use crate::unit_name; 15 16 pub struct Modules; 17 18 const LOADED_FOLDERS: [&str; 3] = [ 19 "/etc/modules-load.d/", 20 "/run/modules-load./", 21 "/usr/lib/modules-load.d/", 22 ]; 23 24 #[async_trait] 25 impl Unit for Modules { 26 unit_name!("modules"); 27 28 async fn start(&mut self) -> Result<()> { 29 if async_fs::metadata("/proc/modules").await.is_err() { 30 return Ok(()); 31 } 32 33 for dir in LOADED_FOLDERS.iter() { 34 let modules = iter( 35 unblock(move || { 36 WalkDir::new(dir) 37 .into_iter() 38 .filter_map(|e| e.ok()) 39 .filter(|e| { 40 e.file_type().is_file() && e.file_name().as_bytes().ends_with(b".conf") 41 }) 42 }) 43 .await, 44 ) 45 .then(|e| async { async_fs::read_to_string(e.into_path()).await }) 46 .filter_map(|e| e.ok()) 47 .collect::<Vec<String>>() 48 .await 49 .into_iter() 50 .flat_map(|e| { 51 e.lines() 52 .filter(|l| !l.starts_with('#') && !l.starts_with(';') && !l.is_empty()) 53 .map(|s| s.to_string()) 54 .collect::<Vec<String>>() 55 }); 56 57 for module in modules { 58 info!("loading module {module}"); 59 60 let succ = Command::new("modprobe") 61 .args(["-b", "-a", "-v", &module]) 62 .spawn() 63 .context("failed to spawn modprobe")? 64 .status() 65 .await 66 .context("failed to wait")? 67 .success(); 68 69 if !succ { 70 warn!("failed to load module {module}"); 71 } 72 } 73 } 74 75 Ok(()) 76 } 77 }